using Comfort.Common; using EFT; using EFT.Hideout; using EFT.InputSystem; using EFT.InventoryLogic; using EFT.UI; using EFT.UI.DragAndDrop; using EFT.UI.Ragfair; using EFT.UI.Utilities.LightScroller; using HarmonyLib; using SPT.Reflection.Utils; using System; using System.Collections.Generic; using System.Linq; using System.Reflection; using System.Threading.Tasks; using TMPro; using UnityEngine; using UnityEngine.UI; namespace UIFixes; public static class R { public static void Init() { // Order is significant, as some reference each other UIElement.InitUITypes(); UIInputNode.InitUITypes(); UIContext.InitTypes(); DialogWindow.InitTypes(); ControlSettings.InitTypes(); ProductionPanel.InitTypes(); ProductionPanelShowSubclass.InitTypes(); Scheme.InitTypes(); AreaScreenSubstrate.InitTypes(); ItemSpecificationPanel.InitTypes(); CompactCharacteristicPanel.InitTypes(); SlotItemAddress.InitTypes(); GridView.InitTypes(); SwapOperation.InitTypes(); InteractionButtonsContainer.InitTypes(); ContextMenuButton.InitTypes(); RagfairScreen.InitTypes(); OfferViewList.InitTypes(); FiltersPanel.InitTypes(); CategoryView.InitTypes(); QuestCache.InitTypes(); ItemMarketPricesPanel.InitTypes(); AddOfferWindow.InitTypes(); ItemUiContext.InitTypes(); Money.InitTypes(); TraderScreensGroup.InitTypes(); TradingItemView.InitTypes(); GridWindow.InitTypes(); GridSortPanel.InitTypes(); RepairStrategy.InitTypes(); RepairKit.InitTypes(); ContextMenuHelper.InitTypes(); RagfairNewOfferItemView.InitTypes(); TradingTableGridView.InitTypes(); ItemReceiver.InitTypes(); InventoryInteractions.InitTypes(); TradingInteractions.InitTypes(); TransferInteractions.InitTypes(); InventoryScreen.InitTypes(); ScavengerInventoryScreen.InitTypes(); LocalizedText.InitTypes(); GameWorld.InitTypes(); MoveOperationResult.InitTypes(); AddOperationResult.InitTypes(); } public abstract class Wrapper(object value) { public object Value { get; protected set; } = value; } public class UIElement(object value) : Wrapper(value) { private static FieldInfo UIField; public static void InitUITypes() { UIField = AccessTools.Field(typeof(EFT.UI.UIElement), "UI"); } public UIContext UI { get { return new UIContext(UIField.GetValue(Value)); } } } public class UIInputNode(object value) : Wrapper(value) { private static FieldInfo UIField; public static void InitUITypes() { UIField = AccessTools.Field(typeof(EFT.UI.UIInputNode), "UI"); } public UIContext UI { get { return new UIContext(UIField.GetValue(Value)); } } } public class UIContext(object value) : Wrapper(value) { public static Type Type { get; private set; } private static MethodInfo AddDisposableActionMethod; public static void InitTypes() { Type = AccessTools.Field(typeof(EFT.UI.UIElement), "UI").FieldType; AddDisposableActionMethod = AccessTools.Method(Type, "AddDisposable", [typeof(Action)]); } public void AddDisposable(Action destroy) => AddDisposableActionMethod.Invoke(Value, [destroy]); } public class DialogWindow(object value) : UIInputNode(value) { public static Type Type { get; private set; } private static MethodInfo AcceptMethod; public static void InitTypes() { Type = typeof(EFT.UI.MessageWindow).BaseType; // DialogWindow AcceptMethod = AccessTools.Method(Type, "Accept"); } public void Accept() => AcceptMethod.Invoke(Value, []); } public class ControlSettings(object value) : Wrapper(value) { public static Type Type { get; private set; } private static MethodInfo GetKeyNameMethod; public static void InitTypes() { Type = PatchConstants.EftTypes.Single(x => x.GetMethod("GetBoundItemNames") != null); // GClass961 GetKeyNameMethod = AccessTools.Method(Type, "GetKeyName"); } public string GetKeyName(EGameKey key) => (string)GetKeyNameMethod.Invoke(Value, [key]); } public class ProductionPanel(object value) : Wrapper(value) { public static Type Type { get; private set; } private static FieldInfo SearchInputFieldField; private static FieldInfo ProductionBuildsField; public static void InitTypes() { Type = typeof(EFT.Hideout.ProductionPanel); SearchInputFieldField = AccessTools.Field(Type, "_searchInputField"); ProductionBuildsField = AccessTools.GetDeclaredFields(Type).Single(f => f.FieldType.GetElementType() == typeof(ProductionBuildAbstractClass)); } public ValidationInputField SeachInputField { get { return (ValidationInputField)SearchInputFieldField.GetValue(Value); } } public ProductionBuildAbstractClass[] ProductionBuilds { get { return (ProductionBuildAbstractClass[])ProductionBuildsField.GetValue(Value); } } } public class ProductionPanelShowSubclass(object value) : Wrapper(value) { public static Type Type { get; private set; } private static FieldInfo ProductionPanelField; public static void InitTypes() { Type = typeof(EFT.Hideout.ProductionPanel).GetNestedTypes().Single(t => t.IsClass && t.GetField("availableSearch") != null); // ProductionPanel.Class1659 ProductionPanelField = AccessTools.Field(Type, "productionPanel_0"); } public EFT.Hideout.ProductionPanel ProductionPanel { get { return (EFT.Hideout.ProductionPanel)ProductionPanelField.GetValue(Value); } } } public class Scheme(object value) : Wrapper(value) { public static Type Type { get; private set; } private static FieldInfo EndProductField; public static void InitTypes() { Type = PatchConstants.EftTypes.Single(t => t.GetField("endProduct") != null); // GClass1923 EndProductField = AccessTools.Field(Type, "endProduct"); } public string EndProduct { get { return (string)EndProductField.GetValue(Value); } } } public class AreaScreenSubstrate(object value) : Wrapper(value) { public static Type Type { get; private set; } private static FieldInfo ContentLayoutField; public static void InitTypes() { Type = typeof(EFT.Hideout.AreaScreenSubstrate); ContentLayoutField = AccessTools.Field(Type, "_contentLayout"); } public LayoutElement ContentLayout { get { return (LayoutElement)ContentLayoutField.GetValue(Value); } } } public class ItemSpecificationPanel(object value) : Wrapper(value) { public static Type Type { get; private set; } private static FieldInfo CompactCharacteristicPanelsField; private static FieldInfo CompactCharacteristicDropdownsField; private static MethodInfo RefreshMethod; public static void InitTypes() { Type = typeof(EFT.UI.ItemSpecificationPanel); CompactCharacteristicPanelsField = AccessTools.GetDeclaredFields(Type).Single(f => typeof(IEnumerable>).IsAssignableFrom(f.FieldType)); CompactCharacteristicDropdownsField = AccessTools.GetDeclaredFields(Type).Single(f => typeof(IEnumerable>).IsAssignableFrom(f.FieldType)); RefreshMethod = AccessTools.Method(Type, nameof(EFT.UI.ItemSpecificationPanel.smethod_1), null, [typeof(EFT.UI.CompactCharacteristicPanel)]); } public IEnumerable> CompactCharacteristicPanels { get { return (IEnumerable>)CompactCharacteristicPanelsField.GetValue(Value); } set { CompactCharacteristicPanelsField.SetValue(Value, value); } } public IEnumerable> CompactCharacteristicDropdowns { get { return (IEnumerable>)CompactCharacteristicDropdownsField.GetValue(Value); } set { CompactCharacteristicDropdownsField.SetValue(Value, value); } } public static IEnumerable> CreateCompactCharacteristicPanels( IEnumerable items, EFT.UI.CompactCharacteristicPanel template, Transform transform, Action showAction) { return (IEnumerable>)Activator.CreateInstance(CompactCharacteristicPanelsField.FieldType, [items, template, transform, showAction]); } public static void Refresh(IEnumerable> viewList, IReadOnlyCollection changedList) => RefreshMethod.Invoke(null, [viewList, changedList]); } public class CompactCharacteristicPanel(object value) : Wrapper(value) { public static Type Type { get; private set; } private static FieldInfo ItemAttributeField; private static FieldInfo CompareItemAttributeField; public static void InitTypes() { Type = typeof(EFT.UI.CompactCharacteristicPanel); ItemAttributeField = AccessTools.Field(Type, "ItemAttribute"); CompareItemAttributeField = AccessTools.Field(Type, "CompareItemAttribute"); } public ItemAttributeClass ItemAttribute { get { return (ItemAttributeClass)ItemAttributeField.GetValue(Value); } } public ItemAttributeClass CompareItemAttribute { get { return (ItemAttributeClass)CompareItemAttributeField.GetValue(Value); } } } public class SlotItemAddress(object value) : Wrapper(value) { public static Type Type { get; private set; } private static FieldInfo SlotField; public static void InitTypes() { Type = PatchConstants.EftTypes.Single(t => typeof(ItemAddress).IsAssignableFrom(t) && t.GetField("Slot") != null); // GClass2783 SlotField = AccessTools.Field(Type, "Slot"); } public static ItemAddress Create(Slot slot) { return (ItemAddress)Activator.CreateInstance(Type, [slot]); } public Slot Slot { get { return (Slot)SlotField.GetValue(Value); } } } public class GridView(object value) : Wrapper(value) { public static Type Type { get; private set; } 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 SwapOperation(object value) : Wrapper(value) { public static Type Type { get; private set; } private static Type CanAcceptType; private static MethodInfo ImplicitCastToGridViewCanAcceptOperationMethod; public static void InitTypes() { Type = AccessTools.Method(typeof(InteractionsHandlerClass), nameof(InteractionsHandlerClass.Swap)).ReturnType; // GStruct414 CanAcceptType = AccessTools.Method(typeof(EFT.UI.DragAndDrop.GridView), "CanAccept").GetParameters()[2].ParameterType.GetElementType(); // GStruct413, parameter is a ref type, get underlying type ImplicitCastToGridViewCanAcceptOperationMethod = Type.GetMethods().Single(m => m.Name == "op_Implicit" && m.ReturnType == CanAcceptType); } public IInventoryEventResult ToGridViewCanAcceptOperation() => (IInventoryEventResult)ImplicitCastToGridViewCanAcceptOperationMethod.Invoke(null, [Value]); } public class InteractionButtonsContainer(object value) : UIElement(value) { public static Type Type { get; private set; } private static FieldInfo ButtonTemplateField; private static FieldInfo ContainerField; private static FieldInfo ContextMenuField; private static FieldInfo ContextMenuButtonField; public static void InitTypes() { Type = typeof(EFT.UI.InteractionButtonsContainer); ButtonTemplateField = AccessTools.Field(Type, "_buttonTemplate"); ContainerField = AccessTools.Field(Type, "_buttonsContainer"); ContextMenuField = AccessTools.Field(Type, "simpleContextMenu_0"); ContextMenuButtonField = AccessTools.Field(Type, "simpleContextMenuButton_0"); } public SimpleContextMenuButton ButtonTemplate { get { return (SimpleContextMenuButton)ButtonTemplateField.GetValue(Value); } } public Transform Container { get { return (Transform)ContainerField.GetValue(Value); } } public SimpleContextMenu ContextMenu { get { return (SimpleContextMenu)ContextMenuField.GetValue(Value); } } public SimpleContextMenuButton ContextMenuButton { get { return (SimpleContextMenuButton)ContextMenuButtonField.GetValue(Value); } } } public class ContextMenuButton(object value) : Wrapper(value) { public static Type Type { get; private set; } private static FieldInfo TextField; public static void InitTypes() { Type = typeof(EFT.UI.ContextMenuButton); TextField = AccessTools.Field(Type, "_text"); } public TextMeshProUGUI Text { get { return (TextMeshProUGUI)TextField.GetValue(Value); } } } public class RagfairScreen(object value) : UIInputNode(value) { public static Type Type { get; private set; } private static FieldInfo OfferViewListField; private static FieldInfo RagfairClassField; public static void InitTypes() { Type = typeof(EFT.UI.Ragfair.RagfairScreen); OfferViewListField = AccessTools.Field(Type, "offerViewList_0"); RagfairClassField = AccessTools.GetDeclaredFields(Type).Single(f => f.FieldType == typeof(RagFairClass)); } public EFT.UI.Ragfair.OfferViewList OfferViewList { get { return (EFT.UI.Ragfair.OfferViewList)OfferViewListField.GetValue(Value); } } public RagFairClass RagfairClass { get { return (RagFairClass)RagfairClassField.GetValue(Value); } } } public class OfferViewList(object value) : Wrapper(value) { public static Type Type { get; private set; } private static FieldInfo ScrollerField; private static FieldInfo FiltersPanelField; public static void InitTypes() { Type = typeof(EFT.UI.Ragfair.OfferViewList); ScrollerField = AccessTools.Field(Type, "_scroller"); FiltersPanelField = AccessTools.Field(Type, "_filtersPanel"); } public LightScroller Scroller { get { return (LightScroller)ScrollerField.GetValue(Value); } } public EFT.UI.Ragfair.FiltersPanel FiltersPanel { get { return (EFT.UI.Ragfair.FiltersPanel)FiltersPanelField.GetValue(Value); } } } public class CategoryView(object value) : Wrapper(value) { public static Type Type { get; private set; } private static FieldInfo IsOpenField; public static void InitTypes() { Type = typeof(EFT.UI.Ragfair.CategoryView); IsOpenField = AccessTools.Field(Type, "bool_3"); } public bool IsOpen { get { return (bool)IsOpenField.GetValue(Value); } } } public class FiltersPanel(object value) : Wrapper(value) { public static Type Type { get; private set; } private static PropertyInfo DescendingProperty; private static FieldInfo BarterButtonField; private static FieldInfo RatingButtonField; private static FieldInfo OfferItemButtonField; private static FieldInfo PriceButtonField; private static FieldInfo ExpirationButtonField; public static void InitTypes() { Type = typeof(EFT.UI.Ragfair.FiltersPanel); DescendingProperty = AccessTools.Property(Type, "Boolean_0"); BarterButtonField = AccessTools.Field(Type, "_barterButton"); RatingButtonField = AccessTools.Field(Type, "_ratingButton"); OfferItemButtonField = AccessTools.Field(Type, "_offerItemButton"); PriceButtonField = AccessTools.Field(Type, "_priceButton"); ExpirationButtonField = AccessTools.Field(Type, "_expirationButton"); } public bool SortDescending { get { return (bool)DescendingProperty.GetValue(Value); } set { DescendingProperty.SetValue(Value, value); } } public RagfairFilterButton BarterButton { get { return (RagfairFilterButton)BarterButtonField.GetValue(Value); } } public RagfairFilterButton RatingButton { get { return (RagfairFilterButton)RatingButtonField.GetValue(Value); } } public RagfairFilterButton OfferItemButton { get { return (RagfairFilterButton)OfferItemButtonField.GetValue(Value); } } public RagfairFilterButton PriceButton { get { return (RagfairFilterButton)PriceButtonField.GetValue(Value); } } public RagfairFilterButton ExpirationButton { get { return (RagfairFilterButton)ExpirationButtonField.GetValue(Value); } } } public class QuestCache(object value) : Wrapper(value) { public static Type Type { get; private set; } private static PropertyInfo InstanceProperty; private static MethodInfo GetAllQuestTemplatesMethod; public static void InitTypes() { Type = PatchConstants.EftTypes.Single(t => t.GetMethod("GetAllQuestTemplates") != null); // GClass3212 InstanceProperty = AccessTools.Property(Type, "Instance"); GetAllQuestTemplatesMethod = AccessTools.Method(Type, "GetAllQuestTemplates"); } public static QuestCache Instance { get { return new QuestCache(InstanceProperty.GetValue(null)); } } public IReadOnlyCollection GetAllQuestTemplates() => (IReadOnlyCollection)GetAllQuestTemplatesMethod.Invoke(Value, []); } public class ItemMarketPricesPanel(object value) : Wrapper(value) { public static Type Type { get; private set; } private static FieldInfo LowestLabelField; private static FieldInfo AverageLabelField; private static FieldInfo MaximumLabelField; public static void InitTypes() { Type = typeof(EFT.UI.Ragfair.ItemMarketPricesPanel); LowestLabelField = AccessTools.Field(Type, "_lowestLabel"); AverageLabelField = AccessTools.Field(Type, "_averageLabel"); MaximumLabelField = AccessTools.Field(Type, "_maximumLabel"); } public TextMeshProUGUI LowestLabel { get { return (TextMeshProUGUI)LowestLabelField.GetValue(Value); } } public TextMeshProUGUI AverageLabel { get { return (TextMeshProUGUI)AverageLabelField.GetValue(Value); } } public TextMeshProUGUI MaximumLabel { get { return (TextMeshProUGUI)MaximumLabelField.GetValue(Value); } } } public class AddOfferWindow(object value) : Wrapper(value) { public static Type Type { get; private set; } private static FieldInfo RagfairField; private static FieldInfo BulkOfferField; public static void InitTypes() { Type = typeof(EFT.UI.Ragfair.AddOfferWindow); RagfairField = AccessTools.GetDeclaredFields(Type).Single(t => t.FieldType == typeof(RagFairClass)); BulkOfferField = AccessTools.Field(Type, "bool_0"); } public RagFairClass Ragfair { get { return (RagFairClass)RagfairField.GetValue(Value); } } public bool BulkOffer { get { return (bool)BulkOfferField.GetValue(Value); } } } public class ItemUiContext(object value) : Wrapper(value) { public static Type Type { get; private set; } private static FieldInfo InventoryControllerField; private static FieldInfo GridWindowTemplateField; private static PropertyInfo ItemContextProperty; public static void InitTypes() { Type = typeof(EFT.UI.ItemUiContext); InventoryControllerField = AccessTools.GetDeclaredFields(Type).Single(t => t.FieldType == typeof(InventoryControllerClass)); GridWindowTemplateField = AccessTools.Field(Type, "_gridWindowTemplate"); ItemContextProperty = AccessTools.GetDeclaredProperties(Type).Single(p => p.PropertyType == typeof(ItemContextAbstractClass)); } public InventoryControllerClass InventoryController { get { return (InventoryControllerClass)InventoryControllerField.GetValue(Value); } } public EFT.UI.GridWindow GridWindowTemplate { get { return (EFT.UI.GridWindow)GridWindowTemplateField.GetValue(Value); } } public ItemContextAbstractClass ItemContext { get { return (ItemContextAbstractClass)ItemContextProperty.GetValue(Value); } } } public static class Money { public static Type Type { get; private set; } private static MethodInfo GetMoneySumsMethod; public static void InitTypes() { Type = PatchConstants.EftTypes.Single(t => t.GetMethod("GetMoneySums", BindingFlags.Public | BindingFlags.Static) != null); GetMoneySumsMethod = AccessTools.Method(Type, "GetMoneySums"); } public static Dictionary GetMoneySums(IEnumerable items) => (Dictionary)GetMoneySumsMethod.Invoke(null, [items]); } public class TraderScreensGroup(object value) : UIInputNode(value) { public static Type Type { get; private set; } private static FieldInfo BuyTabField; private static FieldInfo SellTabField; public static void InitTypes() { Type = typeof(EFT.UI.TraderScreensGroup); BuyTabField = AccessTools.Field(Type, "_buyTab"); SellTabField = AccessTools.Field(Type, "_sellTab"); } public Tab BuyTab { get { return (Tab)BuyTabField.GetValue(Value); } } public Tab SellTab { get { return (Tab)SellTabField.GetValue(Value); } } } public class TradingItemView(object value) : Wrapper(value) { 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) { public static Type Type { get; private set; } private static FieldInfo GridSortPanelField; private static FieldInfo LootItemField; public static void InitTypes() { Type = typeof(EFT.UI.GridWindow); GridSortPanelField = AccessTools.Field(Type, "_sortPanel"); LootItemField = AccessTools.GetDeclaredFields(Type).Single(f => f.FieldType == typeof(LootItemClass)); } public EFT.UI.DragAndDrop.GridSortPanel GridSortPanel { get { return (EFT.UI.DragAndDrop.GridSortPanel)GridSortPanelField.GetValue(Value); } } public LootItemClass LootItem { get { return (LootItemClass)LootItemField.GetValue(Value); } } } public class GridSortPanel(object value) : Wrapper(value) { public static Type Type { get; private set; } private static FieldInfo ButtonField; public static void InitTypes() { Type = typeof(EFT.UI.DragAndDrop.GridSortPanel); ButtonField = AccessTools.Field(Type, "_button"); } public Button Button { get { return (Button)ButtonField.GetValue(Value); } } } public class RepairerParametersPanel(object value) : UIElement(value) { } public class MessageWindow(object value) : UIInputNode(value) { } public class RepairStrategy(object value) : Wrapper(value) { public static Type Type { get; private set; } private static Type ArmorStrategyType; private static Type DefaultStrategyType; private static PropertyInfo RepairersProperty; private static PropertyInfo CurrentRepairerProperty; private static MethodInfo HowMuchRepairScoresCanAcceptMethod; private static MethodInfo TemplateDurabilityMethod; private static MethodInfo GetRepairPriceMethod; private static MethodInfo GetCurrencyPriceMethod; private static MethodInfo RepairItemMethod; private static MethodInfo DurabilityMethod; private static MethodInfo CanRepairMethod; private static MethodInfo BrokenItemErrorMethod; private static MethodInfo IsNoCorrespondingAreaMethod; public static void InitTypes() { Type = PatchConstants.EftTypes.Single(t => t.IsInterface && t.GetMethod("HowMuchRepairScoresCanAccept") != null); // GInterface34 ArmorStrategyType = PatchConstants.EftTypes.Single(t => t.IsClass && Type.IsAssignableFrom(t) && t.GetField("repairableComponent_0", BindingFlags.Instance | BindingFlags.NonPublic) == null); // GClass805 DefaultStrategyType = PatchConstants.EftTypes.Single(t => Type.IsAssignableFrom(t) && t.GetField("repairableComponent_0", BindingFlags.Instance | BindingFlags.NonPublic) != null); // GClass804 RepairersProperty = AccessTools.Property(Type, "Repairers"); CurrentRepairerProperty = AccessTools.Property(Type, "CurrentRepairer"); HowMuchRepairScoresCanAcceptMethod = AccessTools.Method(Type, "HowMuchRepairScoresCanAccept"); TemplateDurabilityMethod = AccessTools.Method(Type, "TemplateDurability"); GetRepairPriceMethod = AccessTools.Method(Type, "GetRepairPrice"); GetCurrencyPriceMethod = AccessTools.Method(Type, "GetCurrencyPrice"); RepairItemMethod = AccessTools.Method(Type, "RepairItem"); DurabilityMethod = AccessTools.Method(Type, "Durability"); CanRepairMethod = AccessTools.Method(Type, "CanRepair"); BrokenItemErrorMethod = AccessTools.Method(Type, "BrokenItemError"); IsNoCorrespondingAreaMethod = AccessTools.Method(Type, "IsNoCorrespondingArea"); } public static RepairStrategy Create(Item item, RepairControllerClass repairController) { if (item.GetItemComponent() != null) { return new RepairStrategy(Activator.CreateInstance(ArmorStrategyType, [item, repairController])); } return new RepairStrategy(Activator.CreateInstance(DefaultStrategyType, [item, repairController])); } public IEnumerable Repairers { get { return (IEnumerable)RepairersProperty.GetValue(Value); } } public IRepairer CurrentRepairer { get { return (IRepairer)CurrentRepairerProperty.GetValue(Value); } set { CurrentRepairerProperty.SetValue(Value, value); } } public float HowMuchRepairScoresCanAccept() => (float)HowMuchRepairScoresCanAcceptMethod.Invoke(Value, []); public int TemplateDurability() => (int)TemplateDurabilityMethod.Invoke(Value, []); public double GetRepairPrice(float repairValue, object repairKit) => (double)GetRepairPriceMethod.Invoke(Value, [repairValue, repairKit]); public int GetCurrencyPrice(float amount) => (int)GetCurrencyPriceMethod.Invoke(Value, [amount]); public Task RepairItem(float repairAmount, object repairKit) => (Task)RepairItemMethod.Invoke(Value, [repairAmount, repairKit]); public float Durability() => (float)DurabilityMethod.Invoke(Value, []); public bool CanRepair(IRepairer repairer, string[] excludedCategories) => (bool)CanRepairMethod.Invoke(Value, [repairer, excludedCategories]); public bool BrokenItemError() => (bool)BrokenItemErrorMethod.Invoke(Value, []); public bool IsNoCorrespondingArea() => (bool)IsNoCorrespondingAreaMethod.Invoke(Value, []); } public class RepairKit(object value) : Wrapper(value) { public static Type Type { get; private set; } private static MethodInfo GetRepairPointsMethod; public static void InitTypes() { Type = R.RepairStrategy.Type.GetMethod("GetRepairPrice").GetParameters()[1].ParameterType; // GClass803 GetRepairPointsMethod = AccessTools.Method(Type, "GetRepairPoints"); } public float GetRepairPoints() => (float)GetRepairPointsMethod.Invoke(Value, []); } public class ContextMenuHelper(object value) : Wrapper(value) { public static Type Type { get; private set; } private static FieldInfo InsuranceCompanyField; public static void InitTypes() { Type = PatchConstants.EftTypes.Single(t => t.GetProperty("IsOwnedByPlayer") != null); // GClass3074 InsuranceCompanyField = AccessTools.GetDeclaredFields(Type).Single(f => f.FieldType == typeof(InsuranceCompanyClass)); } public InsuranceCompanyClass InsuranceCompany { get { return (InsuranceCompanyClass)InsuranceCompanyField.GetValue(Value); } } } public class RagfairNewOfferItemView(object value) : Wrapper(value) { public static Type Type { get; private set; } private static FieldInfo SelectedMarkField; private static FieldInfo SelectedBackgroundField; public static void InitTypes() { Type = typeof(EFT.UI.DragAndDrop.RagfairNewOfferItemView); SelectedMarkField = AccessTools.Field(Type, "_selectedMark"); SelectedBackgroundField = AccessTools.Field(Type, "_selectedBackground"); } 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 class ItemReceiver(object value) : Wrapper(value) // GClass1855 { public static Type Type { get; private set; } private static FieldInfo InventoryControllerField; public static void InitTypes() { Type = PatchConstants.EftTypes.Single(t => { FieldInfo field = t.GetField("localQuestControllerClass", BindingFlags.NonPublic | BindingFlags.Instance); return field != null && field.IsInitOnly; }); InventoryControllerField = Type.GetFields(BindingFlags.NonPublic | BindingFlags.Instance).Single(f => typeof(InventoryControllerClass).IsAssignableFrom(f.FieldType)); } public InventoryControllerClass InventoryController { get { return (InventoryControllerClass)InventoryControllerField.GetValue(Value); } } } public class InventoryInteractions(object value) : Wrapper(value) { public static Type Type { get; private set; } public static Type CompleteType { get; private set; } public static void InitTypes() { Type = PatchConstants.EftTypes.Single(t => t.GetField("HIDEOUT_WEAPON_MODIFICATION_REQUIRED") != null); // GClass3045 CompleteType = PatchConstants.EftTypes.Single(t => t != Type && Type.IsAssignableFrom(t)); // GClass3046 } } public class TradingInteractions(object value) : Wrapper(value) { public static Type Type { get; private set; } private static FieldInfo ItemField; private static readonly HashSet Interactions = [ EItemInfoButton.Inspect, EItemInfoButton.Uninstall, EItemInfoButton.Examine, EItemInfoButton.Open, EItemInfoButton.Insure, EItemInfoButton.Repair, EItemInfoButton.Modding, EItemInfoButton.EditBuild, EItemInfoButton.FilterSearch, EItemInfoButton.LinkedSearch, EItemInfoButton.NeededSearch, EItemInfoButton.Tag, EItemInfoButton.ResetTag, EItemInfoButton.TurnOn, EItemInfoButton.TurnOff, EItemInfoButton.Fold, EItemInfoButton.Unfold, EItemInfoButton.Disassemble, EItemInfoButton.Discard ]; public static void InitTypes() { // GClass3054 Type = PatchConstants.EftTypes.Single(t => { var enumerableField = t.GetField("ienumerable_2", BindingFlags.NonPublic | BindingFlags.Static); if (enumerableField != null) { var enumerable = (IEnumerable)enumerableField.GetValue(null); return Interactions.SetEquals(enumerable); } return false; }); ItemField = AccessTools.Field(Type, "item_0"); } public Item Item { get { return (Item)ItemField.GetValue(Value); } } } public class TransferInteractions(object value) : Wrapper(value) { public static Type Type { get; private set; } private static readonly HashSet Interactions = [ EItemInfoButton.Inspect, EItemInfoButton.Uninstall, EItemInfoButton.Examine, EItemInfoButton.Equip, EItemInfoButton.Open, EItemInfoButton.Fold, EItemInfoButton.Unfold, EItemInfoButton.Disassemble, EItemInfoButton.Discard ]; public static void InitTypes() { // GClass3057 Type = PatchConstants.EftTypes.Single(t => { var enumerableField = t.GetField("ienumerable_2", BindingFlags.NonPublic | BindingFlags.Static); if (enumerableField != null) { var enumerable = (IEnumerable)enumerableField.GetValue(null); return Interactions.SetEquals(enumerable); } return false; }); } } public class InventoryScreen(object value) : UIInputNode(value) { public static Type Type { get; private set; } private static FieldInfo SimpleStashPanelField; public static void InitTypes() { Type = typeof(EFT.UI.InventoryScreen); SimpleStashPanelField = AccessTools.Field(Type, "_simpleStashPanel"); } public SimpleStashPanel SimpleStashPanel { get { return (SimpleStashPanel)SimpleStashPanelField.GetValue(Value); } } } public class ScavengerInventoryScreen(object value) : UIInputNode(value) { public static Type Type { get; private set; } private static FieldInfo SimpleStashPanelField; public static void InitTypes() { Type = typeof(EFT.UI.ScavengerInventoryScreen); SimpleStashPanelField = AccessTools.Field(Type, "_simpleStashPanel"); } public SimpleStashPanel SimpleStashPanel { get { return (SimpleStashPanel)SimpleStashPanelField.GetValue(Value); } } } public class LocalizedText(object value) : UIElement(value) { public static Type Type { get; private set; } private static FieldInfo StringCaseField; public static void InitTypes() { Type = typeof(EFT.UI.LocalizedText); StringCaseField = AccessTools.Field(Type, "_stringCase"); } public EStringCase StringCase { get { return (EStringCase)StringCaseField.GetValue(Value); } set { StringCaseField.SetValue(Value, value); } } } public class GameWorld(object value) : Wrapper(value) { public static Type Type { get; private set; } private static FieldInfo TraderControllerField; public static void InitTypes() { Type = typeof(EFT.GameWorld); TraderControllerField = AccessTools.Field(Type, "traderControllerClass"); } public TraderControllerClass TraderController { get { return (TraderControllerClass)TraderControllerField.GetValue(Value); } } } public class MoveOperationResult(object value) : Wrapper(value) { public static Type Type { get; private set; } private static FieldInfo AddOperationField; public static void InitTypes() { Type = typeof(MoveOperation); AddOperationField = AccessTools.Field(Type, "gclass2798_0"); } public AddOperation AddOperation { get { return (AddOperation)AddOperationField.GetValue(Value); } } } public class AddOperationResult(object value) : Wrapper(value) { public static Type Type { get; private set; } private static FieldInfo ResizeOperationField; public static void InitTypes() { Type = typeof(AddOperation); ResizeOperationField = AccessTools.Field(Type, "gclass2803_0"); } public ResizeOperation ResizeOperation { get { return (ResizeOperation)ResizeOperationField.GetValue(Value); } } } } public static class RExtentensions { public static R.UIElement R(this UIElement value) => new(value); public static R.UIInputNode R(this UIInputNode value) => new(value); public static R.ProductionPanel R(this ProductionPanel value) => new(value); public static R.AreaScreenSubstrate R(this AreaScreenSubstrate value) => new(value); public static R.ItemSpecificationPanel R(this ItemSpecificationPanel value) => new(value); public static R.CompactCharacteristicPanel R(this CompactCharacteristicPanel value) => new(value); public static R.GridView R(this GridView value) => new(value); public static R.InteractionButtonsContainer R(this InteractionButtonsContainer value) => new(value); public static R.ContextMenuButton R(this ContextMenuButton value) => new(value); public static R.RagfairScreen R(this RagfairScreen value) => new(value); public static R.OfferViewList R(this OfferViewList value) => new(value); public static R.CategoryView R(this CategoryView value) => new(value); public static R.FiltersPanel R(this FiltersPanel value) => new(value); public static R.ItemMarketPricesPanel R(this ItemMarketPricesPanel value) => new(value); public static R.AddOfferWindow R(this AddOfferWindow value) => new(value); public static R.ItemUiContext R(this ItemUiContext value) => new(value); public static R.TraderScreensGroup R(this TraderScreensGroup value) => new(value); public static R.TradingItemView R(this TradingItemView value) => new(value); public static R.GridWindow R(this GridWindow value) => new(value); public static R.GridSortPanel R(this GridSortPanel value) => new(value); 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); public static R.InventoryScreen R(this InventoryScreen value) => new(value); public static R.ScavengerInventoryScreen R(this ScavengerInventoryScreen value) => new(value); public static R.LocalizedText R(this LocalizedText value) => new(value); public static R.GameWorld R(this GameWorld value) => new(value); public static R.MoveOperationResult R(this MoveOperation value) => new(value); public static R.AddOperationResult R(this AddOperation value) => new(value); }