Update for SPT 3.9.0

This commit is contained in:
Tyfon
2024-07-06 21:50:51 -07:00
parent 531d8fce06
commit 238e28dbc3
55 changed files with 427 additions and 407 deletions

View File

@@ -41,7 +41,7 @@ namespace UIFixes
{
text = string.Format("<b><color=#C6C4B2>{0}</color></b>", repairer.LocalizedName);
}
else if (repairer is GClass802 repairKit)
else if (repairer is GClass803 repairKit)
{
float pointsLeft = repairKit.GetRepairPoints();
double amount = repairStrategy.GetRepairPrice(repairAmount, repairKit);
@@ -96,7 +96,7 @@ namespace UIFixes
float repairAmount = GetClampedRepairAmount(repairStrategy);
if (repairer is GClass802 repairKit)
if (repairer is GClass803 repairKit)
{
float pointsLeft = repairKit.GetRepairPoints();
double amount = repairStrategy.GetRepairPrice(repairAmount, repairKit);

View File

@@ -5,8 +5,6 @@ using System.Collections.Generic;
using System.Linq;
using UnityEngine;
using GridItemAddress = GClass2769;
namespace UIFixes
{
public static class MultiGrid
@@ -14,7 +12,7 @@ namespace UIFixes
private static readonly Dictionary<Item, Dictionary<StashGridClass, Vector2Int>> GridOffsets = [];
private static readonly Dictionary<Item, Dictionary<int, Dictionary<int, StashGridClass>>> GridsByLocation = [];
public static LocationInGrid GetGridLocation(GridItemAddress realAddress)
public static LocationInGrid GetGridLocation(ItemAddressClass realAddress)
{
if (!IsMultiGrid(realAddress))
{
@@ -25,7 +23,7 @@ namespace UIFixes
return new LocationInGrid(realAddress.LocationInGrid.x + gridOffset.x, realAddress.LocationInGrid.y + gridOffset.y, realAddress.LocationInGrid.r);
}
public static GridItemAddress GetRealAddress(StashGridClass originGrid, LocationInGrid multigridLocation)
public static ItemAddressClass GetRealAddress(StashGridClass originGrid, LocationInGrid multigridLocation)
{
if (!IsMultiGrid(originGrid.ParentItem))
{
@@ -33,7 +31,7 @@ namespace UIFixes
multigridLocation.x = Math.Max(0, Math.Min(originGrid.GridWidth.Value, multigridLocation.x));
multigridLocation.y = Math.Max(0, Math.Min(originGrid.GridHeight.Value, multigridLocation.y));
return new GridItemAddress(originGrid, multigridLocation);
return new ItemAddressClass(originGrid, multigridLocation);
}
var gridsByLocation = GridsByLocation[originGrid.ParentItem];
@@ -54,7 +52,7 @@ namespace UIFixes
Vector2Int offsets = GridOffsets[originGrid.ParentItem][grid];
LocationInGrid location = new(x - offsets.x, y - offsets.y, multigridLocation.r);
return new GridItemAddress(grid, location);
return new ItemAddressClass(grid, location);
}
public static void Cache(GridView initialGridView)
@@ -108,25 +106,9 @@ namespace UIFixes
GridOffsets.Add(parent, gridOffsets);
GridsByLocation.Add(parent, gridsByLocation);
// Best effort attempt at cleanup
IItemOwner owner = parent.Owner;
if (owner != null)
{
void onRemoveItem(GEventArgs3 eventArgs)
{
if (GridOffsets.ContainsKey(eventArgs.Item))
{
GridOffsets.Remove(eventArgs.Item);
GridsByLocation.Remove(eventArgs.Item);
owner.RemoveItemEvent -= onRemoveItem;
}
};
owner.RemoveItemEvent += onRemoveItem;
}
}
private static bool IsMultiGrid(GridItemAddress itemAddress)
private static bool IsMultiGrid(ItemAddressClass itemAddress)
{
return IsMultiGrid(itemAddress.Container.ParentItem);
}

View File

@@ -7,8 +7,6 @@ using System.Threading.Tasks;
using TMPro;
using UnityEngine;
using GridItemAddress = GClass2769;
namespace UIFixes
{
public class MultiSelect
@@ -202,9 +200,9 @@ namespace UIFixes
var result = ItemContexts
.Where(ic => first == null || ic.Item != first.Item)
.OrderByDescending(ic => ic.ItemAddress is GridItemAddress)
.OrderByDescending(ic => ic.ItemAddress is ItemAddressClass)
.ThenByDescending(ic => first != null && first.ItemAddress.Container.ParentItem == ic.ItemAddress.Container.ParentItem)
.ThenBy(ic => ic.ItemAddress is GridItemAddress selectedGridAddress ? gridOrder(MultiGrid.GetGridLocation(selectedGridAddress)) : 0);
.ThenBy(ic => ic.ItemAddress is ItemAddressClass selectedGridAddress ? gridOrder(MultiGrid.GetGridLocation(selectedGridAddress)) : 0);
return first != null && prepend ? result.Prepend(first) : result;
}
@@ -238,7 +236,7 @@ namespace UIFixes
private static bool InteractionAvailable(ItemContextClass itemContext, EItemInfoButton interaction, ItemUiContext itemUiContext)
{
// Since itemContext is for "drag", no context actions are allowed. Get the underlying "inventory" context
ItemContextAbstractClass innerContext = itemContext.GClass2813_0;
ItemContextAbstractClass innerContext = itemContext.ItemContextAbstractClass;
if (innerContext == null)
{
return false;
@@ -283,7 +281,7 @@ namespace UIFixes
var taskSerializer = itemUiContext.gameObject.AddComponent<ItemContextTaskSerializer>();
taskSerializer.Initialize(
SortedItemContexts().Where(ic => InteractionAvailable(ic, EItemInfoButton.Unequip, itemUiContext)),
itemContext => itemUiContext.Uninstall(itemContext.GClass2813_0));
itemContext => itemUiContext.Uninstall(itemContext.ItemContextAbstractClass));
itemUiContext.Tooltip?.Close();
}
@@ -291,19 +289,23 @@ namespace UIFixes
public static Task LoadAmmoAll(ItemUiContext itemUiContext, string ammoTemplateId, bool allOrNothing)
{
StopLoading();
StopLoading(true);
if (!allOrNothing || InteractionCount(EItemInfoButton.LoadAmmo, itemUiContext) == Count)
{
// Call Initialize() before setting UnloadSerializer so that the initial synchronous call to StopProcesses()->StopUnloading() doesn't immediately cancel this
var taskSerializer = itemUiContext.gameObject.AddComponent<ItemContextTaskSerializer>();
Task result = taskSerializer.Initialize(
SortedItemContexts().Where(ic => ic.Item is MagazineClass && InteractionAvailable(ic, EItemInfoButton.LoadAmmo, itemUiContext)),
itemContext => itemUiContext.LoadAmmoByType(itemContext.Item as MagazineClass, ammoTemplateId, itemContext.UpdateView));
LoadUnloadSerializer = itemUiContext.gameObject.AddComponent<ItemContextTaskSerializer>();
Task result = LoadUnloadSerializer.Initialize(
SortedItemContexts()
.Where(ic => ic.Item is MagazineClass && InteractionAvailable(ic, EItemInfoButton.LoadAmmo, itemUiContext))
.SelectMany(ic => ic.RepeatUntilFull()),
itemContext =>
{
IgnoreStopLoading = true;
return itemUiContext.LoadAmmoByType(itemContext.Item as MagazineClass, ammoTemplateId, itemContext.UpdateView);
});
LoadUnloadSerializer = taskSerializer;
itemUiContext.Tooltip?.Close();
return result;
return result.ContinueWith(t => LoadUnloadSerializer = null);
}
return Task.CompletedTask;
@@ -311,12 +313,11 @@ namespace UIFixes
public static void UnloadAmmoAll(ItemUiContext itemUiContext, bool allOrNothing)
{
StopLoading();
StopLoading(true);
if (!allOrNothing || InteractionCount(EItemInfoButton.UnloadAmmo, itemUiContext) == Count)
{
// Call Initialize() before setting UnloadSerializer so that the initial synchronous call to StopProcesses()->StopUnloading() doesn't immediately cancel this
var taskSerializer = itemUiContext.gameObject.AddComponent<ItemContextTaskSerializer>();
taskSerializer.Initialize(
LoadUnloadSerializer = itemUiContext.gameObject.AddComponent<ItemContextTaskSerializer>();
LoadUnloadSerializer.Initialize(
SortedItemContexts().Where(ic => InteractionAvailable(ic, EItemInfoButton.UnloadAmmo, itemUiContext)),
itemContext =>
{
@@ -324,24 +325,34 @@ namespace UIFixes
{
Deselect(itemContext);
}
return itemUiContext.UnloadAmmo(itemContext.Item);
});
LoadUnloadSerializer = taskSerializer;
IgnoreStopLoading = true;
return itemUiContext.UnloadAmmo(itemContext.Item);
}).ContinueWith(t => LoadUnloadSerializer = null);
itemUiContext.Tooltip?.Close();
}
}
public static void StopLoading()
private static bool IgnoreStopLoading = false;
public static void StopLoading(bool force = false)
{
if (LoadUnloadSerializer == null)
{
return;
}
if (!IgnoreStopLoading || force)
{
LoadUnloadSerializer.Cancel();
LoadUnloadSerializer = null;
}
else
{
IgnoreStopLoading = false;
}
}
public static void UnpackAll(ItemUiContext itemUiContext, bool allOrNothing)
{
@@ -402,21 +413,21 @@ namespace UIFixes
public MultiSelectItemContext(ItemContextAbstractClass itemContext, ItemRotation rotation) : base(itemContext, rotation)
{
// Adjust event handlers
if (GClass2813_0 != null)
if (ItemContextAbstractClass != null)
{
// Listen for underlying context being disposed, it might mean the item is gone (merged, destroyed, etc)
GClass2813_0.OnDisposed += OnParentDispose;
ItemContextAbstractClass.OnDisposed += OnParentDispose;
// This serves no purpose and causes stack overflows
GClass2813_0.OnCloseWindow -= CloseDependentWindows;
ItemContextAbstractClass.OnCloseWindow -= CloseDependentWindows;
}
}
public override void Dispose()
{
base.Dispose();
if (GClass2813_0 != null)
if (ItemContextAbstractClass != null)
{
GClass2813_0.OnDisposed -= OnParentDispose;
ItemContextAbstractClass.OnDisposed -= OnParentDispose;
}
}
@@ -433,9 +444,9 @@ namespace UIFixes
// ItemContextClass (drag) defaults to None, but we want what the underlying item allows
public override bool CanQuickMoveTo(ETargetContainer targetContainer)
{
if (GClass2813_0 != null)
if (ItemContextAbstractClass != null)
{
return GClass2813_0.CanQuickMoveTo(targetContainer);
return ItemContextAbstractClass.CanQuickMoveTo(targetContainer);
}
return base.CanQuickMoveTo(targetContainer);
@@ -481,6 +492,18 @@ namespace UIFixes
}
}
public static IEnumerable<ItemContextClass> RepeatUntilFull(this ItemContextClass itemContext)
{
if (itemContext.Item is MagazineClass magazine)
{
int ammoCount = -1;
while (magazine.Count > ammoCount && magazine.Count < magazine.MaxCount)
{
ammoCount = magazine.Count;
yield return itemContext;
}
}
}
}
}

View File

@@ -1,7 +1,7 @@
using Aki.Reflection.Patching;
using EFT.UI.Ragfair;
using EFT.UI.Ragfair;
using HarmonyLib;
using JetBrains.Annotations;
using SPT.Reflection.Patching;
using System.Linq;
using System.Reflection;
using TMPro;

View File

@@ -1,7 +1,7 @@
using Aki.Reflection.Patching;
using EFT.UI;
using EFT.UI;
using EFT.UI.Ragfair;
using HarmonyLib;
using SPT.Reflection.Patching;
using System.Reflection;
using UnityEngine;
@@ -29,7 +29,7 @@ namespace UIFixes
{
protected override MethodBase GetTargetMethod()
{
return AccessTools.Method(typeof(AddOfferWindow), nameof(AddOfferWindow.method_8));
return AccessTools.Method(typeof(AddOfferWindow), nameof(AddOfferWindow.method_7));
}
[PatchPostfix]

View File

@@ -1,12 +1,13 @@
using Aki.Common.Http;
using Aki.Reflection.Patching;
using EFT.UI;
using EFT.UI;
using EFT.UI.Ragfair;
using HarmonyLib;
using Newtonsoft.Json;
using SPT.Common.Http;
using SPT.Reflection.Patching;
using System;
using System.Collections.Generic;
using System.Reflection;
using System.Threading.Tasks;
namespace UIFixes
{
@@ -32,12 +33,15 @@ namespace UIFixes
{
Loading = true;
string response = RequestHandler.GetJson("/uifixes/assortUnlocks");
if (!String.IsNullOrEmpty(response))
Task<string> response = RequestHandler.GetJsonAsync("/uifixes/assortUnlocks");
response.ContinueWith(task =>
{
string json = task.Result;
if (!String.IsNullOrEmpty(json))
{
try
{
AssortUnlocks = JsonConvert.DeserializeObject<Dictionary<string, string>>(response);
AssortUnlocks = JsonConvert.DeserializeObject<Dictionary<string, string>>(json);
}
catch (Exception ex)
{
@@ -46,6 +50,7 @@ namespace UIFixes
}
Loading = false;
});
}
if (__instance.Offer_0.Locked)

View File

@@ -1,6 +1,6 @@
using Aki.Reflection.Patching;
using EFT.UI;
using EFT.UI;
using HarmonyLib;
using SPT.Reflection.Patching;
using System.Reflection;
using UnityEngine;

View File

@@ -1,7 +1,6 @@
using Aki.Reflection.Patching;
using EFT.InputSystem;
using EFT.UI;
using EFT.UI;
using HarmonyLib;
using SPT.Reflection.Patching;
using System.Reflection;
using UnityEngine;
using UnityEngine.UI;

View File

@@ -1,9 +1,9 @@
using Aki.Reflection.Patching;
using Aki.Reflection.Utils;
using Comfort.Common;
using Comfort.Common;
using EFT.InventoryLogic;
using EFT.UI;
using HarmonyLib;
using SPT.Reflection.Patching;
using SPT.Reflection.Utils;
using System;
using System.Collections.Generic;
using System.Linq;
@@ -49,9 +49,9 @@ namespace UIFixes
public static void Enable()
{
// The context menus in the inventory and the trading screen inventory are *completely different code*
InventoryRootInteractionsType = PatchConstants.EftTypes.Single(t => t.GetField("HIDEOUT_WEAPON_MODIFICATION_REQUIRED") != null); // GClass3023
InventoryRootInteractionsType = PatchConstants.EftTypes.Single(t => t.GetField("HIDEOUT_WEAPON_MODIFICATION_REQUIRED") != null); // GClass3045
// GClass3032 - this is nuts to find, have to inspect a static enum array
// GClass3054 - this is nuts to find, have to inspect a static enum array
TradingRootInteractionsType = PatchConstants.EftTypes.Single(t =>
{
var enumerableField = t.GetField("ienumerable_2", BindingFlags.NonPublic | BindingFlags.Static);
@@ -414,7 +414,7 @@ namespace UIFixes
if (selectedItem is BulletClass)
{
__result = new MagazineBuildClass.Class3135(selectedItem);
__result = new MagazineBuildClass.Class3183(selectedItem);
return false;
}

View File

@@ -1,8 +1,8 @@
using Aki.Reflection.Patching;
using EFT.InventoryLogic;
using EFT.InventoryLogic;
using EFT.UI;
using EFT.UI.DragAndDrop;
using HarmonyLib;
using SPT.Reflection.Patching;
using System.Reflection;
using TMPro;
using UnityEngine.EventSystems;
@@ -143,9 +143,9 @@ namespace UIFixes
}
[PatchPostfix]
public static void Postfix(ItemUiContext ___itemUiContext_0, ItemContextAbstractClass ___gclass2813_0)
public static void Postfix(ItemUiContext ___itemUiContext_0, ItemContextAbstractClass ___itemContextAbstractClass)
{
___itemUiContext_0.RegisterCurrentItemContext(___gclass2813_0);
___itemUiContext_0.RegisterCurrentItemContext(___itemContextAbstractClass);
}
}
@@ -157,9 +157,9 @@ namespace UIFixes
}
[PatchPostfix]
public static void Postfix(ItemUiContext ___itemUiContext_0, ItemContextAbstractClass ___gclass2813_0)
public static void Postfix(ItemUiContext ___itemUiContext_0, ItemContextAbstractClass ___itemContextAbstractClass)
{
___itemUiContext_0.UnregisterCurrentItemContext(___gclass2813_0);
___itemUiContext_0.UnregisterCurrentItemContext(___itemContextAbstractClass);
}
}

View File

@@ -1,6 +1,6 @@
using Aki.Reflection.Patching;
using EFT.UI.Ragfair;
using EFT.UI.Ragfair;
using HarmonyLib;
using SPT.Reflection.Patching;
using System.Reflection;
using TMPro;
using UnityEngine;

View File

@@ -1,6 +1,6 @@
using Aki.Reflection.Patching;
using EFT.UI.Chat;
using HarmonyLib;
using SPT.Reflection.Patching;
using System.Reflection;
namespace UIFixes

View File

@@ -1,7 +1,7 @@
using Aki.Reflection.Patching;
using EFT.UI;
using EFT.UI;
using EFT.UI.DragAndDrop;
using HarmonyLib;
using SPT.Reflection.Patching;
using System.Reflection;
using TMPro;
using UnityEngine;

View File

@@ -1,7 +1,7 @@
using Aki.Reflection.Patching;
using Diz.LanguageExtensions;
using Diz.LanguageExtensions;
using EFT.InventoryLogic;
using HarmonyLib;
using SPT.Reflection.Patching;
using System.Reflection;
namespace UIFixes
@@ -13,18 +13,18 @@ namespace UIFixes
return AccessTools.Method(typeof(TraderControllerClass), nameof(TraderControllerClass.ExecutePossibleAction), [typeof(ItemContextAbstractClass), typeof(Item), typeof(bool), typeof(bool)]);
}
// Recreatign this function to add the comment section, so calling this with simulate = false doesn't break everything
// Recreating this function to add the comment section, so calling this with simulate = false doesn't break everything
[PatchPrefix]
[HarmonyPriority(Priority.Last)]
public static bool Prefix(TraderControllerClass __instance, ItemContextAbstractClass itemContext, Item targetItem, bool partialTransferOnly, bool simulate, ref GStruct413 __result)
{
TraderControllerClass.Struct754 opStruct;
TraderControllerClass.Struct775 opStruct;
opStruct.targetItem = targetItem;
opStruct.gclass2758_0 = __instance;
opStruct.traderControllerClass = __instance;
opStruct.simulate = simulate;
opStruct.item = itemContext.Item;
Error error = new GClass3293(opStruct.item);
Error error = new GClass3317(opStruct.item);
bool mergeAvailable = itemContext.MergeAvailable;
bool splitAvailable = itemContext.SplitAvailable;
partialTransferOnly &= splitAvailable;
@@ -45,7 +45,7 @@ namespace UIFixes
}
}
if (opStruct.targetItem is GInterface306 applicable)
if (opStruct.targetItem is GInterface321 applicable)
{
var operation = __instance.method_23(applicable, ref error, ref opStruct);
if (operation.Succeeded)

View File

@@ -1,6 +1,6 @@
using Aki.Reflection.Patching;
using EFT.InventoryLogic;
using EFT.InventoryLogic;
using HarmonyLib;
using SPT.Reflection.Patching;
using System.Collections.Generic;
using System.Reflection;

View File

@@ -1,8 +1,8 @@
using Aki.Reflection.Patching;
using EFT.UI;
using EFT.UI;
using EFT.UI.Ragfair;
using EFT.UI.Utilities.LightScroller;
using HarmonyLib;
using SPT.Reflection.Patching;
using System;
using System.Collections.Generic;
using System.Linq;
@@ -197,7 +197,7 @@ namespace UIFixes
private void ApplyFullFilter(FilterRule filterRule)
{
// Order impacts the order the filters show in the UI
var searches = new List<GClass3196>();
var searches = new List<GClass3219>();
// This part was tricky to figure out. Adding OR removing any of these ID filters will clear the others, so you can only do one of them.
// When going to a state with no id filter, you MUST remove something (or all to be safe)
@@ -322,7 +322,7 @@ namespace UIFixes
{
protected override MethodBase GetTargetMethod()
{
return AccessTools.Method(typeof(RagfairScreen), nameof(RagfairScreen.method_7));
return AccessTools.Method(typeof(RagfairScreen), nameof(RagfairScreen.method_9));
}
[PatchPostfix]

View File

@@ -1,13 +1,10 @@
using Aki.Reflection.Patching;
using EFT.InventoryLogic;
using EFT.UI.Ragfair;
using EFT.UI.Ragfair;
using HarmonyLib;
using SPT.Reflection.Patching;
using System;
using System.Linq;
using System.Reflection;
using TMPro;
using UnityEngine;
using UnityEngine.UI;
namespace UIFixes
{

View File

@@ -1,6 +1,6 @@
using Aki.Reflection.Patching;
using EFT.UI;
using EFT.UI;
using HarmonyLib;
using SPT.Reflection.Patching;
using System.Reflection;
using TMPro;

View File

@@ -1,7 +1,7 @@
using Aki.Reflection.Patching;
using EFT.InventoryLogic;
using EFT.InventoryLogic;
using EFT.UI;
using HarmonyLib;
using SPT.Reflection.Patching;
using System.Reflection;
using UnityEngine;
using UnityEngine.UI;

View File

@@ -1,6 +1,6 @@
using Aki.Reflection.Patching;
using EFT.Hideout;
using EFT.Hideout;
using HarmonyLib;
using SPT.Reflection.Patching;
using System.Reflection;
namespace UIFixes

View File

@@ -1,4 +1,4 @@
using Aki.Reflection.Patching;
using SPT.Reflection.Patching;
using EFT.Hideout;
using EFT.UI;
using HarmonyLib;
@@ -34,7 +34,7 @@ namespace UIFixes
{
protected override MethodBase GetTargetMethod()
{
return AccessTools.Method(R.ProductionPanelShowSubclass.Type, "method_6");
return AccessTools.Method(R.ProductionPanelShowSubclass.Type, "method_2");
}
[PatchPostfix]
@@ -96,7 +96,7 @@ namespace UIFixes
public static void Postfix(ProductionPanel __instance, ValidationInputField ____searchInputField)
{
// Force it to render immediately, at full height, even if the search filtering would reduce the number of children
if (__instance.method_4().Count() > 2)
if (__instance.method_9().Count() > 2)
{
AreaScreenSubstrate areaScreenSubstrate = __instance.GetComponentInParent<AreaScreenSubstrate>();
LayoutElement layoutElement = areaScreenSubstrate.R().ContentLayout;
@@ -109,21 +109,21 @@ namespace UIFixes
}
}
// method_4 gets the sorted list of products. If there's a search term, prioritize the matching items so they load first
// method_9 gets the sorted list of products. If there's a search term, prioritize the matching items so they load first
public class FastHideoutSearchPatch : ModulePatch
{
protected override MethodBase GetTargetMethod()
{
return AccessTools.Method(typeof(ProductionPanel), nameof(ProductionPanel.method_4));
return AccessTools.Method(typeof(ProductionPanel), nameof(ProductionPanel.method_9));
}
// Copied directly from method_4. Working with GClasses directly here, because this would be a nightmare with reflection
// Copied directly from method_9. Working with GClasses directly here, because this would be a nightmare with reflection
[PatchPrefix]
public static bool Prefix(ref IEnumerable<GClass1923> __result, ProductionPanel __instance, GClass1922[] ___gclass1922_0, ValidationInputField ____searchInputField)
public static bool Prefix(ref IEnumerable<GClass1939> __result, ProductionPanel __instance, ProductionBuildAbstractClass[] ___gclass1938_0, ValidationInputField ____searchInputField)
{
__result = ___gclass1922_0.OfType<GClass1923>().Where(scheme => !scheme.locked)
__result = ___gclass1938_0.OfType<GClass1939>().Where(scheme => !scheme.locked)
.OrderBy(scheme => scheme.endProduct.LocalizedName().Contains(____searchInputField.text) ? 0 : 1) // search-matching items first
.ThenBy(__instance.method_10)
.ThenBy(__instance.method_18)
.ThenBy(scheme => scheme.FavoriteIndex)
.ThenBy(scheme => scheme.Level);
@@ -131,18 +131,18 @@ namespace UIFixes
}
}
// method_9 activates/deactivates the product game objects based on the search. Need to resort the list due to above patch
// method_14 activates/deactivates the product game objects based on the search. Need to resort the list due to above patch
public class FixHideoutSearchAgainPatch : ModulePatch
{
protected override MethodBase GetTargetMethod()
{
return AccessTools.Method(typeof(ProductionPanel), nameof(ProductionPanel.method_9));
return AccessTools.Method(typeof(ProductionPanel), nameof(ProductionPanel.method_14));
}
[PatchPrefix]
public static void Prefix(ProductionPanel __instance)
{
__instance.method_8(); // update sort order
__instance.method_13(); // update sort order
}
}

View File

@@ -1,8 +1,8 @@
using Aki.Reflection.Patching;
using EFT.InputSystem;
using EFT.InputSystem;
using EFT.InventoryLogic;
using EFT.UI;
using HarmonyLib;
using SPT.Reflection.Patching;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;

View File

@@ -1,7 +1,7 @@
using Aki.Reflection.Patching;
using EFT.InventoryLogic;
using EFT.InventoryLogic;
using EFT.UI;
using HarmonyLib;
using SPT.Reflection.Patching;
using System;
using System.Collections.Generic;
using System.Globalization;
@@ -304,7 +304,7 @@ namespace UIFixes
// Bar width is currently set to durability/100, and that 100 is pretty much hardcoded by the client
// Just clamp the bar to keep it from overflowing
[PatchPostfix]
public static void Postfix(DurabilityPanel __instance, Image ___Current)
public static void Postfix(Image ___Current)
{
___Current.rectTransform.anchorMax = new Vector2(
Mathf.Min(___Current.rectTransform.anchorMax.x, 1f),

View File

@@ -1,8 +1,8 @@
using Aki.Reflection.Patching;
using EFT.UI;
using EFT.UI;
using EFT.UI.Chat;
using EFT.UI.Screens;
using HarmonyLib;
using SPT.Reflection.Patching;
using System.Reflection;
namespace UIFixes

View File

@@ -1,7 +1,9 @@
using Aki.Reflection.Patching;
using EFT.InventoryLogic;
using EFT.UI.Ragfair;
using EFT.UI.Ragfair;
using HarmonyLib;
using SPT.Reflection.Patching;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Threading.Tasks;
@@ -11,13 +13,42 @@ namespace UIFixes
{
private static bool BlockClose = false;
private static TaskCompletionSource CompletionSource;
private static readonly List<Task> AddOfferTasks = [];
private static AddOfferWindow Window;
public static void Enable()
{
new GetTaskCompletionSourcePatch().Enable();
new PlaceOfferClickPatch().Enable();
new ClosePatch().Enable();
new ManageTaskPatch().Enable();
}
public class GetTaskCompletionSourcePatch : ModulePatch
{
protected override MethodBase GetTargetMethod()
{
return AccessTools.DeclaredMethod(typeof(AddOfferWindow), nameof(AddOfferWindow.Show));
}
[PatchPostfix]
public static void Postfix(AddOfferWindow __instance, ref Task __result)
{
if (!Settings.KeepAddOfferOpen.Value)
{
return;
}
Window = __instance;
AddOfferTasks.Clear();
// Use a different task to mark when everything is actually done
CompletionSource = new TaskCompletionSource();
__result = CompletionSource.Task;
}
}
public class PlaceOfferClickPatch : ModulePatch
{
protected override MethodBase GetTargetMethod()
@@ -26,10 +57,12 @@ namespace UIFixes
}
[PatchPrefix]
public static void Prefix(AddOfferWindow __instance)
public static void Prefix(AddOfferWindow __instance, TaskCompletionSource ___taskCompletionSource_0, ref TaskCompletionSource __state)
{
if (Settings.KeepAddOfferOpen.Value)
{
__state = ___taskCompletionSource_0;
// Close the window if you're gonna hit max offers
var ragfair = __instance.R().Ragfair;
if (Settings.KeepAddOfferOpenIgnoreMaxOffers.Value || ragfair.MyOffersCount + 1 < ragfair.GetMaxOffersCount(ragfair.MyRating))
@@ -40,10 +73,13 @@ namespace UIFixes
}
[PatchPostfix]
public static void Postfix(RequirementView[] ____requirementViews, bool ___bool_2)
public static void Postfix(RequirementView[] ____requirementViews, TaskCompletionSource ___taskCompletionSource_0, ref TaskCompletionSource __state)
{
if (Settings.KeepAddOfferOpen.Value && ___bool_2)
bool isAddingOffer = __state != ___taskCompletionSource_0; // If the taskCompletionSource member was changed, then it's adding an offer :S
if (Settings.KeepAddOfferOpen.Value && isAddingOffer)
{
AddOfferTasks.Add(__state.Task); // This is the task completion source passed into the add offer call
// clear old prices
foreach (var requirementView in ____requirementViews)
{
@@ -59,12 +95,20 @@ namespace UIFixes
{
protected override MethodBase GetTargetMethod()
{
return AccessTools.Method(typeof(AddOfferWindow), nameof(AddOfferWindow.Close));
return AccessTools.Method(typeof(AddOfferWindow), nameof(Window.Close));
}
[PatchPrefix]
public static bool Prefix()
{
if (!BlockClose && AddOfferTasks.All(t => t.IsCompleted))
{
CompletionSource.Complete();
CompletionSource = null;
AddOfferTasks.Clear();
Window = null;
}
return !BlockClose;
}
}
@@ -75,21 +119,25 @@ namespace UIFixes
{
protected override MethodBase GetTargetMethod()
{
return AccessTools.Method(typeof(AddOfferWindow), nameof(AddOfferWindow.method_16));
Type type = typeof(AddOfferWindow).GetNestedTypes().Single(t => t.GetField("completionSource") != null); // AddOfferWindow.Class3068
return AccessTools.Method(type, "method_0");
}
[PatchPrefix]
public static bool Prefix(AddOfferWindow __instance, TaskCompletionSource<object> ___taskCompletionSource_0, ref bool ___bool_2)
public static bool Prefix(TaskCompletionSource ___completionSource)
{
if (!Settings.KeepAddOfferOpen.Value)
if (!Settings.KeepAddOfferOpen.Value || Window == null)
{
return true;
}
___bool_2 = false;
if (!__instance.gameObject.activeInHierarchy)
___completionSource.Complete();
if (!Window.gameObject.activeInHierarchy && AddOfferTasks.All(t => t.IsCompleted))
{
___taskCompletionSource_0.SetResult(null);
CompletionSource.Complete();
CompletionSource = null;
AddOfferTasks.Clear();
Window = null;
}
return false;

View File

@@ -1,7 +1,7 @@
using Aki.Reflection.Patching;
using EFT.InputSystem;
using EFT.InputSystem;
using EFT.UI;
using HarmonyLib;
using SPT.Reflection.Patching;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;

View File

@@ -1,8 +1,8 @@
using Aki.Reflection.Patching;
using EFT.InventoryLogic;
using EFT.InventoryLogic;
using EFT.UI;
using EFT.UI.DragAndDrop;
using HarmonyLib;
using SPT.Reflection.Patching;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;

View File

@@ -1,6 +1,6 @@
using Aki.Reflection.Patching;
using EFT.InventoryLogic;
using EFT.InventoryLogic;
using HarmonyLib;
using SPT.Reflection.Patching;
using System;
using System.Collections.Generic;
using System.Reflection;
@@ -11,8 +11,7 @@ namespace UIFixes
{
protected override MethodBase GetTargetMethod()
{
Type type = AccessTools.Method(typeof(ISession), nameof(ISession.SaveMagBuild)).GetParameters()[0].ParameterType;
return AccessTools.Method(type, "smethod_0");
return AccessTools.Method(typeof(MagazineBuildPresetClass), nameof(MagazineBuildPresetClass.smethod_0));
}
// This method returns a list of places to search for ammo. For whatever reason, it only looks

View File

@@ -1,7 +1,7 @@
using Aki.Reflection.Patching;
using EFT.InventoryLogic;
using EFT.InventoryLogic;
using EFT.UI;
using HarmonyLib;
using SPT.Reflection.Patching;
using System.Linq;
using System.Reflection;
using System.Threading.Tasks;
@@ -53,7 +53,7 @@ namespace UIFixes
{
protected override MethodBase GetTargetMethod()
{
return AccessTools.Method(typeof(GClass2510), nameof(GClass2510.CheckItemFilter));
return AccessTools.Method(typeof(GClass2524), nameof(GClass2524.CheckItemFilter));
}
[PatchPrefix]
@@ -72,7 +72,7 @@ namespace UIFixes
{
protected override MethodBase GetTargetMethod()
{
return AccessTools.Method(typeof(GClass3043), nameof(GClass3043.method_6));
return AccessTools.Method(typeof(GClass3065), nameof(GClass3065.method_6));
}
[PatchPrefix]
@@ -92,7 +92,7 @@ namespace UIFixes
{
protected override MethodBase GetTargetMethod()
{
return AccessTools.Method(typeof(GClass3044), nameof(GClass3044.method_7));
return AccessTools.Method(typeof(GClass3066), nameof(GClass3066.method_7));
}
[PatchPrefix]
@@ -119,11 +119,11 @@ namespace UIFixes
{
protected override MethodBase GetTargetMethod()
{
return AccessTools.Method(typeof(GClass3044), nameof(GClass3044.method_6));
return AccessTools.Method(typeof(GClass3066), nameof(GClass3066.method_6));
}
[PatchPrefix]
public static bool Prefix(GClass2092 preset, ItemUiContext ___itemUiContext_1)
public static bool Prefix(MagazineBuildPresetClass preset, ItemUiContext ___itemUiContext_1)
{
if (!MultiSelect.Active)
{

View File

@@ -1,6 +1,6 @@
using Aki.Reflection.Patching;
using EFT.UI;
using EFT.UI;
using HarmonyLib;
using SPT.Reflection.Patching;
using System.Linq;
using System.Reflection;
using UnityEngine;

View File

@@ -1,5 +1,4 @@
using Aki.Reflection.Patching;
using Comfort.Common;
using Comfort.Common;
using EFT;
using EFT.Communications;
using EFT.InventoryLogic;
@@ -7,28 +6,27 @@ using EFT.UI;
using EFT.UI.DragAndDrop;
using EFT.UI.Insurance;
using HarmonyLib;
using SPT.Reflection.Patching;
using SPT.Reflection.Utils;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Threading;
using System.Threading.Tasks;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.UI;
using BaseItemInfoInteractions = GClass3042;
using DestroyError = GClass3344;
using GenericItemContext = GClass2833;
using GridModificationsUnavailableError = StashGridClass.GClass3315;
using ItemOperation = GStruct413;
using MoveOperation = GClass2786;
using GridItemAddress = GClass2769;
using GridFindExtensions = GClass2503;
using BaseItemInfoInteractions = GClass3021;
using GenericItemContext = GClass2817;
using Stackable = GClass2735;
using NoOpMove = GClass2779;
using DestroyError = GClass3320;
using NoRoomError = GClass3292;
using GridModificationsUnavailableError = StashGridClass.GClass3291;
using MoveSameSpaceError = InteractionsHandlerClass.GClass3329;
using MoveOperation = GClass2802;
using MoveSameSpaceError = InteractionsHandlerClass.GClass3353;
using NoOpMove = GClass2795;
using NoRoomError = GClass3316;
using Stackable = GClass2751;
namespace UIFixes
{
@@ -41,7 +39,7 @@ namespace UIFixes
private static readonly List<Image> Previews = [];
// Point that various QuickFindPlace overrides should start at
private static GridItemAddress FindOrigin = null;
private static ItemAddressClass FindOrigin = null;
private static bool FindVerticalFirst = false;
// Prevents QuickFind from attempting a merge
@@ -91,9 +89,9 @@ namespace UIFixes
// Various location finding
new FindSpotKeepRotationPatch().Enable();
new FindLocationForItemPatch().Enable();
new FindPlaceToPutPatch().Enable();
new AdjustQuickFindFlagsPatch().Enable();
new ReorderContainersPatch().Enable();
new AllowFindSameSpotPatch().Enable();
}
@@ -331,11 +329,14 @@ namespace UIFixes
}
[PatchPostfix]
public static void Postfix()
public static void Postfix(Player.PlayerInventoryController __instance)
{
if (__instance.Profile == PatchConstants.BackEndSession.Profile)
{
MultiSelect.StopLoading();
}
}
}
// TradingItemView overrides GridItemView.OnClick and doesn't call base
public class DeselectOnTradingItemViewClickPatch : ModulePatch
@@ -485,7 +486,7 @@ namespace UIFixes
return false;
}
GridItemAddress hoveredAddress = new(__instance.Grid, hoveredLocation);
ItemAddressClass hoveredAddress = new(__instance.Grid, hoveredLocation);
if (!item.CheckAction(hoveredAddress))
{
return false;
@@ -667,7 +668,7 @@ namespace UIFixes
DisableMerge = targetItemContext == null;
LocationInGrid hoveredLocation = __instance.CalculateItemLocation(itemContext);
GridItemAddress hoveredAddress = new(__instance.Grid, hoveredLocation);
ItemAddressClass hoveredAddress = new(__instance.Grid, hoveredLocation);
if (__instance.Grid.ParentItem is SortingTableClass)
{
@@ -744,26 +745,6 @@ namespace UIFixes
}
}
public class AllowFindSameSpotPatch : ModulePatch
{
protected override MethodBase GetTargetMethod()
{
return AccessTools.Method(typeof(GridFindExtensions), nameof(GridFindExtensions.FindLocationForItem));
}
[PatchPrefix]
public static bool Prefix(IEnumerable<StashGridClass> grids, Item item, ref GridItemAddress __result)
{
if (!MultiSelect.Active)
{
return true;
}
__result = grids.Select(g => g.FindLocationForItem(item)).FirstOrDefault(x => x != null);
return false;
}
}
public class GridViewPickTargetPatch : ModulePatch
{
public static Item FallbackResult = null;
@@ -959,7 +940,7 @@ namespace UIFixes
bool firstItem = true;
LocationInGrid hoveredLocation = __instance.CalculateItemLocation(itemContext);
GridItemAddress hoveredAddress = new(__instance.Grid, hoveredLocation);
ItemAddressClass hoveredAddress = new(__instance.Grid, hoveredLocation);
DisableMerge = true;
@@ -972,7 +953,7 @@ namespace UIFixes
FindVerticalFirst = selectedItemContext.ItemRotation == ItemRotation.Vertical;
operation = firstItem ?
InteractionsHandlerClass.Move(selectedItemContext.Item, new GridItemAddress(__instance.Grid, __instance.CalculateItemLocation(selectedItemContext)), traderAssortmentController.TraderController, false) :
InteractionsHandlerClass.Move(selectedItemContext.Item, new ItemAddressClass(__instance.Grid, __instance.CalculateItemLocation(selectedItemContext)), traderAssortmentController.TraderController, false) :
InteractionsHandlerClass.QuickFindAppropriatePlace(selectedItemContext.Item, traderAssortmentController.TraderController, [__instance.Grid.ParentItem as LootItemClass], InteractionsHandlerClass.EMoveItemOrder.Apply, false);
FindVerticalFirst = false;
@@ -1036,7 +1017,7 @@ namespace UIFixes
TraderAssortmentControllerClass traderAssortmentController = __instance.R().TraderAssortmentController;
LocationInGrid hoveredLocation = __instance.CalculateItemLocation(itemContext);
GridItemAddress hoveredAddress = new(__instance.Grid, hoveredLocation);
ItemAddressClass hoveredAddress = new(__instance.Grid, hoveredLocation);
itemContext.DragCancelled();
traderAssortmentController.PrepareToSell(itemContext.Item, hoveredLocation);
@@ -1054,7 +1035,7 @@ namespace UIFixes
FindVerticalFirst = false;
if (operation.Failed || operation.Value is not MoveOperation moveOperation || moveOperation.To is not GridItemAddress gridAddress)
if (operation.Failed || operation.Value is not MoveOperation moveOperation || moveOperation.To is not ItemAddressClass gridAddress)
{
break;
}
@@ -1137,34 +1118,68 @@ namespace UIFixes
}
// Reorder the grids to start with the same grid as FindOrigin, then loop around
public class FindLocationForItemPatch : ModulePatch
public class ReorderContainersPatch : ModulePatch
{
protected override MethodBase GetTargetMethod()
{
return AccessTools.Method(typeof(GridFindExtensions), nameof(GridFindExtensions.FindLocationForItem));
Type type = typeof(InteractionsHandlerClass).GetNestedTypes().Single(t => t.GetField("noSpaceError") != null);
return AccessTools.Method(type, "method_1");
}
[PatchPrefix]
public static void Prefix(ref IEnumerable<StashGridClass> grids)
public static void Prefix(ref IEnumerable<EFT.InventoryLogic.IContainer> containersToPut)
{
if (!MultiSelect.Active || FindOrigin == null)
{
return;
}
if (!grids.Any(g => g == FindOrigin.Grid))
if (!containersToPut.Any(g => g == FindOrigin.Grid))
{
return;
}
var list = grids.ToList();
AllowFindSameSpotPatch.DisableItemAddressEquals = true;
var list = containersToPut.ToList();
while (list[0] != FindOrigin.Grid)
{
list.Add(list[0]);
list.RemoveAt(0);
}
grids = list;
containersToPut = list;
}
[PatchPostfix]
public static void Postfix()
{
AllowFindSameSpotPatch.DisableItemAddressEquals = false;
}
}
// This is an insane way of doing this, but inside of the above method, I want ItemAddress.Equals to always return false, to allow
// same place moves.
public class AllowFindSameSpotPatch : ModulePatch
{
public static bool DisableItemAddressEquals = false;
protected override MethodBase GetTargetMethod()
{
return AccessTools.DeclaredMethod(typeof(ItemAddress), nameof(ItemAddress.Equals));
}
[PatchPrefix]
public static bool Prefix(ref bool __result)
{
if (!DisableItemAddressEquals)
{
return true;
}
DisableItemAddressEquals = false; // Only do it one time (this is so hacky)
__result = false;
return false;
}
}
@@ -1265,14 +1280,14 @@ namespace UIFixes
private static void ShowPreview(GridView gridView, ItemContextClass itemContext, ItemOperation operation)
{
GridItemAddress gridAddress = null;
ItemAddressClass gridAddress = null;
if (operation.Value is MoveOperation moveOperation)
{
gridAddress = moveOperation.To as GridItemAddress;
gridAddress = moveOperation.To as ItemAddressClass;
}
else if (operation.Value is NoOpMove noopMove)
{
gridAddress = itemContext.ItemAddress as GridItemAddress;
gridAddress = itemContext.ItemAddress as ItemAddressClass;
}
else
{
@@ -1295,7 +1310,7 @@ namespace UIFixes
ShowPreview(gridView, itemContext, gridAddress, backgroundColor);
}
private static void ShowPreview(GridView gridView, ItemContextClass itemContext, GridItemAddress gridAddress, Color backgroundColor)
private static void ShowPreview(GridView gridView, ItemContextClass itemContext, ItemAddressClass gridAddress, Color backgroundColor)
{
Image preview = UnityEngine.Object.Instantiate(gridView.R().HighlightPanel, gridView.transform, false);
preview.gameObject.SetActive(true);
@@ -1338,8 +1353,8 @@ namespace UIFixes
Previews.Clear();
}
private static GridItemAddress GetTargetGridAddress(
ItemContextClass itemContext, ItemContextClass selectedItemContext, GridItemAddress hoveredGridAddress)
private static ItemAddressClass GetTargetGridAddress(
ItemContextClass itemContext, ItemContextClass selectedItemContext, ItemAddressClass hoveredGridAddress)
{
if (Settings.MultiSelectStrat.Value == MultiSelectStrategy.FirstOpenSpace)
{
@@ -1348,8 +1363,8 @@ namespace UIFixes
if (Settings.MultiSelectStrat.Value == MultiSelectStrategy.OriginalSpacing &&
itemContext != selectedItemContext &&
itemContext.ItemAddress is GridItemAddress itemGridAddress &&
selectedItemContext.ItemAddress is GridItemAddress selectedGridAddress &&
itemContext.ItemAddress is ItemAddressClass itemGridAddress &&
selectedItemContext.ItemAddress is ItemAddressClass selectedGridAddress &&
itemGridAddress.Container.ParentItem == selectedGridAddress.Container.ParentItem)
{
// Shared a parent with the dragged item - try to keep position

View File

@@ -1,7 +1,7 @@
using Aki.Reflection.Patching;
using Comfort.Common;
using Comfort.Common;
using EFT.UI;
using HarmonyLib;
using SPT.Reflection.Patching;
using System.Linq;
using System.Reflection;
using UnityEngine;

View File

@@ -1,7 +1,7 @@
using Aki.Reflection.Patching;
using EFT;
using EFT;
using EFT.InventoryLogic;
using HarmonyLib;
using SPT.Reflection.Patching;
using System;
using System.Collections.Generic;
using System.Linq;
@@ -13,14 +13,14 @@ namespace UIFixes
{
protected override MethodBase GetTargetMethod()
{
return AccessTools.Method(typeof(GClass1841), nameof(GClass1841.method_8));
return AccessTools.Method(typeof(GClass1855), nameof(GClass1855.method_9));
}
// The patched method can't handle new items that aren't in stash root.
// Find items that are in subcontainers and handle them first - the patched method will ignore items that have a CurrentAddress
// This is a subset of the original method - doesn't handle slots, equipment containers, etc.
[PatchPrefix]
public static void Prefix(ref GClass1189[] newItems, Profile ___profile_0, ItemFactory ___gclass1486_0, GClass2764 ___gclass2764_0)
public static void Prefix(ref GClass1198[] newItems, Profile ___profile_0, ItemFactory ___itemFactory, GClass2780 ___gclass2780_0)
{
Inventory inventory = ___profile_0.Inventory;
StashClass stash = inventory.Stash;
@@ -40,10 +40,10 @@ namespace UIFixes
List<Item> stashItems = stash.GetNotMergedItems().ToList();
ItemFactory.GStruct134 tree = ___gclass1486_0.FlatItemsToTree(unhandledItems.ToArray(), true, null);
ItemFactory.GStruct135 tree = ___itemFactory.FlatItemsToTree(unhandledItems.ToArray(), true, null);
foreach (Item item in tree.Items.Values.Where(i => i.CurrentAddress == null))
{
GClass1189 newItem = unhandledItems.First(i => i._id == item.Id);
GClass1198 newItem = unhandledItems.First(i => i._id == item.Id);
if (newItem.parentId != null || newItem.slotId != null)
{
// Assuming here that unhandled items are trying to go into containers in the stash - find that container
@@ -52,14 +52,14 @@ namespace UIFixes
{
if (containerCollection.GetContainer(newItem.slotId) is StashGridClass grid)
{
LocationInGrid location = GClass1485.CreateItemLocation<LocationInGrid>(newItem.location);
ItemAddress itemAddress = new GClass2769(grid, location);
LocationInGrid location = GClass1496.CreateItemLocation<LocationInGrid>(newItem.location);
ItemAddress itemAddress = new ItemAddressClass(grid, location);
GStruct414<GClass2782> operation = InteractionsHandlerClass.Add(item, itemAddress, ___gclass2764_0, false);
GStruct414<GClass2798> operation = InteractionsHandlerClass.Add(item, itemAddress, ___gclass2780_0, false);
if (operation.Succeeded)
{
operation.Value.RaiseEvents(___gclass2764_0, CommandStatus.Begin);
operation.Value.RaiseEvents(___gclass2764_0, CommandStatus.Succeed);
operation.Value.RaiseEvents(___gclass2780_0, CommandStatus.Begin);
operation.Value.RaiseEvents(___gclass2780_0, CommandStatus.Succeed);
}
}
}

View File

@@ -1,11 +1,11 @@
using Aki.Reflection.Patching;
using Bsg.GameSettings;
using Bsg.GameSettings;
using Comfort.Common;
using EFT.InputSystem;
using EFT.InventoryLogic;
using EFT.UI;
using EFT.UI.Settings;
using HarmonyLib;
using SPT.Reflection.Patching;
using System.Reflection;
namespace UIFixes

View File

@@ -1,6 +1,6 @@
using Aki.Reflection.Patching;
using EFT.UI;
using EFT.UI;
using HarmonyLib;
using SPT.Reflection.Patching;
using System.Reflection;
using UnityEngine;

View File

@@ -1,5 +1,5 @@
using Aki.Reflection.Patching;
using HarmonyLib;
using HarmonyLib;
using SPT.Reflection.Patching;
using System;
using System.Linq;
using System.Reflection;

View File

@@ -1,10 +1,10 @@
using Aki.Reflection.Patching;
using EFT.Hideout;
using EFT.Hideout;
using EFT.UI;
using EFT.UI.Chat;
using EFT.UI.Ragfair;
using EFT.UI.Utilities.LightScroller;
using HarmonyLib;
using SPT.Reflection.Patching;
using System;
using System.Collections.Generic;
using System.Reflection;
@@ -345,7 +345,7 @@ namespace UIFixes
}
[PatchPostfix]
public static void Postfix(NotesTask __instance, GClass1249 quest)
public static void Postfix(NotesTask __instance, QuestClass quest)
{
void OnTaskSelected(bool open)
{

View File

@@ -1,6 +1,6 @@
using Aki.Reflection.Patching;
using EFT.InventoryLogic;
using EFT.InventoryLogic;
using HarmonyLib;
using SPT.Reflection.Patching;
using System;
using System.Collections.Generic;
using System.Linq;
@@ -23,13 +23,13 @@ namespace UIFixes
protected override MethodBase GetTargetMethod()
{
MethodInfo method = AccessTools.Method(typeof(InteractionsHandlerClass), nameof(InteractionsHandlerClass.smethod_0));
MergeableItemType = method.GetParameters()[2].ParameterType.GetElementType(); // parameter is a ref type, get underlying type
MergeableItemType = method.GetParameters()[2].ParameterType.GetElementType(); // parameter is a ref type, get underlying type, GClass2751
return method;
}
// Reimplementing this entire method to ignore SpawnedInSession for certain types
[PatchPrefix]
public static bool Prefix(IEnumerable<StashGridClass> gridsToPut, Item itemToMerge, ref object mergeableItem, int overrideCount, ref bool __result)
public static bool Prefix(IEnumerable<EFT.InventoryLogic.IContainer> containersToPut, Item itemToMerge, ref object mergeableItem, int overrideCount, ref bool __result)
{
if (!MergeableItemType.IsInstanceOfType(itemToMerge))
{
@@ -56,8 +56,8 @@ namespace UIFixes
ignoreSpawnedInSession = Settings.MergeFIROther.Value;
}
mergeableItem = gridsToPut.SelectMany(x => x.Items)
.Where(x => MergeableItemType.IsInstanceOfType(x))
mergeableItem = containersToPut.SelectMany(x => x.Items)
.Where(MergeableItemType.IsInstanceOfType)
.Where(x => x != itemToMerge)
.Where(x => x.TemplateId == itemToMerge.TemplateId)
.Where(x => ignoreSpawnedInSession || x.SpawnedInSession == itemToMerge.SpawnedInSession)

View File

@@ -1,6 +1,6 @@
using Aki.Reflection.Patching;
using EFT.UI.DragAndDrop;
using EFT.UI.DragAndDrop;
using HarmonyLib;
using SPT.Reflection.Patching;
using System.Reflection;
using System.Threading;
using System.Threading.Tasks;

View File

@@ -1,11 +1,11 @@
using Aki.Reflection.Patching;
using Aki.Reflection.Utils;
using Comfort.Common;
using Comfort.Common;
using EFT;
using EFT.InventoryLogic;
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;
@@ -49,7 +49,7 @@ namespace UIFixes
new FixAddModFirearmOperationPatch().Enable();
}
private static bool ValidPrerequisites(ItemContextClass itemContext, ItemContextAbstractClass targetItemContext, object operation)
private static bool ValidPrerequisites(ItemContextClass itemContext, ItemContextAbstractClass targetItemContext, IInventoryEventResult operation)
{
if (!Settings.SwapItems.Value)
{
@@ -67,9 +67,7 @@ namespace UIFixes
return false;
}
var wrappedOperation = new R.GridViewCanAcceptOperation(operation);
if (InHighlight || itemContext == null || targetItemContext == null || wrappedOperation.Succeeded)
if (InHighlight || itemContext == null || targetItemContext == null || operation.Succeeded)
{
return false;
}
@@ -90,7 +88,7 @@ namespace UIFixes
return false;
}
string error = wrappedOperation.Error.ToString();
string error = operation.Error.ToString();
if (Settings.SwapImpossibleContainers.Value && !Plugin.InRaid() && error.StartsWith("No free room"))
{
// Check if it isn't allowed in that container, if so try to swap
@@ -218,7 +216,7 @@ namespace UIFixes
}
[PatchPostfix]
public static void Postfix(GridView __instance, ItemContextClass itemContext, ItemContextAbstractClass targetItemContext, ref object operation, ref bool __result, Dictionary<string, ItemView> ___dictionary_0)
public static void Postfix(GridView __instance, ItemContextClass itemContext, ItemContextAbstractClass targetItemContext, ref IInventoryEventResult operation, ref bool __result, Dictionary<string, ItemView> ___dictionary_0)
{
if (!ValidPrerequisites(itemContext, targetItemContext, operation))
{
@@ -313,7 +311,7 @@ namespace UIFixes
{
protected override MethodBase GetTargetMethod()
{
return AccessTools.Method(R.SwapOperation.Type.GenericTypeArguments[0], "RaiseEvents"); // GClass2797
return AccessTools.Method(R.SwapOperation.Type.GenericTypeArguments[0], "RaiseEvents"); // GClass2813
}
[PatchPostfix]
@@ -375,7 +373,7 @@ namespace UIFixes
}
[PatchPostfix]
public static void Postfix(ItemContextClass __instance, Slot slot, ItemContextAbstractClass targetItemContext, ref object operation, TraderControllerClass itemController, bool simulate, ref bool __result)
public static void Postfix(ItemContextClass __instance, Slot slot, ItemContextAbstractClass targetItemContext, ref IInventoryEventResult operation, TraderControllerClass itemController, bool simulate, ref bool __result)
{
// targetItemContext here is not the target item, it's the *parent* context, i.e. the owner of the slot
// Do a few more checks
@@ -458,7 +456,7 @@ namespace UIFixes
{
protected override MethodBase GetTargetMethod()
{
Type type = PatchConstants.EftTypes.Single(t => t.GetMethod("CheckItemFilter", BindingFlags.Public | BindingFlags.Static) != null); // GClass2510
Type type = PatchConstants.EftTypes.Single(t => t.GetMethod("CheckItemFilter", BindingFlags.Public | BindingFlags.Static) != null); // GClass2524
return AccessTools.Method(type, "CheckItemFilter");
}
@@ -506,7 +504,7 @@ namespace UIFixes
{
protected override MethodBase GetTargetMethod()
{
return AccessTools.Method(typeof(Player.FirearmController.Class1015), nameof(Player.FirearmController.Class1015.OnModChanged));
return AccessTools.Method(typeof(Player.FirearmController.Class1039), nameof(Player.FirearmController.Class1039.OnModChanged));
}
// The firearm state machine state Class1015 is the "adding mod" state
@@ -514,11 +512,11 @@ namespace UIFixes
// Patched to not be that stupid
[PatchPrefix]
public static bool Prefix(
Player.FirearmController.Class1015 __instance,
Player.FirearmController.Class1039 __instance,
bool ___bool_0,
FirearmsAnimator ___firearmsAnimator_0,
Item ___item_0,
GClass1668 ___gclass1668_0,
WeaponManagerClass ___weaponManagerClass,
Slot ___slot_0,
Weapon ___weapon_0,
Callback ___callback_0,
@@ -532,12 +530,12 @@ namespace UIFixes
___bool_0 = true;
___firearmsAnimator_0.SetupMod(false);
GameObject gameObject = Singleton<PoolManager>.Instance.CreateItem(___item_0, true);
___gclass1668_0.SetupMod(___slot_0, gameObject);
___weaponManagerClass.SetupMod(___slot_0, gameObject);
___firearmsAnimator_0.Fold(___weapon_0.Folded);
__instance.State = Player.EOperationState.Finished;
// Begin change (moved from bottom)
___firearmController_0.InitiateOperation<Player.FirearmController.GClass1608>().Start(null);
___firearmController_0.InitiateOperation<Player.FirearmController.GClass1619>().Start(null);
__instance.method_5(gameObject);
// End change

View File

@@ -1,7 +1,7 @@
using Aki.Reflection.Patching;
using EFT.UI;
using EFT.UI;
using EFT.UI.Ragfair;
using HarmonyLib;
using SPT.Reflection.Patching;
using System.Reflection;
using UnityEngine;
using UnityEngine.UI;
@@ -33,8 +33,9 @@ namespace UIFixes
scrollRect.verticalNormalizedPosition = StashScrollPosition;
scrollRect.onValueChanged.RemoveListener(UpdateScrollPosition);
scrollRect.onValueChanged.AddListener(UpdateScrollPosition);
element.R().UI.AddDisposable(() => scrollRect.onValueChanged.RemoveListener(UpdateScrollPosition));
//element.R().UI.AddDisposable(() => scrollRect.onValueChanged.RemoveListener(UpdateScrollPosition));
}
public class SyncStashScrollPatch : ModulePatch

View File

@@ -1,8 +1,8 @@
using Aki.Reflection.Patching;
using Comfort.Common;
using Comfort.Common;
using EFT.UI;
using EFT.UI.DragAndDrop;
using HarmonyLib;
using SPT.Reflection.Patching;
using System.Reflection;
using UnityEngine;
using UnityEngine.EventSystems;

View File

@@ -1,6 +1,6 @@
using Aki.Reflection.Patching;
using EFT.UI;
using EFT.UI;
using HarmonyLib;
using SPT.Reflection.Patching;
using System.Reflection;
using System.Threading.Tasks;

View File

@@ -1,4 +1,4 @@
using Aki.Reflection.Patching;
using SPT.Reflection.Patching;
using Comfort.Common;
using EFT.HealthSystem;
using EFT.InventoryLogic;
@@ -25,7 +25,7 @@ namespace UIFixes
{
protected override MethodBase GetTargetMethod()
{
return AccessTools.DeclaredProperty(typeof(GClass3032), nameof(GClass3032.AvailableInteractions)).GetMethod;
return AccessTools.DeclaredProperty(typeof(GClass3054), nameof(GClass3054.AvailableInteractions)).GetMethod;
}
[PatchPostfix]
@@ -41,7 +41,7 @@ namespace UIFixes
{
protected override MethodBase GetTargetMethod()
{
return AccessTools.DeclaredProperty(typeof(GClass3035), nameof(GClass3035.AvailableInteractions)).GetMethod;
return AccessTools.DeclaredProperty(typeof(GClass3057), nameof(GClass3057.AvailableInteractions)).GetMethod;
}
[PatchPostfix]
@@ -88,11 +88,11 @@ namespace UIFixes
{
protected override MethodBase GetTargetMethod()
{
return AccessTools.Constructor(typeof(ScavengerInventoryScreen.GClass3131), [typeof(GClass2764), typeof(GClass2764), typeof(IHealthController), typeof(StashClass), typeof(ISession)]);
return AccessTools.Constructor(typeof(ScavengerInventoryScreen.GClass3156), [typeof(GClass2780), typeof(GClass2780), typeof(IHealthController), typeof(StashClass), typeof(ISession)]);
}
[PatchPrefix]
public static void Prefix(GClass2764 scavController)
public static void Prefix(GClass2780 scavController)
{
scavController.Inventory.Stash = null;
}

View File

@@ -1,6 +1,6 @@
using Aki.Reflection.Patching;
using EFT.UI;
using EFT.UI;
using HarmonyLib;
using SPT.Reflection.Patching;
using System;
using System.Linq;
using System.Reflection;
@@ -25,7 +25,7 @@ namespace UIFixes
{
protected override MethodBase GetTargetMethod()
{
Type type = typeof(EditBuildScreen).GetNestedTypes().Single(x => x.GetMethod("CloseScreenInterruption") != null); // EditBuildScreen.GClass3126
Type type = typeof(EditBuildScreen).GetNestedTypes().Single(x => x.GetMethod("CloseScreenInterruption") != null); // EditBuildScreen.GClass3151
return AccessTools.Method(type, "CloseScreenInterruption");
}

View File

@@ -1,7 +1,7 @@
using Aki.Reflection.Patching;
using EFT.UI;
using EFT.UI;
using EFT.UI.WeaponModding;
using HarmonyLib;
using SPT.Reflection.Patching;
using System.Reflection;
using UnityEngine.EventSystems;

26
R.cs
View File

@@ -1,5 +1,4 @@
using Aki.Reflection.Utils;
using Comfort.Common;
using Comfort.Common;
using Diz.LanguageExtensions;
using EFT.Hideout;
using EFT.InputSystem;
@@ -9,6 +8,7 @@ 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;
@@ -39,7 +39,7 @@ namespace UIFixes
GridItemAddress.InitTypes();
SlotItemAddress.InitTypes();
GridView.InitTypes();
GridViewCanAcceptOperation.InitTypes();
//GridViewCanAcceptOperation.InitTypes();
SwapOperation.InitTypes();
InteractionButtonsContainer.InitTypes();
ContextMenuButton.InitTypes();
@@ -112,7 +112,7 @@ namespace UIFixes
public static void InitTypes()
{
Type = typeof(EFT.UI.MessageWindow).BaseType;
Type = typeof(EFT.UI.MessageWindow).BaseType; // DialogWindow<T>
AcceptMethod = AccessTools.Method(Type, "Accept");
}
@@ -126,7 +126,7 @@ namespace UIFixes
public static void InitTypes()
{
Type = PatchConstants.EftTypes.Single(x => x.GetMethod("GetBoundItemNames") != null); // GClass960
Type = PatchConstants.EftTypes.Single(x => x.GetMethod("GetBoundItemNames") != null); // GClass961
GetKeyNameMethod = AccessTools.Method(Type, "GetKeyName");
}
@@ -154,7 +154,7 @@ namespace UIFixes
public static void InitTypes()
{
Type = typeof(EFT.Hideout.ProductionPanel).GetNestedTypes().Single(t => t.GetField("availableSearch") != null); // ProductionPanel.Class1631
Type = typeof(EFT.Hideout.ProductionPanel).GetNestedTypes().Single(t => t.IsClass && t.GetField("availableSearch") != null); // ProductionPanel.Class1659
ProductionPanelField = AccessTools.Field(Type, "productionPanel_0");
}
@@ -312,7 +312,7 @@ namespace UIFixes
public static Color InvalidOperationColor { get { return (Color)InvalidOperationColorField.GetValue(null); } }
}
public class GridViewCanAcceptOperation(object value) : Wrapper(value)
/* public class GridViewCanAcceptOperation(object value) : Wrapper(value)
{
public static Type Type { get; private set; }
private static PropertyInfo SucceededProperty;
@@ -327,20 +327,22 @@ namespace UIFixes
public bool Succeeded { get { return (bool)SucceededProperty.GetValue(Value); } }
public Error Error { get { return (Error)ErrorProperty.GetValue(Value); } }
}
}*/
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<GClass2797>
ImplicitCastToGridViewCanAcceptOperationMethod = Type.GetMethods().Single(m => m.Name == "op_Implicit" && m.ReturnType == GridViewCanAcceptOperation.Type);
Type = AccessTools.Method(typeof(InteractionsHandlerClass), nameof(InteractionsHandlerClass.Swap)).ReturnType; // GStruct414<GClass2813>
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 object ToGridViewCanAcceptOperation() => ImplicitCastToGridViewCanAcceptOperationMethod.Invoke(null, [Value]);
public IInventoryEventResult ToGridViewCanAcceptOperation() => (IInventoryEventResult)ImplicitCastToGridViewCanAcceptOperationMethod.Invoke(null, [Value]);
}
public class InteractionButtonsContainer(object value) : UIElement(value)
@@ -687,7 +689,7 @@ namespace UIFixes
public static void InitTypes()
{
Type = PatchConstants.EftTypes.Single(t => t.GetProperty("IsOwnedByPlayer") != null); // GClass3052
Type = PatchConstants.EftTypes.Single(t => t.GetProperty("IsOwnedByPlayer") != null); // GClass3074
InsuranceCompanyField = AccessTools.GetDeclaredFields(Type).Single(f => f.FieldType == typeof(InsuranceCompanyClass));
}

View File

@@ -4,13 +4,11 @@ Quality of life improvements and fixes for SPT
Tarkov is full of annoyances but we can fix them! Sometimes.
✨ New in the latest version!
## Added features
New UI features enabled by this mod
- Multiselect - select multiple items at once with shift-click or dragging a selection box
- Multiselect - select multiple items at once with shift-click or dragging a selection box
- Move items around as a group, drop them into containers, place them in grids
- Ctrl-click and Alt-click to quick move or equip them all. Compatible with Quick Move to Containers!
- Context menu to insure all, equip all, unequip all, unload ammo from all
@@ -63,6 +61,7 @@ Existing SPT features made better
#### Hideout
- Remember window state when you leave hideout without closing (e.g. when searching for a recipe item on flea)
- Tools used in crafting will be returned to the container they were in
#### Mail
@@ -88,7 +87,7 @@ Fixing bugs that BSG won't or can't
- Remove the unimplemented door actions like "Bang & clear" that are never going to happen
- Fix the keybind for weapons always showing up as 1, 2, and 3. Now shows your actual keybind like every other slot
- Fix the quick item bar not respecting "Autohide" and "Never show" setting
- Fix the quick item bar not respecting "Autohide" and "Never show" setting
#### Mail

View File

@@ -126,7 +126,7 @@ namespace UIFixes
"Show Transfer Items Confirmation Dialog",
TransferConfirmationOption.Never,
new ConfigDescription(
"When to show the confirmation dialog when you close the item transfer screen without taking all the items",
"When to show the confirmation dialog when you close the item transfer screen without tSPTng all the items",
null,
new ConfigurationManagerAttributes { })));
@@ -353,7 +353,7 @@ namespace UIFixes
"Multiselect Item Placement",
MultiSelectStrategy.OriginalSpacing,
new ConfigDescription(
"Controls where multiselected items are placed, relative to the item being dragged. Note that original spacing only refers to items that were in the same grid.",
"Controls where multiselected items are placed, relative to the item being dragged",
null,
new ConfigurationManagerAttributes { })));
@@ -407,7 +407,7 @@ namespace UIFixes
"Autostack Money with FiR Money",
true,
new ConfigDescription(
"Allows automatic stacking of Found In Raid money with other money, making container interaction easier",
"Allows automatic stacking of Found In Raid money with other money, mSPTng container interaction easier",
null,
new ConfigurationManagerAttributes { })));
@@ -416,7 +416,7 @@ namespace UIFixes
"Autostack Ammo with FiR Ammo",
false,
new ConfigDescription(
"Allows automatic stacking of Found In Raid ammo with other money, making container interaction easier",
"Allows automatic stacking of Found In Raid ammo with other money, mSPTng container interaction easier",
null,
new ConfigurationManagerAttributes { })));
@@ -425,7 +425,7 @@ namespace UIFixes
"Autostack Items with FiR Items",
false,
new ConfigDescription(
"Allows automatic stacking of Found In Raid items with other items, making container interaction easier",
"Allows automatic stacking of Found In Raid items with other items, mSPTng container interaction easier",
null,
new ConfigurationManagerAttributes { })));

View File

@@ -26,10 +26,13 @@ namespace UIFixes
}
public void Cancel()
{
if (!totalTask.Task.IsCompleted)
{
totalTask.TrySetCanceled();
Complete();
}
}
public void OnDisable()
{

View File

@@ -4,7 +4,7 @@
<TargetFramework>net471</TargetFramework>
<AssemblyName>Tyfon.UIFixes</AssemblyName>
<Description>SPT UI Fixes</Description>
<Version>1.7.4</Version>
<Version>2.0.0</Version>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<LangVersion>latest</LangVersion>
<Configurations>Debug;Release;Dist</Configurations>
@@ -15,17 +15,17 @@
</PropertyGroup>
<PropertyGroup>
<PathToSPT Condition="'$(Configuration)'=='Debug'">..\..\..\..\SPT\3.8.3-debug</PathToSPT>
<PathToSPT Condition="'$(Configuration)'=='Release'">..\..\..\..\SPT\3.8.3</PathToSPT>
<PathToSPT Condition="'$(Configuration)'=='Dist'">..\..\..\..\SPT\3.8.3</PathToSPT>
<PathToSPT Condition="'$(Configuration)'=='Debug'">..\..\..\..\SPT\3.9.0-debug</PathToSPT>
<PathToSPT Condition="'$(Configuration)'=='Release'">..\..\..\..\SPT\3.9.0</PathToSPT>
<PathToSPT Condition="'$(Configuration)'=='Dist'">..\..\..\..\SPT\3.9.0</PathToSPT>
</PropertyGroup>
<ItemGroup>
<Reference Include="Aki.Common">
<HintPath>$(PathToSPT)\EscapeFromTarkov_Data\Managed\Aki.Common.dll</HintPath>
<Reference Include="spt-common">
<HintPath>$(PathToSPT)\BepInEx\plugins\spt\spt-common.dll</HintPath>
</Reference>
<Reference Include="Aki.Reflection">
<HintPath>$(PathToSPT)\EscapeFromTarkov_Data\Managed\Aki.Reflection.dll</HintPath>
<Reference Include="spt-reflection">
<HintPath>$(PathToSPT)\BepInEx\plugins\spt\spt-reflection.dll</HintPath>
</Reference>
<Reference Include="AnimationSystem.Types">
<HintPath>$(PathToSPT)\EscapeFromTarkov_Data\Managed\AnimationSystem.Types.dll</HintPath>

View File

@@ -38,7 +38,7 @@ import ignore from "ignore";
import archiver from "archiver";
import winston from "winston";
const sptPath = "/SPT/3.8.3-debug";
const sptPath = "/SPT/3.9.0-debug";
// Get the command line arguments to determine whether to use verbose logging.
const args = process.argv.slice(2);

View File

@@ -1,10 +1,10 @@
{
"name": "uifixes",
"version": "1.7.4",
"version": "2.0.0",
"main": "src/mod.js",
"license": "MIT",
"author": "Tyfon",
"akiVersion": "~3.8",
"sptVersion": "~3.9",
"loadBefore": [],
"loadAfter": [],
"incompatibilities": [],

View File

@@ -1,53 +1,29 @@
import type { DependencyContainer } from "tsyringe";
import type { InventoryController } from "@spt-aki/controllers/InventoryController";
import type { HideoutHelper } from "@spt-aki/helpers/HideoutHelper";
import type { InRaidHelper } from "@spt-aki/helpers/InRaidHelper";
import type { InventoryHelper } from "@spt-aki/helpers/InventoryHelper";
import type { ItemHelper } from "@spt-aki/helpers/ItemHelper";
import type { ProfileHelper } from "@spt-aki/helpers/ProfileHelper";
import type { RagfairSortHelper } from "@spt-aki/helpers/RagfairSortHelper";
import type { IHideoutSingleProductionStartRequestData } from "@spt-aki/models/eft/hideout/IHideoutSingleProductionStartRequestData";
import type { IRagfairOffer } from "@spt-aki/models/eft/ragfair/IRagfairOffer";
import { Money } from "@spt-aki/models/enums/Money";
import type { IPreAkiLoadMod } from "@spt-aki/models/external/IPreAkiLoadMod";
import type { ILogger } from "@spt-aki/models/spt/utils/ILogger";
import type { DatabaseServer } from "@spt-aki/servers/DatabaseServer";
import type { StaticRouterModService } from "@spt-aki/services/mod/staticRouter/StaticRouterModService";
import type { JsonUtil } from "@spt-aki/utils/JsonUtil";
import type { HideoutHelper } from "@spt/helpers/HideoutHelper";
import type { InRaidHelper } from "@spt/helpers/InRaidHelper";
import type { InventoryHelper } from "@spt/helpers/InventoryHelper";
import type { ItemHelper } from "@spt/helpers/ItemHelper";
import type { IHideoutSingleProductionStartRequestData } from "@spt/models/eft/hideout/IHideoutSingleProductionStartRequestData";
import type { IPreSptLoadMod } from "@spt/models/external/IPreSptLoadMod";
import type { ILogger } from "@spt/models/spt/utils/ILogger";
import type { DatabaseService } from "@spt/services/DatabaseService";
import type { StaticRouterModService } from "@spt/services/mod/staticRouter/StaticRouterModService";
import type { ICloner } from "@spt/utils/cloners/ICloner";
import config from "../config/config.json";
class UIFixes implements IPreAkiLoadMod {
private databaseServer: DatabaseServer;
class UIFixes implements IPreSptLoadMod {
private databaseService: DatabaseService;
private logger: ILogger;
public preAkiLoad(container: DependencyContainer): void {
this.databaseServer = container.resolve<DatabaseServer>("DatabaseServer");
this.logger = container.resolve<ILogger>("WinstonLogger");
public preSptLoad(container: DependencyContainer): void {
this.databaseService = container.resolve<DatabaseService>("DatabaseService");
this.logger = container.resolve<ILogger>("PrimaryLogger");
const profileHelper = container.resolve<ProfileHelper>("ProfileHelper");
const itemHelper = container.resolve<ItemHelper>("ItemHelper");
const staticRouterModService = container.resolve<StaticRouterModService>("StaticRouterModService");
const jsonUtil = container.resolve<JsonUtil>("JsonUtil");
// Handle scav profile for post-raid scav transfer swaps (fixed in 3.9.0)
container.afterResolution(
"InventoryController",
(_, inventoryController: InventoryController) => {
const original = inventoryController.swapItem;
inventoryController.swapItem = (pmcData, request, sessionID) => {
let playerData = pmcData;
if (request.fromOwner?.type === "Profile" && request.fromOwner.id !== playerData._id) {
playerData = profileHelper.getScavProfile(sessionID);
}
return original.call(inventoryController, playerData, request, sessionID);
};
},
{ frequency: "Always" }
);
const cloner = container.resolve<ICloner>("RecursiveCloner");
// Keep quickbinds for items that aren't actually lost on death
container.afterResolution(
@@ -57,7 +33,7 @@ class UIFixes implements IPreAkiLoadMod {
inRaidHelper.deleteInventory = (pmcData, sessionId) => {
// Copy the existing quickbinds
const fastPanel = jsonUtil.clone(pmcData.Inventory.fastPanel);
const fastPanel = cloner.clone(pmcData.Inventory.fastPanel);
// Nukes the inventory and the fastpanel
original.call(inRaidHelper, pmcData, sessionId);
@@ -73,23 +49,6 @@ class UIFixes implements IPreAkiLoadMod {
{ frequency: "Always" }
);
// Handle barter sort type (fixed in 3.9.0)
container.afterResolution(
"RagfairSortHelper",
(_, ragfairSortHelper: RagfairSortHelper) => {
const original = ragfairSortHelper.sortOffers;
ragfairSortHelper.sortOffers = (offers, type, direction) => {
if (+type == 2) {
offers.sort(this.sortOffersByBarter);
}
return original.call(ragfairSortHelper, offers, type, direction);
};
},
{ frequency: "Always" }
);
// Better tool return - starting production
if (config.putToolsBack) {
container.afterResolution(
@@ -124,7 +83,7 @@ class UIFixes implements IPreAkiLoadMod {
const original = inventoryHelper.addItemToStash;
inventoryHelper.addItemToStash = (sessionId, request, pmcData, output) => {
const itemWithModsToAddClone = jsonUtil.clone(request.itemWithModsToAdd);
const itemWithModsToAddClone = cloner.clone(request.itemWithModsToAdd);
// If a tool marked with uifixes is there, try to return it to its original container
const tool = itemWithModsToAddClone[0];
@@ -141,13 +100,13 @@ class UIFixes implements IPreAkiLoadMod {
containerId
);
const canPlaceResult = inventoryHelper.canPlaceItemInContainer(
jsonUtil.clone(containerFS2D), // will change the array so clone it
// will change the array so clone it
if (
inventoryHelper.canPlaceItemInContainer(
cloner.clone(containerFS2D),
itemWithModsToAddClone
);
// In 3.8.3 canPlaceItemInContainer is wonky and returns undefined when the answer is yes
if (canPlaceResult === undefined) {
)
) {
// At this point everything should succeed
inventoryHelper.placeItemInContainer(
containerFS2D,
@@ -189,7 +148,7 @@ class UIFixes implements IPreAkiLoadMod {
[
{
url: "/uifixes/assortUnlocks",
action: (url, info, sessionId, output) => {
action: async (url, info, sessionId, output) => {
return JSON.stringify(this.loadAssortmentUnlocks());
}
}
@@ -199,8 +158,8 @@ class UIFixes implements IPreAkiLoadMod {
}
private loadAssortmentUnlocks() {
const traders = this.databaseServer.getTables().traders;
const quests = this.databaseServer.getTables().templates.quests;
const traders = this.databaseService.getTraders();
const quests = this.databaseService.getQuests();
const result: Record<string, string> = {};
@@ -231,13 +190,6 @@ class UIFixes implements IPreAkiLoadMod {
return result;
}
private sortOffersByBarter(a: IRagfairOffer, b: IRagfairOffer): number {
const moneyTpls = Object.values<string>(Money);
const aIsOnlyMoney = a.requirements.length == 1 && moneyTpls.includes(a.requirements[0]._tpl) ? 1 : 0;
const bIsOnlyMoney = b.requirements.length == 1 && moneyTpls.includes(b.requirements[0]._tpl) ? 1 : 0;
return aIsOnlyMoney - bIsOnlyMoney;
}
}
module.exports = { mod: new UIFixes() };

View File

@@ -12,11 +12,8 @@
"outDir": "tmp",
"baseUrl": ".",
"paths": {
"@spt-aki/*": ["./types/*"]
"@spt/*": ["./types/*"]
}
},
"include": [
"src/*",
"src/**/*"
]
"include": ["src/*", "src/**/*"]
}