diff --git a/Patches/RememberRepairerPatch.cs b/Patches/RememberRepairerPatch.cs index 5496954..bc74241 100644 --- a/Patches/RememberRepairerPatch.cs +++ b/Patches/RememberRepairerPatch.cs @@ -6,23 +6,46 @@ using UnityEngine; namespace UIFixes { - public class RememberRepairerPatch : ModulePatch + public static class RememberRepairerPatches { - private static readonly string PlayerPrefKey = "UIFixes.Repair.CurrentRepairerIndex"; - - protected override MethodBase GetTargetMethod() + public static void Enable() { - return AccessTools.Method(typeof(RepairerParametersPanel), nameof(RepairerParametersPanel.Show)); + new RememberRepairerPatch().Enable(); + new DefaultMaxRepairPatch().Enable(); } - [PatchPostfix] - public static void Postfix(RepairerParametersPanel __instance, DropDownBox ____tradersDropDown) + public class RememberRepairerPatch : ModulePatch { - __instance.R().UI.AddDisposable(____tradersDropDown.OnValueChanged.Subscribe(index => PlayerPrefs.SetInt(PlayerPrefKey, index))); + private static readonly string PlayerPrefKey = "UIFixes.Repair.CurrentRepairerIndex"; - if (PlayerPrefs.HasKey(PlayerPrefKey)) + protected override MethodBase GetTargetMethod() { - ____tradersDropDown.UpdateValue(PlayerPrefs.GetInt(PlayerPrefKey)); + return AccessTools.Method(typeof(RepairerParametersPanel), nameof(RepairerParametersPanel.Show)); + } + + [PatchPostfix] + public static void Postfix(RepairerParametersPanel __instance, DropDownBox ____tradersDropDown) + { + __instance.R().UI.AddDisposable(____tradersDropDown.OnValueChanged.Subscribe(index => PlayerPrefs.SetInt(PlayerPrefKey, index))); + + if (PlayerPrefs.HasKey(PlayerPrefKey)) + { + ____tradersDropDown.UpdateValue(PlayerPrefs.GetInt(PlayerPrefKey)); + } + } + } + + public class DefaultMaxRepairPatch : ModulePatch + { + protected override MethodBase GetTargetMethod() + { + return AccessTools.Method(typeof(RepairerParametersPanel), nameof(RepairerParametersPanel.method_3)); + } + + [PatchPostfix] + public static void Postfix(ConditionCharacteristicsSlider ____conditionSlider) + { + ____conditionSlider.method_1(); // like clicking >>, aka select max value } } } diff --git a/Plugin.cs b/Plugin.cs index ec38a0b..fc514df 100644 --- a/Plugin.cs +++ b/Plugin.cs @@ -42,7 +42,7 @@ namespace UIFixes AddOfferRememberAutoselectPatches.Enable(); KeepMessagesOpenPatches.Enable(); new FocusTradeQuantityPatch().Enable(); - new RememberRepairerPatch().Enable(); + RememberRepairerPatches.Enable(); new GridWindowButtonsPatch().Enable(); } diff --git a/R.cs b/R.cs index b9a75fb..28a2e4c 100644 --- a/R.cs +++ b/R.cs @@ -1,4 +1,5 @@ using Aki.Reflection.Utils; +using Comfort.Common; using Diz.LanguageExtensions; using EFT.Hideout; using EFT.InputSystem; @@ -12,6 +13,7 @@ using System; using System.Collections.Generic; using System.Linq; using System.Reflection; +using System.Threading.Tasks; using TMPro; using UnityEngine; using UnityEngine.UI; @@ -54,6 +56,7 @@ namespace UIFixes TradingItemView.InitTypes(); GridWindow.InitTypes(); GridSortPanel.InitTypes(); + RepairStrategy.InitTypes(); } public abstract class Wrapper(object value) @@ -585,6 +588,65 @@ namespace UIFixes public class RepairerParametersPanel(object value) : UIElement(value) { } public class MessageWindow(object value) : UIInputNode(value) { } + + public class RepairStrategy(object value) : Wrapper(value) + { + public static Type Type { get; private set; } + private static Type ArmorStrategyType; + private static Type DefaultStrategyType; + private static PropertyInfo RepairersProperty; + private static PropertyInfo CurrentRepairerProperty; + private static MethodInfo HowMuchRepairScoresCanAcceptMethod; + private static MethodInfo GetRepairPriceMethod; + private static MethodInfo GetCurrencyPriceMethod; + private static MethodInfo RepairItemMethod; + private static MethodInfo DurabilityMethod; + private static MethodInfo CanRepairMethod; + private static MethodInfo BrokenItemErrorMethod; + private static MethodInfo IsNoCorrespondingAreaMethod; + + public static void InitTypes() + { + Type = PatchConstants.EftTypes.Single(t => t.IsInterface && t.GetMethod("HowMuchRepairScoresCanAccept") != null); + ArmorStrategyType = PatchConstants.EftTypes.Single(t => t.IsClass && Type.IsAssignableFrom(t) && t.GetField("repairableComponent_0", BindingFlags.Instance | BindingFlags.NonPublic) == null); + DefaultStrategyType = PatchConstants.EftTypes.Single(t => Type.IsAssignableFrom(t) && t.GetField("repairableComponent_0", BindingFlags.Instance | BindingFlags.NonPublic) != null); + RepairersProperty = AccessTools.Property(Type, "Repairers"); + CurrentRepairerProperty = AccessTools.Property(Type, "CurrentRepairer"); + HowMuchRepairScoresCanAcceptMethod = AccessTools.Method(Type, "HowMuchRepairScoresCanAccept"); + GetRepairPriceMethod = AccessTools.Method(Type, "GetRepairPrice"); + GetCurrencyPriceMethod = AccessTools.Method(Type, "GetCurrencyPrice"); + RepairItemMethod = AccessTools.Method(Type, "RepairItem"); + DurabilityMethod = AccessTools.Method(Type, "Durability"); + CanRepairMethod = AccessTools.Method(Type, "CanRepair"); + BrokenItemErrorMethod = AccessTools.Method(Type, "BrokenItemError"); + IsNoCorrespondingAreaMethod = AccessTools.Method(Type, "IsNoCorrespondingArea"); + } + + public static RepairStrategy Create(Item item, RepairControllerClass repairController) + { + if (item.GetItemComponent() != null) + { + return new RepairStrategy(Activator.CreateInstance(ArmorStrategyType, [item, repairController])); + } + + return new RepairStrategy(Activator.CreateInstance(DefaultStrategyType, [item, repairController])); + } + + public IEnumerable Repairers { get { return (IEnumerable)RepairersProperty.GetValue(Value); } } + public IRepairer CurrentRepairer + { + get { return (IRepairer)CurrentRepairerProperty.GetValue(Value); } + set { CurrentRepairerProperty.SetValue(Value, value); } + } + public float HowMuchRepairScoresCanAccept() => (float)HowMuchRepairScoresCanAcceptMethod.Invoke(Value, []); + public double GetRepairPrice(float repairValue, object repairKit) => (double)GetRepairPriceMethod.Invoke(Value, [repairValue, repairKit]); + public int GetCurrencyPrice(float amount) => (int)GetCurrencyPriceMethod.Invoke(Value, [amount]); + public Task RepairItem(float repairAmount, object repairKit) => (Task)RepairItemMethod.Invoke(Value, [repairAmount, repairKit]); + public float Durability() => (float)DurabilityMethod.Invoke(Value, []); + public bool CanRepair(IRepairer repairer, string[] excludedCategories) => (bool)CanRepairMethod.Invoke(Value, [repairer, excludedCategories]); + public bool BrokenItemError() => (bool)BrokenItemErrorMethod.Invoke(Value, []); + public bool IsNoCorrespondingArea() => (bool)IsNoCorrespondingAreaMethod.Invoke(Value, []); + } } public static class RExtentensions diff --git a/RepairInteractions.cs b/RepairInteractions.cs index 348d7c5..e041700 100644 --- a/RepairInteractions.cs +++ b/RepairInteractions.cs @@ -3,7 +3,6 @@ using EFT.Communications; using EFT.InventoryLogic; using EFT.UI; using System; -using System.Collections.Generic; using System.Globalization; using System.Linq; @@ -13,7 +12,7 @@ namespace UIFixes { private readonly RepairControllerClass repairController; private readonly int playerRubles; - private readonly GInterface33 repairStrategy; + private readonly R.RepairStrategy repairStrategy; public RepairInteractions(Item item, ItemUiContext uiContext, int playerRubles) : base(uiContext) { @@ -24,9 +23,7 @@ namespace UIFixes this.playerRubles = playerRubles; - repairStrategy = item.GetItemComponent() != null ? - new GClass804(item, repairController) : - new GClass803(item, repairController); + repairStrategy = R.RepairStrategy.Create(item, repairController); Load(); } @@ -39,7 +36,7 @@ namespace UIFixes float repairAmount = repairStrategy.HowMuchRepairScoresCanAccept(); string text; - if (repairAmount < float.Epsilon) + if (repairAmount < float.Epsilon || !repairStrategy.CanRepair(repairStrategy.CurrentRepairer, repairStrategy.CurrentRepairer.Targets)) { text = string.Format("{0}", repairer.LocalizedName); } @@ -80,6 +77,11 @@ namespace UIFixes IRepairer repairer = repairStrategy.Repairers.Single(r => r.RepairerId == repairerId); repairStrategy.CurrentRepairer = repairer; + if (!repairStrategy.CanRepair(repairStrategy.CurrentRepairer, repairStrategy.CurrentRepairer.Targets)) + { + return new FailedResult(ERepairStatusWarning.ExceptionRepairItem.ToString()); + } + float repairAmount = repairStrategy.HowMuchRepairScoresCanAccept(); if (repairer is GClass802 repairKit)