From 5259d4e60ced86fb219d37a3c14b2d41cdc9c12f Mon Sep 17 00:00:00 2001 From: Tyfon <29051038+tyfon7@users.noreply.github.com> Date: Thu, 26 Sep 2024 15:40:14 -0700 Subject: [PATCH] Wishlist context menu everywhere --- src/GlobalUsings.cs | 2 +- src/Multiselect/MultiSelect.cs | 32 +++++++++ src/Patches/ContextMenuPatches.cs | 112 ++++++++++++++++++++---------- src/Patches/MultiSelectPatches.cs | 8 ++- src/Settings.cs | 12 +++- 5 files changed, 127 insertions(+), 39 deletions(-) diff --git a/src/GlobalUsings.cs b/src/GlobalUsings.cs index 443870f..b80732c 100644 --- a/src/GlobalUsings.cs +++ b/src/GlobalUsings.cs @@ -1,4 +1,4 @@ -// These shouln't change (unless they do) +// These shouldn't change (unless they do) global using GridItemAddress = ItemAddressClass; global using DragItemContext = ItemContextClass; global using InsuranceItem = ItemClass; diff --git a/src/Multiselect/MultiSelect.cs b/src/Multiselect/MultiSelect.cs index 5859374..8637f61 100644 --- a/src/Multiselect/MultiSelect.cs +++ b/src/Multiselect/MultiSelect.cs @@ -419,6 +419,38 @@ public class MultiSelect } } + public static void WishlistAll(ItemUiContext itemUiContext, BaseItemInfoInteractions interactions, bool add, bool allOrNothing) + { + EItemInfoButton interaction = add ? EItemInfoButton.AddToWishlist : EItemInfoButton.RemoveFromWishlist; + if (!allOrNothing || InteractionCount(interaction, itemUiContext) == Count) + { + var taskSerializer = itemUiContext.gameObject.AddComponent(); + taskSerializer.Initialize(ItemContexts.Where(ic => InteractionAvailable(ic, interaction, itemUiContext)), + itemContext => + { + TaskCompletionSource taskSource = new(); + void callback() + { + interactions.RequestRedrawForItem(); + taskSource.Complete(); + } + + if (add) + { + itemUiContext.AddToWishList(itemContext.Item, callback); + } + else + { + itemUiContext.RemoveFromWishList(itemContext.Item, callback); + } + + return taskSource.Task; + }); + + itemUiContext.Tooltip?.Close(); + } + } + private static void ShowSelection(GridItemView itemView) { GameObject selectedMark = itemView.transform.Find("SelectedMark")?.gameObject; diff --git a/src/Patches/ContextMenuPatches.cs b/src/Patches/ContextMenuPatches.cs index 0a4efad..bab1ba7 100644 --- a/src/Patches/ContextMenuPatches.cs +++ b/src/Patches/ContextMenuPatches.cs @@ -4,6 +4,7 @@ using EFT.UI; using EFT.UI.DragAndDrop; using HarmonyLib; using SPT.Reflection.Patching; +using SPT.Reflection.Utils; using System; using System.Collections.Generic; using System.Linq; @@ -47,6 +48,9 @@ public static class ContextMenuPatches new EmptyModSlotMenuRemovePatch().Enable(); new EmptySlotMenuPatch().Enable(); new EmptySlotMenuRemovePatch().Enable(); + + new InventoryWishlistPatch().Enable(); + new TradingWishlistPatch().Enable(); } public class ContextMenuNamesPatch : ModulePatch @@ -64,65 +68,51 @@ public static class ContextMenuPatches return; } + int count = 0; if (caption == EItemInfoButton.Insure.ToString()) { InsuranceCompanyClass insurance = ItemUiContext.Instance.Session.InsuranceCompany; - int count = MultiSelect.ItemContexts.Select(ic => InsuranceItem.FindOrCreate(ic.Item)) + count = MultiSelect.ItemContexts.Select(ic => InsuranceItem.FindOrCreate(ic.Item)) .Where(i => insurance.ItemTypeAvailableForInsurance(i) && !insurance.InsuredItems.Contains(i)) .Count(); - if (count > 0) - { - ____text.text += " (x" + count + ")"; - } } else if (caption == EItemInfoButton.Equip.ToString()) { - int count = MultiSelect.InteractionCount(EItemInfoButton.Equip, ItemUiContext.Instance); - if (count > 0) - { - ____text.text += " (x" + count + ")"; - } + count = MultiSelect.InteractionCount(EItemInfoButton.Equip, ItemUiContext.Instance); } else if (caption == EItemInfoButton.Unequip.ToString()) { - int count = MultiSelect.InteractionCount(EItemInfoButton.Unequip, ItemUiContext.Instance); - if (count > 0) - { - ____text.text += " (x" + count + ")"; - } + count = MultiSelect.InteractionCount(EItemInfoButton.Unequip, ItemUiContext.Instance); } else if (caption == EItemInfoButton.LoadAmmo.ToString()) { - int count = MultiSelect.InteractionCount(EItemInfoButton.LoadAmmo, ItemUiContext.Instance); - if (count > 0) - { - ____text.text += " (x" + count + ")"; - } + count = MultiSelect.InteractionCount(EItemInfoButton.LoadAmmo, ItemUiContext.Instance); } else if (caption == EItemInfoButton.UnloadAmmo.ToString()) { - int count = MultiSelect.InteractionCount(EItemInfoButton.UnloadAmmo, ItemUiContext.Instance); - if (count > 0) - { - ____text.text += " (x" + count + ")"; - } + count = MultiSelect.InteractionCount(EItemInfoButton.UnloadAmmo, ItemUiContext.Instance); } else if (caption == EItemInfoButton.ApplyMagPreset.ToString()) { - int count = MultiSelect.InteractionCount(EItemInfoButton.ApplyMagPreset, ItemUiContext.Instance); - if (count > 0) - { - ____text.text += " (x" + count + ")"; - } + count = MultiSelect.InteractionCount(EItemInfoButton.ApplyMagPreset, ItemUiContext.Instance); } else if (caption == EItemInfoButton.Unpack.ToString()) { - int count = MultiSelect.InteractionCount(EItemInfoButton.Unpack, ItemUiContext.Instance); - if (count > 0) - { - ____text.text += " (x" + count + ")"; - } + count = MultiSelect.InteractionCount(EItemInfoButton.Unpack, ItemUiContext.Instance); + } + else if (caption == EItemInfoButton.AddToWishlist.ToString()) + { + count = MultiSelect.InteractionCount(EItemInfoButton.AddToWishlist, ItemUiContext.Instance); + } + else if (caption == EItemInfoButton.RemoveFromWishlist.ToString()) + { + count = MultiSelect.InteractionCount(EItemInfoButton.RemoveFromWishlist, ItemUiContext.Instance); + } + + if (count > 0) + { + ____text.text += " (x" + count + ")"; } } } @@ -519,7 +509,9 @@ public static class ContextMenuPatches { protected override MethodBase GetTargetMethod() { - return AccessTools.Method(typeof(InteractionButtonsContainer), nameof(InteractionButtonsContainer.SetSubInteractions)).MakeGenericMethod([typeof(InsuranceInteractions.EInsurers)]); + return AccessTools.Method( + typeof(InteractionButtonsContainer), + nameof(InteractionButtonsContainer.SetSubInteractions)).MakeGenericMethod([typeof(InsuranceInteractions.EInsurers)]); } // Existing logic tries to place it on the right, moving to the left if necessary. They didn't do it correctly, so it always goes on the left. @@ -530,6 +522,54 @@ public static class ContextMenuPatches } } + public class InventoryWishlistPatch : ModulePatch + { + protected override MethodBase GetTargetMethod() + { + // R.InventoryActions.Type is only ever referenced by it's child class, which overrides AvailableInteractions + Type type = PatchConstants.EftTypes.First(t => t.BaseType == R.InventoryInteractions.Type); + return AccessTools.DeclaredProperty(type, "AvailableInteractions").GetMethod; + } + + [PatchPostfix] + public static void Postfix(ref IEnumerable __result) + { + if (!Settings.WishlistContextEverywhere.Value) + { + return; + } + + var list = __result.ToList(); + int index = list.IndexOf(EItemInfoButton.Tag); + list.Insert(index, EItemInfoButton.RemoveFromWishlist); + list.Insert(index, EItemInfoButton.AddToWishlist); + __result = list; + } + } + + public class TradingWishlistPatch : ModulePatch + { + protected override MethodBase GetTargetMethod() + { + return AccessTools.DeclaredProperty(R.TradingInteractions.Type, "AvailableInteractions").GetMethod; + } + + [PatchPostfix] + public static void Postfix(ref IEnumerable __result) + { + if (!Settings.WishlistContextEverywhere.Value) + { + return; + } + + var list = __result.ToList(); + int index = list.IndexOf(EItemInfoButton.Tag); + list.Insert(index, EItemInfoButton.RemoveFromWishlist); + list.Insert(index, EItemInfoButton.AddToWishlist); + __result = list; + } + } + private static void PositionContextMenuFlyout(SimpleContextMenuButton button, SimpleContextMenu flyoutMenu) { RectTransform buttonTransform = button.RectTransform(); diff --git a/src/Patches/MultiSelectPatches.cs b/src/Patches/MultiSelectPatches.cs index 961f8f5..7be9306 100644 --- a/src/Patches/MultiSelectPatches.cs +++ b/src/Patches/MultiSelectPatches.cs @@ -315,7 +315,7 @@ public static class MultiSelectPatches } [PatchPrefix] - public static bool Prefix(EItemInfoButton interaction, ItemUiContext ___itemUiContext_1) + public static bool Prefix(BaseItemInfoInteractions __instance, EItemInfoButton interaction, ItemUiContext ___itemUiContext_1) { if (!MultiSelect.Active) { @@ -336,6 +336,12 @@ public static class MultiSelectPatches case EItemInfoButton.Unpack: MultiSelect.UnpackAll(___itemUiContext_1, false); return false; + case EItemInfoButton.AddToWishlist: + MultiSelect.WishlistAll(___itemUiContext_1, __instance, true, false); + return false; + case EItemInfoButton.RemoveFromWishlist: + MultiSelect.WishlistAll(___itemUiContext_1, __instance, false, false); + return false; default: return true; } diff --git a/src/Settings.cs b/src/Settings.cs index bf16312..06cc81f 100644 --- a/src/Settings.cs +++ b/src/Settings.cs @@ -138,6 +138,7 @@ internal class Settings public static ConfigEntry DefaultSortingTableBind { get; set; } // Advanced public static ConfigEntry ContextMenuOnRight { get; set; } public static ConfigEntry AddOfferContextMenu { get; set; } + public static ConfigEntry WishlistContextEverywhere { get; set; } public static ConfigEntry ShowGPCurrency { get; set; } public static ConfigEntry ShowOutOfStockCheckbox { get; set; } public static ConfigEntry SortingTableButton { get; set; } @@ -730,7 +731,7 @@ internal class Settings new ConfigurationManagerAttributes { }))); configEntries.Add(AddOfferContextMenu = config.Bind( - InputSection, + InventorySection, "Add Offer Context Menu", true, new ConfigDescription( @@ -738,6 +739,15 @@ internal class Settings null, new ConfigurationManagerAttributes { }))); + configEntries.Add(WishlistContextEverywhere = config.Bind( + InventorySection, + "Wishlist Context Menu Everywhere", + true, + new ConfigDescription( + "Add/Remove to wishlist available in the context menu on all screens", + null, + new ConfigurationManagerAttributes { }))); + configEntries.Add(ShowGPCurrency = config.Bind( InventorySection, "Show GP Coins in Currency",