using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using HarmonyLib;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.UI;
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyTitle("SwampKeyBundle")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("FSOS-X R10 EXP")]
[assembly: AssemblyProduct("SwampKeyBundle")]
[assembly: AssemblyCopyright("Copyright © FSOS-X R10 EXP 2026")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("4e3c96f9-75e1-43a1-a13d-36cda88fc6ad")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: AssemblyVersion("1.0.0.0")]
namespace ValheimCryptKeySlotHUD;
[HarmonyPatch(typeof(Door), "Interact")]
public static class DoorInteractKeyInjectionPatch
{
public static void Prefix(Door __instance, Humanoid character, bool hold, bool alt)
{
//IL_0047: Unknown result type (might be due to invalid IL or missing references)
//IL_004d: Expected O, but got Unknown
if ((Object)(object)character != (Object)null && ((Character)character).IsPlayer() && (Object)(object)__instance.m_keyItem != (Object)null && __instance.m_keyItem.m_itemData.m_shared.m_name == "$item_cryptkey")
{
Player val = (Player)character;
if (CryptKeySlotHUDMod.VirtualKeyInventory != null && !((Humanoid)val).GetInventory().ContainsItem(__instance.m_keyItem.m_itemData) && CryptKeySlotHUDMod.VirtualKeyInventory.GetItem("$item_cryptkey", -1, false) != null)
{
((Humanoid)val).GetInventory().AddItem(((Component)__instance.m_keyItem).gameObject, 1);
((MonoBehaviour)val).StartCoroutine(RemoveKeyNextFrame(val));
}
}
}
private static IEnumerator RemoveKeyNextFrame(Player player)
{
yield return null;
if ((Object)(object)player != (Object)null && ((Humanoid)player).GetInventory() != null)
{
ItemData item = ((Humanoid)player).GetInventory().GetItem("$item_cryptkey", -1, false);
if (item != null)
{
((Humanoid)player).GetInventory().RemoveItem(item);
}
}
}
}
[HarmonyPatch(typeof(Door), "GetHoverText")]
public static class DoorHoverTextPatch
{
public static void Postfix(Door __instance, ref string __result)
{
if ((Object)(object)__instance.m_keyItem != (Object)null && __instance.m_keyItem.m_itemData.m_shared.m_name == "$item_cryptkey" && (Object)(object)Player.m_localPlayer != (Object)null && CryptKeySlotHUDMod.VirtualKeyInventory != null && CryptKeySlotHUDMod.VirtualKeyInventory.GetItem("$item_cryptkey", -1, false) != null && (__result.Contains("$piece_dungeon_cryptkey_required") || __result.Contains("Swamp Key") || __result.Contains("Need key")))
{
__result = __instance.m_name + "\n[E] Open";
}
}
}
public class CryptKeyClickComponent : MonoBehaviour, IPointerClickHandler, IEventSystemHandler, IPointerEnterHandler, IPointerExitHandler
{
public void OnPointerEnter(PointerEventData eventData)
{
}
public void OnPointerExit(PointerEventData eventData)
{
}
public void OnPointerClick(PointerEventData eventData)
{
//IL_0020: Unknown result type (might be due to invalid IL or missing references)
//IL_00e5: Unknown result type (might be due to invalid IL or missing references)
//IL_00ff: Unknown result type (might be due to invalid IL or missing references)
//IL_01bd: Unknown result type (might be due to invalid IL or missing references)
Player localPlayer = Player.m_localPlayer;
InventoryGui instance = InventoryGui.instance;
if ((Object)(object)localPlayer == (Object)null || (Object)(object)instance == (Object)null)
{
return;
}
if ((int)eventData.button == 0)
{
FieldInfo field = typeof(InventoryGui).GetField("m_dragItem", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
FieldInfo field2 = typeof(InventoryGui).GetField("m_dragInventory", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
MethodInfo method = typeof(InventoryGui).GetMethod("SetupDragItem", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
if (field == null)
{
field = typeof(InventoryGui).GetField("dragItem", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
}
if (field2 == null)
{
field2 = typeof(InventoryGui).GetField("dragInventory", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
}
if (method == null)
{
method = typeof(InventoryGui).GetMethod("SetDragItem", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
}
ItemData val = ((!(field != null)) ? ((ItemData)null) : ((ItemData)field.GetValue(instance)));
Inventory val2 = ((!(field2 != null)) ? ((Inventory)null) : ((Inventory)field2.GetValue(instance)));
if (val != null)
{
if (val.m_shared.m_name == "$item_cryptkey" && CryptKeySlotHUDMod.VirtualKeyInventory.GetItem("$item_cryptkey", -1, false) == null)
{
GameObject itemPrefab = ObjectDB.instance.GetItemPrefab("CryptKey");
if ((Object)(object)itemPrefab != (Object)null)
{
CryptKeySlotHUDMod.VirtualKeyInventory.AddItem(itemPrefab, 1);
if (val2 != null)
{
if (val.m_stack > 1)
{
val.m_stack--;
}
else
{
val2.RemoveItem(val);
}
}
ClearDragItem(method, instance);
if ((Object)(object)itemPrefab.GetComponent() != (Object)null)
{
itemPrefab.GetComponent().m_itemData.m_shared.m_itemType = (ItemType)1;
}
if ((Object)(object)CryptKeySlotHUDMod.KeyPanel != (Object)null)
{
CryptKeySlotHUDMod.KeyPanel.GetComponent().StartCoroutine(CryptKeySlotHUDMod.FlashGreenGlow());
}
}
}
}
else if (val == null)
{
ItemData item = CryptKeySlotHUDMod.VirtualKeyInventory.GetItem("$item_cryptkey", -1, false);
if (item != null)
{
GameObject itemPrefab2 = ObjectDB.instance.GetItemPrefab("CryptKey");
if ((Object)(object)itemPrefab2 != (Object)null)
{
ItemData val3 = ((Humanoid)localPlayer).PickupPrefab(itemPrefab2, 1, true);
if (val3 != null)
{
CryptKeySlotHUDMod.VirtualKeyInventory.RemoveItem(item);
if (method != null)
{
try
{
method.Invoke(instance, new object[3]
{
val3,
((Humanoid)localPlayer).GetInventory(),
1
});
}
catch
{
method.Invoke(instance, new object[2]
{
val3,
((Humanoid)localPlayer).GetInventory()
});
}
}
}
}
}
}
}
CryptKeySlotHUDMod.UpdateSlotVisuals();
instance.m_playerGrid.UpdateInventory(((Humanoid)localPlayer).GetInventory(), localPlayer, (ItemData)null);
}
private void ClearDragItem(MethodInfo setupDragMethod, InventoryGui gui)
{
if (setupDragMethod != null)
{
try
{
setupDragMethod.Invoke(gui, new object[3] { null, null, 0 });
}
catch
{
setupDragMethod.Invoke(gui, null);
}
}
}
}
[BepInPlugin("EndosCryptKeySlot", "EndosCryptKeySlotMod", "1.0.0")]
public class CryptKeySlotHUDMod : BaseUnityPlugin
{
public static Image GlowIconImage;
public const string ModGUID = "EndosCryptKeySlot";
public const string ModName = "EndosCryptKeySlotMod";
public const string ModVersion = "1.0.0";
private Harmony harmony;
public static GameObject KeyPanel;
public static Text SlotText;
public static Image SlotIconImage;
public static Inventory VirtualKeyInventory;
public static ConfigEntry ConfigPosX;
public static ConfigEntry ConfigPosY;
public static void CreateKeySlotUI(InventoryGui gui)
{
if ((Object)(object)gui != (Object)null && ((Component)gui).gameObject.activeInHierarchy)
{
CryptKeySlotHUDMod cryptKeySlotHUDMod = Object.FindAnyObjectByType();
if ((Object)(object)cryptKeySlotHUDMod != (Object)null)
{
((MonoBehaviour)cryptKeySlotHUDMod).StartCoroutine(DelayedCreateUI(gui));
}
}
}
private static IEnumerator DelayedCreateUI(InventoryGui gui)
{
yield return (object)new WaitForSecondsRealtime(0.15f);
if ((Object)(object)gui == (Object)null || (Object)(object)KeyPanel != (Object)null)
{
yield break;
}
GameObject val = GameObject.Find("ArmorSlots") ?? GameObject.Find("EquipmentAndQuickSlots") ?? GameObject.Find("EquipmentPanel") ?? GameObject.Find("EquipmentGui");
if ((Object)(object)val == (Object)null && (Object)(object)((Component)gui).transform.parent != (Object)null)
{
Transform[] componentsInChildren = ((Component)((Component)gui).transform.parent).GetComponentsInChildren(true);
foreach (Transform val2 in componentsInChildren)
{
if ((((Object)((Component)val2).gameObject).name.Contains("Equipment") || ((Object)((Component)val2).gameObject).name.Contains("ArmorSlots")) && ((Component)val2).gameObject.activeInHierarchy)
{
val = ((Component)val2).gameObject;
break;
}
}
}
Transform val3 = (((Object)(object)val != (Object)null) ? val.transform : ((Component)gui.m_playerGrid).transform.parent);
if ((Object)(object)val3 == (Object)null)
{
yield break;
}
KeyPanel = new GameObject("CryptKeySlotHUD", new Type[4]
{
typeof(RectTransform),
typeof(Image),
typeof(CanvasGroup),
typeof(CryptKeyClickComponent)
});
KeyPanel.transform.SetParent(val3, false);
Image component = KeyPanel.GetComponent();
((Graphic)component).raycastTarget = true;
Sprite val4 = null;
Image[] array = Resources.FindObjectsOfTypeAll();
foreach (Image val5 in array)
{
if ((Object)(object)val5 != (Object)null && (Object)(object)val5.sprite != (Object)null)
{
switch (((Object)val5.sprite).name.ToLower())
{
case "ac_bkg":
case "stat_bkg":
case "bkg":
case "damage_bkg":
case "armor_bkg":
break;
default:
continue;
}
val4 = val5.sprite;
((Graphic)component).material = ((Graphic)val5).material;
((Graphic)component).color = ((Graphic)val5).color;
break;
}
}
if ((Object)(object)val4 == (Object)null)
{
GameObject val6 = GameObject.Find("ac") ?? GameObject.Find("ac_bkg") ?? GameObject.Find("Armor") ?? GameObject.Find("ac_icon");
if ((Object)(object)val6 != (Object)null)
{
Image val7 = val6.GetComponent() ?? val6.GetComponentInChildren(true);
if ((Object)(object)val7 != (Object)null && (Object)(object)val7.sprite != (Object)null)
{
val4 = val7.sprite;
((Graphic)component).material = ((Graphic)val7).material;
((Graphic)component).color = ((Graphic)val7).color;
}
}
}
if ((Object)(object)val4 != (Object)null)
{
component.sprite = val4;
component.type = (Type)0;
((Graphic)component).color = Color.white;
}
else
{
((Graphic)component).color = new Color(0f, 0f, 0f, 0.4f);
}
RectTransform component2 = KeyPanel.GetComponent();
component2.anchorMin = new Vector2(0f, 1f);
component2.anchorMax = new Vector2(0f, 1f);
component2.pivot = new Vector2(0.5f, 0.5f);
component2.sizeDelta = new Vector2(54f, 60f);
UpdateSlotPosition();
GameObject val8 = new GameObject("SlotGlow", new Type[2]
{
typeof(RectTransform),
typeof(Image)
});
val8.transform.SetParent(KeyPanel.transform, false);
GlowIconImage = val8.GetComponent();
((Graphic)GlowIconImage).raycastTarget = false;
GlowIconImage.sprite = component.sprite;
((Graphic)GlowIconImage).material = ((Graphic)component).material;
GlowIconImage.type = (Type)0;
((Graphic)GlowIconImage).color = new Color(0f, 1f, 0.2f, 0f);
RectTransform component3 = val8.GetComponent();
component3.anchorMin = new Vector2(0f, 0f);
component3.anchorMax = new Vector2(1f, 1f);
component3.offsetMin = new Vector2(0f, 0f);
component3.offsetMax = new Vector2(0f, 0f);
GameObject val9 = new GameObject("SlotInside", new Type[2]
{
typeof(RectTransform),
typeof(Image)
});
val9.transform.SetParent(KeyPanel.transform, false);
Image component4 = val9.GetComponent();
((Graphic)component4).raycastTarget = false;
((Graphic)component4).color = new Color(0f, 0f, 0f, 0f);
RectTransform component5 = val9.GetComponent();
component5.anchorMin = new Vector2(0f, 0f);
component5.anchorMax = new Vector2(1f, 1f);
component5.offsetMin = new Vector2(0f, 0f);
component5.offsetMax = new Vector2(0f, 0f);
GameObject val10 = new GameObject("KeyIcon", new Type[2]
{
typeof(RectTransform),
typeof(Image)
});
val10.transform.SetParent(val9.transform, false);
SlotIconImage = val10.GetComponent();
((Graphic)SlotIconImage).raycastTarget = false;
RectTransform component6 = val10.GetComponent();
component6.anchorMin = new Vector2(0.5f, 0.5f);
component6.anchorMax = new Vector2(0.5f, 0.5f);
component6.pivot = new Vector2(0.5f, 0.5f);
component6.sizeDelta = new Vector2(40f, 40f);
component6.anchoredPosition = new Vector2(0f, 4f);
GameObject val11 = new GameObject("KeySlotText", new Type[2]
{
typeof(RectTransform),
typeof(Text)
});
val11.transform.SetParent(val9.transform, false);
SlotText = val11.GetComponent();
((Graphic)SlotText).raycastTarget = false;
Font[] array2 = Resources.FindObjectsOfTypeAll();
foreach (Font val12 in array2)
{
if (((Object)val12).name.Contains("Averia"))
{
SlotText.font = val12;
break;
}
}
if ((Object)(object)SlotText.font == (Object)null)
{
? val13 = SlotText;
Object builtinResource = Resources.GetBuiltinResource(typeof(Font), "Arial.ttf");
((Text)val13).font = (Font)(object)((builtinResource is Font) ? builtinResource : null);
}
SlotText.fontSize = 10;
((Graphic)SlotText).color = new Color(1f, 0.85f, 0.4f, 0.8f);
SlotText.alignment = (TextAnchor)7;
Shadow obj = val11.AddComponent();
obj.effectColor = Color.black;
obj.effectDistance = new Vector2(1f, -1f);
RectTransform component7 = val11.GetComponent();
component7.anchorMin = new Vector2(0f, 0f);
component7.anchorMax = new Vector2(1f, 1f);
component7.offsetMin = new Vector2(0f, 4f);
component7.offsetMax = new Vector2(0f, 0f);
UpdateSlotVisuals();
}
public static IEnumerator FlashGreenGlow()
{
if (!((Object)(object)GlowIconImage == (Object)null))
{
float duration = 0.4f;
float elapsed = 0f;
while (elapsed < duration)
{
elapsed += Time.unscaledDeltaTime;
float num = Mathf.Lerp(0f, 0.75f, elapsed / duration);
((Graphic)GlowIconImage).color = new Color(0.1f, 1f, 0.3f, num);
yield return null;
}
elapsed = 0f;
while (elapsed < duration)
{
elapsed += Time.unscaledDeltaTime;
float num2 = Mathf.Lerp(0.75f, 0f, elapsed / duration);
((Graphic)GlowIconImage).color = new Color(0.1f, 1f, 0.3f, num2);
yield return null;
}
((Graphic)GlowIconImage).color = new Color(0.1f, 1f, 0.3f, 0f);
}
}
private void Awake()
{
//IL_0006: Unknown result type (might be due to invalid IL or missing references)
//IL_0010: Expected O, but got Unknown
//IL_00bd: Unknown result type (might be due to invalid IL or missing references)
//IL_00c7: Expected O, but got Unknown
harmony = new Harmony("EndosCryptKeySlot");
harmony.PatchAll();
ConfigPosX = ((BaseUnityPlugin)this).Config.Bind("Position", "Slot X Position", 160f, "The horizontal position relative to the equipment panel.");
ConfigPosY = ((BaseUnityPlugin)this).Config.Bind("Position", "Slot Y Position", -72f, "The vertical position relative to the equipment panel.");
ConfigPosX.SettingChanged += delegate
{
UpdateSlotPosition();
};
ConfigPosY.SettingChanged += delegate
{
UpdateSlotPosition();
};
VirtualKeyInventory = new Inventory("VirtualCryptKeyInv", (Sprite)null, 1, 1);
Inventory virtualKeyInventory = VirtualKeyInventory;
virtualKeyInventory.m_onChanged = (Action)Delegate.Combine(virtualKeyInventory.m_onChanged, new Action(UpdateSlotVisuals));
((BaseUnityPlugin)this).Logger.LogInfo((object)"=== EndosCryptKeySlot successfully loaded! ===");
}
private void OnDestroy()
{
Harmony obj = harmony;
if (obj != null)
{
obj.UnpatchSelf();
}
}
public static void UpdateSlotPosition()
{
//IL_0036: Unknown result type (might be due to invalid IL or missing references)
if ((Object)(object)KeyPanel != (Object)null)
{
RectTransform component = KeyPanel.GetComponent();
if ((Object)(object)component != (Object)null)
{
component.anchoredPosition = new Vector2(ConfigPosX.Value, ConfigPosY.Value);
}
}
}
public static void UpdateSlotVisuals()
{
//IL_0061: Unknown result type (might be due to invalid IL or missing references)
//IL_011e: Unknown result type (might be due to invalid IL or missing references)
if (VirtualKeyInventory == null || (Object)(object)SlotIconImage == (Object)null)
{
return;
}
ItemData item = VirtualKeyInventory.GetItem("$item_cryptkey", -1, false);
if (item != null && item.m_shared.m_icons != null && item.m_shared.m_icons.Length != 0)
{
SlotIconImage.sprite = item.m_shared.m_icons[0];
((Graphic)SlotIconImage).color = Color.white;
if ((Object)(object)SlotText != (Object)null)
{
SlotText.text = "";
}
return;
}
if ((Object)(object)ObjectDB.instance != (Object)null)
{
GameObject itemPrefab = ObjectDB.instance.GetItemPrefab("CryptKey");
if ((Object)(object)itemPrefab != (Object)null)
{
ItemDrop component = itemPrefab.GetComponent();
if ((Object)(object)component != (Object)null && component.m_itemData.m_shared.m_icons != null && component.m_itemData.m_shared.m_icons.Length != 0)
{
SlotIconImage.sprite = component.m_itemData.m_shared.m_icons[0];
((Graphic)SlotIconImage).color = new Color(0f, 0f, 0f, 0.4f);
}
}
}
if ((Object)(object)SlotText != (Object)null)
{
SlotText.text = "Key";
}
}
public static void EmptySlot()
{
if (VirtualKeyInventory == null)
{
return;
}
foreach (ItemData item in new List(VirtualKeyInventory.GetAllItems()))
{
VirtualKeyInventory.RemoveItem(item);
}
}
}
[HarmonyPatch(typeof(InventoryGui), "Show")]
public static class InventoryGuiShowPatch
{
private static void Postfix(InventoryGui __instance)
{
if ((Object)(object)CryptKeySlotHUDMod.KeyPanel == (Object)null)
{
CryptKeySlotHUDMod.CreateKeySlotUI(__instance);
}
if ((Object)(object)CryptKeySlotHUDMod.KeyPanel != (Object)null)
{
CryptKeySlotHUDMod.KeyPanel.SetActive(true);
CryptKeySlotHUDMod.UpdateSlotPosition();
CryptKeySlotHUDMod.UpdateSlotVisuals();
}
}
}
[HarmonyPatch(typeof(InventoryGui), "Hide")]
public static class InventoryGuiHidePatch
{
private static void Postfix()
{
if ((Object)(object)CryptKeySlotHUDMod.KeyPanel != (Object)null)
{
CryptKeySlotHUDMod.KeyPanel.SetActive(false);
}
}
}
[HarmonyPatch(typeof(Player), "Save")]
public static class PlayerSavePatch
{
public static void Postfix(Player __instance)
{
if (!((Object)(object)__instance != (Object)(object)Player.m_localPlayer))
{
bool flag = CryptKeySlotHUDMod.VirtualKeyInventory.GetItem("$item_cryptkey", -1, false) != null;
__instance.m_customData["cryptkey_slot_has_key"] = (flag ? "1" : "0");
}
}
}
[HarmonyPatch(typeof(Player), "Load")]
public static class PlayerLoadPatch
{
public static void Postfix(Player __instance)
{
if ((Object)(object)__instance != (Object)(object)Player.m_localPlayer)
{
return;
}
CryptKeySlotHUDMod.EmptySlot();
if (__instance.m_customData.TryGetValue("cryptkey_slot_has_key", out var value) && value == "1" && (Object)(object)ObjectDB.instance != (Object)null)
{
GameObject itemPrefab = ObjectDB.instance.GetItemPrefab("CryptKey");
if ((Object)(object)itemPrefab != (Object)null)
{
CryptKeySlotHUDMod.VirtualKeyInventory.AddItem(itemPrefab, 1);
}
}
CryptKeySlotHUDMod.UpdateSlotVisuals();
}
}
[HarmonyPatch(typeof(Player), "OnDeath")]
public static class PlayerCreateTombStonePatch
{
private static void Postfix(Player __instance)
{
if (!((Object)(object)__instance != (Object)(object)Player.m_localPlayer))
{
bool flag = CryptKeySlotHUDMod.VirtualKeyInventory.GetItem("$item_cryptkey", -1, false) != null;
__instance.m_customData["cryptkey_slot_has_key"] = (flag ? "1" : "0");
}
}
}
[HarmonyPatch(typeof(Game), "Logout")]
public static class GameLogoutPatch
{
private static void Prefix()
{
Player localPlayer = Player.m_localPlayer;
if (!((Object)(object)localPlayer == (Object)null) && CryptKeySlotHUDMod.VirtualKeyInventory != null)
{
bool flag = CryptKeySlotHUDMod.VirtualKeyInventory.GetItem("$item_cryptkey", -1, false) != null;
localPlayer.m_customData["cryptkey_slot_has_key"] = (flag ? "1" : "0");
CryptKeySlotHUDMod.EmptySlot();
CryptKeySlotHUDMod.UpdateSlotVisuals();
}
}
}