From 428ce52c275dcf5bc9c2cab8a67ed51835da74bc Mon Sep 17 00:00:00 2001 From: Kurt Date: Sun, 5 Jun 2022 13:18:31 -0700 Subject: [PATCH] Add Current Handler checks & toggles Default settings do not flag, as Database view does not track the savefile (LegalityAnalysis only indirectly references the latest loaded save file, not the true source). Bulk Analysis will flag them correctly if run. Can be turned off. --- PKHeX.Core/Legality/BulkAnalysis.cs | 33 ++++++++++++++++++- .../Formatting/LegalityCheckStrings.cs | 4 +++ .../Legality/Verifiers/HistoryVerifier.cs | 21 ++++++++++++ .../Legality/Verifiers/ParseSettings.cs | 11 +++++++ .../Controls/SAV Editor/SAVEditor.cs | 2 +- PKHeX.WinForms/Properties/PKHeXSettings.cs | 14 ++++++++ 6 files changed, 83 insertions(+), 2 deletions(-) diff --git a/PKHeX.Core/Legality/BulkAnalysis.cs b/PKHeX.Core/Legality/BulkAnalysis.cs index e2b52e4b2..e7c20a6e0 100644 --- a/PKHeX.Core/Legality/BulkAnalysis.cs +++ b/PKHeX.Core/Legality/BulkAnalysis.cs @@ -20,11 +20,13 @@ public sealed class BulkAnalysis public readonly Dictionary Trackers = new(); public readonly bool Valid; + private readonly IBulkAnalysisSettings Settings; private readonly bool[] CloneFlags; - public BulkAnalysis(SaveFile sav) + public BulkAnalysis(SaveFile sav, IBulkAnalysisSettings settings) { Trainer = sav; + Settings = settings; var list = new List(sav.BoxSlotCount + (sav.HasParty ? 6 : 0) + 5); SlotInfoLoader.AddFromSaveFile(sav, list); list.RemoveAll(IsEmptyData); @@ -55,7 +57,11 @@ private bool ScanAll() CheckIDReuse(); CheckPIDReuse(); if (Trainer.Generation >= 6) + { CheckECReuse(); + if (Settings.CheckActiveHandler) + CheckHandlerFlag(); + } CheckDuplicateOwnedGifts(); return Parse.All(z => z.Valid); @@ -185,6 +191,31 @@ private void CheckPIDReuse() } } + private void CheckHandlerFlag() + { + for (var i = 0; i < AllData.Count; i++) + { + if (!AllAnalysis[i].Valid) + continue; + var cs = AllData[i]; + var pk = cs.Entity; + var tr = cs.SAV; + var withOT = tr.IsFromTrainer(pk); + var flag = pk.CurrentHandler; + var expect = withOT ? 0 : 1; + if (flag != expect) + AddLine(cs, LegalityCheckStrings.LTransferCurrentHandlerInvalid, CheckIdentifier.Trainer); + + if (flag == 1) + { + if (pk.HT_Name != tr.OT) + AddLine(cs, LegalityCheckStrings.LTransferHTMismatchName, CheckIdentifier.Trainer); + if (pk is IHandlerLanguage h && h.HT_Language != tr.Language) + AddLine(cs, LegalityCheckStrings.LTransferHTMismatchLanguage, CheckIdentifier.Trainer); + } + } + } + private sealed record CombinedReference(SlotCache Slot, LegalityAnalysis Analysis); private void CheckIDReuse() diff --git a/PKHeX.Core/Legality/Formatting/LegalityCheckStrings.cs b/PKHeX.Core/Legality/Formatting/LegalityCheckStrings.cs index 0c355e4bc..b496e21c8 100644 --- a/PKHeX.Core/Legality/Formatting/LegalityCheckStrings.cs +++ b/PKHeX.Core/Legality/Formatting/LegalityCheckStrings.cs @@ -465,11 +465,15 @@ public static class LegalityCheckStrings public static string LSuperUnused { get; set; } = "Unused Super Training Flag is flagged."; public static string LTransferBad { get; set; } = "Incorrectly transferred from previous generation."; + + public static string LTransferCurrentHandlerInvalid { get; set; } = "Invalid Current handler value, trainer details for save file expected another value."; public static string LTransferEgg { get; set; } = "Can't transfer Eggs between Generations."; public static string LTransferEggLocationTransporter { get; set; } = "Invalid Met Location, expected Poké Transfer."; public static string LTransferEggMetLevel { get; set; } = "Invalid Met Level for transfer."; public static string LTransferFlagIllegal { get; set; } = "Flagged as illegal by the game (glitch abuse)."; public static string LTransferHTFlagRequired { get; set; } = "Current handler cannot be past gen OT for transferred specimen."; + public static string LTransferHTMismatchName { get; set; } = "Handling trainer does not match the expected trainer name."; + public static string LTransferHTMismatchLanguage { get; set; } = "Handling trainer does not match the expected trainer language."; public static string LTransferMet { get; set; } = "Invalid Met Location, expected Poké Transfer or Crown."; public static string LTransferNotPossible { get; set; } = "Unable to transfer into current format from origin format."; public static string LTransferMetLocation { get; set; } = "Invalid Transfer Met Location."; diff --git a/PKHeX.Core/Legality/Verifiers/HistoryVerifier.cs b/PKHeX.Core/Legality/Verifiers/HistoryVerifier.cs index f7e06712d..b44995e75 100644 --- a/PKHeX.Core/Legality/Verifiers/HistoryVerifier.cs +++ b/PKHeX.Core/Legality/Verifiers/HistoryVerifier.cs @@ -55,6 +55,27 @@ private void VerifyHandlerState(LegalityAnalysis data, bool neverOT) var Info = data.Info; // HT Flag + if (ParseSettings.CheckActiveHandler) + { + var tr = ParseSettings.ActiveTrainer; + var withOT = tr.IsFromTrainer(pkm); + var flag = pkm.CurrentHandler; + var expect = withOT ? 0 : 1; + if (flag != expect) + { + data.AddLine(GetInvalid(LegalityCheckStrings.LTransferCurrentHandlerInvalid)); + return; + } + + if (flag == 1) + { + if (pkm.HT_Name != tr.OT) + data.AddLine(GetInvalid(LegalityCheckStrings.LTransferHTMismatchName)); + if (pkm is IHandlerLanguage h && h.HT_Language != tr.Language) + data.AddLine(GetInvalid(LegalityCheckStrings.LTransferHTMismatchLanguage)); + } + } + if ((Info.Generation != pkm.Format || neverOT) && pkm.CurrentHandler != 1) data.AddLine(GetInvalid(LegalityCheckStrings.LTransferHTFlagRequired)); } diff --git a/PKHeX.Core/Legality/Verifiers/ParseSettings.cs b/PKHeX.Core/Legality/Verifiers/ParseSettings.cs index 6bb53f323..b74cd618f 100644 --- a/PKHeX.Core/Legality/Verifiers/ParseSettings.cs +++ b/PKHeX.Core/Legality/Verifiers/ParseSettings.cs @@ -31,6 +31,8 @@ public static class ParseSettings public static Severity Gen8TransferTrackerNotPresent { get; private set; } = Severity.Fishy; public static Severity NicknamedAnotherSpecies { get; private set; } = Severity.Fishy; public static Severity ZeroHeightWeight { get; private set; } = Severity.Fishy; + public static Severity CurrentHandlerMismatch { get; private set; } = Severity.Invalid; + public static bool CheckActiveHandler { get; set; } public static IReadOnlyList MoveStrings = Util.GetMovesList(GameLanguage.DefaultLanguage); public static IReadOnlyList SpeciesStrings = Util.GetSpeciesList(GameLanguage.DefaultLanguage); @@ -97,12 +99,15 @@ public static void InitFromSettings(IParseSettings settings) Gen8MemoryMissingHT = settings.Gen8MemoryMissingHT; NicknamedAnotherSpecies = settings.NicknamedAnotherSpecies; ZeroHeightWeight = settings.ZeroHeightWeight; + CurrentHandlerMismatch = settings.CurrentHandlerMismatch; + CheckActiveHandler = settings.CheckActiveHandler; } } public interface IParseSettings { bool CheckWordFilter { get; } + bool CheckActiveHandler { get; } bool AllowGen1Tradeback { get; } Severity NicknamedTrade { get; } @@ -113,5 +118,11 @@ public interface IParseSettings Severity Gen8TransferTrackerNotPresent { get; } Severity NicknamedAnotherSpecies { get; } Severity ZeroHeightWeight { get; } + Severity CurrentHandlerMismatch { get; } + } + + public interface IBulkAnalysisSettings + { + bool CheckActiveHandler { get; } } } diff --git a/PKHeX.WinForms/Controls/SAV Editor/SAVEditor.cs b/PKHeX.WinForms/Controls/SAV Editor/SAVEditor.cs index 6c01fdefc..34042dc16 100644 --- a/PKHeX.WinForms/Controls/SAV Editor/SAVEditor.cs +++ b/PKHeX.WinForms/Controls/SAV Editor/SAVEditor.cs @@ -735,7 +735,7 @@ private void ClickVerifyCHK(object sender, EventArgs e) private void ClickVerifyStoredEntities(object sender, EventArgs e) { - var bulk = new BulkAnalysis(SAV); + var bulk = new BulkAnalysis(SAV, Main.Settings.Bulk); if (bulk.Parse.Count == 0) { WinFormsUtil.Alert("Clean!"); diff --git a/PKHeX.WinForms/Properties/PKHeXSettings.cs b/PKHeX.WinForms/Properties/PKHeXSettings.cs index 71452fced..dd265dc85 100644 --- a/PKHeX.WinForms/Properties/PKHeXSettings.cs +++ b/PKHeX.WinForms/Properties/PKHeXSettings.cs @@ -34,6 +34,7 @@ public sealed class PKHeXSettings public EntityDatabaseSettings EntityDb { get; set; } = new(); public EncounterDatabaseSettings EncounterDb { get; set; } = new(); public MysteryGiftDatabaseSettings MysteryDb { get; set; } = new(); + public BulkAnalysisSettings Bulk { get; set; } = new(); public static PKHeXSettings GetSettings(string configPath) { @@ -182,6 +183,9 @@ public sealed class LegalitySettings : IParseSettings [LocalizedDescription("Checks player given Nicknames and Trainer Names for profanity. Bad words will be flagged using the 3DS console's regex lists.")] public bool CheckWordFilter { get; set; } = true; + [LocalizedDescription("Checks the last loaded player save file data and Current Handler state to determine if the Pokémon's Current Handler does not match the expected value.")] + public bool CheckActiveHandler { get; set; } + [LocalizedDescription("GB: Allow Generation 2 tradeback learnsets for PK1 formats. Disable when checking RBY Metagame rules.")] public bool AllowGen1Tradeback { get; set; } = true; @@ -208,6 +212,9 @@ public sealed class LegalitySettings : IParseSettings [LocalizedDescription("Severity to flag a Legality Check if Pokémon has a zero value for both Height and Weight.")] public Severity ZeroHeightWeight { get; set; } = Severity.Fishy; + + [LocalizedDescription("Severity to flag a Legality Check if Pokémon's Current Handler does not match the expected value.")] + public Severity CurrentHandlerMismatch { get; set; } = Severity.Invalid; } [Serializable] @@ -388,4 +395,11 @@ public sealed class PrivacySettings [LocalizedDescription("Hide Secret Details in Editors")] public bool HideSecretDetails { get; set; } } + + [Serializable] + public sealed class BulkAnalysisSettings : IBulkAnalysisSettings + { + [LocalizedDescription("Checks the save file data and Current Handler state to determine if the Pokémon's Current Handler does not match the expected value.")] + public bool CheckActiveHandler { get; set; } = true; + } }