Color full panel bars, swap containers, fix black text, fix non-delta parens
This commit is contained in:
@@ -8,7 +8,7 @@ using System.Reflection;
|
|||||||
|
|
||||||
namespace UIFixes
|
namespace UIFixes
|
||||||
{
|
{
|
||||||
internal class ContainerStackPatch : ModulePatch
|
public class ContainerStackPatch : ModulePatch
|
||||||
{
|
{
|
||||||
private static Type MergeableItemType;
|
private static Type MergeableItemType;
|
||||||
|
|
||||||
|
@@ -21,18 +21,23 @@ namespace UIFixes
|
|||||||
|
|
||||||
private static FieldInfo ItemComponentItemField;
|
private static FieldInfo ItemComponentItemField;
|
||||||
|
|
||||||
|
private static FieldInfo CompactCharacteristicPanelItemAttributeField;
|
||||||
|
|
||||||
public static void Enable()
|
public static void Enable()
|
||||||
{
|
{
|
||||||
AttributeCompactPanelDictionaryField = AccessTools.GetDeclaredFields(typeof(ItemSpecificationPanel)).First(f => typeof(IEnumerable<KeyValuePair<ItemAttributeClass, CompactCharacteristicPanel>>).IsAssignableFrom(f.FieldType));
|
AttributeCompactPanelDictionaryField = AccessTools.GetDeclaredFields(typeof(ItemSpecificationPanel)).First(f => typeof(IEnumerable<KeyValuePair<ItemAttributeClass, CompactCharacteristicPanel>>).IsAssignableFrom(f.FieldType));
|
||||||
AttributeCompactDropdownDictionaryField = AccessTools.GetDeclaredFields(typeof(ItemSpecificationPanel)).First(f => typeof(IEnumerable<KeyValuePair<ItemAttributeClass, CompactCharacteristicDropdownPanel>>).IsAssignableFrom(f.FieldType));
|
AttributeCompactDropdownDictionaryField = AccessTools.GetDeclaredFields(typeof(ItemSpecificationPanel)).First(f => typeof(IEnumerable<KeyValuePair<ItemAttributeClass, CompactCharacteristicDropdownPanel>>).IsAssignableFrom(f.FieldType));
|
||||||
|
|
||||||
Type ItemComponentType = PatchConstants.EftTypes.First(t => typeof(IItemComponent).IsAssignableFrom(t) && AccessTools.Field(t, "Item") != null);
|
Type itemComponentType = PatchConstants.EftTypes.First(t => typeof(IItemComponent).IsAssignableFrom(t) && t.GetField("Item") != null); // GClass2754
|
||||||
ItemComponentItemField = AccessTools.Field(ItemComponentType, "Item");
|
ItemComponentItemField = AccessTools.Field(itemComponentType, "Item");
|
||||||
|
|
||||||
|
CompactCharacteristicPanelItemAttributeField = AccessTools.Field(typeof(CompactCharacteristicPanel), "ItemAttribute");
|
||||||
|
|
||||||
new InjectButtonPatch().Enable();
|
new InjectButtonPatch().Enable();
|
||||||
new LoadModStatsPatch().Enable();
|
new LoadModStatsPatch().Enable();
|
||||||
new CompareModPatch().Enable();
|
new CompareModPatch().Enable();
|
||||||
new FormatValuesPatch().Enable();
|
new FormatCompactValuesPatch().Enable();
|
||||||
|
new FormatFullValuesPatch().Enable();
|
||||||
}
|
}
|
||||||
|
|
||||||
private class LoadModStatsPatch : ModulePatch
|
private class LoadModStatsPatch : ModulePatch
|
||||||
@@ -238,43 +243,72 @@ namespace UIFixes
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private class FormatValuesPatch : ModulePatch
|
private class FormatCompactValuesPatch : ModulePatch
|
||||||
{
|
{
|
||||||
// These fields are percents, but have been manually multipied by 100 already
|
|
||||||
private static EItemAttributeId[] NonPercentPercents = [EItemAttributeId.ChangeMovementSpeed, EItemAttributeId.ChangeTurningSpeed, EItemAttributeId.Ergonomics];
|
|
||||||
|
|
||||||
private static FieldInfo ItemAttributeField;
|
|
||||||
private static FieldInfo IncreasingColorField;
|
|
||||||
private static FieldInfo DecreasingColorField;
|
|
||||||
|
|
||||||
protected override MethodBase GetTargetMethod()
|
protected override MethodBase GetTargetMethod()
|
||||||
{
|
{
|
||||||
ItemAttributeField = AccessTools.Field(typeof(CompactCharacteristicPanel), "ItemAttribute");
|
|
||||||
IncreasingColorField = AccessTools.Field(typeof(CompactCharacteristicPanel), "_increasingColor");
|
|
||||||
DecreasingColorField = AccessTools.Field(typeof(CompactCharacteristicPanel), "_decreasingColor");
|
|
||||||
|
|
||||||
return AccessTools.Method(typeof(CompactCharacteristicPanel), "SetValues");
|
return AccessTools.Method(typeof(CompactCharacteristicPanel), "SetValues");
|
||||||
}
|
}
|
||||||
|
|
||||||
[PatchPostfix]
|
[PatchPostfix]
|
||||||
private static void Postfix(CompactCharacteristicPanel __instance, TextMeshProUGUI ___ValueText)
|
private static void Postfix(CompactCharacteristicPanel __instance, TextMeshProUGUI ___ValueText)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
FormatText(__instance, ___ValueText);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Logger.LogError(ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private class FormatFullValuesPatch : ModulePatch
|
||||||
|
{
|
||||||
|
protected override MethodBase GetTargetMethod()
|
||||||
|
{
|
||||||
|
return AccessTools.Method(typeof(CharacteristicPanel), "SetValues");
|
||||||
|
}
|
||||||
|
|
||||||
|
[PatchPostfix]
|
||||||
|
private static void Postfix(CharacteristicPanel __instance, TextMeshProUGUI ___ValueText)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
FormatText(__instance, ___ValueText);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Logger.LogError(ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// These fields are percents, but have been manually multipied by 100 already
|
||||||
|
private static readonly EItemAttributeId[] NonPercentPercents = [EItemAttributeId.ChangeMovementSpeed, EItemAttributeId.ChangeTurningSpeed, EItemAttributeId.Ergonomics];
|
||||||
|
|
||||||
|
private static void FormatText(CompactCharacteristicPanel panel, TextMeshProUGUI textMesh)
|
||||||
{
|
{
|
||||||
// Comparisons are shown as <value>(<changed>)
|
// Comparisons are shown as <value>(<changed>)
|
||||||
// <value> is from each attribute type's StringValue() function, so is formatted *mostly* ok
|
// <value> is from each attribute type's StringValue() function, so is formatted *mostly* ok
|
||||||
// <changed> is just naively formatted with ToString("F2"), so I have to figure out what it is and fix that
|
// <changed> is just naively formatted with ToString("F2"), so I have to figure out what it is and fix that
|
||||||
// This method is a gnarly pile of regex and replacements, blame BSG
|
// This method is a gnarly pile of regex and replacements, blame BSG
|
||||||
|
if (!Settings.StyleItemPanel.Value)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
Color increasingColor = (Color)IncreasingColorField.GetValue(__instance);
|
// These come from CompactCharacteristicPanel._increasingColor and _decreasingColor, which are hardcoded. Hardcoding here too because
|
||||||
string increasingColorHex = "#" + ColorUtility.ToHtmlStringRGB(increasingColor);
|
// CharacteristicPanel doesn't define and you get clear
|
||||||
|
const string IncreasingColorHex = "#5EC1FF";
|
||||||
|
const string DecreasingColorHex = "#C40000";
|
||||||
|
|
||||||
Color decreasingColor = (Color)DecreasingColorField.GetValue(__instance);
|
string text = textMesh.text;
|
||||||
string decreasingColorHex = "#" + ColorUtility.ToHtmlStringRGB(decreasingColor);
|
ItemAttributeClass attribute = CompactCharacteristicPanelItemAttributeField.GetValue(panel) as ItemAttributeClass;
|
||||||
|
|
||||||
string text = ___ValueText.text;
|
|
||||||
ItemAttributeClass attribute = ItemAttributeField.GetValue(__instance) as ItemAttributeClass;
|
|
||||||
|
|
||||||
// Some percents are formatted with ToString("P1"), which puts a space before the %. These are percents from 0-1, so the <changed> value need to be converted
|
// Some percents are formatted with ToString("P1"), which puts a space before the %. These are percents from 0-1, so the <changed> value need to be converted
|
||||||
var match = Regex.Match(text, @" %\((.*)\)");
|
var match = Regex.Match(text, @" %\(([+-].*)\)");
|
||||||
if (match.Success)
|
if (match.Success)
|
||||||
{
|
{
|
||||||
float value;
|
float value;
|
||||||
@@ -282,23 +316,23 @@ namespace UIFixes
|
|||||||
if (float.TryParse(match.Groups[1].Value, out value))
|
if (float.TryParse(match.Groups[1].Value, out value))
|
||||||
{
|
{
|
||||||
string sign = value > 0 ? "+" : "";
|
string sign = value > 0 ? "+" : "";
|
||||||
string color = (attribute.LessIsGood && value < 0) || (!attribute.LessIsGood && value > 0) ? increasingColorHex : decreasingColorHex;
|
string color = (attribute.LessIsGood && value < 0) || (!attribute.LessIsGood && value > 0) ? IncreasingColorHex : DecreasingColorHex;
|
||||||
|
|
||||||
// Except some that have a space weren't actually formatted with P1 and are 0-100 with a manually added " %"
|
// Except some that have a space weren't actually formatted with P1 and are 0-100 with a manually added " %"
|
||||||
if (NonPercentPercents.Contains((EItemAttributeId)attribute.Id))
|
if (NonPercentPercents.Contains((EItemAttributeId)attribute.Id))
|
||||||
{
|
{
|
||||||
text = Regex.Replace(text, @"%\(.*\)", "%<color=" + color + ">(" + sign + value + "%)</color>");
|
text = Regex.Replace(text, @"%\([+-].*\)", "%<color=" + color + ">(" + sign + value + "%)</color>");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
text = Regex.Replace(text, @"%\(.*\)", "%<color=" + color + ">(" + sign + value.ToString("P1") + ")</color>");
|
text = Regex.Replace(text, @"%\([+-].*\)", "%<color=" + color + ">(" + sign + value.ToString("P1") + ")</color>");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Others are rendered as num + "%", so there's no space before the %. These are percents but are from 0-100, not 0-1.
|
// Others are rendered as num + "%", so there's no space before the %. These are percents but are from 0-100, not 0-1.
|
||||||
match = Regex.Match(text, @"(\S)%\((.*)\)");
|
match = Regex.Match(text, @"(\S)%\(([+-].*)\)");
|
||||||
if (match.Success)
|
if (match.Success)
|
||||||
{
|
{
|
||||||
float value;
|
float value;
|
||||||
@@ -306,14 +340,14 @@ namespace UIFixes
|
|||||||
if (float.TryParse(match.Groups[2].Value, out value))
|
if (float.TryParse(match.Groups[2].Value, out value))
|
||||||
{
|
{
|
||||||
string sign = value > 0 ? "+" : "";
|
string sign = value > 0 ? "+" : "";
|
||||||
string color = (attribute.LessIsGood && value < 0) || (!attribute.LessIsGood && value > 0) ? increasingColorHex : decreasingColorHex;
|
string color = (attribute.LessIsGood && value < 0) || (!attribute.LessIsGood && value > 0) ? IncreasingColorHex : DecreasingColorHex;
|
||||||
text = Regex.Replace(text, @"(\S)%\((.*)\)", match.Groups[1].Value + "%<color=" + color + ">(" + sign + value + "%)</color>");
|
text = Regex.Replace(text, @"(\S)%\(([+-].*)\)", match.Groups[1].Value + "%<color=" + color + ">(" + sign + value + "%)</color>");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Finally the ones that aren't percents
|
// Finally the ones that aren't percents
|
||||||
match = Regex.Match(text, @"\((.*)\)");
|
match = Regex.Match(text, @"\(([+-].*)\)");
|
||||||
if (match.Success)
|
if (match.Success)
|
||||||
{
|
{
|
||||||
float value;
|
float value;
|
||||||
@@ -321,8 +355,8 @@ namespace UIFixes
|
|||||||
if (float.TryParse(match.Groups[1].Value, out value))
|
if (float.TryParse(match.Groups[1].Value, out value))
|
||||||
{
|
{
|
||||||
string sign = value > 0 ? "+" : "";
|
string sign = value > 0 ? "+" : "";
|
||||||
string color = (attribute.LessIsGood && value < 0) || (!attribute.LessIsGood && value > 0) ? increasingColorHex : decreasingColorHex;
|
string color = (attribute.LessIsGood && value < 0) || (!attribute.LessIsGood && value > 0) ? IncreasingColorHex : DecreasingColorHex;
|
||||||
text = Regex.Replace(text, @"\((.*)\)", "<color=" + color + ">(" + sign + value + ")</color>");
|
text = Regex.Replace(text, @"\(([+-].*)\)", "<color=" + color + ">(" + sign + value + ")</color>");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -335,8 +369,7 @@ namespace UIFixes
|
|||||||
text = text.Replace(" %", "%");
|
text = text.Replace(" %", "%");
|
||||||
text = text.Replace("(", " (");
|
text = text.Replace("(", " (");
|
||||||
|
|
||||||
___ValueText.text = text;
|
textMesh.text = text;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static List<ItemAttributeClass> GetDeepAttributes(Item item, out bool changed)
|
private static List<ItemAttributeClass> GetDeepAttributes(Item item, out bool changed)
|
||||||
@@ -421,7 +454,7 @@ namespace UIFixes
|
|||||||
// b) a dot and some trailing 0
|
// b) a dot and some trailing 0
|
||||||
// And all that is replaced to the original integer, and the significantDigits (if they exist)
|
// And all that is replaced to the original integer, and the significantDigits (if they exist)
|
||||||
// If neither matches this doesn't match and does nothing
|
// If neither matches this doesn't match and does nothing
|
||||||
return Regex.Replace(input, @"(?<integer>\d)((?<significantDecimals>\.[0-9]*[^0])0*\b)?(\.0+\b)?", "${integer}${significantDecimals}");
|
return Regex.Replace(input, @"(?<integer>\d)((?<significantDecimals>\.[0-9]*[1-9])0*\b)?(\.0+\b)?", "${integer}${significantDecimals}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -1,7 +1,8 @@
|
|||||||
using Aki.Reflection.Patching;
|
using Aki.Reflection.Patching;
|
||||||
using Aki.Reflection.Utils;
|
using Aki.Reflection.Utils;
|
||||||
|
using Comfort.Common;
|
||||||
|
using EFT;
|
||||||
using EFT.InventoryLogic;
|
using EFT.InventoryLogic;
|
||||||
using EFT.UI;
|
|
||||||
using EFT.UI.DragAndDrop;
|
using EFT.UI.DragAndDrop;
|
||||||
using HarmonyLib;
|
using HarmonyLib;
|
||||||
using System;
|
using System;
|
||||||
@@ -35,20 +36,24 @@ namespace UIFixes
|
|||||||
// Whether we're being called from the "check every slot" loop
|
// Whether we're being called from the "check every slot" loop
|
||||||
private static bool InHighlight = false;
|
private static bool InHighlight = false;
|
||||||
|
|
||||||
|
// The most recent CheckItemFilter result
|
||||||
|
private static string LastCheckItemFilterId;
|
||||||
|
private static bool LastCheckItemFilterResult;
|
||||||
|
|
||||||
public static void Enable()
|
public static void Enable()
|
||||||
{
|
{
|
||||||
GridItemAddressType = PatchConstants.EftTypes.First(t => typeof(ItemAddress).IsAssignableFrom(t) && AccessTools.Property(t, "Grid") != null);
|
GridItemAddressType = PatchConstants.EftTypes.First(t => typeof(ItemAddress).IsAssignableFrom(t) && t.GetProperty("Grid") != null); // GClass2769
|
||||||
GridItemAddressLocationInGridField = AccessTools.Field(GridItemAddressType, "LocationInGrid");
|
GridItemAddressLocationInGridField = AccessTools.Field(GridItemAddressType, "LocationInGrid");
|
||||||
GridItemAddressGridProperty = AccessTools.Property(GridItemAddressType, "Grid");
|
GridItemAddressGridProperty = AccessTools.Property(GridItemAddressType, "Grid");
|
||||||
|
|
||||||
SlotItemAddressType = PatchConstants.EftTypes.First(t => typeof(ItemAddress).IsAssignableFrom(t) && AccessTools.Field(t, "Slot") != null);
|
SlotItemAddressType = PatchConstants.EftTypes.First(t => typeof(ItemAddress).IsAssignableFrom(t) && t.GetField("Slot") != null); // GClass2767
|
||||||
SlotItemAddressSlotField = AccessTools.Field(SlotItemAddressType, "Slot");
|
SlotItemAddressSlotField = AccessTools.Field(SlotItemAddressType, "Slot");
|
||||||
|
|
||||||
CanAcceptOperationType = AccessTools.Method(typeof(GridView), "CanAccept").GetParameters()[2].ParameterType.GetElementType(); // parameter is a ref type, get underlying type
|
CanAcceptOperationType = AccessTools.Method(typeof(GridView), "CanAccept").GetParameters()[2].ParameterType.GetElementType(); // GStruct413, parameter is a ref type, get underlying type
|
||||||
CanAcceptOperationSucceededProperty = AccessTools.Property(CanAcceptOperationType, "Succeeded");
|
CanAcceptOperationSucceededProperty = AccessTools.Property(CanAcceptOperationType, "Succeeded");
|
||||||
CanAcceptOperationErrorProperty = AccessTools.Property(CanAcceptOperationType, "Error");
|
CanAcceptOperationErrorProperty = AccessTools.Property(CanAcceptOperationType, "Error");
|
||||||
|
|
||||||
SwapOperationType = AccessTools.Method(typeof(InteractionsHandlerClass), "Swap").ReturnType;
|
SwapOperationType = AccessTools.Method(typeof(InteractionsHandlerClass), "Swap").ReturnType; // GStruct414<GClass2797>
|
||||||
SwapOperationToCanAcceptOperationOperator = SwapOperationType.GetMethods().First(m => m.Name == "op_Implicit" && m.ReturnType == CanAcceptOperationType);
|
SwapOperationToCanAcceptOperationOperator = SwapOperationType.GetMethods().First(m => m.Name == "op_Implicit" && m.ReturnType == CanAcceptOperationType);
|
||||||
|
|
||||||
GridViewNonInteractableField = AccessTools.Field(typeof(GridView), "_nonInteractable");
|
GridViewNonInteractableField = AccessTools.Field(typeof(GridView), "_nonInteractable");
|
||||||
@@ -57,6 +62,12 @@ namespace UIFixes
|
|||||||
new GridViewCanAcceptPatch().Enable();
|
new GridViewCanAcceptPatch().Enable();
|
||||||
new GetHightLightColorPatch().Enable();
|
new GetHightLightColorPatch().Enable();
|
||||||
new SlotViewCanAcceptPatch().Enable();
|
new SlotViewCanAcceptPatch().Enable();
|
||||||
|
new CheckItemFilterPatch().Enable();
|
||||||
|
}
|
||||||
|
private static bool InRaid()
|
||||||
|
{
|
||||||
|
bool? inRaid = Singleton<AbstractGame>.Instance?.InRaid;
|
||||||
|
return inRaid.HasValue && inRaid.Value;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static bool ValidPrerequisites(ItemContextClass itemContext, ItemContextAbstractClass targetItemContext, object operation)
|
private static bool ValidPrerequisites(ItemContextClass itemContext, ItemContextAbstractClass targetItemContext, object operation)
|
||||||
@@ -75,6 +86,7 @@ namespace UIFixes
|
|||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if the source container is a non-interactable GridView. Specifically for StashSearch, but may exist in other scenarios?
|
// Check if the source container is a non-interactable GridView. Specifically for StashSearch, but may exist in other scenarios?
|
||||||
if (SourceContainer != null && SourceContainer is GridView && (bool)GridViewNonInteractableField.GetValue(SourceContainer))
|
if (SourceContainer != null && SourceContainer is GridView && (bool)GridViewNonInteractableField.GetValue(SourceContainer))
|
||||||
{
|
{
|
||||||
@@ -82,6 +94,21 @@ namespace UIFixes
|
|||||||
}
|
}
|
||||||
|
|
||||||
string error = CanAcceptOperationErrorProperty.GetValue(operation).ToString();
|
string error = CanAcceptOperationErrorProperty.GetValue(operation).ToString();
|
||||||
|
if (Settings.SwapImpossibleContainers.Value && !InRaid() && error.StartsWith("No free room"))
|
||||||
|
{
|
||||||
|
// Check if it isn't allowed in that container, if so try to swap
|
||||||
|
if (LastCheckItemFilterId == itemContext.Item.Id && !LastCheckItemFilterResult)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if it would ever fit no matter what, if not try to swap
|
||||||
|
if (!CouldEverFit(itemContext, targetItemContext))
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (!error.StartsWith("Cannot add") && !error.StartsWith("Cannot apply") && error != "InventoryError/NoPossibleActions")
|
if (!error.StartsWith("Cannot add") && !error.StartsWith("Cannot apply") && error != "InventoryError/NoPossibleActions")
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
@@ -90,6 +117,30 @@ namespace UIFixes
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static bool CouldEverFit(ItemContextClass itemContext, ItemContextAbstractClass containerItemContext)
|
||||||
|
{
|
||||||
|
Item item = itemContext.Item;
|
||||||
|
LootItemClass container = containerItemContext.Item as LootItemClass;
|
||||||
|
if (container == null)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
var size = item.CalculateCellSize();
|
||||||
|
var rotatedSize = item.CalculateRotatedSize(itemContext.ItemRotation == ItemRotation.Horizontal ? ItemRotation.Vertical : ItemRotation.Horizontal);
|
||||||
|
|
||||||
|
foreach (StashGridClass grid in container.Grids)
|
||||||
|
{
|
||||||
|
if (size.X <= grid.GridWidth.Value && size.Y <= grid.GridHeight.Value ||
|
||||||
|
rotatedSize.X <= grid.GridWidth.Value && rotatedSize.Y <= grid.GridHeight.Value)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
public class ItemViewOnDragPatch : ModulePatch
|
public class ItemViewOnDragPatch : ModulePatch
|
||||||
{
|
{
|
||||||
protected override MethodBase GetTargetMethod()
|
protected override MethodBase GetTargetMethod()
|
||||||
@@ -219,10 +270,10 @@ namespace UIFixes
|
|||||||
{
|
{
|
||||||
// Try original rotations
|
// Try original rotations
|
||||||
var result = InteractionsHandlerClass.Swap(item, itemToAddress, targetItem, targetToAddress, traderControllerClass, true);
|
var result = InteractionsHandlerClass.Swap(item, itemToAddress, targetItem, targetToAddress, traderControllerClass, true);
|
||||||
|
operation = SwapOperationToCanAcceptOperationOperator.Invoke(null, [result]);
|
||||||
|
__result = (bool)CanAcceptOperationSucceededProperty.GetValue(operation);
|
||||||
if (result.Succeeded)
|
if (result.Succeeded)
|
||||||
{
|
{
|
||||||
operation = SwapOperationToCanAcceptOperationOperator.Invoke(null, [result]);
|
|
||||||
__result = true;
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -301,5 +352,22 @@ namespace UIFixes
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// CanApply, when dealing with containers, eventually calls down into FindPlaceForItem, which calls CheckItemFilter. For reasons,
|
||||||
|
// if an item fails the filters, it returns the error "no space", instead of "no action". Try to detect this, so we can swap.
|
||||||
|
public class CheckItemFilterPatch : ModulePatch
|
||||||
|
{
|
||||||
|
protected override MethodBase GetTargetMethod()
|
||||||
|
{
|
||||||
|
Type type = PatchConstants.EftTypes.First(t => t.GetMethod("CheckItemFilter", BindingFlags.Public | BindingFlags.Static) != null); // GClass2510
|
||||||
|
return AccessTools.Method(type, "CheckItemFilter");
|
||||||
|
}
|
||||||
|
|
||||||
|
[PatchPostfix]
|
||||||
|
private static void Postfix(Item item, ref bool __result)
|
||||||
|
{
|
||||||
|
LastCheckItemFilterId = item.Id;
|
||||||
|
LastCheckItemFilterResult = __result;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
24
Settings.cs
24
Settings.cs
@@ -25,6 +25,7 @@ namespace UIFixes
|
|||||||
private const string InputSection = "2. Input";
|
private const string InputSection = "2. Input";
|
||||||
private const string InventorySection = "3. Inventory";
|
private const string InventorySection = "3. Inventory";
|
||||||
private const string InRaidSection = "4. In Raid";
|
private const string InRaidSection = "4. In Raid";
|
||||||
|
private const string AdvancedSection = "5. Advanced";
|
||||||
|
|
||||||
// General
|
// General
|
||||||
public static ConfigEntry<WeaponPresetConfirmationOption> ShowPresetConfirmations { get; set; }
|
public static ConfigEntry<WeaponPresetConfirmationOption> ShowPresetConfirmations { get; set; }
|
||||||
@@ -38,6 +39,7 @@ namespace UIFixes
|
|||||||
|
|
||||||
// Inventory
|
// Inventory
|
||||||
public static ConfigEntry<bool> SwapItems { get; set; }
|
public static ConfigEntry<bool> SwapItems { get; set; }
|
||||||
|
public static ConfigEntry<bool> SwapImpossibleContainers { get; set; }
|
||||||
public static ConfigEntry<bool> MergeFIRMoney { get; set; }
|
public static ConfigEntry<bool> MergeFIRMoney { get; set; }
|
||||||
public static ConfigEntry<bool> MergeFIRAmmo { get; set; }
|
public static ConfigEntry<bool> MergeFIRAmmo { get; set; }
|
||||||
public static ConfigEntry<bool> MergeFIROther { get; set; }
|
public static ConfigEntry<bool> MergeFIROther { get; set; }
|
||||||
@@ -45,6 +47,9 @@ namespace UIFixes
|
|||||||
// In Raid
|
// In Raid
|
||||||
public static ConfigEntry<bool> RemoveDisabledActions { get; set; }
|
public static ConfigEntry<bool> RemoveDisabledActions { get; set; }
|
||||||
|
|
||||||
|
// Advanced
|
||||||
|
public static ConfigEntry<bool> StyleItemPanel { get; set; }
|
||||||
|
|
||||||
public static void Init(ConfigFile config)
|
public static void Init(ConfigFile config)
|
||||||
{
|
{
|
||||||
var configEntries = new List<ConfigEntryBase>();
|
var configEntries = new List<ConfigEntryBase>();
|
||||||
@@ -115,6 +120,15 @@ namespace UIFixes
|
|||||||
null,
|
null,
|
||||||
new ConfigurationManagerAttributes { })));
|
new ConfigurationManagerAttributes { })));
|
||||||
|
|
||||||
|
configEntries.Add(SwapImpossibleContainers = config.Bind(
|
||||||
|
InventorySection,
|
||||||
|
"Swap with Incompatible Containers",
|
||||||
|
false,
|
||||||
|
new ConfigDescription(
|
||||||
|
"Enable swapping items with containers that could never fit that item due to size or filter restrictions. Disabled in raid to avoid costly mistakes.",
|
||||||
|
null,
|
||||||
|
new ConfigurationManagerAttributes { })));
|
||||||
|
|
||||||
configEntries.Add(MergeFIRMoney = config.Bind(
|
configEntries.Add(MergeFIRMoney = config.Bind(
|
||||||
InventorySection,
|
InventorySection,
|
||||||
"Autostack Money with FiR Money",
|
"Autostack Money with FiR Money",
|
||||||
@@ -152,6 +166,16 @@ namespace UIFixes
|
|||||||
null,
|
null,
|
||||||
new ConfigurationManagerAttributes { })));
|
new ConfigurationManagerAttributes { })));
|
||||||
|
|
||||||
|
// Advanced
|
||||||
|
configEntries.Add(StyleItemPanel = config.Bind(
|
||||||
|
AdvancedSection,
|
||||||
|
"Style Item Panel",
|
||||||
|
true,
|
||||||
|
new ConfigDescription(
|
||||||
|
"Clean up and colorize item stats",
|
||||||
|
null,
|
||||||
|
new ConfigurationManagerAttributes { IsAdvanced = true })));
|
||||||
|
|
||||||
RecalcOrder(configEntries);
|
RecalcOrder(configEntries);
|
||||||
}
|
}
|
||||||
private static void RecalcOrder(List<ConfigEntryBase> configEntries)
|
private static void RecalcOrder(List<ConfigEntryBase> configEntries)
|
||||||
|
@@ -1,3 +1,5 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
namespace UIFixes.Test
|
namespace UIFixes.Test
|
||||||
{
|
{
|
||||||
[TestClass]
|
[TestClass]
|
||||||
@@ -21,13 +23,16 @@ namespace UIFixes.Test
|
|||||||
{ "del. 2sec", "del. 2sec" },
|
{ "del. 2sec", "del. 2sec" },
|
||||||
{ "Hello.world", "Hello.world" },
|
{ "Hello.world", "Hello.world" },
|
||||||
{ "2Fast20Furious0", "2Fast20Furious0" },
|
{ "2Fast20Furious0", "2Fast20Furious0" },
|
||||||
{ "1.0.2", "1.0.2" }
|
{ "2.720(+0.57)", "2.72(+0.57)" },
|
||||||
|
{ "2.720<color=#FFFFFF>(+0.64)</color>", "2.72<color=#FFFFFF>(+0.64)</color>" },
|
||||||
|
{ "Class 3 (34)", "Class 3 (34)" },
|
||||||
|
{ "$1234 (30)", "$1234 (30)" }
|
||||||
};
|
};
|
||||||
|
|
||||||
foreach (var testCase in testCases)
|
foreach (var testCase in testCases)
|
||||||
{
|
{
|
||||||
string result = ItemPanelPatches.RemoveTrailingZeros(testCase.Key);
|
string result = ItemPanelPatches.RemoveTrailingZeros(testCase.Key);
|
||||||
Assert.AreEqual(result, testCase.Value);
|
Assert.AreEqual(testCase.Value, result);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -4,7 +4,7 @@
|
|||||||
<TargetFramework>net471</TargetFramework>
|
<TargetFramework>net471</TargetFramework>
|
||||||
<AssemblyName>Tyfon.UIFixes</AssemblyName>
|
<AssemblyName>Tyfon.UIFixes</AssemblyName>
|
||||||
<Description>SPT UI Fixes</Description>
|
<Description>SPT UI Fixes</Description>
|
||||||
<Version>1.3.2</Version>
|
<Version>1.3.3</Version>
|
||||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||||
<LangVersion>latest</LangVersion>
|
<LangVersion>latest</LangVersion>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
@@ -25,6 +25,9 @@
|
|||||||
<Reference Include="Assembly-CSharp">
|
<Reference Include="Assembly-CSharp">
|
||||||
<HintPath>$(PathToSPT)\EscapeFromTarkov_Data\Managed\Assembly-CSharp.dll</HintPath>
|
<HintPath>$(PathToSPT)\EscapeFromTarkov_Data\Managed\Assembly-CSharp.dll</HintPath>
|
||||||
</Reference>
|
</Reference>
|
||||||
|
<Reference Include="Comfort">
|
||||||
|
<HintPath>$(PathToSPT)\EscapeFromTarkov_Data\Managed\Comfort.dll</HintPath>
|
||||||
|
</Reference>
|
||||||
<Reference Include="ItemComponent.Types">
|
<Reference Include="ItemComponent.Types">
|
||||||
<HintPath>$(PathToSPT)\EscapeFromTarkov_Data\Managed\ItemComponent.Types.dll</HintPath>
|
<HintPath>$(PathToSPT)\EscapeFromTarkov_Data\Managed\ItemComponent.Types.dll</HintPath>
|
||||||
</Reference>
|
</Reference>
|
||||||
|
Reference in New Issue
Block a user