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 EpicLootAlphaTest v0.1.0
EpicLootLeslieAlphaTest.dll
Decompiled 3 weeks agousing System; using System.Collections.Generic; using System.ComponentModel; using System.Diagnostics; using System.Linq; using System.Linq.Expressions; using System.Reflection; using System.Reflection.Emit; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using BepInEx; using EpicLoot; using EpicLoot.CraftingV2; using EpicLootAPI; using EpicLoot_UnityLib; using HarmonyLib; using JetBrains.Annotations; using Jotunn.Managers; using Jotunn.Utils; using Microsoft.CodeAnalysis; using Newtonsoft.Json; using UnityEngine; using UnityEngine.UI; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)] [assembly: TargetFramework(".NETFramework,Version=v4.8.1", FrameworkDisplayName = ".NET Framework 4.8.1")] [assembly: AssemblyCompany("EpicLootLeslieAlphaTest")] [assembly: AssemblyConfiguration("Debug")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0")] [assembly: AssemblyProduct("EpicLootLeslieAlphaTest")] [assembly: AssemblyTitle("EpicLootLeslieAlphaTest")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.0.0.0")] [module: UnverifiableCode] namespace EpicLootLeslieAlphaTest.src { [HarmonyPatch(typeof(EnchantingUIController), "BuildEnchantedRune")] internal class EnchantingUIControllerMod { [HarmonyTranspiler] private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions) { //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Expected O, but got Unknown //IL_0063: Unknown result type (might be due to invalid IL or missing references) //IL_0069: Expected O, but got Unknown //IL_00b1: Unknown result type (might be due to invalid IL or missing references) //IL_00b7: Expected O, but got Unknown FieldInfo fieldInfo = AccessTools.Field(typeof(MagicItemEffectDefinitions), "AllDefinitions"); FieldInfo fieldInfo2 = AccessTools.Field(typeof(MagicItemEffect), "EffectValue"); CodeMatcher val = new CodeMatcher(instructions, (ILGenerator)null); Debug.LogWarning((object)$"[EpicLootAlpha] total instructions: {val.Length}"); val.MatchStartForward((CodeMatch[])(object)new CodeMatch[1] { new CodeMatch((OpCode?)OpCodes.Ldsfld, (object)fieldInfo, (string)null) }); Debug.LogWarning((object)$"[EpicLootAlpha] startPos: {val.Pos}, IsValid: {val.IsValid}"); int pos = val.Pos; val.MatchStartForward((CodeMatch[])(object)new CodeMatch[1] { new CodeMatch((OpCode?)OpCodes.Stfld, (object)fieldInfo2, (string)null) }); Debug.LogWarning((object)$"[EpicLootAlpha] endPos: {val.Pos}, IsValid: {val.IsValid}"); int pos2 = val.Pos; Debug.LogWarning((object)$"[EpicLootAlpha] removeCount: {pos2 - pos + 1}"); val.Start().Advance(pos).RemoveInstructions(pos2 - pos + 1); return val.InstructionEnumeration(); } [HarmonyPostfix] private static void Postfix(ref ItemData __result) { if (__result == null) { return; } MagicItem magicItem = ItemDataExtensions.GetMagicItem(__result); if (magicItem == null) { return; } foreach (MagicItemEffect effect in magicItem.Effects) { effect.EffectValue = (float)Math.Round(effect.EffectValue, 2); } ItemDataExtensions.SaveMagicItem(__result, magicItem); } } public static class EnchantingHelper { internal static bool AwaitingConfirmation; internal static float PendingDestroyChance; public static float RuneTooPowerfulEtchDestructionChance(ItemData item, ItemData rune) { //IL_002b: 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) List<MagicItemEffect> effects = ItemDataExtensions.GetMagicItem(rune).Effects; MagicItemEffect val = effects[0]; ValueDef valueDefForRarity = MagicItemEffectDefinitions.AllDefinitions[val.EffectType].ValuesPerRarity.GetValueDefForRarity(ItemDataExtensions.GetRarity(item)); if (valueDefForRarity != null) { float maxValue = MagicItemEffectDefinitions.AllDefinitions[val.EffectType].ValuesPerRarity.GetValueDefForRarity(ItemDataExtensions.GetRarity(item)).MaxValue; bool flag = val.EffectValue >= maxValue * 1.1f; float num = val.EffectValue / maxValue - 1f; Debug.LogWarning((object)$"[EpicLootAlpha] effectValue: {val.EffectValue}, maxDefault: {maxValue}, tooPowerful: {flag}"); if (flag) { float num2 = num * 100f; num2 = Mathf.Clamp(num2, 10f, 90f); return Mathf.Round(num2 / 5f) * 5f; } } return 0f; } } [HarmonyPatch(typeof(EnchantingUIController), "RuneEnhanceItemAndReturnSuccess")] internal class RuneEnhanceItem_DestroyChance_Patch { [HarmonyPrefix] private static bool Prefix(ItemData item, ItemData rune, int enchantment, ref GameObject __result) { //IL_0036: Unknown result type (might be due to invalid IL or missing references) Debug.LogWarning((object)"[EpicLootAlpha] Prefix hit"); List<MagicItemEffect> effects = ItemDataExtensions.GetMagicItem(rune).Effects; MagicItemEffect val = effects[0]; ValueDef valueDefForRarity = MagicItemEffectDefinitions.AllDefinitions[val.EffectType].ValuesPerRarity.GetValueDefForRarity(ItemDataExtensions.GetRarity(item)); if (valueDefForRarity != null) { float num = EnchantingHelper.RuneTooPowerfulEtchDestructionChance(item, rune); if (num > 0f) { float num2 = Random.value * 100f; if (num > num2) { ((Humanoid)Player.m_localPlayer).UnequipItem(item, true); ((Humanoid)Player.m_localPlayer).GetInventory().RemoveItem(item); ((Humanoid)Player.m_localPlayer).GetInventory().RemoveItem(rune); ((Character)Player.m_localPlayer).Message((MessageType)2, $"You rolled {num2:F1} You are not worthy of the rune's power. The item and rune has been destroyed.", 0, (Sprite)null); __result = null; return false; } } } return true; } } public static class MagicEffects { public static void Init() { MagicItemEffectDefinition magicItemEffectDefinition = new MagicItemEffectDefinition("AncestralSlam", "Ancestral Slam", "Reduces damage of weapon. Summons ancestral spirit to mirror attack for each enemy hit"); magicItemEffectDefinition.Requirements.AllowedItemTypes.Add("TwoHandedWeapon"); magicItemEffectDefinition.Requirements.AllowedRarities.Add(ItemRarity.Epic, ItemRarity.Legendary, ItemRarity.Mythic); magicItemEffectDefinition.SelectionWeight = 1f; } } [BepInPlugin("com.leslie.epiclootlesliealphatest", "EpicLootLeslieAlphaTest", "0.1.0")] [BepInDependency(/*Could not decode attribute arguments.*/)] [NetworkCompatibility(/*Could not decode attribute arguments.*/)] internal class EpicLootAlphaTestPlugin : BaseUnityPlugin { public const string PluginGUID = "com.leslie.epiclootlesliealphatest"; public const string PluginName = "EpicLootLeslieAlphaTest"; public const string PluginVersion = "0.1.0"; private void Awake() { //IL_0036: Unknown result type (might be due to invalid IL or missing references) SynchronizationManager.OnConfigurationSynchronized += delegate(object obj, ConfigurationSynchronizationEventArgs attr) { if (attr.InitialSynchronization) { ((BaseUnityPlugin)this).Logger.LogInfo((object)"Initial config sync received"); } else { ((BaseUnityPlugin)this).Logger.LogInfo((object)"Config sync event received"); } }; SynchronizationManager.OnAdminStatusChanged += delegate { ((BaseUnityPlugin)this).Logger.LogInfo((object)$"Admin status changed: {SynchronizationManager.Instance.PlayerIsAdmin}"); }; MagicEffects.Init(); EpicLoot.RegisterAll(); new Harmony("com.leslie.epiclootlesliealphatest").PatchAll(); ((BaseUnityPlugin)this).Logger.LogInfo((object)"EpicLootLeslieAlphaTest v0.1.0 loaded"); } } [HarmonyPatch(typeof(EnchantingTableUIPanelBase), "OnMainButtonClicked")] internal class RuneUIMod_OnMainButtonClicked_Patch { private static bool Prefix(EnchantingTableUIPanelBase __instance) { //IL_00c5: Unknown result type (might be due to invalid IL or missing references) //IL_00cc: Expected O, but got Unknown //IL_0113: Unknown result type (might be due to invalid IL or missing references) //IL_011a: Expected O, but got Unknown //IL_019d: Unknown result type (might be due to invalid IL or missing references) //IL_01a4: Expected O, but got Unknown //IL_01bf: Unknown result type (might be due to invalid IL or missing references) RuneUI val = (RuneUI)(object)((__instance is RuneUI) ? __instance : null); if (val == null) { return true; } FieldInfo fieldInfo = AccessTools.Field(typeof(EnchantingTableUIPanelBase), "_inProgress"); if ((bool)fieldInfo.GetValue(__instance)) { return true; } FieldInfo fieldInfo2 = AccessTools.Field(typeof(RuneUI), "_runeAction"); int num = (int)fieldInfo2.GetValue(__instance); if (num != 1) { return true; } if (EnchantingHelper.AwaitingConfirmation) { EnchantingHelper.AwaitingConfirmation = false; EnchantingHelper.PendingDestroyChance = 0f; return true; } MultiSelectItemList val2 = (MultiSelectItemList)AccessTools.Field(typeof(EnchantingTableUIPanelBase), "AvailableItems").GetValue(__instance); Tuple<InventoryItemListElement, int> singleSelectedItem = val2.GetSingleSelectedItem<InventoryItemListElement>(); if (((singleSelectedItem != null) ? singleSelectedItem.Item1.GetItem() : null) == null) { return true; } MultiSelectItemList val3 = (MultiSelectItemList)AccessTools.Field(typeof(RuneUI), "AvailableRunes").GetValue(__instance); Tuple<InventoryItemListElement, int> singleSelectedItem2 = val3.GetSingleSelectedItem<InventoryItemListElement>(); if (((singleSelectedItem2 != null) ? singleSelectedItem2.Item1.GetItem() : null) == null) { return true; } float num2 = EnchantingHelper.RuneTooPowerfulEtchDestructionChance(singleSelectedItem.Item1.GetItem(), singleSelectedItem2.Item1.GetItem()); if (num2 > 0f) { EnchantingHelper.AwaitingConfirmation = true; EnchantingHelper.PendingDestroyChance = num2; Text val4 = (Text)AccessTools.Field(typeof(RuneUI), "Warning").GetValue(__instance); val4.text = $"WARNING: {num2:0}% chance to DESTROY your item!! Click Etch again to confirm."; ((Graphic)val4).color = Color.red; return false; } return true; } } [HarmonyPatch(typeof(RuneUI), "DoMainAction")] internal class RuneUI_DoMainACtion_Patch { private static bool Prefix(RuneUI __instance) { //IL_0058: Unknown result type (might be due to invalid IL or missing references) //IL_005e: Expected O, but got Unknown //IL_00ad: Unknown result type (might be due to invalid IL or missing references) //IL_00b4: Expected O, but got Unknown //IL_0113: Unknown result type (might be due to invalid IL or missing references) //IL_011a: Expected O, but got Unknown //IL_01ba: Unknown result type (might be due to invalid IL or missing references) //IL_01c1: Expected O, but got Unknown EnchantingHelper.AwaitingConfirmation = false; FieldInfo fieldInfo = AccessTools.Field(typeof(RuneUI), "_runeAction"); int num = (int)fieldInfo.GetValue(__instance); if (num != 1) { return true; } MultiSelectItemList val = (MultiSelectItemList)AccessTools.Field(typeof(EnchantingTableUIPanelBase), "AvailableItems").GetValue(__instance); Tuple<InventoryItemListElement, int> tuple = val.GetSelectedItems<InventoryItemListElement>().FirstOrDefault(); ((EnchantingTableUIPanelBase)__instance).Cancel(); if (((tuple != null) ? tuple.Item1.GetItem() : null) == null) { return false; } MultiSelectItemList val2 = (MultiSelectItemList)AccessTools.Field(typeof(RuneUI), "AvailableRunes").GetValue(__instance); ItemData item = val2.GetSingleSelectedItem<InventoryItemListElement>().Item1.GetItem(); ItemData item2 = tuple.Item1.GetItem(); int num2 = (int)AccessTools.Field(typeof(RuneUI), "_selectedEnchantmentIndex").GetValue(__instance); FieldInfo fieldInfo2 = AccessTools.Field(typeof(RuneUI), "_successDialog"); GameObject val3 = (GameObject)fieldInfo2.GetValue(__instance); if ((Object)(object)val3 != (Object)null) { Object.Destroy((Object)(object)val3); } GameObject val4 = RuneUI.RuneEnchancedItem.Invoke(item2, item, num2); if ((Object)(object)val4 != (Object)null) { fieldInfo2.SetValue(__instance, val4); val4.SetActive(true); InventoryManagement.Instance.RemoveExactItem(item, 1); } else { fieldInfo2.SetValue(__instance, null); AccessTools.Method(typeof(RuneUI), "Unlock", (Type[])null, (Type[])null).Invoke(__instance, null); } MultiSelectItemList val5 = (MultiSelectItemList)AccessTools.Field(typeof(RuneUI), "CostList").GetValue(__instance); val5.SetItems(new List<IListElement>()); ((EnchantingTableUIPanelBase)__instance).DeselectAll(); AccessTools.Method(typeof(RuneUI), "RefreshAvailableItems", (Type[])null, (Type[])null).Invoke(__instance, null); AccessTools.Field(typeof(RuneUI), "_selectedEnchantmentIndex").SetValue(__instance, -1); val5.SetItems(new List<IListElement>()); val2.SetItems(new List<IListElement>()); return false; } } [HarmonyPatch(typeof(RuneUI), "Lock")] internal class RuneUI_Lock_Patch { private static void Postfix(RuneUI __instance) { //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Expected O, but got Unknown Button val = (Button)AccessTools.Field(typeof(EnchantingTableUIPanelBase), "MainButton").GetValue(__instance); if ((Object)(object)val != (Object)null) { ((Selectable)val).interactable = true; } } } } 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; } } } namespace EpicLootAPI { [Serializable] [PublicAPI] internal enum AbilityActivationMode { Passive, Triggerable, Activated } [Serializable] [PublicAPI] internal enum AbilityAction { Custom, StatusEffect } [Serializable] [PublicAPI] internal class AbilityDefinition { public string ID = ""; public string IconAsset = ""; public AbilityActivationMode ActivationMode; public float Cooldown; public AbilityAction Action; public List<string> ActionParams = new List<string>(); internal static readonly Method API_AddAbility = new Method("AddAbility"); internal static readonly Method API_UpdateAbility = new Method("UpdateAbility"); internal static List<AbilityDefinition> Abilities = new List<AbilityDefinition>(); [Description("Register a status effect ability which activates on player input")] public AbilityDefinition(string ID, string iconAsset, float cooldown, string statusEffectName) { this.ID = ID; ActivationMode = AbilityActivationMode.Activated; Cooldown = cooldown; Action = AbilityAction.StatusEffect; ActionParams.Add(statusEffectName); IconAsset = iconAsset; Abilities.Add(this); } internal AbilityDefinition(string ID, AbilityActivationMode mode) { this.ID = ID; ActivationMode = mode; } public AbilityDefinition() { } public static void RegisterAll() { foreach (AbilityDefinition item in new List<AbilityDefinition>(Abilities)) { item.Register(); } } public bool Register() { string text = JsonConvert.SerializeObject((object)this); object[] array = API_AddAbility.Invoke(text); if (!(array[0] is string value)) { return false; } RunTimeRegistry.Register(this, value); Abilities.Remove(this); EpicLoot.logger.LogDebug("Registered ability: " + ID); return true; } public bool Update() { if (!RunTimeRegistry.TryGetValue(this, out string value)) { return false; } string text = JsonConvert.SerializeObject((object)this); object[] array = API_UpdateAbility.Invoke(value, text); bool flag = (bool)(array[0] ?? ((object)false)); EpicLoot.logger.LogDebug($"Updated ability {ID}: {flag}"); return flag; } } [PublicAPI] internal class AbilityProxyDefinition { public readonly AbilityDefinition Ability; public readonly Dictionary<string, Delegate> Callbacks = new Dictionary<string, Delegate>(); internal static readonly List<AbilityProxyDefinition> ProxyAbilities = new List<AbilityProxyDefinition>(); internal static readonly Method API_RegisterProxyAbility = new Method("RegisterProxyAbility"); internal static readonly Method API_UpdateProxyAbility = new Method("UpdateProxyAbility"); [Description("Register a complex ability behavior using Proxy class")] public AbilityProxyDefinition(string ID, AbilityActivationMode mode, Proxy definition) { Ability = new AbilityDefinition(ID, mode); RegisterCallbacks(definition); ProxyAbilities.Add(this); } [Description("Register a complex ability behavior using Proxy class")] public AbilityProxyDefinition(string ID, AbilityActivationMode mode, Type type) { Ability = new AbilityDefinition(ID, mode); if (!typeof(Proxy).IsAssignableFrom(type)) { EpicLoot.logger.LogError("Ability Proxy " + ID + " Type " + type.Name + " does not implement Proxy class"); return; } try { object obj = Activator.CreateInstance(type); RegisterCallbacks((Proxy)obj); ProxyAbilities.Add(this); } catch (Exception ex) { EpicLoot.logger.LogError("Failed to create instance of " + type.Name + ": " + ex.Message); } } private void RegisterCallbacks(Proxy implementation) { Type type = implementation.GetType(); Type typeFromHandle = typeof(Proxy); MethodInfo[] methods = typeFromHandle.GetMethods(); MethodInfo[] array = methods; foreach (MethodInfo methodInfo in array) { try { Type[] array2 = (from p in methodInfo.GetParameters() select p.ParameterType).ToArray(); MethodInfo method = type.GetMethod(methodInfo.Name, array2); if (method == null) { EpicLoot.logger.LogWarning("Method " + methodInfo.Name + " not found in implementation"); continue; } Type type2; if (methodInfo.ReturnType == typeof(void)) { type2 = ((array2.Length != 0) ? Expression.GetActionType(array2) : typeof(Action)); } else { Type[] typeArgs = array2.Concat(new Type[1] { methodInfo.ReturnType }).ToArray(); type2 = Expression.GetFuncType(typeArgs); } Delegate value = Delegate.CreateDelegate(type2, implementation, method); Callbacks[methodInfo.Name] = value; } catch (Exception ex) { EpicLoot.logger.LogError("Failed to register callback for method " + methodInfo.Name + ": " + ex.Message); } } } public static void RegisterAll() { foreach (AbilityProxyDefinition item in new List<AbilityProxyDefinition>(ProxyAbilities)) { item.Register(); } } public bool Register() { string text = JsonConvert.SerializeObject((object)Ability); object[] array = API_RegisterProxyAbility.Invoke(text, Callbacks); if (!(array[0] is string value)) { return false; } RunTimeRegistry.Register(this, value); ProxyAbilities.Remove(this); EpicLoot.logger.LogDebug("Registered proxy ability: " + Ability.ID); return true; } public bool Update() { if (!RunTimeRegistry.TryGetValue(this, out string value)) { return false; } string text = JsonConvert.SerializeObject((object)Ability); object[] array = API_UpdateProxyAbility.Invoke(value, text, Callbacks); bool flag = (bool)(array[0] ?? ((object)false)); EpicLoot.logger.LogDebug($"Updated proxy ability: {Ability.ID}, {flag}"); return flag; } } [Description("Functions are converted into delegates when registered to epic loot")] [PublicAPI] internal class Proxy { protected Player Player; public string AbilityID = ""; public float Cooldown; public virtual string CooldownEndKey => "EpicLoot." + AbilityID + ".CooldownEnd"; public virtual void Initialize(Player player, string id, float cooldown) { Player = player; AbilityID = id; Cooldown = cooldown; } public virtual void OnUpdate() { } public virtual bool ShouldTrigger() { return false; } public virtual bool IsOnCooldown() { if (HasCooldown()) { return GetTime() < GetCooldownEndTime(); } return false; } public virtual float TimeUntilCooldownEnds() { return Mathf.Max(0f, GetCooldownEndTime() - GetTime()); } public virtual float PercentCooldownComplete() { if (HasCooldown() && IsOnCooldown()) { return 1f - TimeUntilCooldownEnds() / Cooldown; } return 1f; } public virtual bool CanActivate() { return !IsOnCooldown(); } public virtual void TryActivate() { if (CanActivate()) { Activate(); } } public virtual void Activate() { if (HasCooldown()) { float cooldownEndTime = GetTime() + Cooldown; SetCooldownEndTime(cooldownEndTime); } } public virtual void ActivateCustomAction() { } public virtual void ActivateStatusEffectAction() { } public virtual bool HasCooldown() { return Cooldown > 0f; } public virtual void SetCooldownEndTime(float cooldownEndTime) { if (!((Object)(object)Player == (Object)null)) { ((Character)Player).m_nview.GetZDO().Set(CooldownEndKey, cooldownEndTime); } } public virtual float GetCooldownEndTime() { if ((Object)(object)Player == (Object)null) { return 0f; } return ((Character)Player).m_nview.GetZDO().GetFloat(CooldownEndKey, 0f); } public virtual void OnRemoved() { } protected static float GetTime() { return (float)ZNet.instance.GetTimeSeconds(); } } internal static class EpicLoot { public static readonly Logger logger = new Logger(); private static readonly Method API_GetTotalActiveMagicEffectValue = new Method("GetTotalActiveMagicEffectValue"); private static readonly Method API_GetTotalActiveMagicEffectValueForWeapon = new Method("GetTotalActiveMagicEffectValueForWeapon"); private static readonly Method API_HasActiveMagicEffect = new Method("HasActiveMagicEffect"); private static readonly Method API_HasActiveMagicEffectOnWeapon = new Method("HasActiveMagicEffectOnWeapon"); private static readonly Method API_GetTotalActiveSetEffectValue = new Method("GetTotalActiveSetEffectValue"); private static readonly Method API_GetAllActiveMagicEffects = new Method("GetAllActiveMagicEffects"); private static readonly Method API_GetAllSetMagicEffects = new Method("GetAllActiveSetMagicEffects"); private static readonly Method API_GetPlayerTotalActiveMagicEffectValue = new Method("GetTotalPlayerActiveMagicEffectValue"); private static readonly Method API_PlayerHasActiveMagicEffect = new Method("PlayerHasActiveMagicEffect"); private static readonly Method API_HasLegendaryItem = new Method("HasLegendaryItem"); private static readonly Method API_HasLegendarySet = new Method("HasLegendarySet"); private static readonly Method API_RegisterAsset = new Method("RegisterAsset"); private static readonly Method API_GetMagicItemJson = new Method("GetMagicItemJson"); [PublicAPI] [Description("Send all your custom conversions, effects, item definitions, etc... to Epic Loot")] public static void RegisterAll() { MaterialConversion.RegisterAll(); MagicItemEffectDefinition.RegisterAll(); AbilityDefinition.RegisterAll(); CustomRecipe.RegisterAll(); Sacrifice.RegisterAll(); TreasureMap.RegisterAll(); SecretStashItem.RegisterAll(); LegendaryInfo.RegisterAll(); LegendarySetInfo.RegisterAll(); BountyTarget.RegisterAll(); AbilityProxyDefinition.RegisterAll(); } [PublicAPI] [Description("Register asset into EpicLoot in order to target them in your definitions")] public static bool RegisterAsset(string name, object asset) { object[] array = API_RegisterAsset.Invoke(name, asset); bool flag = (bool)(array[0] ?? ((object)false)); logger.LogDebug($"Registered asset: {name}, {flag}"); return flag; } [PublicAPI] public static bool HasLegendaryItem(this Player player, string legendaryItemID) { object[] array = API_HasLegendaryItem.Invoke(player, legendaryItemID); bool flag = (bool)(array[0] ?? ((object)false)); logger.LogDebug($"Has legendary item: {legendaryItemID}, {flag} "); return flag; } [PublicAPI] public static bool HasLegendarySet(this Player player, string legendarySetID, out int count) { count = 0; object[] array = API_HasLegendarySet.Invoke(player, legendarySetID, count); count = (int)(array[3] ?? ((object)0)); bool flag = (bool)(array[0] ?? ((object)false)); logger.LogDebug($"Has legendary set: {legendarySetID}, {flag}, count: {count}"); return flag; } [PublicAPI] public static bool HasActiveMagicEffectOnWeapon(Player player, ItemData item, string effectType, out float effectValue) { effectValue = 0f; object[] array = API_HasActiveMagicEffectOnWeapon.Invoke(player, item, effectType, effectValue); effectValue = (float)(array[4] ?? ((object)0f)); bool flag = (bool)(array[0] ?? ((object)false)); logger.LogDebug($"Has magic effect on weapon: {effectType}, {flag}, value: {effectValue}"); return flag; } [PublicAPI] public static float GetTotalActiveMagicEffectValue(Player player, ItemData item, string effectType, float scale = 1f) { object[] array = API_GetTotalActiveMagicEffectValue.Invoke(player, item, effectType); float num = (float)(array[0] ?? ((object)0f)); logger.LogDebug($"Total magic effect value: {effectType}, amount: {num}"); return num; } [PublicAPI] public static float GetTotalActiveMagicEffectValueForWeapon(Player player, ItemData item, string effectType, float scale = 1f) { object[] array = API_GetTotalActiveMagicEffectValueForWeapon.Invoke(player, item, effectType, scale); float num = (float)(array[0] ?? ((object)0f)); logger.LogDebug($"Total effect on weapon: {effectType}, amount: {num}"); return num; } [PublicAPI] public static bool HasActiveMagicEffect(Player player, string effectType, ItemData ignoreThisItem = null, float scale = 1f) { object[] array = API_HasActiveMagicEffect.Invoke(player, ignoreThisItem, effectType, scale); bool flag = (bool)(array[0] ?? ((object)false)); logger.LogDebug($"Has active effect: {effectType}, {flag}"); return flag; } [PublicAPI] public static float GetTotalActiveSetEffectValue(Player player, string effectType, float scale = 1f) { object[] array = API_GetTotalActiveSetEffectValue.Invoke(player, effectType, scale); float num = (float)(array[0] ?? ((object)0f)); logger.LogDebug($"Total effect value: {effectType}, amount: {num}"); return num; } [PublicAPI] public static List<MagicItemEffect> GetAllActiveMagicEffects(this Player player, string effectType = null) { object[] array = API_GetAllActiveMagicEffects.Invoke(player, effectType); List<string> list = (List<string>)(array[0] ?? new List<string>()); if (list.Count <= 0) { return new List<MagicItemEffect>(); } List<MagicItemEffect> list2 = new List<MagicItemEffect>(); list2.DeserializeList(list); return list2; } [PublicAPI] public static List<MagicItemEffect> GetAllActiveSetMagicEffects(this Player player, string effectType = null) { object[] array = API_GetAllSetMagicEffects.Invoke(player, effectType); List<string> list = (List<string>)(array[0] ?? new List<string>()); if (list.Count <= 0) { return new List<MagicItemEffect>(); } List<MagicItemEffect> list2 = new List<MagicItemEffect>(); list2.DeserializeList(list); return list2; } private static void DeserializeList<T>(this List<T> output, List<string> input) { foreach (string item in input) { try { T val = JsonConvert.DeserializeObject<T>(item); if (val != null) { output.Add(val); } } catch { logger.LogWarning("Failed to parse " + typeof(T).Name); } } } [PublicAPI] public static float GetTotalActiveMagicEffectValue(this Player player, string effectType, float scale = 1f, ItemData ignoreThisItem = null) { object[] array = API_GetPlayerTotalActiveMagicEffectValue.Invoke(player, effectType, scale, ignoreThisItem); float num = (float)(array[0] ?? ((object)0f)); logger.LogDebug($"Total magic effect: {effectType}, value: {num}"); return num; } [PublicAPI] public static bool HasActiveMagicEffect(this Player player, string effectType, out float effectValue, float scale = 1f, ItemData ignoreThisItem = null) { effectValue = 0f; object[] array = API_PlayerHasActiveMagicEffect.Invoke(player, effectType, effectValue, scale, ignoreThisItem); effectValue = (float)(array[3] ?? ((object)0f)); bool flag = (bool)(array[0] ?? ((object)false)); logger.LogDebug($"Has active magic effect: {effectType}, value: {flag}"); return flag; } [PublicAPI] public static MagicItem GetMagicItem(this ItemData itemData) { object[] array = API_GetMagicItemJson.Invoke(itemData); string text = (string)(array[0] ?? ""); if (string.IsNullOrEmpty(text)) { return null; } return JsonConvert.DeserializeObject<MagicItem>(text); } } [Serializable] [PublicAPI] internal class BountyMinion { public string ID = ""; public int Count; public BountyMinion(string ID, int count) { this.ID = ID; Count = count; } public BountyMinion() { } } [Serializable] [PublicAPI] internal class BountyTarget { public Biome Biome = (Biome)0; public string TargetID = ""; public int RewardGold; public int RewardIron; public int RewardCoins; public List<BountyMinion> Adds = new List<BountyMinion>(); internal static readonly List<BountyTarget> BountyTargets = new List<BountyTarget>(); internal static readonly Method API_AddBountyTarget = new Method("AddBountyTarget"); internal static readonly Method API_UpdateBountyTarget = new Method("UpdateBountyTarget"); public BountyTarget(Biome biome, string targetID) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) Biome = biome; TargetID = targetID; BountyTargets.Add(this); } public BountyTarget() { }//IL_0002: Unknown result type (might be due to invalid IL or missing references) public static void RegisterAll() { foreach (BountyTarget item in new List<BountyTarget>(BountyTargets)) { item.Register(); } } public bool Register() { string text = JsonConvert.SerializeObject((object)this); object[] array = API_AddBountyTarget.Invoke(text); if (!(array[0] is string value)) { return false; } RunTimeRegistry.Register(BountyTargets, value); BountyTargets.Remove(this); EpicLoot.logger.LogDebug("Registered bounty: " + TargetID); return true; } public bool Update() { if (!RunTimeRegistry.TryGetValue(this, out string value)) { return false; } string text = JsonConvert.SerializeObject((object)BountyTargets); object[] array = API_UpdateBountyTarget.Invoke(value, text); bool flag = (bool)(array[0] ?? ((object)false)); EpicLoot.logger.LogDebug($"Updated bounty target: {TargetID}, {flag}"); return flag; } } [Serializable] [PublicAPI] internal class RecipeRequirement { public string item; public int amount; public RecipeRequirement(string item, int amount = 1) { this.item = item; this.amount = amount; } } [Serializable] [PublicAPI] internal class CustomRecipe { public string name = ""; public string item = ""; public int amount; public string craftingStation = ""; public int minStationLevel = 1; public bool enabled = true; public string repairStation = ""; public List<RecipeRequirement> resources = new List<RecipeRequirement>(); internal static readonly List<CustomRecipe> Recipes = new List<CustomRecipe>(); internal static readonly Method API_AddRecipe = new Method("AddRecipe"); public CustomRecipe(string name, string item, CraftingTable craftingTable, int amount = 1) { this.name = name; this.item = item; this.amount = amount; craftingStation = craftingTable.GetInternalName(); Recipes.Add(this); } public CustomRecipe() { } [PublicAPI] public static void RegisterAll() { foreach (CustomRecipe item in new List<CustomRecipe>(Recipes)) { item.Register(); } } public bool Register() { string text = JsonConvert.SerializeObject((object)this); object[] array = API_AddRecipe.Invoke(text); if (!(array[0] is string value)) { return false; } RunTimeRegistry.Register(this, value); Recipes.Remove(this); EpicLoot.logger.LogDebug("Registered recipe: " + name); return true; } } [PublicAPI] internal enum CraftingTable { [InternalName("piece_workbench")] Workbench, [InternalName("piece_cauldron")] Cauldron, [InternalName("forge")] Forge, [InternalName("piece_artisanstation")] ArtisanTable, [InternalName("piece_stonecutter")] StoneCutter, [InternalName("piece_magetable")] MageTable, [InternalName("blackforge")] BlackForge, [InternalName("piece_preptable")] FoodPreparationTable, [InternalName("piece_MeadCauldron")] MeadKetill } internal class InternalName : Attribute { public readonly string internalName; public InternalName(string internalName) { this.internalName = internalName; } } [PublicAPI] internal static class EffectType { public static string DvergerCirclet = "DvergerCirclet"; public static string InstantMead = "InstantMead"; public static string AutoMead = "AutoMead"; public static string DecreaseMeadCooldown = "DecreaseMeadCooldown"; public static string Megingjord = "Megingjord"; public static string Wishbone = "Wishbone"; public static string Andvaranaut = "Andvaranaut"; public static string ModifyDamage = "ModifyDamage"; public static string ModifyPhysicalDamage = "ModifyPhysicalDamage"; public static string ModifyElementalDamage = "ModifyElementalDamage"; public static string ModifyDurability = "ModifyDurability"; public static string ModifyDrawStaminaUse = "ModifyDrawStaminaUse"; public static string ReduceWeight = "ReduceWeight"; public static string RemoveSpeedPenalty = "RemoveSpeedPenalty"; public static string ModifyBlockPower = "ModifyBlockPower"; public static string ModifyBlockForce = "ModifyBlockForce"; public static string ModifyParry = "ModifyParry"; public static string ModifyArmor = "ModifyArmor"; public static string ModifyBackstab = "ModifyBackstab"; public static string IncreaseMiningDrop = "IncreaseMiningDrop"; public static string IncreaseTreeDrop = "IncreaseTreeDrop"; public static string IncreaseHealth = "IncreaseHealth"; public static string IncreaseHeatResistance = "IncreaseHeatResistance"; public static string IncreaseStamina = "IncreaseStamina"; public static string IncreaseEitr = "IncreaseEitr"; public static string DecreaseForsakenCooldown = "DecreaseForsakenCooldown"; public static string ModifyHealthRegen = "ModifyHealthRegen"; public static string AddHealthRegen = "AddHealthRegen"; public static string ModifyStaminaRegen = "ModifyStaminaRegen"; public static string ModifyEitrRegen = "ModifyEitrRegen"; public static string AddBluntDamage = "AddBluntDamage"; public static string AddSlashingDamage = "AddSlashingDamage"; public static string AddPiercingDamage = "AddPiercingDamage"; public static string AddFireDamage = "AddFireDamage"; public static string AddFrostDamage = "AddFrostDamage"; public static string AddLightningDamage = "AddLightningDamage"; public static string AddPoisonDamage = "AddPoisonDamage"; public static string AddSpiritDamage = "AddSpiritDamage"; public static string AddFireResistancePercentage = "AddFireResistancePercentage"; public static string AddFrostResistancePercentage = "AddFrostResistancePercentage"; public static string AddLightningResistancePercentage = "AddLightningResistancePercentage"; public static string AddPoisonResistancePercentage = "AddPoisonResistancePercentage"; public static string AddSpiritResistancePercentage = "AddSpiritResistancePercentage"; public static string AddElementalResistancePercentage = "AddElementalResistancePercentage"; public static string AddBluntResistancePercentage = "AddBluntResistancePercentage"; public static string AddSlashingResistancePercentage = "AddSlashingResistancePercentage"; public static string AddPiercingResistancePercentage = "AddPiercingResistancePercentage"; public static string AddChoppingResistancePercentage = "AddChoppingResistancePercentage"; public static string AddPhysicalResistancePercentage = "AddPhysicalResistancePercentage"; public static string ModifyMovementSpeed = "ModifyMovementSpeed"; public static string ModifySprintStaminaUse = "ModifySprintStaminaUse"; public static string ModifyNoise = "ModifyNoise"; public static string ModifyBuildDistance = "ModifyBuildDistance"; public static string ModifyPickupRange = "ModifyPickupRange"; public static string ModifyMagicFireRate = "ModifyMagicFireRate"; public static string AmmoConservation = "AmmoConservation"; public static string ModifyProjectileSpeed = "ModifyProjectileSpeed"; public static string ModifyDodgeStaminaUse = "ModifyDodgeStaminaUse"; public static string ModifyJumpStaminaUse = "ModifyJumpStaminaUse"; public static string ModifyAttackStaminaUse = "ModifyAttackStaminaUse"; public static string ModifyAttackEitrUse = "ModifyAttackEitrUse"; public static string ModifyAttackHealthUse = "ModifyAttackHealthUse"; public static string ModifyBlockStaminaUse = "ModifyBlockStaminaUse"; public static string ModifySummonHealth = "ModifySummonHealth"; public static string ModifySummonDamage = "ModifySummonDamage"; public static string ModifyWispRange = "ModifyWispRange"; public static string Indestructible = "Indestructible"; public static string CoinHoarder = "CoinHoarder"; public static string Weightless = "Weightless"; public static string LifeSteal = "LifeSteal"; public static string EitrLeech = "EitrLeech"; public static string Bloodlust = "Bloodlust"; public static string AddCarryWeight = "AddCarryWeight"; public static string ModifyAttackSpeed = "ModifyAttackSpeed"; public static string Throwable = "Throwable"; public static string Waterproof = "Waterproof"; public static string Warmth = "Warmth"; public static string Paralyze = "Paralyze"; public static string DoubleJump = "DoubleJump"; public static string ExplosiveArrows = "ExplosiveArrows"; public static string QuickDraw = "QuickDraw"; public static string AddSwordsSkill = "AddSwordsSkill"; public static string AddKnivesSkill = "AddKnivesSkill"; public static string AddClubsSkill = "AddClubsSkill"; public static string AddPolearmsSkill = "AddPolearmsSkill"; public static string AddSpearsSkill = "AddSpearsSkill"; public static string AddBlockingSkill = "AddBlockingSkill"; public static string AddAxesSkill = "AddAxesSkill"; public static string AddBowsSkill = "AddBowsSkill"; public static string AddCrossbowsSkill = "AddCrossbowsSkill"; public static string AddUnarmedSkill = "AddUnarmedSkill"; public static string AddPickaxesSkill = "AddPickaxesSkill"; public static string AddFishingSkill = "AddFishingSkill"; public static string AddElementalMagicSkill = "AddElementalMagicSkill"; public static string AddBloodMagicSkill = "AddBloodMagicSkill"; public static string AddMovementSkills = "AddMovementSkills"; public static string AddCrafterSkills = "AddCrafterSkills"; public static string ModifyStaggerDuration = "ModifyStaggerDuration"; public static string QuickLearner = "QuickLearner"; public static string RecallWeapon = "RecallWeapon"; public static string ReflectDamage = "ReflectDamage"; public static string AvoidDamageTaken = "AvoidDamageTaken"; public static string StaggerOnDamageTaken = "StaggerOnDamageTaken"; public static string FeatherFall = "FeatherFall"; public static string ModifyDiscoveryRadius = "ModifyDiscoveryRadius"; public static string FreeBuild = "FreeBuild"; public static string Comfortable = "Comfortable"; public static string ModifyLowHealth = "ModifyLowHealth"; public static string ModifyMovementSpeedLowHealth = "ModifyMovementSpeedLowHealth"; public static string ModifyHealthRegenLowHealth = "ModifyHealthRegenLowHealth"; public static string ModifyStaminaRegenLowHealth = "ModifyStaminaRegenLowHealth"; public static string ModifyEitrRegenLowHealth = "ModifyEitrRegenLowHealth"; public static string ModifyArmorLowHealth = "ModifyArmorLowHealth"; public static string ModifyDamageLowHealth = "ModifyDamageLowHealth"; public static string ModifyBlockPowerLowHealth = "ModifyBlockPowerLowHealth"; public static string ModifyParryLowHealth = "ModifyParryLowHealth"; public static string ModifyAttackSpeedLowHealth = "ModifyAttackSpeedLowHealth"; public static string AvoidDamageTakenLowHealth = "AvoidDamageTakenLowHealth"; public static string LifeStealLowHealth = "LifeStealLowHealth"; public static string Glowing = "Glowing"; public static string Executioner = "Executioner"; public static string Riches = "Riches"; public static string Opportunist = "Opportunist"; public static string Duelist = "Duelist"; public static string Immovable = "Immovable"; public static string ModifyStaggerDamage = "ModifyStaggerDamage"; public static string Luck = "Luck"; public static string ModifyParryWindow = "ModifyParryWindow"; public static string Slow = "Slow"; public static string FrostDamageAOE = "FrostDamageAOE"; public static string DoubleMagicShot = "DoubleMagicShot"; public static string TripleBowShot = "TripleBowShot"; public static string SpellSword = "SpellSword"; public static string BulkUp = "BulkUp"; public static string EitrWeave = "EitrWeave"; public static string DartingThoughts = "DartingThoughts"; public static string HeadHunter = "HeadHunter"; public static string DodgeBuff = "DodgeBuff"; public static string OffSetAttack = "OffSetAttack"; public static string ChainLightning = "ChainLightning"; public static string Apportation = "Apportation"; public static string ModifyFireRate = "ModifyFireRate"; public static string Bulwark = "Bulwark"; public static string Undying = "Undying"; } internal static class Helpers { [PublicAPI] public static void Add<T>(this List<T> list, params T[] items) { list.AddRange(items); } [PublicAPI] public static void AddMinion(this List<BountyMinion> list, string ID, int count) { list.Add(new BountyMinion(ID, count)); } [PublicAPI] public static void Add(this List<ItemAmount> list, string item, int amount = 1) { list.Add(new ItemAmount(item, amount)); } [PublicAPI] public static void Add(this List<MaterialConversionRequirement> list, string item, int amount = 1) { list.Add(new MaterialConversionRequirement(item, amount)); } internal static string GetInternalName(this CraftingTable table) { Type typeFromHandle = typeof(CraftingTable); MemberInfo[] member = typeFromHandle.GetMember(table.ToString()); if (member.Length == 0) { return table.ToString(); } InternalName internalName = (InternalName)Attribute.GetCustomAttribute(member[0], typeof(InternalName)); return (internalName != null) ? internalName.internalName : table.ToString(); } [PublicAPI] public static void Add(this List<RecipeRequirement> list, string item, int amount = 1) { list.Add(new RecipeRequirement(item, amount)); } [PublicAPI] public static void Add(this List<SetBonusInfo> list, int count, string type, float min = 1f, float max = 1f, float increment = 1f) { list.Add(new SetBonusInfo(count, type, min, max, increment)); } [PublicAPI] public static void Add(this List<GuaranteedMagicEffect> list, string type, float min = 1f, float max = 1f, float increment = 1f) { list.Add(new GuaranteedMagicEffect(type, min, max, increment)); } } [Serializable] [PublicAPI] internal class GuaranteedMagicEffect { public string Type = ""; public ValueDef Values = new ValueDef(); public GuaranteedMagicEffect(string type, ValueDef values) { Type = type; Values = values; } public GuaranteedMagicEffect(string type, float min = 1f, float max = 1f, float increment = 1f) : this(type, new ValueDef(min, max, increment)) { } public GuaranteedMagicEffect() { } } [Serializable] [PublicAPI] internal class TextureReplacement { public string ItemID = ""; public string MainTexture = ""; public string ChestTex = ""; public string LegsTex = ""; public TextureReplacement(string itemID, string mainTex = "", string chestTex = "", string legsTex = "") { ItemID = itemID; MainTexture = mainTex; ChestTex = chestTex; LegsTex = legsTex; } public TextureReplacement() { } } [Serializable] [PublicAPI] internal class LegendaryInfo { public string ID = ""; public string Name = ""; public string Description = ""; public MagicItemEffectRequirements Requirements = new MagicItemEffectRequirements(); public List<GuaranteedMagicEffect> GuaranteedMagicEffects = new List<GuaranteedMagicEffect>(); public int GuaranteedEffectCount = -1; public float SelectionWeight = 1f; public string EquipFx = ""; public FxAttachMode EquipFxMode = FxAttachMode.Player; public List<TextureReplacement> TextureReplacements = new List<TextureReplacement>(); public bool IsSetItem; public bool Enchantable; public List<RecipeRequirement> EnchantCost = new List<RecipeRequirement>(); private LegendaryType type; internal static readonly List<LegendaryInfo> LegendaryItems = new List<LegendaryInfo>(); internal static readonly Method API_AddLegendaryItem = new Method("AddLegendaryItem"); internal static readonly Method API_UpdateLegendaryItem = new Method("UpdateLegendaryItem"); public LegendaryInfo(LegendaryType type, string ID, string name, string description) { this.ID = ID; Name = name; Description = description; this.type = type; LegendaryItems.Add(this); } public LegendaryInfo() { } public static void RegisterAll() { foreach (LegendaryInfo item in new List<LegendaryInfo>(LegendaryItems)) { item.Register(); } } public bool Register() { string text = JsonConvert.SerializeObject((object)this); object[] array = API_AddLegendaryItem.Invoke(type.ToString(), text); if (!(array[0] is string value)) { return false; } RunTimeRegistry.Register(this, value); LegendaryItems.Remove(this); EpicLoot.logger.LogDebug("Registered legendary item: " + ID); return true; } public bool Update() { if (!RunTimeRegistry.TryGetValue(this, out string value)) { return false; } string text = JsonConvert.SerializeObject((object)this); object[] array = API_UpdateLegendaryItem.Invoke(value, text); bool flag = (bool)(array[0] ?? ((object)false)); EpicLoot.logger.LogDebug($"Updated legendary item: {ID}, {flag}"); return flag; } } [PublicAPI] internal enum LegendaryType { Legendary, Mythic } [Serializable] [PublicAPI] internal class SetBonusInfo { public int Count; public GuaranteedMagicEffect Effect = new GuaranteedMagicEffect(); public SetBonusInfo(int count, string type, ValueDef values) { Count = count; Effect = new GuaranteedMagicEffect(type, values); } public SetBonusInfo(int count, string type, float min, float max, float increment) : this(count, type, new ValueDef(min, max, increment)) { } public SetBonusInfo() { } } [Serializable] [PublicAPI] internal class LegendarySetInfo { public string ID = ""; public string Name = ""; public List<string> LegendaryIDs = new List<string>(); public List<SetBonusInfo> SetBonuses = new List<SetBonusInfo>(); private LegendaryType type; internal static readonly List<LegendarySetInfo> LegendarySets = new List<LegendarySetInfo>(); internal static readonly Method API_AddLegendarySet = new Method("AddLegendarySet"); internal static readonly Method API_UpdateLegendarySet = new Method("UpdateLegendarySet"); public LegendarySetInfo(LegendaryType type, string ID, string name) { this.ID = ID; Name = name; this.type = type; LegendarySets.Add(this); } public LegendarySetInfo() { } public static void RegisterAll() { foreach (LegendarySetInfo item in new List<LegendarySetInfo>(LegendarySets)) { item.Register(); } } public bool Register() { string text = JsonConvert.SerializeObject((object)this); object[] array = API_AddLegendarySet.Invoke(type.ToString(), text); if (!(array[0] is string value)) { return false; } RunTimeRegistry.Register(this, value); EpicLoot.logger.LogDebug("Registered legendary set: " + ID); return true; } public bool Update() { if (!RunTimeRegistry.TryGetValue(this, out string value)) { return false; } string text = JsonConvert.SerializeObject((object)this); object[] array = API_UpdateLegendarySet.Invoke(value, text); bool flag = (bool)(array[0] ?? ((object)false)); EpicLoot.logger.LogDebug($"Updated legendary set: {ID}, {flag}"); return flag; } } internal class Logger { public event Action<string> OnError; public event Action<string> OnDebug; public event Action<string> OnWarning; public void LogError(string message) { this.OnError?.Invoke(message); } public void LogDebug(string message) { this.OnDebug?.Invoke(message); } public void LogWarning(string message) { this.OnWarning?.Invoke(message); } } [Serializable] [PublicAPI] internal class MagicItem { public int Version; public ItemRarity Rarity; public List<MagicItemEffect> Effects = new List<MagicItemEffect>(); public string TypeNameOverride = ""; public int AugmentedEffectIndex; public List<int> AugmentedEffectIndices = new List<int>(); public string DisplayName = ""; public string LegendaryID = ""; public string SetID = ""; } [PublicAPI] internal enum FxAttachMode { None, Player, ItemRoot, EquipRoot } [PublicAPI] internal enum ItemRarity { Magic, Rare, Epic, Legendary, Mythic } [Serializable] [PublicAPI] internal class MagicItemEffect { public int Version = 1; public string EffectType = ""; public float EffectValue; public MagicItemEffect(string type, float value = 1f) { EffectType = type; EffectValue = value; } public MagicItemEffect() { } } [Serializable] [PublicAPI] internal class ValueDef { public float MinValue; public float MaxValue; public float Increment; public ValueDef() { } public ValueDef(float min, float max, float increment) { MinValue = min; MaxValue = max; Increment = increment; } public void Set(float min, float max, float increment = 1f) { MinValue = min; MaxValue = max; Increment = increment; } } [Serializable] [PublicAPI] internal class ValuesPerRarityDef { public ValueDef Magic = new ValueDef(); public ValueDef Rare = new ValueDef(); public ValueDef Epic = new ValueDef(); public ValueDef Legendary = new ValueDef(); public ValueDef Mythic = new ValueDef(); } [Serializable] [PublicAPI] internal class MagicItemEffectDefinition { public string Type = ""; public string DisplayText = ""; public string Description = ""; public MagicItemEffectRequirements Requirements = new MagicItemEffectRequirements(); public ValuesPerRarityDef ValuesPerRarity = new ValuesPerRarityDef(); public float SelectionWeight = 1f; public bool CanBeAugmented = true; public bool CanBeDisenchanted = true; public string Comment = ""; public List<string> Prefixes = new List<string>(); public List<string> Suffixes = new List<string>(); public string EquipFx = ""; public FxAttachMode EquipFxMode = FxAttachMode.Player; public string Ability = ""; internal static readonly List<MagicItemEffectDefinition> MagicEffects = new List<MagicItemEffectDefinition>(); internal static readonly Method API_AddMagicEffect = new Method("AddMagicEffect"); internal static readonly Method API_UpdateMagicEffect = new Method("UpdateMagicEffect"); internal static readonly Method API_GetMagicEffectDefinitionCopy = new Method("GetMagicItemEffectDefinition"); [Description("Adds your new magic item definition to a list, use Register to send to epic loot")] public MagicItemEffectDefinition(string effectType, string displayText = "", string description = "") { Type = effectType; DisplayText = displayText; Description = description; MagicEffects.Add(this); } public MagicItemEffectDefinition() { } public static void RegisterAll() { foreach (MagicItemEffectDefinition item in new List<MagicItemEffectDefinition>(MagicEffects)) { item.Register(); } } public static MagicItemEffectDefinition Copy(string effectType) { string text = (string)(API_GetMagicEffectDefinitionCopy.Invoke(effectType)[0] ?? ""); if (string.IsNullOrEmpty(text)) { return null; } try { return JsonConvert.DeserializeObject<MagicItemEffectDefinition>(text); } catch { EpicLoot.logger.LogWarning("Failed to parse magic item effect definition json"); return null; } } public bool Register() { //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Expected O, but got Unknown MagicEffects.Remove(this); string text = JsonConvert.SerializeObject((object)this, new JsonSerializerSettings { NullValueHandling = (NullValueHandling)0 }); object[] array = API_AddMagicEffect.Invoke(text); if (!(array[0] is string value)) { return false; } RunTimeRegistry.Register(this, value); EpicLoot.logger.LogDebug("Registered magic effect: " + Type); return true; } public bool Update() { if (!RunTimeRegistry.TryGetValue(this, out string value)) { return false; } string text = JsonConvert.SerializeObject((object)this); object[] array = API_UpdateMagicEffect.Invoke(value, text); bool flag = (bool)(array[0] ?? ((object)false)); EpicLoot.logger.LogDebug($"Updated magic effect: {Type}, {flag}"); return flag; } } [Serializable] [PublicAPI] internal class MagicItemEffectRequirements { private static List<string> _flags = new List<string>(); public bool NoRoll; public bool ExclusiveSelf = true; public List<string> ExclusiveEffectTypes = new List<string>(); public List<string> MustHaveEffectTypes = new List<string>(); public List<string> AllowedItemTypes = new List<string>(); public List<string> ExcludedItemTypes = new List<string>(); public List<ItemRarity> AllowedRarities = new List<ItemRarity>(); public List<ItemRarity> ExcludedRarities = new List<ItemRarity>(); public List<SkillType> AllowedSkillTypes = new List<SkillType>(); public List<SkillType> ExcludedSkillTypes = new List<SkillType>(); public List<string> AllowedItemNames = new List<string>(); public List<string> ExcludedItemNames = new List<string>(); public bool? ItemHasPhysicalDamage; public bool? ItemHasElementalDamage; public bool? ItemHasChopDamage; public bool? ItemUsesDurability; public bool? ItemHasNegativeMovementSpeedModifier; public bool? ItemHasBlockPower; public bool? ItemHasParryPower; public bool? ItemHasNoParryPower; public bool? ItemHasArmor; public bool? ItemHasBackstabBonus; public bool? ItemUsesStaminaOnAttack; public bool? ItemUsesEitrOnAttack; public bool? ItemUsesHealthOnAttack; public bool? ItemUsesDrawStaminaOnAttack; public List<string> CustomFlags = new List<string>(); public void AddAllowedItemTypes(params ItemType[] types) { //IL_000b: Unknown result type (might be due to invalid IL or missing references) for (int i = 0; i < types.Length; i++) { ItemType val = types[i]; AllowedItemTypes.Add(((object)(ItemType)(ref val)).ToString()); } } public void AddExcludedItemTypes(params ItemType[] types) { //IL_000b: Unknown result type (might be due to invalid IL or missing references) for (int i = 0; i < types.Length; i++) { ItemType val = types[i]; ExcludedItemTypes.Add(((object)(ItemType)(ref val)).ToString()); } } } [Serializable] [PublicAPI] internal enum MaterialConversionType { Upgrade, Convert, Junk } [Serializable] [PublicAPI] internal class MaterialConversionRequirement { public string Item = ""; public int Amount; public MaterialConversionRequirement(string item, int amount = 1) { Item = item; Amount = amount; } public MaterialConversionRequirement() { } } [Serializable] [PublicAPI] internal class MaterialConversion { public string Name = ""; public string Product = ""; public int Amount; public MaterialConversionType Type; public List<MaterialConversionRequirement> Resources = new List<MaterialConversionRequirement>(); internal static readonly Method API_AddMaterialConversion = new Method("AddMaterialConversion"); internal static readonly Method API_UpdateMaterialConversion = new Method("UpdateMaterialConversion"); internal static readonly List<MaterialConversion> MaterialConversions = new List<MaterialConversion>(); [Description("Creates a new material conversion definition.")] public MaterialConversion(MaterialConversionType type, string name, string product, int amount = 1) { Name = name; Product = product; Amount = amount; Type = type; MaterialConversions.Add(this); } public MaterialConversion() { } public static void RegisterAll() { foreach (MaterialConversion item in new List<MaterialConversion>(MaterialConversions)) { item.Register(); } } [Description("serializes to json and sends to EpicLoot")] public bool Register() { string text = JsonConvert.SerializeObject((object)this); object[] array = API_AddMaterialConversion.Invoke(text); if (!(array[0] is string value)) { return false; } MaterialConversions.Remove(this); RunTimeRegistry.Register(this, value); EpicLoot.logger.LogDebug("Registered material conversion: " + Name); return true; } public bool Update() { if (!RunTimeRegistry.TryGetValue(this, out string value)) { return false; } string text = JsonConvert.SerializeObject((object)this); object[] array = API_UpdateMaterialConversion.Invoke(value, text); bool flag = (bool)(array[0] ?? ((object)false)); EpicLoot.logger.LogDebug($"Updated material conversion: {Name}, {flag}"); return flag; } } internal class Method { private const string Namespace = "EpicLoot"; private const string ClassName = "API"; private const string Assembly = "EpicLoot"; private const string API_LOCATION = "EpicLoot.API, EpicLoot"; private static readonly Dictionary<string, Type> CachedTypes = new Dictionary<string, Type>(); private readonly MethodInfo info; public object[] Invoke(params object[] args) { object obj = info?.Invoke(null, args); object[] array = new object[args.Length + 1]; array[0] = obj; Array.Copy(args, 0, array, 1, args.Length); return array; } public Method(string typeNameWithAssembly, string methodName, BindingFlags bindingFlags = BindingFlags.Static | BindingFlags.Public) { if (!TryGetType(typeNameWithAssembly, out Type type)) { return; } if (type == null) { EpicLoot.logger.LogWarning("Type resolution returned null for: '" + typeNameWithAssembly + "'"); return; } info = type.GetMethod(methodName, bindingFlags); if (info == null) { EpicLoot.logger.LogWarning("Failed to find public static method '" + methodName + "' in type '" + type.FullName + "'. Verify the method name is correct, the method exists, and it is marked as public static. "); } } public Method(string methodName, BindingFlags bindingFlags = BindingFlags.Static | BindingFlags.Public) : this("EpicLoot.API, EpicLoot", methodName, bindingFlags) { } private static bool TryGetType(string typeNameWithAssembly, out Type type) { if (CachedTypes.TryGetValue(typeNameWithAssembly, out type)) { return true; } Type type2 = Type.GetType(typeNameWithAssembly); if ((object)type2 == null) { EpicLoot.logger.LogWarning("Failed to resolve type: '" + typeNameWithAssembly + "'. Verify the namespace, class name, and assembly name are correct. Ensure the assembly is loaded and accessible."); return false; } type = type2; CachedTypes[typeNameWithAssembly] = type2; return true; } public Method(string typeNameWithAssembly, string methodName, params Type[] types) { if (!TryGetType(typeNameWithAssembly, out Type type)) { return; } if (type == null) { EpicLoot.logger.LogWarning("Type resolution returned null for: '" + typeNameWithAssembly + "'"); return; } info = type.GetMethod(methodName, types); if (info == null) { EpicLoot.logger.LogWarning("Failed to find public static method '" + methodName + "' in type '" + type.FullName + "'. Verify the method name is correct, the method exists, and it is marked as public static. "); } } public Method(string methodName, params Type[] types) : this("EpicLoot.API, EpicLoot", methodName, types) { } [PublicAPI] public ParameterInfo[] GetParameters() { return info?.GetParameters() ?? Array.Empty<ParameterInfo>(); } [PublicAPI] public static void ClearCache() { CachedTypes.Clear(); } } internal static class RunTimeRegistry { private static readonly Dictionary<object, string> registry = new Dictionary<object, string>(); public static void Register(object key, string value) { registry[key] = value; } public static bool TryGetValue(object key, out string value) { return registry.TryGetValue(key, out value); } } [Serializable] [PublicAPI] internal class ItemAmount { public string Item = ""; public int Amount; public ItemAmount(string item, int amount = 1) { Item = item; Amount = amount; } public ItemAmount() { } } [Serializable] [PublicAPI] internal class Sacrifice { [Description("Conditional, checks item needs to be magic")] public bool IsMagic; [Description("Can be null")] public ItemRarity Rarity; [Description("Conditional, if empty, does not check if item is of correct type")] public List<string> ItemTypes = new List<string>(); [Description("Conditional, if empty, does not check if item shared name is in list")] public List<string> ItemNames = new List<string>(); [Description("Disenchant product entry")] public List<ItemAmount> Products = new List<ItemAmount>(); internal static readonly List<Sacrifice> Sacrifices = new List<Sacrifice>(); internal static readonly Method API_AddSacrifice = new Method("AddSacrifice"); internal static readonly Method API_UpdateSacrifice = new Method("UpdateSacrifice"); public Sacrifice() { Sacrifices.Add(this); } public void AddRequiredItemType(params ItemType[] types) { //IL_000b: Unknown result type (might be due to invalid IL or missing references) for (int i = 0; i < types.Length; i++) { ItemType val = types[i]; ItemTypes.Add(((object)(ItemType)(ref val)).ToString()); } } public static void RegisterAll() { foreach (Sacrifice item in new List<Sacrifice>(Sacrifices)) { item.Register(); } } public bool Register() { string text = JsonConvert.SerializeObject((object)this); object[] array = API_AddSacrifice.Invoke(text); if (!(array[0] is string value)) { return false; } Sacrifices.Remove(this); RunTimeRegistry.Register(this, value); EpicLoot.logger.LogDebug("Registered sacrifice"); return true; } public bool Update() { if (!RunTimeRegistry.TryGetValue(this, out string value)) { return false; } string text = JsonConvert.SerializeObject((object)this); object[] array = API_UpdateSacrifice.Invoke(value, text); bool flag = (bool)(array[0] ?? ((object)false)); EpicLoot.logger.LogDebug($"Updated sacrifice: {flag}"); return flag; } } [PublicAPI] internal enum SecretStashType { Materials, RandomItems, OtherItems, Gamble, Sale } [Serializable] [PublicAPI] internal class SecretStashItem { public string Item = ""; public int CoinsCost; public int ForestTokenCost; public int IronBountyTokenCost; public int GoldBountyTokenCost; private SecretStashType type; internal static readonly List<SecretStashItem> SecretStashes = new List<SecretStashItem>(); internal static readonly Method API_AddSecretStashItem = new Method("AddSecretStashItem"); internal static readonly Method API_UpdateSecretStashItem = new Method("UpdateSecretStashItem"); public SecretStashItem(SecretStashType type, string item) { Item = item; this.type = type; SecretStashes.Add(this); } public SecretStashItem() { } public static void RegisterAll() { foreach (SecretStashItem item in new List<SecretStashItem>(SecretStashes)) { item.Register(); } } public bool Register() { string text = JsonConvert.SerializeObject((object)this); object[] array = API_AddSecretStashItem.Invoke(type.ToString(), text); if (!(array[0] is string value)) { return false; } SecretStashes.Remove(this); RunTimeRegistry.Register(type, value); EpicLoot.logger.LogDebug("Registered secret stash " + Item); return true; } public bool Update() { if (!RunTimeRegistry.TryGetValue(this, out string value)) { return false; } string text = JsonConvert.SerializeObject((object)this); object[] array = API_UpdateSecretStashItem.Invoke(value, text); bool flag = (bool)(array[0] ?? ((object)false)); EpicLoot.logger.LogDebug($"Updated secret stash {Item}, {flag}"); return flag; } } [Serializable] [PublicAPI] internal class TreasureMap { public Biome Biome = (Biome)0; public int Cost; public int ForestTokens; public int GoldTokens; public int IronTokens; public int Coins; public float MinRadius; public float MaxRadius; internal static readonly List<TreasureMap> Treasures = new List<TreasureMap>(); private static readonly Method API_AddTreasureMap = new Method("AddTreasureMap"); private static readonly Method API_UpdateTreasureMap = new Method("UpdateTreasureMap"); public TreasureMap(Biome biome, int cost, float minRadius, float maxRadius) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Unknown result type (might be due to invalid IL or missing references) Biome = biome; Cost = cost; MinRadius = minRadius; MaxRadius = maxRadius; Treasures.Add(this); } public TreasureMap() { }//IL_0002: Unknown result type (might be due to invalid IL or missing references) public static void RegisterAll() { foreach (TreasureMap item in new List<TreasureMap>(Treasures)) { item.Register(); } } public bool Register() { //IL_0055: Unknown result type (might be due to invalid IL or missing references) string text = JsonConvert.SerializeObject((object)this); object[] array = API_AddTreasureMap.Invoke(text); if (!(array[0] is string value)) { return false; } RunTimeRegistry.Register(this, value); Treasures.Remove(this); EpicLoot.logger.LogDebug($"Added treasure map: {Biome}"); return true; } public bool Update() { //IL_0055: Unknown result type (might be due to invalid IL or missing references) if (!RunTimeRegistry.TryGetValue(this, out string value)) { return false; } string text = JsonConvert.SerializeObject((object)this); object[] array = API_UpdateTreasureMap.Invoke(value, text); bool flag = (bool)(array[0] ?? ((object)false)); EpicLoot.logger.LogDebug($"Updated treasure map: {Biome}, {flag}"); return flag; } } }