From 3c1e7bdc6c184aa85d0edb5ed023614a3e17c5bb Mon Sep 17 00:00:00 2001 From: Kurt Date: Wed, 18 Mar 2026 01:17:17 -0500 Subject: [PATCH] Misc tweaks Overworld8a: acknowledge Nature request 8U/8N: remove unnecessary auto-mint (not applied anywhere else) Nature: use extension properties, use the `IsFixed` check throughout codebase Wallpaper: add PLA default to pasture (not-obvious prior behavior was removed in refactor). Tests: fix ck3 file with OT trash bytes (now cleared) Tests: fix pk3 file with OT trash bytes now passes (added 1 trash pattern, future work) Trash3: initial stubs for default OT trash recognition (one included to pass above ^) --- .../BattleTemplate/Showdown/ShowdownSet.cs | 10 +-- PKHeX.Core/Editing/CommonEdits.cs | 2 +- PKHeX.Core/Game/Enums/Nature.cs | 6 +- .../Encounters/Generator/EncounterCriteria.cs | 6 +- .../Templates/Gen5/EncounterTrade5B2W2.cs | 2 +- .../Templates/Gen6/EncounterStatic6.cs | 2 +- .../Templates/Gen6/EncounterTrade6.cs | 2 +- .../Templates/Gen7/EncounterStatic7.cs | 2 +- .../Templates/Gen7/EncounterTrade7.cs | 2 +- .../Templates/Gen8/EncounterStatic8Nest.cs | 2 - .../Templates/Gen8/EncounterStatic8U.cs | 2 - .../Templates/Gen8/EncounterTrade8.cs | 2 +- .../Templates/Gen9/EncounterStatic9.cs | 4 +- .../Templates/Gen9a/EncounterGift9a.cs | 2 +- .../Templates/Gen9a/EncounterStatic9a.cs | 2 +- .../Templates/Gen9a/EncounterTrade9a.cs | 4 +- .../Encounters/Templates/Gen9a/LumioseRNG.cs | 4 +- .../Interfaces/Properties/IFixedNature.cs | 2 +- .../Legality/RNG/Methods/Gen8/RaidRNG.cs | 4 +- .../RNG/Methods/Gen8a/Overworld8aRNG.cs | 16 ++--- .../RNG/Methods/Gen9/Encounter9RNG.cs | 4 +- .../Legality/Verifiers/Misc/MiscVerifierG3.cs | 62 +++++++++++++++++- .../Verifiers/Misc/MiscVerifierHelpers.cs | 2 +- PKHeX.Core/Legality/Verifiers/PIDVerifier.cs | 2 +- PKHeX.Core/MysteryGifts/WA9.cs | 2 +- PKHeX.Core/PKM/Searching/SearchSettings.cs | 2 +- PKHeX.Core/Saves/SAV3Colosseum.cs | 10 ++- PKHeX.Core/Saves/SAV3XD.cs | 11 +++- PKHeX.Drawing.Misc/Util/WallpaperUtil.cs | 2 + .../Legal (Missing Winning Ribbon).ck3 | Bin 312 -> 312 bytes 30 files changed, 123 insertions(+), 52 deletions(-) diff --git a/PKHeX.Core/Editing/BattleTemplate/Showdown/ShowdownSet.cs b/PKHeX.Core/Editing/BattleTemplate/Showdown/ShowdownSet.cs index c4273affc..b05c2b32e 100644 --- a/PKHeX.Core/Editing/BattleTemplate/Showdown/ShowdownSet.cs +++ b/PKHeX.Core/Editing/BattleTemplate/Showdown/ShowdownSet.cs @@ -342,12 +342,12 @@ private bool ParseLineNature(ReadOnlySpan input, ReadOnlySpan natu return false; var nature = (Nature)index; - if (!nature.IsFixed()) + if (!nature.IsFixed) { LogError(NatureUnrecognized, input); return false; } - if (Nature != Nature.Random && Nature != nature) + if (Nature.IsFixed && Nature != nature) { LogError(NatureAlreadySpecified, input); return false; @@ -627,7 +627,7 @@ private void AddEVs(List result, in BattleTemplateExportSettings setting BattleTemplateToken.EVsAppendNature => GetStringStatsNatureAmp(EVs, 0, nameEVs, Nature), _ => GetStringStats(EVs, 0, nameEVs), }; - if (token is BattleTemplateToken.EVsAppendNature && Nature.IsFixed()) + if (token is BattleTemplateToken.EVsAppendNature && Nature.IsFixed) line += $" ({settings.Localization.Strings.natures[(int)Nature]})"; result.Add(cfg.Push(BattleTemplateToken.EVs, line)); } @@ -1081,7 +1081,7 @@ private bool ParseLineEVs(ReadOnlySpan line, BattleTemplateLocalization lo return false; // invalid line } - if (Nature != Nature.Random) // specified in a separate Nature line + if (Nature.IsFixed) // specified in a separate Nature line LogError(NatureEffortAmpAlreadySpecified, natureName); else Nature = (Nature)natureIndex; @@ -1100,7 +1100,7 @@ private bool ParseLineEVs(ReadOnlySpan line, BattleTemplateLocalization lo result.TreatAmpsAsSpeedNotLast(); var ampNature = AdjustNature(result.Plus, result.Minus); success &= ampNature; - if (ampNature && currentNature != Nature.Random && currentNature != Nature) + if (ampNature && currentNature.IsFixed && currentNature != Nature) { LogError(NatureEffortAmpConflictNature); Nature = currentNature; // revert to original diff --git a/PKHeX.Core/Editing/CommonEdits.cs b/PKHeX.Core/Editing/CommonEdits.cs index 0e7e5035d..a7a12539c 100644 --- a/PKHeX.Core/Editing/CommonEdits.cs +++ b/PKHeX.Core/Editing/CommonEdits.cs @@ -137,7 +137,7 @@ public bool SetUnshiny() /// Desired value to set. public void SetNature(Nature nature) { - if (!nature.IsFixed()) + if (!nature.IsFixed) nature = 0; // default valid var format = pk.Format; diff --git a/PKHeX.Core/Game/Enums/Nature.cs b/PKHeX.Core/Game/Enums/Nature.cs index c0df7d4ce..17833ddb9 100644 --- a/PKHeX.Core/Game/Enums/Nature.cs +++ b/PKHeX.Core/Game/Enums/Nature.cs @@ -55,7 +55,7 @@ public static class NatureUtil /// Checks if the provided is a valid stored value. /// /// True if value is an actual nature. - public bool IsFixed() => value < Nature.Random; + public bool IsFixed => value != Nature.Random; /// /// Checks if the provided is a possible mint nature. @@ -63,12 +63,12 @@ public static class NatureUtil /// /// The only valid mint natures are those which have a stat amp applied, or neutral nature being Serious. /// - public bool IsMint() => (value.IsFixed() && (byte)value % 6 != 0) || value == Nature.Serious; + public bool IsMint => (value.IsFixed && (byte)value % 6 != 0) || value == Nature.Serious; /// /// Checks if the provided is a neutral nature which has no stat amps applied. /// - public bool IsNeutral() => value.IsFixed() && (byte)value % 6 == 0; + public bool IsNeutral => value.IsFixed && (byte)value % 6 == 0; /// /// Converts the provided to a neutral nature. diff --git a/PKHeX.Core/Legality/Encounters/Generator/EncounterCriteria.cs b/PKHeX.Core/Legality/Encounters/Generator/EncounterCriteria.cs index da20cf957..57387f800 100644 --- a/PKHeX.Core/Legality/Encounters/Generator/EncounterCriteria.cs +++ b/PKHeX.Core/Legality/Encounters/Generator/EncounterCriteria.cs @@ -112,7 +112,7 @@ public EncounterCriteria() /// Determines whether a specific Nature is specified in the criteria or if complex nature mutations are allowed. /// /// > if a Nature is specified or complex nature mutations are allowed; otherwise, . - public bool IsSpecifiedNature() => Nature != Nature.Random || Mutations.IsComplexNature(); + public bool IsSpecifiedNature() => Nature.IsFixed || Mutations.IsComplexNature(); /// /// Determines whether a level range is specified in the criteria. @@ -191,7 +191,7 @@ public int GetCountSpecifiedIVs() => Convert.ToInt32(IV_HP != RandomIV) public bool IsSatisfiedNature(Nature nature) { if (Mutations.HasFlag(AllowOnlyNeutralNature)) - return nature.IsNeutral(); + return nature.IsNeutral; if (Nature == Nature.Random) return true; return nature == Nature || Mutations.HasFlag(CanMintNature); @@ -300,7 +300,7 @@ public Nature GetNature(Nature encValue) /// public Nature GetNature() { - if (Nature != Nature.Random) + if (Nature.IsFixed) return Nature; var result = (Nature)Util.Rand.Next(25); if (Mutations.HasFlag(AllowOnlyNeutralNature)) diff --git a/PKHeX.Core/Legality/Encounters/Templates/Gen5/EncounterTrade5B2W2.cs b/PKHeX.Core/Legality/Encounters/Templates/Gen5/EncounterTrade5B2W2.cs index 9eafd4f62..d99581746 100644 --- a/PKHeX.Core/Legality/Encounters/Templates/Gen5/EncounterTrade5B2W2.cs +++ b/PKHeX.Core/Legality/Encounters/Templates/Gen5/EncounterTrade5B2W2.cs @@ -155,7 +155,7 @@ private bool IsMatchNatureGenderShiny(PKM pk) return false; if (Gender != FixedGenderUtil.GenderRandom && Gender != pk.Gender) return false; - if (Nature != Nature.Random && pk.Nature != Nature) + if (Nature.IsFixed && pk.Nature != Nature) return false; return true; } diff --git a/PKHeX.Core/Legality/Encounters/Templates/Gen6/EncounterStatic6.cs b/PKHeX.Core/Legality/Encounters/Templates/Gen6/EncounterStatic6.cs index 5068a0862..c468a27b2 100644 --- a/PKHeX.Core/Legality/Encounters/Templates/Gen6/EncounterStatic6.cs +++ b/PKHeX.Core/Legality/Encounters/Templates/Gen6/EncounterStatic6.cs @@ -153,7 +153,7 @@ public bool IsMatchExact(PKM pk, EvoCriteria evo) return false; if (IVs.IsSpecified && !Legal.GetIsFixedIVSequenceValidSkipRand(IVs, pk)) return false; - if (Nature != Nature.Random && pk.Nature != Nature) + if (Nature.IsFixed && pk.Nature != Nature) return false; if (FlawlessIVCount != 0 && pk.FlawlessIVCount < FlawlessIVCount) return false; diff --git a/PKHeX.Core/Legality/Encounters/Templates/Gen6/EncounterTrade6.cs b/PKHeX.Core/Legality/Encounters/Templates/Gen6/EncounterTrade6.cs index f27420c64..40b728e03 100644 --- a/PKHeX.Core/Legality/Encounters/Templates/Gen6/EncounterTrade6.cs +++ b/PKHeX.Core/Legality/Encounters/Templates/Gen6/EncounterTrade6.cs @@ -167,7 +167,7 @@ private bool IsMatchNatureGenderShiny(PKM pk) return false; if (Gender != pk.Gender) return false; - if (Nature != Nature.Random && pk.Nature != Nature) + if (Nature.IsFixed && pk.Nature != Nature) return false; return true; } diff --git a/PKHeX.Core/Legality/Encounters/Templates/Gen7/EncounterStatic7.cs b/PKHeX.Core/Legality/Encounters/Templates/Gen7/EncounterStatic7.cs index f4a60cf8b..f2a75dc85 100644 --- a/PKHeX.Core/Legality/Encounters/Templates/Gen7/EncounterStatic7.cs +++ b/PKHeX.Core/Legality/Encounters/Templates/Gen7/EncounterStatic7.cs @@ -145,7 +145,7 @@ public bool IsMatchExact(PKM pk, EvoCriteria evo) return false; if (IVs.IsSpecified && !Legal.GetIsFixedIVSequenceValidSkipRand(IVs, pk)) return false; - if (Nature != Nature.Random && pk.Nature != Nature) + if (Nature.IsFixed && pk.Nature != Nature) return false; if (FlawlessIVCount != 0 && pk.FlawlessIVCount < FlawlessIVCount) return false; diff --git a/PKHeX.Core/Legality/Encounters/Templates/Gen7/EncounterTrade7.cs b/PKHeX.Core/Legality/Encounters/Templates/Gen7/EncounterTrade7.cs index f40f83a01..12a12385f 100644 --- a/PKHeX.Core/Legality/Encounters/Templates/Gen7/EncounterTrade7.cs +++ b/PKHeX.Core/Legality/Encounters/Templates/Gen7/EncounterTrade7.cs @@ -166,7 +166,7 @@ private bool IsMatchNatureGenderShiny(PKM pk) return false; if (Gender != pk.Gender) return false; - if (Nature != Nature.Random && pk.Nature != Nature) + if (Nature.IsFixed && pk.Nature != Nature) return false; return true; } diff --git a/PKHeX.Core/Legality/Encounters/Templates/Gen8/EncounterStatic8Nest.cs b/PKHeX.Core/Legality/Encounters/Templates/Gen8/EncounterStatic8Nest.cs index ffb27c72b..9ae754f4c 100644 --- a/PKHeX.Core/Legality/Encounters/Templates/Gen8/EncounterStatic8Nest.cs +++ b/PKHeX.Core/Legality/Encounters/Templates/Gen8/EncounterStatic8Nest.cs @@ -122,8 +122,6 @@ protected virtual void SetPINGA(PK8 pk, in EncounterCriteria criteria, PersonalI } FinishCorrelation(pk, seed); - if (criteria.IsSpecifiedNature() && criteria.Nature != pk.Nature && criteria.Nature.IsMint()) - pk.StatNature = criteria.Nature; } protected GenerateParam8 GetParam() => GetParam(Info); diff --git a/PKHeX.Core/Legality/Encounters/Templates/Gen8/EncounterStatic8U.cs b/PKHeX.Core/Legality/Encounters/Templates/Gen8/EncounterStatic8U.cs index 9bec76922..753546d8b 100644 --- a/PKHeX.Core/Legality/Encounters/Templates/Gen8/EncounterStatic8U.cs +++ b/PKHeX.Core/Legality/Encounters/Templates/Gen8/EncounterStatic8U.cs @@ -78,8 +78,6 @@ protected override void SetPINGA(PK8 pk, in EncounterCriteria criteria, Personal } FinishCorrelation(pk, seed); - if (criteria.IsSpecifiedNature() && criteria.Nature != pk.Nature && criteria.Nature.IsMint()) - pk.StatNature = criteria.Nature; if (criteria.Shiny.IsShiny()) pk.PID = ShinyUtil.GetShinyPID(pk.TID16, pk.SID16, pk.PID, ShinyXor); } diff --git a/PKHeX.Core/Legality/Encounters/Templates/Gen8/EncounterTrade8.cs b/PKHeX.Core/Legality/Encounters/Templates/Gen8/EncounterTrade8.cs index 98f83c806..a936f7197 100644 --- a/PKHeX.Core/Legality/Encounters/Templates/Gen8/EncounterTrade8.cs +++ b/PKHeX.Core/Legality/Encounters/Templates/Gen8/EncounterTrade8.cs @@ -209,7 +209,7 @@ private bool IsMatchNatureGenderShiny(PKM pk) { if (!Shiny.IsValid(pk)) return false; - if (Nature != Nature.Random && pk.Nature != Nature) + if (Nature.IsFixed && pk.Nature != Nature) return false; if (Gender != FixedGenderUtil.GenderRandom && pk.Gender != Gender) return false; diff --git a/PKHeX.Core/Legality/Encounters/Templates/Gen9/EncounterStatic9.cs b/PKHeX.Core/Legality/Encounters/Templates/Gen9/EncounterStatic9.cs index 0646b8e76..6b83a47d2 100644 --- a/PKHeX.Core/Legality/Encounters/Templates/Gen9/EncounterStatic9.cs +++ b/PKHeX.Core/Legality/Encounters/Templates/Gen9/EncounterStatic9.cs @@ -154,7 +154,7 @@ private void SetPINGA(PK9 pk, in EncounterCriteria criteria, PersonalInfo9SV pi) if (Gender != FixedGenderUtil.GenderRandom) pk.Gender = Gender; - if (Nature != Nature.Random) + if (Nature.IsFixed) pk.Nature = pk.StatNature = Nature; } #endregion @@ -178,7 +178,7 @@ public bool IsMatchExact(PKM pk, EvoCriteria evo) return false; if (TeraType != GemType.Random && pk is ITeraType t && !Tera9RNG.IsMatchTeraType(TeraType, Species, Form, (byte)t.TeraTypeOriginal)) return false; - if (Nature != Nature.Random && pk.Nature != Nature) + if (Nature.IsFixed && pk.Nature != Nature) return false; return true; diff --git a/PKHeX.Core/Legality/Encounters/Templates/Gen9a/EncounterGift9a.cs b/PKHeX.Core/Legality/Encounters/Templates/Gen9a/EncounterGift9a.cs index c9fcfa7b4..c0b195ee8 100644 --- a/PKHeX.Core/Legality/Encounters/Templates/Gen9a/EncounterGift9a.cs +++ b/PKHeX.Core/Legality/Encounters/Templates/Gen9a/EncounterGift9a.cs @@ -158,7 +158,7 @@ public bool IsMatchExact(PKM pk, EvoCriteria evo) return false; if (FlawlessIVCount != 0 && pk.FlawlessIVCount < FlawlessIVCount) return false; - if (Nature != Nature.Random && pk.Nature != Nature) + if (Nature.IsFixed && pk.Nature != Nature) return false; if (pk is IAlphaReadOnly a && a.IsAlpha != IsAlpha) return false; diff --git a/PKHeX.Core/Legality/Encounters/Templates/Gen9a/EncounterStatic9a.cs b/PKHeX.Core/Legality/Encounters/Templates/Gen9a/EncounterStatic9a.cs index a56ca36c8..d1d14a04d 100644 --- a/PKHeX.Core/Legality/Encounters/Templates/Gen9a/EncounterStatic9a.cs +++ b/PKHeX.Core/Legality/Encounters/Templates/Gen9a/EncounterStatic9a.cs @@ -135,7 +135,7 @@ public bool IsMatchExact(PKM pk, EvoCriteria evo) return false; if (FlawlessIVCount != 0 && pk.FlawlessIVCount < FlawlessIVCount) return false; - if (Nature != Nature.Random && pk.Nature != Nature) + if (Nature.IsFixed && pk.Nature != Nature) return false; if (pk is IAlphaReadOnly a && a.IsAlpha != IsAlpha) return false; diff --git a/PKHeX.Core/Legality/Encounters/Templates/Gen9a/EncounterTrade9a.cs b/PKHeX.Core/Legality/Encounters/Templates/Gen9a/EncounterTrade9a.cs index 4f8915669..e12339b71 100644 --- a/PKHeX.Core/Legality/Encounters/Templates/Gen9a/EncounterTrade9a.cs +++ b/PKHeX.Core/Legality/Encounters/Templates/Gen9a/EncounterTrade9a.cs @@ -155,7 +155,7 @@ private bool IsMatchNatureGenderShiny(PKM pk) return false; if (pk.Gender != Gender) return false; - if (Nature != Nature.Random && pk.Nature != Nature) + if (Nature.IsFixed && pk.Nature != Nature) return false; return true; } @@ -192,7 +192,7 @@ public bool IsMatchExact(PKM pk, EvoCriteria evo) return false; if (FlawlessIVCount != 0 && pk.FlawlessIVCount < FlawlessIVCount) return false; - if (Nature != Nature.Random && pk.Nature != Nature) + if (Nature.IsFixed && pk.Nature != Nature) return false; if (pk is IAlphaReadOnly a && a.IsAlpha != IsAlpha) return false; diff --git a/PKHeX.Core/Legality/Encounters/Templates/Gen9a/LumioseRNG.cs b/PKHeX.Core/Legality/Encounters/Templates/Gen9a/LumioseRNG.cs index ad21ed595..5a5055930 100644 --- a/PKHeX.Core/Legality/Encounters/Templates/Gen9a/LumioseRNG.cs +++ b/PKHeX.Core/Legality/Encounters/Templates/Gen9a/LumioseRNG.cs @@ -104,7 +104,7 @@ public static bool GenerateData(PA9 pk, in GenerateParam9a enc, in EncounterCrit return false; pk.Gender = gender; - var nature = enc.Nature != Nature.Random ? enc.Nature + var nature = enc.Nature.IsFixed ? enc.Nature : (Nature)rand.NextInt(25); // Compromise on Nature -- some are fixed, some are random. If the request wants a specific nature, just mint it. @@ -264,7 +264,7 @@ private static bool IsMatchIVsAndFollowing(PKM pk, in GenerateParam9a enc, Xoros if (pk.Gender != gender) return false; - var nature = enc.Nature != Nature.Random ? enc.Nature + var nature = enc.Nature.IsFixed ? enc.Nature : (Nature)rand.NextInt(25); if (pk.Nature != nature) return false; diff --git a/PKHeX.Core/Legality/Encounters/Templates/Interfaces/Properties/IFixedNature.cs b/PKHeX.Core/Legality/Encounters/Templates/Interfaces/Properties/IFixedNature.cs index d25cb229c..1ddbc759f 100644 --- a/PKHeX.Core/Legality/Encounters/Templates/Interfaces/Properties/IFixedNature.cs +++ b/PKHeX.Core/Legality/Encounters/Templates/Interfaces/Properties/IFixedNature.cs @@ -13,5 +13,5 @@ public interface IFixedNature /// /// Indicates if the nature is a single value (not random). /// - bool IsFixedNature => Nature != Nature.Random; + bool IsFixedNature => Nature.IsFixed; } diff --git a/PKHeX.Core/Legality/RNG/Methods/Gen8/RaidRNG.cs b/PKHeX.Core/Legality/RNG/Methods/Gen8/RaidRNG.cs index 7317c04d5..083f72ee0 100644 --- a/PKHeX.Core/Legality/RNG/Methods/Gen8/RaidRNG.cs +++ b/PKHeX.Core/Legality/RNG/Methods/Gen8/RaidRNG.cs @@ -114,7 +114,7 @@ public static bool Verify(PKM pk, ulong seed, Span ivs, in GenerateParam8 p break; } - var nature = param.Nature != Nature.Random ? param.Nature + var nature = param.Nature.IsFixed ? param.Nature : param.Species == (int)Species.Toxtricity ? ToxtricityUtil.GetRandomNature(ref rng, pk.Form) : (Nature)rng.NextInt(25); @@ -236,7 +236,7 @@ public static bool TryApply(PK8 pk, ulong seed, Span ivs, in GenerateParam8 return false; pk.Gender = gender; - var nature = param.Nature != Nature.Random ? param.Nature + var nature = param.Nature.IsFixed ? param.Nature : param.Species == (int)Species.Toxtricity ? ToxtricityUtil.GetRandomNature(ref rng, pk.Form) : (Nature)rng.NextInt(25); diff --git a/PKHeX.Core/Legality/RNG/Methods/Gen8a/Overworld8aRNG.cs b/PKHeX.Core/Legality/RNG/Methods/Gen8a/Overworld8aRNG.cs index 978be1bc5..25451a2e4 100644 --- a/PKHeX.Core/Legality/RNG/Methods/Gen8a/Overworld8aRNG.cs +++ b/PKHeX.Core/Legality/RNG/Methods/Gen8a/Overworld8aRNG.cs @@ -172,6 +172,8 @@ public static bool TryApplyFromSeed(PA8 pk, in EncounterCriteria criteria, in Ov pk.Gender = gender; var nature = (Nature)rand.NextInt(25); + if (criteria.IsSpecifiedNature() && !criteria.IsSatisfiedNature(nature)) + return false; pk.Nature = pk.StatNature = nature; var (height, weight) = para.IsAlpha @@ -179,16 +181,10 @@ public static bool TryApplyFromSeed(PA8 pk, in EncounterCriteria criteria, in Ov : ((byte)(rand.NextInt(0x81) + rand.NextInt(0x80)), (byte)(rand.NextInt(0x81) + rand.NextInt(0x80))); - if (pk is IScaledSize s) - { - s.HeightScalar = height; - s.WeightScalar = weight; - if (pk is IScaledSizeValue a) - { - a.ResetHeight(); - a.ResetWeight(); - } - } + pk.HeightScalar = height; + pk.WeightScalar = weight; + pk.ResetHeight(); + pk.ResetWeight(); return true; } diff --git a/PKHeX.Core/Legality/RNG/Methods/Gen9/Encounter9RNG.cs b/PKHeX.Core/Legality/RNG/Methods/Gen9/Encounter9RNG.cs index 876bbce9f..4bf85080a 100644 --- a/PKHeX.Core/Legality/RNG/Methods/Gen9/Encounter9RNG.cs +++ b/PKHeX.Core/Legality/RNG/Methods/Gen9/Encounter9RNG.cs @@ -121,7 +121,7 @@ public static bool GenerateData(PK9 pk, in GenerateParam9 enc, in EncounterCrite return false; pk.Gender = gender; - var nature = enc.Nature != Nature.Random ? enc.Nature : enc.Species == (int)Species.Toxtricity + var nature = enc.Nature.IsFixed ? enc.Nature : enc.Species == (int)Species.Toxtricity ? ToxtricityUtil.GetRandomNature(ref rand, pk.Form) : (Nature)rand.NextInt(25); @@ -205,7 +205,7 @@ public static bool IsMatch(PKM pk, in GenerateParam9 enc, in ulong seed) if (pk.Gender != gender) return false; - var nature = enc.Nature != Nature.Random ? enc.Nature : enc.Species == (int)Species.Toxtricity + var nature = enc.Nature.IsFixed ? enc.Nature : enc.Species == (int)Species.Toxtricity ? ToxtricityUtil.GetRandomNature(ref rand, pk.Form) : (Nature)rand.NextInt(25); if (pk.Nature != nature) diff --git a/PKHeX.Core/Legality/Verifiers/Misc/MiscVerifierG3.cs b/PKHeX.Core/Legality/Verifiers/Misc/MiscVerifierG3.cs index b22e69cfe..0edae4e67 100644 --- a/PKHeX.Core/Legality/Verifiers/Misc/MiscVerifierG3.cs +++ b/PKHeX.Core/Legality/Verifiers/Misc/MiscVerifierG3.cs @@ -122,7 +122,10 @@ private static void VerifyTrashINT(LegalityAnalysis data, PK3 pk) var trash = pk.OriginalTrainerTrash; // OT name from save file is copied byte-for-byte. All 8 bytes are initialized to FF on new game. if (!TrashByteRules3.IsTerminatedFFZero(trash, 7)) - data.AddLine(GetInvalid(Trainer, TrashBytesMissingTerminatorFinal)); + { + if (!TrashByteRules3.IsTrashPatternDefaultTrainer(trash, pk.Version, (LanguageID)pk.Language)) + data.AddLine(GetInvalid(Trainer, TrashBytesMissingTerminatorFinal)); + } // Nickname can be all FF's (nicknamed) or whatever random garbage is in the buffer before filling. Unsure if we can reliably check this, but it should be "dirty" usually. // If it is clean, flag as fishy. FlagIsNicknameClean(data, pk); @@ -214,4 +217,61 @@ public static bool IsTerminatedFFZero(ReadOnlySpan data, int preFill = 0) } return !data[first..].ContainsAnyExcept(0); } + + // TRASH BYTES: New Game Default OTs + // Default OT names in International (not JPN) Gen3 mainline games memcpy 7 chars and FF from the "default OT name" table, regardless of strlen. + // Copied strings therefore contain trash from the next string entry that is encoded into the rom's string table. + // Below is a list of possible (version, language, trash) default OTs, as initialized by the game. An `*` is used to denote the terminator. + + /// + /// Checks if the specified trash byte pattern matches a default trainer name pattern for the given game and . + /// + /// Default trainer names in certain Generation 3 Pokémon games may include trailing bytes ("trash") due to how names are stored in the game's ROM. + /// This method checks if the provided pattern matches any of these known default patterns for the specified version and language. + /// + public static bool IsTrashPatternDefaultTrainer(ReadOnlySpan trash, GameVersion version, LanguageID language) => version switch + { + GameVersion.R or GameVersion.S => IsTrashPatternDefaultTrainerRS(trash, language), + GameVersion.E => IsTrashPatternDefaultTrainerE(trash, language), + GameVersion.FR => IsTrashPatternDefaultTrainerFR(trash, language), + GameVersion.LG => IsTrashPatternDefaultTrainerLG(trash, language), + _ => false, + }; + + /// + /// Default OT names present in and based on the language of the game. + public static bool IsTrashPatternDefaultTrainerRS(ReadOnlySpan trash, LanguageID language) => language switch + { + // TODO + LanguageID.English => trash switch + { + [0xCD, 0xBB, 0xCC, 0xBB, 0xFF, 0xCE, 0xDC] => true, // SARA*Th + _ => false, + }, + _ => false, + }; + + /// + /// Default OT names present in based on the language of the game. + public static bool IsTrashPatternDefaultTrainerE(ReadOnlySpan trash, LanguageID language) => language switch + { + // TODO + _ => false, + }; + + /// + /// Default OT names present in based on the language of the game. + public static bool IsTrashPatternDefaultTrainerFR(ReadOnlySpan trash, LanguageID language) => language switch + { + // TODO + _ => false, + }; + + /// + /// Default OT names present in based on the language of the game. + public static bool IsTrashPatternDefaultTrainerLG(ReadOnlySpan trash, LanguageID language) => language switch + { + // TODO + _ => false, + }; } diff --git a/PKHeX.Core/Legality/Verifiers/Misc/MiscVerifierHelpers.cs b/PKHeX.Core/Legality/Verifiers/Misc/MiscVerifierHelpers.cs index ae942ae25..671c96996 100644 --- a/PKHeX.Core/Legality/Verifiers/Misc/MiscVerifierHelpers.cs +++ b/PKHeX.Core/Legality/Verifiers/Misc/MiscVerifierHelpers.cs @@ -17,7 +17,7 @@ internal static void VerifyStatNature(LegalityAnalysis data, PKM pk) return; // Must be a valid mint nature. - if (!statNature.IsMint()) + if (!statNature.IsMint) data.AddLine(Get(Invalid, Misc, StatNatureInvalid)); } diff --git a/PKHeX.Core/Legality/Verifiers/PIDVerifier.cs b/PKHeX.Core/Legality/Verifiers/PIDVerifier.cs index 0a8db12f9..6567169f2 100644 --- a/PKHeX.Core/Legality/Verifiers/PIDVerifier.cs +++ b/PKHeX.Core/Legality/Verifiers/PIDVerifier.cs @@ -24,7 +24,7 @@ public override void Verify(LegalityAnalysis data) if (pk.PID == 0) data.AddLine(Get(Severity.Fishy, PIDZero)); - if (!pk.Nature.IsFixed()) // out of range + if (!pk.Nature.IsFixed) // out of range data.AddLine(GetInvalid(PIDNatureMismatch)); if (data.Info.EncounterMatch is IEncounterEgg egg) VerifyEggPID(data, pk, egg); diff --git a/PKHeX.Core/MysteryGifts/WA9.cs b/PKHeX.Core/MysteryGifts/WA9.cs index 0c5168df0..8e135f985 100644 --- a/PKHeX.Core/MysteryGifts/WA9.cs +++ b/PKHeX.Core/MysteryGifts/WA9.cs @@ -626,7 +626,7 @@ public override bool IsMatchExact(PKM pk, EvoCriteria evo) if (MetLevel != 0 && MetLevel != pk.MetLevel) return false; if ((Ball == 0 ? 4 : Ball) != pk.Ball) return false; if (OTGender < 2 && OTGender != pk.OriginalTrainerGender) return false; - if (Nature != Nature.Random && pk.Nature != Nature) return false; + if (Nature.IsFixed && pk.Nature != Nature) return false; if (Gender != 3 && Gender != pk.Gender) return false; if (pk is IScaledSize s) diff --git a/PKHeX.Core/PKM/Searching/SearchSettings.cs b/PKHeX.Core/PKM/Searching/SearchSettings.cs index 32a695490..227a912d9 100644 --- a/PKHeX.Core/PKM/Searching/SearchSettings.cs +++ b/PKHeX.Core/PKM/Searching/SearchSettings.cs @@ -168,7 +168,7 @@ private bool SearchSimple(PKM pk) return false; if (Ability > -1 && pk.Ability != Ability) return false; - if (Nature.IsFixed() && pk.StatNature != Nature) + if (Nature.IsFixed && pk.StatNature != Nature) return false; if (Item > -1 && pk.HeldItem != Item) return false; diff --git a/PKHeX.Core/Saves/SAV3Colosseum.cs b/PKHeX.Core/Saves/SAV3Colosseum.cs index d03937a34..310b83bbb 100644 --- a/PKHeX.Core/Saves/SAV3Colosseum.cs +++ b/PKHeX.Core/Saves/SAV3Colosseum.cs @@ -6,13 +6,21 @@ namespace PKHeX.Core; /// /// Generation 3 object for Pokémon Colosseum saves. /// -public sealed class SAV3Colosseum : SaveFile, IGCSaveFile, IBoxDetailName, IDaycareStorage, IDaycareExperience, IGCRegion +public sealed class SAV3Colosseum : SaveFile, IGCSaveFile, IBoxDetailName, IDaycareStorage, IDaycareExperience, IGCRegion, ISaveFileRevision { protected internal override string ShortSummary => $"{OT} ({Version}) - {PlayTimeString}"; public override string Extension => this.GCExtension(); public override PersonalTable3 Personal => PersonalTable.RS; public override ReadOnlySpan HeldItems => Legal.HeldItems_RS; public SAV3GCMemoryCard? MemoryCard { get; init; } + public int SaveRevision => 0; + public string SaveRevisionString => OriginalRegion switch + { + GCRegion.NTSC_J => "-J", + GCRegion.NTSC_U => "-U", + GCRegion.PAL => "-PAL", + _ => "-?", + }; private readonly Memory Container; protected override Span BoxBuffer => Data; diff --git a/PKHeX.Core/Saves/SAV3XD.cs b/PKHeX.Core/Saves/SAV3XD.cs index f6c9bf2f5..fecc4f922 100644 --- a/PKHeX.Core/Saves/SAV3XD.cs +++ b/PKHeX.Core/Saves/SAV3XD.cs @@ -7,9 +7,18 @@ namespace PKHeX.Core; /// /// Generation 3 object for Pokémon XD saves. /// -public sealed class SAV3XD : SaveFile, IGCSaveFile, IBoxDetailName, IDaycareStorage, IDaycareExperience, IGCRegion +public sealed class SAV3XD : SaveFile, IGCSaveFile, IBoxDetailName, IDaycareStorage, IDaycareExperience, IGCRegion, ISaveFileRevision { protected internal override string ShortSummary => $"{OT} ({Version}) {PlayTimeString}"; + public int SaveRevision => 0; + public string SaveRevisionString => OriginalRegion switch + { + GCRegion.NTSC_J => "-J", + GCRegion.NTSC_U => "-U", + GCRegion.PAL => "-PAL", + _ => "-?", + }; + public override string Extension => this.GCExtension(); public SAV3GCMemoryCard? MemoryCard { get; init; } diff --git a/PKHeX.Drawing.Misc/Util/WallpaperUtil.cs b/PKHeX.Drawing.Misc/Util/WallpaperUtil.cs index c2e05cd92..5c69f38fa 100644 --- a/PKHeX.Drawing.Misc/Util/WallpaperUtil.cs +++ b/PKHeX.Drawing.Misc/Util/WallpaperUtil.cs @@ -28,6 +28,8 @@ private static Bitmap GetWallpaper(SaveFile sav, int box) // City box wallpaper for Lumiose City if (sav is SAV9ZA) return Resources.box_wp02bdsp; + if (sav is SAV8LA) // pasture for PLA + return Resources.box_wp01bdsp; int wallpaper = wp.GetBoxWallpaper(box); string s = GetWallpaperResourceName(sav.Version, wallpaper); diff --git a/Tests/PKHeX.Core.Tests/Legality/Legal/General/Ribbons/Legal (Missing Winning Ribbon).ck3 b/Tests/PKHeX.Core.Tests/Legality/Legal/General/Ribbons/Legal (Missing Winning Ribbon).ck3 index 4d8ce82ade7d1a26c1253a8f2ec8e19172604370..be2c241940ddbe84b1b11394568bb68119860027 100644 GIT binary patch delta 22 XcmdnNw1a7aA}0e3OmvW*==vD|Gr0uh delta 22 acmdnNw1a7aB4;T>F#{M(bda9t`WXN~YX!^z