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 Runeforge v0.8.12
BepInEx/plugins/EpicLoot.dll
Decompiled 7 months ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Globalization; using System.IO; using System.Linq; using System.Reflection; using System.Reflection.Emit; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Serialization.Formatters.Binary; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using System.Text; using System.Text.RegularExpressions; using System.Threading; using BepInEx; using BepInEx.Bootstrap; using BepInEx.Configuration; using BepInEx.Logging; using Common; using EpicLoot.Abilities; using EpicLoot.Adventure; using EpicLoot.Adventure.Feature; using EpicLoot.Config; using EpicLoot.Crafting; using EpicLoot.CraftingV2; using EpicLoot.Data; using EpicLoot.GatedItemType; using EpicLoot.General; using EpicLoot.LegendarySystem; using EpicLoot.LootBeams; using EpicLoot.MagicItemEffects; using EpicLoot.Patching; using EpicLoot.src.GamePatches; using EpicLoot.src.Loot; using EpicLoot.src.Magic; using EpicLoot.src.integrations; using EpicLoot_UnityLib; using HarmonyLib; using JetBrains.Annotations; using Jotunn; using Jotunn.Configs; using Jotunn.Entities; using Jotunn.Managers; using Jotunn.Utils; using Microsoft.CodeAnalysis; using Newtonsoft.Json; using Newtonsoft.Json.Linq; using Splatform; using TMPro; using UnityEngine; using UnityEngine.EventSystems; using UnityEngine.Events; using UnityEngine.UI; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: AssemblyTitle("EpicLoot")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("Randy Knapp Mods")] [assembly: AssemblyProduct("EpicLoot")] [assembly: AssemblyCopyright("Copyright © Randy Knapp 2023")] [assembly: AssemblyTrademark("")] [assembly: ComVisible(false)] [assembly: Guid("963cf4f8-ba02-49fc-8884-97e781e6bc18")] [assembly: AssemblyFileVersion("0.11.0")] [assembly: TargetFramework(".NETFramework,Version=v4.8.1", FrameworkDisplayName = ".NET Framework 4.8.1")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("0.11.0.0")] [module: UnverifiableCode] [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.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)] internal sealed class NullableAttribute : Attribute { public readonly byte[] NullableFlags; public NullableAttribute(byte P_0) { NullableFlags = new byte[1] { P_0 }; } public NullableAttribute(byte[] P_0) { NullableFlags = P_0; } } [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] internal sealed class NullableContextAttribute : Attribute { public readonly byte Flag; public NullableContextAttribute(byte P_0) { Flag = P_0; } } [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; } } } public static class PlayerExtensions { public static ZDO GetZDO(this Player player) { return ((Character)player).m_nview.GetZDO(); } } namespace Common { public class ConfigPositionedElement : MonoBehaviour { public ConfigEntry<TextAnchor> AnchorConfig; public ConfigEntry<Vector2> PositionConfig; protected RectTransform _rt; protected TextAnchor _currentAnchor; public virtual void Awake() { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Expected O, but got Unknown _rt = (RectTransform)((Component)this).transform; EnsureCorrectPosition(); } public virtual void Update() { EnsureCorrectPosition(); } public virtual void EnsureCorrectPosition() { //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_0053: Unknown result type (might be due to invalid IL or missing references) //IL_0058: Unknown result type (might be due to invalid IL or missing references) //IL_0059: Unknown result type (might be due to invalid IL or missing references) //IL_0083: Expected I4, but got Unknown //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_00ab: Unknown result type (might be due to invalid IL or missing references) //IL_00b1: Unknown result type (might be due to invalid IL or missing references) //IL_00b2: Unknown result type (might be due to invalid IL or missing references) //IL_00b3: Unknown result type (might be due to invalid IL or missing references) //IL_00b9: Unknown result type (might be due to invalid IL or missing references) //IL_00e7: 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_00ee: Unknown result type (might be due to invalid IL or missing references) //IL_00ef: Unknown result type (might be due to invalid IL or missing references) //IL_00f5: Unknown result type (might be due to invalid IL or missing references) //IL_0123: Unknown result type (might be due to invalid IL or missing references) //IL_0129: Unknown result type (might be due to invalid IL or missing references) //IL_012a: Unknown result type (might be due to invalid IL or missing references) //IL_012b: Unknown result type (might be due to invalid IL or missing references) //IL_0131: Unknown result type (might be due to invalid IL or missing references) //IL_015f: Unknown result type (might be due to invalid IL or missing references) //IL_0165: Unknown result type (might be due to invalid IL or missing references) //IL_0166: Unknown result type (might be due to invalid IL or missing references) //IL_0167: Unknown result type (might be due to invalid IL or missing references) //IL_016d: Unknown result type (might be due to invalid IL or missing references) //IL_019b: Unknown result type (might be due to invalid IL or missing references) //IL_01a1: Unknown result type (might be due to invalid IL or missing references) //IL_01a2: Unknown result type (might be due to invalid IL or missing references) //IL_01a3: Unknown result type (might be due to invalid IL or missing references) //IL_01a9: Unknown result type (might be due to invalid IL or missing references) //IL_01d7: Unknown result type (might be due to invalid IL or missing references) //IL_01dd: Unknown result type (might be due to invalid IL or missing references) //IL_01de: Unknown result type (might be due to invalid IL or missing references) //IL_01df: Unknown result type (might be due to invalid IL or missing references) //IL_01e5: Unknown result type (might be due to invalid IL or missing references) //IL_0213: Unknown result type (might be due to invalid IL or missing references) //IL_0219: Unknown result type (might be due to invalid IL or missing references) //IL_021a: Unknown result type (might be due to invalid IL or missing references) //IL_021b: Unknown result type (might be due to invalid IL or missing references) //IL_0221: Unknown result type (might be due to invalid IL or missing references) //IL_024c: Unknown result type (might be due to invalid IL or missing references) //IL_0252: Unknown result type (might be due to invalid IL or missing references) //IL_0253: Unknown result type (might be due to invalid IL or missing references) //IL_0254: Unknown result type (might be due to invalid IL or missing references) //IL_025a: Unknown result type (might be due to invalid IL or missing references) //IL_0285: Unknown result type (might be due to invalid IL or missing references) //IL_028b: Unknown result type (might be due to invalid IL or missing references) //IL_028c: Unknown result type (might be due to invalid IL or missing references) //IL_028d: Unknown result type (might be due to invalid IL or missing references) //IL_0293: Unknown result type (might be due to invalid IL or missing references) //IL_02a5: Unknown result type (might be due to invalid IL or missing references) if (AnchorConfig != null && PositionConfig != null && (_currentAnchor != AnchorConfig.Value || !(_rt.anchoredPosition == PositionConfig.Value))) { _currentAnchor = AnchorConfig.Value; TextAnchor currentAnchor = _currentAnchor; Vector2 val = default(Vector2); switch ((int)currentAnchor) { case 0: { RectTransform rt25 = _rt; RectTransform rt26 = _rt; RectTransform rt27 = _rt; ((Vector2)(ref val))..ctor(0f, 1f); rt27.anchorMax = val; Vector2 pivot = (rt26.anchorMin = val); rt25.pivot = pivot; break; } case 1: { RectTransform rt22 = _rt; RectTransform rt23 = _rt; RectTransform rt24 = _rt; ((Vector2)(ref val))..ctor(0.5f, 1f); rt24.anchorMax = val; Vector2 pivot = (rt23.anchorMin = val); rt22.pivot = pivot; break; } case 2: { RectTransform rt19 = _rt; RectTransform rt20 = _rt; RectTransform rt21 = _rt; ((Vector2)(ref val))..ctor(1f, 1f); rt21.anchorMax = val; Vector2 pivot = (rt20.anchorMin = val); rt19.pivot = pivot; break; } case 3: { RectTransform rt16 = _rt; RectTransform rt17 = _rt; RectTransform rt18 = _rt; ((Vector2)(ref val))..ctor(0f, 0.5f); rt18.anchorMax = val; Vector2 pivot = (rt17.anchorMin = val); rt16.pivot = pivot; break; } case 4: { RectTransform rt13 = _rt; RectTransform rt14 = _rt; RectTransform rt15 = _rt; ((Vector2)(ref val))..ctor(0.5f, 0.5f); rt15.anchorMax = val; Vector2 pivot = (rt14.anchorMin = val); rt13.pivot = pivot; break; } case 5: { RectTransform rt10 = _rt; RectTransform rt11 = _rt; RectTransform rt12 = _rt; ((Vector2)(ref val))..ctor(1f, 0.5f); rt12.anchorMax = val; Vector2 pivot = (rt11.anchorMin = val); rt10.pivot = pivot; break; } case 6: { RectTransform rt7 = _rt; RectTransform rt8 = _rt; RectTransform rt9 = _rt; ((Vector2)(ref val))..ctor(0f, 0f); rt9.anchorMax = val; Vector2 pivot = (rt8.anchorMin = val); rt7.pivot = pivot; break; } case 7: { RectTransform rt4 = _rt; RectTransform rt5 = _rt; RectTransform rt6 = _rt; ((Vector2)(ref val))..ctor(0.5f, 0f); rt6.anchorMax = val; Vector2 pivot = (rt5.anchorMin = val); rt4.pivot = pivot; break; } case 8: { RectTransform rt = _rt; RectTransform rt2 = _rt; RectTransform rt3 = _rt; ((Vector2)(ref val))..ctor(1f, 0f); rt3.anchorMax = val; Vector2 pivot = (rt2.anchorMin = val); rt.pivot = pivot; break; } } _rt.anchoredPosition = PositionConfig.Value; } } } [Serializable] public class RecipeRequirementConfig { public string item = ""; public int amount = 1; } [Serializable] public class RecipeConfig { public string name = ""; public string item = ""; public int amount = 1; public string craftingStation = ""; public int minStationLevel = 1; public bool enabled = true; public string repairStation = ""; public List<RecipeRequirementConfig> resources = new List<RecipeRequirementConfig>(); } [Serializable] public class RecipesConfig { public List<RecipeConfig> recipes = new List<RecipeConfig>(); } public static class GameObjectExtensions { public static RectTransform RectTransform(this GameObject go) { Transform transform = go.transform; return (RectTransform)(object)((transform is RectTransform) ? transform : null); } public static T RequireComponent<T>(this GameObject go) where T : Component { T component = go.GetComponent<T>(); if (!((Object)(object)component == (Object)null)) { return component; } return go.AddComponent<T>(); } } public class GotDestroyed : MonoBehaviour { public void OnDisable() { Debug.LogError((object)("I got destroyed! (" + ((Object)((Component)this).gameObject).name + ")")); Debug.Log((object)Environment.StackTrace); } } public class MultiValueDictionary<TKey, TValue> : Dictionary<TKey, List<TValue>> { public void Add(TKey key, TValue value) { if (!TryGetValue(key, out var value2)) { value2 = new List<TValue>(); Add(key, value2); } value2.Add(value); } public bool ContainsValue(TKey key, TValue value) { if (TryGetValue(key, out var value2)) { return value2.Contains(value); } return false; } public void Remove(TKey key, TValue value) { if (TryGetValue(key, out var value2)) { value2.Remove(value); if (value2.Count <= 0) { Remove(key); } } } public void Merge(MultiValueDictionary<TKey, TValue> toMergeWith) { if (toMergeWith == null) { return; } foreach (KeyValuePair<TKey, List<TValue>> item in toMergeWith) { foreach (TValue item2 in item.Value) { Add(item.Key, item2); } } } public List<TValue> GetValues(TKey key, bool returnEmptySet = false) { if (!TryGetValue(key, out var value) && returnEmptySet) { return new List<TValue>(); } return value; } } public static class PrefabCreator { public static ManualLogSource Logger; public static Dictionary<string, CraftingStation> CraftingStations; public static T RequireComponent<T>(GameObject go) where T : Component { T val = go.GetComponent<T>(); if ((Object)(object)val == (Object)null) { val = go.AddComponent<T>(); } return val; } public static void Reset() { CraftingStations = null; } private static void InitCraftingStations() { if (CraftingStations != null) { return; } CraftingStations = new Dictionary<string, CraftingStation>(); foreach (Recipe recipe in ObjectDB.instance.m_recipes) { if ((Object)(object)recipe.m_craftingStation != (Object)null && !CraftingStations.ContainsKey(((Object)recipe.m_craftingStation).name)) { CraftingStations.Add(((Object)recipe.m_craftingStation).name, recipe.m_craftingStation); } } } public static Recipe CreateRecipe(string name, string itemId, RecipeConfig recipeConfig) { //IL_0200: Unknown result type (might be due to invalid IL or missing references) //IL_0205: Unknown result type (might be due to invalid IL or missing references) //IL_0212: Unknown result type (might be due to invalid IL or missing references) //IL_0224: Expected O, but got Unknown InitCraftingStations(); GameObject itemPrefab = ObjectDB.instance.GetItemPrefab(itemId); if ((Object)(object)itemPrefab == (Object)null) { ManualLogSource logger = Logger; if (logger != null) { logger.LogWarning((object)("[PrefabCreator] Could not find item prefab (" + itemId + ")")); } return null; } Recipe val = ScriptableObject.CreateInstance<Recipe>(); ((Object)val).name = name; val.m_amount = recipeConfig.amount; val.m_minStationLevel = recipeConfig.minStationLevel; val.m_item = itemPrefab.GetComponent<ItemDrop>(); val.m_enabled = recipeConfig.enabled; if (!string.IsNullOrEmpty(recipeConfig.craftingStation)) { if (!CraftingStations.ContainsKey(recipeConfig.craftingStation)) { ManualLogSource logger2 = Logger; if (logger2 != null) { logger2.LogWarning((object)("[PrefabCreator] Could not find crafting station (" + itemId + "): " + recipeConfig.craftingStation)); } string text = string.Join(", ", CraftingStations.Keys); ManualLogSource logger3 = Logger; if (logger3 != null) { logger3.LogInfo((object)("[PrefabCreator] Available Stations: " + text)); } } else { val.m_craftingStation = CraftingStations[recipeConfig.craftingStation]; } } if (!string.IsNullOrEmpty(recipeConfig.repairStation)) { if (!CraftingStations.ContainsKey(recipeConfig.repairStation)) { ManualLogSource logger4 = Logger; if (logger4 != null) { logger4.LogWarning((object)("[PrefabCreator] Could not find repair station (" + itemId + "): " + recipeConfig.repairStation)); } string text2 = string.Join(", ", CraftingStations.Keys); ManualLogSource logger5 = Logger; if (logger5 != null) { logger5.LogInfo((object)("[PrefabCreator] Available Stations: " + text2)); } } else { val.m_repairStation = CraftingStations[recipeConfig.repairStation]; } } List<Requirement> list = new List<Requirement>(); foreach (RecipeRequirementConfig resource in recipeConfig.resources) { GameObject itemPrefab2 = ObjectDB.instance.GetItemPrefab(resource.item); if ((Object)(object)itemPrefab2 == (Object)null) { ManualLogSource logger6 = Logger; if (logger6 != null) { logger6.LogError((object)("[PrefabCreator] Could not find requirement item (" + itemId + "): " + resource.item)); } } else { list.Add(new Requirement { m_amount = resource.amount, m_resItem = itemPrefab2.GetComponent<ItemDrop>() }); } } val.m_resources = list.ToArray(); return val; } public static Recipe AddNewRecipe(string name, string itemId, RecipeConfig recipeConfig) { Recipe val = CreateRecipe(name, itemId, recipeConfig); if ((Object)(object)val == (Object)null) { ManualLogSource logger = Logger; if (logger != null) { logger.LogError((object)("[PrefabCreator] Failed to create recipe (" + name + ")")); } return null; } return AddNewRecipe(val); } public static Recipe AddNewRecipe(Recipe recipe) { int num = ObjectDB.instance.m_recipes.RemoveAll((Recipe x) => ((Object)x).name == ((Object)recipe).name); if (num > 0) { ManualLogSource logger = Logger; if (logger != null) { logger.LogInfo((object)$"[PrefabCreator] Removed recipe ({((Object)recipe).name}): {num}"); } } ObjectDB.instance.m_recipes.Add(recipe); ManualLogSource logger2 = Logger; if (logger2 != null) { logger2.LogInfo((object)("[PrefabCreator] Added recipe: " + ((Object)recipe).name)); } return recipe; } } [Serializable] public struct SerializableVector3 { public float x; public float y; public float z; public SerializableVector3(float x, float y, float z) { this.x = x; this.y = y; this.z = z; } public void ToPackage(ZPackage pkg) { pkg.Write(x); pkg.Write(y); pkg.Write(z); } public static SerializableVector3 FromPackage(ZPackage pkg) { SerializableVector3 result = default(SerializableVector3); result.x = pkg.ReadSingle(); result.y = pkg.ReadSingle(); result.z = pkg.ReadSingle(); return result; } public override string ToString() { return $"[{x}, {y}, {z}]"; } public static implicit operator Vector3(SerializableVector3 s) { //IL_0012: Unknown result type (might be due to invalid IL or missing references) return new Vector3(s.x, s.y, s.z); } public static implicit operator SerializableVector3(Vector3 v) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) return new SerializableVector3(v.x, v.y, v.z); } public static SerializableVector3 operator +(SerializableVector3 a, SerializableVector3 b) { return new SerializableVector3(a.x + b.x, a.y + b.y, a.z + b.z); } public static SerializableVector3 operator -(SerializableVector3 a, SerializableVector3 b) { return new SerializableVector3(a.x - b.x, a.y - b.y, a.z - b.z); } public static SerializableVector3 operator -(SerializableVector3 a) { return new SerializableVector3(0f - a.x, 0f - a.y, 0f - a.z); } public static SerializableVector3 operator *(SerializableVector3 a, float m) { return new SerializableVector3(a.x * m, a.y * m, a.z * m); } public static SerializableVector3 operator *(float m, SerializableVector3 a) { return new SerializableVector3(a.x * m, a.y * m, a.z * m); } public static SerializableVector3 operator /(SerializableVector3 a, float d) { return new SerializableVector3(a.x / d, a.y / d, a.z / d); } } public static class Utils { public static void PrintObject(object o) { if (o == null) { Debug.Log((object)"null"); } else { Debug.Log((object)(o?.ToString() + ":\n" + GetObjectString(o, " "))); } } public static string GetObjectString(object obj, string indent) { string text = ""; foreach (FieldInfo item in from f in obj.GetType().GetFields() where f.IsPublic select f) { object value = item.GetValue(obj); string text2 = ((value == null) ? "null" : value.ToString()); text = text + "\n" + indent + item.Name + ": " + text2; } return text; } public static string RemoveBetween(string s, string from, string to) { int num = 0; while (num >= 0) { num = s.IndexOf(from, StringComparison.InvariantCulture); if (num < 0) { break; } int num2 = s.IndexOf(to, num, StringComparison.InvariantCulture); if (num2 < 0) { break; } s = s.Remove(num, num2 - num + to.Length); } return s; } public static void CopyFields(object originalObject, object cloneObject, Type typeToReflect, BindingFlags bindingFlags = BindingFlags.Instance | BindingFlags.Public) { FieldInfo[] fields = typeToReflect.GetFields(bindingFlags); foreach (FieldInfo obj in fields) { object value = obj.GetValue(originalObject); obj.SetValue(cloneObject, value); } } public static bool IsServer() { //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Invalid comparison between Unknown and I4 if (!ZNet.instance.IsServer() && !ZNet.instance.IsDedicated()) { return (int)SystemInfo.graphicsDeviceType == 4; } return true; } } public static class ArrayUtils { public static bool IsNullOrEmpty<T>(T[] a) { if (a != null) { return a.Length == 0; } return true; } public static T[] Copy<T>(T[] other) { return other?.ToArray(); } } public static class ListExtensions { public static bool TryFind<T>(this List<T> list, Predicate<T> predicate, out T result) { int num = list.FindIndex(predicate); if (num != -1) { result = list[num]; return true; } result = default(T); return false; } } } namespace EpicLoot { public static class API { private enum SecretStashType { Materials, RandomItems, OtherItems, Gamble, Sale } private static class RuntimeRegistry { private static readonly Dictionary<string, object> registry = new Dictionary<string, object>(); private static int counter; public static string Register(object obj) { string name = obj.GetType().Name; string text = $"{name}_obj_{++counter}"; registry[text] = obj; return text; } public static bool TryGetValue<T>(string key, out T value) where T : class { if (registry.TryGetValue(key, out object value2) && value2 is T val) { value = val; return true; } value = null; return false; } [PublicAPI] public static int GetCount() { return counter; } [PublicAPI] public static List<string> GetRegisteredKeys() { return registry.Keys.ToList(); } } private class AbilityProxyDefinition { public readonly AbilityDefinition Ability; public readonly Dictionary<string, Delegate> Delegates; public AbilityProxyDefinition(AbilityDefinition ability, Dictionary<string, Delegate> delegates) { Ability = ability; Delegates = delegates; } } public class AbilityProxy : Ability { public Dictionary<string, Delegate> _callbacks = new Dictionary<string, Delegate>(); private T? GetCallback<T>(string name) where T : Delegate { if (_callbacks.TryGetValue(name, out Delegate value) && value is T result) { return result; } return null; } public override void Initialize(AbilityDefinition abilityDef, Player player) { base.Initialize(abilityDef, player); GetCallback<Action<Player, string, float>>("Initialize")?.Invoke(player, abilityDef.ID, abilityDef.Cooldown); } public override void OnUpdate() { Action callback = GetCallback<Action>("OnUpdate"); if (callback == null) { base.OnUpdate(); } else { callback(); } } protected override bool ShouldTrigger() { return GetCallback<Func<bool>>("ShouldTrigger")?.Invoke() ?? base.ShouldTrigger(); } public override bool IsOnCooldown() { return GetCallback<Func<bool>>("IsOnCooldown")?.Invoke() ?? base.IsOnCooldown(); } public override float TimeUntilCooldownEnds() { return GetCallback<Func<float>>("TimeUntilCooldownEnds")?.Invoke() ?? base.TimeUntilCooldownEnds(); } public override float PercentCooldownComplete() { return GetCallback<Func<float>>("PercentCooldownComplete")?.Invoke() ?? base.PercentCooldownComplete(); } public override bool CanActivate() { return GetCallback<Func<bool>>("CanActivate")?.Invoke() ?? base.CanActivate(); } public override void TryActivate() { Action callback = GetCallback<Action>("TryActivate"); if (callback == null) { base.TryActivate(); } else { callback(); } } protected override void Activate() { Action callback = GetCallback<Action>("Activate"); if (callback == null) { base.Activate(); } else { callback(); } } protected override void ActivateCustomAction() { Action callback = GetCallback<Action>("ActivateCustomAction"); if (callback == null) { base.ActivateCustomAction(); } else { callback(); } } protected override void ActivateStatusEffectAction() { Action callback = GetCallback<Action>("ActivateStatusEffectAction"); if (callback == null) { base.ActivateStatusEffectAction(); } else { callback(); } } protected override bool HasCooldown() { return GetCallback<Func<bool>>("HasCooldown")?.Invoke() ?? base.HasCooldown(); } protected override void SetCooldownEndTime(float cooldownEndTime) { Action<float> callback = GetCallback<Action<float>>("SetCooldownEndTime"); if (callback == null) { base.SetCooldownEndTime(cooldownEndTime); } else { callback(cooldownEndTime); } } public override float GetCooldownEndTime() { return GetCallback<Func<float>>("GetCooldownEndTime")?.Invoke() ?? base.GetCooldownEndTime(); } } private static bool ShowLogs; private static readonly Dictionary<string, MagicItemEffectDefinition> ExternalMagicItemEffectDefinitions; private static readonly Dictionary<string, AbilityDefinition> ExternalAbilities; private static readonly Dictionary<ItemRarity, List<LegendaryInfo>> ExternalLegendaryItems; private static readonly Dictionary<ItemRarity, List<LegendarySetInfo>> ExternalLegendarySets; private static readonly Dictionary<string, Object> ExternalAssets; private static readonly List<MaterialConversion> ExternalMaterialConversions; private static readonly List<RecipeConfig> ExternalRecipes; private static readonly List<DisenchantProductsConfig> ExternalSacrifices; private static readonly List<BountyTargetConfig> ExternalBountyTargets; private static readonly Dictionary<SecretStashType, List<SecretStashItemConfig>> ExternalSecretStashItems; private static readonly List<TreasureMapBiomeInfoConfig> ExternalTreasureMaps; private static readonly Dictionary<string, Dictionary<string, Delegate>> AbilityProxies; private static event Action<string>? OnReload; private static event Action<string>? OnError; private static event Action<string>? OnDebug; static API() { ShowLogs = false; ExternalMagicItemEffectDefinitions = new Dictionary<string, MagicItemEffectDefinition>(); ExternalAbilities = new Dictionary<string, AbilityDefinition>(); ExternalLegendaryItems = new Dictionary<ItemRarity, List<LegendaryInfo>>(); ExternalLegendarySets = new Dictionary<ItemRarity, List<LegendarySetInfo>>(); ExternalAssets = new Dictionary<string, Object>(); ExternalMaterialConversions = new List<MaterialConversion>(); ExternalRecipes = new List<RecipeConfig>(); ExternalSacrifices = new List<DisenchantProductsConfig>(); ExternalBountyTargets = new List<BountyTargetConfig>(); ExternalSecretStashItems = new Dictionary<SecretStashType, List<SecretStashItemConfig>>(); ExternalTreasureMaps = new List<TreasureMapBiomeInfoConfig>(); AbilityProxies = new Dictionary<string, Dictionary<string, Delegate>>(); MagicItemEffectDefinitions.OnSetupMagicItemEffectDefinitions += ReloadExternalMagicEffects; UniqueLegendaryHelper.OnSetupLegendaryItemConfig += ReloadExternalLegendary; AbilityDefinitions.OnSetupAbilityDefinitions += ReloadExternalAbilities; MaterialConversions.OnSetupMaterialConversions += ReloadExternalMaterialConversions; RecipesHelper.OnSetupRecipeConfig += ReloadExternalRecipes; EnchantCostsHelper.OnSetupEnchantingCosts += ReloadExternalSacrifices; AdventureDataManager.OnSetupAdventureData += ReloadExternalAdventureData; OnReload += delegate(string message) { if (ShowLogs) { EpicLoot.Log(message); } }; OnError += delegate(string message) { if (ShowLogs) { EpicLoot.LogWarning(message); } }; OnDebug += delegate(string message) { if (ShowLogs) { EpicLoot.LogWarningForce(message); } }; } private static void ReloadExternalAdventureData() { ReloadExternalBounties(); ReloadExternalSecretStashItems(); ReloadExternalTreasures(); } private static void ReloadExternalSecretStashItems() { foreach (KeyValuePair<SecretStashType, List<SecretStashItemConfig>> externalSecretStashItem in ExternalSecretStashItems) { switch (externalSecretStashItem.Key) { case SecretStashType.Materials: AdventureDataManager.Config.SecretStash.Materials.AddRange(externalSecretStashItem.Value); break; case SecretStashType.OtherItems: AdventureDataManager.Config.SecretStash.OtherItems.AddRange(externalSecretStashItem.Value); break; case SecretStashType.RandomItems: AdventureDataManager.Config.SecretStash.RandomItems.AddRange(externalSecretStashItem.Value); break; case SecretStashType.Gamble: AdventureDataManager.Config.Gamble.GambleCosts.AddRange(externalSecretStashItem.Value); break; case SecretStashType.Sale: AdventureDataManager.Config.TreasureMap.SaleItems.AddRange(externalSecretStashItem.Value); break; } } } private static void ReloadExternalTreasures() { foreach (TreasureMapBiomeInfoConfig externalTreasureMap in ExternalTreasureMaps) { AdventureDataManager.Config.TreasureMap.BiomeInfo.Add(externalTreasureMap); } API.OnReload?.Invoke("Reloaded external treasures"); } private static void ReloadExternalBounties() { AdventureDataManager.Config.Bounties.Targets.AddRange(ExternalBountyTargets); API.OnReload?.Invoke("Reloaded external bounties"); } private static void ReloadExternalSacrifices() { EnchantCostsHelper.Config.DisenchantProducts.AddRange(ExternalSacrifices); API.OnReload?.Invoke("Reloaded external sacrifices"); } private static void ReloadExternalRecipes() { RecipesHelper.Config.recipes.RemoveAll(ExternalRecipes); RecipesHelper.Config.recipes.AddRange(ExternalRecipes); API.OnReload?.Invoke("Reloaded external recipes"); } private static void ReloadExternalMaterialConversions() { foreach (MaterialConversion externalMaterialConversion in ExternalMaterialConversions) { MaterialConversions.Config.MaterialConversions.Add(externalMaterialConversion); } API.OnReload?.Invoke("Reloaded external material conversions"); } private static void ReloadExternalMagicEffects() { foreach (MagicItemEffectDefinition value in ExternalMagicItemEffectDefinitions.Values) { MagicItemEffectDefinitions.Add(value); } API.OnReload?.Invoke("Reloaded external magic effects"); } private static void ReloadExternalAbilities() { foreach (KeyValuePair<string, AbilityDefinition> externalAbility in ExternalAbilities) { AbilityDefinitions.Config.Abilities.Add(externalAbility.Value); } API.OnReload?.Invoke("Reloaded external abilities"); } private static void ReloadExternalLegendary() { foreach (KeyValuePair<ItemRarity, List<LegendaryInfo>> externalLegendaryItem in ExternalLegendaryItems) { switch (externalLegendaryItem.Key) { case ItemRarity.Legendary: UniqueLegendaryHelper.Config.LegendaryItems.AddRange(externalLegendaryItem.Value); break; case ItemRarity.Mythic: UniqueLegendaryHelper.Config.MythicItems.AddRange(externalLegendaryItem.Value); break; } } foreach (KeyValuePair<ItemRarity, List<LegendarySetInfo>> externalLegendarySet in ExternalLegendarySets) { switch (externalLegendarySet.Key) { case ItemRarity.Legendary: UniqueLegendaryHelper.Config.LegendarySets.AddRange(externalLegendarySet.Value); break; case ItemRarity.Mythic: UniqueLegendaryHelper.Config.MythicSets.AddRange(externalLegendarySet.Value); break; } } API.OnReload?.Invoke("Reloaded external legendary abilities"); } public static void ReloadExternalAssets() { foreach (KeyValuePair<string, Object> externalAsset in ExternalAssets) { EpicLoot._assetCache[externalAsset.Key] = externalAsset.Value; } API.OnReload?.Invoke("Reloaded external assets"); } [PublicAPI] public static string? AddTreasureMap(string json) { try { TreasureMapBiomeInfoConfig treasureMapBiomeInfoConfig = JsonConvert.DeserializeObject<TreasureMapBiomeInfoConfig>(json); if (treasureMapBiomeInfoConfig == null) { return null; } ExternalTreasureMaps.Add(treasureMapBiomeInfoConfig); AdventureDataManager.Config.TreasureMap.BiomeInfo.Add(treasureMapBiomeInfoConfig); return RuntimeRegistry.Register(treasureMapBiomeInfoConfig); } catch { API.OnError?.Invoke("Failed to parse treasure map from external plugin"); return null; } } [PublicAPI] public static bool UpdateTreasureMap(string key, string json) { if (!RuntimeRegistry.TryGetValue<TreasureMapBiomeInfoConfig>(key, out var value)) { return false; } try { TreasureMapBiomeInfoConfig source = JsonConvert.DeserializeObject<TreasureMapBiomeInfoConfig>(json); value.CopyFieldsFrom(source); return true; } catch { API.OnError?.Invoke("Failed to parse treasure map from external plugin"); return false; } } [PublicAPI] public static string? AddSecretStashItem(string type, string json) { try { if (!Enum.TryParse<SecretStashType>(type, ignoreCase: true, out var result)) { return null; } SecretStashItemConfig secretStashItemConfig = JsonConvert.DeserializeObject<SecretStashItemConfig>(json); if (secretStashItemConfig == null) { return null; } ExternalSecretStashItems.AddOrSet(result, secretStashItemConfig); switch (result) { case SecretStashType.Materials: AdventureDataManager.Config.SecretStash.Materials.Add(secretStashItemConfig); break; case SecretStashType.OtherItems: AdventureDataManager.Config.SecretStash.OtherItems.Add(secretStashItemConfig); break; case SecretStashType.RandomItems: AdventureDataManager.Config.SecretStash.RandomItems.Add(secretStashItemConfig); break; case SecretStashType.Gamble: AdventureDataManager.Config.Gamble.GambleCosts.Add(secretStashItemConfig); break; case SecretStashType.Sale: AdventureDataManager.Config.TreasureMap.SaleItems.Add(secretStashItemConfig); break; } return RuntimeRegistry.Register(secretStashItemConfig); } catch { API.OnError?.Invoke("Failed to parse secret stash from external plugin"); return null; } } [PublicAPI] public static bool UpdateSecretStashItem(string key, string json) { if (!RuntimeRegistry.TryGetValue<SecretStashItemConfig>(key, out var value)) { return false; } SecretStashItemConfig secretStashItemConfig = JsonConvert.DeserializeObject<SecretStashItemConfig>(json); if (secretStashItemConfig == null) { return false; } value.CopyFieldsFrom(secretStashItemConfig); return true; } [PublicAPI] public static string? AddMagicEffect(string json) { try { MagicItemEffectDefinition magicItemEffectDefinition = JsonConvert.DeserializeObject<MagicItemEffectDefinition>(json); if (magicItemEffectDefinition == null) { return null; } MagicItemEffectDefinitions.Add(magicItemEffectDefinition); ExternalMagicItemEffectDefinitions[magicItemEffectDefinition.Type] = magicItemEffectDefinition; return RuntimeRegistry.Register(magicItemEffectDefinition); } catch { API.OnError?.Invoke("Failed to parse magic effect from external plugin"); return null; } } [PublicAPI] public static bool UpdateMagicEffect(string key, string json) { if (!RuntimeRegistry.TryGetValue<MagicItemEffectDefinition>(key, out var value)) { return false; } MagicItemEffectDefinition magicItemEffectDefinition = JsonConvert.DeserializeObject<MagicItemEffectDefinition>(json); if (magicItemEffectDefinition == null) { return false; } value.CopyFieldsFrom(magicItemEffectDefinition); return true; } [PublicAPI] public static bool HasLegendaryItem(Player player, string legendaryItemID) { foreach (ItemData item in player.GetEquipment()) { if (item.IsMagic(out var magicItem) && magicItem.LegendaryID == legendaryItemID) { return true; } } return false; } [PublicAPI] public static bool HasLegendarySet(Player player, string legendarySetID, ref int count) { if (!UniqueLegendaryHelper.TryGetLegendarySetInfo(legendarySetID, out var legendarySetInfo, out var _)) { return false; } count = player.GetEquippedSetPieces(legendarySetID).Count; return count >= legendarySetInfo.LegendaryIDs.Count; } [PublicAPI] public static string GetMagicItemEffectDefinition(string type) { if (!MagicItemEffectDefinitions.AllDefinitions.TryGetValue(type, out var value)) { return ""; } return JsonConvert.SerializeObject((object)value); } [PublicAPI] public static float GetTotalActiveMagicEffectValue(Player? player, ItemData? item, string effectType, float scale) { return MagicEffectsHelper.GetTotalActiveMagicEffectValue(player, item, effectType, scale); } [PublicAPI] public static float GetTotalActiveMagicEffectValueForWeapon(Player? player, ItemData? item, string effectType, float scale) { return MagicEffectsHelper.GetTotalActiveMagicEffectValueForWeapon(player, item, effectType, scale); } [PublicAPI] public static bool HasActiveMagicEffect(Player? player, string effectType, ItemData? item, ref float effectValue) { return MagicEffectsHelper.HasActiveMagicEffect(player, item, effectType, out effectValue); } [PublicAPI] public static bool HasActiveMagicEffectOnWeapon(Player player, ItemData item, string effectType, ref float effectValue) { return MagicEffectsHelper.HasActiveMagicEffectOnWeapon(player, item, effectType, out effectValue); } [PublicAPI] public static float GetTotalActiveSetEffectValue(Player player, string effectType, float scale) { return MagicEffectsHelper.GetTotalActiveSetEffectValue(player, effectType, scale); } [PublicAPI] public static List<string> GetAllActiveMagicEffects(Player player, string? effectType = null) { List<MagicItemEffect> allActiveMagicEffects = player.GetAllActiveMagicEffects(effectType); List<string> list = new List<string>(); foreach (MagicItemEffect item in allActiveMagicEffects) { list.Add(JsonConvert.SerializeObject((object)item)); } return list; } [PublicAPI] public static List<string> GetAllActiveSetMagicEffects(Player player, string? effectType = null) { List<MagicItemEffect> allActiveSetMagicEffects = player.GetAllActiveSetMagicEffects(effectType); List<string> list = new List<string>(); foreach (MagicItemEffect item in allActiveSetMagicEffects) { list.Add(JsonConvert.SerializeObject((object)item)); } return list; } [PublicAPI] public static float GetTotalPlayerActiveMagicEffectValue(Player? player, string effectType, float scale, ItemData? ignoreThisItem = null) { return player.GetTotalActiveMagicEffectValue(effectType, scale, ignoreThisItem); } [PublicAPI] public static bool PlayerHasActiveMagicEffect(Player? player, string effectType, ref float effectValue, float scale = 1f, ItemData? ignoreThisItem = null) { return player.HasActiveMagicEffect(effectType, out effectValue, scale, ignoreThisItem); } [PublicAPI] public static string? AddLegendaryItem(string type, string json) { try { if (!Enum.TryParse<ItemRarity>(type, ignoreCase: true, out var result)) { return null; } LegendaryInfo legendaryInfo = JsonConvert.DeserializeObject<LegendaryInfo>(json); if (legendaryInfo == null) { return null; } switch (result) { case ItemRarity.Legendary: UniqueLegendaryHelper.Config.LegendaryItems.Add(legendaryInfo); UniqueLegendaryHelper.LegendaryInfo[legendaryInfo.ID] = legendaryInfo; break; case ItemRarity.Mythic: UniqueLegendaryHelper.Config.MythicItems.Add(legendaryInfo); UniqueLegendaryHelper.MythicInfo[legendaryInfo.ID] = legendaryInfo; break; } ExternalLegendaryItems.AddOrSet(result, legendaryInfo); return RuntimeRegistry.Register(legendaryInfo); } catch { API.OnError?.Invoke("Failed to parse legendary item from external plugin."); return null; } } [PublicAPI] public static bool UpdateLegendaryItem(string key, string json) { if (!RuntimeRegistry.TryGetValue<LegendaryInfo>(key, out var value)) { return false; } LegendaryInfo legendaryInfo = JsonConvert.DeserializeObject<LegendaryInfo>(json); if (legendaryInfo == null) { return false; } value.CopyFieldsFrom(legendaryInfo); return true; } [PublicAPI] public static string? AddLegendarySet(string type, string json) { try { if (!Enum.TryParse<ItemRarity>(type, ignoreCase: true, out var result)) { return null; } LegendarySetInfo legendarySetInfo = JsonConvert.DeserializeObject<LegendarySetInfo>(json); if (legendarySetInfo == null) { return null; } switch (result) { case ItemRarity.Legendary: UniqueLegendaryHelper.LegendarySets[legendarySetInfo.ID] = legendarySetInfo; UniqueLegendaryHelper.Config.LegendarySets.Add(legendarySetInfo); foreach (string legendaryID in legendarySetInfo.LegendaryIDs) { UniqueLegendaryHelper._legendaryItemsToSetMap[legendaryID] = legendarySetInfo; } break; case ItemRarity.Mythic: UniqueLegendaryHelper.MythicSets[legendarySetInfo.ID] = legendarySetInfo; UniqueLegendaryHelper.Config.MythicSets.Add(legendarySetInfo); foreach (string legendaryID2 in legendarySetInfo.LegendaryIDs) { UniqueLegendaryHelper._mythicItemsToSetMap[legendaryID2] = legendarySetInfo; } break; } ExternalLegendarySets.AddOrSet(result, legendarySetInfo); return RuntimeRegistry.Register(legendarySetInfo); } catch { API.OnError?.Invoke("Failed to parse legendary set from external plugin."); return null; } } [PublicAPI] public static bool UpdateLegendarySet(string key, string json) { if (!RuntimeRegistry.TryGetValue<LegendarySetInfo>(key, out var value)) { return false; } LegendarySetInfo legendarySetInfo = JsonConvert.DeserializeObject<LegendarySetInfo>(json); if (legendarySetInfo == null) { return false; } value.CopyFieldsFrom(legendarySetInfo); return true; } [PublicAPI] public static string? AddAbility(string json) { try { AbilityDefinition abilityDefinition = JsonConvert.DeserializeObject<AbilityDefinition>(json); if (abilityDefinition == null) { return null; } if (AbilityDefinitions.Abilities.ContainsKey(abilityDefinition.ID)) { API.OnError?.Invoke("Duplicate entry found for Abilities: " + abilityDefinition.ID + " when adding from external plugin."); return null; } ExternalAbilities[abilityDefinition.ID] = abilityDefinition; AbilityDefinitions.Config.Abilities.Add(abilityDefinition); AbilityDefinitions.Abilities[abilityDefinition.ID] = abilityDefinition; return RuntimeRegistry.Register(abilityDefinition); } catch { API.OnError?.Invoke("Failed to parse ability definition passed in through external plugin."); return null; } } [PublicAPI] public static bool UpdateAbility(string key, string json) { if (!RuntimeRegistry.TryGetValue<AbilityDefinition>(key, out var value)) { return false; } AbilityDefinition abilityDefinition = JsonConvert.DeserializeObject<AbilityDefinition>(json); if (abilityDefinition == null) { return false; } value.CopyFieldsFrom(abilityDefinition); return true; } [PublicAPI] public static bool RegisterAsset(string name, Object asset) { if (EpicLoot._assetCache.ContainsKey(name)) { API.OnError?.Invoke("Duplicate asset: " + name); return false; } EpicLoot._assetCache[name] = asset; ExternalAssets[name] = asset; return true; } [PublicAPI] public static string? AddMaterialConversion(string json) { try { MaterialConversion materialConversion = JsonConvert.DeserializeObject<MaterialConversion>(json); if (materialConversion == null) { return null; } ExternalMaterialConversions.Add(materialConversion); MaterialConversions.Config.MaterialConversions.Add(materialConversion); MaterialConversions.Conversions.Add(materialConversion.Type, materialConversion); return RuntimeRegistry.Register(materialConversion); } catch { API.OnError?.Invoke("Failed to parse material conversion passed in through external plugin."); return null; } } [PublicAPI] public static bool UpdateMaterialConversion(string key, string json) { if (!RuntimeRegistry.TryGetValue<MaterialConversion>(key, out var value)) { return false; } MaterialConversion materialConversion = JsonConvert.DeserializeObject<MaterialConversion>(json); if (materialConversion == null) { return false; } value.CopyFieldsFrom(materialConversion); return true; } [PublicAPI] public static string? AddRecipe(string json) { try { RecipeConfig recipeConfig = JsonConvert.DeserializeObject<RecipeConfig>(json); if (recipeConfig == null) { return null; } ExternalRecipes.Add(recipeConfig); RecipesHelper.Config.recipes.Add(recipeConfig); return RuntimeRegistry.Register(recipeConfig); } catch { API.OnError?.Invoke("Failed to parse recipe passed in through external plugin."); return null; } } [PublicAPI] public static string? AddRecipes(string json) { try { List<RecipeConfig> list = JsonConvert.DeserializeObject<List<RecipeConfig>>(json); if (list == null) { return null; } ExternalRecipes.AddRange(list); RecipesHelper.Config.recipes.AddRange(list); return RuntimeRegistry.Register(list); } catch { API.OnError?.Invoke("Failed to parse recipe from external plugin"); return null; } } [PublicAPI] public static bool UpdateRecipes(string key, string json) { if (!RuntimeRegistry.TryGetValue<List<RecipeConfig>>(key, out var value)) { return false; } List<RecipeConfig> list = JsonConvert.DeserializeObject<List<RecipeConfig>>(json); if (list == null) { return false; } ExternalRecipes.ReplaceThenAdd(value, list); RecipesHelper.Config.recipes.ReplaceThenAdd(value, list); return true; } [PublicAPI] public static string? AddSacrifice(string json) { try { DisenchantProductsConfig disenchantProductsConfig = JsonConvert.DeserializeObject<DisenchantProductsConfig>(json); if (disenchantProductsConfig == null) { return null; } ExternalSacrifices.Add(disenchantProductsConfig); EnchantCostsHelper.Config.DisenchantProducts.Add(disenchantProductsConfig); return RuntimeRegistry.Register(disenchantProductsConfig); } catch { API.OnError?.Invoke("Failed to parse sacrifice from external plugin"); return null; } } [PublicAPI] public static bool UpdateSacrifice(string key, string json) { if (!RuntimeRegistry.TryGetValue<DisenchantProductsConfig>(key, out var value)) { return false; } DisenchantProductsConfig source = JsonConvert.DeserializeObject<DisenchantProductsConfig>(json); value.CopyFieldsFrom(source); return true; } [PublicAPI] public static string? AddBountyTarget(string json) { try { BountyTargetConfig bountyTargetConfig = JsonConvert.DeserializeObject<BountyTargetConfig>(json); if (bountyTargetConfig == null) { return null; } ExternalBountyTargets.Add(bountyTargetConfig); AdventureDataManager.Config.Bounties.Targets.Add(bountyTargetConfig); return RuntimeRegistry.Register(bountyTargetConfig); } catch { API.OnError?.Invoke("Failed to parse bounty target passed in through external plugin."); return null; } } [PublicAPI] public static bool UpdateBountyTarget(string key, string json) { if (!RuntimeRegistry.TryGetValue<BountyTargetConfig>(key, out var value)) { return false; } BountyTargetConfig source = JsonConvert.DeserializeObject<BountyTargetConfig>(json); value.CopyFieldsFrom(source); return true; } private static void AddOrSet<T, V>(this Dictionary<T, List<V>> dict, T key, V value) { if (!dict.ContainsKey(key)) { dict[key] = new List<V>(); } dict[key].Add(value); } private static void CopyFieldsFrom<T>(this T target, T source) { FieldInfo[] fields = typeof(T).GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); foreach (FieldInfo obj in fields) { obj.SetValue(value: obj.GetValue(source), obj: target); } } private static void ReplaceThenAdd<T>(this List<T> list, List<T> original, List<T> replacements) { list.RemoveAll(original); list.AddRange(replacements); } private static void RemoveAll<T>(this List<T> list, List<T> itemsToRemove) { foreach (T item in itemsToRemove) { list.Remove(item); } } private static bool TryGetProxyAbility(string abilityID, out Dictionary<string, Delegate> proxy) { return AbilityProxies.TryGetValue(abilityID, out proxy); } [PublicAPI] public static string? RegisterProxyAbility(string json, Dictionary<string, Delegate> delegates) { try { AbilityDefinition abilityDefinition = JsonConvert.DeserializeObject<AbilityDefinition>(json); if (abilityDefinition == null) { return null; } AbilityFactory.Register(abilityDefinition.ID, typeof(AbilityProxy)); AbilityProxies[abilityDefinition.ID] = delegates; AbilityProxyDefinition obj = new AbilityProxyDefinition(abilityDefinition, delegates); AbilityDefinitions.Config.Abilities.Add(abilityDefinition); AbilityDefinitions.Abilities[abilityDefinition.ID] = abilityDefinition; return RuntimeRegistry.Register(obj); } catch { API.OnError?.Invoke("Failed to parse ability definition from external plugin"); return null; } } [PublicAPI] public static bool UpdateProxyAbility(string key, string json, Dictionary<string, Delegate> proxy) { if (!RuntimeRegistry.TryGetValue<AbilityProxyDefinition>(key, out var value)) { return false; } AbilityDefinition source = JsonConvert.DeserializeObject<AbilityDefinition>(json); value.Ability.CopyFieldsFrom(source); value.Delegates.CopyFieldsFrom<Dictionary<string, Delegate>>(proxy); return true; } public static bool InjectCallbacks(this AbilityProxy proxy, string abilityID) { if (!TryGetProxyAbility(abilityID, out Dictionary<string, Delegate> proxy2)) { return false; } proxy._callbacks = proxy2; return true; } } public enum LogLevel { Info, Warning, Error } public enum BossDropMode { Default, OnePerPlayerOnServer, OnePerPlayerNearBoss } public enum GatedBountyMode { Unlimited, BossKillUnlocksCurrentBiomeBounties, BossKillUnlocksNextBiomeBounties } public class EpicAssets { public AssetBundle AssetBundle; public Sprite EquippedSprite; public Sprite AugaEquippedSprite; public Sprite GenericSetItemSprite; public Sprite AugaSetItemSprite; public Sprite GenericItemBgSprite; public Sprite AugaItemBgSprite; public Sprite EnchantmentSparkle; public GameObject[] MagicItemLootBeamPrefabs = (GameObject[])(object)new GameObject[5]; public readonly Dictionary<string, GameObject[]> CraftingMaterialPrefabs = new Dictionary<string, GameObject[]>(); public Sprite SmallButtonEnchantOverlay; public Sprite DodgeBuffSprite; public AudioClip[] MagicItemDropSFX = (AudioClip[])(object)new AudioClip[5]; public AudioClip ItemLoopSFX; public AudioClip AugmentItemSFX; public GameObject MerchantPanel; public Sprite MapIconTreasureMap; public Sprite MapIconBounty; public AudioClip AbandonBountySFX; public AudioClip DoubleJumpSFX; public AudioClip DodgeBuffSFX; public AudioClip OffSetSFX; public GameObject DebugTextPrefab; public GameObject AbilityBar; public GameObject WelcomMessagePrefab; } public class PieceDef { public string Table; public string CraftingStation; public string ExtendStation; public List<RecipeRequirementConfig> Resources = new List<RecipeRequirementConfig>(); } [BepInPlugin("randyknapp.mods.epicloot", "Epic Loot", "0.12.2")] [BepInDependency(/*Could not decode attribute arguments.*/)] [NetworkCompatibility(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] public class EpicLoot : BaseUnityPlugin { public const string PluginId = "randyknapp.mods.epicloot"; public const string DisplayName = "Epic Loot"; public const string Version = "0.12.2"; private static string ConfigFileName = "randyknapp.mods.epicloot.cfg"; private static string ConfigFileFullPath; public static readonly List<ItemType> AllowedMagicItemTypes; public static readonly Dictionary<string, string> MagicItemColors; public static string[] MagicMaterials; public static string[] ItemNames; public static EpicAssets Assets; public static Dictionary<string, Object> _assetCache; public static bool AlwaysDropCheat; public const PinType BountyPinType = 800; public const PinType TreasureMapPinType = 801; public static bool HasAuga; public static bool AugaTooltipNoTextBoxes; private static EpicLoot _instance; private Harmony _harmony; private float _worldLuckFactor; internal ELConfig cfg; private DateTime _lastReloadTime; private const long RELOAD_DELAY = 10000000L; public static event Action AbilitiesInitialized; public static event Action LootTableLoaded; [UsedImplicitly] public void Awake() { _instance = this; Assembly executingAssembly = Assembly.GetExecutingAssembly(); Logger.LogInfo((object)"Checking for EIDF"); EIDFLegacy.CheckForExtendedItemFrameworkLoaded(_instance); Logger.LogInfo((object)"Loading unitylib"); LoadEmbeddedAssembly(executingAssembly, "EpicLoot-UnityLib.dll"); Logger.LogInfo((object)"Setting up config"); cfg = new ELConfig(((BaseUnityPlugin)this).Config); PrefabCreator.Logger = ((BaseUnityPlugin)this).Logger; Logger.LogInfo((object)"Applying config patches"); FilePatching.LoadAndApplyAllPatches(); Logger.LogInfo((object)"Loading abilities"); InitializeAbilities(); Logger.LogInfo((object)"Adding localization"); AddLocalizations(); Logger.LogInfo((object)"Loading assets"); LoadAssets(); Logger.LogInfo((object)"Starting enchanting controller"); EnchantingUIController.Initialize(); Logger.LogInfo((object)"Harmony Patching"); _harmony = Harmony.CreateAndPatchAll(Assembly.GetExecutingAssembly(), "randyknapp.mods.epicloot"); EpicLoot.LootTableLoaded?.Invoke(); RegisterMagicEffectEvents(); TerminalCommands.AddTerminalCommands(); SetupWatcher(); } private static void RegisterMagicEffectEvents() { MagicItemEffectDefinitions.OnSetupMagicItemEffectDefinitions += Riches_CharacterDrop_GenerateDropList_Patch.UpdateRichesOnEffectSetup; } private static void LoadEmbeddedAssembly(Assembly assembly, string assemblyName) { Stream manifestResourceStream = assembly.GetManifestResourceStream(assembly.GetName().Name + "." + assemblyName); if (manifestResourceStream == null) { LogErrorForce("Could not load embedded assembly (" + assemblyName + ")!"); return; } using (manifestResourceStream) { byte[] array = new byte[manifestResourceStream.Length]; manifestResourceStream.Read(array, 0, array.Length); Assembly.Load(array); } } private void AddLocalizations() { CustomLocalization localization = LocalizationManager.Instance.GetLocalization(); Log("Loading Localizations."); string[] manifestResourceNames = typeof(EpicLoot).Assembly.GetManifestResourceNames(); foreach (string text in manifestResourceNames) { if (text.Contains("localizations")) { string text2 = Regex.Replace(ReadEmbeddedResourceFile(text), "\\/\\/.*\\n", ""); string[] array = text.Split(new char[1] { '.' }); Log("Adding localization: " + array[2]); localization.AddJsonFile(array[2], text2); } } ELConfig.StartupProcessModifiedLocalizations(); } private static void InitializeAbilities() { MagicEffectType.Initialize(); EpicLoot.AbilitiesInitialized?.Invoke(); } public static void Log(string message) { if (ELConfig._loggingEnabled.Value && ELConfig._logLevel.Value <= LogLevel.Info) { ((BaseUnityPlugin)_instance).Logger.LogInfo((object)message); } } public static void LogWarning(string message) { if (ELConfig._loggingEnabled.Value && ELConfig._logLevel.Value <= LogLevel.Warning) { ((BaseUnityPlugin)_instance).Logger.LogWarning((object)message); } } public static void LogError(string message) { if (ELConfig._loggingEnabled.Value && ELConfig._logLevel.Value <= LogLevel.Error) { ((BaseUnityPlugin)_instance).Logger.LogError((object)message); } } public static void LogWarningForce(string message) { ((BaseUnityPlugin)_instance).Logger.LogWarning((object)message); } public static void LogErrorForce(string message) { ((BaseUnityPlugin)_instance).Logger.LogError((object)message); } private void LoadAssets() { AssetBundle val = LoadAssetBundle("epicloot"); if ((Object)(object)val == (Object)null || Assets == null) { LogErrorForce("Unable to load asset bundle! This mod will not behave as expected!"); return; } Assets.AssetBundle = val; Assets.EquippedSprite = val.LoadAsset<Sprite>("Equipped"); Assets.AugaEquippedSprite = val.LoadAsset<Sprite>("AugaEquipped"); Assets.GenericSetItemSprite = val.LoadAsset<Sprite>("GenericSetItemMarker"); Assets.AugaSetItemSprite = val.LoadAsset<Sprite>("AugaSetItem"); Assets.GenericItemBgSprite = val.LoadAsset<Sprite>("GenericItemBg"); Assets.AugaItemBgSprite = val.LoadAsset<Sprite>("AugaItemBG"); Assets.EnchantmentSparkle = val.LoadAsset<Sprite>("sparkle"); Assets.SmallButtonEnchantOverlay = val.LoadAsset<Sprite>("SmallButtonEnchantOverlay"); Assets.DodgeBuffSprite = val.LoadAsset<Sprite>("DodgeBuff"); Assets.MagicItemLootBeamPrefabs[0] = val.LoadAsset<GameObject>("MagicLootBeam"); Assets.MagicItemLootBeamPrefabs[1] = val.LoadAsset<GameObject>("RareLootBeam"); Assets.MagicItemLootBeamPrefabs[2] = val.LoadAsset<GameObject>("EpicLootBeam"); Assets.MagicItemLootBeamPrefabs[3] = val.LoadAsset<GameObject>("LegendaryLootBeam"); Assets.MagicItemLootBeamPrefabs[4] = val.LoadAsset<GameObject>("MythicLootBeam"); Assets.MagicItemDropSFX[0] = val.LoadAsset<AudioClip>("MagicItemDrop"); Assets.MagicItemDropSFX[1] = val.LoadAsset<AudioClip>("RareItemDrop"); Assets.MagicItemDropSFX[2] = val.LoadAsset<AudioClip>("EpicItemDrop"); Assets.MagicItemDropSFX[3] = val.LoadAsset<AudioClip>("LegendaryItemDrop"); Assets.MagicItemDropSFX[4] = val.LoadAsset<AudioClip>("MythicItemDrop"); Assets.ItemLoopSFX = val.LoadAsset<AudioClip>("ItemLoop"); Assets.AugmentItemSFX = val.LoadAsset<AudioClip>("AugmentItem"); Assets.MerchantPanel = val.LoadAsset<GameObject>("MerchantPanel"); Assets.MapIconTreasureMap = val.LoadAsset<Sprite>("TreasureMapIcon"); Assets.MapIconBounty = val.LoadAsset<Sprite>("MapIconBounty"); Assets.AbandonBountySFX = val.LoadAsset<AudioClip>("AbandonBounty"); Assets.DoubleJumpSFX = val.LoadAsset<AudioClip>("DoubleJump"); Assets.DodgeBuffSFX = val.LoadAsset<AudioClip>("evasionbuff"); Assets.OffSetSFX = val.LoadAsset<AudioClip>("offset"); Assets.DebugTextPrefab = val.LoadAsset<GameObject>("DebugText"); Assets.AbilityBar = val.LoadAsset<GameObject>("AbilityBar"); Assets.WelcomMessagePrefab = val.LoadAsset<GameObject>("WelcomeMessage"); LoadCraftingMaterialAssets(); LoadPieces(); LoadItems(); LoadBountySpawner(); PrefabManager.OnPrefabsRegistered += SetupAndvaranaut; ItemManager.OnItemsRegistered += SetupStatusEffects; LoadUnidentifiedItems(); MinimapManager.OnVanillaMapAvailable += delegate { AutoAddEnchantableItems.CheckAndAddAllEnchantableItems(); }; DodgeBuff.CreateMyStatusEffect(); } public static T LoadAsset<T>(string assetName) where T : Object { try { if (_assetCache.ContainsKey(assetName)) { return (T)(object)_assetCache[assetName]; } T val = Assets.AssetBundle.LoadAsset<T>(assetName); _assetCache.Add(assetName, (Object)(object)val); return val; } catch (Exception ex) { LogErrorForce("Error loading asset (" + assetName + "): " + ex.Message); return default(T); } } private static void LoadPieces() { //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Expected O, but got Unknown //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_0046: Unknown result type (might be due to invalid IL or missing references) //IL_0051: Unknown result type (might be due to invalid IL or missing references) //IL_0059: Unknown result type (might be due to invalid IL or missing references) //IL_0061: Expected O, but got Unknown //IL_0063: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Unknown result type (might be due to invalid IL or missing references) //IL_0073: Unknown result type (might be due to invalid IL or missing references) //IL_007a: Unknown result type (might be due to invalid IL or missing references) //IL_0082: Expected O, but got Unknown //IL_0084: Unknown result type (might be due to invalid IL or missing references) //IL_0089: Unknown result type (might be due to invalid IL or missing references) //IL_0094: Unknown result type (might be due to invalid IL or missing references) //IL_009b: Unknown result type (might be due to invalid IL or missing references) //IL_00a3: Expected O, but got Unknown //IL_00a5: Unknown result type (might be due to invalid IL or missing references) //IL_00aa: Unknown result type (might be due to invalid IL or missing references) //IL_00b5: Unknown result type (might be due to invalid IL or missing references) //IL_00bc: Unknown result type (might be due to invalid IL or missing references) //IL_00c4: Expected O, but got Unknown //IL_00d1: Unknown result type (might be due to invalid IL or missing references) //IL_00db: Expected O, but got Unknown //IL_00f1: Unknown result type (might be due to invalid IL or missing references) //IL_00f7: Expected O, but got Unknown //IL_011d: Unknown result type (might be due to invalid IL or missing references) //IL_0122: Unknown result type (might be due to invalid IL or missing references) //IL_012d: Unknown result type (might be due to invalid IL or missing references) //IL_0135: Unknown result type (might be due to invalid IL or missing references) //IL_013d: Expected O, but got Unknown //IL_013f: Unknown result type (might be due to invalid IL or missing references) //IL_0144: Unknown result type (might be due to invalid IL or missing references) //IL_014f: Unknown result type (might be due to invalid IL or missing references) //IL_0156: Unknown result type (might be due to invalid IL or missing references) //IL_015e: Expected O, but got Unknown //IL_0160: Unknown result type (might be due to invalid IL or missing references) //IL_0165: Unknown result type (might be due to invalid IL or missing references) //IL_0170: Unknown result type (might be due to invalid IL or missing references) //IL_0177: Unknown result type (might be due to invalid IL or missing references) //IL_017f: Expected O, but got Unknown //IL_0181: Unknown result type (might be due to invalid IL or missing references) //IL_0186: Unknown result type (might be due to invalid IL or missing references) //IL_0191: Unknown result type (might be due to invalid IL or missing references) //IL_0198: Unknown result type (might be due to invalid IL or missing references) //IL_01a0: Expected O, but got Unknown //IL_01ad: Unknown result type (might be due to invalid IL or missing references) //IL_01b7: Expected O, but got Unknown //IL_01ce: Unknown result type (might be due to invalid IL or missing references) //IL_01d5: Expected O, but got Unknown //IL_01f7: Unknown result type (might be due to invalid IL or missing references) //IL_01fc: Unknown result type (might be due to invalid IL or missing references) //IL_0207: Unknown result type (might be due to invalid IL or missing references) //IL_020f: Unknown result type (might be due to invalid IL or missing references) //IL_0217: Expected O, but got Unknown //IL_0219: Unknown result type (might be due to invalid IL or missing references) //IL_021e: Unknown result type (might be due to invalid IL or missing references) //IL_0229: Unknown result type (might be due to invalid IL or missing references) //IL_0230: Unknown result type (might be due to invalid IL or missing references) //IL_0238: Expected O, but got Unknown //IL_0247: Unknown result type (might be due to invalid IL or missing references) //IL_0251: Expected O, but got Unknown GameObject val = Assets.AssetBundle.LoadAsset<GameObject>("piece_enchanter"); PieceConfig val2 = new PieceConfig(); val2.PieceTable = "Hammer"; val2.Category = PieceCategories.Misc; val2.AllowedInDungeons = false; val2.Requirements = (RequirementConfig[])(object)new RequirementConfig[4] { new RequirementConfig { Item = "Stone", Amount = 10, Recover = true }, new RequirementConfig { Item = "SurtlingCore", Amount = 3, Recover = true }, new RequirementConfig { Item = "Copper", Amount = 3, Recover = true }, new RequirementConfig { Item = "SwordCheat", Amount = 1, Recover = false } }; PieceManager.Instance.AddPiece(new CustomPiece(val, true, val2)); GameObject val3 = Assets.AssetBundle.LoadAsset<GameObject>("piece_augmenter"); PieceConfig val4 = new PieceConfig(); val4.PieceTable = "Hammer"; val4.Category = PieceCategories.Misc; val4.AllowedInDungeons = false; val4.Requirements = (RequirementConfig[])(object)new RequirementConfig[4] { new RequirementConfig { Item = "Obsidian", Amount = 10, Recover = true }, new RequirementConfig { Item = "Crystal", Amount = 3, Recover = true }, new RequirementConfig { Item = "Bronze", Amount = 3, Recover = true }, new RequirementConfig { Item = "SwordCheat", Amount = 1, Recover = false } }; PieceManager.Instance.AddPiece(new CustomPiece(val3, true, val4)); GameObject val5 = Assets.AssetBundle.LoadAsset<GameObject>("piece_enchantingtable"); PieceConfig val6 = new PieceConfig(); val6.PieceTable = "Hammer"; val6.Category = PieceCategories.Crafting; val6.Requirements = (RequirementConfig[])(object)new RequirementConfig[2] { new RequirementConfig { Item = "FineWood", Amount = 10, Recover = true }, new RequirementConfig { Item = "SurtlingCore", Amount = 1, Recover = true } }; PieceManager.Instance.AddPiece(new CustomPiece(val5, true, val6)); } private static void LoadItems() { //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Expected O, but got Unknown string[] itemNames = ItemNames; foreach (string text in itemNames) { CustomItem val = new CustomItem(Assets.AssetBundle.LoadAsset<GameObject>(text), false); ItemManager.Instance.AddItem(val); } } private static void LoadBountySpawner() { //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Expected O, but got Unknown GameObject val = Assets.AssetBundle.LoadAsset<GameObject>("EL_SpawnController"); if ((Object)(object)val == (Object)null) { LogErrorForce("Unable to find bounty spawner asset! This mod will not behave as expected!"); return; } val.AddComponent<AdventureSpawnController>(); CustomPrefab val2 = new CustomPrefab(val, false); PrefabManager.Instance.AddPrefab(val2); } private static void LoadCraftingMaterialAssets() { //IL_00b8: Unknown result type (might be due to invalid IL or missing references) //IL_00bf: Expected O, but got Unknown string[] magicMaterials = MagicMaterials; foreach (string arg in magicMaterials) { foreach (ItemRarity value in Enum.GetValues(typeof(ItemRarity))) { string text = $"{arg}{value}"; GameObject val = Assets.AssetBundle.LoadAsset<GameObject>(text); if ((Object)(object)val == (Object)null) { LogErrorForce("Tried to load asset " + text + " but it does not exist in the asset bundle!"); continue; } ItemDrop component = val.GetComponent<ItemDrop>(); if ((Object)(object)component != (Object)null && component.m_itemData.IsMagicCraftingMaterial()) { component.m_itemData.m_variant = GetRarityIconIndex(value); } CustomItem val2 = new CustomItem(val, false); ItemManager.Instance.AddItem(val2); } } } private static void LoadUnidentifiedItems() { //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Unknown result type (might be due to invalid IL or missing references) //IL_007a: Unknown result type (might be due to invalid IL or missing references) //IL_00d6: Unknown result type (might be due to invalid IL or missing references) //IL_00db: Unknown result type (might be due to invalid IL or missing references) //IL_00e7: Unknown result type (might be due to invalid IL or missing references) //IL_00f7: Unknown result type (might be due to invalid IL or missing references) //IL_0104: Expected O, but got Unknown //IL_0107: Unknown result type (might be due to invalid IL or missing references) //IL_010e: Expected O, but got Unknown foreach (Biome item in new List<Biome> { (Biome)1, (Biome)8, (Biome)2, (Biome)4, (Biome)16, (Biome)512, (Biome)32 }) { foreach (ItemRarity value in Enum.GetValues(typeof(ItemRarity))) { string text = $"{item}_{value}_Unidentified"; GameObject obj = Assets.AssetBundle.LoadAsset<GameObject>(text); MagicItemComponent orCreate = obj.GetComponent<ItemDrop>().m_itemData.Data().GetOrCreate<MagicItemComponent>(); orCreate.SetMagicItem(new MagicItem { Rarity = value, IsUnidentified = true }); orCreate.Save(); ItemConfig val = new ItemConfig { Name = $"$mod_epicloot_{value} $mod_epicloot_unidentified_{item}", Description = "$mod_epicloot_unidentified_introduce" }; CustomItem val2 = new CustomItem(obj, false, val); ItemManager.Instance.AddItem(val2); Log("Added " + text); } } } [UsedImplicitly] public void OnDestroy() { ((BaseUnityPlugin)this).Config.Save(); _instance = null; } public static bool IsObjectDBReady() { if ((Object)(object)ObjectDB.instance != (Object)null && ObjectDB.instance.m_items.Count != 0) { return (Object)(object)ObjectDB.instance.GetItemPrefab("Amber") != (Object)null; } return false; } private static void SetupAndvaranaut() { //IL_019a: Unknown result type (might be due to invalid IL or missing references) //IL_01a1: Expected O, but got Unknown GameObject obj = Assets.AssetBundle.LoadAsset<GameObject>("Andvaranaut"); ItemDrop component = obj.GetComponent<ItemDrop>(); ItemData itemData = component.m_itemData; ItemData itemData2 = ObjectDB.instance.GetItemPrefab("Wishbone").GetComponent<ItemDrop>().m_itemData; StatusEffect equipStatusEffect = itemData2.m_shared.m_equipStatusEffect; SE_CustomFinder sE_CustomFinder = ScriptableObject.CreateInstance<SE_CustomFinder>(); Utils.CopyFields(equipStatusEffect, sE_CustomFinder, typeof(SE_Finder)); ((Object)sE_CustomFinder).name = "CustomWishboneFinder"; SE_CustomFinder sE_CustomFinder2 = ScriptableObject.CreateInstance<SE_CustomFinder>(); Utils.CopyFields(sE_CustomFinder, sE_CustomFinder2, typeof(SE_CustomFinder)); ((Object)sE_CustomFinder2).name = "Andvaranaut"; ((StatusEffect)sE_CustomFinder2).m_name = "$mod_epicloot_item_andvaranaut"; ((StatusEffect)sE_CustomFinder2).m_icon = itemData.GetIcon(); ((StatusEffect)sE_CustomFinder2).m_tooltip = "$mod_epicloot_item_andvaranaut_tooltip"; ((StatusEffect)sE_CustomFinder2).m_startMessage = "$mod_epicloot_item_andvaranaut_startmsg"; sE_CustomFinder2.RequiredComponentTypes = new List<Type> { typeof(TreasureMapChest), typeof(BountyTarget) }; sE_CustomFinder.DisallowedComponentTypes = new List<Type> { typeof(TreasureMapChest), typeof(BountyTarget) }; ObjectDB.instance.m_StatusEffects.Remove(equipStatusEffect); ObjectDB.instance.m_StatusEffects.Add((StatusEffect)(object)sE_CustomFinder2); ObjectDB.instance.m_StatusEffects.Add((StatusEffect)(object)sE_CustomFinder); itemData.m_shared.m_equipStatusEffect = (StatusEffect)(object)sE_CustomFinder2; itemData2.m_shared.m_equipStatusEffect = (StatusEffect)(object)sE_CustomFinder; MagicItem magicItem = new MagicItem { Rarity = ItemRarity.Epic, TypeNameOverride = "$mod_epicloot_item_andvaranaut_type" }; magicItem.Effects.Add(new MagicItemEffect(MagicEffectType.Andvaranaut)); component.m_itemData.SaveMagicItem(magicItem); CustomItem val = new CustomItem(obj, false); ItemManager.Instance.AddItem(val); PrefabManager.OnPrefabsRegistered -= SetupAndvaranaut; } private static void SetupStatusEffects() { StatusEffect statusEffect = ObjectDB.instance.GetStatusEffect("Lightning".GetHashCode()); SE_Paralyzed sE_Paralyzed = ScriptableObject.CreateInstance<SE_Paralyzed>(); Utils.CopyFields(statusEffect, sE_Paralyzed, typeof(StatusEffect)); ((Object)sE_Paralyzed).name = "Paralyze"; ((StatusEffect)sE_Paralyzed).m_name = "$mod_epicloot_se_paralyze"; ObjectDB.instance.m_StatusEffects.Add((StatusEffect)(object)sE_Paralyzed); ItemManager.OnItemsRegistered -= SetupStatusEffects; } public static AssetBundle LoadAssetBundle(string filename) { Assembly callingAssembly = Assembly.GetCallingAssembly(); return AssetBundle.LoadFromStream(callingAssembly.GetManifestResourceStream(callingAssembly.GetName().Name + "." + filename)); } internal static string ReadEmbeddedResourceFile(string filename) { Log("Attempting to load resource path: " + filename); string[] manifestResourceNames = typeof(EpicLoot).Assembly.GetManifestResourceNames(); for (int i = 0; i < manifestResourceNames.Length; i++) { _ = manifestResourceNames[i]; } using Stream stream = typeof(EpicLoot).Assembly.GetManifestResourceStream(filename); using StreamReader streamReader = new StreamReader(stream); return streamReader.ReadToEnd(); } public static bool CanBeMagicItem(ItemData item) { //IL_0026: Unknown result type (might be due to invalid IL or missing references) if (item != null && IsPlayerItem(item) && Nonstackable(item) && IsNotRestrictedItem(item)) { return AllowedMagicItemTypes.Contains(item.m_shared.m_itemType); } return false; } public static Sprite GetMagicItemBgSprite() { if (!HasAuga) { return Assets.GenericItemBgSprite; } return Assets.AugaItemBgSprite; } public static Sprite GetEquippedSprite() { if (!HasAuga) { return Assets.EquippedSprite; } return Assets.AugaEquippedSprite; } public static Sprite GetSetItemSprite() { if (!HasAuga) { return Assets.GenericSetItemSprite; } return Assets.AugaSetItemSprite; } public static string GetMagicEffectPip(bool hasBeenAugmented) { if (!HasAuga) { if (!hasBeenAugmented) { return "◆"; } return "▼"; } if (!hasBeenAugmented) { return "♦"; } return "▾"; } private static bool IsNotRestrictedItem(ItemData item) { if ((Object)(object)item.m_dropPrefab != (Object)null && LootRoller.Config.RestrictedItems.Contains(((Object)item.m_dropPrefab).name)) { return false; } return !LootRoller.Config.RestrictedItems.Contains(item.m_shared.m_name); } private static bool Nonstackable(ItemData item) { return item.m_shared.m_maxStackSize == 1; } private static bool IsPlayerItem(ItemData item) { return item.m_shared.m_icons.Length != 0; } public static string GetCharacterCleanName(Character character) { return ((Object)character).name.Replace("(Clone)", "").Trim(); } public static string GetSetItemColor() { return ELConfig._setItemColor.Value; } public static string GetRarityDisplayName(ItemRarity rarity) { return rarity switch { ItemRarity.Magic => "$mod_epicloot_Magic", ItemRarity.Rare => "$mod_epicloot_Rare", ItemRarity.Epic => "$mod_epicloot_Epic", ItemRarity.Legendary => "$mod_epicloot_Legendary", ItemRarity.Mythic => "$mod_epicloot_Mythic", _ => "<non magic>", }; } public static string GetRarityColor(ItemRarity rarity) { return rarity switch { ItemRarity.Magic => GetColor(ELConfig._magicRarityColor.Value), ItemRarity.Rare => GetColor(ELConfig._rareRarityColor.Value), ItemRarity.Epic => GetColor(ELConfig._epicRarityColor.Value), ItemRarity.Legendary => GetColor(ELConfig._legendaryRarityColor.Value), ItemRarity.Mythic => GetColor(ELConfig._mythicRarityColor.Value), _ => "#FFFFFF", }; } public static Color GetRarityColorARGB(ItemRarity rarity) { //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) Color result = default(Color); if (!ColorUtility.TryParseHtmlString(GetRarityColor(rarity), ref result)) { return Color.white; } return result; } private static string GetColor(string configValue) { if (configValue.StartsWith("#")) { return configValue; } if (MagicItemColors.TryGetValue(configValue, out var value)) { return value; } return "#000000"; } public static int GetRarityIconIndex(ItemRarity rarity) { return rarity switch { ItemRarity.Magic => Mathf.Clamp(ELConfig._magicMaterialIconColor.Value, 0, 9), ItemRarity.Rare => Mathf.Clamp(ELConfig._rareMaterialIconColor.Value, 0, 9), ItemRarity.Epic => Mathf.Clamp(ELConfig._epicMaterialIconColor.Value, 0, 9), ItemRarity.Legendary => Mathf.Clamp(ELConfig._legendaryMaterialIconColor.Value, 0, 9), ItemRarity.Mythic => Mathf.Clamp(ELConfig._mythicMaterialIconColor.Value, 0, 9), _ => throw new ArgumentOutOfRangeException("rarity", rarity, null), }; } public static AudioClip GetMagicItemDropSFX(ItemRarity rarity) { return Assets.MagicItemDropSFX[(int)rarity]; } public static GatedItemTypeMode GetGatedItemTypeMode() { return ELConfig._gatedItemTypeModeConfig.Value; } public static BossDropMode GetBossTrophyDropMode() { return ELConfig._bossTrophyDropMode.Value; } public static float GetBossTrophyDropPlayerRange() { return ELConfig._bossTrophyDropPlayerRange.Value; } public static float GetBossCryptKeyPlayerRange() { return ELConfig._bossCryptKeyDropPlayerRange.Value; } public static BossDropMode GetBossCryptKeyDropMode() { return ELConfig._bossCryptKeyDropMode.Value; } public static BossDropMode GetBossWishboneDropMode() { return ELConfig._bossWishboneDropMode.Value; } public static float GetBossWishboneDropPlayerRange() { return ELConfig._bossWishboneDropPlayerRange.Value; } public static int GetAndvaranautRange() { return ELConfig._andvaranautRange.Value; } public static bool IsAdventureModeEnabled() { return ELConfig._adventureModeEnabled.Value; } public static float GetWorldLuckFactor() { return _instance._worldLuckFactor; } public static void SetWorldLuckFactor(float luckFactor) { _instance._worldLuckFactor = luckFactor; } private void SetupWatcher() { FileSystemWatcher fileSystemWatcher = new FileSystemWatcher(Paths.ConfigPath, ConfigFileName); fileSystemWatcher.Changed += ReadConfigValues; fileSystemWatcher.Created += ReadConfigValues; fileSystemWatcher.Renamed += ReadConfigValues; fileSystemWatcher.IncludeSubdirectories = true; fileSystemWatcher.SynchronizingObject = ThreadingHelper.SynchronizingObject; fileSystemWatcher.EnableRaisingEvents = true; } private void ReadConfigValues(object sender, FileSystemEventArgs e) { DateTime now = DateTime.Now; long num = now.Ticks - _lastReloadTime.Ticks; if (File.Exists(ConfigFileFullPath) && num >= 10000000) { try { Log("Attempting to reload configuration..."); ((BaseUnityPlugin)this).Config.Reload(); } catch { Log("There was an issue loading " + ConfigFileName); return; } _lastReloadTime = now; } } static EpicLoot() { string configPath = Paths.ConfigPath; char directorySeparatorChar = Path.DirectorySeparatorChar; ConfigFileFullPath = configPath + directorySeparatorChar + ConfigFileName; AllowedMagicItemTypes = new List<ItemType> { (ItemType)6, (ItemType)7, (ItemType)11, (ItemType)17, (ItemType)18, (ItemType)4, (ItemType)3, (ItemType)14, (ItemType)22, (ItemType)5, (ItemType)19, (ItemType)15 }; MagicItemColors = new Dictionary<string, string> { { "Red", "#ff4545" }, { "Orange", "#ffac59" }, { "Yellow", "#ffff75" }, { "Green", "#80fa70" }, { "Teal", "#18e7a9" }, { "Blue", "#00abff" }, { "Indigo", "#709bba" }, { "Purple", "#d078ff" }, { "Pink", "#ff63d6" }, { "Gray", "#dbcadb" } }; MagicMaterials = new string[6] { "Runestone", "EtchedRunestone", "Shard", "Dust", "Reagent", "Essence" }; ItemNames = new string[6] { "LeatherBelt", "SilverRing", "GoldRubyRing", "ForestToken", "IronBountyToken", "GoldBountyToken" }; Assets = new EpicAssets(); _assetCache = new Dictionary<string, Object>(); AlwaysDropCheat = false; } } public static class EpicLootAuga { public static Button ReplaceButton(Button button, bool icon = false, bool keepListeners = false) { return ReplaceButtonInternal(button, button, icon, keepListeners); } public static Button ReplaceButtonFancy(Button button, bool icon = false, bool keepListeners = false) { return ReplaceButtonInternal(button, button, icon, keepListeners); } private static Button ReplaceButtonInternal(Button newButton, Button button, bool icon, bool keepListeners) { //IL_0058: Unknown result type (might be due to invalid IL or missing references) //IL_005e: Expected O, but got Unknown //IL_0064: Unknown result type (might be due to invalid IL or missing references) //IL_0069: Unknown result type (might be due to invalid IL or missing references) //IL_006b: Unknown result type (might be due to invalid IL or missing references) //IL_0075: Unknown result type (might be due to invalid IL or missing references) //IL_0077: Unknown result type (might be due to invalid IL or missing references) //IL_0081: Unknown result type (might be due to invalid IL or missing references) //IL_0083: Unknown result type (might be due to invalid IL or missing references) //IL_008d: Unknown result type (might be due to invalid IL or missing references) //IL_008f: Unknown result type (might be due to invalid IL or missing references) //IL_009b: Unknown result type (might be due to invalid IL or missing references) //IL_00a0: Unknown result type (might be due to invalid IL or missing references) //IL_00bd: Unknown result type (might be due to invalid IL or missing references) //IL_00c7: Expected O, but got Unknown //IL_0108: Unknown result type (might be due to invalid IL or missing references) //IL_010d: Unknown result type (might be due to invalid IL or missing references) if (icon) { Object.Destroy((Object)(object)((Component)((Component)newButton).GetComponentInChildren<TMP_Text>()).gameObject); ((Object)Object.Instantiate<Transform>(((Component)button).transform.Find("Icon"), ((Component)newButton).transform)).name = "Icon"; } else { string text = ((Component)button).GetComponentInChildren<Text>().text; ((Component)newButton).GetComponentInChildren<TMP_Text>().text = text; } RectTransform val = (RectTransform)((Component)button).transform; RectTransform val2 = (RectTransform)((Component)newButton).transform; val2.anchorMin = val.anchorMin; val2.anchorMax = val.anchorMax; val2.pivot = val.pivot; val2.anchoredPosition = val.anchoredPosition; Rect rect = val.rect; val2.SetSizeWithCurrentAnchors((Axis)0, ((Rect)(ref rect)).width); if (keepListeners) { newButton.onClick = button.onClick; button.onClick = new ButtonClickedEvent(); } UIGamePad component = ((Component)button).GetComponent<UIGamePad>(); if ((Object)(object)component != (Object)null && (Object)(object)component.m_hint != (Object)null) { component.m_hint.transform.SetParent(((Component)newButton).transform); UIGamePad obj = ((Component)newButton).gameObject.AddComponent<UIGamePad>(); obj.m_keyCode = component.m_keyCode; obj.m_zinputKey = component.m_zinputKey; obj.m_hint = component.m_hint; obj.m_blockingElements = component.m_blockingElements.ToList(); } Object.DestroyImmediate((Object)(object)((Component)button).gameObject); return newButton; } public static void MakeSimpleTooltip(GameObject obj) { } public static void ReplaceBackground(GameObject obj, bool withCornerDecoration) { } public static void FixItemBG(GameObject obj) { } public static void FixListElementColors(GameObject obj) { //IL_0071: Unknown result type (might be due to invalid IL or missing references) //IL_0056: Unknown result type (might be due to invalid IL or missing references) _ = (Object)(object)obj.transform.Find("Selected") != (Object)null; Transform val = obj.transform.Find("Background"); if ((Object)(object)val != (Object)null) { Image component = ((Component)val).GetComponent<Image>(); if ((Object)(object)component != (Object)null) { ((Graphic)component).color = new Color(0f, 0f, 0f, 0.5f); } } Button component2 = obj.GetComponent<Button>(); if ((Object)(object)component2 != (Object)null) { ((Selectable)component2).colors = ColorBlock.defaultColorBlock; } } public static void FixFonts(GameObject obj) { TMP_Text[] componentsInChildren = obj.GetComponentsInChildren<TMP_Text>(true); for (int i = 0; i < componentsInChildren.Length; i++) { _ = componentsInChildren[i]; } } public static Button ReplaceVerticalLargeTab(Button button) { //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Expected O, but got Unknown //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_0051: Unknown result type (might be due to invalid IL or missing references) //IL_005b: Unknown result type (might be due to invalid IL or missing references) //IL_005d: Unknown result type (might be due to invalid IL or missing references) //IL_0067: Unknown result type (might be due to invalid IL or missing references) //IL_0069: Unknown result type (might be due to invalid IL or missing references) //IL_0073: Unknown result type (might be due to invalid IL or missing references) //IL_0075: Unknown result type (might be due to invalid IL or missing references) //IL_0081: Unknown result type (might be due to invalid IL or missing references) //IL_0086: Unknown result type (might be due to invalid IL or missing references) //IL_0136: Unknown result type (might be due to invalid IL or missing references) //IL_013b: Unknown result type (might be due to invalid IL or missing references) GameObject obj = Object.Instantiate<GameObject>(EpicLoot.LoadAsset<GameObject>("EnchantingTabAuga"), ((Component)button).transform.parent); ((Object)obj).name = ((Object)button).name; FixFonts(obj); int siblingIndex = ((Component)button).transform.GetSiblingIndex(); RectTransform val = (RectTransform)((Component)button).transform; RectTransform val2 = (RectTransform)obj.transform; val2.anchorMin = val.anchorMin; val2.anchorMax = val.anchorMax; val2.pivot = val.pivot; val2.anchoredPosition = val.anchoredPosition; Rect rect = val.rect; val2.SetSizeWithCurrentAnchors((Axis)0, ((Rect)(ref rect)).width); ((Component)obj.transform.Find("Text")).GetComponent<TMP_Text>().text = ((Component)((Component)button).transform.Find("Text")).GetComponent<TMP_Text>().text; ((Component)obj.transform.Find("Image")).GetComponent<Image>().sprite = ((Component)((Component)button).transform.Find("Image")).GetComponent<Image>().sprite; FeatureStatus component = obj.GetComponent<FeatureStatus>(); FeatureStatus component2 = ((Component)button).GetComponent<FeatureStatus>(); if ((Object)(object)component2 == (Object)null && (Object)(object)component != (Object)null) { Object.DestroyImmediate((Object)(object)component); } if ((Object)(object)component != (Object)null && (Object)(object)component2 != (Object)null) { component.Feature = component2.Feature; component.Refresh(); } Object.DestroyImmediate((Object)(object)((Component)button).gameObject); obj.transform.SetSiblingIndex(siblingIndex); return obj.GetComponent<Button>(); } public static void FixupScrollbar(Scrollbar scrollbar) { //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Unknown result type (might be due to invalid IL or missing references) Object.Destroy((Object)(object)((Component)scrollbar).GetComponent<Image>()); ((Selectable)scrollbar).colors = ColorBlock.defaultColorBlock; Image component = ((Component)scrollbar.handleRect).GetComponent<Image>(); Color val = default(Color); if (ColorUtility.TryParseHtmlString("#8B7C6A", ref val)) { ((Graphic)component).color = new Color(val.r, val.g, val.b, 1f); } } } [HarmonyPatch] public static class Attack_Patch { public static Attack ActiveAttack; [HarmonyPatch(typeof(Attack), "DoMeleeAttack")] [HarmonyPrefix] [HarmonyPriority(0)] public static void Attack_DoMeleeAttack_Prefix(Attack __instance) { ActiveAttack = __instance; } [HarmonyPatch(typeof(Attack), "DoMeleeAttack")] [HarmonyPostfix] public static void Attack_DoMeleeAttack_Postfix() { ActiveAttack = null; } } [HarmonyPatch(typeof(Container), "AddDefaultItems")] public static class Container_AddDefaultItems_Patch { public static void Postfix(Container __instance) { //IL_0064: Unknown result type (might be due to invalid IL or missing references) //IL_0086: 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) if ((Object)(object)__instance == (Object)null || (Object)(object)__instance.m_piece == (Object)null) { return; } string text = ((Object)__instance.m_piece).name.Replace("(Clone)", "").Trim(); List<LootTable> lootTable = LootRoller.GetLootTable(text); if (lootTable == null || lootTable.Count <= 0) { return; } List<ItemData> list = LootRoller.RollLootTable(lootTable, 1, ((Object)__instance.m_piece).name, ((Component)__instance).transform.position); object arg = list.Count; Vector3 position = ((Component)__instance).transform.position; EpicLoot.Log(string.Format("Rolling on loot table: {0}, spawned {1} items at drop point({2}).", text, arg, ((Vector3)(ref position)).ToString("0"))); foreach (ItemData item in list) { __instance.m_inventory.AddItem(item); EpicLoot.Log(" - " + item.m_shared.m_name + (item.IsMagic() ? (": " + string.Join(", ", item.GetMagicItem().Effects.Select((MagicItemEffect x) => x.EffectType.ToString()))) : "")); } } } public static class EpicLootDropsHelper { public static bool InstantDropsEnabled { get; set; } public static void OnCharacterDeath(CharacterDrop characterDrop) { //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Unknown result type (might be due to invalid IL or missing references) //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_0046: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Unknown result type (might be due to invalid IL or missing references) if (CanCharacterDropLoot(characterDrop.m_character)) { string characterCleanName = EpicLoot.GetCharacterCleanName(characterDrop.m_character); int level = characterDrop.m_character.GetLevel(); Vector3 dropPoint = characterDrop.m_character.GetCenterPoint() + ((Component)characterDrop).transform.TransformVector(characterDrop.m_spawnOffset); OnCharacterDeath(characterCleanName, level, dropPoint); } } public static bool CanCharacterDropLoot(Character character) { if ((Object)(object)character != (Object)null) { return !character.IsTamed(); } return false; } public static void OnCharacterDeath(string characterName, int level, Vector3 dropPoint) { //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_005a: Unknown result type (might be due to invalid IL or missing references) //IL_00aa: Unknown result type (might be due to invalid IL or missing references) List<LootTable> lootTable = LootRoller.GetLootTable(characterName); if (lootTable != null && lootTable.Count > 0) { List<GameObject> list = LootRoller.RollLootTableAndSpawnObjects(lootTable, level, characterName, dropPoint); EpicLoot.Log($"Rolling on loot table: {characterName} (lvl {level}), " + $"spawned {list.Count} items at drop point({dropPoint})."); DropItems(list, dropPoint); { foreach (GameObject item in list) { ItemData itemData = item.GetComponent<ItemDrop>().m_itemData; MagicItem magicItem = itemData.GetMagicItem(); if (magicItem != null) { EpicLoot.Log($" - {itemData.m_shared.m_name} <{item.transform.position}>: " + string.Join(", ", magicItem.Effects.Select((MagicItemEffect x) => x.EffectType.ToString()))); } } return; } } EpicLoot.Log($"Could not find loot table for: {characterName} (lvl {level})"); } public static void DropItems(List<GameObject> loot, Vector3 centerPos, float dropHemisphereRadius = 0.5f) { //IL_0013: 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_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_0078: Unknown result type (might be due to invalid IL or missing references) //IL_007d: Unknown result type (might be due to invalid IL or missing references) //IL_007e: 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_00a5: Unknown result type (might be due to invalid IL or missing references) //IL_0092: Unknown result type (might be due to invalid IL or missing references) foreach (GameObject item in loot) { Vector3 val = Random.insideUnitSphere * dropHemisphereRadius; val.y = Mathf.Abs(val.y); item.transform.position = centerPos + val; item.transform.rotation = Quaternion.Euler(0f, (float)Random.Range(0, 360), 0f); Rigidbody component = item.GetComponent<Rigidbody>(); if ((Object)(object)component != (Object)null) { Vector3 insideUnitSphere = Random.insideUnitSphere; if ((double)insideUnitSphere.y < 0.0) { insideUnitSphere.y = 0f - insideUnitSphere.y; } component.AddForce(insideUnitSphere * 5f, (ForceMode)2); } } } } [HarmonyPatch(typeof(CharacterDrop), "OnDeath")] public static class CharacterDrop_OnDeath_Patch { public static void Postfix(CharacterDrop __instance) { if (EpicLootDropsHelper.InstantDropsEnabled) { EpicLootDropsHelper.OnCharacterDeath(__instance); } } } [HarmonyPatch(typeof(Ragdoll), "Setup")] public static class Ragdoll_Setup_Patch { public static void Postfix(Ragdoll __instance, CharacterDrop characterDrop) { if (!((Object)(object)characterDrop == (Object)null) && !((Object)(object)characterDrop.m_character == (Object)null) && !characterDrop.m_character.IsPlayer() && EpicLootDropsHelper.CanCharacterDropLoot(characterDrop.m_character)) { EpicLootDropsHelper.InstantDropsEnabled = false; string characterCleanName = EpicLoot.GetCharacterCleanName(characterDrop.m_character); int level = characterDrop.m_character.GetLevel(); __instance.m_nview.m_zdo.Set("characterName", characterCleanName); __instance.m_nview.m_zdo.Set("level", level); } } } [HarmonyPatch(typeof(Ragdoll), "SpawnLoot")] public static class Ragdoll_SpawnLoot_Patch { public static void Postfix(Ragdoll __instance, Vector3 center) { //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Unknown res