using 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 Transpiler(IEnumerable 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 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 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 singleSelectedItem = val2.GetSingleSelectedItem(); if (((singleSelectedItem != null) ? singleSelectedItem.Item1.GetItem() : null) == null) { return true; } MultiSelectItemList val3 = (MultiSelectItemList)AccessTools.Field(typeof(RuneUI), "AvailableRunes").GetValue(__instance); Tuple singleSelectedItem2 = val3.GetSingleSelectedItem(); 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 tuple = val.GetSelectedItems().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().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()); ((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()); val2.SetItems(new List()); 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 ActionParams = new List(); internal static readonly Method API_AddAbility = new Method("AddAbility"); internal static readonly Method API_UpdateAbility = new Method("UpdateAbility"); internal static List Abilities = new List(); [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(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 Callbacks = new Dictionary(); internal static readonly List ProxyAbilities = new List(); 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(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 GetAllActiveMagicEffects(this Player player, string effectType = null) { object[] array = API_GetAllActiveMagicEffects.Invoke(player, effectType); List list = (List)(array[0] ?? new List()); if (list.Count <= 0) { return new List(); } List list2 = new List(); list2.DeserializeList(list); return list2; } [PublicAPI] public static List GetAllActiveSetMagicEffects(this Player player, string effectType = null) { object[] array = API_GetAllSetMagicEffects.Invoke(player, effectType); List list = (List)(array[0] ?? new List()); if (list.Count <= 0) { return new List(); } List list2 = new List(); list2.DeserializeList(list); return list2; } private static void DeserializeList(this List output, List input) { foreach (string item in input) { try { T val = JsonConvert.DeserializeObject(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(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 Adds = new List(); internal static readonly List BountyTargets = new List(); 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(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 resources = new List(); internal static readonly List Recipes = new List(); 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(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(this List list, params T[] items) { list.AddRange(items); } [PublicAPI] public static void AddMinion(this List list, string ID, int count) { list.Add(new BountyMinion(ID, count)); } [PublicAPI] public static void Add(this List list, string item, int amount = 1) { list.Add(new ItemAmount(item, amount)); } [PublicAPI] public static void Add(this List 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 list, string item, int amount = 1) { list.Add(new RecipeRequirement(item, amount)); } [PublicAPI] public static void Add(this List 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 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 GuaranteedMagicEffects = new List(); public int GuaranteedEffectCount = -1; public float SelectionWeight = 1f; public string EquipFx = ""; public FxAttachMode EquipFxMode = FxAttachMode.Player; public List TextureReplacements = new List(); public bool IsSetItem; public bool Enchantable; public List EnchantCost = new List(); private LegendaryType type; internal static readonly List LegendaryItems = new List(); 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(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 LegendaryIDs = new List(); public List SetBonuses = new List(); private LegendaryType type; internal static readonly List LegendarySets = new List(); 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(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 OnError; public event Action OnDebug; public event Action 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 Effects = new List(); public string TypeNameOverride = ""; public int AugmentedEffectIndex; public List AugmentedEffectIndices = new List(); 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 Prefixes = new List(); public List Suffixes = new List(); public string EquipFx = ""; public FxAttachMode EquipFxMode = FxAttachMode.Player; public string Ability = ""; internal static readonly List MagicEffects = new List(); 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(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(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 _flags = new List(); public bool NoRoll; public bool ExclusiveSelf = true; public List ExclusiveEffectTypes = new List(); public List MustHaveEffectTypes = new List(); public List AllowedItemTypes = new List(); public List ExcludedItemTypes = new List(); public List AllowedRarities = new List(); public List ExcludedRarities = new List(); public List AllowedSkillTypes = new List(); public List ExcludedSkillTypes = new List(); public List AllowedItemNames = new List(); public List ExcludedItemNames = new List(); 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 CustomFlags = new List(); 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 Resources = new List(); internal static readonly Method API_AddMaterialConversion = new Method("AddMaterialConversion"); internal static readonly Method API_UpdateMaterialConversion = new Method("UpdateMaterialConversion"); internal static readonly List MaterialConversions = new List(); [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(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 CachedTypes = new Dictionary(); 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(); } [PublicAPI] public static void ClearCache() { CachedTypes.Clear(); } } internal static class RunTimeRegistry { private static readonly Dictionary registry = new Dictionary(); 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 ItemTypes = new List(); [Description("Conditional, if empty, does not check if item shared name is in list")] public List ItemNames = new List(); [Description("Disenchant product entry")] public List Products = new List(); internal static readonly List Sacrifices = new List(); 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(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 SecretStashes = new List(); 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(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 Treasures = new List(); 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(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; } } }