Please disclose if your mod was created primarily 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 ExtraSlotsCustomSlots v1.0.17
ExtraSlotsCustomSlots.dll
Decompiled 2 days ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Globalization; using System.IO; using System.IO.Compression; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Serialization; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using BepInEx; using BepInEx.Bootstrap; using BepInEx.Configuration; using ExtraSlots; using ExtraSlotsCustomSlots.AdventureBackpacksCustomSlot; using ExtraSlotsCustomSlots.JudesEquipmentBackpacksCustomSlot; using HarmonyLib; using JetBrains.Annotations; using Microsoft.CodeAnalysis; using ServerSync; using TMPro; using UnityEngine; using UnityEngine.SceneManagement; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)] [assembly: AssemblyTitle("ExtraSlotsCustomSlots")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("")] [assembly: AssemblyProduct("ExtraSlotsCustomSlots")] [assembly: AssemblyCopyright("Copyright © 2024")] [assembly: AssemblyTrademark("")] [assembly: ComVisible(false)] [assembly: Guid("ee3d2a93-2e64-4701-bfd2-efd5a55cfe52")] [assembly: AssemblyFileVersion("1.0.17")] [assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.0.17.0")] [module: UnverifiableCode] 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 ExtraSlotsCustomSlots { public class VikingsSummoner : CustomSlot { [HarmonyPatch] public static class VikingsSummoner_MagicSlot_AddCustomSlot_PreventCustomSlotAddition { public static MethodBase target; public static bool Prepare(MethodBase original) { if (!Chainloader.PluginInfos.TryGetValue("radamanto.Vikings_Summoner", out var value)) { return false; } if ((object)target == null) { target = AccessTools.Method(Assembly.GetAssembly(((object)value.Instance).GetType()).GetType("Vikings_Summoner.TomeCustomSlotManager"), "IsSlotSystemEnabled", (Type[])null, (Type[])null); } if (target == null) { return false; } if (original == null) { ExtraSlotsCustomSlots.LogInfo("Vikings_Summoner.TomeCustomSlotManager:IsSlotSystemEnabled method is patched to enable internal custom slot logic"); } return true; } public static MethodBase TargetMethod() { return target; } public static void Postfix(ref bool __result) { __result = ExtraSlotsCustomSlots.vikingsSummonerSlotEnabled.Value; } } public const string ID = "VikingsSummoner"; public const string pluginID = "radamanto.Vikings_Summoner"; public VikingsSummoner() { CustomSlot.slots.Add(this); GUID = "radamanto.Vikings_Summoner"; slotID = "VikingsSummoner"; if (!base.PluginInstalled) { return; } Assembly assembly = Assembly.GetAssembly(((object)Chainloader.PluginInfos["radamanto.Vikings_Summoner"].Instance).GetType()); MethodInfo isValid = AccessTools.Method(assembly.GetType("Vikings_Summoner.TomeCustomSlotManager"), "IsTomeItem", (Type[])null, (Type[])null); if (isValid == null) { ExtraSlotsCustomSlots.LogWarning("Vikings_Summoner mod is loaded but Vikings_Summoner.TomeCustomSlotManager:IsTomeItem is not found"); return; } itemIsValid = (ItemData item) => item != null && (bool)isValid.Invoke(null, new object[1] { item }); getName = () => ExtraSlotsCustomSlots.vikingsSummonerSlotName.Value; isActive = () => CustomSlot.IsSlotActive(ExtraSlotsCustomSlots.vikingsSummonerSlotGlobalKey.Value, ExtraSlotsCustomSlots.vikingsSummonerSlotItemDiscovered.Value); initialized = true; } } public class JudesEquipmentBackpackSlot : CustomSlot { public const string ID = "JudesEquipmentBackpack"; public const string pluginID = "GoldenJude_JudesEquipment"; public static Assembly assembly; public static bool IsLoaded => Chainloader.PluginInfos.ContainsKey("GoldenJude_JudesEquipment"); public static bool IsActive => IsLoaded && ExtraSlotsCustomSlots.judesEquipmentBackpackSlotEnabled.Value; public JudesEquipmentBackpackSlot() { CustomSlot.slots.Add(this); GUID = "GoldenJude_JudesEquipment"; slotID = "JudesEquipmentBackpack"; if (base.PluginInstalled) { assembly = Assembly.GetAssembly(((object)Chainloader.PluginInfos["GoldenJude_JudesEquipment"].Instance).GetType()); itemIsValid = (ItemData item) => item != null && (Object)(object)item.m_dropPrefab != (Object)null && (((Object)item.m_dropPrefab).name == "BackpackSimple" || ((Object)item.m_dropPrefab).name == "BackpackHeavy"); getName = () => ExtraSlotsCustomSlots.judesEquipmentBackpackSlotName.Value; isActive = () => CustomSlot.IsSlotActive(ExtraSlotsCustomSlots.judesEquipmentBackpackSlotGlobalKey.Value, ExtraSlotsCustomSlots.judesEquipmentBackpackSlotItemDiscovered.Value); initialized = true; global::ExtraSlotsCustomSlots.JudesEquipmentBackpacksCustomSlot.CustomItemType.InitBackpackFunc(itemIsValid); } } } public static class EpicLootCompat { [HarmonyPatch] public static class EpicLoot_EnchantCostsHelper_CanBeMagicItem_TreatBackpackAsShoulder { public static List<MethodBase> targets; public static List<MethodBase> GetTargets() { if ((object)assembly == null) { assembly = Assembly.GetAssembly(((object)Chainloader.PluginInfos["randyknapp.mods.epicloot"].Instance).GetType()); } List<MethodBase> list = new List<MethodBase>(); MethodInfo methodInfo = AccessTools.Method(assembly.GetType("EpicLoot.Crafting.EnchantCostsHelper"), "GetSacrificeProducts", new Type[1] { typeof(ItemData) }, (Type[])null); if ((object)methodInfo != null) { ExtraSlotsCustomSlots.LogInfo("EpicLoot.Crafting.EnchantCostsHelper:GetSacrificeProducts method is patched to make it work with custom backpack item type"); list.Add(methodInfo); } else { ExtraSlotsCustomSlots.LogWarning("EpicLoot.Crafting.EnchantCostsHelper:GetSacrificeProducts method was not found"); } MethodInfo methodInfo2 = AccessTools.Method(assembly.GetType("EpicLoot.Crafting.EnchantCostsHelper"), "GetEnchantCost", (Type[])null, (Type[])null); if ((object)methodInfo2 != null) { ExtraSlotsCustomSlots.LogInfo("EpicLoot.Crafting.EnchantCostsHelper:GetEnchantCost method is patched to make it work with custom backpack item type"); list.Add(methodInfo2); } else { ExtraSlotsCustomSlots.LogWarning("EpicLoot.Crafting.EnchantCostsHelper:GetEnchantCost method was not found"); } MethodInfo methodInfo3 = AccessTools.Method(assembly.GetType("EpicLoot.Crafting.EnchantCostsHelper"), "GetAugmentCost", (Type[])null, (Type[])null); if ((object)methodInfo3 != null) { ExtraSlotsCustomSlots.LogInfo("EpicLoot.Crafting.EnchantCostsHelper:GetAugmentCost method is patched to make it work with custom backpack item type"); list.Add(methodInfo3); } else { ExtraSlotsCustomSlots.LogWarning("EpicLoot.Crafting.EnchantCostsHelper:GetAugmentCost method was not found"); } MethodInfo methodInfo4 = AccessTools.Method(assembly.GetType("EpicLoot.Crafting.EnchantCostsHelper"), "GetReAugmentCost", (Type[])null, (Type[])null); if ((object)methodInfo4 != null) { ExtraSlotsCustomSlots.LogInfo("EpicLoot.Crafting.EnchantCostsHelper:GetReAugmentCost method is patched to make it work with custom backpack item type"); list.Add(methodInfo4); } else { ExtraSlotsCustomSlots.LogWarning("EpicLoot.Crafting.EnchantCostsHelper:GetReAugmentCost method was not found"); } MethodInfo methodInfo5 = AccessTools.Method(assembly.GetType("EpicLoot.EpicLoot"), "CanBeMagicItem", (Type[])null, (Type[])null); if ((object)methodInfo5 != null) { ExtraSlotsCustomSlots.LogInfo("EpicLoot.EpicLoot:CanBeMagicItem method is patched to make it work with custom backpack item type"); list.Add(methodInfo5); } else { ExtraSlotsCustomSlots.LogWarning("EpicLoot.EpicLoot:CanBeMagicItem method was not found"); } return list; } public static bool Prepare() { return JudesEquipmentBackpackSlot.IsLoaded && Chainloader.PluginInfos.ContainsKey("randyknapp.mods.epicloot") && (targets ?? (targets = GetTargets())).Count > 0; } private static IEnumerable<MethodBase> TargetMethods() { return targets; } public static void Prefix(ItemData item, ref bool __state) { //IL_002b: Unknown result type (might be due to invalid IL or missing references) if (JudesEquipmentBackpackSlot.IsActive && (__state = global::ExtraSlotsCustomSlots.JudesEquipmentBackpacksCustomSlot.CustomItemType.IsBackpack(item))) { item.m_shared.m_itemType = (ItemType)17; } } public static void Postfix(ItemData item, bool __state) { if (__state) { JudesEquipmentBackpackItem.PatchBackpackItemData(item); } } } [HarmonyPatch] public static class EpicLoot_MagicItemEffectRequirements_argItemData_TreatBackpackAsShoulder { public static List<MethodBase> targets; public static List<MethodBase> GetTargets() { if ((object)assembly == null) { assembly = Assembly.GetAssembly(((object)Chainloader.PluginInfos["randyknapp.mods.epicloot"].Instance).GetType()); } List<MethodBase> list = new List<MethodBase>(); MethodInfo methodInfo = AccessTools.Method(assembly.GetType("EpicLoot.MagicItemEffectRequirements"), "AllowByItemType", (Type[])null, (Type[])null); if ((object)methodInfo != null) { ExtraSlotsCustomSlots.LogInfo("EpicLoot.MagicItemEffectRequirements:AllowByItemType method is patched to make it work with custom backpack item type"); list.Add(methodInfo); } else { ExtraSlotsCustomSlots.LogWarning("EpicLoot.MagicItemEffectRequirements:AllowByItemType method was not found"); } MethodInfo methodInfo2 = AccessTools.Method(assembly.GetType("EpicLoot.MagicItemEffectRequirements"), "ExcludeByItemType", (Type[])null, (Type[])null); if ((object)methodInfo2 != null) { ExtraSlotsCustomSlots.LogInfo("EpicLoot.MagicItemEffectRequirements:ExcludeByItemType method is patched to make it work with custom backpack item type"); list.Add(methodInfo2); } else { ExtraSlotsCustomSlots.LogWarning("EpicLoot.MagicItemEffectRequirements:ExcludeByItemType method was not found"); } MethodInfo methodInfo3 = AccessTools.Method(assembly.GetType("EpicLoot.MagicItemEffectRequirements"), "CheckRequirements", (Type[])null, (Type[])null); if ((object)methodInfo3 != null) { ExtraSlotsCustomSlots.LogInfo("EpicLoot.MagicItemEffectRequirements:CheckRequirements method is patched to make it work with custom backpack item type"); list.Add(methodInfo3); } else { ExtraSlotsCustomSlots.LogWarning("EpicLoot.MagicItemEffectRequirements:CheckRequirements method was not found"); } return list; } public static bool Prepare() { return JudesEquipmentBackpackSlot.IsLoaded && Chainloader.PluginInfos.ContainsKey("randyknapp.mods.epicloot") && (targets ?? (targets = GetTargets())).Count > 0; } private static IEnumerable<MethodBase> TargetMethods() { return targets; } public static void Prefix(ItemData itemData, ref bool __state) { //IL_002b: Unknown result type (might be due to invalid IL or missing references) if (JudesEquipmentBackpackSlot.IsActive && (__state = global::ExtraSlotsCustomSlots.JudesEquipmentBackpacksCustomSlot.CustomItemType.IsBackpack(itemData))) { itemData.m_shared.m_itemType = (ItemType)17; } } public static void Postfix(ItemData itemData, bool __state) { if (__state) { JudesEquipmentBackpackItem.PatchBackpackItemData(itemData); } } } public const string epicLootGUID = "randyknapp.mods.epicloot"; public static Assembly assembly; } public class AdventureBackpacksSlot : CustomSlot { public const string ID = "AdventureBackpacks"; public const string pluginID = "vapok.mods.adventurebackpacks"; public static Assembly assembly; public static bool IsLoaded => Chainloader.PluginInfos.ContainsKey("vapok.mods.adventurebackpacks"); public static bool IsActive => IsLoaded && ExtraSlotsCustomSlots.adventureBackpackSlotEnabled.Value; public AdventureBackpacksSlot() { CustomSlot.slots.Add(this); GUID = "vapok.mods.adventurebackpacks"; slotID = "AdventureBackpacks"; if (!base.PluginInstalled) { return; } assembly = Assembly.GetAssembly(((object)Chainloader.PluginInfos["vapok.mods.adventurebackpacks"].Instance).GetType()); MethodInfo isValid = AccessTools.Method(assembly.GetType("AdventureBackpacks.API.ABAPI"), "IsBackpack", (Type[])null, (Type[])null); if (isValid == null) { ExtraSlotsCustomSlots.LogWarning("AdventureBackpacks mod is loaded but AdventureBackpacks.API.ABAPI:IsBackpack is not found"); return; } itemIsValid = delegate(ItemData item) { int result; if (item != null) { MethodInfo methodInfo = isValid; object[] parameters = (object[])(object)new ItemData[1] { item }; result = (((bool)methodInfo.Invoke(null, parameters)) ? 1 : 0); } else { result = 0; } return (byte)result != 0; }; getName = () => ExtraSlotsCustomSlots.adventureBackpackSlotName.Value; isActive = () => CustomSlot.IsSlotActive(ExtraSlotsCustomSlots.adventureBackpackSlotGlobalKey.Value, ExtraSlotsCustomSlots.adventureBackpackSlotItemDiscovered.Value); initialized = true; global::ExtraSlotsCustomSlots.AdventureBackpacksCustomSlot.CustomItemType.InitBackpackFunc(itemIsValid); AdventureBackpacksPatches.UnpatchUnequip(); } } public static class AdventureBackpacksPatches { [HarmonyPatch] public static class AdventureBackpacks_PlayerExtensions_CustomSlotItem { public static List<MethodBase> targets; public static List<MethodBase> GetTargets() { List<MethodBase> list = new List<MethodBase>(); if (AdventureBackpacksSlot.assembly == null) { return list; } MethodInfo methodInfo = AccessTools.Method(AdventureBackpacksSlot.assembly.GetType("AdventureBackpacks.Extensions.PlayerExtensions"), "IsBackpackEquipped", (Type[])null, (Type[])null); if ((object)methodInfo != null) { ExtraSlotsCustomSlots.LogInfo("AdventureBackpacks.Extensions.PlayerExtensions:IsBackpackEquipped method is patched to make it work with custom slot"); list.Add(methodInfo); } else { ExtraSlotsCustomSlots.LogWarning("AdventureBackpacks.Extensions.PlayerExtensions:IsBackpackEquipped method was not found"); } MethodInfo methodInfo2 = AccessTools.Method(AdventureBackpacksSlot.assembly.GetType("AdventureBackpacks.Extensions.PlayerExtensions"), "IsThisBackpackEquipped", (Type[])null, (Type[])null); if ((object)methodInfo2 != null) { ExtraSlotsCustomSlots.LogInfo("AdventureBackpacks.Extensions.PlayerExtensions:IsThisBackpackEquipped method is patched to make it work with custom slot"); list.Add(methodInfo2); } else { ExtraSlotsCustomSlots.LogWarning("AdventureBackpacks.Extensions.PlayerExtensions:IsThisBackpackEquipped method was not found"); } MethodInfo methodInfo3 = AccessTools.Method(AdventureBackpacksSlot.assembly.GetType("AdventureBackpacks.Extensions.PlayerExtensions"), "GetEquippedBackpack", (Type[])null, (Type[])null); if ((object)methodInfo3 != null) { ExtraSlotsCustomSlots.LogInfo("AdventureBackpacks.Extensions.PlayerExtensions:GetEquippedBackpack method is patched to make it work with custom slot"); list.Add(methodInfo3); } else { ExtraSlotsCustomSlots.LogWarning("AdventureBackpacks.Extensions.PlayerExtensions:GetEquippedBackpack method was not found"); } return list; } public static bool Prepare() { return AdventureBackpacksSlot.IsLoaded && (targets ?? (targets = GetTargets())).Count > 0; } private static IEnumerable<MethodBase> TargetMethods() { return targets; } public static void Prefix(Player player, ref ItemData __state) { if (AdventureBackpacksSlot.IsActive) { __state = ((Humanoid)player).m_shoulderItem; ((Humanoid)player).m_shoulderItem = ((Humanoid)(object)player).GetAdventureBackpack(); } } public static void Postfix(Player player, ItemData __state) { if (AdventureBackpacksSlot.IsActive) { ((Humanoid)player).m_shoulderItem = __state; } } } [HarmonyPatch(typeof(Humanoid), "UnequipItem")] public static class Humanoid_UnequipItem_CustomItemType_FirstPrefix { public static bool Prepare() { return AdventureBackpacksSlot.IsLoaded; } private static void Prefix(Humanoid __instance, ItemData item) { //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Unknown result type (might be due to invalid IL or missing references) if (AdventureBackpacksSlot.IsActive && !(prefixHumanoidUnequip == null) && item != null && !((Object)(object)Player.m_localPlayer != (Object)(object)__instance)) { Scene activeScene = SceneManager.GetActiveScene(); if (!((Scene)(ref activeScene)).name.Equals("start") && global::ExtraSlotsCustomSlots.AdventureBackpacksCustomSlot.CustomItemType.IsBackpack(item) && item == __instance.GetAdventureBackpack() && item != __instance.m_shoulderItem) { ItemData shoulderItem = __instance.m_shoulderItem; __instance.m_shoulderItem = item; prefixHumanoidUnequip.Invoke(null, new object[1] { item }); __instance.m_shoulderItem = shoulderItem; ExtraSlotsCustomSlots.LogInfo($"Shoulder item {shoulderItem}"); ExtraSlotsCustomSlots.LogInfo("swapped with"); ExtraSlotsCustomSlots.LogInfo($"{item}"); } } } } public static class EpicLootCompat { [HarmonyPatch] public static class EpicLoot_EnchantCostsHelper_CanBeMagicItem_TreatBackpackAsShoulder { public static List<MethodBase> targets; public static List<MethodBase> GetTargets() { if ((object)assembly == null) { assembly = Assembly.GetAssembly(((object)Chainloader.PluginInfos["randyknapp.mods.epicloot"].Instance).GetType()); } List<MethodBase> list = new List<MethodBase>(); MethodInfo methodInfo = AccessTools.Method(assembly.GetType("EpicLoot.Crafting.EnchantCostsHelper"), "GetSacrificeProducts", new Type[1] { typeof(ItemData) }, (Type[])null); if ((object)methodInfo != null) { ExtraSlotsCustomSlots.LogInfo("EpicLoot.Crafting.EnchantCostsHelper:GetSacrificeProducts method is patched to make it work with custom backpack item type"); list.Add(methodInfo); } else { ExtraSlotsCustomSlots.LogWarning("EpicLoot.Crafting.EnchantCostsHelper:GetSacrificeProducts method was not found"); } MethodInfo methodInfo2 = AccessTools.Method(assembly.GetType("EpicLoot.Crafting.EnchantCostsHelper"), "GetEnchantCost", (Type[])null, (Type[])null); if ((object)methodInfo2 != null) { ExtraSlotsCustomSlots.LogInfo("EpicLoot.Crafting.EnchantCostsHelper:GetEnchantCost method is patched to make it work with custom backpack item type"); list.Add(methodInfo2); } else { ExtraSlotsCustomSlots.LogWarning("EpicLoot.Crafting.EnchantCostsHelper:GetEnchantCost method was not found"); } MethodInfo methodInfo3 = AccessTools.Method(assembly.GetType("EpicLoot.Crafting.EnchantCostsHelper"), "GetAugmentCost", (Type[])null, (Type[])null); if ((object)methodInfo3 != null) { ExtraSlotsCustomSlots.LogInfo("EpicLoot.Crafting.EnchantCostsHelper:GetAugmentCost method is patched to make it work with custom backpack item type"); list.Add(methodInfo3); } else { ExtraSlotsCustomSlots.LogWarning("EpicLoot.Crafting.EnchantCostsHelper:GetAugmentCost method was not found"); } MethodInfo methodInfo4 = AccessTools.Method(assembly.GetType("EpicLoot.Crafting.EnchantCostsHelper"), "GetReAugmentCost", (Type[])null, (Type[])null); if ((object)methodInfo4 != null) { ExtraSlotsCustomSlots.LogInfo("EpicLoot.Crafting.EnchantCostsHelper:GetReAugmentCost method is patched to make it work with custom backpack item type"); list.Add(methodInfo4); } else { ExtraSlotsCustomSlots.LogWarning("EpicLoot.Crafting.EnchantCostsHelper:GetReAugmentCost method was not found"); } MethodInfo methodInfo5 = AccessTools.Method(assembly.GetType("EpicLoot.EpicLoot"), "CanBeMagicItem", (Type[])null, (Type[])null); if ((object)methodInfo5 != null) { ExtraSlotsCustomSlots.LogInfo("EpicLoot.EpicLoot:CanBeMagicItem method is patched to make it work with custom backpack item type"); list.Add(methodInfo5); } else { ExtraSlotsCustomSlots.LogWarning("EpicLoot.EpicLoot:CanBeMagicItem method was not found"); } return list; } public static bool Prepare() { return AdventureBackpacksSlot.IsLoaded && Chainloader.PluginInfos.ContainsKey("randyknapp.mods.epicloot") && (targets ?? (targets = GetTargets())).Count > 0; } private static IEnumerable<MethodBase> TargetMethods() { return targets; } public static void Prefix(ItemData item, ref bool __state) { //IL_002b: Unknown result type (might be due to invalid IL or missing references) if (AdventureBackpacksSlot.IsActive && (__state = global::ExtraSlotsCustomSlots.AdventureBackpacksCustomSlot.CustomItemType.IsBackpack(item))) { item.m_shared.m_itemType = (ItemType)17; } } public static void Postfix(ItemData item, bool __state) { if (__state) { AdventureBackpackItem.PatchBackpackItemData(item); } } } [HarmonyPatch] public static class EpicLoot_MagicItemEffectRequirements_argItemData_TreatBackpackAsShoulder { public static List<MethodBase> targets; public static List<MethodBase> GetTargets() { if ((object)assembly == null) { assembly = Assembly.GetAssembly(((object)Chainloader.PluginInfos["randyknapp.mods.epicloot"].Instance).GetType()); } List<MethodBase> list = new List<MethodBase>(); MethodInfo methodInfo = AccessTools.Method(assembly.GetType("EpicLoot.MagicItemEffectRequirements"), "AllowByItemType", (Type[])null, (Type[])null); if ((object)methodInfo != null) { ExtraSlotsCustomSlots.LogInfo("EpicLoot.MagicItemEffectRequirements:AllowByItemType method is patched to make it work with custom backpack item type"); list.Add(methodInfo); } else { ExtraSlotsCustomSlots.LogWarning("EpicLoot.MagicItemEffectRequirements:AllowByItemType method was not found"); } MethodInfo methodInfo2 = AccessTools.Method(assembly.GetType("EpicLoot.MagicItemEffectRequirements"), "ExcludeByItemType", (Type[])null, (Type[])null); if ((object)methodInfo2 != null) { ExtraSlotsCustomSlots.LogInfo("EpicLoot.MagicItemEffectRequirements:ExcludeByItemType method is patched to make it work with custom backpack item type"); list.Add(methodInfo2); } else { ExtraSlotsCustomSlots.LogWarning("EpicLoot.MagicItemEffectRequirements:ExcludeByItemType method was not found"); } MethodInfo methodInfo3 = AccessTools.Method(assembly.GetType("EpicLoot.MagicItemEffectRequirements"), "CheckRequirements", (Type[])null, (Type[])null); if ((object)methodInfo3 != null) { ExtraSlotsCustomSlots.LogInfo("EpicLoot.MagicItemEffectRequirements:CheckRequirements method is patched to make it work with custom backpack item type"); list.Add(methodInfo3); } else { ExtraSlotsCustomSlots.LogWarning("EpicLoot.MagicItemEffectRequirements:CheckRequirements method was not found"); } return list; } public static bool Prepare() { return AdventureBackpacksSlot.IsLoaded && Chainloader.PluginInfos.ContainsKey("randyknapp.mods.epicloot") && (targets ?? (targets = GetTargets())).Count > 0; } private static IEnumerable<MethodBase> TargetMethods() { return targets; } public static void Prefix(ItemData itemData, ref bool __state) { //IL_002b: Unknown result type (might be due to invalid IL or missing references) if (AdventureBackpacksSlot.IsActive && (__state = global::ExtraSlotsCustomSlots.AdventureBackpacksCustomSlot.CustomItemType.IsBackpack(itemData))) { itemData.m_shared.m_itemType = (ItemType)17; } } public static void Postfix(ItemData itemData, bool __state) { if (__state) { AdventureBackpackItem.PatchBackpackItemData(itemData); } } } public const string epicLootGUID = "randyknapp.mods.epicloot"; public static Assembly assembly; } public static MethodInfo prefixHumanoidUnequip; public static void UnpatchUnequip() { MethodInfo methodInfo = AccessTools.Method(typeof(Humanoid), "UnequipItem", (Type[])null, (Type[])null); prefixHumanoidUnequip = AccessTools.Method(AdventureBackpacksSlot.assembly.GetType("AdventureBackpacks.Patches.HumanoidPatches+HumanoidUnequipItemPatch"), "Prefix", (Type[])null, (Type[])null); if (methodInfo != null && prefixHumanoidUnequip != null) { ExtraSlotsCustomSlots.instance.harmony.Unpatch((MethodBase)methodInfo, prefixHumanoidUnequip); ExtraSlotsCustomSlots.LogInfo("AdventureBackpacks.Patches.HumanoidPatches+HumanoidUnequipItemPatch:Prefix was unpatched and will be called directly."); return; } if (methodInfo == null) { ExtraSlotsCustomSlots.LogWarning("Humanoid:UnequipItem was not found."); } if (prefixHumanoidUnequip == null) { ExtraSlotsCustomSlots.LogWarning("AdventureBackpacks.Patches.HumanoidPatches+HumanoidUnequipItemPatch:Prefix was not found."); } } } public class HipLanternSlot : CustomSlot { public const string ID = "HipLantern"; public const string pluginID = "shudnal.HipLantern"; public HipLanternSlot() { CustomSlot.slots.Add(this); GUID = "shudnal.HipLantern"; slotID = "HipLantern"; if (!base.PluginInstalled) { return; } Assembly assembly = Assembly.GetAssembly(((object)Chainloader.PluginInfos["shudnal.HipLantern"].Instance).GetType()); MethodInfo isValid = AccessTools.Method(assembly.GetType("HipLantern.LanternItem"), "IsLanternItem", new Type[1] { typeof(ItemData) }, (Type[])null); if (isValid == null) { ExtraSlotsCustomSlots.LogWarning("HipLantern mod is loaded but HipLantern.LanternItem:IsLanternItem is not found"); return; } itemIsValid = delegate(ItemData item) { int result; if (item != null) { MethodInfo methodInfo = isValid; object[] parameters = (object[])(object)new ItemData[1] { item }; result = (((bool)methodInfo.Invoke(null, parameters)) ? 1 : 0); } else { result = 0; } return (byte)result != 0; }; getName = () => ExtraSlotsCustomSlots.hipLanternSlotName.Value; isActive = () => CustomSlot.IsSlotActive(ExtraSlotsCustomSlots.hipLanternSlotGlobalKey.Value, ExtraSlotsCustomSlots.hipLanternSlotItemDiscovered.Value); initialized = true; } } public class CircletExtendedSlot : CustomSlot { public const string ID = "CircletExtended"; public const string pluginID = "shudnal.CircletExtended"; public CircletExtendedSlot() { CustomSlot.slots.Add(this); GUID = "shudnal.CircletExtended"; slotID = "CircletExtended"; if (!base.PluginInstalled) { return; } Assembly assembly = Assembly.GetAssembly(((object)Chainloader.PluginInfos["shudnal.CircletExtended"].Instance).GetType()); MethodInfo isValid = AccessTools.Method(assembly.GetType("CircletExtended.CircletItem"), "IsCircletItem", new Type[1] { typeof(ItemData) }, (Type[])null); if (isValid == null) { ExtraSlotsCustomSlots.LogWarning("CircletExtended mod is loaded but CircletExtended.CircletItem:IsCircletItem is not found"); return; } MethodInfo isCircletSlotKnown = AccessTools.Method(assembly.GetType("CircletExtended.CircletItem"), "IsCircletSlotKnown", (Type[])null, (Type[])null); itemIsValid = delegate(ItemData item) { int result; if (item != null) { MethodInfo methodInfo = isValid; object[] parameters = (object[])(object)new ItemData[1] { item }; result = (((bool)methodInfo.Invoke(null, parameters)) ? 1 : 0); } else { result = 0; } return (byte)result != 0; }; getName = () => ExtraSlotsCustomSlots.circletExtendedSlotName.Value; isActive = () => CustomSlot.IsSlotActive(ExtraSlotsCustomSlots.circletExtendedSlotGlobalKey.Value, ExtraSlotsCustomSlots.circletExtendedSlotItemDiscovered.Value) && (isCircletSlotKnown == null || (bool)isCircletSlotKnown.Invoke(null, null)); initialized = true; } } public class BowsBeforeHoesSlot : CustomSlot { public const string ID = "BowsBeforeHoes"; public const string pluginID = "Azumatt.BowsBeforeHoes"; public static bool _isActive; private static Func<ItemData, bool> _isQuiver; public static bool IsActive => _isActive && ExtraSlotsCustomSlots.bbhQuiverSlotEnabled.Value; public static bool IsQuiver(ItemData item) { return _isQuiver != null && _isQuiver(item); } public BowsBeforeHoesSlot() { CustomSlot.slots.Add(this); GUID = "Azumatt.BowsBeforeHoes"; slotID = "BowsBeforeHoes"; if (!base.PluginInstalled) { return; } Assembly assembly = Assembly.GetAssembly(((object)Chainloader.PluginInfos["Azumatt.BowsBeforeHoes"].Instance).GetType()); MethodInfo isValid = AccessTools.Method(assembly.GetType("BowsBeforeHoes.Util.Functions"), "IsQuiverSlot", (Type[])null, (Type[])null); if (isValid == null) { ExtraSlotsCustomSlots.LogWarning("BowsBeforeHoes mod is loaded but BowsBeforeHoes.Util.Functions:IsQuiverSlot is not found"); return; } itemIsValid = delegate(ItemData item) { int result; if (item != null) { MethodInfo methodInfo = isValid; object[] parameters = (object[])(object)new ItemData[1] { item }; result = (((bool)methodInfo.Invoke(null, parameters)) ? 1 : 0); } else { result = 0; } return (byte)result != 0; }; getName = () => ExtraSlotsCustomSlots.bbhQuiverSlotName.Value; isActive = () => CustomSlot.IsSlotActive(ExtraSlotsCustomSlots.bbhQuiverSlotGlobalKey.Value, ExtraSlotsCustomSlots.bbhQuiverSlotItemDiscovered.Value); initialized = true; _isActive = true; _isQuiver = itemIsValid; } } public static class BowsBeforeHoesCompat { [HarmonyPatch(typeof(Player), "AddKnownItem")] public static class Player_AddKnownItem_BBHQuiverType { private static void Postfix(Player __instance, ref ItemData item) { if (BowsBeforeHoesSlot.IsActive && !__instance.m_knownMaterial.Contains(item.m_shared.m_name) && BowsBeforeHoesSlot.IsQuiver(item)) { PatchBackpackItemData(item); } } } [HarmonyPatch(typeof(Player), "OnSpawned")] public class Player_OnSpawned_BBHQuiverType { public static void Postfix(Player __instance) { if (BowsBeforeHoesSlot.IsActive && !((Object)(object)__instance != (Object)(object)Player.m_localPlayer)) { PatchInventory(((Humanoid)__instance).GetInventory()); } } } [HarmonyPatch(typeof(Inventory), "Load")] public class Inventory_Load_BBHQuiverType { public static void Postfix(Inventory __instance) { if (BowsBeforeHoesSlot.IsActive) { PatchInventory(__instance); } } } [HarmonyPatch(typeof(ObjectDB), "Awake")] public static class ObjectDB_Awake_ChangeBackpackItemType { [HarmonyPriority(0)] private static void Postfix(ObjectDB __instance) { if (BowsBeforeHoesSlot.IsActive && __instance.m_items.Count != 0 && !((Object)(object)__instance.GetItemPrefab("Wood") == (Object)null)) { UpdateBackpacksItemType(); } } } [HarmonyPatch(typeof(ObjectDB), "CopyOtherDB")] public static class ObjectDB_CopyOtherDB_AddPrefab { [HarmonyPriority(0)] private static void Postfix(ObjectDB __instance) { if (BowsBeforeHoesSlot.IsActive && __instance.m_items.Count != 0 && !((Object)(object)__instance.GetItemPrefab("Wood") == (Object)null)) { UpdateBackpacksItemType(); } } } public static ItemType GetItemType() { //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Unknown result type (might be due to invalid IL or missing references) if (!BowsBeforeHoesSlot.IsActive) { return (ItemType)17; } return (ItemType)16; } public static void PatchBackpackItemData(ItemData itemData) { //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Unknown result type (might be due to invalid IL or missing references) if (itemData != null) { itemData.m_shared.m_itemType = GetItemType(); } } public static void PatchInventory(Inventory inventory, bool force = false) { if ((!BowsBeforeHoesSlot.IsActive && !force) || inventory == null) { return; } foreach (ItemData item in from item in inventory.GetAllItems() where BowsBeforeHoesSlot.IsQuiver(item) select item) { PatchBackpackItemData(item); } } public static void PatchBackpackItemOnConfigChange() { UpdateBackpacksItemType(force: true); Player localPlayer = Player.m_localPlayer; PatchInventory((localPlayer != null) ? ((Humanoid)localPlayer).GetInventory() : null, force: true); } public static void UpdateBackpacksItemType(bool force = false) { if ((!BowsBeforeHoesSlot.IsActive && !force) || !Object.op_Implicit((Object)(object)ObjectDB.instance)) { return; } foreach (GameObject item in ObjectDB.instance.m_items) { if ((Object)(object)item != (Object)null) { ItemData val = item.GetComponent<ItemDrop>()?.m_itemData; if (val != null && BowsBeforeHoesSlot.IsQuiver(val)) { PatchBackpackItemData(val); } } } } } public class JewelcraftingNeckSlot : CustomSlot { public const string ID = "JewelcraftingNeck"; public const string pluginID = "org.bepinex.plugins.jewelcrafting"; public JewelcraftingNeckSlot() { CustomSlot.slots.Add(this); GUID = "org.bepinex.plugins.jewelcrafting"; slotID = "JewelcraftingNeck"; if (!base.PluginInstalled) { return; } Assembly assembly = Assembly.GetAssembly(((object)Chainloader.PluginInfos["org.bepinex.plugins.jewelcrafting"].Instance).GetType()); MethodInfo isValid = AccessTools.Method(assembly.GetType("Jewelcrafting.Visual"), "IsNeckItem", (Type[])null, (Type[])null); if (isValid == null) { ExtraSlotsCustomSlots.LogWarning("Jewelcrafting mod is loaded but Jewelcrafting.Visual:IsNeckItem is not found"); return; } itemIsValid = delegate(ItemData item) { int result; if (item != null) { MethodInfo methodInfo = isValid; object[] parameters = (object[])(object)new ItemData[1] { item }; result = (((bool)methodInfo.Invoke(null, parameters)) ? 1 : 0); } else { result = 0; } return (byte)result != 0; }; getName = () => ExtraSlotsCustomSlots.jewelcraftingNeckSlotName.Value; isActive = () => CustomSlot.IsSlotActive(ExtraSlotsCustomSlots.jewelcraftingNeckSlotGlobalKey.Value, ExtraSlotsCustomSlots.jewelcraftingNeckSlotItemDiscovered.Value); initialized = true; } } public class JewelcraftingRingSlot : CustomSlot { public const string ID = "JewelcraftingRing"; public const string pluginID = "org.bepinex.plugins.jewelcrafting"; public JewelcraftingRingSlot() { CustomSlot.slots.Add(this); GUID = "org.bepinex.plugins.jewelcrafting"; slotID = "JewelcraftingRing"; if (!base.PluginInstalled) { return; } Assembly assembly = Assembly.GetAssembly(((object)Chainloader.PluginInfos["org.bepinex.plugins.jewelcrafting"].Instance).GetType()); MethodInfo isValid = AccessTools.Method(assembly.GetType("Jewelcrafting.Visual"), "IsFingerItem", (Type[])null, (Type[])null); if (isValid == null) { ExtraSlotsCustomSlots.LogWarning("Jewelcrafting mod is loaded but Jewelcrafting.Visual:IsFingerItem is not found"); return; } itemIsValid = delegate(ItemData item) { int result; if (item != null) { MethodInfo methodInfo = isValid; object[] parameters = (object[])(object)new ItemData[1] { item }; result = (((bool)methodInfo.Invoke(null, parameters)) ? 1 : 0); } else { result = 0; } return (byte)result != 0; }; getName = () => ExtraSlotsCustomSlots.jewelcraftingRingSlotName.Value; isActive = () => CustomSlot.IsSlotActive(ExtraSlotsCustomSlots.jewelcraftingRingSlotGlobalKey.Value, ExtraSlotsCustomSlots.jewelcraftingRingSlotItemDiscovered.Value); initialized = true; } } public class BackpacksSlot : CustomSlot { public const string ID = "Backpacks"; public const string pluginID = "org.bepinex.plugins.backpacks"; public BackpacksSlot() { CustomSlot.slots.Add(this); GUID = "org.bepinex.plugins.backpacks"; slotID = "Backpacks"; if (!base.PluginInstalled) { return; } Assembly assembly = Assembly.GetAssembly(((object)Chainloader.PluginInfos["org.bepinex.plugins.backpacks"].Instance).GetType()); MethodInfo isValid = AccessTools.Method(assembly.GetType("Backpacks.Backpacks"), "validateBackpack", (Type[])null, (Type[])null); if (isValid == null) { ExtraSlotsCustomSlots.LogWarning("Backpacks mod is loaded but Backpacks.Backpacks:validateBackpack is not found"); return; } itemIsValid = delegate(ItemData item) { int result; if (item != null) { MethodInfo methodInfo = isValid; object[] parameters = (object[])(object)new ItemData[1] { item }; result = (((bool)methodInfo.Invoke(null, parameters)) ? 1 : 0); } else { result = 0; } return (byte)result != 0; }; getName = () => ExtraSlotsCustomSlots.backpacksSlotName.Value; isActive = () => CustomSlot.IsSlotActive(ExtraSlotsCustomSlots.backpacksSlotGlobalKey.Value, ExtraSlotsCustomSlots.backpacksSlotItemDiscovered.Value); initialized = true; } } internal class CustomConfigs { internal class ConfigurationManagerAttributes { [UsedImplicitly] public Action<ConfigEntryBase>? CustomDrawer; } internal static object? configManager; internal static Type? configManagerStyles; internal static GUIStyle GetStyle(GUIStyle other) { //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_0051: Expected O, but got Unknown if (configManagerStyles == null) { return other; } FieldInfo fieldInfo = AccessTools.Field(configManagerStyles, "fontSize"); if (fieldInfo == null) { return other; } return new GUIStyle(other) { fontSize = (int)fieldInfo.GetValue(configManagerStyles) }; } internal static void Awake() { Assembly assembly = AppDomain.CurrentDomain.GetAssemblies().FirstOrDefault((Assembly a) => a.GetName().Name == "ConfigurationManager"); Type type = assembly?.GetType("ConfigurationManager.ConfigurationManager"); configManager = ((type == null) ? null : Chainloader.ManagerObject.GetComponent(type)); configManagerStyles = assembly?.GetType("ConfigurationManager.ConfigurationManagerStyles") ?? assembly?.GetType("ConfigurationManager.Utilities.ImguiUtils"); } internal static Action<ConfigEntryBase> DrawSeparatedStrings(string splitString) { string splitString2 = splitString; return delegate(ConfigEntryBase cfg) { //IL_010a: Unknown result type (might be due to invalid IL or missing references) //IL_010f: Unknown result type (might be due to invalid IL or missing references) //IL_0125: Expected O, but got Unknown //IL_0155: Unknown result type (might be due to invalid IL or missing references) //IL_015a: Unknown result type (might be due to invalid IL or missing references) //IL_0170: Expected O, but got Unknown bool valueOrDefault = cfg.Description.Tags.Select((object a) => (a.GetType().Name == "ConfigurationManagerAttributes") ? ((bool?)a.GetType().GetField("ReadOnly")?.GetValue(a)) : null).FirstOrDefault((bool? v) => v.HasValue).GetValueOrDefault(); bool flag = false; GUILayout.BeginVertical(Array.Empty<GUILayoutOption>()); List<string> list = new List<string>(); List<string> list2 = ((string)cfg.BoxedValue).Split(new string[1] { splitString2 }, StringSplitOptions.None).ToList(); for (int i = 0; i < list2.Count; i++) { GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>()); string text = list2[i]; string text2 = GUILayout.TextField(text, GetStyle(GUI.skin.textField), (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.ExpandWidth(true) }); if (text2 != text && !valueOrDefault) { flag = true; } if (GUILayout.Button("x", new GUIStyle(GetStyle(GUI.skin.button)) { fixedWidth = 21f }, Array.Empty<GUILayoutOption>()) && !valueOrDefault) { flag = true; } else { list.Add(text2); } if (GUILayout.Button("+", new GUIStyle(GetStyle(GUI.skin.button)) { fixedWidth = 21f }, Array.Empty<GUILayoutOption>()) && !valueOrDefault) { flag = true; list.Add(""); } GUILayout.EndHorizontal(); } GUILayout.EndVertical(); if (flag) { cfg.BoxedValue = string.Join(splitString2, list); } }; } internal static Action<ConfigEntryBase> DrawOrderedFixedStrings(string splitString) { string splitString2 = splitString; return delegate(ConfigEntryBase cfg) { //IL_00e4: Unknown result type (might be due to invalid IL or missing references) //IL_00e9: Unknown result type (might be due to invalid IL or missing references) //IL_00ff: Expected O, but got Unknown //IL_015b: Unknown result type (might be due to invalid IL or missing references) //IL_0160: Unknown result type (might be due to invalid IL or missing references) //IL_0176: Expected O, but got Unknown bool valueOrDefault = cfg.Description.Tags.Select((object a) => (a.GetType().Name == "ConfigurationManagerAttributes") ? ((bool?)a.GetType().GetField("ReadOnly")?.GetValue(a)) : null).FirstOrDefault((bool? v) => v.HasValue).GetValueOrDefault(); bool flag = false; GUILayout.BeginVertical(Array.Empty<GUILayoutOption>()); string[] array = ((string)cfg.BoxedValue).Split(new string[1] { splitString2 }, StringSplitOptions.None).ToArray(); for (int i = 0; i < array.Length; i++) { GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>()); string text = array[i]; GUILayout.Label(text, GetStyle(GUI.skin.textField), (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.ExpandWidth(true) }); if (GUILayout.Button("ʌ", new GUIStyle(GetStyle(GUI.skin.button)) { fixedWidth = 21f }, Array.Empty<GUILayoutOption>()) && !valueOrDefault && (flag = i > 0)) { ref string reference = ref array[i]; ref string reference2 = ref array[i - 1]; string text2 = array[i - 1]; string text3 = array[i]; reference = text2; reference2 = text3; } if (GUILayout.Button("v", new GUIStyle(GetStyle(GUI.skin.button)) { fixedWidth = 21f }, Array.Empty<GUILayoutOption>()) && !valueOrDefault && (flag = i < array.Length - 1)) { ref string reference = ref array[i]; ref string reference3 = ref array[i + 1]; string text3 = array[i + 1]; string text2 = array[i]; reference = text3; reference3 = text2; } GUILayout.EndHorizontal(); } GUILayout.EndVertical(); if (flag) { cfg.BoxedValue = string.Join(splitString2, array); } }; } } public class CustomSlot { public const string slotPrefix = "ESCS"; public string GUID; public bool initialized; public string slotID; public Func<ItemData, bool> itemIsValid; public Func<string> getName; public Func<bool> isActive; public static readonly List<CustomSlot> slots = new List<CustomSlot>(); public static readonly string VanillaOrder = string.Join(",", GetVanillaOrder()); public bool PluginInstalled => Chainloader.PluginInfos.ContainsKey(GUID); public bool AddSlot() { return initialized && API.AddSlot(GetSlotID(slotID), getName, itemIsValid, isActive); } public bool RemoveSlot() { return initialized && (API.RemoveSlot(GetSlotID(slotID)) || API.RemoveSlot(slotID)); } public static string GetSlotID(string slotID) { return "ESCS" + slotID.ToString(); } public override string ToString() { return initialized ? slotID.ToString() : (GUID + " (inactive)"); } public static List<string> GetVanillaOrder() { List<string> list = new List<string> { "Backpacks", "AdventureBackpacks", "JudesEquipmentBackpack", "RustyBagsBag", "CircletExtended", "JewelcraftingNeck", "MagicPluginEarring", "JewelcraftingRing", "MagicPluginTome", "VikingsSummoner", "BowsBeforeHoes", "HipLantern" }; for (int i = 0; i < 8; i++) { list.Add(UserDefinedSlot.GetSlotID(i)); } return list; } public static bool IsSlotActive(string globalKey, string itemDiscovered) { bool flag = !Utility.IsNullOrWhiteSpace(globalKey); bool flag2 = !Utility.IsNullOrWhiteSpace(itemDiscovered); if (!flag && !flag2) { return true; } if (flag && flag2) { return API.IsAnyGlobalKeyActive(globalKey) || API.IsAnyMaterialDiscovered(itemDiscovered); } return flag ? API.IsAnyGlobalKeyActive(globalKey) : API.IsAnyMaterialDiscovered(itemDiscovered); } } [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInPlugin("shudnal.ExtraSlotsCustomSlots", "Extra Slots Custom Slots", "1.0.17")] public class ExtraSlotsCustomSlots : BaseUnityPlugin { public const string pluginID = "shudnal.ExtraSlotsCustomSlots"; public const string pluginName = "Extra Slots Custom Slots"; public const string pluginVersion = "1.0.17"; internal readonly Harmony harmony = new Harmony("shudnal.ExtraSlotsCustomSlots"); internal static readonly ConfigSync configSync = new ConfigSync("shudnal.ExtraSlotsCustomSlots") { DisplayName = "Extra Slots Custom Slots", CurrentVersion = "1.0.17", MinimumRequiredVersion = "1.0.17" }; internal static ExtraSlotsCustomSlots instance; public static ConfigEntry<bool> configLocked; public static ConfigEntry<bool> loggingEnabled; public static ConfigEntry<string> slotsOrder; public static ConfigEntry<bool> adventureBackpackSlotEnabled; public static ConfigEntry<string> adventureBackpackSlotName; public static ConfigEntry<string> adventureBackpackSlotGlobalKey; public static ConfigEntry<string> adventureBackpackSlotItemDiscovered; public static ConfigEntry<bool> backpacksSlotEnabled; public static ConfigEntry<string> backpacksSlotName; public static ConfigEntry<string> backpacksSlotGlobalKey; public static ConfigEntry<string> backpacksSlotItemDiscovered; public static ConfigEntry<bool> bbhQuiverSlotEnabled; public static ConfigEntry<string> bbhQuiverSlotName; public static ConfigEntry<string> bbhQuiverSlotGlobalKey; public static ConfigEntry<string> bbhQuiverSlotItemDiscovered; public static ConfigEntry<bool> circletExtendedSlotEnabled; public static ConfigEntry<string> circletExtendedSlotName; public static ConfigEntry<string> circletExtendedSlotGlobalKey; public static ConfigEntry<string> circletExtendedSlotItemDiscovered; public static ConfigEntry<bool> hipLanternSlotEnabled; public static ConfigEntry<string> hipLanternSlotName; public static ConfigEntry<string> hipLanternSlotGlobalKey; public static ConfigEntry<string> hipLanternSlotItemDiscovered; public static ConfigEntry<bool> jewelcraftingNeckSlotEnabled; public static ConfigEntry<string> jewelcraftingNeckSlotName; public static ConfigEntry<string> jewelcraftingNeckSlotGlobalKey; public static ConfigEntry<string> jewelcraftingNeckSlotItemDiscovered; public static ConfigEntry<bool> jewelcraftingRingSlotEnabled; public static ConfigEntry<string> jewelcraftingRingSlotName; public static ConfigEntry<string> jewelcraftingRingSlotGlobalKey; public static ConfigEntry<string> jewelcraftingRingSlotItemDiscovered; public static ConfigEntry<bool> magicPluginTomeSlotEnabled; public static ConfigEntry<string> magicPluginTomeSlotName; public static ConfigEntry<string> magicPluginTomeSlotGlobalKey; public static ConfigEntry<string> magicPluginTomeSlotItemDiscovered; public static ConfigEntry<bool> magicPluginEarringSlotEnabled; public static ConfigEntry<string> magicPluginEarringSlotName; public static ConfigEntry<string> magicPluginEarringSlotGlobalKey; public static ConfigEntry<string> magicPluginEarringSlotItemDiscovered; public static ConfigEntry<bool> judesEquipmentBackpackSlotEnabled; public static ConfigEntry<string> judesEquipmentBackpackSlotName; public static ConfigEntry<string> judesEquipmentBackpackSlotGlobalKey; public static ConfigEntry<string> judesEquipmentBackpackSlotItemDiscovered; public static ConfigEntry<bool> rustyBagsSlotEnabled; public static ConfigEntry<string> rustyBagsSlotName; public static ConfigEntry<string> rustyBagsSlotGlobalKey; public static ConfigEntry<string> rustyBagsSlotItemDiscovered; public static ConfigEntry<bool> vikingsSummonerSlotEnabled; public static ConfigEntry<string> vikingsSummonerSlotName; public static ConfigEntry<string> vikingsSummonerSlotGlobalKey; public static ConfigEntry<string> vikingsSummonerSlotItemDiscovered; private void Awake() { instance = this; ConfigInit(); configSync.AddLockingConfigEntry<bool>(configLocked); UpdateSlots(); harmony.PatchAll(); } private void OnDestroy() { ((BaseUnityPlugin)this).Config.Save(); instance = null; Harmony obj = harmony; if (obj != null) { obj.UnpatchSelf(); } } public void ConfigInit() { //IL_006d: Unknown result type (might be due to invalid IL or missing references) //IL_0078: Expected O, but got Unknown configLocked = config("General", "Lock Configuration", defaultValue: true, "Configuration is locked and can be changed by server admins only. "); loggingEnabled = config("General", "Logging enabled", defaultValue: false, "Enable logging. [Not synced with Server]", synchronizedSetting: false); slotsOrder = config("General", "Slots order", CustomSlot.VanillaOrder, new ConfigDescription("Comma-separated slot ID order of custom slots", (AcceptableValueBase)null, new object[1] { new CustomConfigs.ConfigurationManagerAttributes { CustomDrawer = CustomConfigs.DrawOrderedFixedStrings(",") } })); slotsOrder.SettingChanged += delegate { UpdateSlots(); }; adventureBackpackSlotEnabled = config("Mod - Adventure Backpacks", "Enabled", defaultValue: true, "Enable adventure backpack slot. Restart the game after change to avoid potential issues."); adventureBackpackSlotName = config("Mod - Adventure Backpacks", "Name", "Backpack", "Slot name. Use ExtraSlots translation files to add localized string."); adventureBackpackSlotGlobalKey = config("Mod - Adventure Backpacks", "Global keys", "", "Comma-separated list of global keys and player unique keys. Slot will be active only if any key is enabled or list is not set."); adventureBackpackSlotItemDiscovered = config("Mod - Adventure Backpacks", "Items discovered", "$vapok_mod_item_backpack_meadows,$vapok_mod_item_backpack_blackforest,$vapok_mod_item_backpack_swamp,$vapok_mod_item_backpack_mountains,$vapok_mod_item_backpack_plains,$vapok_mod_item_backpack_mistlands,$vapok_mod_item_rugged_backpack,$vapok_mod_item_arctic_backpack", "Comma-separated list of items. Slot will be active only if any item is discovered or list is not set."); adventureBackpackSlotEnabled.SettingChanged += delegate { AdventureBackpackItem.PatchBackpackItemOnConfigChange(); UpdateSlots(); }; backpacksSlotEnabled = config("Mod - Backpacks", "Enabled", defaultValue: true, "Enable backpack slot"); backpacksSlotName = config("Mod - Backpacks", "Name", "$bp_backpack_slot_name", "Slot name"); backpacksSlotGlobalKey = config("Mod - Backpacks", "Global keys", "", "Comma-separated list of global keys and player unique keys. Slot will be active only if any key is enabled or list is not set."); backpacksSlotItemDiscovered = config("Mod - Backpacks", "Items discovered", "$item_explorer", "Comma-separated list of items. Slot will be active only if any item is discovered or list is not set."); backpacksSlotEnabled.SettingChanged += delegate { UpdateSlots(); }; bbhQuiverSlotEnabled = config("Mod - BowsBeforeHoes", "Enabled", defaultValue: true, "Enable quiver slot"); bbhQuiverSlotName = config("Mod - BowsBeforeHoes", "Name", "$bbh_slot_quiver", "Slot name"); bbhQuiverSlotGlobalKey = config("Mod - BowsBeforeHoes", "Global keys", "", "Comma-separated list of global keys and player unique keys. Slot will be active only if any key is enabled or list is not set."); bbhQuiverSlotItemDiscovered = config("Mod - BowsBeforeHoes", "Items discovered", "$item_quiver_blackforest,$item_quiver_seeker,$item_quiver_leather,$item_quiver_odinplus,$item_quiver_plainslox", "Comma-separated list of items. Slot will be active only if any item is discovered or list is not set."); bbhQuiverSlotEnabled.SettingChanged += delegate { UpdateSlots(); BowsBeforeHoesCompat.PatchBackpackItemOnConfigChange(); }; circletExtendedSlotEnabled = config("Mod - CircletExtended", "Enabled", defaultValue: true, "Enable circlet slot"); circletExtendedSlotName = config("Mod - CircletExtended", "Name", "Circlet", "Slot name. Use ExtraSlots translation files to add localized string."); circletExtendedSlotGlobalKey = config("Mod - CircletExtended", "Global keys", "", "Comma-separated list of global keys and player unique keys. Slot will be active only if any key is enabled or list is not set."); circletExtendedSlotItemDiscovered = config("Mod - CircletExtended", "Items discovered", "$item_helmet_dverger", "Comma-separated list of items. Slot will be active only if any item is discovered or list is not set."); circletExtendedSlotEnabled.SettingChanged += delegate { UpdateSlots(); }; hipLanternSlotEnabled = config("Mod - HipLantern", "Enabled", defaultValue: true, "Enable hip lantern slot"); hipLanternSlotName = config("Mod - HipLantern", "Name", "Lantern", "Slot name. Use ExtraSlots translation files to add localized string."); hipLanternSlotGlobalKey = config("Mod - HipLantern", "Global keys", "", "Comma-separated list of global keys and player unique keys. Slot will be active only if any key is enabled or list is not set."); hipLanternSlotItemDiscovered = config("Mod - HipLantern", "Items discovered", "$item_hiplantern", "Comma-separated list of items. Slot will be active only if any item is discovered or list is not set."); hipLanternSlotEnabled.SettingChanged += delegate { UpdateSlots(); }; jewelcraftingNeckSlotEnabled = config("Mod - Jewelcrafting - Neck", "Enabled", defaultValue: true, "Enable neck slot"); jewelcraftingNeckSlotName = config("Mod - Jewelcrafting - Neck", "Name", "Neck", "Slot name. Use ExtraSlots translation files to add localized string."); jewelcraftingNeckSlotGlobalKey = config("Mod - Jewelcrafting - Neck", "Global keys", "", "Comma-separated list of global keys and player unique keys. Slot will be active only if any key is enabled or list is not set."); jewelcraftingNeckSlotItemDiscovered = config("Mod - Jewelcrafting - Neck", "Items discovered", "$jc_necklace_red,$jc_necklace_green,$jc_necklace_blue,$jc_necklace_yellow,$jc_necklace_purple,$jc_necklace_orange,$jc_necklace_dvergrnecklace,$jc_necklace_eitrnecklace,$jc_necklace_fireresistnecklace,$jc_necklace_frostresistnecklace,$jc_necklace_poisonresistnecklace,", "Comma-separated list of items. Slot will be active only if any item is discovered or list is not set."); jewelcraftingNeckSlotEnabled.SettingChanged += delegate { UpdateSlots(); }; jewelcraftingRingSlotEnabled = config("Mod - Jewelcrafting - Ring", "Enabled", defaultValue: true, "Enable Ring slot"); jewelcraftingRingSlotName = config("Mod - Jewelcrafting - Ring", "Name", "Finger", "Slot name. Use ExtraSlots translation files to add localized string."); jewelcraftingRingSlotGlobalKey = config("Mod - Jewelcrafting - Ring", "Global keys", "", "Comma-separated list of global keys and player unique keys. Slot will be active only if any key is enabled or list is not set."); jewelcraftingRingSlotItemDiscovered = config("Mod - Jewelcrafting - Ring", "Items discovered", "$jc_ring_purple,$jc_ring_green,$jc_ring_red,$jc_ring_blue,$jc_ring_black,$jc_ring_dvergrring,$jc_ring_eitrring,$jc_ring_fireresistring,$jc_ring_frostresistring,$jc_ring_poisonresistring", "Comma-separated list of items. Slot will be active only if any item is discovered or list is not set."); jewelcraftingRingSlotEnabled.SettingChanged += delegate { UpdateSlots(); }; magicPluginTomeSlotEnabled = config("Mod - Magic Plugin - Tome", "Enabled", defaultValue: true, "Enable tome slot"); magicPluginTomeSlotName = config("Mod - Magic Plugin - Tome", "Name", "$bmp_tomeslot", "Slot name"); magicPluginTomeSlotGlobalKey = config("Mod - Magic Plugin - Tome", "Global keys", "", "Comma-separated list of global keys and player unique keys. Slot will be active only if any key is enabled or list is not set."); magicPluginTomeSlotItemDiscovered = config("Mod - Magic Plugin - Tome", "Items discovered", "$bmp_advance_magicbook,$bmp_beginners_magicbook", "Comma-separated list of items. Slot will be active only if any item is discovered or list is not set."); magicPluginTomeSlotEnabled.SettingChanged += delegate { UpdateSlots(); }; magicPluginEarringSlotEnabled = config("Mod - Magic Plugin - Earring", "Enabled", defaultValue: true, "Enable earring slot"); magicPluginEarringSlotName = config("Mod - Magic Plugin - Earring", "Name", "$bmp_earringslot", "Slot name"); magicPluginEarringSlotGlobalKey = config("Mod - Magic Plugin - Earring", "Global keys", "", "Comma-separated list of global keys and player unique keys. Slot will be active only if any key is enabled or list is not set."); magicPluginEarringSlotItemDiscovered = config("Mod - Magic Plugin - Earring", "Items discovered", "$bmp_dvergr_earring,$bmp_fireresist_earring,$bmp_frostresist_earring,$bmp_poisonresist_earring,$bmp_eitr_earring", "Comma-separated list of items. Slot will be active only if any item is discovered or list is not set."); magicPluginEarringSlotEnabled.SettingChanged += delegate { UpdateSlots(); }; judesEquipmentBackpackSlotEnabled = config("Mod - Judes Equipment", "Enabled", defaultValue: true, "Enable Judes Equipment backpack slot. Restart the game after change to avoid potential issues."); judesEquipmentBackpackSlotName = config("Mod - Judes Equipment", "Name", "Backpack", "Slot name. Use ExtraSlots translation files to add localized string."); judesEquipmentBackpackSlotGlobalKey = config("Mod - Judes Equipment", "Global keys", "", "Comma-separated list of global keys and player unique keys. Slot will be active only if any key is enabled or list is not set."); judesEquipmentBackpackSlotItemDiscovered = config("Mod - Judes Equipment", "Items discovered", "$BackpackSimple,$BackpackHeavy", "Comma-separated list of items. Slot will be active only if any item is discovered or list is not set."); judesEquipmentBackpackSlotEnabled.SettingChanged += delegate { JudesEquipmentBackpackItem.PatchBackpackItemOnConfigChange(); UpdateSlots(); }; rustyBagsSlotEnabled = config("Mod - Rusty Bags", "Enabled", defaultValue: true, "Enable Rusty Bags backpack slot."); rustyBagsSlotName = config("Mod - Rusty Bags", "Name", "Bag", "Slot name. Use ExtraSlots translation files to add localized string."); rustyBagsSlotGlobalKey = config("Mod - Rusty Bags", "Global keys", "", "Comma-separated list of global keys and player unique keys. Slot will be active only if any key is enabled or list is not set."); rustyBagsSlotItemDiscovered = config("Mod - Rusty Bags", "Items discovered", "$item_BarrelBag_RS,$item_CrossbowQuiver_RS,$item_DvergerBag_RS,$item_LeatherBag_RS,$item_MountainQuiver_RS,$item_Quiver_RS,$item_UnbjornBag_RS", "Comma-separated list of items. Slot will be active only if any item is discovered or list is not set."); rustyBagsSlotEnabled.SettingChanged += delegate { UpdateSlots(); }; vikingsSummonerSlotEnabled = config("Mod - Vikings Summoner", "Enabled", defaultValue: true, "Enable Vikings Summoner grimoire slot."); vikingsSummonerSlotName = config("Mod - Vikings Summoner", "Name", "Grimoire", "Slot name. Use ExtraSlots translation files to add localized string."); vikingsSummonerSlotGlobalKey = config("Mod - Vikings Summoner", "Global keys", "", "Comma-separated list of global keys and player unique keys. Slot will be active only if any key is enabled or list is not set."); vikingsSummonerSlotItemDiscovered = config("Mod - Vikings Summoner", "Items discovered", "RD_grimoire_01,RD_grimoire_02,RD_grimoire_03", "Comma-separated list of items. Slot will be active only if any item is discovered or list is not set."); vikingsSummonerSlotEnabled.SettingChanged += delegate { UpdateSlots(); }; for (int i = 0; i < 8; i++) { new UserDefinedSlot(i); } } public static void UpdateSlots() { CollectionExtensions.Do<CustomSlot>((IEnumerable<CustomSlot>)CustomSlot.slots, (Action<CustomSlot>)delegate(CustomSlot slot) { slot.RemoveSlot(); }); CustomSlot.slots.Clear(); CollectionExtensions.Do<string>(from s in slotsOrder.Value.Split(new char[1] { ',' }) select s.Trim() into s where !Utility.IsNullOrWhiteSpace(s) select s, (Action<string>)InitSlot); List<string> vanillaSlots = CustomSlot.VanillaOrder.Split(new char[1] { ',' }).ToList(); CollectionExtensions.Do<CustomSlot>((IEnumerable<CustomSlot>)CustomSlot.slots, (Action<CustomSlot>)delegate(CustomSlot slot) { vanillaSlots.Remove(slot.slotID); }); CollectionExtensions.Do<string>((IEnumerable<string>)vanillaSlots, (Action<string>)InitSlot); CollectionExtensions.Do<CustomSlot>((IEnumerable<CustomSlot>)CustomSlot.slots, (Action<CustomSlot>)TryAddSlot); } public static void TryAddSlot(CustomSlot slot) { if (slot.RemoveSlot()) { LogInfo($"Slot {slot} was removed"); } if (slot.AddSlot()) { LogInfo($"Slot {slot} was added"); } else if (slot.initialized) { LogWarning($"Error while trying to add new slot {slot}."); } } public static void InitSlot(string slotID) { switch (slotID) { case "Backpacks": if (!backpacksSlotEnabled.Value) { break; } new BackpacksSlot(); return; case "AdventureBackpacks": if (!adventureBackpackSlotEnabled.Value) { break; } new AdventureBackpacksSlot(); return; case "JudesEquipmentBackpack": if (!judesEquipmentBackpackSlotEnabled.Value) { break; } new JudesEquipmentBackpackSlot(); return; case "RustyBagsBag": if (!rustyBagsSlotEnabled.Value) { break; } new RustyBagsSlot(); return; case "MagicPluginTome": if (!magicPluginTomeSlotEnabled.Value) { break; } new MagicPluginTomeSlot(); return; case "MagicPluginEarring": if (!magicPluginEarringSlotEnabled.Value) { break; } new MagicPluginEarringSlot(); return; case "JewelcraftingNeck": if (!jewelcraftingNeckSlotEnabled.Value) { break; } new JewelcraftingNeckSlot(); return; case "JewelcraftingRing": if (!jewelcraftingRingSlotEnabled.Value) { break; } new JewelcraftingRingSlot(); return; case "BowsBeforeHoes": if (!bbhQuiverSlotEnabled.Value) { break; } new BowsBeforeHoesSlot(); return; case "CircletExtended": if (!circletExtendedSlotEnabled.Value) { break; } new CircletExtendedSlot(); return; case "HipLantern": if (!hipLanternSlotEnabled.Value) { break; } new HipLanternSlot(); return; case "VikingsSummoner": if (!vikingsSummonerSlotEnabled.Value) { break; } new VikingsSummoner(); return; } if (UserDefinedSlot.IsUserDefinedSlot(slotID)) { UserDefinedSlot.UpdateSlot(slotID); } } public static void LogInfo(object data) { if (loggingEnabled.Value) { ((BaseUnityPlugin)instance).Logger.LogInfo(data); } } public static void LogMessage(object data) { ((BaseUnityPlugin)instance).Logger.LogMessage(data); } public static void LogWarning(object data) { ((BaseUnityPlugin)instance).Logger.LogWarning(data); } internal ConfigEntry<T> config<T>(string group, string name, T defaultValue, ConfigDescription description, bool synchronizedSetting = true) { ConfigEntry<T> val = ((BaseUnityPlugin)this).Config.Bind<T>(group, name, defaultValue, description); SyncedConfigEntry<T> syncedConfigEntry = configSync.AddConfigEntry<T>(val); syncedConfigEntry.SynchronizedConfig = synchronizedSetting; return val; } internal ConfigEntry<T> config<T>(string group, string name, T defaultValue, string description, bool synchronizedSetting = true) { //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Expected O, but got Unknown return config(group, name, defaultValue, new ConfigDescription(description, (AcceptableValueBase)null, Array.Empty<object>()), synchronizedSetting); } } public class RustyBagsSlot : CustomSlot { public const string ID = "RustyBagsBag"; public const string pluginID = "RustyMods.RustyBags"; public RustyBagsSlot() { CustomSlot.slots.Add(this); GUID = "RustyMods.RustyBags"; slotID = "RustyBagsBag"; if (!base.PluginInstalled) { return; } Assembly assembly = Assembly.GetAssembly(((object)Chainloader.PluginInfos["RustyMods.RustyBags"].Instance).GetType()); Type bag = AccessTools.GetTypesFromAssembly(assembly).FirstOrDefault((Type type) => type.FullName == "RustyBags.Bag"); if (bag == null) { ExtraSlotsCustomSlots.LogWarning("RustyBags mod is loaded but RustyBags.Bag type is not found"); return; } itemIsValid = (ItemData item) => item != null && bag.IsInstanceOfType(item); getName = () => ExtraSlotsCustomSlots.rustyBagsSlotName.Value; isActive = () => CustomSlot.IsSlotActive(ExtraSlotsCustomSlots.rustyBagsSlotGlobalKey.Value, ExtraSlotsCustomSlots.rustyBagsSlotItemDiscovered.Value); initialized = true; } } public class MagicPluginTomeSlot : CustomSlot { public const string ID = "MagicPluginTome"; public const string pluginID = "blacks7ar.MagicPlugin"; public MagicPluginTomeSlot() { CustomSlot.slots.Add(this); GUID = "blacks7ar.MagicPlugin"; slotID = "MagicPluginTome"; if (!base.PluginInstalled) { return; } Assembly assembly = Assembly.GetAssembly(((object)Chainloader.PluginInfos["blacks7ar.MagicPlugin"].Instance).GetType()); MethodInfo isValid = AccessTools.Method(assembly.GetType("MagicPlugin.Functions.MagicSlot"), "IsTomeItem", (Type[])null, (Type[])null); if (isValid == null) { ExtraSlotsCustomSlots.LogWarning("MagicPlugin mod is loaded but MagicPlugin.Functions.MagicSlot:IsTomeItem is not found"); return; } itemIsValid = delegate(ItemData item) { int result; if (item != null) { MethodInfo methodInfo = isValid; object[] parameters = (object[])(object)new ItemData[1] { item }; result = (((bool)methodInfo.Invoke(null, parameters)) ? 1 : 0); } else { result = 0; } return (byte)result != 0; }; getName = () => ExtraSlotsCustomSlots.magicPluginTomeSlotName.Value; isActive = () => CustomSlot.IsSlotActive(ExtraSlotsCustomSlots.magicPluginTomeSlotGlobalKey.Value, ExtraSlotsCustomSlots.magicPluginTomeSlotItemDiscovered.Value); initialized = true; } } public class MagicPluginEarringSlot : CustomSlot { public const string ID = "MagicPluginEarring"; public const string pluginID = "blacks7ar.MagicPlugin"; public MagicPluginEarringSlot() { CustomSlot.slots.Add(this); GUID = "blacks7ar.MagicPlugin"; slotID = "MagicPluginEarring"; if (!base.PluginInstalled) { return; } Assembly assembly = Assembly.GetAssembly(((object)Chainloader.PluginInfos["blacks7ar.MagicPlugin"].Instance).GetType()); MethodInfo isValid = AccessTools.Method(assembly.GetType("MagicPlugin.Functions.MagicSlot"), "IsEarringItem", (Type[])null, (Type[])null); if (isValid == null) { ExtraSlotsCustomSlots.LogWarning("MagicPlugin mod is loaded but MagicPlugin.Functions.MagicSlot:IsEarringItem is not found"); return; } itemIsValid = delegate(ItemData item) { int result; if (item != null) { MethodInfo methodInfo = isValid; object[] parameters = (object[])(object)new ItemData[1] { item }; result = (((bool)methodInfo.Invoke(null, parameters)) ? 1 : 0); } else { result = 0; } return (byte)result != 0; }; getName = () => ExtraSlotsCustomSlots.magicPluginEarringSlotName.Value; isActive = () => CustomSlot.IsSlotActive(ExtraSlotsCustomSlots.magicPluginEarringSlotGlobalKey.Value, ExtraSlotsCustomSlots.magicPluginEarringSlotItemDiscovered.Value); initialized = true; } } [HarmonyPatch] public static class MagicPlugin_MagicSlot_AddCustomSlot_PreventCustomSlotAddition { public static MethodBase target; public static bool Prepare(MethodBase original) { if (!Chainloader.PluginInfos.TryGetValue("blacks7ar.MagicPlugin", out var value)) { return false; } if ((object)target == null) { target = AccessTools.Method(Assembly.GetAssembly(((object)value.Instance).GetType()).GetType("MagicPlugin.Functions.MagicSlot"), "AddCustomSlot", (Type[])null, (Type[])null); } if (target == null) { return false; } if (original == null) { ExtraSlotsCustomSlots.LogInfo("MagicPlugin.Functions.MagicSlot:AddCustomSlot method is patched to prevent adding custom slot call"); } return true; } public static MethodBase TargetMethod() { return target; } public static bool Prefix() { return false; } } [HarmonyPatch] public static class MagicPlugin_AzuEPI_IsLoaded_CustomSlotHandle { public static MethodBase target; public static bool Prepare(MethodBase original) { if (!Chainloader.PluginInfos.TryGetValue("blacks7ar.MagicPlugin", out var value)) { return false; } if ((object)target == null) { target = AccessTools.Method(Assembly.GetAssembly(((object)value.Instance).GetType()).GetType("AzuExtendedPlayerInventory.API"), "IsLoaded", (Type[])null, (Type[])null); } if (target == null) { return false; } if (original == null) { ExtraSlotsCustomSlots.LogInfo("MagicPlugin.AzuExtendedPlayerInventory.API:IsLoaded method is patched to enable custom slot handling"); } return true; } public static MethodBase TargetMethod() { return target; } public static void Postfix(ref bool __result) { __result = true; } } public class UserDefinedSlot : CustomSlot { public ConfigEntry<bool> slotEnabled; public ConfigEntry<string> slotName; public ConfigEntry<string> slotGlobalKey; public ConfigEntry<string> slotItemList; public ConfigEntry<bool> itemIsVisible; public string groupName; public List<string> itemList = new List<string>(); public const int maxAmount = 8; public static UserDefinedSlot[] userDefinedSlots = new UserDefinedSlot[8]; public const string UserDefinedSlotID = "CustomSlot"; public void UpdateItemList() { itemList.Clear(); CollectionExtensions.Do<string>(from s in slotItemList.Value.Split(new char[1] { ',' }) select s.Trim() into s where !Utility.IsNullOrWhiteSpace(s) select s, (Action<string>)itemList.Add); } public UserDefinedSlot(int index) { userDefinedSlots[index] = this; groupName = $"User defined - Custom slot {index + 1}"; slotEnabled = ExtraSlotsCustomSlots.instance.config(groupName, "Enabled", defaultValue: false, "Enable custom slot."); slotName = ExtraSlotsCustomSlots.instance.config(groupName, "Name", "Slot", "Slot name. Use ExtraSlots translation files to add localized string."); slotGlobalKey = ExtraSlotsCustomSlots.instance.config(groupName, "Global keys", "", "Comma-separated list of global keys and player unique keys. Slot will be active only if any key is enabled or list is not set."); slotItemList = ExtraSlotsCustomSlots.instance.config(groupName, "Item list", "", "Comma-separated list of items. Slot will be active only if any item is discovered."); itemIsVisible = ExtraSlotsCustomSlots.instance.config(groupName, "Item is visible", defaultValue: true, "Make item in that slot visible on player model (if supported by an item itself)."); slotEnabled.SettingChanged += delegate { ExtraSlotsCustomSlots.UpdateSlots(); }; slotItemList.SettingChanged += delegate { UpdateItemList(); }; itemIsVisible.SettingChanged += delegate { Player localPlayer = Player.m_localPlayer; if (localPlayer != null) { ((Humanoid)localPlayer).SetupEquipment(); } }; UpdateItemList(); GUID = GetSlotID(index); slotID = GUID; itemIsValid = (ItemData item) => item != null && ((item.m_shared != null && itemList.Contains(item.m_shared.m_name)) || ((Object)(object)item.m_dropPrefab != (Object)null && itemList.Contains(((Object)item.m_dropPrefab).name))); getName = () => slotName.Value; isActive = () => CustomSlot.IsSlotActive(slotGlobalKey.Value, slotItemList.Value); initialized = true; } public static void UpdateSlot(string slotID) { UserDefinedSlot userDefinedSlot = userDefinedSlots.FirstOrDefault((UserDefinedSlot slot) => slot.slotID == slotID); if (userDefinedSlot != null && userDefinedSlot.slotEnabled.Value) { CustomSlot.slots.Add(userDefinedSlot); } } public static bool IsUserDefinedSlot(string slotID) { return slotID.StartsWith("CustomSlot"); } public static string GetSlotID(int index) { return string.Format("{0}{1}", "CustomSlot", index + 1); } public static bool IsItemInSlotVisible(int index) { UserDefinedSlot userDefinedSlot = userDefinedSlots[index]; return userDefinedSlot != null && userDefinedSlot.slotEnabled.Value && userDefinedSlot.itemIsVisible.Value; } } } namespace ExtraSlotsCustomSlots.UserDefinedCustomSlots { [Serializable] public class HumanoidCustomItemSlots { public ItemData customItem1; public ItemData customItem2; public ItemData customItem3; public ItemData customItem4; public ItemData customItem5; public ItemData customItem6; public ItemData customItem7; public ItemData customItem8; } public static class HumanoidExtension { private static readonly ConditionalWeakTable<Humanoid, HumanoidCustomItemSlots> data = new ConditionalWeakTable<Humanoid, HumanoidCustomItemSlots>(); public static HumanoidCustomItemSlots GetCustomItemData(this Humanoid humanoid) { return data.GetOrCreateValue(humanoid); } public static ItemData GetCustomItem(this Humanoid humanoid, int index) { if (1 == 0) { } ItemData result = (ItemData)(index switch { 0 => humanoid.GetCustomItemData().customItem1, 1 => humanoid.GetCustomItemData().customItem2, 2 => humanoid.GetCustomItemData().customItem3, 3 => humanoid.GetCustomItemData().customItem4, 4 => humanoid.GetCustomItemData().customItem5, 5 => humanoid.GetCustomItemData().customItem6, 6 => humanoid.GetCustomItemData().customItem7, 7 => humanoid.GetCustomItemData().customItem8, _ => null, }); if (1 == 0) { } return result; } public static ItemData SetCustomItem(this Humanoid humanoid, int index, ItemData item) { if (1 == 0) { } ItemData result = (ItemData)(index switch { 0 => humanoid.GetCustomItemData().customItem1 = item, 1 => humanoid.GetCustomItemData().customItem2 = item, 2 => humanoid.GetCustomItemData().customItem3 = item, 3 => humanoid.GetCustomItemData().customItem4 = item, 4 => humanoid.GetCustomItemData().customItem5 = item, 5 => humanoid.GetCustomItemData().customItem6 = item, 6 => humanoid.GetCustomItemData().customItem7 = item, 7 => humanoid.GetCustomItemData().customItem8 = item, _ => null, }); if (1 == 0) { } return result; } } [Serializable] public class VisEquipmentCustomItemState { public string m_item = ""; public List<GameObject> m_instances; public int m_hash = 0; } [Serializable] public class VisEquipmentCustomItem { public VisEquipmentCustomItemState customItem1 = new VisEquipmentCustomItemState(); public VisEquipmentCustomItemState customItem2 = new VisEquipmentCustomItemState(); public VisEquipmentCustomItemState customItem3 = new VisEquipmentCustomItemState(); public VisEquipmentCustomItemState customItem4 = new VisEquipmentCustomItemState(); public VisEquipmentCustomItemState customItem5 = new VisEquipmentCustomItemState(); public VisEquipmentCustomItemState customItem6 = new VisEquipmentCustomItemState(); public VisEquipmentCustomItemState customItem7 = new VisEquipmentCustomItemState(); public VisEquipmentCustomItemState customItem8 = new VisEquipmentCustomItemState(); } public static class VisEquipmentExtension { [HarmonyPatch(typeof(VisEquipment), "UpdateEquipmentVisuals")] public static class VisEquipment_UpdateEquipmentVisuals_CustomItemType { public static VisEquipment visEq; public static bool updateLodGroup; private static void Prefix(VisEquipment __instance) { ZNetView nview = __instance.m_nview; ZDO val = ((nview != null) ? nview.GetZDO() : null); updateLodGroup = false; for (int i = 0; i < CustomItemSlots.SlotsAmount; i++) { int hash = 0; if (val != null) { hash = val.GetInt(customItemStateZdoHash[i], 0); } else { VisEquipmentCustomItemState customItemState = __instance.GetCustomItemState(i); if (!string.IsNullOrEmpty(customItemState.m_item)) { hash = StringExtensionMethods.GetStableHashCode(customItemState.m_item); } } if (__instance.SetCustomItemEquipped(hash, i)) { updateLodGroup = true; } } visEq = __instance; } private static void Postfix(VisEquipment __instance) { if (updateLodGroup) { __instance.UpdateLodgroup(); } visEq = null; updateLodGroup = false; } } [HarmonyPatch(typeof(VisEquipment), "UpdateLodgroup")] public static class VisEquipment_UpdateLodgroup_CustomItemType { private static void Finalizer(VisEquipment __instance) { if ((Object)(object)__instance == (Object)(object)VisEquipment_UpdateEquipmentVisuals_CustomItemType.visEq) { VisEquipment_UpdateEquipmentVisuals_CustomItemType.updateLodGroup = false; } } } [HarmonyPatch(typeof(Humanoid), "SetupVisEquipment")] public static class Humanoid_SetupVisEquipment_CustomItemType { private static void Postfix(Humanoid __instance, VisEquipment visEq) { for (int i = 0; i < CustomItemSlots.SlotsAmount; i++) { ItemData customItem = __instance.GetCustomItem(i); visEq.SetCustomItemState(i, (customItem != null && (Object)(object)customItem.m_dropPrefab != (Object)null && UserDefinedSlot.IsItemInSlotVisible(i)) ? ((Object)customItem.m_dropPrefab).name : ""); } } } private static readonly List<int> customItemStateZdoHash = new List<int> { StringExtensionMethods.GetStableHashCode("ESCS_CustomItemState_1"), StringExtensionMethods.GetStableHashCode("ESCS_CustomItemState_2"), StringExtensionMethods.GetStableHashCode("ESCS_CustomItemState_3"), StringExtensionMethods.GetStableHashCode("ESCS_CustomItemState_4"), StringExtensionMethods.GetStableHashCode("ESCS_CustomItemState_5"), StringExtensionMethods.GetStableHashCode("ESCS_CustomItemState_6"), StringExtensionMethods.GetStableHashCode("ESCS_CustomItemState_7"), StringExtensionMethods.GetStableHashCode("ESCS_CustomItemState_8") }; private static readonly ConditionalWeakTable<VisEquipment, VisEquipmentCustomItem> data = new ConditionalWeakTable<VisEquipment, VisEquipmentCustomItem>(); public static VisEquipmentCustomItem GetCustomItemData(this VisEquipment visEquipment) { return data.GetOrCreateValue(visEquipment); } public static VisEquipmentCustomItemState GetCustomItemState(this VisEquipment humanoid, int index) { if (1 == 0) { } VisEquipmentCustomItemState result = index switch { 0 => humanoid.GetCustomItemData().customItem1, 1 => humanoid.GetCustomItemData().customItem2, 2 => humanoid.GetCustomItemData().customItem3, 3 => humanoid.GetCustomItemData().customItem4, 4 => humanoid.GetCustomItemData().customItem5, 5 => humanoid.GetCustomItemData().customItem6, 6 => humanoid.GetCustomItemData().customItem7, 7 => humanoid.GetCustomItemData().customItem8, _ => null, }; if (1 == 0) { } return result; } public static void SetCustomItemState(this VisEquipment visEquipment, int index, string name) { VisEquipmentCustomItemState customItemState = visEquipment.GetCustomItemState(index); if (customItemState.m_item != name) { customItemState.m_item = name; if (visEquipment.m_nview.IsValid() && visEquipment.m_nview.IsOwner()) { visEquipment.m_nview.GetZDO().Set(customItemStateZdoHash[index], (!string.IsNullOrEmpty(name)) ? StringExtensionMethods.GetStableHashCode(name) : 0, false); } } } public static bool SetCustomItemEquipped(this VisEquipment visEquipment, int hash, int index) { VisEquipmentCustomItemState customItemState = visEquipment.GetCustomItemState(index); if (customItemState.m_hash == hash) { return false; } if (customItemState.m_instances != null) { foreach (GameObject instance in customItemState.m_instances) { if (Object.op_Implicit((Object)(object)visEquipment.m_lodGroup)) { Utils.RemoveFromLodgroup(visEquipment.m_lodGroup, instance); } Object.Destroy((Object)(object)instance); } customItemState.m_instances = null; } customItemState.m_hash = hash; if (hash != 0) { customItemState.m_instances = visEquipment.AttachArmor(hash, -1); } return true; } } public static class CustomItemSlots { public static class CustomItemPatches { [HarmonyPatch(typeof(Humanoid), "UpdateEquipmentStatusEffects")] private static class Humanoid_UpdateEquipmentStatusEffects_CustomItem { private static void Prefix(Humanoid __instance) { if (!IsValidPlayer(__instance)) { return; } tempEffects.Clear(); ItemData[] equippedItemsArray = GetEquippedItemsArray(); foreach (ItemData val in equippedItemsArray) { if (Object.op_Implicit((Object)(object)val.m_shared.m_equipStatusEffect)) { tempEffects.Add(val.m_shared.m_equipStatusEffect); } if (__instance.HaveSetEffect(val)) { tempEffects.Add(val.m_shared.m_setStatusEffect); } } } private static void Postfix(Humanoid __instance) { foreach (StatusEffect item in tempEffects.Where((StatusEffect item) => !__instance.m_equipmentStatusEffects.Contains(item))) { ((Character)__instance).m_seman.AddStatusEffect(item, false, 0, 0f); } __instance.m_equipmentStatusEffects.UnionWith(tempEffects); tempEffects.Clear(); } } [HarmonyPatch(typeof(SEMan), "RemoveStatusEffect", new Type[] { typeof(int), typeof(bool) })] private static class SEMan_RemoveStatusEffect_CustomItemPreventRemoval { private static void Prefix(SEMan __instance, ref int nameHash) { Player localPlayer = Player.m_localPlayer; if (__instance != ((localPlayer != null) ? ((Character)localPlayer).GetSEMan() : null) || tempEffects.Count == 0) { return; } foreach (StatusEffect tempEffect in tempEffects) { if (tempEffect.NameHash() == nameHash) { nameHash = 0; } } } } [HarmonyPatch(typeof(Humanoid), "GetEquipmentWeight")] private static class Humanoid_GetEquipmentWeight_CustomItem { private static void Postfix(Humanoid __instance, ref float __result) { if (IsValidPlayer(__instance)) { __result += GetEquippedItems().Sum((ItemData item) => item.m_shared.m_weight); } } } [HarmonyPatch(typeof(Humanoid), "EquipItem")] private static class Humanoid_EquipItem_CustomItem { private static readonly ItemType tempType = (ItemType)767; private static ItemType itemType; private static void Prefix(Humanoid __instance, ItemData item, ref int __state) { //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_0057: Unknown result type (might be due to invalid IL or missing references) //IL_005c: Unknown result type (might be due to invalid IL or missing references) //IL_0093: Unknown result type (might be due to invalid IL or missing references) //IL_0098: Unknown result type (might be due to invalid IL or missing references) //IL_009d: Unknown result type (might be due to invalid IL or missing references) //IL_00a8: Unknown result type (might be due to invalid IL or missing references) if (IsValidPlayer(__instance) && item != null && !IsItemEquipped(item) && (__state = GetSlotForItem(item)) != -1) { itemType = item.m_shared.m_itemType; item.m_shared.m_itemType = tempType; if (Object.op_Implicit((Object)(object)__instance.m_visEquipment) && __instance.m_visEquipment.m_isPlayer) { item.m_shared.m_equipEffect.Create(((Component)__instance).transform.position + Vector3.up, ((Component)__instance).transform.rotation, (Transform)null, 1f, -1); } } } [HarmonyPriority(800)] private static void Postfix(Humanoid __instance, ItemData item, bool triggerEquipEffects, int __state, ref bool __result) { //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Unknown result type (might be due to invalid IL or missing references) if (IsValidPlayer(__instance) && item != null && item.m_shared.m_itemType == tempType && __state != -1) { item.m_shared.m_itemType = itemType; ItemData customItem = __instance.GetCustomItem(__state); if (customItem != null) { __instance.UnequipItem(customItem, triggerEquipEffects); } __instance.SetCustomItem(__state, item); if (__instance.IsItemEquiped(item)) { item.m_equipped = true; __result = true; } __instance.SetupEquipment(); } } } [HarmonyPatch(typeof(Humanoid), "UnequipItem")] public static class Humanoid_UnequipItem_CustomItem { [HarmonyPriority(800)] private static void Postfix(Humanoid __instance, ItemData item) { if (item != null) { int customItemIndex = GetCustomItemIndex(item); if (customItemIndex != -1) { __instance.SetCustomItem(customItemIndex, null); __instance.SetupEquipment(); } } } } [HarmonyPatch(typeof(Humanoid), "UnequipAllItems")] public static class Humanoid_UnequipAllItems_CustomItem { [HarmonyPriority(800)] private static void Postfix(Humanoid __instance) { if (IsValidPlayer(__instance)) { CollectionExtensions.Do<ItemData>((IEnumerable<ItemData>)GetEquippedItemsArray(), (Action<ItemData>)delegate(ItemData item) { __instance.UnequipItem(item, false); }); } } } [HarmonyPatch(typeof(Humanoid), "IsItemEquiped")] private static class Humanoid_IsItemEquiped_CustomItem { private static void Postfix(Humanoid __instance, ItemData item, ref bool __result) { if (IsValidPlayer(__instance)) { __result = __result || IsItemEquipped(item); } } } [HarmonyPatch(typeof(Player), "UnequipDeathDropItems")] private static class Player_UnequipDeathDropItems_CustomItem { private static void Prefix(Player __instance) { if (!IsValidPlayer((Humanoid)(object)__instance)) { return; } bool flag = false; for (int i = 0; i < SlotsAmount; i++) { ItemData item = GetItem(i); if (item != null) { item.m_equipped = false; ((Humanoid)(object)__instance).SetCustomItem(i, null); flag = true; } } if (flag) { ((Humanoid)__instance).SetupEquipment(); } } } [HarmonyPatch(typeof(Player), "GetEquipmentEitrRegenModifier")] private static class Player_GetEquipmentEitrRegenModifier_CustomItem { private static void Postfix(Player __instance, ref float __result) { if (IsValidPlayer((Humanoid)(object)__instance)) { __result += GetEquippedItems().Sum((ItemData item) => item.m_shared.m_eitrRegenModifier); } } } [HarmonyPatch(typeof(Humanoid), "UpdateEquipment")] private static class Humanoid_UpdateEquipment_CustomItemDurabilityDrain { private static void Postfix(Humanoid __instance, float dt) { if (IsValidPlayer(__instance)) { CollectionExtensions.DoIf<ItemData>((IEnumerable<ItemData>)GetEquippedItemsArray(), (Func<ItemData, bool>)((ItemData item) => item.m_shared.m_useDurability), (Action<ItemData>)delegate(ItemData item) { __instance.DrainEquipedItemDurability(item, dt); }); } } } [HarmonyPatch(typeof(Player), "ApplyArmorDamageMods")] private static class Player_ApplyArmorDamageMods_CustomItem { private static void Postfix(Player __instance, ref DamageModifiers mods) { //IL_003a: Unknown result type (might be due to invalid IL or missing references) if (IsValidPlayer((Humanoid)(object)__instance)) { CollectionExtensions.Do<List<DamageModPair>>(from item in GetEquippedItems() select item.m_shared.m_damageModifiers, (Action<List<DamageModPair>>)((DamageModifiers)(object)mods).Apply); } } } [HarmonyPatch(typeof(Player), "UpdateModifiers")] private static class Player_UpdateModifiers_CustomItem { private static void Postfix(Player __instance) { if (!IsValidPlayer((Humanoid)(object)__instance) || Player.s_equipmentModifierSourceFields == null) { return; } int i; for (i = 0; i < __instance.m_equipmentModifierValues.Length; i++) { CollectionExtensions.Do<ItemData>(GetEquippedItems(), (Action<ItemData>)delegate(ItemData item) { __instance.m_equipmentModifierValues[i] += (float)Player.s_equipmentModifierSourceFields[i].GetValue(item.m_shared); }); } } } [HarmonyPatch(typeof(Player), "OnInventoryChanged")] private static class Player_OnInventoryChanged_ValidateCustomItemSlots { private static void Postfix(Player __instance) { if (!IsValidPlayer((Humanoid)(object)__instance) || __instance.m_isLoading) { return; } bool flag = false; for (int i = 0; i < SlotsAmount; i++) { ItemData item = GetItem(i); if (item != null && !((Humanoid)Player.m_localPlayer).GetInventory().ContainsItem(item)) { ((Humanoid)(object)__instance).SetCustomItem(i, null); flag = true; } } if (flag) { ((Humanoid)__instance).SetupEquipment(); } } } [HarmonyPatch(typeof(Humanoid), "GetSetCount")] private static class Humanoid_GetSetCount_CustomItem { private static void Postfix(Humanoid __instance, string setName, ref int __result) { if (IsValidPlayer(__instance)) { __result += GetEquippedItems().Count((ItemData item) => item.m_shared.m_setName == setName); } } } } private static readonly List<ItemData> tempItems = new List<ItemData>(); private static readonly HashSet<StatusEffect> tempEffects = new HashSet<StatusEffect>(); public static int SlotsAmount => 8; public static ItemData GetItem(int index) { return ((Humanoid)(object)Player.m_localPlayer)?.GetCustomItem(index); } public static bool IsItemEquipped(ItemData item) { return GetCustomItemIndex(item) != -1; } public static int GetSlotForItem(ItemData item) { int result = -1; for (int i = 0; i < UserDefinedSlot.userDefinedSlots.Length; i++) { UserDefinedSlot userDefinedSlot = UserDefinedSlot.userDefinedSlots[i]; if (userDefinedSlot != null && userDefinedSlot.slotEnabled.Value && userDefinedSlot.isActive() && userDefinedSlot.itemIsValid(item)) { if (GetItem(i) == null) { return i; } result = i; } } return result; } public static IEnumerable<ItemData> GetEquippedItems() { tempItems.Clear(); for (int i = 0; i < SlotsAmount; i++) { ItemData item = GetItem(i); if (item != null) { tempItems.Add(item); } } return tempItems; } public static ItemData[] GetEquippedItemsArray() { return GetEquippedItems().ToArray(); } public static int GetCustomItemIndex(ItemData item) { if (item == null) { return -1; } for (int i = 0; i < SlotsAmount; i++) { ItemData item2 = GetItem(i); if (item2 != null && item2 == item) { return i; } } return -1; } public static bool IsValidPlayer(Humanoid human) { return (Object)(object)human != (Object)null && (Object)(object)human == (Object)(object)Player.m_localPlayer; } } } namespace ExtraSlotsCustomSlots.AdventureBackpacksCustomSlot { [Serializable] public class HumanoidAdventureBackpack { public ItemData backpack; } public static class HumanoidExtension { private static readonly ConditionalWeakTable<Humanoid, HumanoidAdventureBackpack> data = new ConditionalWeakTable<Humanoid, HumanoidAdventureBackpack>(); public static HumanoidAdventureBackpack GetBackpackData(this Humanoid humanoid) { return data.GetOrCreateValue(humanoid); } public static ItemData GetAdventureBackpack(this Humanoid humanoid) { return humanoid.GetBackpackData().backpack; } public static ItemData SetAdventureBackpack(this Humanoid humanoid, ItemData item) { return humanoid.GetBackpackData().backpack = item; } } [Serializable] public class VisEquipmentAdventureBackpack { public string m_backpackItem = ""; public List<GameObject> m_backpackItemInstances; public int m_currentbackpackItemHash = 0; public static readonly int s_backpackItem = StringExtensionMethods.GetStableHashCode("AdventureBackpackItem"); } public static class VisEquipmentExtension { [HarmonyPatch(typeof(VisEquipment), "UpdateEquipmentVisuals")] public static class VisEquipment_UpdateEquipmentVisuals_CustomItemType { private static void Prefix(VisEquipment __instance) { if (!AdventureBackpacksSlot.IsActive) { return; } int hash = 0; ZDO zDO = __instance.m_nview.GetZDO(); if (zDO != null) { hash = zDO.GetInt(VisEquipmentAdventureBackpack.s_backpackItem, 0); } else { VisEquipmentAdventureBackpack backpackData = __instance.GetBackpackData(); if (!string.IsNullOrEmpty(backpackData.m_backpackItem)) { hash = StringExtensionMethods.GetStableHashCode(backpackData.m_backpackItem); } } if (__instance.SetBackpackEquipped(hash)) { __instance.UpdateLodgroup(); } } } [HarmonyPatch(typeof(Humanoid), "SetupVisEquipment")] public static class Humanoid_SetupVisEquipment_CustomItemType { private static void Postfix(Humanoid __instance, VisEquipment visEq) { if (AdventureBackpacksSlot.IsActive) { ItemData adventureBackpack = __instance.GetAdventureBackpack(); visEq.SetBackpackItem((adventureBackpack != null && (Object)(object)adventureBackpack.m_dropPrefab != (Object)null) ? ((Object)adventureBackpack.m_dropPrefab).name : ""); } } } private static readonly ConditionalWeakTable<VisEquipment, VisEquipmentAdventureBackpack> data = new ConditionalWeakTable<VisEquipment, VisEquipmentAdventureBackpack>(); public static VisEquipmentAdventureBackpack GetBackpackData(this VisEquipment visEquipment) { return data.GetOrCreateValue(visEquipment); } public static void SetBackpackItem(this VisEquipment visEquipment, string name) { VisEquipmentAdventureBackpack backpackData = visEquipment.GetBackpackData(); if (!(backpackData.m_backpackItem == name)) { backpackData.m_backpackItem = name; if (visEquipment.m_nview.GetZDO() != null && visEquipment.m_nview.IsOwner()) { visEquipment.m_nview.GetZDO().Set(VisEquipmentAdventureBackpack.s_backpackItem, (!string.IsNullOrEmpty(name)) ? StringExtensionMethods.GetStableHashCode(name) : 0, false); } } } public static bool SetBackpackEquipped(this VisEquipment visEquipment, int hash) { VisEquipmentAdventureBackpack backpackData = visEquipment.GetBackpackData(); if (backpackData.m_currentbackpackItemHash == hash) { return false; } if (backpackData.m_backpackItemInstances != null) { foreach (GameObject backpackItemInstance in backpackData.m_backpackItemInstances) { if (Object.op_Implicit((Object)(object)visEquipment.m_lodGroup)) { Utils.RemoveFromLodgroup(visEquipment.m_lodGroup, backpackItemInstance); } Object.Destroy((Object)(object)backpackItemInstance); } backpackData.m_backpackItemInstances = null; } backpackData.m_currentbackpackItemHash = hash; if (hash != 0) { backpackData.m_backpackItemInstances = visEquipment.AttachArmor(hash, -1); CustomItemType.ReorderBones?.Invoke(visEquipment, hash, backpackData.m_backpackItemInstances); } return true; } } public static class CustomItemType { [HarmonyPatch(typeof(Humanoid), "EquipItem")] public static class Humanoid_EquipItem_CustomItemType { [HarmonyPriority(800)] [HarmonyBefore(new string[] { "vapok.mods.adventurebackpacks" })] private static void Postfix(Humanoid __instance, ItemData item, ref bool __result, bool triggerEquipEffects) { if (AdventureBackpacksSlot.IsActive && !__instance.IsItemEquiped(item) && IsBackpack(item)) { if (__instance.GetAdventureBackpack() != null) { __instance.UnequipItem(__instance.GetAdventureBackpack(), triggerEquipEffects); __instance.m_visEquipment.UpdateEquipmentVisuals(); } __instance.SetAdventureBackpack(item); if (__instance.IsItemEquiped(item)) { item.m_equipped = true; __result = true; } __instance.SetupEquipment(); } } } [HarmonyPatch(typeof(Humanoid), "UnequipItem")] public static class Humanoid_UnequipItem_CustomItemTyp