using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Reflection.Emit;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using System.Security.Permissions;
using System.Text;
using System.Text.RegularExpressions;
using BepInEx;
using BepInEx.Configuration;
using HarmonyLib;
using JetBrains.Annotations;
using Jotunn.Utils;
using Microsoft.CodeAnalysis;
using TMPro;
using UnityEngine;
using Zen;
using Zen.Lib;
using Zen.Lib.Config;
using Zen.Lib.Controls;
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyTitle("ZenUseItem")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("ZenUseItem")]
[assembly: AssemblyCopyright("Copyright © 2025")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("e3243d22-4307-4008-ba36-9f326008cde5")]
[assembly: AssemblyFileVersion("0.0.1.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("0.0.1.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
[CompilerGenerated]
[Microsoft.CodeAnalysis.Embedded]
internal sealed class EmbeddedAttribute : Attribute
{
}
}
namespace System.Runtime.CompilerServices
{
[CompilerGenerated]
[Microsoft.CodeAnalysis.Embedded]
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
internal sealed class NullableAttribute : Attribute
{
public readonly byte[] NullableFlags;
public NullableAttribute(byte P_0)
{
NullableFlags = new byte[1] { P_0 };
}
public NullableAttribute(byte[] P_0)
{
NullableFlags = P_0;
}
}
[CompilerGenerated]
[Microsoft.CodeAnalysis.Embedded]
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)]
internal sealed class NullableContextAttribute : Attribute
{
public readonly byte Flag;
public NullableContextAttribute(byte P_0)
{
Flag = P_0;
}
}
[CompilerGenerated]
[Microsoft.CodeAnalysis.Embedded]
[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
internal sealed class RefSafetyRulesAttribute : Attribute
{
public readonly int Version;
public RefSafetyRulesAttribute(int P_0)
{
Version = P_0;
}
}
}
namespace ZenUseItem
{
internal static class Configs
{
public static readonly ConfigEntry<bool> HideHotbarNumbers = Config.Define<bool>(false, "General", "Hotbar - Hide Numbers", true, "Hide the hotbar 1-8 numbers until the modifier key is held down while the player is standing still.\r\nIf the modifier key is \"None\" then this option will simply hide/show the numbers.");
public static readonly ConfigEntry<KeyCode> HotbarModifierKey = Config.Define<KeyCode>(false, "General", "Hotbar - Modifier Key", (KeyCode)304, "In addition to using items directly from your inventory you can also use items from the hotbar keys 1-8.\r\nKeyboard: Hold down this modifier key and press the hotbar number.\r\nGamepad: Hold down the alt interact button while pressing up on D-pad to use a the hotbar item.\r\nAlt interact is either LB, LT, RB, or RT depending on how you have configured your gamepad layout.\r\nNote: If you set this to \"None\" it will revert to vanilla 1-8 hotbar behavior and you will not need to hold a modifier button.\r\nCaution: Without a modifier it's quite easy to attach your hammer to an item stand or launch your sword with a catapult!");
}
[HarmonyPatch]
internal static class HotbarUI
{
private static bool _isShowNumbers;
public static void Init()
{
_isShowNumbers = true;
}
[HarmonyPostfix]
[HarmonyPatch(typeof(InventoryGui), "Hide")]
private static void InventoryGui_Hide()
{
Init();
}
[HarmonyPostfix]
[HarmonyPatch(typeof(HotkeyBar), "ToggleBindingHint")]
private static void HotkeyBar_ToggleBindingHint(bool bShouldEnable)
{
_isShowNumbers = bShouldEnable;
}
[HarmonyPostfix]
[HarmonyPatch(typeof(HotkeyBar), "Update")]
private static void HotkeyBar_Update(HotkeyBar __instance)
{
UpdateHotbarNumbers(__instance);
}
private static void UpdateHotbarNumbers(HotkeyBar hotkeyBar)
{
//IL_000d: Unknown result type (might be due to invalid IL or missing references)
//IL_0096: Unknown result type (might be due to invalid IL or missing references)
if (ZInput.IsGamepadActive())
{
return;
}
if ((int)Configs.HotbarModifierKey.Value == 0)
{
if (_isShowNumbers != !Configs.HideHotbarNumbers.Value)
{
hotkeyBar.ToggleBindingHint(!Configs.HideHotbarNumbers.Value);
}
return;
}
if (!Configs.HideHotbarNumbers.Value)
{
if (!_isShowNumbers)
{
hotkeyBar.ToggleBindingHint(true);
}
return;
}
Player localPlayer = Player.m_localPlayer;
bool flag = localPlayer != null && ((Vector3)(ref ((Character)localPlayer).m_currentVel)).sqrMagnitude < 1f;
bool flag2 = TextInput.IsVisible() || Console.IsVisible() || Chat.instance.IsChatDialogWindowVisible();
bool flag3 = ZInput.GetKey(Configs.HotbarModifierKey.Value, true) && flag && !flag2 && !Minimap.IsOpen();
if (flag3 != _isShowNumbers)
{
Logging<Plugin>.Info((object)$"Show hotbar numbers: {flag3}", 0);
hotkeyBar.ToggleBindingHint(flag3);
}
}
}
[HarmonyPatch]
internal static class HudHoverText
{
private static readonly StringBuilder Sb = new StringBuilder();
private static string Pattern(string p)
{
return StringExt.RegexPattern(p, (Func<string, string>)((string s) => StringExt.GlyphFix(s, true)), true);
}
[HarmonyPostfix]
[HarmonyPatch(typeof(Hud), "UpdateCrosshair")]
private static void Hud_UpdateCrosshair(Hud __instance)
{
TextMeshProUGUI hoverName = __instance.m_hoverName;
if (Object.op_Implicit((Object)(object)hoverName) && !Utility.IsNullOrWhiteSpace(((TMP_Text)hoverName).text))
{
Sb.Clear();
((TMP_Text)hoverName).text = (InventoryGui.IsVisible() ? GetInventoryOpenText(((TMP_Text)hoverName).text) : GetInventoryClosedText(((TMP_Text)hoverName).text));
}
}
private static string GetInventoryClosedText(string text)
{
string pattern = "^" + Pattern(UI.PromptInteract) + " *(.+)$";
Match match = Regex.Match(text, pattern, RegexOptions.Multiline);
string useItemText = (match.Success ? match.Groups[1].Value : string.Empty);
string pattern2 = "^" + Pattern(UI.PromptUseItem) + " *(.+)\n?";
text = Regex.Replace(text, pattern2, delegate(Match m)
{
string value = m.Groups[1].Value;
return (value == useItemText) ? string.Empty : StringExt.GlyphFix(StringExt.Localize(UI.Prompt("$KEY_Inventory") + " " + value + "\n"), true);
}, RegexOptions.Multiline);
return text;
}
private static string GetInventoryOpenText(string text)
{
//IL_0185: Unknown result type (might be due to invalid IL or missing references)
string[] array = text.Split(new char[1] { '\n' });
string value = StringExt.GlyphFix(StringExt.Localize(UI.PromptInteract), true);
string value2 = StringExt.GlyphFix(StringExt.Localize(UI.PromptInteractAlt), true);
string oldValue = StringExt.GlyphFix(StringExt.Localize(UI.PromptUseItem), true);
string[] array2 = array;
foreach (string text2 in array2)
{
if (!text2.StartsWith(value) && !text2.StartsWith(value2))
{
Sb.Append(text2.Replace(oldValue, string.Empty).Trim() + "\n");
}
}
if (InventoryGui.instance.IsContainerOpen())
{
return Sb.ToString();
}
InventoryGrid playerGrid = InventoryGui.instance.m_playerGrid;
Inventory inventory = playerGrid.GetInventory();
Element val = ((playerGrid.m_uiGroup.IsActive && ZInput.IsGamepadActive()) ? playerGrid.GetElement(playerGrid.m_selected.x, playerGrid.m_selected.y, inventory.GetWidth()) : playerGrid.GetHoveredElement());
if (val == null)
{
return Sb.ToString();
}
ItemData itemAt = inventory.GetItemAt(val.m_pos.x, val.m_pos.y);
if (itemAt == null)
{
return Sb.ToString();
}
string arg = (ZInput.IsGamepadActive() ? $"$KEY_{Inputs.Hold} + $KEY_{Inputs.Main}" : UI.Prompt($"$KEY_{Inputs.Hold} + $KEY_{Inputs.Main}"));
string text3 = $"<color={UIColor.White}><size=20>{ItemDataExt.GetName(itemAt)}</size></color>\n{arg} $settings_apply";
Sb.Append("\n");
Sb.Append(StringExt.Localize(text3));
return Sb.ToString();
}
}
internal static class Inputs
{
public static readonly ActionString Hold = ControlInputs.Create((string)null);
public static readonly ActionString Main = ControlInputs.Create((string)null);
public static void Setup()
{
Main.AddButton((GamepadInput)7, false, false, false, 0f, 0f);
Hold.AddButton((GamepadInput)17, false, false, false, 0f, 0f);
Main.AddButton((KeyCode)323, false, false, false, 0f, 0f);
Hold.AddButton((KeyCode)306, false, false, false, 0f, 0f);
}
}
[BepInPlugin("ZenDragon.ZenUseItem", "ZenUseItem", "0.3.2")]
[BepInDependency(/*Could not decode attribute arguments.*/)]
[BepInDependency(/*Could not decode attribute arguments.*/)]
[SynchronizationMode(/*Could not decode attribute arguments.*/)]
[NetworkCompatibility(/*Could not decode attribute arguments.*/)]
public class Plugin : ZenMod<Plugin>
{
public const string PluginName = "ZenUseItem";
public const string PluginVersion = "0.3.2";
public const string PluginGUID = "ZenDragon.ZenUseItem";
protected override void Setup()
{
base.RegisterInputs += Inputs.Setup;
}
protected override void TitleScene(bool isFirstBoot)
{
}
protected override void WorldStart()
{
UseItem.Init();
HotbarUI.Init();
}
protected override void Shutdown()
{
}
}
[HarmonyPatch]
internal static class UseItem
{
[HarmonyPatch(typeof(Player), "UseHotbarItem")]
private static class PlayerUseHotbarItem
{
[UsedImplicitly]
private static void Prefix()
{
_isUsedFromHotbar = true;
}
[UsedImplicitly]
private static void Postfix()
{
_isUsedFromHotbar = false;
}
}
private static bool _isUsedFromHotbar;
private static bool _isItemUsed;
private static bool IsInteractable
{
get
{
Player localPlayer = Player.m_localPlayer;
return Object.op_Implicit((Object)(object)((localPlayer != null) ? HumanoidExt.GetHoverInteractable((Humanoid)(object)localPlayer) : null));
}
}
public static void Init()
{
KeyHint.SetEvent((HintType)4, (Action)UpdateKeyHints);
}
private static void UpdateKeyHints()
{
KeyHint.SetVisible("Drop", ZInput.IsGamepadActive() || !IsInteractable);
}
[HarmonyPrefix]
[HarmonyPatch(typeof(Humanoid), "UseItem")]
private static void Prefix(Humanoid __instance, Inventory inventory, ItemData item, ref bool fromInventoryGui, ref bool __runOriginal)
{
//IL_000d: Unknown result type (might be due to invalid IL or missing references)
//IL_003a: Unknown result type (might be due to invalid IL or missing references)
if (_isUsedFromHotbar)
{
if ((int)Configs.HotbarModifierKey.Value == 0)
{
fromInventoryGui = false;
}
else if (ZInput.IsGamepadActive())
{
fromInventoryGui = !ZInput.GetButton(ActionString.op_Implicit(Inputs.InteractAlt));
}
else
{
fromInventoryGui = !ZInput.GetKey(Configs.HotbarModifierKey.Value, true);
}
}
}
[HarmonyPrefix]
[HarmonyPatch(typeof(InventoryGui), "OnSelectedItem")]
private static void InventoryGui_OnSelectedItem(InventoryGui __instance, InventoryGrid grid, Modifier mod, ItemData item, ref bool __runOriginal)
{
//IL_0009: Unknown result type (might be due to invalid IL or missing references)
//IL_000b: Invalid comparison between Unknown and I4
if (!__instance.IsContainerOpen() && (int)mod == 2 && IsInteractable)
{
__runOriginal = false;
_isItemUsed = true;
((Humanoid)Player.m_localPlayer).UseItem(grid.GetInventory(), item, false);
_isItemUsed = false;
}
}
[HarmonyTranspiler]
[HarmonyPatch(typeof(Humanoid), "UseItem")]
private static IEnumerable<CodeInstruction> HumanoidUseItem_Transpile(IEnumerable<CodeInstruction> codes)
{
//IL_0030: Unknown result type (might be due to invalid IL or missing references)
//IL_0049: Unknown result type (might be due to invalid IL or missing references)
//IL_004f: Expected O, but got Unknown
//IL_005d: Unknown result type (might be due to invalid IL or missing references)
//IL_0063: Expected O, but got Unknown
//IL_0071: Unknown result type (might be due to invalid IL or missing references)
//IL_0077: Expected O, but got Unknown
//IL_0085: Unknown result type (might be due to invalid IL or missing references)
//IL_008b: Expected O, but got Unknown
MethodInfo methodInfo = AccessTools.Method(typeof(Humanoid), "ToggleEquipped", (Type[])null, (Type[])null);
MethodInfo methodInfo2 = AccessTools.Method(typeof(UseItem), "ToggleEquipped_Intercept", (Type[])null, (Type[])null);
return Transpilers.MethodReplacer(new CodeMatcher(codes, (ILGenerator)null).MatchEndForward((CodeMatch[])(object)new CodeMatch[4]
{
new CodeMatch((OpCode?)OpCodes.Ldarg_2, (object)null, (string)null),
new CodeMatch((OpCode?)OpCodes.Ldfld, (object)null, (string)null),
new CodeMatch((OpCode?)OpCodes.Ldfld, (object)null, (string)null),
new CodeMatch((OpCode?)OpCodes.Ldc_I4_2, (object)null, (string)null)
}).ThrowIfInvalid("Unable to match IL").SetInstruction(CodeInstruction.Call(typeof(UseItem), "ConsumableType_Intercept", (Type[])null, (Type[])null))
.InstructionEnumeration(), (MethodBase)methodInfo, (MethodBase)methodInfo2);
}
private static int ConsumableType_Intercept()
{
if (_isItemUsed)
{
return -1;
}
return 2;
}
private static bool ToggleEquipped_Intercept(Humanoid self, ItemData item)
{
if (_isItemUsed)
{
return false;
}
return self.ToggleEquipped(item);
}
}
}