Please disclose if any significant portion of your mod was created using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of Aicho Dual Hotbar v1.0.0
Aicho_DualHotbar.dll
Decompiled 5 days agousing System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using BepInEx; using BepInEx.Bootstrap; using BepInEx.Configuration; using HarmonyLib; using Microsoft.CodeAnalysis; using TMPro; using UnityEngine; using UnityEngine.Audio; using UnityEngine.Networking; using UnityEngine.UI; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: AssemblyCompany("Aicho_DualHotbar")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyDescription("A second hotbar row for Valheim, swappable with a key.")] [assembly: AssemblyFileVersion("0.7.3.0")] [assembly: AssemblyInformationalVersion("0.7.3")] [assembly: AssemblyProduct("Aicho Dual Hotbar")] [assembly: AssemblyTitle("Aicho_DualHotbar")] [assembly: AssemblyVersion("0.7.3.0")] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [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 AichoDualHotbar { [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInPlugin("aicho.dualhotbar", "Aicho Dual Hotbar", "0.7.3")] public class DualHotbarPlugin : BaseUnityPlugin { public const string PluginGuid = "aicho.dualhotbar"; public const string PluginName = "Aicho Dual Hotbar"; public const string PluginVersion = "0.7.3"; internal const int ExtraRows = 1; internal const string UnlockKey = "aicho_dualhotbar_unlocked"; internal const string MigratedKey = "aicho_dualhotbar_migrated"; internal static ConfigEntry<bool> Enabled; internal static ConfigEntry<KeyboardShortcut> SwapKey; internal static ConfigEntry<int> PurchasePrice; internal static ConfigEntry<string> RequiredGlobalKey; internal static readonly Fixed<float> SeparationGap = new Fixed<float>(20f); internal static readonly Fixed<bool> ShowSecondBarNumbers = new Fixed<bool>(value: true); internal static readonly Fixed<bool> SidePanelsBelowBars = new Fixed<bool>(value: true); internal static readonly Fixed<float> SidePanelsExtraOffset = new Fixed<float>(0f); internal static readonly Fixed<bool> EquipOnSwap = new Fixed<bool>(value: true); internal static readonly Fixed<bool> ProtectFromQuickStack = new Fixed<bool>(value: true); internal static readonly Fixed<bool> RequirePurchase = new Fixed<bool>(value: true); internal static readonly Fixed<bool> SwapSoundEnabled = new Fixed<bool>(value: true); internal static readonly Fixed<float> SwapSoundVolume = new Fixed<float>(0.5f); internal static readonly Fixed<bool> LogKeyPresses = new Fixed<bool>(value: false); internal static float AppliedGap; internal static DualHotbarPlugin Instance; private static readonly KeyCode[] AllKeys = (KeyCode[])Enum.GetValues(typeof(KeyCode)); private static readonly string[] SoundFileNames = new string[3] { "swap.wav", "swap.ogg", "swap.mp3" }; private string _soundFolder; private AudioSource _audio; private AudioClip _externalClip; private AudioClip _embeddedClip; private bool _embeddedTried; private string _clipPath; private DateTime _clipStamp; private bool _loadingClip; private const float MaxVolume = 8f; private const float LimiterKnee = 0.6f; private AudioClip _boostClip; private AudioClip _boostSource; private float _boostGain; internal const string ActiveRowKey = "aicho_dualhotbar_row"; private const string MemoryRowsKey = "aicho_dualhotbar_rowmem"; private const string HoldFlagKey = "aicho_dualhotbar_hold"; internal const string ActiveBarKey = "aicho_dualhotbar_active"; private static readonly MethodInfo ToggleEquippedMethod = AccessTools.Method(typeof(Player), "ToggleEquipped", (Type[])null, (Type[])null); internal static bool BarActive(Player player) { if (Enabled.Value && (Object)(object)player != (Object)null) { if (RequirePurchase.Value) { return ((Humanoid)player).HaveUniqueKey("aicho_dualhotbar_unlocked"); } return true; } return false; } internal static int GetVanillaRows(Player player) { int num = 4; string s = default(string); if (player.TryGetUniqueKeyValue("invrows", ref s) && int.TryParse(s, out var result)) { num = result; } return Mathf.Clamp(num, 0, 9); } internal static void LogWarning(string message) { ((BaseUnityPlugin)Instance).Logger.LogWarning((object)message); } internal static void LogInfo(string message) { ((BaseUnityPlugin)Instance).Logger.LogInfo((object)message); } internal static float CurrentGap() { if (!BarActive(Player.m_localPlayer)) { return 0f; } return Mathf.Max(0f, SeparationGap.Value); } internal static string T(string spanish, string english) { if (Localization.instance == null || !(Localization.instance.GetSelectedLanguage() == "Spanish")) { return english; } return spanish; } internal static void GrantIfAlreadyUsed(Player player, int rows) { if (!RequirePurchase.Value || player.m_customData.ContainsKey("aicho_dualhotbar_migrated")) { return; } player.m_customData["aicho_dualhotbar_migrated"] = "1"; if (((Humanoid)player).HaveUniqueKey("aicho_dualhotbar_unlocked")) { return; } bool flag = player.m_customData.ContainsKey("aicho_dualhotbar_active") || player.m_customData.ContainsKey("aicho_dualhotbar_row"); if (!flag && !Compat.ExtraSlotsOwnsRows) { Inventory inventory = ((Humanoid)player).GetInventory(); foreach (ItemData allItem in inventory.GetAllItems()) { if (allItem.m_gridPos.y >= rows && allItem.m_gridPos.x >= 0 && allItem.m_gridPos.x < inventory.GetWidth()) { flag = true; break; } } } if (flag) { ((Humanoid)player).AddUniqueKey("aicho_dualhotbar_unlocked"); ((BaseUnityPlugin)Instance).Logger.LogInfo((object)"Second hotbar granted: this character already used it before it had to be bought"); } } private void Awake() { //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_007b: Unknown result type (might be due to invalid IL or missing references) //IL_0085: Expected O, but got Unknown //IL_0109: Unknown result type (might be due to invalid IL or missing references) //IL_010e: Unknown result type (might be due to invalid IL or missing references) //IL_0114: Unknown result type (might be due to invalid IL or missing references) //IL_011a: Expected O, but got Unknown //IL_011f: Expected O, but got Unknown Instance = this; Enabled = ((BaseUnityPlugin)this).Config.Bind<bool>("1 - General", "Enabled", true, "Turns the second hotbar row on or off. Needs a restart of the game. Empty the LAST inventory row before turning it off: that row disappears and its items would be dropped on the ground."); SwapKey = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("1 - General", "SwapKey", new KeyboardShortcut((KeyCode)60, Array.Empty<KeyCode>()), "Key that swaps the two hotbar rows. Default is the '<' key."); PurchasePrice = ((BaseUnityPlugin)this).Config.Bind<int>("1 - General", "PurchasePrice", 2000, new ConfigDescription("Price in coins of the second hotbar at Haldor.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 100000), Array.Empty<object>())); RequiredGlobalKey = ((BaseUnityPlugin)this).Config.Bind<string>("1 - General", "RequiredGlobalKey", "defeated_gdking", "World progress needed before Haldor sells it. Default defeated_gdking = The Elder (2nd boss). Other examples: defeated_eikthyr, defeated_bonemass, defeated_dragon (the first sack uses this one), defeated_queen (the second sack). Empty = always available."); IndicatorConfig.Bind(((BaseUnityPlugin)this).Config); ((BaseUnityPlugin)this).Config.SettingChanged += delegate { HotbarIndicator.MarkDirty(); }; _soundFolder = Path.GetDirectoryName(((BaseUnityPlugin)this).Info.Location); RefreshSound(); Compat.Detect(); Harmony val = new Harmony("aicho.dualhotbar"); val.PatchAll(); Compat.PatchExtraSlots(val); Compat.PatchQuickStack(val); ((BaseUnityPlugin)this).Logger.LogInfo((object)"Aicho Dual Hotbar 0.7.3 loaded"); } private string FindSoundFile() { string[] soundFileNames = SoundFileNames; foreach (string path in soundFileNames) { string text = Path.Combine(_soundFolder, path); if (File.Exists(text)) { return text; } } return null; } private void RefreshSound() { if (_loadingClip) { return; } string text = FindSoundFile(); if (text == null) { if (_clipPath != null) { ((BaseUnityPlugin)this).Logger.LogInfo((object)"Swap sound file removed, using the built-in sound"); } SetExternalClip(null); _clipPath = null; GetEmbeddedClip(); } else { DateTime lastWriteTimeUtc = File.GetLastWriteTimeUtc(text); if (!(text == _clipPath) || !(lastWriteTimeUtc == _clipStamp)) { ((MonoBehaviour)this).StartCoroutine(LoadSound(text, lastWriteTimeUtc)); } } } private IEnumerator LoadSound(string path, DateTime stamp) { _loadingClip = true; string text = Path.GetExtension(path).ToLowerInvariant(); AudioType val = (AudioType)((text == ".ogg") ? 14 : ((text == ".mp3") ? 13 : 20)); UnityWebRequest request = UnityWebRequestMultimedia.GetAudioClip(new Uri(path).AbsoluteUri, val); try { yield return request.SendWebRequest(); _clipPath = path; _clipStamp = stamp; if ((int)request.result != 1) { SetExternalClip(null); ((BaseUnityPlugin)this).Logger.LogWarning((object)("Could not load swap sound " + Path.GetFileName(path) + ": " + request.error + "; using the built-in sound")); } else { AudioClip content = DownloadHandlerAudioClip.GetContent(request); if ((Object)(object)content == (Object)null || content.length <= 0f) { SetExternalClip(null); ((BaseUnityPlugin)this).Logger.LogWarning((object)("Swap sound " + Path.GetFileName(path) + " is empty or unreadable; using the built-in sound")); } else { ((Object)content).name = "AichoSwap"; SetExternalClip(content); ((BaseUnityPlugin)this).Logger.LogInfo((object)$"Swap sound loaded: {Path.GetFileName(path)} ({content.length:0.00} s)"); } } } finally { ((IDisposable)request)?.Dispose(); } _loadingClip = false; } private static AudioClip GetSwapClip() { DualHotbarPlugin instance = Instance; if ((Object)(object)instance == (Object)null) { return null; } if (!((Object)(object)instance._externalClip != (Object)null)) { return instance.GetEmbeddedClip(); } return instance._externalClip; } private AudioClip GetEmbeddedClip() { if ((Object)(object)_embeddedClip == (Object)null && !_embeddedTried) { _embeddedTried = true; _embeddedClip = EmbeddedAssets.LoadSwapClip(); if ((Object)(object)_embeddedClip != (Object)null) { ((BaseUnityPlugin)this).Logger.LogInfo((object)$"Swap sound loaded: built-in ({_embeddedClip.length:0.00} s)"); } } return _embeddedClip; } private void SetExternalClip(AudioClip clip) { if ((Object)(object)_externalClip != (Object)null) { Object.Destroy((Object)(object)_externalClip); } _externalClip = clip; } private AudioClip GetBoostedClip(AudioClip source, float gain) { if ((Object)(object)_boostClip != (Object)null && (Object)(object)_boostSource == (Object)(object)source && Mathf.Approximately(_boostGain, gain)) { return _boostClip; } float[] array = new float[source.samples * source.channels]; if (!source.GetData(array, 0)) { return source; } float num = 0.39999998f; for (int i = 0; i < array.Length; i++) { float num2 = array[i] * gain; float num3 = Mathf.Abs(num2); if (num3 > 0.6f) { num2 = Mathf.Sign(num2) * (0.6f + num * (float)Math.Tanh((num3 - 0.6f) / num)); } array[i] = num2; } AudioClip val = AudioClip.Create("AichoSwapBoost", source.samples, source.channels, source.frequency, false); val.SetData(array, 0); if ((Object)(object)_boostClip != (Object)null) { Object.Destroy((Object)(object)_boostClip); } _boostClip = val; _boostSource = source; _boostGain = gain; return val; } private static AudioMixerGroup GetSfxMixerGroup() { AudioMixer val = (((Object)(object)AudioMan.instance != (Object)null) ? AudioMan.instance.m_masterMixer : null); if ((Object)(object)val == (Object)null) { return null; } AudioMixerGroup[] array = val.FindMatchingGroups("SFX"); if (array == null || array.Length == 0) { return null; } return array[0]; } internal static void PlaySwapSound() { DualHotbarPlugin instance = Instance; if ((Object)(object)instance == (Object)null || !SwapSoundEnabled.Value) { return; } instance.RefreshSound(); float num = Mathf.Clamp(SwapSoundVolume.Value, 0f, 8f); AudioClip val = GetSwapClip(); if (!((Object)(object)val == (Object)null) && !(num <= 0f)) { float num2 = Mathf.Min(num, 1f); if (num > 1f) { val = instance.GetBoostedClip(val, num); num2 = 1f; } if ((Object)(object)instance._audio == (Object)null) { instance._audio = ((Component)instance).gameObject.AddComponent<AudioSource>(); instance._audio.playOnAwake = false; instance._audio.spatialBlend = 0f; } if ((Object)(object)instance._audio.outputAudioMixerGroup == (Object)null) { instance._audio.outputAudioMixerGroup = GetSfxMixerGroup(); } instance._audio.PlayOneShot(val, num2); } } private void Update() { //IL_006f: Unknown result type (might be due to invalid IL or missing references) //IL_0074: Unknown result type (might be due to invalid IL or missing references) //IL_0082: Unknown result type (might be due to invalid IL or missing references) //IL_0089: Invalid comparison between Unknown and I4 //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_0056: Expected I4, but got Unknown if (!Enabled.Value) { return; } HotbarIndicator.UpdateFrame(); if (LogKeyPresses.Value && Input.anyKeyDown) { KeyCode[] allKeys = AllKeys; foreach (KeyCode val in allKeys) { if (Input.GetKeyDown(val)) { ((BaseUnityPlugin)this).Logger.LogInfo((object)$"Key pressed: {val} ({(int)val})"); } } } KeyboardShortcut value = SwapKey.Value; bool flag = ((KeyboardShortcut)(ref value)).IsDown(); if (!flag && (int)((KeyboardShortcut)(ref value)).MainKey == 60 && Input.inputString.IndexOf('<') >= 0) { flag = true; } if (flag) { TrySwapBars(); } } private static bool CanSwapNow(Player player) { if ((Object)(object)player == (Object)null || ((Character)player).IsDead()) { return false; } if ((Object)(object)Chat.instance != (Object)null && Chat.instance.HasFocus()) { return false; } if (Console.IsVisible() || TextInput.IsVisible() || Menu.IsVisible()) { return false; } return true; } internal static void TrySwapBars() { Player localPlayer = Player.m_localPlayer; if (!CanSwapNow(localPlayer)) { return; } if (!BarActive(localPlayer)) { ((Character)localPlayer).Message((MessageType)2, T("Aún no tienes la segunda barra. Cómprasela a Haldor.", "You don't have the second hotbar yet. Buy it from Haldor."), 0, (Sprite)null, false); return; } Inventory inventory = ((Humanoid)localPlayer).GetInventory(); if (inventory.GetHeight() >= 2) { int num = ActiveRow(localPlayer); int num2 = 1 - num; int num3 = ReadPlayerInt(localPlayer, "aicho_dualhotbar_rowmem"); List<ItemData> held = null; if (EquipOnSwap.Value) { held = RememberHeldItems(inventory, num); } HotbarTransition.Begin(num, num2); WritePlayerInt(localPlayer, "aicho_dualhotbar_row", num2); if (EquipOnSwap.Value) { WritePlayerInt(localPlayer, "aicho_dualhotbar_rowmem", num3 | (1 << num)); bool arrivingHasMemory = (num3 & (1 << num2)) != 0; SwapHeldItems(localPlayer, inventory, held, num2, arrivingHasMemory); } PlaySwapSound(); } } internal static int ActiveRow(Player player) { if (!BarActive(player)) { return 0; } return Mathf.Clamp(ReadPlayerInt(player, "aicho_dualhotbar_row"), 0, 1); } internal static int ReadPlayerInt(Player player, string key) { if (!player.m_customData.TryGetValue(key, out var value) || !int.TryParse(value, out var result)) { return 0; } return result; } private static void WritePlayerInt(Player player, string key, int value) { player.m_customData[key] = value.ToString(); } private static List<ItemData> RememberHeldItems(Inventory inventory, int row) { List<ItemData> list = new List<ItemData>(); foreach (ItemData allItem in inventory.GetAllItems()) { if (allItem.m_gridPos.y == row && IsHandItem(allItem)) { if (allItem.m_equipped) { allItem.m_customData["aicho_dualhotbar_hold"] = "1"; list.Add(allItem); } else { allItem.m_customData.Remove("aicho_dualhotbar_hold"); } } } return list; } private static bool IsHandItem(ItemData item) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Invalid comparison between Unknown and I4 //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Invalid comparison between Unknown and I4 //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Invalid comparison between Unknown and I4 //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Invalid comparison between Unknown and I4 //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Invalid comparison between Unknown and I4 ItemType itemType = item.m_shared.m_itemType; if ((int)itemType <= 15) { if (itemType - 3 <= 2 || itemType - 14 <= 1) { goto IL_002a; } } else if ((int)itemType == 19 || (int)itemType == 22) { goto IL_002a; } return false; IL_002a: return true; } private static void SwapHeldItems(Player player, Inventory inventory, List<ItemData> held, int arrivingRow, bool arrivingHasMemory) { if (((Character)player).InAttack()) { return; } List<int> list = new List<int>(); foreach (ItemData item in held) { ((Humanoid)player).UnequipItem(item, true); if (!list.Contains(item.m_gridPos.x)) { list.Add(item.m_gridPos.x); } } list.Sort(); List<ItemData> list2 = new List<ItemData>(); for (int i = 0; i < inventory.GetWidth(); i++) { ItemData itemAt = inventory.GetItemAt(i, arrivingRow); if (itemAt != null && IsHandItem(itemAt)) { bool flag = itemAt.m_customData.ContainsKey("aicho_dualhotbar_hold"); if (arrivingHasMemory ? flag : list.Contains(i)) { list2.Add(itemAt); } itemAt.m_customData.Remove("aicho_dualhotbar_hold"); } } foreach (ItemData item2 in list2) { if (!((Humanoid)player).IsItemEquiped(item2)) { ToggleEquippedMethod.Invoke(player, new object[1] { item2 }); } } } } [HarmonyPatch(typeof(Player), "SetInventorySize")] internal static class PlayerSetInventorySizePatch { private static bool Prefix(Player __instance, int rows) { //IL_00a0: Unknown result type (might be due to invalid IL or missing references) //IL_00b0: Unknown result type (might be due to invalid IL or missing references) //IL_00bc: Unknown result type (might be due to invalid IL or missing references) if (!DualHotbarPlugin.Enabled.Value || (Object)(object)__instance != (Object)(object)Player.m_localPlayer) { return true; } if (Compat.ExtraSlotsOwnsRows) { return true; } rows = Mathf.Clamp(rows, 0, 9); DualHotbarPlugin.GrantIfAlreadyUsed(__instance, rows); bool flag = DualHotbarPlugin.BarActive(__instance); int num = rows + (flag ? 1 : 0); ((Humanoid)__instance).GetInventory().SetHeight(num); __instance.AddUniqueKeyValue("invrows", rows.ToString()); float num2 = (DualHotbarPlugin.AppliedGap = (flag ? Mathf.Max(0f, DualHotbarPlugin.SeparationGap.Value) : 0f)); InventoryGui instance = InventoryGui.instance; instance.SetInventorySize(num); instance.m_player.sizeDelta = new Vector2(instance.m_player.sizeDelta.x, instance.m_player.sizeDelta.y + num2); ((Humanoid)__instance).DropInvalidItems(); return false; } } [HarmonyPatch(typeof(Player), "OnSpawned")] internal static class PlayerOnSpawnedPatch { private static void Postfix(Player __instance) { if (!DualHotbarPlugin.Enabled.Value || (Object)(object)__instance != (Object)(object)Player.m_localPlayer) { return; } int vanillaRows = DualHotbarPlugin.GetVanillaRows(__instance); bool flag = DualHotbarPlugin.BarActive(__instance); DualHotbarPlugin.GrantIfAlreadyUsed(__instance, vanillaRows); bool flag2 = DualHotbarPlugin.BarActive(__instance); if (Compat.ExtraSlotsOwnsRows) { if (flag2 && !flag) { __instance.SetInventorySize(vanillaRows); } } else { int num = vanillaRows + (flag2 ? 1 : 0); if (((Humanoid)__instance).GetInventory().GetHeight() != num) { __instance.SetInventorySize(vanillaRows); } } SidePanels.Refresh(__instance); } } [HarmonyPatch(typeof(InventoryGrid), "UpdateGui")] internal static class InventoryGridLayoutPatch { private static readonly FieldRef<InventoryGrid, List<InventoryElement>> ElementsRef = AccessTools.FieldRefAccess<InventoryGrid, List<InventoryElement>>("m_elements"); private const float SecondBarNumberAlpha = 0.5f; private static void Postfix(InventoryGrid __instance) { //IL_00e8: Unknown result type (might be due to invalid IL or missing references) //IL_00ed: Unknown result type (might be due to invalid IL or missing references) //IL_00ef: Unknown result type (might be due to invalid IL or missing references) //IL_0101: Unknown result type (might be due to invalid IL or missing references) //IL_010a: Unknown result type (might be due to invalid IL or missing references) if (!DualHotbarPlugin.BarActive(Player.m_localPlayer)) { return; } InventoryGui instance = InventoryGui.instance; if ((Object)(object)instance == (Object)null || (Object)(object)__instance != (Object)(object)instance.m_playerGrid) { return; } Inventory inventory = __instance.GetInventory(); if (inventory == null) { return; } int width = inventory.GetWidth(); int height = inventory.GetHeight(); if (width <= 0 || height <= 2) { return; } bool extraSlotsOwnsRows = Compat.ExtraSlotsOwnsRows; int num = (extraSlotsOwnsRows ? Compat.PlayerRows(height) : height); List<InventoryElement> list = ElementsRef.Invoke(__instance); float elementSpace = __instance.m_elementSpace; float num2 = (extraSlotsOwnsRows ? DualHotbarPlugin.CurrentGap() : DualHotbarPlugin.AppliedGap); for (int i = 0; i < list.Count; i++) { int num3 = i / width; int col = i - num3 * width; InventoryElement val = list[i]; RectTransform val2 = (RectTransform)((num3 < num) ? /*isinst with value type is only supported in some contexts*/: null); if ((Object)(object)val2 != (Object)null) { float num4 = (float)(-num3) * elementSpace - ((num3 >= 2) ? num2 : 0f); Vector2 anchoredPosition = val2.anchoredPosition; if (!Mathf.Approximately(anchoredPosition.y, num4)) { val2.anchoredPosition = new Vector2(anchoredPosition.x, num4); } } if (num3 == 1) { ApplySecondBarLabel(list, val, col); } } if (!extraSlotsOwnsRows) { __instance.m_gridRoot.SetSizeWithCurrentAnchors((Axis)1, (float)height * elementSpace + num2); } } private static void ApplySecondBarLabel(List<InventoryElement> elements, InventoryElement element, int col) { //IL_006b: Unknown result type (might be due to invalid IL or missing references) //IL_0070: Unknown result type (might be due to invalid IL or missing references) //IL_00ca: Unknown result type (might be due to invalid IL or missing references) //IL_00b7: Unknown result type (might be due to invalid IL or missing references) //IL_00bc: Unknown result type (might be due to invalid IL or missing references) Transform val = ((Component)element).transform.Find("binding"); TMP_Text val2 = (((Object)(object)val != (Object)null) ? ((Component)val).GetComponent<TMP_Text>() : null); if ((Object)(object)val2 == (Object)null) { return; } if (!DualHotbarPlugin.ShowSecondBarNumbers.Value) { ((Behaviour)val2).enabled = false; return; } ((Behaviour)val2).enabled = true; string text = (col + 1).ToString(); if (val2.text != text) { val2.text = text; } Color color = Color.white; Transform val3 = ((col < elements.Count) ? ((Component)elements[col]).transform.Find("binding") : null); TMP_Text val4 = (((Object)(object)val3 != (Object)null) ? ((Component)val3).GetComponent<TMP_Text>() : null); if ((Object)(object)val4 != (Object)null) { color = ((Graphic)val4).color; } color.a = 0.5f; ((Graphic)val2).color = color; } } internal static class Compat { internal const string ExtraSlotsGuid = "shudnal.ExtraSlots"; internal const string QuickStackGuid = "goldenrevolver.quick_stack_store"; internal static bool ExtraSlotsOwnsRows; internal static bool ExtraSlotsPresent; internal static bool QuickStackPresent; private static Func<Player> s_currentPlayer; private static Func<int> s_playerRows; private static FieldInfo[] s_backgroundFields; private static FieldInfo s_fixContainer; private static Action<Humanoid> s_bumpHotbarRevision; private static bool s_bumpResolved; internal static void Detect() { ExtraSlotsPresent = Chainloader.PluginInfos.ContainsKey("shudnal.ExtraSlots"); QuickStackPresent = Chainloader.PluginInfos.ContainsKey("goldenrevolver.quick_stack_store"); DualHotbarPlugin.LogInfo(Chainloader.PluginInfos.ContainsKey("shudnal.ExtraSlots") ? "Extra Slots detected: the second hotbar row is added through its extra rows" : "Extra Slots not installed"); if (QuickStackPresent) { DualHotbarPlugin.LogInfo("Quick Stack Store detected: the second bar is shielded from its actions"); } } internal static void PatchExtraSlots(Harmony harmony) { //IL_009e: Unknown result type (might be due to invalid IL or missing references) //IL_00ab: Expected O, but got Unknown //IL_0197: Unknown result type (might be due to invalid IL or missing references) //IL_01a4: Expected O, but got Unknown if (!Chainloader.PluginInfos.ContainsKey("shudnal.ExtraSlots")) { return; } try { Type type = AccessTools.TypeByName("ExtraSlots.Slots"); MethodInfo methodInfo = ((type != null) ? AccessTools.Method(type, "GetExtraRows", (Type[])null, (Type[])null) : null); MethodInfo methodInfo2 = ((type != null) ? AccessTools.PropertyGetter(type, "CurrentPlayer") : null); if (methodInfo == null) { DualHotbarPlugin.LogWarning("Extra Slots is installed but its row count method was not found; the second hotbar will use row 2 of the inventory without adding a row"); return; } if (methodInfo2 != null) { s_currentPlayer = (Func<Player>)Delegate.CreateDelegate(typeof(Func<Player>), methodInfo2); } harmony.Patch((MethodBase)methodInfo, (HarmonyMethod)null, new HarmonyMethod(typeof(Compat), "ExtraRowsPostfix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); ExtraSlotsOwnsRows = true; DualHotbarPlugin.LogInfo("Extra Slots: second hotbar row patched into its extra rows"); MethodInfo methodInfo3 = AccessTools.PropertyGetter(type, "InventoryHeightPlayer"); if (methodInfo3 != null) { s_playerRows = (Func<int>)Delegate.CreateDelegate(typeof(Func<int>), methodInfo3); } Type type2 = AccessTools.TypeByName("ExtraSlots.EquipmentPanel"); MethodInfo methodInfo4 = ((type2 != null) ? AccessTools.Method(type2, "UpdateEquipmentBackground", (Type[])null, (Type[])null) : null); if (methodInfo4 != null) { s_backgroundFields = new FieldInfo[3] { AccessTools.Field(type2, "inventoryBackground"), AccessTools.Field(type2, "inventoryDarken"), AccessTools.Field(type2, "inventorySelectedFrame") }; Type type3 = AccessTools.TypeByName("ExtraSlots.ExtraSlots"); s_fixContainer = ((type3 != null) ? AccessTools.Field(type3, "fixContainerPosition") : null); harmony.Patch((MethodBase)methodInfo4, (HarmonyMethod)null, new HarmonyMethod(typeof(Compat), "BackgroundPostfix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); } else { DualHotbarPlugin.LogWarning("Extra Slots panel background method not found; the gap between the bars and the inventory will not extend its panel"); } } catch (Exception ex) { DualHotbarPlugin.LogWarning("Could not integrate with Extra Slots (" + ex.Message + "); the second hotbar will use row 2 of the inventory without adding a row"); } } internal static void RequestHotbarRefresh(Player player) { if (!ExtraSlotsPresent || (Object)(object)player == (Object)null) { return; } if (!s_bumpResolved) { s_bumpResolved = true; try { Type type = AccessTools.TypeByName("ExtraSlots.HotBars.QuickBars"); Type type2 = ((type != null) ? AccessTools.Inner(type, "HotkeyBarRefreshGate") : null); MethodInfo methodInfo = ((type2 != null) ? AccessTools.Method(type2, "BumpRevision", (Type[])null, (Type[])null) : null); if (methodInfo != null) { s_bumpHotbarRevision = (Action<Humanoid>)Delegate.CreateDelegate(typeof(Action<Humanoid>), methodInfo); } else { DualHotbarPlugin.LogWarning("Extra Slots hotbar refresh method not found; the bar change may show up to a second late"); } } catch (Exception ex) { DualHotbarPlugin.LogWarning("Could not hook the Extra Slots hotbar refresh (" + ex.Message + ")"); } } s_bumpHotbarRevision?.Invoke((Humanoid)(object)player); } internal static int PlayerRows(int fallback) { if (s_playerRows == null) { return fallback; } return s_playerRows(); } private static void BackgroundPostfix() { //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_003f: 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_009f: Unknown result type (might be due to invalid IL or missing references) //IL_00ab: Unknown result type (might be due to invalid IL or missing references) //IL_0120: Unknown result type (might be due to invalid IL or missing references) //IL_0125: Unknown result type (might be due to invalid IL or missing references) //IL_0139: Unknown result type (might be due to invalid IL or missing references) //IL_0145: Unknown result type (might be due to invalid IL or missing references) //IL_0152: Unknown result type (might be due to invalid IL or missing references) //IL_0157: Unknown result type (might be due to invalid IL or missing references) //IL_0162: Unknown result type (might be due to invalid IL or missing references) float num = DualHotbarPlugin.CurrentGap(); if (num <= 0f || s_backgroundFields == null) { return; } InventoryGui instance = InventoryGui.instance; if ((Object)(object)instance == (Object)null || (Object)(object)instance.m_player == (Object)null) { return; } Rect rect = instance.m_player.rect; float height = ((Rect)(ref rect)).height; if (height < 1f) { return; } float num2 = num / height; FieldInfo[] array = s_backgroundFields; foreach (FieldInfo fieldInfo in array) { RectTransform val = (RectTransform)((fieldInfo != null) ? /*isinst with value type is only supported in some contexts*/: null); if ((Object)(object)val != (Object)null) { val.anchorMin = new Vector2(val.anchorMin.x, val.anchorMin.y - num2); } } bool flag = true; if (s_fixContainer != null) { object? value = s_fixContainer.GetValue(null); ConfigEntryBase val2 = (ConfigEntryBase)((value is ConfigEntryBase) ? value : null); if (val2 != null && val2.BoxedValue is bool flag2) { flag = flag2; } } RectTransform container = instance.m_container; if (flag && (Object)(object)container != (Object)null) { rect = container.rect; if (((Rect)(ref rect)).height > 1f) { float x = container.pivot.x; float y = container.pivot.y; rect = container.rect; container.pivot = new Vector2(x, y + num / ((Rect)(ref rect)).height); } } } private static void ExtraRowsPostfix(ref int __result) { if (DualHotbarPlugin.BarActive((s_currentPlayer != null) ? s_currentPlayer() : Player.m_localPlayer)) { __result++; } } internal static void PatchQuickStack(Harmony harmony) { if (!QuickStackPresent) { return; } try { QuickStackShield.Install(harmony); } catch (Exception ex) { DualHotbarPlugin.LogWarning("Could not shield the second bar from Quick Stack Store: " + ex.Message); } } } internal static class EmbeddedAssets { internal const string SwapSound = "swap.wav"; internal const string ShopIcon = "second_bar.png"; internal static byte[] Read(string name) { using Stream stream = typeof(EmbeddedAssets).Assembly.GetManifestResourceStream(name); if (stream == null) { return null; } byte[] array = new byte[stream.Length]; int num; for (int i = 0; i < array.Length; i += num) { num = stream.Read(array, i, array.Length - i); if (num <= 0) { break; } } return array; } internal static AudioClip LoadSwapClip() { byte[] array = Read("swap.wav"); if (array == null) { DualHotbarPlugin.LogWarning("The built-in swap sound is missing from the DLL"); return null; } if (!WavDecoder.TryDecode(array, out var result, out var error)) { DualHotbarPlugin.LogWarning("Could not read the built-in swap sound: " + error); return null; } AudioClip obj = AudioClip.Create("AichoSwap", result.Samples.Length / result.Channels, result.Channels, result.Frequency, false); obj.SetData(result.Samples, 0); return obj; } } [HarmonyPatch(typeof(HotkeyBar), "UpdateIcons")] internal static class HotkeyBarIndicatorPatch { private static void Postfix(HotkeyBar __instance, Player player) { if (((Object)__instance).name != "HotKeyBar") { HotbarIndicator.RemoveClone(__instance); } else { HotbarTransition.Reapply(__instance); } } } internal static class HotbarIndicator { private struct FontChoice { public TMP_FontAsset Font; public bool IsBoldAsset; } private sealed class KeyCap { public Image Box; public TextMeshProUGUI Text; } private const float RoundBorder = 64f; private static readonly Dictionary<string, string> OsFonts = new Dictionary<string, string> { { "Arial", "Arial" }, { "SegoeUI", "Segoe UI" }, { "Verdana", "Verdana" }, { "Tahoma", "Tahoma" }, { "Calibri", "Calibri" } }; private static GameObject s_root; private static RectTransform s_rootRect; private static RectTransform s_keysRect; private static readonly Image[] s_boxes = (Image[])(object)new Image[2]; private static readonly Image[] s_dots = (Image[])(object)new Image[2]; private static readonly List<KeyCap> s_caps = new List<KeyCap>(); private static readonly Dictionary<string, FontChoice> s_fonts = new Dictionary<string, FontChoice>(); private static Sprite s_round; private static Sprite s_frameSprite; private static TMP_FontAsset s_fallbackFont; private static float s_canvasPpu = 100f; private static bool s_failed; private static bool s_dirty = true; private static int s_lastCount = -1; private static int s_lastActive = -1; private static float s_lastY; private static KeyboardShortcut s_lastShortcut; private static bool s_hasShortcut; private static readonly FieldInfo ElementsField = AccessTools.Field(typeof(HotkeyBar), "m_elements"); private static FieldInfo s_elementGoField; internal const string MainBarName = "HotKeyBar"; private const string RootName = "AichoDualBarIndicator"; private static HotkeyBar s_mainBar; private static readonly HashSet<int> s_cleanedBars = new HashSet<int>(); private static readonly List<RectTransform> s_rectBuffer = new List<RectTransform>(); internal static void MarkDirty() { s_dirty = true; } internal static void UpdateFrame() { Player localPlayer = Player.m_localPlayer; if ((Object)(object)localPlayer == (Object)null || (Object)(object)Hud.instance == (Object)null) { return; } if ((Object)(object)s_mainBar == (Object)null) { Transform val = (((Object)(object)Hud.instance.m_rootObject != (Object)null) ? Hud.instance.m_rootObject.transform.Find("HotKeyBar") : null); s_mainBar = (((Object)(object)val != (Object)null) ? ((Component)val).GetComponent<HotkeyBar>() : null); if ((Object)(object)s_mainBar == (Object)null) { return; } } HotbarTransition.Tick(s_mainBar, localPlayer); Refresh(s_mainBar, localPlayer); } internal static void RemoveClone(HotkeyBar bar) { if (s_cleanedBars.Add(((Object)bar).GetInstanceID())) { Transform val = ((Component)bar).transform.Find("AichoDualBarIndicator"); if ((Object)(object)val != (Object)null) { Object.Destroy((Object)(object)((Component)val).gameObject); } } } internal unsafe static void Refresh(HotkeyBar bar, Player player) { //IL_00f1: Unknown result type (might be due to invalid IL or missing references) //IL_00f6: Unknown result type (might be due to invalid IL or missing references) //IL_0120: Unknown result type (might be due to invalid IL or missing references) //IL_0126: Unknown result type (might be due to invalid IL or missing references) //IL_0127: Unknown result type (might be due to invalid IL or missing references) //IL_0109: Unknown result type (might be due to invalid IL or missing references) if (s_failed) { return; } try { if ((!IndicatorConfig.ShowSquares.Value && !IndicatorConfig.ShowKey.Value) || !((Object)(object)player != (Object)null) || ((Character)player).IsDead() || !DualHotbarPlugin.BarActive(player)) { if ((Object)(object)s_root != (Object)null && s_root.activeSelf) { s_root.SetActive(false); } return; } if ((Object)(object)s_root == (Object)null || (Object)(object)s_root.transform.parent != (Object)(object)((Component)bar).transform) { Build(bar); s_dirty = true; } if (!s_root.activeSelf) { s_root.SetActive(true); } bool flag = IndicatorConfig.ShowKey.Value && !ZInput.IsGamepadActive(); if (((Component)s_keysRect).gameObject.activeSelf != flag) { ((Component)s_keysRect).gameObject.SetActive(flag); } KeyboardShortcut value = DualHotbarPlugin.SwapKey.Value; bool flag2 = false; if (s_dirty || !s_hasShortcut || !((object)(*(KeyboardShortcut*)(&value))/*cast due to .constrained prefix*/).Equals((object?)s_lastShortcut)) { ApplyStyle(value); s_lastShortcut = value; s_hasShortcut = true; s_dirty = false; s_lastActive = -1; flag2 = true; } IList list = ElementsField.GetValue(bar) as IList; int num = list?.Count ?? 0; if (flag2 || num != s_lastCount) { Layout(list, num); s_lastCount = num; } int num2 = HotbarTransition.DisplayedRow(DualHotbarPlugin.ActiveRow(player)); if (num2 != s_lastActive) { ((Behaviour)s_dots[0]).enabled = num2 == 0; ((Behaviour)s_dots[1]).enabled = num2 == 1; s_lastActive = num2; } } catch (Exception ex) { s_failed = true; DualHotbarPlugin.LogWarning("Hotbar indicator disabled after an error: " + ex); } } private static void Build(HotkeyBar bar) { //IL_00d8: Unknown result type (might be due to invalid IL or missing references) //IL_00e2: Expected O, but got Unknown //IL_00ec: Unknown result type (might be due to invalid IL or missing references) //IL_00f6: Expected O, but got Unknown //IL_0116: Unknown result type (might be due to invalid IL or missing references) //IL_0188: Unknown result type (might be due to invalid IL or missing references) //IL_018f: Unknown result type (might be due to invalid IL or missing references) //IL_0191: Unknown result type (might be due to invalid IL or missing references) //IL_0192: Unknown result type (might be due to invalid IL or missing references) //IL_0199: Unknown result type (might be due to invalid IL or missing references) //IL_01d2: Unknown result type (might be due to invalid IL or missing references) //IL_01dc: Unknown result type (might be due to invalid IL or missing references) //IL_01e6: Expected O, but got Unknown //IL_0211: Unknown result type (might be due to invalid IL or missing references) //IL_0218: Unknown result type (might be due to invalid IL or missing references) //IL_022e: Unknown result type (might be due to invalid IL or missing references) //IL_023d: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)s_root != (Object)null) { Object.Destroy((Object)(object)s_root); } s_caps.Clear(); s_lastCount = -1; s_lastActive = -1; s_hasShortcut = false; Canvas val = ((Component)bar).GetComponentInParent<Canvas>(); if ((Object)(object)val != (Object)null) { val = val.rootCanvas; } s_canvasPpu = (((Object)(object)val != (Object)null) ? val.referencePixelsPerUnit : 100f); if ((Object)(object)s_round == (Object)null) { s_round = MakeRoundedSprite(256, 64); } TMP_Text componentInChildren = ((Component)bar).GetComponentInChildren<TMP_Text>(true); s_fallbackFont = (((Object)(object)componentInChildren != (Object)null) ? componentInChildren.font : (((Object)(object)Hud.instance != (Object)null) ? ((TMP_Text)Hud.instance.m_hoverName).font : null)); s_root = new GameObject("AichoDualBarIndicator", new Type[1] { typeof(RectTransform) }); s_rootRect = (RectTransform)s_root.transform; ((Transform)s_rootRect).SetParent(((Component)bar).transform, false); s_rootRect.pivot = new Vector2(0f, 0.5f); Vector2 val3 = default(Vector2); Vector2 val4 = default(Vector2); for (int i = 0; i < 2; i++) { s_boxes[i] = MakeImage("BarSquare" + (i + 1), s_rootRect); Image val2 = MakeImage("ActiveSquare", ((Graphic)s_boxes[i]).rectTransform); RectTransform rectTransform = ((Graphic)val2).rectTransform; RectTransform rectTransform2 = ((Graphic)val2).rectTransform; RectTransform rectTransform3 = ((Graphic)val2).rectTransform; ((Vector2)(ref val3))..ctor(0.5f, 0.5f); rectTransform3.pivot = val3; val4 = (rectTransform.anchorMin = (rectTransform2.anchorMax = val3)); ((Behaviour)val2).enabled = false; s_dots[i] = val2; } s_keysRect = (RectTransform)new GameObject("Keys", new Type[1] { typeof(RectTransform) }).transform; ((Transform)s_keysRect).SetParent((Transform)(object)s_rootRect, false); RectTransform obj = s_keysRect; RectTransform obj2 = s_keysRect; ((Vector2)(ref val4))..ctor(0f, 0.5f); obj2.anchorMax = val4; obj.anchorMin = val4; s_keysRect.pivot = new Vector2(0f, 0.5f); s_keysRect.sizeDelta = Vector2.zero; DualHotbarPlugin.LogInfo($"Hotbar indicator built (canvas reference PPU {s_canvasPpu})"); } private static Image MakeImage(string name, RectTransform parent) { //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_005d: Unknown result type (might be due to invalid IL or missing references) //IL_0063: Unknown result type (might be due to invalid IL or missing references) //IL_0064: Unknown result type (might be due to invalid IL or missing references) //IL_0065: Unknown result type (might be due to invalid IL or missing references) //IL_006b: Unknown result type (might be due to invalid IL or missing references) GameObject val = new GameObject(name, new Type[1] { typeof(RectTransform) }); val.transform.SetParent((Transform)(object)parent, false); Image obj = val.AddComponent<Image>(); obj.sprite = s_round; obj.type = (Type)1; ((Graphic)obj).raycastTarget = false; RectTransform rectTransform = ((Graphic)obj).rectTransform; Vector2 val2 = default(Vector2); ((Vector2)(ref val2))..ctor(0f, 0.5f); rectTransform.pivot = val2; Vector2 anchorMin = (rectTransform.anchorMax = val2); rectTransform.anchorMin = anchorMin; return obj; } private static KeyCap CapAt(int index) { //IL_0044: 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_005b: Unknown result type (might be due to invalid IL or missing references) //IL_0062: Unknown result type (might be due to invalid IL or missing references) //IL_00af: Unknown result type (might be due to invalid IL or missing references) //IL_00b9: Unknown result type (might be due to invalid IL or missing references) while (s_caps.Count <= index) { Image val = MakeImage("Key" + s_caps.Count, s_keysRect); GameObject val2 = new GameObject("KeyText", new Type[1] { typeof(RectTransform) }); val2.transform.SetParent((Transform)(object)((Graphic)val).rectTransform, false); val2.SetActive(false); TextMeshProUGUI val3 = val2.AddComponent<TextMeshProUGUI>(); if ((Object)(object)s_fallbackFont != (Object)null) { ((TMP_Text)val3).font = s_fallbackFont; } ((TMP_Text)val3).alignment = (TextAlignmentOptions)514; ((TMP_Text)val3).enableWordWrapping = false; ((TMP_Text)val3).overflowMode = (TextOverflowModes)0; ((TMP_Text)val3).richText = false; ((Graphic)val3).raycastTarget = false; RectTransform rectTransform = ((TMP_Text)val3).rectTransform; rectTransform.anchorMin = Vector2.zero; rectTransform.anchorMax = Vector2.one; val2.SetActive(true); s_caps.Add(new KeyCap { Box = val, Text = val3 }); } return s_caps[index]; } private static void ApplyStyle(KeyboardShortcut shortcut) { //IL_0033: 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_0061: Unknown result type (might be due to invalid IL or missing references) //IL_0099: Unknown result type (might be due to invalid IL or missing references) //IL_00c7: Unknown result type (might be due to invalid IL or missing references) //IL_00e0: Unknown result type (might be due to invalid IL or missing references) //IL_0121: Unknown result type (might be due to invalid IL or missing references) //IL_0145: Unknown result type (might be due to invalid IL or missing references) //IL_0155: Unknown result type (might be due to invalid IL or missing references) //IL_01f4: Unknown result type (might be due to invalid IL or missing references) //IL_01fe: Unknown result type (might be due to invalid IL or missing references) float value = IndicatorConfig.SquareSize.Value; float value2 = IndicatorConfig.SquareGap.Value; float num = (value + value2) * 0.5f; s_rootRect.sizeDelta = new Vector2(0f, value * 2f + value2); Sprite val = MakeFrameSprite(value, IndicatorConfig.SquareFrameThickness.Value, IndicatorConfig.SquareRoundness.Value, IndicatorConfig.SquareColor.Value, IndicatorConfig.SquareFillColor.Value); for (int i = 0; i < 2; i++) { Image obj = s_boxes[i]; ((Component)obj).gameObject.SetActive(IndicatorConfig.ShowSquares.Value); ((Graphic)obj).rectTransform.sizeDelta = new Vector2(value, value); ((Graphic)obj).rectTransform.anchoredPosition = new Vector2(IndicatorConfig.SquareOffsetX.Value, ((i == 0) ? num : (0f - num)) + IndicatorConfig.SquareOffsetY.Value); obj.type = (Type)0; obj.sprite = val; ((Graphic)obj).color = Color.white; StyleOutline(obj, IndicatorConfig.SquareOutlineOpacity.Value, IndicatorConfig.SquareOutlineThickness.Value); float value3 = IndicatorConfig.MarkerSize.Value; Image obj2 = s_dots[i]; ((Graphic)obj2).rectTransform.sizeDelta = new Vector2(value3, value3); ((Graphic)obj2).rectTransform.anchoredPosition = new Vector2(IndicatorConfig.MarkerOffsetX.Value, IndicatorConfig.MarkerOffsetY.Value); ((Graphic)obj2).color = IndicatorConfig.MarkerColor.Value; SetCorner(obj2, value3, IndicatorConfig.MarkerRoundness.Value); } if ((Object)(object)s_frameSprite != (Object)null && (Object)(object)s_frameSprite != (Object)(object)val) { Object.Destroy((Object)(object)s_frameSprite.texture); Object.Destroy((Object)(object)s_frameSprite); } s_frameSprite = val; float num2 = (IndicatorConfig.ShowSquares.Value ? (value + IndicatorConfig.GapSquaresToKey.Value) : 0f); s_keysRect.anchoredPosition = new Vector2(num2 + IndicatorConfig.KeyOffsetX.Value, IndicatorConfig.KeyOffsetY.Value); RebuildKeys(shortcut); } private static Sprite MakeFrameSprite(float sizeUnits, float thicknessUnits, float roundness, Color frame, Color fill) { //IL_021e: Unknown result type (might be due to invalid IL or missing references) //IL_0223: Unknown result type (might be due to invalid IL or missing references) //IL_022a: Unknown result type (might be due to invalid IL or missing references) //IL_0231: Unknown result type (might be due to invalid IL or missing references) //IL_0238: Unknown result type (might be due to invalid IL or missing references) //IL_0253: Unknown result type (might be due to invalid IL or missing references) //IL_0262: Unknown result type (might be due to invalid IL or missing references) //IL_0271: Expected O, but got Unknown //IL_00ff: Unknown result type (might be due to invalid IL or missing references) //IL_010a: Unknown result type (might be due to invalid IL or missing references) //IL_0169: Unknown result type (might be due to invalid IL or missing references) //IL_0172: Unknown result type (might be due to invalid IL or missing references) //IL_0182: Unknown result type (might be due to invalid IL or missing references) //IL_018b: Unknown result type (might be due to invalid IL or missing references) //IL_019b: Unknown result type (might be due to invalid IL or missing references) //IL_01a4: Unknown result type (might be due to invalid IL or missing references) //IL_01e4: Unknown result type (might be due to invalid IL or missing references) //IL_01e9: Unknown result type (might be due to invalid IL or missing references) //IL_0132: Unknown result type (might be due to invalid IL or missing references) //IL_013f: Unknown result type (might be due to invalid IL or missing references) //IL_014c: 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_015f: Unknown result type (might be due to invalid IL or missing references) float num = 64f; float num2 = Mathf.Clamp01(roundness) * 0.5f * 128f; float num3 = Mathf.Clamp(thicknessUnits / Mathf.Max(0.01f, sizeUnits), 0f, 0.5f) * 128f; Color32[] array = (Color32[])(object)new Color32[16384]; for (int i = 0; i < 128; i++) { for (int j = 0; j < 128; j++) { float num4 = (float)j + 0.5f - num; float num5 = (float)i + 0.5f - num; float num6 = Mathf.Abs(num4) - (num - num2); float num7 = Mathf.Abs(num5) - (num - num2); float num8 = Mathf.Sqrt(Mathf.Max(num6, 0f) * Mathf.Max(num6, 0f) + Mathf.Max(num7, 0f) * Mathf.Max(num7, 0f)) + Mathf.Min(Mathf.Max(num6, num7), 0f) - num2; float num9 = Mathf.Clamp01(0.5f - num8); float num10 = Mathf.Clamp01(0.5f - (num8 + num3)); float num11 = Mathf.Clamp01(num9 - num10); float num12 = frame.a * num11; float num13 = fill.a * num10; float num14 = num12 + num13; if (num14 <= 0.0001f) { array[i * 128 + j] = new Color32((byte)(frame.r * 255f), (byte)(frame.g * 255f), (byte)(frame.b * 255f), (byte)0); continue; } float num15 = (frame.r * num12 + fill.r * num13) / num14; float num16 = (frame.g * num12 + fill.g * num13) / num14; float num17 = (frame.b * num12 + fill.b * num13) / num14; array[i * 128 + j] = new Color32((byte)(num15 * 255f), (byte)(num16 * 255f), (byte)(num17 * 255f), (byte)(num14 * 255f)); } } Texture2D val = new Texture2D(128, 128, (TextureFormat)4, true) { wrapMode = (TextureWrapMode)1, filterMode = (FilterMode)2 }; val.SetPixels32(array); val.Apply(true); return Sprite.Create(val, new Rect(0f, 0f, 128f, 128f), new Vector2(0.5f, 0.5f), 100f); } private static void RebuildKeys(KeyboardShortcut shortcut) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0025: 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) //IL_00c6: Unknown result type (might be due to invalid IL or missing references) //IL_00fa: Unknown result type (might be due to invalid IL or missing references) //IL_011f: Unknown result type (might be due to invalid IL or missing references) //IL_013d: Unknown result type (might be due to invalid IL or missing references) //IL_0167: Unknown result type (might be due to invalid IL or missing references) //IL_0183: Unknown result type (might be due to invalid IL or missing references) //IL_0198: Unknown result type (might be due to invalid IL or missing references) List<string> list = Tokens(shortcut); FontChoice font = GetFont(); FontStyles fontStyle = (FontStyles)((IndicatorConfig.TextBold.Value && !font.IsBoldAsset) ? 1 : 0); float value = IndicatorConfig.KeyHeight.Value; float num = 0f; for (int i = 0; i < s_caps.Count || i < list.Count; i++) { if (i >= list.Count) { ((Component)s_caps[i].Box).gameObject.SetActive(false); continue; } KeyCap keyCap = CapAt(i); ((Component)keyCap.Box).gameObject.SetActive(true); TextMeshProUGUI text = keyCap.Text; if ((Object)(object)font.Font != (Object)null) { ((TMP_Text)text).font = font.Font; } ((TMP_Text)text).fontStyle = fontStyle; ((TMP_Text)text).fontSize = IndicatorConfig.TextSize.Value; ((Graphic)text).color = IndicatorConfig.TextColor.Value; ((TMP_Text)text).text = list[i]; ((TMP_Text)text).rectTransform.offsetMin = new Vector2(IndicatorConfig.TextOffsetX.Value, IndicatorConfig.TextOffsetY.Value); ((TMP_Text)text).rectTransform.offsetMax = new Vector2(IndicatorConfig.TextOffsetX.Value, IndicatorConfig.TextOffsetY.Value); float num2 = Mathf.Max(IndicatorConfig.KeyMinWidth.Value, ((TMP_Text)text).GetPreferredValues(list[i]).x + IndicatorConfig.KeyWidthPadding.Value); ((Graphic)keyCap.Box).rectTransform.sizeDelta = new Vector2(num2, value); ((Graphic)keyCap.Box).rectTransform.anchoredPosition = new Vector2(num, 0f); ((Graphic)keyCap.Box).color = IndicatorConfig.KeyColor.Value; SetCorner(keyCap.Box, value, IndicatorConfig.KeyRoundness.Value); StyleOutline(keyCap.Box, IndicatorConfig.KeyOutlineOpacity.Value, IndicatorConfig.KeyOutlineThickness.Value); num += num2 + IndicatorConfig.KeyGap.Value; } } private static void Layout(IList elements, int count) { //IL_00a4: Unknown result type (might be due to invalid IL or missing references) //IL_00dd: 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_0024: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_005b: Unknown result type (might be due to invalid IL or missing references) //IL_0060: Unknown result type (might be due to invalid IL or missing references) //IL_0064: Unknown result type (might be due to invalid IL or missing references) //IL_006e: Unknown result type (might be due to invalid IL or missing references) float num = 0f; float num2 = s_lastY; RectTransform val = LastElementRect(elements, count); if ((Object)(object)val != (Object)null) { Vector3 localPosition = ((Transform)val).localPosition; Vector3 localScale = ((Transform)val).localScale; float x = localPosition.x; Rect rect = val.rect; num = x + ((Rect)(ref rect)).xMax * Mathf.Abs(localScale.x); float num3 = localPosition.y - HotbarTransition.OffsetY; rect = val.rect; num2 = (s_lastY = num3 + ((Rect)(ref rect)).center.y * Mathf.Abs(localScale.y)); } float num4 = Mathf.Max(0.1f, IndicatorConfig.Scale.Value); ((Transform)s_rootRect).localScale = new Vector3(num4, num4, 1f); ((Transform)s_rootRect).localPosition = new Vector3(num + IndicatorConfig.DistanceFromBar.Value * num4 + IndicatorConfig.OffsetX.Value, num2 + IndicatorConfig.OffsetY.Value, 0f); } internal static List<RectTransform> ElementRects(HotkeyBar bar) { s_rectBuffer.Clear(); if (!(ElementsField.GetValue(bar) is IList list)) { return s_rectBuffer; } for (int i = 0; i < list.Count; i++) { object obj = list[i]; RectTransform item = null; if (obj != null) { if (s_elementGoField == null) { s_elementGoField = AccessTools.Field(obj.GetType(), "m_go"); } GameObject val = (GameObject)((s_elementGoField != null) ? /*isinst with value type is only supported in some contexts*/: null); item = (RectTransform)(((Object)(object)val != (Object)null) ? /*isinst with value type is only supported in some contexts*/: null); } s_rectBuffer.Add(item); } return s_rectBuffer; } private static RectTransform LastElementRect(IList elements, int count) { if (elements == null || count <= 0) { return null; } object obj = elements[count - 1]; if (obj == null) { return null; } if (s_elementGoField == null) { s_elementGoField = AccessTools.Field(obj.GetType(), "m_go"); } GameObject val = (GameObject)((s_elementGoField != null) ? /*isinst with value type is only supported in some contexts*/: null); if (!((Object)(object)val != (Object)null)) { return null; } Transform transform = val.transform; return (RectTransform)(object)((transform is RectTransform) ? transform : null); } private static void StyleOutline(Image image, float opacity, float thickness) { //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_005b: Unknown result type (might be due to invalid IL or missing references) Outline val = ((Component)image).GetComponent<Outline>(); if ((Object)(object)val == (Object)null) { val = ((Component)image).gameObject.AddComponent<Outline>(); ((Shadow)val).useGraphicAlpha = false; } ((Behaviour)val).enabled = opacity > 0.001f && thickness > 0.001f; ((Shadow)val).effectColor = new Color(0f, 0f, 0f, opacity); ((Shadow)val).effectDistance = new Vector2(thickness, 0f - thickness); } private static void SetCorner(Image image, float height, float roundness) { float num = height * 0.5f * Mathf.Clamp01(roundness); float num2 = 100f / Mathf.Max(0.01f, s_canvasPpu); image.pixelsPerUnitMultiplier = 64f / (Mathf.Max(0.5f, num) * num2); } private static FontChoice GetFont() { string value = IndicatorConfig.TextFont.Value; bool value2 = IndicatorConfig.TextBold.Value; string key = value + (value2 ? "|bold" : ""); if (!s_fonts.TryGetValue(key, out var value3)) { value3 = CreateFont(value, value2); s_fonts[key] = value3; } return value3; } private static FontChoice CreateFont(string choice, bool bold) { if (OsFonts.TryGetValue(choice, out var value)) { try { TMP_FontAsset val = null; bool flag = false; if (bold) { val = TMP_FontAsset.CreateFontAsset(value, "Bold", 90); flag = (Object)(object)val != (Object)null; } if ((Object)(object)val == (Object)null) { val = TMP_FontAsset.CreateFontAsset(value, "Regular", 90); } if ((Object)(object)val != (Object)null) { ((Object)val).name = "AichoOS-" + choice + (flag ? "-Bold" : ""); return new FontChoice { Font = val, IsBoldAsset = flag }; } } catch (Exception ex) { DualHotbarPlugin.LogWarning("Could not create the font '" + value + "' for the hotbar indicator: " + ex.Message); } } return new FontChoice { Font = s_fallbackFont, IsBoldAsset = false }; } private static List<string> Tokens(KeyboardShortcut shortcut) { //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_001d: 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) //IL_0048: Unknown result type (might be due to invalid IL or missing references) List<string> list = new List<string>(); foreach (KeyCode modifier in ((KeyboardShortcut)(ref shortcut)).Modifiers) { list.Add(KeyName(modifier)); } if ((int)((KeyboardShortcut)(ref shortcut)).MainKey != 0) { list.Add(KeyName(((KeyboardShortcut)(ref shortcut)).MainKey)); } return list; } private unsafe static string KeyName(KeyCode key) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0003: Invalid comparison between Unknown and I4 //IL_006a: Unknown result type (might be due to invalid IL or missing references) //IL_0070: Invalid comparison between Unknown and I4 //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Invalid comparison between Unknown and I4 //IL_00c8: Unknown result type (might be due to invalid IL or missing references) //IL_00ce: Unknown result type (might be due to invalid IL or missing references) //IL_00f4: Expected I4, but got Unknown //IL_0072: Unknown result type (might be due to invalid IL or missing references) //IL_0075: Unknown result type (might be due to invalid IL or missing references) //IL_0093: Expected I4, but got Unknown //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_004c: Expected I4, but got Unknown //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Invalid comparison between Unknown and I4 //IL_00f4: Unknown result type (might be due to invalid IL or missing references) //IL_00fa: Unknown result type (might be due to invalid IL or missing references) //IL_0114: Expected I4, but got Unknown //IL_0093: Unknown result type (might be due to invalid IL or missing references) //IL_0099: Unknown result type (might be due to invalid IL or missing references) //IL_00c3: Expected I4, but got Unknown //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_0065: Expected I4, but got Unknown //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Invalid comparison between Unknown and I4 if ((int)key <= 62) { if ((int)key <= 32) { if ((int)key == 13) { return "Enter"; } if ((int)key == 32) { return DualHotbarPlugin.T("Espacio", "Space"); } } else { switch (key - 39) { default: switch (key - 59) { case 1: return "<"; case 3: return ">"; case 2: return "="; case 0: return ";"; } break; case 5: return ","; case 7: return "."; case 6: return "-"; case 8: return "/"; case 0: return "'"; case 1: case 2: case 3: case 4: break; } } } else if ((int)key <= 281) { switch (key - 91) { default: switch (key - 273) { case 7: return DualHotbarPlugin.T("RePag", "PgUp"); case 8: return DualHotbarPlugin.T("AvPag", "PgDn"); case 5: return DualHotbarPlugin.T("Inicio", "Home"); case 6: return DualHotbarPlugin.T("Fin", "End"); case 0: return "↑"; case 1: return "↓"; case 3: return "←"; case 2: return "→"; } break; case 1: return "\\"; case 5: return "`"; case 0: return "["; case 2: return "]"; case 3: case 4: break; } } else { switch (key - 301) { default: switch (key - 323) { case 0: return "M1"; case 1: return "M2"; case 2: return "M3"; case 3: return "M4"; case 4: return "M5"; } break; case 2: case 3: return "Shift"; case 4: case 5: return "Ctrl"; case 6: case 7: return "Alt"; case 0: return DualHotbarPlugin.T("Bloq Mayús", "Caps"); case 1: break; } } string text = ((object)(*(KeyCode*)(&key))/*cast due to .constrained prefix*/).ToString(); if (text.StartsWith("Alpha")) { return text.Substring(5); } if (text.StartsWith("Keypad")) { return "Num" + text.Substring(6); } return text; } private static Sprite MakeRoundedSprite(int size, int radius) { //IL_0004: Unknown result type (might be due to invalid IL or missing references) //IL_0009: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Expected O, but got Unknown //IL_00f1: Unknown result type (might be due to invalid IL or missing references) //IL_0100: Unknown result type (might be due to invalid IL or missing references) //IL_0114: Unknown result type (might be due to invalid IL or missing references) //IL_00b4: Unknown result type (might be due to invalid IL or missing references) //IL_00b9: Unknown result type (might be due to invalid IL or missing references) Texture2D val = new Texture2D(size, size, (TextureFormat)4, true) { wrapMode = (TextureWrapMode)1, filterMode = (FilterMode)2 }; Color32[] array = (Color32[])(object)new Color32[size * size]; for (int i = 0; i < size; i++) { for (int j = 0; j < size; j++) { float num = (float)j + 0.5f; float num2 = (float)i + 0.5f; float num3 = Mathf.Clamp(num, (float)radius, (float)(size - radius)); float num4 = Mathf.Clamp(num2, (float)radius, (float)(size - radius)); float num5 = Mathf.Sqrt((num - num3) * (num - num3) + (num2 - num4) * (num2 - num4)); byte b = (byte)Mathf.RoundToInt(Mathf.Clamp01((float)radius - num5 + 0.5f) * 255f); array[i * size + j] = new Color32(byte.MaxValue, byte.MaxValue, byte.MaxValue, b); } } val.SetPixels32(array); val.Apply(true); return Sprite.Create(val, new Rect(0f, 0f, (float)size, (float)size), new Vector2(0.5f, 0.5f), 100f, 0u, (SpriteMeshType)0, new Vector4((float)radius, (float)radius, (float)radius, (float)radius)); } } internal static class HotbarRows { internal static bool Applies(Inventory inventory, out Player player) { player = Player.m_localPlayer; if ((Object)(object)player != (Object)null && inventory == ((Humanoid)player).GetInventory()) { return DualHotbarPlugin.BarActive(player); } return false; } } [HarmonyPatch(typeof(Inventory), "GetBoundItems")] internal static class GetBoundItemsPatch { private static bool Prefix(Inventory __instance, List<ItemData> bound) { if (!HotbarRows.Applies(__instance, out var player)) { return true; } int num = HotbarTransition.DisplayedRow(DualHotbarPlugin.ActiveRow(player)); bound.Clear(); foreach (ItemData allItem in __instance.GetAllItems()) { if (allItem.m_gridPos.y == num) { bound.Add(allItem); } } return false; } } [HarmonyPatch(typeof(Inventory), "GetHotbar")] internal static class GetHotbarPatch { private static bool Prefix(Inventory __instance, bool includeEmpty, ref List<ItemData> __result) { if (!HotbarRows.Applies(__instance, out var player)) { return true; } int row = DualHotbarPlugin.ActiveRow(player); List<ItemData> source = (from item in __instance.GetAllItems() where item.m_gridPos.y == row select item).ToList(); if (!includeEmpty) { __result = source.OrderBy((ItemData item) => item.m_gridPos.x).ToList(); return false; } List<ItemData> list = new List<ItemData>(); for (int num = 0; num < 8; num++) { int column = num; list.Add(((IEnumerable<ItemData>)source).FirstOrDefault((Func<ItemData, bool>)((ItemData item) => item.m_gridPos.x == column))); } __result = list; return false; } } [HarmonyPatch(typeof(Player), "UseHotbarItem")] internal static class UseHotbarItemPatch { private static bool Prefix(Player __instance, int index) { if ((Object)(object)__instance != (Object)(object)Player.m_localPlayer || !DualHotbarPlugin.BarActive(__instance)) { return true; } int num = DualHotbarPlugin.ActiveRow(__instance); if (num == 0) { return true; } ItemData itemAt = ((Humanoid)__instance).GetInventory().GetItemAt(index - 1, num); if (itemAt != null) { ((Humanoid)__instance).UseItem((Inventory)null, itemAt, false); } return false; } } internal static class TransitionConfig { internal static readonly Fixed<string> Style = new Fixed<string>("Slide"); internal static readonly Fixed<float> Duration = new Fixed<float>(0.3f); internal static readonly Fixed<float> SlideDistance = new Fixed<float>(18f); } internal static class HotbarTransition { private enum Phase { Idle, Out, In } private static Phase s_phase = Phase.Idle; private static int s_displayedRow; private static float s_t; private static float s_alpha = 1f; private static float s_offset; private static float s_fromAlpha = 1f; private static float s_fromOffset; private static float s_direction; private static float s_lastTick; internal static float OffsetY => s_offset; private static bool Enabled { get { if (TransitionConfig.Style.Value != "None") { return TransitionConfig.Duration.Value > 0.02f; } return false; } } internal static int DisplayedRow(int actualRow) { if (s_phase != Phase.Out) { return actualRow; } return s_displayedRow; } internal static void Begin(int leavingRow, int arrivingRow) { Compat.RequestHotbarRefresh(Player.m_localPlayer); if (!Enabled) { s_phase = Phase.Idle; s_alpha = 1f; s_offset = 0f; return; } if (s_phase != Phase.Out) { s_displayedRow = leavingRow; } s_direction = ((arrivingRow == 0) ? (-1f) : 1f); s_fromAlpha = s_alpha; s_fromOffset = s_offset; s_phase = Phase.Out; s_t = 0f; s_lastTick = Time.unscaledTime; } internal static void Reapply(HotkeyBar bar) { if (s_phase != Phase.Idle) { Apply(bar); } } internal static void Tick(HotkeyBar bar, Player player) { if (s_phase == Phase.Idle) { return; } Compat.RequestHotbarRefresh(player); float unscaledTime = Time.unscaledTime; if (unscaledTime - s_lastTick > 1f) { Reset(bar); return; } s_lastTick = unscaledTime; float num = Mathf.Max(0.01f, TransitionConfig.Duration.Value * 0.5f); bool flag = TransitionConfig.Style.Value == "Slide"; float value = TransitionConfig.SlideDistance.Value; s_t += Mathf.Min(0.1f, Time.unscaledDeltaTime) / num; float num2 = Ease(Mathf.Clamp01(s_t)); if (s_phase == Phase.Out) { s_alpha = Mathf.Lerp(s_fromAlpha, 0f, num2); s_offset = (flag ? Mathf.Lerp(s_fromOffset, s_direction * value, num2) : 0f); if (s_t >= 1f) { s_phase = Phase.In; s_t = 0f; } } else { s_alpha = num2; s_offset = (flag ? ((0f - s_direction) * value * (1f - num2)) : 0f); if (s_t >= 1f) { s_phase = Phase.Idle; s_alpha = 1f; s_offset = 0f; } } Apply(bar); } private static float Ease(float k) { return k * k * (3f - 2f * k); } private static void Reset(HotkeyBar bar) { s_phase = Phase.Idle; s_alpha = 1f; s_offset = 0f; Apply(bar); } private static void Apply(HotkeyBar bar) { //IL_005d: Unknown result type (might be due to invalid IL or missing references) //IL_0067: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)bar == (Object)null) { return; } List<RectTransform> list = HotbarIndicator.ElementRects(bar); for (int i = 0; i < list.Count; i++) { RectTransform val = list[i]; if (!((Object)(object)val == (Object)null)) { CanvasGroup val2 = ((Component)val).GetComponent<CanvasGroup>(); if ((Object)(object)val2 == (Object)null) { val2 = ((Component)val).gameObject.AddComponent<CanvasGroup>(); } val2.alpha = s_alpha; ((Transform)val).localPosition = new Vector3((float)i * bar.m_elementSpace, s_offset, ((Transform)val).localPosition.z); } } } } internal sealed class Fixed<T> { internal T Value { get; } internal Fixed(T value) { Value = value; } } internal static class IndicatorConfig { internal static ConfigEntry<bool> ShowSquares; internal static ConfigEntry<bool> ShowKey; internal static readonly Fixed<float> Scale = new Fixed<float>(0.587f); internal static readonly Fixed<float> OffsetX = new Fixed<float>(0f); internal static readonly Fixed<float> OffsetY = new Fixed<float>(0f); internal static readonly Fixed<float> DistanceFromBar = new Fixed<float>(16f); internal static readonly Fixed<float> GapSquaresToKey = new Fixed<float>(13.979f); internal static readonly Fixed<float> SquareSize = new Fixed<float>(28.129f); internal static readonly Fixed<float> SquareGap = new Fixed<float>(9.959f); internal static readonly Fixed<float> SquareRoundness = new Fixed<float>(0.443f); internal static readonly Fixed<Color> SquareColor = new Fixed<Color>(new Color(1f, 1f, 1f, 1f)); internal static readonly Fixed<float> SquareFrameThickness = new Fixed<float>(2f); internal static readonly Fixed<Color> SquareFillColor = new Fixed<Color>(new Color(0f, 0f, 0f, 0f)); internal static readonly Fixed<float> SquareOutlineOpacity = new Fixed<float>(0f); internal static readonly Fixed<float> SquareOutlineThickness = new Fixed<float>(0.27f); internal static readonly Fixed<float> SquareOffsetX = new Fixed<float>(0f); internal static readonly Fixed<float> SquareOffsetY = new Fixed<float>(0f); internal static readonly Fixed<float> MarkerSize = new Fixed<float>(14.366f); internal static readonly Fixed<float> MarkerRoundness = new Fixed<float>(0.191f); internal static readonly Fixed<Color> MarkerColor = new Fixed<Color>(new Color(1f, 1f, 0f, 1f)); internal static readonly Fixed<float> MarkerOffsetX = new Fixed<float>(0.3f); internal static readonly Fixed<float> MarkerOffsetY = new Fixed<float>(0.3f); internal static readonly Fixed<float> KeyHeight = new Fixed<float>(31.8f); internal static readonly Fixed<float> KeyMinWidth = new Fixed<float>(38.4f); internal static readonly Fixed<float> KeyWidthPadding = new Fixed<float>(8.98f); internal static readonly Fixed<float> KeyGap = new Fixed<float>(6f); internal static readonly Fixed<float> KeyRoundness = new Fixed<float>(0.536f); internal static readonly Fixed<Color> KeyColor = new Fixed<Color>(new Color(1f, 1f, 1f, 1f)); internal static readonly Fixed<float> KeyOutlineOpacity = new Fixed<float>(0.6f); internal static readonly Fixed<float> KeyOutlineThickness = new Fixed<float>(0f); internal static readonly Fixed<float> KeyOffsetX = new Fixed<float>(0f); internal static readonly Fixed<float> KeyOffsetY = new Fixed<float>(0f); internal static readonly Fixed<float> TextSize = new Fixed<float>(34f); internal static readonly Fixed<Color> TextColor = new Fixed<Color>(new Color(2f / 51f, 2f / 51f, 2f / 51f, 1f)); internal static readonly Fixed<string> TextFont = new Fixed<string>("Arial"); internal static readonly Fixed<bool> TextBold = new Fixed<bool>(value: true); internal static readonly Fixed<float> TextOffsetX = new Fixed<float>(0f); internal static readonly Fixed<float> TextOffsetY = new Fixed<float>(0f); internal static void Bind(ConfigFile file) { ShowSquares = file.Bind<bool>("1 - General", "ShowSquares", true, "Shows the two squares at the end of the hotbar (the one of the active bar has a small square inside)."); ShowKey = file.Bind<bool>("1 - General", "ShowKeyButton", true, "Shows the button with the swap key at the end of the hotbar (always hidden while using a gamepad)."); } } internal static class QuickStackShield { private const string Namespace = "QuickStackStore."; private static readonly List<KeyValuePair<int, ItemData>> s_hidden = new List<KeyValuePair<int, ItemData>>(); private static bool s_hiding; private static readonly MethodInfo InventoryChanged = AccessTools.Method(typeof(Inventory), "Changed", (Type[])null, (Type[])null); internal static void Install(Harmony harmony) { //IL_0148: Unknown result type (might be due to invalid IL or missing references) //IL_0155: Expected O, but got Unknown Type type = AccessTools.TypeByName("QuickStackStore.UserConfig"); Assembly assembly = ((type != null) ? type.Assembly : null); if (assembly == null) { DualHotbarPlugin.LogWarning("Quick Stack Store assembly not found; the second bar is not shielded from it"); return; } int num = 0; num += Wrap(harmony, assembly, "QuickStackModule", "DoQuickStack", "PrefixLocalPlayer"); num += Wrap(harmony, assembly, "RestockModule", "DoRestock", "PrefixLocalPlayer"); num += Wrap(harmony, assembly, "StoreTakeAllModule", "MoveAllItemsInOrder", "PrefixStore"); num += Wrap(harmony, assembly, "SortModule", "SortInternal", "PrefixInventory"); MethodInfo method = null; Type[] types = assembly.GetTypes(); foreach (Type type2 in types) { MethodInfo methodInfo = ((type2.Namespace == "QuickStackStore") ? type2.GetMethod("QuickTrash", BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic) : null); if (methodInfo != null) { method = methodInfo; break; } } num += WrapMethod(harmony, method, "PrefixLocalPlayer"); Type type3 = assembly.GetType("QuickStackStore.SortModule"); MethodInfo methodInfo2 = ((type3 != null) ? AccessTools.Method(type3, "GetAllowedSlots", (Type[])null, (Type[])null) : null); if (methodInfo2 != null) { harmony.Patch((MethodBase)methodInfo2, (HarmonyMethod)null, new HarmonyMethod(typeof(QuickStackShield), "AllowedSlotsPostfix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); num++; } else { DualHotbarPlugin.LogWarning("Quick Stack Store sort slot method not found; Sort may place items in the second bar"); } DualHotbarPlugin.LogInfo($"Quick Stack Store: {num} actions shielded from touching the second bar"); } private static int Wrap(Harmony harmony, Assembly assembly, string typeName, string methodName, string prefixName) { Type type = assembly.GetType("QuickStackStore." + typeName); MethodInfo method = ((type != null) ? AccessTools.Method(type, methodName, (Type[])null, (Type[])null) : null); return WrapMethod(harmony, method, prefixName); } private static int WrapMethod(Harmony harmony, MethodInfo method, string prefixName) { //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_0050: Expected O, but got Unknown //IL_0050: Expected O, but got Unknown if (method == null) { DualHotbarPlugin.LogWarning("Quick Stack Store method for '" + prefixName + "' not found; one action is not shielded"); return 0; } harmony.Patch((MethodBase)method, new HarmonyMethod(typeof(QuickStackShield), prefixName, (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, new HarmonyMethod(typeof(QuickStackShield), "RestoreFinalizer", (Type[])null), (HarmonyMethod)null); return 1; } private static void PrefixLocalPlayer(out bool __state) { __state = Hide(); } private static void PrefixStore(Inventory fromInventory, bool takeAllOverride, out bool __state) { __state = !takeAllOverride && IsPlayerInventory(fromInventory) && Hide(); } private static void PrefixInventory(Inventory inventory, out bool __state) { __state = IsPlayerInventory(inventory) && Hide(); } private static Exception RestoreFinalizer(bool __state, Exception __exception) { if (__state) { Restore(); } return __exception; } private static void AllowedSlotsPostfix(Inventory inventory, ref List<Vector2i> __result) { if (__result != null && IsPlayerInventory(inventory) && DualHotbarPlugin.ProtectFromQuickStack.Value && DualHotbarPlugin.BarActive(Player.m_localPlayer)) { __result.RemoveAll((Vector2i slot) => slot.y == 1); } } private static bool IsPlayerInventory(Inventory inventory) { Player localPlayer = Player.m_localPlayer; if (inventory != null && (Object)(object)localPlayer != (Object)null) { return inventory == ((Humanoid)localPlayer).GetInventory(); } return false; } private static bool Hide() { if (s_hiding || !DualHotbarPlugin.ProtectFromQuickStack.Value) { return false; } Player localPlayer = Player.m_localPlayer; if ((Object)(object)localPlayer == (Object)null || !DualHotbarPlugin.BarActive(localPlayer)) { return false; } List<ItemData> allItems = ((Humanoid)localPlayer).GetInventory().GetAllItems(); s_hidden.Clear(); for (int i = 0; i < allItems.Count; i++) { if (allItems[i].m_gridPos.y == 1) { s_hidden.Add(new KeyValuePair<int, ItemData>(i, allItems[i])); } } if (s_hidden.Count == 0) { return false; } for (int num = s_hidden.Count - 1; num >= 0; num--) { allItems.RemoveAt(s_hidden[num].Key); } s_hiding = true; return true; } private static void Restore() { Player localPlayer = Player.m_localPlayer; Inventory val = (((Object)(object)localPlayer != (Object)null) ? ((Humanoid)localPlayer).GetInventory() : null); if (val != null) { List<ItemData> allItems = val.GetAllItems(); foreach (KeyValuePair<int, ItemData> item in s_hidden) { allItems.Insert(Math.Min(item.Key, allItems.Count), item.Value); } InventoryChanged?.Invoke(val, new object[2] { false, false }); } s_hidden.Clear(); s_hiding = false; } } internal static class SecondBarShop { internal const string HaldorName = "$npc_haldor"; private const string CounterKey = "aicho_dualhotbar_bar"; private static TradeItem s_item; private static Sprite s_icon; private static TradeItem FindSack(Trader trader) { foreach (TradeItem item in trader.m_items) { if (item.m_incrementKey == "invrows") { return item; } } return null; } internal static TradeItem GetItem(Trader trader) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Expected O, but got Unknown //IL_0040: Expected O, but got Unknown if (s_item == null) { s_item = new TradeItem { m_stack = 1, m_buyKey = "aicho_dualhotbar_unlocked", m_incrementKey = "aicho_dualhotbar_bar", m_incrementAmount = 1, m_buyPlayerEffects = new EffectList() }; } TradeItem val = FindSack(trader); if (val != null) { s_item.m_levelUpEffect = val.m_levelUpEffect; if (val.m_buyPlayerEffects != null) { s_item.m_buyPlayerEffects = val.m_buyPlayerEffects; } } s_item.m_price = Mathf.Max(0, DualHotbarPlugin.PurchasePrice.Value); s_item.m_requiredGlobalKey = DualHotbarPlugin.RequiredGlobalKey.Value ?? string.Empty; s_item.m_name = DualHotbarPlugin.T("Segunda barra rápida", "Second Hotbar"); s_item.m_tooltip = DualHotbarPlugin.T("Añade una segunda fila de 8 espacios junto a tu barra rápida. La intercambias con la tecla de cambio de barra, y cada barra recuerda lo que llevabas equipado.", "Adds a second row of 8 slots next to your hotbar. Swap them with the bar swap key; each bar remembers what you had equipped."); s_item.m_icon = GetIcon(); return s_item; } private static Sprite GetIcon() { if ((Object)(object)s_icon == (Object)null) { s_icon = BuildIcon(); } return s_icon; } private static Sprite BuildIcon() { //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Expected O, but got Unknown //IL_0088: Unknown result type (might be due to invalid IL or missing references) //IL_0097: Unknown result type (might be due to invalid IL or missing references) Texture2D val = null; try { byte[] array = EmbeddedAssets.Read("second_bar.png"); if (array != null) { Texture2D val2 = new Texture2D(2, 2, (TextureFormat)4, true); if (ImageConversion.LoadImage(val2, array)) { val2.Apply(true); val = val2; } } } catch (Exception ex) { DualHotbarPlugin.LogWarning("Could not load the built-in shop icon: " + ex.Message); } if ((Object)(object)val == (Object)null) { val = DrawDefaultIcon(); } ((Texture)val).filterMode = (FilterMode)((((Texture)val).mipmapCount <= 1) ? 1 : 2); ((Texture)val).wrapMode = (TextureWrapMode)1; return Sprite.Create(val, new Rect(0f, 0f, (float)((Texture)val).width, (float)((Texture)val).height), new Vector2(0.5f, 0.5f), 100f); } private static Texture2D DrawDefaultIcon() { //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0144: Unknown result type (might be due to invalid IL or missing references) //IL_0149: Unknown result type (might be due to invalid IL or missing references) //IL_0150: Unknown result type (might be due to invalid IL or missing references) //IL_0157: Expected O, but got Unknown //IL_00e5: Unknown result type (might be due to invalid IL or missing references) //IL_0102: Unknown result type (might be due to invalid IL or missing references) //IL_00fe: Unknown result type (might be due to invalid IL or missing references) //IL_0121: Unknown result type (might be due to invalid IL or missing references) //IL_011d: Unknown result type (might be due to invalid IL or missing references) Color32[] array = (Color32[])(object)new Color32[4096]; Color32 val = default(Color32); ((Color32)(ref val))..ctor((byte)0, (byte)0, (byte)0, (byte)0); for (int i = 0; i < array.Length; i++) { array[i] = val; } Color32 color = default(Color32); ((Color32)(ref color))..ctor((byte)38, (byte)24, (byte)14, byte.MaxValue); Color32 val2 = default(Color32); ((Color32)(ref val2))..ctor((byte)222, (byte)170, (byte)70, byte.MaxValue); Color32 val3 = default(Color32); ((Color32)(ref val3))..ctor((byte)250, (byte)214, (byte)120, byte.MaxValue); Color32 val4 = default(Color32); ((Color32)(ref val4))..ctor((byte)150, (byte)98, (byte)52, byte.MaxValue); Color32 val5 = default(Color32); ((Color32)(ref val5))..ctor((byte)188, (byte)132, (byte)78, byte.MaxValue); int num = 61; int num2 = (64 - num) / 2; int[] array2 = new int[2] { 34, 17 }; for (int j = 0; j < 2; j++) { for (int k = 0; k < 4; k++) { int num3 = num2 + k * 16; int num4 = array2[j]; FillRect(array, 64, num3, num4, 13, 13, color); FillRect(array, 64, num3 + 1, num4 + 1, 11, 11, (j == 0) ? val2 : val4); FillRect(array, 64, num3 + 2, num4 + 13 - 4, 9, 2, (j == 0) ? val3 : val5); } } Texture2D val6 = new Texture2D(64, 64, (TextureFormat)4, false); val6.SetPixels32(array); val6.Apply(); return val6; } private static void FillRect(Color32[] pixels, int size, int x, int y, int width, int height, Color32 color) { //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Unknown result type (might be due to invalid IL or missing references) for (int i = y; i < y + height; i++) { for (int j = x; j < x + width; j++) { if (j >= 0 && j < size && i >= 0 && i < size) { pixels[i * size + j] = color; } } } } } [HarmonyPatch(typeof(Trader), "GetAvailableItems")] internal static class TraderAvailableItemsPatch { private static void Postfix(Trader __instance, List<TradeItem> __result) { Player localPlayer = Player.m_localPlayer; if (!((Object)(object)localPlayer == (Object)null) && DualHotbarPlugin.Enabled.Value && DualHotbarPlugin.RequirePurchase.Value && !(__instance.m_name != "$npc_haldor") && !((Humanoid)localPlayer).HaveUniqueKey("aicho_dualhotbar_unlocked")) { string value = DualHotbarPlugin.RequiredGlobalKey.Value; if (string.IsNullOrEmpty(value) || ZoneSystem.instance.GetGlobalKey(value)) { __result.Add(SecondBarShop.GetItem(__instance)); } } } } [HarmonyPatch(typeof(StoreGui), "BuySelectedItem")] internal static class StoreBuyPatch { private static bool s_hadBar; private static void Prefix() { s_hadBar = DualHotbarPlugin.BarActive(Player.m_localPlayer); } private static void Postfix() { Player localPlayer = Player.m_localPlayer; if (!((Object)(object)localPlayer == (Object)null) && !s_hadBar && DualHotbarPlugin.BarActive(localPlayer)) { localPlayer.SetInventorySize(DualHotbarPlugin.GetVanillaRows(localPlayer)); SidePanels.Refresh(localPlayer); ((Character)localPlayer).Message((MessageType)2, DualHotbarPlugin.T("Segunda barra desbloqueada", "Second hotbar unlocked"), 0, (Sprite)null, false); } } } internal static class SidePanels { private static readonly string[] PanelPaths = new string[4] { "Armor", "Weight", "selected_frame/selected (2)", "selected_frame/selected (3)" }; private static InventoryGui s_gui; private static float s_applied; internal static void Refresh(Player player) { //IL_00d9: 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_00ea: Unknown result type (might be due to invalid IL or missing references) InventoryGui instance = InventoryGui.instance; if ((Object)(object)instance == (Object)null || (Object)(object)instance.m_player == (Object)null) { return; } if ((Object)(object)instance != (Object)(object)s_gui) { s_gui = instance; s_applied = 0f; } float num = 0f; if (DualHotbarPlugin.SidePanelsBelowBars.Value && DualHotbarPlugin.BarActive(player)) { float num2 = (((Object)(object)instance.m_playerGrid != (Object)null) ? instance.m_playerGrid.m_elementSpace : 70f); num = 2f * num2 + DualHotbarPlugin.CurrentGap() + DualHotbarPlugin.SidePanelsExtraOffset.Value; } float num3 = num - s_applied; if (Mathf.Approximately(num3, 0f)) { return; } string[] panelPaths = PanelPaths; foreach (string text in panelPaths) { Transform obj = ((Transform)instance.m_player).Find(text); RectTransform val = (RectTransform)(object)((obj is RectTransform) ? obj : null); if ((Object)(object)val != (Object)null) { val.anchoredPosition += new Vector2(0f, 0f - num3); } } s_applied = num; DualHotbarPlugin.LogInfo($"Side panels moved down by {num3:0.#} (total {num:0.#})"); } } internal static class WavDecoder { internal sealed class Result { internal float[] Samples; internal int Channels; internal int Frequency; } internal static bool TryDecode(byte[] file, out Result result, out string error) { result = null; error = null; if (file == null || file.Length < 12 || !HasTag(file, 0, "RIFF") || !HasTag(file, 8, "WAVE")) { error = "not a RIFF/WAVE file"; return false; } int num = 0; int num2 = 0; int num3 = 0; int num4 = 0; int num5 = -1; int num6 = 0; int num7 = 12; while (num7 + 8 <= file.Length) { int num8 = BitConverter.ToInt32(file, num7 + 4); int num9 = num7 + 8; int num10 = file.Length - num9; int num11 = ((num8 < 0 || num8 > num10) ? num10 : num8); if (HasTag(file, num7, "fmt ") && num11 >= 16) { num = BitConverter.ToUInt16(file, num9); num2 = BitConverter.ToUInt16(file, num9 + 2); num3 = BitConverter.ToInt32(file, num9 + 4); num4 = BitConverter.ToUInt16(file, num9 + 14); if (num == 65534 && num11 >= 26) { num = BitConverter.ToUInt16(file, num9 + 24); } } else if (HasTag(file, num7, "data")) { num5 = num9; num6 = num11; break; } num7 = num9 + num11 + (num11 & 1); } if (num2 <= 0 || num3 <= 0 || num5 < 0) { error = "missing format or data chunk"; return false; } bool num12 = num == 1; bool flag = num == 3; if ((!num12 || (num4 != 8 && num4 != 16 && num4 != 24 && num4 != 32)) && (!flag || num4 != 32)) { error = $"unsupported sample format (type {num}, {num4} bit)"; return false; } int num13 = num4 / 8; int num14 = num6 / num13 / num2 * num2; if (num14 <= 0) { error = "no audio data"; return false; } float[] array = new float[num14]; for (int i = 0; i < num14; i++) { int num15 = num5 + i * num13; switch (num4) { case 8: array[i] = (float)(file[num15] - 128) / 128f; break; case 16: array[i] = (float)BitConverter.ToInt16(file, num15) / 32768f; break; case 24: array[i] = (float)(((file[num15] << 8) | (file[num15 + 1] << 16) | (file[num15 + 2] << 24)) >> 8) / 8388608f; break; default: array[i] = (flag ? BitConverter.ToSingle(file, num15) : ((float)BitConverter.ToInt32(file, num15) / 2.1474836E+09f)); break; } } result = new Result { Samples = array, Channels = num2, Frequency = num3 }; return true; } private static bool HasTag(byte[] data, int offset, string tag) { for (int i = 0; i < 4; i++) { if (data[offset + i] != tag[i]) { return false; } } return true; } } }