Show mod stats!
This commit is contained in:
400
Patches/ItemPanelPatches.cs
Normal file
400
Patches/ItemPanelPatches.cs
Normal file
@@ -0,0 +1,400 @@
|
|||||||
|
using Aki.Reflection.Patching;
|
||||||
|
using Aki.Reflection.Utils;
|
||||||
|
using EFT.InventoryLogic;
|
||||||
|
using EFT.UI;
|
||||||
|
using HarmonyLib;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Globalization;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Reflection;
|
||||||
|
using System.Text.RegularExpressions;
|
||||||
|
using TMPro;
|
||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
namespace UIFixes
|
||||||
|
{
|
||||||
|
internal class ItemPanelPatches
|
||||||
|
{
|
||||||
|
private static FieldInfo AttributeCompactPanelDictionaryField;
|
||||||
|
private static FieldInfo AttributeCompactDropdownDictionaryField;
|
||||||
|
|
||||||
|
private static FieldInfo ItemComponentItemField;
|
||||||
|
|
||||||
|
public static void Enable()
|
||||||
|
{
|
||||||
|
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));
|
||||||
|
|
||||||
|
Type ItemComponentType = PatchConstants.EftTypes.First(t => typeof(IItemComponent).IsAssignableFrom(t) && AccessTools.Field(t, "Item") != null);
|
||||||
|
ItemComponentItemField = AccessTools.Field(ItemComponentType, "Item");
|
||||||
|
|
||||||
|
new InjectButtonPatch().Enable();
|
||||||
|
new LoadModStatsPatch().Enable();
|
||||||
|
new CompareModPatch().Enable();
|
||||||
|
new FormatValuesPatch().Enable();
|
||||||
|
}
|
||||||
|
|
||||||
|
private class LoadModStatsPatch : ModulePatch
|
||||||
|
{
|
||||||
|
protected override MethodBase GetTargetMethod()
|
||||||
|
{
|
||||||
|
return AccessTools.Method(typeof(ItemSpecificationPanel), "method_5");
|
||||||
|
}
|
||||||
|
|
||||||
|
[PatchPostfix]
|
||||||
|
private static void Postfix(
|
||||||
|
ItemSpecificationPanel __instance,
|
||||||
|
Item ___item_0,
|
||||||
|
CompactCharacteristicPanel ____compactCharTemplate,
|
||||||
|
Transform ____compactPanel,
|
||||||
|
SimpleTooltip ___simpleTooltip_0)
|
||||||
|
{
|
||||||
|
if (!Settings.ShowModStats.Value || !(___item_0 is Mod))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool changed;
|
||||||
|
var deepAttributes = GetDeepAttributes(___item_0, out changed);
|
||||||
|
if (!changed)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var compactPanels = AttributeCompactPanelDictionaryField.GetValue(__instance) as IDisposable;
|
||||||
|
// Clean up existing one
|
||||||
|
if (compactPanels != null)
|
||||||
|
{
|
||||||
|
compactPanels.Dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
var newCompactPanels = Activator.CreateInstance(AttributeCompactPanelDictionaryField.FieldType,
|
||||||
|
[
|
||||||
|
deepAttributes,
|
||||||
|
____compactCharTemplate,
|
||||||
|
____compactPanel,
|
||||||
|
(ItemAttributeClass attribute, CompactCharacteristicPanel viewer) => viewer.Show(attribute, ___simpleTooltip_0, __instance.Boolean_0, 100)
|
||||||
|
]) as IEnumerable<KeyValuePair<ItemAttributeClass, CompactCharacteristicPanel>>;
|
||||||
|
|
||||||
|
AttributeCompactPanelDictionaryField.SetValue(__instance, newCompactPanels);
|
||||||
|
|
||||||
|
if (newCompactPanels.Any())
|
||||||
|
{
|
||||||
|
newCompactPanels.Last().Value.OnTextWidthCalculated += __instance.method_3;
|
||||||
|
int siblingIndex = newCompactPanels.Last().Value.Transform.GetSiblingIndex();
|
||||||
|
|
||||||
|
var compactDropdownPanels = AttributeCompactDropdownDictionaryField.GetValue(__instance) as IEnumerable<KeyValuePair<ItemAttributeClass, CompactCharacteristicDropdownPanel>>;
|
||||||
|
foreach (var item in compactDropdownPanels)
|
||||||
|
{
|
||||||
|
item.Value.Transform.SetSiblingIndex(++siblingIndex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
__instance.method_10(0f);
|
||||||
|
__instance.method_6(null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// The fundamental thing about mods is that unlike weapons, armor, etc, they do not change their own attributes when they "accept" inner mods.
|
||||||
|
// I guess weapons figure out their stats by deeply iterating all mods, rather than just their direct mods
|
||||||
|
// As a result, the compare method that works with weapons/armor doesn't work with mods. Normally, it "adds" the mod, clones the result, then reverts the "add". Hence
|
||||||
|
// the compareItem is the item with the mods. But again, as mods don't change their values, we see no change.
|
||||||
|
// I wish I could prefix method_6 and update the compare item with the deep attributes, but that only works when adding a mod
|
||||||
|
// When removing, current item and compare item end up the same since current item never considers the mod anyway
|
||||||
|
// So I have to forcably call the refresh values method
|
||||||
|
private class CompareModPatch : ModulePatch
|
||||||
|
{
|
||||||
|
private static MethodInfo RefreshStaticMethod;
|
||||||
|
|
||||||
|
protected override MethodBase GetTargetMethod()
|
||||||
|
{
|
||||||
|
RefreshStaticMethod = AccessTools.Method(typeof(ItemSpecificationPanel), "smethod_1", null, [typeof(CompactCharacteristicPanel)]);
|
||||||
|
|
||||||
|
return AccessTools.Method(typeof(ItemSpecificationPanel), "method_6");
|
||||||
|
}
|
||||||
|
|
||||||
|
[PatchPrefix]
|
||||||
|
private static void Prefix(Item compareItem)
|
||||||
|
{
|
||||||
|
if (compareItem is ArmorClass)
|
||||||
|
{
|
||||||
|
// Armor points is added in method_5, but not in other places so it's missed by compare
|
||||||
|
ArmorComponent[] armorComponents = compareItem.GetItemComponentsInChildren<ArmorComponent>(true).Where(c => c.ArmorClass > 0).ToArray<ArmorComponent>();
|
||||||
|
float maxDurability = armorComponents.Sum(c => c.Repairable.Durability);
|
||||||
|
|
||||||
|
ItemAttributeClass itemAttributeClass = new ItemAttributeClass(EItemAttributeId.ArmorPoints);
|
||||||
|
itemAttributeClass.Name = EItemAttributeId.ArmorPoints.GetName();
|
||||||
|
itemAttributeClass.Base = () => maxDurability;
|
||||||
|
itemAttributeClass.StringValue = () => Math.Round(maxDurability, 1).ToString(CultureInfo.InvariantCulture);
|
||||||
|
itemAttributeClass.DisplayType = () => EItemAttributeDisplayType.Compact;
|
||||||
|
|
||||||
|
compareItem.Attributes.Insert(0, itemAttributeClass);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[PatchPostfix]
|
||||||
|
private static void Postfix(ItemSpecificationPanel __instance, Item compareItem)
|
||||||
|
{
|
||||||
|
if (!Settings.ShowModStats.Value || !(compareItem is Mod))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool changed;
|
||||||
|
List<ItemAttributeClass> deepAttributes = GetDeepAttributes(compareItem, out changed);
|
||||||
|
if (!changed)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var compactPanels = AttributeCompactPanelDictionaryField.GetValue(__instance);
|
||||||
|
RefreshStaticMethod.Invoke(null, [compactPanels, deepAttributes]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private class InjectButtonPatch : ModulePatch
|
||||||
|
{
|
||||||
|
private static FieldInfo InteractionsButtonsContainerButtonTemplateField;
|
||||||
|
private static FieldInfo InteractionsButtonsContainerContainerField;
|
||||||
|
|
||||||
|
private static FieldInfo InteractionsButtonContainerUIField;
|
||||||
|
private static MethodInfo InteractionsButtonContainerUIDisposeMethod;
|
||||||
|
|
||||||
|
private static FieldInfo SimpleContextMenuButtonTextField;
|
||||||
|
|
||||||
|
protected override MethodBase GetTargetMethod()
|
||||||
|
{
|
||||||
|
InteractionsButtonsContainerButtonTemplateField = AccessTools.Field(typeof(InteractionButtonsContainer), "_buttonTemplate");
|
||||||
|
InteractionsButtonsContainerContainerField = AccessTools.Field(typeof(InteractionButtonsContainer), "_buttonsContainer");
|
||||||
|
|
||||||
|
InteractionsButtonContainerUIField = AccessTools.Field(typeof(InteractionButtonsContainer), "UI");
|
||||||
|
InteractionsButtonContainerUIDisposeMethod = AccessTools.Method(InteractionsButtonContainerUIField.FieldType, "AddDisposable", [typeof(Action)]);
|
||||||
|
|
||||||
|
SimpleContextMenuButtonTextField = AccessTools.Field(typeof(ContextMenuButton), "_text");
|
||||||
|
|
||||||
|
return AccessTools.Method(typeof(ItemSpecificationPanel), "method_4");
|
||||||
|
}
|
||||||
|
|
||||||
|
private static string GetLabel()
|
||||||
|
{
|
||||||
|
return Settings.ShowModStats.Value ? "HIDE MOD STATS" : "SHOW MOD STATS";
|
||||||
|
}
|
||||||
|
|
||||||
|
[PatchPostfix]
|
||||||
|
private static void Postfix(ItemSpecificationPanel __instance, ItemInfoInteractionsAbstractClass<EItemInfoButton> contextInteractions, Item ___item_0, InteractionButtonsContainer ____interactionButtonsContainer)
|
||||||
|
{
|
||||||
|
if (!(___item_0 is Mod))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
SimpleContextMenuButton template = InteractionsButtonsContainerButtonTemplateField.GetValue(____interactionButtonsContainer) as SimpleContextMenuButton;
|
||||||
|
Transform transform = InteractionsButtonsContainerContainerField.GetValue(____interactionButtonsContainer) as Transform;
|
||||||
|
|
||||||
|
SimpleContextMenuButton toggleButton = null;
|
||||||
|
|
||||||
|
Action onClick = () =>
|
||||||
|
{
|
||||||
|
Settings.ShowModStats.Value = !Settings.ShowModStats.Value;
|
||||||
|
|
||||||
|
var text = SimpleContextMenuButtonTextField.GetValue(toggleButton) as TextMeshProUGUI;
|
||||||
|
text.text = GetLabel();
|
||||||
|
|
||||||
|
__instance.method_5(); // rebuild stat panels
|
||||||
|
};
|
||||||
|
|
||||||
|
// Listen to the setting to handle multiple windows open at once
|
||||||
|
EventHandler onSettingChanged = (sender, args) =>
|
||||||
|
{
|
||||||
|
var text = SimpleContextMenuButtonTextField.GetValue(toggleButton) as TextMeshProUGUI;
|
||||||
|
text.text = GetLabel();
|
||||||
|
};
|
||||||
|
Settings.ShowModStats.SettingChanged += onSettingChanged;
|
||||||
|
|
||||||
|
Action createButton = () =>
|
||||||
|
{
|
||||||
|
Sprite sprite = CacheResourcesPopAbstractClass.Pop<Sprite>("Characteristics/Icons/Modding");
|
||||||
|
toggleButton = UnityEngine.Object.Instantiate(template, transform, false);
|
||||||
|
toggleButton.Show(GetLabel(), null, sprite, onClick, null);
|
||||||
|
____interactionButtonsContainer.method_5(toggleButton); // add to disposable list
|
||||||
|
};
|
||||||
|
|
||||||
|
// Subscribe to redraws to recreate when mods get dropped in
|
||||||
|
contextInteractions.OnRedrawRequired += createButton;
|
||||||
|
|
||||||
|
// And unsubscribe when the window goes away
|
||||||
|
InteractionsButtonContainerUIDisposeMethod.Invoke(InteractionsButtonContainerUIField.GetValue(____interactionButtonsContainer), [() =>
|
||||||
|
{
|
||||||
|
contextInteractions.OnRedrawRequired -= createButton;
|
||||||
|
Settings.ShowModStats.SettingChanged -= onSettingChanged;
|
||||||
|
}]);
|
||||||
|
|
||||||
|
createButton();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private class FormatValuesPatch : 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()
|
||||||
|
{
|
||||||
|
ItemAttributeField = AccessTools.Field(typeof(CompactCharacteristicPanel), "ItemAttribute");
|
||||||
|
IncreasingColorField = AccessTools.Field(typeof(CompactCharacteristicPanel), "_increasingColor");
|
||||||
|
DecreasingColorField = AccessTools.Field(typeof(CompactCharacteristicPanel), "_decreasingColor");
|
||||||
|
|
||||||
|
return AccessTools.Method(typeof(CompactCharacteristicPanel), "SetValues");
|
||||||
|
}
|
||||||
|
|
||||||
|
[PatchPostfix]
|
||||||
|
private static void Postfix(CompactCharacteristicPanel __instance, TextMeshProUGUI ___ValueText)
|
||||||
|
{
|
||||||
|
// Comparisons are shown as <value>(<changed>)
|
||||||
|
// <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
|
||||||
|
// This method is a gnarly pile of regex and replacements, blame BSG
|
||||||
|
|
||||||
|
Color increasingColor = (Color)IncreasingColorField.GetValue(__instance);
|
||||||
|
string increasingColorHex = "#" + ColorUtility.ToHtmlStringRGB(increasingColor);
|
||||||
|
|
||||||
|
Color decreasingColor = (Color)DecreasingColorField.GetValue(__instance);
|
||||||
|
string decreasingColorHex = "#" + ColorUtility.ToHtmlStringRGB(decreasingColor);
|
||||||
|
|
||||||
|
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
|
||||||
|
var match = Regex.Match(text, @" %\((.*)\)");
|
||||||
|
if (match.Success)
|
||||||
|
{
|
||||||
|
float value = float.Parse(match.Groups[1].Value);
|
||||||
|
string sign = value > 0 ? "+" : "";
|
||||||
|
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 " %"
|
||||||
|
if (NonPercentPercents.Contains((EItemAttributeId)attribute.Id))
|
||||||
|
{
|
||||||
|
text = Regex.Replace(text, @"%\(.*\)", "%<color=" + color + ">(" + sign + value + "%)</color>");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
text = Regex.Replace(text, @"%\(.*\)", "%<color=" + color + ">(" + sign + value.ToString("P1") + ")</color>");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// 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)%\((.*)\)");
|
||||||
|
if (match.Success)
|
||||||
|
{
|
||||||
|
float value = float.Parse(match.Groups[2].Value);
|
||||||
|
string sign = value > 0 ? "+" : "";
|
||||||
|
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>");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Finally the ones that aren't percents
|
||||||
|
match = Regex.Match(text, @"\((.*)\)");
|
||||||
|
if (match.Success)
|
||||||
|
{
|
||||||
|
float value = float.Parse(match.Groups[1].Value);
|
||||||
|
string sign = value > 0 ? "+" : "";
|
||||||
|
string color = (attribute.LessIsGood && value < 0) || (!attribute.LessIsGood && value > 0) ? increasingColorHex : decreasingColorHex;
|
||||||
|
text = Regex.Replace(text, @"\((.*)\)", "<color=" + color + ">(" + sign + value + ")</color>");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove trailing 0s
|
||||||
|
text = Regex.Replace(text, @"\.([1-9]*)0+\b", ".$1");
|
||||||
|
text = Regex.Replace(text, @"\.\B", "");
|
||||||
|
|
||||||
|
// Fix spacing
|
||||||
|
text = text.Replace(" %", "%");
|
||||||
|
text = text.Replace("(", " (");
|
||||||
|
|
||||||
|
___ValueText.text = text;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static List<ItemAttributeClass> GetDeepAttributes(Item item, out bool changed)
|
||||||
|
{
|
||||||
|
changed = false;
|
||||||
|
List<ItemAttributeClass> itemAttributes = item.Attributes.Where(a => a.DisplayType() == EItemAttributeDisplayType.Compact).ToList();
|
||||||
|
var subComponents = item.GetItemComponentsInChildren<IItemComponent>(true);
|
||||||
|
foreach (var subComponent in subComponents)
|
||||||
|
{
|
||||||
|
var subItem = ItemComponentItemField.GetValue(subComponent) as Item;
|
||||||
|
if (subItem == item)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
var subAttributes = GetDeepAttributes(subItem, out changed);
|
||||||
|
itemAttributes = CombineAttributes(itemAttributes, subAttributes).ToList();
|
||||||
|
changed = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return itemAttributes;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static IEnumerable<ItemAttributeClass> CombineAttributes(IList<ItemAttributeClass> first, IList<ItemAttributeClass> second)
|
||||||
|
{
|
||||||
|
foreach (EItemAttributeId id in first.Select(a => a.Id).Union(second.Select(a => a.Id)))
|
||||||
|
{
|
||||||
|
// Need to cast the id since it's of type Enum for some reason
|
||||||
|
var attribute = first.FirstOrDefault(a => (EItemAttributeId)a.Id == id);
|
||||||
|
var other = second.FirstOrDefault(a => (EItemAttributeId)a.Id == id);
|
||||||
|
if (attribute == null)
|
||||||
|
{
|
||||||
|
yield return other;
|
||||||
|
}
|
||||||
|
else if (other == null)
|
||||||
|
{
|
||||||
|
yield return attribute;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var combined = attribute.Clone();
|
||||||
|
switch (attribute.Id)
|
||||||
|
{
|
||||||
|
case EItemAttributeId.EffectiveDist:
|
||||||
|
case EItemAttributeId.SightingRange:
|
||||||
|
combined.Base = () => Math.Max(attribute.Base(), other.Base());
|
||||||
|
combined.StringValue = () => combined.Base().ToString();
|
||||||
|
break;
|
||||||
|
case EItemAttributeId.Accuracy:
|
||||||
|
case EItemAttributeId.Recoil:
|
||||||
|
combined.Base = () => attribute.Base() + other.Base();
|
||||||
|
combined.StringValue = () => combined.Base() + "%";
|
||||||
|
break;
|
||||||
|
case EItemAttributeId.Loudness:
|
||||||
|
case EItemAttributeId.Ergonomics:
|
||||||
|
case EItemAttributeId.Velocity:
|
||||||
|
combined.Base = () => attribute.Base() + other.Base();
|
||||||
|
combined.StringValue = () => combined.Base().ToString();
|
||||||
|
break;
|
||||||
|
case EItemAttributeId.DurabilityBurn:
|
||||||
|
case EItemAttributeId.HeatFactor:
|
||||||
|
case EItemAttributeId.CoolFactor:
|
||||||
|
combined.Base = () => attribute.Base() + other.Base();
|
||||||
|
combined.StringValue = () => combined.Base().ToString("P1");
|
||||||
|
break;
|
||||||
|
case EItemAttributeId.RaidModdable:
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
yield return combined;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@@ -3,7 +3,7 @@ using EFT.UI.DragAndDrop;
|
|||||||
using System;
|
using System;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
|
|
||||||
namespace UIFixes.Patches
|
namespace UIFixes
|
||||||
{
|
{
|
||||||
public class TooltipPatch : ModulePatch
|
public class TooltipPatch : ModulePatch
|
||||||
{
|
{
|
||||||
|
@@ -1,5 +1,4 @@
|
|||||||
using BepInEx;
|
using BepInEx;
|
||||||
using UIFixes.Patches;
|
|
||||||
|
|
||||||
namespace UIFixes
|
namespace UIFixes
|
||||||
{
|
{
|
||||||
@@ -19,6 +18,7 @@ namespace UIFixes
|
|||||||
new DisabledActionsPatch().Enable();
|
new DisabledActionsPatch().Enable();
|
||||||
SwapPatch.Enable();
|
SwapPatch.Enable();
|
||||||
new TooltipPatch().Enable();
|
new TooltipPatch().Enable();
|
||||||
|
ItemPanelPatches.Enable();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -12,6 +12,7 @@ namespace UIFixes
|
|||||||
public static ConfigEntry<int> MouseScrollMulti { get; set; }
|
public static ConfigEntry<int> MouseScrollMulti { get; set; }
|
||||||
public static ConfigEntry<bool> RemoveDisabledActions { get; set; }
|
public static ConfigEntry<bool> RemoveDisabledActions { get; set; }
|
||||||
public static ConfigEntry<bool> SwapItems { get; set; }
|
public static ConfigEntry<bool> SwapItems { get; set; }
|
||||||
|
public static ConfigEntry<bool> ShowModStats { get; set; }
|
||||||
|
|
||||||
public static void Init(ConfigFile config)
|
public static void Init(ConfigFile config)
|
||||||
{
|
{
|
||||||
@@ -23,6 +24,7 @@ namespace UIFixes
|
|||||||
MouseScrollMulti = config.Bind<int>("Inventory", "Mousewheel scrolling multiplier", 1, "How many rows to scroll with the mousewheel");
|
MouseScrollMulti = config.Bind<int>("Inventory", "Mousewheel scrolling multiplier", 1, "How many rows to scroll with the mousewheel");
|
||||||
SwapItems = config.Bind<bool>("Inventory", "In-place item swapping", true);
|
SwapItems = config.Bind<bool>("Inventory", "In-place item swapping", true);
|
||||||
RemoveDisabledActions = config.Bind<bool>("In Raid", "Hide unimplemented actions", false, "Hides actions you can't actually do, like \"Bang and Clear\", etc from locked doors and other interactable objects");
|
RemoveDisabledActions = config.Bind<bool>("In Raid", "Hide unimplemented actions", false, "Hides actions you can't actually do, like \"Bang and Clear\", etc from locked doors and other interactable objects");
|
||||||
|
ShowModStats = config.Bind<bool>("Items", "Show total mod stats", true, "Item mods will show stats that include mods attached to them (you can also control this from a mod's inspect window)");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -4,7 +4,7 @@
|
|||||||
<TargetFramework>net472</TargetFramework>
|
<TargetFramework>net472</TargetFramework>
|
||||||
<AssemblyName>Tyfon.UIFixes</AssemblyName>
|
<AssemblyName>Tyfon.UIFixes</AssemblyName>
|
||||||
<Description>SPT UI Fixes</Description>
|
<Description>SPT UI Fixes</Description>
|
||||||
<Version>1.2.0</Version>
|
<Version>1.3.0</Version>
|
||||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||||
<LangVersion>latest</LangVersion>
|
<LangVersion>latest</LangVersion>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
@@ -16,9 +16,15 @@
|
|||||||
<Reference Include="Assembly-CSharp">
|
<Reference Include="Assembly-CSharp">
|
||||||
<HintPath>..\..\..\..\SPT\3.8.0\EscapeFromTarkov_Data\Managed\Assembly-CSharp.dll</HintPath>
|
<HintPath>..\..\..\..\SPT\3.8.0\EscapeFromTarkov_Data\Managed\Assembly-CSharp.dll</HintPath>
|
||||||
</Reference>
|
</Reference>
|
||||||
|
<Reference Include="ItemComponent.Types">
|
||||||
|
<HintPath>..\..\..\..\SPT\3.8.0-debug\EscapeFromTarkov_Data\Managed\ItemComponent.Types.dll</HintPath>
|
||||||
|
</Reference>
|
||||||
<Reference Include="Sirenix.Serialization">
|
<Reference Include="Sirenix.Serialization">
|
||||||
<HintPath>..\..\..\..\SPT\3.8.0\EscapeFromTarkov_Data\Managed\Sirenix.Serialization.dll</HintPath>
|
<HintPath>..\..\..\..\SPT\3.8.0\EscapeFromTarkov_Data\Managed\Sirenix.Serialization.dll</HintPath>
|
||||||
</Reference>
|
</Reference>
|
||||||
|
<Reference Include="Unity.TextMeshPro">
|
||||||
|
<HintPath>..\..\..\..\SPT\3.8.0-debug\EscapeFromTarkov_Data\Managed\Unity.TextMeshPro.dll</HintPath>
|
||||||
|
</Reference>
|
||||||
<Reference Include="UnityEngine">
|
<Reference Include="UnityEngine">
|
||||||
<HintPath>..\..\..\..\SPT\3.8.0\EscapeFromTarkov_Data\Managed\UnityEngine.dll</HintPath>
|
<HintPath>..\..\..\..\SPT\3.8.0\EscapeFromTarkov_Data\Managed\UnityEngine.dll</HintPath>
|
||||||
</Reference>
|
</Reference>
|
||||||
|
Reference in New Issue
Block a user