From 550d5914642c4e4c0aa2f9feb29b82fb817e3f5c Mon Sep 17 00:00:00 2001 From: Tyfon <29051038+tyfon7@users.noreply.github.com> Date: Mon, 17 Jun 2024 02:24:43 -0700 Subject: [PATCH] trading view, lots of fixes --- DrawMultiSelect.cs | 19 ++- MultiSelect.cs | 80 +++++++-- MultiSelectDebug.cs | 16 +- Patches/MultiSelectPatches.cs | 310 +++++++++++++++++++++++++++------- R.cs | 26 ++- 5 files changed, 365 insertions(+), 86 deletions(-) diff --git a/DrawMultiSelect.cs b/DrawMultiSelect.cs index eae5e86..6f947f3 100644 --- a/DrawMultiSelect.cs +++ b/DrawMultiSelect.cs @@ -21,6 +21,7 @@ namespace UIFixes private GraphicRaycaster preloaderRaycaster; private bool drawing; + private bool secondary; public void Start() { @@ -75,6 +76,7 @@ namespace UIFixes selectOrigin = Input.mousePosition; drawing = true; + secondary = Input.GetKey(KeyCode.LeftShift) || Input.GetKey(KeyCode.RightShift); } if (drawing) @@ -101,7 +103,7 @@ namespace UIFixes preloaderRaycaster.Raycast(eventData, raycastResults); if (raycastResults.Any() && !raycastResults[0].gameObject.transform.IsDescendantOf(itemTransform)) { - MultiSelect.Deselect(gridItemView); + MultiSelect.Deselect(gridItemView, secondary); continue; } @@ -110,7 +112,7 @@ namespace UIFixes preloaderRaycaster.Raycast(eventData, raycastResults); if (raycastResults.Any() && !raycastResults[0].gameObject.transform.IsDescendantOf(itemTransform)) { - MultiSelect.Deselect(gridItemView); + MultiSelect.Deselect(gridItemView, secondary); continue; } @@ -119,7 +121,7 @@ namespace UIFixes preloaderRaycaster.Raycast(eventData, raycastResults); if (raycastResults.Any() && !raycastResults[0].gameObject.transform.IsDescendantOf(itemTransform)) { - MultiSelect.Deselect(gridItemView); + MultiSelect.Deselect(gridItemView, secondary); continue; } @@ -128,21 +130,26 @@ namespace UIFixes preloaderRaycaster.Raycast(eventData, raycastResults); if (raycastResults.Any() && !raycastResults[0].gameObject.transform.IsDescendantOf(itemTransform)) { - MultiSelect.Deselect(gridItemView); + MultiSelect.Deselect(gridItemView, secondary); continue; } - MultiSelect.Select(gridItemView); + MultiSelect.Select(gridItemView, secondary); continue; } - MultiSelect.Deselect(gridItemView); + MultiSelect.Deselect(gridItemView, secondary); } } if (drawing && !Input.GetKey(KeyCode.Mouse0)) { drawing = false; + if (secondary) + { + MultiSelect.CombineSecondary(); + secondary = false; + } } } diff --git a/MultiSelect.cs b/MultiSelect.cs index 3122fe8..e1be398 100644 --- a/MultiSelect.cs +++ b/MultiSelect.cs @@ -15,6 +15,9 @@ namespace UIFixes private static readonly Dictionary SelectedItemViews = []; private static readonly List SortedItemContexts = []; + private static readonly Dictionary SecondaryItemViews = []; + private static readonly List SecondaryItemContexts = []; + public static void Initialize() { // Grab the selection objects from ragfair as templates @@ -29,15 +32,16 @@ namespace UIFixes ragfairNewOfferItemView.ReturnToPool(); } - public static void Toggle(GridItemView itemView) + public static void Toggle(GridItemView itemView, bool secondary = false) { - if (SelectedItemViews.ContainsKey(itemView)) + var dictionary = secondary ? SecondaryItemViews : SelectedItemViews; + if (dictionary.ContainsKey(itemView)) { - Deselect(itemView); + Deselect(itemView, secondary); } else { - Select(itemView); + Select(itemView, secondary); } } @@ -50,29 +54,38 @@ namespace UIFixes } } - public static void Select(GridItemView itemView) + public static void Select(GridItemView itemView, bool secondary = false) { - if (itemView.IsSelectable() && !SelectedItemViews.ContainsKey(itemView)) + var dictionary = secondary ? SecondaryItemViews : SelectedItemViews; + var list = secondary ? SecondaryItemContexts : SortedItemContexts; + + if (itemView.IsSelectable() && !SelectedItemViews.ContainsKey(itemView) && !SecondaryItemViews.ContainsKey(itemView)) { ItemContextClass itemContext = new(itemView.ItemContext, itemView.ItemRotation); itemContext.GClass2813_0.OnDisposed += RugPull; itemContext.OnDisposed += RugPull; - SelectedItemViews.Add(itemView, itemContext); - SortedItemContexts.Add(itemContext); + // Remove event handlers that no one cares about and cause stack overflows + itemContext.method_1(); + + dictionary.Add(itemView, itemContext); + list.Add(itemContext); ShowSelection(itemView); } } - public static void Deselect(GridItemView itemView) + public static void Deselect(GridItemView itemView, bool secondary = false) { - if (SelectedItemViews.TryGetValue(itemView, out ItemContextClass itemContext)) + var dictionary = secondary ? SecondaryItemViews : SelectedItemViews; + var list = secondary ? SecondaryItemContexts : SortedItemContexts; + + if (dictionary.TryGetValue(itemView, out ItemContextClass itemContext)) { itemContext.GClass2813_0.OnDisposed -= RugPull; itemContext.OnDisposed -= RugPull; itemContext.Dispose(); - SortedItemContexts.Remove(itemContext); - SelectedItemViews.Remove(itemView); + list.Remove(itemContext); + dictionary.Remove(itemView); HideSelection(itemView); } } @@ -82,16 +95,42 @@ namespace UIFixes return SelectedItemViews.ContainsKey(itemView); } + public static void CombineSecondary() + { + foreach (var entry in SecondaryItemViews) + { + SelectedItemViews.Add(entry.Key, entry.Value); + } + + foreach (ItemContextClass itemContext in SecondaryItemContexts) + { + SortedItemContexts.Add(itemContext); + } + + SecondaryItemViews.Clear(); + SecondaryItemContexts.Clear(); + } + public static IEnumerable ItemContexts { get { return SortedItemContexts; } } + public static IEnumerable SecondaryContexts + { + get { return SecondaryItemContexts; } + } + public static int Count { get { return SelectedItemViews.Count; } } + public static int SecondaryCount + { + get { return SecondaryItemViews.Count; } + } + public static bool Active { get { return SelectedItemViews.Count > 1; } @@ -159,7 +198,22 @@ namespace UIFixes { public static bool IsSelectable(this ItemView itemView) { - return itemView.IsInteractable && itemView.IsSearched && itemView.RemoveError.Value == null; + // Common non-interactable stuff + if (!itemView.IsInteractable || !itemView.IsSearched || itemView.RemoveError.Value != null) + { + return false; + } + + // You can't multi-select trader's items or items being sold + if (itemView is TradingItemView tradingItemView) + { + if (itemView is not TradingPlayerItemView || tradingItemView.R().IsBeingSold) + { + return false; + } + } + + return true; } } } diff --git a/MultiSelectDebug.cs b/MultiSelectDebug.cs index a92a9bb..96595a6 100644 --- a/MultiSelectDebug.cs +++ b/MultiSelectDebug.cs @@ -1,4 +1,5 @@ -using System.Text; +using System.Linq; +using System.Text; using UnityEngine; namespace UIFixes @@ -31,8 +32,7 @@ namespace UIFixes builder.Append("MultiSelect\n"); builder.AppendFormat("Active: {1}\n", MultiSelect.Active ? "green" : "red", MultiSelect.Active); - builder.AppendFormat("Count: {0}\n", MultiSelect.Count); - builder.Append("Items:\n"); + builder.AppendFormat("Items: {0}\n", MultiSelect.Count); foreach (ItemContextClass itemContext in MultiSelect.ItemContexts) { @@ -40,6 +40,16 @@ namespace UIFixes builder.AppendLine(); } + if (MultiSelect.SecondaryContexts.Any()) + { + builder.AppendFormat("Secondary Items: {0}\n", MultiSelect.SecondaryCount); + foreach (ItemContextClass itemContext in MultiSelect.SecondaryContexts) + { + builder.Append(itemContext.Item.ToString()); + builder.AppendLine(); + } + } + guiContent.text = builder.ToString(); guiRect.size = guiStyle.CalcSize(guiContent); diff --git a/Patches/MultiSelectPatches.cs b/Patches/MultiSelectPatches.cs index 9ac5b77..ebf4cd5 100644 --- a/Patches/MultiSelectPatches.cs +++ b/Patches/MultiSelectPatches.cs @@ -21,31 +21,36 @@ namespace UIFixes private static bool InPatch = false; // If the can accept method should render highlights - private static bool ShowHighlights = false; private static readonly List HighlightPanels = []; public static void Enable() { - new InitializePatch().Enable(); - new SelectPatch().Enable(); - new DeselectOnOtherMouseDown().Enable(); + new InitializeCommonUIPatch().Enable(); + new InitializeMenuUIPatch().Enable(); + new SelectOnMouseDownPatch().Enable(); + new DeselectOnGridItemViewClickPatch().Enable(); + new DeselectOnTradingItemViewClickPatch().Enable(); new DeselectOnItemViewKillPatch().Enable(); new BeginDragPatch().Enable(); new EndDragPatch().Enable(); new InspectWindowHack().Enable(); + new DisableSplitPatch().Enable(); + new DisableSplitTargetPatch().Enable(); new GridViewCanAcceptPatch().Enable(); new GridViewAcceptItemPatch().Enable(); new GridViewPickTargetPatch().Enable(); - new GridViewHighlightPatch().Enable(); new GridViewDisableHighlightPatch().Enable(); new SlotViewCanAcceptPatch().Enable(); new SlotViewAcceptItemPatch().Enable(); + new TradingTableCanAcceptPatch().Enable(); + new TradingTableAcceptItemPatch().Enable(); + new TradingTableGetHighlightColorPatch().Enable(); } - public class InitializePatch : ModulePatch + public class InitializeCommonUIPatch : ModulePatch { protected override MethodBase GetTargetMethod() { @@ -73,35 +78,26 @@ namespace UIFixes } } - public class SelectPatch : ModulePatch + public class InitializeMenuUIPatch : ModulePatch { protected override MethodBase GetTargetMethod() { - return AccessTools.Method(typeof(GridItemView), nameof(GridItemView.OnClick)); + return AccessTools.Method(typeof(MenuUI), nameof(MenuUI.Awake)); } [PatchPostfix] - public static void Postfix(GridItemView __instance, PointerEventData.InputButton button) + public static void Postfix(MenuUI __instance) { if (!Settings.EnableMultiSelect.Value) { return; } - if (__instance.Item != null && button == PointerEventData.InputButton.Left && (Input.GetKey(KeyCode.LeftShift) || Input.GetKey(KeyCode.RightShift))) - { - MultiSelect.Toggle(__instance); - return; - } - - if (button == PointerEventData.InputButton.Left) - { - MultiSelect.Clear(); - } + __instance.TraderScreensGroup.transform.Find("Deal Screen").gameObject.GetOrAddComponent(); } } - public class DeselectOnOtherMouseDown : ModulePatch + public class SelectOnMouseDownPatch : ModulePatch { protected override MethodBase GetTargetMethod() { @@ -116,13 +112,60 @@ namespace UIFixes return; } - if (eventData.button == PointerEventData.InputButton.Left && (Input.GetKey(KeyCode.LeftShift) || Input.GetKey(KeyCode.RightShift))) + if (__instance is GridItemView gridItemView && eventData.button == PointerEventData.InputButton.Left && (Input.GetKey(KeyCode.LeftShift) || Input.GetKey(KeyCode.RightShift))) { - // This will be shift-click, let it cook + MultiSelect.Toggle(gridItemView); return; } - if (__instance is not GridItemView gridItemView || !MultiSelect.IsSelected(gridItemView)) + if (__instance is not GridItemView gridItemView2 || !MultiSelect.IsSelected(gridItemView2)) + { + MultiSelect.Clear(); + } + } + } + + public class DeselectOnGridItemViewClickPatch : ModulePatch + { + protected override MethodBase GetTargetMethod() + { + return AccessTools.Method(typeof(GridItemView), nameof(GridItemView.OnClick)); + } + + [PatchPostfix] + public static void Postfix(GridItemView __instance, PointerEventData.InputButton button) + { + if (!Settings.EnableMultiSelect.Value) + { + return; + } + + // Mousedown handles most things, just need to handle the non-shift click of a selected item + if (button == PointerEventData.InputButton.Left && !Input.GetKey(KeyCode.LeftShift) && !Input.GetKey(KeyCode.RightShift)) + { + MultiSelect.Clear(); + } + } + } + + // TradingItemView overrides GridItemView.OnClick and doesn't call base + public class DeselectOnTradingItemViewClickPatch : ModulePatch + { + protected override MethodBase GetTargetMethod() + { + return AccessTools.Method(typeof(TradingItemView), nameof(TradingItemView.OnClick)); + } + + [PatchPostfix] + public static void Postfix(TradingItemView __instance, PointerEventData.InputButton button) + { + if (!Settings.EnableMultiSelect.Value || __instance is not TradingPlayerItemView) + { + return; + } + + // Mousedown handles most things, just need to handle the non-shift click of a selected item + if (button == PointerEventData.InputButton.Left && !Input.GetKey(KeyCode.LeftShift) && !Input.GetKey(KeyCode.RightShift)) { MultiSelect.Clear(); } @@ -263,7 +306,7 @@ namespace UIFixes operations.Push(operation); if (targetItem != null && showHighlights) // targetItem was originally null so this is the rest of the items { - ShowHighlight(__instance, operation); + ShowHighlight(__instance, selectedItemContext, operation); } } else @@ -310,12 +353,13 @@ namespace UIFixes IEnumerable itemContexts = MultiSelect.ItemContexts.Where(ic => ic.Item != itemContext.Item).Prepend(itemContext); var serializer = __instance.GetOrAddComponent(); - __result = serializer.Initialize(itemContexts, ic => __instance.AcceptItem(ic, targetItemContext)); - + __result = serializer.Initialize(itemContexts, ic => __instance.AcceptItem(ic, targetItemContext)); + // Setting the fallback after initializing means it only applies after the first item is already moved GridViewPickTargetPatch.FallbackResult = __instance.Grid.ParentItem; - __result.ContinueWith(_ => { + __result.ContinueWith(_ => + { InPatch = false; GridViewPickTargetPatch.FallbackResult = null; }); @@ -340,39 +384,8 @@ namespace UIFixes } } - public class GridViewHighlightPatch : ModulePatch + private static void ShowHighlight(GridView gridView, ItemContextClass itemContext, GStruct413 operation) { - protected override MethodBase GetTargetMethod() - { - return AccessTools.Method(typeof(GridView), nameof(GridView.HighlightItemViewPosition)); - } - - [PatchPrefix] - public static void Prefix(ItemContextAbstractClass targetItemContext) - { - if (!Settings.EnableMultiSelect.Value || !MultiSelect.Active || targetItemContext != null) - { - return; - } - - ShowHighlights = true; - } - - [PatchPostfix] - public static void Postfix(GridView __instance, ItemContextClass itemContext, ItemContextAbstractClass targetItemContext, Image ____highlightPanel) - { - if (!Settings.EnableMultiSelect.Value || !MultiSelect.Active || targetItemContext != null) - { - return; - } - - ShowHighlights = false; - } - - } - - private static void ShowHighlight(GridView gridView, GStruct413 operation) - { if (operation.Value is not GClass2786 moveOperation || moveOperation.To is not GClass2769 gridAddress) { return; @@ -383,7 +396,7 @@ namespace UIFixes GridView otherGridView = gridView.transform.parent.GetComponentsInChildren().FirstOrDefault(gv => gv.Grid == gridAddress.Grid); if (otherGridView != null) { - ShowHighlight(otherGridView, operation); + ShowHighlight(otherGridView, itemContext, operation); } return; @@ -393,7 +406,7 @@ namespace UIFixes Image highLightPanel = UnityEngine.Object.Instantiate(gridView.R().HighlightPanel, gridView.transform, false); highLightPanel.gameObject.SetActive(true); HighlightPanels.Add(highLightPanel); - highLightPanel.color = gridView.GetHighlightColor(null, operation, null); // 1st and 3rd args aren't even used + highLightPanel.color = gridView.GetHighlightColor(itemContext, operation, null); RectTransform rectTransform = highLightPanel.rectTransform; rectTransform.localScale = Vector3.one; @@ -420,8 +433,7 @@ namespace UIFixes { foreach (Image highLightPanel in HighlightPanels) { - highLightPanel.gameObject.SetActive(false); - UnityEngine.Object.Destroy(highLightPanel); + UnityEngine.Object.Destroy(highLightPanel.gameObject); } HighlightPanels.Clear(); @@ -516,6 +528,144 @@ namespace UIFixes } } + public class TradingTableCanAcceptPatch : ModulePatch + { + protected override MethodBase GetTargetMethod() + { + return AccessTools.Method(typeof(TradingTableGridView), nameof(TradingTableGridView.CanAccept)); + } + + [PatchPrefix] + public static bool Prefix(TradingTableGridView __instance, ItemContextClass itemContext, ItemContextAbstractClass targetItemContext, ref GStruct413 operation, ref bool __result) + { + if (!Settings.EnableMultiSelect.Value || !MultiSelect.Active) + { + return true; + } + + operation = default; + __result = false; + + TraderAssortmentControllerClass traderAssortmentController = __instance.R().TraderAssortmentController; + + HideHighlights(); + + bool firstItem = true; + + Stack operations = new(); + IEnumerable itemContexts = MultiSelect.ItemContexts.Where(ic => ic.Item != itemContext.Item).Prepend(itemContext); + foreach (ItemContextClass selectedItemContext in itemContexts) + { + if (traderAssortmentController.CanPrepareItemToSell(selectedItemContext.Item)) + { + operation = firstItem ? + InteractionsHandlerClass.Move(selectedItemContext.Item, new GClass2769(__instance.Grid, __instance.CalculateItemLocation(selectedItemContext)), traderAssortmentController.TraderController, false) : + InteractionsHandlerClass.QuickFindAppropriatePlace(selectedItemContext.Item, traderAssortmentController.TraderController, [__instance.Grid.ParentItem as LootItemClass], InteractionsHandlerClass.EMoveItemOrder.Apply, false); + + if (__result = operation.Succeeded) + { + operations.Push(operation); + if (!firstItem) // targetItem was originally null so this is the rest of the items + { + ShowHighlight(__instance, selectedItemContext, operation); + } + } + else + { + break; + } + } + else + { + operation = default; + __result = false; + break; + } + + firstItem = false; + } + + // We didn't simulate so now we undo + while (operations.Any()) + { + operations.Pop().Value?.RollBack(); + } + + return false; + } + } + + public class TradingTableAcceptItemPatch : ModulePatch + { + protected override MethodBase GetTargetMethod() + { + return AccessTools.Method(typeof(TradingTableGridView), nameof(TradingTableGridView.AcceptItem)); + } + + [PatchPrefix] + public static bool Prefix(TradingTableGridView __instance, ItemContextClass itemContext, ItemContextAbstractClass targetItemContext, ref Task __result) + { + if (!Settings.EnableMultiSelect.Value || !MultiSelect.Active) + { + return true; + } + + TraderAssortmentControllerClass traderAssortmentController = __instance.R().TraderAssortmentController; + + LocationInGrid locationInGrid = __instance.CalculateItemLocation(itemContext); + itemContext.DragCancelled(); + traderAssortmentController.PrepareToSell(itemContext.Item, locationInGrid); + itemContext.CloseDependentWindows(); + + // For the rest of the items we still need to use quickfind + foreach (ItemContextClass selectedItemContext in MultiSelect.ItemContexts.Where(ic => ic.Item != itemContext.Item)) + { + GStruct413 operation = InteractionsHandlerClass.QuickFindAppropriatePlace(selectedItemContext.Item, traderAssortmentController.TraderController, [__instance.Grid.ParentItem as LootItemClass], InteractionsHandlerClass.EMoveItemOrder.Apply, true); + if (operation.Failed || operation.Value is not GClass2786 moveOperation || moveOperation.To is not GClass2769 gridAddress) + { + break; + } + + traderAssortmentController.PrepareToSell(selectedItemContext.Item, gridAddress.LocationInGrid); + } + + MultiSelect.Clear(); // explicitly clear since the items are no longer selectable + __result = Task.CompletedTask; + return false; + } + } + + // Reimplement this method because BSG ignores the operation that is passed in and re-does the entire logic, + // like the dumb assholes they are + public class TradingTableGetHighlightColorPatch : ModulePatch + { + protected override MethodBase GetTargetMethod() + { + return AccessTools.Method(typeof(TradingTableGridView), nameof(TradingTableGridView.GetHighlightColor)); + } + + [PatchPrefix] + public static bool Prefix(TradingTableGridView __instance, ItemContextClass itemContext, ItemContextAbstractClass targetItemContext, ref Color __result) + { + if (!Settings.EnableMultiSelect.Value || !MultiSelect.Active || targetItemContext != null) + { + return true; + } + + TraderAssortmentControllerClass traderAssortmentController = __instance.R().TraderAssortmentController; + if (MultiSelect.ItemContexts.All(ic => traderAssortmentController.CanPrepareItemToSell(ic.Item))) + { + __result = R.GridView.ValidMoveColor; + } + else + { + __result = R.GridView.InvalidOperationColor; + } + + return false; + } + } + // The inspect window likes to recreate itself entirely when a slot is removed, which destroys all of the gridviews and // borks the multiselect. This patch just stops it from responding until the last one (since by then the selection is down to 1, which // is considered inactive multiselect) @@ -539,6 +689,40 @@ namespace UIFixes } } + public class DisableSplitPatch : ModulePatch + { + protected override MethodBase GetTargetMethod() + { + return AccessTools.Method(typeof(TraderControllerClass), nameof(TraderControllerClass.ExecutePossibleAction), [typeof(ItemContextAbstractClass), typeof(Item), typeof(bool), typeof(bool)]); + } + + [PatchPrefix] + public static void Prefix(ref bool partialTransferOnly) + { + if (MultiSelect.Active) + { + partialTransferOnly = false; + } + } + } + + public class DisableSplitTargetPatch : ModulePatch + { + protected override MethodBase GetTargetMethod() + { + return AccessTools.Method(typeof(TraderControllerClass), nameof(TraderControllerClass.ExecutePossibleAction), [typeof(ItemContextAbstractClass), typeof(ItemContextAbstractClass), typeof(ItemAddress), typeof(bool), typeof(bool)]); + } + + [PatchPrefix] + public static void Prefix(ref bool partialTransferOnly) + { + if (MultiSelect.Active) + { + partialTransferOnly = false; + } + } + } + public class TaskSerializer : MonoBehaviour { private Func func; diff --git a/R.cs b/R.cs index 111618a..dcb7c67 100644 --- a/R.cs +++ b/R.cs @@ -59,6 +59,7 @@ namespace UIFixes RepairStrategy.InitTypes(); ContextMenuHelper.InitTypes(); RagfairNewOfferItemView.InitTypes(); + TradingTableGridView.InitTypes(); } public abstract class Wrapper(object value) @@ -292,18 +293,23 @@ namespace UIFixes private static FieldInfo TraderControllerField; private static FieldInfo NonInteractableField; private static FieldInfo HighlightPanelField; - + private static FieldInfo ValidMoveColorField; + private static FieldInfo InvalidOperationColorField; public static void InitTypes() { Type = typeof(EFT.UI.DragAndDrop.GridView); TraderControllerField = AccessTools.GetDeclaredFields(Type).Single(f => f.FieldType == typeof(TraderControllerClass)); // field gclass2758_0 NonInteractableField = AccessTools.Field(Type, "_nonInteractable"); HighlightPanelField = AccessTools.Field(Type, "_highlightPanel"); + ValidMoveColorField = AccessTools.Field(Type, "ValidMoveColor"); + InvalidOperationColorField = AccessTools.Field(Type, "InvalidOperationColor"); } public TraderControllerClass TraderController { get { return (TraderControllerClass)TraderControllerField.GetValue(Value); } } public bool NonInteractable { get { return (bool)NonInteractableField.GetValue(Value); } } public Image HighlightPanel { get { return (Image)HighlightPanelField.GetValue(Value); } } + public static Color ValidMoveColor { get { return (Color)ValidMoveColorField.GetValue(null); } } + public static Color InvalidOperationColor { get { return (Color)InvalidOperationColorField.GetValue(null); } } } public class GridViewCanAcceptOperation(object value) : Wrapper(value) @@ -558,14 +564,17 @@ namespace UIFixes { public static Type Type { get; private set; } private static FieldInfo TraderAssortmentControllerField; + private static FieldInfo IsBeingSoldField; public static void InitTypes() { Type = typeof(EFT.UI.DragAndDrop.TradingItemView); TraderAssortmentControllerField = AccessTools.GetDeclaredFields(Type).Single(t => t.FieldType == typeof(TraderAssortmentControllerClass)); + IsBeingSoldField = AccessTools.GetDeclaredFields(Type).First(f => f.FieldType == typeof(BindableState)); } public TraderAssortmentControllerClass TraderAssortmentController { get { return (TraderAssortmentControllerClass)TraderAssortmentControllerField.GetValue(Value); } } + public bool IsBeingSold { get { return ((BindableState)IsBeingSoldField.GetValue(Value)).Value; } } } public class GridWindow(object value) : UIInputNode(value) @@ -695,6 +704,20 @@ namespace UIFixes public GameObject SelectedMark { get { return (GameObject)SelectedMarkField.GetValue(Value); } } public GameObject SelectedBackground { get { return (GameObject)SelectedBackgroundField.GetValue(Value); } } } + + public class TradingTableGridView(object value) : GridView(value) + { + public new static Type Type { get; private set; } + private static FieldInfo TraderAssortmentControllerField; + + public new static void InitTypes() + { + Type = typeof(EFT.UI.DragAndDrop.TradingTableGridView); + TraderAssortmentControllerField = AccessTools.GetDeclaredFields(Type).Single(f => f.FieldType == typeof(TraderAssortmentControllerClass)); + } + + public TraderAssortmentControllerClass TraderAssortmentController { get { return (TraderAssortmentControllerClass)TraderAssortmentControllerField.GetValue(Value); } } + } } public static class RExtentensions @@ -722,5 +745,6 @@ namespace UIFixes public static R.RepairerParametersPanel R(this RepairerParametersPanel value) => new(value); public static R.MessageWindow R(this MessageWindow value) => new(value); public static R.RagfairNewOfferItemView R(this RagfairNewOfferItemView value) => new(value); + public static R.TradingTableGridView R(this TradingTableGridView value) => new(value); } }