diff --git a/Patches/FleaPrevSearchPatches.cs b/Patches/FleaPrevSearchPatches.cs index 0b81e69..830a1ab 100644 --- a/Patches/FleaPrevSearchPatches.cs +++ b/Patches/FleaPrevSearchPatches.cs @@ -1,4 +1,5 @@ using Aki.Reflection.Patching; +using EFT.Quests; using EFT.UI; using EFT.UI.Ragfair; using EFT.UI.Utilities.LightScroller; @@ -35,9 +36,10 @@ namespace UIFixes { new RagfairScreenShowPatch().Enable(); new OfferViewListCategoryPickedPatch().Enable(); - new OfferViewDoneLoadingPatch().Enable(); - new OfferViewChangedPatch().Enable(); + new OfferViewListDoneLoadingPatch().Enable(); + new ChangedViewListType().Enable(); new OfferItemFixMaskPatch().Enable(); + new OfferViewLockedQuestPatch().Enable(); Settings.EnableFleaHistory.SettingChanged += (object sender, EventArgs args) => { @@ -138,7 +140,7 @@ namespace UIFixes if (current != null && current.filterRule.IsSimilarTo(session.RagFair.FilterRule)) { // Minor filter change, just update the current one - History.Peek().filterRule = session.RagFair.FilterRule; + current.filterRule = session.RagFair.FilterRule; return; } @@ -198,13 +200,29 @@ namespace UIFixes new(EFilterType.RemoveBartering, filterRule.RemoveBartering ? 1 : 0, filterRule.RemoveBartering), new(EFilterType.OfferOwnerType, filterRule.OfferOwnerType, filterRule.OfferOwnerType != 0), new(EFilterType.OnlyFunctional, filterRule.OnlyFunctional ? 1 : 0, filterRule.OnlyFunctional), - - // The following are all mutually exclusive - new(EFilterType.FilterSearch, filterRule.FilterSearchId, !filterRule.FilterSearchId.IsNullOrEmpty()), - new(EFilterType.NeededSearch, filterRule.NeededSearchId, !filterRule.NeededSearchId.IsNullOrEmpty()), - new(EFilterType.LinkedSearch, filterRule.LinkedSearchId, !filterRule.LinkedSearchId.IsNullOrEmpty()) }; + // 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) + if (!filterRule.FilterSearchId.IsNullOrEmpty()) + { + searches.Add(new(EFilterType.FilterSearch, filterRule.FilterSearchId, true)); + } + else if (!filterRule.NeededSearchId.IsNullOrEmpty()) + { + searches.Add(new(EFilterType.NeededSearch, filterRule.NeededSearchId, true)); + } + else if (!filterRule.LinkedSearchId.IsNullOrEmpty()) + { + searches.Add(new(EFilterType.LinkedSearch, filterRule.LinkedSearchId, true)); + } + else + { + searches.Add(new(EFilterType.FilterSearch, String.Empty, false)); + searches.Add(new(EFilterType.NeededSearch, String.Empty, false)); + searches.Add(new(EFilterType.LinkedSearch, String.Empty, false)); + } + ragFair.method_24(filterRule.ViewListType, [.. searches], false, out FilterRule newRule); // These properties don't consistute a new search, so much as a different view of the same search @@ -215,7 +233,7 @@ namespace UIFixes // Treat HandbookId as a new search, since it feels like a new view newRule.HandbookId = filterRule.HandbookId; - ragFair.SetFilterRule(newRule, true, true); + ragFair.SetFilterRule(newRule, true, !newRule.AnyIdSearch); } private static void UpdateColumnHeaders(FiltersPanel filtersPanel, ESortType sortType, bool sortDirection) @@ -247,7 +265,7 @@ namespace UIFixes } } - public class OfferViewChangedPatch : ModulePatch + public class ChangedViewListType : ModulePatch { protected override MethodBase GetTargetMethod() { @@ -282,7 +300,7 @@ namespace UIFixes } } - public class OfferViewDoneLoadingPatch : ModulePatch + public class OfferViewListDoneLoadingPatch : ModulePatch { protected override MethodBase GetTargetMethod() { @@ -301,6 +319,47 @@ namespace UIFixes } } + public class OfferViewLockedQuestPatch : ModulePatch + { + private static readonly Dictionary QuestUnlocks = []; + + protected override MethodBase GetTargetMethod() + { + return AccessTools.Method(typeof(OfferView), nameof(OfferView.method_10)); + } + + [PatchPostfix] + public static void Postfix(OfferView __instance, HoverTooltipArea ____hoverTooltipArea) + { + if (!Settings.ShowRequiredQuest.Value) + { + return; + } + + string templateId = __instance.Offer_0.Item.TemplateId; + if (__instance.Offer_0.Locked) + { + RawQuestClass quest = null; + if (QuestUnlocks.ContainsKey(templateId)) + { + quest = QuestUnlocks[templateId]; + } + else + { + quest = R.QuestCache.Instance.GetAllQuestTemplates() + .FirstOrDefault(q => q.Rewards[EQuestStatus.Success] + .Any(r => r.type == ERewardType.AssortmentUnlock && r.items.Any(i => i._tpl == templateId))); + QuestUnlocks[templateId] = quest; + } + + if (quest != null) + { + ____hoverTooltipArea.SetMessageText(____hoverTooltipArea.String_1 + " (" + quest.Name + ")", true); + } + } + } + } + public class OfferItemFixMaskPatch : ModulePatch { protected override MethodBase GetTargetMethod() diff --git a/R.cs b/R.cs index 91026bf..f8a278d 100644 --- a/R.cs +++ b/R.cs @@ -41,6 +41,7 @@ namespace UIFixes RagfairScreen.InitTypes(); OfferViewList.InitTypes(); FiltersPanel.InitTypes(); + QuestCache.InitTypes(); } public abstract class Wrapper(object value) @@ -378,6 +379,24 @@ namespace UIFixes public RagfairFilterButton PriceButton { get { return (RagfairFilterButton)PriceButtonField.GetValue(Value); } } public RagfairFilterButton ExpirationButton { get { return (RagfairFilterButton)ExpirationButtonField.GetValue(Value); } } } + + public class QuestCache(object value) : Wrapper(value) + { + public static Type Type { get; private set; } + private static PropertyInfo InstanceProperty; + private static MethodInfo GetAllQuestTemplatesMethod; + + public static void InitTypes() + { + Type = PatchConstants.EftTypes.First(t => t.GetMethod("GetAllQuestTemplates") != null); // GClass3212 + InstanceProperty = AccessTools.Property(Type, "Instance"); + GetAllQuestTemplatesMethod = AccessTools.Method(Type, "GetAllQuestTemplates"); + + } + + public static QuestCache Instance { get { return new QuestCache(InstanceProperty.GetValue(null)); } } + public IReadOnlyCollection GetAllQuestTemplates() => (IReadOnlyCollection)GetAllQuestTemplatesMethod.Invoke(Value, []); + } } public static class RExtentensions diff --git a/Settings.cs b/Settings.cs index bcdb88e..c0a9f82 100644 --- a/Settings.cs +++ b/Settings.cs @@ -57,6 +57,7 @@ namespace UIFixes // Flea Market public static ConfigEntry EnableFleaHistory { get; set; } + public static ConfigEntry ShowRequiredQuest { get; set; } // Advanced public static ConfigEntry StyleItemPanel { get; set; } @@ -224,6 +225,15 @@ namespace UIFixes null, new ConfigurationManagerAttributes { }))); + configEntries.Add(ShowRequiredQuest = config.Bind( + FleaMarketSection, + "Show Required Quest for Locked Offers", + true, + new ConfigDescription( + "For trader items locked behind quest completion, add the name of the quest to the tooltip", + null, + new ConfigurationManagerAttributes { }))); + // Advanced configEntries.Add(StyleItemPanel = config.Bind( AdvancedSection,