unpack keybind; multi equip, unequip, unload ammo

This commit is contained in:
Tyfon
2024-06-20 02:05:40 -07:00
parent 4700ff5aa3
commit dc6b879d58
5 changed files with 178 additions and 59 deletions

View File

@@ -175,6 +175,22 @@ namespace UIFixes
get { return SelectedItems.Count > 0; } get { return SelectedItems.Count > 0; }
} }
// Sort the items to prioritize the items that share a grid with the dragged item, prepend the dragContext as the first one
// Can pass no itemContext, and it just sorts items by their grid order
public static IEnumerable<ItemContextClass> SortedItemContexts(ItemContextClass first = null, bool prepend = true)
{
static int gridOrder(LocationInGrid loc, StashGridClass grid) => grid.GridWidth.Value * loc.y + loc.x;
var result = ItemContexts
.Where(ic => first == null || ic.Item != first.Item)
.OrderByDescending(ic => ic.ItemAddress is GClass2769)
.ThenByDescending(ic => first != null && first.ItemAddress is GClass2769 originalDraggedAddress && ic.ItemAddress is GClass2769 selectedGridAddress && selectedGridAddress.Grid == originalDraggedAddress.Grid)
.ThenByDescending(ic => ic.ItemAddress is GClass2769 selectedGridAddress ? selectedGridAddress.Grid.Id : null)
.ThenBy(ic => ic.ItemAddress is GClass2769 selectedGridAddress ? gridOrder(selectedGridAddress.LocationInGrid, selectedGridAddress.Grid) : 0);
return first != null && prepend ? result.Prepend(first) : result;
}
public static void ShowDragCount(DraggedItemView draggedItemView) public static void ShowDragCount(DraggedItemView draggedItemView)
{ {
if (draggedItemView != null && Count > 1) if (draggedItemView != null && Count > 1)
@@ -196,6 +212,68 @@ namespace UIFixes
} }
} }
public static int InteractionCount(EItemInfoButton interaction, ItemUiContext itemUiContext)
{
int count = 0;
foreach (ItemContextClass selectedItemContext in SortedItemContexts())
{
ItemContextAbstractClass innerContext = selectedItemContext.GClass2813_0;
if (innerContext == null)
{
continue;
}
var contextInteractions = itemUiContext.GetItemContextInteractions(innerContext, null);
if (!contextInteractions.IsInteractionAvailable(interaction))
{
continue;
}
++count;
}
return count;
}
public static void EquipAll(ItemUiContext itemUiContext, bool allOrNothing)
{
if (!allOrNothing || InteractionCount(EItemInfoButton.Equip, itemUiContext) == Count)
{
foreach (ItemContextClass selectedItemContext in SortedItemContexts())
{
itemUiContext.QuickEquip(selectedItemContext.Item).HandleExceptions();
}
itemUiContext.Tooltip?.Close();
}
}
public static void UnequipAll(ItemUiContext itemUiContext, bool allOrNothing)
{
if (!allOrNothing || InteractionCount(EItemInfoButton.Unequip, itemUiContext) == Count)
{
foreach (ItemContextClass selectedItemContext in SortedItemContexts())
{
itemUiContext.Uninstall(selectedItemContext.GClass2813_0).HandleExceptions();
}
itemUiContext.Tooltip?.Close();
}
}
public static void UnloadAmmoAll(ItemUiContext itemUiContext, bool allOrNothing)
{
if (!allOrNothing || InteractionCount(EItemInfoButton.UnloadAmmo, itemUiContext) == Count)
{
foreach (ItemContextClass selectedItemContext in SortedItemContexts())
{
itemUiContext.UnloadAmmo(selectedItemContext.Item).HandleExceptions();
}
itemUiContext.Tooltip?.Close();
}
}
private static void ShowSelection(GridItemView itemView) private static void ShowSelection(GridItemView itemView)
{ {
GameObject selectedMark = itemView.transform.Find("SelectedMark")?.gameObject; GameObject selectedMark = itemView.transform.Find("SelectedMark")?.gameObject;

View File

@@ -88,7 +88,12 @@ namespace UIFixes
[PatchPostfix] [PatchPostfix]
public static void Postfix(string caption, TextMeshProUGUI ____text) public static void Postfix(string caption, TextMeshProUGUI ____text)
{ {
if (caption == EItemInfoButton.Insure.ToString() && MultiSelect.Count > 1) if (MultiSelect.Count < 1)
{
return;
}
if (caption == EItemInfoButton.Insure.ToString())
{ {
InsuranceCompanyClass insurance = ItemUiContext.Instance.Session.InsuranceCompany; InsuranceCompanyClass insurance = ItemUiContext.Instance.Session.InsuranceCompany;
int count = MultiSelect.ItemContexts.Select(ic => ItemClass.FindOrCreate(ic.Item)) int count = MultiSelect.ItemContexts.Select(ic => ItemClass.FindOrCreate(ic.Item))
@@ -99,6 +104,30 @@ namespace UIFixes
{ {
____text.text += " (x" + count + ")"; ____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 + ")";
}
}
else if (caption == EItemInfoButton.Unequip.ToString())
{
int count = MultiSelect.InteractionCount(EItemInfoButton.Unequip, ItemUiContext.Instance);
if (count > 0)
{
____text.text += " (x" + count + ")";
}
}
else if (caption == EItemInfoButton.UnloadAmmo.ToString())
{
int count = MultiSelect.InteractionCount(EItemInfoButton.UnloadAmmo, ItemUiContext.Instance);
if (count > 0)
{
____text.text += " (x" + count + ")";
}
} }
} }
} }

View File

@@ -78,6 +78,12 @@ namespace UIFixes
return; return;
} }
if (Settings.UnpackKeyBind.Value.IsDown())
{
interactions.ExecuteInteraction(EItemInfoButton.Unpack);
return;
}
if (Settings.FilterByKeyBind.Value.IsDown()) if (Settings.FilterByKeyBind.Value.IsDown())
{ {
interactions.ExecuteInteraction(EItemInfoButton.FilterSearch); interactions.ExecuteInteraction(EItemInfoButton.FilterSearch);

View File

@@ -1,4 +1,5 @@
using Aki.Reflection.Patching; using Aki.Reflection.Patching;
using Aki.Reflection.Utils;
using Comfort.Common; using Comfort.Common;
using EFT.Communications; using EFT.Communications;
using EFT.InventoryLogic; using EFT.InventoryLogic;
@@ -38,31 +39,43 @@ namespace UIFixes
public static void Enable() public static void Enable()
{ {
// Initialization
new InitializeCommonUIPatch().Enable(); new InitializeCommonUIPatch().Enable();
new InitializeMenuUIPatch().Enable(); new InitializeMenuUIPatch().Enable();
// Selection
new SelectOnMouseDownPatch().Enable(); new SelectOnMouseDownPatch().Enable();
new ItemViewClickPatch().Enable();
new DeselectOnTradingItemViewClickPatch().Enable(); new DeselectOnTradingItemViewClickPatch().Enable();
new HandleItemViewInitPatch().Enable(); new HandleItemViewInitPatch().Enable();
new HandleItemViewKillPatch().Enable(); new HandleItemViewKillPatch().Enable();
new BeginDragPatch().Enable(); new BeginDragPatch().Enable();
new EndDragPatch().Enable(); new EndDragPatch().Enable();
// Workarounds
new DisableSplitPatch().Enable(); new DisableSplitPatch().Enable();
new DisableSplitTargetPatch().Enable(); new DisableSplitTargetPatch().Enable();
// Actions
new ItemViewClickPatch().Enable();
new ContextActionsPatch().Enable();
// GridView
new GridViewCanAcceptPatch().Enable(); new GridViewCanAcceptPatch().Enable();
new GridViewAcceptItemPatch().Enable(); new GridViewAcceptItemPatch().Enable();
new GridViewPickTargetPatch().Enable(); new GridViewPickTargetPatch().Enable();
new GridViewDisableHighlightPatch().Enable(); new GridViewDisableHighlightPatch().Enable();
new GridViewClearTooltipPatch().Enable(); new GridViewClearTooltipPatch().Enable();
// SlotView
new SlotViewCanAcceptPatch().Enable(); new SlotViewCanAcceptPatch().Enable();
new SlotViewAcceptItemPatch().Enable(); new SlotViewAcceptItemPatch().Enable();
// TradingTableGridView
new TradingTableCanAcceptPatch().Enable(); new TradingTableCanAcceptPatch().Enable();
new TradingTableAcceptItemPatch().Enable(); new TradingTableAcceptItemPatch().Enable();
new TradingTableGetHighlightColorPatch().Enable(); new TradingTableGetHighlightColorPatch().Enable();
// Various location finding
new FindSpotKeepRotationPatch().Enable(); new FindSpotKeepRotationPatch().Enable();
new FindLocationForItemPatch().Enable(); new FindLocationForItemPatch().Enable();
new FindPlaceToPutPatch().Enable(); new FindPlaceToPutPatch().Enable();
@@ -173,7 +186,7 @@ namespace UIFixes
if (altDown && !shiftDown && !ctrlDown) if (altDown && !shiftDown && !ctrlDown)
{ {
QuickEquip(___ItemUiContext); MultiSelect.EquipAll(___ItemUiContext, true);
return false; return false;
} }
@@ -188,45 +201,13 @@ namespace UIFixes
return true; return true;
} }
private static void QuickEquip(ItemUiContext itemUiContext)
{
bool allowed = true;
var selectedItemContexts = SortSelectedContexts(MultiSelect.ItemContexts);
foreach (ItemContextClass selectedItemContext in selectedItemContexts)
{
ItemContextAbstractClass innerContext = selectedItemContext.GClass2813_0;
if (innerContext == null)
{
allowed = false;
break;
}
var contextInteractions = itemUiContext.GetItemContextInteractions(innerContext, null);
if (!contextInteractions.IsInteractionAvailable(EItemInfoButton.Equip))
{
allowed = false;
break;
}
}
if (allowed)
{
foreach (ItemContextClass selectedItemContext in selectedItemContexts)
{
itemUiContext.QuickEquip(selectedItemContext.Item).HandleExceptions();
}
itemUiContext.Tooltip?.Close();
}
}
private static void QuickMove(GridItemView gridItemView, ItemUiContext itemUiContext, TraderControllerClass itemController) private static void QuickMove(GridItemView gridItemView, ItemUiContext itemUiContext, TraderControllerClass itemController)
{ {
bool succeeded = true; bool succeeded = true;
DisableMerge = true; DisableMerge = true;
IgnoreItemParent = true; IgnoreItemParent = true;
Stack<GStruct413> operations = new(); Stack<GStruct413> operations = new();
foreach (ItemContextClass selectedItemContext in SortSelectedContexts(MultiSelect.ItemContexts)) foreach (ItemContextClass selectedItemContext in MultiSelect.SortedItemContexts())
{ {
GStruct413 operation = itemUiContext.QuickFindAppropriatePlace(selectedItemContext, itemController, false /*forceStash*/, false /*showWarnings*/, false /*simulate*/); GStruct413 operation = itemUiContext.QuickFindAppropriatePlace(selectedItemContext, itemController, false /*forceStash*/, false /*showWarnings*/, false /*simulate*/);
if (operation.Succeeded && itemController.CanExecute(operation.Value)) if (operation.Succeeded && itemController.CanExecute(operation.Value))
@@ -282,6 +263,38 @@ namespace UIFixes
} }
} }
public class ContextActionsPatch : ModulePatch
{
protected override MethodBase GetTargetMethod()
{
return AccessTools.Method(typeof(GClass3021), nameof(GClass3021.ExecuteInteractionInternal));
}
[PatchPrefix]
public static bool Prefix(GClass3021 __instance, EItemInfoButton interaction, ItemUiContext ___itemUiContext_1)
{
if (!MultiSelect.Active)
{
return true;
}
switch (interaction)
{
case EItemInfoButton.Equip:
MultiSelect.EquipAll(___itemUiContext_1, false);
return false;
case EItemInfoButton.Unequip:
MultiSelect.UnequipAll(___itemUiContext_1, false);
return false;
case EItemInfoButton.UnloadAmmo:
MultiSelect.UnloadAmmoAll(___itemUiContext_1, false);
return false;
default:
return true;
}
}
}
// TradingItemView overrides GridItemView.OnClick and doesn't call base // TradingItemView overrides GridItemView.OnClick and doesn't call base
public class DeselectOnTradingItemViewClickPatch : ModulePatch public class DeselectOnTradingItemViewClickPatch : ModulePatch
{ {
@@ -446,7 +459,7 @@ namespace UIFixes
bool showHighlights = targetItem == null; bool showHighlights = targetItem == null;
Stack<GStruct413> operations = new(); Stack<GStruct413> operations = new();
foreach (ItemContextClass selectedItemContext in SortSelectedContexts(MultiSelect.ItemContexts, itemContext)) foreach (ItemContextClass selectedItemContext in MultiSelect.SortedItemContexts(itemContext))
{ {
FindOrigin = GetTargetGridAddress(itemContext, selectedItemContext, hoveredAddress); FindOrigin = GetTargetGridAddress(itemContext, selectedItemContext, hoveredAddress);
FindVerticalFirst = selectedItemContext.ItemRotation == ItemRotation.Vertical; FindVerticalFirst = selectedItemContext.ItemRotation == ItemRotation.Vertical;
@@ -566,7 +579,7 @@ namespace UIFixes
} }
var serializer = __instance.GetOrAddComponent<ItemContextTaskSerializer>(); var serializer = __instance.GetOrAddComponent<ItemContextTaskSerializer>();
__result = serializer.Initialize(SortSelectedContexts(MultiSelect.ItemContexts, itemContext), ic => __result = serializer.Initialize(MultiSelect.SortedItemContexts(itemContext), ic =>
{ {
FindOrigin = GetTargetGridAddress(itemContext, ic, hoveredAddress); FindOrigin = GetTargetGridAddress(itemContext, ic, hoveredAddress);
FindVerticalFirst = ic.ItemRotation == ItemRotation.Vertical; FindVerticalFirst = ic.ItemRotation == ItemRotation.Vertical;
@@ -677,23 +690,6 @@ namespace UIFixes
} }
} }
// Sort the items to prioritize the items that share a grid with the dragged item, prepend the dragContext as the first one
// Can pass no itemContext, and it just sorts items by their grid order
private static IEnumerable<ItemContextClass> SortSelectedContexts(
IEnumerable<ItemContextClass> selectedContexts, ItemContextClass itemContext = null, bool prepend = true)
{
static int gridOrder(LocationInGrid loc, StashGridClass grid) => grid.GridWidth.Value * loc.y + loc.x;
var result = selectedContexts
.Where(ic => itemContext == null || ic.Item != itemContext.Item)
.OrderByDescending(ic => ic.ItemAddress is GClass2769)
.ThenByDescending(ic => itemContext != null && itemContext.ItemAddress is GClass2769 originalDraggedAddress && ic.ItemAddress is GClass2769 selectedGridAddress && selectedGridAddress.Grid == originalDraggedAddress.Grid)
.ThenByDescending(ic => ic.ItemAddress is GClass2769 selectedGridAddress ? selectedGridAddress.Grid.Id : null)
.ThenBy(ic => ic.ItemAddress is GClass2769 selectedGridAddress ? gridOrder(selectedGridAddress.LocationInGrid, selectedGridAddress.Grid) : 0);
return itemContext != null && prepend ? result.Prepend(itemContext) : result;
}
public class GridViewDisableHighlightPatch : ModulePatch public class GridViewDisableHighlightPatch : ModulePatch
{ {
protected override MethodBase GetTargetMethod() protected override MethodBase GetTargetMethod()
@@ -751,7 +747,7 @@ namespace UIFixes
} }
Stack<GStruct413> operations = new(); Stack<GStruct413> operations = new();
foreach (ItemContextClass itemContext in SortSelectedContexts(MultiSelect.ItemContexts, null, false)) foreach (ItemContextClass itemContext in MultiSelect.SortedItemContexts())
{ {
__result = itemContext.CanAccept(__instance.Slot, __instance.ParentItemContext, ___InventoryController, out operation, false /* simulate */); __result = itemContext.CanAccept(__instance.Slot, __instance.ParentItemContext, ___InventoryController, out operation, false /* simulate */);
if (operation.Succeeded) if (operation.Succeeded)
@@ -798,7 +794,7 @@ namespace UIFixes
InPatch = true; InPatch = true;
var serializer = __instance.GetOrAddComponent<ItemContextTaskSerializer>(); var serializer = __instance.GetOrAddComponent<ItemContextTaskSerializer>();
__result = serializer.Initialize(SortSelectedContexts(MultiSelect.ItemContexts, null, false), itemContext => __instance.AcceptItem(itemContext, targetItemContext)); __result = serializer.Initialize(MultiSelect.SortedItemContexts(), itemContext => __instance.AcceptItem(itemContext, targetItemContext));
__result.ContinueWith(_ => { InPatch = false; }); __result.ContinueWith(_ => { InPatch = false; });
@@ -834,7 +830,7 @@ namespace UIFixes
GClass2769 hoveredAddress = new(__instance.Grid, hoveredLocation); GClass2769 hoveredAddress = new(__instance.Grid, hoveredLocation);
Stack<GStruct413> operations = new(); Stack<GStruct413> operations = new();
foreach (ItemContextClass selectedItemContext in SortSelectedContexts(MultiSelect.ItemContexts, itemContext)) foreach (ItemContextClass selectedItemContext in MultiSelect.SortedItemContexts(itemContext))
{ {
if (traderAssortmentController.CanPrepareItemToSell(selectedItemContext.Item)) if (traderAssortmentController.CanPrepareItemToSell(selectedItemContext.Item))
{ {
@@ -912,7 +908,7 @@ namespace UIFixes
itemContext.CloseDependentWindows(); itemContext.CloseDependentWindows();
// For the rest of the items, still need to use quickfind // For the rest of the items, still need to use quickfind
foreach (ItemContextClass selectedItemContext in SortSelectedContexts(MultiSelect.ItemContexts, itemContext, false)) foreach (ItemContextClass selectedItemContext in MultiSelect.SortedItemContexts(itemContext, false))
{ {
FindOrigin = GetTargetGridAddress(itemContext, selectedItemContext, hoveredAddress); FindOrigin = GetTargetGridAddress(itemContext, selectedItemContext, hoveredAddress);
FindVerticalFirst = selectedItemContext.ItemRotation == ItemRotation.Vertical; FindVerticalFirst = selectedItemContext.ItemRotation == ItemRotation.Vertical;

View File

@@ -58,6 +58,7 @@ namespace UIFixes
public static ConfigEntry<KeyboardShortcut> UseKeyBind { get; set; } public static ConfigEntry<KeyboardShortcut> UseKeyBind { get; set; }
public static ConfigEntry<KeyboardShortcut> UseAllKeyBind { get; set; } public static ConfigEntry<KeyboardShortcut> UseAllKeyBind { get; set; }
public static ConfigEntry<KeyboardShortcut> UnloadKeyBind { get; set; } public static ConfigEntry<KeyboardShortcut> UnloadKeyBind { get; set; }
public static ConfigEntry<KeyboardShortcut> UnpackKeyBind { get; set; }
public static ConfigEntry<KeyboardShortcut> FilterByKeyBind { get; set; } public static ConfigEntry<KeyboardShortcut> FilterByKeyBind { get; set; }
public static ConfigEntry<KeyboardShortcut> LinkedSearchKeyBind { get; set; } public static ConfigEntry<KeyboardShortcut> LinkedSearchKeyBind { get; set; }
public static ConfigEntry<bool> UseRaidMouseScrollMulti { get; set; } // Advanced public static ConfigEntry<bool> UseRaidMouseScrollMulti { get; set; } // Advanced
@@ -248,6 +249,15 @@ namespace UIFixes
null, null,
new ConfigurationManagerAttributes { }))); new ConfigurationManagerAttributes { })));
configEntries.Add(UnpackKeyBind = config.Bind(
InputSection,
"Unpack Shortcut",
new KeyboardShortcut(KeyCode.None),
new ConfigDescription(
"Keybind to unpack a sealed weapons case, etc",
null,
new ConfigurationManagerAttributes { })));
configEntries.Add(FilterByKeyBind = config.Bind( configEntries.Add(FilterByKeyBind = config.Bind(
InputSection, InputSection,
"Filter by Item Shortcut", "Filter by Item Shortcut",