From 95fbf66a6ec07c0e68f94607e3425db096f43d39 Mon Sep 17 00:00:00 2001 From: Kurt Date: Thu, 22 Feb 2024 21:20:54 -0600 Subject: [PATCH] Refactor: Gen3/4 Lead Encounters, property fixing (#4193) In addition to the Method 1 (and other sibling PIDIV types) correlation, an encounter can only be triggered if the calls prior land on the Method {1} seed. The RNG community has dubbed these patterns as "Method J" (D/P/Pt), "Method K" (HG/SS), and "Method H" (Gen3, coined by yours truly). The basic gist of these is that they are pre-requisites, like the Shadow locks of Colosseum/XD. Rename/re-type a bunch of properties to get the codebase more in line with correct property names & more obvious underlying types. --- .../Editing/Applicators/BallApplicator.cs | 16 +- .../Applicators/CatchRateApplicator.cs | 6 +- .../Editing/Applicators/GenderApplicator.cs | 19 +- .../Editing/Applicators/MemoryApplicator.cs | 18 +- PKHeX.Core/Editing/Bulk/BatchEditing.cs | 6 +- PKHeX.Core/Editing/Bulk/BatchMods.cs | 2 +- .../Bulk/Suggestion/BatchModifications.cs | 10 +- PKHeX.Core/Editing/CommonEdits.cs | 42 +- .../Editing/Database/TrainerDatabase.cs | 40 +- PKHeX.Core/Editing/HiddenPower.cs | 9 + PKHeX.Core/Editing/IBattleTemplate.cs | 6 +- PKHeX.Core/Editing/ISpriteBuilder.cs | 2 +- PKHeX.Core/Editing/LocationEdits.cs | 4 +- PKHeX.Core/Editing/NatureAmp.cs | 44 +- .../Editing/PKM/EntitySuggestionUtil.cs | 4 +- PKHeX.Core/Editing/PKM/EntitySummary.cs | 68 +- PKHeX.Core/Editing/PKM/EntityTemplates.cs | 30 +- PKHeX.Core/Editing/PKM/QR/QRMessageUtil.cs | 4 +- PKHeX.Core/Editing/PKM/QR/QRPK7.cs | 51 +- PKHeX.Core/Editing/PKM/QR/QRPKM.cs | 2 +- PKHeX.Core/Editing/Pokerus.cs | 4 +- .../Editing/Program/StartupArguments.cs | 10 +- .../Saves/BoxManip/BoxManipDefaults.cs | 2 +- .../Saves/Editors/EventOld/EventWorkspace.cs | 8 +- .../Editing/Saves/Editors/FakeSaveFile.cs | 4 +- PKHeX.Core/Editing/Showdown/ShowdownSet.cs | 24 +- PKHeX.Core/Game/Enums/GameVersion.cs | 10 +- PKHeX.Core/Game/Enums/MoveType.cs | 2 +- PKHeX.Core/Game/Enums/Nature.cs | 6 +- PKHeX.Core/Game/GameStrings/GameDataSource.cs | 6 +- PKHeX.Core/Game/GameStrings/GameInfo.cs | 7 +- PKHeX.Core/Game/GameStrings/GameStrings.cs | 18 +- .../GameStrings/LocationSet/LocationSet0.cs | 4 + .../GameStrings/LocationSet/LocationSet4.cs | 6 +- .../GameStrings/LocationSet/LocationSet6.cs | 6 +- PKHeX.Core/Game/GameUtil.cs | 123 ++-- PKHeX.Core/Game/Locations/Locations.cs | 31 +- PKHeX.Core/Game/Locations/Locations4.cs | 4 +- PKHeX.Core/Game/Locations/LocationsHOME.cs | 69 +- PKHeX.Core/Legality/Breeding.cs | 2 +- .../Bulk/DuplicateEncryptionChecker.cs | 2 +- .../Legality/Bulk/DuplicatePIDChecker.cs | 2 +- .../Legality/Bulk/DuplicateTrainerChecker.cs | 2 +- PKHeX.Core/Legality/Bulk/HandlerChecker.cs | 4 +- .../Legality/Bulk/StandardCloneChecker.cs | 2 +- PKHeX.Core/Legality/Core.cs | 28 +- .../Encounters/Data/Gen1/Encounters1GBEra.cs | 40 +- .../Encounters/Data/Gen1/Encounters1VC.cs | 4 +- .../Encounters/Data/Gen2/Encounters2GBEra.cs | 282 ++++---- .../Encounters/Data/Gen3/Encounters3Colo.cs | 2 +- .../Encounters/Data/Gen3/Encounters3FRLG.cs | 2 +- .../Encounters/Data/Gen3/Encounters3RSE.cs | 10 +- .../Encounters/Data/Gen3/EncountersWC3.cs | 339 +++++----- .../Encounters/Data/Gen4/Encounters4DPPt.cs | 40 +- .../Encounters/Data/Gen6/Encounters6AO.cs | 12 +- .../ByGeneration/EncounterGenerator2.cs | 2 +- .../ByGeneration/EncounterGenerator3.cs | 84 +-- .../ByGeneration/EncounterGenerator3GC.cs | 10 +- .../ByGeneration/EncounterGenerator4.cs | 117 ++-- .../ByGeneration/EncounterGenerator5.cs | 4 +- .../ByGeneration/EncounterGenerator6.cs | 4 +- .../ByGeneration/EncounterGenerator7.cs | 10 +- .../ByGeneration/EncounterGenerator7GG.cs | 2 +- .../ByGeneration/EncounterGenerator8.cs | 4 +- .../ByGeneration/EncounterGenerator8b.cs | 4 +- .../ByGeneration/EncounterGenerator9.cs | 10 +- .../ByGeneration/EncounterStateUtil.cs | 10 +- .../ByGeneration/Lump/EncounterGenerator12.cs | 2 +- .../ByGeneration/Lump/EncounterGenerator7X.cs | 8 +- .../ByGeneration/Lump/EncounterGenerator8X.cs | 12 +- .../ByGeneration/Lump/EncounterGeneratorGO.cs | 2 +- .../Encounters/Generator/EncounterCriteria.cs | 46 +- .../Encounters/Generator/EncounterFinder.cs | 38 +- .../Generator/EncounterGenerator.cs | 4 +- .../Moveset/EncounterMovesetGenerator.cs | 30 +- .../Generator/Possible/EncounterPossible2.cs | 4 +- .../Generator/Possible/EncounterPossible4.cs | 2 +- .../Generator/Possible/EncounterPossible5.cs | 2 +- .../Generator/Possible/EncounterPossible6.cs | 2 +- .../Generator/Possible/EncounterPossible7.cs | 2 +- .../Possible/EncounterPossible7GG.cs | 2 +- .../Dirtied/EncounterEnumerator8bSWSH.cs | 12 +- .../Dirtied/EncounterEnumerator9SWSH.cs | 12 +- .../Generator/Search/EncounterEnumerator2.cs | 8 +- .../Generator/Search/EncounterEnumerator3.cs | 4 +- .../Search/EncounterEnumerator3GC.cs | 4 +- .../Generator/Search/EncounterEnumerator4.cs | 8 +- .../Generator/Search/EncounterEnumerator5.cs | 10 +- .../Generator/Search/EncounterEnumerator6.cs | 14 +- .../Generator/Search/EncounterEnumerator7.cs | 12 +- .../Search/EncounterEnumerator7GG.cs | 4 +- .../Generator/Search/EncounterEnumerator8.cs | 8 +- .../Generator/Search/EncounterEnumerator8a.cs | 4 +- .../Generator/Search/EncounterEnumerator8b.cs | 12 +- .../Generator/Search/EncounterEnumerator9.cs | 8 +- .../Information/EncounterSuggestion.cs | 67 +- .../Information/EncounterSuggestionData.cs | 8 +- .../Information/EncounterSummary.cs | 14 +- .../Encounters/Information/EncounterText.cs | 2 +- .../Encounters/Templates/Enums/Shiny.cs | 2 +- .../Encounters/Templates/Enums/SlotType.cs | 112 ---- .../Templates/GO/EncounterSlot7GO.cs | 37 +- .../Templates/GO/EncounterSlot8GO.cs | 48 +- .../Templates/Gen1/EncounterArea1.cs | 30 +- .../Templates/Gen1/EncounterGift1.cs | 35 +- .../Templates/Gen1/EncounterSlot1.cs | 10 +- .../Templates/Gen1/EncounterStatic1.cs | 10 +- .../Templates/Gen1/EncounterTrade1.cs | 12 +- .../Templates/Gen2/EncounterArea2.cs | 61 +- .../Templates/Gen2/EncounterGift2.cs | 67 +- .../Templates/Gen2/EncounterSlot2.cs | 32 +- .../Templates/Gen2/EncounterStatic2.cs | 38 +- .../Templates/Gen2/EncounterTrade2.cs | 26 +- .../Templates/Gen3/Colo/EncounterGift3Colo.cs | 30 +- .../Gen3/Colo/EncounterShadow3Colo.cs | 31 +- .../Gen3/Colo/EncounterStatic3Colo.cs | 28 +- .../Templates/Gen3/EncounterArea3.cs | 63 +- .../Templates/Gen3/EncounterSlot3.cs | 64 +- .../Templates/Gen3/EncounterStatic3.cs | 42 +- .../Templates/Gen3/EncounterTrade3.cs | 52 +- .../Templates/Gen3/XD/EncounterArea3XD.cs | 3 +- .../Templates/Gen3/XD/EncounterShadow3XD.cs | 28 +- .../Templates/Gen3/XD/EncounterSlot3XD.cs | 25 +- .../Templates/Gen3/XD/EncounterStatic3XD.cs | 28 +- .../Templates/Gen3/XD/EncounterTrade3XD.cs | 28 +- .../Templates/Gen4/EncounterArea4.cs | 72 ++- .../Templates/Gen4/EncounterSlot4.cs | 83 ++- .../Templates/Gen4/EncounterStatic4.cs | 60 +- .../Gen4/EncounterStatic4Pokewalker.cs | 30 +- .../Templates/Gen4/EncounterTrade4PID.cs | 72 +-- .../Gen4/EncounterTrade4RanchGift.cs | 43 +- .../Templates/Gen4/IGroundTypeTile.cs | 2 +- .../Templates/Gen5/EncounterArea5.cs | 28 +- .../Templates/Gen5/EncounterSlot5.cs | 30 +- .../Templates/Gen5/EncounterStatic5.cs | 46 +- .../Templates/Gen5/EncounterStatic5Entree.cs | 30 +- .../Templates/Gen5/EncounterStatic5N.cs | 32 +- .../Templates/Gen5/EncounterStatic5Radar.cs | 36 +- .../Templates/Gen5/EncounterTrade5B2W2.cs | 30 +- .../Templates/Gen5/EncounterTrade5BW.cs | 30 +- .../Templates/Gen6/EncounterArea6AO.cs | 17 +- .../Templates/Gen6/EncounterArea6XY.cs | 43 +- .../Templates/Gen6/EncounterSlot6AO.cs | 36 +- .../Templates/Gen6/EncounterSlot6XY.cs | 42 +- .../Templates/Gen6/EncounterStatic6.cs | 61 +- .../Templates/Gen6/EncounterTrade6.cs | 65 +- .../Templates/Gen7/EncounterArea7.cs | 23 +- .../Templates/Gen7/EncounterSlot7.cs | 31 +- .../Templates/Gen7/EncounterStatic7.cs | 49 +- .../Templates/Gen7/EncounterTrade7.cs | 57 +- .../Templates/Gen7/EncounterTransfer7.cs | 6 +- .../Templates/Gen7b/EncounterArea7b.cs | 13 +- .../Templates/Gen7b/EncounterSlot7b.cs | 33 +- .../Templates/Gen7b/EncounterStatic7b.cs | 39 +- .../Templates/Gen7b/EncounterTrade7b.cs | 45 +- .../Templates/Gen8/EncounterArea8.cs | 31 +- .../Templates/Gen8/EncounterSlot8.cs | 39 +- .../Templates/Gen8/EncounterStatic8.cs | 34 +- .../Templates/Gen8/EncounterStatic8N.cs | 39 +- .../Templates/Gen8/EncounterStatic8NC.cs | 8 +- .../Templates/Gen8/EncounterStatic8ND.cs | 15 +- .../Templates/Gen8/EncounterStatic8Nest.cs | 32 +- .../Templates/Gen8/EncounterStatic8U.cs | 10 +- .../Templates/Gen8/EncounterTrade8.cs | 77 +-- .../Gen8/{AreaSlotType8.cs => SlotType8.cs} | 14 +- .../Templates/Gen8a/EncounterArea8a.cs | 24 +- .../Templates/Gen8a/EncounterSlot8a.cs | 43 +- .../Templates/Gen8a/EncounterStatic8a.cs | 34 +- .../Gen8a/IMasteryInitialMoveShop8.cs | 2 +- .../Templates/Gen8b/EncounterArea8b.cs | 41 +- .../Templates/Gen8b/EncounterSlot8b.cs | 36 +- .../Templates/Gen8b/EncounterStatic8b.cs | 56 +- .../Templates/Gen8b/EncounterTrade8b.cs | 62 +- .../Templates/Gen9/EncounterArea9.cs | 13 +- .../Templates/Gen9/EncounterDist9.cs | 28 +- .../Templates/Gen9/EncounterFixed9.cs | 56 +- .../Templates/Gen9/EncounterMight9.cs | 28 +- .../Templates/Gen9/EncounterOutbreak9.cs | 58 +- .../Templates/Gen9/EncounterSlot9.cs | 39 +- .../Templates/Gen9/EncounterStatic9.cs | 48 +- .../Templates/Gen9/EncounterTera9.cs | 28 +- .../Templates/Gen9/EncounterTrade9.cs | 62 +- .../Templates/Interfaces/IEncounterArea.cs | 4 +- .../Interfaces/IEncounterTemplate.cs | 2 +- .../Templates/Interfaces/ILocation.cs | 14 +- .../Interfaces/Properties/IEncounterSlot34.cs | 21 + .../Interfaces/Properties/ILevelRange.cs | 15 +- .../Interfaces/Properties/IRestrictVersion.cs | 2 +- .../Templates/Interfaces/RNG/IMagnetStatic.cs | 35 +- .../Templates/Interfaces/RNG/ISlotRNGType.cs | 12 - .../Templates/Shared/EncounterEgg.cs | 45 +- .../Templates/Shared/EncounterInvalid.cs | 12 +- .../Encounters/Verifiers/EggHatchLocation3.cs | 12 +- .../Encounters/Verifiers/EggHatchLocation4.cs | 12 +- .../Encounters/Verifiers/EggHatchLocation5.cs | 12 +- .../Encounters/Verifiers/EggHatchLocation6.cs | 4 +- .../Encounters/Verifiers/EggHatchLocation7.cs | 6 +- .../Encounters/Verifiers/EggHatchLocation8.cs | 2 +- .../Verifiers/EggHatchLocation8b.cs | 6 +- .../Encounters/Verifiers/EggHatchLocation9.cs | 6 +- .../Encounters/Verifiers/EncounterVerifier.cs | 90 ++- .../Verifiers/MysteryGiftVerifier.cs | 18 +- .../Legality/Evolutions/EncounterOrigin.cs | 20 +- .../Legality/Evolutions/EvolutionChain.cs | 6 +- .../EvolutionGroup/EvolutionGroup1.cs | 6 +- .../EvolutionGroup/EvolutionGroup2.cs | 6 +- .../EvolutionGroup/EvolutionGroup3.cs | 6 +- .../EvolutionGroup/EvolutionGroup4.cs | 8 +- .../EvolutionGroup/EvolutionGroup5.cs | 4 +- .../EvolutionGroup/EvolutionGroup6.cs | 2 +- .../EvolutionGroup/EvolutionGroup7.cs | 4 +- .../EvolutionGroup/EvolutionGroup7b.cs | 2 +- .../EvolutionGroup/EvolutionGroupHOME.cs | 2 +- .../EvolutionGroup/EvolutionOrigin.cs | 4 +- .../Evolutions/Methods/EvolutionMethod.cs | 4 +- .../Formatting/LegalityCheckStrings.cs | 2 +- .../Legality/Formatting/LegalityFormatting.cs | 56 +- .../Legality/LearnSource/Group/LearnGroup1.cs | 2 +- .../Legality/LearnSource/Group/LearnGroup2.cs | 2 +- .../Legality/LearnSource/Group/LearnGroup3.cs | 2 +- .../Legality/LearnSource/Group/LearnGroup4.cs | 2 +- .../Legality/LearnSource/Group/LearnGroup5.cs | 2 +- .../Legality/LearnSource/Group/LearnGroup6.cs | 2 +- .../Legality/LearnSource/Group/LearnGroup7.cs | 2 +- .../LearnSource/Group/LearnGroup7b.cs | 2 +- .../Legality/LearnSource/Group/LearnGroup8.cs | 2 +- .../LearnSource/Group/LearnGroup8a.cs | 2 +- .../LearnSource/Group/LearnGroup8b.cs | 2 +- .../Legality/LearnSource/Group/LearnGroup9.cs | 2 +- .../LearnSource/Group/LearnGroupHOME.cs | 8 +- .../LearnSource/Sources/LearnSource2C.cs | 2 +- .../LearnSource/Sources/LearnSource3E.cs | 2 +- .../LearnSource/Sources/LearnSource3FR.cs | 2 +- .../LearnSource/Sources/LearnSource3LG.cs | 2 +- .../LearnSource/Sources/LearnSource3RS.cs | 2 +- .../LearnSource/Sources/LearnSource4DP.cs | 2 +- .../LearnSource/Sources/LearnSource4HGSS.cs | 2 +- .../LearnSource/Sources/LearnSource4Pt.cs | 2 +- .../LearnSource/Verify/LearnPossible.cs | 2 +- .../Verify/LearnVerifierHistory.cs | 2 +- .../Verify/LearnVerifierRelearn.cs | 2 +- PKHeX.Core/Legality/LegalityAnalysis.cs | 6 +- PKHeX.Core/Legality/MoveListSuggest.cs | 8 +- .../Legality/Moves/Breeding/EggSource.cs | 4 +- .../Legality/Moves/Breeding/MoveBreed.cs | 6 +- .../Legality/Moves/Breeding/MoveBreed6.cs | 2 +- PKHeX.Core/Legality/RNG/Algorithms/LCRNG.cs | 11 + .../Legality/RNG/Algorithms/LCRNGReversal.cs | 2 +- .../RNG/Algorithms/LCRNGReversalSkip.cs | 4 +- PKHeX.Core/Legality/RNG/CXD/NPCLock.cs | 2 +- PKHeX.Core/Legality/RNG/CXD/TeamLock.cs | 20 +- .../Gen4 => ClassicEra}/ClassicEraRNG.cs | 42 +- .../Legality/RNG/ClassicEra/Gen3/MethodH.cs | 602 ++++++++++++++++++ .../RNG/ClassicEra/Gen3/MethodHCondition.cs | 29 + .../RNG/ClassicEra/Gen3/MethodHWindowInfo.cs | 16 + .../RNG/ClassicEra/Gen3/SlotMethodH.cs | 100 +++ .../Legality/RNG/ClassicEra/Gen4/MethodJ.cs | 481 ++++++++++++++ .../Legality/RNG/ClassicEra/Gen4/MethodK.cs | 583 +++++++++++++++++ .../Gen4/PokewalkerRNG.cs | 6 +- .../RNG/ClassicEra/Gen4/RuinsOfAlph4.cs | 117 ++++ .../RNG/ClassicEra/Gen4/SlotMethodJ.cs | 57 ++ .../RNG/ClassicEra/Gen4/SlotMethodK.cs | 109 ++++ .../RNG/ClassicEra/Gen4/SolaceonRuins4.cs | 48 ++ .../Legality/RNG/ClassicEra/LeadEncounter.cs | 28 + .../Legality/RNG/ClassicEra/LeadFinder.cs | 111 ++++ .../Legality/RNG/ClassicEra/LeadSeed.cs | 34 + PKHeX.Core/Legality/RNG/Frame/Frame.cs | 91 --- .../Legality/RNG/Frame/FrameCheckDetails.cs | 28 + PKHeX.Core/Legality/RNG/Frame/FrameFinder.cs | 399 ------------ .../Legality/RNG/Frame/FrameGenerator.cs | 98 --- PKHeX.Core/Legality/RNG/Frame/FrameType.cs | 18 - PKHeX.Core/Legality/RNG/Frame/LeadRequired.cs | 112 +++- PKHeX.Core/Legality/RNG/Frame/Pokeblock.cs | 19 - PKHeX.Core/Legality/RNG/Frame/SeedInfo.cs | 119 ---- PKHeX.Core/Legality/RNG/Frame/SlotNumber.cs | 146 ----- PKHeX.Core/Legality/RNG/Frame/SlotRange.cs | 162 ----- PKHeX.Core/Legality/RNG/MethodFinder.cs | 113 +++- .../RNG/Methods/Gen8/Overworld8RNG.cs | 8 +- .../Legality/RNG/Methods/Gen8/RaidRNG.cs | 32 +- .../RNG/Methods/Gen8a/Overworld8aRNG.cs | 42 +- .../RNG/Methods/Gen8b/Roaming8bRNG.cs | 12 +- .../Legality/RNG/Methods/Gen8b/Wild8bRNG.cs | 16 +- .../RNG/Methods/Gen9/Encounter9RNG.cs | 44 +- PKHeX.Core/Legality/RNG/PIDGenerator.cs | 19 +- PKHeX.Core/Legality/RNG/PIDIV.cs | 50 +- PKHeX.Core/Legality/RNG/PIDType.cs | 30 +- .../Legality/RNG/Util/ToxtricityUtil.cs | 8 +- .../Legality/Restrictions/GBRestrictions.cs | 2 +- .../Restrictions/Memories/MemoryContext.cs | 2 +- .../Restrictions/Memories/MemoryContext6.cs | 4 +- .../Memories/MemoryContext6Data.cs | 12 + .../Restrictions/Memories/MemoryContext8.cs | 6 +- .../Memories/MemoryContext8Data.cs | 12 +- .../Memories/MemoryPermissions.cs | 6 +- .../Restrictions/Memories/MemoryRules.cs | 4 +- .../Memories/MemoryVariableSet.cs | 4 +- .../Legality/Structures/CheckIdentifier.cs | 6 +- PKHeX.Core/Legality/Structures/LegalInfo.cs | 23 +- PKHeX.Core/Legality/Tables/FormChangeUtil.cs | 4 +- PKHeX.Core/Legality/Tables/FormInfo.cs | 12 +- PKHeX.Core/Legality/Tables/FormItem.cs | 8 +- .../Verifiers/Ability/AbilityVerifier.cs | 24 +- .../Verifiers/Ball/BallContextHOME.cs | 2 +- .../Verifiers/Ball/BallUseLegality.cs | 6 +- .../Legality/Verifiers/Ball/BallVerifier.cs | 14 +- PKHeX.Core/Legality/Verifiers/CXDVerifier.cs | 13 +- .../Legality/Verifiers/ContestStatVerifier.cs | 8 +- .../Legality/Verifiers/EffortValueVerifier.cs | 13 +- .../Verifiers/Egg/EggStateLegality.cs | 20 +- .../Verifiers/FormArgumentVerifier.cs | 2 +- .../Legality/Verifiers/GenderVerifier.cs | 6 +- .../Legality/Verifiers/HistoryVerifier.cs | 34 +- .../Verifiers/IndividualValueVerifier.cs | 15 +- .../Legality/Verifiers/LanguageVerifier.cs | 10 +- .../Verifiers/LegendsArceusVerifier.cs | 12 +- .../Legality/Verifiers/LevelVerifier.cs | 23 +- .../Legality/Verifiers/MemoryVerifier.cs | 64 +- .../Misc/ContestStatGrantingSheen.cs | 2 +- .../Verifiers/Misc/ContestStatInfo.cs | 68 +- PKHeX.Core/Legality/Verifiers/MiscVerifier.cs | 24 +- .../Legality/Verifiers/NicknameVerifier.cs | 10 +- PKHeX.Core/Legality/Verifiers/PIDVerifier.cs | 6 +- .../Legality/Verifiers/ParseSettings.cs | 17 +- .../Legality/Verifiers/Ribbons/MarkRules.cs | 4 +- .../Legality/Verifiers/Ribbons/RibbonRules.cs | 8 +- .../Ribbons/RibbonVerifierCommon6.cs | 8 +- .../Ribbons/RibbonVerifierCommon8.cs | 6 +- .../Legality/Verifiers/TrainerIDVerifier.cs | 2 +- .../Legality/Verifiers/TrainerNameVerifier.cs | 14 +- .../Legality/Verifiers/TransferVerifier.cs | 30 +- PKHeX.Core/Moves/MoveInfo.cs | 2 +- PKHeX.Core/MysteryGifts/MysteryGift.cs | 27 +- PKHeX.Core/MysteryGifts/MysteryUtil.cs | 12 +- PKHeX.Core/MysteryGifts/PCD.cs | 32 +- PKHeX.Core/MysteryGifts/PGF.cs | 104 +-- PKHeX.Core/MysteryGifts/PGT.cs | 42 +- PKHeX.Core/MysteryGifts/PL6.cs | 42 +- PKHeX.Core/MysteryGifts/WA8.cs | 114 ++-- PKHeX.Core/MysteryGifts/WB7.cs | 84 ++- PKHeX.Core/MysteryGifts/WB8.cs | 141 ++-- PKHeX.Core/MysteryGifts/WC3.cs | 86 +-- PKHeX.Core/MysteryGifts/WC6.cs | 164 +++-- PKHeX.Core/MysteryGifts/WC7.cs | 157 +++-- PKHeX.Core/MysteryGifts/WC8.cs | 116 ++-- PKHeX.Core/MysteryGifts/WC9.cs | 114 ++-- PKHeX.Core/MysteryGifts/WR7.cs | 22 +- PKHeX.Core/PKM/BK4.cs | 56 +- PKHeX.Core/PKM/CK3.cs | 40 +- PKHeX.Core/PKM/Enums/PokeSize.cs | 2 +- PKHeX.Core/PKM/Enums/PokeSizeDetailed.cs | 12 +- PKHeX.Core/PKM/Enums/PokeblockFlavor.cs | 24 + PKHeX.Core/PKM/HOME/GameDataCore.cs | 186 +++--- PKHeX.Core/PKM/HOME/GameDataPA8.cs | 20 +- PKHeX.Core/PKM/HOME/GameDataPB7.cs | 64 +- PKHeX.Core/PKM/HOME/GameDataPB8.cs | 18 +- PKHeX.Core/PKM/HOME/GameDataPK8.cs | 48 +- PKHeX.Core/PKM/HOME/GameDataPK9.cs | 12 +- PKHeX.Core/PKM/HOME/HomeCrypto.cs | 8 +- PKHeX.Core/PKM/HOME/IGameDataSide.cs | 18 +- PKHeX.Core/PKM/HOME/IPokerusStatus.cs | 2 +- PKHeX.Core/PKM/HOME/PKH.cs | 120 ++-- PKHeX.Core/PKM/Interfaces/IAffection.cs | 6 +- PKHeX.Core/PKM/Interfaces/IAwakened.cs | 4 +- PKHeX.Core/PKM/Interfaces/IBattleVersion.cs | 15 +- PKHeX.Core/PKM/Interfaces/ICaughtData2.cs | 8 +- PKHeX.Core/PKM/Interfaces/IContestStats.cs | 12 +- PKHeX.Core/PKM/Interfaces/IFormArgument.cs | 2 +- PKHeX.Core/PKM/Interfaces/IHandlerLanguage.cs | 2 +- PKHeX.Core/PKM/Interfaces/IHyperTrain.cs | 2 +- PKHeX.Core/PKM/Interfaces/IMemoryHT.cs | 26 +- PKHeX.Core/PKM/Interfaces/IMemoryOT.cs | 10 +- PKHeX.Core/PKM/Interfaces/INature.cs | 2 +- PKHeX.Core/PKM/Interfaces/IObedienceLevel.cs | 4 +- PKHeX.Core/PKM/Interfaces/ITrainerID32.cs | 6 +- .../Interfaces/Metadata/IGameValueLimit.cs | 4 +- .../PKM/Interfaces/Metadata/IGeneration.cs | 4 +- .../Interfaces/Metadata}/IVersion.cs | 24 +- .../Templates/IContestStatsReadOnly.cs | 84 +-- .../Templates/IFixedOTFriendship.cs | 2 +- .../Interfaces/Templates/IMemoryOTReadOnly.cs | 8 +- .../Interfaces/Templates/INatureReadOnly.cs | 2 +- PKHeX.Core/PKM/PA8.cs | 152 ++--- PKHeX.Core/PKM/PB7.cs | 94 +-- PKHeX.Core/PKM/PB8.cs | 40 +- PKHeX.Core/PKM/PK1.cs | 72 +-- PKHeX.Core/PKM/PK2.cs | 71 +-- PKHeX.Core/PKM/PK3.cs | 89 ++- PKHeX.Core/PKM/PK4.cs | 89 +-- PKHeX.Core/PKM/PK5.cs | 163 ++--- PKHeX.Core/PKM/PK6.cs | 124 ++-- PKHeX.Core/PKM/PK7.cs | 124 ++-- PKHeX.Core/PKM/PK8.cs | 36 +- PKHeX.Core/PKM/PK9.cs | 160 ++--- PKHeX.Core/PKM/PKM.cs | 199 +++--- PKHeX.Core/PKM/RK4.cs | 74 +-- PKHeX.Core/PKM/SK2.cs | 48 +- PKHeX.Core/PKM/Searching/SearchSettings.cs | 16 +- PKHeX.Core/PKM/Searching/SearchUtil.cs | 4 +- PKHeX.Core/PKM/Shared/G3PKM.cs | 54 +- PKHeX.Core/PKM/Shared/G4PKM.cs | 130 ++-- PKHeX.Core/PKM/Shared/G6PKM.cs | 24 +- PKHeX.Core/PKM/Shared/G8PKM.cs | 112 ++-- PKHeX.Core/PKM/Shared/GBPKM.cs | 22 +- PKHeX.Core/PKM/Shared/GBPKML.cs | 26 +- PKHeX.Core/PKM/Shared/PokeList1.cs | 4 +- PKHeX.Core/PKM/Shared/PokeList2.cs | 4 +- PKHeX.Core/PKM/Shared/PokeListGB.cs | 16 +- PKHeX.Core/PKM/Strings/StringConverter.cs | 6 +- .../Strings/StringConverter12Transporter.cs | 16 +- .../PKM/Util/Conversion/EntityConverter.cs | 6 +- .../PKM/Util/Conversion/FormConverter.cs | 30 +- .../PKM/Util/Conversion/IEntityRejuvenator.cs | 34 +- .../PKM/Util/Conversion/ItemConverter.cs | 14 +- PKHeX.Core/PKM/Util/EffortValues.cs | 4 +- PKHeX.Core/PKM/Util/EntityBlank.cs | 17 +- PKHeX.Core/PKM/Util/EntityContext.cs | 8 +- PKHeX.Core/PKM/Util/EntityFormat.cs | 4 +- PKHeX.Core/PKM/Util/EntityGender.cs | 10 +- PKHeX.Core/PKM/Util/EntityPID.cs | 10 +- PKHeX.Core/PKM/Util/EntitySorting.cs | 14 +- PKHeX.Core/PKM/Util/Experience.cs | 24 +- PKHeX.Core/PKM/Util/Language.cs | 4 +- PKHeX.Core/PKM/Util/PKX.cs | 2 +- PKHeX.Core/PKM/Util/RecentTrainerCache.cs | 10 +- PKHeX.Core/PKM/Util/SpeciesName.cs | 18 +- PKHeX.Core/PKM/XK3.cs | 44 +- PKHeX.Core/PersonalInfo/Info/PersonalInfo1.cs | 4 +- PKHeX.Core/PersonalInfo/Info/PersonalInfo2.cs | 4 +- PKHeX.Core/PersonalInfo/Info/PersonalInfo3.cs | 4 +- PKHeX.Core/PersonalInfo/Info/PersonalInfo4.cs | 4 +- .../PersonalInfo/Info/PersonalInfo5B2W2.cs | 4 +- .../PersonalInfo/Info/PersonalInfo5BW.cs | 4 +- .../PersonalInfo/Info/PersonalInfo6AO.cs | 4 +- .../PersonalInfo/Info/PersonalInfo6XY.cs | 4 +- PKHeX.Core/PersonalInfo/Info/PersonalInfo7.cs | 4 +- .../PersonalInfo/Info/PersonalInfo7GG.cs | 4 +- .../PersonalInfo/Info/PersonalInfo8BDSP.cs | 4 +- .../PersonalInfo/Info/PersonalInfo8LA.cs | 13 +- .../PersonalInfo/Info/PersonalInfo8SWSH.cs | 4 +- .../PersonalInfo/Info/PersonalInfo9SV.cs | 4 +- .../PersonalInfo/Interfaces/IGenderDetail.cs | 10 +- .../Interfaces/IPersonalEncounter.cs | 4 +- .../Interfaces/IPersonalInfoTM.cs | 7 + .../Interfaces/IPersonalInfoTR.cs | 7 + .../Interfaces/IPersonalInfoTutorType.cs | 7 + PKHeX.Core/PersonalInfo/PersonalInfo.cs | 39 +- .../checks/LegalityCheckStrings_de.txt | 2 +- .../checks/LegalityCheckStrings_en.txt | 2 +- .../checks/LegalityCheckStrings_it.txt | 2 +- .../legality/wild/Gen1/encounter_blue.pkl | Bin 3264 -> 5836 bytes .../legality/wild/Gen1/encounter_blue_jp.pkl | Bin 1112 -> 2216 bytes .../wild/Gen1/encounter_blue_jp_f.pkl | Bin 172 -> 0 bytes .../legality/wild/Gen1/encounter_red.pkl | Bin 3264 -> 5836 bytes .../legality/wild/Gen1/encounter_yellow.pkl | Bin 3608 -> 5988 bytes .../legality/wild/Gen2/encounter_crystal.pkl | Bin 20040 -> 19972 bytes .../legality/wild/Gen2/encounter_gold.pkl | Bin 19864 -> 19796 bytes .../legality/wild/Gen2/encounter_silver.pkl | Bin 19864 -> 19796 bytes .../legality/wild/Gen2/trees_h_c.pkl | Bin 1903 -> 0 bytes .../legality/wild/Gen3/encounter_e.pkl | Bin 16316 -> 16316 bytes .../legality/wild/Gen3/encounter_fr.pkl | Bin 21712 -> 21712 bytes .../legality/wild/Gen3/encounter_lg.pkl | Bin 21712 -> 21712 bytes .../legality/wild/Gen3/encounter_r.pkl | Bin 15172 -> 15172 bytes .../wild/Gen3/encounter_rse_swarm.pkl | Bin 188 -> 188 bytes .../legality/wild/Gen3/encounter_s.pkl | Bin 15300 -> 15300 bytes .../legality/wild/Gen4/encounter_d.pkl | Bin 33752 -> 33900 bytes .../legality/wild/Gen4/encounter_hg.pkl | Bin 88860 -> 81164 bytes .../legality/wild/Gen4/encounter_p.pkl | Bin 33652 -> 33660 bytes .../legality/wild/Gen4/encounter_pt.pkl | Bin 32396 -> 32592 bytes .../legality/wild/Gen4/encounter_ss.pkl | Bin 88288 -> 80772 bytes .../legality/wild/Gen5/encounter_b.pkl | Bin 14744 -> 14744 bytes .../legality/wild/Gen5/encounter_b2.pkl | Bin 20808 -> 20808 bytes .../legality/wild/Gen5/encounter_w.pkl | Bin 14896 -> 14896 bytes .../legality/wild/Gen5/encounter_w2.pkl | Bin 20780 -> 20780 bytes .../legality/wild/Gen6/encounter_as.pkl | Bin 28196 -> 28196 bytes .../legality/wild/Gen6/encounter_or.pkl | Bin 28196 -> 28196 bytes .../legality/wild/Gen6/encounter_x.pkl | Bin 17476 -> 17476 bytes .../legality/wild/Gen6/encounter_y.pkl | Bin 17476 -> 17476 bytes .../legality/wild/Gen7/encounter_mn.pkl | Bin 6136 -> 6136 bytes .../legality/wild/Gen7/encounter_sn.pkl | Bin 6120 -> 6120 bytes .../legality/wild/Gen7/encounter_um.pkl | Bin 7696 -> 7696 bytes .../legality/wild/Gen7/encounter_us.pkl | Bin 7688 -> 7688 bytes .../wild/Gen9/encounter_outbreak_paldea.pkl | Bin 74480 -> 82040 bytes PKHeX.Core/Saves/Abstractions/ITrainerInfo.cs | 38 +- .../Saves/Abstractions/SimpleTrainerInfo.cs | 12 +- .../Saves/Access/SaveBlockAccessor9SV.cs | 9 +- PKHeX.Core/Saves/SAV1.cs | 20 +- PKHeX.Core/Saves/SAV1Stadium.cs | 15 +- PKHeX.Core/Saves/SAV1StadiumJ.cs | 12 +- PKHeX.Core/Saves/SAV2.cs | 20 +- PKHeX.Core/Saves/SAV2Stadium.cs | 13 +- PKHeX.Core/Saves/SAV3.cs | 8 +- PKHeX.Core/Saves/SAV3Colosseum.cs | 8 +- PKHeX.Core/Saves/SAV3E.cs | 9 +- PKHeX.Core/Saves/SAV3FRLG.cs | 2 +- PKHeX.Core/Saves/SAV3GCMemoryCard.cs | 8 +- PKHeX.Core/Saves/SAV3RS.cs | 2 +- PKHeX.Core/Saves/SAV3RSBox.cs | 6 +- PKHeX.Core/Saves/SAV3XD.cs | 8 +- PKHeX.Core/Saves/SAV4.cs | 8 +- PKHeX.Core/Saves/SAV4BR.cs | 6 +- PKHeX.Core/Saves/SAV5.cs | 16 +- PKHeX.Core/Saves/SAV6.cs | 12 +- PKHeX.Core/Saves/SAV6AO.cs | 7 +- PKHeX.Core/Saves/SAV6AODemo.cs | 7 +- PKHeX.Core/Saves/SAV6XY.cs | 7 +- PKHeX.Core/Saves/SAV7.cs | 22 +- PKHeX.Core/Saves/SAV7b.cs | 15 +- PKHeX.Core/Saves/SAV8BS.cs | 15 +- PKHeX.Core/Saves/SAV8LA.cs | 14 +- PKHeX.Core/Saves/SAV8SWSH.cs | 15 +- PKHeX.Core/Saves/SAV9SV.cs | 15 +- PKHeX.Core/Saves/SAV_STADIUM.cs | 2 +- PKHeX.Core/Saves/SaveFile.cs | 12 +- PKHeX.Core/Saves/Storage/BulkStorage.cs | 4 +- PKHeX.Core/Saves/Storage/SAV4Ranch.cs | 6 +- .../Saves/Substructures/Battle Videos/BV3.cs | 2 +- .../Saves/Substructures/Battle Videos/BV6.cs | 2 +- .../Saves/Substructures/Battle Videos/BV7.cs | 2 +- .../Battle Videos/BattleVideo.cs | 2 +- .../Gen3/CXD/ShadowInfoEntryColo.cs | 2 +- .../Saves/Substructures/Gen3/HallFame3.cs | 4 +- .../Saves/Substructures/Gen3/Record3.cs | 18 +- .../Saves/Substructures/Gen3/Roamer3.cs | 18 +- .../Saves/Substructures/Gen3/SecretBase3.cs | 6 +- .../Substructures/Gen3/SecretBase3PKM.cs | 2 +- PKHeX.Core/Saves/Substructures/Gen3/Swarm3.cs | 8 + .../Saves/Substructures/Gen4/Dendou4.cs | 14 +- .../Saves/Substructures/Gen5/Color15Bit.cs | 14 +- .../Substructures/Gen5/Entree/EntreeSlot.cs | 4 +- .../Saves/Substructures/Gen5/PlayerData5.cs | 14 +- .../Saves/Substructures/Gen6/Encount6.cs | 2 +- .../Substructures/Gen6/HallFame6Entity.cs | 12 +- .../Saves/Substructures/Gen6/MyStatus6.cs | 14 +- .../Saves/Substructures/Gen6/MyStatus6XY.cs | 8 +- PKHeX.Core/Saves/Substructures/Gen6/PSS6.cs | 12 +- .../Gen6/SecretBase/SecretBase6PKM.cs | 8 +- .../Substructures/Gen6/SuperTrainBlock.cs | 2 +- .../Substructures/Gen6/TrainerFashion6.cs | 2 +- .../Saves/Substructures/Gen7/FestaFacility.cs | 4 +- .../Saves/Substructures/Gen7/LGPE/GP1.cs | 22 +- .../Substructures/Gen7/LGPE/MyStatus7b.cs | 14 +- .../Saves/Substructures/Gen7/MyStatus7.cs | 16 +- PKHeX.Core/Saves/Substructures/Gen7/QR7.cs | 2 +- .../Saves/Substructures/Gen8/BS/MyStatus8b.cs | 14 +- .../Substructures/Gen8/BS/MysteryBlock8b.cs | 2 +- .../Saves/Substructures/Gen8/BS/Zukan8b.cs | 2 +- .../Substructures/Gen8/BS/ZukanSpinda8b.cs | 12 +- .../Saves/Substructures/Gen8/LA/MyStatus8a.cs | 14 +- .../Gen8/LA/Pokedex/PokedexSave8a.cs | 2 +- .../Substructures/Gen8/SWSH/MyStatus8.cs | 14 +- .../Substructures/Gen8/SWSH/TitleScreen8.cs | 4 +- .../Substructures/Gen8/SWSH/TrainerCard8.cs | 14 +- .../Saves/Substructures/Gen9/MyStatus9.cs | 14 +- .../Gen9/PlayerFashionUnlock9.cs | 2 +- .../Substructures/Gen9/RaidSevenStar9.cs | 11 +- PKHeX.Core/Saves/Substructures/Mail/Mail4.cs | 8 +- PKHeX.Core/Saves/Substructures/Mail/Mail5.cs | 6 +- .../PokeDex/Gen9/PokeDexEntry9Kitakami.cs | 4 +- .../PokeDex/Gen9/PokeDexEntry9Paldea.cs | 4 +- .../Substructures/PokeDex/Gen9/Zukan9.cs | 5 +- .../PokeDex/Gen9/Zukan9Kitakami.cs | 6 +- .../Saves/Substructures/PokeDex/Zukan.cs | 10 +- .../Saves/Substructures/PokeDex/Zukan4.cs | 12 +- .../Saves/Substructures/PokeDex/Zukan5.cs | 2 +- .../Saves/Substructures/PokeDex/Zukan6.cs | 10 +- .../Saves/Substructures/PokeDex/Zukan7.cs | 54 +- .../Saves/Substructures/PokeDex/Zukan7b.cs | 18 +- .../Saves/Substructures/PokeDex/Zukan8.cs | 2 +- PKHeX.Core/Saves/Util/DexFormUtil.cs | 206 +++--- PKHeX.Core/Saves/Util/SaveExtensions.cs | 2 +- PKHeX.Core/Saves/Util/SaveUtil.cs | 56 +- PKHeX.Core/Saves/Util/StadiumUtil.cs | 9 +- PKHeX.Drawing.Misc/Util/TypeSpriteUtil.cs | 6 +- .../Builder/SpriteBuilder.cs | 14 +- .../Builder/SpriteBuilder5668.cs | 4 +- .../Builder/SpriteBuilder5668a.cs | 4 +- .../Builder/SpriteBuilder5668c.cs | 4 +- PKHeX.Drawing.PokeSprite/Util/SpriteName.cs | 4 +- PKHeX.Drawing.PokeSprite/Util/SpriteUtil.cs | 21 +- .../Controls/PKM Editor/BallBrowser.cs | 12 +- .../Controls/PKM Editor/ContestStat.cs | 12 +- .../Controls/PKM Editor/DrawConfig.cs | 2 +- PKHeX.WinForms/Controls/PKM Editor/EditPK2.cs | 12 +- .../PKM Editor/EntityInstructionBuilder.cs | 2 +- .../Controls/PKM Editor/GenderToggle.cs | 6 +- .../Controls/PKM Editor/IMainEditor.cs | 2 +- .../Controls/PKM Editor/LoadSave.cs | 122 ++-- .../Controls/PKM Editor/PKMEditor.Designer.cs | 12 +- .../Controls/PKM Editor/PKMEditor.cs | 243 ++++--- .../Controls/PKM Editor/StatEditor.cs | 24 +- .../Controls/PKM Editor/TrainerID.cs | 4 +- PKHeX.WinForms/Controls/Slots/PokePreview.cs | 2 +- PKHeX.WinForms/MainWindow/Main.cs | 26 +- PKHeX.WinForms/Misc/QR.cs | 7 +- PKHeX.WinForms/Properties/PKHeXSettings.cs | 9 +- .../Resources/text/changelog_2018.txt | 12 +- .../Resources/text/changelog_2022.txt | 2 +- PKHeX.WinForms/Resources/text/lang_es.txt | 4 +- .../Subforms/PKM Editors/MemoryAmie.cs | 84 +-- PKHeX.WinForms/Subforms/PKM Editors/Text.cs | 4 +- PKHeX.WinForms/Subforms/SAV_Database.cs | 10 +- PKHeX.WinForms/Subforms/SAV_Encounters.cs | 6 +- PKHeX.WinForms/Subforms/SAV_MysteryGiftDB.cs | 27 +- .../Subforms/Save Editors/Gen3/SAV_Roamer3.cs | 4 +- .../Save Editors/Gen4/SAV_Pokedex4.cs | 2 +- .../Subforms/Save Editors/Gen5/SAV_Misc5.cs | 2 +- .../Save Editors/Gen6/SAV_HallOfFame.cs | 23 +- .../Save Editors/Gen6/SAV_SecretBase.cs | 23 +- .../Subforms/Save Editors/Gen6/SAV_Trainer.cs | 14 +- .../Save Editors/Gen7/SAV_FestivalPlaza.cs | 8 +- .../Save Editors/Gen7/SAV_PokedexGG.cs | 131 ++-- .../Save Editors/Gen7/SAV_PokedexSM.cs | 143 ++--- .../Save Editors/Gen7/SAV_Trainer7.cs | 8 +- .../Save Editors/Gen7/SAV_Trainer7GG.cs | 4 +- .../Save Editors/Gen8/SAV_Trainer8.cs | 4 +- .../Save Editors/Gen8/SAV_Trainer8b.cs | 4 +- .../Save Editors/Gen9/SAV_Trainer9.cs | 4 +- .../Subforms/Save Editors/SAV_MailBox.cs | 94 +-- .../Subforms/Save Editors/SAV_Wondercard.cs | 2 +- .../PKHeX.Core.Tests/General/MarshalTests.cs | 3 +- ...s - 2CFF3D0BA012 transfer minlevel evo.pk6 | Bin 232 -> 0 bytes ...c - C65D0BA29204 transfer minlevel evo.pk6 | Bin 0 -> 260 bytes .../266 ★ - Silcoon - 319000000002.pk7 | Bin 232 -> 0 bytes .../268 ★ - Cascoon - A8FB00000007.pk7 | Bin 232 -> 0 bytes .../269 ★ - Dustox - C03700000003.pk7 | Bin 232 -> 0 bytes .../Legality/LegalityRules.cs | 6 +- .../Legality/RNG/MethodJChecks.cs | 69 ++ .../Legality/RNG/MockSlot4.cs | 29 + .../Legality/{ => RNG}/RaidTests.cs | 0 .../Legality/{ => RNG}/ShadowTests.cs | 54 +- .../Legality/{ => RNG}/Wild8aRNGTests.cs | 0 .../Legality/{ => RNG}/Wild8bRNGTests.cs | 0 .../PKHeX.Core.Tests/PKM/HiddenPowerTests.cs | 5 +- Tests/PKHeX.Core.Tests/PKM/PIDIVTests.cs | 70 +- Tests/PKHeX.Core.Tests/PKM/PKMTests.cs | 108 ++-- Tests/PKHeX.Core.Tests/PKM/StringTests.cs | 6 +- .../Simulator/GeneratorTests.cs | 28 +- .../Simulator/ShowdownSetTests.cs | 12 +- 638 files changed, 9620 insertions(+), 7839 deletions(-) delete mode 100644 PKHeX.Core/Legality/Encounters/Templates/Enums/SlotType.cs rename PKHeX.Core/Legality/Encounters/Templates/Gen8/{AreaSlotType8.cs => SlotType8.cs} (52%) create mode 100644 PKHeX.Core/Legality/Encounters/Templates/Interfaces/Properties/IEncounterSlot34.cs delete mode 100644 PKHeX.Core/Legality/Encounters/Templates/Interfaces/RNG/ISlotRNGType.cs rename PKHeX.Core/Legality/RNG/{Methods/Gen4 => ClassicEra}/ClassicEraRNG.cs (51%) create mode 100644 PKHeX.Core/Legality/RNG/ClassicEra/Gen3/MethodH.cs create mode 100644 PKHeX.Core/Legality/RNG/ClassicEra/Gen3/MethodHCondition.cs create mode 100644 PKHeX.Core/Legality/RNG/ClassicEra/Gen3/MethodHWindowInfo.cs create mode 100644 PKHeX.Core/Legality/RNG/ClassicEra/Gen3/SlotMethodH.cs create mode 100644 PKHeX.Core/Legality/RNG/ClassicEra/Gen4/MethodJ.cs create mode 100644 PKHeX.Core/Legality/RNG/ClassicEra/Gen4/MethodK.cs rename PKHeX.Core/Legality/RNG/{Methods => ClassicEra}/Gen4/PokewalkerRNG.cs (98%) create mode 100644 PKHeX.Core/Legality/RNG/ClassicEra/Gen4/RuinsOfAlph4.cs create mode 100644 PKHeX.Core/Legality/RNG/ClassicEra/Gen4/SlotMethodJ.cs create mode 100644 PKHeX.Core/Legality/RNG/ClassicEra/Gen4/SlotMethodK.cs create mode 100644 PKHeX.Core/Legality/RNG/ClassicEra/Gen4/SolaceonRuins4.cs create mode 100644 PKHeX.Core/Legality/RNG/ClassicEra/LeadEncounter.cs create mode 100644 PKHeX.Core/Legality/RNG/ClassicEra/LeadFinder.cs create mode 100644 PKHeX.Core/Legality/RNG/ClassicEra/LeadSeed.cs delete mode 100644 PKHeX.Core/Legality/RNG/Frame/Frame.cs create mode 100644 PKHeX.Core/Legality/RNG/Frame/FrameCheckDetails.cs delete mode 100644 PKHeX.Core/Legality/RNG/Frame/FrameFinder.cs delete mode 100644 PKHeX.Core/Legality/RNG/Frame/FrameGenerator.cs delete mode 100644 PKHeX.Core/Legality/RNG/Frame/FrameType.cs delete mode 100644 PKHeX.Core/Legality/RNG/Frame/Pokeblock.cs delete mode 100644 PKHeX.Core/Legality/RNG/Frame/SeedInfo.cs delete mode 100644 PKHeX.Core/Legality/RNG/Frame/SlotNumber.cs delete mode 100644 PKHeX.Core/Legality/RNG/Frame/SlotRange.cs create mode 100644 PKHeX.Core/PKM/Enums/PokeblockFlavor.cs rename PKHeX.Core/{Legality/Encounters/Templates/Interfaces/Properties => PKM/Interfaces/Metadata}/IVersion.cs (63%) create mode 100644 PKHeX.Core/PersonalInfo/Interfaces/IPersonalInfoTM.cs create mode 100644 PKHeX.Core/PersonalInfo/Interfaces/IPersonalInfoTR.cs create mode 100644 PKHeX.Core/PersonalInfo/Interfaces/IPersonalInfoTutorType.cs delete mode 100644 PKHeX.Core/Resources/legality/wild/Gen1/encounter_blue_jp_f.pkl delete mode 100644 PKHeX.Core/Resources/legality/wild/Gen2/trees_h_c.pkl delete mode 100644 Tests/PKHeX.Core.Tests/Legality/Legal/Generation 6/350 - Milobellus - 2CFF3D0BA012 transfer minlevel evo.pk6 create mode 100644 Tests/PKHeX.Core.Tests/Legality/Legal/Generation 6/350 - Milotic - C65D0BA29204 transfer minlevel evo.pk6 delete mode 100644 Tests/PKHeX.Core.Tests/Legality/Legal/Generation 7 Transfer/266 ★ - Silcoon - 319000000002.pk7 delete mode 100644 Tests/PKHeX.Core.Tests/Legality/Legal/Generation 7 Transfer/268 ★ - Cascoon - A8FB00000007.pk7 delete mode 100644 Tests/PKHeX.Core.Tests/Legality/Legal/Generation 7 Transfer/269 ★ - Dustox - C03700000003.pk7 create mode 100644 Tests/PKHeX.Core.Tests/Legality/RNG/MethodJChecks.cs create mode 100644 Tests/PKHeX.Core.Tests/Legality/RNG/MockSlot4.cs rename Tests/PKHeX.Core.Tests/Legality/{ => RNG}/RaidTests.cs (100%) rename Tests/PKHeX.Core.Tests/Legality/{ => RNG}/ShadowTests.cs (78%) rename Tests/PKHeX.Core.Tests/Legality/{ => RNG}/Wild8aRNGTests.cs (100%) rename Tests/PKHeX.Core.Tests/Legality/{ => RNG}/Wild8bRNGTests.cs (100%) diff --git a/PKHeX.Core/Editing/Applicators/BallApplicator.cs b/PKHeX.Core/Editing/Applicators/BallApplicator.cs index 61a9dc7c3..2b4a97e65 100644 --- a/PKHeX.Core/Editing/Applicators/BallApplicator.cs +++ b/PKHeX.Core/Editing/Applicators/BallApplicator.cs @@ -22,7 +22,7 @@ public static IEnumerable GetLegalBalls(PKM pk) var clone = pk.Clone(); foreach (var b in BallList) { - var ball = (int)b; + var ball = (byte)b; clone.Ball = ball; if (clone.Ball != ball) continue; // Some setters guard against out of bounds values. @@ -38,7 +38,7 @@ public static IEnumerable GetLegalBalls(PKM pk) /// Requires checking the for every that is tried. /// /// Pokémon to modify. - public static int ApplyBallLegalRandom(PKM pk) + public static byte ApplyBallLegalRandom(PKM pk) { Span balls = stackalloc Ball[MaxBallSpanAlloc]; var count = GetBallListFromColor(pk, balls); @@ -54,7 +54,7 @@ public static int ApplyBallLegalRandom(PKM pk) /// Requires checking the for every that is tried. /// /// Pokémon to modify. - public static int ApplyBallLegalByColor(PKM pk) + public static byte ApplyBallLegalByColor(PKM pk) { Span balls = stackalloc Ball[MaxBallSpanAlloc]; GetBallListFromColor(pk, balls); @@ -65,20 +65,20 @@ public static int ApplyBallLegalByColor(PKM pk) /// Applies a random ball value in a cyclical manner. /// /// Pokémon to modify. - public static int ApplyBallNext(PKM pk) + public static byte ApplyBallNext(PKM pk) { Span balls = stackalloc Ball[MaxBallSpanAlloc]; GetBallList(pk.Ball, balls); var next = balls[0]; - return pk.Ball = (int)next; + return pk.Ball = (byte)next; } - private static int ApplyFirstLegalBall(PKM pk, ReadOnlySpan balls) + private static byte ApplyFirstLegalBall(PKM pk, ReadOnlySpan balls) { var initial = pk.Ball; foreach (var b in balls) { - var test = (int)b; + var test = (byte)b; pk.Ball = test; if (new LegalityAnalysis(pk).Valid) return test; @@ -86,7 +86,7 @@ private static int ApplyFirstLegalBall(PKM pk, ReadOnlySpan balls) return initial; // fail, revert } - private static int GetBallList(int ball, Span result) + private static int GetBallList(byte ball, Span result) { var balls = BallList; var currentBall = (Ball)ball; diff --git a/PKHeX.Core/Editing/Applicators/CatchRateApplicator.cs b/PKHeX.Core/Editing/Applicators/CatchRateApplicator.cs index f83cc666c..34a34fcad 100644 --- a/PKHeX.Core/Editing/Applicators/CatchRateApplicator.cs +++ b/PKHeX.Core/Editing/Applicators/CatchRateApplicator.cs @@ -40,16 +40,16 @@ public static byte GetSuggestedCatchRate(PK1 pk, SaveFile sav, LegalityAnalysis } } - private static PersonalTable1 GetPersonalTable(SaveFile sav, GameVersion ver) + private static PersonalTable1 GetPersonalTable(SaveFile sav, GameVersion version) { if (sav.Personal is PersonalTable1 pt) { var other = sav.Version; - if (other.Contains(ver) || ver.Contains(other)) + if (other.Contains(version) || version.Contains(other)) return pt; } - if (!GameVersion.RB.Contains(ver)) + if (!GameVersion.RB.Contains(version)) return PersonalTable.Y; return PersonalTable.RB; } diff --git a/PKHeX.Core/Editing/Applicators/GenderApplicator.cs b/PKHeX.Core/Editing/Applicators/GenderApplicator.cs index 4af0fa9cf..38b3157a8 100644 --- a/PKHeX.Core/Editing/Applicators/GenderApplicator.cs +++ b/PKHeX.Core/Editing/Applicators/GenderApplicator.cs @@ -13,9 +13,16 @@ public static class GenderApplicator /// Pokémon to modify. /// Desired value to set. /// Has special logic for an unspecified gender. - public static void SetSaneGender(this PKM pk, int gender) + public static void SetSaneGender(this PKM pk, byte gender) { - int g = gender == -1 ? pk.GetSaneGender() : gender; + var g = gender > 2 ? pk.GetSaneGender() : gender; + pk.SetGender(g); + } + + /// + public static void SetSaneGender(this PKM pk, byte? gender) + { + var g = gender ?? pk.GetSaneGender(); pk.SetGender(g); } @@ -24,9 +31,9 @@ public static void SetSaneGender(this PKM pk, int gender) /// /// Pokémon to modify. /// Desired value to set. - public static void SetGender(this PKM pk, int gender) + public static void SetGender(this PKM pk, byte gender) { - gender = Math.Clamp(gender, 0, 2); + gender = Math.Clamp(gender, (byte)0, (byte)2); if (pk.Gender == gender) return; @@ -50,7 +57,7 @@ public static void SetGender(this PKM pk, int gender) /// /// /// Most-legal value - public static int GetSaneGender(this PKM pk) + public static byte GetSaneGender(this PKM pk) { var gt = pk.PersonalInfo.Gender; switch (gt) @@ -69,7 +76,7 @@ public static int GetSaneGender(this PKM pk) /// /// Pokémon to modify. /// Desired . - public static void SetAttackIVFromGender(this PKM pk, int gender) + public static void SetAttackIVFromGender(this PKM pk, byte gender) { var rnd = Util.Rand; while (pk.Gender != gender) diff --git a/PKHeX.Core/Editing/Applicators/MemoryApplicator.cs b/PKHeX.Core/Editing/Applicators/MemoryApplicator.cs index bd5a00617..982066462 100644 --- a/PKHeX.Core/Editing/Applicators/MemoryApplicator.cs +++ b/PKHeX.Core/Editing/Applicators/MemoryApplicator.cs @@ -12,7 +12,7 @@ public static class MemoryApplicator public static void ClearMemories(this PKM pk) { if (pk is IAffection a) - a.OT_Affection = a.HT_Affection = 0; + a.OriginalTrainerAffection = a.HandlingTrainerAffection = 0; if (pk is IMemoryOT o) o.ClearMemoriesOT(); if (pk is IMemoryHT h) @@ -27,13 +27,13 @@ public static void SetHatchMemory6(this PKM pk) { if (pk is IMemoryOT o) { - o.OT_Memory = 2; - o.OT_Feeling = MemoryContext6.GetRandomFeeling6(2); - o.OT_Intensity = 1; - o.OT_TextVar = pk.XY ? (ushort)43 : (ushort)27; // riverside road : battling spot + o.OriginalTrainerMemory = 2; + o.OriginalTrainerMemoryFeeling = MemoryContext6.GetRandomFeeling6(2); + o.OriginalTrainerMemoryIntensity = 1; + o.OriginalTrainerMemoryVariable = pk.XY ? (ushort)43 : (ushort)27; // riverside road : battling spot } if (pk is IAffection a) - a.OT_Affection = 0; + a.OriginalTrainerAffection = 0; } /// @@ -44,8 +44,8 @@ public static void SetRandomMemory6(this PK6 pk) { // for lack of better randomization :) const byte memory = 63; // almost got lost when it explored a forest with {Trainer} - pk.OT_Memory = memory; - pk.OT_Feeling = MemoryContext6.GetRandomFeeling6(memory); - pk.OT_Intensity = MemoryContext6.MaxIntensity; + pk.OriginalTrainerMemory = memory; + pk.OriginalTrainerMemoryFeeling = MemoryContext6.GetRandomFeeling6(memory); + pk.OriginalTrainerMemoryIntensity = MemoryContext6.MaxIntensity; } } diff --git a/PKHeX.Core/Editing/Bulk/BatchEditing.cs b/PKHeX.Core/Editing/Bulk/BatchEditing.cs index 1098a0b4d..c3693fb95 100644 --- a/PKHeX.Core/Editing/Bulk/BatchEditing.cs +++ b/PKHeX.Core/Editing/Bulk/BatchEditing.cs @@ -500,9 +500,9 @@ private static ModifyResult SetByteArrayProperty(PKM pk, StringInstruction cmd) { switch (cmd.PropertyName) { - case nameof(PKM.Nickname_Trash): StringUtil.LoadHexBytesTo(cmd.PropertyValue.AsSpan(CONST_BYTES.Length), pk.Nickname_Trash, 3); return ModifyResult.Modified; - case nameof(PKM.OT_Trash): StringUtil.LoadHexBytesTo(cmd.PropertyValue.AsSpan(CONST_BYTES.Length), pk.OT_Trash, 3); return ModifyResult.Modified; - case nameof(PKM.HT_Trash): StringUtil.LoadHexBytesTo(cmd.PropertyValue.AsSpan(CONST_BYTES.Length), pk.HT_Trash, 3); return ModifyResult.Modified; + case nameof(PKM.NicknameTrash): StringUtil.LoadHexBytesTo(cmd.PropertyValue.AsSpan(CONST_BYTES.Length), pk.NicknameTrash, 3); return ModifyResult.Modified; + case nameof(PKM.OriginalTrainerTrash): StringUtil.LoadHexBytesTo(cmd.PropertyValue.AsSpan(CONST_BYTES.Length), pk.OriginalTrainerTrash, 3); return ModifyResult.Modified; + case nameof(PKM.HandlingTrainerTrash): StringUtil.LoadHexBytesTo(cmd.PropertyValue.AsSpan(CONST_BYTES.Length), pk.HandlingTrainerTrash, 3); return ModifyResult.Modified; default: return ModifyResult.Error; } diff --git a/PKHeX.Core/Editing/Bulk/BatchMods.cs b/PKHeX.Core/Editing/Bulk/BatchMods.cs index 409d987b8..72eb1bbc5 100644 --- a/PKHeX.Core/Editing/Bulk/BatchMods.cs +++ b/PKHeX.Core/Editing/Bulk/BatchMods.cs @@ -45,7 +45,7 @@ public static class BatchMods new ComplexSuggestion(PROP_EVS, (_, _, info) => BatchModifications.SetEVs(info.Entity)), new ComplexSuggestion(nameof(PKM.RelearnMoves), (_, value, info) => BatchModifications.SetSuggestedRelearnData(info, value)), new ComplexSuggestion(PROP_RIBBONS, (_, value, info) => BatchModifications.SetSuggestedRibbons(info, value)), - new ComplexSuggestion(nameof(PKM.Met_Location), (_, _, info) => BatchModifications.SetSuggestedMetData(info)), + new ComplexSuggestion(nameof(PKM.MetLocation), (_, _, info) => BatchModifications.SetSuggestedMetData(info)), new ComplexSuggestion(nameof(PKM.CurrentLevel), (_, _, info) => BatchModifications.SetMinimumCurrentLevel(info)), new ComplexSuggestion(PROP_CONTESTSTATS, p => p is IContestStats, (_, value, info) => BatchModifications.SetContestStats(info.Entity, info.Legality, value)), new ComplexSuggestion(PROP_MOVEMASTERY, (_, value, info) => BatchModifications.SetSuggestedMasteryData(info, value)), diff --git a/PKHeX.Core/Editing/Bulk/Suggestion/BatchModifications.cs b/PKHeX.Core/Editing/Bulk/Suggestion/BatchModifications.cs index fbc8f5c42..cc70d356f 100644 --- a/PKHeX.Core/Editing/Bulk/Suggestion/BatchModifications.cs +++ b/PKHeX.Core/Editing/Bulk/Suggestion/BatchModifications.cs @@ -92,12 +92,12 @@ public static ModifyResult SetSuggestedMetData(BatchInfo info) if (encounter == null) return ModifyResult.Error; - int level = encounter.LevelMin; - int location = encounter.Location; - int minimumLevel = EncounterSuggestion.GetLowestLevel(pk, encounter.LevelMin); + var location = encounter.Location; + var level = encounter.LevelMin; + var minimumLevel = EncounterSuggestion.GetLowestLevel(pk, level); - pk.Met_Level = level; - pk.Met_Location = location; + pk.MetLevel = level; + pk.MetLocation = location; pk.CurrentLevel = Math.Max(minimumLevel, level); return ModifyResult.Modified; diff --git a/PKHeX.Core/Editing/CommonEdits.cs b/PKHeX.Core/Editing/CommonEdits.cs index dd250ee0f..41b3d930a 100644 --- a/PKHeX.Core/Editing/CommonEdits.cs +++ b/PKHeX.Core/Editing/CommonEdits.cs @@ -8,7 +8,7 @@ namespace PKHeX.Core; public static class CommonEdits { /// - /// Setting which enables/disables automatic manipulation of when importing from a . + /// Setting which enables/disables automatic manipulation of when importing from a . /// public static bool ShowdownSetIVMarkings { get; set; } = true; @@ -51,12 +51,12 @@ public static string ClearNickname(this PKM pk) /// Sets the value by sanity checking the provided against the possible pool of abilities. /// /// Pokémon to modify. - /// Desired value to set. - public static void SetAbility(this PKM pk, int abil) + /// Desired value to set. + public static void SetAbility(this PKM pk, int abilityID) { - if (abil < 0) + if (abilityID < 0) return; - var index = pk.PersonalInfo.GetIndexOfAbility(abil); + var index = pk.PersonalInfo.GetIndexOfAbility(abilityID); index = Math.Max(0, index); pk.SetAbilityIndex(index); } @@ -82,7 +82,7 @@ public static void SetAbilityIndex(this PKM pk, int index) /// Pokémon to modify. public static void SetRandomEC(this PKM pk) { - int gen = pk.Generation; + var gen = pk.Generation; if (gen is 3 or 4 or 5) { pk.EncryptionConstant = pk.PID; @@ -109,7 +109,7 @@ public static bool SetShiny(PKM pk, Shiny type = Shiny.Random) if (pk.IsShiny && type.IsValid(pk)) return false; - if (type == Shiny.Random || pk.FatefulEncounter || pk.Version == (int)GameVersion.GO || pk.Format <= 2) + if (type == Shiny.Random || pk.FatefulEncounter || pk.Version == GameVersion.GO || pk.Format <= 2) { pk.SetShiny(); return true; @@ -140,16 +140,18 @@ public static bool SetUnshiny(this PKM pk) /// /// Pokémon to modify. /// Desired value to set. - public static void SetNature(this PKM pk, int nature) + public static void SetNature(this PKM pk, Nature nature) { - var value = Math.Clamp(nature, (int)Nature.Hardy, (int)Nature.Quirky); + if (!nature.IsFixed()) + nature = 0; // default valid + var format = pk.Format; if (format >= 8) - pk.StatNature = value; + pk.StatNature = nature; else if (format is 3 or 4) - pk.SetPIDNature(value); + pk.SetPIDNature(nature); else - pk.Nature = value; + pk.Nature = nature; } /// @@ -344,12 +346,12 @@ public static void ForceHatchPKM(this PKM pk, ITrainerInfo? tr = null, bool reHa pk.ClearNickname(); pk.CurrentFriendship = pk.PersonalInfo.BaseFriendship; if (pk.IsTradedEgg) - pk.Egg_Location = pk.Met_Location; + pk.EggLocation = pk.MetLocation; if (pk.Version == 0) - pk.Version = (int)EggStateLegality.GetEggHatchVersion(pk, (GameVersion)(tr?.Game ?? RecentTrainerCache.Game)); + pk.Version = EggStateLegality.GetEggHatchVersion(pk, tr?.Version ?? RecentTrainerCache.Version); var loc = EncounterSuggestion.GetSuggestedEggMetLocation(pk); - if (loc >= 0) - pk.Met_Location = loc; + if (loc != EncounterSuggestion.LocationNone) + pk.MetLocation = loc; if (pk.Format >= 4) pk.MetDate = EncounterDate.GetDate(pk.Context.GetConsole()); if (pk.Gen6) @@ -371,7 +373,7 @@ public static void SetEggMetData(this PKM pk, GameVersion origin, GameVersion de var date = EncounterDate.GetDate(console); var today = pk.MetDate = date; bool traded = origin != dest; - pk.Egg_Location = EncounterSuggestion.GetSuggestedEncounterEggLocationEgg(pk.Generation, origin, traded); + pk.EggLocation = EncounterSuggestion.GetSuggestedEncounterEggLocationEgg(pk.Generation, origin, traded); pk.EggMetDate = today; } @@ -382,7 +384,7 @@ public static void SetEggMetData(this PKM pk, GameVersion origin, GameVersion de public static void MaximizeFriendship(this PKM pk) { if (pk.IsEgg) - pk.OT_Friendship = 1; + pk.OriginalTrainerFriendship = 1; else pk.CurrentFriendship = byte.MaxValue; if (pk is ICombatPower pb) @@ -433,8 +435,8 @@ public static string GetLocationString(this PKM pk, bool eggmet) if (pk.Format < 2) return string.Empty; - int location = eggmet ? pk.Egg_Location : pk.Met_Location; - return GameInfo.GetLocationName(eggmet, location, pk.Format, pk.Generation, (GameVersion)pk.Version); + ushort location = eggmet ? pk.EggLocation : pk.MetLocation; + return GameInfo.GetLocationName(eggmet, location, pk.Format, pk.Generation, pk.Version); } /// diff --git a/PKHeX.Core/Editing/Database/TrainerDatabase.cs b/PKHeX.Core/Editing/Database/TrainerDatabase.cs index b7b4c3033..0f2a6e995 100644 --- a/PKHeX.Core/Editing/Database/TrainerDatabase.cs +++ b/PKHeX.Core/Editing/Database/TrainerDatabase.cs @@ -16,23 +16,15 @@ public sealed class TrainerDatabase /// Version the trainer should originate from /// Language to request for /// Null if no trainer found for this version. - public ITrainerInfo? GetTrainer(int version, LanguageID? language = null) => GetTrainer((GameVersion)version, language); - - /// - /// Fetches an appropriate trainer based on the requested . - /// - /// Version the trainer should originate from - /// Language to request for - /// Null if no trainer found for this version. - public ITrainerInfo? GetTrainer(GameVersion ver, LanguageID? language = null) + public ITrainerInfo? GetTrainer(GameVersion version, LanguageID? language = null) { - if (ver <= 0) + if (version <= 0) return null; - if (!ver.IsValidSavedVersion()) - return GetTrainerFromGroup(ver, language); + if (!version.IsValidSavedVersion()) + return GetTrainerFromGroup(version, language); - if (Database.TryGetValue(ver, out var list)) + if (Database.TryGetValue(version, out var list)) return GetRandomChoice(list); return null; @@ -46,14 +38,14 @@ private static T GetRandomChoice(IReadOnlyList list) } /// - /// Fetches an appropriate trainer based on the requested group. + /// Fetches an appropriate trainer based on the requested group. /// - /// Version the trainer should originate from + /// Version the trainer should originate from /// Language to request for /// Null if no trainer found for this version. - private ITrainerInfo? GetTrainerFromGroup(GameVersion ver, LanguageID? lang = null) + private ITrainerInfo? GetTrainerFromGroup(GameVersion version, LanguageID? lang = null) { - var possible = Database.Where(z => ver.Contains(z.Key)).ToList(); + var possible = Database.Where(z => version.Contains(z.Key)).ToList(); if (lang != null) { possible = possible.Select(z => @@ -71,7 +63,7 @@ private static T GetRandomChoice(IReadOnlyList list) /// Generation the trainer should inhabit /// Language to request for /// Null if no trainer found for this version. - public ITrainerInfo? GetTrainerFromGen(int generation, LanguageID? lang = null) + public ITrainerInfo? GetTrainerFromGen(byte generation, LanguageID? lang = null) { var possible = Database.Where(z => z.Key.GetGeneration() == generation).ToList(); if (lang != null) @@ -99,12 +91,10 @@ private static T GetRandomChoice(IReadOnlyList list) /// Trainer details to add. public void Register(ITrainerInfo trainer) { - var ver = (GameVersion)trainer.Game; - if (ver <= 0 && trainer is SaveFile s) - ver = s.Version; - if (!Database.TryGetValue(ver, out var list)) + var version = trainer.Version; + if (!Database.TryGetValue(version, out var list)) { - Database.Add(ver, [trainer]); + Database.Add(version, [trainer]); return; } @@ -129,9 +119,9 @@ public void Register(ITrainerInfo trainer) private static SimpleTrainerInfo GetTrainerReference(PKM pk) { - var result = new SimpleTrainerInfo((GameVersion)pk.Version) + var result = new SimpleTrainerInfo(pk.Version) { - TID16 = pk.TID16, SID16 = pk.SID16, OT = pk.OT_Name, Gender = pk.OT_Gender, + TID16 = pk.TID16, SID16 = pk.SID16, OT = pk.OriginalTrainerName, Gender = pk.OriginalTrainerGender, Language = pk.Language, Generation = pk.Generation, }; diff --git a/PKHeX.Core/Editing/HiddenPower.cs b/PKHeX.Core/Editing/HiddenPower.cs index db69228ca..bf403735e 100644 --- a/PKHeX.Core/Editing/HiddenPower.cs +++ b/PKHeX.Core/Editing/HiddenPower.cs @@ -310,4 +310,13 @@ public static uint SetIVsBigEndian(int type, uint ivs) 0b111101, // Dragon 0b111111, // Dark ]; + + /// + /// Gets the suggested low-bits for the input Hidden Power Type + /// + public static byte GetLowBits(int type) + { + var arr = DefaultLowBits; + return (uint)type < arr.Length ? arr[type] : (byte)0; + } } diff --git a/PKHeX.Core/Editing/IBattleTemplate.cs b/PKHeX.Core/Editing/IBattleTemplate.cs index d0de644c4..1fa1577e1 100644 --- a/PKHeX.Core/Editing/IBattleTemplate.cs +++ b/PKHeX.Core/Editing/IBattleTemplate.cs @@ -18,7 +18,7 @@ public interface IBattleTemplate : ISpeciesForm, IGigantamaxReadOnly, IDynamaxLe /// /// name of the Set entity. /// - int Gender { get; } + byte? Gender { get; } /// /// of the Set entity. @@ -33,7 +33,7 @@ public interface IBattleTemplate : ISpeciesForm, IGigantamaxReadOnly, IDynamaxLe /// /// of the Set entity. /// - int Level { get; } + byte Level { get; } /// /// of the Set entity. @@ -43,7 +43,7 @@ public interface IBattleTemplate : ISpeciesForm, IGigantamaxReadOnly, IDynamaxLe /// /// of the Set entity. /// - int Friendship { get; } + byte Friendship { get; } /// /// name of the Set entity, stored in PKHeX style (instead of Showdown's) diff --git a/PKHeX.Core/Editing/ISpriteBuilder.cs b/PKHeX.Core/Editing/ISpriteBuilder.cs index aa111debd..01c283aac 100644 --- a/PKHeX.Core/Editing/ISpriteBuilder.cs +++ b/PKHeX.Core/Editing/ISpriteBuilder.cs @@ -9,7 +9,7 @@ public interface ISpriteBuilder /// /// Gets a sprite using the requested parameters. /// - T GetSprite(ushort species, byte form, int gender, uint formarg, int heldItem, bool isEgg, Shiny shiny, + T GetSprite(ushort species, byte form, byte gender, uint formarg, int heldItem, bool isEgg, Shiny shiny, EntityContext context = EntityContext.None); /// diff --git a/PKHeX.Core/Editing/LocationEdits.cs b/PKHeX.Core/Editing/LocationEdits.cs index 5af3fb7b0..474d7e9aa 100644 --- a/PKHeX.Core/Editing/LocationEdits.cs +++ b/PKHeX.Core/Editing/LocationEdits.cs @@ -8,12 +8,12 @@ public static class LocationEdits /// /// Gets the "None" location index for a specific context. /// - public static int GetNoneLocation(PKM pk) => GetNoneLocation(pk.Context); + public static ushort GetNoneLocation(PKM pk) => GetNoneLocation(pk.Context); /// /// Gets the "None" location index for a specific context. /// - public static int GetNoneLocation(EntityContext context) => context switch + public static ushort GetNoneLocation(EntityContext context) => context switch { EntityContext.Gen8b => Locations.Default8bNone, _ => 0, diff --git a/PKHeX.Core/Editing/NatureAmp.cs b/PKHeX.Core/Editing/NatureAmp.cs index f093afe8b..c74c22ddc 100644 --- a/PKHeX.Core/Editing/NatureAmp.cs +++ b/PKHeX.Core/Editing/NatureAmp.cs @@ -15,18 +15,18 @@ public static class NatureAmp /// Stat Index to mutate /// Current nature to derive the current amps from /// New nature value - public static int GetNewNature(this NatureAmpRequest type, int statIndex, int currentNature) + public static Nature GetNewNature(this NatureAmpRequest type, int statIndex, Nature currentNature) { - if (currentNature >= NatureCount) - return -1; + if ((uint)currentNature >= NatureCount) + return Nature.Random; var (up, dn) = GetNatureModification(currentNature); return GetNewNature(type, statIndex, up, dn); } - /// - public static int GetNewNature(NatureAmpRequest type, int statIndex, int up, int dn) + /// + public static Nature GetNewNature(NatureAmpRequest type, int statIndex, int up, int dn) { // switch (type) @@ -41,7 +41,7 @@ public static int GetNewNature(NatureAmpRequest type, int statIndex, int up, int up = dn = statIndex; break; default: - return -1; // failure + return Nature.Random; // failure } return CreateNatureFromAmps(up, dn); @@ -53,20 +53,20 @@ public static int GetNewNature(NatureAmpRequest type, int statIndex, int up, int /// Increased stat /// Decreased stat /// Nature - public static int CreateNatureFromAmps(int up, int dn) + public static Nature CreateNatureFromAmps(int up, int dn) { if ((uint)up > 5 || (uint)dn > 5) - return -1; - return (up * 5) + dn; + return Nature.Random; + return (Nature)((up * 5) + dn); } /// /// Decompose the nature to the two stat indexes that are modified /// - public static (int up, int dn) GetNatureModification(int nature) + public static (int up, int dn) GetNatureModification(Nature nature) { - var up = (nature / 5); - var dn = (nature % 5); + var up = ((byte)nature / 5); + var dn = ((byte)nature % 5); return (up, dn); } @@ -77,13 +77,13 @@ public static (int up, int dn) GetNatureModification(int nature) /// Increased stat /// Decreased stat /// True if nature modification values are equal or the Nature is out of range. - public static bool IsNeutralOrInvalid(int nature, int up, int dn) + public static bool IsNeutralOrInvalid(Nature nature, int up, int dn) { - return up == dn || nature >= 25; // invalid + return up == dn || (byte)nature >= 25; // invalid } - /// - public static bool IsNeutralOrInvalid(int nature) + /// + public static bool IsNeutralOrInvalid(Nature nature) { var (up, dn) = GetNatureModification(nature); return IsNeutralOrInvalid(nature, up, dn); @@ -94,7 +94,7 @@ public static bool IsNeutralOrInvalid(int nature) /// /// Current stats to amplify if appropriate /// Nature - public static void ModifyStatsForNature(Span stats, int nature) + public static void ModifyStatsForNature(Span stats, Nature nature) { var (up, dn) = GetNatureModification(nature); if (IsNeutralOrInvalid(nature, up, dn)) @@ -139,17 +139,17 @@ public static void ModifyStatsForNature(Span stats, int nature) 0, 0, 0, 0, 0, // Quirky ]; - private const int NatureCount = 25; + private const byte NatureCount = 25; private const int AmpWidth = 5; - public static int AmplifyStat(int nature, int index, int initial) => GetNatureAmp(nature, index) switch + public static int AmplifyStat(Nature nature, int index, int initial) => GetNatureAmp(nature, index) switch { 1 => 110 * initial / 100, // 110% -1 => 90 * initial / 100, // 90% _ => initial, }; - private static sbyte GetNatureAmp(int nature, int index) + private static sbyte GetNatureAmp(Nature nature, int index) { if ((uint)nature >= NatureCount) return -1; @@ -157,11 +157,11 @@ private static sbyte GetNatureAmp(int nature, int index) return amps[index]; } - public static ReadOnlySpan GetAmps(int nature) + public static ReadOnlySpan GetAmps(Nature nature) { if ((uint)nature >= NatureCount) nature = 0; - return Table.Slice(AmpWidth * nature, AmpWidth); + return Table.Slice(AmpWidth * (byte)nature, AmpWidth); } } diff --git a/PKHeX.Core/Editing/PKM/EntitySuggestionUtil.cs b/PKHeX.Core/Editing/PKM/EntitySuggestionUtil.cs index a399fb7d6..595ccd0d4 100644 --- a/PKHeX.Core/Editing/PKM/EntitySuggestionUtil.cs +++ b/PKHeX.Core/Editing/PKM/EntitySuggestionUtil.cs @@ -9,12 +9,12 @@ namespace PKHeX.Core; /// public static class EntitySuggestionUtil { - public static List GetMetLocationSuggestionMessage(PKM pk, int level, int location, int minimumLevel, IEncounterable? enc) + public static List GetMetLocationSuggestionMessage(PKM pk, int level, ushort location, int minimumLevel, IEncounterable? enc) { var suggestion = new List { MsgPKMSuggestionStart }; if (pk.Format >= 3) { - var metList = GameInfo.GetLocationList((GameVersion)pk.Version, pk.Context, egg: false); + var metList = GameInfo.GetLocationList(pk.Version, pk.Context, egg: false); var locationName = metList.First(loc => loc.Value == location).Text; suggestion.Add($"{MsgPKMSuggestionMetLocation} {locationName}"); suggestion.Add($"{MsgPKMSuggestionMetLevel} {level}"); diff --git a/PKHeX.Core/Editing/PKM/EntitySummary.cs b/PKHeX.Core/Editing/PKM/EntitySummary.cs index a1f565716..9db6bac9b 100644 --- a/PKHeX.Core/Editing/PKM/EntitySummary.cs +++ b/PKHeX.Core/Editing/PKM/EntitySummary.cs @@ -19,7 +19,7 @@ public class EntitySummary : IFatefulEncounterReadOnly // do NOT seal, allow inh public virtual string Position => "???"; public string Nickname => pk.Nickname; public string Species => Get(Strings.specieslist, pk.Species); - public string Nature => Get(Strings.natures, pk.StatNature); + public string Nature => Get(Strings.natures, (byte)pk.StatNature); public string Gender => Get(GenderSymbols, pk.Gender); public string ESV => pk.PSV.ToString("0000"); public string HP_Type => Get(Strings.types, pk.HPType + 1); @@ -38,44 +38,44 @@ public class EntitySummary : IFatefulEncounterReadOnly // do NOT seal, allow inh public string MetLoc => pk.GetLocationString(eggmet: false); public string EggLoc => pk.GetLocationString(eggmet: true); public string Ball => Get(Strings.balllist, pk.Ball); - public string OT => pk.OT_Name; - public string Version => Get(Strings.gamelist, pk.Version); + public string OT => pk.OriginalTrainerName; + public string Version => Get(Strings.gamelist, (int)pk.Version); public string OTLang => ((LanguageID)pk.Language).ToString(); public string Legal { get { var la = new LegalityAnalysis(pk); return la.Parsed ? la.Valid.ToString() : "-"; } } #region Extraneous public string EC => pk.EncryptionConstant.ToString("X8"); public string PID => pk.PID.ToString("X8"); - public int HP_IV => pk.IV_HP; - public int ATK_IV => pk.IV_ATK; - public int DEF_IV => pk.IV_DEF; - public int SPA_IV => pk.IV_SPA; - public int SPD_IV => pk.IV_SPD; - public int SPE_IV => pk.IV_SPE; + public int IV_HP => pk.IV_HP; + public int IV_ATK => pk.IV_ATK; + public int IV_DEF => pk.IV_DEF; + public int IV_SPA => pk.IV_SPA; + public int IV_SPD => pk.IV_SPD; + public int IV_SPE => pk.IV_SPE; public uint EXP => pk.EXP; public int Level => pk.CurrentLevel; - public int HP_EV => pk.EV_HP; - public int ATK_EV => pk.EV_ATK; - public int DEF_EV => pk.EV_DEF; - public int SPA_EV => pk.EV_SPA; - public int SPD_EV => pk.EV_SPD; - public int SPE_EV => pk.EV_SPE; - public int Cool => pk is IContestStatsReadOnly s ? s.CNT_Cool : 0; - public int Beauty => pk is IContestStatsReadOnly s ? s.CNT_Beauty : 0; - public int Cute => pk is IContestStatsReadOnly s ? s.CNT_Cute : 0; - public int Smart => pk is IContestStatsReadOnly s ? s.CNT_Smart : 0; - public int Tough => pk is IContestStatsReadOnly s ? s.CNT_Tough : 0; - public int Sheen => pk is IContestStatsReadOnly s ? s.CNT_Sheen : 0; + public int EV_HP => pk.EV_HP; + public int EV_ATK => pk.EV_ATK; + public int EV_DEF => pk.EV_DEF; + public int EV_SPA => pk.EV_SPA; + public int EV_SPD => pk.EV_SPD; + public int EV_SPE => pk.EV_SPE; + public int Cool => pk is IContestStatsReadOnly s ? s.ContestCool : 0; + public int Beauty => pk is IContestStatsReadOnly s ? s.ContestBeauty : 0; + public int Cute => pk is IContestStatsReadOnly s ? s.ContestCute : 0; + public int Smart => pk is IContestStatsReadOnly s ? s.ContestSmart : 0; + public int Tough => pk is IContestStatsReadOnly s ? s.ContestTough : 0; + public int Sheen => pk is IContestStatsReadOnly s ? s.ContestSheen : 0; - public string NotOT => pk.Format > 5 ? pk.HT_Name : "N/A"; + public string NotOT => pk.Format > 5 ? pk.HandlingTrainerName : "N/A"; public int AbilityNum => pk.Format > 5 ? pk.AbilityNumber : -1; - public int GenderFlag => pk.Gender; + public byte GenderFlag => pk.Gender; public byte Form => pk.Form; - public int PKRS_Strain => pk.PKRS_Strain; - public int PKRS_Days => pk.PKRS_Days; - public int MetLevel => pk.Met_Level; - public int OT_Gender => pk.OT_Gender; + public int PokerusStrain => pk.PokerusStrain; + public int PokerusDays => pk.PokerusDays; + public int MetLevel => pk.MetLevel; + public byte OriginalTrainerGender => pk.OriginalTrainerGender; public bool FatefulEncounter => pk.FatefulEncounter; public bool IsEgg => pk.IsEgg; @@ -98,13 +98,13 @@ public class EntitySummary : IFatefulEncounterReadOnly // do NOT seal, allow inh public string Relearn3 => Get(Strings.movelist, pk.RelearnMove3); public string Relearn4 => Get(Strings.movelist, pk.RelearnMove4); public ushort Checksum => pk is ISanityChecksum s ? s.Checksum : Checksums.CRC16_CCITT(pk.Data.AsSpan(pk.SIZE_STORED)); - public int Friendship => pk.OT_Friendship; - public int Egg_Year => pk.EggMetDate.GetValueOrDefault().Year; - public int Egg_Month => pk.EggMetDate.GetValueOrDefault().Month; - public int Egg_Day => pk.EggMetDate.GetValueOrDefault().Day; - public int Met_Year => pk.MetDate.GetValueOrDefault().Year; - public int Met_Month => pk.MetDate.GetValueOrDefault().Month; - public int Met_Day => pk.MetDate.GetValueOrDefault().Day; + public int Friendship => pk.OriginalTrainerFriendship; + public int EggYear => pk.EggMetDate.GetValueOrDefault().Year; + public int EggMonth => pk.EggMetDate.GetValueOrDefault().Month; + public int EggDay => pk.EggMetDate.GetValueOrDefault().Day; + public int MetYear => pk.MetDate.GetValueOrDefault().Year; + public int MetMonth => pk.MetDate.GetValueOrDefault().Month; + public int MetDay => pk.MetDate.GetValueOrDefault().Day; #endregion diff --git a/PKHeX.Core/Editing/PKM/EntityTemplates.cs b/PKHeX.Core/Editing/PKM/EntityTemplates.cs index 50a0459fb..7ba11565c 100644 --- a/PKHeX.Core/Editing/PKM/EntityTemplates.cs +++ b/PKHeX.Core/Editing/PKM/EntityTemplates.cs @@ -25,8 +25,8 @@ public static void TemplateFields(PKM pk, ITrainerInfo tr) pk.ClearNickname(); - pk.OT_Name = tr.OT; - pk.OT_Gender = tr.Gender; + pk.OriginalTrainerName = tr.OT; + pk.OriginalTrainerGender = tr.Gender; pk.ID32 = tr.ID32; if (tr is IRegionOrigin o && pk is IRegionOrigin gt) { @@ -39,22 +39,14 @@ public static void TemplateFields(PKM pk, ITrainerInfo tr) pk.RefreshChecksum(); } - private static int GetTemplateVersion(ITrainerInfo tr) + private static GameVersion GetTemplateVersion(ITrainerInfo tr) { - GameVersion version = (GameVersion)tr.Game; + var version = tr.Version; if (version.IsValidSavedVersion()) - return (int)version; - - if (tr is IVersion v) - { - version = v.Version; - if (version.IsValidSavedVersion()) - return (int)version; - version = v.GetSingleVersion(); - if (version.IsValidSavedVersion()) - return (int)version; - } - + return version; + version = version.GetSingleVersion(); + if (version.IsValidSavedVersion()) + return version; return default; // 0 } @@ -66,17 +58,17 @@ private static void ApplyTrashBytes(PKM pk, ITrainerInfo tr) switch (tr) { case SAV1 s1: - s1.OT_Trash.CopyTo(pk12.OT_Trash); + s1.OriginalTrainerTrash.CopyTo(pk12.OriginalTrainerTrash); break; case SAV2 s2: - s2.OT_Trash.CopyTo(pk12.OT_Trash); + s2.OriginalTrainerTrash.CopyTo(pk12.OriginalTrainerTrash); break; } } private static ushort GetTemplateSpecies(PKM pk, ITrainerInfo tr) { - ushort species = tr is IGameValueLimit s ? s.MaxSpeciesID : ((GameVersion)pk.Version).GetMaxSpeciesID(); + ushort species = tr is IGameValueLimit s ? s.MaxSpeciesID : pk.Version.GetMaxSpeciesID(); if (species == 0) species = pk.MaxSpeciesID; return species; diff --git a/PKHeX.Core/Editing/PKM/QR/QRMessageUtil.cs b/PKHeX.Core/Editing/PKM/QR/QRMessageUtil.cs index b19a37d26..0e50efe8f 100644 --- a/PKHeX.Core/Editing/PKM/QR/QRMessageUtil.cs +++ b/PKHeX.Core/Editing/PKM/QR/QRMessageUtil.cs @@ -12,8 +12,8 @@ public static class QRMessageUtil private const string QR6PathBad = "null/#"; private const string QR6Path = "http://lunarcookies.github.io/b1s1.html#"; private const string QR6PathWC = "http://lunarcookies.github.io/wc.html#"; - private static string GetExploitURLPrefixPKM(int format) => format == 6 ? QR6Path : QR6PathBad; - private static string GetExploitURLPrefixWC(int format) => format == 6 ? QR6PathWC : QR6PathBad; + private static string GetExploitURLPrefixPKM(byte format) => format == 6 ? QR6Path : QR6PathBad; + private static string GetExploitURLPrefixWC(byte format) => format == 6 ? QR6PathWC : QR6PathBad; /// /// Gets the data from the message that is encoded in a QR. diff --git a/PKHeX.Core/Editing/PKM/QR/QRPK7.cs b/PKHeX.Core/Editing/PKM/QR/QRPK7.cs index 865e13755..9e244fcbb 100644 --- a/PKHeX.Core/Editing/PKM/QR/QRPK7.cs +++ b/PKHeX.Core/Editing/PKM/QR/QRPK7.cs @@ -10,25 +10,24 @@ public sealed class QRPK7(byte[] Data) : IEncounterInfo { private readonly byte[] Data = (byte[])Data.Clone(); - public GameVersion Version => (GameVersion)CassetteVersion; public bool EggEncounter => false; public byte LevelMin => Level; public byte LevelMax => Level; - public int Generation => Version.GetGeneration(); + public byte Generation => Version.GetGeneration(); public EntityContext Context => EntityContext.Gen7; public bool IsShiny => false; public const int SIZE = 0x30; public uint EncryptionConstant => ReadUInt32LittleEndian(Data.AsSpan(0)); - public byte HT_Flags => Data[4]; - public int Unk_5 => Data[5]; - public int Unk_6 => Data[6]; - public int Unk_7 => Data[7]; - public int Move1_PPUps => Data[8]; - public int Move2_PPUps => Data[9]; - public int Move3_PPUps => Data[0xA]; - public int Move4_PPUps => Data[0xB]; + public byte HyperTrainFlags => Data[4]; + public byte Unk_5 => Data[5]; + public byte Unk_6 => Data[6]; + public byte Unk_7 => Data[7]; + public byte Move1_PPUps => Data[8]; + public byte Move2_PPUps => Data[9]; + public byte Move3_PPUps => Data[0xA]; + public byte Move4_PPUps => Data[0xB]; public uint IV32 { get => ReadUInt32LittleEndian(Data.AsSpan(0xC)); set => WriteUInt32LittleEndian(Data.AsSpan(0xC), value); } public int IV_HP { get => (int)(IV32 >> 00) & 0x1F; set => IV32 = (IV32 & ~(0x1Fu << 00)) | (uint)((value > 31 ? 31 : value) << 00); } public int IV_ATK { get => (int)(IV32 >> 05) & 0x1F; set => IV32 = (IV32 & ~(0x1Fu << 05)) | (uint)((value > 31 ? 31 : value) << 05); } @@ -43,11 +42,11 @@ public sealed class QRPK7(byte[] Data) : IEncounterInfo public ushort Move2 => ReadUInt16LittleEndian(Data.AsSpan(0x1A)); public ushort Move3 => ReadUInt16LittleEndian(Data.AsSpan(0x1C)); public ushort Move4 => ReadUInt16LittleEndian(Data.AsSpan(0x1E)); - public int Unk_20 => Data[0x20]; - public int AbilityIndex => Data[0x21]; - public int Nature => Data[0x22]; + public byte Unk_20 => Data[0x20]; + public byte AbilityIndex => Data[0x21]; + public Nature Nature => (Nature)Data[0x22]; public bool FatefulEncounter => (Data[0x23] & 1) == 1; - public int Gender => (Data[0x23] >> 1) & 3; + public byte Gender => (byte)((Data[0x23] >> 1) & 3); public byte Form => (byte)(Data[0x23] >> 3); public byte EV_HP => Data[0x24]; public byte EV_ATK => Data[0x25]; @@ -55,12 +54,12 @@ public sealed class QRPK7(byte[] Data) : IEncounterInfo public byte EV_SPE => Data[0x27]; public byte EV_SPA => Data[0x28]; public byte EV_SPD => Data[0x29]; - public int Unk_2A => Data[0x2A]; - public int Friendship => Data[0x2B]; - public int Ball => Data[0x2C]; + public byte Unk_2A => Data[0x2A]; + public byte Friendship => Data[0x2B]; + public byte Ball => Data[0x2C]; public byte Level => Data[0x2D]; - public int CassetteVersion => Data[0x2E]; - public int Language => Data[0x2F]; + public GameVersion Version => (GameVersion)Data[0x2E]; + public byte Language => Data[0x2F]; /// /// Converts the to a rough PKM. @@ -82,7 +81,7 @@ public PKM ConvertToPKM(ITrainerInfo tr, EncounterCriteria criteria) Nature = Nature, FatefulEncounter = FatefulEncounter, Form = Form, - HyperTrainFlags = HT_Flags, + HyperTrainFlags = HyperTrainFlags, IV_HP = IV_HP, IV_ATK = IV_ATK, IV_DEF = IV_DEF, @@ -104,15 +103,15 @@ public PKM ConvertToPKM(ITrainerInfo tr, EncounterCriteria criteria) Move3_PPUps = Move3_PPUps, Move4_PPUps = Move4_PPUps, HeldItem = HeldItem, - HT_Friendship = Friendship, - OT_Friendship = Friendship, + HandlingTrainerFriendship = Friendship, + OriginalTrainerFriendship = Friendship, Ball = Ball, - Version = CassetteVersion, + Version = Version, - OT_Name = tr.OT, - HT_Name = tr.OT, + OriginalTrainerName = tr.OT, + HandlingTrainerName = tr.OT, CurrentLevel = Level, - Met_Level = Level, + MetLevel = Level, MetDate = EncounterDate.GetDate3DS(), }; RecentTrainerCache.SetConsoleRegionData3DS(pk, tr); diff --git a/PKHeX.Core/Editing/PKM/QR/QRPKM.cs b/PKHeX.Core/Editing/PKM/QR/QRPKM.cs index 578a57114..4f523e193 100644 --- a/PKHeX.Core/Editing/PKM/QR/QRPKM.cs +++ b/PKHeX.Core/Editing/PKM/QR/QRPKM.cs @@ -68,6 +68,6 @@ private static IEnumerable GetHeader(PKM pk, GameStrings s) } if (pk.Format >= 3 && (uint)pk.Nature < s.Natures.Count) - yield return s.natures[pk.Nature]; + yield return s.natures[(byte)pk.Nature]; } } diff --git a/PKHeX.Core/Editing/Pokerus.cs b/PKHeX.Core/Editing/Pokerus.cs index 12e33292b..5d40f4fc8 100644 --- a/PKHeX.Core/Editing/Pokerus.cs +++ b/PKHeX.Core/Editing/Pokerus.cs @@ -112,7 +112,7 @@ public static bool IsDurationValid(int strain, int days, out int max) /// Overwrites all Pokérus values even if already legal. public static void Vaccinate(this PKM pk) { - pk.PKRS_Strain = IsObtainable(pk) ? 1 : 0; - pk.PKRS_Days = 0; + pk.PokerusStrain = IsObtainable(pk) ? 1 : 0; + pk.PokerusDays = 0; } } diff --git a/PKHeX.Core/Editing/Program/StartupArguments.cs b/PKHeX.Core/Editing/Program/StartupArguments.cs index a154aac59..b131c4330 100644 --- a/PKHeX.Core/Editing/Program/StartupArguments.cs +++ b/PKHeX.Core/Editing/Program/StartupArguments.cs @@ -90,11 +90,11 @@ public void ReadTemplateIfNoEntity(string path) private static SaveFile GetBlank(PKM pk) { var ctx = pk.Context; - var ver = ctx.GetSingleGameVersion(); + var version = ctx.GetSingleGameVersion(); if (pk is { Format: 1, Japanese: true }) - ver = GameVersion.BU; + version = GameVersion.BU; - return SaveUtil.GetBlankSAV(ver, pk.OT_Name, (LanguageID)pk.Language); + return SaveUtil.GetBlankSAV(version, pk.OriginalTrainerName, (LanguageID)pk.Language); } private static SaveFile GetBlankSaveFile(GameVersion version, SaveFile? current) @@ -105,8 +105,8 @@ private static SaveFile GetBlankSaveFile(GameVersion version, SaveFile? current) if (sav.Version == GameVersion.Invalid) // will fail to load { var max = GameInfo.VersionDataSource.MaxBy(z => z.Value) ?? throw new Exception(); - var ver = (GameVersion)max.Value; - sav = SaveUtil.GetBlankSAV(ver, tr, lang); + var maxVer = (GameVersion)max.Value; + sav = SaveUtil.GetBlankSAV(maxVer, tr, lang); } return sav; } diff --git a/PKHeX.Core/Editing/Saves/BoxManip/BoxManipDefaults.cs b/PKHeX.Core/Editing/Saves/BoxManip/BoxManipDefaults.cs index e9e68a19e..b887c5252 100644 --- a/PKHeX.Core/Editing/Saves/BoxManip/BoxManipDefaults.cs +++ b/PKHeX.Core/Editing/Saves/BoxManip/BoxManipDefaults.cs @@ -37,7 +37,7 @@ public static class BoxManipDefaults new BoxManipSortComplex(SortOwner, (list, sav) => list.OrderByOwnership(sav)), new BoxManipSort(SortType, list => list.OrderByCustom(pk => pk.PersonalInfo.Type1, pk => pk.PersonalInfo.Type2)), new BoxManipSort(SortTypeTera, list => list.OrderByCustom(pk => ((ITeraType)pk).GetTeraType()), s => s.BlankPKM is ITeraType), - new BoxManipSort(SortVersion, list => list.OrderByCustom(pk => pk.Generation, pk => pk.Version, pk => pk.Met_Location), s => s.Generation >= 3), + new BoxManipSort(SortVersion, list => list.OrderByCustom(pk => pk.Generation, pk => pk.Version, pk => pk.MetLocation), s => s.Generation >= 3), new BoxManipSort(SortBST, list => list.OrderByCustom(pk => pk.PersonalInfo.GetBaseStatTotal())), new BoxManipSort(SortCP, list => list.OrderByCustom(pk => pk is PB7 pb7 ? pb7.Stat_CP : 0), s => s is SAV7b), new BoxManipSort(SortScale, list => list.OrderByCustom(pk => pk is IScaledSize3 s3 ? s3.Scale : -1), s => s.BlankPKM is IScaledSize3), diff --git a/PKHeX.Core/Editing/Saves/Editors/EventOld/EventWorkspace.cs b/PKHeX.Core/Editing/Saves/Editors/EventOld/EventWorkspace.cs index a300169dc..85e1f0bd8 100644 --- a/PKHeX.Core/Editing/Saves/Editors/EventOld/EventWorkspace.cs +++ b/PKHeX.Core/Editing/Saves/Editors/EventOld/EventWorkspace.cs @@ -28,7 +28,7 @@ public void Save() s7.UpdateMagearnaConstant(); } - private static string GetResourceSuffix(TSave ver) => GetVersion(ver) switch + private static string GetResourceSuffix(TSave version) => GetVersion(version) switch { X or Y or XY => "xy", OR or AS or ORAS => "oras", @@ -44,12 +44,12 @@ public void Save() FR or LG or FRLG => "frlg", C => "c", GD or SI or GS => "gs", - _ => throw new ArgumentOutOfRangeException(nameof(ver), ver, null), + _ => throw new ArgumentOutOfRangeException(nameof(version), version, null), }; - private static GameVersion GetVersion(TSave ver) + private static GameVersion GetVersion(TSave version) { - if (ver is IVersion v) + if (version is IVersion v) return v.Version; return Invalid; } diff --git a/PKHeX.Core/Editing/Saves/Editors/FakeSaveFile.cs b/PKHeX.Core/Editing/Saves/Editors/FakeSaveFile.cs index 48cdc1e77..0144cfc66 100644 --- a/PKHeX.Core/Editing/Saves/Editors/FakeSaveFile.cs +++ b/PKHeX.Core/Editing/Saves/Editors/FakeSaveFile.cs @@ -10,7 +10,7 @@ public sealed class FakeSaveFile : SaveFile public override string Extension => string.Empty; public override bool ChecksumsValid => true; public override string ChecksumInfo => string.Empty; - public override int Generation => 3; + public override byte Generation => 3; public override string GetString(ReadOnlySpan data) => string.Empty; public override int SetString(Span destBuffer, ReadOnlySpan value, int maxLength, StringConverterOption option) => 0; public override PersonalTable3 Personal => PersonalTable.RS; @@ -25,7 +25,7 @@ public sealed class FakeSaveFile : SaveFile public override ushort MaxSpeciesID => 1; public override int MaxItemID => 5; public override int MaxBallID => 5; - public override int MaxGameID => 5; + public override GameVersion MaxGameID => GameVersion.LG; public override int MaxAbilityID => 0; public override int BoxCount => 1; public override int GetPartyOffset(int slot) => -1; diff --git a/PKHeX.Core/Editing/Showdown/ShowdownSet.cs b/PKHeX.Core/Editing/Showdown/ShowdownSet.cs index 3136be7d9..92ee3abc4 100644 --- a/PKHeX.Core/Editing/Showdown/ShowdownSet.cs +++ b/PKHeX.Core/Editing/Showdown/ShowdownSet.cs @@ -35,7 +35,7 @@ public sealed class ShowdownSet : IBattleTemplate public string Nickname { get; private set; } = string.Empty; /// - public int Gender { get; private set; } = -1; + public byte? Gender { get; private set; } /// public int HeldItem { get; private set; } @@ -44,16 +44,16 @@ public sealed class ShowdownSet : IBattleTemplate public int Ability { get; private set; } = -1; /// - public int Level { get; private set; } = 100; + public byte Level { get; private set; } = 100; /// public bool Shiny { get; private set; } /// - public int Friendship { get; private set; } = 255; + public byte Friendship { get; private set; } = 255; /// - public int Nature { get; private set; } = -1; + public Nature Nature { get; private set; } = Nature.Random; /// public string FormName { get; private set; } = string.Empty; @@ -254,14 +254,14 @@ private bool ParseSingle(ReadOnlySpan identifier) var firstSpace = identifier.IndexOf(' '); if (firstSpace == -1) return false; - var naturestr = identifier[..firstSpace]; - return (Nature = StringUtil.FindIndexIgnoreCase(Strings.natures, naturestr)) >= 0; + var nature = identifier[..firstSpace]; + return (Nature = (Nature)StringUtil.FindIndexIgnoreCase(Strings.natures, nature)).IsFixed(); } private bool ParseEntry(ReadOnlySpan identifier, ReadOnlySpan value) => identifier switch { "Ability" => (Ability = StringUtil.FindIndexIgnoreCase(Strings.abilitylist, value)) >= 0, - "Nature" => (Nature = StringUtil.FindIndexIgnoreCase(Strings.natures , value)) >= 0, + "Nature" => (Nature = (Nature)StringUtil.FindIndexIgnoreCase(Strings.natures , value)).IsFixed(), "Shiny" => Shiny = StringUtil.IsMatchIgnoreCase("Yes", value), "Gigantamax" => CanGigantamax = StringUtil.IsMatchIgnoreCase("Yes", value), "Friendship" => ParseFriendship(value), @@ -275,7 +275,7 @@ private bool ParseSingle(ReadOnlySpan identifier) private bool ParseLevel(ReadOnlySpan value) { - if (!int.TryParse(value.Trim(), out var val)) + if (!byte.TryParse(value.Trim(), out var val)) return false; if ((uint)val is 0 or > 100) return false; @@ -285,9 +285,7 @@ private bool ParseLevel(ReadOnlySpan value) private bool ParseFriendship(ReadOnlySpan value) { - if (!int.TryParse(value.Trim(), out var val)) - return false; - if ((uint)val > byte.MaxValue) + if (!byte.TryParse(value.Trim(), out var val)) return false; Friendship = val; return true; @@ -389,7 +387,7 @@ public List GetSetLines() result.Add("Gigantamax: Yes"); if ((uint)Nature < Strings.Natures.Count) - result.Add($"{Strings.Natures[Nature]} Nature"); + result.Add($"{Strings.Natures[(byte)Nature]} Nature"); // Moves result.AddRange(GetStringMoves()); @@ -511,7 +509,7 @@ public ShowdownSet(PKM pk) pk.GetIVs(IVs); pk.GetMoves(Moves); Nature = pk.StatNature; - Gender = (uint)pk.Gender < 2 ? pk.Gender : 2; + Gender = pk.Gender < 2 ? pk.Gender : (byte)2; Friendship = pk.CurrentFriendship; Level = pk.CurrentLevel; Shiny = pk.IsShiny; diff --git a/PKHeX.Core/Game/Enums/GameVersion.cs b/PKHeX.Core/Game/Enums/GameVersion.cs index 68c286749..88283c13b 100644 --- a/PKHeX.Core/Game/Enums/GameVersion.cs +++ b/PKHeX.Core/Game/Enums/GameVersion.cs @@ -268,7 +268,7 @@ public enum GameVersion : byte GSC, /// - /// Pokémon Ruby & Sapphire [] identifier. + /// Pokémon Ruby & Sapphire [] identifier. /// /// /// @@ -283,7 +283,7 @@ public enum GameVersion : byte RSE, /// - /// Pokémon FireRed/LeafGreen [] identifier. + /// Pokémon FireRed/LeafGreen [] identifier. /// /// /// @@ -309,7 +309,7 @@ public enum GameVersion : byte XD, /// - /// Pokémon Diamond & Pearl [] identifier. + /// Pokémon Diamond & Pearl [] identifier. /// /// /// @@ -325,7 +325,7 @@ public enum GameVersion : byte DPPt, /// - /// Pokémon HeartGold & SoulSilver [] identifier. + /// Pokémon HeartGold & SoulSilver [] identifier. /// /// /// @@ -361,7 +361,7 @@ public enum GameVersion : byte XY, /// - /// Pokémon Omega Ruby & Alpha Sapphire Demo [] identifier. + /// Pokémon Omega Ruby & Alpha Sapphire Demo [] identifier. /// /// ORASDEMO, diff --git a/PKHeX.Core/Game/Enums/MoveType.cs b/PKHeX.Core/Game/Enums/MoveType.cs index 43013a4bd..59a0f349b 100644 --- a/PKHeX.Core/Game/Enums/MoveType.cs +++ b/PKHeX.Core/Game/Enums/MoveType.cs @@ -31,7 +31,7 @@ public enum MoveType : sbyte /// public static class MoveTypeExtensions { - public static MoveType GetMoveTypeGeneration(this MoveType type, int generation) + public static MoveType GetMoveTypeGeneration(this MoveType type, byte generation) { if (generation <= 2) return GetMoveTypeFromG12(type); diff --git a/PKHeX.Core/Game/Enums/Nature.cs b/PKHeX.Core/Game/Enums/Nature.cs index 9425f9b9f..8b32f2834 100644 --- a/PKHeX.Core/Game/Enums/Nature.cs +++ b/PKHeX.Core/Game/Enums/Nature.cs @@ -43,10 +43,10 @@ public static class NatureUtil /// Gets the value that corresponds to the provided . /// /// Actual nature values will be unchanged; only out-of-bounds values re-map to . - public static Nature GetNature(int value) => value switch + public static Nature GetNature(Nature value) => value switch { - < 0 or >= (int)Nature.Random => Nature.Random, - _ => (Nature)value, + >= Nature.Random => Nature.Random, + _ => value, }; /// diff --git a/PKHeX.Core/Game/GameStrings/GameDataSource.cs b/PKHeX.Core/Game/GameStrings/GameDataSource.cs index 7b970d2c4..daa02d0b3 100644 --- a/PKHeX.Core/Game/GameStrings/GameDataSource.cs +++ b/PKHeX.Core/Game/GameStrings/GameDataSource.cs @@ -131,12 +131,12 @@ public List GetItemDataSource(GameVersion game, EntityContext context return HaX ? Util.GetCBList(items) : Util.GetCBList(items, allowed); } - public static IReadOnlyList LanguageDataSource(int gen) + public static IReadOnlyList LanguageDataSource(byte generation) { var languages = new List(LanguageList); - if (gen == 3) + if (generation == 3) languages.RemoveAll(static l => l.Value >= (int)LanguageID.Korean); - else if (gen < 7) + else if (generation < 7) languages.RemoveAll(static l => l.Value > (int)LanguageID.Korean); return languages; } diff --git a/PKHeX.Core/Game/GameStrings/GameInfo.cs b/PKHeX.Core/Game/GameStrings/GameInfo.cs index fe9127cb2..c0e891331 100644 --- a/PKHeX.Core/Game/GameStrings/GameInfo.cs +++ b/PKHeX.Core/Game/GameStrings/GameInfo.cs @@ -55,18 +55,19 @@ public static string GetVersionName(GameVersion version) public static IReadOnlyList GroundTileDataSource => Sources.GroundTileDataSource; public static IReadOnlyList Regions => GameDataSource.Regions; - public static IReadOnlyList LanguageDataSource(int gen) => GameDataSource.LanguageDataSource(gen); + public static IReadOnlyList LanguageDataSource(byte generation) + => GameDataSource.LanguageDataSource(generation); /// /// Gets the location name for the specified parameters. /// - /// Location is from the + /// Location is from the /// Location value /// Current /// of origin /// Current GameVersion (only applicable for differentiation) /// Location name - public static string GetLocationName(bool isEggLocation, int location, int format, int generation, GameVersion version) + public static string GetLocationName(bool isEggLocation, ushort location, byte format, byte generation, GameVersion version) { return Strings.GetLocationName(isEggLocation, location, format, generation, version); } diff --git a/PKHeX.Core/Game/GameStrings/GameStrings.cs b/PKHeX.Core/Game/GameStrings/GameStrings.cs index dac5d013a..f143b3351 100644 --- a/PKHeX.Core/Game/GameStrings/GameStrings.cs +++ b/PKHeX.Core/Game/GameStrings/GameStrings.cs @@ -739,13 +739,13 @@ private string[] GetItemStrings3(GameVersion game) /// /// Gets the location name for the specified parameters. /// - /// Location is from the + /// Location is from the /// Location value /// Current /// of origin /// Current GameVersion (only applicable for differentiation) /// Location name. Potentially an empty string if no location name is known for that location value. - public string GetLocationName(bool isEggLocation, int location, int format, int generation, GameVersion version) + public string GetLocationName(bool isEggLocation, ushort location, byte format, byte generation, GameVersion version) { if (format == 1) { @@ -762,7 +762,7 @@ public string GetLocationName(bool isEggLocation, int location, int format, int return set.GetLocationName(location); } - private static int GetGeneration(int generation, bool isEggLocation, int format) + private static byte GetGeneration(byte generation, bool isEggLocation, byte format) { if (format == 2) return 2; @@ -774,16 +774,16 @@ private static int GetGeneration(int generation, bool isEggLocation, int format) return generation; if (format >= 5) return format; - return -1; // Nonsensical inputs. + return 0; // Nonsensical inputs. } /// /// Gets the location names array for a specified generation. /// - /// Generation to get location names for. + /// Generation to get location names for. /// Version of origin /// List of location names. - public ILocationSet? GetLocations(int gen, GameVersion version) => gen switch + public ILocationSet? GetLocations(byte generation, GameVersion version) => generation switch { 2 => Gen2, 3 => GameVersion.CXD.Contains(version) ? CXD : Gen3, @@ -803,13 +803,13 @@ private static int GetGeneration(int generation, bool isEggLocation, int format) /// /// Gets the location names array for a specified generation. /// - /// Generation to get location names for. + /// Generation to get location names for. /// Version of origin /// BankID used to choose the text bank. /// List of location names. - public ReadOnlySpan GetLocationNames(int gen, GameVersion version, int bankID = 0) + public ReadOnlySpan GetLocationNames(byte generation, GameVersion version, int bankID = 0) { - var set = GetLocations(gen, version); + var set = GetLocations(generation, version); if (set is null) return []; return set.GetLocationNames(bankID); diff --git a/PKHeX.Core/Game/GameStrings/LocationSet/LocationSet0.cs b/PKHeX.Core/Game/GameStrings/LocationSet/LocationSet0.cs index 7e69e0ae7..6dcd22d4e 100644 --- a/PKHeX.Core/Game/GameStrings/LocationSet/LocationSet0.cs +++ b/PKHeX.Core/Game/GameStrings/LocationSet/LocationSet0.cs @@ -3,6 +3,10 @@ namespace PKHeX.Core; +/// +/// Generation 2-3 specific met location name holder. +/// +/// Single segment, no shift bias. public sealed record LocationSet0(string[] Met0) : ILocationSet { public ReadOnlySpan GetLocationNames(int bankID) => bankID switch diff --git a/PKHeX.Core/Game/GameStrings/LocationSet/LocationSet4.cs b/PKHeX.Core/Game/GameStrings/LocationSet/LocationSet4.cs index 7c249b984..ca614fcad 100644 --- a/PKHeX.Core/Game/GameStrings/LocationSet/LocationSet4.cs +++ b/PKHeX.Core/Game/GameStrings/LocationSet/LocationSet4.cs @@ -3,6 +3,10 @@ namespace PKHeX.Core; +/// +/// Generation 4 specific met location name holder. +/// +/// Multi-segment, small gaps. public sealed record LocationSet4(string[] Met0, string[] Met2, string[] Met3) : ILocationSet { public ReadOnlySpan GetLocationNames(int bankID) => bankID switch @@ -20,7 +24,7 @@ public sealed record LocationSet4(string[] Met0, string[] Met2, string[] Met3) : _ => Get(Met0, locationID), }; - private static string Get(string[] names, int index) + private static string Get(ReadOnlySpan names, int index) { if ((uint)index >= names.Length) return string.Empty; diff --git a/PKHeX.Core/Game/GameStrings/LocationSet/LocationSet6.cs b/PKHeX.Core/Game/GameStrings/LocationSet/LocationSet6.cs index c9db33d39..cf2919edf 100644 --- a/PKHeX.Core/Game/GameStrings/LocationSet/LocationSet6.cs +++ b/PKHeX.Core/Game/GameStrings/LocationSet/LocationSet6.cs @@ -3,6 +3,10 @@ namespace PKHeX.Core; +/// +/// Generation 5+ specific met location name holder. +/// +/// Multi-segment, large gaps. public sealed record LocationSet6(string[] Met0, string[] Met3, string[] Met4, string[] Met6) : ILocationSet { public ReadOnlySpan GetLocationNames(int bankID) => bankID switch @@ -22,7 +26,7 @@ public sealed record LocationSet6(string[] Met0, string[] Met3, string[] Met4, s _ => Get(Met0, locationID), }; - private static string Get(string[] names, int index) + private static string Get(ReadOnlySpan names, int index) { if ((uint)index >= names.Length) return string.Empty; diff --git a/PKHeX.Core/Game/GameUtil.cs b/PKHeX.Core/Game/GameUtil.cs index 6eac1b2f8..5de6b8670 100644 --- a/PKHeX.Core/Game/GameUtil.cs +++ b/PKHeX.Core/Game/GameUtil.cs @@ -88,7 +88,7 @@ private static GameVersion[] GetValidGameVersions() /// /// Generation ID /// Version ID from requested generation. If none, return . - public static GameVersion GetVersion(int generation) => generation switch + public static GameVersion GetVersion(byte generation) => generation switch { 1 => RBY, 2 => C, @@ -107,7 +107,7 @@ private static GameVersion[] GetValidGameVersions() /// /// Game to retrieve the generation for /// Generation ID - public static int GetGeneration(this GameVersion game) + public static byte GetGeneration(this GameVersion game) { if (Gen1.Contains(game)) return 1; if (Gen2.Contains(game)) return 2; @@ -119,7 +119,7 @@ public static int GetGeneration(this GameVersion game) if (Gen7b.Contains(game)) return 7; if (Gen8.Contains(game)) return 8; if (Gen9.Contains(game)) return 9; - return -1; + return 0; } /// @@ -167,63 +167,71 @@ public static bool Contains(this GameVersion g1, GameVersion g2) { if (g1 == g2 || g1 == Any) return true; - - return g1 switch - { - RB => g2 is RD or BU or GN, - RBY or Stadium => RB.Contains(g2) || g2 == YW, - Gen1 => RBY.Contains(g2) || g2 == Stadium, - - GS => g2 is GD or SI, - GSC or Stadium2 => GS.Contains(g2) || g2 == C, - Gen2 => GSC.Contains(g2) || g2 == Stadium2, - - RS => g2 is R or S, - RSE => RS.Contains(g2) || g2 == E, - FRLG => g2 is FR or LG, - COLO or XD => g2 == CXD, - CXD => g2 is COLO or XD, - RSBOX => RS.Contains(g2) || g2 == E || FRLG.Contains(g2), - Gen3 => RSE.Contains(g2) || FRLG.Contains(g2) || CXD.Contains(g2) || g2 == RSBOX, - - DP => g2 is D or P, - HGSS => g2 is HG or SS, - DPPt => DP.Contains(g2) || g2 == Pt, - BATREV => DP.Contains(g2) || g2 == Pt || HGSS.Contains(g2), - Gen4 => DPPt.Contains(g2) || HGSS.Contains(g2) || g2 == BATREV, - - BW => g2 is B or W, - B2W2 => g2 is B2 or W2, - Gen5 => BW.Contains(g2) || B2W2.Contains(g2), - - XY => g2 is X or Y, - ORAS => g2 is OR or AS, - - Gen6 => XY.Contains(g2) || ORAS.Contains(g2), - SM => g2 is SN or MN, - USUM => g2 is US or UM, - GG => g2 is GP or GE, - Gen7 => SM.Contains(g2) || USUM.Contains(g2), - Gen7b => GG.Contains(g2) || GO == g2, - - SWSH => g2 is SW or SH, - BDSP => g2 is BD or SP, - Gen8 => SWSH.Contains(g2) || BDSP.Contains(g2) || PLA == g2, - - SV => g2 is SL or VL, - Gen9 => SV.Contains(g2), - _ => false, - }; + if (g1.IsValidSavedVersion()) + return false; + return g1.ContainsFromLumped(g2); } + public static bool ContainsFromLumped(this GameVersion lump, GameVersion version) => lump switch + { + RB => version is RD or BU or GN, + RBY => version is RD or BU or GN or YW or RB, + Stadium => version is RD or BU or GN or YW or RB or RBY, + StadiumJ => version is RD or BU or GN or YW or RB or RBY, + Gen1 => version is RD or BU or GN or YW or RB or RBY or Stadium, + + GS => version is GD or SI, + GSC => version is GD or SI or C or GS, + Stadium2 => version is GD or SI or C or GS or GSC, + Gen2 => version is GD or SI or C or GS or GSC or Stadium2, + + RS => version is R or S, + RSE => version is R or S or E or RS, + FRLG => version is FR or LG, + RSBOX => version is R or S or E or FR or LG, + Gen3 => version is R or S or E or FR or LG or CXD or RSBOX or RS or RSE or FRLG, + COLO => version is CXD, + XD => version is CXD, + + DP => version is D or P, + HGSS => version is HG or SS, + DPPt => version is D or P or Pt or DP, + BATREV => version is D or P or Pt or HG or SS, + Gen4 => version is D or P or Pt or HG or SS or BATREV or DP or HGSS or DPPt, + + BW => version is B or W, + B2W2 => version is B2 or W2, + Gen5 => version is B or W or B2 or W2 or BW or B2W2, + + XY => version is X or Y, + ORAS => version is OR or AS, + Gen6 => version is X or Y or OR or AS or XY or ORAS, + + SM => version is SN or MN, + USUM => version is US or UM, + Gen7 => version is SN or MN or US or UM or SM or USUM, + + GG => version is GP or GE, + Gen7b => version is GP or GE or GO, + + SWSH => version is SW or SH, + BDSP => version is BD or SP, + Gen8 => version is SW or SH or BD or SP or SWSH or BDSP or PLA, + + SV => version is SL or VL, + Gen9 => version is SL or VL or SV, + + _ => false, + }; + /// /// List of possible values within the provided . /// /// Generation to look within - /// - public static GameVersion[] GetVersionsInGeneration(int generation, int pkVersion) + /// + public static GameVersion[] GetVersionsInGeneration(byte generation, GameVersion version) { - if (Gen7b.Contains(pkVersion)) + if (Gen7b.Contains(version)) return [GO, GP, GE]; return Array.FindAll(GameVersions, z => z.GetGeneration() == generation); } @@ -233,14 +241,14 @@ public static GameVersion[] GetVersionsInGeneration(int generation, int pkVersio /// /// Criteria for retrieving versions /// Generation format minimum (necessary for the CXD/Gen4 swap etc.) - public static IEnumerable GetVersionsWithinRange(IGameValueLimit obj, int generation = -1) + public static IEnumerable GetVersionsWithinRange(IGameValueLimit obj, byte generation = 0) { var max = obj.MaxGameID; if (max == Legal.MaxGameID_7b) // edge case return [GO, GP, GE]; var versions = GameVersions - .Where(version => (GameVersion)obj.MinGameID <= version && version <= (GameVersion)max); - if (generation < 0) + .Where(version => obj.MinGameID <= version && version <= max); + if (generation == 0) return versions; if (max == Legal.MaxGameID_7 && generation == 7) versions = versions.Where(version => version != GO); @@ -251,6 +259,9 @@ public static IEnumerable GetVersionsWithinRange(IGameValueLimit ob return versions.Where(version => version.GetGeneration() <= generation); } + /// + /// Finds all values within the . + /// public static GameVersion[] GetVersionsWithinRange(this GameVersion lump, GameVersion[] source) => Array.FindAll(source, z => lump.Contains(z)); } diff --git a/PKHeX.Core/Game/Locations/Locations.cs b/PKHeX.Core/Game/Locations/Locations.cs index 2f505159c..fc4fdfa45 100644 --- a/PKHeX.Core/Game/Locations/Locations.cs +++ b/PKHeX.Core/Game/Locations/Locations.cs @@ -110,40 +110,41 @@ public static class Locations /// Gets the egg location value for a traded unhatched egg. /// /// Generation of the egg - /// Game version of the egg + /// Game version of the egg /// Egg Location value /// Location will be set to the Met Location until it hatches, then moves to Egg Location. - public static int TradedEggLocation(int generation, GameVersion ver) => generation switch + public static ushort TradedEggLocation(byte generation, GameVersion version) => generation switch { 4 => LinkTrade4, 5 => LinkTrade5, - 8 when GameVersion.BDSP.Contains(ver) => LinkTrade6NPC, + 8 when GameVersion.BDSP.Contains(version) => LinkTrade6NPC, _ => LinkTrade6, }; - public static bool IsPtHGSSLocation(int location) => location is > 111 and < 2000; - public static bool IsPtHGSSLocationEgg(int location) => location is > 2010 and < 3000; - public static bool IsEventLocation3(int location) => location is 255; - public static bool IsEventLocation4(int location) => location is >= 3000 and <= 3076; - public static bool IsEventLocation5(int location) => location is > 40000 and < 50000; + public static bool IsPtHGSSLocation(ushort location) => location is > 111 and < 2000; + public static bool IsPtHGSSLocationEgg(ushort location) => location is > 2010 and < 3000; + public static bool IsEventLocation3(ushort location) => location is 255; + public static bool IsEventLocation4(ushort location) => location is >= 3000 and <= 3076; + public static bool IsEventLocation5(ushort location) => location is > 40000 and < 50000; private const int SafariLocation_RSE = 57; private const int SafariLocation_FRLG = 136; public static bool IsSafariZoneLocation3(byte loc) => loc is SafariLocation_RSE or SafariLocation_FRLG; + public static bool IsSafariZoneLocation3RSE(byte loc) => loc == SafariLocation_RSE; - public static bool IsEggLocationBred4(int loc, GameVersion ver) + public static bool IsEggLocationBred4(ushort loc, GameVersion version) { if (loc is Daycare4 or LinkTrade4) return true; - return loc == Faraway4 && ver is GameVersion.Pt or GameVersion.HG or GameVersion.SS; + return loc == Faraway4 && version is GameVersion.Pt or GameVersion.HG or GameVersion.SS; } - public static bool IsEggLocationBred5(int loc) => loc is Daycare5 or LinkTrade5; - public static bool IsEggLocationBred6(int loc) => loc is Daycare5 or LinkTrade6; - public static bool IsEggLocationBred8b(int loc) => loc is Daycare8b or LinkTrade6NPC; - public static bool IsEggLocationBred9(int loc) => loc is Picnic9 or LinkTrade6; + public static bool IsEggLocationBred5(ushort loc) => loc is Daycare5 or LinkTrade5; + public static bool IsEggLocationBred6(ushort loc) => loc is Daycare5 or LinkTrade6; + public static bool IsEggLocationBred8b(ushort loc) => loc is Daycare8b or LinkTrade6NPC; + public static bool IsEggLocationBred9(ushort loc) => loc is Picnic9 or LinkTrade6; - public static int GetDaycareLocation(int generation, GameVersion version) => generation switch + public static ushort GetDaycareLocation(byte generation, GameVersion version) => generation switch { 1 or 2 or 3 => 0, 4 => Daycare4, diff --git a/PKHeX.Core/Game/Locations/Locations4.cs b/PKHeX.Core/Game/Locations/Locations4.cs index d3e62c9c9..94b716281 100644 --- a/PKHeX.Core/Game/Locations/Locations4.cs +++ b/PKHeX.Core/Game/Locations/Locations4.cs @@ -9,7 +9,9 @@ public static class Locations4 { private const int SafariLocation_HGSS = 202; private const int MarshLocation_DPPt = 52; - public static bool IsSafariZoneLocation(ushort loc) => loc is MarshLocation_DPPt or SafariLocation_HGSS; + public static bool IsSafariBallRequired(ushort loc) => loc is MarshLocation_DPPt or SafariLocation_HGSS; + public static bool IsMarsh(ushort loc) => loc == MarshLocation_DPPt; + public static bool IsSafari(ushort loc) => loc == SafariLocation_HGSS; /// /// Available location list for the 00000 set of location names. diff --git a/PKHeX.Core/Game/Locations/LocationsHOME.cs b/PKHeX.Core/Game/Locations/LocationsHOME.cs index 1223db80e..c9228be78 100644 --- a/PKHeX.Core/Game/Locations/LocationsHOME.cs +++ b/PKHeX.Core/Game/Locations/LocationsHOME.cs @@ -1,4 +1,5 @@ using System; +using static PKHeX.Core.GameVersion; namespace PKHeX.Core; @@ -22,14 +23,14 @@ public static class LocationsHOME /// /// /// True if a known remap exists. - public static bool IsVersionRemapNeeded(int version) => GetRemapIndex(version) < RemapCount; + public static bool IsVersionRemapNeeded(GameVersion version) => GetRemapIndex(version) < RemapCount; - private static int GetRemapIndex(int version) => version - (int)GameVersion.PLA; + private static int GetRemapIndex(GameVersion version) => version - PLA; /// /// Checks if the SW/SH-context Met Location is one of the remapped HOME locations. /// - public static bool IsLocationSWSH(int met) => met switch + public static bool IsLocationSWSH(ushort met) => met switch { SHVL or SWSL or SHSP or SWBD or SWLA => true, _ => false, @@ -38,46 +39,46 @@ public static class LocationsHOME /// /// Checks if the SW/SH-context Egg Location is valid with respect to the location. /// - public static bool IsLocationSWSHEgg(int ver, int met, int egg, ushort original) + public static bool IsLocationSWSHEgg(GameVersion version, ushort met, int egg, ushort original) { if (original > SWLA && egg == SWSHEgg) return true; // >60000 can be reset to Link Trade (30001), then altered differently. - var expect = GetMetSWSH(original, ver); + var expect = GetMetSWSH(original, version); return expect == met && expect == egg; } /// - /// Gets the SW/SH-context Egg Location when an external entity from the input resides in SW/SH. + /// Gets the SW/SH-context Egg Location when an external entity from the input resides in SW/SH. /// - public static ushort GetLocationSWSHEgg(int ver, ushort egg) + public static ushort GetLocationSWSHEgg(GameVersion version, ushort egg) { if (egg == 0) return 0; if (egg > SWLA) return SWSHEgg; // >60000 can be reset to Link Trade (30001), then altered differently. - return GetMetSWSH(egg, ver); + return GetMetSWSH(egg, version); } /// - /// Gets the SW/SH-context when an external entity from the input resides in SW/SH. + /// Gets the SW/SH-context when an external entity from the input resides in SW/SH. /// - public static int GetVersionSWSH(int ver) => (GameVersion)ver switch + public static GameVersion GetVersionSWSH(GameVersion version) => version switch { - GameVersion.PLA => (int)GameVersion.SW, - GameVersion.BD => (int)GameVersion.SW, - GameVersion.SP => (int)GameVersion.SH, - GameVersion.SL => (int)GameVersion.SW, - GameVersion.VL => (int)GameVersion.SH, - _ => ver, + GameVersion.PLA => GameVersion.SW, + GameVersion.BD => GameVersion.SW, + GameVersion.SP => GameVersion.SH, + GameVersion.SL => GameVersion.SW, + GameVersion.VL => GameVersion.SH, + _ => version, }; /// - /// Gets the SW/SH-context Met Location when an external entity from the input resides in SW/SH. + /// Gets the SW/SH-context Met Location when an external entity from the input resides in SW/SH. /// - public static ushort GetMetSWSH(ushort loc, int ver) => (GameVersion)ver switch + public static ushort GetMetSWSH(ushort loc, GameVersion version) => version switch { GameVersion.PLA => SWLA, GameVersion.BD => SWBD, @@ -87,35 +88,35 @@ public static ushort GetLocationSWSHEgg(int ver, ushort egg) _ => loc, }; - public static int GetVersionSWSHOriginal(ushort loc) => loc switch + public static GameVersion GetVersionSWSHOriginal(ushort loc) => loc switch { - SWLA => (int)GameVersion.PLA, - SWBD => (int)GameVersion.BD, - SHSP => (int)GameVersion.SP, - SWSL => (int)GameVersion.SL, - SHVL => (int)GameVersion.VL, - _ => int.MinValue, + SWLA => GameVersion.PLA, + SWBD => GameVersion.BD, + SHSP => GameVersion.SP, + SWSL => GameVersion.SL, + SHVL => GameVersion.VL, + _ => GameVersion.SW, }; /// - /// Checks if the met location is a valid location for the input . + /// Checks if the met location is a valid location for the input . /// /// Relevant when an entity from BD/SP is transferred to SW/SH. - public static bool IsValidMetBDSP(ushort loc, int ver) => loc switch + public static bool IsValidMetBDSP(ushort loc, GameVersion version) => loc switch { - SHSP when ver == (int)GameVersion.SH => true, - SWBD when ver == (int)GameVersion.SW => true, + SHSP when version == SH => true, + SWBD when version == SW => true, _ => false, }; /// - /// Checks if the met location is a valid location for the input . + /// Checks if the met location is a valid location for the input . /// /// Relevant when an entity from S/V is transferred to SW/SH. - public static bool IsValidMetSV(ushort loc, int ver) => loc switch + public static bool IsValidMetSV(ushort loc, GameVersion version) => loc switch { - SHVL when ver == (int)GameVersion.SH => true, - SWSL when ver == (int)GameVersion.SW => true, + SHVL when version == SH => true, + SWSL when version == SW => true, _ => false, }; @@ -141,7 +142,7 @@ public static LocationRemapState GetRemapState(EntityContext original, EntityCon }; } - public static bool IsMatchLocation(EntityContext original, EntityContext current, int met, int expect, int version) + public static bool IsMatchLocation(EntityContext original, EntityContext current, ushort met, int expect, GameVersion version) { var state = GetRemapState(original, current); return state switch diff --git a/PKHeX.Core/Legality/Breeding.cs b/PKHeX.Core/Legality/Breeding.cs index b03303e30..2cf9aee9b 100644 --- a/PKHeX.Core/Legality/Breeding.cs +++ b/PKHeX.Core/Legality/Breeding.cs @@ -61,7 +61,7 @@ internal static bool GetCanInheritMoves(ushort species) /// /// Species that can yield a different baby species when bred. /// - public static bool IsSplitBreedNotBabySpecies(ushort species, int generation) + public static bool IsSplitBreedNotBabySpecies(ushort species, byte generation) { if (generation == 3) return IsSplitBreedNotBabySpecies3(species); diff --git a/PKHeX.Core/Legality/Bulk/DuplicateEncryptionChecker.cs b/PKHeX.Core/Legality/Bulk/DuplicateEncryptionChecker.cs index 358fbee70..72e43ba2d 100644 --- a/PKHeX.Core/Legality/Bulk/DuplicateEncryptionChecker.cs +++ b/PKHeX.Core/Legality/Bulk/DuplicateEncryptionChecker.cs @@ -47,7 +47,7 @@ private static void VerifyECShare(BulkAnalysis input, CombinedReference pr, Comb var (cs, ca) = cr; const CheckIdentifier ident = PID; - int gen = pa.Info.Generation; + var gen = pa.Info.Generation; bool gbaNDS = gen is 3 or 4 or 5; if (!gbaNDS) diff --git a/PKHeX.Core/Legality/Bulk/DuplicatePIDChecker.cs b/PKHeX.Core/Legality/Bulk/DuplicatePIDChecker.cs index a1e25a5d2..bf80bb4ae 100644 --- a/PKHeX.Core/Legality/Bulk/DuplicatePIDChecker.cs +++ b/PKHeX.Core/Legality/Bulk/DuplicatePIDChecker.cs @@ -47,7 +47,7 @@ private static void VerifyPIDShare(BulkAnalysis input, CombinedReference pr, Com var cs = cr.Slot; var ca = cr.Analysis; const CheckIdentifier ident = PID; - int gen = pa.Info.Generation; + var gen = pa.Info.Generation; if (ca.Info.Generation != gen) { diff --git a/PKHeX.Core/Legality/Bulk/DuplicateTrainerChecker.cs b/PKHeX.Core/Legality/Bulk/DuplicateTrainerChecker.cs index 6ba9690aa..b23683fac 100644 --- a/PKHeX.Core/Legality/Bulk/DuplicateTrainerChecker.cs +++ b/PKHeX.Core/Legality/Bulk/DuplicateTrainerChecker.cs @@ -66,7 +66,7 @@ private static bool VerifyIDReuse(BulkAnalysis input, SlotCache ps, LegalityAnal } // ID-SID16 should only occur for one Trainer name - if (pp.OT_Name != cp.OT_Name) + if (pp.OriginalTrainerName != cp.OriginalTrainerName) { var severity = ca.Info.Generation == 4 ? Severity.Fishy : Severity.Invalid; input.AddLine(ps, cs, "TID sharing across different trainer names detected.", ident, severity); diff --git a/PKHeX.Core/Legality/Bulk/HandlerChecker.cs b/PKHeX.Core/Legality/Bulk/HandlerChecker.cs index 210043eea..9fd1367eb 100644 --- a/PKHeX.Core/Legality/Bulk/HandlerChecker.cs +++ b/PKHeX.Core/Legality/Bulk/HandlerChecker.cs @@ -35,9 +35,9 @@ private static void Verify(BulkAnalysis input, SlotCache cs) if (flag != 1) return; - if (pk.HT_Name != tr.OT) + if (pk.HandlingTrainerName != tr.OT) input.AddLine(cs, LegalityCheckStrings.LTransferHTMismatchName, Trainer); - if (pk is IHandlerLanguage h && h.HT_Language != tr.Language) + if (pk is IHandlerLanguage h && h.HandlingTrainerLanguage != tr.Language) input.AddLine(cs, LegalityCheckStrings.LTransferHTMismatchLanguage, Trainer); } } diff --git a/PKHeX.Core/Legality/Bulk/StandardCloneChecker.cs b/PKHeX.Core/Legality/Bulk/StandardCloneChecker.cs index 65f0f852a..bcab87d1f 100644 --- a/PKHeX.Core/Legality/Bulk/StandardCloneChecker.cs +++ b/PKHeX.Core/Legality/Bulk/StandardCloneChecker.cs @@ -48,7 +48,7 @@ private static void CheckClonedTrackerHOME(BulkAnalysis input, IHomeTrack home, private static void CheckTrackerMissing(BulkAnalysis input, SlotCache cs, LegalityAnalysis ca) { - if (ca.Info.Generation is (< 8 and not -1)) + if (ca.Info.Generation is (< 8 and not 0)) input.AddLine(cs, "Missing tracker.", Encounter); } diff --git a/PKHeX.Core/Legality/Core.cs b/PKHeX.Core/Legality/Core.cs index 412034d2a..3f9f8c692 100644 --- a/PKHeX.Core/Legality/Core.cs +++ b/PKHeX.Core/Legality/Core.cs @@ -25,7 +25,7 @@ public static class Legal internal const int MaxItemID_3_XD = 593; internal const int MaxAbilityID_3 = 77; internal const int MaxBallID_3 = 0xC; - internal const int MaxGameID_3 = 15; // CXD + internal const GameVersion MaxGameID_3 = GameVersion.CXD; internal const int MaxSpeciesID_4 = 493; internal const int MaxMoveID_4 = 467; @@ -34,7 +34,7 @@ public static class Legal internal const int MaxItemID_4_HGSS = 536; internal const int MaxAbilityID_4 = 123; internal const int MaxBallID_4 = 0x18; - internal const int MaxGameID_4 = 15; // CXD + internal const GameVersion MaxGameID_4 = GameVersion.CXD; internal const int MaxSpeciesID_5 = 649; internal const int MaxMoveID_5 = 559; @@ -42,7 +42,7 @@ public static class Legal internal const int MaxItemID_5_B2W2 = 638; internal const int MaxAbilityID_5 = 164; internal const int MaxBallID_5 = 0x19; - internal const int MaxGameID_5 = 23; // B2 + internal const GameVersion MaxGameID_5 = GameVersion.B2; internal const int MaxSpeciesID_6 = 721; internal const int MaxMoveID_6_XY = 617; @@ -52,14 +52,14 @@ public static class Legal internal const int MaxAbilityID_6_XY = 188; internal const int MaxAbilityID_6_AO = 191; internal const int MaxBallID_6 = 0x19; - internal const int MaxGameID_6 = 27; // OR + internal const GameVersion MaxGameID_6 = GameVersion.OR; internal const int MaxSpeciesID_7 = 802; internal const int MaxMoveID_7 = 719; internal const int MaxItemID_7 = 920; internal const int MaxAbilityID_7 = 232; internal const int MaxBallID_7 = 0x1A; // 26 - internal const int MaxGameID_7 = 41; // Crystal (VC?) + internal const GameVersion MaxGameID_7 = GameVersion.C; internal const int MaxSpeciesID_7_USUM = 807; internal const int MaxMoveID_7_USUM = 728; @@ -70,7 +70,7 @@ public static class Legal internal const int MaxMoveID_7b = 742; // Double Iron Bash internal const int MaxItemID_7b = 1057; // Magmar Candy internal const int MaxBallID_7b = (int)Ball.Beast; - internal const int MaxGameID_7b = (int)GameVersion.GE; + internal const GameVersion MaxGameID_7b = GameVersion.GE; internal const int MaxAbilityID_7b = MaxAbilityID_7_USUM; // Current Binaries @@ -98,20 +98,20 @@ public static class Legal internal const int MaxAbilityID_8_R2 = 267; // As One (Glastrier) internal const int MaxBallID_8 = 0x1A; // 26 Beast - internal const int MaxGameID_8 = 45; // Shield + internal const GameVersion MaxGameID_8 = GameVersion.SH; internal const int MaxSpeciesID_8a = (int)Species.Enamorus; internal const int MaxMoveID_8a = (int)Move.TakeHeart; internal const int MaxItemID_8a = 1828; // Legend Plate internal const int MaxBallID_8a = (int)Ball.LAOrigin; - //internal const int MaxGameID_8a = (int)GameVersion.SP; + //internal const GameVersion MaxGameID_8a = GameVersion.SP; internal const int MaxAbilityID_8a = MaxAbilityID_8_R2; internal const int MaxSpeciesID_8b = MaxSpeciesID_4; // Arceus-493 internal const int MaxMoveID_8b = MaxMoveID_8_R2; internal const int MaxItemID_8b = 1822; // DS Sounds internal const int MaxBallID_8b = (int)Ball.LAOrigin; - //internal const int MaxGameID_8b = (int)GameVersion.SP; + //internal const GameVersion MaxGameID_8b = GameVersion.SP; internal const int MaxAbilityID_8b = MaxAbilityID_8_R2; internal const int MaxSpeciesID_9 = MaxSpeciesID_9_T2; @@ -135,8 +135,8 @@ public static class Legal internal const int MaxAbilityID_9_T2 = (int)Ability.PoisonPuppeteer; internal const int MaxBallID_9 = (int)Ball.LAOrigin; - internal const int MaxGameID_9 = (int)GameVersion.VL; - internal const int MaxGameID_HOME = MaxGameID_9; + internal const GameVersion MaxGameID_9 = GameVersion.VL; + internal const GameVersion MaxGameID_HOME = MaxGameID_9; internal static readonly ushort[] HeldItems_GSC = ItemStorage2.GetAllHeld(); internal static readonly ushort[] HeldItems_RS = ItemStorage3RS.GetAllHeld(); @@ -154,7 +154,7 @@ public static class Legal internal static readonly ushort[] HeldItems_LA = []; internal static readonly ushort[] HeldItems_SV = ItemStorage9SV.GetAllHeld(); - internal static int GetMaxLanguageID(int generation) => generation switch + internal static int GetMaxLanguageID(byte generation) => generation switch { 1 => (int) LanguageID.Spanish, // 1-7 except 6 3 => (int) LanguageID.Spanish, // 1-7 except 6 @@ -208,7 +208,7 @@ public static bool IsPPUpAvailable(PKM pk) /// /// Generation of the Trainer /// Language of the Trainer - public static int GetMaxLengthOT(int generation, LanguageID language) => language switch + public static int GetMaxLengthOT(byte generation, LanguageID language) => language switch { LanguageID.ChineseS or LanguageID.ChineseT => 6, LanguageID.Japanese or LanguageID.Korean => generation >= 6 ? 6 : 5, @@ -220,7 +220,7 @@ public static bool IsPPUpAvailable(PKM pk) /// /// Generation of the Trainer /// Language of the Trainer - public static int GetMaxLengthNickname(int generation, LanguageID language) => language switch + public static int GetMaxLengthNickname(byte generation, LanguageID language) => language switch { LanguageID.ChineseS or LanguageID.ChineseT => 6, LanguageID.Japanese or LanguageID.Korean => generation >= 6 ? 6 : 5, diff --git a/PKHeX.Core/Legality/Encounters/Data/Gen1/Encounters1GBEra.cs b/PKHeX.Core/Legality/Encounters/Data/Gen1/Encounters1GBEra.cs index 49eb94651..fb07c7124 100644 --- a/PKHeX.Core/Legality/Encounters/Data/Gen1/Encounters1GBEra.cs +++ b/PKHeX.Core/Legality/Encounters/Data/Gen1/Encounters1GBEra.cs @@ -11,28 +11,28 @@ internal static class Encounters1GBEra internal static readonly EncounterGift1[] Gifts = [ // Stadium 1 (International) - new(001, 05, GameVersion.Stadium) {Moves = new(033, 045), TID16 = 2000, OT_Names = StadiumOT_Int, Language = EncounterGBLanguage.International}, // Bulbasaur - new(004, 05, GameVersion.Stadium) {Moves = new(010, 043), TID16 = 2000, OT_Names = StadiumOT_Int, Language = EncounterGBLanguage.International}, // Charmander - new(007, 05, GameVersion.Stadium) {Moves = new(033, 045), TID16 = 2000, OT_Names = StadiumOT_Int, Language = EncounterGBLanguage.International}, // Squirtle - new(106, 20, GameVersion.Stadium) {Moves = new(024, 096), TID16 = 2000, OT_Names = StadiumOT_Int, Language = EncounterGBLanguage.International}, // Hitmonlee - new(107, 20, GameVersion.Stadium) {Moves = new(004, 097), TID16 = 2000, OT_Names = StadiumOT_Int, Language = EncounterGBLanguage.International}, // Hitmonchan - new(133, 25, GameVersion.Stadium) {Moves = new(033, 039), TID16 = 2000, OT_Names = StadiumOT_Int, Language = EncounterGBLanguage.International}, // Eevee - new(138, 20, GameVersion.Stadium) {Moves = new(055, 110), TID16 = 2000, OT_Names = StadiumOT_Int, Language = EncounterGBLanguage.International}, // Omanyte - new(140, 20, GameVersion.Stadium) {Moves = new(010, 106), TID16 = 2000, OT_Names = StadiumOT_Int, Language = EncounterGBLanguage.International}, // Kabuto - new(054, 15, GameVersion.Stadium) {Moves = new(133, 010), TID16 = 2000, OT_Names = StadiumOT_Int, Language = EncounterGBLanguage.International}, // Psyduck (Amnesia) + new(001, 05, GameVersion.Stadium) {Moves = new(033, 045), TID16 = 2000, TrainerNames = StadiumOT_Int, Language = EncounterGBLanguage.International}, // Bulbasaur + new(004, 05, GameVersion.Stadium) {Moves = new(010, 043), TID16 = 2000, TrainerNames = StadiumOT_Int, Language = EncounterGBLanguage.International}, // Charmander + new(007, 05, GameVersion.Stadium) {Moves = new(033, 045), TID16 = 2000, TrainerNames = StadiumOT_Int, Language = EncounterGBLanguage.International}, // Squirtle + new(106, 20, GameVersion.Stadium) {Moves = new(024, 096), TID16 = 2000, TrainerNames = StadiumOT_Int, Language = EncounterGBLanguage.International}, // Hitmonlee + new(107, 20, GameVersion.Stadium) {Moves = new(004, 097), TID16 = 2000, TrainerNames = StadiumOT_Int, Language = EncounterGBLanguage.International}, // Hitmonchan + new(133, 25, GameVersion.Stadium) {Moves = new(033, 039), TID16 = 2000, TrainerNames = StadiumOT_Int, Language = EncounterGBLanguage.International}, // Eevee + new(138, 20, GameVersion.Stadium) {Moves = new(055, 110), TID16 = 2000, TrainerNames = StadiumOT_Int, Language = EncounterGBLanguage.International}, // Omanyte + new(140, 20, GameVersion.Stadium) {Moves = new(010, 106), TID16 = 2000, TrainerNames = StadiumOT_Int, Language = EncounterGBLanguage.International}, // Kabuto + new(054, 15, GameVersion.Stadium) {Moves = new(133, 010), TID16 = 2000, TrainerNames = StadiumOT_Int, Language = EncounterGBLanguage.International}, // Psyduck (Amnesia) // Stadium 2 (Japan) - new(001, 05, GameVersion.Stadium) {Moves = new(033, 045), TID16 = 1999, OT_Name = StadiumOT_JPN}, // Bulbasaur - new(004, 05, GameVersion.Stadium) {Moves = new(010, 043), TID16 = 1999, OT_Name = StadiumOT_JPN}, // Charmander - new(007, 05, GameVersion.Stadium) {Moves = new(033, 045), TID16 = 1999, OT_Name = StadiumOT_JPN}, // Squirtle - new(106, 20, GameVersion.Stadium) {Moves = new(024, 096), TID16 = 1999, OT_Name = StadiumOT_JPN}, // Hitmonlee - new(107, 20, GameVersion.Stadium) {Moves = new(004, 097), TID16 = 1999, OT_Name = StadiumOT_JPN}, // Hitmonchan - new(133, 25, GameVersion.Stadium) {Moves = new(033, 039), TID16 = 1999, OT_Name = StadiumOT_JPN}, // Eevee - new(138, 20, GameVersion.Stadium) {Moves = new(055, 110), TID16 = 1999, OT_Name = StadiumOT_JPN}, // Omanyte - new(140, 20, GameVersion.Stadium) {Moves = new(010, 106), TID16 = 1999, OT_Name = StadiumOT_JPN}, // Kabuto - new(054, 15, GameVersion.Stadium) {Moves = new(133, 010), TID16 = 1999, OT_Name = StadiumOT_JPN}, // Psyduck (Amnesia) + new(001, 05, GameVersion.Stadium) {Moves = new(033, 045), TID16 = 1999, OriginalTrainerName = StadiumOT_JPN}, // Bulbasaur + new(004, 05, GameVersion.Stadium) {Moves = new(010, 043), TID16 = 1999, OriginalTrainerName = StadiumOT_JPN}, // Charmander + new(007, 05, GameVersion.Stadium) {Moves = new(033, 045), TID16 = 1999, OriginalTrainerName = StadiumOT_JPN}, // Squirtle + new(106, 20, GameVersion.Stadium) {Moves = new(024, 096), TID16 = 1999, OriginalTrainerName = StadiumOT_JPN}, // Hitmonlee + new(107, 20, GameVersion.Stadium) {Moves = new(004, 097), TID16 = 1999, OriginalTrainerName = StadiumOT_JPN}, // Hitmonchan + new(133, 25, GameVersion.Stadium) {Moves = new(033, 039), TID16 = 1999, OriginalTrainerName = StadiumOT_JPN}, // Eevee + new(138, 20, GameVersion.Stadium) {Moves = new(055, 110), TID16 = 1999, OriginalTrainerName = StadiumOT_JPN}, // Omanyte + new(140, 20, GameVersion.Stadium) {Moves = new(010, 106), TID16 = 1999, OriginalTrainerName = StadiumOT_JPN}, // Kabuto + new(054, 15, GameVersion.Stadium) {Moves = new(133, 010), TID16 = 1999, OriginalTrainerName = StadiumOT_JPN}, // Psyduck (Amnesia) - new(151, 5, GameVersion.RB) {IVs = Yoshira, OT_Names = YoshiOT, Language = EncounterGBLanguage.International }, // Yoshira Mew Events - new(151, 5, GameVersion.RB) {IVs = Yoshira, OT_Names = TourOT, Language = EncounterGBLanguage.International }, // Pokémon 2000 Stadium Tour Mew + new(151, 5, GameVersion.RB) {IVs = Yoshira, TrainerNames = YoshiOT, Language = EncounterGBLanguage.International }, // Yoshira Mew Events + new(151, 5, GameVersion.RB) {IVs = Yoshira, TrainerNames = TourOT, Language = EncounterGBLanguage.International }, // Pokémon 2000 Stadium Tour Mew ]; } diff --git a/PKHeX.Core/Legality/Encounters/Data/Gen1/Encounters1VC.cs b/PKHeX.Core/Legality/Encounters/Data/Gen1/Encounters1VC.cs index 1b6b0af49..4ee248d36 100644 --- a/PKHeX.Core/Legality/Encounters/Data/Gen1/Encounters1VC.cs +++ b/PKHeX.Core/Legality/Encounters/Data/Gen1/Encounters1VC.cs @@ -7,7 +7,7 @@ internal static class Encounters1VC internal static readonly EncounterGift1[] Gifts = [ // Event Mew - new(151, 5, GameVersion.RBY) { IVs = Flawless15, TID16 = 22796, OT_Name = "GF", Language = EncounterGBLanguage.International }, - new(151, 5, GameVersion.RBY) { IVs = Flawless15, TID16 = 22796, OT_Name = "ゲーフリ" }, + new(151, 5, GameVersion.RBY) { IVs = Flawless15, TID16 = 22796, OriginalTrainerName = "GF", Language = EncounterGBLanguage.International }, + new(151, 5, GameVersion.RBY) { IVs = Flawless15, TID16 = 22796, OriginalTrainerName = "ゲーフリ" }, ]; } diff --git a/PKHeX.Core/Legality/Encounters/Data/Gen2/Encounters2GBEra.cs b/PKHeX.Core/Legality/Encounters/Data/Gen2/Encounters2GBEra.cs index 32f8028f3..d1b618406 100644 --- a/PKHeX.Core/Legality/Encounters/Data/Gen2/Encounters2GBEra.cs +++ b/PKHeX.Core/Legality/Encounters/Data/Gen2/Encounters2GBEra.cs @@ -11,218 +11,218 @@ internal static class Encounters2GBEra internal static readonly EncounterGift2[] StaticEventsGB = [ // Stadium 2 Baton Pass Farfetch'd - new(083, 05, C) {Moves = new(226, 14, 97, 163), Location = 127, TID16 = 2000, OT_Name = "スタジアム"}, - new(083, 05, C) {Moves = new(226, 14, 97, 163), Location = 127, TID16 = 2000, OT_Name = "Stadium", Language = International}, - new(083, 05, C) {Moves = new(226, 14, 97, 163), Location = 127, TID16 = 2001, OT_Names = Stadium2, Language = International}, + new(083, 05, C) {Moves = new(226, 14, 97, 163), Location = 127, TID16 = 2000, OriginalTrainerName = "スタジアム"}, + new(083, 05, C) {Moves = new(226, 14, 97, 163), Location = 127, TID16 = 2000, OriginalTrainerName = "Stadium", Language = International}, + new(083, 05, C) {Moves = new(226, 14, 97, 163), Location = 127, TID16 = 2001, TrainerNames = Stadium2, Language = International}, // Stadium 2 Earthquake Gligar - new(207, 05, C) {Moves = new(89, 68, 17), Location = 127, TID16 = 2000, OT_Name = "スタジアム"}, - new(207, 05, C) {Moves = new(89, 68, 17), Location = 127, TID16 = 2000, OT_Name = "Stadium", Language = International}, - new(207, 05, C) {Moves = new(89, 68, 17), Location = 127, TID16 = 2001, OT_Names = Stadium2, Language = International}, + new(207, 05, C) {Moves = new(89, 68, 17), Location = 127, TID16 = 2000, OriginalTrainerName = "スタジアム"}, + new(207, 05, C) {Moves = new(89, 68, 17), Location = 127, TID16 = 2000, OriginalTrainerName = "Stadium", Language = International}, + new(207, 05, C) {Moves = new(89, 68, 17), Location = 127, TID16 = 2001, TrainerNames = Stadium2, Language = International}, //New York Pokémon Center Events // Legendary Beasts (November 22 to 29, 2001) - new(243, 05, C) {OT_Names = PCNYx, CurrentLevel = 40, Shiny = Shiny.Always, Location = 127, Language = International}, // Shiny Raikou - new(244, 05, C) {OT_Names = PCNYx, CurrentLevel = 40, Shiny = Shiny.Always, Location = 127, Language = International}, // Shiny Entei - new(245, 05, C) {OT_Names = PCNYx, CurrentLevel = 40, Shiny = Shiny.Always, Location = 127, Language = International}, // Shiny Suicune + new(243, 05, C) {TrainerNames = PCNYx, CurrentLevel = 40, Shiny = Shiny.Always, Location = 127, Language = International}, // Shiny Raikou + new(244, 05, C) {TrainerNames = PCNYx, CurrentLevel = 40, Shiny = Shiny.Always, Location = 127, Language = International}, // Shiny Entei + new(245, 05, C) {TrainerNames = PCNYx, CurrentLevel = 40, Shiny = Shiny.Always, Location = 127, Language = International}, // Shiny Suicune // Legendary Birds (November 30 to December 6, 2001) - new(144, 05, C) {OT_Names = PCNYx, CurrentLevel = 50, Shiny = Shiny.Always, Location = 127, Language = International}, // Shiny Articuno - new(145, 05, C) {OT_Names = PCNYx, CurrentLevel = 50, Shiny = Shiny.Always, Location = 127, Language = International}, // Shiny Zapdos - new(146, 05, C) {OT_Names = PCNYx, CurrentLevel = 50, Shiny = Shiny.Always, Location = 127, Language = International}, // Shiny Moltres + new(144, 05, C) {TrainerNames = PCNYx, CurrentLevel = 50, Shiny = Shiny.Always, Location = 127, Language = International}, // Shiny Articuno + new(145, 05, C) {TrainerNames = PCNYx, CurrentLevel = 50, Shiny = Shiny.Always, Location = 127, Language = International}, // Shiny Zapdos + new(146, 05, C) {TrainerNames = PCNYx, CurrentLevel = 50, Shiny = Shiny.Always, Location = 127, Language = International}, // Shiny Moltres // Christmas Week (December 21 to 27, 2001) - new(225, 05, GS) {OT_Names = PCNYx, Moves = new(006), EggCycles = 10, Language = International}, // Pay Day Delibird - new(251, 05, C) {OT_Names = PCNYx, Location = 127, Language = International}, // Celebi + new(225, 05, GS) {TrainerNames = PCNYx, Moves = new(006), EggCycles = 10, Language = International}, // Pay Day Delibird + new(251, 05, C) {TrainerNames = PCNYx, Location = 127, Language = International}, // Celebi // The Initial Three Set (December 28, 2001, to January 31, 2002) - new(001, 05, GS) {OT_Names = PCNYx, Moves = new(246), EggCycles = 10, Language = International}, // Bulbasaur Ancientpower - new(004, 05, GS) {OT_Names = PCNYx, Moves = new(242), EggCycles = 10, Language = International}, // Charmander Crunch - new(007, 05, GS) {OT_Names = PCNYx, Moves = new(192), EggCycles = 10, Language = International}, // Squirtle Zap Cannon - new(152, 05, GS) {OT_Names = PCNYx, Moves = new(080), EggCycles = 10, Language = International}, // Chikorita Petal Dance - new(155, 05, GS) {OT_Names = PCNYx, Moves = new(038), EggCycles = 10, Language = International}, // Cyndaquil Double-Edge - new(158, 05, GS) {OT_Names = PCNYx, Moves = new(066), EggCycles = 10, Language = International}, // Totodile Submission + new(001, 05, GS) {TrainerNames = PCNYx, Moves = new(246), EggCycles = 10, Language = International}, // Bulbasaur Ancientpower + new(004, 05, GS) {TrainerNames = PCNYx, Moves = new(242), EggCycles = 10, Language = International}, // Charmander Crunch + new(007, 05, GS) {TrainerNames = PCNYx, Moves = new(192), EggCycles = 10, Language = International}, // Squirtle Zap Cannon + new(152, 05, GS) {TrainerNames = PCNYx, Moves = new(080), EggCycles = 10, Language = International}, // Chikorita Petal Dance + new(155, 05, GS) {TrainerNames = PCNYx, Moves = new(038), EggCycles = 10, Language = International}, // Cyndaquil Double-Edge + new(158, 05, GS) {TrainerNames = PCNYx, Moves = new(066), EggCycles = 10, Language = International}, // Totodile Submission // Valentine Week (February 1 to 14, 2002) - new(029, 05, GS) {OT_Names = PCNYx, Moves = new(142), EggCycles = 10, Language = International}, // Nidoran (F) Lovely Kiss - new(029, 05, GS) {OT_Names = PCNYx, Moves = new(186), EggCycles = 10, Language = International}, // Nidoran (F) Sweet Kiss - new(032, 05, GS) {OT_Names = PCNYx, Moves = new(142), EggCycles = 10, Language = International}, // Nidoran (M) Lovely Kiss - new(032, 05, GS) {OT_Names = PCNYx, Moves = new(186), EggCycles = 10, Language = International}, // Nidoran (M) Sweet Kiss - new(069, 05, GS) {OT_Names = PCNYx, Moves = new(142), EggCycles = 10, Language = International}, // Bellsprout Lovely Kiss - new(069, 05, GS) {OT_Names = PCNYx, Moves = new(186), EggCycles = 10, Language = International}, // Bellsprout Sweet Kiss + new(029, 05, GS) {TrainerNames = PCNYx, Moves = new(142), EggCycles = 10, Language = International}, // Nidoran (F) Lovely Kiss + new(029, 05, GS) {TrainerNames = PCNYx, Moves = new(186), EggCycles = 10, Language = International}, // Nidoran (F) Sweet Kiss + new(032, 05, GS) {TrainerNames = PCNYx, Moves = new(142), EggCycles = 10, Language = International}, // Nidoran (M) Lovely Kiss + new(032, 05, GS) {TrainerNames = PCNYx, Moves = new(186), EggCycles = 10, Language = International}, // Nidoran (M) Sweet Kiss + new(069, 05, GS) {TrainerNames = PCNYx, Moves = new(142), EggCycles = 10, Language = International}, // Bellsprout Lovely Kiss + new(069, 05, GS) {TrainerNames = PCNYx, Moves = new(186), EggCycles = 10, Language = International}, // Bellsprout Sweet Kiss // Swarm Week (February 22 to March 14, 2002) - new(183, 05, GS) {OT_Names = PCNYx, Moves = new(056), EggCycles = 10, Language = International}, // Marill Hydro Pump - new(193, 05, GS) {OT_Names = PCNYx, Moves = new(211), EggCycles = 10, Language = International}, // Yanma Steel Wing - new(206, 05, GS) {OT_Names = PCNYx, Moves = new(032), EggCycles = 10, Language = International}, // Dunsparce Horn Drill - new(209, 05, GS) {OT_Names = PCNYx, Moves = new(142), EggCycles = 10, Language = International}, // Snubbull Lovely Kiss - new(211, 05, GS) {OT_Names = PCNYx, Moves = new(038), EggCycles = 10, Language = International}, // Qwilfish Double-Edge - new(223, 05, GS) {OT_Names = PCNYx, Moves = new(133), EggCycles = 10, Language = International}, // Remoraid Amnesia + new(183, 05, GS) {TrainerNames = PCNYx, Moves = new(056), EggCycles = 10, Language = International}, // Marill Hydro Pump + new(193, 05, GS) {TrainerNames = PCNYx, Moves = new(211), EggCycles = 10, Language = International}, // Yanma Steel Wing + new(206, 05, GS) {TrainerNames = PCNYx, Moves = new(032), EggCycles = 10, Language = International}, // Dunsparce Horn Drill + new(209, 05, GS) {TrainerNames = PCNYx, Moves = new(142), EggCycles = 10, Language = International}, // Snubbull Lovely Kiss + new(211, 05, GS) {TrainerNames = PCNYx, Moves = new(038), EggCycles = 10, Language = International}, // Qwilfish Double-Edge + new(223, 05, GS) {TrainerNames = PCNYx, Moves = new(133), EggCycles = 10, Language = International}, // Remoraid Amnesia // Shiny RBY Starters (March 15 to 21, 2002) - new(003, 05, C) {OT_Names = PCNYx, CurrentLevel = 40, Shiny = Shiny.Always, Location = 127, Language = International}, // Shiny Venusaur - new(006, 05, C) {OT_Names = PCNYx, CurrentLevel = 40, Shiny = Shiny.Always, Location = 127, Language = International}, // Shiny Charizard - new(009, 05, C) {OT_Names = PCNYx, CurrentLevel = 40, Shiny = Shiny.Always, Location = 127, Language = International}, // Shiny Blastoise + new(003, 05, C) {TrainerNames = PCNYx, CurrentLevel = 40, Shiny = Shiny.Always, Location = 127, Language = International}, // Shiny Venusaur + new(006, 05, C) {TrainerNames = PCNYx, CurrentLevel = 40, Shiny = Shiny.Always, Location = 127, Language = International}, // Shiny Charizard + new(009, 05, C) {TrainerNames = PCNYx, CurrentLevel = 40, Shiny = Shiny.Always, Location = 127, Language = International}, // Shiny Blastoise // Babies Week (March 22 to April 11, 2002) - new(172, 05, GS) {OT_Names = PCNYx, Moves = new(047), EggCycles = 10, Language = International}, // Pichu Sing - new(173, 05, GS) {OT_Names = PCNYx, Moves = new(129), EggCycles = 10, Language = International}, // Cleffa Swift - new(174, 05, GS) {OT_Names = PCNYx, Moves = new(102), EggCycles = 10, Language = International}, // Igglybuff Mimic - new(238, 05, GS) {OT_Names = PCNYx, Moves = new(118), EggCycles = 10, Language = International}, // Smoochum Metronome - new(239, 05, GS) {OT_Names = PCNYx, Moves = new(228), EggCycles = 10, Language = International}, // Elekid Pursuit - new(240, 05, GS) {OT_Names = PCNYx, Moves = new(185), EggCycles = 10, Language = International}, // Magby Faint Attack + new(172, 05, GS) {TrainerNames = PCNYx, Moves = new(047), EggCycles = 10, Language = International}, // Pichu Sing + new(173, 05, GS) {TrainerNames = PCNYx, Moves = new(129), EggCycles = 10, Language = International}, // Cleffa Swift + new(174, 05, GS) {TrainerNames = PCNYx, Moves = new(102), EggCycles = 10, Language = International}, // Igglybuff Mimic + new(238, 05, GS) {TrainerNames = PCNYx, Moves = new(118), EggCycles = 10, Language = International}, // Smoochum Metronome + new(239, 05, GS) {TrainerNames = PCNYx, Moves = new(228), EggCycles = 10, Language = International}, // Elekid Pursuit + new(240, 05, GS) {TrainerNames = PCNYx, Moves = new(185), EggCycles = 10, Language = International}, // Magby Faint Attack // Spring Into Spring (April 12 to May 4, 2002) - new(054, 05, GS) {OT_Names = PCNYx, Moves = new(080), EggCycles = 10, Language = International}, // Psyduck Petal Dance - new(152, 05, GS) {OT_Names = PCNYx, Moves = new(080), EggCycles = 10, Language = International}, // Chikorita Petal Dance - new(172, 05, GS) {OT_Names = PCNYx, Moves = new(080), EggCycles = 10, Language = International}, // Pichu Petal Dance - new(173, 05, GS) {OT_Names = PCNYx, Moves = new(080), EggCycles = 10, Language = International}, // Cleffa Petal Dance - new(174, 05, GS) {OT_Names = PCNYx, Moves = new(080), EggCycles = 10, Language = International}, // Igglybuff Petal Dance - new(238, 05, GS) {OT_Names = PCNYx, Moves = new(080), EggCycles = 10, Language = International}, // Smoochum Petal Dance + new(054, 05, GS) {TrainerNames = PCNYx, Moves = new(080), EggCycles = 10, Language = International}, // Psyduck Petal Dance + new(152, 05, GS) {TrainerNames = PCNYx, Moves = new(080), EggCycles = 10, Language = International}, // Chikorita Petal Dance + new(172, 05, GS) {TrainerNames = PCNYx, Moves = new(080), EggCycles = 10, Language = International}, // Pichu Petal Dance + new(173, 05, GS) {TrainerNames = PCNYx, Moves = new(080), EggCycles = 10, Language = International}, // Cleffa Petal Dance + new(174, 05, GS) {TrainerNames = PCNYx, Moves = new(080), EggCycles = 10, Language = International}, // Igglybuff Petal Dance + new(238, 05, GS) {TrainerNames = PCNYx, Moves = new(080), EggCycles = 10, Language = International}, // Smoochum Petal Dance // Baby Weeks (May 5 to June 7, 2002) new(194, 05, GS) {Moves = new(187), EggCycles = 10, Language = International}, // Wooper Belly Drum // Tropical Promotion to Summer Festival 1 (June 8 to 21, 2002) - new(060, 05, GS) {OT_Names = PCNYx, Moves = new(074), EggCycles = 10, Language = International}, // Poliwag Growth - new(116, 05, GS) {OT_Names = PCNYx, Moves = new(114), EggCycles = 10, Language = International}, // Horsea Haze - new(118, 05, GS) {OT_Names = PCNYx, Moves = new(014), EggCycles = 10, Language = International}, // Goldeen Swords Dance - new(129, 05, GS) {OT_Names = PCNYx, Moves = new(179), EggCycles = 10, Language = International}, // Magikarp Reversal - new(183, 05, GS) {OT_Names = PCNYx, Moves = new(146), EggCycles = 10, Language = International}, // Marill Dizzy Punch + new(060, 05, GS) {TrainerNames = PCNYx, Moves = new(074), EggCycles = 10, Language = International}, // Poliwag Growth + new(116, 05, GS) {TrainerNames = PCNYx, Moves = new(114), EggCycles = 10, Language = International}, // Horsea Haze + new(118, 05, GS) {TrainerNames = PCNYx, Moves = new(014), EggCycles = 10, Language = International}, // Goldeen Swords Dance + new(129, 05, GS) {TrainerNames = PCNYx, Moves = new(179), EggCycles = 10, Language = International}, // Magikarp Reversal + new(183, 05, GS) {TrainerNames = PCNYx, Moves = new(146), EggCycles = 10, Language = International}, // Marill Dizzy Punch // Tropical Promotion to Summer Festival 2 (July 12 to August 8, 2002) - new(054, 05, GS) {OT_Names = PCNYx, Moves = new(161), EggCycles = 10, Language = International}, // Psyduck Tri Attack - new(072, 05, GS) {OT_Names = PCNYx, Moves = new(109), EggCycles = 10, Language = International}, // Tentacool Confuse Ray - new(131, 05, GS) {OT_Names = PCNYx, Moves = new(044), EggCycles = 10, Language = International}, // Lapras Bite - new(170, 05, GS) {OT_Names = PCNYx, Moves = new(113), EggCycles = 10, Language = International}, // Chinchou Light Screen - new(223, 05, GS) {OT_Names = PCNYx, Moves = new(054), EggCycles = 10, Language = International}, // Remoraid Mist - new(226, 05, GS) {OT_Names = PCNYx, Moves = new(016), EggCycles = 10, Language = International}, // Mantine Gust + new(054, 05, GS) {TrainerNames = PCNYx, Moves = new(161), EggCycles = 10, Language = International}, // Psyduck Tri Attack + new(072, 05, GS) {TrainerNames = PCNYx, Moves = new(109), EggCycles = 10, Language = International}, // Tentacool Confuse Ray + new(131, 05, GS) {TrainerNames = PCNYx, Moves = new(044), EggCycles = 10, Language = International}, // Lapras Bite + new(170, 05, GS) {TrainerNames = PCNYx, Moves = new(113), EggCycles = 10, Language = International}, // Chinchou Light Screen + new(223, 05, GS) {TrainerNames = PCNYx, Moves = new(054), EggCycles = 10, Language = International}, // Remoraid Mist + new(226, 05, GS) {TrainerNames = PCNYx, Moves = new(016), EggCycles = 10, Language = International}, // Mantine Gust // Safari Week (August 9 to 29, 2002) - new(029, 05, GS) {OT_Names = PCNYx, Moves = new(236), EggCycles = 10, Language = International}, // Nidoran (F) Moonlight - new(032, 05, GS) {OT_Names = PCNYx, Moves = new(234), EggCycles = 10, Language = International}, // Nidoran (M) Morning Sun - new(113, 05, GS) {OT_Names = PCNYx, Moves = new(230), EggCycles = 10, Language = International}, // Chansey Sweet Scent - new(115, 05, GS) {OT_Names = PCNYx, Moves = new(185), EggCycles = 10, Language = International}, // Kangaskhan Faint Attack - new(128, 05, GS) {OT_Names = PCNYx, Moves = new(098), EggCycles = 10, Language = International}, // Tauros Quick Attack - new(147, 05, GS) {OT_Names = PCNYx, Moves = new(056), EggCycles = 10, Language = International}, // Dratini Hydro Pump + new(029, 05, GS) {TrainerNames = PCNYx, Moves = new(236), EggCycles = 10, Language = International}, // Nidoran (F) Moonlight + new(032, 05, GS) {TrainerNames = PCNYx, Moves = new(234), EggCycles = 10, Language = International}, // Nidoran (M) Morning Sun + new(113, 05, GS) {TrainerNames = PCNYx, Moves = new(230), EggCycles = 10, Language = International}, // Chansey Sweet Scent + new(115, 05, GS) {TrainerNames = PCNYx, Moves = new(185), EggCycles = 10, Language = International}, // Kangaskhan Faint Attack + new(128, 05, GS) {TrainerNames = PCNYx, Moves = new(098), EggCycles = 10, Language = International}, // Tauros Quick Attack + new(147, 05, GS) {TrainerNames = PCNYx, Moves = new(056), EggCycles = 10, Language = International}, // Dratini Hydro Pump // Sky Week (August 30 to September 26, 2002) - new(021, 05, GS) {OT_Names = PCNYx, Moves = new(049), EggCycles = 10, Language = International}, // Spearow SonicBoom - new(083, 05, GS) {OT_Names = PCNYx, Moves = new(210), EggCycles = 10, Language = International}, // Farfetch'd Fury Cutter - new(084, 05, GS) {OT_Names = PCNYx, Moves = new(067), EggCycles = 10, Language = International}, // Doduo Low Kick - new(177, 05, GS) {OT_Names = PCNYx, Moves = new(219), EggCycles = 10, Language = International}, // Natu Safeguard - new(198, 05, GS) {OT_Names = PCNYx, Moves = new(251), EggCycles = 10, Language = International}, // Murkrow Beat Up - new(227, 05, GS) {OT_Names = PCNYx, Moves = new(210), EggCycles = 10, Language = International}, // Skarmory Fury Cutter + new(021, 05, GS) {TrainerNames = PCNYx, Moves = new(049), EggCycles = 10, Language = International}, // Spearow SonicBoom + new(083, 05, GS) {TrainerNames = PCNYx, Moves = new(210), EggCycles = 10, Language = International}, // Farfetch'd Fury Cutter + new(084, 05, GS) {TrainerNames = PCNYx, Moves = new(067), EggCycles = 10, Language = International}, // Doduo Low Kick + new(177, 05, GS) {TrainerNames = PCNYx, Moves = new(219), EggCycles = 10, Language = International}, // Natu Safeguard + new(198, 05, GS) {TrainerNames = PCNYx, Moves = new(251), EggCycles = 10, Language = International}, // Murkrow Beat Up + new(227, 05, GS) {TrainerNames = PCNYx, Moves = new(210), EggCycles = 10, Language = International}, // Skarmory Fury Cutter // The Kanto Initial Three Pokémon (September 27 to October 3, 2002) - new(150, 05, C) {OT_Names = PCNYx, CurrentLevel = 70, Shiny = Shiny.Always, Location = 127, Language = International}, // Shiny Mewtwo + new(150, 05, C) {TrainerNames = PCNYx, CurrentLevel = 70, Shiny = Shiny.Always, Location = 127, Language = International}, // Shiny Mewtwo // Power Plant Pokémon (October 4 to October 10, 2002) - new(172, 05, GS) {OT_Names = PCNYx, Moves = new(146), EggCycles = 10, Language = International}, // Pichu Dizzy Punch - new(081, 05, GS) {OT_Names = PCNYx, Moves = new(097), EggCycles = 10, Language = International}, // Magnemite Agility - new(239, 05, GS) {OT_Names = PCNYx, Moves = new(146), EggCycles = 10, Language = International}, // Elekid Dizzy Punch - new(100, 05, GS) {OT_Names = PCNYx, Moves = new(097), EggCycles = 10, Language = International}, // Voltorb Agility + new(172, 05, GS) {TrainerNames = PCNYx, Moves = new(146), EggCycles = 10, Language = International}, // Pichu Dizzy Punch + new(081, 05, GS) {TrainerNames = PCNYx, Moves = new(097), EggCycles = 10, Language = International}, // Magnemite Agility + new(239, 05, GS) {TrainerNames = PCNYx, Moves = new(146), EggCycles = 10, Language = International}, // Elekid Dizzy Punch + new(100, 05, GS) {TrainerNames = PCNYx, Moves = new(097), EggCycles = 10, Language = International}, // Voltorb Agility // Scary Face Pokémon (October 25 to October 31, 2002) - new(173, 05, GS) {OT_Names = PCNYx, Moves = new(184), EggCycles = 10, Language = International}, // Cleffa Scary Face - new(174, 05, GS) {OT_Names = PCNYx, Moves = new(184), EggCycles = 10, Language = International}, // Igglybuff Scary Face - new(183, 05, GS) {OT_Names = PCNYx, Moves = new(184), EggCycles = 10, Language = International}, // Marill Scary Face - new(172, 05, GS) {OT_Names = PCNYx, Moves = new(184), EggCycles = 10, Language = International}, // Pichu Scary Face - new(194, 05, GS) {OT_Names = PCNYx, Moves = new(184), EggCycles = 10, Language = International}, // Wooper Scary Face + new(173, 05, GS) {TrainerNames = PCNYx, Moves = new(184), EggCycles = 10, Language = International}, // Cleffa Scary Face + new(174, 05, GS) {TrainerNames = PCNYx, Moves = new(184), EggCycles = 10, Language = International}, // Igglybuff Scary Face + new(183, 05, GS) {TrainerNames = PCNYx, Moves = new(184), EggCycles = 10, Language = International}, // Marill Scary Face + new(172, 05, GS) {TrainerNames = PCNYx, Moves = new(184), EggCycles = 10, Language = International}, // Pichu Scary Face + new(194, 05, GS) {TrainerNames = PCNYx, Moves = new(184), EggCycles = 10, Language = International}, // Wooper Scary Face // Silver Cave (November 1 to November 7, 2002) - new(114, 05, GS) {OT_Names = PCNYx, Moves = new(235), EggCycles = 10, Language = International}, // Tangela Synthesis - new(077, 05, GS) {OT_Names = PCNYx, Moves = new(067), EggCycles = 10, Language = International}, // Ponyta Low Kick - new(200, 05, GS) {OT_Names = PCNYx, Moves = new(095), EggCycles = 10, Language = International}, // Misdreavus Hypnosis - new(246, 05, GS) {OT_Names = PCNYx, Moves = new(099), EggCycles = 10, Language = International}, // Larvitar Rage + new(114, 05, GS) {TrainerNames = PCNYx, Moves = new(235), EggCycles = 10, Language = International}, // Tangela Synthesis + new(077, 05, GS) {TrainerNames = PCNYx, Moves = new(067), EggCycles = 10, Language = International}, // Ponyta Low Kick + new(200, 05, GS) {TrainerNames = PCNYx, Moves = new(095), EggCycles = 10, Language = International}, // Misdreavus Hypnosis + new(246, 05, GS) {TrainerNames = PCNYx, Moves = new(099), EggCycles = 10, Language = International}, // Larvitar Rage // Union Cave Pokémon (November 8 to 14, 2002) - new(120, 05, GS) {OT_Names = PCNYx, Moves = new(239), EggCycles = 10, Language = International}, // Staryu Twister - new(098, 05, GS) {OT_Names = PCNYx, Moves = new(232), EggCycles = 10, Language = International}, // Krabby Metal Claw - new(095, 05, GS) {OT_Names = PCNYx, Moves = new(159), EggCycles = 10, Language = International}, // Onix Sharpen - new(131, 05, GS) {OT_Names = PCNYx, Moves = new(248), EggCycles = 10, Language = International}, // Lapras Future Sight + new(120, 05, GS) {TrainerNames = PCNYx, Moves = new(239), EggCycles = 10, Language = International}, // Staryu Twister + new(098, 05, GS) {TrainerNames = PCNYx, Moves = new(232), EggCycles = 10, Language = International}, // Krabby Metal Claw + new(095, 05, GS) {TrainerNames = PCNYx, Moves = new(159), EggCycles = 10, Language = International}, // Onix Sharpen + new(131, 05, GS) {TrainerNames = PCNYx, Moves = new(248), EggCycles = 10, Language = International}, // Lapras Future Sight // Johto Legendary (November 15 to 21, 2002) - new(250, 05, C) {OT_Names = PCNYx, CurrentLevel = 40, Shiny = Shiny.Always, Location = 127, Language = International}, // Shiny Ho-Oh - new(249, 05, C) {OT_Names = PCNYx, CurrentLevel = 40, Shiny = Shiny.Always, Location = 127, Language = International}, // Shiny Lugia + new(250, 05, C) {TrainerNames = PCNYx, CurrentLevel = 40, Shiny = Shiny.Always, Location = 127, Language = International}, // Shiny Ho-Oh + new(249, 05, C) {TrainerNames = PCNYx, CurrentLevel = 40, Shiny = Shiny.Always, Location = 127, Language = International}, // Shiny Lugia // Celebi Present SP (November 22 to 28, 2002) - new(151, 05, C) {OT_Names = PCNYx, Shiny = Shiny.Always, Location = 127, Language = International}, // Shiny Mew + new(151, 05, C) {TrainerNames = PCNYx, Shiny = Shiny.Always, Location = 127, Language = International}, // Shiny Mew // Psychic Type Pokémon (November 29 to December 5, 2002) - new(063, 05, GS) {OT_Names = PCNYx, Moves = new(193), EggCycles = 10, Language = International}, // Abra Foresight - new(096, 05, GS) {OT_Names = PCNYx, Moves = new(133), EggCycles = 10, Language = International}, // Drowzee Amnesia - new(102, 05, GS) {OT_Names = PCNYx, Moves = new(230), EggCycles = 10, Language = International}, // Exeggcute Sweet Scent - new(122, 05, GS) {OT_Names = PCNYx, Moves = new(170), EggCycles = 10, Language = International}, // Mr. Mime Mind Reader + new(063, 05, GS) {TrainerNames = PCNYx, Moves = new(193), EggCycles = 10, Language = International}, // Abra Foresight + new(096, 05, GS) {TrainerNames = PCNYx, Moves = new(133), EggCycles = 10, Language = International}, // Drowzee Amnesia + new(102, 05, GS) {TrainerNames = PCNYx, Moves = new(230), EggCycles = 10, Language = International}, // Exeggcute Sweet Scent + new(122, 05, GS) {TrainerNames = PCNYx, Moves = new(170), EggCycles = 10, Language = International}, // Mr. Mime Mind Reader // The Johto Initial Three Pokémon (December 6 to 12, 2002) - new(154, 05, C) {OT_Names = PCNYx, CurrentLevel = 40, Shiny = Shiny.Always, Location = 127, Language = International}, // Shiny Meganium - new(157, 05, C) {OT_Names = PCNYx, CurrentLevel = 40, Shiny = Shiny.Always, Location = 127, Language = International}, // Shiny Typhlosion - new(160, 05, C) {OT_Names = PCNYx, CurrentLevel = 40, Shiny = Shiny.Always, Location = 127, Language = International}, // Shiny Feraligatr + new(154, 05, C) {TrainerNames = PCNYx, CurrentLevel = 40, Shiny = Shiny.Always, Location = 127, Language = International}, // Shiny Meganium + new(157, 05, C) {TrainerNames = PCNYx, CurrentLevel = 40, Shiny = Shiny.Always, Location = 127, Language = International}, // Shiny Typhlosion + new(160, 05, C) {TrainerNames = PCNYx, CurrentLevel = 40, Shiny = Shiny.Always, Location = 127, Language = International}, // Shiny Feraligatr // Rock Tunnel Pokémon (December 13 to December 19, 2002) - new(074, 05, GS) {OT_Names = PCNYx, Moves = new(229), EggCycles = 10, Language = International}, // Geodude Rapid Spin - new(041, 05, GS) {OT_Names = PCNYx, Moves = new(175), EggCycles = 10, Language = International}, // Zubat Flail - new(066, 05, GS) {OT_Names = PCNYx, Moves = new(037), EggCycles = 10, Language = International}, // Machop Thrash - new(104, 05, GS) {OT_Names = PCNYx, Moves = new(031), EggCycles = 10, Language = International}, // Cubone Fury Attack + new(074, 05, GS) {TrainerNames = PCNYx, Moves = new(229), EggCycles = 10, Language = International}, // Geodude Rapid Spin + new(041, 05, GS) {TrainerNames = PCNYx, Moves = new(175), EggCycles = 10, Language = International}, // Zubat Flail + new(066, 05, GS) {TrainerNames = PCNYx, Moves = new(037), EggCycles = 10, Language = International}, // Machop Thrash + new(104, 05, GS) {TrainerNames = PCNYx, Moves = new(031), EggCycles = 10, Language = International}, // Cubone Fury Attack // Ice Type Pokémon (December 20 to 26, 2002) - new(225, 05, GS) {OT_Names = PCNYx, Moves = new(191), EggCycles = 10, Language = International}, // Delibird Spikes - new(086, 05, GS) {OT_Names = PCNYx, Moves = new(175), EggCycles = 10, Language = International}, // Seel Flail - new(220, 05, GS) {OT_Names = PCNYx, Moves = new(018), EggCycles = 10, Language = International}, // Swinub Whirlwind + new(225, 05, GS) {TrainerNames = PCNYx, Moves = new(191), EggCycles = 10, Language = International}, // Delibird Spikes + new(086, 05, GS) {TrainerNames = PCNYx, Moves = new(175), EggCycles = 10, Language = International}, // Seel Flail + new(220, 05, GS) {TrainerNames = PCNYx, Moves = new(018), EggCycles = 10, Language = International}, // Swinub Whirlwind // Pokémon that Appear at Night only (December 27, 2002, to January 2, 2003) - new(163, 05, GS) {OT_Names = PCNYx, Moves = new(101), EggCycles = 10, Language = International}, // Hoothoot Night Shade - new(215, 05, GS) {OT_Names = PCNYx, Moves = new(236), EggCycles = 10, Language = International}, // Sneasel Moonlight + new(163, 05, GS) {TrainerNames = PCNYx, Moves = new(101), EggCycles = 10, Language = International}, // Hoothoot Night Shade + new(215, 05, GS) {TrainerNames = PCNYx, Moves = new(236), EggCycles = 10, Language = International}, // Sneasel Moonlight // Grass Type ( January 3 to 9, 2003) - new(191, 05, GS) {OT_Names = PCNYx, Moves = new(150), EggCycles = 10, Language = International}, // Sunkern Splash - new(046, 05, GS) {OT_Names = PCNYx, Moves = new(235), EggCycles = 10, Language = International}, // Paras Synthesis - new(187, 05, GS) {OT_Names = PCNYx, Moves = new(097), EggCycles = 10, Language = International}, // Hoppip Agility - new(043, 05, GS) {OT_Names = PCNYx, Moves = new(073), EggCycles = 10, Language = International}, // Oddish Leech Seed + new(191, 05, GS) {TrainerNames = PCNYx, Moves = new(150), EggCycles = 10, Language = International}, // Sunkern Splash + new(046, 05, GS) {TrainerNames = PCNYx, Moves = new(235), EggCycles = 10, Language = International}, // Paras Synthesis + new(187, 05, GS) {TrainerNames = PCNYx, Moves = new(097), EggCycles = 10, Language = International}, // Hoppip Agility + new(043, 05, GS) {TrainerNames = PCNYx, Moves = new(073), EggCycles = 10, Language = International}, // Oddish Leech Seed // Normal Pokémon (January 10 to 16, 2003) - new(161, 05, GS) {OT_Names = PCNYx, Moves = new(146), EggCycles = 10, Language = International}, // Sentret Dizzy Punch - new(234, 05, GS) {OT_Names = PCNYx, Moves = new(219), EggCycles = 10, Language = International}, // Stantler Safeguard - new(241, 05, GS) {OT_Names = PCNYx, Moves = new(025), EggCycles = 10, Language = International}, // Miltank Mega Kick - new(190, 05, GS) {OT_Names = PCNYx, Moves = new(102), EggCycles = 10, Language = International}, // Aipom Mimic - new(108, 05, GS) {OT_Names = PCNYx, Moves = new(003), EggCycles = 10, Language = International}, // Lickitung DoubleSlap - new(143, 05, GS) {OT_Names = PCNYx, Moves = new(150), EggCycles = 10, Language = International}, // Snorlax Splash + new(161, 05, GS) {TrainerNames = PCNYx, Moves = new(146), EggCycles = 10, Language = International}, // Sentret Dizzy Punch + new(234, 05, GS) {TrainerNames = PCNYx, Moves = new(219), EggCycles = 10, Language = International}, // Stantler Safeguard + new(241, 05, GS) {TrainerNames = PCNYx, Moves = new(025), EggCycles = 10, Language = International}, // Miltank Mega Kick + new(190, 05, GS) {TrainerNames = PCNYx, Moves = new(102), EggCycles = 10, Language = International}, // Aipom Mimic + new(108, 05, GS) {TrainerNames = PCNYx, Moves = new(003), EggCycles = 10, Language = International}, // Lickitung DoubleSlap + new(143, 05, GS) {TrainerNames = PCNYx, Moves = new(150), EggCycles = 10, Language = International}, // Snorlax Splash // Mt. Mortar (January 24 to 30, 2003) - new(066, 05, GS) {OT_Names = PCNYx, Moves = new(206), EggCycles = 10, Language = International}, // Machop False Swipe - new(129, 05, GS) {OT_Names = PCNYx, Moves = new(145), EggCycles = 10, Language = International}, // Magikarp Bubble - new(236, 05, GS) {OT_Names = PCNYx, Moves = new(099), EggCycles = 10, Language = International}, // Tyrogue Rage + new(066, 05, GS) {TrainerNames = PCNYx, Moves = new(206), EggCycles = 10, Language = International}, // Machop False Swipe + new(129, 05, GS) {TrainerNames = PCNYx, Moves = new(145), EggCycles = 10, Language = International}, // Magikarp Bubble + new(236, 05, GS) {TrainerNames = PCNYx, Moves = new(099), EggCycles = 10, Language = International}, // Tyrogue Rage // Dark Cave Pokémon (January 31 to February 6, 2003) - new(206, 05, GS) {OT_Names = PCNYx, Moves = new(031), EggCycles = 10, Language = International}, // Dunsparce Fury Attack - new(202, 05, GS) {OT_Names = PCNYx, Moves = new(102), EggCycles = 10, Language = International}, // Wobbuffet Mimic - new(231, 05, GS) {OT_Names = PCNYx, Moves = new(071), EggCycles = 10, Language = International}, // Phanpy Absorb - new(216, 05, GS) {OT_Names = PCNYx, Moves = new(230), EggCycles = 10, Language = International}, // Teddiursa Sweet Scent + new(206, 05, GS) {TrainerNames = PCNYx, Moves = new(031), EggCycles = 10, Language = International}, // Dunsparce Fury Attack + new(202, 05, GS) {TrainerNames = PCNYx, Moves = new(102), EggCycles = 10, Language = International}, // Wobbuffet Mimic + new(231, 05, GS) {TrainerNames = PCNYx, Moves = new(071), EggCycles = 10, Language = International}, // Phanpy Absorb + new(216, 05, GS) {TrainerNames = PCNYx, Moves = new(230), EggCycles = 10, Language = International}, // Teddiursa Sweet Scent // Valentine's Day Special (February 7 to 13, 2003) - new(060, 05, GS) {OT_Names = PCNYx, Moves = new(186), EggCycles = 10, Language = International}, // Poliwag Sweet Kiss - new(060, 05, GS) {OT_Names = PCNYx, Moves = new(142), EggCycles = 10, Language = International}, // Poliwag Lovely Kiss - new(143, 05, GS) {OT_Names = PCNYx, Moves = new(186), EggCycles = 10, Language = International}, // Snorlax Sweet Kiss - new(143, 05, GS) {OT_Names = PCNYx, Moves = new(142), EggCycles = 10, Language = International}, // Snorlax Lovely Kiss + new(060, 05, GS) {TrainerNames = PCNYx, Moves = new(186), EggCycles = 10, Language = International}, // Poliwag Sweet Kiss + new(060, 05, GS) {TrainerNames = PCNYx, Moves = new(142), EggCycles = 10, Language = International}, // Poliwag Lovely Kiss + new(143, 05, GS) {TrainerNames = PCNYx, Moves = new(186), EggCycles = 10, Language = International}, // Snorlax Sweet Kiss + new(143, 05, GS) {TrainerNames = PCNYx, Moves = new(142), EggCycles = 10, Language = International}, // Snorlax Lovely Kiss // Rare Pokémon (February 21 to 27, 2003) - new(140, 05, GS) {OT_Names = PCNYx, Moves = new(088), EggCycles = 10, Language = International}, // Kabuto Rock Throw - new(138, 05, GS) {OT_Names = PCNYx, Moves = new(088), EggCycles = 10, Language = International}, // Omanyte Rock Throw - new(142, 05, GS) {OT_Names = PCNYx, Moves = new(088), EggCycles = 10, Language = International}, // Aerodactyl Rock Throw - new(137, 05, GS) {OT_Names = PCNYx, Moves = new(112), EggCycles = 10, Language = International}, // Porygon Barrier - new(133, 05, GS) {OT_Names = PCNYx, Moves = new(074), EggCycles = 10, Language = International}, // Eevee Growth - new(185, 05, GS) {OT_Names = PCNYx, Moves = new(164), EggCycles = 10, Language = International}, // Sudowoodo Substitute + new(140, 05, GS) {TrainerNames = PCNYx, Moves = new(088), EggCycles = 10, Language = International}, // Kabuto Rock Throw + new(138, 05, GS) {TrainerNames = PCNYx, Moves = new(088), EggCycles = 10, Language = International}, // Omanyte Rock Throw + new(142, 05, GS) {TrainerNames = PCNYx, Moves = new(088), EggCycles = 10, Language = International}, // Aerodactyl Rock Throw + new(137, 05, GS) {TrainerNames = PCNYx, Moves = new(112), EggCycles = 10, Language = International}, // Porygon Barrier + new(133, 05, GS) {TrainerNames = PCNYx, Moves = new(074), EggCycles = 10, Language = International}, // Eevee Growth + new(185, 05, GS) {TrainerNames = PCNYx, Moves = new(164), EggCycles = 10, Language = International}, // Sudowoodo Substitute // Bug Type Pokémon (February 28 to March 6, 2003) - new(123, 05, GS) {OT_Names = PCNYx, Moves = new(049), EggCycles = 10, Language = International}, // Scyther SonicBoom - new(214, 05, GS) {OT_Names = PCNYx, Moves = new(069), EggCycles = 10, Language = International}, // Heracross Seismic Toss - new(127, 05, GS) {OT_Names = PCNYx, Moves = new(088), EggCycles = 10, Language = International}, // Pinsir Rock Throw - new(165, 05, GS) {OT_Names = PCNYx, Moves = new(112), EggCycles = 10, Language = International}, // Ledyba Barrier - new(167, 05, GS) {OT_Names = PCNYx, Moves = new(074), EggCycles = 10, Language = International}, // Spinarak Growth - new(193, 05, GS) {OT_Names = PCNYx, Moves = new(186), EggCycles = 10, Language = International}, // Yanma Sweet Kiss - new(204, 05, GS) {OT_Names = PCNYx, Moves = new(164), EggCycles = 10, Language = International}, // Pineco Substitute + new(123, 05, GS) {TrainerNames = PCNYx, Moves = new(049), EggCycles = 10, Language = International}, // Scyther SonicBoom + new(214, 05, GS) {TrainerNames = PCNYx, Moves = new(069), EggCycles = 10, Language = International}, // Heracross Seismic Toss + new(127, 05, GS) {TrainerNames = PCNYx, Moves = new(088), EggCycles = 10, Language = International}, // Pinsir Rock Throw + new(165, 05, GS) {TrainerNames = PCNYx, Moves = new(112), EggCycles = 10, Language = International}, // Ledyba Barrier + new(167, 05, GS) {TrainerNames = PCNYx, Moves = new(074), EggCycles = 10, Language = International}, // Spinarak Growth + new(193, 05, GS) {TrainerNames = PCNYx, Moves = new(186), EggCycles = 10, Language = International}, // Yanma Sweet Kiss + new(204, 05, GS) {TrainerNames = PCNYx, Moves = new(164), EggCycles = 10, Language = International}, // Pineco Substitute // Japanese Only (all below) new(251, 30, GSC) {Location = 014}, // Celebi @ Ilex Forest (GBC) diff --git a/PKHeX.Core/Legality/Encounters/Data/Gen3/Encounters3Colo.cs b/PKHeX.Core/Legality/Encounters/Data/Gen3/Encounters3Colo.cs index d295a4cf0..c47c8555f 100644 --- a/PKHeX.Core/Legality/Encounters/Data/Gen3/Encounters3Colo.cs +++ b/PKHeX.Core/Legality/Encounters/Data/Gen3/Encounters3Colo.cs @@ -16,7 +16,7 @@ internal static class Encounters3Colo internal static readonly EncounterGift3Colo[] Gifts = [ // In-Game without Bonus Disk - new(311, 13, TrainerNameDuking, GameVersion.CXD) { Location = 254, TID16 = 37149, OT_Gender = 0, Moves = new(045, 086, 098, 270) }, // Plusle @ Ingame Trade + new(311, 13, TrainerNameDuking, GameVersion.CXD) { Location = 254, TID16 = 37149, OriginalTrainerGender = 0, Moves = new(045, 086, 098, 270) }, // Plusle @ Ingame Trade ]; internal static readonly EncounterShadow3Colo[] Shadow = diff --git a/PKHeX.Core/Legality/Encounters/Data/Gen3/Encounters3FRLG.cs b/PKHeX.Core/Legality/Encounters/Data/Gen3/Encounters3FRLG.cs index 264e5a502..98e383441 100644 --- a/PKHeX.Core/Legality/Encounters/Data/Gen3/Encounters3FRLG.cs +++ b/PKHeX.Core/Legality/Encounters/Data/Gen3/Encounters3FRLG.cs @@ -15,7 +15,7 @@ internal static class Encounters3FRLG internal static readonly EncounterArea3[] SlotsFR = GetRegular("fr", "fr"u8, FR); internal static readonly EncounterArea3[] SlotsLG = GetRegular("lg", "lg"u8, LG); - private static EncounterArea3[] GetRegular([ConstantExpected] string resource, [Length(2, 2)] ReadOnlySpan ident, GameVersion game) => EncounterArea3.GetAreas(Get(resource, ident), game); + private static EncounterArea3[] GetRegular([ConstantExpected] string resource, [Length(2, 2)] ReadOnlySpan ident, [ConstantExpected] GameVersion game) => EncounterArea3.GetAreas(Get(resource, ident), game); private const string tradeFRLG = "tradefrlg"; private static readonly string[][] TradeNames = Util.GetLanguageStrings7(tradeFRLG); diff --git a/PKHeX.Core/Legality/Encounters/Data/Gen3/Encounters3RSE.cs b/PKHeX.Core/Legality/Encounters/Data/Gen3/Encounters3RSE.cs index 07798d81b..0f4ff4325 100644 --- a/PKHeX.Core/Legality/Encounters/Data/Gen3/Encounters3RSE.cs +++ b/PKHeX.Core/Legality/Encounters/Data/Gen3/Encounters3RSE.cs @@ -17,9 +17,9 @@ internal static class Encounters3RSE internal static readonly EncounterArea3[] SlotsS = GetRegular("s", "sa"u8, S); internal static readonly EncounterArea3[] SlotsE = GetRegular("e", "em"u8, E); - private static EncounterArea3[] GetRegular([ConstantExpected] string resource, [Length(2, 2)] ReadOnlySpan ident, GameVersion game) + private static EncounterArea3[] GetRegular([ConstantExpected] string resource, [Length(2, 2)] ReadOnlySpan ident, [ConstantExpected] GameVersion game) => EncounterArea3.GetAreas(Get(resource, ident), game); - private static EncounterArea3[] GetSwarm([ConstantExpected] string resource, [Length(2, 2)] ReadOnlySpan ident, GameVersion game) + private static EncounterArea3[] GetSwarm([ConstantExpected] string resource, [Length(2, 2)] ReadOnlySpan ident, [ConstantExpected] GameVersion game) => EncounterArea3.GetAreasSwarm(Get(resource, ident), game); private static readonly string[] TrainersPikachu = [string.Empty, "コロシアム", "COLOS", "COLOSSEUM", "ARENA", "COLOSSEUM", string.Empty, "CLAUDIO"]; @@ -29,14 +29,14 @@ private static EncounterArea3[] GetSwarm([ConstantExpected] string resource, [Le internal static readonly EncounterGift3Colo[] ColoGiftsR = [ // In-Game Bonus Disk (Japan only) - new(025, 10, TrainersPikachu, R) { Location = 255, TID16 = 31121, OT_Gender = 0 }, // Colosseum Pikachu bonus gift - new(251, 10, TrainersCelebi, R) { Location = 255, TID16 = 31121, OT_Gender = 1 }, // Ageto Celebi bonus gift + new(025, 10, TrainersPikachu, R) { Location = 255, TID16 = 31121, OriginalTrainerGender = 0 }, // Colosseum Pikachu bonus gift + new(251, 10, TrainersCelebi, R) { Location = 255, TID16 = 31121, OriginalTrainerGender = 1 }, // Ageto Celebi bonus gift ]; internal static readonly EncounterGift3Colo[] ColoGiftsS = [ // In-Game without Bonus Disk - new(250, 70, TrainersMattle, S) { Location = 255, TID16 = 10048, OT_Gender = 0, Moves = new(105, 126, 241, 129) }, // Ho-oh @ Mt. Battle + new(250, 70, TrainersMattle, S) { Location = 255, TID16 = 10048, OriginalTrainerGender = 0, Moves = new(105, 126, 241, 129) }, // Ho-oh @ Mt. Battle ]; private const string tradeRSE = "traderse"; diff --git a/PKHeX.Core/Legality/Encounters/Data/Gen3/EncountersWC3.cs b/PKHeX.Core/Legality/Encounters/Data/Gen3/EncountersWC3.cs index bda92fadd..62b18b704 100644 --- a/PKHeX.Core/Legality/Encounters/Data/Gen3/EncountersWC3.cs +++ b/PKHeX.Core/Legality/Encounters/Data/Gen3/EncountersWC3.cs @@ -1,3 +1,8 @@ +using static PKHeX.Core.GameVersion; +using static PKHeX.Core.PIDType; +using static PKHeX.Core.Shiny; +using static PKHeX.Core.LanguageID; + namespace PKHeX.Core; /// @@ -11,7 +16,7 @@ internal static class EncountersWC3 { internal static readonly WC3[] Encounter_Event3_Special = [ - new() { Species = 385, Level = 05, ID32 = 20043, OT_Gender = 0, Version = GameVersion.R, Method = PIDType.BACD_R, OT_Name = "WISHMKR", CardTitle = "Wishmaker Jirachi", Language = (int)LanguageID.English }, + new(R) { Species = 385, Level = 05, ID32 = 20043, OriginalTrainerGender = 0, Method = BACD_R, OriginalTrainerName = "WISHMKR", CardTitle = "Wishmaker Jirachi", Language = (int)English }, ]; internal static readonly WC3[] Encounter_Event3 = Encounter_Event3_Special; @@ -19,215 +24,215 @@ internal static class EncountersWC3 internal static readonly WC3[] Encounter_Event3_FRLG = [ // PCJP - Egg Pokémon Present Eggs (March 21 to April 4, 2004) - new(true) { Species = 043, IsEgg = true, Level = 05, Version = GameVersion.FRLG, Moves = new(071,073,000,000), Method = PIDType.Method_2 }, // Oddish with Leech Seed - new(true) { Species = 052, IsEgg = true, Level = 05, Version = GameVersion.FRLG, Moves = new(010,045,080,000), Method = PIDType.Method_2 }, // Meowth with Petal Dance - new(true) { Species = 060, IsEgg = true, Level = 05, Version = GameVersion.FRLG, Moves = new(145,186,000,000), Method = PIDType.Method_2 }, // Poliwag with Sweet Kiss - new(true) { Species = 069, IsEgg = true, Level = 05, Version = GameVersion.FRLG, Moves = new(022,298,000,000), Method = PIDType.Method_2 }, // Bellsprout with Teeter Dance + new(FRLG, true) { Species = 043, IsEgg = true, Level = 05, Moves = new(071,073,000,000), Method = Method_2 }, // Oddish with Leech Seed + new(FRLG, true) { Species = 052, IsEgg = true, Level = 05, Moves = new(010,045,080,000), Method = Method_2 }, // Meowth with Petal Dance + new(FRLG, true) { Species = 060, IsEgg = true, Level = 05, Moves = new(145,186,000,000), Method = Method_2 }, // Poliwag with Sweet Kiss + new(FRLG, true) { Species = 069, IsEgg = true, Level = 05, Moves = new(022,298,000,000), Method = Method_2 }, // Bellsprout with Teeter Dance // PCNY - Wish Eggs (December 16, 2004, to January 2, 2005) - new(true) { Species = 083, IsEgg = true, Level = 05, Version = GameVersion.FRLG, Moves = new(281,273,000,000), Method = PIDType.Method_2 }, // Farfetch'd with Wish & Yawn - new(true) { Species = 096, IsEgg = true, Level = 05, Version = GameVersion.FRLG, Moves = new(187,273,000,000), Method = PIDType.Method_2 }, // Drowzee with Wish & Belly Drum - new(true) { Species = 102, IsEgg = true, Level = 05, Version = GameVersion.FRLG, Moves = new(230,273,000,000), Method = PIDType.Method_2 }, // Exeggcute with Wish & Sweet Scent - new(true) { Species = 108, IsEgg = true, Level = 05, Version = GameVersion.FRLG, Moves = new(215,273,000,000), Method = PIDType.Method_2 }, // Lickitung with Wish & Heal Bell - new(true) { Species = 113, IsEgg = true, Level = 05, Version = GameVersion.FRLG, Moves = new(230,273,000,000), Method = PIDType.Method_2 }, // Chansey with Wish & Sweet Scent - new(true) { Species = 115, IsEgg = true, Level = 05, Version = GameVersion.FRLG, Moves = new(281,273,000,000), Method = PIDType.Method_2 }, // Kangaskhan with Wish & Yawn + new(FRLG, true) { Species = 083, IsEgg = true, Level = 05, Moves = new(281,273,000,000), Method = Method_2 }, // Farfetch'd with Wish & Yawn + new(FRLG, true) { Species = 096, IsEgg = true, Level = 05, Moves = new(187,273,000,000), Method = Method_2 }, // Drowzee with Wish & Belly Drum + new(FRLG, true) { Species = 102, IsEgg = true, Level = 05, Moves = new(230,273,000,000), Method = Method_2 }, // Exeggcute with Wish & Sweet Scent + new(FRLG, true) { Species = 108, IsEgg = true, Level = 05, Moves = new(215,273,000,000), Method = Method_2 }, // Lickitung with Wish & Heal Bell + new(FRLG, true) { Species = 113, IsEgg = true, Level = 05, Moves = new(230,273,000,000), Method = Method_2 }, // Chansey with Wish & Sweet Scent + new(FRLG, true) { Species = 115, IsEgg = true, Level = 05, Moves = new(281,273,000,000), Method = Method_2 }, // Kangaskhan with Wish & Yawn // PokePark Eggs - Wondercard - new(true) { Species = 054, IsEgg = true, Level = 05, Version = GameVersion.FRLG, Moves = new(346,010,039,300), Method = PIDType.Method_2 }, // Psyduck with Mud Sport - new(true) { Species = 172, IsEgg = true, Level = 05, Version = GameVersion.FRLG, Moves = new(084,204,266,000), Method = PIDType.Method_2 }, // Pichu with Follow me - new(true) { Species = 174, IsEgg = true, Level = 05, Version = GameVersion.FRLG, Moves = new(047,204,111,321), Method = PIDType.Method_2 }, // Igglybuff with Tickle - new(true) { Species = 222, IsEgg = true, Level = 05, Version = GameVersion.FRLG, Moves = new(033,300,000,000), Method = PIDType.Method_2 }, // Corsola with Mud Sport - new(true) { Species = 276, IsEgg = true, Level = 05, Version = GameVersion.FRLG, Moves = new(064,045,116,297), Method = PIDType.Method_2 }, // Taillow with Feather Dance - new(true) { Species = 283, IsEgg = true, Level = 05, Version = GameVersion.FRLG, Moves = new(145,300,000,000), Method = PIDType.Method_2 }, // Surskit with Mud Sport - new(true) { Species = 293, IsEgg = true, Level = 05, Version = GameVersion.FRLG, Moves = new(001,253,298,000), Method = PIDType.Method_2 }, // Whismur with Teeter Dance - new(true) { Species = 300, IsEgg = true, Level = 05, Version = GameVersion.FRLG, Moves = new(045,033,039,205), Method = PIDType.Method_2 }, // Skitty with Rollout - new(true) { Species = 311, IsEgg = true, Level = 05, Version = GameVersion.FRLG, Moves = new(045,086,346,000), Method = PIDType.Method_2 }, // Plusle with Water Sport - new(true) { Species = 312, IsEgg = true, Level = 05, Version = GameVersion.FRLG, Moves = new(045,086,300,000), Method = PIDType.Method_2 }, // Minun with Mud Sport - new(true) { Species = 325, IsEgg = true, Level = 05, Version = GameVersion.FRLG, Moves = new(150,253,000,000), Method = PIDType.Method_2 }, // Spoink with Uproar - new(true) { Species = 327, IsEgg = true, Level = 05, Version = GameVersion.FRLG, Moves = new(033,253,047,000), Method = PIDType.Method_2 }, // Spinda with Sing - new(true) { Species = 331, IsEgg = true, Level = 05, Version = GameVersion.FRLG, Moves = new(040,043,071,227), Method = PIDType.Method_2 }, // Cacnea with Encore - new(true) { Species = 341, IsEgg = true, Level = 05, Version = GameVersion.FRLG, Moves = new(145,346,000,000), Method = PIDType.Method_2 }, // Corphish with Water Sport - new(true) { Species = 360, IsEgg = true, Level = 05, Version = GameVersion.FRLG, Moves = new(150,204,227,321), Method = PIDType.Method_2 }, // Wynaut with Tickle + new(FRLG, true) { Species = 054, IsEgg = true, Level = 05, Moves = new(346,010,039,300), Method = Method_2 }, // Psyduck with Mud Sport + new(FRLG, true) { Species = 172, IsEgg = true, Level = 05, Moves = new(084,204,266,000), Method = Method_2 }, // Pichu with Follow me + new(FRLG, true) { Species = 174, IsEgg = true, Level = 05, Moves = new(047,204,111,321), Method = Method_2 }, // Igglybuff with Tickle + new(FRLG, true) { Species = 222, IsEgg = true, Level = 05, Moves = new(033,300,000,000), Method = Method_2 }, // Corsola with Mud Sport + new(FRLG, true) { Species = 276, IsEgg = true, Level = 05, Moves = new(064,045,116,297), Method = Method_2 }, // Taillow with Feather Dance + new(FRLG, true) { Species = 283, IsEgg = true, Level = 05, Moves = new(145,300,000,000), Method = Method_2 }, // Surskit with Mud Sport + new(FRLG, true) { Species = 293, IsEgg = true, Level = 05, Moves = new(001,253,298,000), Method = Method_2 }, // Whismur with Teeter Dance + new(FRLG, true) { Species = 300, IsEgg = true, Level = 05, Moves = new(045,033,039,205), Method = Method_2 }, // Skitty with Rollout + new(FRLG, true) { Species = 311, IsEgg = true, Level = 05, Moves = new(045,086,346,000), Method = Method_2 }, // Plusle with Water Sport + new(FRLG, true) { Species = 312, IsEgg = true, Level = 05, Moves = new(045,086,300,000), Method = Method_2 }, // Minun with Mud Sport + new(FRLG, true) { Species = 325, IsEgg = true, Level = 05, Moves = new(150,253,000,000), Method = Method_2 }, // Spoink with Uproar + new(FRLG, true) { Species = 327, IsEgg = true, Level = 05, Moves = new(033,253,047,000), Method = Method_2 }, // Spinda with Sing + new(FRLG, true) { Species = 331, IsEgg = true, Level = 05, Moves = new(040,043,071,227), Method = Method_2 }, // Cacnea with Encore + new(FRLG, true) { Species = 341, IsEgg = true, Level = 05, Moves = new(145,346,000,000), Method = Method_2 }, // Corphish with Water Sport + new(FRLG, true) { Species = 360, IsEgg = true, Level = 05, Moves = new(150,204,227,321), Method = Method_2 }, // Wynaut with Tickle ]; internal static readonly WC3[] Encounter_Event3_RS = [ // PCJP - Pokémon Center 5th Anniversary Eggs (April 25 to May 18, 2003) - new() { Species = 172, IsEgg = true, Level = 05, OT_Name = "オヤNAME", Version = GameVersion.R, Moves = new(084,204,298,000), Method = PIDType.BACD_R }, // Pichu with Teeter Dance - new() { Species = 172, IsEgg = true, Level = 05, OT_Name = "オヤNAME", Version = GameVersion.R, Moves = new(084,204,273,000), Method = PIDType.BACD_R }, // Pichu with Wish - new() { Species = 172, IsEgg = true, Level = 05, OT_Name = "オヤNAME", Version = GameVersion.R, Moves = new(084,204,298,000), Method = PIDType.BACD_R_S }, // Pichu with Teeter Dance - new() { Species = 172, IsEgg = true, Level = 05, OT_Name = "オヤNAME", Version = GameVersion.R, Moves = new(084,204,273,000), Method = PIDType.BACD_R_S }, // Pichu with Wish - new() { Species = 280, IsEgg = true, Level = 05, OT_Name = "オヤNAME", Version = GameVersion.R, Moves = new(045,204,000,000), Method = PIDType.BACD_R }, // Ralts with Charm - new() { Species = 280, IsEgg = true, Level = 05, OT_Name = "オヤNAME", Version = GameVersion.R, Moves = new(045,273,000,000), Method = PIDType.BACD_R }, // Ralts with Wish - new() { Species = 359, IsEgg = true, Level = 05, OT_Name = "オヤNAME", Version = GameVersion.R, Moves = new(010,043,180,000), Method = PIDType.BACD_R }, // Absol with Spite - new() { Species = 359, IsEgg = true, Level = 05, OT_Name = "オヤNAME", Version = GameVersion.R, Moves = new(010,043,273,000), Method = PIDType.BACD_R }, // Absol with Wish - new() { Species = 371, IsEgg = true, Level = 05, OT_Name = "オヤNAME", Version = GameVersion.R, Moves = new(099,044,334,000), Method = PIDType.BACD_R }, // Bagon with Iron Defense - new() { Species = 371, IsEgg = true, Level = 05, OT_Name = "オヤNAME", Version = GameVersion.R, Moves = new(099,044,273,000), Method = PIDType.BACD_R }, // Bagon with Wish + new(R) { Species = 172, IsEgg = true, Level = 05, OriginalTrainerName = "オヤNAME", Moves = new(084,204,298,000), Method = BACD_R }, // Pichu with Teeter Dance + new(R) { Species = 172, IsEgg = true, Level = 05, OriginalTrainerName = "オヤNAME", Moves = new(084,204,273,000), Method = BACD_R }, // Pichu with Wish + new(R) { Species = 172, IsEgg = true, Level = 05, OriginalTrainerName = "オヤNAME", Moves = new(084,204,298,000), Method = BACD_R_S }, // Pichu with Teeter Dance + new(R) { Species = 172, IsEgg = true, Level = 05, OriginalTrainerName = "オヤNAME", Moves = new(084,204,273,000), Method = BACD_R_S }, // Pichu with Wish + new(R) { Species = 280, IsEgg = true, Level = 05, OriginalTrainerName = "オヤNAME", Moves = new(045,204,000,000), Method = BACD_R }, // Ralts with Charm + new(R) { Species = 280, IsEgg = true, Level = 05, OriginalTrainerName = "オヤNAME", Moves = new(045,273,000,000), Method = BACD_R }, // Ralts with Wish + new(R) { Species = 359, IsEgg = true, Level = 05, OriginalTrainerName = "オヤNAME", Moves = new(010,043,180,000), Method = BACD_R }, // Absol with Spite + new(R) { Species = 359, IsEgg = true, Level = 05, OriginalTrainerName = "オヤNAME", Moves = new(010,043,273,000), Method = BACD_R }, // Absol with Wish + new(R) { Species = 371, IsEgg = true, Level = 05, OriginalTrainerName = "オヤNAME", Moves = new(099,044,334,000), Method = BACD_R }, // Bagon with Iron Defense + new(R) { Species = 371, IsEgg = true, Level = 05, OriginalTrainerName = "オヤNAME", Moves = new(099,044,273,000), Method = BACD_R }, // Bagon with Wish // Negai Boshi Jirachi - new() { Species = 385, Level = 05, ID32 = 30719, OT_Gender = 0, OT_Name = "ネガイボシ", Version = GameVersion.R, Method = PIDType.BACD_R, Language = (int)LanguageID.Japanese, Shiny = Shiny.Never }, - new() { Species = 385, Level = 05, ID32 = 30719, OT_Name = "ネガイボシ", Version = GameVersion.RS, Method = PIDType.BACD_U_AX, Language = (int)LanguageID.Japanese, Shiny = Shiny.Never }, + new(R) { Species = 385, Level = 05, ID32 = 30719, OriginalTrainerGender = 0, OriginalTrainerName = "ネガイボシ", Method = BACD_R, Language = (int)Japanese, Shiny = Never }, + new(RS) { Species = 385, Level = 05, ID32 = 30719, OriginalTrainerName = "ネガイボシ", Method = BACD_U_AX, Language = (int)Japanese, Shiny = Never }, // Berry Glitch Fix // PCJP - (December 29, 2003, to March 31, 2004) - new() { Species = 263, Level = 5, Version = GameVersion.S, Language = (int)LanguageID.Japanese, Method = PIDType.BACD_R_S, ID32 = 21121, OT_Name = "ルビー", OT_Gender = 1, Shiny = Shiny.Always }, - new() { Species = 263, Level = 5, Version = GameVersion.S, Language = (int)LanguageID.Japanese, Method = PIDType.BACD_R_S, ID32 = 21121, OT_Name = "サファイア", OT_Gender = 0, Shiny = Shiny.Always }, + new(S) { Species = 263, Level = 5, Language = (int)Japanese, Method = BACD_R_S, ID32 = 21121, OriginalTrainerName = "ルビー", OriginalTrainerGender = 1, Shiny = Always }, + new(S) { Species = 263, Level = 5, Language = (int)Japanese, Method = BACD_R_S, ID32 = 21121, OriginalTrainerName = "サファイア", OriginalTrainerGender = 0, Shiny = Always }, // EBGames/GameStop (March 1, 2004, to April 22, 2007), also via multi-game discs - new() { Species = 263, Level = 5, Version = GameVersion.S, Language = (int)LanguageID.English, Method = PIDType.BACD_R_S, ID32 = 30317, OT_Name = "RUBY", OT_Gender = 1 }, - new() { Species = 263, Level = 5, Version = GameVersion.S, Language = (int)LanguageID.English, Method = PIDType.BACD_R_S, ID32 = 30317, OT_Name = "SAPHIRE", OT_Gender = 0 }, + new(S) { Species = 263, Level = 5, Language = (int)English, Method = BACD_R_S, ID32 = 30317, OriginalTrainerName = "RUBY", OriginalTrainerGender = 1 }, + new(S) { Species = 263, Level = 5, Language = (int)English, Method = BACD_R_S, ID32 = 30317, OriginalTrainerName = "SAPHIRE", OriginalTrainerGender = 0 }, // Channel Jirachi - new() { Species = 385, Level = 5, Version = GameVersion.RS, Method = PIDType.Channel, TID16 = 40122, OT_Gender = 3, OT_Name = "CHANNEL", CardTitle = "Channel Jirachi", Met_Level = 0 }, + new(RS) { Species = 385, Level = 5, Method = Channel, TID16 = 40122, OriginalTrainerGender = 3, OriginalTrainerName = "CHANNEL", CardTitle = "Channel Jirachi", MetLevel = 0 }, // Aura Mew - new(true) { Species = 151, Level = 10, Version = GameVersion.R, Language = (int)LanguageID.English, Method = PIDType.BACD_R, ID32 = 20078, OT_Name = "Aura", Shiny = Shiny.Never }, // Mew - new(true) { Species = 151, Level = 10, Version = GameVersion.R, Language = (int)LanguageID.French, Method = PIDType.BACD_R, ID32 = 20078, OT_Name = "Aura", Shiny = Shiny.Never }, // Mew - new(true) { Species = 151, Level = 10, Version = GameVersion.R, Language = (int)LanguageID.Italian, Method = PIDType.BACD_R, ID32 = 20078, OT_Name = "Aura", Shiny = Shiny.Never }, // Mew - new(true) { Species = 151, Level = 10, Version = GameVersion.R, Language = (int)LanguageID.German, Method = PIDType.BACD_R, ID32 = 20078, OT_Name = "Aura", Shiny = Shiny.Never }, // Mew - new(true) { Species = 151, Level = 10, Version = GameVersion.R, Language = (int)LanguageID.Spanish, Method = PIDType.BACD_R, ID32 = 20078, OT_Name = "Aura", Shiny = Shiny.Never }, // Mew + new(R, true) { Species = 151, Level = 10, Language = (int)English, Method = BACD_R, ID32 = 20078, OriginalTrainerName = "Aura", Shiny = Never }, // Mew + new(R, true) { Species = 151, Level = 10, Language = (int)French, Method = BACD_R, ID32 = 20078, OriginalTrainerName = "Aura", Shiny = Never }, // Mew + new(R, true) { Species = 151, Level = 10, Language = (int)Italian, Method = BACD_R, ID32 = 20078, OriginalTrainerName = "Aura", Shiny = Never }, // Mew + new(R, true) { Species = 151, Level = 10, Language = (int)German, Method = BACD_R, ID32 = 20078, OriginalTrainerName = "Aura", Shiny = Never }, // Mew + new(R, true) { Species = 151, Level = 10, Language = (int)Spanish, Method = BACD_R, ID32 = 20078, OriginalTrainerName = "Aura", Shiny = Never }, // Mew // English Events - new() { Species = 006, Level = 70, Version = GameVersion.R, Moves = new(017,163,082,083), Language = (int)LanguageID.English, Method = PIDType.BACD_R, ID32 = 06227, OT_Name = "10ANNIV", Shiny = Shiny.Never }, // Charizard - new() { Species = 025, Level = 70, Version = GameVersion.R, Moves = new(085,097,087,113), Language = (int)LanguageID.English, Method = PIDType.BACD_R, ID32 = 06227, OT_Name = "10ANNIV", Shiny = Shiny.Never }, // Pikachu - new() { Species = 144, Level = 70, Version = GameVersion.R, Moves = new(097,170,058,115), Language = (int)LanguageID.English, Method = PIDType.BACD_R, ID32 = 06227, OT_Name = "10ANNIV", Shiny = Shiny.Never }, // Articuno - new() { Species = 243, Level = 70, Version = GameVersion.R, Moves = new(098,209,115,242), Language = (int)LanguageID.English, Method = PIDType.BACD_R, ID32 = 06227, OT_Name = "10ANNIV", Shiny = Shiny.Never }, // Raikou - new() { Species = 244, Level = 70, Version = GameVersion.R, Moves = new(083,023,053,207), Language = (int)LanguageID.English, Method = PIDType.BACD_R, ID32 = 06227, OT_Name = "10ANNIV", Shiny = Shiny.Never }, // Entei - new() { Species = 245, Level = 70, Version = GameVersion.R, Moves = new(016,062,054,243), Language = (int)LanguageID.English, Method = PIDType.BACD_R, ID32 = 06227, OT_Name = "10ANNIV", Shiny = Shiny.Never }, // Suicune - new() { Species = 249, Level = 70, Version = GameVersion.R, Moves = new(105,056,240,129), Language = (int)LanguageID.English, Method = PIDType.BACD_R, ID32 = 06227, OT_Name = "10ANNIV", Shiny = Shiny.Never }, // Lugia - new() { Species = 250, Level = 70, Version = GameVersion.R, Moves = new(105,126,241,129), Language = (int)LanguageID.English, Method = PIDType.BACD_R, ID32 = 06227, OT_Name = "10ANNIV", Shiny = Shiny.Never }, // Ho-Oh - new() { Species = 380, Level = 70, Version = GameVersion.R, Moves = new(296,094,105,204), Language = (int)LanguageID.English, Method = PIDType.BACD_R, ID32 = 06227, OT_Name = "10ANNIV", Shiny = Shiny.Never }, // Latias - new() { Species = 381, Level = 70, Version = GameVersion.R, Moves = new(295,094,105,349), Language = (int)LanguageID.English, Method = PIDType.BACD_R, ID32 = 06227, OT_Name = "10ANNIV", Shiny = Shiny.Never }, // Latios + new(R) { Species = 006, Level = 70, Moves = new(017,163,082,083), Language = (int)English, Method = BACD_R, ID32 = 06227, OriginalTrainerName = "10ANNIV", Shiny = Never }, // Charizard + new(R) { Species = 025, Level = 70, Moves = new(085,097,087,113), Language = (int)English, Method = BACD_R, ID32 = 06227, OriginalTrainerName = "10ANNIV", Shiny = Never }, // Pikachu + new(R) { Species = 144, Level = 70, Moves = new(097,170,058,115), Language = (int)English, Method = BACD_R, ID32 = 06227, OriginalTrainerName = "10ANNIV", Shiny = Never }, // Articuno + new(R) { Species = 243, Level = 70, Moves = new(098,209,115,242), Language = (int)English, Method = BACD_R, ID32 = 06227, OriginalTrainerName = "10ANNIV", Shiny = Never }, // Raikou + new(R) { Species = 244, Level = 70, Moves = new(083,023,053,207), Language = (int)English, Method = BACD_R, ID32 = 06227, OriginalTrainerName = "10ANNIV", Shiny = Never }, // Entei + new(R) { Species = 245, Level = 70, Moves = new(016,062,054,243), Language = (int)English, Method = BACD_R, ID32 = 06227, OriginalTrainerName = "10ANNIV", Shiny = Never }, // Suicune + new(R) { Species = 249, Level = 70, Moves = new(105,056,240,129), Language = (int)English, Method = BACD_R, ID32 = 06227, OriginalTrainerName = "10ANNIV", Shiny = Never }, // Lugia + new(R) { Species = 250, Level = 70, Moves = new(105,126,241,129), Language = (int)English, Method = BACD_R, ID32 = 06227, OriginalTrainerName = "10ANNIV", Shiny = Never }, // Ho-Oh + new(R) { Species = 380, Level = 70, Moves = new(296,094,105,204), Language = (int)English, Method = BACD_R, ID32 = 06227, OriginalTrainerName = "10ANNIV", Shiny = Never }, // Latias + new(R) { Species = 381, Level = 70, Moves = new(295,094,105,349), Language = (int)English, Method = BACD_R, ID32 = 06227, OriginalTrainerName = "10ANNIV", Shiny = Never }, // Latios // French - new() { Species = 006, Level = 70, Version = GameVersion.R, Moves = new(017,163,082,083), Language = (int)LanguageID.French, Method = PIDType.BACD_R, ID32 = 06227, OT_Name = "10ANNIV", Shiny = Shiny.Never }, // Charizard - new() { Species = 025, Level = 70, Version = GameVersion.R, Moves = new(085,097,087,113), Language = (int)LanguageID.French, Method = PIDType.BACD_R, ID32 = 06227, OT_Name = "10ANNIV", Shiny = Shiny.Never }, // Pikachu - new() { Species = 144, Level = 70, Version = GameVersion.R, Moves = new(097,170,058,115), Language = (int)LanguageID.French, Method = PIDType.BACD_R, ID32 = 06227, OT_Name = "10ANNIV", Shiny = Shiny.Never }, // Articuno - new() { Species = 243, Level = 70, Version = GameVersion.R, Moves = new(098,209,115,242), Language = (int)LanguageID.French, Method = PIDType.BACD_R, ID32 = 06227, OT_Name = "10ANNIV", Shiny = Shiny.Never }, // Raikou - new() { Species = 244, Level = 70, Version = GameVersion.R, Moves = new(083,023,053,207), Language = (int)LanguageID.French, Method = PIDType.BACD_R, ID32 = 06227, OT_Name = "10ANNIV", Shiny = Shiny.Never }, // Entei - new() { Species = 245, Level = 70, Version = GameVersion.R, Moves = new(016,062,054,243), Language = (int)LanguageID.French, Method = PIDType.BACD_R, ID32 = 06227, OT_Name = "10ANNIV", Shiny = Shiny.Never }, // Suicune - new() { Species = 249, Level = 70, Version = GameVersion.R, Moves = new(105,056,240,129), Language = (int)LanguageID.French, Method = PIDType.BACD_R, ID32 = 06227, OT_Name = "10ANNIV", Shiny = Shiny.Never }, // Lugia - new() { Species = 250, Level = 70, Version = GameVersion.R, Moves = new(105,126,241,129), Language = (int)LanguageID.French, Method = PIDType.BACD_R, ID32 = 06227, OT_Name = "10ANNIV", Shiny = Shiny.Never }, // Ho-Oh - new() { Species = 380, Level = 70, Version = GameVersion.R, Moves = new(296,094,105,204), Language = (int)LanguageID.French, Method = PIDType.BACD_R, ID32 = 06227, OT_Name = "10ANNIV", Shiny = Shiny.Never }, // Latias - new() { Species = 381, Level = 70, Version = GameVersion.R, Moves = new(295,094,105,349), Language = (int)LanguageID.French, Method = PIDType.BACD_R, ID32 = 06227, OT_Name = "10ANNIV", Shiny = Shiny.Never }, // Latios + new(R) { Species = 006, Level = 70, Moves = new(017,163,082,083), Language = (int)French, Method = BACD_R, ID32 = 06227, OriginalTrainerName = "10ANNIV", Shiny = Never }, // Charizard + new(R) { Species = 025, Level = 70, Moves = new(085,097,087,113), Language = (int)French, Method = BACD_R, ID32 = 06227, OriginalTrainerName = "10ANNIV", Shiny = Never }, // Pikachu + new(R) { Species = 144, Level = 70, Moves = new(097,170,058,115), Language = (int)French, Method = BACD_R, ID32 = 06227, OriginalTrainerName = "10ANNIV", Shiny = Never }, // Articuno + new(R) { Species = 243, Level = 70, Moves = new(098,209,115,242), Language = (int)French, Method = BACD_R, ID32 = 06227, OriginalTrainerName = "10ANNIV", Shiny = Never }, // Raikou + new(R) { Species = 244, Level = 70, Moves = new(083,023,053,207), Language = (int)French, Method = BACD_R, ID32 = 06227, OriginalTrainerName = "10ANNIV", Shiny = Never }, // Entei + new(R) { Species = 245, Level = 70, Moves = new(016,062,054,243), Language = (int)French, Method = BACD_R, ID32 = 06227, OriginalTrainerName = "10ANNIV", Shiny = Never }, // Suicune + new(R) { Species = 249, Level = 70, Moves = new(105,056,240,129), Language = (int)French, Method = BACD_R, ID32 = 06227, OriginalTrainerName = "10ANNIV", Shiny = Never }, // Lugia + new(R) { Species = 250, Level = 70, Moves = new(105,126,241,129), Language = (int)French, Method = BACD_R, ID32 = 06227, OriginalTrainerName = "10ANNIV", Shiny = Never }, // Ho-Oh + new(R) { Species = 380, Level = 70, Moves = new(296,094,105,204), Language = (int)French, Method = BACD_R, ID32 = 06227, OriginalTrainerName = "10ANNIV", Shiny = Never }, // Latias + new(R) { Species = 381, Level = 70, Moves = new(295,094,105,349), Language = (int)French, Method = BACD_R, ID32 = 06227, OriginalTrainerName = "10ANNIV", Shiny = Never }, // Latios // Italian - new() { Species = 006, Level = 70, Version = GameVersion.R, Moves = new(017,163,082,083), Language = (int)LanguageID.Italian, Method = PIDType.BACD_R, ID32 = 06227, OT_Name = "10ANNI", Shiny = Shiny.Never }, // Charizard - new() { Species = 025, Level = 70, Version = GameVersion.R, Moves = new(085,097,087,113), Language = (int)LanguageID.Italian, Method = PIDType.BACD_R, ID32 = 06227, OT_Name = "10ANNI", Shiny = Shiny.Never }, // Pikachu - new() { Species = 144, Level = 70, Version = GameVersion.R, Moves = new(097,170,058,115), Language = (int)LanguageID.Italian, Method = PIDType.BACD_R, ID32 = 06227, OT_Name = "10ANNI", Shiny = Shiny.Never }, // Articuno - new() { Species = 243, Level = 70, Version = GameVersion.R, Moves = new(098,209,115,242), Language = (int)LanguageID.Italian, Method = PIDType.BACD_R, ID32 = 06227, OT_Name = "10ANNI", Shiny = Shiny.Never }, // Raikou - new() { Species = 244, Level = 70, Version = GameVersion.R, Moves = new(083,023,053,207), Language = (int)LanguageID.Italian, Method = PIDType.BACD_R, ID32 = 06227, OT_Name = "10ANNI", Shiny = Shiny.Never }, // Entei - new() { Species = 245, Level = 70, Version = GameVersion.R, Moves = new(016,062,054,243), Language = (int)LanguageID.Italian, Method = PIDType.BACD_R, ID32 = 06227, OT_Name = "10ANNI", Shiny = Shiny.Never }, // Suicune - new() { Species = 249, Level = 70, Version = GameVersion.R, Moves = new(105,056,240,129), Language = (int)LanguageID.Italian, Method = PIDType.BACD_R, ID32 = 06227, OT_Name = "10ANNI", Shiny = Shiny.Never }, // Lugia - new() { Species = 250, Level = 70, Version = GameVersion.R, Moves = new(105,126,241,129), Language = (int)LanguageID.Italian, Method = PIDType.BACD_R, ID32 = 06227, OT_Name = "10ANNI", Shiny = Shiny.Never }, // Ho-Oh - new() { Species = 380, Level = 70, Version = GameVersion.R, Moves = new(296,094,105,204), Language = (int)LanguageID.Italian, Method = PIDType.BACD_R, ID32 = 06227, OT_Name = "10ANNI", Shiny = Shiny.Never }, // Latias - new() { Species = 381, Level = 70, Version = GameVersion.R, Moves = new(295,094,105,349), Language = (int)LanguageID.Italian, Method = PIDType.BACD_R, ID32 = 06227, OT_Name = "10ANNI", Shiny = Shiny.Never }, // Latios + new(R) { Species = 006, Level = 70, Moves = new(017,163,082,083), Language = (int)Italian, Method = BACD_R, ID32 = 06227, OriginalTrainerName = "10ANNI", Shiny = Never }, // Charizard + new(R) { Species = 025, Level = 70, Moves = new(085,097,087,113), Language = (int)Italian, Method = BACD_R, ID32 = 06227, OriginalTrainerName = "10ANNI", Shiny = Never }, // Pikachu + new(R) { Species = 144, Level = 70, Moves = new(097,170,058,115), Language = (int)Italian, Method = BACD_R, ID32 = 06227, OriginalTrainerName = "10ANNI", Shiny = Never }, // Articuno + new(R) { Species = 243, Level = 70, Moves = new(098,209,115,242), Language = (int)Italian, Method = BACD_R, ID32 = 06227, OriginalTrainerName = "10ANNI", Shiny = Never }, // Raikou + new(R) { Species = 244, Level = 70, Moves = new(083,023,053,207), Language = (int)Italian, Method = BACD_R, ID32 = 06227, OriginalTrainerName = "10ANNI", Shiny = Never }, // Entei + new(R) { Species = 245, Level = 70, Moves = new(016,062,054,243), Language = (int)Italian, Method = BACD_R, ID32 = 06227, OriginalTrainerName = "10ANNI", Shiny = Never }, // Suicune + new(R) { Species = 249, Level = 70, Moves = new(105,056,240,129), Language = (int)Italian, Method = BACD_R, ID32 = 06227, OriginalTrainerName = "10ANNI", Shiny = Never }, // Lugia + new(R) { Species = 250, Level = 70, Moves = new(105,126,241,129), Language = (int)Italian, Method = BACD_R, ID32 = 06227, OriginalTrainerName = "10ANNI", Shiny = Never }, // Ho-Oh + new(R) { Species = 380, Level = 70, Moves = new(296,094,105,204), Language = (int)Italian, Method = BACD_R, ID32 = 06227, OriginalTrainerName = "10ANNI", Shiny = Never }, // Latias + new(R) { Species = 381, Level = 70, Moves = new(295,094,105,349), Language = (int)Italian, Method = BACD_R, ID32 = 06227, OriginalTrainerName = "10ANNI", Shiny = Never }, // Latios // German - new() { Species = 006, Level = 70, Version = GameVersion.R, Moves = new(017,163,082,083), Language = (int)LanguageID.German, Method = PIDType.BACD_R, ID32 = 06227, OT_Name = "10JAHRE", Shiny = Shiny.Never }, // Charizard - new() { Species = 025, Level = 70, Version = GameVersion.R, Moves = new(085,097,087,113), Language = (int)LanguageID.German, Method = PIDType.BACD_R, ID32 = 06227, OT_Name = "10JAHRE", Shiny = Shiny.Never }, // Pikachu - new() { Species = 144, Level = 70, Version = GameVersion.R, Moves = new(097,170,058,115), Language = (int)LanguageID.German, Method = PIDType.BACD_R, ID32 = 06227, OT_Name = "10JAHRE", Shiny = Shiny.Never }, // Articuno - new() { Species = 243, Level = 70, Version = GameVersion.R, Moves = new(098,209,115,242), Language = (int)LanguageID.German, Method = PIDType.BACD_R, ID32 = 06227, OT_Name = "10JAHRE", Shiny = Shiny.Never }, // Raikou - new() { Species = 244, Level = 70, Version = GameVersion.R, Moves = new(083,023,053,207), Language = (int)LanguageID.German, Method = PIDType.BACD_R, ID32 = 06227, OT_Name = "10JAHRE", Shiny = Shiny.Never }, // Entei - new() { Species = 245, Level = 70, Version = GameVersion.R, Moves = new(016,062,054,243), Language = (int)LanguageID.German, Method = PIDType.BACD_R, ID32 = 06227, OT_Name = "10JAHRE", Shiny = Shiny.Never }, // Suicune - new() { Species = 249, Level = 70, Version = GameVersion.R, Moves = new(105,056,240,129), Language = (int)LanguageID.German, Method = PIDType.BACD_R, ID32 = 06227, OT_Name = "10JAHRE", Shiny = Shiny.Never }, // Lugia - new() { Species = 250, Level = 70, Version = GameVersion.R, Moves = new(105,126,241,129), Language = (int)LanguageID.German, Method = PIDType.BACD_R, ID32 = 06227, OT_Name = "10JAHRE", Shiny = Shiny.Never }, // Ho-Oh - new() { Species = 380, Level = 70, Version = GameVersion.R, Moves = new(296,094,105,204), Language = (int)LanguageID.German, Method = PIDType.BACD_R, ID32 = 06227, OT_Name = "10JAHRE", Shiny = Shiny.Never }, // Latias - new() { Species = 381, Level = 70, Version = GameVersion.R, Moves = new(295,094,105,349), Language = (int)LanguageID.German, Method = PIDType.BACD_R, ID32 = 06227, OT_Name = "10JAHRE", Shiny = Shiny.Never }, // Latios + new(R) { Species = 006, Level = 70, Moves = new(017,163,082,083), Language = (int)German, Method = BACD_R, ID32 = 06227, OriginalTrainerName = "10JAHRE", Shiny = Never }, // Charizard + new(R) { Species = 025, Level = 70, Moves = new(085,097,087,113), Language = (int)German, Method = BACD_R, ID32 = 06227, OriginalTrainerName = "10JAHRE", Shiny = Never }, // Pikachu + new(R) { Species = 144, Level = 70, Moves = new(097,170,058,115), Language = (int)German, Method = BACD_R, ID32 = 06227, OriginalTrainerName = "10JAHRE", Shiny = Never }, // Articuno + new(R) { Species = 243, Level = 70, Moves = new(098,209,115,242), Language = (int)German, Method = BACD_R, ID32 = 06227, OriginalTrainerName = "10JAHRE", Shiny = Never }, // Raikou + new(R) { Species = 244, Level = 70, Moves = new(083,023,053,207), Language = (int)German, Method = BACD_R, ID32 = 06227, OriginalTrainerName = "10JAHRE", Shiny = Never }, // Entei + new(R) { Species = 245, Level = 70, Moves = new(016,062,054,243), Language = (int)German, Method = BACD_R, ID32 = 06227, OriginalTrainerName = "10JAHRE", Shiny = Never }, // Suicune + new(R) { Species = 249, Level = 70, Moves = new(105,056,240,129), Language = (int)German, Method = BACD_R, ID32 = 06227, OriginalTrainerName = "10JAHRE", Shiny = Never }, // Lugia + new(R) { Species = 250, Level = 70, Moves = new(105,126,241,129), Language = (int)German, Method = BACD_R, ID32 = 06227, OriginalTrainerName = "10JAHRE", Shiny = Never }, // Ho-Oh + new(R) { Species = 380, Level = 70, Moves = new(296,094,105,204), Language = (int)German, Method = BACD_R, ID32 = 06227, OriginalTrainerName = "10JAHRE", Shiny = Never }, // Latias + new(R) { Species = 381, Level = 70, Moves = new(295,094,105,349), Language = (int)German, Method = BACD_R, ID32 = 06227, OriginalTrainerName = "10JAHRE", Shiny = Never }, // Latios // Spanish - new() { Species = 006, Level = 70, Version = GameVersion.R, Moves = new(017,163,082,083), Language = (int)LanguageID.Spanish, Method = PIDType.BACD_R, ID32 = 06227, OT_Name = "10ANIV", Shiny = Shiny.Never }, // Charizard - new() { Species = 025, Level = 70, Version = GameVersion.R, Moves = new(085,097,087,113), Language = (int)LanguageID.Spanish, Method = PIDType.BACD_R, ID32 = 06227, OT_Name = "10ANIV", Shiny = Shiny.Never }, // Pikachu - new() { Species = 144, Level = 70, Version = GameVersion.R, Moves = new(097,170,058,115), Language = (int)LanguageID.Spanish, Method = PIDType.BACD_R, ID32 = 06227, OT_Name = "10ANIV", Shiny = Shiny.Never }, // Articuno - new() { Species = 243, Level = 70, Version = GameVersion.R, Moves = new(098,209,115,242), Language = (int)LanguageID.Spanish, Method = PIDType.BACD_R, ID32 = 06227, OT_Name = "10ANIV", Shiny = Shiny.Never }, // Raikou - new() { Species = 244, Level = 70, Version = GameVersion.R, Moves = new(083,023,053,207), Language = (int)LanguageID.Spanish, Method = PIDType.BACD_R, ID32 = 06227, OT_Name = "10ANIV", Shiny = Shiny.Never }, // Entei - new() { Species = 245, Level = 70, Version = GameVersion.R, Moves = new(016,062,054,243), Language = (int)LanguageID.Spanish, Method = PIDType.BACD_R, ID32 = 06227, OT_Name = "10ANIV", Shiny = Shiny.Never }, // Suicune - new() { Species = 249, Level = 70, Version = GameVersion.R, Moves = new(105,056,240,129), Language = (int)LanguageID.Spanish, Method = PIDType.BACD_R, ID32 = 06227, OT_Name = "10ANIV", Shiny = Shiny.Never }, // Lugia - new() { Species = 250, Level = 70, Version = GameVersion.R, Moves = new(105,126,241,129), Language = (int)LanguageID.Spanish, Method = PIDType.BACD_R, ID32 = 06227, OT_Name = "10ANIV", Shiny = Shiny.Never }, // Ho-Oh - new() { Species = 380, Level = 70, Version = GameVersion.R, Moves = new(296,094,105,204), Language = (int)LanguageID.Spanish, Method = PIDType.BACD_R, ID32 = 06227, OT_Name = "10ANIV", Shiny = Shiny.Never }, // Latias - new() { Species = 381, Level = 70, Version = GameVersion.R, Moves = new(295,094,105,349), Language = (int)LanguageID.Spanish, Method = PIDType.BACD_R, ID32 = 06227, OT_Name = "10ANIV", Shiny = Shiny.Never }, // Latios + new(R) { Species = 006, Level = 70, Moves = new(017,163,082,083), Language = (int)Spanish, Method = BACD_R, ID32 = 06227, OriginalTrainerName = "10ANIV", Shiny = Never }, // Charizard + new(R) { Species = 025, Level = 70, Moves = new(085,097,087,113), Language = (int)Spanish, Method = BACD_R, ID32 = 06227, OriginalTrainerName = "10ANIV", Shiny = Never }, // Pikachu + new(R) { Species = 144, Level = 70, Moves = new(097,170,058,115), Language = (int)Spanish, Method = BACD_R, ID32 = 06227, OriginalTrainerName = "10ANIV", Shiny = Never }, // Articuno + new(R) { Species = 243, Level = 70, Moves = new(098,209,115,242), Language = (int)Spanish, Method = BACD_R, ID32 = 06227, OriginalTrainerName = "10ANIV", Shiny = Never }, // Raikou + new(R) { Species = 244, Level = 70, Moves = new(083,023,053,207), Language = (int)Spanish, Method = BACD_R, ID32 = 06227, OriginalTrainerName = "10ANIV", Shiny = Never }, // Entei + new(R) { Species = 245, Level = 70, Moves = new(016,062,054,243), Language = (int)Spanish, Method = BACD_R, ID32 = 06227, OriginalTrainerName = "10ANIV", Shiny = Never }, // Suicune + new(R) { Species = 249, Level = 70, Moves = new(105,056,240,129), Language = (int)Spanish, Method = BACD_R, ID32 = 06227, OriginalTrainerName = "10ANIV", Shiny = Never }, // Lugia + new(R) { Species = 250, Level = 70, Moves = new(105,126,241,129), Language = (int)Spanish, Method = BACD_R, ID32 = 06227, OriginalTrainerName = "10ANIV", Shiny = Never }, // Ho-Oh + new(R) { Species = 380, Level = 70, Moves = new(296,094,105,204), Language = (int)Spanish, Method = BACD_R, ID32 = 06227, OriginalTrainerName = "10ANIV", Shiny = Never }, // Latias + new(R) { Species = 381, Level = 70, Moves = new(295,094,105,349), Language = (int)Spanish, Method = BACD_R, ID32 = 06227, OriginalTrainerName = "10ANIV", Shiny = Never }, // Latios - new() { Species = 375, Level = 30, Version = GameVersion.R, Moves = new(036,093,232,287), Language = (int)LanguageID.English, Method = PIDType.BACD_R, ID32 = 02005, OT_Name = "ROCKS", OT_Gender = 0, RibbonNational = true, Shiny = Shiny.Never }, // Metang - new(true) { Species = 386, Level = 70, Version = GameVersion.R, Moves = new(322,105,354,063), Language = (int)LanguageID.English, Method = PIDType.BACD_R, ID32 = 28606, OT_Name = "DOEL", Shiny = Shiny.Never }, // Deoxys - new(true) { Species = 386, Level = 70, Version = GameVersion.R, Moves = new(322,105,354,063), Language = (int)LanguageID.English, Method = PIDType.BACD_R, ID32 = 00010, OT_Name = "SPACE C", Shiny = Shiny.Never }, // Deoxys - new(true) { Species = 151, Level = 10, Version = GameVersion.R, Language = (int)LanguageID.English, Method = PIDType.BACD_U, ID32 = 06930, OT_Name = "MYSTRY", Shiny = Shiny.Never }, // Mew - new(true) { Species = 151, Level = 10, Version = GameVersion.R, Language = (int)LanguageID.English, Method = PIDType.BACD_R, ID32 = 06930, OT_Name = "MYSTRY", Shiny = Shiny.Never }, // Mew + new(R) { Species = 375, Level = 30, Moves = new(036,093,232,287), Language = (int)English, Method = BACD_R, ID32 = 02005, OriginalTrainerName = "ROCKS", OriginalTrainerGender = 0, RibbonNational = true, Shiny = Never }, // Metang + new(R, true) { Species = 386, Level = 70, Moves = new(322,105,354,063), Language = (int)English, Method = BACD_R, ID32 = 28606, OriginalTrainerName = "DOEL", Shiny = Never }, // Deoxys + new(R, true) { Species = 386, Level = 70, Moves = new(322,105,354,063), Language = (int)English, Method = BACD_R, ID32 = 00010, OriginalTrainerName = "SPACE C", Shiny = Never }, // Deoxys + new(R, true) { Species = 151, Level = 10, Language = (int)English, Method = BACD_U, ID32 = 06930, OriginalTrainerName = "MYSTRY", Shiny = Never }, // Mew + new(R, true) { Species = 151, Level = 10, Language = (int)English, Method = BACD_R, ID32 = 06930, OriginalTrainerName = "MYSTRY", Shiny = Never }, // Mew // Party of the Decade - new() { Species = 001, Level = 70, Version = GameVersion.R, Moves = new(230,074,076,235), Language = (int)LanguageID.English, Method = PIDType.BACD_R, ID32 = 06808, OT_Name = "10 ANIV", Shiny = Shiny.Never }, // Bulbasaur - new() { Species = 006, Level = 70, Version = GameVersion.R, Moves = new(017,163,082,083), Language = (int)LanguageID.English, Method = PIDType.BACD_R, ID32 = 06808, OT_Name = "10 ANIV", Shiny = Shiny.Never }, // Charizard - new() { Species = 009, Level = 70, Version = GameVersion.R, Moves = new(182,240,130,056), Language = (int)LanguageID.English, Method = PIDType.BACD_R, ID32 = 06808, OT_Name = "10 ANIV", Shiny = Shiny.Never }, // Blastoise - new() { Species = 025, Level = 70, Version = GameVersion.R, Moves = new(085,087,113,019), Language = (int)LanguageID.English, Method = PIDType.BACD_R, ID32 = 06808, OT_Name = "10 ANIV", HeldItem = 202, Shiny = Shiny.Never }, // Pikachu (Fly) - new() { Species = 065, Level = 70, Version = GameVersion.R, Moves = new(248,347,094,271), Language = (int)LanguageID.English, Method = PIDType.BACD_R, ID32 = 06808, OT_Name = "10 ANIV", Shiny = Shiny.Never }, // Alakazam - new() { Species = 144, Level = 70, Version = GameVersion.R, Moves = new(097,170,058,115), Language = (int)LanguageID.English, Method = PIDType.BACD_R, ID32 = 06808, OT_Name = "10 ANIV", Shiny = Shiny.Never }, // Articuno - new() { Species = 145, Level = 70, Version = GameVersion.R, Moves = new(097,197,065,268), Language = (int)LanguageID.English, Method = PIDType.BACD_R, ID32 = 06808, OT_Name = "10 ANIV", Shiny = Shiny.Never }, // Zapdos - new() { Species = 146, Level = 70, Version = GameVersion.R, Moves = new(097,203,053,219), Language = (int)LanguageID.English, Method = PIDType.BACD_R, ID32 = 06808, OT_Name = "10 ANIV", Shiny = Shiny.Never }, // Moltres - new() { Species = 149, Level = 70, Version = GameVersion.R, Moves = new(097,219,017,200), Language = (int)LanguageID.English, Method = PIDType.BACD_R, ID32 = 06808, OT_Name = "10 ANIV", Shiny = Shiny.Never }, // Dragonite - new() { Species = 157, Level = 70, Version = GameVersion.R, Moves = new(098,172,129,053), Language = (int)LanguageID.English, Method = PIDType.BACD_R, ID32 = 06808, OT_Name = "10 ANIV", Shiny = Shiny.Never }, // Typhlosion - new() { Species = 196, Level = 70, Version = GameVersion.R, Moves = new(060,244,094,234), Language = (int)LanguageID.English, Method = PIDType.BACD_R, ID32 = 06808, OT_Name = "10 ANIV", Shiny = Shiny.Never }, // Espeon - new() { Species = 197, Level = 70, Version = GameVersion.R, Moves = new(185,212,103,236), Language = (int)LanguageID.English, Method = PIDType.BACD_R, ID32 = 06808, OT_Name = "10 ANIV", Shiny = Shiny.Never }, // Umbreon - new() { Species = 243, Level = 70, Version = GameVersion.R, Moves = new(098,209,115,242), Language = (int)LanguageID.English, Method = PIDType.BACD_R, ID32 = 06808, OT_Name = "10 ANIV", Shiny = Shiny.Never }, // Raikou - new() { Species = 244, Level = 70, Version = GameVersion.R, Moves = new(083,023,053,207), Language = (int)LanguageID.English, Method = PIDType.BACD_R, ID32 = 06808, OT_Name = "10 ANIV", Shiny = Shiny.Never }, // Entei - new() { Species = 245, Level = 70, Version = GameVersion.R, Moves = new(016,062,054,243), Language = (int)LanguageID.English, Method = PIDType.BACD_R, ID32 = 06808, OT_Name = "10 ANIV", Shiny = Shiny.Never }, // Suicune - new() { Species = 248, Level = 70, Version = GameVersion.R, Moves = new(037,184,242,089), Language = (int)LanguageID.English, Method = PIDType.BACD_R, ID32 = 06808, OT_Name = "10 ANIV", Shiny = Shiny.Never }, // Tyranitar - new() { Species = 257, Level = 70, Version = GameVersion.R, Moves = new(299,163,119,327), Language = (int)LanguageID.English, Method = PIDType.BACD_R, ID32 = 06808, OT_Name = "10 ANIV", Shiny = Shiny.Never }, // Blaziken - new() { Species = 359, Level = 70, Version = GameVersion.R, Moves = new(104,163,248,195), Language = (int)LanguageID.English, Method = PIDType.BACD_R, ID32 = 06808, OT_Name = "10 ANIV", Shiny = Shiny.Never }, // Absol - new() { Species = 380, Level = 70, Version = GameVersion.R, Moves = new(296,094,105,204), Language = (int)LanguageID.English, Method = PIDType.BACD_R, ID32 = 06808, OT_Name = "10 ANIV", HeldItem = 191, Shiny = Shiny.Never }, // Latias - new() { Species = 381, Level = 70, Version = GameVersion.R, Moves = new(295,094,105,349), Language = (int)LanguageID.English, Method = PIDType.BACD_R, ID32 = 06808, OT_Name = "10 ANIV", HeldItem = 191, Shiny = Shiny.Never }, // Latios + new(R) { Species = 001, Level = 70, Moves = new(230,074,076,235), Language = (int)English, Method = BACD_R, ID32 = 06808, OriginalTrainerName = "10 ANIV", Shiny = Never }, // Bulbasaur + new(R) { Species = 006, Level = 70, Moves = new(017,163,082,083), Language = (int)English, Method = BACD_R, ID32 = 06808, OriginalTrainerName = "10 ANIV", Shiny = Never }, // Charizard + new(R) { Species = 009, Level = 70, Moves = new(182,240,130,056), Language = (int)English, Method = BACD_R, ID32 = 06808, OriginalTrainerName = "10 ANIV", Shiny = Never }, // Blastoise + new(R) { Species = 025, Level = 70, Moves = new(085,087,113,019), Language = (int)English, Method = BACD_R, ID32 = 06808, OriginalTrainerName = "10 ANIV", HeldItem = 202, Shiny = Never }, // Pikachu (Fly) + new(R) { Species = 065, Level = 70, Moves = new(248,347,094,271), Language = (int)English, Method = BACD_R, ID32 = 06808, OriginalTrainerName = "10 ANIV", Shiny = Never }, // Alakazam + new(R) { Species = 144, Level = 70, Moves = new(097,170,058,115), Language = (int)English, Method = BACD_R, ID32 = 06808, OriginalTrainerName = "10 ANIV", Shiny = Never }, // Articuno + new(R) { Species = 145, Level = 70, Moves = new(097,197,065,268), Language = (int)English, Method = BACD_R, ID32 = 06808, OriginalTrainerName = "10 ANIV", Shiny = Never }, // Zapdos + new(R) { Species = 146, Level = 70, Moves = new(097,203,053,219), Language = (int)English, Method = BACD_R, ID32 = 06808, OriginalTrainerName = "10 ANIV", Shiny = Never }, // Moltres + new(R) { Species = 149, Level = 70, Moves = new(097,219,017,200), Language = (int)English, Method = BACD_R, ID32 = 06808, OriginalTrainerName = "10 ANIV", Shiny = Never }, // Dragonite + new(R) { Species = 157, Level = 70, Moves = new(098,172,129,053), Language = (int)English, Method = BACD_R, ID32 = 06808, OriginalTrainerName = "10 ANIV", Shiny = Never }, // Typhlosion + new(R) { Species = 196, Level = 70, Moves = new(060,244,094,234), Language = (int)English, Method = BACD_R, ID32 = 06808, OriginalTrainerName = "10 ANIV", Shiny = Never }, // Espeon + new(R) { Species = 197, Level = 70, Moves = new(185,212,103,236), Language = (int)English, Method = BACD_R, ID32 = 06808, OriginalTrainerName = "10 ANIV", Shiny = Never }, // Umbreon + new(R) { Species = 243, Level = 70, Moves = new(098,209,115,242), Language = (int)English, Method = BACD_R, ID32 = 06808, OriginalTrainerName = "10 ANIV", Shiny = Never }, // Raikou + new(R) { Species = 244, Level = 70, Moves = new(083,023,053,207), Language = (int)English, Method = BACD_R, ID32 = 06808, OriginalTrainerName = "10 ANIV", Shiny = Never }, // Entei + new(R) { Species = 245, Level = 70, Moves = new(016,062,054,243), Language = (int)English, Method = BACD_R, ID32 = 06808, OriginalTrainerName = "10 ANIV", Shiny = Never }, // Suicune + new(R) { Species = 248, Level = 70, Moves = new(037,184,242,089), Language = (int)English, Method = BACD_R, ID32 = 06808, OriginalTrainerName = "10 ANIV", Shiny = Never }, // Tyranitar + new(R) { Species = 257, Level = 70, Moves = new(299,163,119,327), Language = (int)English, Method = BACD_R, ID32 = 06808, OriginalTrainerName = "10 ANIV", Shiny = Never }, // Blaziken + new(R) { Species = 359, Level = 70, Moves = new(104,163,248,195), Language = (int)English, Method = BACD_R, ID32 = 06808, OriginalTrainerName = "10 ANIV", Shiny = Never }, // Absol + new(R) { Species = 380, Level = 70, Moves = new(296,094,105,204), Language = (int)English, Method = BACD_R, ID32 = 06808, OriginalTrainerName = "10 ANIV", HeldItem = 191, Shiny = Never }, // Latias + new(R) { Species = 381, Level = 70, Moves = new(295,094,105,349), Language = (int)English, Method = BACD_R, ID32 = 06808, OriginalTrainerName = "10 ANIV", HeldItem = 191, Shiny = Never }, // Latios // Journey Across America - new() { Species = 001, Level = 70, Version = GameVersion.R, Moves = new(230,074,076,235), Language = (int)LanguageID.English, Method = PIDType.BACD_R, ID32 = 00010, OT_Name = "10 ANIV", Shiny = Shiny.Never }, // Bulbasaur - new() { Species = 006, Level = 70, Version = GameVersion.R, Moves = new(017,163,082,083), Language = (int)LanguageID.English, Method = PIDType.BACD_R, ID32 = 00010, OT_Name = "10 ANIV", Shiny = Shiny.Never }, // Charizard - new() { Species = 009, Level = 70, Version = GameVersion.R, Moves = new(182,240,130,056), Language = (int)LanguageID.English, Method = PIDType.BACD_R, ID32 = 00010, OT_Name = "10 ANIV", Shiny = Shiny.Never }, // Blastoise - new() { Species = 025, Level = 70, Version = GameVersion.R, Moves = new(085,097,087,113), Language = (int)LanguageID.English, Method = PIDType.BACD_R, ID32 = 00010, OT_Name = "10 ANIV", HeldItem = 202, Shiny = Shiny.Never }, // Pikachu (No Fly) - new() { Species = 065, Level = 70, Version = GameVersion.R, Moves = new(248,347,094,271), Language = (int)LanguageID.English, Method = PIDType.BACD_R, ID32 = 00010, OT_Name = "10 ANIV", Shiny = Shiny.Never }, // Alakazam - new() { Species = 144, Level = 70, Version = GameVersion.R, Moves = new(097,170,058,115), Language = (int)LanguageID.English, Method = PIDType.BACD_R, ID32 = 00010, OT_Name = "10 ANIV", Shiny = Shiny.Never }, // Articuno - new() { Species = 145, Level = 70, Version = GameVersion.R, Moves = new(097,197,065,268), Language = (int)LanguageID.English, Method = PIDType.BACD_R, ID32 = 00010, OT_Name = "10 ANIV", Shiny = Shiny.Never }, // Zapdos - new() { Species = 146, Level = 70, Version = GameVersion.R, Moves = new(097,203,053,219), Language = (int)LanguageID.English, Method = PIDType.BACD_R, ID32 = 00010, OT_Name = "10 ANIV", Shiny = Shiny.Never }, // Moltres - new() { Species = 149, Level = 70, Version = GameVersion.R, Moves = new(097,219,017,200), Language = (int)LanguageID.English, Method = PIDType.BACD_R, ID32 = 00010, OT_Name = "10 ANIV", Shiny = Shiny.Never }, // Dragonite - new() { Species = 157, Level = 70, Version = GameVersion.R, Moves = new(098,172,129,053), Language = (int)LanguageID.English, Method = PIDType.BACD_R, ID32 = 00010, OT_Name = "10 ANIV", Shiny = Shiny.Never }, // Typhlosion - new() { Species = 196, Level = 70, Version = GameVersion.R, Moves = new(060,244,094,234), Language = (int)LanguageID.English, Method = PIDType.BACD_R, ID32 = 00010, OT_Name = "10 ANIV", Shiny = Shiny.Never }, // Espeon - new() { Species = 197, Level = 70, Version = GameVersion.R, Moves = new(185,212,103,236), Language = (int)LanguageID.English, Method = PIDType.BACD_R, ID32 = 00010, OT_Name = "10 ANIV", Shiny = Shiny.Never }, // Umbreon - new() { Species = 243, Level = 70, Version = GameVersion.R, Moves = new(098,209,115,242), Language = (int)LanguageID.English, Method = PIDType.BACD_R, ID32 = 00010, OT_Name = "10 ANIV", Shiny = Shiny.Never }, // Raikou - new() { Species = 244, Level = 70, Version = GameVersion.R, Moves = new(083,023,053,207), Language = (int)LanguageID.English, Method = PIDType.BACD_R, ID32 = 00010, OT_Name = "10 ANIV", Shiny = Shiny.Never }, // Entei - new() { Species = 245, Level = 70, Version = GameVersion.R, Moves = new(016,062,054,243), Language = (int)LanguageID.English, Method = PIDType.BACD_R, ID32 = 00010, OT_Name = "10 ANIV", Shiny = Shiny.Never }, // Suicune - new() { Species = 248, Level = 70, Version = GameVersion.R, Moves = new(037,184,242,089), Language = (int)LanguageID.English, Method = PIDType.BACD_R, ID32 = 00010, OT_Name = "10 ANIV", Shiny = Shiny.Never }, // Tyranitar - new() { Species = 251, Level = 70, Version = GameVersion.R, Moves = new(246,248,226,195), Language = (int)LanguageID.English, Method = PIDType.BACD_R, ID32 = 00010, OT_Name = "10 ANIV", Shiny = Shiny.Never }, // Celebi - new() { Species = 257, Level = 70, Version = GameVersion.R, Moves = new(299,163,119,327), Language = (int)LanguageID.English, Method = PIDType.BACD_R, ID32 = 00010, OT_Name = "10 ANIV", Shiny = Shiny.Never }, // Blaziken - new() { Species = 359, Level = 70, Version = GameVersion.R, Moves = new(104,163,248,195), Language = (int)LanguageID.English, Method = PIDType.BACD_R, ID32 = 00010, OT_Name = "10 ANIV", Shiny = Shiny.Never }, // Absol - new() { Species = 380, Level = 70, Version = GameVersion.R, Moves = new(296,094,105,204), Language = (int)LanguageID.English, Method = PIDType.BACD_R, ID32 = 00010, OT_Name = "10 ANIV", HeldItem = 191, Shiny = Shiny.Never }, // Latias - new() { Species = 381, Level = 70, Version = GameVersion.R, Moves = new(295,094,105,349), Language = (int)LanguageID.English, Method = PIDType.BACD_R, ID32 = 00010, OT_Name = "10 ANIV", HeldItem = 191, Shiny = Shiny.Never }, // Latios + new(R) { Species = 001, Level = 70, Moves = new(230,074,076,235), Language = (int)English, Method = BACD_R, ID32 = 00010, OriginalTrainerName = "10 ANIV", Shiny = Never }, // Bulbasaur + new(R) { Species = 006, Level = 70, Moves = new(017,163,082,083), Language = (int)English, Method = BACD_R, ID32 = 00010, OriginalTrainerName = "10 ANIV", Shiny = Never }, // Charizard + new(R) { Species = 009, Level = 70, Moves = new(182,240,130,056), Language = (int)English, Method = BACD_R, ID32 = 00010, OriginalTrainerName = "10 ANIV", Shiny = Never }, // Blastoise + new(R) { Species = 025, Level = 70, Moves = new(085,097,087,113), Language = (int)English, Method = BACD_R, ID32 = 00010, OriginalTrainerName = "10 ANIV", HeldItem = 202, Shiny = Never }, // Pikachu (No Fly) + new(R) { Species = 065, Level = 70, Moves = new(248,347,094,271), Language = (int)English, Method = BACD_R, ID32 = 00010, OriginalTrainerName = "10 ANIV", Shiny = Never }, // Alakazam + new(R) { Species = 144, Level = 70, Moves = new(097,170,058,115), Language = (int)English, Method = BACD_R, ID32 = 00010, OriginalTrainerName = "10 ANIV", Shiny = Never }, // Articuno + new(R) { Species = 145, Level = 70, Moves = new(097,197,065,268), Language = (int)English, Method = BACD_R, ID32 = 00010, OriginalTrainerName = "10 ANIV", Shiny = Never }, // Zapdos + new(R) { Species = 146, Level = 70, Moves = new(097,203,053,219), Language = (int)English, Method = BACD_R, ID32 = 00010, OriginalTrainerName = "10 ANIV", Shiny = Never }, // Moltres + new(R) { Species = 149, Level = 70, Moves = new(097,219,017,200), Language = (int)English, Method = BACD_R, ID32 = 00010, OriginalTrainerName = "10 ANIV", Shiny = Never }, // Dragonite + new(R) { Species = 157, Level = 70, Moves = new(098,172,129,053), Language = (int)English, Method = BACD_R, ID32 = 00010, OriginalTrainerName = "10 ANIV", Shiny = Never }, // Typhlosion + new(R) { Species = 196, Level = 70, Moves = new(060,244,094,234), Language = (int)English, Method = BACD_R, ID32 = 00010, OriginalTrainerName = "10 ANIV", Shiny = Never }, // Espeon + new(R) { Species = 197, Level = 70, Moves = new(185,212,103,236), Language = (int)English, Method = BACD_R, ID32 = 00010, OriginalTrainerName = "10 ANIV", Shiny = Never }, // Umbreon + new(R) { Species = 243, Level = 70, Moves = new(098,209,115,242), Language = (int)English, Method = BACD_R, ID32 = 00010, OriginalTrainerName = "10 ANIV", Shiny = Never }, // Raikou + new(R) { Species = 244, Level = 70, Moves = new(083,023,053,207), Language = (int)English, Method = BACD_R, ID32 = 00010, OriginalTrainerName = "10 ANIV", Shiny = Never }, // Entei + new(R) { Species = 245, Level = 70, Moves = new(016,062,054,243), Language = (int)English, Method = BACD_R, ID32 = 00010, OriginalTrainerName = "10 ANIV", Shiny = Never }, // Suicune + new(R) { Species = 248, Level = 70, Moves = new(037,184,242,089), Language = (int)English, Method = BACD_R, ID32 = 00010, OriginalTrainerName = "10 ANIV", Shiny = Never }, // Tyranitar + new(R) { Species = 251, Level = 70, Moves = new(246,248,226,195), Language = (int)English, Method = BACD_R, ID32 = 00010, OriginalTrainerName = "10 ANIV", Shiny = Never }, // Celebi + new(R) { Species = 257, Level = 70, Moves = new(299,163,119,327), Language = (int)English, Method = BACD_R, ID32 = 00010, OriginalTrainerName = "10 ANIV", Shiny = Never }, // Blaziken + new(R) { Species = 359, Level = 70, Moves = new(104,163,248,195), Language = (int)English, Method = BACD_R, ID32 = 00010, OriginalTrainerName = "10 ANIV", Shiny = Never }, // Absol + new(R) { Species = 380, Level = 70, Moves = new(296,094,105,204), Language = (int)English, Method = BACD_R, ID32 = 00010, OriginalTrainerName = "10 ANIV", HeldItem = 191, Shiny = Never }, // Latias + new(R) { Species = 381, Level = 70, Moves = new(295,094,105,349), Language = (int)English, Method = BACD_R, ID32 = 00010, OriginalTrainerName = "10 ANIV", HeldItem = 191, Shiny = Never }, // Latios ]; internal static readonly WC3[] Encounter_Event3_Common = [ // Pokémon Box -- RSE Recipient - new() { Species = 333, IsEgg = true, Level = 05, Moves = new(064,045,206,000), Method = PIDType.BACD_U, OT_Gender = 1, OT_Name = "AZUSA", Version = GameVersion.RSE }, // Swablu Egg with False Swipe - new() { Species = 263, IsEgg = true, Level = 05, Moves = new(033,045,039,245), Method = PIDType.BACD_U, OT_Gender = 1, OT_Name = "AZUSA", Version = GameVersion.RSE }, // Zigzagoon Egg with Extreme Speed - new() { Species = 300, IsEgg = true, Level = 05, Moves = new(045,033,039,006), Method = PIDType.BACD_U, OT_Gender = 1, OT_Name = "AZUSA", Version = GameVersion.RSE }, // Skitty Egg with Pay Day - new() { Species = 172, IsEgg = true, Level = 05, Moves = new(084,204,057,000), Method = PIDType.BACD_U, OT_Gender = 1, OT_Name = "AZUSA", Version = GameVersion.RSE }, // Pichu Egg with Surf + new(RSE) { Species = 333, IsEgg = true, Level = 05, Moves = new(064,045,206,000), Method = BACD_U, OriginalTrainerGender = 1, OriginalTrainerName = "AZUSA" }, // Swablu Egg with False Swipe + new(RSE) { Species = 263, IsEgg = true, Level = 05, Moves = new(033,045,039,245), Method = BACD_U, OriginalTrainerGender = 1, OriginalTrainerName = "AZUSA" }, // Zigzagoon Egg with Extreme Speed + new(RSE) { Species = 300, IsEgg = true, Level = 05, Moves = new(045,033,039,006), Method = BACD_U, OriginalTrainerGender = 1, OriginalTrainerName = "AZUSA" }, // Skitty Egg with Pay Day + new(RSE) { Species = 172, IsEgg = true, Level = 05, Moves = new(084,204,057,000), Method = BACD_U, OriginalTrainerGender = 1, OriginalTrainerName = "AZUSA" }, // Pichu Egg with Surf // Pokémon Box -- FRLG Recipient - new() { Species = 333, IsEgg = true, Level = 05, Moves = new(064,045,206,000), Method = PIDType.BACD_U, OT_Gender = 1, OT_Name = "AZUSA", Version = GameVersion.FRLG }, // Swablu Egg with False Swipe - new() { Species = 263, IsEgg = true, Level = 05, Moves = new(033,045,039,245), Method = PIDType.BACD_U, OT_Gender = 1, OT_Name = "AZUSA", Version = GameVersion.FRLG }, // Zigzagoon Egg with Extreme Speed - new() { Species = 300, IsEgg = true, Level = 05, Moves = new(045,033,039,006), Method = PIDType.BACD_U, OT_Gender = 1, OT_Name = "AZUSA", Version = GameVersion.FRLG }, // Skitty Egg with Pay Day - new() { Species = 172, IsEgg = true, Level = 05, Moves = new(084,204,057,000), Method = PIDType.BACD_U, OT_Gender = 1, OT_Name = "AZUSA", Version = GameVersion.FRLG }, // Pichu Egg with Surf + new(FRLG) { Species = 333, IsEgg = true, Level = 05, Moves = new(064,045,206,000), Method = BACD_U, OriginalTrainerGender = 1, OriginalTrainerName = "AZUSA" }, // Swablu Egg with False Swipe + new(FRLG) { Species = 263, IsEgg = true, Level = 05, Moves = new(033,045,039,245), Method = BACD_U, OriginalTrainerGender = 1, OriginalTrainerName = "AZUSA" }, // Zigzagoon Egg with Extreme Speed + new(FRLG) { Species = 300, IsEgg = true, Level = 05, Moves = new(045,033,039,006), Method = BACD_U, OriginalTrainerGender = 1, OriginalTrainerName = "AZUSA" }, // Skitty Egg with Pay Day + new(FRLG) { Species = 172, IsEgg = true, Level = 05, Moves = new(084,204,057,000), Method = BACD_U, OriginalTrainerGender = 1, OriginalTrainerName = "AZUSA" }, // Pichu Egg with Surf // PokePark Eggs - DS Download Play - new() { Species = 054, IsEgg = true, Level = 05, Met_Level = 05, TID16 = 50318, OT_Gender = 0, OT_Name = "ポケパーク", Version = GameVersion.R, Moves = new(300), Method = PIDType.BACD_R }, // Psyduck with Mud Sport - new() { Species = 172, IsEgg = true, Level = 05, Met_Level = 05, TID16 = 50318, OT_Gender = 0, OT_Name = "ポケパーク", Version = GameVersion.R, Moves = new(266), Method = PIDType.BACD_R }, // Pichu with Follow Me - new() { Species = 174, IsEgg = true, Level = 05, Met_Level = 05, TID16 = 50318, OT_Gender = 0, OT_Name = "ポケパーク", Version = GameVersion.R, Moves = new(321), Method = PIDType.BACD_R }, // Igglybuff with Tickle - new() { Species = 222, IsEgg = true, Level = 05, Met_Level = 05, TID16 = 50318, OT_Gender = 0, OT_Name = "ポケパーク", Version = GameVersion.R, Moves = new(300), Method = PIDType.BACD_R }, // Corsola with Mud Sport - new() { Species = 276, IsEgg = true, Level = 05, Met_Level = 05, TID16 = 50318, OT_Gender = 0, OT_Name = "ポケパーク", Version = GameVersion.R, Moves = new(297), Method = PIDType.BACD_R }, // Taillow with Feather Dance - new() { Species = 283, IsEgg = true, Level = 05, Met_Level = 05, TID16 = 50318, OT_Gender = 0, OT_Name = "ポケパーク", Version = GameVersion.R, Moves = new(300), Method = PIDType.BACD_R }, // Surskit with Mud Sport - new() { Species = 293, IsEgg = true, Level = 05, Met_Level = 05, TID16 = 50318, OT_Gender = 0, OT_Name = "ポケパーク", Version = GameVersion.R, Moves = new(298), Method = PIDType.BACD_R }, // Whismur with Teeter Dance - new() { Species = 300, IsEgg = true, Level = 05, Met_Level = 05, TID16 = 50318, OT_Gender = 0, OT_Name = "ポケパーク", Version = GameVersion.R, Moves = new(205), Method = PIDType.BACD_R }, // Skitty with Rollout - new() { Species = 311, IsEgg = true, Level = 05, Met_Level = 05, TID16 = 50318, OT_Gender = 0, OT_Name = "ポケパーク", Version = GameVersion.R, Moves = new(346), Method = PIDType.BACD_R }, // Plusle with Water Sport - new() { Species = 312, IsEgg = true, Level = 05, Met_Level = 05, TID16 = 50318, OT_Gender = 0, OT_Name = "ポケパーク", Version = GameVersion.R, Moves = new(300), Method = PIDType.BACD_R }, // Minun with Mud Sport - new() { Species = 325, IsEgg = true, Level = 05, Met_Level = 05, TID16 = 50318, OT_Gender = 0, OT_Name = "ポケパーク", Version = GameVersion.R, Moves = new(253), Method = PIDType.BACD_R }, // Spoink with Uproar - new() { Species = 327, IsEgg = true, Level = 05, Met_Level = 05, TID16 = 50318, OT_Gender = 0, OT_Name = "ポケパーク", Version = GameVersion.R, Moves = new(047), Method = PIDType.BACD_R }, // Spinda with Sing - new() { Species = 331, IsEgg = true, Level = 05, Met_Level = 05, TID16 = 50318, OT_Gender = 0, OT_Name = "ポケパーク", Version = GameVersion.R, Moves = new(227), Method = PIDType.BACD_R }, // Cacnea with Encore - new() { Species = 341, IsEgg = true, Level = 05, Met_Level = 05, TID16 = 50318, OT_Gender = 0, OT_Name = "ポケパーク", Version = GameVersion.R, Moves = new(346), Method = PIDType.BACD_R }, // Corphish with Water Sport - new() { Species = 360, IsEgg = true, Level = 05, Met_Level = 05, TID16 = 50318, OT_Gender = 0, OT_Name = "ポケパーク", Version = GameVersion.R, Moves = new(321), Method = PIDType.BACD_R }, // Wynaut with Tickle + new(R) { Species = 054, IsEgg = true, Level = 05, MetLevel = 05, TID16 = 50318, OriginalTrainerGender = 0, OriginalTrainerName = "ポケパーク", Moves = new(300), Method = BACD_R }, // Psyduck with Mud Sport + new(R) { Species = 172, IsEgg = true, Level = 05, MetLevel = 05, TID16 = 50318, OriginalTrainerGender = 0, OriginalTrainerName = "ポケパーク", Moves = new(266), Method = BACD_R }, // Pichu with Follow Me + new(R) { Species = 174, IsEgg = true, Level = 05, MetLevel = 05, TID16 = 50318, OriginalTrainerGender = 0, OriginalTrainerName = "ポケパーク", Moves = new(321), Method = BACD_R }, // Igglybuff with Tickle + new(R) { Species = 222, IsEgg = true, Level = 05, MetLevel = 05, TID16 = 50318, OriginalTrainerGender = 0, OriginalTrainerName = "ポケパーク", Moves = new(300), Method = BACD_R }, // Corsola with Mud Sport + new(R) { Species = 276, IsEgg = true, Level = 05, MetLevel = 05, TID16 = 50318, OriginalTrainerGender = 0, OriginalTrainerName = "ポケパーク", Moves = new(297), Method = BACD_R }, // Taillow with Feather Dance + new(R) { Species = 283, IsEgg = true, Level = 05, MetLevel = 05, TID16 = 50318, OriginalTrainerGender = 0, OriginalTrainerName = "ポケパーク", Moves = new(300), Method = BACD_R }, // Surskit with Mud Sport + new(R) { Species = 293, IsEgg = true, Level = 05, MetLevel = 05, TID16 = 50318, OriginalTrainerGender = 0, OriginalTrainerName = "ポケパーク", Moves = new(298), Method = BACD_R }, // Whismur with Teeter Dance + new(R) { Species = 300, IsEgg = true, Level = 05, MetLevel = 05, TID16 = 50318, OriginalTrainerGender = 0, OriginalTrainerName = "ポケパーク", Moves = new(205), Method = BACD_R }, // Skitty with Rollout + new(R) { Species = 311, IsEgg = true, Level = 05, MetLevel = 05, TID16 = 50318, OriginalTrainerGender = 0, OriginalTrainerName = "ポケパーク", Moves = new(346), Method = BACD_R }, // Plusle with Water Sport + new(R) { Species = 312, IsEgg = true, Level = 05, MetLevel = 05, TID16 = 50318, OriginalTrainerGender = 0, OriginalTrainerName = "ポケパーク", Moves = new(300), Method = BACD_R }, // Minun with Mud Sport + new(R) { Species = 325, IsEgg = true, Level = 05, MetLevel = 05, TID16 = 50318, OriginalTrainerGender = 0, OriginalTrainerName = "ポケパーク", Moves = new(253), Method = BACD_R }, // Spoink with Uproar + new(R) { Species = 327, IsEgg = true, Level = 05, MetLevel = 05, TID16 = 50318, OriginalTrainerGender = 0, OriginalTrainerName = "ポケパーク", Moves = new(047), Method = BACD_R }, // Spinda with Sing + new(R) { Species = 331, IsEgg = true, Level = 05, MetLevel = 05, TID16 = 50318, OriginalTrainerGender = 0, OriginalTrainerName = "ポケパーク", Moves = new(227), Method = BACD_R }, // Cacnea with Encore + new(R) { Species = 341, IsEgg = true, Level = 05, MetLevel = 05, TID16 = 50318, OriginalTrainerGender = 0, OriginalTrainerName = "ポケパーク", Moves = new(346), Method = BACD_R }, // Corphish with Water Sport + new(R) { Species = 360, IsEgg = true, Level = 05, MetLevel = 05, TID16 = 50318, OriginalTrainerGender = 0, OriginalTrainerName = "ポケパーク", Moves = new(321), Method = BACD_R }, // Wynaut with Tickle ]; internal static readonly WC3[] Encounter_WC3 = [..Encounter_Event3, ..Encounter_Event3_RS, ..Encounter_Event3_FRLG, ..Encounter_Event3_Common]; diff --git a/PKHeX.Core/Legality/Encounters/Data/Gen4/Encounters4DPPt.cs b/PKHeX.Core/Legality/Encounters/Data/Gen4/Encounters4DPPt.cs index de876a6e9..2206ea504 100644 --- a/PKHeX.Core/Legality/Encounters/Data/Gen4/Encounters4DPPt.cs +++ b/PKHeX.Core/Legality/Encounters/Data/Gen4/Encounters4DPPt.cs @@ -112,26 +112,26 @@ internal static class Encounters4DPPt internal static readonly EncounterTrade4RanchGift[] RanchGifts = [ - new(323975838, 025, 18) { Moves = new(447,085,148,104), TID16 = 1000, SID16 = 19840, OTGender = 1, MetLocation = 0068, Gender = 0, Ability = OnlyFirst, CurrentLevel = 20 }, // Pikachu - new(323977664, 037, 16) { Moves = new(412,109,053,219), TID16 = 1000, SID16 = 21150, OTGender = 1, MetLocation = 3000, Gender = 0, Ability = OnlyFirst, CurrentLevel = 30 }, // Vulpix - new(323975579, 077, 13) { Moves = new(036,033,039,052), TID16 = 1000, SID16 = 01123, OTGender = 1, MetLocation = 3000, Gender = 0, Ability = OnlySecond, CurrentLevel = 16 }, // Ponyta - new(323975564, 108, 34) { Moves = new(076,111,014,205), TID16 = 1000, SID16 = 03050, OTGender = 1, MetLocation = 0077, Gender = 0, Ability = OnlyFirst, CurrentLevel = 40 }, // Lickitung - new(323977579, 114, 01) { Moves = new(437,438,079,246), TID16 = 1000, SID16 = 49497, OTGender = 1, MetLocation = 3000, Gender = 1, Ability = OnlySecond }, // Tangela - new(323977675, 133, 16) { Moves = new(363,270,098,247), TID16 = 1000, SID16 = 47710, OTGender = 1, MetLocation = 0068, Gender = 0, Ability = OnlySecond, CurrentLevel = 30 }, // Eevee - new(323977588, 142, 20) { Moves = new(363,089,444,332), TID16 = 1000, SID16 = 43066, OTGender = 1, MetLocation = 0094, Gender = 0, Ability = OnlyFirst, CurrentLevel = 50 }, // Aerodactyl - new(232975554, 193, 22) { Moves = new(318,095,246,138), TID16 = 1000, SID16 = 42301, OTGender = 1, MetLocation = 0052, Gender = 0, Ability = OnlyFirst, CurrentLevel = 45, FixedBall = Ball.Safari }, // Yanma - new(323975570, 241, 16) { Moves = new(208,215,360,359), TID16 = 1000, SID16 = 02707, OTGender = 1, MetLocation = 3000, Gender = 1, Ability = OnlyFirst, CurrentLevel = 48 }, // Miltank - new(323975563, 285, 22) { Moves = new(402,147,206,078), TID16 = 1000, SID16 = 02788, OTGender = 1, MetLocation = 3000, Gender = 0, Ability = OnlySecond, CurrentLevel = 45, FixedBall = Ball.Safari }, // Shroomish - new(323975559, 320, 30) { Moves = new(156,323,133,058), TID16 = 1000, SID16 = 27046, OTGender = 1, MetLocation = 0038, Gender = 0, Ability = OnlySecond, CurrentLevel = 45 }, // Wailmer - new(323977657, 360, 01) { Moves = new(204,150,227,000), TID16 = 1000, SID16 = 01788, OTGender = 1, MetLocation = 0004, Gender = 0, Ability = OnlySecond, EggLocation = 2000 }, // Wynaut - new(323975563, 397, 02) { Moves = new(355,017,283,018), TID16 = 1000, SID16 = 59298, OTGender = 1, MetLocation = 0016, Gender = 0, Ability = OnlySecond, CurrentLevel = 23 }, // Staravia - new(323970584, 415, 05) { Moves = new(230,016,000,000), TID16 = 1000, SID16 = 54140, OTGender = 1, MetLocation = 0020, Gender = 1, Ability = OnlyFirst, CurrentLevel = 20 }, // Combee - new(323977539, 417, 09) { Moves = new(447,045,351,098), TID16 = 1000, SID16 = 18830, OTGender = 1, MetLocation = 0020, Gender = 1, Ability = OnlySecond, CurrentLevel = 10 }, // Pachirisu - new(323974107, 422, 20) { Moves = new(363,352,426,104), TID16 = 1000, SID16 = 39272, OTGender = 1, MetLocation = 0028, Gender = 0, Ability = OnlySecond, CurrentLevel = 25, Form = 1 }, // Shellos - new(323977566, 427, 10) { Moves = new(204,193,409,098), TID16 = 1000, SID16 = 31045, OTGender = 1, MetLocation = 3000, Gender = 1, Ability = OnlyFirst, CurrentLevel = 16 }, // Buneary - new(323975579, 453, 22) { Moves = new(310,207,426,389), TID16 = 1000, SID16 = 41342, OTGender = 1, MetLocation = 0052, Gender = 0, Ability = OnlySecond, CurrentLevel = 31, FixedBall = Ball.Safari }, // Croagunk - new(323977566, 456, 15) { Moves = new(213,352,219,392), TID16 = 1000, SID16 = 48348, OTGender = 1, MetLocation = 0020, Gender = 1, Ability = OnlyFirst, CurrentLevel = 35 }, // Finneon - new(323975582, 459, 32) { Moves = new(452,420,275,059), TID16 = 1000, SID16 = 23360, OTGender = 1, MetLocation = 0031, Gender = 0, Ability = OnlyFirst, CurrentLevel = 41 }, // Snover + new(323975838, 025, 18) { Moves = new(447,085,148,104), TID16 = 1000, SID16 = 19840, OTGender = 1, Location = 0068, Gender = 0, Ability = OnlyFirst, CurrentLevel = 20 }, // Pikachu + new(323977664, 037, 16) { Moves = new(412,109,053,219), TID16 = 1000, SID16 = 21150, OTGender = 1, Location = 3000, Gender = 0, Ability = OnlyFirst, CurrentLevel = 30 }, // Vulpix + new(323975579, 077, 13) { Moves = new(036,033,039,052), TID16 = 1000, SID16 = 01123, OTGender = 1, Location = 3000, Gender = 0, Ability = OnlySecond, CurrentLevel = 16 }, // Ponyta + new(323975564, 108, 34) { Moves = new(076,111,014,205), TID16 = 1000, SID16 = 03050, OTGender = 1, Location = 0077, Gender = 0, Ability = OnlyFirst, CurrentLevel = 40 }, // Lickitung + new(323977579, 114, 01) { Moves = new(437,438,079,246), TID16 = 1000, SID16 = 49497, OTGender = 1, Location = 3000, Gender = 1, Ability = OnlySecond }, // Tangela + new(323977675, 133, 16) { Moves = new(363,270,098,247), TID16 = 1000, SID16 = 47710, OTGender = 1, Location = 0068, Gender = 0, Ability = OnlySecond, CurrentLevel = 30 }, // Eevee + new(323977588, 142, 20) { Moves = new(363,089,444,332), TID16 = 1000, SID16 = 43066, OTGender = 1, Location = 0094, Gender = 0, Ability = OnlyFirst, CurrentLevel = 50 }, // Aerodactyl + new(232975554, 193, 22) { Moves = new(318,095,246,138), TID16 = 1000, SID16 = 42301, OTGender = 1, Location = 0052, Gender = 0, Ability = OnlyFirst, CurrentLevel = 45, FixedBall = Ball.Safari }, // Yanma + new(323975570, 241, 16) { Moves = new(208,215,360,359), TID16 = 1000, SID16 = 02707, OTGender = 1, Location = 3000, Gender = 1, Ability = OnlyFirst, CurrentLevel = 48 }, // Miltank + new(323975563, 285, 22) { Moves = new(402,147,206,078), TID16 = 1000, SID16 = 02788, OTGender = 1, Location = 3000, Gender = 0, Ability = OnlySecond, CurrentLevel = 45, FixedBall = Ball.Safari }, // Shroomish + new(323975559, 320, 30) { Moves = new(156,323,133,058), TID16 = 1000, SID16 = 27046, OTGender = 1, Location = 0038, Gender = 0, Ability = OnlySecond, CurrentLevel = 45 }, // Wailmer + new(323977657, 360, 01) { Moves = new(204,150,227,000), TID16 = 1000, SID16 = 01788, OTGender = 1, Location = 0004, Gender = 0, Ability = OnlySecond, EggLocation = 2000 }, // Wynaut + new(323975563, 397, 02) { Moves = new(355,017,283,018), TID16 = 1000, SID16 = 59298, OTGender = 1, Location = 0016, Gender = 0, Ability = OnlySecond, CurrentLevel = 23 }, // Staravia + new(323970584, 415, 05) { Moves = new(230,016,000,000), TID16 = 1000, SID16 = 54140, OTGender = 1, Location = 0020, Gender = 1, Ability = OnlyFirst, CurrentLevel = 20 }, // Combee + new(323977539, 417, 09) { Moves = new(447,045,351,098), TID16 = 1000, SID16 = 18830, OTGender = 1, Location = 0020, Gender = 1, Ability = OnlySecond, CurrentLevel = 10 }, // Pachirisu + new(323974107, 422, 20) { Moves = new(363,352,426,104), TID16 = 1000, SID16 = 39272, OTGender = 1, Location = 0028, Gender = 0, Ability = OnlySecond, CurrentLevel = 25, Form = 1 }, // Shellos + new(323977566, 427, 10) { Moves = new(204,193,409,098), TID16 = 1000, SID16 = 31045, OTGender = 1, Location = 3000, Gender = 1, Ability = OnlyFirst, CurrentLevel = 16 }, // Buneary + new(323975579, 453, 22) { Moves = new(310,207,426,389), TID16 = 1000, SID16 = 41342, OTGender = 1, Location = 0052, Gender = 0, Ability = OnlySecond, CurrentLevel = 31, FixedBall = Ball.Safari }, // Croagunk + new(323977566, 456, 15) { Moves = new(213,352,219,392), TID16 = 1000, SID16 = 48348, OTGender = 1, Location = 0020, Gender = 1, Ability = OnlyFirst, CurrentLevel = 35 }, // Finneon + new(323975582, 459, 32) { Moves = new(452,420,275,059), TID16 = 1000, SID16 = 23360, OTGender = 1, Location = 0031, Gender = 0, Ability = OnlyFirst, CurrentLevel = 41 }, // Snover new(151, 50) { Moves = new(235,216,095,100), TID16 = 1000, SID16 = 59228, OTGender = 1, FixedBall = Ball.Cherish, Gender = 2, Ability = Any12 }, // Mew new(489, 01) { Moves = new(447,240,156,057), TID16 = 1000, SID16 = 09248, OTGender = 1, FixedBall = Ball.Cherish, Gender = 2, Ability = Any12, CurrentLevel = 50, EggLocation = 3000 }, // Phione ]; diff --git a/PKHeX.Core/Legality/Encounters/Data/Gen6/Encounters6AO.cs b/PKHeX.Core/Legality/Encounters/Data/Gen6/Encounters6AO.cs index 7b733cebf..ad38e2841 100644 --- a/PKHeX.Core/Legality/Encounters/Data/Gen6/Encounters6AO.cs +++ b/PKHeX.Core/Legality/Encounters/Data/Gen6/Encounters6AO.cs @@ -25,11 +25,11 @@ internal static class Encounters6AO Gender = 1, Ability = OnlyHidden, FlawlessIVCount = 3, - CNT_Cool = 70, - CNT_Beauty = 70, - CNT_Cute = 70, - CNT_Tough = 70, - CNT_Smart = 70, + ContestCool = 70, + ContestBeauty = 70, + ContestCute = 70, + ContestTough = 70, + ContestSmart = 70, FixedBall = Ball.Poke, Shiny = Shiny.Never, }; @@ -72,7 +72,7 @@ internal static class Encounters6AO // Gift new(ORAS) { Species = 374, Level = 01, Location = 196, Ability = OnlyFirst, FixedBall = Ball.Poke, IVs = new(-1,-1,31,-1,-1,31) }, // Beldum - new(ORAS) { Species = 351, Level = 30, Location = 240, Ability = OnlyFirst, FixedBall = Ball.Poke, IVs = new(-1,-1,-1,-1,31,-1), CNT_Beauty = 100, Gender = 1, Nature = Nature.Lax }, // Castform + new(ORAS) { Species = 351, Level = 30, Location = 240, Ability = OnlyFirst, FixedBall = Ball.Poke, IVs = new(-1,-1,-1,-1,31,-1), ContestBeauty = 100, Gender = 1, Nature = Nature.Lax }, // Castform new(ORAS) { Species = 319, Level = 40, Location = 318, Ability = OnlyFirst, FixedBall = Ball.Poke, Gender = 1, Nature = Nature.Adamant }, // Sharpedo new(ORAS) { Species = 323, Level = 40, Location = 318, Ability = OnlyFirst, FixedBall = Ball.Poke, Gender = 1, Nature = Nature.Quiet }, // Camerupt diff --git a/PKHeX.Core/Legality/Encounters/Generator/ByGeneration/EncounterGenerator2.cs b/PKHeX.Core/Legality/Encounters/Generator/ByGeneration/EncounterGenerator2.cs index e11aa46fc..612b628a8 100644 --- a/PKHeX.Core/Legality/Encounters/Generator/ByGeneration/EncounterGenerator2.cs +++ b/PKHeX.Core/Legality/Encounters/Generator/ByGeneration/EncounterGenerator2.cs @@ -35,7 +35,7 @@ private static IEnumerable GetEncounters(PKM pk, EvoCriteria[] c yield return enc.Encounter; } - private const int Generation = 2; + private const byte Generation = 2; private const EntityContext Context = EntityContext.Gen2; private const byte EggLevel = 5; diff --git a/PKHeX.Core/Legality/Encounters/Generator/ByGeneration/EncounterGenerator3.cs b/PKHeX.Core/Legality/Encounters/Generator/ByGeneration/EncounterGenerator3.cs index e9b0369f8..483c5932a 100644 --- a/PKHeX.Core/Legality/Encounters/Generator/ByGeneration/EncounterGenerator3.cs +++ b/PKHeX.Core/Legality/Encounters/Generator/ByGeneration/EncounterGenerator3.cs @@ -1,6 +1,5 @@ using System; using System.Collections.Generic; -using System.Linq; using System.Diagnostics.CodeAnalysis; namespace PKHeX.Core; @@ -28,60 +27,71 @@ public IEnumerable GetEncounters(PKM pk, EvoCriteria[] chain, Le yield break; info.PIDIV = MethodFinder.Analyze(pk); - IEncounterable? partial = null; - - foreach (var z in GetEncountersInner(pk, chain, info)) - { - if (IsTypeCompatible(z, pk, info.PIDIV.Type)) - yield return z; - else - partial ??= z; - } - static bool IsTypeCompatible(IEncounterTemplate enc, PKM pk, PIDType type) - { - if (enc is IRandomCorrelation r) - return r.IsCompatible(type, pk); - return type == PIDType.None; - } - - if (partial == null) - yield break; - - info.PIDIVMatches = false; - yield return partial; - } - - private static IEnumerable GetEncountersInner(PKM pk, EvoCriteria[] chain, LegalInfo info) - { - var game = (GameVersion)pk.Version; + var game = pk.Version; var iterator = new EncounterEnumerator3(pk, chain, game); + IEncounterable? deferType = null; EncounterSlot3? deferSlot = null; - List? frames = null; + var leadQueue = new LeadEncounterQueue(); + + bool emerald = pk.E; + byte gender = pk.Gender; + if (pk.Species is (int)Species.Marill or (int)Species.Azumarill) + gender = EntityGender.GetFromPIDAndRatio(pk.EncryptionConstant, 0x3F); + foreach (var enc in iterator) { var e = enc.Encounter; - if (e is not EncounterSlot3 s3 || s3 is EncounterSlot3Swarm) + if (!IsTypeCompatible(e, pk, info.PIDIV.Type)) + { + deferType ??= e; + continue; + } + + if (e is not EncounterSlot3 slot) { yield return e; continue; } - var wildFrames = frames ?? AnalyzeFrames(pk, info); - var frame = wildFrames.Find(s => s.IsSlotCompatibile(s3, pk)); - if (frame != null) - yield return s3; - deferSlot ??= s3; + var evo = LeadFinder.GetLevelConstraint(pk, chain, slot, 3); + var lead = LeadFinder.GetLeadInfo3(slot, info.PIDIV, evo, emerald, gender, pk.Format); + if (!lead.IsValid()) + { + deferSlot ??= slot; + continue; + } + leadQueue.Insert(lead, slot); } + + foreach (var cache in leadQueue.List) + { + info.PIDIV = info.PIDIV.AsEncounteredVia(cache.Lead); + yield return cache.Encounter; + } + if (leadQueue.List.Count != 0) + yield break; + + // Error will be flagged later if this is chosen. if (deferSlot != null) + { + info.ManualFlag = EncounterYieldFlag.InvalidFrame; yield return deferSlot; + } + else if (deferType != null) + { + info.ManualFlag = EncounterYieldFlag.InvalidPIDIV; + yield return deferType; + } } - private static List AnalyzeFrames(PKM pk, LegalInfo info) + private static bool IsTypeCompatible(IEncounterTemplate enc, PKM pk, PIDType type) { - return FrameFinder.GetFrames(info.PIDIV, pk).ToList(); + if (enc is IRandomCorrelation r) + return r.IsCompatible(type, pk); + return type == PIDType.None; } - private const int Generation = 3; + private const byte Generation = 3; private const EntityContext Context = EntityContext.Gen3; private const byte EggLevel = 5; diff --git a/PKHeX.Core/Legality/Encounters/Generator/ByGeneration/EncounterGenerator3GC.cs b/PKHeX.Core/Legality/Encounters/Generator/ByGeneration/EncounterGenerator3GC.cs index 606bda895..9a6827f7d 100644 --- a/PKHeX.Core/Legality/Encounters/Generator/ByGeneration/EncounterGenerator3GC.cs +++ b/PKHeX.Core/Legality/Encounters/Generator/ByGeneration/EncounterGenerator3GC.cs @@ -56,11 +56,11 @@ static bool IsTypeCompatible(IEncounterTemplate enc, PKM pk, PIDType type) partial ??= z; } - if (partial == null) - yield break; - - info.PIDIVMatches = false; - yield return partial; + if (partial != null) + { + info.ManualFlag = EncounterYieldFlag.InvalidPIDIV; + yield return partial; + } } private static IEnumerable IterateInner(PKM pk, EvoCriteria[] chain) diff --git a/PKHeX.Core/Legality/Encounters/Generator/ByGeneration/EncounterGenerator4.cs b/PKHeX.Core/Legality/Encounters/Generator/ByGeneration/EncounterGenerator4.cs index 7f8fdffb8..2fce4308d 100644 --- a/PKHeX.Core/Legality/Encounters/Generator/ByGeneration/EncounterGenerator4.cs +++ b/PKHeX.Core/Legality/Encounters/Generator/ByGeneration/EncounterGenerator4.cs @@ -1,6 +1,5 @@ using System; using System.Collections.Generic; -using System.Linq; using System.Diagnostics.CodeAnalysis; namespace PKHeX.Core; @@ -30,77 +29,85 @@ public IEnumerable GetPossible(PKM pk, EvoCriteria[] chain, Game public IEnumerable GetEncounters(PKM pk, EvoCriteria[] chain, LegalInfo info) { info.PIDIV = MethodFinder.Analyze(pk); - var deferredPIDIV = new List(); - var deferredEType = new List(); - - foreach (var z in GetEncountersInner(pk, chain, info)) - { - if (!IsTypeCompatible(z, pk, info.PIDIV.Type)) - deferredPIDIV.Add(z); - else if (!IsTileCompatible(z, pk)) - deferredEType.Add(z); - else - yield return z; - } - - static bool IsTileCompatible(IEncounterable encounterable, PKM pk) - { - if (pk is not IGroundTile e) - return true; // No longer has the data to check - if (encounterable is not IGroundTypeTile t) - return e.GroundTile == 0; - return t.GroundTile.Contains(e.GroundTile); - } - - static bool IsTypeCompatible(IEncounterTemplate enc, PKM pk, PIDType type) - { - if (enc is IRandomCorrelation r) - return r.IsCompatible(type, pk); - return type == PIDType.None; - } - - foreach (var z in deferredEType) - yield return z; - - if (deferredPIDIV.Count == 0) - yield break; - - info.PIDIVMatches = false; - foreach (var z in deferredPIDIV) - yield return z; - } - - private static IEnumerable GetEncountersInner(PKM pk, EvoCriteria[] chain, LegalInfo info) - { - var game = (GameVersion)pk.Version; + var game = pk.Version; var iterator = new EncounterEnumerator4(pk, chain, game); EncounterSlot4? deferSlot = null; - List? frames = null; + IEncounterable? deferTile = null; + IEncounterable? deferType = null; + var leadQueue = new LeadEncounterQueue(); + foreach (var enc in iterator) { var e = enc.Encounter; - if (e is not EncounterSlot4 s4) + if (!IsTileCompatible(e, pk)) + { + deferTile ??= e; + continue; + } + + if (e is not EncounterSlot4 slot) { yield return e; continue; } + if (!IsTypeCompatible(e, pk, info.PIDIV.Type)) + { + deferSlot ??= slot; + continue; + } - var wildFrames = frames ?? AnalyzeFrames(pk, info); - var frame = wildFrames.Find(s => s.IsSlotCompatibile(s4, pk)); - if (frame != null) - yield return s4; - deferSlot ??= s4; + var evo = LeadFinder.GetLevelConstraint(pk, chain, slot, 4); + var lead = LeadFinder.GetLeadInfo4(pk, slot, info.PIDIV, evo); + if (!lead.IsValid()) + { + deferSlot ??= slot; + continue; + } + leadQueue.Insert(lead, slot); } - if (deferSlot != null) + + foreach (var cache in leadQueue.List) + { + info.PIDIV = info.PIDIV.AsEncounteredVia(cache.Lead); + yield return cache.Encounter; + } + if (leadQueue.List.Count != 0) + yield break; + + // Error will be flagged later if this is chosen. + if (deferTile != null) + { + yield return deferTile; + } + else if (deferSlot != null) + { + info.ManualFlag = EncounterYieldFlag.InvalidFrame; yield return deferSlot; + } + else if (deferType != null) + { + info.ManualFlag = EncounterYieldFlag.InvalidPIDIV; + yield return deferType; + } } - private static List AnalyzeFrames(PKM pk, LegalInfo info) + private static bool IsTileCompatible(IEncounterTemplate enc, PKM pk) { - return FrameFinder.GetFrames(info.PIDIV, pk).ToList(); + if (pk is not IGroundTile e) + return true; // No longer has the data to check + if (enc is not IGroundTypeTile t) + return e.GroundTile == 0; + return t.GroundTile.Contains(e.GroundTile); } - private const int Generation = 4; + private static bool IsTypeCompatible(IEncounterTemplate enc, PKM pk, PIDType type) + { + if (enc is IRandomCorrelation r) + return r.IsCompatible(type, pk); + return type == PIDType.None; + } + + private const byte Generation = 4; private const EntityContext Context = EntityContext.Gen4; private const byte EggLevel = 1; diff --git a/PKHeX.Core/Legality/Encounters/Generator/ByGeneration/EncounterGenerator5.cs b/PKHeX.Core/Legality/Encounters/Generator/ByGeneration/EncounterGenerator5.cs index 43e9b7c86..831c14368 100644 --- a/PKHeX.Core/Legality/Encounters/Generator/ByGeneration/EncounterGenerator5.cs +++ b/PKHeX.Core/Legality/Encounters/Generator/ByGeneration/EncounterGenerator5.cs @@ -25,12 +25,12 @@ public IEnumerable GetPossible(PKM _, EvoCriteria[] chain, GameV public IEnumerable GetEncounters(PKM pk, EvoCriteria[] chain, LegalInfo info) { - var iterator = new EncounterEnumerator5(pk, chain, (GameVersion)pk.Version); + var iterator = new EncounterEnumerator5(pk, chain, pk.Version); foreach (var enc in iterator) yield return enc.Encounter; } - private const int Generation = 5; + private const byte Generation = 5; private const EntityContext Context = EntityContext.Gen5; private const byte EggLevel = EggStateLegality.EggMetLevel; diff --git a/PKHeX.Core/Legality/Encounters/Generator/ByGeneration/EncounterGenerator6.cs b/PKHeX.Core/Legality/Encounters/Generator/ByGeneration/EncounterGenerator6.cs index 1b806826d..008b588b6 100644 --- a/PKHeX.Core/Legality/Encounters/Generator/ByGeneration/EncounterGenerator6.cs +++ b/PKHeX.Core/Legality/Encounters/Generator/ByGeneration/EncounterGenerator6.cs @@ -23,12 +23,12 @@ public IEnumerable GetEncounters(PKM pk, LegalInfo info) public IEnumerable GetEncounters(PKM pk, EvoCriteria[] chain, LegalInfo info) { - var iterator = new EncounterEnumerator6(pk, chain, (GameVersion)pk.Version); + var iterator = new EncounterEnumerator6(pk, chain, pk.Version); foreach (var enc in iterator) yield return enc.Encounter; } - private const int Generation = 6; + private const byte Generation = 6; private const EntityContext Context = EntityContext.Gen6; private const byte EggLevel = EggStateLegality.EggMetLevel; diff --git a/PKHeX.Core/Legality/Encounters/Generator/ByGeneration/EncounterGenerator7.cs b/PKHeX.Core/Legality/Encounters/Generator/ByGeneration/EncounterGenerator7.cs index 1f7af12ea..a8508e160 100644 --- a/PKHeX.Core/Legality/Encounters/Generator/ByGeneration/EncounterGenerator7.cs +++ b/PKHeX.Core/Legality/Encounters/Generator/ByGeneration/EncounterGenerator7.cs @@ -17,7 +17,7 @@ public IEnumerable GetPossible(PKM _, EvoCriteria[] chain, GameV public IEnumerable GetEncounters(PKM pk, EvoCriteria[] chain, LegalInfo info) { - var iterator = new EncounterEnumerator7(pk, chain, (GameVersion)pk.Version); + var iterator = new EncounterEnumerator7(pk, chain, pk.Version); foreach (var enc in iterator) yield return enc.Encounter; } @@ -25,7 +25,7 @@ public IEnumerable GetEncounters(PKM pk, EvoCriteria[] chain, Le internal static EncounterTransfer7 GetVCStaticTransferEncounter(PKM pk, ushort encSpecies, ReadOnlySpan chain) { // Obtain the lowest evolution species with matching OT friendship. Not all species chains have the same base friendship. - var met = (byte)pk.Met_Level; + var met = pk.MetLevel; if (pk.VC1) { // Only yield a VC1 template if it could originate in VC1. @@ -43,7 +43,7 @@ internal static EncounterTransfer7 GetVCStaticTransferEncounter(PKM pk, ushort e } /// - /// Get the most devolved species that matches the . + /// Get the most devolved species that matches the . /// private static ushort GetVCSpecies(ReadOnlySpan chain, PKM pk, ushort maxSpecies) { @@ -54,14 +54,14 @@ private static ushort GetVCSpecies(ReadOnlySpan chain, PKM pk, usho continue; if (evo.Form != 0) continue; - if (PersonalTable.SM.GetFormEntry(evo.Species, evo.Form).BaseFriendship != pk.OT_Friendship) + if (PersonalTable.SM.GetFormEntry(evo.Species, evo.Form).BaseFriendship != pk.OriginalTrainerFriendship) continue; return evo.Species; } return pk.Species; } - private const int Generation = 7; + private const byte Generation = 7; private const EntityContext Context = EntityContext.Gen7; private const byte EggLevel = EggStateLegality.EggMetLevel; diff --git a/PKHeX.Core/Legality/Encounters/Generator/ByGeneration/EncounterGenerator7GG.cs b/PKHeX.Core/Legality/Encounters/Generator/ByGeneration/EncounterGenerator7GG.cs index ee8672473..19da12437 100644 --- a/PKHeX.Core/Legality/Encounters/Generator/ByGeneration/EncounterGenerator7GG.cs +++ b/PKHeX.Core/Legality/Encounters/Generator/ByGeneration/EncounterGenerator7GG.cs @@ -18,7 +18,7 @@ public IEnumerable GetPossible(PKM _, EvoCriteria[] chain, GameV public IEnumerable GetEncounters(PKM pk, EvoCriteria[] chain, LegalInfo info) { - var iterator = new EncounterEnumerator7GG(pk, chain, (GameVersion)pk.Version); + var iterator = new EncounterEnumerator7GG(pk, chain, pk.Version); foreach (var enc in iterator) yield return enc.Encounter; } diff --git a/PKHeX.Core/Legality/Encounters/Generator/ByGeneration/EncounterGenerator8.cs b/PKHeX.Core/Legality/Encounters/Generator/ByGeneration/EncounterGenerator8.cs index 697c775b3..76cbd5fc2 100644 --- a/PKHeX.Core/Legality/Encounters/Generator/ByGeneration/EncounterGenerator8.cs +++ b/PKHeX.Core/Legality/Encounters/Generator/ByGeneration/EncounterGenerator8.cs @@ -17,12 +17,12 @@ public IEnumerable GetPossible(PKM _, EvoCriteria[] chain, GameV public IEnumerable GetEncounters(PKM pk, EvoCriteria[] chain, LegalInfo info) { - var iterator = new EncounterEnumerator8(pk, chain, (GameVersion)pk.Version); + var iterator = new EncounterEnumerator8(pk, chain, pk.Version); foreach (var enc in iterator) yield return enc.Encounter; } - private const int Generation = 8; + private const byte Generation = 8; private const EntityContext Context = EntityContext.Gen8; private const byte EggLevel = 1; diff --git a/PKHeX.Core/Legality/Encounters/Generator/ByGeneration/EncounterGenerator8b.cs b/PKHeX.Core/Legality/Encounters/Generator/ByGeneration/EncounterGenerator8b.cs index f1478010d..b624d7c71 100644 --- a/PKHeX.Core/Legality/Encounters/Generator/ByGeneration/EncounterGenerator8b.cs +++ b/PKHeX.Core/Legality/Encounters/Generator/ByGeneration/EncounterGenerator8b.cs @@ -17,7 +17,7 @@ public IEnumerable GetPossible(PKM pk, EvoCriteria[] chain, Game public IEnumerable GetEncounters(PKM pk, EvoCriteria[] chain, LegalInfo info) { - var game = (GameVersion)pk.Version; + var game = pk.Version; var iterator = new EncounterEnumerator8b(pk, chain, game); foreach (var enc in iterator) yield return enc.Encounter; @@ -30,7 +30,7 @@ public IEnumerable GetEncountersSWSH(PKM pk, EvoCriteria[] chain yield return enc.Encounter; } - private const int Generation = 8; + private const byte Generation = 8; private const EntityContext Context = EntityContext.Gen8b; private const byte EggLevel = 1; diff --git a/PKHeX.Core/Legality/Encounters/Generator/ByGeneration/EncounterGenerator9.cs b/PKHeX.Core/Legality/Encounters/Generator/ByGeneration/EncounterGenerator9.cs index fd09d6cb3..2086fe620 100644 --- a/PKHeX.Core/Legality/Encounters/Generator/ByGeneration/EncounterGenerator9.cs +++ b/PKHeX.Core/Legality/Encounters/Generator/ByGeneration/EncounterGenerator9.cs @@ -14,10 +14,10 @@ public IEnumerable GetEncounters(PKM pk, LegalInfo info) if (chain.Length == 0) return []; - return (GameVersion)pk.Version switch + return pk.Version switch { - SW when pk.Met_Location == LocationsHOME.SWSL => Instance.GetEncountersSWSH(pk, chain, SL), - SH when pk.Met_Location == LocationsHOME.SHVL => Instance.GetEncountersSWSH(pk, chain, VL), + SW when pk.MetLocation == LocationsHOME.SWSL => Instance.GetEncountersSWSH(pk, chain, SL), + SH when pk.MetLocation == LocationsHOME.SHVL => Instance.GetEncountersSWSH(pk, chain, VL), _ => GetEncounters(pk, chain, info), }; } @@ -38,12 +38,12 @@ public IEnumerable GetEncountersSWSH(PKM pk, EvoCriteria[] chain public IEnumerable GetEncounters(PKM pk, EvoCriteria[] chain, LegalInfo info) { - var iterator = new EncounterEnumerator9(pk, chain, (GameVersion)pk.Version); + var iterator = new EncounterEnumerator9(pk, chain, pk.Version); foreach (var enc in iterator) yield return enc.Encounter; } - private const int Generation = 9; + private const byte Generation = 9; private const EntityContext Context = EntityContext.Gen9; private const byte EggLevel = 1; diff --git a/PKHeX.Core/Legality/Encounters/Generator/ByGeneration/EncounterStateUtil.cs b/PKHeX.Core/Legality/Encounters/Generator/ByGeneration/EncounterStateUtil.cs index 4c6974ca0..0dac8dad2 100644 --- a/PKHeX.Core/Legality/Encounters/Generator/ByGeneration/EncounterStateUtil.cs +++ b/PKHeX.Core/Legality/Encounters/Generator/ByGeneration/EncounterStateUtil.cs @@ -27,11 +27,11 @@ public static bool CanBeWildEncounter(PKM pk) /// Only applicable for Generation 4 origins and above. public static bool IsMetAsEgg(PKM pk) => pk switch { - // This all could be simplified to just checking Egg_Day != 0 without type checks. - // Leaving like this to indicate how Egg_Location is not a true indicator due to quirks from BD/SP. + // This all could be simplified to just checking EggDay != 0 without type checks. + // Leaving like this to indicate how EggLocation is not a true indicator due to quirks from BD/SP. - PA8 or PK8 => pk.Egg_Location is not 0 || pk is { BDSP: true, Egg_Day: not 0 }, - PB8 pb8 => pb8.Egg_Location is not Locations.Default8bNone, - _ => pk.Egg_Location is not 0, + PA8 or PK8 => pk.EggLocation is not 0 || pk is { BDSP: true, EggDay: not 0 }, + PB8 pb8 => pb8.EggLocation is not Locations.Default8bNone, + _ => pk.EggLocation is not 0, }; } diff --git a/PKHeX.Core/Legality/Encounters/Generator/ByGeneration/Lump/EncounterGenerator12.cs b/PKHeX.Core/Legality/Encounters/Generator/ByGeneration/Lump/EncounterGenerator12.cs index 663e660f7..4b13d73cd 100644 --- a/PKHeX.Core/Legality/Encounters/Generator/ByGeneration/Lump/EncounterGenerator12.cs +++ b/PKHeX.Core/Legality/Encounters/Generator/ByGeneration/Lump/EncounterGenerator12.cs @@ -22,7 +22,7 @@ public IEnumerable GetEncounters(PKM pk, LegalInfo info) private static IEnumerable GetEncounters(PKM pk) { // If the current data indicates that it must have originated from Crystal, only yield encounter data from Crystal. - bool crystal = pk is ICaughtData2 { CaughtData: not 0 } or { Format: >= 7, OT_Gender: 1 }; + bool crystal = pk is ICaughtData2 { CaughtData: not 0 } or { Format: >= 7, OriginalTrainerGender: 1 }; if (crystal) return EncounterGenerator2.Instance.GetEncounters(pk, GameVersion.C); diff --git a/PKHeX.Core/Legality/Encounters/Generator/ByGeneration/Lump/EncounterGenerator7X.cs b/PKHeX.Core/Legality/Encounters/Generator/ByGeneration/Lump/EncounterGenerator7X.cs index b12ce3bf1..d3d644383 100644 --- a/PKHeX.Core/Legality/Encounters/Generator/ByGeneration/Lump/EncounterGenerator7X.cs +++ b/PKHeX.Core/Legality/Encounters/Generator/ByGeneration/Lump/EncounterGenerator7X.cs @@ -8,8 +8,8 @@ public sealed class EncounterGenerator7X : IEncounterGenerator public IEnumerable GetPossible(PKM pk, EvoCriteria[] chain, GameVersion game, EncounterTypeGroup groups) => pk.Version switch { - (int)GameVersion.GO => EncounterGenerator7GO.Instance.GetPossible(pk, chain, game, groups), - > (int)GameVersion.GO => EncounterGenerator7GG.Instance.GetPossible(pk, chain, game, groups), + GameVersion.GO => EncounterGenerator7GO.Instance.GetPossible(pk, chain, game, groups), + > GameVersion.GO => EncounterGenerator7GG.Instance.GetPossible(pk, chain, game, groups), _ => EncounterGenerator7.Instance.GetPossible(pk, chain, game, groups), }; @@ -21,8 +21,8 @@ public IEnumerable GetEncounters(PKM pk, LegalInfo info) public IEnumerable GetEncounters(PKM pk, EvoCriteria[] chain, LegalInfo info) => pk.Version switch { - (int)GameVersion.GO => EncounterGenerator7GO.Instance.GetEncounters(pk, chain, info), - > (int)GameVersion.GO => EncounterGenerator7GG.Instance.GetEncounters(pk, chain, info), + GameVersion.GO => EncounterGenerator7GO.Instance.GetEncounters(pk, chain, info), + > GameVersion.GO => EncounterGenerator7GG.Instance.GetEncounters(pk, chain, info), _ => EncounterGenerator7.Instance.GetEncounters(pk, chain, info), }; } diff --git a/PKHeX.Core/Legality/Encounters/Generator/ByGeneration/Lump/EncounterGenerator8X.cs b/PKHeX.Core/Legality/Encounters/Generator/ByGeneration/Lump/EncounterGenerator8X.cs index 1b48e3312..45f489ebd 100644 --- a/PKHeX.Core/Legality/Encounters/Generator/ByGeneration/Lump/EncounterGenerator8X.cs +++ b/PKHeX.Core/Legality/Encounters/Generator/ByGeneration/Lump/EncounterGenerator8X.cs @@ -21,16 +21,16 @@ public IEnumerable GetEncounters(PKM pk, LegalInfo info) return GetEncounters(pk, chain, info); } - public IEnumerable GetEncounters(PKM pk, EvoCriteria[] chain, LegalInfo info) => (GameVersion)pk.Version switch + public IEnumerable GetEncounters(PKM pk, EvoCriteria[] chain, LegalInfo info) => pk.Version switch { GO => EncounterGeneratorGO.Instance.GetEncounters(pk, chain, info), PLA => EncounterGenerator8a.Instance.GetEncounters(pk, chain, info), BD or SP => EncounterGenerator8b.Instance.GetEncounters(pk, chain, info), - SW when pk.Met_Location == LocationsHOME.SWLA => EncounterGenerator8a.Instance.GetEncounters(pk, chain, info), - SW when pk.Met_Location == LocationsHOME.SWBD => EncounterGenerator8b.Instance.GetEncountersSWSH(pk, chain, BD), - SH when pk.Met_Location == LocationsHOME.SHSP => EncounterGenerator8b.Instance.GetEncountersSWSH(pk, chain, SP), - SW when pk.Met_Location == LocationsHOME.SWSL => EncounterGenerator9.Instance.GetEncountersSWSH(pk, chain, SL), - SH when pk.Met_Location == LocationsHOME.SHVL => EncounterGenerator9.Instance.GetEncountersSWSH(pk, chain, VL), + SW when pk.MetLocation == LocationsHOME.SWLA => EncounterGenerator8a.Instance.GetEncounters(pk, chain, info), + SW when pk.MetLocation == LocationsHOME.SWBD => EncounterGenerator8b.Instance.GetEncountersSWSH(pk, chain, BD), + SH when pk.MetLocation == LocationsHOME.SHSP => EncounterGenerator8b.Instance.GetEncountersSWSH(pk, chain, SP), + SW when pk.MetLocation == LocationsHOME.SWSL => EncounterGenerator9.Instance.GetEncountersSWSH(pk, chain, SL), + SH when pk.MetLocation == LocationsHOME.SHVL => EncounterGenerator9.Instance.GetEncountersSWSH(pk, chain, VL), _ => EncounterGenerator8.Instance.GetEncounters(pk, chain, info), }; } diff --git a/PKHeX.Core/Legality/Encounters/Generator/ByGeneration/Lump/EncounterGeneratorGO.cs b/PKHeX.Core/Legality/Encounters/Generator/ByGeneration/Lump/EncounterGeneratorGO.cs index d6790315b..61fa72a3f 100644 --- a/PKHeX.Core/Legality/Encounters/Generator/ByGeneration/Lump/EncounterGeneratorGO.cs +++ b/PKHeX.Core/Legality/Encounters/Generator/ByGeneration/Lump/EncounterGeneratorGO.cs @@ -8,7 +8,7 @@ public sealed class EncounterGeneratorGO : IEncounterGenerator public IEnumerable GetEncounters(PKM pk, EvoCriteria[] chain, LegalInfo info) { - var loc = pk.Met_Location; + var loc = pk.MetLocation; if (loc == Locations.GO7) return EncounterGenerator7GO.Instance.GetEncounters(pk, chain, info); if (loc == Locations.GO8 && pk is not PB7) diff --git a/PKHeX.Core/Legality/Encounters/Generator/EncounterCriteria.cs b/PKHeX.Core/Legality/Encounters/Generator/EncounterCriteria.cs index a3025a948..f86a8ea6b 100644 --- a/PKHeX.Core/Legality/Encounters/Generator/EncounterCriteria.cs +++ b/PKHeX.Core/Legality/Encounters/Generator/EncounterCriteria.cs @@ -6,7 +6,7 @@ namespace PKHeX.Core; /// /// Object that can be fed to a converter to ensure that the resulting meets rough specifications. /// -public sealed record EncounterCriteria : IFixedNature, IFixedGender, IFixedAbilityNumber, IShinyPotential +public sealed record EncounterCriteria : IFixedNature, IFixedAbilityNumber, IShinyPotential { /// /// Default criteria with no restrictions (random) for all fields. @@ -14,8 +14,8 @@ public sealed record EncounterCriteria : IFixedNature, IFixedGender, IFixedAbili public static readonly EncounterCriteria Unrestricted = new(); /// End result's gender. - /// Leave as -1 to not restrict gender. - public byte Gender { get; init; } = FixedGenderUtil.GenderRandom; + /// Leave as null to not restrict gender. + public byte? Gender { get; init; } /// End result's ability numbers permitted. /// Leave as to not restrict ability. @@ -48,13 +48,23 @@ public sealed record EncounterCriteria : IFixedNature, IFixedGender, IFixedAbili private const int RandomIV = -1; + public bool IsSpecifiedNature() => Nature != Nature.Random; + public bool IsSpecifiedTeraType() => TeraType != -1; + + public bool IsSpecifiedIVs() => IV_HP != RandomIV + && IV_ATK != RandomIV + && IV_DEF != RandomIV + && IV_SPA != RandomIV + && IV_SPD != RandomIV + && IV_SPE != RandomIV; + /// /// Checks if the IVs are compatible with the encounter's defined IV restrictions. /// /// Encounter template's IV restrictions. Speed is last! /// Destination generation /// True if compatible, false if incompatible. - public bool IsIVsCompatibleSpeedLast(Span encounterIVs, int generation) + public bool IsIVsCompatibleSpeedLast(Span encounterIVs, byte generation) { var IVs = encounterIVs; if (!ivCanMatch(IV_HP , IVs[0])) return false; @@ -91,7 +101,7 @@ public static EncounterCriteria GetCriteria(IBattleTemplate s, IPersonalTable t) /// Initialized criteria data to be passed to generators. public static EncounterCriteria GetCriteria(IBattleTemplate s, IPersonalInfo pi) => new() { - Gender = (byte)s.Gender, + Gender = s.Gender, IV_HP = s.IVs[0], IV_ATK = s.IVs[1], IV_DEF = s.IVs[2], @@ -146,27 +156,45 @@ public Nature GetNature() return (Nature)Util.Rand.Next(25); } + /// + /// Indicates if the is specified. + /// + public bool IsGenderSpecified => Gender != null; + + /// + /// Indicates if the requested gender matches the criteria. + /// + public bool IsGenderSatisfied(byte gender) => !IsGenderSpecified || gender == Gender; + /// /// Gets the gender to generate, random if unspecified by the template or criteria. /// - public int GetGender(int gender, IGenderDetail pkPersonalInfo) + public byte GetGender(byte gender, IGenderDetail pkPersonalInfo) { if ((uint)gender < 3) return gender; return GetGender(pkPersonalInfo); } + /// + public byte GetGender(Gender gender, IGenderDetail pkPersonalInfo) + { + if (gender == Core.Gender.Random) + return GetGender(pkPersonalInfo); + return (byte)gender; + } + /// /// Gets the gender to generate, random if unspecified. /// - public int GetGender(IGenderDetail pkPersonalInfo) + public byte GetGender(IGenderDetail pkPersonalInfo) { if (!pkPersonalInfo.IsDualGender) return pkPersonalInfo.FixedGender(); if (pkPersonalInfo.Genderless) return 2; - if (Gender is 0 or 1) - return Gender; + if (Gender is { } request and (0 or 1)) + return request; return pkPersonalInfo.RandomGender(); } diff --git a/PKHeX.Core/Legality/Encounters/Generator/EncounterFinder.cs b/PKHeX.Core/Legality/Encounters/Generator/EncounterFinder.cs index 7e4afe25d..d5620e174 100644 --- a/PKHeX.Core/Legality/Encounters/Generator/EncounterFinder.cs +++ b/PKHeX.Core/Legality/Encounters/Generator/EncounterFinder.cs @@ -67,10 +67,14 @@ public static void FindVerifiedEncounter(PKM pk, LegalInfo info) break; } - if (info is { FrameMatches: false }) // if false, all valid RNG frame matches have already been consumed - info.Parse.Add(new CheckResult(ParseSettings.RNGFrameNotFound, CheckIdentifier.PID, LEncConditionBadRNGFrame)); // todo for further confirmation - if (!info.PIDIVMatches) // if false, all valid PIDIV matches have already been consumed - info.Parse.Add(new CheckResult(Severity.Invalid, CheckIdentifier.PID, LPIDTypeMismatch)); + var manual = info.ManualFlag; + if (manual != EncounterYieldFlag.None) + { + if (!info.FrameMatches) // if false, all valid RNG frame matches have already been consumed + info.Parse.Add(new CheckResult(info.Generation == 3 ? ParseSettings.RNGFrameNotFound3 : ParseSettings.RNGFrameNotFound4, CheckIdentifier.PID, LEncConditionBadRNGFrame)); + else if (!info.PIDIVMatches) // if false, all valid PIDIV matches have already been consumed + info.Parse.Add(new CheckResult(Severity.Invalid, CheckIdentifier.PID, LPIDTypeMismatch)); + } } /// @@ -115,14 +119,14 @@ private static bool VerifySecondaryChecks(PKM pk, LegalInfo info, PeekEnumerator // Memories of Knowing a move which is later forgotten can be problematic with encounters that have special moves. if (pk is ITrainerMemories m) { - if (m is IMemoryOT o && MemoryPermissions.IsMemoryOfKnownMove(o.OT_Memory)) + if (m is IMemoryOT o && MemoryPermissions.IsMemoryOfKnownMove(o.OriginalTrainerMemory)) { var mem = MemoryVariableSet.Read(m, 0); bool valid = MemoryPermissions.CanKnowMove(pk, mem, info.EncounterMatch.Context, info); if (!valid && iterator.PeekIsNext()) return false; } - if (m is IMemoryHT h && MemoryPermissions.IsMemoryOfKnownMove(h.HT_Memory) && !pk.HasMove(h.HT_TextVar)) + if (m is IMemoryHT h && MemoryPermissions.IsMemoryOfKnownMove(h.HandlingTrainerMemory) && !pk.HasMove(h.HandlingTrainerMemoryVariable)) { var mem = MemoryVariableSet.Read(m, 1); @@ -167,9 +171,9 @@ private static void VerifyWithoutEncounter(PKM pk, LegalInfo info) LearnVerifier.Verify(info.Moves, pk, info.EncounterMatch, info.EvoChainsAllGens); } - private static string GetHintWhyNotFound(PKM pk, int generation) + private static string GetHintWhyNotFound(PKM pk, byte generation) { - if (WasGiftEgg(pk, generation, (ushort)pk.Egg_Location)) + if (WasGiftEgg(pk, generation, pk.EggLocation)) return LEncGift; if (WasEventEgg(pk, generation)) return LEncGiftEggEvent; @@ -178,29 +182,29 @@ private static string GetHintWhyNotFound(PKM pk, int generation) return LEncInvalid; } - private static bool WasGiftEgg(PKM pk, int generation, ushort eggLocation) => !pk.FatefulEncounter && generation switch + private static bool WasGiftEgg(PKM pk, byte generation, ushort eggLocation) => !pk.FatefulEncounter && generation switch { - 3 => pk.IsEgg && (byte)pk.Met_Location == 253, // Gift Egg, indistinguishable from normal eggs after hatch + 3 => pk.IsEgg && (byte)pk.MetLocation == 253, // Gift Egg, indistinguishable from normal eggs after hatch 4 => eggLocation - 2009u <= (2014 - 2009) || (pk.Format != 4 && (eggLocation == Locations.Faraway4 && pk.HGSS)), 5 => eggLocation is Locations.Breeder5, _ => eggLocation is Locations.Breeder6, }; - private static bool WasEventEgg(PKM pk, int gen) => gen switch + private static bool WasEventEgg(PKM pk, byte generation) => generation switch { // Event Egg, indistinguishable from normal eggs after hatch // can't tell after transfer - 3 => pk is { Context: EntityContext.Gen3, IsEgg: true } && Locations.IsEventLocation3(pk.Met_Location), + 3 => pk is { Context: EntityContext.Gen3, IsEgg: true } && Locations.IsEventLocation3(pk.MetLocation), // Manaphy was the only generation 4 released event egg - _ => pk.FatefulEncounter && pk.Egg_Day != 0, + _ => pk.FatefulEncounter && pk.EggDay != 0, }; - private static bool WasEvent(PKM pk, int gen) => pk.FatefulEncounter || gen switch + private static bool WasEvent(PKM pk, byte generation) => pk.FatefulEncounter || generation switch { - 3 => Locations.IsEventLocation3(pk.Met_Location) && pk.Format == 3, - 4 => Locations.IsEventLocation4(pk.Met_Location) && pk.Format == 4, - >=5 => Locations.IsEventLocation5(pk.Met_Location), + 3 => Locations.IsEventLocation3(pk.MetLocation) && pk.Format == 3, + 4 => Locations.IsEventLocation4(pk.MetLocation) && pk.Format == 4, + >=5 => Locations.IsEventLocation5(pk.MetLocation), _ => false, }; } diff --git a/PKHeX.Core/Legality/Encounters/Generator/EncounterGenerator.cs b/PKHeX.Core/Legality/Encounters/Generator/EncounterGenerator.cs index ebb0a71bc..e9f7eee89 100644 --- a/PKHeX.Core/Legality/Encounters/Generator/EncounterGenerator.cs +++ b/PKHeX.Core/Legality/Encounters/Generator/EncounterGenerator.cs @@ -21,7 +21,7 @@ public static class EncounterGenerator { 1 => EncounterGenerator12.Instance.GetEncounters(pk, info), 2 => EncounterGenerator12.Instance.GetEncounters(pk, info), - 3 => pk.Version == (int)GameVersion.CXD + 3 => pk.Version == GameVersion.CXD ? EncounterGenerator3GC.Instance.GetEncounters(pk, info) : EncounterGenerator3.Instance.GetEncounters(pk, info), 4 => EncounterGenerator4.Instance.GetEncounters(pk, info), @@ -44,7 +44,7 @@ public static class EncounterGenerator /// /// Original encounter version /// Generation group - public static IEncounterGenerator GetGeneration(GameVersion version, int generation) => generation switch + public static IEncounterGenerator GetGeneration(GameVersion version, byte generation) => generation switch { 1 => EncounterGenerator1.Instance, 2 => EncounterGenerator2.Instance, diff --git a/PKHeX.Core/Legality/Encounters/Generator/Moveset/EncounterMovesetGenerator.cs b/PKHeX.Core/Legality/Encounters/Generator/Moveset/EncounterMovesetGenerator.cs index 5d43421ae..93459e7ed 100644 --- a/PKHeX.Core/Legality/Encounters/Generator/Moveset/EncounterMovesetGenerator.cs +++ b/PKHeX.Core/Legality/Encounters/Generator/Moveset/EncounterMovesetGenerator.cs @@ -38,9 +38,9 @@ public static IEnumerable GenerateEncounters(PKM pk, ITrainerInf OptimizeCriteria(pk, info); var vers = versions.Length >= 1 ? versions : GameUtil.GetVersionsWithinRange(pk, pk.Format); - foreach (var ver in vers) + foreach (var version in vers) { - var encounters = GenerateVersionEncounters(pk, moves, ver); + var encounters = GenerateVersionEncounters(pk, moves, version); foreach (var enc in encounters) yield return enc; } @@ -54,7 +54,7 @@ public static IEnumerable GenerateEncounters(PKM pk, ITrainerInf public static void OptimizeCriteria(PKM pk, ITrainerID32 info) { pk.ID32 = info.ID32; // Necessary for Gen2 Headbutt encounters and Honey Tree encounters - var htTrash = pk.HT_Trash; + var htTrash = pk.HandlingTrainerTrash; if (htTrash.Length != 0) htTrash[0] = 1; // Fake Trash to indicate trading. } @@ -66,7 +66,7 @@ public static void OptimizeCriteria(PKM pk, ITrainerID32 info) /// Specific generation to iterate versions for. /// Moves that the resulting must be able to learn. /// A consumable list of possible encounters. - public static IEnumerable GenerateEncounter(PKM pk, int generation, ReadOnlyMemory moves) + public static IEnumerable GenerateEncounter(PKM pk, byte generation, ReadOnlyMemory moves) { var vers = GameUtil.GetVersionsInGeneration(generation, pk.Version); return GenerateEncounters(pk, moves, vers); @@ -92,9 +92,9 @@ public static IEnumerable GenerateEncounters(PKM pk, ReadOnlyMem } var vers = GameUtil.GetVersionsWithinRange(pk, pk.Format); - foreach (var ver in vers) + foreach (var version in vers) { - foreach (var enc in GenerateVersionEncounters(pk, moves, ver)) + foreach (var enc in GenerateVersionEncounters(pk, moves, version)) yield return enc; } } @@ -111,9 +111,9 @@ public static IEnumerable GenerateEncounters(PKM pk, ReadOnlyMem if (!IsSane(pk, moves.Span)) yield break; - foreach (var ver in vers) + foreach (var version in vers) { - foreach (var enc in GenerateVersionEncounters(pk, moves, ver)) + foreach (var enc in GenerateVersionEncounters(pk, moves, version)) yield return enc; } } @@ -127,9 +127,9 @@ public static IEnumerable GenerateEncounters(PKM pk, ReadOnlyMem /// A consumable list of possible encounters. private static IEnumerable GenerateVersionEncounters(PKM pk, ReadOnlyMemory moves, GameVersion version) { - pk.Version = (byte)version; + pk.Version = version; var context = version.GetContext(); - var generation = (byte)version.GetGeneration(); + var generation = version.GetGeneration(); foreach (var enc in GenerateVersionEncounters(pk, moves, version, generation, context)) yield return enc; @@ -145,7 +145,7 @@ private static IEnumerable GenerateVersionEncounters(PKM pk, Rea private static IEnumerable GenerateVersionEncounters(PKM pk, ReadOnlyMemory moves, GameVersion version, byte generation, EntityContext context) { - var origin = new EvolutionOrigin(pk.Species, (byte)version, generation, 1, 100, OriginOptions.EncounterTemplate); + var origin = new EvolutionOrigin(pk.Species, version, generation, 1, 100, OriginOptions.EncounterTemplate); var chain = EvolutionChain.GetOriginChain(pk, origin); if (chain.Length == 0) yield break; @@ -193,7 +193,7 @@ private static bool IsPlausibleSmeargleMoveset(EntityContext context, ReadOnlySp return true; } - private readonly record struct NeededEncounter(EntityContext Context, int Generation, GameVersion Version) + private readonly record struct NeededEncounter(EntityContext Context, byte Generation, GameVersion Version) : IEncounterTemplate { public bool EggEncounter => false; @@ -205,7 +205,7 @@ private static bool IsPlausibleSmeargleMoveset(EntityContext context, ReadOnlySp public bool IsShiny => false; } - private static ushort[] GetNeededMoves(PKM pk, ReadOnlySpan moves, GameVersion ver, int generation, EntityContext context) + private static ushort[] GetNeededMoves(PKM pk, ReadOnlySpan moves, GameVersion version, byte generation, EntityContext context) { if (pk.Species == (int)Species.Smeargle) return []; @@ -213,9 +213,9 @@ private static ushort[] GetNeededMoves(PKM pk, ReadOnlySpan moves, GameV var length = pk.MaxMoveID + 1; var rent = ArrayPool.Shared.Rent(length); var permitted = rent.AsSpan(0, length); - var enc = new EvolutionOrigin(pk.Species, (byte)ver, (byte)generation, 1, 100, OriginOptions.EncounterTemplate); + var enc = new EvolutionOrigin(pk.Species, version, generation, 1, 100, OriginOptions.EncounterTemplate); var history = EvolutionChain.GetEvolutionChainsSearch(pk, enc, context, 0); - var e = new NeededEncounter(context, generation, ver); // default empty + var e = new NeededEncounter(context, generation, version); // default empty LearnPossible.Get(pk, e, history, permitted); int ctr = 0; // count of moves that can be learned diff --git a/PKHeX.Core/Legality/Encounters/Generator/Possible/EncounterPossible2.cs b/PKHeX.Core/Legality/Encounters/Generator/Possible/EncounterPossible2.cs index 2496116eb..cc8d96ad2 100644 --- a/PKHeX.Core/Legality/Encounters/Generator/Possible/EncounterPossible2.cs +++ b/PKHeX.Core/Legality/Encounters/Generator/Possible/EncounterPossible2.cs @@ -61,8 +61,8 @@ public bool MoveNext() case YieldState.Bred: // try with specific version, for yielded metadata purposes. - var ver = Version is GameVersion.GD or GameVersion.SI ? Version : GameVersion.GS; - if (!EncounterGenerator2.TryGetEgg(Chain, ver, out var egg)) + var version = Version is GameVersion.GD or GameVersion.SI ? Version : GameVersion.GS; + if (!EncounterGenerator2.TryGetEgg(Chain, version, out var egg)) goto case YieldState.TradeStart; State = ParseSettings.AllowGen2Crystal(Entity) ? YieldState.BredCrystal : YieldState.TradeStart; return SetCurrent(egg); diff --git a/PKHeX.Core/Legality/Encounters/Generator/Possible/EncounterPossible4.cs b/PKHeX.Core/Legality/Encounters/Generator/Possible/EncounterPossible4.cs index e11a0343d..58594ca08 100644 --- a/PKHeX.Core/Legality/Encounters/Generator/Possible/EncounterPossible4.cs +++ b/PKHeX.Core/Legality/Encounters/Generator/Possible/EncounterPossible4.cs @@ -222,7 +222,7 @@ private bool TryGetNext(EncounterArea4[] areas) for (; Index < db.Length;) { var enc = db[Index++]; - if (!enc.CanBeReceivedByVersion((int)Version)) + if (!enc.CanBeReceivedByVersion(Version)) continue; foreach (var evo in Chain) { diff --git a/PKHeX.Core/Legality/Encounters/Generator/Possible/EncounterPossible5.cs b/PKHeX.Core/Legality/Encounters/Generator/Possible/EncounterPossible5.cs index 9ee8f48f1..70e2f2dad 100644 --- a/PKHeX.Core/Legality/Encounters/Generator/Possible/EncounterPossible5.cs +++ b/PKHeX.Core/Legality/Encounters/Generator/Possible/EncounterPossible5.cs @@ -273,7 +273,7 @@ public bool MoveNext() for (; Index < db.Length;) { var enc = db[Index++]; - if (!enc.CanBeReceivedByVersion((int)Version)) + if (!enc.CanBeReceivedByVersion(Version)) continue; foreach (var evo in Chain) { diff --git a/PKHeX.Core/Legality/Encounters/Generator/Possible/EncounterPossible6.cs b/PKHeX.Core/Legality/Encounters/Generator/Possible/EncounterPossible6.cs index 0c50be832..e0e60dd6b 100644 --- a/PKHeX.Core/Legality/Encounters/Generator/Possible/EncounterPossible6.cs +++ b/PKHeX.Core/Legality/Encounters/Generator/Possible/EncounterPossible6.cs @@ -232,7 +232,7 @@ public bool MoveNext() for (; Index < db.Length;) { var enc = db[Index++]; - if (!enc.CanBeReceivedByVersion((int)Version)) + if (!enc.CanBeReceivedByVersion(Version)) continue; foreach (var evo in Chain) { diff --git a/PKHeX.Core/Legality/Encounters/Generator/Possible/EncounterPossible7.cs b/PKHeX.Core/Legality/Encounters/Generator/Possible/EncounterPossible7.cs index a2127bc78..9c104741f 100644 --- a/PKHeX.Core/Legality/Encounters/Generator/Possible/EncounterPossible7.cs +++ b/PKHeX.Core/Legality/Encounters/Generator/Possible/EncounterPossible7.cs @@ -231,7 +231,7 @@ public bool MoveNext() for (; Index < db.Length;) { var enc = db[Index++]; - if (!enc.CanBeReceivedByVersion((int)Version)) + if (!enc.CanBeReceivedByVersion(Version)) continue; foreach (var evo in Chain) { diff --git a/PKHeX.Core/Legality/Encounters/Generator/Possible/EncounterPossible7GG.cs b/PKHeX.Core/Legality/Encounters/Generator/Possible/EncounterPossible7GG.cs index 2f6d75328..533f21179 100644 --- a/PKHeX.Core/Legality/Encounters/Generator/Possible/EncounterPossible7GG.cs +++ b/PKHeX.Core/Legality/Encounters/Generator/Possible/EncounterPossible7GG.cs @@ -175,7 +175,7 @@ public bool MoveNext() for (; Index < db.Length;) { var enc = db[Index++]; - if (!enc.CanBeReceivedByVersion((int)Version)) + if (!enc.CanBeReceivedByVersion(Version)) continue; foreach (var evo in Chain) { diff --git a/PKHeX.Core/Legality/Encounters/Generator/Search/Dirtied/EncounterEnumerator8bSWSH.cs b/PKHeX.Core/Legality/Encounters/Generator/Search/Dirtied/EncounterEnumerator8bSWSH.cs index 103449d1b..dc350396c 100644 --- a/PKHeX.Core/Legality/Encounters/Generator/Search/Dirtied/EncounterEnumerator8bSWSH.cs +++ b/PKHeX.Core/Legality/Encounters/Generator/Search/Dirtied/EncounterEnumerator8bSWSH.cs @@ -17,7 +17,7 @@ public record struct EncounterEnumerator8bSWSH(PKM Entity, EvoCriteria[] Chain, private bool Yielded; public MatchedEncounter Current { get; private set; } private YieldState State; - private int met; + private ushort met; private bool hasOriginalLocation; private bool mustBeWild; readonly object IEnumerator.Current => Current; @@ -152,23 +152,23 @@ public bool MoveNext() return false; } - private readonly bool WasBredEggBDSP() => Entity.Met_Level == EggStateLegality.EggMetLevel && Entity.Egg_Location switch + private readonly bool WasBredEggBDSP() => Entity.MetLevel == EggStateLegality.EggMetLevel && Entity.EggLocation switch { LocationsHOME.SWSHEgg => true, // Regular hatch location (not link trade) - LocationsHOME.SWBD => Entity.Met_Location == LocationsHOME.SWBD, // Link Trade transferred over must match Met Location - LocationsHOME.SHSP => Entity.Met_Location == LocationsHOME.SHSP, // Link Trade transferred over must match Met Location + LocationsHOME.SWBD => Entity.MetLocation == LocationsHOME.SWBD, // Link Trade transferred over must match Met Location + LocationsHOME.SHSP => Entity.MetLocation == LocationsHOME.SHSP, // Link Trade transferred over must match Met Location _ => false, }; private void InitializeWildLocationInfo() { mustBeWild = Entity.Ball == (byte)Ball.Safari; - met = Entity.Met_Location; + met = Entity.MetLocation; var location = met; var remap = LocationsHOME.GetRemapState(EntityContext.Gen8b, Entity.Context); hasOriginalLocation = true; if (remap.HasFlag(LocationRemapState.Remapped)) - hasOriginalLocation = location != LocationsHOME.GetMetSWSH((ushort)location, (int)Version); + hasOriginalLocation = location != LocationsHOME.GetMetSWSH(location, Version); } private bool TryGetNext(TArea[] areas) diff --git a/PKHeX.Core/Legality/Encounters/Generator/Search/Dirtied/EncounterEnumerator9SWSH.cs b/PKHeX.Core/Legality/Encounters/Generator/Search/Dirtied/EncounterEnumerator9SWSH.cs index 39f862306..f7cc85328 100644 --- a/PKHeX.Core/Legality/Encounters/Generator/Search/Dirtied/EncounterEnumerator9SWSH.cs +++ b/PKHeX.Core/Legality/Encounters/Generator/Search/Dirtied/EncounterEnumerator9SWSH.cs @@ -16,7 +16,7 @@ public record struct EncounterEnumerator9SWSH(PKM Entity, EvoCriteria[] Chain, G private bool Yielded; public MatchedEncounter Current { get; private set; } private YieldState State; - //private int met; + //private ushort met; private bool mustBeSlot; readonly object IEnumerator.Current => Current; @@ -80,7 +80,7 @@ public bool MoveNext() goto case YieldState.TradeStart; case YieldState.TradeStart: - //if (Entity.Met_Location == Locations.LinkTrade6NPC) + //if (Entity.MetLocation == Locations.LinkTrade6NPC) // goto case YieldState.Trade; goto case YieldState.StartCaptures; case YieldState.Trade: @@ -170,18 +170,18 @@ public bool MoveNext() return false; } - private readonly bool WasBredEggSWSH() => Entity.Met_Level == EggStateLegality.EggMetLevel && Entity.Egg_Location switch + private readonly bool WasBredEggSWSH() => Entity.MetLevel == EggStateLegality.EggMetLevel && Entity.EggLocation switch { LocationsHOME.SWSHEgg => true, // Regular hatch location (not link trade) - LocationsHOME.SWSL => Entity.Met_Location == LocationsHOME.SWSL, // Link Trade transferred over must match Met Location - LocationsHOME.SHVL => Entity.Met_Location == LocationsHOME.SHVL, // Link Trade transferred over must match Met Location + LocationsHOME.SWSL => Entity.MetLocation == LocationsHOME.SWSL, // Link Trade transferred over must match Met Location + LocationsHOME.SHVL => Entity.MetLocation == LocationsHOME.SHVL, // Link Trade transferred over must match Met Location _ => false, }; private void InitializeWildLocationInfo() { mustBeSlot = Entity is IRibbonIndex r && r.HasEncounterMark(); - //met = Entity.Met_Location; + //met = Entity.MetLocation; } private bool TryGetNext(TArea[] areas) diff --git a/PKHeX.Core/Legality/Encounters/Generator/Search/EncounterEnumerator2.cs b/PKHeX.Core/Legality/Encounters/Generator/Search/EncounterEnumerator2.cs index 6162a7943..18c9cad66 100644 --- a/PKHeX.Core/Legality/Encounters/Generator/Search/EncounterEnumerator2.cs +++ b/PKHeX.Core/Legality/Encounters/Generator/Search/EncounterEnumerator2.cs @@ -18,7 +18,7 @@ public record struct EncounterEnumerator2 : IEnumerator(Encounters2.SlotsC)) return true; - if (hasOriginalMet || Entity.OT_Gender == 1) + if (hasOriginalMet || Entity.OriginalTrainerGender == 1) { Index = 0; goto case YieldState.SlotEnd; } Index = 0; State = YieldState.SlotGD; goto case YieldState.SlotGD; case YieldState.SlotGD: diff --git a/PKHeX.Core/Legality/Encounters/Generator/Search/EncounterEnumerator3.cs b/PKHeX.Core/Legality/Encounters/Generator/Search/EncounterEnumerator3.cs index f5a68aadd..2453eb802 100644 --- a/PKHeX.Core/Legality/Encounters/Generator/Search/EncounterEnumerator3.cs +++ b/PKHeX.Core/Legality/Encounters/Generator/Search/EncounterEnumerator3.cs @@ -15,7 +15,7 @@ public record struct EncounterEnumerator3(PKM Entity, EvoCriteria[] Chain, GameV private EncounterMatchRating Rating = EncounterMatchRating.MaxNotMatch; public MatchedEncounter Current { get; private set; } private YieldState State; - private int met; + private ushort met; private bool mustBeSlot; private bool hasOriginalLocation; @@ -244,7 +244,7 @@ public bool MoveNext() private void InitializeWildLocationInfo() { - met = Entity.Met_Location; + met = Entity.MetLocation; mustBeSlot = Entity.Ball is (int)Ball.Safari; // never static hasOriginalLocation = Entity.Format == 3; } diff --git a/PKHeX.Core/Legality/Encounters/Generator/Search/EncounterEnumerator3GC.cs b/PKHeX.Core/Legality/Encounters/Generator/Search/EncounterEnumerator3GC.cs index 72de84efd..f3a4a44f4 100644 --- a/PKHeX.Core/Legality/Encounters/Generator/Search/EncounterEnumerator3GC.cs +++ b/PKHeX.Core/Legality/Encounters/Generator/Search/EncounterEnumerator3GC.cs @@ -15,7 +15,7 @@ public record struct EncounterEnumerator3GC(PKM Entity, EvoCriteria[] Chain) : I private EncounterMatchRating Rating = EncounterMatchRating.MaxNotMatch; public MatchedEncounter Current { get; private set; } private YieldState State; - private int met; + private ushort met; private bool hasOriginalLocation; readonly object IEnumerator.Current => Current; @@ -103,7 +103,7 @@ public bool MoveNext() private void InitializeWildLocationInfo() { - met = Entity.Met_Location; + met = Entity.MetLocation; hasOriginalLocation = Entity.Format == 3; } diff --git a/PKHeX.Core/Legality/Encounters/Generator/Search/EncounterEnumerator4.cs b/PKHeX.Core/Legality/Encounters/Generator/Search/EncounterEnumerator4.cs index a2c47f05f..db7b6bb7f 100644 --- a/PKHeX.Core/Legality/Encounters/Generator/Search/EncounterEnumerator4.cs +++ b/PKHeX.Core/Legality/Encounters/Generator/Search/EncounterEnumerator4.cs @@ -16,7 +16,7 @@ public record struct EncounterEnumerator4(PKM Entity, EvoCriteria[] Chain, GameV private bool Yielded; public MatchedEncounter Current { get; private set; } private YieldState State; - private int met; + private ushort met; private bool mustBeSlot; private bool hasOriginalLocation; @@ -98,7 +98,7 @@ public bool MoveNext() Index = 0; goto case YieldState.Bred; case YieldState.Bred: - if (!Locations.IsEggLocationBred4(Entity.Egg_Location, Version)) + if (!Locations.IsEggLocationBred4(Entity.EggLocation, Version)) goto case YieldState.TradeStart; if (!EncounterGenerator4.TryGetEgg(Chain, Version, out var egg)) goto case YieldState.TradeStart; @@ -241,8 +241,8 @@ public bool MoveNext() private void InitializeWildLocationInfo() { - met = Entity.Met_Location; - mustBeSlot = Entity is { Egg_Location: 0, Ball: (int)Ball.Sport or (int)Ball.Safari }; // never static + met = Entity.MetLocation; + mustBeSlot = Entity is { EggLocation: 0, Ball: (int)Ball.Sport or (int)Ball.Safari }; // never static hasOriginalLocation = Entity.Format == 4; } diff --git a/PKHeX.Core/Legality/Encounters/Generator/Search/EncounterEnumerator5.cs b/PKHeX.Core/Legality/Encounters/Generator/Search/EncounterEnumerator5.cs index 0f110ec9e..62879240e 100644 --- a/PKHeX.Core/Legality/Encounters/Generator/Search/EncounterEnumerator5.cs +++ b/PKHeX.Core/Legality/Encounters/Generator/Search/EncounterEnumerator5.cs @@ -16,7 +16,7 @@ public record struct EncounterEnumerator5(PKM Entity, EvoCriteria[] Chain, GameV private bool Yielded; public MatchedEncounter Current { get; private set; } private YieldState State; - private int met; + private ushort met; readonly object IEnumerator.Current => Current; public readonly void Reset() => throw new NotSupportedException(); @@ -73,7 +73,7 @@ public bool MoveNext() if (Chain.Length == 0) break; - if (Entity.Met_Location == Locations.LinkTrade5NPC) + if (Entity.MetLocation == Locations.LinkTrade5NPC) goto case YieldState.TradeStart; if (!Entity.FatefulEncounter) goto case YieldState.Bred; @@ -91,14 +91,14 @@ public bool MoveNext() Index = 0; goto case YieldState.Bred; case YieldState.Bred: - if (!Locations.IsEggLocationBred5(Entity.Egg_Location)) + if (!Locations.IsEggLocationBred5(Entity.EggLocation)) goto case YieldState.StartCaptures; if (!EncounterGenerator5.TryGetEgg(Chain, Version, out var egg)) goto case YieldState.StartCaptures; State = YieldState.BredSplit; return SetCurrent(egg); case YieldState.BredSplit: - bool daycare = Entity.Egg_Location == Locations.Daycare5; + bool daycare = Entity.EggLocation == Locations.Daycare5; State = daycare ? YieldState.End : YieldState.StartCaptures; if (EncounterGenerator5.TryGetSplit((EncounterEgg)Current.Encounter, Chain, out egg)) return SetCurrent(egg); @@ -259,7 +259,7 @@ public bool MoveNext() private void InitializeWildLocationInfo() { - met = Entity.Met_Location; + met = Entity.MetLocation; } private bool TryGetNext(TArea[] areas) diff --git a/PKHeX.Core/Legality/Encounters/Generator/Search/EncounterEnumerator6.cs b/PKHeX.Core/Legality/Encounters/Generator/Search/EncounterEnumerator6.cs index c856d0d88..ae882e977 100644 --- a/PKHeX.Core/Legality/Encounters/Generator/Search/EncounterEnumerator6.cs +++ b/PKHeX.Core/Legality/Encounters/Generator/Search/EncounterEnumerator6.cs @@ -16,7 +16,7 @@ public record struct EncounterEnumerator6(PKM Entity, EvoCriteria[] Chain, GameV private bool Yielded; public MatchedEncounter Current { get; private set; } private YieldState State; - private int met; + private ushort met; readonly object IEnumerator.Current => Current; public readonly void Reset() => throw new NotSupportedException(); @@ -66,10 +66,10 @@ public bool MoveNext() if (Chain.Length == 0) break; - if (Entity.Met_Location == Locations.LinkTrade6NPC) + if (Entity.MetLocation == Locations.LinkTrade6NPC) goto case YieldState.TradeStart; - if (Entity.FatefulEncounter || Entity.Met_Location == Locations.LinkGift6) + if (Entity.FatefulEncounter || Entity.MetLocation == Locations.LinkGift6) { State = YieldState.Event; goto case YieldState.Event; } goto case YieldState.Bred; @@ -85,7 +85,7 @@ public bool MoveNext() Index = 0; goto case YieldState.Bred; case YieldState.Bred: - if (!Locations.IsEggLocationBred6(Entity.Egg_Location)) + if (!Locations.IsEggLocationBred6(Entity.EggLocation)) goto case YieldState.StartCaptures; if (!EncounterGenerator6.TryGetEgg(Chain, Version, out var egg)) break; @@ -93,7 +93,7 @@ public bool MoveNext() return SetCurrent(egg); case YieldState.BredTrade: State = YieldState.BredSplit; - if (Entity.Egg_Location != Locations.LinkTrade6) + if (Entity.EggLocation != Locations.LinkTrade6) goto case YieldState.BredSplit; egg = EncounterGenerator6.MutateEggTrade((EncounterEgg)Current.Encounter); return SetCurrent(egg); @@ -106,7 +106,7 @@ public bool MoveNext() return SetCurrent(egg); case YieldState.BredSplitTrade: State = YieldState.StartCaptures; - if (Entity.Egg_Location != Locations.LinkTrade6) + if (Entity.EggLocation != Locations.LinkTrade6) goto case YieldState.StartCaptures; egg = EncounterGenerator6.MutateEggTrade((EncounterEgg)Current.Encounter); return SetCurrent(egg); @@ -213,7 +213,7 @@ public bool MoveNext() private void InitializeWildLocationInfo() { - met = Entity.Met_Location; + met = Entity.MetLocation; } private bool TryGetNext(TArea[] areas) diff --git a/PKHeX.Core/Legality/Encounters/Generator/Search/EncounterEnumerator7.cs b/PKHeX.Core/Legality/Encounters/Generator/Search/EncounterEnumerator7.cs index a495691df..80412d1c1 100644 --- a/PKHeX.Core/Legality/Encounters/Generator/Search/EncounterEnumerator7.cs +++ b/PKHeX.Core/Legality/Encounters/Generator/Search/EncounterEnumerator7.cs @@ -16,7 +16,7 @@ public record struct EncounterEnumerator7(PKM Entity, EvoCriteria[] Chain, GameV private bool Yielded; public MatchedEncounter Current { get; private set; } private YieldState State; - private int met; + private ushort met; readonly object IEnumerator.Current => Current; public readonly void Reset() => throw new NotSupportedException(); @@ -66,7 +66,7 @@ public bool MoveNext() if (Chain.Length == 0) break; - if (Entity.Met_Location == Locations.LinkTrade6NPC) + if (Entity.MetLocation == Locations.LinkTrade6NPC) goto case YieldState.TradeStart; if (!Entity.FatefulEncounter) goto case YieldState.Bred; @@ -84,7 +84,7 @@ public bool MoveNext() Index = 0; goto case YieldState.Bred; case YieldState.Bred: - if (!Locations.IsEggLocationBred6(Entity.Egg_Location)) + if (!Locations.IsEggLocationBred6(Entity.EggLocation)) goto case YieldState.StartCaptures; if (!EncounterGenerator7.TryGetEgg(Chain, Version, out var egg)) goto case YieldState.StartCaptures; @@ -92,7 +92,7 @@ public bool MoveNext() return SetCurrent(egg); case YieldState.BredTrade: State = YieldState.BredSplit; - if (Entity.Egg_Location != Locations.LinkTrade6) + if (Entity.EggLocation != Locations.LinkTrade6) goto case YieldState.BredSplit; egg = EncounterGenerator7.MutateEggTrade((EncounterEgg)Current.Encounter); return SetCurrent(egg); @@ -105,7 +105,7 @@ public bool MoveNext() return SetCurrent(egg); case YieldState.BredSplitTrade: State = YieldState.End; - if (Entity.Egg_Location != Locations.LinkTrade6) + if (Entity.EggLocation != Locations.LinkTrade6) break; egg = EncounterGenerator7.MutateEggTrade((EncounterEgg)Current.Encounter); return SetCurrent(egg); @@ -212,7 +212,7 @@ public bool MoveNext() private void InitializeWildLocationInfo() { - met = Entity.Met_Location; + met = Entity.MetLocation; } private bool TryGetNext(TArea[] areas) diff --git a/PKHeX.Core/Legality/Encounters/Generator/Search/EncounterEnumerator7GG.cs b/PKHeX.Core/Legality/Encounters/Generator/Search/EncounterEnumerator7GG.cs index 9ec8bc5ba..801aafe11 100644 --- a/PKHeX.Core/Legality/Encounters/Generator/Search/EncounterEnumerator7GG.cs +++ b/PKHeX.Core/Legality/Encounters/Generator/Search/EncounterEnumerator7GG.cs @@ -16,7 +16,7 @@ public record struct EncounterEnumerator7GG(PKM Entity, EvoCriteria[] Chain, Gam private bool Yielded; public MatchedEncounter Current { get; private set; } private YieldState State; - private int met; + private ushort met; readonly object IEnumerator.Current => Current; public readonly void Reset() => throw new NotSupportedException(); @@ -145,7 +145,7 @@ public bool MoveNext() private void InitializeWildLocationInfo() { - met = Entity.Met_Location; + met = Entity.MetLocation; } private bool TryGetNext(TArea[] areas) diff --git a/PKHeX.Core/Legality/Encounters/Generator/Search/EncounterEnumerator8.cs b/PKHeX.Core/Legality/Encounters/Generator/Search/EncounterEnumerator8.cs index 53026817b..e4c220ea4 100644 --- a/PKHeX.Core/Legality/Encounters/Generator/Search/EncounterEnumerator8.cs +++ b/PKHeX.Core/Legality/Encounters/Generator/Search/EncounterEnumerator8.cs @@ -16,7 +16,7 @@ public record struct EncounterEnumerator8(PKM Entity, EvoCriteria[] Chain, GameV private bool Yielded; public MatchedEncounter Current { get; private set; } private YieldState State; - private int met; + private ushort met; private bool mustBeSlot; readonly object IEnumerator.Current => Current; @@ -65,7 +65,7 @@ public bool MoveNext() if (Chain.Length == 0) break; - if (Entity.Met_Location == Locations.LinkTrade6NPC) + if (Entity.MetLocation == Locations.LinkTrade6NPC) goto case YieldState.TradeStart; if (!Entity.FatefulEncounter) goto case YieldState.Bred; @@ -83,7 +83,7 @@ public bool MoveNext() Index = 0; goto case YieldState.Bred; case YieldState.Bred: - if (!Locations.IsEggLocationBred6(Entity.Egg_Location)) + if (!Locations.IsEggLocationBred6(Entity.EggLocation)) goto case YieldState.StartCaptures; if (!EncounterGenerator8.TryGetEgg(Chain, Version, out var egg)) goto case YieldState.StartCaptures; @@ -213,7 +213,7 @@ public bool MoveNext() private void InitializeWildLocationInfo() { mustBeSlot = Entity is IRibbonIndex r && r.HasEncounterMark(); - met = Entity.Met_Location; + met = Entity.MetLocation; } private bool TryGetNext(TArea[] areas) diff --git a/PKHeX.Core/Legality/Encounters/Generator/Search/EncounterEnumerator8a.cs b/PKHeX.Core/Legality/Encounters/Generator/Search/EncounterEnumerator8a.cs index ff59b46cc..e10546e17 100644 --- a/PKHeX.Core/Legality/Encounters/Generator/Search/EncounterEnumerator8a.cs +++ b/PKHeX.Core/Legality/Encounters/Generator/Search/EncounterEnumerator8a.cs @@ -16,7 +16,7 @@ public record struct EncounterEnumerator8a(PKM Entity, EvoCriteria[] Chain) : IE private bool Yielded; public MatchedEncounter Current { get; private set; } private YieldState State; - private int met; + private ushort met; private bool hasOriginalMet; readonly object IEnumerator.Current => Current; @@ -89,7 +89,7 @@ public bool MoveNext() private void InitializeWildLocationInfo() { - met = Entity.Met_Location; + met = Entity.MetLocation; var remap = LocationsHOME.GetRemapState(EntityContext.Gen8a, Entity.Context); hasOriginalMet = true; if (remap.HasFlag(LocationRemapState.Remapped)) diff --git a/PKHeX.Core/Legality/Encounters/Generator/Search/EncounterEnumerator8b.cs b/PKHeX.Core/Legality/Encounters/Generator/Search/EncounterEnumerator8b.cs index 52dc04d2c..68f085509 100644 --- a/PKHeX.Core/Legality/Encounters/Generator/Search/EncounterEnumerator8b.cs +++ b/PKHeX.Core/Legality/Encounters/Generator/Search/EncounterEnumerator8b.cs @@ -17,7 +17,7 @@ public record struct EncounterEnumerator8b(PKM Entity, EvoCriteria[] Chain, Game private bool Yielded; public MatchedEncounter Current { get; private set; } private YieldState State; - private int met; + private ushort met; private bool hasOriginalLocation; private bool mustBeSlot; readonly object IEnumerator.Current => Current; @@ -77,20 +77,20 @@ public bool MoveNext() Index = 0; goto case YieldState.Bred; case YieldState.Bred: - if (!Locations.IsEggLocationBred8b(Entity.Egg_Location)) + if (!Locations.IsEggLocationBred8b(Entity.EggLocation)) goto case YieldState.TradeStart; if (!EncounterGenerator8b.TryGetEgg(Chain, Version, out var egg)) goto case YieldState.TradeStart; State = YieldState.BredSplit; return SetCurrent(egg); case YieldState.BredSplit: - State = Entity.Egg_Location == Locations.Daycare8b ? YieldState.End : YieldState.StartCaptures; + State = Entity.EggLocation == Locations.Daycare8b ? YieldState.End : YieldState.StartCaptures; if (EncounterGenerator8b.TryGetSplit((EncounterEgg)Current.Encounter, Chain, out egg)) return SetCurrent(egg); break; case YieldState.TradeStart: - if (Entity.Met_Location != Locations.LinkTrade6NPC) + if (Entity.MetLocation != Locations.LinkTrade6NPC) goto case YieldState.StartCaptures; State = YieldState.Trade; goto case YieldState.Trade; case YieldState.Trade: @@ -160,12 +160,12 @@ public bool MoveNext() private void InitializeWildLocationInfo() { mustBeSlot = Entity.Ball == (byte)Ball.Safari; - met = Entity.Met_Location; + met = Entity.MetLocation; var location = met; var remap = LocationsHOME.GetRemapState(EntityContext.Gen8b, Entity.Context); hasOriginalLocation = true; if (remap.HasFlag(LocationRemapState.Remapped)) - hasOriginalLocation = location != LocationsHOME.GetMetSWSH((ushort)location, (int)Version); + hasOriginalLocation = location != LocationsHOME.GetMetSWSH(location, Version); } private bool TryGetNext(TArea[] areas) diff --git a/PKHeX.Core/Legality/Encounters/Generator/Search/EncounterEnumerator9.cs b/PKHeX.Core/Legality/Encounters/Generator/Search/EncounterEnumerator9.cs index f0e3ea5f0..4273ac655 100644 --- a/PKHeX.Core/Legality/Encounters/Generator/Search/EncounterEnumerator9.cs +++ b/PKHeX.Core/Legality/Encounters/Generator/Search/EncounterEnumerator9.cs @@ -16,7 +16,7 @@ public record struct EncounterEnumerator9(PKM Entity, EvoCriteria[] Chain, GameV private bool Yielded; public MatchedEncounter Current { get; private set; } private YieldState State; - private int met; + private ushort met; private bool mustBeSlot; readonly object IEnumerator.Current => Current; @@ -80,14 +80,14 @@ public bool MoveNext() case YieldState.Bred: State = Entity.IsEgg ? YieldState.StaticShared : YieldState.TradeStart; - if (Locations.IsEggLocationBred9(Entity.Egg_Location) && EncounterGenerator9.TryGetEgg(Entity, Chain, Version, out var egg)) + if (Locations.IsEggLocationBred9(Entity.EggLocation) && EncounterGenerator9.TryGetEgg(Entity, Chain, Version, out var egg)) return SetCurrent(egg); if (Entity.IsEgg) goto case YieldState.StaticShared; goto case YieldState.TradeStart; case YieldState.TradeStart: - if (Entity.Met_Location != Locations.LinkTrade6NPC) + if (Entity.MetLocation != Locations.LinkTrade6NPC) goto case YieldState.StartCaptures; State = YieldState.Trade; goto case YieldState.Trade; case YieldState.Trade: @@ -180,7 +180,7 @@ public bool MoveNext() private void InitializeWildLocationInfo() { mustBeSlot = Entity is IRibbonIndex r && r.HasEncounterMark(); - met = Entity.Met_Location; + met = Entity.MetLocation; } private bool TryGetNext(TArea[] areas) diff --git a/PKHeX.Core/Legality/Encounters/Information/EncounterSuggestion.cs b/PKHeX.Core/Legality/Encounters/Information/EncounterSuggestion.cs index f8d6142ce..7b0242038 100644 --- a/PKHeX.Core/Legality/Encounters/Information/EncounterSuggestion.cs +++ b/PKHeX.Core/Legality/Encounters/Information/EncounterSuggestion.cs @@ -14,20 +14,21 @@ public static class EncounterSuggestion /// public static EncounterSuggestionData? GetSuggestedMetInfo(PKM pk) { - int loc = GetSuggestedTransferLocation(pk); + var loc = TryGetSuggestedTransferLocation(pk); if (pk.WasEgg) return GetSuggestedEncounterEgg(pk, loc); Span chain = stackalloc EvoCriteria[EvolutionTree.MaxEvolutions]; - var origin = new EvolutionOrigin(pk.Species, (byte)pk.Version, (byte)pk.Generation, (byte)pk.CurrentLevel, (byte)pk.CurrentLevel, OriginOptions.SkipChecks); + var lvl = pk.CurrentLevel; + var origin = new EvolutionOrigin(pk.Species, pk.Version, pk.Generation, lvl, lvl, OriginOptions.SkipChecks); var count = EvolutionChain.GetOriginChain(chain, pk, origin); - var ver = (GameVersion)pk.Version; - var generator = EncounterGenerator.GetGenerator(ver); + var version = pk.Version; + var generator = EncounterGenerator.GetGenerator(version); var evos = chain[..count].ToArray(); - var w = EncounterSelection.GetMinByLevel(evos, generator.GetPossible(pk, evos, ver, EncounterTypeGroup.Slot)); - var s = EncounterSelection.GetMinByLevel(evos, generator.GetPossible(pk, evos, ver, EncounterTypeGroup.Static)); + var w = EncounterSelection.GetMinByLevel(evos, generator.GetPossible(pk, evos, version, EncounterTypeGroup.Slot)); + var s = EncounterSelection.GetMinByLevel(evos, generator.GetPossible(pk, evos, version, EncounterTypeGroup.Static)); if (w is null) return s is null ? null : GetSuggestedEncounter(pk, s, loc); @@ -52,10 +53,10 @@ public static class EncounterSuggestion return false; } - private static EncounterSuggestionData GetSuggestedEncounterEgg(PKM pk, int loc = -1) + private static EncounterSuggestionData GetSuggestedEncounterEgg(PKM pk, ushort loc = LocationNone) { int lvl = GetSuggestedEncounterEggMetLevel(pk); - var met = loc != -1 ? loc : GetSuggestedEggMetLocation(pk); + var met = loc != LocationNone ? loc : GetSuggestedEggMetLocation(pk); return new EncounterSuggestionData(pk, met, (byte)lvl); } @@ -64,16 +65,16 @@ public static int GetSuggestedEncounterEggMetLevel(PKM pk) if (pk is { IsNative: false, Generation: < 5 }) return pk.CurrentLevel; // be generous with transfer conditions if (pk.Format < 5) // and native - return pk.Format == 2 && pk.Met_Location != 0 ? 1 : 0; + return pk.Format == 2 && pk.MetLocation != 0 ? 1 : 0; return 1; // Gen5+ } - public static int GetSuggestedEncounterEggLocationEgg(PKM pk, bool traded = false) + public static ushort GetSuggestedEncounterEggLocationEgg(PKM pk, bool traded = false) { - return GetSuggestedEncounterEggLocationEgg(pk.Generation, (GameVersion)pk.Version, traded); + return GetSuggestedEncounterEggLocationEgg(pk.Generation, pk.Version, traded); } - public static int GetSuggestedEncounterEggLocationEgg(int generation, GameVersion version, bool traded = false) => generation switch + public static ushort GetSuggestedEncounterEggLocationEgg(byte generation, GameVersion version, bool traded = false) => generation switch { 1 or 2 or 3 => 0, 4 => traded ? Locations.LinkTrade4 : Locations.Daycare4, @@ -83,28 +84,28 @@ public static int GetSuggestedEncounterEggLocationEgg(PKM pk, bool traded = fals _ => traded ? Locations.LinkTrade6 : Locations.Daycare5, }; - private static EncounterSuggestionData GetSuggestedEncounter(PKM pk, IEncounterable enc, int loc = -1) + private static EncounterSuggestionData GetSuggestedEncounter(PKM pk, IEncounterable enc, ushort loc = LocationNone) { - var met = loc != -1 ? loc : enc.Location; + var met = loc != LocationNone ? loc : enc.Location; return new EncounterSuggestionData(pk, enc, met); } /// - public static int GetSuggestedEggMetLocation(PKM pk) => EggStateLegality.GetEggHatchLocation((GameVersion)pk.Version, pk.Format); + public static ushort GetSuggestedEggMetLocation(PKM pk) => EggStateLegality.GetEggHatchLocation(pk.Version, pk.Format); /// /// Gets the correct Transfer Met location for the origin game. /// /// Pokémon data to suggest for /// - /// Returns -1 if the met location is not overriden with a transfer location + /// Returns default if the met location is not overriden with a transfer location /// - public static int GetSuggestedTransferLocation(PKM pk) + public static ushort TryGetSuggestedTransferLocation(PKM pk) { - if (pk.Version == (int)GO) + if (pk.Version == GO) return Locations.GO8; if (pk.HasOriginalMetLocation) - return -1; + return LocationNone; if (pk.VC1) return Locations.Transfer1; if (pk.VC2) @@ -113,22 +114,24 @@ public static int GetSuggestedTransferLocation(PKM pk) return Locations.Transfer3; if (pk.Format >= 5) // Transporter return PK5.GetTransferMetLocation4(pk); - return -1; + return LocationNone; } - public static int GetLowestLevel(PKM pk, byte startLevel) + public const ushort LocationNone = 0; + + public static byte GetLowestLevel(PKM pk, byte startLevel) { if (startLevel >= 100) startLevel = 100; int most = 1; Span chain = stackalloc EvoCriteria[EvolutionTree.MaxEvolutions]; - var origin = new EvolutionOrigin(pk.Species, (byte)pk.Version, (byte)pk.Generation, startLevel, 100, OriginOptions.SkipChecks); + var origin = new EvolutionOrigin(pk.Species, pk.Version, pk.Generation, startLevel, 100, OriginOptions.SkipChecks); while (true) { var count = EvolutionChain.GetOriginChain(chain, pk, origin); if (count < most) // lost an evolution, prior level was minimum current level - return GetMaxLevelMax(chain) + 1; + return unchecked((byte)(GetMaxLevelMax(chain) + 1)); most = count; if (origin.LevelMax == origin.LevelMin) return startLevel; @@ -151,7 +154,7 @@ private static int GetMaxLevelMax(ReadOnlySpan evos) /// Current state is legal or invalid (false) /// Maximum level to iterate down from /// True if the level was changed, false if it was already at the lowest level possible or impossible. - public static bool IterateMinimumCurrentLevel(PKM pk, bool isLegal, int level = 100) + public static bool IterateMinimumCurrentLevel(PKM pk, bool isLegal, byte level = 100) { // Find the lowest level possible while still remaining legal. var growth = pk.PersonalInfo.EXPGrowth; @@ -166,7 +169,7 @@ public static bool IterateMinimumCurrentLevel(PKM pk, bool isLegal, int level = return false; // Skip to original - 1, since all levels [original,max] are already legal. - level = original - 1; + level = unchecked((byte)(original - 1)); } // If it's not legal, then we'll first try the max level and abort if it will never be legal. @@ -183,7 +186,7 @@ public static bool IterateMinimumCurrentLevel(PKM pk, bool isLegal, int level = } // First illegal level found, revert to the previous level. - level = Math.Min(100, level + 1); + level = Math.Min((byte)100, unchecked((byte)(level + 1))); if (level == original) // same, revert actual EXP value. { pk.EXP = originalEXP; @@ -199,19 +202,19 @@ public static bool IterateMinimumCurrentLevel(PKM pk, bool isLegal, int level = } /// - /// Gets the suggested based on a baseline and the 's current moves. + /// Gets the suggested based on a baseline and the 's current moves. /// /// Entity to calculate for /// Encounter minimum level to calculate for - /// Minimum level the can have for its - /// Brute-forces the value by cloning the and adjusting the and returning the lowest valid value. - public static int GetSuggestedMetLevel(PKM pk, int minLevel) + /// Minimum level the can have for its + /// Brute-forces the value by cloning the and adjusting the and returning the lowest valid value. + public static int GetSuggestedMetLevel(PKM pk, byte minLevel) { var clone = pk.Clone(); int minMove = -1; - for (int i = clone.CurrentLevel; i >= minLevel; i--) + for (byte i = clone.CurrentLevel; i >= minLevel; i--) { - clone.Met_Level = i; + clone.MetLevel = i; var la = new LegalityAnalysis(clone); if (la.Valid) return i; diff --git a/PKHeX.Core/Legality/Encounters/Information/EncounterSuggestionData.cs b/PKHeX.Core/Legality/Encounters/Information/EncounterSuggestionData.cs index da9e436c5..d5eb8afd8 100644 --- a/PKHeX.Core/Legality/Encounters/Information/EncounterSuggestionData.cs +++ b/PKHeX.Core/Legality/Encounters/Information/EncounterSuggestionData.cs @@ -9,14 +9,14 @@ public sealed class EncounterSuggestionData : ISpeciesForm, IRelearn, ILevelRang public ushort Species { get; } public byte Form { get; } - public int Location { get; } + public ushort Location { get; } public byte LevelMin { get; } public byte LevelMax { get; } public Moveset Relearn => Encounter is IRelearn r ? r.Relearn : default; - public EncounterSuggestionData(PKM pk, IEncounterable enc, int met) + public EncounterSuggestionData(PKM pk, IEncounterable enc, ushort met) { Encounter = enc; Species = pk.Species; @@ -27,7 +27,7 @@ public EncounterSuggestionData(PKM pk, IEncounterable enc, int met) LevelMax = enc.LevelMax; } - public EncounterSuggestionData(PKM pk, int met, byte lvl) + public EncounterSuggestionData(PKM pk, ushort met, byte lvl) { Species = pk.Species; Form = pk.Form; @@ -39,5 +39,5 @@ public EncounterSuggestionData(PKM pk, int met, byte lvl) public int GetSuggestedMetLevel(PKM pk) => EncounterSuggestion.GetSuggestedMetLevel(pk, LevelMin); public GroundTileType GetSuggestedGroundTile() => Encounter is IGroundTypeTile t ? t.GroundTile.GetIndex() : 0; - public bool HasGroundTile(int format) => Encounter is IGroundTypeTile t && t.HasGroundTile(format); + public bool HasGroundTile(byte format) => Encounter is IGroundTypeTile t && t.HasGroundTile(format); } diff --git a/PKHeX.Core/Legality/Encounters/Information/EncounterSummary.cs b/PKHeX.Core/Legality/Encounters/Information/EncounterSummary.cs index b7f8bea8e..24a24748f 100644 --- a/PKHeX.Core/Legality/Encounters/Information/EncounterSummary.cs +++ b/PKHeX.Core/Legality/Encounters/Information/EncounterSummary.cs @@ -19,18 +19,18 @@ private EncounterSummary(IEncounterTemplate z) private static string GetLocationName(IEncounterTemplate z) { - var gen = z.Generation; + var generation = z.Generation; var version = z.Version; - if (gen < 0 && version > 0) - gen = version.GetGeneration(); + if (generation == 0 && version > 0) + generation = version.GetGeneration(); if (z is not ILocation l) - return $"[Gen{gen}]\t"; - var loc = l.GetEncounterLocation(gen, (int)version); + return $"[Gen{generation}]\t"; + var loc = l.GetEncounterLocation(generation, version); if (string.IsNullOrWhiteSpace(loc)) - return $"[Gen{gen}]\t"; - return $"[Gen{gen}]\t{loc}: "; + return $"[Gen{generation}]\t"; + return $"[Gen{generation}]\t{loc}: "; } public static IEnumerable SummarizeGroup(IEnumerable items, string header = "", bool advanced = false) diff --git a/PKHeX.Core/Legality/Encounters/Information/EncounterText.cs b/PKHeX.Core/Legality/Encounters/Information/EncounterText.cs index 9a144aa8f..46ce56a31 100644 --- a/PKHeX.Core/Legality/Encounters/Information/EncounterText.cs +++ b/PKHeX.Core/Legality/Encounters/Information/EncounterText.cs @@ -33,7 +33,7 @@ public static IReadOnlyList GetTextLines(this IEncounterInfo enc, GameSt } var el = enc as ILocation; - var loc = el?.GetEncounterLocation(enc.Generation, (int)enc.Version); + var loc = el?.GetEncounterLocation(enc.Generation, enc.Version); if (!string.IsNullOrEmpty(loc)) lines.Add(string.Format(L_F0_1, "Location", loc)); diff --git a/PKHeX.Core/Legality/Encounters/Templates/Enums/Shiny.cs b/PKHeX.Core/Legality/Encounters/Templates/Enums/Shiny.cs index 0941ede89..ce87568fe 100644 --- a/PKHeX.Core/Legality/Encounters/Templates/Enums/Shiny.cs +++ b/PKHeX.Core/Legality/Encounters/Templates/Enums/Shiny.cs @@ -68,6 +68,6 @@ public static bool IsSquareShinyExist(PKM pk) { if (pk.Format < 8 && !ShowSquareBeforeGen8) return false; - return pk.ShinyXor == 0 || pk.FatefulEncounter || pk.Version == (int)GameVersion.GO; + return pk.ShinyXor == 0 || pk.FatefulEncounter || pk.Version == GameVersion.GO; } } diff --git a/PKHeX.Core/Legality/Encounters/Templates/Enums/SlotType.cs b/PKHeX.Core/Legality/Encounters/Templates/Enums/SlotType.cs deleted file mode 100644 index 462e9b8bf..000000000 --- a/PKHeX.Core/Legality/Encounters/Templates/Enums/SlotType.cs +++ /dev/null @@ -1,112 +0,0 @@ -using System; - -namespace PKHeX.Core; - -/// -/// Wild Encounter data Type -/// -/// -/// Different from , this corresponds to the method that the may be encountered. -[Flags] -public enum SlotType : byte -{ - /// - /// Default (un-assigned) encounter slot type. - /// - Any = 0, - - /// - /// Slot is encountered via Grass. - /// - Grass = 1, - - /// - /// Slot is encountered via Surfing. - /// - Surf = 2, - - /// - /// Slot is encountered via Old Rod (Fishing). - /// - Old_Rod = 3, - - /// - /// Slot is encountered via Good Rod (Fishing). - /// - Good_Rod = 4, - - /// - /// Slot is encountered via Super Rod (Fishing). - /// - Super_Rod = 5, - - /// - /// Slot is encountered via Rock Smash. - /// - Rock_Smash = 6, - - /// - /// Slot is encountered via Headbutt. - /// - Headbutt = 7, - - /// - /// Slot is encountered via a Honey Tree. - /// - HoneyTree = 8, - - /// - /// Slot is encountered via the Bug Catching Contest. - /// - BugContest = 9, - - /// - /// Slot is encountered via Generation 5 Hidden Grotto. - /// - HiddenGrotto = 10, - - // GoPark = 11, UNUSED, now EncounterSlot7g - - /// - /// Slot is encountered via Generation 6 Friend Safari. - /// - FriendSafari = 12, - - /// - /// Slot is encountered via Generation 6 Horde Battle. - /// - Horde = 13, - - // Pokeradar = 14, // UNUSED, don't need to differentiate Gen4 Radar Slots - - /// - /// Slot is encountered via Generation 7 SOS triggers only. - /// - SOS = 15, - - // Legends: Arceus - Overworld = 16, - Distortion = 17, - Landmark = 18, - OverworldMass = 19, - OverworldMMO = 20, - - // Modifiers - - /// - /// Used to differentiate the two types of headbutt tree encounters. - /// - /// - Special = 1 << 6, - - /// - /// Used to identify encounters that are triggered via alternate ESV proc calculations. - /// - Swarm = 1 << 7, -} - -public static partial class Extensions -{ - internal static bool IsFishingRodType(this SlotType t) => (t & (SlotType)0xF) is SlotType.Old_Rod or SlotType.Good_Rod or SlotType.Super_Rod; - internal static bool IsSweetScentType(this SlotType t) => (t & (SlotType)0xF) is SlotType.Grass or SlotType.Surf or SlotType.BugContest; -} diff --git a/PKHeX.Core/Legality/Encounters/Templates/GO/EncounterSlot7GO.cs b/PKHeX.Core/Legality/Encounters/Templates/GO/EncounterSlot7GO.cs index 5510ed1f9..497233ef2 100644 --- a/PKHeX.Core/Legality/Encounters/Templates/GO/EncounterSlot7GO.cs +++ b/PKHeX.Core/Legality/Encounters/Templates/GO/EncounterSlot7GO.cs @@ -9,16 +9,16 @@ namespace PKHeX.Core; public sealed record EncounterSlot7GO(int StartDate, int EndDate, ushort Species, byte Form, byte LevelMin, byte LevelMax, Shiny Shiny, Gender Gender, PogoType Type) : IEncounterable, IEncounterMatch, IPogoSlot, IEncounterConvertible { - public int Generation => 7; + public byte Generation => 7; public EntityContext Context => EntityContext.Gen7b; public Ball FixedBall => Ball.None; // GO Park can override the ball; obey capture rules for LGP/E public bool EggEncounter => false; public AbilityPermission Ability => AbilityPermission.Any12; public bool IsShiny => Shiny.IsShiny(); - public int EggLocation => 0; + public ushort EggLocation => 0; public GameVersion Version => GameVersion.GO; - public int Location => Locations.GO7; + public ushort Location => Locations.GO7; public string Name => $"Wild Encounter ({Version})"; public string LongName { @@ -41,23 +41,24 @@ public string LongName public PB7 ConvertToPKM(ITrainerInfo tr, EncounterCriteria criteria) { int lang = (int)Language.GetSafeLanguage(Generation, (LanguageID)tr.Language); + var rnd = Util.Rand; var pk = new PB7 { - PID = Util.Rand32(), - EncryptionConstant = Util.Rand32(), + PID = rnd.Rand32(), + EncryptionConstant = rnd.Rand32(), Species = Species, Form = Form, CurrentLevel = LevelMin, - OT_Friendship = PersonalTable.GG[Species].BaseFriendship, - Met_Location = Location, - Met_Level = LevelMin, - Version = (byte)Version, + OriginalTrainerFriendship = PersonalTable.GG[Species].BaseFriendship, + MetLocation = Location, + MetLevel = LevelMin, + Version = Version, Ball = (byte)Ball.Poke, MetDate = this.GetRandomValidDate(), Language = lang, - OT_Name = tr.OT, - OT_Gender = tr.Gender, + OriginalTrainerName = tr.OT, + OriginalTrainerGender = tr.Gender, ID32 = tr.ID32, }; SetPINGA(pk, criteria); @@ -65,8 +66,8 @@ public PB7 ConvertToPKM(ITrainerInfo tr, EncounterCriteria criteria) pk.Nickname = SpeciesName.GetSpeciesNameGeneration(Species, lang, Generation); SetEncounterMoves(pk, LevelMin); pk.AwakeningSetAllTo(2); - pk.HeightScalar = PokeSizeUtil.GetRandomScalar(); - pk.WeightScalar = PokeSizeUtil.GetRandomScalar(); + pk.HeightScalar = PokeSizeUtil.GetRandomScalar(rnd); + pk.WeightScalar = PokeSizeUtil.GetRandomScalar(rnd); pk.ResetHeight(); pk.ResetWeight(); pk.ResetCP(); @@ -76,9 +77,9 @@ public PB7 ConvertToPKM(ITrainerInfo tr, EncounterCriteria criteria) private void SetPINGA(PB7 pk, EncounterCriteria criteria) { - var g = Gender == Gender.Random ? -1 : (int)Gender; - int gender = criteria.GetGender(g, PersonalTable.GG[Species]); - int nature = (int)criteria.GetNature(); + var pi = PersonalTable.GG[Species]; + var gender = criteria.GetGender(Gender, pi); + var nature = criteria.GetNature(); var ability = criteria.GetAbilityFromNumber(Ability); criteria.SetRandomIVsGO(pk, Type.GetMinIV()); @@ -118,7 +119,7 @@ public bool IsMatchExact(PKM pk, EvoCriteria evo) // Since it is possible to evolve before transferring, we only need the highest evolution species possible. // PoGoEncTool has already extrapolated the evolutions to separate encounters! - if (!this.IsLevelWithinRange(pk.Met_Level)) + if (!this.IsLevelWithinRange(pk.MetLevel)) return false; //if (!slot.IsBallValid(ball)) -- can have any of the in-game balls due to re-capture // continue; @@ -132,7 +133,7 @@ public bool IsMatchExact(PKM pk, EvoCriteria evo) public EncounterMatchRating GetMatchRating(PKM pk) { - var stamp = PogoDateRangeExtensions.GetTimeStamp(pk.Met_Year + 2000, pk.Met_Month, pk.Met_Day); + var stamp = PogoDateRangeExtensions.GetTimeStamp(pk.MetYear + 2000, pk.MetMonth, pk.MetDay); if (!this.IsWithinStartEnd(stamp)) return EncounterMatchRating.DeferredErrors; if (!this.GetIVsValid(pk)) diff --git a/PKHeX.Core/Legality/Encounters/Templates/GO/EncounterSlot8GO.cs b/PKHeX.Core/Legality/Encounters/Templates/GO/EncounterSlot8GO.cs index efeac62d7..4b665111d 100644 --- a/PKHeX.Core/Legality/Encounters/Templates/GO/EncounterSlot8GO.cs +++ b/PKHeX.Core/Legality/Encounters/Templates/GO/EncounterSlot8GO.cs @@ -10,15 +10,15 @@ namespace PKHeX.Core; public sealed record EncounterSlot8GO(int StartDate, int EndDate, ushort Species, byte Form, byte LevelMin, byte LevelMax, Shiny Shiny, Gender Gender, PogoType Type, PogoImportFormat OriginFormat) : IEncounterable, IEncounterMatch, IEncounterConvertible, IPogoSlot, IFixedOTFriendship, IEncounterServerDate { - public int Generation => 8; + public byte Generation => 8; public bool IsDateRestricted => true; public bool IsShiny => Shiny.IsShiny(); public Ball FixedBall => Type.GetValidBall(); public bool EggEncounter => false; public AbilityPermission Ability => AbilityPermission.Any12; - public int EggLocation => 0; + public ushort EggLocation => 0; public GameVersion Version => GameVersion.GO; - public int Location => Locations.GO8; + public ushort Location => Locations.GO8; public string Name => $"Wild Encounter ({Version})"; public string LongName @@ -114,27 +114,28 @@ public PKM ConvertToPKM(ITrainerInfo tr, EncounterCriteria criteria) { var pk = GetBlank(); int lang = (int)Language.GetSafeLanguage(Generation, (LanguageID)tr.Language); + var rnd = Util.Rand; { pk.Language = lang; - pk.PID = Util.Rand32(); - pk.EncryptionConstant = Util.Rand32(); + pk.PID = rnd.Rand32(); + pk.EncryptionConstant = rnd.Rand32(); pk.Species = Species; pk.Form = Form; pk.CurrentLevel = LevelMin; - pk.OT_Friendship = OT_Friendship; - pk.Met_Location = Location; - pk.Met_Level = LevelMin; - pk.Version = (byte)GameVersion.GO; + pk.OriginalTrainerFriendship = OriginalTrainerFriendship; + pk.MetLocation = Location; + pk.MetLevel = LevelMin; + pk.Version = GameVersion.GO; pk.Ball = (byte)GetRequiredBall(Ball.Poke); pk.MetDate = this.GetRandomValidDate(); - pk.OT_Name = tr.OT; + pk.OriginalTrainerName = tr.OT; pk.ID32 = tr.ID32; - pk.OT_Gender = tr.Gender; - pk.HT_Name = "PKHeX"; + pk.OriginalTrainerGender = tr.Gender; + pk.HandlingTrainerName = "PKHeX"; pk.CurrentHandler = 1; if (pk is IHandlerLanguage l) - l.HT_Language = 2; + l.HandlingTrainerLanguage = 2; } SetPINGA(pk, criteria); EncounterUtil.SetEncounterMoves(pk, Version, LevelMin); @@ -143,8 +144,8 @@ public PKM ConvertToPKM(ITrainerInfo tr, EncounterCriteria criteria) if (pk is IScaledSize s2) { - s2.HeightScalar = PokeSizeUtil.GetRandomScalar(); - s2.WeightScalar = PokeSizeUtil.GetRandomScalar(); + s2.HeightScalar = PokeSizeUtil.GetRandomScalar(rnd); + s2.WeightScalar = PokeSizeUtil.GetRandomScalar(rnd); if (pk is IScaledSize3 s3) s3.Scale = s2.HeightScalar; } @@ -157,7 +158,7 @@ public PKM ConvertToPKM(ITrainerInfo tr, EncounterCriteria criteria) { var pi = pk9.PersonalInfo; pk9.TeraTypeOriginal = pk9.TeraTypeOverride = TeraTypeUtil.GetTeraTypeImport(pi.Type1, pi.Type2); - pk9.Obedience_Level = (byte)pk9.Met_Level; + pk9.Obedience_Level = pk9.MetLevel; } pk.ResetPartyStats(); return pk; @@ -168,9 +169,8 @@ private void SetPINGA(PKM pk, EncounterCriteria criteria) var pi = GetPersonal(); if (OriginFormat is PogoImportFormat.PK7) pk.EXP = Experience.GetEXP(LevelMin, pi.EXPGrowth); - var g = Gender == Gender.Random ? -1 : (int)Gender; - int gender = criteria.GetGender(g, pi); - int nature = (int)criteria.GetNature(); + var gender = criteria.GetGender(Gender, pi); + var nature = criteria.GetNature(); var ability = criteria.GetAbilityFromNumber(Ability); pk.Nature = pk.StatNature = nature; @@ -214,7 +214,7 @@ public void GetInitialMoves(int level, Span moves) public bool IsMatchExact(PKM pk, EvoCriteria evo) { - if (!this.IsLevelWithinRange(pk.Met_Level)) + if (!this.IsLevelWithinRange(pk.MetLevel)) return false; if (!IsBallValid((Ball)pk.Ball, pk.Species, pk)) return false; @@ -234,7 +234,7 @@ public EncounterMatchRating GetMatchRating(PKM pk) return EncounterMatchRating.Match; } - public byte OT_Friendship => Species switch + public byte OriginalTrainerFriendship => Species switch { (int)Timburr when Form == 0 => 70, (int)Stunfisk when Form == 0 => 70, @@ -244,7 +244,7 @@ public EncounterMatchRating GetMatchRating(PKM pk) private byte GetHOMEFriendship() { - var fs = (byte)GetPersonal().BaseFriendship; + var fs = GetPersonal().BaseFriendship; if (fs == 70) return 50; return fs; @@ -258,7 +258,7 @@ private bool IsMatchPartial(PKM pk) return true; // Eevee & Glaceon have different base friendships. Make sure if it is invalid that we yield the other encounter before. - if (pk.OT_Friendship != OT_Friendship) + if (pk.OriginalTrainerFriendship != OriginalTrainerFriendship) return true; return IsFormArgIncorrect(pk); @@ -266,7 +266,7 @@ private bool IsMatchPartial(PKM pk) public bool IsWithinDistributionWindow(PKM pk) { - var date = new DateOnly(pk.Met_Year + 2000, pk.Met_Month, pk.Met_Day); + var date = new DateOnly(pk.MetYear + 2000, pk.MetMonth, pk.MetDay); return IsWithinDistributionWindow(date); } diff --git a/PKHeX.Core/Legality/Encounters/Templates/Gen1/EncounterArea1.cs b/PKHeX.Core/Legality/Encounters/Templates/Gen1/EncounterArea1.cs index 90757edd1..edd3b6f67 100644 --- a/PKHeX.Core/Legality/Encounters/Templates/Gen1/EncounterArea1.cs +++ b/PKHeX.Core/Legality/Encounters/Templates/Gen1/EncounterArea1.cs @@ -1,4 +1,5 @@ using System; +using System.Diagnostics.CodeAnalysis; namespace PKHeX.Core; @@ -11,10 +12,10 @@ public sealed record EncounterArea1 : IEncounterArea public GameVersion Version { get; } public readonly byte Location; - public readonly SlotType Type; + public readonly SlotType1 Type; public readonly byte Rate; - public static EncounterArea1[] GetAreas(BinLinkerAccessor input, GameVersion game) + public static EncounterArea1[] GetAreas(BinLinkerAccessor input, [ConstantExpected] GameVersion game) { var result = new EncounterArea1[input.Length]; for (int i = 0; i < result.Length; i++) @@ -22,27 +23,40 @@ public static EncounterArea1[] GetAreas(BinLinkerAccessor input, GameVersion gam return result; } - private EncounterArea1(ReadOnlySpan data, GameVersion game) + private EncounterArea1(ReadOnlySpan data, [ConstantExpected] GameVersion game) { Location = data[0]; // 1 byte unused - Type = (SlotType)data[2]; + Type = (SlotType1)data[2]; Rate = data[3]; Version = game; + Slots = ReadSlots(data[4..]); + } - var next = data[4..]; - int count = next.Length / 4; + private EncounterSlot1[] ReadSlots(ReadOnlySpan data) + { + int count = data.Length / 4; var slots = new EncounterSlot1[count]; for (int i = 0; i < slots.Length; i++) { const int size = 4; - var entry = next.Slice(i * size, size); + var entry = data.Slice(i * size, size); byte max = entry[3]; byte min = entry[2]; byte slotNum = entry[1]; byte species = entry[0]; slots[i] = new EncounterSlot1(this, species, min, max, slotNum); } - Slots = slots; + + return slots; } } + +public enum SlotType1 : byte +{ + Grass = 0, + Surf = 1, + Old_Rod = 2, + Good_Rod = 3, + Super_Rod = 4, +} diff --git a/PKHeX.Core/Legality/Encounters/Templates/Gen1/EncounterGift1.cs b/PKHeX.Core/Legality/Encounters/Templates/Gen1/EncounterGift1.cs index 9b1a94f75..206860f8e 100644 --- a/PKHeX.Core/Legality/Encounters/Templates/Gen1/EncounterGift1.cs +++ b/PKHeX.Core/Legality/Encounters/Templates/Gen1/EncounterGift1.cs @@ -1,5 +1,4 @@ -using System.Collections.Generic; -using System.Linq; +using System; namespace PKHeX.Core; @@ -9,14 +8,14 @@ namespace PKHeX.Core; public sealed record EncounterGift1(ushort Species, byte Level, GameVersion Version = GameVersion.RB) : IEncounterable, IEncounterMatch, IEncounterConvertible, IFixedGBLanguage, IMoveset, IFixedIVSet { - public int Generation => 1; + public byte Generation => 1; public EntityContext Context => EntityContext.Gen1; public bool EggEncounter => false; - public int EggLocation => 0; + public ushort EggLocation => 0; public Ball FixedBall => Ball.Poke; public AbilityPermission Ability => AbilityPermission.OnlyHidden; public bool IsShiny => false; - public int Location => 0; + public ushort Location => 0; public const ushort UnspecifiedID = 0; @@ -26,9 +25,9 @@ public sealed record EncounterGift1(ushort Species, byte Level, GameVersion Vers public EncounterGBLanguage Language { get; init; } = EncounterGBLanguage.Japanese; /// Trainer name for the event. - public string OT_Name { get; init; } = string.Empty; + public string OriginalTrainerName { get; init; } = string.Empty; - public IReadOnlyList OT_Names { get; init; } = []; + public ReadOnlyMemory TrainerNames { get; init; } /// Trainer ID for the event. public ushort TID16 { get; init; } = UnspecifiedID; @@ -59,7 +58,7 @@ public PK1 ConvertToPKM(ITrainerInfo tr, EncounterCriteria criteria) CatchRate = GetInitialCatchRate(pi), DV16 = IVs.IsSpecified ? EncounterUtil.GetDV16(IVs) : EncounterUtil.GetRandomDVs(Util.Rand), - OT_Name = EncounterUtil.GetTrainerName(tr, lang), + OriginalTrainerName = EncounterUtil.GetTrainerName(tr, lang), TID16 = tr.TID16, Nickname = SpeciesName.GetSpeciesNameGeneration(Species, lang, Generation), Type1 = pi.Type1, @@ -68,10 +67,10 @@ public PK1 ConvertToPKM(ITrainerInfo tr, EncounterCriteria criteria) if (TID16 != UnspecifiedID) pk.TID16 = TID16; - if (OT_Name.Length != 0) - pk.OT_Name = OT_Name; - else if (OT_Names.Count != 0) - pk.OT_Name = OT_Names[Util.Rand.Next(OT_Names.Count)]; + if (OriginalTrainerName.Length != 0) + pk.OriginalTrainerName = OriginalTrainerName; + else if (TrainerNames.Length != 0) + pk.OriginalTrainerName = TrainerNames.Span[Util.Rand.Next(TrainerNames.Length)]; if (Version == GameVersion.Stadium) { @@ -112,7 +111,7 @@ private byte GetInitialCatchRate(PersonalInfo1 pi) { // Amnesia Psyduck has different catch rates depending on language if (Species == (int)Core.Species.Psyduck) - return (Language == EncounterGBLanguage.Japanese) ? (byte)167 : (byte)168; + return Language == EncounterGBLanguage.Japanese ? (byte)167 : (byte)168; } // Encounters can have different Catch Rates (RBG vs Y) @@ -156,14 +155,14 @@ public bool IsMatchExact(PKM pk, EvoCriteria evo) if (TID16 != UnspecifiedID && pk.TID16 != TID16) return false; - if (OT_Name.Length != 0) + if (OriginalTrainerName.Length != 0) { - if (pk.OT_Name != OT_Name) + if (pk.OriginalTrainerName != OriginalTrainerName) return false; } - else if (OT_Names.Count != 0) + else if (TrainerNames.Length != 0) { - if (!OT_Names.Contains(pk.OT_Name)) + if (!TrainerNames.Span.Contains(pk.OriginalTrainerName)) return false; } @@ -183,7 +182,7 @@ private static bool IsMatchEggLocation(PKM pk) return true; var expect = pk is PB8 ? Locations.Default8bNone : 0; - return pk.Egg_Location == expect; + return pk.EggLocation == expect; } public EncounterMatchRating GetMatchRating(PKM pk) diff --git a/PKHeX.Core/Legality/Encounters/Templates/Gen1/EncounterSlot1.cs b/PKHeX.Core/Legality/Encounters/Templates/Gen1/EncounterSlot1.cs index aba63766e..6fb938546 100644 --- a/PKHeX.Core/Legality/Encounters/Templates/Gen1/EncounterSlot1.cs +++ b/PKHeX.Core/Legality/Encounters/Templates/Gen1/EncounterSlot1.cs @@ -6,22 +6,22 @@ namespace PKHeX.Core; public sealed record EncounterSlot1(EncounterArea1 Parent, ushort Species, byte LevelMin, byte LevelMax, byte SlotNumber) : IEncounterConvertible, IEncounterable, IEncounterMatch, INumberedSlot { - public int Generation => 1; + public byte Generation => 1; public EntityContext Context => EntityContext.Gen1; public bool EggEncounter => false; public Ball FixedBall => Ball.Poke; public AbilityPermission Ability => TransporterLogic.IsHiddenDisallowedVC1(Species) ? AbilityPermission.OnlyFirst : AbilityPermission.OnlyHidden; public Shiny Shiny => Shiny.Random; public bool IsShiny => false; - public int EggLocation => 0; + public ushort EggLocation => 0; public byte Form => 0; public string Name => $"Wild Encounter ({Version})"; public string LongName => $"{Name} {Type.ToString().Replace('_', ' ')}"; public GameVersion Version => Parent.Version; - public int Location => Parent.Location; - public SlotType Type => Parent.Type; + public ushort Location => Parent.Location; + public SlotType1 Type => Parent.Type; #region Generating PKM IEncounterConvertible.ConvertToPKM(ITrainerInfo tr, EncounterCriteria criteria) => ConvertToPKM(tr, criteria); @@ -41,7 +41,7 @@ public PK1 ConvertToPKM(ITrainerInfo tr, EncounterCriteria criteria) CatchRate = pi.CatchRate, DV16 = EncounterUtil.GetRandomDVs(Util.Rand), - OT_Name = EncounterUtil.GetTrainerName(tr, lang), + OriginalTrainerName = EncounterUtil.GetTrainerName(tr, lang), TID16 = tr.TID16, Nickname = SpeciesName.GetSpeciesNameGeneration(Species, lang, Generation), Type1 = pi.Type1, diff --git a/PKHeX.Core/Legality/Encounters/Templates/Gen1/EncounterStatic1.cs b/PKHeX.Core/Legality/Encounters/Templates/Gen1/EncounterStatic1.cs index 9606ac28f..ceb114212 100644 --- a/PKHeX.Core/Legality/Encounters/Templates/Gen1/EncounterStatic1.cs +++ b/PKHeX.Core/Legality/Encounters/Templates/Gen1/EncounterStatic1.cs @@ -6,15 +6,15 @@ namespace PKHeX.Core; public sealed record EncounterStatic1(ushort Species, byte Level, GameVersion Version) : IEncounterable, IEncounterMatch, IEncounterConvertible { - public int Generation => 1; + public byte Generation => 1; public EntityContext Context => EntityContext.Gen1; public bool EggEncounter => false; - public int EggLocation => 0; + public ushort EggLocation => 0; public Ball FixedBall => Ball.Poke; public AbilityPermission Ability => AbilityPermission.OnlyHidden; public Shiny Shiny => Shiny.Random; public bool IsShiny => false; - public int Location => 0; + public ushort Location => 0; private const byte LightBallPikachuCatchRate = 0xA3; // 163 - Light Ball public byte Form => 0; @@ -44,7 +44,7 @@ public PK1 ConvertToPKM(ITrainerInfo tr, EncounterCriteria criteria) CatchRate = IsStarterPikachu ? LightBallPikachuCatchRate : pi.CatchRate, DV16 = EncounterUtil.GetRandomDVs(Util.Rand), - OT_Name = EncounterUtil.GetTrainerName(tr, lang), + OriginalTrainerName = EncounterUtil.GetTrainerName(tr, lang), TID16 = tr.TID16, Nickname = SpeciesName.GetSpeciesNameGeneration(Species, lang, Generation), Type1 = pi.Type1, @@ -82,7 +82,7 @@ private static bool IsMatchEggLocation(PKM pk) return true; var expect = pk is PB8 ? Locations.Default8bNone : 0; - return pk.Egg_Location == expect; + return pk.EggLocation == expect; } public EncounterMatchRating GetMatchRating(PKM pk) diff --git a/PKHeX.Core/Legality/Encounters/Templates/Gen1/EncounterTrade1.cs b/PKHeX.Core/Legality/Encounters/Templates/Gen1/EncounterTrade1.cs index 66f5b6596..bb870c928 100644 --- a/PKHeX.Core/Legality/Encounters/Templates/Gen1/EncounterTrade1.cs +++ b/PKHeX.Core/Legality/Encounters/Templates/Gen1/EncounterTrade1.cs @@ -12,15 +12,15 @@ namespace PKHeX.Core; /// public sealed record EncounterTrade1 : IEncounterable, IEncounterMatch, IFixedTrainer, IFixedNickname, IEncounterConvertible { - public int Generation => 1; + public byte Generation => 1; public EntityContext Context => EntityContext.Gen1; public bool EggEncounter => false; public Ball FixedBall => Ball.Poke; public AbilityPermission Ability => Species == (ushort)Core.Species.Haunter ? AbilityPermission.OnlyFirst : AbilityPermission.OnlyHidden; public Shiny Shiny => Shiny.Random; public bool IsShiny => false; - public int Location => 0; - public int EggLocation => 0; + public ushort Location => 0; + public ushort EggLocation => 0; public bool IsFixedTrainer => true; public bool IsFixedNickname => true; @@ -73,10 +73,10 @@ private bool IsNicknameValid(PKM pk, ReadOnlySpan nick) private static bool IsTrainerNameValid(PKM pk) { if (pk.Format <= 2) - return pk.OT_Trash is [StringConverter12.G1TradeOTCode, StringConverter12.G1TerminatorCode, ..]; + return pk.OriginalTrainerTrash is [StringConverter12.G1TradeOTCode, StringConverter12.G1TerminatorCode, ..]; var lang = pk.Language; var expect = StringConverter12Transporter.GetTradeNameGen1(lang); - return pk.OT_Name == expect; + return pk.OriginalTrainerName == expect; } private int GetNicknameIndex(ReadOnlySpan nickname) => GetIndex(nickname, Nicknames); @@ -126,7 +126,7 @@ public PK1 ConvertToPKM(ITrainerInfo tr, EncounterCriteria criteria) Type1 = pi.Type1, Type2 = pi.Type2, }; - pk.OT_Trash[0] = StringConverter12.G1TradeOTCode; + pk.OriginalTrainerTrash[0] = StringConverter12.G1TradeOTCode; EncounterUtil.SetEncounterMoves(pk, Version, level); if (EvolveOnTrade) diff --git a/PKHeX.Core/Legality/Encounters/Templates/Gen2/EncounterArea2.cs b/PKHeX.Core/Legality/Encounters/Templates/Gen2/EncounterArea2.cs index 43bf9009d..329d29a2c 100644 --- a/PKHeX.Core/Legality/Encounters/Templates/Gen2/EncounterArea2.cs +++ b/PKHeX.Core/Legality/Encounters/Templates/Gen2/EncounterArea2.cs @@ -1,4 +1,6 @@ using System; +using System.Diagnostics.CodeAnalysis; +using static PKHeX.Core.SlotType2; namespace PKHeX.Core; @@ -10,19 +12,25 @@ public sealed record EncounterArea2 : IEncounterArea, IAreaLocat public EncounterSlot2[] Slots { get; } public GameVersion Version { get; } - private static ReadOnlySpan BCC_SlotRates => [ 20, 20, 10, 10, 05, 05, 10, 10, 05, 05 ]; private static ReadOnlySpan RatesGrass => [ 30, 30, 20, 10, 5, 4, 1 ]; private static ReadOnlySpan RatesSurf => [ 60, 30, 10 ]; - public readonly byte[]? Rates; + private readonly byte[] Rates; // Slot specific rates internal readonly EncounterTime Time; - public readonly byte Rate; + public readonly byte Rate; // Area Rate public readonly byte Location; - public readonly SlotType Type; + public readonly SlotType2 Type; - public bool IsMatchLocation(int location) => location == Location; + public bool IsMatchLocation(ushort location) => location == Location; - public static EncounterArea2[] GetAreas(BinLinkerAccessor input, GameVersion game) + public ReadOnlySpan GetSlotRates() => Type switch + { + Grass => RatesGrass, + Surf => RatesSurf, + _ => Rates, + }; + + public static EncounterArea2[] GetAreas(BinLinkerAccessor input, [ConstantExpected] GameVersion game) { var result = new EncounterArea2[input.Length]; for (int i = 0; i < result.Length; i++) @@ -30,39 +38,38 @@ public static EncounterArea2[] GetAreas(BinLinkerAccessor input, GameVersion gam return result; } - private EncounterArea2(ReadOnlySpan data, GameVersion game) + private EncounterArea2(ReadOnlySpan data, [ConstantExpected] GameVersion game) { Location = data[0]; Time = (EncounterTime)data[1]; - var type = (Type = (SlotType)data[2]) & (SlotType)0xF; + Type = (SlotType2)data[2]; Rate = data[3]; Version = game; - var next = data[4..]; - if (type is > SlotType.Surf and not SlotType.BugContest) // Not Grass/Surf + var slotData = data[4..]; + if (Type > Surf) // Not Grass/Surf { - const int size = 5; - int count = next.Length / size; - Rates = next[..count].ToArray(); - Slots = ReadSlots(next[count..], count); + int count = slotData.Length / (SlotSize + 1); // each slot has a rate + Rates = slotData[..count].ToArray(); + Slots = ReadSlots(slotData[count..], count); } else { - const int size = 4; - int count = next.Length / size; - Rates = null; // fetch as needed. - Slots = ReadSlots(next, count); + int count = slotData.Length / SlotSize; // shared rate value + Rates = []; // fetch as needed. + Slots = ReadSlots(slotData, count); } } + private const int SlotSize = 4; + private EncounterSlot2[] ReadSlots(ReadOnlySpan data, int count) { - const int size = 4; var slots = new EncounterSlot2[count]; for (int i = 0; i < slots.Length; i++) { - var entry = data.Slice(i * size, size); + var entry = data.Slice(i * SlotSize, SlotSize); byte max = entry[3]; byte min = entry[2]; byte slotNum = entry[1]; @@ -73,3 +80,17 @@ private EncounterSlot2[] ReadSlots(ReadOnlySpan data, int count) return slots; } } + +public enum SlotType2 : byte +{ + Grass = 0, + Surf = 1, + Old_Rod = 2, + Good_Rod = 3, + Super_Rod = 4, + Rock_Smash = 5, + + Headbutt = 6, + HeadbuttSpecial = 7, + BugContest = 8, +} diff --git a/PKHeX.Core/Legality/Encounters/Templates/Gen2/EncounterGift2.cs b/PKHeX.Core/Legality/Encounters/Templates/Gen2/EncounterGift2.cs index 2d4104527..d3b3549c1 100644 --- a/PKHeX.Core/Legality/Encounters/Templates/Gen2/EncounterGift2.cs +++ b/PKHeX.Core/Legality/Encounters/Templates/Gen2/EncounterGift2.cs @@ -1,5 +1,4 @@ -using System.Collections.Generic; -using System.Linq; +using System; namespace PKHeX.Core; @@ -9,13 +8,13 @@ namespace PKHeX.Core; public sealed record EncounterGift2(ushort Species, byte Level, GameVersion Version = GameVersion.GS) : IEncounterable, IEncounterMatch, IEncounterConvertible, IFixedGBLanguage, IHatchCycle, IMoveset, IFixedIVSet { - public int Generation => 2; + public byte Generation => 2; public EntityContext Context => EntityContext.Gen2; public byte Form => 0; public Ball FixedBall => Ball.Poke; - int ILocation.Location => Location; - public int EggLocation => 0; + ushort ILocation.Location => Location; + public ushort EggLocation => 0; public bool IsShiny => Shiny == Shiny.Always; public AbilityPermission Ability => AbilityPermission.OnlyHidden; @@ -32,9 +31,9 @@ public sealed record EncounterGift2(ushort Species, byte Level, GameVersion Vers public EncounterGBLanguage Language { get; init; } = EncounterGBLanguage.Japanese; /// Trainer name for the event. - public string OT_Name { get; init; } = string.Empty; + public string OriginalTrainerName { get; init; } = string.Empty; - public IReadOnlyList OT_Names { get; init; } = []; + public ReadOnlyMemory TrainerNames { get; init; } private const ushort UnspecifiedID = 0; @@ -43,7 +42,7 @@ public sealed record EncounterGift2(ushort Species, byte Level, GameVersion Vers public bool IsGift => TID16 != UnspecifiedID; - public sbyte CurrentLevel { get; init; } = -1; + public byte CurrentLevel { get; init; } public byte EggCycles { get; init; } @@ -55,18 +54,18 @@ public sealed record EncounterGift2(ushort Species, byte Level, GameVersion Vers public PK2 ConvertToPKM(ITrainerInfo tr, EncounterCriteria criteria) { - var version = this.GetCompatibleVersion((GameVersion)tr.Game); + var version = this.GetCompatibleVersion(tr.Version); int lang = GetTemplateLanguage(tr); var pi = PersonalTable.C[Species]; var pk = new PK2 { Species = Species, - CurrentLevel = CurrentLevel == -1 ? LevelMin : CurrentLevel, + CurrentLevel = CurrentLevel == 0 ? LevelMin : CurrentLevel, TID16 = TID16 != UnspecifiedID ? TID16 : tr.TID16, - OT_Name = GetInitialOT(tr), + OriginalTrainerName = GetInitialOT(tr), - OT_Friendship = pi.BaseFriendship, + OriginalTrainerFriendship = pi.BaseFriendship, Nickname = SpeciesName.GetSpeciesNameGeneration(Species, lang, Generation), }; @@ -74,13 +73,13 @@ public PK2 ConvertToPKM(ITrainerInfo tr, EncounterCriteria criteria) if (EggEncounter) { } - else if (Version == GameVersion.C || (Version == GameVersion.GSC && tr.Game == (int)GameVersion.C)) + else if (Version == GameVersion.C || (Version == GameVersion.GSC && tr.Version == GameVersion.C)) { if (!IsGift) - pk.OT_Gender = tr.Gender; - pk.Met_Level = LevelMin; - pk.Met_Location = Location; - pk.Met_TimeOfDay = EncounterTime.Any.RandomValidTime(); + pk.OriginalTrainerGender = tr.Gender; + pk.MetLevel = LevelMin; + pk.MetLocation = Location; + pk.MetTimeOfDay = EncounterTime.Any.RandomValidTime(); } if (Shiny == Shiny.Always) @@ -116,10 +115,10 @@ private int GetTemplateLanguage(ITrainerInfo tr) private string GetInitialOT(ITrainerInfo tr) { - if (OT_Name.Length != 0) - return OT_Name; - if (OT_Names.Count != 0) - return OT_Names[Util.Rand.Next(OT_Names.Count)]; + if (OriginalTrainerName.Length != 0) + return OriginalTrainerName; + if (TrainerNames.Length != 0) + return TrainerNames.Span[Util.Rand.Next(TrainerNames.Length)]; return tr.OT; } @@ -156,7 +155,7 @@ public bool IsMatchExact(PKM pk, EvoCriteria evo) if (Language != EncounterGBLanguage.Any && pk.Japanese != (Language == EncounterGBLanguage.Japanese)) return false; - if (CurrentLevel != -1 && CurrentLevel > pk.CurrentLevel) + if (CurrentLevel != 0 && CurrentLevel > pk.CurrentLevel) return false; // EC/PID check doesn't exist for these, so check Shiny state here. @@ -170,14 +169,14 @@ public bool IsMatchExact(PKM pk, EvoCriteria evo) if (TID16 != UnspecifiedID && pk.TID16 != TID16) return false; - if (OT_Name.Length != 0) + if (OriginalTrainerName.Length != 0) { - if (pk.OT_Name != OT_Name) + if (pk.OriginalTrainerName != OriginalTrainerName) return false; } - else if (OT_Names.Count != 0) + else if (TrainerNames.Length != 0) { - if (!OT_Names.Contains(pk.OT_Name)) + if (!TrainerNames.Span.Contains(pk.OriginalTrainerName)) return false; } @@ -189,28 +188,28 @@ private bool IsMatchEggLocation(PKM pk) if (pk is not ICaughtData2 c2) { var expect = pk is PB8 ? Locations.Default8bNone : EggLocation; - return pk.Egg_Location == expect; + return pk.EggLocation == expect; } if (pk.IsEgg) { if (!EggEncounter) return false; - if (c2.Met_Location != 0 && c2.Met_Level != 0) + if (c2.MetLocation != 0 && c2.MetLevel != 0) return false; - if (pk.OT_Friendship > EggCycles) + if (pk.OriginalTrainerFriendship > EggCycles) return false; } else { - switch (c2.Met_Level) + switch (c2.MetLevel) { - case 0 when c2.Met_Location != 0: + case 0 when c2.MetLocation != 0: return false; case 1: // 0 = second floor of every Pokémon Center, valid return true; default: - if (pk.Met_Location == 0 && c2.Met_Level != 0) + if (pk.MetLocation == 0 && c2.MetLevel != 0) return false; break; } @@ -229,7 +228,7 @@ private bool IsMatchLocation(PKM pk) if (Version is GameVersion.C or GameVersion.GSC) { if (c2.CaughtData is not 0) - return Location == pk.Met_Location; + return Location == pk.MetLocation; if (pk.Species == (int)Core.Species.Celebi) return false; // Cannot reset the Met data } @@ -248,7 +247,7 @@ private bool IsMatchLevel(PKM pk, EvoCriteria evo) if (evo.LevelMax < Level) return false; if (pk is ICaughtData2 { CaughtData: not 0 }) - return pk.Met_Level == (EggEncounter ? 1 : Level); + return pk.MetLevel == (EggEncounter ? 1 : Level); return true; } diff --git a/PKHeX.Core/Legality/Encounters/Templates/Gen2/EncounterSlot2.cs b/PKHeX.Core/Legality/Encounters/Templates/Gen2/EncounterSlot2.cs index 611956a27..45f1977df 100644 --- a/PKHeX.Core/Legality/Encounters/Templates/Gen2/EncounterSlot2.cs +++ b/PKHeX.Core/Legality/Encounters/Templates/Gen2/EncounterSlot2.cs @@ -1,4 +1,5 @@ using System; +using static PKHeX.Core.SlotType2; namespace PKHeX.Core; @@ -11,25 +12,22 @@ namespace PKHeX.Core; public sealed record EncounterSlot2(EncounterArea2 Parent, ushort Species, byte Form, byte LevelMin, byte LevelMax, byte SlotNumber) : IEncounterable, IEncounterMatch, IEncounterConvertible, INumberedSlot, IEncounterFormRandom { - public int Generation => 2; + public byte Generation => 2; public EntityContext Context => EntityContext.Gen2; public bool EggEncounter => false; public Ball FixedBall => Ball.Poke; public AbilityPermission Ability => TransporterLogic.IsHiddenDisallowedVC2(Species) ? AbilityPermission.OnlyFirst : AbilityPermission.OnlyHidden; public Shiny Shiny => Shiny.Random; public bool IsShiny => false; - public int EggLocation => 0; + public ushort EggLocation => 0; public bool IsRandomUnspecificForm => Form >= EncounterUtil.FormDynamic; public string Name => $"Wild Encounter ({Version})"; public string LongName => $"{Name} {Type.ToString().Replace('_', ' ')}"; public GameVersion Version => Parent.Version; - public int Location => Parent.Location; - public SlotType Type => Parent.Type; - - // we have "Special" bitflag. Strip it out. - public SlotType SlotType => Type & (SlotType)0xF; - public bool IsHeadbutt => SlotType == SlotType.Headbutt; + public ushort Location => Parent.Location; + public SlotType2 Type => Parent.Type; + public bool IsHeadbutt => Type is Headbutt or HeadbuttSpecial; private static ReadOnlySpan TreeIndexes => [ @@ -69,7 +67,7 @@ public bool IsTreeAvailable(ushort trainerID) var pivot = trainerID % 10; return Type switch { - SlotType.Headbutt => (permissions & (1 << pivot)) != 0, + Headbutt => (permissions & (1 << pivot)) != 0, /*special*/ _ => (permissions & (1 << (pivot + 12))) != 0, }; } @@ -90,21 +88,21 @@ public PK2 ConvertToPKM(ITrainerInfo tr, EncounterCriteria criteria) Species = Species, // Form is only Unown and is derived from IVs. CurrentLevel = LevelMin, - OT_Friendship = pi.BaseFriendship, + OriginalTrainerFriendship = pi.BaseFriendship, DV16 = EncounterUtil.GetRandomDVs(Util.Rand), Language = lang, - OT_Name = tr.OT, + OriginalTrainerName = tr.OT, TID16 = tr.TID16, Nickname = SpeciesName.GetSpeciesNameGeneration(Species, lang, Generation), }; if (Version == GameVersion.C) { - pk.OT_Gender = tr.Gender; - pk.Met_Level = LevelMin; - pk.Met_Location = Location; - pk.Met_TimeOfDay = GetRandomTime(); + pk.OriginalTrainerGender = tr.Gender; + pk.MetLevel = LevelMin; + pk.MetLocation = Location; + pk.MetTimeOfDay = GetRandomTime(); } EncounterUtil.SetEncounterMoves(pk, Version, LevelMin); @@ -141,9 +139,9 @@ public bool IsMatchExact(PKM pk, EvoCriteria evo) if (pk is not ICaughtData2 {CaughtData: not 0} c2) return LevelMin <= evo.LevelMax; - if (!this.IsLevelWithinRange(c2.Met_Level)) + if (!this.IsLevelWithinRange(c2.MetLevel)) return false; - if (!Parent.Time.Contains(c2.Met_TimeOfDay)) + if (!Parent.Time.Contains(c2.MetTimeOfDay)) return false; return true; } diff --git a/PKHeX.Core/Legality/Encounters/Templates/Gen2/EncounterStatic2.cs b/PKHeX.Core/Legality/Encounters/Templates/Gen2/EncounterStatic2.cs index eae5111c6..655824279 100644 --- a/PKHeX.Core/Legality/Encounters/Templates/Gen2/EncounterStatic2.cs +++ b/PKHeX.Core/Legality/Encounters/Templates/Gen2/EncounterStatic2.cs @@ -6,15 +6,15 @@ namespace PKHeX.Core; public sealed record EncounterStatic2(ushort Species, byte Level, GameVersion Version) : IEncounterable, IEncounterMatch, IEncounterConvertible, IHatchCycle, IFixedGender, IMoveset, IFixedIVSet { - public int Generation => 2; + public byte Generation => 2; public EntityContext Context => EntityContext.Gen2; public byte Form => 0; public byte EggCycles => DizzyPunchEgg ? (byte)20 : (byte)0; public bool DizzyPunchEgg => EggEncounter && Moves.HasMoves; public Ball FixedBall => Ball.Poke; - int ILocation.Location => Location; - public int EggLocation => 0; + ushort ILocation.Location => Location; + public ushort EggLocation => 0; public bool IsShiny => Shiny == Shiny.Always; public AbilityPermission Ability => Species != (int)Core.Species.Koffing ? AbilityPermission.OnlyHidden : AbilityPermission.OnlyFirst; public bool Roaming => Species is (int)Core.Species.Entei or (int)Core.Species.Raikou or (int)Core.Species.Suicune && Location != 23; @@ -39,7 +39,7 @@ public sealed record EncounterStatic2(ushort Species, byte Level, GameVersion Ve public PK2 ConvertToPKM(ITrainerInfo tr, EncounterCriteria criteria) { - var version = this.GetCompatibleVersion((GameVersion)tr.Game); + var version = this.GetCompatibleVersion(tr.Version); int lang = (int)Language.GetSafeLanguage(Generation, (LanguageID)tr.Language, version); var pi = PersonalTable.C[Species]; var pk = new PK2 @@ -48,9 +48,9 @@ public PK2 ConvertToPKM(ITrainerInfo tr, EncounterCriteria criteria) CurrentLevel = LevelMin, TID16 = tr.TID16, - OT_Name = tr.OT, + OriginalTrainerName = tr.OT, - OT_Friendship = pi.BaseFriendship, + OriginalTrainerFriendship = pi.BaseFriendship, Nickname = SpeciesName.GetSpeciesNameGeneration(Species, lang, Generation), }; @@ -60,12 +60,12 @@ public PK2 ConvertToPKM(ITrainerInfo tr, EncounterCriteria criteria) if (DizzyPunchEgg) // Fixed EXP value instead of exactly Level 5 pk.EXP = 125; } - else if (Version == GameVersion.C || (Version == GameVersion.GSC && tr.Game == (int)GameVersion.C)) + else if (Version == GameVersion.C || (Version == GameVersion.GSC && tr.Version == GameVersion.C)) { - pk.OT_Gender = tr.Gender; - pk.Met_Level = LevelMin; - pk.Met_Location = Location; - pk.Met_TimeOfDay = EncounterTime.Any.RandomValidTime(); + pk.OriginalTrainerGender = tr.Gender; + pk.MetLevel = LevelMin; + pk.MetLocation = Location; + pk.MetTimeOfDay = EncounterTime.Any.RandomValidTime(); } if (Moves.HasMoves) @@ -145,26 +145,26 @@ private bool IsMatchEggLocation(PKM pk) if (pk is not ICaughtData2 c2) { var expect = pk is PB8 ? Locations.Default8bNone : EggLocation; - return pk.Egg_Location == expect; + return pk.EggLocation == expect; } if (pk.IsEgg) { if (!EggEncounter) return false; - if (c2.Met_Location != 0 && c2.Met_Level != 0) + if (c2.MetLocation != 0 && c2.MetLevel != 0) return false; } else { - switch (c2.Met_Level) + switch (c2.MetLevel) { - case 0 when c2.Met_Location != 0: + case 0 when c2.MetLocation != 0: return false; case 1: // 0 = second floor of every Pokémon Center, valid return true; default: - if (pk.Met_Location == 0 && c2.Met_Level != 0) + if (pk.MetLocation == 0 && c2.MetLevel != 0) return false; break; } @@ -178,7 +178,7 @@ private bool IsMatchLevel(PKM pk, EvoCriteria evo) if (evo.LevelMax < Level) return false; if (pk is ICaughtData2 { CaughtData: not 0 }) - return pk.Met_Level == (EggEncounter ? 1 : Level); + return pk.MetLevel == (EggEncounter ? 1 : Level); return true; } @@ -199,13 +199,13 @@ private bool IsMatchLocation(PKM pk) if (Roaming) { // Gen2 met location is always u8 - var loc = c2.Met_Location; + var loc = c2.MetLocation; return loc <= 45 && ((RoamLocations & (1UL << loc)) != 0); } if (Version is GameVersion.C or GameVersion.GSC) { if (c2.CaughtData is not 0) - return Location == pk.Met_Location; + return Location == pk.MetLocation; if (pk.Species == (int)Core.Species.Celebi) return false; // Cannot reset the Met data } diff --git a/PKHeX.Core/Legality/Encounters/Templates/Gen2/EncounterTrade2.cs b/PKHeX.Core/Legality/Encounters/Templates/Gen2/EncounterTrade2.cs index 4353687f9..313ebe876 100644 --- a/PKHeX.Core/Legality/Encounters/Templates/Gen2/EncounterTrade2.cs +++ b/PKHeX.Core/Legality/Encounters/Templates/Gen2/EncounterTrade2.cs @@ -8,16 +8,16 @@ namespace PKHeX.Core; /// public sealed record EncounterTrade2 : IEncounterable, IEncounterMatch, IFixedTrainer, IFixedNickname, IFixedGender, IFixedIVSet, IEncounterConvertible { - public int Generation => 2; + public byte Generation => 2; public EntityContext Context => EntityContext.Gen2; - public int Location => Locations.LinkTrade2NPC; + public ushort Location => Locations.LinkTrade2NPC; public GameVersion Version => GameVersion.GSC; public bool EggEncounter => false; public Ball FixedBall => Ball.Poke; public AbilityPermission Ability => AbilityPermission.OnlyHidden; public Shiny Shiny => Shiny.Random; public bool IsShiny => false; - public int EggLocation => 0; + public ushort EggLocation => 0; public bool IsFixedTrainer => true; public bool IsFixedNickname => true; @@ -64,17 +64,17 @@ public PK2 ConvertToPKM(ITrainerInfo tr, EncounterCriteria criteria) Species = Species, CurrentLevel = Level, - Met_Location = Location, + MetLocation = Location, Nickname = Nicknames[lang], - OT_Name = TrainerNames[lang], - OT_Friendship = pi.BaseFriendship, + OriginalTrainerName = TrainerNames[lang], + OriginalTrainerFriendship = pi.BaseFriendship, }; if (IVs.IsSpecified) { pk.DV16 = EncounterUtil.GetDV16(IVs); - pk.OT_Gender = OTGender; + pk.OriginalTrainerGender = OTGender; pk.TID16 = TID16; } else @@ -108,18 +108,18 @@ public bool IsMatchExact(PKM pk, EvoCriteria evo) } if (pk is ICaughtData2 { CaughtData: not 0 } c) { - if (c.Met_Location != Locations.LinkTrade2NPC) + if (c.MetLocation != Locations.LinkTrade2NPC) return false; - if (c.Met_Level != 0) + if (c.MetLevel != 0) return false; - if (IVs.IsSpecified && c.OT_Gender != OTGender) + if (IVs.IsSpecified && c.OriginalTrainerGender != OTGender) return false; } } else // 7+ { // require male except if transferred from GS - if (pk.VC1 && pk.OT_Gender != 0) + if (pk.VC1 && pk.OriginalTrainerGender != 0) return false; if (IVs.IsSpecified) { @@ -134,7 +134,7 @@ public bool IsMatchExact(PKM pk, EvoCriteria evo) private bool IsTrainerNicknameCorrect(PKM pk) { - var indexOT = GetIndexTrainer(pk.OT_Name, pk); + var indexOT = GetIndexTrainer(pk.OriginalTrainerName, pk); if (indexOT == -1) return false; if (pk.Nickname != Nicknames[indexOT]) @@ -192,7 +192,7 @@ public EncounterMatchRating GetMatchRating(PKM pk) public bool IsNicknameMatch(PKM pk, ReadOnlySpan nickname, int language) { - var index = GetIndexTrainer(pk.OT_Name, pk); + var index = GetIndexTrainer(pk.OriginalTrainerName, pk); if (index == -1) return false; return nickname.SequenceEqual(Nicknames[index]); diff --git a/PKHeX.Core/Legality/Encounters/Templates/Gen3/Colo/EncounterGift3Colo.cs b/PKHeX.Core/Legality/Encounters/Templates/Gen3/Colo/EncounterGift3Colo.cs index f66528b53..08d40497d 100644 --- a/PKHeX.Core/Legality/Encounters/Templates/Gen3/Colo/EncounterGift3Colo.cs +++ b/PKHeX.Core/Legality/Encounters/Templates/Gen3/Colo/EncounterGift3Colo.cs @@ -7,11 +7,11 @@ namespace PKHeX.Core; /// public sealed record EncounterGift3Colo : IEncounterable, IEncounterMatch, IEncounterConvertible, IRandomCorrelation, IFixedTrainer, IMoveset { - public int Generation => 3; + public byte Generation => 3; public EntityContext Context => EntityContext.Gen3; public GameVersion Version { get; } - int ILocation.EggLocation => 0; - int ILocation.Location => Location; + ushort ILocation.EggLocation => 0; + ushort ILocation.Location => Location; public bool IsShiny => false; public Shiny Shiny => Shiny.Never; public byte Form => 0; @@ -27,7 +27,7 @@ public sealed record EncounterGift3Colo : IEncounterable, IEncounterMatch, IEnco public required byte Location { get; init; } public Moveset Moves { get; init; } public required ushort TID16 { get; init; } - public required byte OT_Gender { get; init; } + public required byte OriginalTrainerGender { get; init; } public EncounterGift3Colo(ushort species, byte level, string[] trainers, GameVersion game) { @@ -57,16 +57,16 @@ public CK3 ConvertToPKM(ITrainerInfo tr, EncounterCriteria criteria) { Species = Species, CurrentLevel = Level, - OT_Friendship = pi.BaseFriendship, + OriginalTrainerFriendship = pi.BaseFriendship, - Met_Location = Location, - Met_Level = Level, - Version = (byte)Version, + MetLocation = Location, + MetLevel = Level, + Version = Version, Ball = (byte)Ball.Poke, Language = lang, - OT_Name = TrainerNames[lang], - OT_Gender = OT_Gender, + OriginalTrainerName = TrainerNames[lang], + OriginalTrainerGender = OriginalTrainerGender, ID32 = TID16, Nickname = SpeciesName.GetSpeciesNameGeneration(Species, lang, Generation), }; @@ -90,8 +90,8 @@ private int GetTemplateLanguage(ITrainerInfo tr) private void SetPINGA(CK3 pk, EncounterCriteria criteria, PersonalInfo3 pi) { - int gender = criteria.GetGender(pi); - int nature = (int)criteria.GetNature(); + var gender = criteria.GetGender(pi); + var nature = criteria.GetNature(); var ability = criteria.GetAbilityFromNumber(Ability); do { @@ -127,14 +127,14 @@ private static bool IsMatchEggLocation(PKM pk) return true; var expect = pk is PB8 ? Locations.Default8bNone : 0; - return pk.Egg_Location == expect; + return pk.EggLocation == expect; } private bool IsMatchLevel(PKM pk, EvoCriteria evo) { if (pk.Format != 3) // Met Level lost on PK3=>PK4 return evo.LevelMax >= Level; - return pk.Met_Level == Level; + return pk.MetLevel == Level; } private bool IsMatchLocation(PKM pk) @@ -142,7 +142,7 @@ private bool IsMatchLocation(PKM pk) if (pk.Format != 3) return true; // transfer location verified later - var met = pk.Met_Location; + var met = pk.MetLocation; return Location == met; } diff --git a/PKHeX.Core/Legality/Encounters/Templates/Gen3/Colo/EncounterShadow3Colo.cs b/PKHeX.Core/Legality/Encounters/Templates/Gen3/Colo/EncounterShadow3Colo.cs index 7de82b69d..d48c9892a 100644 --- a/PKHeX.Core/Legality/Encounters/Templates/Gen3/Colo/EncounterShadow3Colo.cs +++ b/PKHeX.Core/Legality/Encounters/Templates/Gen3/Colo/EncounterShadow3Colo.cs @@ -13,11 +13,11 @@ public sealed record EncounterShadow3Colo(byte ID, short Gauge, ReadOnlyMemory, IShadow3, IMoveset, IRandomCorrelation { // ReSharper restore NotAccessedPositionalProperty.Global - public int Generation => 3; + public byte Generation => 3; public EntityContext Context => EntityContext.Gen3; public GameVersion Version => GameVersion.COLO; - int ILocation.EggLocation => 0; - int ILocation.Location => Location; + ushort ILocation.EggLocation => 0; + ushort ILocation.Location => Location; public bool IsShiny => false; public bool EggEncounter => false; public Shiny Shiny => Shiny.Random; @@ -53,16 +53,16 @@ public CK3 ConvertToPKM(ITrainerInfo tr, EncounterCriteria criteria) { Species = Species, CurrentLevel = LevelMin, - OT_Friendship = pi.BaseFriendship, + OriginalTrainerFriendship = pi.BaseFriendship, - Met_Location = Location, - Met_Level = LevelMin, - Version = (byte)GameVersion.CXD, + MetLocation = Location, + MetLevel = LevelMin, + Version = GameVersion.CXD, Ball = (byte)Ball.Poke, Language = lang, - OT_Name = EncounterUtil.GetTrainerName(tr, lang), - OT_Gender = 0, + OriginalTrainerName = EncounterUtil.GetTrainerName(tr, lang), + OriginalTrainerGender = 0, ID32 = tr.ID32, Nickname = SpeciesName.GetSpeciesNameGeneration(Species, lang, Generation), @@ -89,8 +89,8 @@ private void SetPINGA(CK3 pk, EncounterCriteria criteria, PersonalInfo3 pi) private void SetPINGA_Regular(CK3 pk, EncounterCriteria criteria, PersonalInfo3 pi) { - int gender = criteria.GetGender(pi); - int nature = (int)criteria.GetNature(); + var gender = criteria.GetGender(pi); + var nature = criteria.GetNature(); int ability = criteria.GetAbilityFromNumber(Ability); // Ensure that any generated specimen has valid Shadow Locks @@ -125,9 +125,10 @@ private void SetPINGA_EReader(CK3 pk) // Cancel this operation if too many attempts are made to prevent infinite loops. int ctr = 0; const int max = 100_000; + var rnd = Util.Rand; do { - var seed = Util.Rand32(); + var seed = rnd.Rand32(); PIDGenerator.SetValuesFromSeedXDRNG_EReader(pk, seed); if (pk.Nature != nature || pk.Gender != gender) continue; @@ -179,21 +180,21 @@ private static bool IsMatchEggLocation(PKM pk) return true; var expect = pk is PB8 ? Locations.Default8bNone : 0; - return pk.Egg_Location == expect; + return pk.EggLocation == expect; } private bool IsMatchLevel(PKM pk, EvoCriteria evo) { if (pk.Format != 3) // Met Level lost on PK3=>PK4 return evo.LevelMax >= Level; - return pk.Met_Level == Level; + return pk.MetLevel == Level; } private bool IsMatchLocation(PKM pk) { if (pk.Format != 3) return true; // transfer location verified later - return pk.Met_Location == Location; + return pk.MetLocation == Location; } #endregion diff --git a/PKHeX.Core/Legality/Encounters/Templates/Gen3/Colo/EncounterStatic3Colo.cs b/PKHeX.Core/Legality/Encounters/Templates/Gen3/Colo/EncounterStatic3Colo.cs index 1aaa79e80..d372c0a58 100644 --- a/PKHeX.Core/Legality/Encounters/Templates/Gen3/Colo/EncounterStatic3Colo.cs +++ b/PKHeX.Core/Legality/Encounters/Templates/Gen3/Colo/EncounterStatic3Colo.cs @@ -6,11 +6,11 @@ namespace PKHeX.Core; public sealed record EncounterStatic3Colo(ushort Species, byte Level) : IEncounterable, IEncounterMatch, IEncounterConvertible, IFixedGender, IRandomCorrelation, IMoveset { - public int Generation => 3; + public byte Generation => 3; public EntityContext Context => EntityContext.Gen3; public GameVersion Version => GameVersion.COLO; - int ILocation.EggLocation => 0; - int ILocation.Location => Location; + ushort ILocation.EggLocation => 0; + ushort ILocation.Location => Location; public bool IsShiny => false; public Shiny Shiny => Shiny.Never; public byte Form => 0; @@ -43,16 +43,16 @@ public CK3 ConvertToPKM(ITrainerInfo tr, EncounterCriteria criteria) { Species = Species, CurrentLevel = Level, - OT_Friendship = pi.BaseFriendship, + OriginalTrainerFriendship = pi.BaseFriendship, - Met_Location = Location, - Met_Level = Level, - Version = (byte)GameVersion.CXD, + MetLocation = Location, + MetLevel = Level, + Version = GameVersion.CXD, Ball = (byte)Ball.Poke, Language = lang, - OT_Name = tr.OT, - OT_Gender = 0, + OriginalTrainerName = tr.OT, + OriginalTrainerGender = 0, ID32 = tr.ID32, Nickname = SpeciesName.GetSpeciesNameGeneration(Species, lang, Generation), }; @@ -71,8 +71,8 @@ public CK3 ConvertToPKM(ITrainerInfo tr, EncounterCriteria criteria) private void SetPINGA(CK3 pk, EncounterCriteria criteria, PersonalInfo3 pi) { - int gender = criteria.GetGender(Gender, pi); - int nature = (int)criteria.GetNature(); + var gender = criteria.GetGender(Gender, pi); + var nature = criteria.GetNature(); var ability = criteria.GetAbilityFromNumber(Ability); do { @@ -112,14 +112,14 @@ private static bool IsMatchEggLocation(PKM pk) return true; var expect = pk is PB8 ? Locations.Default8bNone : 0; - return pk.Egg_Location == expect; + return pk.EggLocation == expect; } private bool IsMatchLevel(PKM pk, EvoCriteria evo) { if (pk.Format != 3) // Met Level lost on PK3=>PK4 return evo.LevelMax >= Level; - return pk.Met_Level == Level; + return pk.MetLevel == Level; } private bool IsMatchLocation(PKM pk) @@ -127,7 +127,7 @@ private bool IsMatchLocation(PKM pk) if (pk.Format != 3) return true; // transfer location verified later - var met = pk.Met_Location; + var met = pk.MetLocation; return Location == met; } diff --git a/PKHeX.Core/Legality/Encounters/Templates/Gen3/EncounterArea3.cs b/PKHeX.Core/Legality/Encounters/Templates/Gen3/EncounterArea3.cs index 6798df09b..d19584c94 100644 --- a/PKHeX.Core/Legality/Encounters/Templates/Gen3/EncounterArea3.cs +++ b/PKHeX.Core/Legality/Encounters/Templates/Gen3/EncounterArea3.cs @@ -1,23 +1,25 @@ using System; +using System.Diagnostics.CodeAnalysis; using static System.Buffers.Binary.BinaryPrimitives; +using static PKHeX.Core.SlotType3; namespace PKHeX.Core; /// /// encounter area /// -public sealed record EncounterArea3 : IEncounterArea, ISlotRNGType, IAreaLocation +public sealed record EncounterArea3 : IEncounterArea, IAreaLocation { public EncounterSlot3[] Slots { get; } public GameVersion Version { get; } - public SlotType Type { get; } + public SlotType3 Type { get; } public readonly byte Rate; public readonly byte Location; - public bool IsMatchLocation(int location) => location == Location; + public bool IsMatchLocation(ushort location) => location == Location; - public static EncounterArea3[] GetAreas(BinLinkerAccessor input, GameVersion game) + public static EncounterArea3[] GetAreas(BinLinkerAccessor input, [ConstantExpected] GameVersion game) { var result = new EncounterArea3[input.Length]; for (int i = 0; i < result.Length; i++) @@ -25,42 +27,44 @@ public static EncounterArea3[] GetAreas(BinLinkerAccessor input, GameVersion gam return result; } - public static EncounterArea3[] GetAreasSwarm(BinLinkerAccessor input, GameVersion game) + public static EncounterArea3[] GetAreasSwarm(BinLinkerAccessor input, [ConstantExpected] GameVersion game) { var result = new EncounterArea3[input.Length]; for (int i = 0; i < result.Length; i++) - result[i] = new EncounterArea3(input[i], game, SlotType.Swarm | SlotType.Grass); + result[i] = new EncounterArea3(input[i], game, SwarmGrass50); return result; } - private EncounterArea3(ReadOnlySpan data, GameVersion game) + private EncounterArea3(ReadOnlySpan data, [ConstantExpected] GameVersion game) { Location = data[0]; - Type = (SlotType)data[2]; + // data[1] is unused because location is always <= 255. + Type = (SlotType3)data[2]; Rate = data[3]; Version = game; - Slots = ReadRegularSlots(data); + Slots = ReadRegularSlots(data[4..]); } - private EncounterArea3(ReadOnlySpan data, GameVersion game, SlotType type) + private EncounterArea3(ReadOnlySpan data, [ConstantExpected] GameVersion game, [ConstantExpected] SlotType3 type) { Location = data[0]; - Type = type; + // data[1] is unused because location is always <= 255. + Type = type; // data[2] but it's always the same value Rate = data[3]; Version = game; - Slots = ReadSwarmSlots(data); + Slots = ReadSwarmSlots(data[4..]); } private EncounterSlot3[] ReadRegularSlots(ReadOnlySpan data) { const int size = 10; - int count = (data.Length - 4) / size; + int count = data.Length / size; var slots = new EncounterSlot3[count]; for (int i = 0; i < slots.Length; i++) { - int offset = 4 + (size * i); + int offset = size * i; var entry = data.Slice(offset, size); slots[i] = ReadRegularSlot(entry); } @@ -86,11 +90,11 @@ private EncounterSlot3 ReadRegularSlot(ReadOnlySpan entry) private EncounterSlot3[] ReadSwarmSlots(ReadOnlySpan data) { const int size = 14; - int count = (data.Length - 4) / size; + int count = data.Length / size; var slots = new EncounterSlot3[count]; for (int i = 0; i < slots.Length; i++) { - int offset = 4 + (size * i); + int offset = size * i; var entry = data.Slice(offset, size); slots[i] = ReadSwarmSlot(entry); } @@ -115,4 +119,31 @@ private EncounterSlot3Swarm ReadSwarmSlot(ReadOnlySpan entry) return new EncounterSlot3Swarm(this, species, min, max, slotNum, moves); } + + public byte GetPressureMax(ushort species, byte levelMax) + { + foreach (var slot in Slots) + { + if (slot.Species != species) + continue; + if (slot.LevelMax < levelMax) + continue; + levelMax = slot.LevelMax; + } + return levelMax; + } +} + + +public enum SlotType3 : byte +{ + Grass = 0, + Surf = 1, + Old_Rod = 2, + Good_Rod = 3, + Super_Rod = 4, + Rock_Smash = 5, + + SwarmGrass50 = 6, + SwarmFish50 = 7, } diff --git a/PKHeX.Core/Legality/Encounters/Templates/Gen3/EncounterSlot3.cs b/PKHeX.Core/Legality/Encounters/Templates/Gen3/EncounterSlot3.cs index 469a4c812..22e7ae801 100644 --- a/PKHeX.Core/Legality/Encounters/Templates/Gen3/EncounterSlot3.cs +++ b/PKHeX.Core/Legality/Encounters/Templates/Gen3/EncounterSlot3.cs @@ -1,29 +1,35 @@ +using static PKHeX.Core.PIDType; +using static PKHeX.Core.SlotType3; + namespace PKHeX.Core; /// /// Encounter Slot found in . /// public record EncounterSlot3(EncounterArea3 Parent, ushort Species, byte Form, byte LevelMin, byte LevelMax, byte SlotNumber, byte MagnetPullIndex, byte MagnetPullCount, byte StaticIndex, byte StaticCount) - : IEncounterable, IEncounterMatch, IEncounterConvertible, IMagnetStatic, INumberedSlot, ISlotRNGType, IRandomCorrelation + : IEncounterable, IEncounterMatch, IEncounterConvertible, IEncounterSlot3, IRandomCorrelation { - public int Generation => 3; - int ILocation.Location => Location; + public byte Generation => 3; + ushort ILocation.Location => Location; public EntityContext Context => EntityContext.Gen3; public bool EggEncounter => false; public Ball FixedBall => GetRequiredBall(); + public byte AreaRate => Parent.Rate; public AbilityPermission Ability => AbilityPermission.Any12; public Shiny Shiny => Shiny.Random; public bool IsShiny => false; - public int EggLocation => 0; + public ushort EggLocation => 0; public string Name => $"Wild Encounter ({Version})"; public string LongName => $"{Name} {Type.ToString().Replace('_', ' ')}"; public GameVersion Version => Parent.Version; public byte Location => Parent.Location; - public SlotType Type => Parent.Type; + public SlotType3 Type => Parent.Type; + public bool IsSafari => Locations.IsSafariZoneLocation3(Location); + public bool IsSafariHoenn => Locations.IsSafariZoneLocation3RSE(Location); - private Ball GetRequiredBall(Ball fallback = Ball.None) => Locations.IsSafariZoneLocation3(Location) ? Ball.Safari : fallback; + private Ball GetRequiredBall(Ball fallback = Ball.None) => IsSafari ? Ball.Safari : fallback; #region Generating PKM IEncounterConvertible.ConvertToPKM(ITrainerInfo tr, EncounterCriteria criteria) => ConvertToPKM(tr, criteria); @@ -33,22 +39,22 @@ public record EncounterSlot3(EncounterArea3 Parent, ushort Species, byte Form, b public PK3 ConvertToPKM(ITrainerInfo tr, EncounterCriteria criteria) { int lang = (int)Language.GetSafeLanguage(Generation, (LanguageID)tr.Language); - var version = Version != GameVersion.RSE ? Version : GameVersion.RSE.Contains(tr.Game) ? (GameVersion)tr.Game : GameVersion.E; + var version = Version != GameVersion.RSE ? Version : GameVersion.RSE.Contains(tr.Version) ? tr.Version : GameVersion.E; var pi = PersonalTable.E[Species]; var pk = new PK3 { Species = Species, CurrentLevel = LevelMin, - OT_Friendship = pi.BaseFriendship, + OriginalTrainerFriendship = pi.BaseFriendship, - Met_Location = Location, - Met_Level = LevelMin, - Version = (byte)version, + MetLocation = Location, + MetLevel = LevelMin, + Version = version, Ball = (byte)GetRequiredBall(Ball.Poke), Language = lang, - OT_Name = tr.OT, - OT_Gender = tr.Gender, + OriginalTrainerName = tr.OT, + OriginalTrainerGender = tr.Gender, ID32 = tr.ID32, Nickname = SpeciesName.GetSpeciesNameGeneration(Species, lang, Generation), }; @@ -62,20 +68,32 @@ public PK3 ConvertToPKM(ITrainerInfo tr, EncounterCriteria criteria) private void SetPINGA(PK3 pk, EncounterCriteria criteria, PersonalInfo3 pi) { - int gender = criteria.GetGender(pi); - int nature = (int)criteria.GetNature(); + var gender = criteria.GetGender(pi); + var nature = criteria.GetNature(); var ability = criteria.GetAbilityFromNumber(Ability); + var lvl = new SingleLevelRange(LevelMin); + int ctr = 0; + if (Species == (int)Core.Species.Unown) { do { - PIDGenerator.SetRandomWildPID4(pk, nature, ability, gender, PIDType.Method_1_Unown); + var seed = PIDGenerator.SetRandomWildPID4(pk, nature, ability, gender, Method_1_Unown); + var lead = MethodH.GetSeed(this, seed, lvl, false, 2, 3); + if (pk.Form != Form && lead.IsValid()) + return; ability ^= 1; // some nature-forms cannot have a certain PID-ability set, so just flip it as Unown doesn't have dual abilities. - } while (pk.Form != Form); + } while (ctr++ < 10_000); } else { - PIDGenerator.SetRandomWildPID4(pk, nature, ability, gender, PIDType.Method_1); + do + { + var seed = PIDGenerator.SetRandomWildPID4(pk, nature, ability, gender, Method_1); + var result = MethodH.GetSeed(this, seed, lvl, pk.E, pk.Gender, 3); + if (result.IsValid()) + return; + } while (ctr++ < 10_000); } } @@ -92,7 +110,7 @@ public bool IsMatchExact(PKM pk, EvoCriteria evo) if (pk.Format == 3) { // Must match level exactly. - if (!this.IsLevelWithinRange(pk.Met_Level)) + if (!this.IsLevelWithinRange(pk.MetLevel)) return false; } else @@ -120,9 +138,11 @@ public EncounterMatchRating GetMatchRating(PKM pk) public bool IsCompatible(PIDType val, PKM pk) { if (Species != (int)Core.Species.Unown) - return val is (PIDType.Method_1 or PIDType.Method_2 or PIDType.Method_3 or PIDType.Method_4); - return val is (PIDType.Method_1_Unown or PIDType.Method_2_Unown or PIDType.Method_3_Unown or PIDType.Method_4_Unown); + return val is (Method_1 or Method_2 or Method_3 or Method_4); + return val is (Method_1_Unown or Method_2_Unown or Method_3_Unown or Method_4_Unown); } - public PIDType GetSuggestedCorrelation() => Species == (int)Core.Species.Unown ? PIDType.Method_1_Unown : PIDType.Method_1; + public PIDType GetSuggestedCorrelation() => Species == (int)Core.Species.Unown ? Method_1_Unown : Method_1; + + public byte PressureLevel => Type != Grass ? LevelMax : Parent.GetPressureMax(Species, LevelMax); } diff --git a/PKHeX.Core/Legality/Encounters/Templates/Gen3/EncounterStatic3.cs b/PKHeX.Core/Legality/Encounters/Templates/Gen3/EncounterStatic3.cs index 0f4f28d31..2db4190e7 100644 --- a/PKHeX.Core/Legality/Encounters/Templates/Gen3/EncounterStatic3.cs +++ b/PKHeX.Core/Legality/Encounters/Templates/Gen3/EncounterStatic3.cs @@ -6,11 +6,11 @@ namespace PKHeX.Core; public sealed record EncounterStatic3(ushort Species, byte Level, GameVersion Version) : IEncounterable, IEncounterMatch, IEncounterConvertible, IFatefulEncounterReadOnly, IRandomCorrelation, IMoveset { - public int Generation => 3; + public byte Generation => 3; public EntityContext Context => EntityContext.Gen3; public bool Roaming { get; init; } - int ILocation.EggLocation => 0; - int ILocation.Location => Location; + ushort ILocation.EggLocation => 0; + ushort ILocation.Location => Location; public bool IsShiny => false; private bool Gift => FixedBall == Ball.Poke; public Shiny Shiny => Shiny.Random; @@ -38,23 +38,23 @@ public sealed record EncounterStatic3(ushort Species, byte Level, GameVersion Ve public PK3 ConvertToPKM(ITrainerInfo tr, EncounterCriteria criteria) { int lang = GetTemplateLanguage(tr); - var version = this.GetCompatibleVersion((GameVersion)tr.Game); + var version = this.GetCompatibleVersion(tr.Version); var pi = PersonalTable.E[Species]; var pk = new PK3 { Species = Species, CurrentLevel = LevelMin, - OT_Friendship = pi.BaseFriendship, + OriginalTrainerFriendship = pi.BaseFriendship, - Met_Location = Location, - Met_Level = LevelMin, - Version = (byte)version, + MetLocation = Location, + MetLevel = LevelMin, + Version = version, Ball = (byte)(FixedBall != Ball.None ? FixedBall : Ball.Poke), FatefulEncounter = FatefulEncounter, Language = lang, - OT_Name = EncounterUtil.GetTrainerName(tr, lang), - OT_Gender = tr.Gender, + OriginalTrainerName = EncounterUtil.GetTrainerName(tr, lang), + OriginalTrainerGender = tr.Gender, ID32 = tr.ID32, Nickname = SpeciesName.GetSpeciesNameGeneration(Species, lang, Generation), }; @@ -62,8 +62,8 @@ public PK3 ConvertToPKM(ITrainerInfo tr, EncounterCriteria criteria) if (EggEncounter) { // Fake as hatched. - pk.Met_Level = EggStateLegality.EggMetLevel34; - pk.Met_Location = version is GameVersion.FR or GameVersion.LG + pk.MetLevel = EggStateLegality.EggMetLevel34; + pk.MetLocation = version is GameVersion.FR or GameVersion.LG ? Locations.HatchLocationFRLG : Locations.HatchLocationRSE; } @@ -93,8 +93,8 @@ private int GetTemplateLanguage(ITrainerInfo tr) private void SetPINGA(PK3 pk, EncounterCriteria criteria, PersonalInfo3 pi) { - int gender = criteria.GetGender(pi); - int nature = (int)criteria.GetNature(); + var gender = criteria.GetGender(pi); + var nature = criteria.GetNature(); var ability = criteria.GetAbilityFromNumber(Ability); var type = Roaming && Version != GameVersion.E ? PIDType.Method_1_Roamer : PIDType.Method_1; do @@ -133,7 +133,7 @@ private static bool IsMatchEggLocation(PKM pk) return true; var expect = pk is PB8 ? Locations.Default8bNone : 0; - return pk.Egg_Location == expect; + return pk.EggLocation == expect; } private bool IsMatchLevel(PKM pk, EvoCriteria evo) @@ -141,8 +141,8 @@ private bool IsMatchLevel(PKM pk, EvoCriteria evo) if (pk.Format != 3) // Met Level lost on PK3=>PK4 return evo.LevelMax >= Level; if (!EggEncounter) - return pk.Met_Level == Level; - return pk is { Met_Level: EggStateLegality.EggMetLevel34, CurrentLevel: >= 5 }; // met level 0, origin level 5 + return pk.MetLevel == Level; + return pk is { MetLevel: EggStateLegality.EggMetLevel34, CurrentLevel: >= 5 }; // met level 0, origin level 5 } private bool IsMatchLocation(PKM pk) @@ -151,9 +151,9 @@ private bool IsMatchLocation(PKM pk) return true; // transfer location verified later if (EggEncounter) - return !pk.IsEgg || pk.Met_Location == Location; + return !pk.IsEgg || pk.MetLocation == Location; - var met = pk.Met_Location; + var met = pk.MetLocation; if (!Roaming) return Location == met; @@ -179,9 +179,9 @@ private bool IsMatchPartial(PKM pk) public bool IsCompatible(PIDType val, PKM pk) { var version = pk.Version; - if (version is (int)GameVersion.E) + if (version is GameVersion.E) return val is PIDType.Method_1; - if (version is (int)GameVersion.FR or(int) GameVersion.LG) + if (version is GameVersion.FR or GameVersion.LG) return Roaming ? IsRoamerPIDIV(val, pk) : val is PIDType.Method_1; // RS, roamer glitch && RSBox s/w emulation => method 4 available return Roaming ? IsRoamerPIDIV(val, pk) : val is (PIDType.Method_1 or PIDType.Method_4); diff --git a/PKHeX.Core/Legality/Encounters/Templates/Gen3/EncounterTrade3.cs b/PKHeX.Core/Legality/Encounters/Templates/Gen3/EncounterTrade3.cs index 583c7023b..17a0e1a30 100644 --- a/PKHeX.Core/Legality/Encounters/Templates/Gen3/EncounterTrade3.cs +++ b/PKHeX.Core/Legality/Encounters/Templates/Gen3/EncounterTrade3.cs @@ -7,14 +7,14 @@ namespace PKHeX.Core; /// public sealed record EncounterTrade3 : IEncounterable, IEncounterMatch, IFixedTrainer, IFixedNickname, IFixedGender, IFixedNature, IEncounterConvertible, IContestStatsReadOnly { - public int Generation => 3; + public byte Generation => 3; public EntityContext Context => EntityContext.Gen3; - public int Location => Locations.LinkTrade3NPC; + public ushort Location => Locations.LinkTrade3NPC; public Shiny Shiny => Shiny.FixedValue; public bool EggEncounter => false; public Ball FixedBall => Ball.Poke; public bool IsShiny => false; - public int EggLocation => 0; + public ushort EggLocation => 0; public bool IsFixedTrainer => true; public bool IsFixedNickname => true; public Nature Nature => (Nature)(PID % 25); @@ -45,23 +45,23 @@ public sealed record EncounterTrade3 : IEncounterable, IEncounterMatch, IFixedTr public required ushort TID16 { get; init; } public ushort SID16 { get; init; } - public byte CNT_Cool { get; private init; } - public byte CNT_Beauty { get; private init; } - public byte CNT_Cute { get; private init; } - public byte CNT_Smart { get; private init; } - public byte CNT_Tough { get; private init; } - public byte CNT_Sheen { get; private init; } + public byte ContestCool { get; private init; } + public byte ContestBeauty { get; private init; } + public byte ContestCute { get; private init; } + public byte ContestSmart { get; private init; } + public byte ContestTough { get; private init; } + public byte ContestSheen { get; private init; } public required ReadOnlySpan Contest { init { - CNT_Cool = value[0]; - CNT_Beauty = value[1]; - CNT_Cute = value[2]; - CNT_Smart = value[3]; - CNT_Tough = value[4]; - CNT_Sheen = value[5]; + ContestCool = value[0]; + ContestBeauty = value[1]; + ContestCute = value[2]; + ContestSmart = value[3]; + ContestTough = value[4]; + ContestSheen = value[5]; } } @@ -84,7 +84,7 @@ public EncounterTrade3(ReadOnlySpan names, byte index, GameVersion gam public PK3 ConvertToPKM(ITrainerInfo tr, EncounterCriteria criteria) { - var version = this.GetCompatibleVersion((GameVersion)tr.Game); + var version = this.GetCompatibleVersion(tr.Version); int lang = (int)Language.GetSafeLanguage(Generation, (LanguageID)tr.Language, version); var pi = PersonalTable.E[Species]; var pk = new PK3 @@ -92,14 +92,14 @@ public PK3 ConvertToPKM(ITrainerInfo tr, EncounterCriteria criteria) Species = Species, CurrentLevel = Level, - Met_Location = Location, - Met_Level = Level, - Version = (byte)version, + MetLocation = Location, + MetLevel = Level, + Version = version, Ball = (byte)FixedBall, - OT_Friendship = pi.BaseFriendship, + OriginalTrainerFriendship = pi.BaseFriendship, Language = lang, - OT_Gender = OTGender, + OriginalTrainerGender = OTGender, TID16 = TID16, SID16 = SID16, }; @@ -108,7 +108,7 @@ public PK3 ConvertToPKM(ITrainerInfo tr, EncounterCriteria criteria) if (Species == (int)Core.Species.Jynx && version == GameVersion.LG && lang == (int)LanguageID.Italian) lang = 2; pk.Nickname = Nicknames[lang]; - pk.OT_Name = TrainerNames[lang]; + pk.OriginalTrainerName = TrainerNames[lang]; EncounterUtil.SetEncounterMoves(pk, Version, Level); SetPINGA(pk, criteria); @@ -147,9 +147,9 @@ public bool IsMatchExact(PKM pk, EvoCriteria evo) return false; if (pk.Gender != Gender) return false; - if (pk.OT_Gender != OTGender) + if (pk.OriginalTrainerGender != OTGender) return false; - if (pk.Egg_Location != 0) + if (pk.EggLocation != 0) return false; if (pk is IContestStatsReadOnly s && s.IsContestBelow(this)) return false; @@ -161,14 +161,14 @@ public bool IsMatchExact(PKM pk, EvoCriteria evo) public bool IsTrainerMatch(PKM pk, ReadOnlySpan trainer, int language) { - if (Species == (int)Core.Species.Jynx && pk.Version == (int)GameVersion.LG && language == (int)LanguageID.Italian) + if (Species == (int)Core.Species.Jynx && pk.Version == GameVersion.LG && language == (int)LanguageID.Italian) language = 2; return language != 0 && (uint)language < TrainerNames.Length && trainer.SequenceEqual(TrainerNames[language]); } public bool IsNicknameMatch(PKM pk, ReadOnlySpan nickname, int language) { - if (Species == (int)Core.Species.Jynx && pk.Version == (int)GameVersion.LG && language == (int)LanguageID.Italian) + if (Species == (int)Core.Species.Jynx && pk.Version == GameVersion.LG && language == (int)LanguageID.Italian) language = 2; return language != 0 && (uint)language < Nicknames.Length && nickname.SequenceEqual(Nicknames[language]); } diff --git a/PKHeX.Core/Legality/Encounters/Templates/Gen3/XD/EncounterArea3XD.cs b/PKHeX.Core/Legality/Encounters/Templates/Gen3/XD/EncounterArea3XD.cs index 5a49aca22..9859900e8 100644 --- a/PKHeX.Core/Legality/Encounters/Templates/Gen3/XD/EncounterArea3XD.cs +++ b/PKHeX.Core/Legality/Encounters/Templates/Gen3/XD/EncounterArea3XD.cs @@ -6,11 +6,10 @@ namespace PKHeX.Core; public sealed record EncounterArea3XD : IVersion, IEncounterArea, IAreaLocation { public EncounterSlot3XD[] Slots { get; } - public SlotType Type => SlotType.Grass; public GameVersion Version => GameVersion.XD; public readonly byte Location; - public bool IsMatchLocation(int location) => location == Location; + public bool IsMatchLocation(ushort location) => location == Location; public EncounterArea3XD(byte loc, ushort s0, byte l0, ushort s1, byte l1, ushort s2, byte l2) { diff --git a/PKHeX.Core/Legality/Encounters/Templates/Gen3/XD/EncounterShadow3XD.cs b/PKHeX.Core/Legality/Encounters/Templates/Gen3/XD/EncounterShadow3XD.cs index 9f6bc8adf..3ab69512e 100644 --- a/PKHeX.Core/Legality/Encounters/Templates/Gen3/XD/EncounterShadow3XD.cs +++ b/PKHeX.Core/Legality/Encounters/Templates/Gen3/XD/EncounterShadow3XD.cs @@ -13,11 +13,11 @@ public sealed record EncounterShadow3XD(byte ID, short Gauge, ReadOnlyMemory, IShadow3, IFatefulEncounterReadOnly, IMoveset, IRandomCorrelation { // ReSharper restore NotAccessedPositionalProperty.Global - public int Generation => 3; + public byte Generation => 3; public EntityContext Context => EntityContext.Gen3; public GameVersion Version => GameVersion.XD; - int ILocation.EggLocation => 0; - int ILocation.Location => Location; + ushort ILocation.EggLocation => 0; + ushort ILocation.Location => Location; public bool IsShiny => false; public bool EggEncounter => false; public Shiny Shiny => Shiny.Never; // Different from Colosseum! @@ -49,17 +49,17 @@ public XK3 ConvertToPKM(ITrainerInfo tr, EncounterCriteria criteria) { Species = Species, CurrentLevel = LevelMin, - OT_Friendship = pi.BaseFriendship, + OriginalTrainerFriendship = pi.BaseFriendship, - Met_Location = Location, - Met_Level = LevelMin, - Version = (byte)GameVersion.CXD, + MetLocation = Location, + MetLevel = LevelMin, + Version = GameVersion.CXD, Ball = (byte)(FixedBall != Ball.None ? FixedBall : Ball.Poke), FatefulEncounter = FatefulEncounter, Language = lang, - OT_Name = tr.OT, - OT_Gender = 0, + OriginalTrainerName = tr.OT, + OriginalTrainerGender = 0, ID32 = tr.ID32, Nickname = SpeciesName.GetSpeciesNameGeneration(Species, lang, Generation), @@ -79,8 +79,8 @@ public XK3 ConvertToPKM(ITrainerInfo tr, EncounterCriteria criteria) private void SetPINGA(XK3 pk, EncounterCriteria criteria, PersonalInfo3 pi) { - int gender = criteria.GetGender(pi); - int nature = (int)criteria.GetNature(); + var gender = criteria.GetGender(pi); + var nature = criteria.GetNature(); int ability = criteria.GetAbilityFromNumber(Ability); // Ensure that any generated specimen has valid Shadow Locks @@ -137,14 +137,14 @@ private static bool IsMatchEggLocation(PKM pk) return true; var expect = pk is PB8 ? Locations.Default8bNone : 0; - return pk.Egg_Location == expect; + return pk.EggLocation == expect; } private bool IsMatchLevel(PKM pk, EvoCriteria evo) { if (pk.Format != 3) // Met Level lost on PK3=>PK4 return evo.LevelMax >= Level; - return pk.Met_Level == Level; + return pk.MetLevel == Level; } private bool IsMatchLocation(PKM pk) @@ -152,7 +152,7 @@ private bool IsMatchLocation(PKM pk) if (pk.Format != 3) return true; // transfer location verified later - var met = pk.Met_Location; + var met = pk.MetLocation; if (met == Location) return true; diff --git a/PKHeX.Core/Legality/Encounters/Templates/Gen3/XD/EncounterSlot3XD.cs b/PKHeX.Core/Legality/Encounters/Templates/Gen3/XD/EncounterSlot3XD.cs index 72b5cbcf0..9ea94336e 100644 --- a/PKHeX.Core/Legality/Encounters/Templates/Gen3/XD/EncounterSlot3XD.cs +++ b/PKHeX.Core/Legality/Encounters/Templates/Gen3/XD/EncounterSlot3XD.cs @@ -6,7 +6,7 @@ namespace PKHeX.Core; public sealed record EncounterSlot3XD(EncounterArea3XD Parent, ushort Species, byte LevelMin, byte LevelMax, byte SlotNumber) : IEncounterable, IEncounterMatch, IEncounterConvertible, INumberedSlot, IFatefulEncounterReadOnly, IRandomCorrelation { - public int Generation => 3; + public byte Generation => 3; public EntityContext Context => EntityContext.Gen3; public bool FatefulEncounter => true; public bool EggEncounter => false; @@ -14,15 +14,14 @@ public sealed record EncounterSlot3XD(EncounterArea3XD Parent, ushort Species, b public AbilityPermission Ability => AbilityPermission.Any12; public Shiny Shiny => Shiny.Random; public bool IsShiny => false; - public int EggLocation => 0; + public ushort EggLocation => 0; public byte Form => 0; public string Name => $"Wild Encounter ({Version})"; - public string LongName => $"{Name} {Type.ToString().Replace('_', ' ')}"; + public string LongName => $"{Name} - Cave Spot"; public GameVersion Version => Parent.Version; - public int Location => Parent.Location; - public SlotType Type => Parent.Type; + public ushort Location => Parent.Location; #region Generating PKM IEncounterConvertible.ConvertToPKM(ITrainerInfo tr, EncounterCriteria criteria) => ConvertToPKM(tr, criteria); @@ -37,16 +36,16 @@ public XK3 ConvertToPKM(ITrainerInfo tr, EncounterCriteria criteria) { Species = Species, CurrentLevel = LevelMin, - OT_Friendship = pi.BaseFriendship, + OriginalTrainerFriendship = pi.BaseFriendship, FatefulEncounter = FatefulEncounter, - Met_Location = Location, - Met_Level = LevelMin, - Version = (byte)GameVersion.CXD, + MetLocation = Location, + MetLevel = LevelMin, + Version = GameVersion.CXD, Ball = (byte)Ball.Poke, Language = lang, - OT_Name = tr.OT, - OT_Gender = 0, + OriginalTrainerName = tr.OT, + OriginalTrainerGender = 0, ID32 = tr.ID32, Nickname = SpeciesName.GetSpeciesNameGeneration(Species, lang, Generation), }; @@ -60,8 +59,8 @@ public XK3 ConvertToPKM(ITrainerInfo tr, EncounterCriteria criteria) private void SetPINGA(XK3 pk, EncounterCriteria criteria, PersonalInfo3 pi) { - int gender = criteria.GetGender(pi); - int nature = (int)criteria.GetNature(); + var gender = criteria.GetGender(pi); + var nature = criteria.GetNature(); int ability = criteria.GetAbilityFromNumber(Ability); PIDGenerator.SetRandomPokeSpotPID(pk, nature, gender, ability, SlotNumber); } diff --git a/PKHeX.Core/Legality/Encounters/Templates/Gen3/XD/EncounterStatic3XD.cs b/PKHeX.Core/Legality/Encounters/Templates/Gen3/XD/EncounterStatic3XD.cs index 259d32a1e..d2ba2d073 100644 --- a/PKHeX.Core/Legality/Encounters/Templates/Gen3/XD/EncounterStatic3XD.cs +++ b/PKHeX.Core/Legality/Encounters/Templates/Gen3/XD/EncounterStatic3XD.cs @@ -6,11 +6,11 @@ namespace PKHeX.Core; public sealed record EncounterStatic3XD(ushort Species, byte Level) : IEncounterable, IEncounterMatch, IEncounterConvertible, IFatefulEncounterReadOnly, IRandomCorrelation, IMoveset { - public int Generation => 3; + public byte Generation => 3; public EntityContext Context => EntityContext.Gen3; public GameVersion Version => GameVersion.XD; - int ILocation.EggLocation => 0; - int ILocation.Location => Location; + ushort ILocation.EggLocation => 0; + ushort ILocation.Location => Location; public bool IsShiny => false; private bool Gift => FixedBall == Ball.Poke; public Shiny Shiny => Shiny.Random; @@ -44,17 +44,17 @@ public XK3 ConvertToPKM(ITrainerInfo tr, EncounterCriteria criteria) { Species = Species, CurrentLevel = LevelMin, - OT_Friendship = pi.BaseFriendship, + OriginalTrainerFriendship = pi.BaseFriendship, - Met_Location = Location, - Met_Level = LevelMin, - Version = (byte)GameVersion.CXD, + MetLocation = Location, + MetLevel = LevelMin, + Version = GameVersion.CXD, Ball = (byte)(FixedBall != Ball.None ? FixedBall : Ball.Poke), FatefulEncounter = FatefulEncounter, Language = lang, - OT_Name = tr.OT, - OT_Gender = 0, + OriginalTrainerName = tr.OT, + OriginalTrainerGender = 0, ID32 = tr.ID32, Nickname = SpeciesName.GetSpeciesNameGeneration(Species, lang, Generation), }; @@ -71,8 +71,8 @@ public XK3 ConvertToPKM(ITrainerInfo tr, EncounterCriteria criteria) private void SetPINGA(XK3 pk, EncounterCriteria criteria, PersonalInfo3 pi) { - int gender = criteria.GetGender(pi); - int nature = (int)criteria.GetNature(); + var gender = criteria.GetGender(pi); + var nature = criteria.GetNature(); var ability = criteria.GetAbilityFromNumber(Ability); do { @@ -108,14 +108,14 @@ private static bool IsMatchEggLocation(PKM pk) return true; var expect = pk is PB8 ? Locations.Default8bNone : 0; - return pk.Egg_Location == expect; + return pk.EggLocation == expect; } private bool IsMatchLevel(PKM pk, EvoCriteria evo) { if (pk.Format != 3) // Met Level lost on PK3=>PK4 return evo.LevelMax >= Level; - return pk.Met_Level == Level; + return pk.MetLevel == Level; } private bool IsMatchLocation(PKM pk) @@ -123,7 +123,7 @@ private bool IsMatchLocation(PKM pk) if (pk.Format != 3) return true; // transfer location verified later - var met = pk.Met_Location; + var met = pk.MetLocation; return Location == met; } diff --git a/PKHeX.Core/Legality/Encounters/Templates/Gen3/XD/EncounterTrade3XD.cs b/PKHeX.Core/Legality/Encounters/Templates/Gen3/XD/EncounterTrade3XD.cs index fcebeeee8..597f21474 100644 --- a/PKHeX.Core/Legality/Encounters/Templates/Gen3/XD/EncounterTrade3XD.cs +++ b/PKHeX.Core/Legality/Encounters/Templates/Gen3/XD/EncounterTrade3XD.cs @@ -7,11 +7,11 @@ namespace PKHeX.Core; /// public sealed record EncounterTrade3XD : IEncounterable, IEncounterMatch, IEncounterConvertible, IRandomCorrelation, IFixedTrainer, IFixedNickname, IFatefulEncounterReadOnly, IMoveset { - public int Generation => 3; + public byte Generation => 3; public EntityContext Context => EntityContext.Gen3; public GameVersion Version => GameVersion.XD; - int ILocation.EggLocation => 0; - int ILocation.Location => Location; + ushort ILocation.EggLocation => 0; + ushort ILocation.Location => Location; public bool IsShiny => false; private bool Gift => FixedBall == Ball.Poke; public Shiny Shiny => Shiny.Random; @@ -64,16 +64,16 @@ public XK3 ConvertToPKM(ITrainerInfo tr, EncounterCriteria criteria) { Species = Species, CurrentLevel = LevelMin, - OT_Friendship = pi.BaseFriendship, + OriginalTrainerFriendship = pi.BaseFriendship, - Met_Location = Location, - Met_Level = Level, - Version = (byte)GameVersion.CXD, + MetLocation = Location, + MetLevel = Level, + Version = GameVersion.CXD, Ball = (byte)Ball.Poke, FatefulEncounter = FatefulEncounter, Language = lang, - OT_Name = TrainerNames[lang], - OT_Gender = 0, + OriginalTrainerName = TrainerNames[lang], + OriginalTrainerGender = 0, TID16 = TID16, SID16 = tr.SID16, Nickname = IsFixedNickname ? GetNickname(lang) : SpeciesName.GetSpeciesNameGeneration(Species, lang, Generation), @@ -93,8 +93,8 @@ public XK3 ConvertToPKM(ITrainerInfo tr, EncounterCriteria criteria) private void SetPINGA(XK3 pk, EncounterCriteria criteria, PersonalInfo3 pi) { - int gender = criteria.GetGender(pi); - int nature = (int)criteria.GetNature(); + var gender = criteria.GetGender(pi); + var nature = criteria.GetNature(); var ability = criteria.GetAbilityFromNumber(Ability); if (Species == (int)Core.Species.Unown) { @@ -144,14 +144,14 @@ private static bool IsMatchEggLocation(PKM pk) return true; var expect = pk is PB8 ? Locations.Default8bNone : 0; - return pk.Egg_Location == expect; + return pk.EggLocation == expect; } private bool IsMatchLevel(PKM pk, EvoCriteria evo) { if (pk.Format != 3) // Met Level lost on PK3=>PK4 return evo.LevelMax >= Level; - return pk.Met_Level == Level; + return pk.MetLevel == Level; } private bool IsMatchLocation(PKM pk) @@ -159,7 +159,7 @@ private bool IsMatchLocation(PKM pk) if (pk.Format != 3) return true; // transfer location verified later - var met = pk.Met_Location; + var met = pk.MetLocation; return Location == met; } diff --git a/PKHeX.Core/Legality/Encounters/Templates/Gen4/EncounterArea4.cs b/PKHeX.Core/Legality/Encounters/Templates/Gen4/EncounterArea4.cs index 0b4d1225e..8ed97eefb 100644 --- a/PKHeX.Core/Legality/Encounters/Templates/Gen4/EncounterArea4.cs +++ b/PKHeX.Core/Legality/Encounters/Templates/Gen4/EncounterArea4.cs @@ -1,4 +1,5 @@ using System; +using System.Diagnostics.CodeAnalysis; using static System.Buffers.Binary.BinaryPrimitives; namespace PKHeX.Core; @@ -6,19 +7,19 @@ namespace PKHeX.Core; /// /// encounter area /// -public sealed record EncounterArea4 : IEncounterArea, ISlotRNGType, IGroundTypeTile, IAreaLocation +public sealed record EncounterArea4 : IEncounterArea, IGroundTypeTile, IAreaLocation { public EncounterSlot4[] Slots { get; } public GameVersion Version { get; } - public SlotType Type { get; } + public SlotType4 Type { get; } public GroundTileAllowed GroundTile { get; } - public readonly ushort Location; + public readonly byte Location; public readonly byte Rate; - public bool IsMatchLocation(int location) => location == Location; + public bool IsMatchLocation(ushort location) => location == Location; - public static EncounterArea4[] GetAreas(BinLinkerAccessor input, GameVersion game) + public static EncounterArea4[] GetAreas(BinLinkerAccessor input, [ConstantExpected] GameVersion game) { var result = new EncounterArea4[input.Length]; for (int i = 0; i < result.Length; i++) @@ -26,26 +27,27 @@ public static EncounterArea4[] GetAreas(BinLinkerAccessor input, GameVersion gam return result; } - private EncounterArea4(ReadOnlySpan data, GameVersion game) + private EncounterArea4(ReadOnlySpan data, [ConstantExpected] GameVersion game) { - Location = ReadUInt16LittleEndian(data); - Type = (SlotType)data[2]; + Location = data[0]; + // data[1] is unused because location is always <= 255. + Type = (SlotType4)data[2]; Rate = data[3]; Version = game; // although GroundTilePermission flags are 32bit, none have values > 16bit. GroundTile = (GroundTileAllowed)ReadUInt16LittleEndian(data[4..]); - Slots = ReadRegularSlots(data); + Slots = ReadRegularSlots(data[6..]); } private EncounterSlot4[] ReadRegularSlots(ReadOnlySpan data) { const int size = 10; - int count = (data.Length - 6) / size; + int count = data.Length / size; var slots = new EncounterSlot4[count]; for (int i = 0; i < slots.Length; i++) { - int offset = 6 + (size * i); + int offset = size * i; var entry = data.Slice(offset, size); slots[i] = ReadRegularSlot(entry); } @@ -67,8 +69,23 @@ private EncounterSlot4 ReadRegularSlot(ReadOnlySpan entry) return new EncounterSlot4(this, species, form, min, max, slotNum, mpi, mpc, sti, stc); } + public byte GetPressureMax(ushort species, byte levelMax) + { + foreach (var slot in Slots) + { + if (slot.Species != species) + continue; + if (slot.LevelMax < levelMax) + continue; + levelMax = slot.LevelMax; + } + return levelMax; + } + public bool IsMunchlaxTree(ITrainerID32 pk) => IsMunchlaxTree(pk, Location); + public bool IsCoronetFeebasArea => Rate is byte.MaxValue; // Sentinel only for Fishing slots. + private static bool IsMunchlaxTree(ITrainerID32 pk, ushort location) { // We didn't encode the honey tree index to the encounter slot resource. @@ -110,4 +127,37 @@ private static bool IsMunchlaxTree(ReadOnlySpan trees, ushort location) 49, // 19 Fuego Ironworks 58, // 20 Floaroma Meadow ]; + + public static bool IsUnownFormValid(PKM pk, byte form) + { + return pk.HGSS + ? RuinsOfAlph4.IsUnownFormValid(pk, form) + : SolaceonRuins4.IsUnownFormValid(pk, form); + } +} + +/// +/// Wild Encounter data Type +/// +/// +/// Different from , this corresponds to the method that the may be encountered. +public enum SlotType4 : byte +{ + Grass = 0, + Surf = 1, + Old_Rod = 2, + Good_Rod = 3, + Super_Rod = 4, + Rock_Smash = 5, + + Headbutt = 6, + HeadbuttSpecial = 7, + BugContest = 8, + HoneyTree = 9, + + Safari_Grass = 10, + Safari_Surf = 11, + Safari_Old_Rod = 12, + Safari_Good_Rod = 13, + Safari_Super_Rod = 14, } diff --git a/PKHeX.Core/Legality/Encounters/Templates/Gen4/EncounterSlot4.cs b/PKHeX.Core/Legality/Encounters/Templates/Gen4/EncounterSlot4.cs index e49a16fc7..70fbc7815 100644 --- a/PKHeX.Core/Legality/Encounters/Templates/Gen4/EncounterSlot4.cs +++ b/PKHeX.Core/Legality/Encounters/Templates/Gen4/EncounterSlot4.cs @@ -1,36 +1,41 @@ +using static PKHeX.Core.SlotType4; + namespace PKHeX.Core; /// /// Encounter Slot found in . /// public sealed record EncounterSlot4(EncounterArea4 Parent, ushort Species, byte Form, byte LevelMin, byte LevelMax, byte SlotNumber, byte MagnetPullIndex, byte MagnetPullCount, byte StaticIndex, byte StaticCount) - : IEncounterable, IEncounterMatch, IEncounterConvertible, IMagnetStatic, INumberedSlot, IGroundTypeTile, ISlotRNGType, IEncounterFormRandom, IRandomCorrelation + : IEncounterable, IEncounterMatch, IEncounterConvertible, IEncounterSlot4, IGroundTypeTile, IEncounterFormRandom, IRandomCorrelation { - public int Generation => 4; - int ILocation.Location => Location; + public byte Generation => 4; + ushort ILocation.Location => Location; public EntityContext Context => EntityContext.Gen4; public bool EggEncounter => false; public AbilityPermission Ability => AbilityPermission.Any12; public Ball FixedBall => GetRequiredBallValue(); public Shiny Shiny => Shiny.Random; public bool IsShiny => false; - public int EggLocation => 0; + public ushort EggLocation => 0; public bool IsRandomUnspecificForm => Form >= EncounterUtil.FormDynamic; public string Name => $"Wild Encounter ({Version})"; public string LongName => $"{Name} {Type.ToString().Replace('_', ' ')}"; public GameVersion Version => Parent.Version; public ushort Location => Parent.Location; - public SlotType Type => Parent.Type; + public SlotType4 Type => Parent.Type; public GroundTileAllowed GroundTile => Parent.GroundTile; + public byte AreaRate => Parent.Rate; - public bool CanUseRadar => Version is not (GameVersion.HG or GameVersion.SS) && GroundTile.HasFlag(GroundTileAllowed.Grass) && !Locations4.IsSafariZoneLocation(Location); + public bool CanUseRadar => Version >= GameVersion.D // HG/SS are below + && GroundTile.HasFlag(GroundTileAllowed.Grass) + && !Locations4.IsMarsh(Location); private Ball GetRequiredBallValue(Ball fallback = Ball.None) { - if (Type is SlotType.BugContest) + if (Type is BugContest) return Ball.Sport; - return Locations4.IsSafariZoneLocation(Location) ? Ball.Safari : fallback; + return Locations4.IsSafariBallRequired(Location) ? Ball.Safari : fallback; } #region Generating @@ -47,18 +52,18 @@ public PK4 ConvertToPKM(ITrainerInfo tr, EncounterCriteria criteria) Species = Species, Form = GetWildForm(Form), CurrentLevel = LevelMin, - OT_Friendship = pi.BaseFriendship, + OriginalTrainerFriendship = pi.BaseFriendship, - Met_Location = Location, - Met_Level = LevelMin, - Version = (byte)Version, + MetLocation = Location, + MetLevel = LevelMin, + Version = Version, GroundTile = GroundTile.GetIndex(), MetDate = EncounterDate.GetDateNDS(), Ball = (byte)GetRequiredBallValue(Ball.Poke), Language = lang, - OT_Name = tr.OT, - OT_Gender = tr.Gender, + OriginalTrainerName = tr.OT, + OriginalTrainerGender = tr.Gender, ID32 = tr.ID32, Nickname = SpeciesName.GetSpeciesNameGeneration(Species, lang, Generation), }; @@ -79,23 +84,36 @@ private byte GetWildForm(byte form) private void SetPINGA(PK4 pk, EncounterCriteria criteria, PersonalInfo4 pi) { - int gender = criteria.GetGender(pi); - int nature = (int)criteria.GetNature(); + var gender = criteria.GetGender(pi); + var nature = criteria.GetNature(); var ability = criteria.GetAbilityFromNumber(Ability); + var lvl = new SingleLevelRange(LevelMin); + bool hgss = pk.HGSS; int ctr = 0; do { - PIDGenerator.SetRandomWildPID4(pk, nature, ability, gender, PIDType.Method_1); - var pidiv = MethodFinder.Analyze(pk); - var frames = FrameFinder.GetFrames(pidiv, pk); - foreach (var frame in frames) - { - if (frame.IsSlotCompatibile(this, pk)) - return; - } + var seed = PIDGenerator.SetRandomWildPID4(pk, nature, ability, gender, PIDType.Method_1); + if (!LeadFinder.TryGetLeadInfo4(this, lvl, hgss, seed, 4, out _)) + continue; + if (Species == (int)Core.Species.Unown) + pk.Form = GetUnownForm(seed, hgss); + break; } while (ctr++ < 10_000); } + /// + /// Gets a legal Unown form based on the game version and seed that generated the Method 1 spread. + /// + private static byte GetUnownForm(uint seed, bool hgss) + { + // ABCD|E(Item)|F(Form) determination + if (!hgss) + return 8; // Always 100% form as 'I' in one of the rooms. Don't need to check rand(1) choice. + + var formSeed = LCRNG.Next6(seed); + return RuinsOfAlph4.GetEntranceForm(formSeed); // !? + } + #endregion #region Matching @@ -112,7 +130,7 @@ public bool IsMatchExact(PKM pk, EvoCriteria evo) if (pk.Format == 4) { // Must match level exactly. - if (!this.IsLevelWithinRange(pk.Met_Level)) + if (!this.IsLevelWithinRange(pk.MetLevel)) return false; } else @@ -131,16 +149,16 @@ public bool IsMatchExact(PKM pk, EvoCriteria evo) public bool IsInvalidMunchlaxTree(PKM pk) { - if (Type is not SlotType.HoneyTree) + if (Type is not HoneyTree) return false; return Species == (int)Core.Species.Munchlax && !Parent.IsMunchlaxTree(pk); } public EncounterMatchRating GetMatchRating(PKM pk) { - if ((pk.Ball == (int)Ball.Safari) != Locations4.IsSafariZoneLocation(Location)) + if ((pk.Ball == (int)Ball.Safari) != Locations4.IsSafariBallRequired(Location)) return EncounterMatchRating.PartialMatch; - if ((pk.Ball == (int)Ball.Sport) != (Type == SlotType.BugContest)) + if ((pk.Ball == (int)Ball.Sport) != (Type == BugContest)) { // Nincada => Shedinja can wipe the ball back to Poke if (pk.Species != (int)Core.Species.Shedinja || pk.Ball != (int)Ball.Poke) @@ -148,8 +166,11 @@ public EncounterMatchRating GetMatchRating(PKM pk) } if (IsDeferredWurmple(pk)) return EncounterMatchRating.PartialMatch; + if (pk.Species == (int)Core.Species.Unown && !EncounterArea4.IsUnownFormValid(pk, pk.Form)) + return EncounterMatchRating.PartialMatch; return EncounterMatchRating.Match; } + private bool IsDeferredWurmple(PKM pk) => Species == (int)Core.Species.Wurmple && pk.Species != (int)Core.Species.Wurmple && !WurmpleUtil.IsWurmpleEvoValid(pk); #endregion @@ -162,9 +183,13 @@ public bool IsCompatible(PIDType val, PKM pk) if (val is PIDType.ChainShiny) return pk.IsShiny && CanUseRadar; if (val is PIDType.CuteCharm) - return pk.Gender is 0 or 1 && MethodFinder.IsCuteCharm4Valid(this, pk); + return MethodFinder.IsCuteCharm4Valid(this, pk); return false; } public PIDType GetSuggestedCorrelation() => PIDType.Method_1; + + public byte PressureLevel => Type != Grass ? LevelMax : Parent.GetPressureMax(Species, LevelMax); + public bool IsBugContest => Type == BugContest; + public bool IsSafariHGSS => Locations4.IsSafari(Location); } diff --git a/PKHeX.Core/Legality/Encounters/Templates/Gen4/EncounterStatic4.cs b/PKHeX.Core/Legality/Encounters/Templates/Gen4/EncounterStatic4.cs index 945727688..790a47aeb 100644 --- a/PKHeX.Core/Legality/Encounters/Templates/Gen4/EncounterStatic4.cs +++ b/PKHeX.Core/Legality/Encounters/Templates/Gen4/EncounterStatic4.cs @@ -9,10 +9,10 @@ namespace PKHeX.Core; public sealed record EncounterStatic4(GameVersion Version) : IEncounterable, IEncounterMatch, IEncounterConvertible, IMoveset, IGroundTypeTile, IFatefulEncounterReadOnly, IFixedGender, IRandomCorrelation, IFixedNature { - public int Generation => 4; + public byte Generation => 4; public EntityContext Context => EntityContext.Gen4; - int ILocation.Location => Location; - int ILocation.EggLocation => EggLocation; + ushort ILocation.Location => Location; + ushort ILocation.EggLocation => EggLocation; public bool IsShiny => false; public bool EggEncounter => EggLocation != 0; private bool Gift => FixedBall == Ball.Poke; @@ -52,26 +52,26 @@ public sealed record EncounterStatic4(GameVersion Version) public PK4 ConvertToPKM(ITrainerInfo tr, EncounterCriteria criteria) { int lang = (int)Language.GetSafeLanguage(Generation, (LanguageID)tr.Language); - var version = this.GetCompatibleVersion((GameVersion)tr.Game); + var version = this.GetCompatibleVersion(tr.Version); var pi = PersonalTable.HGSS[Species]; var pk = new PK4 { Species = Species, Form = Form, CurrentLevel = LevelMin, - OT_Friendship = pi.BaseFriendship, + OriginalTrainerFriendship = pi.BaseFriendship, - Met_Location = Location, - Met_Level = LevelMin, - Version = (byte)version, + MetLocation = Location, + MetLevel = LevelMin, + Version = version, GroundTile = GroundTile.GetIndex(), MetDate = EncounterDate.GetDateNDS(), Ball = (byte)(FixedBall != Ball.None ? FixedBall : Ball.Poke), FatefulEncounter = FatefulEncounter, Language = lang, - OT_Name = tr.OT, - OT_Gender = tr.Gender, + OriginalTrainerName = tr.OT, + OriginalTrainerGender = tr.Gender, ID32 = tr.ID32, Nickname = SpeciesName.GetSpeciesNameGeneration(Species, lang, Generation), }; @@ -79,9 +79,9 @@ public PK4 ConvertToPKM(ITrainerInfo tr, EncounterCriteria criteria) if (EggEncounter) { // Fake as hatched. - pk.Met_Location = version is GameVersion.HG or GameVersion.SS ? Locations.HatchLocationHGSS : Locations.HatchLocationDPPt; - pk.Met_Level = EggStateLegality.EggMetLevel34; - pk.Egg_Location = EggLocation; + pk.MetLocation = version is GameVersion.HG or GameVersion.SS ? Locations.HatchLocationHGSS : Locations.HatchLocationDPPt; + pk.MetLevel = EggStateLegality.EggMetLevel34; + pk.EggLocation = EggLocation; pk.EggMetDate = pk.MetDate; } else if (Species == (int)Core.Species.Giratina && Form == 1) @@ -110,8 +110,8 @@ private void SetPINGA(PK4 pk, EncounterCriteria criteria, PersonalInfo4 pi) return; } - int gender = criteria.GetGender(Gender, pi); - int nature = (int)criteria.GetNature(Nature); + var gender = criteria.GetGender(Gender, pi); + var nature = criteria.GetNature(Nature); int ability = criteria.GetAbilityFromNumber(Ability); if (Shiny == Shiny.Always) // Chain Shiny { @@ -122,7 +122,7 @@ private void SetPINGA(PK4 pk, EncounterCriteria criteria, PersonalInfo4 pi) PIDGenerator.SetRandomWildPID4(pk, nature, ability, gender, type); } - private static void SetChainShiny(PK4 pk, byte gr, int ability, int gender, int nature) + private static void SetChainShiny(PK4 pk, byte gr, int ability, byte gender, Nature nature) { pk.RefreshAbility(ability); pk.Gender = gender; @@ -131,7 +131,7 @@ private static void SetChainShiny(PK4 pk, byte gr, int ability, int gender, int while (true) { var pid = ClassicEraRNG.GetChainShinyPID(ref seed, id32); - if (pid % 25 != nature) + if ((Nature)(pid % 25) != nature) continue; if (EntityGender.GetFromPIDAndRatio(pid, gr) != gender) continue; @@ -175,7 +175,7 @@ private bool IsMatchLocation(PKM pk) if (pk is not G4PKM pk4) return true; - var met = pk4.Met_Location; + var met = pk4.MetLocation; if (EggEncounter) return true; if (!Roaming) @@ -194,31 +194,31 @@ private bool IsMatchEggLocation(PKM pk) if (!EggEncounter) { var expect = pk is PB8 ? Locations.Default8bNone : EggLocation; - return pk.Egg_Location == expect; + return pk.EggLocation == expect; } - var eggloc = pk.Egg_Location; + var eggLoc = pk.EggLocation; // Transferring 4->5 clears Pt/HG/SS location value and keeps Faraway Place if (pk is not G4PKM pk4) { - if (eggloc == Locations.LinkTrade4) + if (eggLoc == Locations.LinkTrade4) return true; var cmp = Locations.IsPtHGSSLocationEgg(EggLocation) ? Locations.Faraway4 : EggLocation; - return eggloc == cmp; + return eggLoc == cmp; } if (!pk4.IsEgg) // hatched - return eggloc == EggLocation || eggloc == Locations.LinkTrade4; + return eggLoc == EggLocation || eggLoc == Locations.LinkTrade4; // Unhatched: - if (eggloc != EggLocation) + if (eggLoc != EggLocation) return false; - if (pk4.Met_Location is not (0 or Locations.LinkTrade4)) + if (pk4.MetLocation is not (0 or Locations.LinkTrade4)) return false; return true; } - private static bool IsMatchLocationGrass(int location, int met) => location switch + private static bool IsMatchLocationGrass(ushort location, ushort met) => location switch { FirstS => IsMatchRoamerLocation(PermitGrassS, met, FirstS), FirstJ => IsMatchRoamerLocation(PermitGrassJ, met, FirstJ), @@ -226,7 +226,7 @@ private bool IsMatchEggLocation(PKM pk) _ => false, }; - private static bool IsMatchLocationWater(int location, int met) => location switch + private static bool IsMatchLocationWater(ushort location, ushort met) => location switch { FirstS => IsMatchRoamerLocation(PermitWaterS, met, FirstS), FirstJ => IsMatchRoamerLocation(PermitWaterJ, met, FirstJ), @@ -239,12 +239,12 @@ private bool IsMatchLevel(PKM pk, EvoCriteria evo) if (pk.Format != 4) // Met Level lost on PK4=>PK5 return Level <= evo.LevelMax; - return pk.Met_Level == (EggEncounter ? 0 : Level); + return pk.MetLevel == (EggEncounter ? 0 : Level); } private bool IsMatchPartial(PKM pk) => Gift && pk.Ball != (byte)FixedBall; - public static bool IsMatchRoamerLocation([ConstantExpected] ulong permit, int location, int first) + public static bool IsMatchRoamerLocation([ConstantExpected] ulong permit, ushort location, int first) { var value = location - first; if ((uint)value >= 64) @@ -252,7 +252,7 @@ public static bool IsMatchRoamerLocation([ConstantExpected] ulong permit, int lo return (permit & (1ul << value)) != 0; } - public static bool IsMatchRoamerLocation([ConstantExpected] uint permit, int location, int first) + public static bool IsMatchRoamerLocation([ConstantExpected] uint permit, ushort location, int first) { var value = location - first; if ((uint)value >= 32) diff --git a/PKHeX.Core/Legality/Encounters/Templates/Gen4/EncounterStatic4Pokewalker.cs b/PKHeX.Core/Legality/Encounters/Templates/Gen4/EncounterStatic4Pokewalker.cs index c732b7742..7ccd37f02 100644 --- a/PKHeX.Core/Legality/Encounters/Templates/Gen4/EncounterStatic4Pokewalker.cs +++ b/PKHeX.Core/Legality/Encounters/Templates/Gen4/EncounterStatic4Pokewalker.cs @@ -9,18 +9,18 @@ namespace PKHeX.Core; public sealed record EncounterStatic4Pokewalker(PokewalkerCourse4 Course) : IEncounterable, IEncounterMatch, IEncounterConvertible, IMoveset, IRandomCorrelation, IFixedGender { - public int Generation => 4; + public byte Generation => 4; public EntityContext Context => EntityContext.Gen4; public GameVersion Version => GameVersion.HGSS; - public int Location => Locations.PokeWalker4; + public ushort Location => Locations.PokeWalker4; public bool IsShiny => false; public bool EggEncounter => false; public Ball FixedBall => Ball.Poke; public AbilityPermission Ability => AbilityPermission.Any12; public Shiny Shiny => Shiny.Never; public byte Form => 0; - public int EggLocation => 0; + public ushort EggLocation => 0; public ushort Species { get; } public byte Level { get; } @@ -69,23 +69,23 @@ public static EncounterStatic4Pokewalker[] GetAll(ReadOnlySpan data) public PK4 ConvertToPKM(ITrainerInfo tr, EncounterCriteria criteria) { int lang = (int)Language.GetSafeLanguage(Generation, (LanguageID)tr.Language); - var version = this.GetCompatibleVersion((GameVersion)tr.Game); + var version = this.GetCompatibleVersion(tr.Version); var pi = PersonalTable.HGSS[Species]; var pk = new PK4 { Species = Species, CurrentLevel = LevelMin, - OT_Friendship = pi.BaseFriendship, + OriginalTrainerFriendship = pi.BaseFriendship, - Met_Location = Location, - Met_Level = LevelMin, - Version = (byte)version, + MetLocation = Location, + MetLevel = LevelMin, + Version = version, MetDate = EncounterDate.GetDateNDS(), Ball = (byte)FixedBall, Language = lang, - OT_Name = tr.OT, - OT_Gender = tr.Gender, + OriginalTrainerName = tr.OT, + OriginalTrainerGender = tr.Gender, ID32 = tr.ID32, Nickname = SpeciesName.GetSpeciesNameGeneration(Species, lang, Generation), }; @@ -102,7 +102,7 @@ public PK4 ConvertToPKM(ITrainerInfo tr, EncounterCriteria criteria) private void SetPINGA(PK4 pk, EncounterCriteria criteria, PersonalInfo4 pi) { - int gender = criteria.GetGender(Gender, pi); + var gender = criteria.GetGender(Gender, pi); var nature = (uint)criteria.GetNature(); var pid = pk.PID = PokewalkerRNG.GetPID(pk.TID16, pk.SID16, nature, pk.Gender = gender, pi.Gender); @@ -154,13 +154,13 @@ private bool IsMatchGender(PKM pk) private static bool IsMatchEggLocation(PKM pk) { var expect = pk is PB8 ? Locations.Default8bNone : 0; - return pk.Egg_Location == expect; + return pk.EggLocation == expect; } private bool IsMatchLocation(PKM pk) { if (pk.Format == 4) - return pk.Met_Location == Location; + return pk.MetLocation == Location; return true; // transfer location verified later } @@ -168,7 +168,7 @@ private bool IsMatchLevel(PKM pk, EvoCriteria evo) { if (pk.Format != 4) // Met Level lost on PK4=>PK5 return evo.LevelMax >= Level; - return pk.Met_Level == Level; + return pk.MetLevel == Level; } public EncounterMatchRating GetMatchRating(PKM pk) @@ -190,7 +190,7 @@ public bool IsCompatible(PIDType val, PKM pk) // Pokewalker can sometimes be confused with CuteCharm due to the PID creation routine. Double check if it is okay. if (val is PIDType.CuteCharm) - return MethodFinder.GetCuteCharmMatch(pk, pk.EncryptionConstant, out _) && MethodFinder.IsCuteCharm4Valid(this, pk); + return MethodFinder.IsCuteCharm(pk, pk.EncryptionConstant) && MethodFinder.IsCuteCharm4Valid(this, pk); return false; } diff --git a/PKHeX.Core/Legality/Encounters/Templates/Gen4/EncounterTrade4PID.cs b/PKHeX.Core/Legality/Encounters/Templates/Gen4/EncounterTrade4PID.cs index a8c5af162..f2e304758 100644 --- a/PKHeX.Core/Legality/Encounters/Templates/Gen4/EncounterTrade4PID.cs +++ b/PKHeX.Core/Legality/Encounters/Templates/Gen4/EncounterTrade4PID.cs @@ -8,13 +8,13 @@ namespace PKHeX.Core; public sealed record EncounterTrade4PID : IEncounterable, IEncounterMatch, IFixedTrainer, IFixedNickname, IEncounterConvertible, IContestStatsReadOnly, IMoveset, IFixedGender, IFixedNature { - public int Generation => 4; + public byte Generation => 4; public EntityContext Context => EntityContext.Gen4; public Shiny Shiny => Shiny.FixedValue; public bool IsFixedNickname => true; public GameVersion Version { get; } public bool EggEncounter => false; - public int EggLocation => 0; + public ushort EggLocation => 0; public Ball FixedBall => Ball.Poke; public bool IsShiny => false; public bool IsFixedTrainer => true; @@ -39,7 +39,7 @@ public sealed record EncounterTrade4PID public Moveset Moves { get; init; } public byte MetLocation { get; init; } - public int Location => MetLocation == default ? Locations.LinkTrade4NPC : MetLocation; + public ushort Location => MetLocation == default ? Locations.LinkTrade4NPC : MetLocation; /// /// Fixed value the encounter must have. @@ -50,23 +50,23 @@ public sealed record EncounterTrade4PID public string Name => _name; public string LongName => _name; - public byte CNT_Cool { get; private init; } - public byte CNT_Beauty { get; private init; } - public byte CNT_Cute { get; private init; } - public byte CNT_Smart { get; private init; } - public byte CNT_Tough { get; private init; } - public byte CNT_Sheen => 0; + public byte ContestCool { get; private init; } + public byte ContestBeauty { get; private init; } + public byte ContestCute { get; private init; } + public byte ContestSmart { get; private init; } + public byte ContestTough { get; private init; } + public byte ContestSheen => 0; public byte Contest { init { - CNT_Cool = value; - CNT_Beauty = value; - CNT_Cute = value; - CNT_Smart = value; - CNT_Tough = value; - //CNT_Sheen = value; + ContestCool = value; + ContestBeauty = value; + ContestCute = value; + ContestSmart = value; + ContestTough = value; + //ContestSheen = value; } } @@ -89,7 +89,7 @@ public EncounterTrade4PID(ReadOnlySpan names, byte index, GameVersion public PK4 ConvertToPKM(ITrainerInfo tr, EncounterCriteria criteria) { - var version = this.GetCompatibleVersion((GameVersion)tr.Game); + var version = this.GetCompatibleVersion(tr.Version); int lang = (int)Language.GetSafeLanguage(Generation, (LanguageID)tr.Language, version); var pi = PersonalTable.DP[Species]; var pk = new PK4 @@ -97,26 +97,26 @@ public PK4 ConvertToPKM(ITrainerInfo tr, EncounterCriteria criteria) PID = PID, Species = Species, CurrentLevel = Level, - Met_Location = Location, - Met_Level = Level, + MetLocation = Location, + MetLevel = Level, MetDate = EncounterDate.GetDateNDS(), Gender = Gender, - Nature = (byte)Nature, + Nature = Nature, Ball = (byte)FixedBall, ID32 = ID32, - Version = (byte)version, + Version = version, Language = GetReceivedLanguage(lang, version), - OT_Gender = OTGender, - OT_Name = TrainerNames[lang], + OriginalTrainerGender = OTGender, + OriginalTrainerName = TrainerNames[lang], - OT_Friendship = pi.BaseFriendship, + OriginalTrainerFriendship = pi.BaseFriendship, IsNicknamed = true, Nickname = Nicknames[lang], - HT_Name = tr.OT, - HT_Gender = tr.Gender, + HandlingTrainerName = tr.OT, + HandlingTrainerGender = tr.Gender, }; if (Moves.HasMoves) @@ -178,7 +178,7 @@ public bool IsMatchExact(PKM pk, EvoCriteria evo) return false; if (evo.Form != Form && !FormInfo.IsFormChangeable(Species, Form, pk.Form, Context, pk.Context)) return false; - if (pk.OT_Gender != OTGender) + if (pk.OriginalTrainerGender != OTGender) return false; if (!IsMatchEggLocation(pk)) return false; @@ -193,7 +193,7 @@ private bool IsMatchLocation(PKM pk) if (pk is not G4PKM pk4) return true; - var met = pk4.Met_Location; + var met = pk4.MetLocation; return met == Location; } @@ -203,15 +203,15 @@ private bool IsMatchLevel(PKM pk, EvoCriteria evo) return evo.LevelMax >= Level; if (MetLocation != default) - return pk.Met_Level == Level; - return pk.Met_Level >= LevelMin; + return pk.MetLevel == Level; + return pk.MetLevel >= LevelMin; } private bool IsMatchNatureGenderShiny(PKM pk) { if (pk.EncryptionConstant != PID) return false; - if ((int)Nature != pk.Nature) + if (Nature != pk.Nature) return false; return true; } @@ -221,7 +221,7 @@ private bool IsMatchEggLocation(PKM pk) var expect = EggLocation; if (pk is PB8) expect = Locations.Default8bNone; - return pk.Egg_Location == expect; + return pk.EggLocation == expect; } public EncounterMatchRating GetMatchRating(PKM pk) => EncounterMatchRating.Match; @@ -239,11 +239,11 @@ public int DetectOriginalLanguage(PKM pk) return DetectTradeLanguageG4MeisterMagikarp(pk, lang); } // D/P English origin are Japanese lang. Can't have LanguageID 2 - if (lang != 1 || pk.Version is not ((int)GameVersion.D or (int)GameVersion.P)) + if (lang != 1 || pk.Version is not (GameVersion.D or GameVersion.P)) return lang; // Since two locales (JPN/ENG) can have the same LanguageID, check which we should be validating with. - ReadOnlySpan ot = pk.OT_Name; + ReadOnlySpan ot = pk.OriginalTrainerName; var expect = TrainerNames[1]; var match = ot.SequenceEqual(expect); if (!match) @@ -257,7 +257,7 @@ private int DetectTradeLanguageG4MeisterMagikarp(PKM pk,int currentLanguageID) return (int)LanguageID.German; // All have German, regardless of origin version. - var lang = DetectTradeLanguage(pk.OT_Name, currentLanguageID); + var lang = DetectTradeLanguage(pk.OriginalTrainerName, currentLanguageID); if (lang == (int)LanguageID.English) // possible collision with FR/ES/DE. Check nickname return pk.Nickname == Nicknames[(int)LanguageID.French] ? (int)LanguageID.French : (int)LanguageID.Spanish; // Spanish is same as English @@ -270,7 +270,7 @@ private int DetectTradeLanguageG4SurgePikachu(PKM pk, int currentLanguageID) return (int)LanguageID.English; // All have English, regardless of origin version. - var lang = DetectTradeLanguage(pk.OT_Name, currentLanguageID); + var lang = DetectTradeLanguage(pk.OriginalTrainerName, currentLanguageID); if (lang == 2) // possible collision with ES/IT. Check nickname return pk.Nickname == Nicknames[(int)LanguageID.Italian] ? (int)LanguageID.Italian : (int)LanguageID.Spanish; @@ -292,6 +292,6 @@ private int DetectTradeLanguage(ReadOnlySpan OT, int currentLanguageID) public bool IsIncorrectEnglish(PKM pk) { // Localized English forgot to change the Language ID values. - return pk is { Language: (int)LanguageID.English, Version: (int)GameVersion.D or (int)GameVersion.P }; + return pk is { Language: (int)LanguageID.English, Version: GameVersion.D or GameVersion.P }; } } diff --git a/PKHeX.Core/Legality/Encounters/Templates/Gen4/EncounterTrade4RanchGift.cs b/PKHeX.Core/Legality/Encounters/Templates/Gen4/EncounterTrade4RanchGift.cs index 5cc443fdd..dccfff2dc 100644 --- a/PKHeX.Core/Legality/Encounters/Templates/Gen4/EncounterTrade4RanchGift.cs +++ b/PKHeX.Core/Legality/Encounters/Templates/Gen4/EncounterTrade4RanchGift.cs @@ -8,7 +8,7 @@ namespace PKHeX.Core; public sealed record EncounterTrade4RanchGift : IEncounterable, IEncounterMatch, IEncounterConvertible, IFatefulEncounterReadOnly, IFixedTrainer, IMoveset, IFixedGender, IFixedNature { - public int Generation => 4; + public byte Generation => 4; public EntityContext Context => EntityContext.Gen4; /// @@ -18,12 +18,11 @@ public sealed record EncounterTrade4RanchGift public Nature Nature => (Nature)(PID % 25); - public int MetLocation { private get; init; } - public int Location => MetLocation; + public ushort Location { get; init; } public Shiny Shiny => FatefulEncounter ? Shiny.Never : Shiny.FixedValue; public GameVersion Version { get; } public bool EggEncounter => false; - public int EggLocation { get; init; } + public ushort EggLocation { get; init; } public Ball FixedBall { get; init; } = Ball.Poke; public bool IsShiny => false; @@ -64,7 +63,7 @@ public EncounterTrade4RanchGift(ushort species, byte level) Species = species; Level = level; FatefulEncounter = true; - MetLocation = 3000; + Location = 3000; } #region Generating @@ -76,7 +75,7 @@ public EncounterTrade4RanchGift(ushort species, byte level) public PK4 ConvertToPKM(ITrainerInfo tr, EncounterCriteria criteria) { - var version = this.GetCompatibleVersion((GameVersion)tr.Game); + var version = this.GetCompatibleVersion(tr.Version); int lang = (int)Language.GetSafeLanguage(Generation, (LanguageID)tr.Language, version); var actualLevel = CurrentLevel != default ? CurrentLevel : Level; var pi = PersonalTable.DP[Species]; @@ -85,29 +84,29 @@ public PK4 ConvertToPKM(ITrainerInfo tr, EncounterCriteria criteria) Species = Species, Form = Form, CurrentLevel = actualLevel, - Met_Location = Location, - Met_Level = Level, + MetLocation = Location, + MetLevel = Level, MetDate = EncounterDate.GetDateNDS(), Ball = (byte)FixedBall, FatefulEncounter = FatefulEncounter, ID32 = ID32, - Version = (byte)version, + Version = version, Language = lang, - OT_Gender = OTGender, - OT_Name = TrainerNames[lang], + OriginalTrainerGender = OTGender, + OriginalTrainerName = TrainerNames[lang], - OT_Friendship = pi.BaseFriendship, + OriginalTrainerFriendship = pi.BaseFriendship, Nickname = SpeciesName.GetSpeciesNameGeneration(Species, lang, Generation), - HT_Name = tr.OT, - HT_Gender = tr.Gender, + HandlingTrainerName = tr.OT, + HandlingTrainerGender = tr.Gender, }; if (EggLocation != 0) { - pk.Egg_Location = EggLocation; + pk.EggLocation = EggLocation; pk.EggMetDate = pk.MetDate; } @@ -125,7 +124,7 @@ private void SetPINGA(PK4 pk, EncounterCriteria criteria) { var pid = FatefulEncounter ? Util.Rand32() : PID; pk.PID = pid; - pk.Nature = (int)(pid % 25); + pk.Nature = (Nature)(pid % 25); pk.Gender = Gender; pk.RefreshAbility((int)(pid % 2)); criteria.SetRandomIVs(pk); @@ -149,7 +148,7 @@ public bool IsMatchExact(PKM pk, EvoCriteria evo) return false; if (evo.Form != Form && !FormInfo.IsFormChangeable(Species, Form, pk.Form, Context, pk.Context)) return false; - if (pk.OT_Gender != OTGender) + if (pk.OriginalTrainerGender != OTGender) return false; if (!IsMatchEggLocation(pk)) return false; @@ -164,7 +163,7 @@ private bool IsMatchLocation(PKM pk) if (pk is not G4PKM pk4) return true; - var met = pk4.Met_Location; + var met = pk4.MetLocation; return met == Location; } @@ -173,9 +172,9 @@ private bool IsMatchLevel(PKM pk, EvoCriteria evo) if (pk.Format != 4) // Met Level lost on PK4=>PK5 return evo.LevelMax >= Level; - if (MetLocation != default) - return pk.Met_Level == Level; - return pk.Met_Level >= LevelMin; + if (Location != default) + return pk.MetLevel == Level; + return pk.MetLevel >= LevelMin; } private bool IsMatchNatureGenderShiny(PKM pk) @@ -192,7 +191,7 @@ private bool IsMatchEggLocation(PKM pk) var expect = EggLocation; if (pk is PB8) expect = Locations.Default8bNone; - return pk.Egg_Location == expect; + return pk.EggLocation == expect; } public EncounterMatchRating GetMatchRating(PKM pk) => EncounterMatchRating.Match; diff --git a/PKHeX.Core/Legality/Encounters/Templates/Gen4/IGroundTypeTile.cs b/PKHeX.Core/Legality/Encounters/Templates/Gen4/IGroundTypeTile.cs index 784834b75..60f6ac3ab 100644 --- a/PKHeX.Core/Legality/Encounters/Templates/Gen4/IGroundTypeTile.cs +++ b/PKHeX.Core/Legality/Encounters/Templates/Gen4/IGroundTypeTile.cs @@ -18,5 +18,5 @@ public interface IGroundTypeTile /// Gets if the resulting will still have a value depending on the current . /// /// Generation 7 no longer stores this value. - bool HasGroundTile(int format) => format is (4 or 5 or 6); + bool HasGroundTile(byte format) => format is (4 or 5 or 6); } diff --git a/PKHeX.Core/Legality/Encounters/Templates/Gen5/EncounterArea5.cs b/PKHeX.Core/Legality/Encounters/Templates/Gen5/EncounterArea5.cs index 8e884d3af..0ea70654a 100644 --- a/PKHeX.Core/Legality/Encounters/Templates/Gen5/EncounterArea5.cs +++ b/PKHeX.Core/Legality/Encounters/Templates/Gen5/EncounterArea5.cs @@ -1,4 +1,5 @@ using System; +using System.Diagnostics.CodeAnalysis; using static System.Buffers.Binary.BinaryPrimitives; namespace PKHeX.Core; @@ -12,11 +13,11 @@ public sealed record EncounterArea5 : IEncounterArea, IAreaLocat public GameVersion Version { get; } public readonly ushort Location; - public readonly SlotType Type; + public readonly SlotType5 Type; - public bool IsMatchLocation(int location) => Location == location; + public bool IsMatchLocation(ushort location) => Location == location; - public static EncounterArea5[] GetAreas(BinLinkerAccessor input, GameVersion game) + public static EncounterArea5[] GetAreas(BinLinkerAccessor input, [ConstantExpected] GameVersion game) { var result = new EncounterArea5[input.Length]; for (int i = 0; i < result.Length; i++) @@ -24,23 +25,23 @@ public static EncounterArea5[] GetAreas(BinLinkerAccessor input, GameVersion gam return result; } - private EncounterArea5(ReadOnlySpan data, GameVersion game) + private EncounterArea5(ReadOnlySpan data, [ConstantExpected] GameVersion game) { Location = ReadUInt16LittleEndian(data); - Type = (SlotType)data[2]; + Type = (SlotType5)data[2]; Version = game; - Slots = ReadSlots(data); + Slots = ReadSlots(data[4..]); } private EncounterSlot5[] ReadSlots(ReadOnlySpan data) { const int size = 4; - int count = (data.Length - 4) / size; + int count = data.Length / size; var slots = new EncounterSlot5[count]; for (int i = 0; i < slots.Length; i++) { - int offset = 4 + (size * i); + int offset = size * i; var entry = data.Slice(offset, size); slots[i] = ReadSlot(entry); } @@ -58,3 +59,14 @@ private EncounterSlot5 ReadSlot(ReadOnlySpan entry) return new EncounterSlot5(this, species, form, min, max); } } + +public enum SlotType5 : byte +{ + Standard = 0, + Grass = 1, + Surf = 2, + Super_Rod = 3, + + Swarm = 4, + HiddenGrotto = 5, +} diff --git a/PKHeX.Core/Legality/Encounters/Templates/Gen5/EncounterSlot5.cs b/PKHeX.Core/Legality/Encounters/Templates/Gen5/EncounterSlot5.cs index 42e4e58bd..6cb24b167 100644 --- a/PKHeX.Core/Legality/Encounters/Templates/Gen5/EncounterSlot5.cs +++ b/PKHeX.Core/Legality/Encounters/Templates/Gen5/EncounterSlot5.cs @@ -6,23 +6,23 @@ namespace PKHeX.Core; public sealed record EncounterSlot5(EncounterArea5 Parent, ushort Species, byte Form, byte LevelMin, byte LevelMax) : IEncounterable, IEncounterMatch, IEncounterConvertible { - public int Generation => 5; + public byte Generation => 5; public EntityContext Context => EntityContext.Gen5; public bool EggEncounter => false; public Ball FixedBall => Ball.None; public Shiny Shiny => IsHiddenGrotto ? Shiny.Never : Shiny.Random; public bool IsShiny => false; - public int EggLocation => 0; + public ushort EggLocation => 0; public string Name => $"Wild Encounter ({Version})"; public string LongName => $"{Name} {Type.ToString().Replace('_', ' ')}"; public GameVersion Version => Parent.Version; - public int Location => Parent.Location; - public SlotType Type => Parent.Type; + public ushort Location => Parent.Location; + public SlotType5 Type => Parent.Type; - public bool IsHiddenGrotto => Type == SlotType.HiddenGrotto; + public bool IsHiddenGrotto => Type == SlotType5.HiddenGrotto; - private HiddenAbilityPermission IsHiddenAbilitySlot() => Type == SlotType.HiddenGrotto ? HiddenAbilityPermission.Always : HiddenAbilityPermission.Never; + private HiddenAbilityPermission IsHiddenAbilitySlot() => IsHiddenGrotto ? HiddenAbilityPermission.Always : HiddenAbilityPermission.Never; public AbilityPermission Ability => IsHiddenAbilitySlot() switch { @@ -52,16 +52,16 @@ public PK5 ConvertToPKM(ITrainerInfo tr, EncounterCriteria criteria) Species = Species, Form = GetWildForm(Form), CurrentLevel = LevelMin, - OT_Friendship = pi.BaseFriendship, - Met_Location = Location, - Met_Level = LevelMin, - Version = (byte)Version, + OriginalTrainerFriendship = pi.BaseFriendship, + MetLocation = Location, + MetLevel = LevelMin, + Version = Version, Ball = (byte)Ball.Poke, MetDate = EncounterDate.GetDateNDS(), Language = lang, - OT_Name = tr.OT, - OT_Gender = tr.Gender, + OriginalTrainerName = tr.OT, + OriginalTrainerGender = tr.Gender, ID32 = tr.ID32, Nickname = SpeciesName.GetSpeciesNameGeneration(Species, lang, Generation), }; @@ -82,8 +82,8 @@ private byte GetWildForm(byte form) private void SetPINGA(PK5 pk, EncounterCriteria criteria, PersonalInfo5B2W2 pi) { - int gender = criteria.GetGender(pi); - int nature = (int)criteria.GetNature(); + var gender = criteria.GetGender(pi); + var nature = criteria.GetNature(); var ability = criteria.GetAbilityFromNumber(Ability); PIDGenerator.SetRandomWildPID5(pk, nature, ability, gender); criteria.SetRandomIVs(pk); @@ -94,7 +94,7 @@ private void SetPINGA(PK5 pk, EncounterCriteria criteria, PersonalInfo5B2W2 pi) public bool IsMatchExact(PKM pk, EvoCriteria evo) { - if (!this.IsLevelWithinRange(pk.Met_Level)) + if (!this.IsLevelWithinRange(pk.MetLevel)) return false; // Deerling and Sawsbuck can change forms when seasons change, thus can be any of the [0,3] form values. diff --git a/PKHeX.Core/Legality/Encounters/Templates/Gen5/EncounterStatic5.cs b/PKHeX.Core/Legality/Encounters/Templates/Gen5/EncounterStatic5.cs index 5343f6dc8..1ab404e7a 100644 --- a/PKHeX.Core/Legality/Encounters/Templates/Gen5/EncounterStatic5.cs +++ b/PKHeX.Core/Legality/Encounters/Templates/Gen5/EncounterStatic5.cs @@ -6,11 +6,11 @@ namespace PKHeX.Core; public sealed record EncounterStatic5(GameVersion Version) : IEncounterable, IEncounterMatch, IEncounterConvertible, IFixedGender { - public int Generation => 5; + public byte Generation => 5; public EntityContext Context => EntityContext.Gen5; public bool Roaming { get; init; } - int ILocation.Location => Location; - int ILocation.EggLocation => EggLocation; + ushort ILocation.Location => Location; + ushort ILocation.EggLocation => EggLocation; public bool IsShiny => false; public bool EggEncounter => EggLocation != 0; private bool Gift => FixedBall == Ball.Poke; @@ -40,7 +40,7 @@ public sealed record EncounterStatic5(GameVersion Version) public PK5 ConvertToPKM(ITrainerInfo tr, EncounterCriteria criteria) { - var version = this.GetCompatibleVersion((GameVersion)tr.Game); + var version = this.GetCompatibleVersion(tr.Version); int lang = (int)Language.GetSafeLanguage(Generation, (LanguageID)tr.Language, version); var pi = PersonalTable.B2W2[Species]; var pk = new PK5 @@ -48,18 +48,18 @@ public PK5 ConvertToPKM(ITrainerInfo tr, EncounterCriteria criteria) Species = Species, Form = Form, CurrentLevel = LevelMin, - Met_Location = Location, - Met_Level = LevelMin, + MetLocation = Location, + MetLevel = LevelMin, MetDate = EncounterDate.GetDateNDS(), Ball = (byte)(FixedBall is Ball.None ? Ball.Poke : FixedBall), ID32 = tr.ID32, - Version = (byte)version, + Version = version, Language = lang, - OT_Gender = tr.Gender, - OT_Name = tr.OT, + OriginalTrainerGender = tr.Gender, + OriginalTrainerName = tr.OT, - OT_Friendship = pi.BaseFriendship, + OriginalTrainerFriendship = pi.BaseFriendship, Nickname = SpeciesName.GetSpeciesNameGeneration(Species, lang, Generation), }; @@ -67,9 +67,9 @@ public PK5 ConvertToPKM(ITrainerInfo tr, EncounterCriteria criteria) if (EggEncounter) { // Fake as hatched. - pk.Met_Location = Locations.HatchLocation5; - pk.Met_Level = EggStateLegality.EggMetLevel; - pk.Egg_Location = EggLocation; + pk.MetLocation = Locations.HatchLocation5; + pk.MetLevel = EggStateLegality.EggMetLevel; + pk.EggLocation = EggLocation; pk.EggMetDate = pk.MetDate; } @@ -83,8 +83,8 @@ public PK5 ConvertToPKM(ITrainerInfo tr, EncounterCriteria criteria) private void SetPINGA(PK5 pk, EncounterCriteria criteria, PersonalInfo5B2W2 pi) { - int gender = criteria.GetGender(Gender, pi); - int nature = (int)criteria.GetNature(); + var gender = criteria.GetGender(Gender, pi); + var nature = criteria.GetNature(); var ability = criteria.GetAbilityFromNumber(Ability); var type = Shiny == Shiny.Always ? PIDType.G5MGShiny : PIDType.None; PIDGenerator.SetRandomWildPID5(pk, nature, ability, gender, type); @@ -137,7 +137,7 @@ public bool IsMatchExact(PKM pk, EvoCriteria evo) return false; if (!IsMatchLocation(pk)) return false; - if (pk.Met_Level != Level) + if (pk.MetLevel != Level) return false; if (Gender != FixedGenderUtil.GenderRandom && pk.Gender != Gender) return false; @@ -160,7 +160,7 @@ private bool IsMatchPartial(PKM pk) private bool IsMatchLocation(PKM pk) { - var met = pk.Met_Location; + var met = pk.MetLocation; if (EggEncounter) return true; if (!Roaming) @@ -173,17 +173,17 @@ private bool IsMatchEggLocation(PKM pk) if (!EggEncounter) { var expect = pk is PB8 ? Locations.Default8bNone : EggLocation; - return pk.Egg_Location == expect; + return pk.EggLocation == expect; } - var eggloc = pk.Egg_Location; + var eggLoc = pk.EggLocation; if (!pk.IsEgg) // hatched - return eggloc == EggLocation || eggloc == Locations.LinkTrade5; + return eggLoc == EggLocation || eggLoc == Locations.LinkTrade5; // Unhatched: - if (eggloc != EggLocation) + if (eggLoc != EggLocation) return false; - if (pk.Met_Location is not (0 or Locations.LinkTrade5)) + if (pk.MetLocation is not (0 or Locations.LinkTrade5)) return false; return true; } @@ -193,7 +193,7 @@ private bool IsMatchEggLocation(PKM pk) // 17,18,29, // Route 4, 5, 16 Daytime // 19,20,21, // Route 6, 7, 8 Evening // 22,23,24, // Route 9, 10, 11 Night former half - private static bool IsRoamerMet(int location) + private static bool IsRoamerMet(ushort location) { if ((uint)location >= 32) return false; diff --git a/PKHeX.Core/Legality/Encounters/Templates/Gen5/EncounterStatic5Entree.cs b/PKHeX.Core/Legality/Encounters/Templates/Gen5/EncounterStatic5Entree.cs index 3e8561afe..30b489a3d 100644 --- a/PKHeX.Core/Legality/Encounters/Templates/Gen5/EncounterStatic5Entree.cs +++ b/PKHeX.Core/Legality/Encounters/Templates/Gen5/EncounterStatic5Entree.cs @@ -6,14 +6,14 @@ namespace PKHeX.Core; public sealed record EncounterStatic5Entree(GameVersion Version, ushort Species, byte Level, byte Form, byte Gender, AbilityPermission Ability) : IEncounterable, IEncounterMatch, IEncounterConvertible, IMoveset, IFixedGender { - public int Generation => 5; + public byte Generation => 5; public EntityContext Context => EntityContext.Gen5; public Ball FixedBall => Ball.None; public Shiny Shiny => Shiny.Never; public bool IsShiny => false; public bool EggEncounter => false; - public int EggLocation => 0; - public int Location => 075; + public ushort EggLocation => 0; + public ushort Location => 075; public string Name => $"Entree Forest Encounter ({Version})"; public string LongName => Name; public byte LevelMin => Level; @@ -32,7 +32,7 @@ public EncounterStatic5Entree(GameVersion version, ushort species, byte level, b public PK5 ConvertToPKM(ITrainerInfo tr, EncounterCriteria criteria) { - var version = this.GetCompatibleVersion((GameVersion)tr.Game); + var version = this.GetCompatibleVersion(tr.Version); int lang = (int)Language.GetSafeLanguage(Generation, (LanguageID)tr.Language, version); var pi = PersonalTable.B2W2[Species]; var pk = new PK5 @@ -40,18 +40,18 @@ public PK5 ConvertToPKM(ITrainerInfo tr, EncounterCriteria criteria) Species = Species, Form = Form, CurrentLevel = Level, - Met_Location = Location, - Met_Level = Level, + MetLocation = Location, + MetLevel = Level, MetDate = EncounterDate.GetDateNDS(), Ball = (byte)Ball.Dream, ID32 = tr.ID32, - Version = (byte)version, + Version = version, Language = lang, - OT_Gender = tr.Gender, - OT_Name = tr.OT, + OriginalTrainerGender = tr.Gender, + OriginalTrainerName = tr.OT, - OT_Friendship = pi.BaseFriendship, + OriginalTrainerFriendship = pi.BaseFriendship, Nickname = SpeciesName.GetSpeciesNameGeneration(Species, lang, Generation), }; @@ -69,8 +69,8 @@ public PK5 ConvertToPKM(ITrainerInfo tr, EncounterCriteria criteria) private void SetPINGA(PK5 pk, EncounterCriteria criteria, PersonalInfo5B2W2 pi) { - int gender = criteria.GetGender(Gender, pi); - int nature = (int)criteria.GetNature(); + var gender = criteria.GetGender(Gender, pi); + var nature = criteria.GetNature(); var ability = criteria.GetAbilityFromNumber(Ability); PIDGenerator.SetRandomWildPID5(pk, nature, ability, gender); if (pk.IsShiny) @@ -86,9 +86,9 @@ public bool IsMatchExact(PKM pk, EvoCriteria evo) { if (!IsMatchEggLocation(pk)) return false; - if (pk.Met_Location != Location) + if (pk.MetLocation != Location) return false; - if (pk.Met_Level != Level) + if (pk.MetLevel != Level) return false; if (Gender != FixedGenderUtil.GenderRandom && pk.Gender != Gender) return true; @@ -100,7 +100,7 @@ public bool IsMatchExact(PKM pk, EvoCriteria evo) private bool IsMatchEggLocation(PKM pk) { var expect = pk is PB8 ? Locations.Default8bNone : EggLocation; - return pk.Egg_Location == expect; + return pk.EggLocation == expect; } public EncounterMatchRating GetMatchRating(PKM pk) => EncounterMatchRating.Match; diff --git a/PKHeX.Core/Legality/Encounters/Templates/Gen5/EncounterStatic5N.cs b/PKHeX.Core/Legality/Encounters/Templates/Gen5/EncounterStatic5N.cs index ab1149b1b..02edb2a56 100644 --- a/PKHeX.Core/Legality/Encounters/Templates/Gen5/EncounterStatic5N.cs +++ b/PKHeX.Core/Legality/Encounters/Templates/Gen5/EncounterStatic5N.cs @@ -8,7 +8,7 @@ namespace PKHeX.Core; public sealed record EncounterStatic5N(uint PID) : IEncounterable, IEncounterMatch, IEncounterConvertible, IFixedTrainer, IFixedNature { - public int Generation => 5; + public byte Generation => 5; public EntityContext Context => EntityContext.Gen5; public GameVersion Version => GameVersion.B2W2; public const bool NSparkle = true; @@ -17,11 +17,11 @@ public sealed record EncounterStatic5N(uint PID) private const byte IV = 30; public byte Form => 0; - int ILocation.Location => Location; + ushort ILocation.Location => Location; public bool IsShiny => false; public Shiny Shiny => Shiny.FixedValue; public bool EggEncounter => false; - public int EggLocation => 0; + public ushort EggLocation => 0; public Ball FixedBall => Species == (int)Core.Species.Zorua ? Ball.Poke : Ball.None; // Zorua can't be captured; others can. public required ushort Species { get; init; } @@ -43,22 +43,22 @@ public sealed record EncounterStatic5N(uint PID) public PK5 ConvertToPKM(ITrainerInfo tr, EncounterCriteria criteria) { - var version = this.GetCompatibleVersion((GameVersion)tr.Game); + var version = this.GetCompatibleVersion(tr.Version); int lang = (int)Language.GetSafeLanguage(Generation, (LanguageID)tr.Language, version); var pi = PersonalTable.B2W2[Species]; var pk = new PK5 { Species = Species, CurrentLevel = LevelMin, - Met_Location = Location, - Met_Level = LevelMin, + MetLocation = Location, + MetLevel = LevelMin, MetDate = EncounterDate.GetDateNDS(), Ball = (byte)(FixedBall != Ball.None ? FixedBall : Ball.Poke), - Version = (byte)version, + Version = version, Language = lang, - OT_Friendship = pi.BaseFriendship, + OriginalTrainerFriendship = pi.BaseFriendship, Nickname = SpeciesName.GetSpeciesNameGeneration(Species, lang, Generation), IV_HP = IV, @@ -69,12 +69,12 @@ public PK5 ConvertToPKM(ITrainerInfo tr, EncounterCriteria criteria) IV_SPE = IV, NSparkle = NSparkle, - OT_Name = GetOT(lang), - OT_Gender = 0, + OriginalTrainerName = GetOT(lang), + OriginalTrainerGender = 0, ID32 = ID32, PID = PID, - Nature = (byte)Nature, - Gender = pi.Genderless ? 2 : 0, + Nature = Nature, + Gender = pi.Genderless ? (byte)2 : default, Ability = Ability switch { AbilityPermission.OnlyFirst => pi.Ability1, @@ -101,16 +101,16 @@ public bool IsMatchExact(PKM pk, EvoCriteria evo) return false; if (!IsMatchEggLocation(pk)) return false; - if (pk.Met_Location != Location) + if (pk.MetLocation != Location) return false; - if (pk.Met_Level != Level) + if (pk.MetLevel != Level) return false; if (Form != evo.Form && !FormInfo.IsFormChangeable(Species, Form, pk.Form, Context, pk.Context)) return false; var pi = PersonalTable.B2W2.GetFormEntry(Species, Form); if (pk.Gender != (pi.Genderless ? 2 : 0)) return false; - if (pk.OT_Gender != 0) + if (pk.OriginalTrainerGender != 0) return false; if (pk is not { IV_HP: IV, IV_ATK: IV, IV_DEF: IV, IV_SPA: IV, IV_SPD: IV, IV_SPE: IV }) return false; @@ -122,7 +122,7 @@ public bool IsMatchExact(PKM pk, EvoCriteria evo) private bool IsMatchEggLocation(PKM pk) { var expect = pk is PB8 ? Locations.Default8bNone : EggLocation; - return pk.Egg_Location == expect; + return pk.EggLocation == expect; } private static string GetOT(int lang) => lang == (int)LanguageID.Japanese ? "N" : "N"; diff --git a/PKHeX.Core/Legality/Encounters/Templates/Gen5/EncounterStatic5Radar.cs b/PKHeX.Core/Legality/Encounters/Templates/Gen5/EncounterStatic5Radar.cs index f05199b4f..9728a5ec9 100644 --- a/PKHeX.Core/Legality/Encounters/Templates/Gen5/EncounterStatic5Radar.cs +++ b/PKHeX.Core/Legality/Encounters/Templates/Gen5/EncounterStatic5Radar.cs @@ -6,15 +6,15 @@ namespace PKHeX.Core; public sealed record EncounterStatic5Radar(ushort Species, byte Form, AbilityPermission Ability = AbilityPermission.OnlyHidden) : IEncounterable, IEncounterMatch, IEncounterConvertible { - public int Generation => 5; + public byte Generation => 5; public EntityContext Context => EntityContext.Gen5; public GameVersion Version => GameVersion.B2W2; - public int Location => 30015; + public ushort Location => 30015; public Ball FixedBall => Ball.Dream; public bool IsShiny => false; public Shiny Shiny => Shiny.Never; public bool EggEncounter => false; - public int EggLocation => 0; + public ushort EggLocation => 0; public byte LevelMin => 5; public byte LevelMax => 40; public string Name => "Dream Radar Encounter"; @@ -28,7 +28,7 @@ public sealed record EncounterStatic5Radar(ushort Species, byte Form, AbilityPer public PK5 ConvertToPKM(ITrainerInfo tr, EncounterCriteria criteria) { - var version = this.GetCompatibleVersion((GameVersion)tr.Game); + var version = this.GetCompatibleVersion(tr.Version); int lang = (int)Language.GetSafeLanguage(Generation, (LanguageID)tr.Language, version); var pi = PersonalTable.B2W2[Species]; var pk = new PK5 @@ -36,18 +36,18 @@ public PK5 ConvertToPKM(ITrainerInfo tr, EncounterCriteria criteria) Species = Species, Form = Form, CurrentLevel = LevelMin, - Met_Location = Location, - Met_Level = LevelMin, + MetLocation = Location, + MetLevel = LevelMin, MetDate = EncounterDate.GetDateNDS(), Ball = (byte)FixedBall, ID32 = tr.ID32, - Version = (byte)version, + Version = version, Language = lang, - OT_Gender = tr.Gender, - OT_Name = tr.OT, + OriginalTrainerGender = tr.Gender, + OriginalTrainerName = tr.OT, - OT_Friendship = pi.BaseFriendship, + OriginalTrainerFriendship = pi.BaseFriendship, Nickname = SpeciesName.GetSpeciesNameGeneration(Species, lang, Generation), }; @@ -62,8 +62,8 @@ public PK5 ConvertToPKM(ITrainerInfo tr, EncounterCriteria criteria) private void SetPINGA(PK5 pk, EncounterCriteria criteria, PersonalInfo5B2W2 pi) { - int gender = criteria.GetGender(pi); - int nature = (int)criteria.GetNature(); + var gender = criteria.GetGender(pi); + var nature = criteria.GetNature(); var ability = criteria.GetAbilityFromNumber(Ability); PIDGenerator.SetRandomWildPID5(pk, nature, ability, gender); if (pk.IsShiny) @@ -79,26 +79,26 @@ public bool IsMatchExact(PKM pk, EvoCriteria evo) { if (!IsMatchEggLocation(pk)) return false; - if (pk.Met_Location != Location) + if (pk.MetLocation != Location) return false; - if (!IsMatchLevel(pk.Met_Level)) + if (!IsMatchLevel(pk.MetLevel)) return false; if (Form != evo.Form && !FormInfo.IsFormChangeable(Species, Form, pk.Form, Context, pk.Context)) return false; return true; } - private static bool IsMatchLevel(int met) + private static bool IsMatchLevel(int metLevel) { // Level from 5->40 depends on the number of badges - if (met % 5 != 0) + if (metLevel % 5 != 0) return false; // must be a multiple of 5 - return (uint)(met - 5) <= 35; // 5 <= x <= 40 + return (uint)(metLevel - 5) <= 35; // 5 <= x <= 40 } private bool IsMatchEggLocation(PKM pk) { var expect = pk is PB8 ? Locations.Default8bNone : EggLocation; - return pk.Egg_Location == expect; + return pk.EggLocation == expect; } public EncounterMatchRating GetMatchRating(PKM pk) => EncounterMatchRating.Match; diff --git a/PKHeX.Core/Legality/Encounters/Templates/Gen5/EncounterTrade5B2W2.cs b/PKHeX.Core/Legality/Encounters/Templates/Gen5/EncounterTrade5B2W2.cs index 37f1a7446..2b8fa2b89 100644 --- a/PKHeX.Core/Legality/Encounters/Templates/Gen5/EncounterTrade5B2W2.cs +++ b/PKHeX.Core/Legality/Encounters/Templates/Gen5/EncounterTrade5B2W2.cs @@ -8,16 +8,16 @@ namespace PKHeX.Core; /// public sealed record EncounterTrade5B2W2 : IEncounterable, IEncounterMatch, IFixedTrainer, IFixedNickname, IEncounterConvertible, IFixedGender, IFixedNature, IFixedIVSet { - public int Generation => 5; + public byte Generation => 5; public EntityContext Context => EntityContext.Gen5; - public int Location => Locations.LinkTrade5NPC; + public ushort Location => Locations.LinkTrade5NPC; public bool IsFixedNickname { get; init; } public GameVersion Version { get; } public Shiny Shiny => Shiny.Never; public bool EggEncounter => false; public Ball FixedBall => Ball.Poke; public bool IsShiny => false; - public int EggLocation => 0; + public ushort EggLocation => 0; public bool IsFixedTrainer => true; public required ushort Species { get; init; } @@ -68,7 +68,7 @@ public EncounterTrade5B2W2(string[] names, GameVersion version) public PK5 ConvertToPKM(ITrainerInfo tr, EncounterCriteria criteria) { - var version = this.GetCompatibleVersion((GameVersion)tr.Game); + var version = this.GetCompatibleVersion(tr.Version); int lang = (int)Language.GetSafeLanguage(Generation, (LanguageID)tr.Language, version); var pi = PersonalTable.B2W2[Species]; var pk = new PK5 @@ -77,18 +77,18 @@ public PK5 ConvertToPKM(ITrainerInfo tr, EncounterCriteria criteria) Species = Species, Form = Form, CurrentLevel = Level, - Met_Location = Location, - Met_Level = Level, + MetLocation = Location, + MetLevel = Level, MetDate = EncounterDate.GetDateNDS(), Ball = (byte)FixedBall, ID32 = ID32, - Version = (byte)version, + Version = version, Language = lang, - OT_Gender = OTGender, - OT_Name = TrainerNames[lang], + OriginalTrainerGender = OTGender, + OriginalTrainerName = TrainerNames[lang], - OT_Friendship = pi.BaseFriendship, + OriginalTrainerFriendship = pi.BaseFriendship, IsNicknamed = IsFixedNickname, Nickname = IsFixedNickname ? Nicknames[lang] : SpeciesName.GetSpeciesNameGeneration(Species, lang, Generation), @@ -105,7 +105,7 @@ private void SetPINGA(PK5 pk, EncounterCriteria criteria, PersonalInfo5B2W2 pi) { if (pk.IsShiny) pk.PID ^= 0x1000_0000; - var nature = (int)criteria.GetNature(Nature); + var nature = criteria.GetNature(Nature); var gender = criteria.GetGender(Gender, pi); var ability = criteria.GetAbilityFromNumber(Ability); PIDGenerator.SetRandomWildPID5(pk, nature, ability, gender); @@ -122,7 +122,7 @@ private void SetPINGA(PK5 pk, EncounterCriteria criteria, PersonalInfo5B2W2 pi) public bool IsMatchExact(PKM pk, EvoCriteria evo) { - if (pk.Met_Level != Level) + if (pk.MetLevel != Level) return false; if (IVs.IsSpecified && !Legal.GetIsFixedIVSequenceValidNoRand(IVs, pk)) return false; @@ -132,7 +132,7 @@ public bool IsMatchExact(PKM pk, EvoCriteria evo) return false; if (evo.Form != Form && !FormInfo.IsFormChangeable(Species, Form, pk.Form, Context, pk.Context)) return false; - if (pk.OT_Gender != OTGender) + if (pk.OriginalTrainerGender != OTGender) return false; if (!IsMatchEggLocation(pk)) return false; @@ -144,7 +144,7 @@ private bool IsMatchEggLocation(PKM pk) var expect = EggLocation; if (pk is PB8) expect = Locations.Default8bNone; - return pk.Egg_Location == expect; + return pk.EggLocation == expect; } private bool IsMatchNatureGenderShiny(PKM pk) { @@ -152,7 +152,7 @@ private bool IsMatchNatureGenderShiny(PKM pk) return false; if (Gender != FixedGenderUtil.GenderRandom && Gender != pk.Gender) return false; - if (Nature != Nature.Random && pk.Nature != (int)Nature) + if (Nature != Nature.Random && pk.Nature != Nature) return false; return true; } diff --git a/PKHeX.Core/Legality/Encounters/Templates/Gen5/EncounterTrade5BW.cs b/PKHeX.Core/Legality/Encounters/Templates/Gen5/EncounterTrade5BW.cs index 91e3d624c..f389cb8fa 100644 --- a/PKHeX.Core/Legality/Encounters/Templates/Gen5/EncounterTrade5BW.cs +++ b/PKHeX.Core/Legality/Encounters/Templates/Gen5/EncounterTrade5BW.cs @@ -5,14 +5,14 @@ namespace PKHeX.Core; /// Generation 5 Trade with Fixed PID public sealed record EncounterTrade5BW : IEncounterable, IEncounterMatch, IFixedTrainer, IFixedNickname, IFixedGender, IFixedNature, IEncounterConvertible { - public int Generation => 5; + public byte Generation => 5; public EntityContext Context => EntityContext.Gen5; - public int Location => Locations.LinkTrade5NPC; + public ushort Location => Locations.LinkTrade5NPC; public bool IsFixedNickname => true; public GameVersion Version { get; } public Shiny Shiny => Shiny.Never; public bool EggEncounter => false; - public int EggLocation => 0; + public ushort EggLocation => 0; public Ball FixedBall => Ball.Poke; public bool IsShiny => false; public bool IsFixedTrainer => true; @@ -66,7 +66,7 @@ public EncounterTrade5BW(ReadOnlySpan names, byte index, GameVersion v public PK5 ConvertToPKM(ITrainerInfo tr, EncounterCriteria criteria) { - var version = this.GetCompatibleVersion((GameVersion)tr.Game); + var version = this.GetCompatibleVersion(tr.Version); int lang = (int)Language.GetSafeLanguage(Generation, (LanguageID)tr.Language, version); var pi = PersonalTable.BW[Species]; var pk = new PK5 @@ -75,20 +75,20 @@ public PK5 ConvertToPKM(ITrainerInfo tr, EncounterCriteria criteria) Species = Species, Form = Form, CurrentLevel = Level, - Met_Location = Location, - Met_Level = Level, + MetLocation = Location, + MetLevel = Level, MetDate = EncounterDate.GetDateNDS(), Gender = Gender, - Nature = (byte)Nature, + Nature = Nature, Ball = (byte)FixedBall, ID32 = ID32, - Version = (byte)version, + Version = version, Language = lang == 1 ? 0 : lang, // Trades for JPN games have language ID of 0, not 1. - OT_Gender = OTGender, - OT_Name = TrainerNames[lang], + OriginalTrainerGender = OTGender, + OriginalTrainerName = TrainerNames[lang], - OT_Friendship = pi.BaseFriendship, + OriginalTrainerFriendship = pi.BaseFriendship, IsNicknamed = IsFixedNickname, Nickname = IsFixedNickname ? Nicknames[lang] : SpeciesName.GetSpeciesNameGeneration(Species, lang, Generation), @@ -112,7 +112,7 @@ public PK5 ConvertToPKM(ITrainerInfo tr, EncounterCriteria criteria) public bool IsMatchExact(PKM pk, EvoCriteria evo) { - if (pk.Met_Level != Level) + if (pk.MetLevel != Level) return false; if (!Legal.GetIsFixedIVSequenceValidNoRand(IVs, pk)) return false; @@ -122,7 +122,7 @@ public bool IsMatchExact(PKM pk, EvoCriteria evo) return false; if (evo.Form != Form && !FormInfo.IsFormChangeable(Species, Form, pk.Form, Context, pk.Context)) return false; - if (pk.OT_Gender != OTGender) + if (pk.OriginalTrainerGender != OTGender) return false; if (!IsMatchEggLocation(pk)) return false; @@ -133,7 +133,7 @@ private bool IsMatchNatureGenderShiny(PKM pk) { if (PID != pk.EncryptionConstant) return false; - if ((int)Nature != pk.Nature) + if (Nature != pk.Nature) return false; return true; } @@ -143,7 +143,7 @@ private bool IsMatchEggLocation(PKM pk) var expect = EggLocation; if (pk is PB8) expect = Locations.Default8bNone; - return pk.Egg_Location == expect; + return pk.EggLocation == expect; } public EncounterMatchRating GetMatchRating(PKM pk) => EncounterMatchRating.Match; diff --git a/PKHeX.Core/Legality/Encounters/Templates/Gen6/EncounterArea6AO.cs b/PKHeX.Core/Legality/Encounters/Templates/Gen6/EncounterArea6AO.cs index f31ee71d6..4fcc66581 100644 --- a/PKHeX.Core/Legality/Encounters/Templates/Gen6/EncounterArea6AO.cs +++ b/PKHeX.Core/Legality/Encounters/Templates/Gen6/EncounterArea6AO.cs @@ -1,4 +1,5 @@ using System; +using System.Diagnostics.CodeAnalysis; using static System.Buffers.Binary.BinaryPrimitives; namespace PKHeX.Core; @@ -12,11 +13,11 @@ public sealed record EncounterArea6AO : IEncounterArea, IAreaL public GameVersion Version { get; } public readonly ushort Location; - public readonly SlotType Type; + public readonly SlotType6 Type; - public bool IsMatchLocation(int location) => Location == location; + public bool IsMatchLocation(ushort location) => Location == location; - public static EncounterArea6AO[] GetAreas(BinLinkerAccessor input, GameVersion game) + public static EncounterArea6AO[] GetAreas(BinLinkerAccessor input, [ConstantExpected] GameVersion game) { var result = new EncounterArea6AO[input.Length]; for (int i = 0; i < result.Length; i++) @@ -24,23 +25,23 @@ public static EncounterArea6AO[] GetAreas(BinLinkerAccessor input, GameVersion g return result; } - private EncounterArea6AO(ReadOnlySpan data, GameVersion game) + private EncounterArea6AO(ReadOnlySpan data, [ConstantExpected] GameVersion game) { Location = ReadUInt16LittleEndian(data); - Type = (SlotType)data[2]; + Type = (SlotType6)data[2]; Version = game; - Slots = ReadSlots(data); + Slots = ReadSlots(data[4..]); } private EncounterSlot6AO[] ReadSlots(ReadOnlySpan data) { const int size = 4; - int count = (data.Length - 4) / size; + int count = data.Length / size; var slots = new EncounterSlot6AO[count]; for (int i = 0; i < slots.Length; i++) { - int offset = 4 + (size * i); + int offset = size * i; var entry = data.Slice(offset, size); slots[i] = ReadSlot(entry); } diff --git a/PKHeX.Core/Legality/Encounters/Templates/Gen6/EncounterArea6XY.cs b/PKHeX.Core/Legality/Encounters/Templates/Gen6/EncounterArea6XY.cs index 3aa4e2450..2aef8f60f 100644 --- a/PKHeX.Core/Legality/Encounters/Templates/Gen6/EncounterArea6XY.cs +++ b/PKHeX.Core/Legality/Encounters/Templates/Gen6/EncounterArea6XY.cs @@ -1,8 +1,23 @@ using System; +using System.Diagnostics.CodeAnalysis; using static System.Buffers.Binary.BinaryPrimitives; namespace PKHeX.Core; +public enum SlotType6 : byte +{ + Standard = 0, + Grass = 1, + Surf = 2, + Old_Rod = 3, + Good_Rod = 4, + Super_Rod = 5, + Rock_Smash = 6, + + Horde = 7, + FriendSafari = 8, +} + /// /// encounter area /// @@ -12,11 +27,11 @@ public sealed record EncounterArea6XY : IEncounterArea, IAreaL public GameVersion Version { get; } public readonly ushort Location; - public readonly SlotType Type; + public readonly SlotType6 Type; - public bool IsMatchLocation(int location) => Location == location; + public bool IsMatchLocation(ushort location) => Location == location; - public static EncounterArea6XY[] GetAreas(BinLinkerAccessor input, GameVersion game, EncounterArea6XY safari) + public static EncounterArea6XY[] GetAreas(BinLinkerAccessor input, [ConstantExpected] GameVersion game, EncounterArea6XY safari) { int count = input.Length; var result = new EncounterArea6XY[count + 1]; @@ -29,19 +44,19 @@ public static EncounterArea6XY[] GetAreas(BinLinkerAccessor input, GameVersion g public EncounterArea6XY() { Location = 148; // Friend Safari - Type = SlotType.FriendSafari; + Type = SlotType6.FriendSafari; Version = GameVersion.XY; Slots = LoadSafariSlots(); } - private EncounterArea6XY(ReadOnlySpan data, GameVersion game) + private EncounterArea6XY(ReadOnlySpan data, [ConstantExpected] GameVersion game) { Location = ReadUInt16LittleEndian(data); - Type = (SlotType)data[2]; + Type = (SlotType6)data[2]; Version = game; - Slots = ReadSlots(data); + Slots = ReadSlots(data[4..]); } private EncounterSlot6XY[] LoadSafariSlots() @@ -50,7 +65,7 @@ private EncounterSlot6XY[] LoadSafariSlots() const byte Level = 30; // Single form species - var species = AllSpecies; + var species = AllFriendSafariSpecies; var slots = new EncounterSlot6XY[species.Length + SpeciesFormSlots]; int i = 0; for (; i < species.Length; i++) @@ -66,7 +81,11 @@ private EncounterSlot6XY[] LoadSafariSlots() return slots; } - private static ReadOnlySpan AllSpecies => + /// + /// All species available in the Friend Safari. + /// + /// Handle Vivillon (666) and Floette (670) separately + private static ReadOnlySpan AllFriendSafariSpecies => [ 002, 005, 008, 012, 014, 016, 021, 025, 027, 035, 038, 039, 043, 044, 046, 049, 049, 051, 056, 058, @@ -88,18 +107,16 @@ private EncounterSlot6XY[] LoadSafariSlots() 657, 660, 662, 662, 668, 673, 674, 677, 682, 684, 686, 689, 694, 701, 702, 702, 705, 707, 708, 710, 712, 714, - - // Handle Floette (670) and Vivillon (666) separately ]; private EncounterSlot6XY[] ReadSlots(ReadOnlySpan data) { const int size = 4; - int count = (data.Length - 4) / size; + int count = data.Length / size; var slots = new EncounterSlot6XY[count]; for (int i = 0; i < slots.Length; i++) { - int offset = 4 + (size * i); + int offset = size * i; var entry = data.Slice(offset, size); ushort species = ReadUInt16LittleEndian(entry); byte form = (byte)(species >> 11); diff --git a/PKHeX.Core/Legality/Encounters/Templates/Gen6/EncounterSlot6AO.cs b/PKHeX.Core/Legality/Encounters/Templates/Gen6/EncounterSlot6AO.cs index 6e8a932bf..84e160519 100644 --- a/PKHeX.Core/Legality/Encounters/Templates/Gen6/EncounterSlot6AO.cs +++ b/PKHeX.Core/Legality/Encounters/Templates/Gen6/EncounterSlot6AO.cs @@ -1,4 +1,5 @@ using System; +using static PKHeX.Core.SlotType6; namespace PKHeX.Core; @@ -8,22 +9,22 @@ namespace PKHeX.Core; public sealed record EncounterSlot6AO(EncounterArea6AO Parent, ushort Species, byte Form, byte LevelMin, byte LevelMax) : IEncounterable, IEncounterMatch, IEncounterConvertible, IEncounterFormRandom { - public int Generation => 6; + public byte Generation => 6; public EntityContext Context => EntityContext.Gen6; public bool EggEncounter => false; public Ball FixedBall => Ball.None; public Shiny Shiny => Shiny.Random; public bool IsShiny => false; - public int EggLocation => 0; + public ushort EggLocation => 0; public bool IsRandomUnspecificForm => Form >= EncounterUtil.FormDynamic; public string Name => $"Wild Encounter ({Version})"; public string LongName => $"{Name} {Type.ToString().Replace('_', ' ')}"; public GameVersion Version => Parent.Version; - public int Location => Parent.Location; - public SlotType Type => Parent.Type; - public bool CanDexNav => Type != SlotType.Rock_Smash; - public bool IsHorde => Type == SlotType.Horde; + public ushort Location => Parent.Location; + public SlotType6 Type => Parent.Type; + public bool CanDexNav => Type != Rock_Smash; + public bool IsHorde => Type == Horde; private HiddenAbilityPermission IsHiddenAbilitySlot() => CanDexNav || IsHorde ? HiddenAbilityPermission.Possible : HiddenAbilityPermission.Never; @@ -63,16 +64,16 @@ public PK6 ConvertToPKM(ITrainerInfo tr, EncounterCriteria criteria) Species = Species, Form = GetWildForm(Form), CurrentLevel = LevelMin, - OT_Friendship = pi.BaseFriendship, - Met_Location = Location, - Met_Level = LevelMin, - Version = (byte)Version, + OriginalTrainerFriendship = pi.BaseFriendship, + MetLocation = Location, + MetLevel = LevelMin, + Version = Version, Ball = (byte)Ball.Poke, MetDate = EncounterDate.GetDate3DS(), Language = lang, - OT_Name = tr.OT, - OT_Gender = tr.Gender, + OriginalTrainerName = tr.OT, + OriginalTrainerGender = tr.Gender, ID32 = tr.ID32, Nickname = SpeciesName.GetSpeciesNameGeneration(Species, lang, Generation), }; @@ -104,9 +105,10 @@ private byte GetWildForm(byte form) private void SetPINGA(PK6 pk, EncounterCriteria criteria, PersonalInfo6AO pi) { - pk.PID = Util.Rand32(); - pk.EncryptionConstant = Util.Rand32(); - pk.Nature = (int)criteria.GetNature(); + var rnd = Util.Rand; + pk.PID = rnd.Rand32(); + pk.EncryptionConstant = rnd.Rand32(); + pk.Nature = criteria.GetNature(); pk.Gender = criteria.GetGender(pi); pk.RefreshAbility(criteria.GetAbilityFromNumber(Ability)); criteria.SetRandomIVs(pk); @@ -121,9 +123,9 @@ private void SetPINGA(PK6 pk, EncounterCriteria criteria, PersonalInfo6AO pi) public bool IsMatchExact(PKM pk, EvoCriteria evo) { - var boostMax = Type != SlotType.Rock_Smash ? DexNavBoost : FluteBoostMax; + var boostMax = Type != Rock_Smash ? DexNavBoost : FluteBoostMax; const int boostMin = FluteBoostMin; - if (!this.IsLevelWithinRange(pk.Met_Level, boostMin, boostMax)) + if (!this.IsLevelWithinRange(pk.MetLevel, boostMin, boostMax)) return false; if (evo.Form != Form && !IsRandomUnspecificForm) diff --git a/PKHeX.Core/Legality/Encounters/Templates/Gen6/EncounterSlot6XY.cs b/PKHeX.Core/Legality/Encounters/Templates/Gen6/EncounterSlot6XY.cs index 5f8059b36..d061220dc 100644 --- a/PKHeX.Core/Legality/Encounters/Templates/Gen6/EncounterSlot6XY.cs +++ b/PKHeX.Core/Legality/Encounters/Templates/Gen6/EncounterSlot6XY.cs @@ -6,13 +6,13 @@ namespace PKHeX.Core; public sealed record EncounterSlot6XY(EncounterArea6XY Parent, ushort Species, byte Form, byte LevelMin, byte LevelMax) : IEncounterable, IEncounterMatch, IEncounterConvertible, IEncounterFormRandom, IFlawlessIVCount { - public int Generation => 6; + public byte Generation => 6; public EntityContext Context => EntityContext.Gen6; public bool EggEncounter => false; public Ball FixedBall => Ball.None; public Shiny Shiny => Shiny.Random; public bool IsShiny => false; - public int EggLocation => 0; + public ushort EggLocation => 0; public bool IsRandomUnspecificForm => Form >= EncounterUtil.FormDynamic; private PersonalInfo6XY PersonalInfo => PersonalTable.XY[Species]; @@ -21,11 +21,11 @@ public sealed record EncounterSlot6XY(EncounterArea6XY Parent, ushort Species, b public string Name => $"Wild Encounter ({Version})"; public string LongName => $"{Name} {Type.ToString().Replace('_', ' ')}"; public GameVersion Version => Parent.Version; - public int Location => Parent.Location; - public SlotType Type => Parent.Type; + public ushort Location => Parent.Location; + public SlotType6 Type => Parent.Type; - public bool IsFriendSafari => Type == SlotType.FriendSafari; - public bool IsHorde => Type == SlotType.Horde; + public bool IsFriendSafari => Type == SlotType6.FriendSafari; + public bool IsHorde => Type == SlotType6.Horde; private HiddenAbilityPermission IsHiddenAbilitySlot() => IsHorde || IsFriendSafari ? HiddenAbilityPermission.Possible : HiddenAbilityPermission.Never; @@ -50,26 +50,26 @@ public sealed record EncounterSlot6XY(EncounterArea6XY Parent, ushort Species, b public PK6 ConvertToPKM(ITrainerInfo tr, EncounterCriteria criteria) { int lang = (int)Language.GetSafeLanguage(Generation, (LanguageID)tr.Language); - var version = Version != GameVersion.XY ? Version : GameVersion.XY.Contains(tr.Game) ? (GameVersion)tr.Game : GameVersion.X; + var version = Version != GameVersion.XY ? Version : GameVersion.XY.Contains(tr.Version) ? tr.Version : GameVersion.X; var form = GetWildForm(Form); - var pi = PersonalInfo; + var pi = PersonalTable.XY[Species, form]; var pk = new PK6 { Species = Species, Form = form, CurrentLevel = LevelMin, - Met_Location = Location, - Met_Level = LevelMin, + MetLocation = Location, + MetLevel = LevelMin, Ball = (byte)Ball.Poke, MetDate = EncounterDate.GetDate3DS(), - Version = (byte)version, + Version = version, Language = lang, - OT_Name = tr.OT, - OT_Gender = tr.Gender, + OriginalTrainerName = tr.OT, + OriginalTrainerGender = tr.Gender, ID32 = tr.ID32, Nickname = SpeciesName.GetSpeciesNameGeneration(Species, lang, Generation), - OT_Friendship = pi.BaseFriendship, + OriginalTrainerFriendship = pi.BaseFriendship, }; if (tr is IRegionOrigin r) r.CopyRegionOrigin(pk); @@ -79,7 +79,7 @@ public PK6 ConvertToPKM(ITrainerInfo tr, EncounterCriteria criteria) if (IsRandomUnspecificForm && Form == EncounterUtil.FormVivillon) pk.Form = Vivillon3DS.GetPattern(pk.Country, pk.Region); - SetPINGA(pk, criteria); + SetPINGA(pk, criteria, pi); EncounterUtil.SetEncounterMoves(pk, Version, LevelMin); pk.SetRandomMemory6(); pk.ResetPartyStats(); @@ -97,12 +97,12 @@ private byte GetWildForm(byte form) return (byte)Util.Rand.Next(PersonalTable.XY[Species].FormCount); } - private void SetPINGA(PK6 pk, EncounterCriteria criteria) + private void SetPINGA(PK6 pk, EncounterCriteria criteria, PersonalInfo6XY pi) { - var pi = PersonalTable.XY.GetFormEntry(Species, Form); - pk.PID = Util.Rand32(); - pk.EncryptionConstant = Util.Rand32(); - pk.Nature = (int)criteria.GetNature(); + var rnd = Util.Rand; + pk.PID = rnd.Rand32(); + pk.EncryptionConstant = rnd.Rand32(); + pk.Nature = criteria.GetNature(); pk.Gender = criteria.GetGender(pi); pk.RefreshAbility(criteria.GetAbilityFromNumber(Ability)); criteria.SetRandomIVs(pk, FlawlessIVCount); @@ -114,7 +114,7 @@ private void SetPINGA(PK6 pk, EncounterCriteria criteria) public bool IsMatchExact(PKM pk, EvoCriteria evo) { - if (!this.IsLevelWithinRange(pk.Met_Level)) + if (!this.IsLevelWithinRange(pk.MetLevel)) return false; if (Form != evo.Form && !IsRandomUnspecificForm && !IsValidOutOfBoundsForm(pk)) diff --git a/PKHeX.Core/Legality/Encounters/Templates/Gen6/EncounterStatic6.cs b/PKHeX.Core/Legality/Encounters/Templates/Gen6/EncounterStatic6.cs index 10a406422..aae5c5df4 100644 --- a/PKHeX.Core/Legality/Encounters/Templates/Gen6/EncounterStatic6.cs +++ b/PKHeX.Core/Legality/Encounters/Templates/Gen6/EncounterStatic6.cs @@ -6,10 +6,10 @@ namespace PKHeX.Core; public sealed record EncounterStatic6(GameVersion Version) : IEncounterable, IEncounterMatch, IEncounterConvertible, IContestStatsReadOnly, IHatchCycle, IFlawlessIVCount, IFatefulEncounterReadOnly, IFixedGender, IFixedNature, IMoveset, IFixedIVSet { - public int Generation => 6; + public byte Generation => 6; public EntityContext Context => EntityContext.Gen6; - int ILocation.Location => Location; - int ILocation.EggLocation => EggLocation; + ushort ILocation.Location => Location; + ushort ILocation.EggLocation => EggLocation; public bool IsShiny => false; public bool EggEncounter => EggLocation != 0; public Ball FixedBall { get; init; } @@ -29,12 +29,12 @@ public sealed record EncounterStatic6(GameVersion Version) public byte LevelMax => Level; public byte Gender { get; init; } = FixedGenderUtil.GenderRandom; - public byte CNT_Cool { get; init; } - public byte CNT_Beauty { get; init; } - public byte CNT_Cute { get; init; } - public byte CNT_Smart { get; init; } - public byte CNT_Tough { get; init; } - public byte CNT_Sheen { get; init; } + public byte ContestCool { get; init; } + public byte ContestBeauty { get; init; } + public byte ContestCute { get; init; } + public byte ContestSmart { get; init; } + public byte ContestTough { get; init; } + public byte ContestSheen { get; init; } public byte EggCycles { get; init; } public byte FlawlessIVCount { get; init; } @@ -50,27 +50,29 @@ public sealed record EncounterStatic6(GameVersion Version) public PK6 ConvertToPKM(ITrainerInfo tr, EncounterCriteria criteria) { - var version = this.GetCompatibleVersion((GameVersion)tr.Game); + var version = this.GetCompatibleVersion(tr.Version); int lang = (int)Language.GetSafeLanguage(Generation, (LanguageID)tr.Language, version); var pi = PersonalTable.AO[Species]; + var rnd = Util.Rand; var pk = new PK6 { - EncryptionConstant = Util.Rand32(), + EncryptionConstant = rnd.Rand32(), + PID = rnd.Rand32(), Species = Species, Form = Form, CurrentLevel = LevelMin, - Met_Location = Location, - Met_Level = LevelMin, + MetLocation = Location, + MetLevel = LevelMin, MetDate = EncounterDate.GetDate3DS(), Ball = (byte)(FixedBall is Ball.None ? Ball.Poke : FixedBall), FatefulEncounter = FatefulEncounter, ID32 = tr.ID32, - Version = (byte)version, + Version = version, Language = lang, - OT_Gender = tr.Gender, - OT_Name = tr.OT, + OriginalTrainerGender = tr.Gender, + OriginalTrainerName = tr.OT, - OT_Friendship = pi.BaseFriendship, + OriginalTrainerFriendship = pi.BaseFriendship, Nickname = SpeciesName.GetSpeciesNameGeneration(Species, lang, Generation), }; @@ -78,9 +80,9 @@ public PK6 ConvertToPKM(ITrainerInfo tr, EncounterCriteria criteria) if (EggEncounter) { // Fake as hatched. - pk.Met_Location = version is GameVersion.X or GameVersion.Y ? Locations.HatchLocation6XY : Locations.HatchLocation6AO; - pk.Met_Level = EggStateLegality.EggMetLevel; - pk.Egg_Location = EggLocation; + pk.MetLocation = version is GameVersion.X or GameVersion.Y ? Locations.HatchLocation6XY : Locations.HatchLocation6AO; + pk.MetLevel = EggStateLegality.EggMetLevel; + pk.EggLocation = EggLocation; pk.EggMetDate = pk.MetDate; } @@ -104,7 +106,6 @@ public PK6 ConvertToPKM(ITrainerInfo tr, EncounterCriteria criteria) private void SetPINGA(PK6 pk, EncounterCriteria criteria, PersonalInfo6AO pi) { - pk.PID = Util.Rand32(); if (pk.IsShiny) { if (Shiny == Shiny.Never || (Shiny != Shiny.Always && !criteria.Shiny.IsShiny())) @@ -122,7 +123,7 @@ private void SetPINGA(PK6 pk, EncounterCriteria criteria, PersonalInfo6AO pi) criteria.SetRandomIVs(pk, FlawlessIVCount); var ability = criteria.GetAbilityFromNumber(Ability); - pk.Nature = (int)criteria.GetNature(Nature); + pk.Nature = criteria.GetNature(Nature); pk.Gender = criteria.GetGender(Gender, pi); pk.AbilityNumber = 1 << ability; pk.Ability = pi.GetAbilityAtIndex(ability); @@ -144,7 +145,7 @@ public bool IsMatchExact(PKM pk, EvoCriteria evo) return false; if (!IsMatchLocation(pk)) return false; - if (pk.Met_Level != Level) + if (pk.MetLevel != Level) return false; if (Form != evo.Form && !FormInfo.IsFormChangeable(Species, Form, pk.Form, Context, pk.Context)) return false; @@ -152,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 != (int)Nature) + if (Nature != Nature.Random && pk.Nature != Nature) return false; if (FlawlessIVCount != 0 && pk.FlawlessIVCount < FlawlessIVCount) return false; @@ -170,7 +171,7 @@ private bool IsMatchLocation(PKM pk) { if (EggEncounter) return true; - var met = pk.Met_Location; + var met = pk.MetLocation; if (met == Location) return true; @@ -186,17 +187,17 @@ private bool IsMatchEggLocation(PKM pk) if (!EggEncounter) { var expect = pk is PB8 ? Locations.Default8bNone : EggLocation; - return pk.Egg_Location == expect; + return pk.EggLocation == expect; } - var eggloc = pk.Egg_Location; + var eggLoc = pk.EggLocation; if (!pk.IsEgg) // hatched - return eggloc == EggLocation || eggloc == Locations.LinkTrade6; + return eggLoc == EggLocation || eggLoc == Locations.LinkTrade6; // Unhatched: - if (eggloc != EggLocation) + if (eggLoc != EggLocation) return false; - if (pk.Met_Location is not (0 or Locations.LinkTrade6)) + if (pk.MetLocation is not (0 or Locations.LinkTrade6)) return false; return true; } diff --git a/PKHeX.Core/Legality/Encounters/Templates/Gen6/EncounterTrade6.cs b/PKHeX.Core/Legality/Encounters/Templates/Gen6/EncounterTrade6.cs index f97bd236c..3b22c0423 100644 --- a/PKHeX.Core/Legality/Encounters/Templates/Gen6/EncounterTrade6.cs +++ b/PKHeX.Core/Legality/Encounters/Templates/Gen6/EncounterTrade6.cs @@ -7,14 +7,14 @@ namespace PKHeX.Core; /// public sealed record EncounterTrade6 : IEncounterable, IEncounterMatch, IFixedTrainer, IFixedNickname, IFixedGender, IFixedNature, IEncounterConvertible, IMemoryOTReadOnly { - public int Generation => 6; + public byte Generation => 6; public EntityContext Context => EntityContext.Gen6; - public int Location => Locations.LinkTrade6NPC; + public ushort Location => Locations.LinkTrade6NPC; public Shiny Shiny => Shiny.Never; public bool EggEncounter => false; public Ball FixedBall => Ball.Poke; public bool IsShiny => false; - public int EggLocation => 0; + public ushort EggLocation => 0; public bool IsFixedTrainer => true; public bool IsFixedNickname { get; init; } = true; @@ -32,10 +32,10 @@ public sealed record EncounterTrade6 : IEncounterable, IEncounterMatch, IFixedTr public byte Form => 0; public required byte Level { get; init; } public GameVersion Version { get; } - public byte OT_Memory { get; } - public byte OT_Intensity { get; } - public byte OT_Feeling { get; } - public ushort OT_TextVar { get; } + public byte OriginalTrainerMemory { get; } + public byte OriginalTrainerMemoryIntensity { get; } + public byte OriginalTrainerMemoryFeeling { get; } + public ushort OriginalTrainerMemoryVariable { get; } private const string _name = "In-game Trade"; public string Name => _name; @@ -48,10 +48,10 @@ public EncounterTrade6(ReadOnlySpan names, byte index, GameVersion ver Nicknames = EncounterUtil.GetNamesForLanguage(names, index); TrainerNames = EncounterUtil.GetNamesForLanguage(names, (uint)(index + (names[1].Length >> 1))); Version = version; - OT_Memory = m; - OT_Intensity = i; - OT_Feeling = f; - OT_TextVar = v; + OriginalTrainerMemory = m; + OriginalTrainerMemoryIntensity = i; + OriginalTrainerMemoryFeeling = f; + OriginalTrainerMemoryVariable = v; } #region Generating @@ -63,41 +63,42 @@ public EncounterTrade6(ReadOnlySpan names, byte index, GameVersion ver public PK6 ConvertToPKM(ITrainerInfo tr, EncounterCriteria criteria) { - var version = this.GetCompatibleVersion((GameVersion)tr.Game); + var version = this.GetCompatibleVersion(tr.Version); int lang = (int)Language.GetSafeLanguage(Generation, (LanguageID)tr.Language, version); var pi = PersonalTable.AO[Species]; + var rnd = Util.Rand; var pk = new PK6 { - PID = Util.Rand32(), - EncryptionConstant = Util.Rand32(), + PID = rnd.Rand32(), + EncryptionConstant = rnd.Rand32(), Species = Species, CurrentLevel = Level, - Met_Location = Location, - Met_Level = Level, + MetLocation = Location, + MetLevel = Level, MetDate = EncounterDate.GetDate3DS(), Gender = Gender, - Nature = (byte)Nature, + Nature = Nature, Ball = (byte)FixedBall, ID32 = ID32, - Version = (byte)version, + Version = version, Language = lang, - OT_Gender = OTGender, - OT_Name = TrainerNames[lang], + OriginalTrainerGender = OTGender, + OriginalTrainerName = TrainerNames[lang], - OT_Memory = OT_Memory, - OT_Intensity = OT_Intensity, - OT_Feeling = OT_Feeling, - OT_TextVar = OT_TextVar, - OT_Friendship = pi.BaseFriendship, + OriginalTrainerMemory = OriginalTrainerMemory, + OriginalTrainerMemoryIntensity = OriginalTrainerMemoryIntensity, + OriginalTrainerMemoryFeeling = OriginalTrainerMemoryFeeling, + OriginalTrainerMemoryVariable = OriginalTrainerMemoryVariable, + OriginalTrainerFriendship = pi.BaseFriendship, IsNicknamed = IsFixedNickname, Nickname = IsFixedNickname ? Nicknames[lang] : SpeciesName.GetSpeciesNameGeneration(Species, lang, Generation), - HT_Name = tr.OT, - HT_Gender = tr.Gender, + HandlingTrainerName = tr.OT, + HandlingTrainerGender = tr.Gender, CurrentHandler = 1, - HT_Friendship = pi.BaseFriendship, + HandlingTrainerFriendship = pi.BaseFriendship, }; if (tr is IRegionOrigin r) r.CopyRegionOrigin(pk); @@ -129,7 +130,7 @@ public bool IsNicknameMatch(PKM pk, ReadOnlySpan nickname, int language) public bool IsMatchExact(PKM pk, EvoCriteria evo) { - if (pk.Met_Level != Level) + if (pk.MetLevel != Level) return false; if (IVs.IsSpecified) { @@ -142,7 +143,7 @@ public bool IsMatchExact(PKM pk, EvoCriteria evo) return false; if (evo.Form != Form && !FormInfo.IsFormChangeable(Species, Form, pk.Form, Context, pk.Context)) return false; - if (pk.OT_Gender != OTGender) + if (pk.OriginalTrainerGender != OTGender) return false; if (!IsMatchEggLocation(pk)) return false; @@ -154,7 +155,7 @@ private bool IsMatchEggLocation(PKM pk) var expect = EggLocation; if (pk is PB8 && expect is 0) expect = Locations.Default8bNone; - return pk.Egg_Location == expect; + return pk.EggLocation == expect; } private bool IsMatchNatureGenderShiny(PKM pk) { @@ -162,7 +163,7 @@ private bool IsMatchNatureGenderShiny(PKM pk) return false; if (Gender != pk.Gender) return false; - if (Nature != Nature.Random && pk.Nature != (int)Nature) + if (Nature != Nature.Random && pk.Nature != Nature) return false; return true; } diff --git a/PKHeX.Core/Legality/Encounters/Templates/Gen7/EncounterArea7.cs b/PKHeX.Core/Legality/Encounters/Templates/Gen7/EncounterArea7.cs index 0ebc9dca8..a3a8874b5 100644 --- a/PKHeX.Core/Legality/Encounters/Templates/Gen7/EncounterArea7.cs +++ b/PKHeX.Core/Legality/Encounters/Templates/Gen7/EncounterArea7.cs @@ -1,8 +1,15 @@ using System; +using System.Diagnostics.CodeAnalysis; using static System.Buffers.Binary.BinaryPrimitives; namespace PKHeX.Core; +public enum SlotType7 : byte +{ + Standard = 0, + SOS = 1, +} + /// /// encounter area /// @@ -12,11 +19,11 @@ public sealed record EncounterArea7 : IEncounterArea, IAreaLocat public GameVersion Version { get; } public readonly ushort Location; - public readonly SlotType Type; + public readonly SlotType7 Type; - public bool IsMatchLocation(int location) => Location == location; + public bool IsMatchLocation(ushort location) => Location == location; - public static EncounterArea7[] GetAreas(BinLinkerAccessor input, GameVersion game) + public static EncounterArea7[] GetAreas(BinLinkerAccessor input, [ConstantExpected] GameVersion game) { var result = new EncounterArea7[input.Length]; for (int i = 0; i < result.Length; i++) @@ -24,23 +31,23 @@ public static EncounterArea7[] GetAreas(BinLinkerAccessor input, GameVersion gam return result; } - private EncounterArea7(ReadOnlySpan data, GameVersion game) + private EncounterArea7(ReadOnlySpan data, [ConstantExpected] GameVersion game) { Location = ReadUInt16LittleEndian(data); - Type = (SlotType)data[2]; + Type = (SlotType7)data[2]; Version = game; - Slots = ReadSlots(data); + Slots = ReadSlots(data[4..]); } private EncounterSlot7[] ReadSlots(ReadOnlySpan data) { const int size = 4; - int count = (data.Length - 4) / size; + int count = data.Length / size; var slots = new EncounterSlot7[count]; for (int i = 0; i < slots.Length; i++) { - int offset = 4 + (size * i); + int offset = size * i; var entry = data.Slice(offset, size); slots[i] = ReadSlot(entry); } diff --git a/PKHeX.Core/Legality/Encounters/Templates/Gen7/EncounterSlot7.cs b/PKHeX.Core/Legality/Encounters/Templates/Gen7/EncounterSlot7.cs index 7f2e5d9c6..9e1487347 100644 --- a/PKHeX.Core/Legality/Encounters/Templates/Gen7/EncounterSlot7.cs +++ b/PKHeX.Core/Legality/Encounters/Templates/Gen7/EncounterSlot7.cs @@ -6,22 +6,22 @@ namespace PKHeX.Core; public sealed record EncounterSlot7(EncounterArea7 Parent, ushort Species, byte Form, byte LevelMin, byte LevelMax) : IEncounterable, IEncounterMatch, IEncounterConvertible, IEncounterFormRandom, IFlawlessIVCountConditional { - public int Generation => 7; + public byte Generation => 7; public EntityContext Context => EntityContext.Gen7; public bool EggEncounter => false; public Ball FixedBall => Location == Locations.Pelago7 ? Ball.Poke : Ball.None; public Shiny Shiny => Shiny.Random; public bool IsShiny => false; - public int EggLocation => 0; + public ushort EggLocation => 0; public bool IsRandomUnspecificForm => Form >= EncounterUtil.FormDynamic; public string Name => $"Wild Encounter ({Version})"; public string LongName => $"{Name} {Type.ToString().Replace('_', ' ')}"; public GameVersion Version => Parent.Version; - public int Location => Parent.Location; - public SlotType Type => Parent.Type; + public ushort Location => Parent.Location; + public SlotType7 Type => Parent.Type; - public bool IsSOS => Type == SlotType.SOS; + public bool IsSOS => Type == SlotType7.SOS; public AbilityPermission Ability => IsHiddenAbilitySlot() switch { @@ -53,18 +53,18 @@ public PK7 ConvertToPKM(ITrainerInfo tr, EncounterCriteria criteria) Species = Species, Form = form, CurrentLevel = LevelMin, - Met_Location = Location, - Met_Level = LevelMin, - Version = (byte)Version, + MetLocation = Location, + MetLevel = LevelMin, + Version = Version, MetDate = EncounterDate.GetDate3DS(), Ball = (byte)Ball.Poke, Language = lang, - OT_Name = tr.OT, - OT_Gender = tr.Gender, + OriginalTrainerName = tr.OT, + OriginalTrainerGender = tr.Gender, ID32 = tr.ID32, Nickname = SpeciesName.GetSpeciesNameGeneration(Species, lang, Generation), - OT_Friendship = pi.BaseFriendship, + OriginalTrainerFriendship = pi.BaseFriendship, }; if (tr is IRegionOrigin r) r.CopyRegionOrigin(pk); @@ -88,9 +88,10 @@ private byte GetWildForm(byte form) private void SetPINGA(PK7 pk, EncounterCriteria criteria, PersonalInfo7 pi) { - pk.PID = Util.Rand32(); - pk.EncryptionConstant = Util.Rand32(); - pk.Nature = (int)criteria.GetNature(); + var rnd = Util.Rand; + pk.PID = rnd.Rand32(); + pk.EncryptionConstant = rnd.Rand32(); + pk.Nature = criteria.GetNature(); pk.Gender = criteria.GetGender(pi); criteria.SetRandomIVs(pk); @@ -106,7 +107,7 @@ private void SetPINGA(PK7 pk, EncounterCriteria criteria, PersonalInfo7 pi) public bool IsMatchExact(PKM pk, EvoCriteria evo) { - if (!this.IsLevelWithinRange(pk.Met_Level)) + if (!this.IsLevelWithinRange(pk.MetLevel)) return false; if (Form != evo.Form && Species is not ((int)Core.Species.Furfrou or (int)Core.Species.Oricorio)) diff --git a/PKHeX.Core/Legality/Encounters/Templates/Gen7/EncounterStatic7.cs b/PKHeX.Core/Legality/Encounters/Templates/Gen7/EncounterStatic7.cs index ea75f4cc2..a57973e6d 100644 --- a/PKHeX.Core/Legality/Encounters/Templates/Gen7/EncounterStatic7.cs +++ b/PKHeX.Core/Legality/Encounters/Templates/Gen7/EncounterStatic7.cs @@ -6,10 +6,10 @@ namespace PKHeX.Core; public sealed record EncounterStatic7(GameVersion Version) : IEncounterable, IEncounterMatch, IEncounterConvertible, IRelearn, IEncounterFormRandom, IFlawlessIVCount, IFatefulEncounterReadOnly, IFixedGender, IFixedNature, IFixedIVSet { - public int Generation => 7; + public byte Generation => 7; public EntityContext Context => EntityContext.Gen7; - int ILocation.Location => Location; - int ILocation.EggLocation => EggLocation; + ushort ILocation.Location => Location; + ushort ILocation.EggLocation => EggLocation; public bool RibbonWishing => Species == (int)Core.Species.Magearna; public bool EggEncounter => EggLocation != 0; @@ -53,28 +53,27 @@ public sealed record EncounterStatic7(GameVersion Version) public PK7 ConvertToPKM(ITrainerInfo tr, EncounterCriteria criteria) { - var version = this.GetCompatibleVersion((GameVersion)tr.Game); + var version = this.GetCompatibleVersion(tr.Version); int lang = (int)Language.GetSafeLanguage(Generation, (LanguageID)tr.Language, version); var pi = PersonalTable.USUM[Species, Form]; var pk = new PK7 { - EncryptionConstant = Util.Rand32(), Species = Species, Form = GetWildForm(Form, tr), CurrentLevel = LevelMin, - Met_Location = Location, - Met_Level = LevelMin, + MetLocation = Location, + MetLevel = LevelMin, MetDate = EncounterDate.GetDate3DS(), Ball = (byte)(FixedBall is Ball.None ? Ball.Poke : FixedBall), FatefulEncounter = FatefulEncounter, ID32 = tr.ID32, - Version = (byte)version, + Version = version, Language = lang, - OT_Gender = tr.Gender, - OT_Name = tr.OT, + OriginalTrainerGender = tr.Gender, + OriginalTrainerName = tr.OT, - OT_Friendship = pi.BaseFriendship, + OriginalTrainerFriendship = pi.BaseFriendship, Nickname = SpeciesName.GetSpeciesNameGeneration(Species, lang, Generation), }; @@ -89,9 +88,9 @@ public PK7 ConvertToPKM(ITrainerInfo tr, EncounterCriteria criteria) if (EggEncounter) { // Fake as hatched. - pk.Met_Location = Locations.HatchLocation7; - pk.Met_Level = EggStateLegality.EggMetLevel; - pk.Egg_Location = EggLocation; + pk.MetLocation = Locations.HatchLocation7; + pk.MetLevel = EggStateLegality.EggMetLevel; + pk.EggLocation = EggLocation; pk.EggMetDate = pk.MetDate; } @@ -119,7 +118,9 @@ private static byte GetWildForm(byte form, ITrainerInfo tr) private void SetPINGA(PK7 pk, EncounterCriteria criteria, PersonalInfo7 pi) { - pk.PID = Util.Rand32(); + var rnd = Util.Rand; + pk.EncryptionConstant = rnd.Rand32(); + pk.PID = rnd.Rand32(); if (pk.IsShiny) { if (Shiny == Shiny.Never || (Shiny != Shiny.Always && !criteria.Shiny.IsShiny())) @@ -137,7 +138,7 @@ private void SetPINGA(PK7 pk, EncounterCriteria criteria, PersonalInfo7 pi) criteria.SetRandomIVs(pk, FlawlessIVCount); var ability = criteria.GetAbilityFromNumber(Ability); - pk.Nature = (int)criteria.GetNature(Nature); + pk.Nature = criteria.GetNature(Nature); pk.Gender = criteria.GetGender(Gender, pi); pk.AbilityNumber = 1 << ability; pk.Ability = pi.GetAbilityAtIndex(ability); @@ -159,7 +160,7 @@ public bool IsMatchExact(PKM pk, EvoCriteria evo) return false; if (!IsMatchLocation(pk)) return false; - if (pk.Met_Level != Level) + if (pk.MetLevel != Level) return false; if (!IsMatchForm(pk, evo)) return false; @@ -167,7 +168,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 != (int)Nature) + if (Nature != Nature.Random && pk.Nature != Nature) return false; if (FlawlessIVCount != 0 && pk.FlawlessIVCount < FlawlessIVCount) return false; @@ -186,7 +187,7 @@ private bool IsMatchLocation(PKM pk) if (EggEncounter) return true; - return pk.Met_Location == Location; + return pk.MetLocation == Location; } private bool IsMatchEggLocation(PKM pk) @@ -194,21 +195,21 @@ private bool IsMatchEggLocation(PKM pk) if (!EggEncounter) { var expect = pk is PB8 ? Locations.Default8bNone : EggLocation; - return pk.Egg_Location == expect; + return pk.EggLocation == expect; } // Gift Eevee edge case if (EggLocation == Locations.Daycare5 && !Relearn.HasMoves && pk.RelearnMove1 != 0) return false; - var eggloc = pk.Egg_Location; + var eggLoc = pk.EggLocation; if (!pk.IsEgg) // hatched - return eggloc == EggLocation || eggloc == Locations.LinkTrade6; + return eggLoc == EggLocation || eggLoc == Locations.LinkTrade6; // Unhatched: - if (eggloc != EggLocation) + if (eggLoc != EggLocation) return false; - if (pk.Met_Location is not (0 or Locations.LinkTrade6)) + if (pk.MetLocation is not (0 or Locations.LinkTrade6)) return false; return true; } diff --git a/PKHeX.Core/Legality/Encounters/Templates/Gen7/EncounterTrade7.cs b/PKHeX.Core/Legality/Encounters/Templates/Gen7/EncounterTrade7.cs index 9764a68b8..3d0153d6a 100644 --- a/PKHeX.Core/Legality/Encounters/Templates/Gen7/EncounterTrade7.cs +++ b/PKHeX.Core/Legality/Encounters/Templates/Gen7/EncounterTrade7.cs @@ -7,18 +7,18 @@ namespace PKHeX.Core; /// public sealed record EncounterTrade7 : IEncounterable, IEncounterMatch, IFixedTrainer, IFixedNickname, IEncounterConvertible, IMemoryOTReadOnly, IFixedGender, IFixedNature { - public int Generation => 7; + public byte Generation => 7; public EntityContext Context => EntityContext.Gen7; - public int Location => Locations.LinkTrade6NPC; - public byte OT_Memory => 1; - public byte OT_Intensity => 3; - public byte OT_Feeling => 5; - public ushort OT_TextVar => 40; + public ushort Location => Locations.LinkTrade6NPC; + public byte OriginalTrainerMemory => 1; + public byte OriginalTrainerMemoryIntensity => 3; + public byte OriginalTrainerMemoryFeeling => 5; + public ushort OriginalTrainerMemoryVariable => 40; public Shiny Shiny => Shiny.Never; public bool EggEncounter => false; public Ball FixedBall => Ball.Poke; public bool IsShiny => false; - public int EggLocation => 0; + public ushort EggLocation => 0; public bool IsFixedTrainer => true; public bool IsFixedNickname => true; @@ -61,42 +61,43 @@ public EncounterTrade7(ReadOnlySpan names, byte index, GameVersion ver public PK7 ConvertToPKM(ITrainerInfo tr, EncounterCriteria criteria) { - var version = this.GetCompatibleVersion((GameVersion)tr.Game); + var version = this.GetCompatibleVersion(tr.Version); int lang = (int)Language.GetSafeLanguage(Generation, (LanguageID)tr.Language, version); var pi = PersonalTable.USUM[Species, Form]; + var rnd = Util.Rand; var pk = new PK7 { - PID = Util.Rand32(), - EncryptionConstant = Util.Rand32(), + PID = rnd.Rand32(), + EncryptionConstant = rnd.Rand32(), Species = Species, Form = Form, CurrentLevel = Level, - Met_Location = Location, - Met_Level = Level, + MetLocation = Location, + MetLevel = Level, MetDate = EncounterDate.GetDate3DS(), Gender = Gender, - Nature = (byte)Nature, + Nature = Nature, Ball = (byte)FixedBall, ID32 = ID32, - Version = (byte)version, + Version = version, Language = lang, - OT_Gender = OTGender, - OT_Name = TrainerNames[lang], + OriginalTrainerGender = OTGender, + OriginalTrainerName = TrainerNames[lang], - OT_Memory = OT_Memory, - OT_Intensity = OT_Intensity, - OT_Feeling = OT_Feeling, - OT_TextVar = OT_TextVar, - OT_Friendship = pi.BaseFriendship, + OriginalTrainerMemory = OriginalTrainerMemory, + OriginalTrainerMemoryIntensity = OriginalTrainerMemoryIntensity, + OriginalTrainerMemoryFeeling = OriginalTrainerMemoryFeeling, + OriginalTrainerMemoryVariable = OriginalTrainerMemoryVariable, + OriginalTrainerFriendship = pi.BaseFriendship, IsNicknamed = true, Nickname = Nicknames[lang], - HT_Name = tr.OT, - HT_Gender = tr.Gender, + HandlingTrainerName = tr.OT, + HandlingTrainerGender = tr.Gender, CurrentHandler = 1, - HT_Friendship = pi.BaseFriendship, + HandlingTrainerFriendship = pi.BaseFriendship, }; if (tr is IRegionOrigin r) r.CopyRegionOrigin(pk); @@ -126,7 +127,7 @@ public PK7 ConvertToPKM(ITrainerInfo tr, EncounterCriteria criteria) public bool IsMatchExact(PKM pk, EvoCriteria evo) { - if (pk.Met_Level != Level) + if (pk.MetLevel != Level) return false; if (IVs.IsSpecified) { @@ -139,7 +140,7 @@ public bool IsMatchExact(PKM pk, EvoCriteria evo) return false; if (evo.Form != Form && !FormInfo.IsFormChangeable(Species, Form, pk.Form, Context, pk.Context)) return false; - if (pk.OT_Gender != OTGender) + if (pk.OriginalTrainerGender != OTGender) return false; if (!IsMatchEggLocation(pk)) return false; @@ -153,7 +154,7 @@ private bool IsMatchEggLocation(PKM pk) var expect = EggLocation; if (pk is PB8) expect = Locations.Default8bNone; - return pk.Egg_Location == expect; + return pk.EggLocation == expect; } private bool IsMatchNatureGenderShiny(PKM pk) { @@ -161,7 +162,7 @@ private bool IsMatchNatureGenderShiny(PKM pk) return false; if (Gender != pk.Gender) return false; - if (Nature != Nature.Random && pk.Nature != (int)Nature) + if (Nature != Nature.Random && pk.Nature != Nature) return false; return true; } diff --git a/PKHeX.Core/Legality/Encounters/Templates/Gen7/EncounterTransfer7.cs b/PKHeX.Core/Legality/Encounters/Templates/Gen7/EncounterTransfer7.cs index 1f02816d6..2748d6bff 100644 --- a/PKHeX.Core/Legality/Encounters/Templates/Gen7/EncounterTransfer7.cs +++ b/PKHeX.Core/Legality/Encounters/Templates/Gen7/EncounterTransfer7.cs @@ -10,14 +10,14 @@ namespace PKHeX.Core; /// Level transferred at. public sealed record EncounterTransfer7(GameVersion Version, ushort Species, byte Level) : IEncounterable, IFlawlessIVCount, IFatefulEncounterReadOnly { - public int Generation => 7; + public byte Generation => 7; public EntityContext Context => EntityContext.Gen7; public Ball FixedBall => Ball.Poke; public bool EggEncounter => false; - public int EggLocation => 0; + public ushort EggLocation => 0; public byte Form => 0; - public int Location { get; private init; } + public ushort Location { get; private init; } public Shiny Shiny { get; private init; } public AbilityPermission Ability { get; private init; } public bool FatefulEncounter { get; private init; } diff --git a/PKHeX.Core/Legality/Encounters/Templates/Gen7b/EncounterArea7b.cs b/PKHeX.Core/Legality/Encounters/Templates/Gen7b/EncounterArea7b.cs index dc7e5f8fe..65b133a97 100644 --- a/PKHeX.Core/Legality/Encounters/Templates/Gen7b/EncounterArea7b.cs +++ b/PKHeX.Core/Legality/Encounters/Templates/Gen7b/EncounterArea7b.cs @@ -1,4 +1,5 @@ using System; +using System.Diagnostics.CodeAnalysis; using static System.Buffers.Binary.BinaryPrimitives; namespace PKHeX.Core; @@ -13,9 +14,9 @@ public sealed record EncounterArea7b : IEncounterArea, IAreaLoc public readonly ushort Location; - public bool IsMatchLocation(int location) => Location == location; + public bool IsMatchLocation(ushort location) => Location == location; - public static EncounterArea7b[] GetAreas(BinLinkerAccessor input, GameVersion game) + public static EncounterArea7b[] GetAreas(BinLinkerAccessor input, [ConstantExpected] GameVersion game) { var result = new EncounterArea7b[input.Length]; for (int i = 0; i < result.Length; i++) @@ -23,21 +24,21 @@ public static EncounterArea7b[] GetAreas(BinLinkerAccessor input, GameVersion ga return result; } - private EncounterArea7b(ReadOnlySpan data, GameVersion game) + private EncounterArea7b(ReadOnlySpan data, [ConstantExpected] GameVersion game) { Location = ReadUInt16LittleEndian(data); Version = game; - Slots = ReadSlots(data); + Slots = ReadSlots(data[2..]); } private EncounterSlot7b[] ReadSlots(ReadOnlySpan data) { const int size = 4; - int count = (data.Length - 2) / size; + int count = data.Length / size; var slots = new EncounterSlot7b[count]; for (int i = 0; i < slots.Length; i++) { - int offset = 2 + (size * i); + int offset = size * i; var entry = data.Slice(offset, size); slots[i] = ReadSlot(entry); } diff --git a/PKHeX.Core/Legality/Encounters/Templates/Gen7b/EncounterSlot7b.cs b/PKHeX.Core/Legality/Encounters/Templates/Gen7b/EncounterSlot7b.cs index b982f62d4..b718a221f 100644 --- a/PKHeX.Core/Legality/Encounters/Templates/Gen7b/EncounterSlot7b.cs +++ b/PKHeX.Core/Legality/Encounters/Templates/Gen7b/EncounterSlot7b.cs @@ -6,21 +6,21 @@ namespace PKHeX.Core; public sealed record EncounterSlot7b(EncounterArea7b Parent, ushort Species, byte LevelMin, byte LevelMax) : IEncounterable, IEncounterMatch, IEncounterConvertible { - public int Generation => 7; + public byte Generation => 7; public EntityContext Context => EntityContext.Gen7b; public bool EggEncounter => false; public Ball FixedBall => Ball.None; public Shiny Shiny => Shiny.Random; public AbilityPermission Ability => AbilityPermission.Any12; public bool IsShiny => false; - public int EggLocation => 0; + public ushort EggLocation => 0; public byte Form => 0; public string Name => $"Wild Encounter ({Version})"; public string LongName => $"{Name}"; public GameVersion Version => Parent.Version; - public int Location => Parent.Location; + public ushort Location => Parent.Location; #region Generating PKM IEncounterConvertible.ConvertToPKM(ITrainerInfo tr, EncounterCriteria criteria) => ConvertToPKM(tr, criteria); @@ -34,19 +34,16 @@ public PB7 ConvertToPKM(ITrainerInfo tr, EncounterCriteria criteria) { Species = Species, CurrentLevel = LevelMin, - OT_Friendship = pi.BaseFriendship, - Met_Location = Location, - Met_Level = LevelMin, - Version = (byte)Version, + OriginalTrainerFriendship = pi.BaseFriendship, + MetLocation = Location, + MetLevel = LevelMin, + Version = Version, MetDate = EncounterDate.GetDateSwitch(), Ball = (byte)Ball.Poke, - HeightScalar = PokeSizeUtil.GetRandomScalar(), - WeightScalar = PokeSizeUtil.GetRandomScalar(), - Language = lang, - OT_Name = tr.OT, - OT_Gender = tr.Gender, + OriginalTrainerName = tr.OT, + OriginalTrainerGender = tr.Gender, ID32 = tr.ID32, Nickname = SpeciesName.GetSpeciesNameGeneration(Species, lang, Generation), }; @@ -61,12 +58,16 @@ public PB7 ConvertToPKM(ITrainerInfo tr, EncounterCriteria criteria) private void SetPINGA(PB7 pk, EncounterCriteria criteria, PersonalInfo7GG pi) { - pk.PID = Util.Rand32(); - pk.EncryptionConstant = Util.Rand32(); - pk.Nature = (int)criteria.GetNature(); + var rnd = Util.Rand; + pk.PID = rnd.Rand32(); + pk.EncryptionConstant = rnd.Rand32(); + pk.Nature = criteria.GetNature(); pk.Gender = criteria.GetGender(pi); pk.RefreshAbility(criteria.GetAbilityFromNumber(Ability)); + pk.HeightScalar = PokeSizeUtil.GetRandomScalar(rnd); + pk.WeightScalar = PokeSizeUtil.GetRandomScalar(rnd); + criteria.SetRandomIVs(pk); } #endregion @@ -75,7 +76,7 @@ private void SetPINGA(PB7 pk, EncounterCriteria criteria, PersonalInfo7GG pi) public bool IsMatchExact(PKM pk, EvoCriteria evo) { - if (!this.IsLevelWithinRange(pk.Met_Level, 0, CatchComboBonus)) + if (!this.IsLevelWithinRange(pk.MetLevel, 0, CatchComboBonus)) return false; if (Form != evo.Form) return false; diff --git a/PKHeX.Core/Legality/Encounters/Templates/Gen7b/EncounterStatic7b.cs b/PKHeX.Core/Legality/Encounters/Templates/Gen7b/EncounterStatic7b.cs index 9881d2826..20736622a 100644 --- a/PKHeX.Core/Legality/Encounters/Templates/Gen7b/EncounterStatic7b.cs +++ b/PKHeX.Core/Legality/Encounters/Templates/Gen7b/EncounterStatic7b.cs @@ -6,10 +6,10 @@ namespace PKHeX.Core; public sealed record EncounterStatic7b(GameVersion Version) : IEncounterable, IEncounterMatch, IEncounterConvertible, IFlawlessIVCount, IFixedIVSet { - public int Generation => 7; + public byte Generation => 7; public EntityContext Context => EntityContext.Gen7b; - int ILocation.Location => Location; - public int EggLocation => 0; + ushort ILocation.Location => Location; + public ushort EggLocation => 0; public bool IsShiny => false; public bool EggEncounter => false; @@ -35,26 +35,23 @@ public sealed record EncounterStatic7b(GameVersion Version) public PB7 ConvertToPKM(ITrainerInfo tr, EncounterCriteria criteria) { int lang = (int)Language.GetSafeLanguage(Generation, (LanguageID)tr.Language); - var version = this.GetCompatibleVersion((GameVersion)tr.Game); + var version = this.GetCompatibleVersion(tr.Version); var pi = PersonalTable.GG[Species, Form]; var pk = new PB7 { Species = Species, Form = Form, CurrentLevel = LevelMin, - OT_Friendship = pi.BaseFriendship, - Met_Location = Location, - Met_Level = LevelMin, - Version = (byte)version, + OriginalTrainerFriendship = pi.BaseFriendship, + MetLocation = Location, + MetLevel = LevelMin, + Version = version, MetDate = EncounterDate.GetDateSwitch(), Ball = (byte)Ball.Poke, - HeightScalar = PokeSizeUtil.GetRandomScalar(), - WeightScalar = PokeSizeUtil.GetRandomScalar(), - Language = lang, - OT_Name = tr.OT, - OT_Gender = tr.Gender, + OriginalTrainerName = tr.OT, + OriginalTrainerGender = tr.Gender, ID32 = tr.ID32, Nickname = SpeciesName.GetSpeciesNameGeneration(Species, lang, Generation), }; @@ -69,12 +66,16 @@ public PB7 ConvertToPKM(ITrainerInfo tr, EncounterCriteria criteria) private void SetPINGA(PB7 pk, EncounterCriteria criteria, PersonalInfo7GG pi) { - pk.PID = Util.Rand32(); - pk.EncryptionConstant = Util.Rand32(); - pk.Nature = (int)criteria.GetNature(); + var rnd = Util.Rand; + pk.PID = rnd.Rand32(); + pk.EncryptionConstant = rnd.Rand32(); + pk.Nature = criteria.GetNature(); pk.Gender = criteria.GetGender(pi); pk.RefreshAbility(criteria.GetAbilityFromNumber(Ability)); + pk.HeightScalar = PokeSizeUtil.GetRandomScalar(rnd); + pk.WeightScalar = PokeSizeUtil.GetRandomScalar(rnd); + if (IVs.IsSpecified) criteria.SetRandomIVs(pk, IVs); else @@ -88,9 +89,9 @@ public bool IsMatchExact(PKM pk, EvoCriteria evo) { if (!IsMatchEggLocation(pk)) return false; - if (pk.Met_Location != Location) + if (pk.MetLocation != Location) return false; - if (pk.Met_Level != Level) + if (pk.MetLevel != Level) return false; if (Form != evo.Form && !FormInfo.IsFormChangeable(Species, Form, pk.Form, Context, pk.Context)) return false; @@ -104,7 +105,7 @@ public bool IsMatchExact(PKM pk, EvoCriteria evo) private bool IsMatchEggLocation(PKM pk) { var expect = pk is PB8 ? Locations.Default8bNone : EggLocation; - return pk.Egg_Location == expect; + return pk.EggLocation == expect; } #endregion } diff --git a/PKHeX.Core/Legality/Encounters/Templates/Gen7b/EncounterTrade7b.cs b/PKHeX.Core/Legality/Encounters/Templates/Gen7b/EncounterTrade7b.cs index 1c06b9ff7..f9da01f6f 100644 --- a/PKHeX.Core/Legality/Encounters/Templates/Gen7b/EncounterTrade7b.cs +++ b/PKHeX.Core/Legality/Encounters/Templates/Gen7b/EncounterTrade7b.cs @@ -7,14 +7,14 @@ namespace PKHeX.Core; /// public sealed record EncounterTrade7b(GameVersion Version) : IEncounterable, IEncounterMatch, IFixedTrainer, IEncounterConvertible { - public int Generation => 7; + public byte Generation => 7; public EntityContext Context => EntityContext.Gen7b; - public int Location => Locations.LinkTrade6NPC; + public ushort Location => Locations.LinkTrade6NPC; public Shiny Shiny => Shiny.Random; public bool EggEncounter => false; public Ball FixedBall => Ball.Poke; public bool IsShiny => false; - public int EggLocation => 0; + public ushort EggLocation => 0; public bool IsFixedTrainer => true; public AbilityPermission Ability => AbilityPermission.Any12; @@ -43,7 +43,7 @@ public sealed record EncounterTrade7b(GameVersion Version) : IEncounterable, IEn public PB7 ConvertToPKM(ITrainerInfo tr, EncounterCriteria criteria) { - var version = this.GetCompatibleVersion((GameVersion)tr.Game); + var version = this.GetCompatibleVersion(tr.Version); int lang = (int)Language.GetSafeLanguage(Generation, (LanguageID)tr.Language, version); var pi = PersonalTable.GG[Species, Form]; var pk = new PB7 @@ -51,28 +51,25 @@ public PB7 ConvertToPKM(ITrainerInfo tr, EncounterCriteria criteria) Species = Species, Form = Form, CurrentLevel = Level, - Met_Location = Location, - Met_Level = Level, + MetLocation = Location, + MetLevel = Level, MetDate = EncounterDate.GetDateSwitch(), Ball = (byte)FixedBall, ID32 = ID32, - Version = (byte)version, + Version = version, Language = lang, - OT_Gender = OTGender, - OT_Name = TrainerNames[lang], + OriginalTrainerGender = OTGender, + OriginalTrainerName = TrainerNames[lang], - OT_Friendship = pi.BaseFriendship, - - HeightScalar = PokeSizeUtil.GetRandomScalar(), - WeightScalar = PokeSizeUtil.GetRandomScalar(), + OriginalTrainerFriendship = pi.BaseFriendship, Nickname = SpeciesName.GetSpeciesNameGeneration(Species, lang, Generation), - HT_Name = tr.OT, - HT_Gender = tr.Gender, + HandlingTrainerName = tr.OT, + HandlingTrainerGender = tr.Gender, CurrentHandler = 1, - HT_Friendship = pi.BaseFriendship, + HandlingTrainerFriendship = pi.BaseFriendship, }; EncounterUtil.SetEncounterMoves(pk, version, Level); @@ -87,11 +84,15 @@ public PB7 ConvertToPKM(ITrainerInfo tr, EncounterCriteria criteria) private void SetPINGA(PB7 pk, EncounterCriteria criteria, PersonalInfo7GG pi) { - pk.PID = Util.Rand32(); - pk.EncryptionConstant = Util.Rand32(); - pk.Nature = (int)criteria.GetNature(); + var rnd = Util.Rand; + pk.PID = rnd.Rand32(); + pk.EncryptionConstant = rnd.Rand32(); + pk.Nature = criteria.GetNature(); pk.Gender = criteria.GetGender(pi); pk.RefreshAbility(criteria.GetAbilityFromNumber(Ability)); + + pk.HeightScalar = PokeSizeUtil.GetRandomScalar(rnd); + pk.WeightScalar = PokeSizeUtil.GetRandomScalar(rnd); criteria.SetRandomIVs(pk, IVs); } @@ -103,7 +104,7 @@ private void SetPINGA(PB7 pk, EncounterCriteria criteria, PersonalInfo7GG pi) public bool IsMatchExact(PKM pk, EvoCriteria evo) { - if (pk.Met_Level != Level) + if (pk.MetLevel != Level) return false; if (IVs.IsSpecified) { @@ -114,7 +115,7 @@ public bool IsMatchExact(PKM pk, EvoCriteria evo) return false; if (evo.Form != Form && !FormInfo.IsFormChangeable(Species, Form, pk.Form, Context, pk.Context)) return false; - if (pk.OT_Gender != OTGender) + if (pk.OriginalTrainerGender != OTGender) return false; if (!IsMatchEggLocation(pk)) return false; @@ -124,7 +125,7 @@ public bool IsMatchExact(PKM pk, EvoCriteria evo) private bool IsMatchEggLocation(PKM pk) { var expect = pk is PB8 ? Locations.Default8bNone : EggLocation; - return pk.Egg_Location == expect; + return pk.EggLocation == expect; } public EncounterMatchRating GetMatchRating(PKM pk) => EncounterMatchRating.Match; diff --git a/PKHeX.Core/Legality/Encounters/Templates/Gen8/EncounterArea8.cs b/PKHeX.Core/Legality/Encounters/Templates/Gen8/EncounterArea8.cs index 00c97ead0..fde69c6f1 100644 --- a/PKHeX.Core/Legality/Encounters/Templates/Gen8/EncounterArea8.cs +++ b/PKHeX.Core/Legality/Encounters/Templates/Gen8/EncounterArea8.cs @@ -1,6 +1,7 @@ using System; +using System.Diagnostics.CodeAnalysis; using static PKHeX.Core.AreaWeather8; -using static PKHeX.Core.AreaSlotType8; +using static PKHeX.Core.SlotType8; using static System.Buffers.Binary.BinaryPrimitives; namespace PKHeX.Core; @@ -23,7 +24,7 @@ public sealed record EncounterArea8 : IEncounterArea, IAreaLocat /// public readonly bool PermitCrossover; - public bool IsMatchLocation(int location) + public bool IsMatchLocation(ushort location) { if (Location == location) return true; @@ -38,7 +39,7 @@ public bool IsMatchLocation(int location) return others.Contains((byte)location); } - public static bool CanCrossoverTo(int fromLocation, int toLocation, AreaSlotType8 type) + public static bool CanCrossoverTo(int fromLocation, int toLocation, SlotType8 type) { if (!type.CanCrossover()) return false; @@ -50,13 +51,13 @@ public static bool CanCrossoverTo(int fromLocation, int toLocation, AreaSlotType /// public const int BoostLevel = 60; - public static bool IsWildArea(int location) => IsWildArea8(location) || IsWildArea8Armor(location) || IsWildArea8Crown(location); - public static bool IsBoostedArea60(int location) => IsWildArea(location); - public static bool IsBoostedArea60Fog(int location) => IsWildArea8(location); // IoA doesn't have fog restriction by badges, and all Crown stuff is above 60. + public static bool IsWildArea(ushort location) => IsWildArea8(location) || IsWildArea8Armor(location) || IsWildArea8Crown(location); + public static bool IsBoostedArea60(ushort location) => IsWildArea(location); + public static bool IsBoostedArea60Fog(ushort location) => IsWildArea8(location); // IoA doesn't have fog restriction by badges, and all Crown stuff is above 60. - public static bool IsWildArea8(int location) => location is >= 122 and <= 154; // Rolling Fields -> Lake of Outrage - public static bool IsWildArea8Armor(int location) => location is >= 164 and <= 194; // Fields of Honor -> Honeycalm Island - public static bool IsWildArea8Crown(int location) => location is >= 204 and <= 234 and not 206; // Slippery Slope -> Dyna Tree Hill, skip Freezington + public static bool IsWildArea8(ushort location) => location is >= 122 and <= 154; // Rolling Fields -> Lake of Outrage + public static bool IsWildArea8Armor(ushort location) => location is >= 164 and <= 194; // Fields of Honor -> Honeycalm Island + public static bool IsWildArea8Crown(ushort location) => location is >= 204 and <= 234 and not 206; // Slippery Slope -> Dyna Tree Hill, skip Freezington /// /// Location, and areas that it can feed encounters to. @@ -290,15 +291,15 @@ public static bool CanCrossoverTo(int fromLocation, int toLocation, AreaSlotType _ => None, }; - public static bool IsCrossoverBleedPossible(AreaSlotType8 type, int fromLocation, byte toLocation) => true; + public static bool IsCrossoverBleedPossible(SlotType8 type, int fromLocation, byte toLocation) => true; - public static bool IsWeatherBleedPossible(AreaSlotType8 type, AreaWeather8 permit, byte location) + public static bool IsWeatherBleedPossible(SlotType8 type, AreaWeather8 permit, byte location) { var weather = GetWeatherBleed(type, location); return weather.HasFlag(permit); } - private static AreaWeather8 GetWeatherBleed(AreaSlotType8 type, byte location) => type switch + private static AreaWeather8 GetWeatherBleed(SlotType8 type, byte location) => type switch { SymbolMain or SymbolMain2 or SymbolMain3 => GetWeatherBleedSymbol(location), HiddenMain or HiddenMain2 => GetWeatherBleedHiddenGrass(location), @@ -307,7 +308,7 @@ public static bool IsWeatherBleedPossible(AreaSlotType8 type, AreaWeather8 permi _ => None, }; - public static EncounterArea8[] GetAreas(BinLinkerAccessor input, GameVersion game, bool symbol = false) + public static EncounterArea8[] GetAreas(BinLinkerAccessor input, [ConstantExpected] GameVersion game, [ConstantExpected] bool symbol = false) { var result = new EncounterArea8[input.Length]; for (int i = 0; i < result.Length; i++) @@ -315,7 +316,7 @@ public static EncounterArea8[] GetAreas(BinLinkerAccessor input, GameVersion gam return result; } - private EncounterArea8(ReadOnlySpan areaData, bool symbol, GameVersion game) + private EncounterArea8(ReadOnlySpan areaData, [ConstantExpected] bool symbol, [ConstantExpected] GameVersion game) { PermitCrossover = symbol; Location = areaData[0]; @@ -337,7 +338,7 @@ private EncounterSlot8[] ReadSlots(ReadOnlySpan areaData, byte slotCount) var min = meta[2]; var max = meta[3]; var count = meta[4]; - var slotType = (AreaSlotType8)meta[5]; + var slotType = (SlotType8)meta[5]; ofs += 6; // Read slots diff --git a/PKHeX.Core/Legality/Encounters/Templates/Gen8/EncounterSlot8.cs b/PKHeX.Core/Legality/Encounters/Templates/Gen8/EncounterSlot8.cs index 4459a352e..a4d604957 100644 --- a/PKHeX.Core/Legality/Encounters/Templates/Gen8/EncounterSlot8.cs +++ b/PKHeX.Core/Legality/Encounters/Templates/Gen8/EncounterSlot8.cs @@ -5,22 +5,22 @@ namespace PKHeX.Core; /// /// Encounter Slot found in . /// -public sealed record EncounterSlot8(EncounterArea8 Parent, ushort Species, byte Form, byte LevelMin, byte LevelMax, AreaWeather8 Weather, AreaSlotType8 Type) +public sealed record EncounterSlot8(EncounterArea8 Parent, ushort Species, byte Form, byte LevelMin, byte LevelMax, AreaWeather8 Weather, SlotType8 Type) : IEncounterable, IEncounterMatch, IEncounterConvertible, IOverworldCorrelation8 { - public int Generation => 8; + public byte Generation => 8; public EntityContext Context => EntityContext.Gen8; public bool EggEncounter => false; public Ball FixedBall => Ball.None; public AbilityPermission Ability => AbilityPermission.Any12; public Shiny Shiny => Shiny.Random; public bool IsShiny => false; - public int EggLocation => 0; + public ushort EggLocation => 0; public string Name => $"Wild Encounter ({Version})"; public string LongName => $"{Name} [{Type}] - {Weather.ToString().Replace("_", string.Empty)}"; public GameVersion Version => Parent.Version; - public int Location => Parent.Location; + public ushort Location => Parent.Location; // Fishing are only from the hidden table (not symbol). public bool CanEncounterViaFishing => Type.CanEncounterViaFishing(Weather); @@ -55,18 +55,18 @@ public PK8 ConvertToPKM(ITrainerInfo tr, EncounterCriteria criteria) Species = Species, Form = form, CurrentLevel = LevelMin, - Met_Location = Location, - Met_Level = LevelMin, - Version = (byte)Version, + MetLocation = Location, + MetLevel = LevelMin, + Version = Version, MetDate = EncounterDate.GetDateSwitch(), Ball = (byte)Ball.Poke, Language = lang, - OT_Name = tr.OT, - OT_Gender = tr.Gender, + OriginalTrainerName = tr.OT, + OriginalTrainerGender = tr.Gender, ID32 = tr.ID32, Nickname = SpeciesName.GetSpeciesNameGeneration(Species, lang, Generation), - OT_Friendship = pi.BaseFriendship, + OriginalTrainerFriendship = pi.BaseFriendship, }; SetPINGA(pk, criteria, pi); EncounterUtil.SetEncounterMoves(pk, Version, LevelMin); @@ -76,7 +76,7 @@ public PK8 ConvertToPKM(ITrainerInfo tr, EncounterCriteria criteria) pk.RibbonMarkCurry = true; if (Weather is AreaWeather8.Heavy_Fog && EncounterArea8.IsBoostedArea60Fog(Location)) - pk.CurrentLevel = pk.Met_Level = EncounterArea8.BoostLevel; + pk.MetLevel = pk.CurrentLevel = EncounterArea8.BoostLevel; pk.ResetPartyStats(); return pk; } @@ -95,7 +95,7 @@ private void SetPINGA(PK8 pk, EncounterCriteria criteria, PersonalInfo8SWSH pi) bool symbol = Parent.PermitCrossover; var c = symbol ? EncounterCriteria.Unrestricted : criteria; pk.RefreshAbility(criteria.GetAbilityFromNumber(Ability)); - pk.Nature = pk.StatNature = (int)criteria.GetNature(); + pk.Nature = pk.StatNature = criteria.GetNature(); pk.Gender = criteria.GetGender(pi); var req = GetRequirement(pk); @@ -136,17 +136,17 @@ public OverworldCorrelation8Requirement GetRequirement(PKM pk) public bool IsOverworldCorrelationCorrect(PKM pk) { - var flawless = GetFlawlessIVCount(pk.Met_Level); + var flawless = GetFlawlessIVCount(pk.MetLevel); return Overworld8RNG.ValidateOverworldEncounter(pk, flawless: flawless); } - private int GetFlawlessIVCount(int met) + private int GetFlawlessIVCount(int metLevel) { const int none = 0; const int any023 = -1; // Brilliant encounters are boosted to max level for the slot. - if (met < LevelMax) + if (metLevel < LevelMax) return none; if (Parent.PermitCrossover) @@ -163,11 +163,11 @@ public bool IsMatchExact(PKM pk, EvoCriteria evo) if (Form != evo.Form && Species is not (int)Core.Species.Rotom) return false; - var metLocation = pk.Met_Location; + var metLocation = pk.MetLocation; if (Location != metLocation && !EncounterArea8.CanCrossoverTo(Location, metLocation, Type)) return false; - var met = pk.Met_Level; + var met = pk.MetLevel; if (met == EncounterArea8.BoostLevel && EncounterArea8.IsBoostedArea60(Location)) return true; @@ -199,7 +199,7 @@ public EncounterMatchRating GetMatchRating(PKM pk) return EncounterMatchRating.DeferredErrors; // Galar Mine hidden encounters can only be found via Curry or Fishing. - if (Location is (30 or 54) && Type is AreaSlotType8.HiddenMain && !m.RibbonMarkCurry && !Type.CanEncounterViaFishing(Weather)) + if (Location is (30 or 54) && Type is SlotType8.HiddenMain && !m.RibbonMarkCurry && !Type.CanEncounterViaFishing(Weather)) return EncounterMatchRating.DeferredErrors; } @@ -210,6 +210,7 @@ public EncounterMatchRating GetMatchRating(PKM pk) MustNotHave when IsOverworldCorrelationCorrect(pk) => EncounterMatchRating.DeferredErrors, _ => EncounterMatchRating.Match, }; - #endregion } + + #endregion } diff --git a/PKHeX.Core/Legality/Encounters/Templates/Gen8/EncounterStatic8.cs b/PKHeX.Core/Legality/Encounters/Templates/Gen8/EncounterStatic8.cs index 60a286a48..8619f8c4b 100644 --- a/PKHeX.Core/Legality/Encounters/Templates/Gen8/EncounterStatic8.cs +++ b/PKHeX.Core/Legality/Encounters/Templates/Gen8/EncounterStatic8.cs @@ -9,13 +9,13 @@ public sealed record EncounterStatic8(GameVersion Version = GameVersion.SWSH) : IEncounterable, IEncounterMatch, IEncounterConvertible, IMoveset, IRelearn, IFlawlessIVCount, IFixedIVSet, IFixedGender, IFixedNature, IDynamaxLevelReadOnly, IGigantamaxReadOnly, IOverworldCorrelation8, IFatefulEncounterReadOnly { - public int Generation => 8; + public byte Generation => 8; public EntityContext Context => EntityContext.Gen8; - int ILocation.Location => Location; + ushort ILocation.Location => Location; public bool Gift => FixedBall != Ball.None; public bool IsShiny => Shiny == Shiny.Always; public bool EggEncounter => false; - int ILocation.EggLocation => 0; + ushort ILocation.EggLocation => 0; public required ushort Location { get; init; } public required ushort Species { get; init; } @@ -72,29 +72,27 @@ public bool IsOverworldCorrelationCorrect(PKM pk) public PK8 ConvertToPKM(ITrainerInfo tr, EncounterCriteria criteria) { - var version = this.GetCompatibleVersion((GameVersion)tr.Game); + var version = this.GetCompatibleVersion(tr.Version); int lang = (int)Language.GetSafeLanguage(Generation, (LanguageID)tr.Language, version); var pk = new PK8 { Species = Species, Form = Form, CurrentLevel = Level, - Met_Location = Location, - Met_Level = Level, + MetLocation = Location, + MetLevel = Level, MetDate = EncounterDate.GetDateSwitch(), Ball = (byte)(FixedBall != Ball.None ? FixedBall : Ball.Poke), FatefulEncounter = FatefulEncounter, ID32 = tr.ID32, - Version = (byte)version, + Version = version, Language = lang, - OT_Gender = tr.Gender, - OT_Name = tr.OT, - OT_Friendship = PersonalTable.SWSH[Species, Form].BaseFriendship, + OriginalTrainerGender = tr.Gender, + OriginalTrainerName = tr.OT, + OriginalTrainerFriendship = PersonalTable.SWSH[Species, Form].BaseFriendship, Nickname = SpeciesName.GetSpeciesNameGeneration(Species, lang, Generation), - HeightScalar = PokeSizeUtil.GetRandomScalar(), - WeightScalar = PokeSizeUtil.GetRandomScalar(), DynamaxLevel = DynamaxLevel, CanGigantamax = CanGigantamax, @@ -114,11 +112,11 @@ public PK8 ConvertToPKM(ITrainerInfo tr, EncounterCriteria criteria) private void SetPINGA(PK8 pk, EncounterCriteria criteria) { if (Weather is AreaWeather8.Heavy_Fog && EncounterArea8.IsBoostedArea60Fog(Location)) - pk.CurrentLevel = pk.Met_Level = EncounterArea8.BoostLevel; + pk.MetLevel = pk.CurrentLevel = EncounterArea8.BoostLevel; var pi = PersonalTable.SWSH[Species, Form]; pk.RefreshAbility(criteria.GetAbilityFromNumber(Ability)); - pk.Nature = pk.StatNature = (int)criteria.GetNature(); + pk.Nature = pk.StatNature = criteria.GetNature(); pk.Gender = criteria.GetGender(Gender, pi); var req = GetRequirement(pk); @@ -153,7 +151,7 @@ public bool IsMatchExact(PKM pk, EvoCriteria evo) return false; if (pk is PK8 d && d.DynamaxLevel < DynamaxLevel) return false; - if (pk.Met_Level < EncounterArea8.BoostLevel && Weather is AreaWeather8.Heavy_Fog && EncounterArea8.IsBoostedArea60Fog(Location)) + if (pk.MetLevel < EncounterArea8.BoostLevel && Weather is AreaWeather8.Heavy_Fog && EncounterArea8.IsBoostedArea60Fog(Location)) return false; if (Gender != FixedGenderUtil.GenderRandom && pk.Gender != Gender) return false; @@ -169,12 +167,12 @@ public bool IsMatchExact(PKM pk, EvoCriteria evo) private static bool IsMatchEggLocation(PKM pk) { var expect = pk is PB8 ? Locations.Default8bNone : 0; - return pk.Egg_Location == expect; + return pk.EggLocation == expect; } private bool IsMatchLocation(PKM pk) { - var met = pk.Met_Location; + var met = pk.MetLocation; if (met == Location) return true; if ((uint)met > byte.MaxValue) @@ -184,7 +182,7 @@ private bool IsMatchLocation(PKM pk) private bool IsMatchLevel(PKM pk) { - var met = pk.Met_Level; + var met = pk.MetLevel; var lvl = Level; if (met == lvl) return true; diff --git a/PKHeX.Core/Legality/Encounters/Templates/Gen8/EncounterStatic8N.cs b/PKHeX.Core/Legality/Encounters/Templates/Gen8/EncounterStatic8N.cs index 208201a42..ea8121b40 100644 --- a/PKHeX.Core/Legality/Encounters/Templates/Gen8/EncounterStatic8N.cs +++ b/PKHeX.Core/Legality/Encounters/Templates/Gen8/EncounterStatic8N.cs @@ -1,4 +1,5 @@ using System; +using System.Diagnostics.CodeAnalysis; using static PKHeX.Core.Encounters8Nest; using static System.Buffers.Binary.BinaryPrimitives; @@ -23,7 +24,7 @@ public sealed record EncounterStatic8N : EncounterStatic8Nest public override byte LevelMin => LevelCaps[MinRank * 2]; public override byte LevelMax => LevelCaps[(MaxRank * 2) + 1]; - public EncounterStatic8N(byte nestID, byte minRank, byte maxRank, byte val, GameVersion game) : base(game) + public EncounterStatic8N(byte nestID, byte minRank, byte maxRank, byte val, [ConstantExpected] GameVersion game) : base(game) { NestID = nestID; MinRank = minRank; @@ -32,7 +33,7 @@ public EncounterStatic8N(byte nestID, byte minRank, byte maxRank, byte val, Game FlawlessIVCount = val; } - public static EncounterStatic8N Read(ReadOnlySpan data, GameVersion game) => new(data[6], data[7], data[8], data[9], game) + public static EncounterStatic8N Read(ReadOnlySpan data, [ConstantExpected] GameVersion game) => new(data[6], data[7], data[8], data[9], game) { Species = ReadUInt16LittleEndian(data), Form = data[2], @@ -52,18 +53,22 @@ public static EncounterStatic8N Read(ReadOnlySpan data, GameVersion game) protected override bool IsMatchLevel(PKM pk) { - var met = pk.Met_Level; - var metLevel = met - 15; - var rank = ((uint)metLevel) / 10; + var met = pk.MetLevel; + var metLevel = met - 15u; + var rank = metLevel / 10; if (rank > 4) return false; if (rank > MaxRank) return false; - if (rank <= 1 && met <= byte.MaxValue) + if (rank <= 1) { - if (IsInaccessibleRank12Nest(NestID, (byte)met)) - return false; + var location = pk.MetLocation; + if (location <= byte.MaxValue) // Should always be true, no met locations > 255. + { + if (IsInaccessibleRank12Nest(NestID, (byte)location)) + return false; + } } if (rank < MinRank) // down-leveled @@ -74,18 +79,18 @@ protected override bool IsMatchLevel(PKM pk) public bool IsDownLeveled(PKM pk) { - var met = pk.Met_Level; - var metLevel = met - 15; + var met = pk.MetLevel; + var metLevel = met - 15u; return met != LevelMax && IsDownLeveled(pk, metLevel, met); } - private bool IsDownLeveled(PKM pk, int metLevel, int met) + private bool IsDownLeveled(PKM pk, uint metLevel, int met) { - if (metLevel % 5 != 0) + if (metLevel > int.MaxValue || metLevel % 5 != 0) return false; // shared nests can be down-leveled to any - if (pk.Met_Location == SharedNest) + if (pk.MetLocation == SharedNest) return met >= 20; // native down-levels: only allow 1 rank down (1 badge 2star -> 25), (3badge 3star -> 35) @@ -95,7 +100,7 @@ private bool IsDownLeveled(PKM pk, int metLevel, int met) protected override bool IsMatchLocation(PKM pk) { - var loc = pk.Met_Location; + var loc = pk.MetLocation; if (loc == SharedNest) return true; if (loc > byte.MaxValue) @@ -107,7 +112,7 @@ protected override bool IsMatchLocation(PKM pk) { var rand = new Xoroshiro128Plus(seed); var levelDelta = (int)rand.NextInt(6); - var met = pk.Met_Level; + var met = pk.MetLevel; for (int i = MaxRank; i >= MinRank; i--) { // check for dmax level @@ -129,7 +134,7 @@ protected override bool IsMatchLocation(PKM pk) if (met > levelMin) break; - if (IsDownLeveled(pk, met - 15, met)) + if (IsDownLeveled(pk, met - 15u, met)) return (Possible: true, ForceNoShiny: true); } return default; @@ -172,7 +177,7 @@ protected override void FinishCorrelation(PK8 pk, ulong seed) var levelMin = LevelCaps[MinRank * 2]; var level = levelMin + levelDelta; - pk.Met_Level = (byte)level; + pk.MetLevel = (byte)level; pk.CurrentLevel = (byte)level; pk.DynamaxLevel = GetInitialDynamaxLevel(xoro, MinRank); } diff --git a/PKHeX.Core/Legality/Encounters/Templates/Gen8/EncounterStatic8NC.cs b/PKHeX.Core/Legality/Encounters/Templates/Gen8/EncounterStatic8NC.cs index 8f340db27..6fac123d4 100644 --- a/PKHeX.Core/Legality/Encounters/Templates/Gen8/EncounterStatic8NC.cs +++ b/PKHeX.Core/Legality/Encounters/Templates/Gen8/EncounterStatic8NC.cs @@ -8,7 +8,7 @@ namespace PKHeX.Core; /// public sealed record EncounterStatic8NC(GameVersion Version) : EncounterStatic8Nest(Version), ILocation { - int ILocation.Location => Watchtower; + ushort ILocation.Location => Watchtower; public const ushort Location = Watchtower; public override string Name => "Watchtower Crystal Den Encounter"; @@ -16,13 +16,13 @@ public sealed record EncounterStatic8NC(GameVersion Version) : EncounterStatic8N protected override bool IsMatchLocation(PKM pk) { - var loc = pk.Met_Location; + var loc = pk.MetLocation; return loc is SharedNest or Watchtower; } protected override bool IsMatchLevel(PKM pk) { - var lvl = pk.Met_Level; + var lvl = pk.MetLevel; if (lvl == Level) return true; @@ -31,7 +31,7 @@ protected override bool IsMatchLevel(PKM pk) return false; if (lvl is < 20 or > 55) return false; - if (pk is { Met_Location: Watchtower, IsShiny: true }) + if (pk is { MetLocation: Watchtower, IsShiny: true }) return false; // host cannot downlevel and be shiny return lvl % 5 == 0; } diff --git a/PKHeX.Core/Legality/Encounters/Templates/Gen8/EncounterStatic8ND.cs b/PKHeX.Core/Legality/Encounters/Templates/Gen8/EncounterStatic8ND.cs index cbe9f0795..ae1e44cba 100644 --- a/PKHeX.Core/Legality/Encounters/Templates/Gen8/EncounterStatic8ND.cs +++ b/PKHeX.Core/Legality/Encounters/Templates/Gen8/EncounterStatic8ND.cs @@ -1,4 +1,5 @@ using System; +using System.Diagnostics.CodeAnalysis; using static PKHeX.Core.Encounters8Nest; using static System.Buffers.Binary.BinaryPrimitives; @@ -16,7 +17,7 @@ public sealed record EncounterStatic8ND : EncounterStatic8Nest $"Distribution Raid Den Encounter - {Index:000}"; - public EncounterStatic8ND(byte lvl, byte dyna, byte flawless, byte index, GameVersion game) : base(game) + public EncounterStatic8ND(byte lvl, byte dyna, byte flawless, byte index, [ConstantExpected] GameVersion game) : base(game) { Level = lvl; DynamaxLevel = dyna; @@ -24,7 +25,7 @@ public EncounterStatic8ND(byte lvl, byte dyna, byte flawless, byte index, GameVe Index = index; } - public static EncounterStatic8ND Read(ReadOnlySpan data, GameVersion game) + public static EncounterStatic8ND Read(ReadOnlySpan data, [ConstantExpected] GameVersion game) { var d = data[13]; var dlvl = (byte)(d & 0x7F); @@ -57,11 +58,11 @@ public static EncounterStatic8ND Read(ReadOnlySpan data, GameVersion game) protected override bool IsMatchLevel(PKM pk) { - var lvl = pk.Met_Level; + var lvl = pk.MetLevel; if (lvl <= 25) // 1 or 2 stars { - var met = pk.Met_Location; + var met = pk.MetLocation; if (met <= byte.MaxValue && InaccessibleRank12DistributionLocations.Contains((byte)met)) return false; } @@ -79,7 +80,7 @@ protected override bool IsMatchLevel(PKM pk) return false; // shared nests can be down-leveled to any - if (pk.Met_Location == SharedNest) + if (pk.MetLocation == SharedNest) return true; // native down-levels: only allow 1 rank down (1 badge 2star -> 25), (3badge 3star -> 35) @@ -92,7 +93,7 @@ protected override bool IsMatchLevel(PKM pk) protected override bool IsMatchLocation(PKM pk) { - var loc = pk.Met_Location; + var loc = pk.MetLocation; return loc is SharedNest || Index switch { >= IndexMinDLC2 => EncounterArea8.IsWildArea(loc), @@ -103,7 +104,7 @@ protected override bool IsMatchLocation(PKM pk) protected override bool IsMatchSeed(PKM pk, ulong seed) { - bool IsDownleveled = pk.Met_Level < Level; + bool IsDownleveled = pk.MetLevel < Level; return Verify(pk, seed, IsDownleveled); } } diff --git a/PKHeX.Core/Legality/Encounters/Templates/Gen8/EncounterStatic8Nest.cs b/PKHeX.Core/Legality/Encounters/Templates/Gen8/EncounterStatic8Nest.cs index b7c3785b2..6e07d8403 100644 --- a/PKHeX.Core/Legality/Encounters/Templates/Gen8/EncounterStatic8Nest.cs +++ b/PKHeX.Core/Legality/Encounters/Templates/Gen8/EncounterStatic8Nest.cs @@ -11,15 +11,15 @@ public abstract record EncounterStatic8Nest(GameVersion Version) : IEncounterable, IEncounterMatch, IEncounterConvertible, IMoveset, ISeedCorrelation64, IFlawlessIVCount, IFixedIVSet, IFixedGender, IDynamaxLevelReadOnly, IGigantamaxReadOnly where T : EncounterStatic8Nest { - public int Generation => 8; + public byte Generation => 8; public EntityContext Context => EntityContext.Gen8; - int ILocation.Location => SharedNest; + ushort ILocation.Location => SharedNest; private const ushort Location = SharedNest; public bool IsShiny => Shiny == Shiny.Always; public bool EggEncounter => false; - int ILocation.EggLocation => 0; + ushort ILocation.EggLocation => 0; public Ball FixedBall => Ball.None; public ushort Species { get; init; } @@ -50,7 +50,7 @@ public abstract record EncounterStatic8Nest(GameVersion Version) public PK8 ConvertToPKM(ITrainerInfo tr, EncounterCriteria criteria) { - var version = this.GetCompatibleVersion((GameVersion)tr.Game); + var version = this.GetCompatibleVersion(tr.Version); int lang = (int)Language.GetSafeLanguage(Generation, (LanguageID)tr.Language, version); var pi = Info; var pk = new PK8 @@ -58,17 +58,17 @@ public PK8 ConvertToPKM(ITrainerInfo tr, EncounterCriteria criteria) Species = Species, Form = Form, CurrentLevel = Level, - Met_Location = GetLocation(), - Met_Level = Level, + MetLocation = GetLocation(), + MetLevel = Level, MetDate = EncounterDate.GetDateSwitch(), Ball = (byte)Ball.Poke, ID32 = tr.ID32, - Version = (byte)version, + Version = version, Language = lang, - OT_Gender = tr.Gender, - OT_Name = tr.OT, - OT_Friendship = pi.BaseFriendship, + OriginalTrainerGender = tr.Gender, + OriginalTrainerName = tr.OT, + OriginalTrainerFriendship = pi.BaseFriendship, Nickname = SpeciesName.GetSpeciesNameGeneration(Species, lang, Generation), @@ -113,8 +113,8 @@ private void SetPINGA(PK8 pk, EncounterCriteria criteria, PersonalInfo8SWSH pi) while (!TryApply(pk, seed = rand.Next(), iv, param, EncounterCriteria.Unrestricted)) { } FinishCorrelation(pk, seed); - if ((byte)criteria.Nature != pk.Nature && criteria.Nature.IsMint()) - pk.StatNature = (byte)criteria.Nature; + if (criteria.IsSpecifiedNature() && criteria.Nature != pk.Nature && criteria.Nature.IsMint()) + pk.StatNature = criteria.Nature; } private GenerateParam8 GetParam(PersonalInfo8SWSH pi) @@ -133,7 +133,7 @@ public bool IsMatchExact(PKM pk, EvoCriteria evo) if (pk is PK8 d && d.DynamaxLevel < DynamaxLevel) return false; - if (Version != GameVersion.SWSH && pk.Version != (int)Version && pk.Met_Location != SharedNest) + if (Version != GameVersion.SWSH && pk.Version != Version && pk.MetLocation != SharedNest) return false; if (pk is IRibbonSetMark8 { HasMarkEncounter8: true }) @@ -160,14 +160,14 @@ public bool IsMatchExact(PKM pk, EvoCriteria evo) return true; } - protected virtual bool IsMatchLocation(PKM pk) => Location == pk.Met_Location; + protected virtual bool IsMatchLocation(PKM pk) => Location == pk.MetLocation; private static bool IsMatchEggLocation(PKM pk) { var expect = pk is PB8 ? Locations.Default8bNone : 0; - return pk.Egg_Location == expect; + return pk.EggLocation == expect; } - protected virtual bool IsMatchLevel(PKM pk) => pk.Met_Level == Level; + protected virtual bool IsMatchLevel(PKM pk) => pk.MetLevel == Level; private bool IsMatchGender(PKM pk) => Gender == FixedGenderUtil.GenderRandom || Gender == pk.Gender; private bool IsMatchForm(PKM pk, EvoCriteria evo) => Form == evo.Form || FormInfo.IsFormChangeable(Species, Form, pk.Form, Context, pk.Context); private bool IsMatchIVs(PKM pk) diff --git a/PKHeX.Core/Legality/Encounters/Templates/Gen8/EncounterStatic8U.cs b/PKHeX.Core/Legality/Encounters/Templates/Gen8/EncounterStatic8U.cs index 2972b8b52..b52b264b0 100644 --- a/PKHeX.Core/Legality/Encounters/Templates/Gen8/EncounterStatic8U.cs +++ b/PKHeX.Core/Legality/Encounters/Templates/Gen8/EncounterStatic8U.cs @@ -10,7 +10,7 @@ namespace PKHeX.Core; /// public sealed record EncounterStatic8U : EncounterStatic8Nest, ILocation { - int ILocation.Location => MaxLair; + ushort ILocation.Location => MaxLair; private const ushort Location = MaxLair; public override string Name => "Max Lair Encounter"; @@ -42,8 +42,8 @@ public static EncounterStatic8U Read(ReadOnlySpan data) protected override ushort GetLocation() => Location; // no downleveling, unlike all other raids - protected override bool IsMatchLevel(PKM pk) => pk.Met_Level == Level; - protected override bool IsMatchLocation(PKM pk) => Location == pk.Met_Location; + protected override bool IsMatchLevel(PKM pk) => pk.MetLevel == Level; + protected override bool IsMatchLocation(PKM pk) => Location == pk.MetLocation; public bool IsShinyXorValid(ushort pkShinyXor) => pkShinyXor is > 15 or 1; @@ -62,7 +62,7 @@ public void ApplyTrashBytes(PKM pk) { // Normally we would apply the trash before applying the OT, but we already did. // Just add in the expected trash after the OT. - var ot = pk.OT_Trash; + var ot = pk.OriginalTrainerTrash; var language = pk.Language; var scientist = GetScientistName(language); StringConverter8.ApplyTrashBytes(ot, scientist); @@ -72,7 +72,7 @@ public static TrashMatch HasScientistTrash(PKM pk) { var language = pk.Language; var name = GetScientistName(language); - return StringConverter8.GetTrashState(pk.OT_Trash, name); + return StringConverter8.GetTrashState(pk.OriginalTrainerTrash, name); } private static ReadOnlySpan GetScientistName(int language) => language switch diff --git a/PKHeX.Core/Legality/Encounters/Templates/Gen8/EncounterTrade8.cs b/PKHeX.Core/Legality/Encounters/Templates/Gen8/EncounterTrade8.cs index 0a79005a8..da09a1c69 100644 --- a/PKHeX.Core/Legality/Encounters/Templates/Gen8/EncounterTrade8.cs +++ b/PKHeX.Core/Legality/Encounters/Templates/Gen8/EncounterTrade8.cs @@ -8,15 +8,15 @@ namespace PKHeX.Core; /// public sealed record EncounterTrade8 : IEncounterable, IEncounterMatch, IFixedTrainer, IFixedNickname, IEncounterConvertible, IDynamaxLevelReadOnly, IRelearn, IMemoryOTReadOnly, IFlawlessIVCount, IFixedGender, IFixedNature { - public int Generation => 8; + public byte Generation => 8; public EntityContext Context => EntityContext.Gen8; - public int Location => Locations.LinkTrade6NPC; + public ushort Location => Locations.LinkTrade6NPC; public Moveset Relearn { get; init; } - public ushort OT_TextVar { get; } - public byte OT_Memory { get; } - public byte OT_Feeling { get; } - public byte OT_Intensity { get; } + public ushort OriginalTrainerMemoryVariable { get; } + public byte OriginalTrainerMemory { get; } + public byte OriginalTrainerMemoryFeeling { get; } + public byte OriginalTrainerMemoryIntensity { get; } public byte DynamaxLevel { get; init; } public byte FlawlessIVCount { get; init; } public Shiny Shiny { get; } @@ -24,7 +24,7 @@ public sealed record EncounterTrade8 : IEncounterable, IEncounterMatch, IFixedTr public bool EggEncounter => false; public Ball FixedBall => Ball.Poke; public bool IsShiny => false; - public int EggLocation => 0; + public ushort EggLocation => 0; public bool IsFixedTrainer => true; public bool IsFixedNickname { get; } @@ -60,10 +60,10 @@ public EncounterTrade8(ReadOnlySpan names, byte index, GameVersion gam Level = level; Shiny = Shiny.Never; - OT_Memory = memory; - OT_TextVar = arg; - OT_Feeling = feel; - OT_Intensity = intensity; + OriginalTrainerMemory = memory; + OriginalTrainerMemoryVariable = arg; + OriginalTrainerMemoryFeeling = feel; + OriginalTrainerMemoryIntensity = intensity; IsFixedNickname = true; } @@ -77,10 +77,10 @@ public EncounterTrade8(string[] trainerNames, GameVersion game, ushort species, Level = level; Shiny = Shiny.Random; - OT_Memory = memory; - OT_TextVar = arg; - OT_Feeling = feel; - OT_Intensity = intensity; + OriginalTrainerMemory = memory; + OriginalTrainerMemoryVariable = arg; + OriginalTrainerMemoryFeeling = feel; + OriginalTrainerMemoryIntensity = intensity; IsFixedNickname = false; Gender = FixedGenderUtil.GenderRandom; Nature = Nature.Random; @@ -95,42 +95,43 @@ public EncounterTrade8(string[] trainerNames, GameVersion game, ushort species, public PK8 ConvertToPKM(ITrainerInfo tr, EncounterCriteria criteria) { - var version = this.GetCompatibleVersion((GameVersion)tr.Game); + var version = this.GetCompatibleVersion(tr.Version); int lang = (int)Language.GetSafeLanguage(Generation, (LanguageID)tr.Language, version); var pi = PersonalTable.SWSH[Species, Form]; + var rnd = Util.Rand; var pk = new PK8 { - PID = Util.Rand32(), - EncryptionConstant = Util.Rand32(), + PID = rnd.Rand32(), + EncryptionConstant = rnd.Rand32(), Species = Species, Form = Form, CurrentLevel = Level, - Met_Location = Location, - Met_Level = Level, + MetLocation = Location, + MetLevel = Level, MetDate = EncounterDate.GetDateSwitch(), Ball = (byte)FixedBall, Gender = Gender, ID32 = ID32, - Version = (byte)version, + Version = version, Language = lang, - OT_Gender = OTGender, - OT_Name = TrainerNames[lang], + OriginalTrainerGender = OTGender, + OriginalTrainerName = TrainerNames[lang], - OT_Memory = OT_Memory, - OT_Intensity = OT_Intensity, - OT_Feeling = OT_Feeling, - OT_TextVar = OT_TextVar, - OT_Friendship = pi.BaseFriendship, + OriginalTrainerMemory = OriginalTrainerMemory, + OriginalTrainerMemoryIntensity = OriginalTrainerMemoryIntensity, + OriginalTrainerMemoryFeeling = OriginalTrainerMemoryFeeling, + OriginalTrainerMemoryVariable = OriginalTrainerMemoryVariable, + OriginalTrainerFriendship = pi.BaseFriendship, IsNicknamed = IsFixedNickname, Nickname = IsFixedNickname ? Nicknames[lang] : SpeciesName.GetSpeciesNameGeneration(Species, lang, Generation), DynamaxLevel = DynamaxLevel, - HT_Name = tr.OT, - HT_Gender = tr.Gender, - HT_Language = (byte)tr.Language, + HandlingTrainerName = tr.OT, + HandlingTrainerGender = tr.Gender, + HandlingTrainerLanguage = (byte)tr.Language, CurrentHandler = 1, - HT_Friendship = pi.BaseFriendship, + HandlingTrainerFriendship = pi.BaseFriendship, }; if (Shiny == Shiny.Never && pk.IsShiny) pk.PID ^= 0x1000_0000u; @@ -146,8 +147,8 @@ public PK8 ConvertToPKM(ITrainerInfo tr, EncounterCriteria criteria) private void SetPINGA(PK8 pk, EncounterCriteria criteria, PersonalInfo8SWSH pi) { - int gender = criteria.GetGender(Gender, pi); - int nature = (int)criteria.GetNature(Nature); + var gender = criteria.GetGender(Gender, pi); + var nature = criteria.GetNature(Nature); int ability = criteria.GetAbilityFromNumber(Ability); pk.Nature = pk.StatNature = nature; pk.Gender = gender; @@ -168,7 +169,7 @@ private void SetPINGA(PK8 pk, EncounterCriteria criteria, PersonalInfo8SWSH pi) public bool IsMatchExact(PKM pk, EvoCriteria evo) { - if (pk.Met_Level != Level) + if (pk.MetLevel != Level) return false; if (IVs.IsSpecified) { @@ -185,7 +186,7 @@ public bool IsMatchExact(PKM pk, EvoCriteria evo) return false; if (evo.Form != Form && !FormInfo.IsFormChangeable(Species, Form, pk.Form, Context, pk.Context)) return false; - if (pk.OT_Gender != OTGender) + if (pk.OriginalTrainerGender != OTGender) return false; if (!IsMatchEggLocation(pk)) return false; @@ -197,14 +198,14 @@ private bool IsMatchEggLocation(PKM pk) var expect = EggLocation; if (pk is PB8) expect = Locations.Default8bNone; - return pk.Egg_Location == expect; + return pk.EggLocation == expect; } private bool IsMatchNatureGenderShiny(PKM pk) { if (!Shiny.IsValid(pk)) return false; - if (Nature != Nature.Random && pk.Nature != (int)Nature) + if (Nature != Nature.Random && pk.Nature != Nature) return false; if (Gender != FixedGenderUtil.GenderRandom && pk.Gender != Gender) return false; diff --git a/PKHeX.Core/Legality/Encounters/Templates/Gen8/AreaSlotType8.cs b/PKHeX.Core/Legality/Encounters/Templates/Gen8/SlotType8.cs similarity index 52% rename from PKHeX.Core/Legality/Encounters/Templates/Gen8/AreaSlotType8.cs rename to PKHeX.Core/Legality/Encounters/Templates/Gen8/SlotType8.cs index db36081f3..caab8393b 100644 --- a/PKHeX.Core/Legality/Encounters/Templates/Gen8/AreaSlotType8.cs +++ b/PKHeX.Core/Legality/Encounters/Templates/Gen8/SlotType8.cs @@ -1,4 +1,4 @@ -using static PKHeX.Core.AreaSlotType8; +using static PKHeX.Core.SlotType8; using static PKHeX.Core.AreaWeather8; namespace PKHeX.Core; @@ -6,7 +6,7 @@ namespace PKHeX.Core; /// /// Encounter Slot Types for /// -public enum AreaSlotType8 : byte +public enum SlotType8 : byte { SymbolMain, SymbolMain2, @@ -28,11 +28,11 @@ public enum AreaSlotType8 : byte } /// -/// Extension methods for . +/// Extension methods for . /// -public static class AreaSlotType8Extensions +public static class SlotType8Extensions { - public static bool CanCrossover(this AreaSlotType8 type) => type is not (HiddenMain or HiddenMain2 or OnlyFishing); - public static bool CanEncounterViaFishing(this AreaSlotType8 type, AreaWeather8 weather) => type is OnlyFishing || weather.HasFlag(Fishing); - public static bool CanEncounterViaCurry(this AreaSlotType8 type) => type is HiddenMain or HiddenMain2; + public static bool CanCrossover(this SlotType8 type) => type is not (HiddenMain or HiddenMain2 or OnlyFishing); + public static bool CanEncounterViaFishing(this SlotType8 type, AreaWeather8 weather) => type is OnlyFishing || weather.HasFlag(Fishing); + public static bool CanEncounterViaCurry(this SlotType8 type) => type is HiddenMain or HiddenMain2; } diff --git a/PKHeX.Core/Legality/Encounters/Templates/Gen8a/EncounterArea8a.cs b/PKHeX.Core/Legality/Encounters/Templates/Gen8a/EncounterArea8a.cs index 07b6e870b..974d66bd2 100644 --- a/PKHeX.Core/Legality/Encounters/Templates/Gen8a/EncounterArea8a.cs +++ b/PKHeX.Core/Legality/Encounters/Templates/Gen8a/EncounterArea8a.cs @@ -3,6 +3,15 @@ namespace PKHeX.Core; +public enum SlotType8a : byte +{ + Standard = 0, + Distortion = 1, + Landmark = 2, + MassOutbreakRegular = 3, + MassOutbreakMassive = 4, +} + /// /// encounter area /// @@ -12,11 +21,11 @@ public sealed record EncounterArea8a : IEncounterArea, IAreaLoc public GameVersion Version => GameVersion.PLA; private readonly byte[] Locations; - public readonly SlotType Type; + public readonly SlotType8a Type; - public int Location => Locations[0]; + public ushort Location => Locations[0]; - public bool IsMatchLocation(int location) + public bool IsMatchLocation(ushort location) { return Array.IndexOf(Locations, (byte)location) != -1; } @@ -32,14 +41,13 @@ public static EncounterArea8a[] GetAreas(BinLinkerAccessor input) private EncounterArea8a(ReadOnlySpan areaData) { // Area Metadata - int locationCount = areaData[0]; + var locationCount = areaData[0]; Locations = areaData.Slice(1, locationCount).ToArray(); - int align = (locationCount + 1); - if ((align & 1) == 1) - align++; + var align = (locationCount + 1); + align += align & 1; // ensure alignment is even areaData = areaData[align..]; - Type = areaData[0] + SlotType.Overworld; + Type = (SlotType8a)areaData[0]; var count = areaData[1]; var slots = areaData[2..]; diff --git a/PKHeX.Core/Legality/Encounters/Templates/Gen8a/EncounterSlot8a.cs b/PKHeX.Core/Legality/Encounters/Templates/Gen8a/EncounterSlot8a.cs index fe4c18305..c38e60b4c 100644 --- a/PKHeX.Core/Legality/Encounters/Templates/Gen8a/EncounterSlot8a.cs +++ b/PKHeX.Core/Legality/Encounters/Templates/Gen8a/EncounterSlot8a.cs @@ -10,26 +10,24 @@ namespace PKHeX.Core; public sealed record EncounterSlot8a(EncounterArea8a Parent, ushort Species, byte Form, byte LevelMin, byte LevelMax, byte AlphaType, byte FlawlessIVCount, Gender Gender) : IEncounterable, IEncounterMatch, IEncounterConvertible, IAlphaReadOnly, IMasteryInitialMoveShop8, IFlawlessIVCount { - public int Generation => 8; + public byte Generation => 8; public EntityContext Context => EntityContext.Gen8a; public bool EggEncounter => false; public AbilityPermission Ability => AbilityPermission.Any12; public Ball FixedBall => Ball.None; public Shiny Shiny => Shiny.Random; public bool IsShiny => false; - public int EggLocation => 0; + public ushort EggLocation => 0; public bool IsAlpha => AlphaType is not 0; public string Name => $"Wild Encounter ({Version})"; public string LongName => $"{Name} {Type.ToString().Replace('_', ' ')}"; public GameVersion Version => Parent.Version; - public int Location => Parent.Location; - public SlotType Type => Parent.Type; + public ushort Location => Parent.Location; + public SlotType8a Type => Parent.Type; - public bool HasAlphaMove => IsAlpha && Type is not SlotType.Landmark; - - private const byte ScaleMax = 255; + public bool HasAlphaMove => IsAlpha && Type is not SlotType8a.Landmark; #region Generating PKM IEncounterConvertible.ConvertToPKM(ITrainerInfo tr, EncounterCriteria criteria) => ConvertToPKM(tr, criteria); @@ -45,20 +43,17 @@ public PA8 ConvertToPKM(ITrainerInfo tr, EncounterCriteria criteria) Species = Species, Form = Form, CurrentLevel = LevelMin, - Met_Location = Location, - Met_Level = LevelMin, + MetLocation = Location, + MetLevel = LevelMin, MetDate = EncounterDate.GetDateSwitch(), - Version = (byte)GameVersion.PLA, + Version = GameVersion.PLA, IsAlpha = IsAlpha, Ball = (int)Ball.LAPoke, - OT_Name = tr.OT, - OT_Gender = tr.Gender, + OriginalTrainerName = tr.OT, + OriginalTrainerGender = tr.Gender, ID32 = tr.ID32, - OT_Friendship = pi.BaseFriendship, - - HeightScalar = IsAlpha ? ScaleMax : PokeSizeUtil.GetRandomScalar(), - WeightScalar = IsAlpha ? ScaleMax : PokeSizeUtil.GetRandomScalar(), + OriginalTrainerFriendship = pi.BaseFriendship, Nickname = SpeciesName.GetSpeciesNameGeneration(Species, lang, Generation), }; SetPINGA(pk, criteria, pi); @@ -82,7 +77,7 @@ private void SetPINGA(PA8 pk, EncounterCriteria criteria, PersonalInfo8LA pi) var lvl = Overworld8aRNG.GetRandomLevel(slotSeed, LevelMin, LevelMax); if (criteria.ForceMinLevelRange && lvl != LevelMin) continue; - pk.CurrentLevel = pk.Met_Level = lvl; + pk.MetLevel = pk.CurrentLevel = lvl; } break; } @@ -105,10 +100,10 @@ private OverworldParam8a GetParams(PersonalInfo8LA pi) => new() // hardcoded 7 to assume max dex progress + shiny charm. private const int MaxRollCount = 7; - private static byte GetRollCount(SlotType type) => (byte)(MaxRollCount + type switch + private static byte GetRollCount(SlotType8a type) => (byte)(MaxRollCount + type switch { - SlotType.OverworldMMO => 12, - SlotType.OverworldMass => 25, + SlotType8a.MassOutbreakMassive => 12, + SlotType8a.MassOutbreakRegular => 25, _ => 0, }); @@ -144,7 +139,7 @@ public void LoadInitialMoveset(PA8 pa8, Span moves, Learnset learn, int public bool IsMatchExact(PKM pk, EvoCriteria evo) { - if (!this.IsLevelWithinRange(pk.Met_Level)) + if (!this.IsLevelWithinRange(pk.MetLevel)) return false; if (Form != evo.Form && Species is not ((int)Core.Species.Rotom or (int)Core.Species.Burmy or (int)Core.Species.Wormadam)) return false; @@ -187,7 +182,7 @@ private EncounterMatchRating GetMoveCompatibility(PKM pk) var alphaMove = pa.AlphaMove; bool hasAlphaMove = alphaMove != 0; - if (!pa.IsAlpha || Type is SlotType.Landmark) + if (!pa.IsAlpha || Type is SlotType8a.Landmark) return !hasAlphaMove ? EncounterMatchRating.Match : EncounterMatchRating.DeferredErrors; var pi = PersonalTable.LA.GetFormEntry(Species, Form); @@ -217,8 +212,8 @@ public bool IsForcedMasteryCorrect(PKM pk) if (pk is not IMoveShop8Mastery p) return true; // Can't check. - bool allowAlphaPurchaseBug = Type is not SlotType.OverworldMMO; // Everything else Alpha is pre-1.1 - var level = pk.Met_Level; + bool allowAlphaPurchaseBug = Type is not SlotType8a.MassOutbreakMassive; // Everything else Alpha is pre-1.1 + var level = pk.MetLevel; var (learn, mastery) = GetLevelUpInfo(); ushort alpha = pk is PA8 pa ? pa.AlphaMove : (ushort)0; if (!p.IsValidPurchasedEncounter(learn, level, alpha, allowAlphaPurchaseBug)) diff --git a/PKHeX.Core/Legality/Encounters/Templates/Gen8a/EncounterStatic8a.cs b/PKHeX.Core/Legality/Encounters/Templates/Gen8a/EncounterStatic8a.cs index 68a0221c4..612e75749 100644 --- a/PKHeX.Core/Legality/Encounters/Templates/Gen8a/EncounterStatic8a.cs +++ b/PKHeX.Core/Legality/Encounters/Templates/Gen8a/EncounterStatic8a.cs @@ -8,11 +8,11 @@ namespace PKHeX.Core; public sealed record EncounterStatic8a : IEncounterable, IEncounterMatch, IEncounterConvertible, IAlphaReadOnly, IMasteryInitialMoveShop8, IScaledSizeReadOnly, IMoveset, IFlawlessIVCount, IFatefulEncounterReadOnly, IFixedGender { - public int Generation => 8; + public byte Generation => 8; public EntityContext Context => EntityContext.Gen8a; public GameVersion Version => GameVersion.PLA; - public int EggLocation => 0; - int ILocation.Location => Location; + public ushort EggLocation => 0; + ushort ILocation.Location => Location; public bool IsShiny => Shiny == Shiny.Always; public bool EggEncounter => false; public AbilityPermission Ability => AbilityPermission.Any12; @@ -65,15 +65,15 @@ public PA8 ConvertToPKM(ITrainerInfo tr, EncounterCriteria criteria) Species = Species, Form = Form, CurrentLevel = LevelMin, - OT_Friendship = pi.BaseFriendship, + OriginalTrainerFriendship = pi.BaseFriendship, FatefulEncounter = FatefulEncounter, - Met_Location = Location, - Met_Level = LevelMin, + MetLocation = Location, + MetLevel = LevelMin, MetDate = EncounterDate.GetDateSwitch(), - Version = (byte)Version, + Version = Version, - OT_Name = tr.OT, - OT_Gender = tr.Gender, + OriginalTrainerName = tr.OT, + OriginalTrainerGender = tr.Gender, ID32 = tr.ID32, IsAlpha = IsAlpha, @@ -83,7 +83,7 @@ public PA8 ConvertToPKM(ITrainerInfo tr, EncounterCriteria criteria) SetPINGA(pk, criteria); pk.ResetHeight(); pk.ResetWeight(); - SetEncounterMoves(pk, (byte)pk.Met_Level); + SetEncounterMoves(pk, pk.MetLevel); if (IsAlpha) pk.IsAlpha = true; @@ -98,7 +98,7 @@ private void SetPINGA(PA8 pk, EncounterCriteria criteria) var (_, slotSeed) = Overworld8aRNG.ApplyDetails(pk, criteria, para, IsAlpha); // Phione and Zorua have random levels; follow the correlation instead of giving the lowest level. if (LevelMin != LevelMax) - pk.CurrentLevel = pk.Met_Level = Overworld8aRNG.GetRandomLevel(slotSeed, LevelMin, LevelMax); + pk.MetLevel = pk.CurrentLevel = Overworld8aRNG.GetRandomLevel(slotSeed, LevelMin, LevelMax); // Disassociate the correlation if it is supposed to use the global 128-bit RNG state instead. if (Method == EncounterStatic8aCorrelation.Fixed) @@ -165,7 +165,7 @@ private byte GetGenderRatioPersonal() #region Matching public bool IsMatchExact(PKM pk, EvoCriteria evo) { - if (!this.IsLevelWithinRange(pk.Met_Level)) + if (!this.IsLevelWithinRange(pk.MetLevel)) return false; if (Gender != FixedGenderUtil.GenderRandom && pk.Gender != Gender) return false; @@ -222,20 +222,20 @@ public bool IsMatchExact(PKM pk, EvoCriteria evo) private bool IsMatchEggLocation(PKM pk) { var expect = pk is PB8 ? Locations.Default8bNone : EggLocation; - return pk.Egg_Location == expect; + return pk.EggLocation == expect; } private bool IsMatchLocation(PKM pk) { var metState = LocationsHOME.GetRemapState(Context, pk.Context); if (metState == LocationRemapState.Original) - return pk.Met_Location == Location; + return pk.MetLocation == Location; if (metState == LocationRemapState.Remapped) return IsMetRemappedSWSH(pk); - return pk.Met_Location == Location || IsMetRemappedSWSH(pk); + return pk.MetLocation == Location || IsMetRemappedSWSH(pk); } - private static bool IsMetRemappedSWSH(PKM pk) => pk.Met_Location == LocationsHOME.SWLA; + private static bool IsMetRemappedSWSH(PKM pk) => pk.MetLocation == LocationsHOME.SWLA; public EncounterMatchRating GetMatchRating(PKM pk) { @@ -269,7 +269,7 @@ public bool IsForcedMasteryCorrect(PKM pk) return true; const bool allowAlphaPurchaseBug = true; // Everything else Alpha is pre-1.1 - var level = pk.Met_Level; + var level = pk.MetLevel; var (learn, mastery) = GetLevelUpInfo(); if (!p.IsValidPurchasedEncounter(learn, level, alpha, allowAlphaPurchaseBug)) return false; diff --git a/PKHeX.Core/Legality/Encounters/Templates/Gen8a/IMasteryInitialMoveShop8.cs b/PKHeX.Core/Legality/Encounters/Templates/Gen8a/IMasteryInitialMoveShop8.cs index b23aa24da..d44833213 100644 --- a/PKHeX.Core/Legality/Encounters/Templates/Gen8a/IMasteryInitialMoveShop8.cs +++ b/PKHeX.Core/Legality/Encounters/Templates/Gen8a/IMasteryInitialMoveShop8.cs @@ -19,7 +19,7 @@ void SetInitialMastery(PKM pk) void SetInitialMastery(PA8 pk) { Span moves = stackalloc ushort[4]; - var level = pk.Met_Level; + var level = pk.MetLevel; var (learn, mastery) = LearnSource8LA.GetLearnsetAndMastery(pk.Species, pk.Form); LoadInitialMoveset(pk, moves, learn, level); pk.SetEncounterMasteryFlags(moves, mastery, level); diff --git a/PKHeX.Core/Legality/Encounters/Templates/Gen8b/EncounterArea8b.cs b/PKHeX.Core/Legality/Encounters/Templates/Gen8b/EncounterArea8b.cs index a6787ac5e..d10d42515 100644 --- a/PKHeX.Core/Legality/Encounters/Templates/Gen8b/EncounterArea8b.cs +++ b/PKHeX.Core/Legality/Encounters/Templates/Gen8b/EncounterArea8b.cs @@ -1,5 +1,7 @@ using System; +using System.Diagnostics.CodeAnalysis; using static System.Buffers.Binary.BinaryPrimitives; +using static PKHeX.Core.SlotType8b; namespace PKHeX.Core; @@ -12,9 +14,9 @@ public sealed record EncounterArea8b : IEncounterArea, IAreaLoc public GameVersion Version { get; } public readonly ushort Location; - public readonly SlotType Type; + public readonly SlotType8b Type; - public static EncounterArea8b[] GetAreas(BinLinkerAccessor input, GameVersion game) + public static EncounterArea8b[] GetAreas(BinLinkerAccessor input, [ConstantExpected] GameVersion game) { var result = new EncounterArea8b[input.Length]; for (int i = 0; i < result.Length; i++) @@ -22,23 +24,23 @@ public static EncounterArea8b[] GetAreas(BinLinkerAccessor input, GameVersion ga return result; } - private EncounterArea8b(ReadOnlySpan data, GameVersion game) + private EncounterArea8b(ReadOnlySpan data, [ConstantExpected] GameVersion game) { Location = ReadUInt16LittleEndian(data); - Type = (SlotType)data[2]; + Type = (SlotType8b)data[2]; Version = game; - Slots = ReadSlots(data); + Slots = ReadSlots(data[4..]); } private EncounterSlot8b[] ReadSlots(ReadOnlySpan data) { const int size = 4; - int count = (data.Length - 4) / size; + int count = data.Length / size; var slots = new EncounterSlot8b[count]; for (int i = 0; i < slots.Length; i++) { - int offset = 4 + (size * i); + int offset = size * i; var entry = data.Slice(offset, size); slots[i] = ReadSlot(entry); } @@ -55,16 +57,16 @@ private EncounterSlot8b ReadSlot(ReadOnlySpan data) return new EncounterSlot8b(this, species, form, min, max); } - public bool IsMatchLocation(int location) + public bool IsMatchLocation(ushort location) { if (location == Location) return true; return CanCrossoverTo(location); } - private bool CanCrossoverTo(int location) + private bool CanCrossoverTo(ushort location) { - if (Type is SlotType.Surf) + if (Type is Surf) { return Location switch { @@ -126,3 +128,22 @@ private static bool IsMunchlaxTree(ReadOnlySpan trees, ushort location) 253, // 20 Floaroma Meadow ]; } + + +public enum SlotType8b : byte +{ + // Unused; relic from previous PKHeX codebase and pkl not updated to remove. + Any = 0, + + Grass = 1, + Surf = 2, + Old_Rod = 3, + Good_Rod = 4, + Super_Rod = 5, + Rock_Smash = 6, + + // Unused; relic from previous PKHeX codebase and pkl not updated to remove. + Headbutt = 7, + + HoneyTree = 8, +} diff --git a/PKHeX.Core/Legality/Encounters/Templates/Gen8b/EncounterSlot8b.cs b/PKHeX.Core/Legality/Encounters/Templates/Gen8b/EncounterSlot8b.cs index 0dc784794..18a675841 100644 --- a/PKHeX.Core/Legality/Encounters/Templates/Gen8b/EncounterSlot8b.cs +++ b/PKHeX.Core/Legality/Encounters/Templates/Gen8b/EncounterSlot8b.cs @@ -1,4 +1,5 @@ using System; +using static PKHeX.Core.SlotType8b; namespace PKHeX.Core; @@ -8,12 +9,12 @@ namespace PKHeX.Core; public sealed record EncounterSlot8b(EncounterArea8b Parent, ushort Species, byte Form, byte LevelMin, byte LevelMax) : IEncounterable, IEncounterMatch, IEncounterConvertible { - public int Generation => 8; + public byte Generation => 8; public EntityContext Context => EntityContext.Gen8b; public bool EggEncounter => false; public Shiny Shiny => Shiny.Random; public bool IsShiny => false; - public int EggLocation => 0; + public ushort EggLocation => 0; public bool IsUnderground => Locations8b.IsUnderground(Parent.Location); public bool IsMarsh => Locations8b.IsMarsh(Parent.Location); public Ball FixedBall => GetRequiredBall(); @@ -22,12 +23,12 @@ public sealed record EncounterSlot8b(EncounterArea8b Parent, ushort Species, byt public string Name => $"Wild Encounter ({Version})"; public string LongName => $"{Name} {Type.ToString().Replace('_', ' ')}"; public GameVersion Version => Parent.Version; - public int Location => Parent.Location; - public SlotType Type => Parent.Type; + public ushort Location => Parent.Location; + public SlotType8b Type => Parent.Type; - public bool CanUseRadar => Type is SlotType.Grass && !IsUnderground && !IsMarsh && CanUseRadarOverworld(Location); + public bool CanUseRadar => Type is Grass && !IsUnderground && !IsMarsh && CanUseRadarOverworld(Location); - private static bool CanUseRadarOverworld(int location) => location switch + private static bool CanUseRadarOverworld(ushort location) => location switch { 195 or 196 => false, // Oreburgh Mine 203 or 204 or 205 or 208 or 209 or 210 or 211 or 212 or 213 or 214 or 215 => false, // Mount Coronet, 206/207 exterior @@ -71,18 +72,18 @@ public PB8 ConvertToPKM(ITrainerInfo tr, EncounterCriteria criteria) Species = Species, Form = Form, CurrentLevel = LevelMin, - Met_Location = Location, - Met_Level = LevelMin, - Version = (byte)Version, + MetLocation = Location, + MetLevel = LevelMin, + Version = Version, MetDate = EncounterDate.GetDateSwitch(), Ball = (byte)GetRequiredBall(Ball.Poke), Language = lang, - OT_Name = tr.OT, - OT_Gender = tr.Gender, + OriginalTrainerName = tr.OT, + OriginalTrainerGender = tr.Gender, ID32 = tr.ID32, Nickname = SpeciesName.GetSpeciesNameGeneration(Species, lang, Generation), - OT_Friendship = pi.BaseFriendship, + OriginalTrainerFriendship = pi.BaseFriendship, }; SetPINGA(pk, criteria, pi); EncounterUtil.SetEncounterMoves(pk, Version, LevelMin); @@ -94,10 +95,11 @@ public PB8 ConvertToPKM(ITrainerInfo tr, EncounterCriteria criteria) private void SetPINGA(PB8 pk, EncounterCriteria criteria, PersonalInfo8BDSP pi) { - pk.PID = Util.Rand32(); - pk.EncryptionConstant = Util.Rand32(); + var rnd = Util.Rand; + pk.PID = rnd.Rand32(); + pk.EncryptionConstant = rnd.Rand32(); criteria.SetRandomIVs(pk); - pk.Nature = pk.StatNature = (int)criteria.GetNature(); + pk.Nature = pk.StatNature = criteria.GetNature(); pk.Gender = criteria.GetGender(pi); pk.RefreshAbility(criteria.GetAbilityFromNumber(Ability)); } @@ -129,7 +131,7 @@ private static bool GetBaseEggMove(out ushort move, PersonalInfo8BDSP pi) public bool IsMatchExact(PKM pk, EvoCriteria evo) { - if (!this.IsLevelWithinRange(pk.Met_Level)) + if (!this.IsLevelWithinRange(pk.MetLevel)) return false; if (Form != evo.Form && Species is not (int)Core.Species.Burmy) @@ -145,7 +147,7 @@ public bool IsMatchExact(PKM pk, EvoCriteria evo) public bool IsInvalidMunchlaxTree(PKM pk) { - if (Type is not SlotType.HoneyTree) + if (Type is not HoneyTree) return false; return Species == (int)Core.Species.Munchlax && !Parent.IsMunchlaxTree(pk); } diff --git a/PKHeX.Core/Legality/Encounters/Templates/Gen8b/EncounterStatic8b.cs b/PKHeX.Core/Legality/Encounters/Templates/Gen8b/EncounterStatic8b.cs index ba1f51b9f..fd04dc75e 100644 --- a/PKHeX.Core/Legality/Encounters/Templates/Gen8b/EncounterStatic8b.cs +++ b/PKHeX.Core/Legality/Encounters/Templates/Gen8b/EncounterStatic8b.cs @@ -9,10 +9,10 @@ namespace PKHeX.Core; public sealed record EncounterStatic8b(GameVersion Version) : IEncounterable, IEncounterMatch, IEncounterConvertible, IFlawlessIVCount, IFatefulEncounterReadOnly, IStaticCorrelation8b { - public int Generation => 8; + public byte Generation => 8; public EntityContext Context => EntityContext.Gen8b; - int ILocation.EggLocation => EggLocation; - int ILocation.Location => Location; + ushort ILocation.EggLocation => EggLocation; + ushort ILocation.Location => Location; public bool EggEncounter => EggLocation != None; private const ushort None = Locations.Default8bNone; public byte Form => 0; @@ -44,7 +44,7 @@ public bool IsStaticCorrelationCorrect(PKM pk) } // defined by mvpoke in encounter data - private static ReadOnlySpan Roaming_MetLocation_BDSP => + private static ReadOnlySpan RoamingLocations => [ 197, 201, 354, 355, 356, 357, 358, 359, 361, 362, 364, 365, 367, 373, 375, 377, 378, 379, 383, 385, 392, 394, 395, 397, 400, 403, 404, 407, @@ -60,38 +60,36 @@ public bool IsStaticCorrelationCorrect(PKM pk) public PB8 ConvertToPKM(ITrainerInfo tr, EncounterCriteria criteria) { - var version = this.GetCompatibleVersion((GameVersion)tr.Game); + var version = this.GetCompatibleVersion(tr.Version); int lang = (int)Language.GetSafeLanguage(Generation, (LanguageID)tr.Language, version); var pi = PersonalTable.BDSP[Species, Form]; var pk = new PB8 { Species = Species, CurrentLevel = Level, - Met_Location = Location, - Egg_Location = EggLocation, - Met_Level = Level, + MetLocation = Location, + EggLocation = EggLocation, + MetLevel = Level, MetDate = EncounterDate.GetDateSwitch(), Ball = (byte)(FixedBall != Ball.None ? FixedBall : Ball.Poke), FatefulEncounter = FatefulEncounter, ID32 = tr.ID32, - Version = (byte)version, + Version = version, Language = lang, - OT_Gender = tr.Gender, - OT_Name = tr.OT, - OT_Friendship = pi.BaseFriendship, + OriginalTrainerGender = tr.Gender, + OriginalTrainerName = tr.OT, + OriginalTrainerFriendship = pi.BaseFriendship, Nickname = SpeciesName.GetSpeciesNameGeneration(Species, lang, Generation), - HeightScalar = PokeSizeUtil.GetRandomScalar(), - WeightScalar = PokeSizeUtil.GetRandomScalar(), }; if (EggEncounter) { // Fake as hatched. - pk.Met_Location = Locations.HatchLocation8b; - pk.Met_Level = EggStateLegality.EggMetLevel; - pk.Egg_Location = EggLocation; + pk.MetLocation = Locations.HatchLocation8b; + pk.MetLevel = EggStateLegality.EggMetLevel; + pk.EggLocation = EggLocation; pk.EggMetDate = pk.MetDate; } @@ -126,7 +124,7 @@ private void SetPINGA(PB8 pk, EncounterCriteria criteria) public bool IsMatchExact(PKM pk, EvoCriteria evo) { - if (pk.Met_Level != Level) + if (pk.MetLevel != Level) return false; if (!IsMatchLocation(pk)) return false; @@ -152,32 +150,32 @@ private bool IsMatchLocation(PKM pk) private bool IsMatchLocationExact(PKM pk) { if (EggEncounter) - return !pk.IsEgg || pk.Met_Location == Location || pk.Met_Location == Locations.LinkTrade6NPC; + return !pk.IsEgg || pk.MetLocation == Location || pk.MetLocation == Locations.LinkTrade6NPC; if (!Roaming) - return pk.Met_Location == Location; + return pk.MetLocation == Location; return IsRoamingLocation(pk); } private bool IsMatchEggLocationExact(PKM pk) { - var eggloc = pk.Egg_Location; + var eggLoc = pk.EggLocation; if (!EggEncounter) - return eggloc == EggLocation; + return eggLoc == EggLocation; if (!pk.IsEgg) // hatched - return eggloc == EggLocation || eggloc == Locations.LinkTrade6NPC; + return eggLoc == EggLocation || eggLoc == Locations.LinkTrade6NPC; // Unhatched: - if (eggloc != EggLocation) + if (eggLoc != EggLocation) return false; - if (pk.Met_Location is not (Locations.Default8bNone or Locations.LinkTrade6NPC)) + if (pk.MetLocation is not (Locations.Default8bNone or Locations.LinkTrade6NPC)) return false; return true; } private bool IsMatchLocationRemapped(PKM pk) { - var met = (ushort)pk.Met_Location; + var met = pk.MetLocation; var version = pk.Version; if (pk.Context == EntityContext.Gen8) return LocationsHOME.IsValidMetBDSP(met, version); @@ -198,11 +196,11 @@ private bool IsMatchEggLocation(PKM pk) private bool IsMatchEggLocationRemapped(PKM pk) { if (!EggEncounter) - return pk.Egg_Location == 0; - return LocationsHOME.IsLocationSWSHEgg(pk.Version, pk.Met_Location, pk.Egg_Location, EggLocation); + return pk.EggLocation == 0; + return LocationsHOME.IsLocationSWSHEgg(pk.Version, pk.MetLocation, pk.EggLocation, EggLocation); } - private static bool IsRoamingLocation(PKM pk) => Roaming_MetLocation_BDSP.Contains((ushort)pk.Met_Location); + private static bool IsRoamingLocation(PKM pk) => RoamingLocations.Contains(pk.MetLocation); #endregion } diff --git a/PKHeX.Core/Legality/Encounters/Templates/Gen8b/EncounterTrade8b.cs b/PKHeX.Core/Legality/Encounters/Templates/Gen8b/EncounterTrade8b.cs index fc554f3d9..0b3866d76 100644 --- a/PKHeX.Core/Legality/Encounters/Templates/Gen8b/EncounterTrade8b.cs +++ b/PKHeX.Core/Legality/Encounters/Templates/Gen8b/EncounterTrade8b.cs @@ -7,14 +7,14 @@ namespace PKHeX.Core; /// public sealed record EncounterTrade8b : IEncounterable, IEncounterMatch, IFixedTrainer, IFixedNickname, IEncounterConvertible, IScaledSizeReadOnly, IFixedOTFriendship, IMoveset, IContestStatsReadOnly, IFixedGender, IFixedNature { - public int Generation => 8; + public byte Generation => 8; public EntityContext Context => EntityContext.Gen8b; - public int Location => Locations.LinkTrade6NPC; + public ushort Location => Locations.LinkTrade6NPC; public Shiny Shiny => Shiny.Never; public bool EggEncounter => false; public Ball FixedBall => Ball.Poke; public bool IsShiny => false; - public int EggLocation => Locations.Default8bNone; + public ushort EggLocation => Locations.Default8bNone; public bool IsFixedTrainer => true; public bool IsFixedNickname => true; public GameVersion Version { get; } @@ -36,15 +36,15 @@ public sealed record EncounterTrade8b : IEncounterable, IEncounterMatch, IFixedT public required ushort Species { get; init; } public required byte Level { get; init; } - public byte OT_Friendship => Species == (int)Core.Species.Chatot ? (byte)35 : (byte)50; + public byte OriginalTrainerFriendship => Species == (int)Core.Species.Chatot ? (byte)35 : (byte)50; private byte BaseContest => Species == (int)Core.Species.Chatot ? (byte)20 : (byte)0; - public byte CNT_Cool => BaseContest; - public byte CNT_Beauty => BaseContest; - public byte CNT_Cute => BaseContest; - public byte CNT_Smart => BaseContest; - public byte CNT_Tough => BaseContest; - public byte CNT_Sheen => 0; + public byte ContestCool => BaseContest; + public byte ContestBeauty => BaseContest; + public byte ContestCute => BaseContest; + public byte ContestSmart => BaseContest; + public byte ContestTough => BaseContest; + public byte ContestSheen => 0; public byte Form => 0; @@ -70,7 +70,7 @@ public EncounterTrade8b(ReadOnlySpan names, byte index, GameVersion ga public PB8 ConvertToPKM(ITrainerInfo tr, EncounterCriteria criteria) { - var version = this.GetCompatibleVersion((GameVersion)tr.Game); + var version = this.GetCompatibleVersion(tr.Version); int lang = (int)Language.GetSafeLanguage(Generation, (LanguageID)tr.Language, version); var pi = PersonalTable.BDSP[Species, Form]; var pk = new PB8 @@ -79,29 +79,29 @@ public PB8 ConvertToPKM(ITrainerInfo tr, EncounterCriteria criteria) EncryptionConstant = EncryptionConstant, Species = Species, CurrentLevel = Level, - Met_Location = Location, - Met_Level = Level, + MetLocation = Location, + MetLevel = Level, MetDate = EncounterDate.GetDateSwitch(), Gender = Gender, - Nature = (byte)Nature, - StatNature = (byte)Nature, + Nature = Nature, + StatNature = Nature, Ball = (byte)FixedBall, ID32 = ID32, - Version = (byte)version, + Version = version, Language = lang, - OT_Gender = OTGender, - OT_Name = TrainerNames[lang], + OriginalTrainerGender = OTGender, + OriginalTrainerName = TrainerNames[lang], - OT_Friendship = OT_Friendship, + OriginalTrainerFriendship = OriginalTrainerFriendship, IsNicknamed = IsFixedNickname, Nickname = IsFixedNickname ? Nicknames[lang] : SpeciesName.GetSpeciesNameGeneration(Species, lang, Generation), HeightScalar = HeightScalar, WeightScalar = WeightScalar, - HT_Name = tr.OT, - HT_Language = (byte)tr.Language, - HT_Friendship = pi.BaseFriendship, + HandlingTrainerName = tr.OT, + HandlingTrainerLanguage = (byte)tr.Language, + HandlingTrainerFriendship = pi.BaseFriendship, }; // Has German Language ID for all except German origin, which is Japanese @@ -129,7 +129,7 @@ public PB8 ConvertToPKM(ITrainerInfo tr, EncounterCriteria criteria) public bool IsMatchExact(PKM pk, EvoCriteria evo) { - if (pk.Met_Level != Level) + if (pk.MetLevel != Level) return false; if (pk.EncryptionConstant != EncryptionConstant) return false; @@ -147,13 +147,13 @@ public bool IsMatchExact(PKM pk, EvoCriteria evo) return false; if (pk.Gender != Gender) return false; - if (pk.Nature != (int)Nature) + if (pk.Nature != Nature) return false; if (pk.ID32 != ID32) return false; if (evo.Form != Form && !FormInfo.IsFormChangeable(Species, Form, pk.Form, Context, pk.Context)) return false; - if (pk.OT_Gender != OTGender) + if (pk.OriginalTrainerGender != OTGender) return false; if (!IsMatchEggLocation(pk)) return false; @@ -170,15 +170,15 @@ private bool IsMatchLocation(PKM pk) return IsMatchLocationExact(pk) || IsMatchLocationRemapped(pk); } - private bool IsMatchLocationExact(PKM pk) => pk.Met_Location == Location; + private bool IsMatchLocationExact(PKM pk) => pk.MetLocation == Location; private bool IsMatchLocationRemapped(PKM pk) { - var met = (ushort)pk.Met_Location; + var met = pk.MetLocation; var version = pk.Version; if (pk.Context == EntityContext.Gen8) return LocationsHOME.IsValidMetBDSP(met, version); - return LocationsHOME.GetMetSWSH((ushort)Location, version) == met; + return LocationsHOME.GetMetSWSH(Location, version) == met; } private bool IsMatchEggLocation(PKM pk) @@ -192,8 +192,8 @@ private bool IsMatchEggLocation(PKM pk) return IsMatchEggLocationExact(pk) || IsMatchEggLocationRemapped(pk); } - private static bool IsMatchEggLocationRemapped(PKM pk) => pk.Egg_Location == 0; - private bool IsMatchEggLocationExact(PKM pk) => pk.Egg_Location == EggLocation; + private static bool IsMatchEggLocationRemapped(PKM pk) => pk.EggLocation == 0; + private bool IsMatchEggLocationExact(PKM pk) => pk.EggLocation == EggLocation; public int DetectMeisterMagikarpLanguage(ReadOnlySpan nick, ReadOnlySpan ot, int currentLanguageID) { @@ -225,7 +225,7 @@ public int DetectMeisterMagikarpLanguage(ReadOnlySpan nick, ReadOnlySpanTrue if matches the pattern of a traded Magikarp. public bool IsMagikarpJapaneseTradedBDSP(PKM pk) { - return Species is (int)Core.Species.Magikarp && pk is { Language: (int)LanguageID.Japanese, OT_Name: "Diamond." or "Pearl." }; + return Species is (int)Core.Species.Magikarp && pk is { Language: (int)LanguageID.Japanese, OriginalTrainerName: "Diamond." or "Pearl." }; } /// diff --git a/PKHeX.Core/Legality/Encounters/Templates/Gen9/EncounterArea9.cs b/PKHeX.Core/Legality/Encounters/Templates/Gen9/EncounterArea9.cs index b3fe8c8a0..d8b8a81d7 100644 --- a/PKHeX.Core/Legality/Encounters/Templates/Gen9/EncounterArea9.cs +++ b/PKHeX.Core/Legality/Encounters/Templates/Gen9/EncounterArea9.cs @@ -1,4 +1,5 @@ using System; +using System.Diagnostics.CodeAnalysis; using static System.Buffers.Binary.BinaryPrimitives; namespace PKHeX.Core; @@ -11,13 +12,13 @@ public sealed record EncounterArea9 : IEncounterArea, IAreaLocat public EncounterSlot9[] Slots { get; } public GameVersion Version { get; } - public readonly ushort Location; + public readonly byte Location; + public readonly byte CrossFrom; // Actual location if not default + public byte ActualLocation() => CrossFrom == 0 ? Location : CrossFrom; - public bool IsMatchLocation(int location) => Location == location; + public bool IsMatchLocation(ushort location) => Location == location; - public ushort CrossFrom { get; } - - public static EncounterArea9[] GetAreas(BinLinkerAccessor input, GameVersion game) + public static EncounterArea9[] GetAreas(BinLinkerAccessor input, [ConstantExpected] GameVersion game) { var result = new EncounterArea9[input.Length]; for (int i = 0; i < result.Length; i++) @@ -25,7 +26,7 @@ public static EncounterArea9[] GetAreas(BinLinkerAccessor input, GameVersion gam return result; } - private EncounterArea9(ReadOnlySpan areaData, GameVersion game) + private EncounterArea9(ReadOnlySpan areaData, [ConstantExpected] GameVersion game) { Location = areaData[0]; CrossFrom = areaData[2]; diff --git a/PKHeX.Core/Legality/Encounters/Templates/Gen9/EncounterDist9.cs b/PKHeX.Core/Legality/Encounters/Templates/Gen9/EncounterDist9.cs index 1f1d44535..d0e3209a8 100644 --- a/PKHeX.Core/Legality/Encounters/Templates/Gen9/EncounterDist9.cs +++ b/PKHeX.Core/Legality/Encounters/Templates/Gen9/EncounterDist9.cs @@ -8,8 +8,8 @@ namespace PKHeX.Core; public sealed record EncounterDist9 : IEncounterable, IEncounterMatch, IEncounterConvertible, ITeraRaid9, IMoveset, IFlawlessIVCount, IFixedGender, IFixedNature { - public int Generation => 9; - int ILocation.Location => Location; + public byte Generation => 9; + ushort ILocation.Location => Location; public const ushort Location = Locations.TeraCavern9; public EntityContext Context => EntityContext.Gen9; public GameVersion Version => GameVersion.SV; @@ -17,7 +17,7 @@ public sealed record EncounterDist9 public Ball FixedBall => Ball.None; public bool EggEncounter => false; public bool IsShiny => Shiny == Shiny.Always; - public int EggLocation => 0; + public ushort EggLocation => 0; public required ushort Species { get; init; } public required byte Form { get; init; } @@ -241,7 +241,7 @@ private static EncounterDist9 ReadEncounter(ReadOnlySpan data) => new() public PK9 ConvertToPKM(ITrainerInfo tr, EncounterCriteria criteria) { int lang = (int)Language.GetSafeLanguage(Generation, (LanguageID)tr.Language); - var version = this.GetCompatibleVersion((GameVersion)tr.Game); + var version = this.GetCompatibleVersion(tr.Version); var pi = PersonalTable.SV[Species, Form]; var pk = new PK9 { @@ -249,17 +249,17 @@ public PK9 ConvertToPKM(ITrainerInfo tr, EncounterCriteria criteria) Species = Species, Form = Form, CurrentLevel = LevelMin, - OT_Friendship = pi.BaseFriendship, - Met_Location = Location, - Met_Level = LevelMin, + OriginalTrainerFriendship = pi.BaseFriendship, + MetLocation = Location, + MetLevel = LevelMin, MetDate = EncounterDate.GetDateSwitch(), - Version = (byte)version, + Version = version, Ball = (byte)Ball.Poke, Nickname = SpeciesName.GetSpeciesNameGeneration(Species, lang, Generation), Obedience_Level = LevelMin, - OT_Name = tr.OT, - OT_Gender = tr.Gender, + OriginalTrainerName = tr.OT, + OriginalTrainerGender = tr.Gender, ID32 = tr.ID32, }; SetPINGA(pk, criteria, pi); @@ -287,7 +287,7 @@ private void SetPINGA(PK9 pk, EncounterCriteria criteria, PersonalInfo9SV pi) #region Matching public bool IsMatchExact(PKM pk, EvoCriteria evo) { - if (!this.IsLevelWithinRange(pk.Met_Level)) + if (!this.IsLevelWithinRange(pk.MetLevel)) return false; if (Gender != FixedGenderUtil.GenderRandom && pk.Gender != Gender) return false; @@ -306,7 +306,7 @@ public bool IsMatchExact(PKM pk, EvoCriteria evo) private bool IsMatchEggLocation(PKM pk) { var expect = pk is PB8 ? Locations.Default8bNone : EggLocation; - return pk.Egg_Location == expect; + return pk.EggLocation == expect; } private bool IsMatchLocation(PKM pk) @@ -326,11 +326,11 @@ public EncounterMatchRating GetMatchRating(PKM pk) return IsMatchDeferred(pk); } - private static bool IsMatchLocationExact(PKM pk) => pk.Met_Location == Location; + private static bool IsMatchLocationExact(PKM pk) => pk.MetLocation == Location; private static bool IsMatchLocationRemapped(PKM pk) { - var met = (ushort)pk.Met_Location; + var met = pk.MetLocation; var version = pk.Version; if (pk.Context == EntityContext.Gen8) return LocationsHOME.IsValidMetSV(met, version); diff --git a/PKHeX.Core/Legality/Encounters/Templates/Gen9/EncounterFixed9.cs b/PKHeX.Core/Legality/Encounters/Templates/Gen9/EncounterFixed9.cs index dcdcbd60a..121cd8312 100644 --- a/PKHeX.Core/Legality/Encounters/Templates/Gen9/EncounterFixed9.cs +++ b/PKHeX.Core/Legality/Encounters/Templates/Gen9/EncounterFixed9.cs @@ -10,8 +10,8 @@ namespace PKHeX.Core; public sealed record EncounterFixed9 : IEncounterable, IEncounterMatch, IEncounterConvertible, IMoveset, IFlawlessIVCount, IGemType, IFixedGender { - public int Generation => 9; - int ILocation.Location => Location; + public byte Generation => 9; + ushort ILocation.Location => Location; public byte Location => Location0; public EntityContext Context => EntityContext.Gen9; public GameVersion Version => GameVersion.SV; @@ -19,7 +19,7 @@ public sealed record EncounterFixed9 public bool EggEncounter => false; public Ball FixedBall => Ball.None; public bool IsShiny => false; - public int EggLocation => 0; + public ushort EggLocation => 0; public AbilityPermission Ability { get; init; } public required ushort Species { get; init; } @@ -78,7 +78,7 @@ private static EncounterFixed9 ReadEncounter(ReadOnlySpan data) => new() public PK9 ConvertToPKM(ITrainerInfo tr, EncounterCriteria criteria) { int lang = (int)Language.GetSafeLanguage(Generation, (LanguageID)tr.Language); - var version = this.GetCompatibleVersion((GameVersion)tr.Game); + var version = this.GetCompatibleVersion(tr.Version); var pi = PersonalTable.SV[Species, Form]; var pk = new PK9 { @@ -86,29 +86,20 @@ public PK9 ConvertToPKM(ITrainerInfo tr, EncounterCriteria criteria) Species = Species, Form = Form, CurrentLevel = LevelMin, - OT_Friendship = pi.BaseFriendship, - Met_Location = Location, - Met_Level = LevelMin, + OriginalTrainerFriendship = pi.BaseFriendship, + MetLocation = Location, + MetLevel = LevelMin, MetDate = EncounterDate.GetDateSwitch(), - Version = (byte)version, + Version = version, Ball = (byte)Ball.Poke, Nickname = SpeciesName.GetSpeciesNameGeneration(Species, lang, Generation), Obedience_Level = LevelMin, - OT_Name = tr.OT, - OT_Gender = tr.Gender, + OriginalTrainerName = tr.OT, + OriginalTrainerGender = tr.Gender, ID32 = tr.ID32, }; - var type = Tera9RNG.GetTeraType(Util.Rand.Rand64(), TeraType, Species, Form); - pk.TeraTypeOriginal = (MoveType)type; - if (criteria.TeraType != -1 && type != criteria.TeraType) - pk.SetTeraType(type); // sets the override type - - pk.HeightScalar = PokeSizeUtil.GetRandomScalar(); - pk.WeightScalar = PokeSizeUtil.GetRandomScalar(); - pk.Scale = TeraType != 0 ? (byte)(MinScaleStrongTera + Util.Rand.Next(byte.MaxValue - MinScaleStrongTera + 1)) : PokeSizeUtil.GetRandomScalar(); - SetPINGA(pk, criteria, pi); if (Moves.HasMoves) pk.SetMoves(Moves); @@ -121,20 +112,33 @@ public PK9 ConvertToPKM(ITrainerInfo tr, EncounterCriteria criteria) private void SetPINGA(PK9 pk, EncounterCriteria criteria, PersonalInfo9SV pi) { - pk.PID = Util.Rand32(); - pk.EncryptionConstant = Util.Rand32(); - pk.Nature = pk.StatNature = (int)criteria.GetNature(); + var rnd = Util.Rand; + pk.PID = rnd.Rand32(); + pk.EncryptionConstant = rnd.Rand32(); + pk.Nature = pk.StatNature = criteria.GetNature(); pk.Gender = criteria.GetGender(pi); pk.RefreshAbility(criteria.GetAbilityFromNumber(Ability)); criteria.SetRandomIVs(pk, FlawlessIVCount); + + var type = Tera9RNG.GetTeraType(rnd.Rand64(), TeraType, Species, Form); + pk.TeraTypeOriginal = (MoveType)type; + if (criteria.IsSpecifiedTeraType() && type != criteria.TeraType) + pk.SetTeraType(type); // sets the override type + + pk.HeightScalar = PokeSizeUtil.GetRandomScalar(rnd); + pk.WeightScalar = PokeSizeUtil.GetRandomScalar(rnd); + pk.Scale = TeraType != 0 + ? (byte)(MinScaleStrongTera + rnd.Next(byte.MaxValue - MinScaleStrongTera + 1)) + : PokeSizeUtil.GetRandomScalar(rnd); + } #endregion #region Matching public bool IsMatchExact(PKM pk, EvoCriteria evo) { - if (!this.IsLevelWithinRange(pk.Met_Level)) + if (!this.IsLevelWithinRange(pk.MetLevel)) return false; if (Gender != FixedGenderUtil.GenderRandom && pk.Gender != Gender) return false; @@ -177,7 +181,7 @@ private bool IsMatchForm(PKM pk, EvoCriteria evo) private bool IsMatchEggLocation(PKM pk) { var expect = pk is PB8 ? Locations.Default8bNone : EggLocation; - return pk.Egg_Location == expect; + return pk.EggLocation == expect; } private bool IsMatchLocation(PKM pk) @@ -192,7 +196,7 @@ private bool IsMatchLocation(PKM pk) private bool IsMatchLocationRemapped(PKM pk) { - var met = (ushort)pk.Met_Location; + var met = pk.MetLocation; var version = pk.Version; if (pk.Context == EntityContext.Gen8) return LocationsHOME.IsValidMetSV(met, version); @@ -201,7 +205,7 @@ private bool IsMatchLocationRemapped(PKM pk) private bool IsMatchLocationExact(PKM pk) { - var loc = pk.Met_Location; + var loc = pk.MetLocation; if (loc == Location0) return true; if (loc == 0) diff --git a/PKHeX.Core/Legality/Encounters/Templates/Gen9/EncounterMight9.cs b/PKHeX.Core/Legality/Encounters/Templates/Gen9/EncounterMight9.cs index fbeda5b27..2687f4588 100644 --- a/PKHeX.Core/Legality/Encounters/Templates/Gen9/EncounterMight9.cs +++ b/PKHeX.Core/Legality/Encounters/Templates/Gen9/EncounterMight9.cs @@ -6,8 +6,8 @@ namespace PKHeX.Core; public sealed record EncounterMight9 : IEncounterable, IEncounterMatch, IEncounterConvertible, ITeraRaid9, IMoveset, IFlawlessIVCount, IFixedGender, IFixedNature { - public int Generation => 9; - int ILocation.Location => Location; + public byte Generation => 9; + ushort ILocation.Location => Location; public const ushort Location = Locations.TeraCavern9; public EntityContext Context => EntityContext.Gen9; public GameVersion Version => GameVersion.SV; @@ -15,7 +15,7 @@ public sealed record EncounterMight9 public Ball FixedBall => Ball.None; public bool EggEncounter => false; public bool IsShiny => Shiny == Shiny.Always; - public int EggLocation => 0; + public ushort EggLocation => 0; public required Moveset Moves { get; init; } public required IndividualValueSet IVs { get; init; } @@ -255,7 +255,7 @@ private static EncounterMight9 ReadEncounter(ReadOnlySpan data) => new() public PK9 ConvertToPKM(ITrainerInfo tr, EncounterCriteria criteria) { int lang = (int)Language.GetSafeLanguage(Generation, (LanguageID)tr.Language); - var version = this.GetCompatibleVersion((GameVersion)tr.Game); + var version = this.GetCompatibleVersion(tr.Version); var pi = PersonalTable.SV[Species, Form]; var pk = new PK9 { @@ -263,19 +263,19 @@ public PK9 ConvertToPKM(ITrainerInfo tr, EncounterCriteria criteria) Species = Species, Form = Form, CurrentLevel = LevelMin, - OT_Friendship = pi.BaseFriendship, - Met_Location = Location, - Met_Level = LevelMin, + OriginalTrainerFriendship = pi.BaseFriendship, + MetLocation = Location, + MetLevel = LevelMin, MetDate = EncounterDate.GetDateSwitch(), - Version = (byte)version, + Version = version, Ball = (byte)Ball.Poke, Nickname = SpeciesName.GetSpeciesNameGeneration(Species, lang, Generation), Obedience_Level = LevelMin, RibbonMarkMightiest = true, AffixedRibbon = (sbyte)RibbonIndex.MarkMightiest, - OT_Name = tr.OT, - OT_Gender = tr.Gender, + OriginalTrainerName = tr.OT, + OriginalTrainerGender = tr.Gender, ID32 = tr.ID32, }; SetPINGA(pk, criteria, pi); @@ -304,7 +304,7 @@ private void SetPINGA(PK9 pk, EncounterCriteria criteria, PersonalInfo9SV pi) #region Matching public bool IsMatchExact(PKM pk, EvoCriteria evo) { - if (!this.IsLevelWithinRange(pk.Met_Level)) + if (!this.IsLevelWithinRange(pk.MetLevel)) return false; if (Gender != FixedGenderUtil.GenderRandom && pk.Gender != Gender) return false; @@ -321,7 +321,7 @@ public bool IsMatchExact(PKM pk, EvoCriteria evo) private bool IsMatchEggLocation(PKM pk) { var expect = pk is PB8 ? Locations.Default8bNone : EggLocation; - return pk.Egg_Location == expect; + return pk.EggLocation == expect; } private bool IsMatchLocation(PKM pk) @@ -341,11 +341,11 @@ public EncounterMatchRating GetMatchRating(PKM pk) return IsMatchDeferred(pk); } - private static bool IsMatchLocationExact(PKM pk) => pk.Met_Location == Location; + private static bool IsMatchLocationExact(PKM pk) => pk.MetLocation == Location; private static bool IsMatchLocationRemapped(PKM pk) { - var met = (ushort)pk.Met_Location; + var met = pk.MetLocation; var version = pk.Version; if (pk.Context == EntityContext.Gen8) return LocationsHOME.IsValidMetSV(met, version); diff --git a/PKHeX.Core/Legality/Encounters/Templates/Gen9/EncounterOutbreak9.cs b/PKHeX.Core/Legality/Encounters/Templates/Gen9/EncounterOutbreak9.cs index 479f7b783..b1ad1f2dd 100644 --- a/PKHeX.Core/Legality/Encounters/Templates/Gen9/EncounterOutbreak9.cs +++ b/PKHeX.Core/Legality/Encounters/Templates/Gen9/EncounterOutbreak9.cs @@ -9,15 +9,15 @@ namespace PKHeX.Core; public sealed record EncounterOutbreak9 : IEncounterable, IEncounterMatch, IEncounterConvertible, IFixedGender { - public int Generation => 9; - int ILocation.Location => Location; + public byte Generation => 9; + ushort ILocation.Location => Location; public ushort Location => GetFirstMetLocation(MetBase, MetFlags); public EntityContext Context => EntityContext.Gen9; public GameVersion Version => GameVersion.SV; public Shiny Shiny => IsShiny ? Shiny.Always : Shiny.Random; public bool EggEncounter => false; public Ball FixedBall => Ball.None; - public int EggLocation => 0; + public ushort EggLocation => 0; public AbilityPermission Ability => AbilityPermission.Any12; public required ushort Species { get; init; } @@ -75,7 +75,7 @@ private static EncounterOutbreak9 ReadEncounter(ReadOnlySpan data) => new( public PK9 ConvertToPKM(ITrainerInfo tr, EncounterCriteria criteria) { int lang = (int)Language.GetSafeLanguage(Generation, (LanguageID)tr.Language); - var version = this.GetCompatibleVersion((GameVersion)tr.Game); + var version = this.GetCompatibleVersion(tr.Version); var pi = PersonalTable.SV[Species, Form]; var pk = new PK9 { @@ -83,17 +83,17 @@ public PK9 ConvertToPKM(ITrainerInfo tr, EncounterCriteria criteria) Species = Species, Form = Form, CurrentLevel = LevelMin, - OT_Friendship = pi.BaseFriendship, - Met_Location = Location, - Met_Level = LevelMin, + OriginalTrainerFriendship = pi.BaseFriendship, + MetLocation = Location, + MetLevel = LevelMin, MetDate = EncounterDate.GetDateSwitch(), - Version = (byte)version, + Version = version, Ball = (byte)Ball.Poke, Nickname = SpeciesName.GetSpeciesNameGeneration(Species, lang, Generation), Obedience_Level = LevelMin, - OT_Name = tr.OT, - OT_Gender = tr.Gender, + OriginalTrainerName = tr.OT, + OriginalTrainerGender = tr.Gender, ID32 = tr.ID32, }; @@ -101,15 +101,6 @@ public PK9 ConvertToPKM(ITrainerInfo tr, EncounterCriteria criteria) if (Ribbon != Unset) pk.SetRibbonIndex(Ribbon); - var type = Tera9RNG.GetTeraType(Util.Rand.Rand64(), GemType.Default, Species, Form); - pk.TeraTypeOriginal = (MoveType)type; - if (criteria.TeraType != -1 && type != criteria.TeraType) - pk.SetTeraType(type); // sets the override type - - pk.HeightScalar = PokeSizeUtil.GetRandomScalar(); - pk.WeightScalar = PokeSizeUtil.GetRandomScalar(); - pk.Scale = !IsForcedScaleRange ? PokeSizeUtil.GetRandomScalar() : (byte)Util.Rand.Next(ScaleMin, ScaleMax + 1); - SetPINGA(pk, criteria, pi); EncounterUtil.SetEncounterMoves(pk, Version, Level); @@ -119,20 +110,33 @@ public PK9 ConvertToPKM(ITrainerInfo tr, EncounterCriteria criteria) private void SetPINGA(PK9 pk, EncounterCriteria criteria, PersonalInfo9SV pi) { - pk.PID = Util.Rand32(); - pk.EncryptionConstant = Util.Rand32(); - pk.Nature = pk.StatNature = (int)criteria.GetNature(); + var rnd = Util.Rand; + pk.PID = rnd.Rand32(); + pk.EncryptionConstant = rnd.Rand32(); + pk.Nature = pk.StatNature = criteria.GetNature(); pk.Gender = criteria.GetGender(pi); pk.RefreshAbility(criteria.GetAbilityFromNumber(Ability)); criteria.SetRandomIVs(pk); + + var type = Tera9RNG.GetTeraType(rnd.Rand64(), GemType.Default, Species, Form); + pk.TeraTypeOriginal = (MoveType)type; + if (criteria.IsSpecifiedTeraType() && type != criteria.TeraType) + pk.SetTeraType(type); // sets the override type + + pk.HeightScalar = PokeSizeUtil.GetRandomScalar(rnd); + pk.WeightScalar = PokeSizeUtil.GetRandomScalar(rnd); + pk.Scale = !IsForcedScaleRange + ? PokeSizeUtil.GetRandomScalar(rnd) + : (byte)rnd.Next(ScaleMin, ScaleMax + 1); + } -#endregion + #endregion #region Matching public bool IsMatchExact(PKM pk, EvoCriteria evo) { - if (!this.IsLevelWithinRange(pk.Met_Level)) + if (!this.IsLevelWithinRange(pk.MetLevel)) return false; if (Gender != FixedGenderUtil.GenderRandom && pk.Gender != Gender) return false; @@ -148,7 +152,7 @@ public bool IsMatchExact(PKM pk, EvoCriteria evo) private bool IsMatchEggLocation(PKM pk) { var expect = pk is PB8 ? Locations.Default8bNone : EggLocation; - return pk.Egg_Location == expect; + return pk.EggLocation == expect; } private bool IsMatchLocation(PKM pk) @@ -163,14 +167,14 @@ private bool IsMatchLocation(PKM pk) private bool IsMatchLocationRemapped(PKM pk) { - var met = (ushort)pk.Met_Location; + var met = pk.MetLocation; var version = pk.Version; if (pk.Context == EntityContext.Gen8) return LocationsHOME.IsValidMetSV(met, version); return LocationsHOME.GetMetSWSH(Location, version) == met; } - private bool IsMatchLocationExact(PKM pk) => IsMetLocationMatch(MetBase, MetFlags, pk.Met_Location); + private bool IsMatchLocationExact(PKM pk) => IsMetLocationMatch(MetBase, MetFlags, pk.MetLocation); private static ushort GetFirstMetLocation(byte met, UInt128 flags) { diff --git a/PKHeX.Core/Legality/Encounters/Templates/Gen9/EncounterSlot9.cs b/PKHeX.Core/Legality/Encounters/Templates/Gen9/EncounterSlot9.cs index c3a053a85..4059dd4ef 100644 --- a/PKHeX.Core/Legality/Encounters/Templates/Gen9/EncounterSlot9.cs +++ b/PKHeX.Core/Legality/Encounters/Templates/Gen9/EncounterSlot9.cs @@ -8,20 +8,20 @@ namespace PKHeX.Core; public sealed record EncounterSlot9(EncounterArea9 Parent, ushort Species, byte Form, byte LevelMin, byte LevelMax, byte Gender, byte Time) : IEncounterable, IEncounterMatch, IEncounterConvertible, IEncounterFormRandom, IFixedGender { - public int Generation => 9; + public byte Generation => 9; public EntityContext Context => EntityContext.Gen9; public bool EggEncounter => false; public AbilityPermission Ability => AbilityPermission.Any12; public Ball FixedBall => Ball.None; public Shiny Shiny => Shiny.Random; public bool IsShiny => false; - public int EggLocation => 0; + public ushort EggLocation => 0; public bool IsRandomUnspecificForm => Form >= EncounterUtil.FormDynamic; public string Name => $"Wild Encounter ({Version})"; public string LongName => $"{Name}"; public GameVersion Version => Parent.Version; - public int Location => Parent.CrossFrom == 0 ? Parent.Location : Parent.CrossFrom; + public ushort Location => Parent.ActualLocation(); private static int GetTime(RibbonIndex mark) => mark switch { @@ -129,25 +129,25 @@ public PK9 ConvertToPKM(ITrainerInfo tr, EncounterCriteria criteria) { int lang = (int)Language.GetSafeLanguage(Generation, (LanguageID)tr.Language); var form = GetWildForm(Form); - var version = Version != GameVersion.SV ? Version : GameVersion.SV.Contains(tr.Game) ? (GameVersion)tr.Game : GameVersion.SL; + var version = Version != GameVersion.SV ? Version : GameVersion.SV.Contains(tr.Version) ? tr.Version : GameVersion.SL; var pi = PersonalTable.SV[Species, form]; var pk = new PK9 { Species = Species, Form = form, CurrentLevel = LevelMin, - Met_Location = Location, - Met_Level = LevelMin, - Version = (byte)version, + MetLocation = Location, + MetLevel = LevelMin, + Version = version, Ball = (byte)Ball.Poke, MetDate = EncounterDate.GetDateSwitch(), Language = lang, - OT_Name = tr.OT, - OT_Gender = tr.Gender, + OriginalTrainerName = tr.OT, + OriginalTrainerGender = tr.Gender, ID32 = tr.ID32, Obedience_Level = LevelMin, - OT_Friendship = pi.BaseFriendship, + OriginalTrainerFriendship = pi.BaseFriendship, Nickname = SpeciesName.GetSpeciesNameGeneration(Species, lang, Generation), }; SetPINGA(pk, criteria, pi); @@ -170,25 +170,26 @@ private byte GetWildForm(byte form) private void SetPINGA(PK9 pk, EncounterCriteria criteria, PersonalInfo9SV pi) { - pk.PID = Util.Rand32(); - pk.EncryptionConstant = Util.Rand32(); + var rnd = Util.Rand; + pk.PID = rnd.Rand32(); + pk.EncryptionConstant = rnd.Rand32(); criteria.SetRandomIVs(pk); - pk.Nature = pk.StatNature = (int)criteria.GetNature(); + pk.Nature = pk.StatNature = criteria.GetNature(); pk.Gender = criteria.GetGender(Gender, pi); pk.RefreshAbility(criteria.GetAbilityFromNumber(Ability)); - var rand = new Xoroshiro128Plus(Util.Rand.Rand64()); + var rand = new Xoroshiro128Plus(rnd.Rand64()); var type = Tera9RNG.GetTeraTypeFromPersonal(Species, Form, rand.Next()); pk.TeraTypeOriginal = (MoveType)type; - if (criteria.TeraType != -1 && type != criteria.TeraType) + if (criteria.IsSpecifiedTeraType() && type != criteria.TeraType) pk.SetTeraType(type); // sets the override type if (Species == (int)Core.Species.Toxtricity) pk.Nature = ToxtricityUtil.GetRandomNature(ref rand, Form); - pk.HeightScalar = PokeSizeUtil.GetRandomScalar(); - pk.WeightScalar = PokeSizeUtil.GetRandomScalar(); - pk.Scale = PokeSizeUtil.GetRandomScalar(); + pk.HeightScalar = PokeSizeUtil.GetRandomScalar(rnd); + pk.WeightScalar = PokeSizeUtil.GetRandomScalar(rnd); + pk.Scale = PokeSizeUtil.GetRandomScalar(rnd); } #endregion @@ -200,7 +201,7 @@ public bool IsMatchExact(PKM pk, EvoCriteria evo) return false; if (Gender != FixedGenderUtil.GenderRandom && pk.Gender != Gender) return false; - if (!this.IsLevelWithinRange(pk.Met_Level)) + if (!this.IsLevelWithinRange(pk.MetLevel)) return false; if (pk is ITeraType t) diff --git a/PKHeX.Core/Legality/Encounters/Templates/Gen9/EncounterStatic9.cs b/PKHeX.Core/Legality/Encounters/Templates/Gen9/EncounterStatic9.cs index 7715982ff..71004047f 100644 --- a/PKHeX.Core/Legality/Encounters/Templates/Gen9/EncounterStatic9.cs +++ b/PKHeX.Core/Legality/Encounters/Templates/Gen9/EncounterStatic9.cs @@ -8,12 +8,12 @@ namespace PKHeX.Core; public sealed record EncounterStatic9(GameVersion Version) : IEncounterable, IEncounterMatch, IEncounterConvertible, IMoveset, IFlawlessIVCount, IFixedIVSet, IGemType, IFatefulEncounterReadOnly, IFixedGender, IFixedNature, IEncounterMarkExtra { - public int Generation => 9; + public byte Generation => 9; public EntityContext Context => EntityContext.Gen9; public bool IsShiny => Shiny == Shiny.Always; public bool EggEncounter => EggLocation != 0; - int ILocation.Location => Location; - int ILocation.EggLocation => EggLocation; + ushort ILocation.Location => Location; + ushort ILocation.EggLocation => EggLocation; public Ball FixedBall { get; init; } public required ushort Location { get; init; } @@ -67,7 +67,7 @@ public bool IsMissingExtraMark(PKM pk, out RibbonIndex index) public PK9 ConvertToPKM(ITrainerInfo tr, EncounterCriteria criteria) { int lang = (int)Language.GetSafeLanguage(Generation, (LanguageID)tr.Language); - var version = this.GetCompatibleVersion((GameVersion)tr.Game); + var version = this.GetCompatibleVersion(tr.Version); var pi = PersonalTable.SV[Species, Form]; var pk = new PK9 { @@ -75,32 +75,32 @@ public PK9 ConvertToPKM(ITrainerInfo tr, EncounterCriteria criteria) Species = Species, Form = Form, CurrentLevel = LevelMin, - OT_Friendship = pi.BaseFriendship, - Met_Location = Location, - Met_Level = LevelMin, + OriginalTrainerFriendship = pi.BaseFriendship, + MetLocation = Location, + MetLevel = LevelMin, MetDate = EncounterDate.GetDateSwitch(), - Version = (byte)version, + Version = version, Ball = (byte)Ball.Poke, FatefulEncounter = FatefulEncounter, Nickname = SpeciesName.GetSpeciesNameGeneration(Species, lang, Generation), Obedience_Level = LevelMin, - OT_Name = tr.OT, - OT_Gender = tr.Gender, + OriginalTrainerName = tr.OT, + OriginalTrainerGender = tr.Gender, ID32 = tr.ID32, }; if (EggEncounter) { // Fake as hatched. - pk.Met_Location = Locations.HatchLocation9; - pk.Met_Level = EggStateLegality.EggMetLevel; - pk.Egg_Location = EggLocation; + pk.MetLocation = Locations.HatchLocation9; + pk.MetLevel = EggStateLegality.EggMetLevel; + pk.EggLocation = EggLocation; pk.EggMetDate = pk.MetDate; } if (Gift && !ScriptedYungoos) - pk.HT_Language = (byte)pk.Language; + pk.HandlingTrainerLanguage = (byte)pk.Language; if (StarterBoxLegend) pk.FormArgument = 1; // Not Ride Form. if (IsTitan) @@ -160,14 +160,14 @@ private void SetPINGA(PK9 pk, EncounterCriteria criteria, PersonalInfo9SV pi) if (Gender != FixedGenderUtil.GenderRandom) pk.Gender = Gender; if (Nature != Nature.Random) - pk.Nature = pk.StatNature = (int)Nature; + pk.Nature = pk.StatNature = Nature; } #endregion #region Matching public bool IsMatchExact(PKM pk, EvoCriteria evo) { - if (!this.IsLevelWithinRange(pk.Met_Level)) + if (!this.IsLevelWithinRange(pk.MetLevel)) return false; if (Gender != FixedGenderUtil.GenderRandom && pk.Gender != Gender) return false; @@ -183,7 +183,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 != (int)Nature) + if (Nature != Nature.Random && pk.Nature != Nature) return false; return true; @@ -191,20 +191,20 @@ public bool IsMatchExact(PKM pk, EvoCriteria evo) private bool IsMatchEggLocation(PKM pk) { - var eggloc = pk.Egg_Location; + var eggLoc = pk.EggLocation; if (!EggEncounter) { var expect = pk is PB8 ? Locations.Default8bNone : EggLocation; - return eggloc == expect; + return eggLoc == expect; } if (!pk.IsEgg) // hatched - return eggloc == EggLocation || eggloc == Locations.LinkTrade6; + return eggLoc == EggLocation || eggLoc == Locations.LinkTrade6; // Unhatched: - if (eggloc != EggLocation) + if (eggLoc != EggLocation) return false; - if (pk.Met_Location is not (0 or Locations.LinkTrade6)) + if (pk.MetLocation is not (0 or Locations.LinkTrade6)) return false; return true; } @@ -230,12 +230,12 @@ private bool IsMatchLocationExact(PKM pk) { if (EggEncounter) return true; - return pk.Met_Location == Location; + return pk.MetLocation == Location; } private bool IsMatchLocationRemapped(PKM pk) { - var met = (ushort)pk.Met_Location; + var met = pk.MetLocation; var version = pk.Version; if (pk.Context == EntityContext.Gen8) return LocationsHOME.IsValidMetSV(met, version); diff --git a/PKHeX.Core/Legality/Encounters/Templates/Gen9/EncounterTera9.cs b/PKHeX.Core/Legality/Encounters/Templates/Gen9/EncounterTera9.cs index f96f5d6fb..5cc53f5c4 100644 --- a/PKHeX.Core/Legality/Encounters/Templates/Gen9/EncounterTera9.cs +++ b/PKHeX.Core/Legality/Encounters/Templates/Gen9/EncounterTera9.cs @@ -10,16 +10,16 @@ namespace PKHeX.Core; public sealed record EncounterTera9 : IEncounterable, IEncounterMatch, IEncounterConvertible, ITeraRaid9, IMoveset, IFlawlessIVCount, IFixedGender, IEncounterFormRandom { - public int Generation => 9; + public byte Generation => 9; public EntityContext Context => EntityContext.Gen9; public GameVersion Version => GameVersion.SV; - int ILocation.Location => Location; + ushort ILocation.Location => Location; public const ushort Location = Locations.TeraCavern9; public bool IsDistribution => Index != 0; public Ball FixedBall => Ball.None; public bool EggEncounter => false; public bool IsShiny => Shiny == Shiny.Always; - public int EggLocation => 0; + public ushort EggLocation => 0; public required ushort Species { get; init; } public required byte Form { get; init; } @@ -178,7 +178,7 @@ private static EncounterTera9 ReadEncounter(ReadOnlySpan data, TeraRaidMap public PK9 ConvertToPKM(ITrainerInfo tr, EncounterCriteria criteria) { int lang = (int)Language.GetSafeLanguage(Generation, (LanguageID)tr.Language); - var version = this.GetCompatibleVersion((GameVersion)tr.Game); + var version = this.GetCompatibleVersion(tr.Version); var pi = PersonalTable.SV[Species, Form]; var pk = new PK9 { @@ -186,17 +186,17 @@ public PK9 ConvertToPKM(ITrainerInfo tr, EncounterCriteria criteria) Species = Species, Form = Form, CurrentLevel = LevelMin, - OT_Friendship = pi.BaseFriendship, - Met_Location = Location, - Met_Level = LevelMin, + OriginalTrainerFriendship = pi.BaseFriendship, + MetLocation = Location, + MetLevel = LevelMin, MetDate = EncounterDate.GetDateSwitch(), - Version = (byte)version, + Version = version, Ball = (byte)Ball.Poke, Nickname = SpeciesName.GetSpeciesNameGeneration(Species, lang, Generation), Obedience_Level = LevelMin, - OT_Name = tr.OT, - OT_Gender = tr.Gender, + OriginalTrainerName = tr.OT, + OriginalTrainerGender = tr.Gender, ID32 = tr.ID32, }; SetPINGA(pk, criteria, pi); @@ -225,7 +225,7 @@ private void SetPINGA(PK9 pk, EncounterCriteria criteria, PersonalInfo9SV pi) #region Matching public bool IsMatchExact(PKM pk, EvoCriteria evo) { - if (!this.IsLevelWithinRange(pk.Met_Level)) + if (!this.IsLevelWithinRange(pk.MetLevel)) return false; if (Gender != FixedGenderUtil.GenderRandom && pk.Gender != Gender) return false; @@ -242,7 +242,7 @@ public bool IsMatchExact(PKM pk, EvoCriteria evo) private bool IsMatchEggLocation(PKM pk) { var expect = pk is PB8 ? Locations.Default8bNone : EggLocation; - return pk.Egg_Location == expect; + return pk.EggLocation == expect; } private bool IsMatchLocation(PKM pk) @@ -262,11 +262,11 @@ public EncounterMatchRating GetMatchRating(PKM pk) return IsMatchDeferred(pk); } - private static bool IsMatchLocationExact(PKM pk) => pk.Met_Location == Location; + private static bool IsMatchLocationExact(PKM pk) => pk.MetLocation == Location; private static bool IsMatchLocationRemapped(PKM pk) { - var met = (ushort)pk.Met_Location; + var met = pk.MetLocation; var version = pk.Version; if (pk.Context == EntityContext.Gen8) return LocationsHOME.IsValidMetSV(met, version); diff --git a/PKHeX.Core/Legality/Encounters/Templates/Gen9/EncounterTrade9.cs b/PKHeX.Core/Legality/Encounters/Templates/Gen9/EncounterTrade9.cs index 5fa56006f..d77b0472a 100644 --- a/PKHeX.Core/Legality/Encounters/Templates/Gen9/EncounterTrade9.cs +++ b/PKHeX.Core/Legality/Encounters/Templates/Gen9/EncounterTrade9.cs @@ -8,14 +8,14 @@ namespace PKHeX.Core; public sealed record EncounterTrade9 : IEncounterable, IEncounterMatch, IFixedTrainer, IFixedNickname, IEncounterConvertible, IGemType, IFixedGender, IFixedNature, IRibbonPartner, IMoveset { - public int Generation => 9; + public byte Generation => 9; public EntityContext Context => EntityContext.Gen9; - public int Location => Locations.LinkTrade6NPC; + public ushort Location => Locations.LinkTrade6NPC; public Shiny Shiny { get; init; } = Shiny.Never; public bool EggEncounter => false; public Ball FixedBall { get; init; } public bool IsShiny => false; - public int EggLocation => 0; + public ushort EggLocation => 0; public bool IsFixedTrainer => true; public bool IsFixedNickname => Nicknames.Length > 0; public GameVersion Version { get; } @@ -67,43 +67,44 @@ public EncounterTrade9(ReadOnlySpan names, byte index, GameVersion gam public PK9 ConvertToPKM(ITrainerInfo tr, EncounterCriteria criteria) { - var version = this.GetCompatibleVersion((GameVersion)tr.Game); + var version = this.GetCompatibleVersion(tr.Version); int lang = (int)Language.GetSafeLanguage(Generation, (LanguageID)tr.Language, version); var pi = PersonalTable.SV[Species, Form]; - var rnd = new Xoroshiro128Plus(Util.Rand.Rand64()); + var rnd = Util.Rand; + var xoro = new Xoroshiro128Plus(rnd.Rand64()); var pk = new PK9 { Species = Species, Form = Form, CurrentLevel = Level, - Met_Location = Location, - Met_Level = Level, + MetLocation = Location, + MetLevel = Level, MetDate = EncounterDate.GetDateSwitch(), Gender = Gender, - Nature = (byte)Nature, - StatNature = (byte)Nature, + Nature = Nature, + StatNature = Nature, Ball = (byte)FixedBall, ID32 = ID32, - Version = (byte)version, + Version = version, Language = lang, - OT_Gender = OTGender, - OT_Name = TrainerNames[lang], + OriginalTrainerGender = OTGender, + OriginalTrainerName = TrainerNames[lang], - OT_Friendship = pi.BaseFriendship, + OriginalTrainerFriendship = pi.BaseFriendship, IsNicknamed = IsFixedNickname, Nickname = IsFixedNickname ? Nicknames[lang] : SpeciesName.GetSpeciesNameGeneration(Species, lang, Generation), - HeightScalar = PokeSizeUtil.GetRandomScalar(), - WeightScalar = Weight.GetSizeValue(Weight != SizeType9.RANDOM ? FixedValueScale : default, ref rnd), - Scale = Scale.GetSizeValue(Scale != SizeType9.RANDOM ? FixedValueScale : default, ref rnd), + HeightScalar = PokeSizeUtil.GetRandomScalar(rnd), + WeightScalar = Weight.GetSizeValue(Weight != SizeType9.RANDOM ? FixedValueScale : default, ref xoro), + Scale = Scale.GetSizeValue(Scale != SizeType9.RANDOM ? FixedValueScale : default, ref xoro), TeraTypeOriginal = GetOriginalTeraType(), - HT_Name = tr.OT, - HT_Language = (byte)tr.Language, + HandlingTrainerName = tr.OT, + HandlingTrainerLanguage = (byte)tr.Language, CurrentHandler = 1, - HT_Friendship = pi.BaseFriendship, + HandlingTrainerFriendship = pi.BaseFriendship, Obedience_Level = Level, }; @@ -124,9 +125,10 @@ public PK9 ConvertToPKM(ITrainerInfo tr, EncounterCriteria criteria) private void SetPINGA(PK9 pk, EncounterCriteria criteria, PersonalInfo9SV pi) { - pk.PID = Util.Rand32(); - pk.EncryptionConstant = Util.Rand32(); - pk.Nature = pk.StatNature = (int)criteria.GetNature(Nature); + var rnd = Util.Rand; + pk.PID = rnd.Rand32(); + pk.EncryptionConstant = rnd.Rand32(); + pk.Nature = pk.StatNature = criteria.GetNature(Nature); pk.Gender = criteria.GetGender(Gender, pi); pk.RefreshAbility(criteria.GetAbilityFromNumber(Ability)); criteria.SetRandomIVs(pk, IVs); @@ -155,7 +157,7 @@ private bool IsMatchNatureGenderShiny(PKM pk) return false; if (pk.Gender != Gender) return false; - if (pk.Nature != (int)Nature) + if (pk.Nature != Nature) return false; return true; } @@ -166,7 +168,7 @@ private bool IsMatchNatureGenderShiny(PKM pk) public bool IsMatchExact(PKM pk, EvoCriteria evo) { - if (pk.Met_Level != Level) + if (pk.MetLevel != Level) return false; if (TeraType != GemType.Random && pk is ITeraType t && !Tera9RNG.IsMatchTeraType(TeraType, Species, Form, (byte)t.TeraTypeOriginal)) return false; @@ -180,7 +182,7 @@ public bool IsMatchExact(PKM pk, EvoCriteria evo) return false; if (evo.Form != Form && !FormInfo.IsFormChangeable(Species, Form, pk.Form, Context, pk.Context)) return false; - if (pk.OT_Gender != OTGender) + if (pk.OriginalTrainerGender != OTGender) return false; if (!IsMatchEggLocation(pk)) return false; @@ -214,8 +216,8 @@ private bool IsMatchEggLocation(PKM pk) return IsMatchEggLocationExact(pk) || IsMatchEggLocationRemapped(pk); } - private static bool IsMatchEggLocationRemapped(PKM pk) => pk.Egg_Location == 0; - private bool IsMatchEggLocationExact(PKM pk) => pk.Egg_Location == EggLocation; + private static bool IsMatchEggLocationRemapped(PKM pk) => pk.EggLocation == 0; + private bool IsMatchEggLocationExact(PKM pk) => pk.EggLocation == EggLocation; private bool IsMatchLocation(PKM pk) { @@ -227,14 +229,14 @@ private bool IsMatchLocation(PKM pk) return IsMatchLocationExact(pk) || IsMatchLocationRemapped(pk); } - private bool IsMatchLocationExact(PKM pk) => pk.Met_Location == Location; + private bool IsMatchLocationExact(PKM pk) => pk.MetLocation == Location; private bool IsMatchLocationRemapped(PKM pk) { - var met = (ushort)pk.Met_Location; + var met = pk.MetLocation; var version = pk.Version; if (pk.Context == EntityContext.Gen8) return LocationsHOME.IsValidMetSV(met, version); - return LocationsHOME.GetMetSWSH((ushort)Location, version) == met; + return LocationsHOME.GetMetSWSH(Location, version) == met; } } diff --git a/PKHeX.Core/Legality/Encounters/Templates/Interfaces/IEncounterArea.cs b/PKHeX.Core/Legality/Encounters/Templates/Interfaces/IEncounterArea.cs index e634ad72b..4257f6d5c 100644 --- a/PKHeX.Core/Legality/Encounters/Templates/Interfaces/IEncounterArea.cs +++ b/PKHeX.Core/Legality/Encounters/Templates/Interfaces/IEncounterArea.cs @@ -4,7 +4,7 @@ namespace PKHeX.Core; /// Contains a collection of for the area. /// /// Encounter Slot type. -public interface IEncounterArea where T : IEncounterTemplate, IVersion +public interface IEncounterArea where T : IEncounterTemplate { /// /// Slots in the area. @@ -17,5 +17,5 @@ public interface IEncounterArea where T : IEncounterTemplate, IVersion /// public interface IAreaLocation { - bool IsMatchLocation(int location); + bool IsMatchLocation(ushort location); } diff --git a/PKHeX.Core/Legality/Encounters/Templates/Interfaces/IEncounterTemplate.cs b/PKHeX.Core/Legality/Encounters/Templates/Interfaces/IEncounterTemplate.cs index 336e451b3..57ba41b2d 100644 --- a/PKHeX.Core/Legality/Encounters/Templates/Interfaces/IEncounterTemplate.cs +++ b/PKHeX.Core/Legality/Encounters/Templates/Interfaces/IEncounterTemplate.cs @@ -27,6 +27,6 @@ public static bool IsWithinEncounterRange(this IEncounterTemplate encounter, PKM return level == encounter.LevelMin; if (encounter is MysteryGift g) return level == g.Level; - return level == pk.Met_Level; + return level == pk.MetLevel; } } diff --git a/PKHeX.Core/Legality/Encounters/Templates/Interfaces/ILocation.cs b/PKHeX.Core/Legality/Encounters/Templates/Interfaces/ILocation.cs index 907647cc6..9a6798f20 100644 --- a/PKHeX.Core/Legality/Encounters/Templates/Interfaces/ILocation.cs +++ b/PKHeX.Core/Legality/Encounters/Templates/Interfaces/ILocation.cs @@ -8,30 +8,30 @@ public interface ILocation /// /// Met Location ID the encounter is found at. /// - int Location { get; } + ushort Location { get; } /// /// Egg Location ID the encounter is obtained with. /// - int EggLocation { get; } + ushort EggLocation { get; } } public static partial class Extensions { - public static int GetLocation(this ILocation enc) + public static ushort GetLocation(this ILocation enc) { return enc.Location != 0 ? enc.Location : enc.EggLocation; } - public static string? GetEncounterLocation(this ILocation enc, int gen, int version = -1) + public static string? GetEncounterLocation(this ILocation enc, byte generation, GameVersion version = 0) { - int loc = enc.GetLocation(); - if (loc < 0) + ushort loc = enc.GetLocation(); + if (loc == 0) return null; bool egg = loc != enc.Location; - return GameInfo.GetLocationName(egg, loc, gen, gen, (GameVersion)version); + return GameInfo.GetLocationName(egg, loc, generation, generation, version); } } diff --git a/PKHeX.Core/Legality/Encounters/Templates/Interfaces/Properties/IEncounterSlot34.cs b/PKHeX.Core/Legality/Encounters/Templates/Interfaces/Properties/IEncounterSlot34.cs new file mode 100644 index 000000000..d679d9ebb --- /dev/null +++ b/PKHeX.Core/Legality/Encounters/Templates/Interfaces/Properties/IEncounterSlot34.cs @@ -0,0 +1,21 @@ +namespace PKHeX.Core; + +/// +/// Common RNG-related properties for encounter slots in Gen 3-4. +/// +public interface IEncounterSlot34 : ILevelRange, IMagnetStatic, INumberedSlot, ISpeciesForm +{ + byte PressureLevel { get; } + byte AreaRate { get; } +} + +public interface IEncounterSlot4 : IEncounterSlot34 +{ + SlotType4 Type { get; } +} + +public interface IEncounterSlot3 : IEncounterSlot34 +{ + SlotType3 Type { get; } + bool IsSafariHoenn { get; } +} diff --git a/PKHeX.Core/Legality/Encounters/Templates/Interfaces/Properties/ILevelRange.cs b/PKHeX.Core/Legality/Encounters/Templates/Interfaces/Properties/ILevelRange.cs index f72e8ad63..591c8b1bc 100644 --- a/PKHeX.Core/Legality/Encounters/Templates/Interfaces/Properties/ILevelRange.cs +++ b/PKHeX.Core/Legality/Encounters/Templates/Interfaces/Properties/ILevelRange.cs @@ -16,7 +16,17 @@ public interface ILevelRange byte LevelMax { get; } } -public static class ILevelRangeExtensions +/// +/// Simple abstraction to hold a single level. +/// +/// Min and Max level. +public readonly record struct SingleLevelRange(byte Level) : ILevelRange +{ + public byte LevelMin => Level; + public byte LevelMax => Level; +} + +public static class LevelRangeExtensions { public static bool IsFixedLevel(this ILevelRange r) => r.LevelMin == r.LevelMax; public static bool IsRandomLevel(this ILevelRange r) => r.LevelMin != r.LevelMax; @@ -29,6 +39,9 @@ public static class ILevelRangeExtensions /// True if within slot's range, false if impossible. public static bool IsLevelWithinRange(this ILevelRange r, int lvl) => r.LevelMin <= lvl && lvl <= r.LevelMax; + /// + public static bool IsLevelWithinRange(int level, int min, int max) => min <= level && level <= max; + /// /// Gets if the specified level inputs are within range of the and /// diff --git a/PKHeX.Core/Legality/Encounters/Templates/Interfaces/Properties/IRestrictVersion.cs b/PKHeX.Core/Legality/Encounters/Templates/Interfaces/Properties/IRestrictVersion.cs index 8a3ac4594..5b61f742e 100644 --- a/PKHeX.Core/Legality/Encounters/Templates/Interfaces/Properties/IRestrictVersion.cs +++ b/PKHeX.Core/Legality/Encounters/Templates/Interfaces/Properties/IRestrictVersion.cs @@ -2,5 +2,5 @@ namespace PKHeX.Core; public interface IRestrictVersion { - bool CanBeReceivedByVersion(int version); + bool CanBeReceivedByVersion(GameVersion version); } diff --git a/PKHeX.Core/Legality/Encounters/Templates/Interfaces/RNG/IMagnetStatic.cs b/PKHeX.Core/Legality/Encounters/Templates/Interfaces/RNG/IMagnetStatic.cs index fe1f67e53..2be323c3d 100644 --- a/PKHeX.Core/Legality/Encounters/Templates/Interfaces/RNG/IMagnetStatic.cs +++ b/PKHeX.Core/Legality/Encounters/Templates/Interfaces/RNG/IMagnetStatic.cs @@ -23,13 +23,38 @@ public interface IMagnetStatic /// /// Indicates if the slot can be yielded by . /// - bool IsStaticSlot => StaticCount != 0 && StaticIndex != byte.MaxValue; + bool IsStaticSlot => StaticCount != 0; /// /// Indicates if the slot can be yielded by . /// - bool IsMagnetSlot => MagnetPullCount != 0 && MagnetPullIndex != byte.MaxValue; - - bool IsMatchStatic(int index, int count) => index == StaticIndex && count == StaticCount; - bool IsMatchMagnet(int index, int count) => index == MagnetPullIndex && count == MagnetPullCount; + bool IsMagnetSlot => MagnetPullCount != 0; +} + +public static class MagnetStaticExtensions +{ + /// + /// Checks if the can be an encounter slot chosen via Static or Magnet Pull. + /// + /// Encounter Slot + /// [0,65535] + /// Which one it matched, if any. + /// False if not a matching slot. + public static bool IsSlotValidStaticMagnet(this T enc, uint u16SlotRand, out LeadRequired lead) where T : IMagnetStatic + { + if (enc.IsStaticSlot && u16SlotRand % enc.StaticCount == enc.StaticIndex) + { + lead = LeadRequired.Static; + return true; + } + // Isn't checked for Fishing slots, but no fishing slots are steel type -- always false. + if (enc.IsMagnetSlot && u16SlotRand % enc.MagnetPullCount == enc.MagnetPullIndex) + { + lead = LeadRequired.MagnetPull; + return true; + } + + lead = LeadRequired.None; + return false; + } } diff --git a/PKHeX.Core/Legality/Encounters/Templates/Interfaces/RNG/ISlotRNGType.cs b/PKHeX.Core/Legality/Encounters/Templates/Interfaces/RNG/ISlotRNGType.cs deleted file mode 100644 index 87109efd8..000000000 --- a/PKHeX.Core/Legality/Encounters/Templates/Interfaces/RNG/ISlotRNGType.cs +++ /dev/null @@ -1,12 +0,0 @@ -namespace PKHeX.Core; - -/// -/// Contains information about the slot types the object represents. -/// -public interface ISlotRNGType -{ - /// - /// Encounter Slot Type - /// - SlotType Type { get; } -} diff --git a/PKHeX.Core/Legality/Encounters/Templates/Shared/EncounterEgg.cs b/PKHeX.Core/Legality/Encounters/Templates/Shared/EncounterEgg.cs index 0a7ae5e51..1df89673c 100644 --- a/PKHeX.Core/Legality/Encounters/Templates/Shared/EncounterEgg.cs +++ b/PKHeX.Core/Legality/Encounters/Templates/Shared/EncounterEgg.cs @@ -5,7 +5,7 @@ namespace PKHeX.Core; /// /// Egg Encounter Data /// -public sealed record EncounterEgg(ushort Species, byte Form, byte Level, int Generation, GameVersion Version, EntityContext Context) : IEncounterable +public sealed record EncounterEgg(ushort Species, byte Form, byte Level, byte Generation, GameVersion Version, EntityContext Context) : IEncounterable { public string Name => "Egg"; public string LongName => "Egg"; @@ -14,8 +14,8 @@ public sealed record EncounterEgg(ushort Species, byte Form, byte Level, int Gen public byte LevelMin => Level; public byte LevelMax => Level; public bool IsShiny => false; - public int Location => 0; - public int EggLocation => Locations.GetDaycareLocation(Generation, Version); + public ushort Location => 0; + public ushort EggLocation => Locations.GetDaycareLocation(Generation, Version); public Ball FixedBall => Generation <= 5 ? Ball.Poke : Ball.None; public Shiny Shiny => Shiny.Random; public AbilityPermission Ability => AbilityPermission.Any12H; @@ -26,7 +26,7 @@ public sealed record EncounterEgg(ushort Species, byte Form, byte Level, int Gen public PKM ConvertToPKM(ITrainerInfo tr, EncounterCriteria criteria) { - int gen = Generation; + var gen = Generation; var version = Version; var pk = EntityBlank.GetBlank(gen, version); @@ -38,27 +38,28 @@ public PKM ConvertToPKM(ITrainerInfo tr, EncounterCriteria criteria) pk.Language = lang; pk.Nickname = SpeciesName.GetSpeciesNameGeneration(Species, lang, gen); pk.CurrentLevel = Level; - pk.Version = (byte)version; + pk.Version = version; var ball = FixedBall; - pk.Ball = ball is Ball.None ? (int)Ball.Poke : (int)ball; - pk.OT_Friendship = pk.PersonalInfo.BaseFriendship; + pk.Ball = ball is Ball.None ? (byte)Ball.Poke : (byte)ball; + pk.OriginalTrainerFriendship = pk.PersonalInfo.BaseFriendship; SetEncounterMoves(pk, version); pk.HealPP(); + var rnd = Util.Rand; SetPINGA(pk, criteria); if (gen <= 2) { if (version != GameVersion.C) { - pk.OT_Gender = 0; + pk.OriginalTrainerGender = 0; } else { - pk.Met_Location = Locations.HatchLocationC; - pk.Met_Level = 1; - ((PK2)pk).Met_TimeOfDay = Util.Rand.Next(1, 4); // Morning | Day | Night + pk.MetLocation = Locations.HatchLocationC; + pk.MetLevel = 1; + ((PK2)pk).MetTimeOfDay = rnd.Next(1, 4); // Morning | Day | Night } return pk; } @@ -66,7 +67,7 @@ public PKM ConvertToPKM(ITrainerInfo tr, EncounterCriteria criteria) SetMetData(pk); if (gen >= 4) - pk.SetEggMetData(version, (GameVersion)tr.Game); + pk.SetEggMetData(version, tr.Version); if (gen < 6) return pk; @@ -82,17 +83,17 @@ public PKM ConvertToPKM(ITrainerInfo tr, EncounterCriteria criteria) pk.RelearnMove4 = pk.Move4; if (pk is IScaledSize s) { - s.HeightScalar = PokeSizeUtil.GetRandomScalar(); - s.WeightScalar = PokeSizeUtil.GetRandomScalar(); + s.HeightScalar = PokeSizeUtil.GetRandomScalar(rnd); + s.WeightScalar = PokeSizeUtil.GetRandomScalar(rnd); if (pk is IScaledSize3 s3) - s3.Scale = PokeSizeUtil.GetRandomScalar(); + s3.Scale = PokeSizeUtil.GetRandomScalar(rnd); } if (pk is ITeraType tera) { - var type = Tera9RNG.GetTeraTypeFromPersonal(Species, Form, Util.Rand.Rand64()); + var type = Tera9RNG.GetTeraTypeFromPersonal(Species, Form, rnd.Rand64()); tera.TeraTypeOriginal = (MoveType)type; - if (criteria.TeraType != -1 && type != criteria.TeraType) + if (criteria.IsSpecifiedTeraType() && type != criteria.TeraType) tera.SetTeraType(type); // sets the override type } @@ -120,8 +121,8 @@ private static void SetPINGA(PKM pk, EncounterCriteria criteria) if (pk.Format <= 2) return; - int gender = criteria.GetGender(pk.PersonalInfo); - int nature = (int)criteria.GetNature(); + var gender = criteria.GetGender(pk.PersonalInfo); + var nature = criteria.GetNature(); if (pk.Format <= 5) { @@ -142,11 +143,11 @@ private static void SetPINGA(PKM pk, EncounterCriteria criteria) private void SetMetData(PKM pk) { - pk.Met_Level = EggStateLegality.GetEggLevelMet(Version, Generation); - pk.Met_Location = Math.Max(0, EggStateLegality.GetEggHatchLocation(Version, Generation)); + pk.MetLevel = EggStateLegality.GetEggLevelMet(Version, Generation); + pk.MetLocation = Math.Max((ushort)0, EggStateLegality.GetEggHatchLocation(Version, Generation)); if (pk is IObedienceLevel l) - l.Obedience_Level = (byte)pk.Met_Level; + l.Obedience_Level = pk.MetLevel; } private void SetEncounterMoves(PKM pk, GameVersion version) diff --git a/PKHeX.Core/Legality/Encounters/Templates/Shared/EncounterInvalid.cs b/PKHeX.Core/Legality/Encounters/Templates/Shared/EncounterInvalid.cs index 59e1032a9..e566c5020 100644 --- a/PKHeX.Core/Legality/Encounters/Templates/Shared/EncounterInvalid.cs +++ b/PKHeX.Core/Legality/Encounters/Templates/Shared/EncounterInvalid.cs @@ -14,7 +14,7 @@ public sealed record EncounterInvalid : IEncounterable public byte LevelMin { get; } public byte LevelMax { get; } public bool EggEncounter { get; } - public int Generation { get; } + public byte Generation { get; } public EntityContext Context { get; } public GameVersion Version { get; } public bool IsShiny => false; @@ -22,8 +22,8 @@ public sealed record EncounterInvalid : IEncounterable public string Name => "Invalid"; public string LongName => "Invalid"; - public int Location => 0; - public int EggLocation => 0; + public ushort Location => 0; + public ushort EggLocation => 0; public AbilityPermission Ability => AbilityPermission.Any12H; public Ball FixedBall => Ball.None; @@ -33,11 +33,11 @@ public EncounterInvalid(PKM pk) { Species = pk.Species; Form = pk.Form; - LevelMin = (byte)pk.Met_Level; - LevelMax = (byte)pk.CurrentLevel; + LevelMin = pk.MetLevel; + LevelMax = pk.CurrentLevel; EggEncounter = pk.WasEgg; Generation = pk.Generation; - Version = (GameVersion)pk.Version; + Version = pk.Version; Context = pk.Context; } diff --git a/PKHeX.Core/Legality/Encounters/Verifiers/EggHatchLocation3.cs b/PKHeX.Core/Legality/Encounters/Verifiers/EggHatchLocation3.cs index b796b65f9..369be3a0e 100644 --- a/PKHeX.Core/Legality/Encounters/Verifiers/EggHatchLocation3.cs +++ b/PKHeX.Core/Legality/Encounters/Verifiers/EggHatchLocation3.cs @@ -16,7 +16,7 @@ public static class EggHatchLocation3 /// /// Returns true if the hatch location is valid for the specified Generation 3 game. /// - public static bool IsValidMet3(int location, GameVersion game) => game switch + public static bool IsValidMet3(ushort location, GameVersion game) => game switch { R or S => IsValidMet3RS(location), E => IsValidMet3E(location), @@ -27,24 +27,24 @@ public static class EggHatchLocation3 /// /// Returns true if the hatch location is valid for Ruby and Sapphire. /// - public static bool IsValidMet3RS(int location) => HasLocationFlag(LocationPermitted3, MaskRS, location); + public static bool IsValidMet3RS(ushort location) => HasLocationFlag(LocationPermitted3, MaskRS, location); /// /// Returns true if the hatch location is valid for Emerald. /// - public static bool IsValidMet3E(int location) => HasLocationFlag(LocationPermitted3, MaskE, location); + public static bool IsValidMet3E(ushort location) => HasLocationFlag(LocationPermitted3, MaskE, location); /// /// Returns true if the hatch location is valid for FireRed and LeafGreen. /// - public static bool IsValidMet3FRLG(int location) => HasLocationFlag(LocationPermitted3, MaskFRLG, location); + public static bool IsValidMet3FRLG(ushort location) => HasLocationFlag(LocationPermitted3, MaskFRLG, location); /// /// Returns true if the hatch location is valid for any Generation 3 game. /// - public static bool IsValidMet3Any(int location) => HasLocationFlag(LocationPermitted3, MaskAll, location); + public static bool IsValidMet3Any(ushort location) => HasLocationFlag(LocationPermitted3, MaskAll, location); - private static bool HasLocationFlag(ReadOnlySpan arr, byte mask, int location) + private static bool HasLocationFlag(ReadOnlySpan arr, byte mask, ushort location) { if ((uint)location >= arr.Length) return false; diff --git a/PKHeX.Core/Legality/Encounters/Verifiers/EggHatchLocation4.cs b/PKHeX.Core/Legality/Encounters/Verifiers/EggHatchLocation4.cs index fe3599174..a5f05f24b 100644 --- a/PKHeX.Core/Legality/Encounters/Verifiers/EggHatchLocation4.cs +++ b/PKHeX.Core/Legality/Encounters/Verifiers/EggHatchLocation4.cs @@ -16,7 +16,7 @@ public static class EggHatchLocation4 /// /// Returns true if the hatch location is valid for the specified Generation 4 game. /// - public static bool IsValidMet4(int location, GameVersion game) => game switch + public static bool IsValidMet4(ushort location, GameVersion game) => game switch { D or P => IsValidMet4DP(location), Pt => IsValidMet4Pt(location), @@ -27,24 +27,24 @@ public static class EggHatchLocation4 /// /// Returns true if the hatch location is valid for Diamond and Pearl. /// - public static bool IsValidMet4DP(int location) => HasLocationFlag(LocationPermitted4, MaskDP, location); + public static bool IsValidMet4DP(ushort location) => HasLocationFlag(LocationPermitted4, MaskDP, location); /// /// Returns true if the hatch location is valid for Platinum. /// - public static bool IsValidMet4Pt(int location) => HasLocationFlag(LocationPermitted4, MaskPt, location); + public static bool IsValidMet4Pt(ushort location) => HasLocationFlag(LocationPermitted4, MaskPt, location); /// /// Returns true if the hatch location is valid for HeartGold and SoulSilver. /// - public static bool IsValidMet4HGSS(int location) => HasLocationFlag(LocationPermitted4, MaskHGSS, location); + public static bool IsValidMet4HGSS(ushort location) => HasLocationFlag(LocationPermitted4, MaskHGSS, location); /// /// Returns true if the hatch location is valid for any Generation 4 game. /// - public static bool IsValidMet4Any(int location) => HasLocationFlag(LocationPermitted4, MaskAll4, location); + public static bool IsValidMet4Any(ushort location) => HasLocationFlag(LocationPermitted4, MaskAll4, location); - private static bool HasLocationFlag(ReadOnlySpan arr, byte mask, int location) + private static bool HasLocationFlag(ReadOnlySpan arr, byte mask, ushort location) { if ((uint)location >= arr.Length) return false; diff --git a/PKHeX.Core/Legality/Encounters/Verifiers/EggHatchLocation5.cs b/PKHeX.Core/Legality/Encounters/Verifiers/EggHatchLocation5.cs index eebbb579c..900de2339 100644 --- a/PKHeX.Core/Legality/Encounters/Verifiers/EggHatchLocation5.cs +++ b/PKHeX.Core/Legality/Encounters/Verifiers/EggHatchLocation5.cs @@ -16,7 +16,7 @@ public static class EggHatchLocation5 /// /// Returns true if the location is valid for the specified Generation 5 game. /// - public static bool IsValidMet5(int location, GameVersion game) + public static bool IsValidMet5(ushort location, GameVersion game) { var shift = (uint)(game - W); if (shift >= 4) @@ -29,24 +29,24 @@ public static bool IsValidMet5(int location, GameVersion game) /// /// Returns true if the hatch location is valid for White. /// - public static bool IsValidMet5W(int location) => HasLocationFlag(LocationPermitted5, MaskWhite, location); + public static bool IsValidMet5W(ushort location) => HasLocationFlag(LocationPermitted5, MaskWhite, location); /// /// Returns true if the hatch location is valid for Black. /// - public static bool IsValidMet5B(int location) => HasLocationFlag(LocationPermitted5, MaskBlack, location); + public static bool IsValidMet5B(ushort location) => HasLocationFlag(LocationPermitted5, MaskBlack, location); /// /// Returns true if the hatch location is valid for White 2. /// - public static bool IsValidMet5W2(int location) => HasLocationFlag(LocationPermitted5, MaskWhite2, location); + public static bool IsValidMet5W2(ushort location) => HasLocationFlag(LocationPermitted5, MaskWhite2, location); /// /// Returns true if the hatch location is valid for Black 2. /// - public static bool IsValidMet5B2(int location) => HasLocationFlag(LocationPermitted5, MaskBlack2, location); + public static bool IsValidMet5B2(ushort location) => HasLocationFlag(LocationPermitted5, MaskBlack2, location); - private static bool HasLocationFlag(ReadOnlySpan arr, byte mask, int location) + private static bool HasLocationFlag(ReadOnlySpan arr, byte mask, ushort location) { if ((uint)location >= arr.Length) return false; diff --git a/PKHeX.Core/Legality/Encounters/Verifiers/EggHatchLocation6.cs b/PKHeX.Core/Legality/Encounters/Verifiers/EggHatchLocation6.cs index c309c3556..e40386c2a 100644 --- a/PKHeX.Core/Legality/Encounters/Verifiers/EggHatchLocation6.cs +++ b/PKHeX.Core/Legality/Encounters/Verifiers/EggHatchLocation6.cs @@ -8,7 +8,7 @@ public static class EggHatchLocation6 /// /// Returns true if the hatch location is valid for X and Y. /// - public static bool IsValidMet6XY(int location) + public static bool IsValidMet6XY(ushort location) { const int min = 6; const int max = 168; @@ -24,7 +24,7 @@ public static bool IsValidMet6XY(int location) /// /// Returns true if the hatch location is valid for Omega Ruby and Alpha Sapphire. /// - public static bool IsValidMet6AO(int location) + public static bool IsValidMet6AO(ushort location) { const int min = 170; const int max = 354; diff --git a/PKHeX.Core/Legality/Encounters/Verifiers/EggHatchLocation7.cs b/PKHeX.Core/Legality/Encounters/Verifiers/EggHatchLocation7.cs index 3c2e91dc5..bfb01ec18 100644 --- a/PKHeX.Core/Legality/Encounters/Verifiers/EggHatchLocation7.cs +++ b/PKHeX.Core/Legality/Encounters/Verifiers/EggHatchLocation7.cs @@ -13,7 +13,7 @@ public static class EggHatchLocation7 /// /// Returns true if the hatch location is valid for Sun and Moon. /// - public static bool IsValidMet7SM(int location) + public static bool IsValidMet7SM(ushort location) { if (HasLocationFlag(LocationPermitted7, MaskSM, location)) return true; @@ -23,14 +23,14 @@ public static bool IsValidMet7SM(int location) /// /// Returns true if the hatch location is valid for Ultra Sun and Ultra Moon. /// - public static bool IsValidMet7USUM(int location) + public static bool IsValidMet7USUM(ushort location) { if (HasLocationFlag(LocationPermitted7, MaskUSUM, location)) return true; return location == Locations.Pelago7; // 30016 } - private static bool HasLocationFlag(ReadOnlySpan arr, byte mask, int location) + private static bool HasLocationFlag(ReadOnlySpan arr, byte mask, ushort location) { if ((uint)location >= arr.Length) return false; diff --git a/PKHeX.Core/Legality/Encounters/Verifiers/EggHatchLocation8.cs b/PKHeX.Core/Legality/Encounters/Verifiers/EggHatchLocation8.cs index 56d557eb7..d16444847 100644 --- a/PKHeX.Core/Legality/Encounters/Verifiers/EggHatchLocation8.cs +++ b/PKHeX.Core/Legality/Encounters/Verifiers/EggHatchLocation8.cs @@ -10,7 +10,7 @@ public static class EggHatchLocation8 /// /// Returns true if the hatch location is valid for Sword and Shield. /// - public static bool IsValidMet8SWSH(int location) + public static bool IsValidMet8SWSH(ushort location) { if (location % 2 != 0) return false; diff --git a/PKHeX.Core/Legality/Encounters/Verifiers/EggHatchLocation8b.cs b/PKHeX.Core/Legality/Encounters/Verifiers/EggHatchLocation8b.cs index d7a7e7e6b..6b5bb916a 100644 --- a/PKHeX.Core/Legality/Encounters/Verifiers/EggHatchLocation8b.cs +++ b/PKHeX.Core/Legality/Encounters/Verifiers/EggHatchLocation8b.cs @@ -13,14 +13,14 @@ public static class EggHatchLocation8b /// /// Returns true if the hatch location is valid for Brilliant Diamond. /// - public static bool IsValidMet8BD(int location) => HasLocationFlag(LocationPermitted8b, MaskBD, location); + public static bool IsValidMet8BD(ushort location) => HasLocationFlag(LocationPermitted8b, MaskBD, location); /// /// Returns true if the hatch location is valid for Shining Pearl. /// - public static bool IsValidMet8SP(int location) => HasLocationFlag(LocationPermitted8b, MaskSP, location); + public static bool IsValidMet8SP(ushort location) => HasLocationFlag(LocationPermitted8b, MaskSP, location); - private static bool HasLocationFlag(ReadOnlySpan arr, byte mask, int location) + private static bool HasLocationFlag(ReadOnlySpan arr, byte mask, ushort location) { if ((uint)location >= arr.Length) return false; diff --git a/PKHeX.Core/Legality/Encounters/Verifiers/EggHatchLocation9.cs b/PKHeX.Core/Legality/Encounters/Verifiers/EggHatchLocation9.cs index 1df0f8ad8..1da699936 100644 --- a/PKHeX.Core/Legality/Encounters/Verifiers/EggHatchLocation9.cs +++ b/PKHeX.Core/Legality/Encounters/Verifiers/EggHatchLocation9.cs @@ -13,14 +13,14 @@ public static class EggHatchLocation9 /// /// Returns true if the hatch location is valid for Scarlet. /// - public static bool IsValidMet9SL(int location) => HasLocationFlag(LocationPermitted9, MaskScarlet, location); + public static bool IsValidMet9SL(ushort location) => HasLocationFlag(LocationPermitted9, MaskScarlet, location); /// /// Returns true if the hatch location is valid for Violet. /// - public static bool IsValidMet9VL(int location) => HasLocationFlag(LocationPermitted9, MaskViolet, location); + public static bool IsValidMet9VL(ushort location) => HasLocationFlag(LocationPermitted9, MaskViolet, location); - private static bool HasLocationFlag(ReadOnlySpan arr, byte mask, int location) + private static bool HasLocationFlag(ReadOnlySpan arr, byte mask, ushort location) { if ((uint)location >= arr.Length) return false; diff --git a/PKHeX.Core/Legality/Encounters/Verifiers/EncounterVerifier.cs b/PKHeX.Core/Legality/Encounters/Verifiers/EncounterVerifier.cs index 1dae5905f..5b3287f72 100644 --- a/PKHeX.Core/Legality/Encounters/Verifiers/EncounterVerifier.cs +++ b/PKHeX.Core/Legality/Encounters/Verifiers/EncounterVerifier.cs @@ -13,7 +13,7 @@ public static class EncounterVerifier /// /// Source generation to verify /// Returns the verification method appropriate for the input PKM - public static Func GetEncounterVerifierMethod(int generation) => generation switch + public static Func GetEncounterVerifierMethod(byte generation) => generation switch { 1 or 2 => VerifyEncounterG12, _ => VerifyEncounter, @@ -25,7 +25,7 @@ public static class EncounterVerifier EncounterShadow3Colo { IsEReader: true } when pk.Language != (int)LanguageID.Japanese => GetInvalid(LG3EReader), EncounterStatic3 { Species: (int)Species.Mew, Location: 201 } when pk.Language != (int)LanguageID.Japanese => GetInvalid(LEncUnreleasedEMewJP), EncounterStatic3 { Species: (int)Species.Deoxys, Location: 200 } when pk.Language == (int)LanguageID.Japanese => GetInvalid(LEncUnreleased), - EncounterStatic4 { Roaming: true } when pk is G4PKM { Met_Location: 193, GroundTile: GroundTileType.Water } => GetInvalid(LG4InvalidTileR45Surf), + EncounterStatic4 { Roaming: true } when pk is G4PKM { MetLocation: 193, GroundTile: GroundTileType.Water } => GetInvalid(LG4InvalidTileR45Surf), MysteryGift g => VerifyEncounterEvent(pk, g), { EggEncounter: true } when !pk.IsEgg => VerifyEncounterEgg(pk, enc.Generation), EncounterInvalid => GetInvalid(LEncInvalid), @@ -48,22 +48,16 @@ private static CheckResult VerifyEncounterG12(PKM pk, IEncounterTemplate enc) } // Gen2 Wild Encounters - private static CheckResult VerifyWildEncounterGen2(ITrainerID16 pk, EncounterSlot2 enc) => enc.SlotType switch + private static CheckResult VerifyWildEncounterGen2(ITrainerID16 pk, EncounterSlot2 enc) => enc.Type switch { - SlotType.Headbutt => enc.IsTreeAvailable(pk.TID16) + SlotType2.Headbutt or SlotType2.HeadbuttSpecial => enc.IsTreeAvailable(pk.TID16) ? GetValid(LG2TreeID) : GetInvalid(LG2InvalidTileTreeNotFound), - SlotType.Old_Rod or SlotType.Good_Rod or SlotType.Super_Rod => enc.Location switch - { - 19 => GetInvalid(LG2InvalidTilePark), // National Park - 76 => GetInvalid(LG2InvalidTileR14), // Route 14 - _ => GetValid(LEncCondition), - }, _ => GetValid(LEncCondition), }; // Eggs - private static CheckResult VerifyEncounterEgg(PKM pk, int gen) => gen switch + private static CheckResult VerifyEncounterEgg(PKM pk, byte generation) => generation switch { 2 => pk.IsEgg ? VerifyUnhatchedEgg2(pk) : VerifyEncounterEgg2(pk), 3 => pk.IsEgg ? VerifyUnhatchedEgg3(pk) : VerifyEncounterEgg3(pk), @@ -71,7 +65,7 @@ private static CheckResult VerifyEncounterG12(PKM pk, IEncounterTemplate enc) 5 => pk.IsEgg ? VerifyUnhatchedEgg(pk, Locations.LinkTrade5) : VerifyEncounterEgg5(pk), 6 => pk.IsEgg ? VerifyUnhatchedEgg(pk, Locations.LinkTrade6) : VerifyEncounterEgg6(pk), 7 => pk.IsEgg ? VerifyUnhatchedEgg(pk, Locations.LinkTrade6) : VerifyEncounterEgg7(pk), - 8 when GameVersion.BDSP.Contains((GameVersion)pk.Version) => pk.IsEgg ? VerifyUnhatchedEgg(pk, Locations.LinkTrade6NPC, Locations.Default8bNone) : VerifyEncounterEgg8BDSP(pk), + 8 when GameVersion.BDSP.Contains(pk.Version) => pk.IsEgg ? VerifyUnhatchedEgg(pk, Locations.LinkTrade6NPC, Locations.Default8bNone) : VerifyEncounterEgg8BDSP(pk), 8 => pk.IsEgg ? VerifyUnhatchedEgg(pk, Locations.LinkTrade6) : VerifyEncounterEgg8(pk), 9 => pk.IsEgg ? VerifyUnhatchedEgg(pk, Locations.LinkTrade6) : VerifyEncounterEgg9(pk), _ => GetInvalid(LEggLocationInvalid), @@ -82,10 +76,10 @@ private static CheckResult VerifyEncounterEgg2(PKM pk) if (pk is not ICaughtData2 { CaughtData: not 0 } c2) return GetValid(LEggLocation); - if (c2.Met_Level != 1) + if (c2.MetLevel != 1) return GetInvalid(string.Format(LEggFMetLevel_0, 1)); - if (pk.Met_Location > 95) + if (pk.MetLocation > 95) return GetInvalid(LEggMetLocationFail); // Any met location is fine. return GetValid(LEggLocation); @@ -96,21 +90,21 @@ private static CheckResult VerifyUnhatchedEgg2(PKM pk) if (pk is not ICaughtData2 { CaughtData: not 0 } c2) return new CheckResult(CheckIdentifier.Encounter); - if (c2.Met_Level != 1) + if (c2.MetLevel != 1) return GetInvalid(string.Format(LEggFMetLevel_0, 1)); - if (c2.Met_Location != 0) + if (c2.MetLocation != 0) return GetInvalid(LEggLocationInvalid); return GetValid(LEggLocation); } private static CheckResult VerifyUnhatchedEgg3(PKM pk) { - if (pk.Met_Level != 0) + if (pk.MetLevel != 0) return GetInvalid(string.Format(LEggFMetLevel_0, 0)); // Only EncounterEgg should reach here. var loc = pk.FRLG ? Locations.HatchLocationFRLG : Locations.HatchLocationRSE; - if (pk.Met_Location != loc) + if (pk.MetLocation != loc) return GetInvalid(LEggMetLocationFail); return GetValid(LEggLocation); @@ -121,12 +115,12 @@ private static CheckResult VerifyEncounterEgg3(PKM pk) if (pk.Format != 3) return VerifyEncounterEgg3Transfer(pk); - if (pk.Met_Level != 0) + if (pk.MetLevel != 0) return GetInvalid(string.Format(LEggFMetLevel_0, 0)); // Check the origin game list. - var met = (byte)pk.Met_Location; - bool valid = EggHatchLocation3.IsValidMet3(met, (GameVersion)pk.Version); + var met = (byte)pk.MetLocation; + bool valid = EggHatchLocation3.IsValidMet3(met, pk.Version); if (valid) return GetValid(LEggLocation); @@ -143,21 +137,21 @@ private static CheckResult VerifyEncounterEgg3Transfer(PKM pk) { if (pk.IsEgg) return GetInvalid(LTransferEgg); - if (pk.Met_Level < 5) + if (pk.MetLevel < 5) return GetInvalid(LTransferEggMetLevel); var expectEgg = pk is PB8 ? Locations.Default8bNone : 0; - if (pk.Egg_Location != expectEgg) + if (pk.EggLocation != expectEgg) return GetInvalid(LEggLocationNone); if (pk.Format != 4) { - if (pk.Met_Location != Locations.Transfer4) + if (pk.MetLocation != Locations.Transfer4) return GetInvalid(LTransferEggLocationTransporter); } else { - if (pk.Met_Location != Locations.Transfer3) + if (pk.MetLocation != Locations.Transfer3) return GetInvalid(LEggLocationPalPark); } @@ -170,20 +164,20 @@ private static CheckResult VerifyEncounterEgg4(PKM pk) { if (pk.IsEgg) return GetInvalid(LTransferEgg); - if (pk.Met_Level < 1) + if (pk.MetLevel < 1) return GetInvalid(LTransferEggMetLevel); - if (pk.Met_Location != Locations.Transfer4) + if (pk.MetLocation != Locations.Transfer4) return GetInvalid(LTransferEggLocationTransporter); return GetValid(LEggLocation); } // Native const byte level = EggStateLegality.EggMetLevel34; - if (pk.Met_Level != level) + if (pk.MetLevel != level) return GetInvalid(string.Format(LEggFMetLevel_0, level)); - var met = (ushort)pk.Met_Location; - bool valid = EggHatchLocation4.IsValidMet4(met, (GameVersion)pk.Version); + var met = pk.MetLocation; + bool valid = EggHatchLocation4.IsValidMet4(met, pk.Version); if (valid) return GetValid(LEggLocation); @@ -196,11 +190,11 @@ private static CheckResult VerifyEncounterEgg4(PKM pk) private static CheckResult VerifyEncounterEgg5(PKM pk) { const byte level = EggStateLegality.EggMetLevel; - if (pk.Met_Level != level) + if (pk.MetLevel != level) return GetInvalid(string.Format(LEggFMetLevel_0, level)); - var met = (ushort)pk.Met_Location; - bool valid = EggHatchLocation5.IsValidMet5(met, (GameVersion)pk.Version); + var met = pk.MetLocation; + bool valid = EggHatchLocation5.IsValidMet5(met, pk.Version); if (valid) return GetValid(LEggLocation); @@ -210,10 +204,10 @@ private static CheckResult VerifyEncounterEgg5(PKM pk) private static CheckResult VerifyEncounterEgg6(PKM pk) { const byte level = EggStateLegality.EggMetLevel; - if (pk.Met_Level != level) + if (pk.MetLevel != level) return GetInvalid(string.Format(LEggFMetLevel_0, level)); - var met = (ushort)pk.Met_Location; + var met = pk.MetLocation; bool valid = pk.XY ? EggHatchLocation6.IsValidMet6XY(met) : EggHatchLocation6.IsValidMet6AO(met); @@ -226,10 +220,10 @@ private static CheckResult VerifyEncounterEgg6(PKM pk) private static CheckResult VerifyEncounterEgg7(PKM pk) { const byte level = EggStateLegality.EggMetLevel; - if (pk.Met_Level != level) + if (pk.MetLevel != level) return GetInvalid(string.Format(LEggFMetLevel_0, level)); - var met = (ushort)pk.Met_Location; + var met = pk.MetLocation; bool valid = pk.SM ? EggHatchLocation7.IsValidMet7SM(met) : EggHatchLocation7.IsValidMet7USUM(met); @@ -242,10 +236,10 @@ private static CheckResult VerifyEncounterEgg7(PKM pk) private static CheckResult VerifyEncounterEgg8(PKM pk) { const byte level = EggStateLegality.EggMetLevel; - if (pk.Met_Level != level) + if (pk.MetLevel != level) return GetInvalid(string.Format(LEggFMetLevel_0, level)); - var valid = IsValidMetForeignEggSWSH(pk, (ushort)pk.Met_Location); + var valid = IsValidMetForeignEggSWSH(pk, pk.MetLocation); if (valid) return GetValid(LEggLocation); return GetInvalid(LEggLocationInvalid); @@ -266,11 +260,11 @@ private static CheckResult VerifyEncounterEgg8BDSP(PKM pk) return VerifyEncounterEgg8(pk); const byte level = EggStateLegality.EggMetLevel; - if (pk.Met_Level != level) + if (pk.MetLevel != level) return GetInvalid(string.Format(LEggFMetLevel_0, level)); - var met = (ushort)pk.Met_Location; - bool valid = pk.Version == (int)GameVersion.BD + var met = pk.MetLocation; + bool valid = pk.Version == GameVersion.BD ? EggHatchLocation8b.IsValidMet8BD(met) : EggHatchLocation8b.IsValidMet8SP(met); @@ -285,11 +279,11 @@ private static CheckResult VerifyEncounterEgg9(PKM pk) return VerifyEncounterEgg8(pk); const byte level = EggStateLegality.EggMetLevel; - if (pk.Met_Level != level) + if (pk.MetLevel != level) return GetInvalid(string.Format(LEggFMetLevel_0, level)); - var met = (ushort)pk.Met_Location; - bool valid = pk.Version == (int)GameVersion.SL + var met = pk.MetLocation; + bool valid = pk.Version == GameVersion.SL ? EggHatchLocation9.IsValidMet9SL(met) : EggHatchLocation9.IsValidMet9VL(met); @@ -301,12 +295,12 @@ private static CheckResult VerifyEncounterEgg9(PKM pk) private static CheckResult VerifyUnhatchedEgg(PKM pk, int tradeLoc, int noneLoc = 0) { var eggLevel = pk.Format is 3 or 4 ? EggStateLegality.EggMetLevel34 : EggStateLegality.EggMetLevel; - if (pk.Met_Level != eggLevel) + if (pk.MetLevel != eggLevel) return GetInvalid(string.Format(LEggFMetLevel_0, eggLevel)); - if (pk.Egg_Location == tradeLoc) + if (pk.EggLocation == tradeLoc) return GetInvalid(LEggLocationTradeFail); - var met = pk.Met_Location; + var met = pk.MetLocation; if (met == tradeLoc) return GetValid(LEggLocationTrade); return met == noneLoc diff --git a/PKHeX.Core/Legality/Encounters/Verifiers/MysteryGiftVerifier.cs b/PKHeX.Core/Legality/Encounters/Verifiers/MysteryGiftVerifier.cs index 85ee8aa74..e1b9ffc10 100644 --- a/PKHeX.Core/Legality/Encounters/Verifiers/MysteryGiftVerifier.cs +++ b/PKHeX.Core/Legality/Encounters/Verifiers/MysteryGiftVerifier.cs @@ -12,14 +12,14 @@ public static class MysteryGiftVerifier private static Dictionary?[] Get() { var s = new Dictionary?[PKX.Generation + 1]; - for (int i = 3; i < s.Length; i++) + for (byte i = 3; i < s.Length; i++) s[i] = GetRestriction(i); return s; } - private static string RestrictionSetName(int generation) => $"mgrestrict{generation}.pkl"; + private static string RestrictionSetName(byte generation) => $"mgrestrict{generation}.pkl"; - private static Dictionary GetRestriction(int generation) + private static Dictionary GetRestriction(byte generation) { var resource = RestrictionSetName(generation); var data = Util.GetBinaryResource(resource).AsSpan(); @@ -40,8 +40,8 @@ public static CheckResult VerifyGift(PKM pk, MysteryGift g) if (!restricted) return new CheckResult(CheckIdentifier.GameOrigin); - var ver = (int)value >> 16; - if (ver != 0 && !CanVersionReceiveGift(g.Generation, ver, pk.Version)) + var version = (int)value >> 16; + if (version != 0 && !CanVersionReceiveGift(g.Generation, version, pk.Version)) return new CheckResult(Severity.Invalid, CheckIdentifier.GameOrigin, LEncGiftVersionNotDistributed); var lang = value & MysteryGiftRestriction.LangRestrict; @@ -74,10 +74,10 @@ public static bool IsValidChangedOTName(PKM pk, MysteryGift g) return false; // no data if (!val.HasFlag(MysteryGiftRestriction.OTReplacedOnTrade)) return false; - return CurrentOTMatchesReplaced(g.Generation, pk.OT_Name); + return CurrentOTMatchesReplaced(g.Generation, pk.OriginalTrainerName); } - private static bool CanVersionReceiveGift(int generation, int version4bit, int version) + private static bool CanVersionReceiveGift(byte generation, int version4bit, GameVersion version) { return generation switch { @@ -85,7 +85,7 @@ private static bool CanVersionReceiveGift(int generation, int version4bit, int v }; } - private static bool CurrentOTMatchesReplaced(int format, ReadOnlySpan pkOtName) + private static bool CurrentOTMatchesReplaced(byte format, ReadOnlySpan pkOtName) { if (format <= 4 && IsMatchName(pkOtName, 4)) return true; @@ -98,7 +98,7 @@ private static bool CurrentOTMatchesReplaced(int format, ReadOnlySpan pkOt return false; } - private static bool IsMatchName(ReadOnlySpan pkOtName, int generation) + private static bool IsMatchName(ReadOnlySpan ot, byte generation) { return generation switch { diff --git a/PKHeX.Core/Legality/Evolutions/EncounterOrigin.cs b/PKHeX.Core/Legality/Evolutions/EncounterOrigin.cs index fd3ea037f..bc819326a 100644 --- a/PKHeX.Core/Legality/Evolutions/EncounterOrigin.cs +++ b/PKHeX.Core/Legality/Evolutions/EncounterOrigin.cs @@ -17,7 +17,7 @@ public static class EncounterOrigin public static EvoCriteria[] GetOriginChain(PKM pk, byte generation) { var (minLevel, maxLevel) = GetMinMax(pk, generation); - var origin = new EvolutionOrigin(pk.Species, (byte)pk.Version, generation, minLevel, maxLevel); + var origin = new EvolutionOrigin(pk.Species, pk.Version, generation, minLevel, maxLevel); return EvolutionChain.GetOriginChain(pk, origin); } @@ -31,22 +31,22 @@ public static EvoCriteria[] GetOriginChain12(PKM pk, GameVersion gameSource) { var (minLevel, maxLevel) = GetMinMaxGB(pk); bool rby = gameSource == GameVersion.RBY; - byte ver = rby ? (byte)GameVersion.RBY : (byte)GameVersion.GSC; + GameVersion version = rby ? GameVersion.RBY : GameVersion.GSC; byte gen = rby ? (byte)1 : (byte)2; - var origin = new EvolutionOrigin(pk.Species, ver, gen, minLevel, maxLevel); + var origin = new EvolutionOrigin(pk.Species, version, gen, minLevel, maxLevel); return EvolutionChain.GetOriginChain(pk, origin); } private static (byte minLevel, byte maxLevel) GetMinMax(PKM pk, byte generation) { - byte maxLevel = (byte)pk.CurrentLevel; + byte maxLevel = pk.CurrentLevel; byte minLevel = GetLevelOriginMin(pk, generation); return (minLevel, maxLevel); } private static (byte minLevel, byte maxLevel) GetMinMaxGB(PKM pk) { - byte maxLevel = (byte)pk.CurrentLevel; + byte maxLevel = pk.CurrentLevel; byte minLevel = GetLevelOriginMinGB(pk); return (minLevel, maxLevel); } @@ -55,10 +55,10 @@ private static (byte minLevel, byte maxLevel) GetMinMaxGB(PKM pk) { 3 => GetLevelOriginMin3(pk), 4 => GetLevelOriginMin4(pk), - _ => Math.Max((byte)1, (byte)pk.Met_Level), + _ => Math.Max((byte)1, pk.MetLevel), }; - private static bool IsEggLocationNonZero(PKM pk) => pk.Egg_Location != LocationEdits.GetNoneLocation(pk.Context); + private static bool IsEggLocationNonZero(PKM pk) => pk.EggLocation != LocationEdits.GetNoneLocation(pk.Context); private static byte GetLevelOriginMinGB(PKM pk) { @@ -68,7 +68,7 @@ private static byte GetLevelOriginMinGB(PKM pk) return EggLevel; if (pk is not ICaughtData2 { CaughtData: not 0 } pk2) return MinWildLevel; - return (byte)pk2.Met_Level; + return pk2.MetLevel; } private static byte GetLevelOriginMin3(PKM pk) @@ -79,7 +79,7 @@ private static byte GetLevelOriginMin3(PKM pk) return MinWildLevel; if (pk.IsEgg) return EggLevel; - return (byte)pk.Met_Level; + return pk.MetLevel; } private static byte GetLevelOriginMin4(PKM pk) @@ -90,6 +90,6 @@ private static byte GetLevelOriginMin4(PKM pk) return IsEggLocationNonZero(pk) ? EggLevel : MinWildLevel; if (pk.IsEgg || IsEggLocationNonZero(pk)) return EggLevel; - return (byte)pk.Met_Level; + return pk.MetLevel; } } diff --git a/PKHeX.Core/Legality/Evolutions/EvolutionChain.cs b/PKHeX.Core/Legality/Evolutions/EvolutionChain.cs index bc7bd97a9..38821591c 100644 --- a/PKHeX.Core/Legality/Evolutions/EvolutionChain.cs +++ b/PKHeX.Core/Legality/Evolutions/EvolutionChain.cs @@ -15,7 +15,7 @@ public static class EvolutionChain public static EvolutionHistory GetEvolutionChainsAllGens(PKM pk, IEncounterTemplate enc) { var min = GetMinLevel(pk, enc); - var origin = new EvolutionOrigin(pk.Species, (byte)enc.Version, (byte)enc.Generation, min, (byte)pk.CurrentLevel); + var origin = new EvolutionOrigin(pk.Species, enc.Version, enc.Generation, min, pk.CurrentLevel); if (!pk.IsEgg && enc is not EncounterInvalid) return GetEvolutionChainsSearch(pk, origin, enc.Context, enc.Species); @@ -37,9 +37,9 @@ public static EvolutionHistory GetEvolutionChainsSearch(PKM pk, EvolutionOrigin private static byte GetMinLevel(PKM pk, IEncounterTemplate enc) => enc.Generation switch { - 2 => pk is ICaughtData2 c2 ? Math.Max((byte)c2.Met_Level, enc.LevelMin) : enc.LevelMin, + 2 => pk is ICaughtData2 c2 ? Math.Max(c2.MetLevel, enc.LevelMin) : enc.LevelMin, <= 4 when pk.Format != enc.Generation => enc.LevelMin, - _ => Math.Max((byte)pk.Met_Level, enc.LevelMin), + _ => Math.Max(pk.MetLevel, enc.LevelMin), }; private static EvolutionHistory EvolutionChainsSearch(PKM pk, EvolutionOrigin enc, EntityContext context, ushort encSpecies, Span chain) diff --git a/PKHeX.Core/Legality/Evolutions/EvolutionGroup/EvolutionGroup1.cs b/PKHeX.Core/Legality/Evolutions/EvolutionGroup/EvolutionGroup1.cs index a33ae0088..3114ec278 100644 --- a/PKHeX.Core/Legality/Evolutions/EvolutionGroup/EvolutionGroup1.cs +++ b/PKHeX.Core/Legality/Evolutions/EvolutionGroup/EvolutionGroup1.cs @@ -26,8 +26,8 @@ public int Devolve(Span result, PKM pk, EvolutionOrigin enc) { if (pk.Format >= 7 && !enc.SkipChecks) { - var max = pk.Met_Level; - enc = enc with { LevelMin = 2, LevelMax = (byte)max }; + var max = pk.MetLevel; + enc = enc with { LevelMin = 2, LevelMax = max }; } int present = 1; for (int i = 1; i < result.Length; i++) @@ -53,7 +53,7 @@ public bool TryDevolve(T head, PKM pk, byte currentMaxLevel, byte levelMin, b public int Evolve(Span result, PKM pk, EvolutionOrigin enc, EvolutionHistory history) { if (pk.Format > 2) - enc = enc with { LevelMax = (byte)pk.Met_Level }; + enc = enc with { LevelMax = pk.MetLevel }; int present = 1; for (int i = result.Length - 1; i >= 1; i--) diff --git a/PKHeX.Core/Legality/Evolutions/EvolutionGroup/EvolutionGroup2.cs b/PKHeX.Core/Legality/Evolutions/EvolutionGroup/EvolutionGroup2.cs index 0815776ee..2504e4f0c 100644 --- a/PKHeX.Core/Legality/Evolutions/EvolutionGroup/EvolutionGroup2.cs +++ b/PKHeX.Core/Legality/Evolutions/EvolutionGroup/EvolutionGroup2.cs @@ -6,7 +6,7 @@ public sealed class EvolutionGroup2 : IEvolutionGroup { public static readonly EvolutionGroup2 Instance = new(); private static readonly EvolutionTree Tree = EvolutionTree.Evolves2; - private const int Generation = 2; + private const byte Generation = 2; private static PersonalTable2 Personal => PersonalTable.C; private static EvolutionRuleTweak Tweak => EvolutionRuleTweak.Default; @@ -24,7 +24,7 @@ public int Devolve(Span result, PKM pk, EvolutionOrigin enc) { if (pk.Format > Generation && !enc.SkipChecks) { - byte max = (byte)pk.Met_Level; + byte max = pk.MetLevel; EvolutionUtil.UpdateCeiling(result, max); enc = enc with { LevelMin = 2, LevelMax = max }; } @@ -52,7 +52,7 @@ public int Devolve(Span result, PKM pk, EvolutionOrigin enc) public int Evolve(Span result, PKM pk, EvolutionOrigin enc, EvolutionHistory history) { if (pk.Format > Generation) - enc = enc with { LevelMax = (byte)pk.Met_Level }; + enc = enc with { LevelMax = pk.MetLevel }; int present = 1; for (int i = result.Length - 1; i >= 1; i--) diff --git a/PKHeX.Core/Legality/Evolutions/EvolutionGroup/EvolutionGroup3.cs b/PKHeX.Core/Legality/Evolutions/EvolutionGroup/EvolutionGroup3.cs index 0953f79a3..7f6eb55b1 100644 --- a/PKHeX.Core/Legality/Evolutions/EvolutionGroup/EvolutionGroup3.cs +++ b/PKHeX.Core/Legality/Evolutions/EvolutionGroup/EvolutionGroup3.cs @@ -6,7 +6,7 @@ public sealed class EvolutionGroup3 : IEvolutionGroup { public static readonly EvolutionGroup3 Instance = new(); private static readonly EvolutionTree Tree = EvolutionTree.Evolves3; - private const int Generation = 3; + private const byte Generation = 3; private static PersonalTable3 Personal => PersonalTable.E; private static EvolutionRuleTweak Tweak => EvolutionRuleTweak.Default; @@ -18,7 +18,7 @@ public int Devolve(Span result, PKM pk, EvolutionOrigin enc) { if (pk.Format == 4 && !enc.SkipChecks) // 5+ already have been revised { - byte max = (byte)pk.Met_Level; + byte max = pk.MetLevel; EvolutionUtil.UpdateCeiling(result, max); enc = enc with { LevelMin = 1, LevelMax = max }; } @@ -46,7 +46,7 @@ public int Devolve(Span result, PKM pk, EvolutionOrigin enc) public int Evolve(Span result, PKM pk, EvolutionOrigin enc, EvolutionHistory history) { if (pk.Format > Generation) - enc = enc with { LevelMax = (byte)pk.Met_Level }; + enc = enc with { LevelMax = pk.MetLevel }; int present = 1; for (int i = result.Length - 1; i >= 1; i--) diff --git a/PKHeX.Core/Legality/Evolutions/EvolutionGroup/EvolutionGroup4.cs b/PKHeX.Core/Legality/Evolutions/EvolutionGroup/EvolutionGroup4.cs index d50557e13..4acc4391f 100644 --- a/PKHeX.Core/Legality/Evolutions/EvolutionGroup/EvolutionGroup4.cs +++ b/PKHeX.Core/Legality/Evolutions/EvolutionGroup/EvolutionGroup4.cs @@ -6,7 +6,7 @@ public sealed class EvolutionGroup4 : IEvolutionGroup { public static readonly EvolutionGroup4 Instance = new(); private static readonly EvolutionTree Tree = EvolutionTree.Evolves4; - private const int Generation = 4; + private const byte Generation = 4; private static PersonalTable4 Personal => PersonalTable.HGSS; private static EvolutionRuleTweak Tweak => EvolutionRuleTweak.Default; @@ -18,7 +18,7 @@ public int Devolve(Span result, PKM pk, EvolutionOrigin enc) { if (pk.Format > Generation && !enc.SkipChecks) { - byte max = (byte)pk.Met_Level; + byte max = pk.MetLevel; EvolutionUtil.UpdateCeiling(result, max); enc = enc with { LevelMin = 1, LevelMax = max }; } @@ -46,9 +46,9 @@ public int Devolve(Span result, PKM pk, EvolutionOrigin enc) public int Evolve(Span result, PKM pk, EvolutionOrigin enc, EvolutionHistory history) { if (pk.Format > Generation) - enc = enc with { LevelMax = (byte)pk.Met_Level }; + enc = enc with { LevelMax = pk.MetLevel }; else if (enc.Generation < Generation) - EvolutionUtil.UpdateFloor(result, (byte)pk.Met_Level, enc.LevelMax); + EvolutionUtil.UpdateFloor(result, pk.MetLevel, enc.LevelMax); int present = 1; for (int i = result.Length - 1; i >= 1; i--) diff --git a/PKHeX.Core/Legality/Evolutions/EvolutionGroup/EvolutionGroup5.cs b/PKHeX.Core/Legality/Evolutions/EvolutionGroup/EvolutionGroup5.cs index fc47fe6ae..b125aaf83 100644 --- a/PKHeX.Core/Legality/Evolutions/EvolutionGroup/EvolutionGroup5.cs +++ b/PKHeX.Core/Legality/Evolutions/EvolutionGroup/EvolutionGroup5.cs @@ -6,7 +6,7 @@ public sealed class EvolutionGroup5 : IEvolutionGroup { public static readonly EvolutionGroup5 Instance = new(); private static readonly EvolutionTree Tree = EvolutionTree.Evolves5; - private const int Generation = 5; + private const byte Generation = 5; private static PersonalTable5B2W2 Personal => PersonalTable.B2W2; private static EvolutionRuleTweak Tweak => EvolutionRuleTweak.Default; @@ -39,7 +39,7 @@ public int Devolve(Span result, PKM pk, EvolutionOrigin enc) public int Evolve(Span result, PKM pk, EvolutionOrigin enc, EvolutionHistory history) { if (enc.Generation < Generation) - EvolutionUtil.UpdateFloor(result, (byte)pk.Met_Level, enc.LevelMax); + EvolutionUtil.UpdateFloor(result, pk.MetLevel, enc.LevelMax); int present = 1; for (int i = result.Length - 1; i >= 1; i--) diff --git a/PKHeX.Core/Legality/Evolutions/EvolutionGroup/EvolutionGroup6.cs b/PKHeX.Core/Legality/Evolutions/EvolutionGroup/EvolutionGroup6.cs index 78c09a94d..ad5bff404 100644 --- a/PKHeX.Core/Legality/Evolutions/EvolutionGroup/EvolutionGroup6.cs +++ b/PKHeX.Core/Legality/Evolutions/EvolutionGroup/EvolutionGroup6.cs @@ -6,7 +6,7 @@ public sealed class EvolutionGroup6 : IEvolutionGroup { public static readonly EvolutionGroup6 Instance = new(); private static readonly EvolutionTree Tree = EvolutionTree.Evolves6; - private const int Generation = 6; + private const byte Generation = 6; private static PersonalTable6AO Personal => PersonalTable.AO; private static EvolutionRuleTweak Tweak => EvolutionRuleTweak.Default; diff --git a/PKHeX.Core/Legality/Evolutions/EvolutionGroup/EvolutionGroup7.cs b/PKHeX.Core/Legality/Evolutions/EvolutionGroup/EvolutionGroup7.cs index 990a3ca8e..7d2a44963 100644 --- a/PKHeX.Core/Legality/Evolutions/EvolutionGroup/EvolutionGroup7.cs +++ b/PKHeX.Core/Legality/Evolutions/EvolutionGroup/EvolutionGroup7.cs @@ -6,7 +6,7 @@ public sealed class EvolutionGroup7 : IEvolutionGroup { public static readonly EvolutionGroup7 Instance = new(); private static readonly EvolutionTree Tree = EvolutionTree.Evolves7; - private const int Generation = 7; + private const byte Generation = 7; private static PersonalTable7 Personal => PersonalTable.USUM; private static EvolutionRuleTweak Tweak => EvolutionRuleTweak.Default; @@ -52,7 +52,7 @@ private static void RevertMutatedForms(ref EvoCriteria evo) public int Evolve(Span result, PKM pk, EvolutionOrigin enc, EvolutionHistory history) { if (enc.Generation <= 2) // VC Transfer - EvolutionUtil.UpdateFloor(result, (byte)pk.Met_Level, enc.LevelMax); + EvolutionUtil.UpdateFloor(result, pk.MetLevel, enc.LevelMax); int present = 1; for (int i = result.Length - 1; i >= 1; i--) diff --git a/PKHeX.Core/Legality/Evolutions/EvolutionGroup/EvolutionGroup7b.cs b/PKHeX.Core/Legality/Evolutions/EvolutionGroup/EvolutionGroup7b.cs index 71da82339..ff1cf59d0 100644 --- a/PKHeX.Core/Legality/Evolutions/EvolutionGroup/EvolutionGroup7b.cs +++ b/PKHeX.Core/Legality/Evolutions/EvolutionGroup/EvolutionGroup7b.cs @@ -6,7 +6,7 @@ public sealed class EvolutionGroup7b : IEvolutionGroup { public static readonly EvolutionGroup7b Instance = new(); private static readonly EvolutionTree Tree = EvolutionTree.Evolves7b; - private const int Generation = 7; + private const byte Generation = 7; private static PersonalTable7GG Personal => PersonalTable.GG; private static EvolutionRuleTweak Tweak => EvolutionRuleTweak.Default; diff --git a/PKHeX.Core/Legality/Evolutions/EvolutionGroup/EvolutionGroupHOME.cs b/PKHeX.Core/Legality/Evolutions/EvolutionGroup/EvolutionGroupHOME.cs index 9cd7d761c..3b55f6f49 100644 --- a/PKHeX.Core/Legality/Evolutions/EvolutionGroup/EvolutionGroupHOME.cs +++ b/PKHeX.Core/Legality/Evolutions/EvolutionGroup/EvolutionGroupHOME.cs @@ -20,7 +20,7 @@ public sealed class EvolutionGroupHOME : IEvolutionGroup { if (enc.Generation >= 8) return null; - if ((GameVersion)enc.Version is GP or GE or GG or GO) + if (enc.Version is GP or GE or GG or GO) return EvolutionGroup7b.Instance; return EvolutionGroup7.Instance; } diff --git a/PKHeX.Core/Legality/Evolutions/EvolutionGroup/EvolutionOrigin.cs b/PKHeX.Core/Legality/Evolutions/EvolutionGroup/EvolutionOrigin.cs index 4b5b96d9b..6975f982d 100644 --- a/PKHeX.Core/Legality/Evolutions/EvolutionGroup/EvolutionOrigin.cs +++ b/PKHeX.Core/Legality/Evolutions/EvolutionGroup/EvolutionOrigin.cs @@ -11,7 +11,7 @@ namespace PKHeX.Core; /// Minimum level the encounter originated at /// Maximum level in final state /// Options to toggle logic when using this data -public readonly record struct EvolutionOrigin(ushort Species, byte Version, byte Generation, byte LevelMin, byte LevelMax, OriginOptions Options = 0) +public readonly record struct EvolutionOrigin(ushort Species, GameVersion Version, byte Generation, byte LevelMin, byte LevelMax, OriginOptions Options = 0) { /// /// Checks if evolution checks against the Entity should be skipped when devolving or devolving. @@ -21,7 +21,7 @@ namespace PKHeX.Core; /// /// Internally used to enforce Gen1 origin encounters NOT jumping to Gen2 to continue devolving. /// - public bool IsDiscardRequired(int format) => format <= 2 && Options.HasFlag(OriginOptions.ForceDiscard); + public bool IsDiscardRequired(byte format) => format <= 2 && Options.HasFlag(OriginOptions.ForceDiscard); } [Flags] diff --git a/PKHeX.Core/Legality/Evolutions/Methods/EvolutionMethod.cs b/PKHeX.Core/Legality/Evolutions/Methods/EvolutionMethod.cs index ef232228e..e65cdd86b 100644 --- a/PKHeX.Core/Legality/Evolutions/Methods/EvolutionMethod.cs +++ b/PKHeX.Core/Legality/Evolutions/Methods/EvolutionMethod.cs @@ -76,11 +76,11 @@ public EvolutionCheckResult Check(PKM pk, byte lvl, byte levelMin, bool skipChec LevelUpFormFemale1 when pk.Form != 1 => BadForm, // Permit the evolution if we're exploring for mistakes. - LevelUpBeauty when pk is IContestStatsReadOnly s && s.CNT_Beauty < Argument => skipChecks ? Valid : LowContestStat, + LevelUpBeauty when pk is IContestStatsReadOnly s && s.ContestBeauty < Argument => skipChecks ? Valid : LowContestStat, LevelUpNatureAmped or LevelUpNatureLowKey when ToxtricityUtil.GetAmpLowKeyResult(pk.Nature) != pk.Form => skipChecks ? Valid : BadForm, // Version checks come in pairs, check for any pair match - LevelUpVersion or LevelUpVersionDay or LevelUpVersionNight when ((pk.Version & 1) != (Argument & 1) && pk.IsUntraded) => skipChecks ? Valid : VisitVersion, + LevelUpVersion or LevelUpVersionDay or LevelUpVersionNight when (((byte)pk.Version & 1) != (Argument & 1) && pk.IsUntraded) => skipChecks ? Valid : VisitVersion, LevelUpKnowMoveEC100 when pk.EncryptionConstant % 100 != 0 => skipChecks ? Valid : WrongEC, LevelUpKnowMoveECElse when pk.EncryptionConstant % 100 == 0 => skipChecks ? Valid : WrongEC, diff --git a/PKHeX.Core/Legality/Formatting/LegalityCheckStrings.cs b/PKHeX.Core/Legality/Formatting/LegalityCheckStrings.cs index 158fa3c5b..4e59a361c 100644 --- a/PKHeX.Core/Legality/Formatting/LegalityCheckStrings.cs +++ b/PKHeX.Core/Legality/Formatting/LegalityCheckStrings.cs @@ -433,7 +433,7 @@ public static class LegalityCheckStrings public static string LPIDGenderMismatch { get; set; } = "PID-Gender mismatch."; public static string LPIDNatureMatch { get; set; } = "Nature matches PID."; public static string LPIDNatureMismatch { get; set; } = "PID-Nature mismatch."; - public static string LPIDTypeMismatch { get; set; } = "Encounter Type PID mismatch."; + public static string LPIDTypeMismatch { get; set; } = "PID+ correlation does not match what was expected for the Encounter's type."; public static string LPIDZero { get; set; } = "PID is not set."; public static string LPokerusDaysTooHigh_0 { get; set; } = "Pokérus Days Remaining value is too high; expected <= {0}."; diff --git a/PKHeX.Core/Legality/Formatting/LegalityFormatting.cs b/PKHeX.Core/Legality/Formatting/LegalityFormatting.cs index 61e457499..4005acba8 100644 --- a/PKHeX.Core/Legality/Formatting/LegalityFormatting.cs +++ b/PKHeX.Core/Legality/Formatting/LegalityFormatting.cs @@ -97,14 +97,60 @@ public static void AddEncounterInfoPIDIV(LegalityAnalysis la, List lines var info = la.Info; if (!info.PIDParsed) info.PIDIV = MethodFinder.Analyze(la.Entity); - AddEncounterInfoPIDIV(lines, info.PIDIV); + AddEncounterInfoPIDIV(lines, info); } - private static void AddEncounterInfoPIDIV(List lines, PIDIV pidiv) + private static void AddEncounterInfoPIDIV(List lines, LegalInfo info) { + var pidiv = info.PIDIV; lines.Add(string.Format(L_FPIDType_0, pidiv.Type)); - if (!pidiv.NoSeed) - lines.Add(string.Format(L_FOriginSeed_0, pidiv.OriginSeed.ToString("X8"))); + if (pidiv.NoSeed) + return; + + if (pidiv.IsSeed64()) + { + var seed = pidiv.Seed64; + lines.Add(string.Format(L_FOriginSeed_0, seed.ToString("X16"))); + return; + } + if (info is { EncounterMatch: IEncounterSlot34 s }) + { + var lead = pidiv.Lead; + var seed = !info.FrameMatches || lead == LeadRequired.Invalid ? pidiv.OriginSeed : pidiv.EncounterSeed; + var line = string.Format(L_FOriginSeed_0, seed.ToString("X8")); + if (lead != LeadRequired.None) + { + if (lead is LeadRequired.Static) + line += $" [{s.StaticIndex}/{s.StaticCount}]"; + else if (lead is LeadRequired.MagnetPull) + line += $" [{s.MagnetPullIndex}/{s.MagnetPullCount}]"; + else + line += $" [{s.SlotNumber}]"; + + line += $" ({lead.Localize()})"; + } + else + { + line += $" [{s.SlotNumber}]"; + } + lines.Add(line); + } + else + { + var seed = pidiv.OriginSeed; + var line = string.Format(L_FOriginSeed_0, seed.ToString("X8")); + lines.Add(line); + } + } + + private static string Localize(this LeadRequired lead) + { + if (lead is LeadRequired.Invalid) + return "❌"; + var (ability, isFail) = lead.GetDisplayAbility(); + var abilities = GameInfo.Strings.Ability; + var name = abilities[(int)ability]; + return isFail ? string.Format(L_F0_1, name, "❌") : name; } public static string GetEncounterName(this IEncounterable enc) @@ -118,6 +164,6 @@ public static string GetEncounterName(this IEncounterable enc) { if (enc is not ILocation loc) return null; - return loc.GetEncounterLocation(enc.Generation, (int)enc.Version); + return loc.GetEncounterLocation(enc.Generation, enc.Version); } } diff --git a/PKHeX.Core/Legality/LearnSource/Group/LearnGroup1.cs b/PKHeX.Core/Legality/LearnSource/Group/LearnGroup1.cs index bfa2b53d4..934ef0562 100644 --- a/PKHeX.Core/Legality/LearnSource/Group/LearnGroup1.cs +++ b/PKHeX.Core/Legality/LearnSource/Group/LearnGroup1.cs @@ -8,7 +8,7 @@ namespace PKHeX.Core; public sealed class LearnGroup1 : ILearnGroup { public static readonly LearnGroup1 Instance = new(); - private const int Generation = 1; + private const byte Generation = 1; public ushort MaxMoveID => Legal.MaxMoveID_1; public ILearnGroup? GetPrevious(PKM pk, EvolutionHistory history, IEncounterTemplate enc, LearnOption option) => pk.Context switch diff --git a/PKHeX.Core/Legality/LearnSource/Group/LearnGroup2.cs b/PKHeX.Core/Legality/LearnSource/Group/LearnGroup2.cs index df29f8502..c3ae988f7 100644 --- a/PKHeX.Core/Legality/LearnSource/Group/LearnGroup2.cs +++ b/PKHeX.Core/Legality/LearnSource/Group/LearnGroup2.cs @@ -8,7 +8,7 @@ namespace PKHeX.Core; public sealed class LearnGroup2 : ILearnGroup { public static readonly LearnGroup2 Instance = new(); - private const int Generation = 2; + private const byte Generation = 2; public ushort MaxMoveID => Legal.MaxMoveID_2; public ILearnGroup? GetPrevious(PKM pk, EvolutionHistory history, IEncounterTemplate enc, LearnOption option) => pk.Context switch diff --git a/PKHeX.Core/Legality/LearnSource/Group/LearnGroup3.cs b/PKHeX.Core/Legality/LearnSource/Group/LearnGroup3.cs index 7d1c7d9ab..7be1c213d 100644 --- a/PKHeX.Core/Legality/LearnSource/Group/LearnGroup3.cs +++ b/PKHeX.Core/Legality/LearnSource/Group/LearnGroup3.cs @@ -8,7 +8,7 @@ namespace PKHeX.Core; public sealed class LearnGroup3 : ILearnGroup { public static readonly LearnGroup3 Instance = new(); - private const int Generation = 3; + private const byte Generation = 3; public ushort MaxMoveID => Legal.MaxMoveID_3; public ILearnGroup? GetPrevious(PKM pk, EvolutionHistory history, IEncounterTemplate enc, LearnOption option) => null; // Gen3 is the end of the line! diff --git a/PKHeX.Core/Legality/LearnSource/Group/LearnGroup4.cs b/PKHeX.Core/Legality/LearnSource/Group/LearnGroup4.cs index a8d55b190..bf04ccd4c 100644 --- a/PKHeX.Core/Legality/LearnSource/Group/LearnGroup4.cs +++ b/PKHeX.Core/Legality/LearnSource/Group/LearnGroup4.cs @@ -8,7 +8,7 @@ namespace PKHeX.Core; public sealed class LearnGroup4 : ILearnGroup { public static readonly LearnGroup4 Instance = new(); - private const int Generation = 4; + private const byte Generation = 4; public ushort MaxMoveID => Legal.MaxMoveID_4; public ILearnGroup? GetPrevious(PKM pk, EvolutionHistory history, IEncounterTemplate enc, LearnOption option) => enc.Generation is Generation ? null : LearnGroup3.Instance; diff --git a/PKHeX.Core/Legality/LearnSource/Group/LearnGroup5.cs b/PKHeX.Core/Legality/LearnSource/Group/LearnGroup5.cs index 5bc3d9679..b5112c934 100644 --- a/PKHeX.Core/Legality/LearnSource/Group/LearnGroup5.cs +++ b/PKHeX.Core/Legality/LearnSource/Group/LearnGroup5.cs @@ -8,7 +8,7 @@ namespace PKHeX.Core; public sealed class LearnGroup5 : ILearnGroup { public static readonly LearnGroup5 Instance = new(); - private const int Generation = 5; + private const byte Generation = 5; public ushort MaxMoveID => Legal.MaxMoveID_5; public ILearnGroup? GetPrevious(PKM pk, EvolutionHistory history, IEncounterTemplate enc, LearnOption option) => enc.Generation is Generation ? null : LearnGroup4.Instance; diff --git a/PKHeX.Core/Legality/LearnSource/Group/LearnGroup6.cs b/PKHeX.Core/Legality/LearnSource/Group/LearnGroup6.cs index 5094c9cec..d3f996c28 100644 --- a/PKHeX.Core/Legality/LearnSource/Group/LearnGroup6.cs +++ b/PKHeX.Core/Legality/LearnSource/Group/LearnGroup6.cs @@ -8,7 +8,7 @@ namespace PKHeX.Core; public sealed class LearnGroup6 : ILearnGroup { public static readonly LearnGroup6 Instance = new(); - private const int Generation = 6; + private const byte Generation = 6; public ushort MaxMoveID => Legal.MaxMoveID_6_AO; public ILearnGroup? GetPrevious(PKM pk, EvolutionHistory history, IEncounterTemplate enc, LearnOption option) => enc.Generation is Generation ? null : LearnGroup5.Instance; diff --git a/PKHeX.Core/Legality/LearnSource/Group/LearnGroup7.cs b/PKHeX.Core/Legality/LearnSource/Group/LearnGroup7.cs index 0fac2b60b..6b2e64d67 100644 --- a/PKHeX.Core/Legality/LearnSource/Group/LearnGroup7.cs +++ b/PKHeX.Core/Legality/LearnSource/Group/LearnGroup7.cs @@ -8,7 +8,7 @@ namespace PKHeX.Core; public sealed class LearnGroup7 : ILearnGroup { public static readonly LearnGroup7 Instance = new(); - private const int Generation = 7; + private const byte Generation = 7; public ushort MaxMoveID => Legal.MaxMoveID_7_USUM; public ILearnGroup? GetPrevious(PKM pk, EvolutionHistory history, IEncounterTemplate enc, LearnOption option) => enc.Generation switch diff --git a/PKHeX.Core/Legality/LearnSource/Group/LearnGroup7b.cs b/PKHeX.Core/Legality/LearnSource/Group/LearnGroup7b.cs index 52602ec7d..b6d2a0972 100644 --- a/PKHeX.Core/Legality/LearnSource/Group/LearnGroup7b.cs +++ b/PKHeX.Core/Legality/LearnSource/Group/LearnGroup7b.cs @@ -8,7 +8,7 @@ namespace PKHeX.Core; public sealed class LearnGroup7b : ILearnGroup { public static readonly LearnGroup7b Instance = new(); - private const int Generation = 7; + private const byte Generation = 7; public ushort MaxMoveID => Legal.MaxMoveID_7b; public ILearnGroup? GetPrevious(PKM pk, EvolutionHistory history, IEncounterTemplate enc, LearnOption option) => null; diff --git a/PKHeX.Core/Legality/LearnSource/Group/LearnGroup8.cs b/PKHeX.Core/Legality/LearnSource/Group/LearnGroup8.cs index 2f14c68cb..f7a46eac0 100644 --- a/PKHeX.Core/Legality/LearnSource/Group/LearnGroup8.cs +++ b/PKHeX.Core/Legality/LearnSource/Group/LearnGroup8.cs @@ -8,7 +8,7 @@ namespace PKHeX.Core; public sealed class LearnGroup8 : ILearnGroup { public static readonly LearnGroup8 Instance = new(); - private const int Generation = 8; + private const byte Generation = 8; private const EntityContext Context = EntityContext.Gen8; public ushort MaxMoveID => Legal.MaxMoveID_8; diff --git a/PKHeX.Core/Legality/LearnSource/Group/LearnGroup8a.cs b/PKHeX.Core/Legality/LearnSource/Group/LearnGroup8a.cs index f52c58277..49f12d1d5 100644 --- a/PKHeX.Core/Legality/LearnSource/Group/LearnGroup8a.cs +++ b/PKHeX.Core/Legality/LearnSource/Group/LearnGroup8a.cs @@ -8,7 +8,7 @@ namespace PKHeX.Core; public sealed class LearnGroup8a : ILearnGroup { public static readonly LearnGroup8a Instance = new(); - private const int Generation = 8; + private const byte Generation = 8; private const EntityContext Context = EntityContext.Gen8a; public ushort MaxMoveID => Legal.MaxMoveID_8a; diff --git a/PKHeX.Core/Legality/LearnSource/Group/LearnGroup8b.cs b/PKHeX.Core/Legality/LearnSource/Group/LearnGroup8b.cs index ac6b29793..bb4eca6fb 100644 --- a/PKHeX.Core/Legality/LearnSource/Group/LearnGroup8b.cs +++ b/PKHeX.Core/Legality/LearnSource/Group/LearnGroup8b.cs @@ -8,7 +8,7 @@ namespace PKHeX.Core; public sealed class LearnGroup8b : ILearnGroup { public static readonly LearnGroup8b Instance = new(); - private const int Generation = 8; + private const byte Generation = 8; private const EntityContext Context = EntityContext.Gen8b; public ushort MaxMoveID => Legal.MaxMoveID_8b; diff --git a/PKHeX.Core/Legality/LearnSource/Group/LearnGroup9.cs b/PKHeX.Core/Legality/LearnSource/Group/LearnGroup9.cs index 965055982..476e6bf52 100644 --- a/PKHeX.Core/Legality/LearnSource/Group/LearnGroup9.cs +++ b/PKHeX.Core/Legality/LearnSource/Group/LearnGroup9.cs @@ -8,7 +8,7 @@ namespace PKHeX.Core; public sealed class LearnGroup9 : ILearnGroup { public static readonly LearnGroup9 Instance = new(); - private const int Generation = 9; + private const byte Generation = 9; private const EntityContext Context = EntityContext.Gen9; public ushort MaxMoveID => Legal.MaxMoveID_9; diff --git a/PKHeX.Core/Legality/LearnSource/Group/LearnGroupHOME.cs b/PKHeX.Core/Legality/LearnSource/Group/LearnGroupHOME.cs index 8ca04e4dc..311a785cc 100644 --- a/PKHeX.Core/Legality/LearnSource/Group/LearnGroupHOME.cs +++ b/PKHeX.Core/Legality/LearnSource/Group/LearnGroupHOME.cs @@ -182,7 +182,7 @@ private static bool TryAddOriginalMoves(Span result, ReadOnlySpan moves = stackalloc ushort[4]; - g8.GetInitialMoves(pk.Met_Level, moves); + g8.GetInitialMoves(pk.MetLevel, moves); return AddOriginalMoves(result, current, moves, g8.Generation); } return false; @@ -199,7 +199,7 @@ private static void AddOriginalMoves(Span result, PKM pk, IEncounterTempla else if (enc is EncounterSlot8GO { OriginFormat: PogoImportFormat.PK7 or PogoImportFormat.PB7 } g8) { Span moves = stackalloc ushort[4]; - g8.GetInitialMoves(pk.Met_Level, moves); + g8.GetInitialMoves(pk.MetLevel, moves); AddOriginalMoves(result, pk, evos, types, local, moves); } } @@ -308,7 +308,7 @@ private static void AddOriginalMoves(Span result, PKM pk, ReadOnlySpan result, ReadOnlySpan current, Span moves, int generation) + private static bool AddOriginalMoves(Span result, ReadOnlySpan current, Span moves, byte generation) { bool addedAny = false; foreach (var move in moves) @@ -321,7 +321,7 @@ private static bool AddOriginalMoves(Span result, ReadOnlySpan, I private static readonly Learnset[] Learnsets = LearnsetReader.GetArray(BinLinkerAccessor.Get(Util.GetBinaryResource("lvlmove_e.pkl"), "em"u8)); private const int MaxSpecies = Legal.MaxSpeciesID_3; private const LearnEnvironment Game = E; - private const int Generation = 3; + private const byte Generation = 3; private const int CountTM = 50; public Learnset GetLearnset(ushort species, byte form) => Learnsets[species]; diff --git a/PKHeX.Core/Legality/LearnSource/Sources/LearnSource3FR.cs b/PKHeX.Core/Legality/LearnSource/Sources/LearnSource3FR.cs index a77acd911..9f411e401 100644 --- a/PKHeX.Core/Legality/LearnSource/Sources/LearnSource3FR.cs +++ b/PKHeX.Core/Legality/LearnSource/Sources/LearnSource3FR.cs @@ -15,7 +15,7 @@ public sealed class LearnSource3FR : LearnSource3, ILearnSource, private static readonly Learnset[] Learnsets = LearnsetReader.GetArray(BinLinkerAccessor.Get(Util.GetBinaryResource("lvlmove_fr.pkl"), "fr"u8)); private const int MaxSpecies = Legal.MaxSpeciesID_3; private const LearnEnvironment Game = FR; - private const int Generation = 3; + private const byte Generation = 3; private const int CountTM = 50; public Learnset GetLearnset(ushort species, byte form) => Learnsets[species]; diff --git a/PKHeX.Core/Legality/LearnSource/Sources/LearnSource3LG.cs b/PKHeX.Core/Legality/LearnSource/Sources/LearnSource3LG.cs index bb2761310..ee298a871 100644 --- a/PKHeX.Core/Legality/LearnSource/Sources/LearnSource3LG.cs +++ b/PKHeX.Core/Legality/LearnSource/Sources/LearnSource3LG.cs @@ -15,7 +15,7 @@ public sealed class LearnSource3LG : LearnSource3, ILearnSource, private static readonly Learnset[] Learnsets = LearnsetReader.GetArray(BinLinkerAccessor.Get(Util.GetBinaryResource("lvlmove_lg.pkl"), "lg"u8)); private const int MaxSpecies = Legal.MaxSpeciesID_3; private const LearnEnvironment Game = LG; - private const int Generation = 3; + private const byte Generation = 3; private const int CountTM = 50; public Learnset GetLearnset(ushort species, byte form) => Learnsets[species]; diff --git a/PKHeX.Core/Legality/LearnSource/Sources/LearnSource3RS.cs b/PKHeX.Core/Legality/LearnSource/Sources/LearnSource3RS.cs index b47f46083..d4d05e5f7 100644 --- a/PKHeX.Core/Legality/LearnSource/Sources/LearnSource3RS.cs +++ b/PKHeX.Core/Legality/LearnSource/Sources/LearnSource3RS.cs @@ -15,7 +15,7 @@ public sealed class LearnSource3RS : LearnSource3, ILearnSource, private static readonly Learnset[] Learnsets = LearnsetReader.GetArray(BinLinkerAccessor.Get(Util.GetBinaryResource("lvlmove_rs.pkl"), "rs"u8)); private const int MaxSpecies = Legal.MaxSpeciesID_3; private const LearnEnvironment Game = RS; - private const int Generation = 3; + private const byte Generation = 3; private const int CountTM = 50; public Learnset GetLearnset(ushort species, byte form) => Learnsets[species]; diff --git a/PKHeX.Core/Legality/LearnSource/Sources/LearnSource4DP.cs b/PKHeX.Core/Legality/LearnSource/Sources/LearnSource4DP.cs index f7cc79c43..1782754fa 100644 --- a/PKHeX.Core/Legality/LearnSource/Sources/LearnSource4DP.cs +++ b/PKHeX.Core/Legality/LearnSource/Sources/LearnSource4DP.cs @@ -15,7 +15,7 @@ public sealed class LearnSource4DP : LearnSource4, ILearnSource, private static readonly Learnset[] Learnsets = LearnsetReader.GetArray(BinLinkerAccessor.Get(Util.GetBinaryResource("lvlmove_dp.pkl"), "dp"u8)); private const int MaxSpecies = Legal.MaxSpeciesID_4; private const LearnEnvironment Game = DP; - private const int Generation = 4; + private const byte Generation = 4; private const int CountTM = 92; public Learnset GetLearnset(ushort species, byte form) => Learnsets[Personal.GetFormIndex(species, form)]; diff --git a/PKHeX.Core/Legality/LearnSource/Sources/LearnSource4HGSS.cs b/PKHeX.Core/Legality/LearnSource/Sources/LearnSource4HGSS.cs index c897b5e27..3454fefdc 100644 --- a/PKHeX.Core/Legality/LearnSource/Sources/LearnSource4HGSS.cs +++ b/PKHeX.Core/Legality/LearnSource/Sources/LearnSource4HGSS.cs @@ -17,7 +17,7 @@ public sealed class LearnSource4HGSS : ILearnSource, IEggSource private static readonly EggMoves6[] EggMoves = EggMoves6.GetArray(BinLinkerAccessor.Get(Util.GetBinaryResource("eggmove_hgss.pkl"), "hs"u8)); private const int MaxSpecies = Legal.MaxSpeciesID_4; private const LearnEnvironment Game = HGSS; - private const int Generation = 4; + private const byte Generation = 4; public Learnset GetLearnset(ushort species, byte form) => Learnsets[Personal.GetFormIndex(species, form)]; diff --git a/PKHeX.Core/Legality/LearnSource/Sources/LearnSource4Pt.cs b/PKHeX.Core/Legality/LearnSource/Sources/LearnSource4Pt.cs index 4f050632d..12be3f8d4 100644 --- a/PKHeX.Core/Legality/LearnSource/Sources/LearnSource4Pt.cs +++ b/PKHeX.Core/Legality/LearnSource/Sources/LearnSource4Pt.cs @@ -15,7 +15,7 @@ public sealed class LearnSource4Pt : LearnSource4, ILearnSource, private static readonly Learnset[] Learnsets = LearnsetReader.GetArray(BinLinkerAccessor.Get(Util.GetBinaryResource("lvlmove_pt.pkl"), "pt"u8)); private const int MaxSpecies = Legal.MaxSpeciesID_4; private const LearnEnvironment Game = Pt; - private const int Generation = 4; + private const byte Generation = 4; public Learnset GetLearnset(ushort species, byte form) => Learnsets[Personal.GetFormIndex(species, form)]; diff --git a/PKHeX.Core/Legality/LearnSource/Verify/LearnPossible.cs b/PKHeX.Core/Legality/LearnSource/Verify/LearnPossible.cs index 19ec0bea1..781117252 100644 --- a/PKHeX.Core/Legality/LearnSource/Verify/LearnPossible.cs +++ b/PKHeX.Core/Legality/LearnSource/Verify/LearnPossible.cs @@ -37,7 +37,7 @@ private static void FlagEncounterMoves(PKM pk, IEncounterTemplate enc, Span initial = stackalloc ushort[4]; - g.GetInitialMoves(pk.Met_Level, initial); + g.GetInitialMoves(pk.MetLevel, initial); SetAll(initial, result); } else if (enc.Generation >= 6) diff --git a/PKHeX.Core/Legality/LearnSource/Verify/LearnVerifierHistory.cs b/PKHeX.Core/Legality/LearnSource/Verify/LearnVerifierHistory.cs index 67b431d32..890fff096 100644 --- a/PKHeX.Core/Legality/LearnSource/Verify/LearnVerifierHistory.cs +++ b/PKHeX.Core/Legality/LearnSource/Verify/LearnVerifierHistory.cs @@ -56,7 +56,7 @@ private static void MarkSpecialMoves(Span result, ReadOnlySpan initial = stackalloc ushort[4]; - g.GetInitialMoves(pk.Met_Level, initial); + g.GetInitialMoves(pk.MetLevel, initial); MarkInitialMoves(result, current, initial); } } diff --git a/PKHeX.Core/Legality/LearnSource/Verify/LearnVerifierRelearn.cs b/PKHeX.Core/Legality/LearnSource/Verify/LearnVerifierRelearn.cs index ca5459921..2526d194b 100644 --- a/PKHeX.Core/Legality/LearnSource/Verify/LearnVerifierRelearn.cs +++ b/PKHeX.Core/Legality/LearnSource/Verify/LearnVerifierRelearn.cs @@ -84,7 +84,7 @@ private static void VerifyEggMoveset(EncounterEgg e, Span result, PK internal static void VerifyEggMoveset(EncounterEgg e, Span result, ReadOnlySpan moves) { - int gen = e.Generation; + var gen = e.Generation; Span origins = stackalloc byte[moves.Length]; var valid = MoveBreed.Validate(gen, e.Species, e.Form, e.Version, moves, origins); if (valid) diff --git a/PKHeX.Core/Legality/LegalityAnalysis.cs b/PKHeX.Core/Legality/LegalityAnalysis.cs index 3b6990e6c..83c2e0954 100644 --- a/PKHeX.Core/Legality/LegalityAnalysis.cs +++ b/PKHeX.Core/Legality/LegalityAnalysis.cs @@ -176,8 +176,8 @@ private Action GetParseMethod() private int GetParseFormat() { - int gen = Entity.Generation; - if (gen > 0) + var gen = Entity.Generation; + if (gen != 0) return gen; if (Entity is PK9 { IsUnhatchedEgg: true }) return 9; @@ -201,7 +201,7 @@ private void ParsePK3() if (Entity.Format > 3) Transfer.VerifyTransferLegalityG3(this); - if (Entity.Version == (int)GameVersion.CXD) + if (Entity.Version == GameVersion.CXD) CXD.Verify(this); if (Info.EncounterMatch is WC3 {NotDistributed: true}) diff --git a/PKHeX.Core/Legality/MoveListSuggest.cs b/PKHeX.Core/Legality/MoveListSuggest.cs index 727a476ae..4cd9999c0 100644 --- a/PKHeX.Core/Legality/MoveListSuggest.cs +++ b/PKHeX.Core/Legality/MoveListSuggest.cs @@ -26,7 +26,7 @@ private static void GetSuggestedMoves(PKM pk, EvolutionHistory evoChains, MoveSo // try to give current moves if (enc.Generation <= 2 && pk.Format < 8) { - var lvl = pk.Format >= 7 ? pk.Met_Level : pk.CurrentLevel; + var lvl = pk.Format >= 7 ? pk.MetLevel : pk.CurrentLevel; var source = GameData.GetLearnSource(enc.Version); source.SetEncounterMoves(enc.Species, 0, lvl, moves); return; @@ -34,7 +34,7 @@ private static void GetSuggestedMoves(PKM pk, EvolutionHistory evoChains, MoveSo if (pk.Species == enc.Species || pk.Context.Generation() >= 8) { - var game = (GameVersion)pk.Version; // account for SW/SH foreign mutated versions + var game = pk.Version; // account for SW/SH foreign mutated versions if (pk.Context.Generation() >= 8) game = pk.Context.GetSingleGameVersion(); var source = GameData.GetLearnSource(game); @@ -166,7 +166,7 @@ public static void GetSuggestedRelearnMovesFromEncounter(this LegalityAnalysis a private static void GetSuggestedRelearnEgg(this IEncounterTemplate enc, ReadOnlySpan parse, PKM pk, Span moves) { enc.GetEggRelearnMoves(parse, pk, moves); - int generation = enc.Generation; + byte generation = enc.Generation; // Gen2 does not have split breed, Gen5 and below do not store relearn moves in the data structure. if (generation <= 5) @@ -188,7 +188,7 @@ private static void GetSuggestedRelearnEgg(this IEncounterTemplate enc, ReadOnly var generator = EncounterGenerator.GetGenerator(enc.Version); Span chain = stackalloc EvoCriteria[EvolutionTree.MaxEvolutions]; - var origin = new EvolutionOrigin(enc.Species, (byte)enc.Version, (byte)enc.Generation, 1, 100, OriginOptions.EncounterTemplate); + var origin = new EvolutionOrigin(enc.Species, enc.Version, enc.Generation, 1, 100, OriginOptions.EncounterTemplate); int count = EvolutionChain.GetOriginChain(chain, pk, origin); var evos = chain[..count].ToArray(); var other = generator.GetPossible(pk, evos, enc.Version, EncounterTypeGroup.Egg); diff --git a/PKHeX.Core/Legality/Moves/Breeding/EggSource.cs b/PKHeX.Core/Legality/Moves/Breeding/EggSource.cs index 353d5f418..d41d153db 100644 --- a/PKHeX.Core/Legality/Moves/Breeding/EggSource.cs +++ b/PKHeX.Core/Legality/Moves/Breeding/EggSource.cs @@ -94,7 +94,7 @@ public static class EggSourceUtil /// /// Unboxes the parse result and returns a user-friendly string for the move result. /// - public static string GetSourceString(Array parse, int generation, int index) + public static string GetSourceString(Array parse, byte generation, int index) { if (index >= parse.Length) return LMoveSourceEmpty; @@ -155,7 +155,7 @@ public static string GetSourceString(Array parse, int generation, int index) /// /// Converts the parse result and returns a user-friendly string for the move result. /// - public static LearnMethod GetSource(byte value, int generation) => generation switch + public static LearnMethod GetSource(byte value, byte generation) => generation switch { 2 => ((EggSource2)value).GetSource(), 3 or 4 => ((EggSource34)value).GetSource(), diff --git a/PKHeX.Core/Legality/Moves/Breeding/MoveBreed.cs b/PKHeX.Core/Legality/Moves/Breeding/MoveBreed.cs index 66462bd70..9704e377c 100644 --- a/PKHeX.Core/Legality/Moves/Breeding/MoveBreed.cs +++ b/PKHeX.Core/Legality/Moves/Breeding/MoveBreed.cs @@ -18,7 +18,7 @@ public static class MoveBreed /// Moves the egg supposedly originated with /// Output buffer indicating the origin of each index within /// True if the moves are ordered correctly, without missing moves. - public static bool Validate(int generation, ushort species, byte form, GameVersion version, ReadOnlySpan moves, Span origins) => generation switch + public static bool Validate(byte generation, ushort species, byte form, GameVersion version, ReadOnlySpan moves, Span origins) => generation switch { 2 => MoveBreed2.Validate(species, version, moves, origins), 3 => MoveBreed3.Validate(species, version, moves, origins), @@ -53,7 +53,7 @@ public static bool GetExpectedMoves(ReadOnlySpan moves, IEncounterTempla /// Uses inputs calculated from . Don't call this directly unless already parsed the input as invalid. /// Expected moves for the encounter /// - public static bool GetExpectedMoves(int generation, ushort species, byte form, GameVersion version, ReadOnlySpan moves, Span origins, Span result) + public static bool GetExpectedMoves(byte generation, ushort species, byte form, GameVersion version, ReadOnlySpan moves, Span origins, Span result) { // Try rearranging the order of the moves. // Group and order moves by their possible origin flags. @@ -94,7 +94,7 @@ public static bool GetExpectedMoves(int generation, ushort species, byte form, G return false; } - private static void GetSortedMoveOrder(int generation, ReadOnlySpan moves, Span origins, Span expected) + private static void GetSortedMoveOrder(byte generation, ReadOnlySpan moves, Span origins, Span expected) { if (generation == 2) { diff --git a/PKHeX.Core/Legality/Moves/Breeding/MoveBreed6.cs b/PKHeX.Core/Legality/Moves/Breeding/MoveBreed6.cs index 538939f2e..37f01d8e3 100644 --- a/PKHeX.Core/Legality/Moves/Breeding/MoveBreed6.cs +++ b/PKHeX.Core/Legality/Moves/Breeding/MoveBreed6.cs @@ -14,7 +14,7 @@ public static class MoveBreed6 private const int level = 1; /// - public static bool Validate(int generation, ushort species, byte form, GameVersion version, ReadOnlySpan moves, Span origins) + public static bool Validate(byte generation, ushort species, byte form, GameVersion version, ReadOnlySpan moves, Span origins) { var count = moves.IndexOf((ushort)0); if (count == 0) diff --git a/PKHeX.Core/Legality/RNG/Algorithms/LCRNG.cs b/PKHeX.Core/Legality/RNG/Algorithms/LCRNG.cs index 70d652ced..911062e43 100644 --- a/PKHeX.Core/Legality/RNG/Algorithms/LCRNG.cs +++ b/PKHeX.Core/Legality/RNG/Algorithms/LCRNG.cs @@ -98,6 +98,17 @@ public static uint Next16(ref uint seed) return seed >> 16; } + /// + /// Gets the previous 16 bits of the previous RNG seed. + /// + /// Seed to advance one step. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static uint Prev16(ref uint seed) + { + seed = Prev(seed); + return seed >> 16; + } + /// /// Advances the RNG seed to the next state value a specified amount of times. /// diff --git a/PKHeX.Core/Legality/RNG/Algorithms/LCRNGReversal.cs b/PKHeX.Core/Legality/RNG/Algorithms/LCRNGReversal.cs index de566c5c3..8f9044bd5 100644 --- a/PKHeX.Core/Legality/RNG/Algorithms/LCRNGReversal.cs +++ b/PKHeX.Core/Legality/RNG/Algorithms/LCRNGReversal.cs @@ -16,7 +16,7 @@ public static class LCRNGReversal private const uint LCRNG_INC = 0x4034; // (((diff * 0x67d3 + 0x4034) >> 16) * 0xd3e) % 0x67d3 line up with the first 16bit low solution modulo 0x67d3 if it exists (see diff definition in code) /// - /// Finds all seeds that can generate the IVs, with a vblank skip between the two IV rand() calls. + /// Finds all seeds that can generate the IVs. /// /// Result storage array, to be populated starting at index 0. /// Entity IV for HP diff --git a/PKHeX.Core/Legality/RNG/Algorithms/LCRNGReversalSkip.cs b/PKHeX.Core/Legality/RNG/Algorithms/LCRNGReversalSkip.cs index 22d921b22..7b5a10775 100644 --- a/PKHeX.Core/Legality/RNG/Algorithms/LCRNGReversalSkip.cs +++ b/PKHeX.Core/Legality/RNG/Algorithms/LCRNGReversalSkip.cs @@ -75,13 +75,13 @@ public static int GetSeedsIVs(Span result, uint first, uint third) return ctr; } - private static void AddSeeds(Span result, uint low, uint first, uint second, ref int ctr) + private static void AddSeeds(Span result, uint low, uint first, uint third, ref int ctr) { // at most 5 iterations do { var test = first | low; - if ((LCRNG.Next2(test) & 0x7fff0000) != second) + if ((LCRNG.Next2(test) & 0x7fff0000) != third) continue; var seed = LCRNG.Prev(test); result[ctr++] = seed; diff --git a/PKHeX.Core/Legality/RNG/CXD/NPCLock.cs b/PKHeX.Core/Legality/RNG/CXD/NPCLock.cs index f22d4a300..68433eabc 100644 --- a/PKHeX.Core/Legality/RNG/CXD/NPCLock.cs +++ b/PKHeX.Core/Legality/RNG/CXD/NPCLock.cs @@ -14,7 +14,7 @@ namespace PKHeX.Core; public int FramesConsumed => Seen ? 5 : 7; public bool Seen => State > 1; public bool Shadow => State != 0; - public (byte Nature, byte Gender) GetLock => (Nature, Gender); + public (Nature Nature, byte Gender) GetLock => ((Nature)Nature, Gender); // Not-Shadow public NPCLock(ushort s, byte n, byte g, byte r) diff --git a/PKHeX.Core/Legality/RNG/CXD/TeamLock.cs b/PKHeX.Core/Legality/RNG/CXD/TeamLock.cs index fa4052d10..a8df50a0e 100644 --- a/PKHeX.Core/Legality/RNG/CXD/TeamLock.cs +++ b/PKHeX.Core/Legality/RNG/CXD/TeamLock.cs @@ -3,21 +3,11 @@ namespace PKHeX.Core; /// /// Represents a Team of Pokémon that is generated before a shadow . /// -public sealed class TeamLock(ushort Species, NPCLockDetail Comment, NPCLock[] Locks) +/// Species of shadow Pokémon that is generated after the . +/// For trainers that have different teams, this indicates what conditions (when/where) the trainer must be battled. +/// Team generated before the Species. +public sealed record TeamLock(ushort Species, NPCLockDetail Comment, NPCLock[] Locks) { - /// - /// Team generated before the Species. - /// - public readonly NPCLock[] Locks = Locks; - /// - /// For trainers that have different teams, this indicates what conditions (when/where) the trainer must be battled. - /// - public readonly NPCLockDetail Comment = Comment; - /// - /// Species of shadow Pokémon that is generated after the . - /// - public readonly ushort Species = Species; - public TeamLock(ushort Species, NPCLock[] Locks) : this(Species, 0, Locks) { } public override string ToString() @@ -30,6 +20,8 @@ public override string ToString() public enum NPCLockDetail : byte { + None = 0, + CipherLab, Post, PhenacCity, diff --git a/PKHeX.Core/Legality/RNG/Methods/Gen4/ClassicEraRNG.cs b/PKHeX.Core/Legality/RNG/ClassicEra/ClassicEraRNG.cs similarity index 51% rename from PKHeX.Core/Legality/RNG/Methods/Gen4/ClassicEraRNG.cs rename to PKHeX.Core/Legality/RNG/ClassicEra/ClassicEraRNG.cs index 3f12a5840..ce7acebef 100644 --- a/PKHeX.Core/Legality/RNG/Methods/Gen4/ClassicEraRNG.cs +++ b/PKHeX.Core/Legality/RNG/ClassicEra/ClassicEraRNG.cs @@ -29,9 +29,9 @@ public static uint GetChainShinyPID(ref uint seed, in uint id32) } /// - /// Generates a PID for a given seed. + /// Rolls the RNG forward twice to get the usual Method 1 call-ordered PID. /// - /// Seed to use for the RNG. + /// Seed right before the first PID call. /// 32-bit value containing the PID (high | low). public static uint GetSequentialPID(ref uint seed) { @@ -40,6 +40,44 @@ public static uint GetSequentialPID(ref uint seed) return (rand2 << 16) | rand1; } + /// + /// Rolls the RNG forward twice to get the usual Method 1 call-ordered PID. + /// + /// Seed right before the first PID call. + /// 32-bit value containing the PID (high | low). + public static uint GetSequentialPID(uint seed) + { + var rand1 = LCRNG.Next16(ref seed); + var rand2 = LCRNG.Next16(ref seed); + return (rand2 << 16) | rand1; + } + + /// + /// Rolls the RNG forward twice to get the reverse Method 1 call-ordered PID. + /// + /// Seed right before the first PID call. + /// Generation 3 Unown + /// 32-bit value containing the PID (high | low). + public static uint GetReversePID(ref uint seed) + { + var rand1 = LCRNG.Next16(ref seed); + var rand2 = LCRNG.Next16(ref seed); + return (rand2 << 16) | rand1; + } + + /// + /// Rolls the RNG forward twice to get the reverse Method 1 call-ordered PID. + /// + /// Seed right before the first PID call. + /// Generation 3 Unown + /// 32-bit value containing the PID (high | low). + public static uint GetReversePID(uint seed) + { + var rand1 = LCRNG.Next16(ref seed); + var rand2 = LCRNG.Next16(ref seed); + return (rand1 << 16) | rand2; + } + /// /// Generates IVs for a given seed. /// diff --git a/PKHeX.Core/Legality/RNG/ClassicEra/Gen3/MethodH.cs b/PKHeX.Core/Legality/RNG/ClassicEra/Gen3/MethodH.cs new file mode 100644 index 000000000..67e6a0f66 --- /dev/null +++ b/PKHeX.Core/Legality/RNG/ClassicEra/Gen3/MethodH.cs @@ -0,0 +1,602 @@ +using System.Runtime.CompilerServices; +using static PKHeX.Core.MethodHCondition; +using static PKHeX.Core.LeadRequired; +using static PKHeX.Core.SlotType3; + +namespace PKHeX.Core; + +/// +/// Method H logic used by mainline RNG. +/// +public static class MethodH +{ + /// + /// High-level method to get the first possible encounter conditions. + /// + /// Encounter template. + /// Seed that immediately generates the PID. + /// Level range constraints for the capture, if known. + /// Version encountered in (either Emerald or not) + /// Gender encountered as + /// Current format (different from 3) + public static LeadSeed GetSeed(TEnc enc, uint seed, TEvo evo, bool emerald, byte gender, byte format) + where TEnc : IEncounterSlot3 + where TEvo : ILevelRange + { + var pid = enc.Species != (ushort)Species.Unown + ? ClassicEraRNG.GetSequentialPID(seed) + : ClassicEraRNG.GetReversePID(seed); + var nature = (byte)(pid % 25); + + var info = GetReversalWindow(enc, seed, nature, emerald, gender); + return GetOriginSeed(info, enc, seed, nature, evo.LevelMin, evo.LevelMax, format); + } + + /// + public static LeadSeed GetSeed(TEnc enc, uint seed, bool emerald, byte gender, byte format) + where TEnc : IEncounterSlot3 => GetSeed(enc, seed, enc, emerald, gender, format); + + // Summary of Random Determinations: + // Nature: rand() % 25 == nature + // Cute Charm: rand() % 3 != 0; (2/3 odds) + // Sync: rand() & 1 == 0; (50% odds) + // Static/Magnet Pull: rand() & 1 == 0; + // Pressure/Hustle/Vital Spirit: rand() & 1 == 1; + // Intimidate/Keen Eye: rand() & 1 == 1; -- 0 will reject the encounter. + + private const byte Format = 3; + + private static bool IsCuteCharmFail(uint rand) => (rand % 3) == 0; // 1/3 odds + private static bool IsCuteCharmPass(uint rand) => (rand % 3) != 0; // 2/3 odds + + //private static bool IsSyncFail(uint rand) => (rand & 1) != 0; + private static bool IsSyncPass(uint rand) => (rand & 1) == 0; + + private static bool IsStaticMagnetFail(uint rand) => (rand & 1) != 0; + private static bool IsStaticMagnetPass(uint rand) => (rand & 1) == 0; + + private static bool IsHustleVitalFail(uint rand) => (rand & 1) != 1; + private static bool IsHustleVitalPass(uint rand) => (rand & 1) == 1; + + //private static bool IsIntimidateKeenEyeFail(uint rand) => (rand & 1) != 1; + private static bool IsIntimidateKeenEyePass(uint rand) => (rand & 1) == 1; + private static bool IsSafariBlockProc(uint seed) => (seed >> 16) % 100 < 80; + + private static uint GetNature(uint rand) => rand % 25; + private static bool IsMatchUnown(uint pid, byte nature, byte form) => pid % 25 == nature && EntityPID.GetUnownForm3(pid) == form; + + private static bool IsMatchGender(uint pid, byte genderMin, byte genderMax) + { + var gender = pid & 0xFF; + return genderMin <= gender && gender <= genderMax; + } + + /// + /// Gets the appropriate for the species and game. + /// + public static MethodHCondition GetCondition(ushort species, GameVersion version) + { + if (species == (ushort)Species.Unown) + return Unown; + if (version == GameVersion.E) + return Emerald; + return Regular; + } + + /// + /// Caches details useful for the rolling look-back allowed for the input seed. + /// + public static MethodHWindowInfo GetReversalWindow(T enc, uint seed, byte nature, bool emerald, byte gender) + where T : IEncounterSlot3 + { + if (emerald) + { + var pi = PersonalTable.E[enc.Species]; + var ratio = pi.Gender; + if (ratio == PersonalInfo.RatioMagicGenderless) + return new((ushort)GetReversalWindow(seed, nature), Emerald); + + var (min, max) = PersonalInfo.GetGenderMinMax(gender, ratio); + var result = GetReversalWindowCute(seed, nature, min, max); + return new((ushort)result.NoLead, Emerald, ratio, (ushort)result.Cute); + } + if (enc.Species == (int)Species.Unown) // Never Emerald + { + var result = GetReversalWindow(seed, nature, enc.Form); + return new((ushort)result, Unown); + } + // Otherwise... + { + var result = GetReversalWindow(seed, nature); + return new((ushort)result, Regular); + } + } + + /// + /// Gets the first possible origin seed and lead for the input encounter & constraints. + /// + public static LeadSeed GetOriginSeed(in MethodHWindowInfo info, T enc, uint seed, byte nature, byte levelMin, byte levelMax, byte format = Format) + where T : IEncounterSlot3 + { + return info.Type == Emerald + ? GetOriginSeedEmerald(enc, seed, nature, info.CountRegular, info.CountCute, levelMin, levelMax, format) + : GetOriginSeed(enc, seed, nature, info.CountRegular, levelMin, levelMax, format); + } + + private static LeadSeed GetOriginSeedEmerald(T enc, uint seed, byte nature, int reverseCount, int revCute, byte levelMin, byte levelMax, byte format = Format) + where T : IEncounterSlot3 + { + LeadSeed prefer = default; + while (true) + { + if (TryGetMatch(enc, levelMin, levelMax, seed, nature, format, out var result)) + { + if (CheckEncounterActivationEmerald(enc, ref result)) + { + if (result.IsNoAbilityLead()) + return result; + if (result.IsBetterThan(prefer)) + prefer = result; + } + } + + if (reverseCount == 0) + { + // If we haven't found a lead, we can try checking for Cute Charm if allowed. + if (revCute == 0 || prefer.IsValid()) + return prefer; + break; + } + reverseCount--; + seed = LCRNG.Prev2(seed); + } + + while (true) + { + if (TryGetMatch(enc, levelMin, levelMax, seed, nature, format, out var result) + && result.IsNoAbilityLead()) + { + result.Lead = CuteCharm; + if (CheckEncounterActivationEmerald(enc, ref result)) + { + if (result.IsNoAbilityLead()) + return result; + if (result.IsBetterThan(prefer)) + prefer = result; + } + } + revCute--; + if (revCute == 0) + return prefer; + seed = LCRNG.Prev2(seed); + } + } + + private static bool CheckEncounterActivationEmerald(T enc, ref LeadSeed result) + where T : IEncounterSlot3 + { + if (enc.Type is Rock_Smash) + return IsRockSmashPossible(enc.AreaRate, ref result.Seed); + if (enc.Type.IsFishingRodType()) + return true; // can just wait and trigger after hooking. + + // Can sweet scent trigger. + return true; + } + + private static LeadSeed GetOriginSeed(T enc, uint seed, byte nature, int reverseCount, byte levelMin, byte levelMax, byte format = Format) + where T : IEncounterSlot3 + { + while (true) + { + if (TryGetMatchNoLead(enc, levelMin, levelMax, seed, nature, format, out var result)) + { + if (CheckEncounterActivation(enc, ref result)) + return result; + } + if (reverseCount == 0) + break; + reverseCount--; + seed = LCRNG.Prev2(seed); + } + return default; + } + + private static bool CheckEncounterActivation(T enc, ref LeadSeed result) + where T : IEncounterSlot3 + { + if (enc.Type is Rock_Smash) + return IsRockSmashPossible(enc.AreaRate, ref result.Seed); + if (enc.Type.IsFishingRodType()) + return true; // can just wait and trigger after hooking. + // Can sweet scent trigger. + return true; + } + + /// + private static int GetReversalWindow(uint seed, byte nature) => MethodJ.GetReversalWindow(seed, nature); + + /// + /// Seed that generates the expected resulting PID. + /// Nature of the resulting PID. + /// Inclusive low-bound for the gender portion of the PID. + /// Inclusive high-bound for the gender portion of the PID. + /// Count of reverses allowed for no specific lead (not requiring cute charm) and a matching cute charm lead. + /// Only accessible in Emerald for gendered Pokémon. + private static (int NoLead, int Cute) GetReversalWindowCute(uint seed, byte nature, byte genderMin, byte genderMax) + { + int noLead = 0; + int ctr = 0; + uint b = seed >> 16; + while (true) + { + var a = LCRNG.Prev16(ref seed); + var pid = b << 16 | a; + if (pid % 25 == nature) + { + if (noLead == 0) + noLead = ctr; + if (IsMatchGender(pid, genderMin, genderMax)) + return (noLead, ctr - noLead); + } + b = LCRNG.Prev16(ref seed); + ctr++; + } + } + + /// + /// Seed that generates the expected resulting PID. + /// Nature of the resulting PID. + /// Form of the resulting PID. + /// Only used for FR/LG . + private static int GetReversalWindow(uint seed, byte nature, byte form) + { + // Reverses the PID calls, and ensures the form matches. + int ctr = 0; + uint b = seed >> 16; + while (true) + { + var a = LCRNG.Prev16(ref seed); + var pid = a << 16 | b; + if (IsMatchUnown(pid, nature, form)) + break; // Correct Nature and Form. + b = LCRNG.Prev16(ref seed); + ctr++; + } + return ctr; + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static bool TryGetMatchNoLead(T enc, byte levelMin, byte levelMax, uint seed, byte nature, byte format, out LeadSeed result) + where T : IEncounterSlot3 + { + var p0 = seed >> 16; // 0 + + var rseSafari = enc.IsSafariHoenn; + if (rseSafari) + { + // Seek backwards to the activation check (80%). + // The nature preference table consumes 300 RNG calls, so we need to jump back that far. + // Below are the magic RNG multiply & add for 300 prev calls. + var safariBlockSeed = (0xC048C851u * seed) + 0x196302B4u; + if (IsSafariBlockProc(safariBlockSeed)) + { + var ctx = new FrameCheckDetails(enc, safariBlockSeed, levelMin, levelMax, format); + if (IsSlotValidRegular(ctx, out uint origin)) + { result = new(origin, None); return true; } + } + } + var reg = GetNature(p0) == nature; + if (reg) + { + // Still consumes a dummy call between nature and prior. + // Assume no Safari Block was placed, so that the nature rolls are used. + if (rseSafari) + seed = LCRNG.Prev(seed); + + var ctx = new FrameCheckDetails(enc, seed, levelMin, levelMax, format); + if (IsSlotValidRegular(ctx, out uint origin)) + { result = new(origin, None); return true; } + } + result = default; return false; + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static bool TryGetMatch(T enc, byte levelMin, byte levelMax, uint seed, byte nature, byte format, out LeadSeed result) + where T : IEncounterSlot3 + { + var p0 = seed >> 16; // 0 + + if (enc.IsSafariHoenn) + { + // Seek backwards to the activation check (80%). + // The nature preference table consumes 300 RNG calls, so we need to jump back that far. + // Below are the magic RNG multiply & add for 300 prev calls. + var safariBlockSeed = (0xC048C851u * seed) + 0x196302B4u; + if (IsSafariBlockProc(safariBlockSeed)) + { + var ctx = new FrameCheckDetails(enc, safariBlockSeed, levelMin, levelMax, format); + if (TryGetMatchNoSync(ctx, out result)) + return true; + } + + // Still consumes a dummy call between nature and prior. + // Assume no Safari Block was placed, so that the nature rolls are used. + // Do this before checking either; it's a >50% chance of being a Sync or regular nature call. + seed = LCRNG.Prev(seed); + } + + var syncProc = IsSyncPass(p0); + if (syncProc) + { + var ctx = new FrameCheckDetails(enc, seed, levelMin, levelMax, format); + if (IsSlotValidRegular(ctx, out seed)) + { + result = new(seed, Synchronize); + return true; + } + } + var reg = GetNature(p0) == nature; + if (reg) + { + var ctx = new FrameCheckDetails(enc, seed, levelMin, levelMax, format); + if (TryGetMatchNoSync(ctx, out result)) + return true; + } + result = default; return false; + } + + private static bool TryGetMatchCuteCharm(in FrameCheckDetails ctx, out uint result) + { + // Cute Charm + // -3 ESV + // -2 Level + // -1 CC Proc (Random() % 3 != 0) + // 0 Nature + if (IsCuteCharmFail(ctx.Prev1)) + { result = default; return false; } + + return IsSlotValidFrom1Skip(ctx, out result); + } + + private static bool IsSlotValidCuteCharmFail(in FrameCheckDetails ctx, out uint result) + { + // Cute Charm + // -3 ESV + // -2 Level + // -1 CC Proc (Random() % 3 == 0) + // 0 Nature + if (IsCuteCharmPass(ctx.Prev1)) // should have triggered + { result = default; return false; } + + return IsSlotValidFrom1Skip(ctx, out result); + } + + private static bool IsSlotValidSyncFail(in FrameCheckDetails ctx, out uint result) + { + // Keen Eye, Intimidate (Not compatible with Sweet Scent) + // -3 ESV + // -2 Level + // -1 Sync Proc (Random() % 2) FAIL + // 0 Nature + if (IsSyncPass(ctx.Prev1)) // should have triggered + { result = default; return false; } + + return IsSlotValidFrom1Skip(ctx, out result); + } + + private static bool IsSlotValidIntimidate(in FrameCheckDetails ctx, out uint result) + { + // Keen Eye, Intimidate (Not compatible with Sweet Scent) + // -3 ESV + // -2 Level + // -1 Level Adequate Check !(Random() % 2 == 1) rejects -- rand%2==1 is adequate + // 0 Nature + // Note: if this check fails, the encounter generation routine is aborted. + if (IsIntimidateKeenEyePass(ctx.Prev1)) // encounter routine aborted + { result = default; return false; } + + return IsSlotValidFrom1Skip(ctx, out result); + } + + private static bool IsSlotValidHustleVitalFail(in FrameCheckDetails ctx, out uint result) + { + // Pressure, Hustle, Vital Spirit = Force Maximum Level from slot + // -3 ESV + // -2 Level + // -1 LevelMax proc (Random() & 1) FAIL + // 0 Nature + if (IsHustleVitalPass(ctx.Prev1)) // should have triggered + { result = default; return false; } + + return IsSlotValidFrom1Skip(ctx, out result); + } + + private static bool TryGetMatchNoSync(in FrameCheckDetails ctx, out LeadSeed result) + { + if (IsSlotValidRegular(ctx, out uint seed)) + { result = new(seed, None); return true; } + + if (IsSlotValidSyncFail(ctx, out seed)) + { result = new(seed, SynchronizeFail); return true; } + if (IsSlotValidCuteCharmFail(ctx, out seed)) + { result = new(seed, CuteCharmFail); return true; } + if (IsSlotValidHustleVitalFail(ctx, out seed)) + { result = new(seed, PressureHustleSpiritFail); return true; } + if (IsSlotValidStaticMagnetFail(ctx, out seed)) + { result = new(seed, StaticMagnetFail); return true; } + // Intimidate/Keen Eye failing will result in no encounter. + + if (IsSlotValidStaticMagnet(ctx, out seed, out var lead)) + { result = new(seed, lead); return true; } + if (IsSlotValidHustleVital(ctx, out seed)) + { result = new(seed, PressureHustleSpirit); return true; } + if (IsSlotValidIntimidate(ctx, out seed)) + { result = new(seed, IntimidateKeenEyeFail); return true; } + if (TryGetMatchCuteCharm(ctx, out seed)) + { result = new(seed, CuteCharm); return true; } + + result = default; return false; + } + + private static bool IsSlotValidFrom1Skip(FrameCheckDetails ctx, out uint result) + { + // -3 ESV + // -2 Level + // -1 (Proc Already Checked) + // 0 Nature + if (IsLevelValid(ctx.Encounter, ctx.LevelMin, ctx.LevelMax, ctx.Format, ctx.Prev2)) + { + if (IsSlotValid(ctx.Encounter, ctx.Prev3)) + { result = ctx.Seed4; return true; } + } + result = default; return false; + } + + private static bool IsSlotValidRegular(in FrameCheckDetails ctx, out uint result) + where T : IEncounterSlot3 + { + // -2 ESV + // -1 Level + // 0 Nature + if (IsLevelValid(ctx.Encounter, ctx.LevelMin, ctx.LevelMax, ctx.Format, ctx.Prev1)) + { + if (IsSlotValid(ctx.Encounter, ctx.Prev2)) + { result = ctx.Seed3; return true; } + } + result = default; return false; + } + + private static bool IsSlotValidHustleVital(in FrameCheckDetails ctx, out uint result) + where T : IEncounterSlot3 + { + // Pressure, Hustle, Vital Spirit = Force Maximum Level from slot + // -3 ESV + // -2 Level + // -1 LevelMax proc (Random() & 1) + // 0 Nature + if (IsHustleVitalFail(ctx.Prev1)) // should have triggered + { result = default; return false; } + + var expectLevel = ctx.Encounter.PressureLevel; + if (!IsOriginalLevelValid(ctx.LevelMin, ctx.LevelMax, ctx.Format, expectLevel)) + { result = default; return false; } + + // Level is always rand(), but... + { + // Don't bother evaluating Prev2 for level, as it's always bumped to max after. + if (IsSlotValid(ctx.Encounter, ctx.Prev3)) + { result = ctx.Seed4; return true; } + } + result = default; return false; + } + + private static bool IsSlotValidStaticMagnet(in FrameCheckDetails ctx, out uint result, out LeadRequired lead) + where T : IEncounterSlot3 + { + // Static or Magnet Pull + // -3 SlotProc (Random % 2 == 0) + // -2 ESV (select slot) + // -1 Level + // 0 Nature + lead = None; + if (IsStaticMagnetFail(ctx.Prev3)) // should have triggered + { result = default; return false; } + + if (IsLevelValid(ctx.Encounter, ctx.LevelMin, ctx.LevelMax, ctx.Format, ctx.Prev1)) + { + if (ctx.Encounter.IsSlotValidStaticMagnet(ctx.Prev2, out lead)) + { result = ctx.Seed4; return true; } + } + result = default; return false; + } + + private static bool IsSlotValidStaticMagnetFail(in FrameCheckDetails ctx, out uint result) + where T : IEncounterSlot3 + { + // Static or Magnet Pull + // -3 SlotProc (Random % 2 == 1) FAIL + // -2 ESV (select slot) + // -1 Level + // 0 Nature + if (IsStaticMagnetPass(ctx.Prev3)) // should have triggered + { result = default; return false; } + + if (IsLevelValid(ctx.Encounter, ctx.LevelMin, ctx.LevelMax, ctx.Format, ctx.Prev1)) + { + if (IsSlotValid(ctx.Encounter, ctx.Prev2)) + { result = ctx.Seed4; return true; } + } + result = default; return false; + } + + private static bool IsSlotValid(T enc, uint u16SlotRand) + where T : IEncounterSlot3, INumberedSlot + { + var slot = SlotMethodH.GetSlot(enc.Type, u16SlotRand); + return slot == enc.SlotNumber; + } + + private static bool IsLevelValid(T enc, byte min, byte max, byte format, uint u16LevelRand) where T : ILevelRange + { + var level = GetExpectedLevel(enc, u16LevelRand); + return IsOriginalLevelValid(min, max, format, level); + } + + private static bool IsOriginalLevelValid(byte min, byte max, byte format, uint level) + { + if (format == Format) + return level == min; // Met Level matches + return LevelRangeExtensions.IsLevelWithinRange((int)level, min, max); + } + + private static uint GetExpectedLevel(ILevelRange enc, uint u16LevelRand) + { + uint mod = 1u + enc.LevelMax - enc.LevelMin; + return (u16LevelRand % mod) + enc.LevelMin; + } + + private static bool IsRockSmashPossible(byte areaRate, ref uint seed) + { + if (IsRatePass(seed, areaRate, None)) // Lead doesn't matter, doesn't influence. + { + seed = LCRNG.Prev(seed); + return true; + } + return false; + } + + private const ushort MaxEncounterRate = 2880; // 0xB40 + + private static bool IsRatePass(uint seed, byte areaRate, LeadRequired lead, bool ignoreAbility = true) + { + var u16 = seed >> 16; + var encRate = GetEncounterRate(areaRate, lead, ignoreAbility); + return u16 % MaxEncounterRate < encRate; + } + + private static uint GetEncounterRate(byte areaRate, LeadRequired lead, bool ignoreAbility) + { + uint encRate = areaRate * 16u; + // We intend to pass the encounter, as we want an encounter to trigger. + // Player on a Bike adjusts by *80 /100. We assume the player is not on a bike. + // Cleanse Tag adjusts by *2 /3. We assume the player is not using a Cleanse Tag. + // Black Flute adjusts by /2. We assume the player is not using a Black Flute. + // White Flute adjusts by += /2. We assume the player is using a White Flute.*** + encRate += (encRate >> 1); // +50% + + if (!ignoreAbility && lead == None) + { + // Stench, White Smoke, and Sand Veil (in Sandstorm) halve the rate. We assume the player is not using any of these. + // Illuminate and Arena Trap double the rate. + encRate <<= 1; // *2 + } + return encRate; + } + + private static bool IsFishingRodType(this SlotType3 t) => t + is Old_Rod + or Good_Rod + or Super_Rod + or SwarmFish50; +} diff --git a/PKHeX.Core/Legality/RNG/ClassicEra/Gen3/MethodHCondition.cs b/PKHeX.Core/Legality/RNG/ClassicEra/Gen3/MethodHCondition.cs new file mode 100644 index 000000000..f4945a4a6 --- /dev/null +++ b/PKHeX.Core/Legality/RNG/ClassicEra/Gen3/MethodHCondition.cs @@ -0,0 +1,29 @@ +namespace PKHeX.Core; + +/// +/// Types of Method H sub-patterns for Gen 3. +/// +public enum MethodHCondition : byte +{ + /// + /// Invalid sentinel value. + /// + Empty = 0, + + /// + /// Disallow logic to be used. + /// + /// Used by and . + Regular, + + /// + /// Allow logic to be used. + /// + Emerald, + + /// + /// + /// + /// Only available in , so never . + Unown, +} diff --git a/PKHeX.Core/Legality/RNG/ClassicEra/Gen3/MethodHWindowInfo.cs b/PKHeX.Core/Legality/RNG/ClassicEra/Gen3/MethodHWindowInfo.cs new file mode 100644 index 000000000..05440cb26 --- /dev/null +++ b/PKHeX.Core/Legality/RNG/ClassicEra/Gen3/MethodHWindowInfo.cs @@ -0,0 +1,16 @@ +namespace PKHeX.Core; + +/// +/// Cache-able representation of the Method H window information. +/// +/// Count of reversals allowed for no specific lead (not requiring cute charm). +/// Type of Method H logic. +/// Gender Ratio of the encountered Pokémon. +/// Count of reversals allowed for a matching cute charm lead. +public readonly record struct MethodHWindowInfo(ushort CountRegular, MethodHCondition Type, byte Gender = 0, ushort CountCute = 0) +{ + private bool IsUninitialized => Type == MethodHCondition.Empty; + private bool IsGenderRatioDifferentCuteCharm(ushort Species) => Type == MethodHCondition.Emerald && PersonalTable.E[Species].Gender != Gender; + + public bool ShouldRevise(ushort Species) => IsUninitialized || IsGenderRatioDifferentCuteCharm(Species); +} diff --git a/PKHeX.Core/Legality/RNG/ClassicEra/Gen3/SlotMethodH.cs b/PKHeX.Core/Legality/RNG/ClassicEra/Gen3/SlotMethodH.cs new file mode 100644 index 000000000..3fe6447d5 --- /dev/null +++ b/PKHeX.Core/Legality/RNG/ClassicEra/Gen3/SlotMethodH.cs @@ -0,0 +1,100 @@ +using static PKHeX.Core.SlotType3; + +namespace PKHeX.Core; + +/// +/// Encounter slot determination for . +/// +public static class SlotMethodH +{ + private const byte Invalid = byte.MaxValue; // all slots are [0,X], unsigned. This will always result in a non-match. + + /// + /// Gets the from the raw 16bit seed half. + /// + public static byte GetSlot(SlotType3 type, uint rand) => type switch + { + Grass => GetRegular(rand % 100), + Surf => GetSurf(rand % 100), + Old_Rod => GetOldRod(rand % 100), + Good_Rod => GetGoodRod(rand % 100), + Super_Rod => GetSuperRod(rand % 100), + Rock_Smash => GetSurf(rand % 100), + + SwarmFish50 => (rand % 100 < 50) ? (byte)0 : Invalid, + SwarmGrass50 => (rand % 100 < 50) ? (byte)0 : Invalid, + _ => Invalid, + }; + + /// + /// Calculates the encounter slot index based on the roll for a Gen3 Wild encounter. + /// + /// [0,100) + public static byte GetRegular(uint roll) => roll switch + { + < 20 => 0, // 00,19 (20%) + < 40 => 1, // 20,39 (20%) + < 50 => 2, // 40,49 (10%) + < 60 => 3, // 50,59 (10%) + < 70 => 4, // 60,69 (10%) + < 80 => 5, // 70,79 (10%) + < 85 => 6, // 80,84 ( 5%) + < 90 => 7, // 85,89 ( 5%) + < 94 => 8, // 90,93 ( 4%) + < 98 => 9, // 94,97 ( 4%) + < 99 => 10,// 98,98 ( 1%) + 99 => 11,// 99 ( 1%) + _ => Invalid, + }; + + /// + /// Calculates the encounter slot index based on the roll for a Gen3 Surf encounter. + /// + /// [0,100) + public static byte GetSurf(uint roll) => roll switch + { + < 60 => 0, // 00,59 (60%) + < 90 => 1, // 60,89 (30%) + < 95 => 2, // 90,94 ( 5%) + < 99 => 3, // 95,98 ( 4%) + 99 => 4, // 99 ( 1%) + _ => Invalid, + }; + + /// + /// Calculates the encounter slot index based on the roll for a Gen3 Old Rod encounter. + /// + /// [0,100) + public static byte GetOldRod(uint roll) => roll switch + { + < 70 => 0, // 00,69 (70%) + <= 99 => 1, // 70,99 (30%) + _ => Invalid, + }; + + /// + /// Calculates the encounter slot index based on the roll for a Gen3 Good Rod encounter. + /// + /// [0,100) + public static byte GetGoodRod(uint roll) => roll switch + { + < 60 => 0, // 00,59 (60%) + < 80 => 1, // 60,79 (20%) + <= 99 => 2, // 80,99 (20%) + _ => Invalid, + }; + + /// + /// Calculates the encounter slot index based on the roll for a Gen3 Super Rod encounter. + /// + /// [0,100) + public static byte GetSuperRod(uint roll) => roll switch + { + < 40 => 0, // 00,39 (40%) + < 80 => 1, // 40,69 (40%) + < 95 => 2, // 70,94 (15%) + < 99 => 3, // 95,98 ( 4%) + 99 => 4, // 99 ( 1%) + _ => Invalid, + }; +} diff --git a/PKHeX.Core/Legality/RNG/ClassicEra/Gen4/MethodJ.cs b/PKHeX.Core/Legality/RNG/ClassicEra/Gen4/MethodJ.cs new file mode 100644 index 000000000..326e312f9 --- /dev/null +++ b/PKHeX.Core/Legality/RNG/ClassicEra/Gen4/MethodJ.cs @@ -0,0 +1,481 @@ +using System; +using System.Runtime.CompilerServices; +using static PKHeX.Core.LeadRequired; +using static PKHeX.Core.GameVersion; +using static PKHeX.Core.SlotType4; + +namespace PKHeX.Core; + +/// +/// Method J logic used by RNG. +/// +public static class MethodJ +{ + /// + /// High-level method to get the first possible encounter conditions. + /// + /// Encounter template. + /// Seed that immediately generates the PID. + /// Level range constraints for the capture, if known. + /// Current format (different from 4) + public static LeadSeed GetSeed(TEnc enc, uint seed, TEvo evo, byte format) + where TEnc : IEncounterSlot4 + where TEvo : ILevelRange + { + var pid = ClassicEraRNG.GetSequentialPID(seed); + var nature = (byte)(pid % 25); + + var frames = GetReversalWindow(seed, nature); + return GetOriginSeed(enc, seed, nature, frames, evo.LevelMin, evo.LevelMax, format); + } + + /// + public static LeadSeed GetSeed(TEnc enc, uint seed, byte format) + where TEnc : IEncounterSlot4 => GetSeed(enc, seed, enc, format); + + // Summary of Random Determinations: + // For constant-value rand choices, the games avoid using modulo via: + // Rand(x) == rand16() / ((0xFFFF/x) + 1) + // For variable rand choices (like level & Static/Magnet Pull), they use modulo. + // Nature: rand() / 0xA3E == nature (1/25 odds) + // Cute Charm: rand() / 0x5556 != 0; (2/3 odds) + // Sync: rand() >> 15 == 0; (50% odds) + // Static/Magnet Pull: rand() >> 15 == 0; + // Pressure/Hustle/Vital Spirit: rand() >> 15 == 1; + // Intimidate/Keen Eye: rand() >> 15 == 1; -- 0 will reject the encounter. + // Feebas Spot: rand() >> 15 == 1; -- 0 will use regular encounters. + + private const byte Format = 4; + + private static bool IsCuteCharmFail(uint rand) => (rand / 0x5556) == 0; // 1/3 odds + private static bool IsCuteCharmPass(uint rand) => (rand / 0x5556) != 0; // 2/3 odds + + //private static bool IsSyncFail(uint rand) => (rand >> 15) != 0; + private static bool IsSyncPass(uint rand) => (rand >> 15) == 0; + + private static bool IsStaticMagnetFail(uint rand) => (rand >> 15) != 0; + private static bool IsStaticMagnetPass(uint rand) => (rand >> 15) == 0; + + private static bool IsHustleVitalFail(uint rand) => (rand >> 15) != 1; + private static bool IsHustleVitalPass(uint rand) => (rand >> 15) == 1; + + //private static bool IsIntimidateKeenEyeFail(uint rand) => (rand >> 15) != 1; + private static bool IsIntimidateKeenEyePass(uint rand) => (rand >> 15) == 1; + + private static bool IsFeebasChance(uint rand) => (rand >> 15) == 1; + + private static uint GetNature(uint rand) => rand / 0xA3Eu; + + /// + /// Gets the first possible origin seed and lead for the input encounter & constraints. + /// + public static LeadSeed GetOriginSeed(T enc, uint seed, byte nature, int reverseCount, byte levelMin, byte levelMax, byte format = Format) + where T : IEncounterSlot4 + { + LeadSeed prefer = default; + while (true) + { + if (TryGetMatch(enc, levelMin, levelMax, seed, nature, format, out var result)) + { + if (CheckEncounterActivation(enc, ref result)) + { + if (result.IsNoRequirement()) + return result; + if (result.IsBetterThan(prefer)) + prefer = result; + } + } + if (reverseCount == 0) + return prefer; + reverseCount--; + seed = LCRNG.Prev2(seed); + } + } + + private static bool CheckEncounterActivation(T enc, ref LeadSeed result) + where T : IEncounterSlot4 + { + if (enc.Type.IsFishingRodType()) + { + if (enc is EncounterSlot4 { Parent.IsCoronetFeebasArea: true } s4) + { + if (!IsValidCoronetB1F(s4, ref result.Seed)) + return false; + } + // D/P don't reference Suction Cups or Sticky Hold. + return enc is IVersion { Version: Pt } + ? IsFishPossible(enc.Type, ref result.Seed, ref result.Lead) + : IsFishPossible(enc.Type, ref result.Seed); + } + // Can sweet scent trigger. + return true; + } + + private static bool CheckEncounterActivation(T enc, ref uint result) + where T : IEncounterSlot4 + { + // Lead is required to be Cute Charm. + if (enc.Type.IsFishingRodType()) + { + if (enc is EncounterSlot4 { Parent.IsCoronetFeebasArea: true } s4) + { + if (!IsValidCoronetB1F(s4, ref result)) + return false; + } + return IsFishPossible(enc.Type, ref result); + } + // Can sweet scent trigger. + return true; + } + + private static bool IsValidCoronetB1F(ISpeciesForm s4, ref uint result) + { + // The game rolls to check if it might need to replace the slots with Feebas. + // This occurs in Mt. Coronet B1F; if passed, check if the player is on a Feebas tile before replacing. + // 0 - Hook + // 1 - CheckTiles -- current seed + // 2- ESV + if (s4.Species is (int)Species.Feebas && !IsFeebasChance(result >> 16)) + return false; + + // Regular slots don't need to falsify the rand(). + // Players can just fish from a non-Feebas tile. + // The rand() call is unavoidable when in the area. + result = LCRNG.Prev(result); + return true; + } + + /// + /// Attempts to find a matching seed for the given encounter and constraints for Cute Charm buffered PIDs. + /// + public static bool TryGetMatchCuteCharm(T enc, ReadOnlySpan seeds, byte nature, byte levelMin, byte levelMax, out uint result) + where T : IEncounterSlot4 + { + foreach (uint seed in seeds) + { + var p0 = seed >> 16; // 0 + var reg = GetNature(p0) == nature; + if (!reg) + continue; + var ctx = new FrameCheckDetails(enc, seed, levelMin, levelMax, 4); + if (!TryGetMatchCuteCharm(ctx, out result)) + continue; + if (!CheckEncounterActivation(enc, ref result)) + continue; + return true; + } + result = default; return false; + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static bool TryGetMatch(T enc, byte levelMin, byte levelMax, uint seed, byte nature, byte format, out LeadSeed result) + where T : IEncounterSlot4 + { + var p0 = seed >> 16; // 0 + var reg = GetNature(p0) == nature; + if (reg) + { + var ctx = new FrameCheckDetails(enc, seed, levelMin, levelMax, format); + return TryGetMatchNoSync(ctx, out result); + } + var syncProc = IsSyncPass(p0); + if (syncProc) + { + var ctx = new FrameCheckDetails(enc, seed, levelMin, levelMax, format); + if (IsSlotValidRegular(ctx, out seed)) + { + result = new(seed, Synchronize); + return true; + } + } + result = default; + return false; + } + + private static bool TryGetMatchCuteCharm(in FrameCheckDetails ctx, out uint result) + where T : IEncounterSlot4 + { + if (IsCuteCharmFail(ctx.Prev1)) + { result = default; return false; } + + return IsSlotValidFrom1Skip(ctx, out result); + } + + private static bool IsSlotValidCuteCharmFail(in FrameCheckDetails ctx, out uint result) + where T : IEncounterSlot4 + { + if (IsCuteCharmPass(ctx.Prev1)) // should have triggered + { result = default; return false; } + + return IsSlotValidFrom1Skip(ctx, out result); + } + + private static bool IsSlotValidSyncFail(in FrameCheckDetails ctx, out uint result) + where T : IEncounterSlot4 + { + if (IsSyncPass(ctx.Prev1)) // should have triggered + { result = default; return false; } + + return IsSlotValidFrom1Skip(ctx, out result); + } + + private static bool IsSlotValidIntimidate(in FrameCheckDetails ctx, out uint result) + where T : IEncounterSlot4 + { + // Requires lead with level 5+ above the encounter's level. Always possible. + if (IsIntimidateKeenEyePass(ctx.Prev1)) // encounter routine aborted + { result = default; return false; } + + return IsSlotValidFrom1Skip(ctx, out result); + } + + private static bool IsSlotValidHustleVitalFail(in FrameCheckDetails ctx, out uint result) + where T : IEncounterSlot4 + { + if (IsHustleVitalPass(ctx.Prev1)) // should have triggered + { result = default; return false; } + + return IsSlotValidFrom1Skip(ctx, out result); + } + + private static bool TryGetMatchNoSync(in FrameCheckDetails ctx, out LeadSeed result) + where T : IEncounterSlot4 + { + if (IsSlotValidRegular(ctx, out uint seed)) + { result = new(seed, None); return true; } + + if (IsSlotValidSyncFail(ctx, out seed)) + { result = new(seed, SynchronizeFail); return true; } + if (IsSlotValidCuteCharmFail(ctx, out seed)) + { result = new(seed, CuteCharmFail); return true; } + if (IsSlotValidHustleVitalFail(ctx, out seed)) + { result = new(seed, PressureHustleSpiritFail); return true; } + if (IsSlotValidStaticMagnetFail(ctx, out seed)) + { result = new(seed, StaticMagnetFail); return true; } + // Intimidate/Keen Eye failing will result in no encounter. + + if (IsSlotValidStaticMagnet(ctx, out seed, out var lead)) + { result = new(seed, lead); return true; } + if (IsSlotValidHustleVital(ctx, out seed)) + { result = new(seed, PressureHustleSpirit); return true; } + if (IsSlotValidIntimidate(ctx, out seed)) + { result = new(seed, IntimidateKeenEyeFail); return true; } + + result = default; return false; + } + + private static bool IsSlotValidFrom1Skip(FrameCheckDetails ctx, out uint result) + where T : IEncounterSlot4 + { + if (!ctx.Encounter.IsFixedLevel()) + { + if (IsLevelValid(ctx.Encounter, ctx.LevelMin, ctx.LevelMax, ctx.Format, ctx.Prev2)) + { + if (IsSlotValid(ctx.Encounter, ctx.Prev3)) + { result = ctx.Seed4; return true; } + } + } + else // Not random level + { + if (IsSlotValid(ctx.Encounter, ctx.Prev2)) + { result = ctx.Seed3; return true; } + } + result = default; return false; + } + + private static bool IsSlotValidRegular(in FrameCheckDetails ctx, out uint result) + where T : IEncounterSlot4 + { + if (!ctx.Encounter.IsFixedLevel()) + { + if (IsLevelValid(ctx.Encounter, ctx.LevelMin, ctx.LevelMax, ctx.Format, ctx.Prev1)) + { + if (IsSlotValid(ctx.Encounter, ctx.Prev2)) + { result = ctx.Seed3; return true; } + } + } + else // Not random level + { + if (IsSlotValid(ctx.Encounter, ctx.Prev1)) + { result = ctx.Seed2; return true; } + } + result = default; return false; + } + + private static bool IsSlotValidHustleVital(in FrameCheckDetails ctx, out uint result) + where T : IEncounterSlot4 + { + if (IsHustleVitalFail(ctx.Prev1)) // should have triggered + { result = default; return false; } + + var expectLevel = ctx.Encounter.PressureLevel; + if (!IsOriginalLevelValid(ctx.LevelMin, ctx.LevelMax, ctx.Format, expectLevel)) + { result = default; return false; } + + if (!ctx.Encounter.IsFixedLevel()) + { + // Don't bother evaluating Prev1 for level, as it's always bumped to max after. + if (IsSlotValid(ctx.Encounter, ctx.Prev3)) + { result = ctx.Seed4; return true; } + } + else // Not random level + { + if (IsSlotValid(ctx.Encounter, ctx.Prev2)) + { result = ctx.Seed3; return true; } + } + result = default; return false; + } + + private static bool IsSlotValidStaticMagnet(in FrameCheckDetails ctx, out uint result, out LeadRequired lead) + where T : IEncounterSlot4 + { + lead = None; + if (!ctx.Encounter.IsFixedLevel()) + { + if (IsStaticMagnetFail(ctx.Prev3)) // should have triggered + { result = default; return false; } + + if (IsLevelValid(ctx.Encounter, ctx.LevelMin, ctx.LevelMax, ctx.Format, ctx.Prev1)) + { + if (ctx.Encounter.IsSlotValidStaticMagnet(ctx.Prev2, out lead)) + { result = ctx.Seed4; return true; } + } + } + else // Not random level + { + if (IsStaticMagnetFail(ctx.Prev3)) // should have triggered + { result = default; return false; } + + if (ctx.Encounter.IsSlotValidStaticMagnet(ctx.Prev1, out lead)) + { result = ctx.Seed3; return true; } + } + result = default; return false; + } + + private static bool IsSlotValidStaticMagnetFail(in FrameCheckDetails ctx, out uint result) + where T : IEncounterSlot4 + { + if (!ctx.Encounter.IsFixedLevel()) + { + if (IsStaticMagnetPass(ctx.Prev3)) // should have triggered + { result = default; return false; } + + if (IsLevelValid(ctx.Encounter, ctx.LevelMin, ctx.LevelMax, ctx.Format, ctx.Prev1)) + { + if (IsSlotValid(ctx.Encounter, ctx.Prev2)) + { result = ctx.Seed4; return true; } + } + } + else // Not random level + { + if (IsStaticMagnetPass(ctx.Prev2)) // should have triggered + { result = default; return false; } + + if (IsSlotValid(ctx.Encounter, ctx.Prev1)) + { result = ctx.Seed3; return true; } + } + result = default; return false; + } + + private static bool IsSlotValid(T enc, uint u16SlotRand) + where T : IEncounterSlot4 + { + if (enc.Type is HoneyTree) + return true; // pre-determined + var slot = SlotMethodJ.GetSlot(enc.Type, u16SlotRand); + return slot == enc.SlotNumber; + } + + private static bool IsLevelValid(T enc, byte min, byte max, byte format, uint u16LevelRand) where T : ILevelRange + { + var level = GetExpectedLevel(enc, u16LevelRand); + return IsOriginalLevelValid(min, max, format, level); + } + + private static bool IsOriginalLevelValid(byte min, byte max, byte format, uint level) + { + if (format == Format) + return level == min; // Met Level matches + return LevelRangeExtensions.IsLevelWithinRange((int)level, min, max); + } + + private static uint GetExpectedLevel(ILevelRange enc, uint u16LevelRand) + { + uint mod = 1u + enc.LevelMax - enc.LevelMin; + return (u16LevelRand % mod) + enc.LevelMin; + } + + /// + /// Gets the amount of reverses allowed prior to another satisfactory PID being generated. + /// + /// Seed that generates the expected resulting PID. + /// Nature of the resulting PID. + /// Count of reverses allowed for no specific lead (not cute charm). + public static int GetReversalWindow(uint seed, byte nature) + { + int ctr = 0; + // Seed is currently the second RNG call. Unroll to the first. + uint b = seed >> 16; + while (true) + { + var a = LCRNG.Prev16(ref seed); + var pid = b << 16 | a; + if (pid % 25 == nature) + break; + b = LCRNG.Prev16(ref seed); + ctr++; + } + return ctr; + } + + private static bool IsFishPossible(SlotType4 encType, ref uint seed) + { + var rodRate = GetRodRate(encType); + var u16 = seed >> 16; + var roll = u16 / 656; + if (roll < rodRate) + { + seed = LCRNG.Prev(seed); + return true; + } + return false; + } + + private static bool IsFishPossible(SlotType4 encType, ref uint seed, ref LeadRequired lead) + { + var rodRate = GetRodRate(encType); + var u16 = seed >> 16; + var roll = u16 / 656; + if (roll < rodRate) + { + seed = LCRNG.Prev(seed); + return true; + } + + if (lead != None) + return false; + + // Suction Cups / Sticky Hold + if (roll < rodRate * 2) + { + seed = LCRNG.Prev(seed); + lead = SuctionCups; + return true; + } + + return false; + } + + private static byte GetRodRate(SlotType4 type) => type switch + { + Old_Rod => 25, + Good_Rod => 50, + Super_Rod => 75, + _ => 0, + }; + + private static bool IsFishingRodType(this SlotType4 t) => t + is Old_Rod + or Good_Rod + or Super_Rod; +} diff --git a/PKHeX.Core/Legality/RNG/ClassicEra/Gen4/MethodK.cs b/PKHeX.Core/Legality/RNG/ClassicEra/Gen4/MethodK.cs new file mode 100644 index 000000000..b4f131d85 --- /dev/null +++ b/PKHeX.Core/Legality/RNG/ClassicEra/Gen4/MethodK.cs @@ -0,0 +1,583 @@ +using System; +using System.Runtime.CompilerServices; +using static PKHeX.Core.LeadRequired; +using static PKHeX.Core.SlotType4; + +namespace PKHeX.Core; + +/// +/// Method K logic used by RNG. +/// +public static class MethodK +{ + /// + /// High-level method to get the first possible encounter conditions. + /// + /// Encounter template. + /// Seed that immediately generates the PID. + /// Level range constraints for the capture, if known. + /// Current format (different from 4) + public static LeadSeed GetSeed(TEnc enc, uint seed, TEvo evo, byte format = Format) + where TEnc : IEncounterSlot4 + where TEvo : ILevelRange + => GetSeed(enc, seed, evo.LevelMin, evo.LevelMax, format); + + public static LeadSeed GetSeed(TEnc enc, uint seed, byte levelMin, byte levelMax, byte format = Format, int depth = 0) + where TEnc : IEncounterSlot4 + { + var pid = ClassicEraRNG.GetSequentialPID(seed); + var nature = (byte)(pid % 25); + + var frames = GetReversalWindow(seed, nature); + return GetOriginSeed(enc, seed, nature, frames, levelMin, levelMax, format, depth); + } + + /// + public static LeadSeed GetSeed(TEnc enc, uint seed) + where TEnc : IEncounterSlot4 => GetSeed(enc, seed, enc); + + /// + /// Count of reverses allowed for no specific lead (not cute charm). + public static int GetReversalWindow(uint seed, byte nature) => MethodJ.GetReversalWindow(seed, nature); + + // Summary of Random Determinations: + // Nature: rand() % 25 == nature + // Cute Charm: rand() % 3 != 0; (2/3 odds) + // Sync: rand() & 1 == 0; (50% odds) + // Static/Magnet Pull: rand() & 1 == 0; + // Pressure/Hustle/Vital Spirit: rand() & 1 == 1; + // Intimidate/Keen Eye: rand() & 1 == 1; -- 0 will reject the encounter. + + private const byte Format = 4; + + private static bool IsCuteCharmFail(uint rand) => (rand % 3) == 0; // 1/3 odds + private static bool IsCuteCharmPass(uint rand) => (rand % 3) != 0; // 2/3 odds + + //private static bool IsSyncFail(uint rand) => (rand & 1) != 0; + private static bool IsSyncPass(uint rand) => (rand & 1) == 0; + + private static bool IsStaticMagnetFail(uint rand) => (rand & 1) != 0; + private static bool IsStaticMagnetPass(uint rand) => (rand & 1) == 0; + + private static bool IsHustleVitalFail(uint rand) => (rand & 1) != 1; + private static bool IsHustleVitalPass(uint rand) => (rand & 1) == 1; + + //private static bool IsIntimidateKeenEyeFail(uint rand) => (rand & 1) != 1; + private static bool IsIntimidateKeenEyePass(uint rand) => (rand & 1) == 1; + + private static uint GetNature(uint rand) => rand % 25; + + /// + /// Gets the first possible origin seed and lead for the input encounter & constraints. + /// + public static LeadSeed GetOriginSeed(T enc, uint seed, byte nature, int reverseCount, byte levelMin, byte levelMax, byte format = Format, int depth = 0) + where T : IEncounterSlot4 + { + LeadSeed prefer = default; + while (true) + { + if (TryGetMatch(enc, levelMin, levelMax, seed, nature, format, out var result, depth)) + { + if (result.IsNoRequirement()) + return result; + if (result.IsBetterThan(prefer)) + prefer = result; + } + if (reverseCount == 0) + return prefer; + reverseCount--; + seed = LCRNG.Prev2(seed); + } + } + + private static bool CheckEncounterActivation(T enc, ref LeadSeed result) + where T : IEncounterSlot4 + { + if (enc.Type.IsFishingRodType()) + return IsFishPossible(enc.Type, ref result.Seed, ref result.Lead); + if (enc.Type is Rock_Smash) + return IsRockSmashPossible(enc.AreaRate, ref result.Seed, ref result.Lead); + + // Ability & Sweet Scent deadlock for BCC: + if (enc.Type is BugContest && !result.Lead.IsAbleToSweetScent()) + return IsBugContestPossibleDeadlock(enc.AreaRate, ref result.Seed); + + // Can sweet scent trigger. + return true; + } + + private static bool IsAbleToSweetScent(this LeadRequired lead) => lead + is None // Pretty much anything grass. + or IntimidateKeenEyeFail // Masquerain & Mawile + or PressureHustleSpirit or PressureHustleSpiritFail // Vespiquen + // Synchronize: None + // Cute Charm: None + // Static/Magnet Pull: None + ; + + private static bool CheckEncounterActivationCuteCharm(T enc, ref uint result) where T : IEncounterSlot4 + { + // Lead is required to be Cute Charm. + if (enc.Type.IsFishingRodType()) + return IsFishPossible(enc.Type, ref result); + if (enc.Type is Rock_Smash) + return IsRockSmashPossible(enc.AreaRate, ref result); + + // Ability & Sweet Scent deadlock for BCC: + if (enc.Type is BugContest) // No species with Sweet Scent can have Cute Charm. + return IsBugContestPossibleDeadlock(enc.AreaRate, ref result); + + // Can sweet scent trigger. + return true; + } + + /// + /// Attempts to find a matching seed for the given encounter and constraints for Cute Charm buffered PIDs. + /// + public static bool TryGetMatchCuteCharm(T enc, ReadOnlySpan seeds, byte nature, byte levelMin, byte levelMax, out uint result) + where T : IEncounterSlot4 + { + foreach (uint seed in seeds) + { + var p0 = seed >> 16; // 0 + var reg = GetNature(p0) == nature; + if (!reg) + continue; + var ctx = new FrameCheckDetails(enc, seed, levelMin, levelMax, 4); + if (!TryGetMatchCuteCharm(ctx, out result)) + continue; + if (CheckEncounterActivationCuteCharm(enc, ref result)) + return true; + } + result = default; return false; + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static bool TryGetMatch(T enc, byte levelMin, byte levelMax, uint seed, byte nature, byte format, out LeadSeed result, int depth = 0) + where T : IEncounterSlot4 + { + var p0 = seed >> 16; // 0 + var reg = GetNature(p0) == nature; + if (reg) + { + var ctx = new FrameCheckDetails(enc, seed, levelMin, levelMax, format); + if (TryGetMatchNoSync(ctx, out result) && CheckEncounterActivation(enc, ref result)) + return true; + if (depth != 4 && enc is EncounterSlot4 s && (s.IsBugContest || s.IsSafariHGSS)) + return Recurse4x(enc, levelMin, levelMax, seed, nature, format, out result, ++depth); + } + else if (IsSyncPass(p0)) + { + var ctx = new FrameCheckDetails(enc, seed, levelMin, levelMax, format); + if (IsSlotValidRegular(ctx, out seed)) + { + result = new(seed, Synchronize); + if (CheckEncounterActivation(enc, ref result)) + return true; + } + if (depth != 4 && enc is EncounterSlot4 s && (s.IsBugContest || s.IsSafariHGSS)) + return Recurse4x(enc, levelMin, levelMax, seed, nature, format, out result, ++depth); + } + result = default; + return false; + } + + private const int MaxSafariContest = 4; + + private static bool Recurse4x(T enc, byte levelMin, byte levelMax, uint seed, byte nature, byte format, + out LeadSeed result, int depth) + where T : IEncounterSlot4 + { + // When generating Pokémon's IVs, the game tries to give at least one flawless IV. + // The game will roll the {nature,PID/IV} up to 4 times if none of the IVs are at 31 (total of 3 re-rolls) + result = default; + + // Use the depth to keep track of how many we have already burned. + // First entry to this method will be 1/4 burned (final result). + if (depth == MaxSafariContest) + return false; + + // Check if the previous 4 frames were a 31-IV Pokémon. If so, it couldn't have been re-rolled from. + // If it was, we can adjust our parameters and try the entire search again (expensive!) + + // First we need to determine how far back we can permit the previous skipped encounter to be originating from. + // Our only requirement is that the nature PID we currently have not been generated. + // This is the same "solved" problem as the regular reversal window. + + // Each loop we have a ~18.75% chance to hit a >=1 31 IV setup and return false. + // On average, we look back 5-6 times. + bool breakNext = false; + while (true) + { + var iv2 = seed >> 16; + if (IsAny31(iv2)) + return false; + + var iv1 = LCRNG.Prev16(ref seed); + if (IsAny31(iv1)) + return false; + + // Since we're looking backwards and doing recursion in the same method, we need to ensure we don't exceed our previous nature window. + var sanityNature = ClassicEraRNG.GetSequentialPID(seed) % 25; + if (sanityNature == nature) + breakNext = true; + + // Cool, the skipped Pokémon was not 31-IV. Let's try again. + // The skipped Pokémon probably had a different nature, so we need to use that value instead. + // We basically need to repeat the entire top-level check with slightly adjusted parameters. + var origin = LCRNG.Prev2(seed); + + // We need to double-check that this skipped PID/IV could have been landed on via the nature/sync check. + // The innate recursion will return true if the skipped frame could have been landed on, or if an even-more previous skipped was landed. + result = GetSeed(enc, origin, levelMin, levelMax, format, depth); + if (result.IsValid()) + return true; + + // If the forwards window no longer lets us land on the frame we entered this method from, the window is exhausted. + // We need to do at least one recursion as the 4 calls we look backwards from will hide a double-nature PID/frame pair. + if (breakNext) + return false; // Window exhausted, this nature would have been chosen instead of the frame we entered this method from. + } + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static bool IsAny31(uint iv16) + => IsLow5Bits31(iv16) + || IsLow5Bits31(iv16 >> 5) + || IsLow5Bits31(iv16 >> 10); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static bool IsLow5Bits31(uint iv16) => (iv16 & 0x1F) == 0x1F; + + private static bool TryGetMatchCuteCharm(in FrameCheckDetails ctx, out uint result) + where T : IEncounterSlot4 + { + if (IsCuteCharmFail(ctx.Prev1)) + { result = default; return false; } + + return IsSlotValidFrom1Skip(ctx, out result); + } + + private static bool IsSlotValidCuteCharmFail(in FrameCheckDetails ctx, out uint result) + where T : IEncounterSlot4 + { + if (IsCuteCharmPass(ctx.Prev1)) // should have triggered + { result = default; return false; } + + return IsSlotValidFrom1Skip(ctx, out result); + } + + private static bool IsSlotValidSyncFail(in FrameCheckDetails ctx, out uint result) + where T : IEncounterSlot4 + { + if (IsSyncPass(ctx.Prev1)) // should have triggered + { result = default; return false; } + + return IsSlotValidFrom1Skip(ctx, out result); + } + + private static bool IsSlotValidIntimidate(in FrameCheckDetails ctx, out uint result) + where T : IEncounterSlot4 + { + if (IsIntimidateKeenEyePass(ctx.Prev1)) // encounter routine aborted + { result = default; return false; } + + return IsSlotValidFrom1Skip(ctx, out result); + } + + private static bool IsSlotValidHustleVitalFail(in FrameCheckDetails ctx, out uint result) + where T : IEncounterSlot4 + { + if (IsHustleVitalPass(ctx.Prev1)) // should have triggered + { result = default; return false; } + + return IsSlotValidFrom1Skip(ctx, out result); + } + + private static bool TryGetMatchNoSync(in FrameCheckDetails ctx, out LeadSeed result) + where T : IEncounterSlot4 + { + if (IsSlotValidRegular(ctx, out uint seed)) + { result = new(seed, None); return true; } + + if (IsSlotValidSyncFail(ctx, out seed)) + { result = new(seed, SynchronizeFail); return true; } + if (IsSlotValidCuteCharmFail(ctx, out seed)) + { result = new(seed, CuteCharmFail); return true; } + if (IsSlotValidHustleVitalFail(ctx, out seed)) + { result = new(seed, PressureHustleSpiritFail); return true; } + if (IsSlotValidStaticMagnetFail(ctx, out seed)) + { result = new(seed, StaticMagnetFail); return true; } + // Intimidate/Keen Eye failing will result in no encounter. + + if (IsSlotValidStaticMagnet(ctx, out seed, out var sm)) + { result = new(seed, sm); return true; } + if (IsSlotValidHustleVital(ctx, out seed)) + { result = new(seed, PressureHustleSpirit); return true; } + if (IsSlotValidIntimidate(ctx, out seed)) + { result = new(seed, IntimidateKeenEyeFail); return true; } + + result = default; return false; + } + + private static bool IsSlotValidFrom1Skip(FrameCheckDetails ctx, out uint result) + where T : IEncounterSlot4 + { + if (!ctx.Encounter.IsFixedLevel()) + { + if (IsLevelValid(ctx.Encounter, ctx.LevelMin, ctx.LevelMax, ctx.Format, ctx.Prev2)) + { + if (IsSlotValid(ctx.Encounter, ctx.Prev3)) + { result = ctx.Seed4; return true; } + } + } + else // Not random level + { + if (IsSlotValid(ctx.Encounter, ctx.Prev2)) + { result = ctx.Seed3; return true; } + } + result = default; return false; + } + + private static bool IsSlotValidRegular(in FrameCheckDetails ctx, out uint result) + where T : IEncounterSlot4 + { + if (!ctx.Encounter.IsFixedLevel()) + { + if (IsLevelValid(ctx.Encounter, ctx.LevelMin, ctx.LevelMax, ctx.Format, ctx.Prev1)) + { + if (IsSlotValid(ctx.Encounter, ctx.Prev2)) + { result = ctx.Seed3; return true; } + } + } + else // Not random level + { + if (IsSlotValid(ctx.Encounter, ctx.Prev1)) + { result = ctx.Seed2; return true; } + } + result = default; return false; + } + + private static bool IsSlotValidHustleVital(in FrameCheckDetails ctx, out uint result) + where T : IEncounterSlot4 + { + if (IsHustleVitalFail(ctx.Prev1)) // should have triggered + { result = default; return false; } + + var expectLevel = ctx.Encounter.PressureLevel; + if (!IsOriginalLevelValid(ctx.LevelMin, ctx.LevelMax, ctx.Format, expectLevel)) + { result = default; return false; } + + if (!ctx.Encounter.IsFixedLevel()) + { + // Don't bother evaluating Prev1 for level, as it's always bumped to max after. + if (IsSlotValid(ctx.Encounter, ctx.Prev3)) + { result = ctx.Seed4; return true; } + } + else // Not random level + { + if (IsSlotValid(ctx.Encounter, ctx.Prev2)) + { result = ctx.Seed3; return true; } + } + result = default; return false; + } + + private static bool IsSlotValidStaticMagnet(in FrameCheckDetails ctx, out uint result, out LeadRequired lead) + where T : IEncounterSlot4 + { + // Static or Magnet Pull + // -3 SlotProc (Random % 2 == 0) + // -2 ESV (select slot) + // -1 Level + // 0 Nature + lead = None; + if (!ctx.Encounter.IsFixedLevel()) + { + if (IsStaticMagnetFail(ctx.Prev3)) // should have triggered + { result = default; return false; } + + if (IsLevelValid(ctx.Encounter, ctx.LevelMin, ctx.LevelMax, ctx.Format, ctx.Prev1)) + { + if (ctx.Encounter.IsSlotValidStaticMagnet(ctx.Prev2, out lead)) + { result = ctx.Seed4; return true; } + } + } + else // Not random level + { + if (IsStaticMagnetFail(ctx.Prev2)) // should have triggered + { result = default; return false; } + + if (ctx.Encounter.IsSlotValidStaticMagnet(ctx.Prev1, out lead)) + { result = ctx.Seed3; return true; } + } + result = default; return false; + } + + private static bool IsSlotValidStaticMagnetFail(in FrameCheckDetails ctx, out uint result) + where T : IEncounterSlot4 + { + if (!ctx.Encounter.IsFixedLevel()) + { + if (IsStaticMagnetPass(ctx.Prev3)) // should have triggered + { result = default; return false; } + + if (IsLevelValid(ctx.Encounter, ctx.LevelMin, ctx.LevelMax, ctx.Format, ctx.Prev1)) + { + if (IsSlotValid(ctx.Encounter, ctx.Prev2)) + { result = ctx.Seed4; return true; } + } + } + else // Not random level + { + if (IsStaticMagnetPass(ctx.Prev2)) // should have triggered + { result = default; return false; } + + if (IsSlotValid(ctx.Encounter, ctx.Prev1)) + { result = ctx.Seed2; return true; } + } + result = default; return false; + } + + private static bool IsSlotValid(T enc, uint u16SlotRand) + where T : IEncounterSlot4 + { + var slot = SlotMethodK.GetSlot(enc.Type, u16SlotRand); + return slot == enc.SlotNumber; + } + + private static bool IsLevelValid(T enc, byte min, byte max, byte format, uint u16LevelRand) where T : ILevelRange + { + var level = GetExpectedLevel(enc, u16LevelRand); + return IsOriginalLevelValid(min, max, format, level); + } + + private static bool IsOriginalLevelValid(byte min, byte max, byte format, uint level) + { + if (format == Format) + return level == min; // Met Level matches + return LevelRangeExtensions.IsLevelWithinRange((int)level, min, max); + } + + private static uint GetExpectedLevel(ILevelRange enc, uint u16LevelRand) + { + uint mod = 1u + enc.LevelMax - enc.LevelMin; + return (u16LevelRand % mod) + enc.LevelMin; + } + + private static bool IsBugContestPossibleDeadlock(uint areaRate, ref uint result) + { + // BCC only allows one Pokémon to be in the party. + // Specific lead abilities can learn Sweet Scent, while others cannot. + // The only entry into this method requires an ability that has no species available with Sweet Scent. + // Therefore, without Sweet Scent, we need to trigger via turning/walking. + // With an area rate of 25, this arrangement will succeed 37% of the time. + + // The game checks 2 random calls to trigger the encounter: movement -> rate -> generate. + // HG/SS has an underflow error (via radio) which can pass the first rand call for movement. + // Only need to check the second call for rate. + // Rate can be improved by 50% if the White Flute is used. + // Other abilities can also affect the rate, but we can't use them with our current lead. + var rate = areaRate + (areaRate >> 1); // +50% White Flute + var rand = (result >> 16); + var roll = rand % 100; + if (roll >= rate) + return false; + + // Skip backwards before the two calls. Valid encounter seed found. + result = LCRNG.Prev2(result); + return true; + } + + private static bool IsFishPossible(SlotType4 encType, ref uint seed, ref LeadRequired lead) + { + var rodRate = GetRodRate(encType); + var u16 = seed >> 16; + var roll = u16 % 100; + if (roll < rodRate) + { + seed = LCRNG.Prev(seed); + return true; + } + + if (lead != None) + return false; + + // Suction Cups / Sticky Hold + if (roll < rodRate * 2) + { + seed = LCRNG.Prev(seed); + lead = SuctionCups; + return true; + } + + return false; + } + + private static bool IsFishPossible(SlotType4 encType, ref uint seed) + { + var rate = GetRodRate(encType); + var u16 = seed >> 16; + var roll = u16 % 100; + if (roll < rate) + { + seed = LCRNG.Prev(seed); + return true; + } + return false; + } + + private static bool IsRockSmashPossible(byte areaRate, ref uint seed) + { + var u16 = seed >> 16; + var roll = u16 % 100; + if (roll < areaRate) + { + seed = LCRNG.Prev(seed); + return true; + } + return false; + } + + private static bool IsRockSmashPossible(byte areaRate, ref uint seed, ref LeadRequired lead) + { + // No flute boost. + var u16 = seed >> 16; + var roll = u16 % 100; + if (roll < areaRate) + { + seed = LCRNG.Prev(seed); + return true; + } + if (lead != None) + return false; + if (roll < areaRate * 2u) + { + seed = LCRNG.Prev(seed); + lead = Illuminate; + return true; + } + return false; + } + + private static byte GetRodRate(SlotType4 type) => type switch + { + Old_Rod => 25, + Good_Rod => 50, + Super_Rod => 75, + + Safari_Old_Rod => 25, + Safari_Good_Rod => 50, + Safari_Super_Rod => 75, + + _ => 0, + }; + + private static bool IsFishingRodType(this SlotType4 t) => t + is Old_Rod + or Good_Rod + or Super_Rod + + or Safari_Old_Rod + or Safari_Good_Rod + or Safari_Super_Rod; +} diff --git a/PKHeX.Core/Legality/RNG/Methods/Gen4/PokewalkerRNG.cs b/PKHeX.Core/Legality/RNG/ClassicEra/Gen4/PokewalkerRNG.cs similarity index 98% rename from PKHeX.Core/Legality/RNG/Methods/Gen4/PokewalkerRNG.cs rename to PKHeX.Core/Legality/RNG/ClassicEra/Gen4/PokewalkerRNG.cs index ad579c88d..544e6c4d0 100644 --- a/PKHeX.Core/Legality/RNG/Methods/Gen4/PokewalkerRNG.cs +++ b/PKHeX.Core/Legality/RNG/ClassicEra/Gen4/PokewalkerRNG.cs @@ -178,8 +178,8 @@ public static ushort GetSpecies(PokewalkerCourse4 course, int group, int rare) return span[(group * 2) + rare]; } - /// - public static uint GetPID(uint id32, uint nature, int gender, byte genderRatio) => + /// + public static uint GetPID(uint id32, uint nature, byte gender, byte genderRatio) => GetPID((ushort)id32, (ushort)(id32 >> 16), nature, gender, genderRatio); /// @@ -191,7 +191,7 @@ public static ushort GetSpecies(PokewalkerCourse4 course, int group, int rare) /// Gender to set PID to. /// Gender ratio of the species. /// PID for the given parameters. - public static uint GetPID(ushort TID16, ushort SID16, uint nature, int gender, byte genderRatio) + public static uint GetPID(ushort TID16, ushort SID16, uint nature, byte gender, byte genderRatio) { if (nature >= 24) nature = 0; diff --git a/PKHeX.Core/Legality/RNG/ClassicEra/Gen4/RuinsOfAlph4.cs b/PKHeX.Core/Legality/RNG/ClassicEra/Gen4/RuinsOfAlph4.cs new file mode 100644 index 000000000..59f4ae872 --- /dev/null +++ b/PKHeX.Core/Legality/RNG/ClassicEra/Gen4/RuinsOfAlph4.cs @@ -0,0 +1,117 @@ +using System; + +namespace PKHeX.Core; + +public static class RuinsOfAlph4 +{ + /// + /// Checks if the requested is valid for the given seed. + /// + public static bool IsUnownFormValid(PKM pk, byte form) + { + if (!MethodFinder.GetLCRNGMethod1Match(pk, out var seed)) + return true; // invalid anyway, don't care. + + // ABCD|E(Item)|F(Form) determination + var f = LCRNG.Next6(seed); + return IsFormValid(form, f); + } + + /// + /// Checks if the requested is valid for the given seed. + /// + /// Form to validate + /// RNG state that determines the form + /// + public static bool IsFormValid(byte form, uint seed) + { + if (form >= 26) // Entrance + return form == GetEntranceForm(seed); + + var u16 = seed >> 16; + var radio = (u16 % 100) < 50; + if (radio) + { + if (IsFormValidRadio(form)) + return true; + // Try without radio. + if (IsFormValidInterior(form, u16)) + return true; + } + else + { + // Try without radio. + if (IsFormValidInterior(form, u16)) + return true; + var next = LCRNG.Next16(ref seed); + return IsFormValidInterior(form, next); + } + return false; + } + + /// + /// Gets one of the two entry area forms (!?) + /// + /// RNG state that determines which form is picked. + /// Form ID + public static byte GetEntranceForm(uint seed) => (byte)(26 + ((seed >> 16) & 1)); + + // give a random not-yet-seen form + // this can be anything depending on the player's SaveFile progress + private static bool IsFormValidRadio(byte _) => true; + + private const int MaxDepth = 4; + + private static bool IsFormValidInterior(byte form, uint rand) + { + // Eager-check the full set of forms, as most players will have unlocked all forms. + var full = rand % 26; + if (full == form) + return true; + + // Let's have some fun: permute the combinations of unlocked forms & resulting form choice-s. + Span forms = stackalloc byte[26]; // A-Z + return Recurse(forms, form, rand, 0); + } + + private static bool Recurse(in Span forms, in byte form, in uint rand, int count, int depth = 0) + { + if (depth == MaxDepth) + return false; + + // Unlock the forms for this depth-set. Retain the count to keep both "ranges" available. + // Try adding the forms for the entire depth and checking if it's valid. + // Most players will unlock all forms anyway, so we go for that eager case. + int newCount = AddForms(forms, count, depth); + if (Recurse(forms, form, rand, newCount, depth + 1)) + return true; + + // Try checking without the added forms. No need to clear what we just added. + // Check this case before the nothing-else case, as players aren't likely to be missing many sets. + if (Recurse(forms, form, rand, count, depth + 1)) + return true; + + // Try with the forms we added in this stack frame. + // Don't need to check the not-added case as earlier depths will check the same set when needed. + var roll = rand % newCount; + var expect = forms[(int)roll]; + return expect == form; + } + + private static int AddForms(Span forms, int count, int depth) + { + var (start, end) = GetForms(depth); + for (var i = start; i <= end; i++) + forms[count++] = i; + return count; + } + + private static (byte Start, byte End) GetForms(int index) => index switch + { + 0 => (00, 09), // A-J [00,09] = 10 + 1 => (10, 16), // K-Q [10,16] = 7 + 2 => (17, 21), // R-V [17,21] = 5 + 3 => (22, 25), // W-Z [22,25] = 4 + _ => throw new ArgumentOutOfRangeException(nameof(index)), + }; +} diff --git a/PKHeX.Core/Legality/RNG/ClassicEra/Gen4/SlotMethodJ.cs b/PKHeX.Core/Legality/RNG/ClassicEra/Gen4/SlotMethodJ.cs new file mode 100644 index 000000000..850289658 --- /dev/null +++ b/PKHeX.Core/Legality/RNG/ClassicEra/Gen4/SlotMethodJ.cs @@ -0,0 +1,57 @@ +using System.Runtime.CompilerServices; +using static PKHeX.Core.SlotType4; + +namespace PKHeX.Core; + +/// +/// Encounter slot determination for . +/// +public static class SlotMethodJ +{ + private const byte Invalid = byte.MaxValue; // all slots are [0,X], unsigned. This will always result in a non-match. + + /// + /// Gets the from the raw 16bit seed half. + /// + public static int GetSlot(SlotType4 type, uint rand) + { + uint ESV = rand / 656; + return type switch + { + Old_Rod or Surf => GetSurf(ESV), + Good_Rod or Super_Rod => GetSuperRod(ESV), + HoneyTree => 0, + _ => GetRegular(ESV), + }; + } + + /// + /// Calculates the encounter slot index based on the roll for a Gen4 Wild encounter. + /// + /// [0,100) + /// Same as + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static byte GetRegular(uint roll) => SlotMethodH.GetRegular(roll); + + /// + /// Calculates the encounter slot index based on the roll for a Gen4 Surf encounter. + /// + /// [0,100) + /// Same as + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static byte GetSurf(uint roll) => SlotMethodH.GetSurf(roll); + + /// + /// Calculates the encounter slot index based on the roll for a D/P/Pt Super Rod encounter. + /// + /// [0,100) + public static int GetSuperRod(uint roll) => roll switch + { + < 40 => 0, // 00,39 (40%) + < 80 => 1, // 40,79 (40%) + < 95 => 2, // 80,94 (15%) + < 99 => 3, // 95,98 ( 4%) + 99 => 4, // 99 ( 1%) + _ => Invalid, + }; +} diff --git a/PKHeX.Core/Legality/RNG/ClassicEra/Gen4/SlotMethodK.cs b/PKHeX.Core/Legality/RNG/ClassicEra/Gen4/SlotMethodK.cs new file mode 100644 index 000000000..2d5c2d474 --- /dev/null +++ b/PKHeX.Core/Legality/RNG/ClassicEra/Gen4/SlotMethodK.cs @@ -0,0 +1,109 @@ +using System.Runtime.CompilerServices; +using static PKHeX.Core.SlotType4; + +namespace PKHeX.Core; + +/// +/// Encounter slot determination for . +/// +public static class SlotMethodK +{ + private const byte Invalid = byte.MaxValue; // all slots are [0,X], unsigned. This will always result in a non-match. + + /// + /// Gets the from the raw 16bit seed half. + /// + public static byte GetSlot(SlotType4 type, uint rand) => type switch + { + Grass => GetRegular(rand % 100), + Surf => GetSurf(rand % 100), + Old_Rod or Good_Rod or Super_Rod => GetSuperRod(rand % 100), + Rock_Smash => GetRockSmash(rand % 100), + Headbutt or HeadbuttSpecial => GetHeadbutt(rand % 100), + BugContest => GetBugCatchingContest(rand % 100), + // Honey Tree shouldn't enter here. + Safari_Grass or Safari_Surf or + Safari_Old_Rod or Safari_Good_Rod or Safari_Super_Rod => GetSafari(rand % 10), + _ => Invalid, + }; + + /// + /// Calculates the encounter slot index based on the roll for a Gen4 Wild encounter. + /// + /// [0,100) + /// Same as + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static byte GetRegular(uint roll) => SlotMethodH.GetRegular(roll); + + /// + /// Calculates the encounter slot index based on the roll for a Gen4 Surf encounter. + /// + /// [0,100) + /// Same as + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static byte GetSurf(uint roll) => SlotMethodH.GetSurf(roll); + + /// + /// Calculates the encounter slot index based on the roll for a Gen4 Rock Smash encounter. + /// + /// [0,100) + public static byte GetRockSmash(uint roll) => roll >= 80 ? (byte)1 : (byte)0; + + /// + /// Calculates the encounter slot index based on the roll for a HG/SS Super Rod encounter. + /// + /// [0,100) + public static byte GetSuperRod(uint roll) => roll switch + { + < 40 => 0, // 00,39 (40%) + < 70 => 1, // 40,69 (30%) + < 85 => 2, // 70,84 (15%) + < 95 => 3, // 85,94 (10%) + 99 => 4, // 95 ( 5%) + _ => Invalid, + }; + + /// + /// Calculates the encounter slot index based on the roll for a Safari Zone encounter. + /// + /// [0,9] raw roll + /// + public static byte GetSafari(uint roll) => (byte)roll; + + /// + /// Calculates the encounter slot index based on the roll for a Bug Catching Contest encounter. + /// + /// [0,100) + /// + /// Slot indexes are reversed for the Bug Catching Contest. + /// + public static byte GetBugCatchingContest(uint roll) => roll switch + { + < 05 => 9, // 00,04 ( 5%) + < 10 => 8, // 05,09 ( 5%) + < 15 => 7, // 10,14 ( 5%) + < 20 => 6, // 15,19 ( 5%) + < 30 => 5, // 20,29 (10%) + < 40 => 4, // 30,39 (10%) + < 50 => 3, // 40,49 (10%) + < 60 => 2, // 50,59 (10%) + < 80 => 1, // 60,79 (20%) + <100 => 0, // 80,99 (20%) + _ => Invalid, + }; + + /// + /// Calculates the encounter slot index based on the roll for a HG/SS Headbutt encounter. + /// + /// [0,100) + public static byte GetHeadbutt(uint roll) => roll switch + { + < 50 => 0, // 00,49 (50%) + < 65 => 1, // 50,64 (15%) + < 80 => 2, // 65,79 (15%) + < 90 => 3, // 80,89 (10%) + < 95 => 4, // 90,94 ( 5%) + <100 => 5, // 95,99 ( 5%) + _ => Invalid, + }; +} diff --git a/PKHeX.Core/Legality/RNG/ClassicEra/Gen4/SolaceonRuins4.cs b/PKHeX.Core/Legality/RNG/ClassicEra/Gen4/SolaceonRuins4.cs new file mode 100644 index 000000000..c77877a7e --- /dev/null +++ b/PKHeX.Core/Legality/RNG/ClassicEra/Gen4/SolaceonRuins4.cs @@ -0,0 +1,48 @@ +using System; + +namespace PKHeX.Core; + +public static class SolaceonRuins4 +{ + /// + /// Checks if the requested is valid for the given seed. + /// + public static bool IsUnownFormValid(PKM pk, byte form) + { + if (IsSingleFormRoomUnown(form)) + return true; // FRIEND: Specific rooms with only one form. + + // Only forms beyond here are the !? and Dead End rooms. + + if (!MethodFinder.GetLCRNGMethod1Match(pk, out var seed)) + return true; // invalid anyway, don't care. + + var f = LCRNG.Next6(seed) >> 16; + var expect = GetUnownForm(f, form); + return expect == form; + } + + /// + /// Unown forms available in every Dead End room. + /// + private static ReadOnlySpan Unown0 => + [ + 0, 1, 2, + 6, 7, + 9, 10, 11, 12, + 14, 15, 16, + 18, 19, 20, 21, 22, 23, 24, 25 + ]; + + private static byte GetUnownForm(uint rand, byte prefer) + { + if (prefer >= 26) // Area from Maniac Tunnel + return (byte)(26 + (rand & 1)); + return Unown0[(int)(rand % Unown0.Length)]; + } + + // Forms that appear with others in the same room, and are not 100% guaranteed. + // 100% Guaranteed Forms are F,R,I,E,N,D + private const uint FormRandomUnown = 0b1111111111011101111011000111u; + public static bool IsSingleFormRoomUnown(byte actual) => (FormRandomUnown & (1 << actual)) == 0; +} diff --git a/PKHeX.Core/Legality/RNG/ClassicEra/LeadEncounter.cs b/PKHeX.Core/Legality/RNG/ClassicEra/LeadEncounter.cs new file mode 100644 index 000000000..d2c11fd1d --- /dev/null +++ b/PKHeX.Core/Legality/RNG/ClassicEra/LeadEncounter.cs @@ -0,0 +1,28 @@ +using System.Collections.Generic; + +namespace PKHeX.Core; + +public readonly struct LeadEncounterQueue +{ + public readonly List> List = new(0); + public LeadEncounterQueue() { } + + public void Insert(LeadSeed lead, TEnc encounter) => Insert(new(lead, encounter)); + + public void Insert(LeadEncounter toInsert) + { + for (int i = 0; i < List.Count; i++) + { + if (!toInsert.IsBetterThan(List[i])) + continue; + List.Insert(i, toInsert); + return; + } + List.Add(toInsert); + } +} + +public readonly record struct LeadEncounter(LeadSeed Lead, T Encounter) +{ + public bool IsBetterThan(LeadEncounter other) => Lead.IsBetterThan(other.Lead); +} diff --git a/PKHeX.Core/Legality/RNG/ClassicEra/LeadFinder.cs b/PKHeX.Core/Legality/RNG/ClassicEra/LeadFinder.cs new file mode 100644 index 000000000..cb1b81902 --- /dev/null +++ b/PKHeX.Core/Legality/RNG/ClassicEra/LeadFinder.cs @@ -0,0 +1,111 @@ +using System; +using System.Diagnostics.CodeAnalysis; +using static PKHeX.Core.PIDType; + +namespace PKHeX.Core; + +/// +/// High-level wrappers for the Golden Era of RNG manipulation. +/// +public static class LeadFinder +{ + /// + public static LeadSeed GetLeadInfo3(TEnc enc, in PIDIV pv, TEvo evo, bool emerald, byte gender, byte format) + where TEnc : IEncounterSlot3 + where TEvo : ILevelRange + { + var type = pv.Type; + if (type.IsClassicMethod()) + return MethodH.GetSeed(enc, pv.OriginSeed, evo, emerald, gender, format); + return default; + } + + /// + /// Gets the lead information for the given and . + /// + /// Entity to check + /// Encounter slot + /// PID/IV information + /// Level range + /// If found, origin seed and lead conditions. + public static LeadSeed GetLeadInfo4(PKM pk, TEnc enc, in PIDIV pv, TEvo evo) + where TEnc : IEncounterSlot4 + where TEvo : ILevelRange + { + var type = pv.Type; + if (type is Method_1) + { + if (TryGetLeadInfo4(enc, evo, pk.HGSS, pv.OriginSeed, pk.Format, out var result)) + return result; + + // There's a very-very rare chance that the PID-IV can be from Cute Charm too. + // It may match Method 1, but since we early-return, we don't check for Cute Charm. + // So, we check for Cute Charm here and try checking Cute Charm frames if it matches. + if (MethodFinder.IsCuteCharm(pk, pk.EncryptionConstant)) + type = CuteCharm; + } + if (type is CuteCharm) + { + // Needs to fetch all possible seeds for IVs. + // Kinda sucks to do this every encounter, but it's relatively rare -- still good enough perf. + var result = TryGetMatchCuteCharm4(enc, pk, evo, out var seed); + if (result) + return new(seed, LeadRequired.CuteCharm); + } + return default; + } + + /// + /// Tries to get the lead information for a Generation 4 encounter. + /// + /// If found, origin seed and lead conditions. + public static bool TryGetLeadInfo4(TEnc enc, TEvo evo, bool hgss, uint seed, byte format, out LeadSeed result) + where TEnc : IEncounterSlot4 + where TEvo : ILevelRange + { + result = hgss + ? MethodK.GetSeed(enc, seed, evo, format) + : MethodJ.GetSeed(enc, seed, evo, format); + return result.IsValid(); + } + + private static bool TryGetMatchCuteCharm4(TEnc enc, PKM pk, TEvo evo, out uint seed) + where TEnc : IEncounterSlot4 + where TEvo : ILevelRange + { + // Can be one of many seeds. + Span seeds = stackalloc uint[LCRNG.MaxCountSeedsIV]; + var ctr = GetSeedsIVs(pk, seeds); + seeds = seeds[..ctr]; + + var nature = (byte)(pk.EncryptionConstant % 25); + var (min, max) = (evo.LevelMin, evo.LevelMax); + return pk.HGSS + ? MethodK.TryGetMatchCuteCharm(enc, seeds, nature, min, max, out seed) + : MethodJ.TryGetMatchCuteCharm(enc, seeds, nature, min, max, out seed); + } + + private static int GetSeedsIVs(PKM pk, Span seeds) + { + var hp = (uint)pk.IV_HP; + var atk = (uint)pk.IV_ATK; + var def = (uint)pk.IV_DEF; + var spa = (uint)pk.IV_SPA; + var spd = (uint)pk.IV_SPD; + var spe = (uint)pk.IV_SPE; + return LCRNGReversal.GetSeedsIVs(seeds, hp, atk, def, spa, spd, spe); + } + + public static EvoCriteria GetLevelConstraint(PKM pk, ReadOnlySpan chain, TEnc enc, [ConstantExpected] byte generation) + where TEnc : IEncounterSlot34, ISpeciesForm + { + if (pk.Format == generation) + return new EvoCriteria { Species = enc.Species, LevelMin = pk.MetLevel, LevelMax = pk.MetLevel }; + foreach (var evo in chain) + { + if (evo.Species == enc.Species) + return evo; + } + throw new ArgumentException("No matching species found in the evolution chain."); + } +} diff --git a/PKHeX.Core/Legality/RNG/ClassicEra/LeadSeed.cs b/PKHeX.Core/Legality/RNG/ClassicEra/LeadSeed.cs new file mode 100644 index 000000000..70dae0765 --- /dev/null +++ b/PKHeX.Core/Legality/RNG/ClassicEra/LeadSeed.cs @@ -0,0 +1,34 @@ +using static PKHeX.Core.LeadRequired; + +namespace PKHeX.Core; + +/// +/// Result wrapper for encounter lead information. +/// +public struct LeadSeed(uint Seed, LeadRequired Lead) +{ + /// + /// Seed the encounter was triggered from. + /// + public uint Seed = Seed; + + /// + /// Lead condition required for the encounter. + /// + public LeadRequired Lead = Lead; + + public readonly void Deconstruct(out uint seed, out LeadRequired lead) + { + seed = Seed; + lead = Lead; + } + + public readonly bool IsNoRequirement() => Lead == None; + public readonly bool IsNoAbilityLead() => Lead == None; + public readonly bool IsValid() => Lead != Invalid; + + /// + /// Prefers the lead with the most likely value (lowest value). + /// + public readonly bool IsBetterThan(in LeadSeed other) => Lead > other.Lead; +} diff --git a/PKHeX.Core/Legality/RNG/Frame/Frame.cs b/PKHeX.Core/Legality/RNG/Frame/Frame.cs deleted file mode 100644 index 0e4312dbd..000000000 --- a/PKHeX.Core/Legality/RNG/Frame/Frame.cs +++ /dev/null @@ -1,91 +0,0 @@ -using System.Diagnostics; - -namespace PKHeX.Core; - -/// -/// Represents an RNG seed and the conditions of which it occurs. -/// -/// Ending seed value for the frame (prior to nature call). -/// -/// -[DebuggerDisplay($"{{{nameof(FrameType)},nq}}[{{{nameof(Lead)},nq}}]")] -public sealed record Frame(uint Seed, FrameType FrameType, LeadRequired Lead) -{ - /// - /// Starting seed for the frame (to generate the frame). - /// - public uint OriginSeed { get; set; } - - /// - /// RNG Call Value for the Level Calc - /// - public ushort RandLevel { get; set; } - - /// - /// RNG Call Value for the Encounter Slot Calc - /// - public ushort RandESV { get; set; } - - public bool LevelSlotModified => Lead.IsLevelOrSlotModified() || (Lead & LeadRequired.UsesLevelCall) != 0; - - /// - /// Checks the Encounter Slot for RNG calls before the Nature loop. - /// - /// Slot Data - /// Ancillary pk data for determining how to check level. - /// Slot number for this frame & lead value. - public bool IsSlotCompatibile(T slot, PKM pk) where T : IMagnetStatic, INumberedSlot, ISlotRNGType, ILevelRange - { - // The only level rand type slots are Honey Tree and National Park BCC - // Gen3 always does level rand, but the level ranges are same min,max. - if (FrameType != FrameType.MethodH) - { - bool hasLevelCall = slot.IsRandomLevel(); - if (Lead.NeedsLevelCall() != hasLevelCall) - return false; - } - - if (slot.Type is not (SlotType.HoneyTree)) - { - int calcSlot = GetSlot(slot); - if (calcSlot != slot.SlotNumber) - return false; - } - - // Check Level Now - var lvl = SlotRange.GetLevel(slot, Lead, RandLevel); - if (pk.HasOriginalMetLocation) - { - if (lvl != pk.Met_Level) - return false; - } - else - { - if (lvl > pk.Met_Level) - return false; - } - - // Check if the slot is actually encounterable (considering Sweet Scent) - bool encounterable = SlotRange.GetIsEncounterable(slot, FrameType, (int)(OriginSeed >> 16), Lead); - return encounterable; - } - - /// - /// Gets the slot value for the input slot. - /// - /// Slot Data - /// Slot number for this frame & lead value. - private int GetSlot(T slot) where T : IMagnetStatic, INumberedSlot, ISlotRNGType - { - // Static and Magnet Pull do a slot search rather than slot mapping 0-99. - return Lead != LeadRequired.StaticMagnet - ? SlotRange.GetSlot(slot.Type, RandESV, FrameType) - : SlotRange.GetSlotStaticMagnet(slot, RandESV); - } - - /// - /// Only use this for test methods. - /// - /// - public int GetSlot(SlotType t) => SlotRange.GetSlot(t, RandESV, FrameType); -} diff --git a/PKHeX.Core/Legality/RNG/Frame/FrameCheckDetails.cs b/PKHeX.Core/Legality/RNG/Frame/FrameCheckDetails.cs new file mode 100644 index 000000000..990d6cab8 --- /dev/null +++ b/PKHeX.Core/Legality/RNG/Frame/FrameCheckDetails.cs @@ -0,0 +1,28 @@ +namespace PKHeX.Core; + +public readonly ref struct FrameCheckDetails +{ + public readonly T Encounter; + public readonly byte LevelMin; + public readonly byte LevelMax; + public readonly uint Seed1; + public readonly uint Seed2; + public readonly uint Seed3; + public readonly byte Format; + + public uint Seed4 => LCRNG.Prev(Seed3); + public uint Prev1 => Seed1 >> 16; + public uint Prev2 => Seed2 >> 16; + public uint Prev3 => Seed3 >> 16; + + public FrameCheckDetails(T enc, uint seed, byte levelMin, byte levelMax, byte format) + { + Encounter = enc; + LevelMin = levelMin; + LevelMax = levelMax; + Format = format; + seed = Seed1 = LCRNG.Prev(seed); + seed = Seed2 = LCRNG.Prev(seed); + Seed3 = LCRNG.Prev(seed); + } +} diff --git a/PKHeX.Core/Legality/RNG/Frame/FrameFinder.cs b/PKHeX.Core/Legality/RNG/Frame/FrameFinder.cs deleted file mode 100644 index 5e29288a1..000000000 --- a/PKHeX.Core/Legality/RNG/Frame/FrameFinder.cs +++ /dev/null @@ -1,399 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; - -namespace PKHeX.Core; - -/// -/// Logic for finding a from inputs. -/// -public static class FrameFinder -{ - /// - /// Checks a to see if any encounter frames can generate the spread. Requires further filtering against matched Encounter Slots and generation patterns. - /// - /// Matched containing info and . - /// object containing various accessible information required for the encounter. - /// to yield possible encounter details for further filtering - public static IEnumerable GetFrames(PIDIV pidiv, PKM pk) - { - if (pk.Version == (int)GameVersion.CXD) - return []; - - // Don't trust pk.Nature, just get the correct original via EncryptionConstant - var info = new FrameGenerator(pk) {Nature = (byte)(pk.EncryptionConstant % 25)}; - var seeds = GetSeeds(pidiv, info, pk); - var frames = pidiv.Type == PIDType.CuteCharm - ? FilterCuteCharm(seeds, info) - : FilterNatureSync(seeds, info); - - return GetRefinedSeeds(frames, info, pidiv); - } - - // gather possible nature determination seeds until a same-nature PID breaks the unrolling - private static IEnumerable GetSeeds(PIDIV pidiv, FrameGenerator info, PKM pk) - { - if (pk is { Species: (int)Species.Unown, FRLG: true }) // Gen3 FRLG Unown: reversed await case - return SeedInfo.GetSeedsUntilUnownForm(pidiv, info, pk.Form); - if (pidiv.Type == PIDType.CuteCharm && info.FrameType != FrameType.MethodH) // Gen4: ambiguous seed due to gender-buffered PID - return SeedInfo.GetSeedsUntilNature4Cute(pk); - return SeedInfo.GetSeedsUntilNature(pidiv, info); - } - - private static IEnumerable GetRefinedSeeds(IEnumerable frames, FrameGenerator info, PIDIV pidiv) - { - var refined = RefineFrames(frames, info); - if (pidiv.Type == PIDType.CuteCharm && info.FrameType != FrameType.MethodH) // only permit cute charm successful frames - return refined.Where(z => (z.Lead & ~LeadRequired.UsesLevelCall) == LeadRequired.CuteCharm); - return refined; - } - - private static IEnumerable RefineFrames(IEnumerable frames, FrameGenerator info) - { - return info.FrameType == FrameType.MethodH - ? RefineFrames3(frames, info) - : RefineFrames4(frames, info); - } - - private static IEnumerable RefineFrames3(IEnumerable frames, FrameGenerator info) - { - // ESV - // Level - // Nature - // Current Seed of the frame is the Level Calc (frame before nature) - foreach (var f in frames) - { - bool noLead = !info.AllowLeads && f.Lead != LeadRequired.None; - if (noLead) - continue; - - var prev = LCRNG.Prev(f.Seed); // ESV - f.RandESV = (ushort)(prev >> 16); - f.RandLevel = (ushort)(f.Seed >> 16); - f.OriginSeed = LCRNG.Prev(prev); - if (f.Lead != LeadRequired.CuteCharm) // needs proc checking - yield return f; - - // Generate frames for other slots after the regular slots - if (info.AllowLeads && (f.Lead is LeadRequired.CuteCharm or LeadRequired.None)) - { - var leadframes = GenerateLeadSpecificFrames3(f, info); - foreach (var frame in leadframes) - yield return frame; - } - } - } - - private static IEnumerable GenerateLeadSpecificFrames3(Frame f, FrameGenerator info) - { - // Check leads -- none in list if leads are not allowed - // Certain leads inject an RNG call - // 3 different rand places - LeadRequired lead; - var prev0 = f.Seed; // 0 - var prev1 = LCRNG.Prev(f.Seed); // -1 - var prev2 = LCRNG.Prev(prev1); // -2 - var prev3 = LCRNG.Prev(prev2); // -3 - - // Rand call raw values - var p0 = prev0 >> 16; - var p1 = prev1 >> 16; - var p2 = prev2 >> 16; - - // Cute Charm - // -2 ESV - // -1 Level - // 0 CC Proc (Random() % 3 != 0) - // 1 Nature - if (info.Gendered) - { - bool cc = p0 % 3 != 0; - if (f.Lead == LeadRequired.CuteCharm) // 100% required for frame base - { - if (cc) - yield return info.GetFrame(prev2, LeadRequired.CuteCharm, (ushort)p2, (ushort)p1, prev3); - yield break; - } - lead = cc ? LeadRequired.CuteCharm : LeadRequired.CuteCharmFail; - yield return info.GetFrame(prev2, lead, (ushort)p2, (ushort)p1, prev3); - } - if (f.Lead == LeadRequired.CuteCharm) - yield break; - - // Pressure, Hustle, Vital Spirit = Force Maximum Level from slot - // -2 ESV - // -1 Level - // 0 LevelMax proc (Random() & 1) - // 1 Nature - bool max = p0 % 2 == 1; - lead = max ? LeadRequired.PressureHustleSpirit : LeadRequired.PressureHustleSpiritFail; - yield return info.GetFrame(prev2, lead, (ushort)p2, (ushort)p1, prev3); - - // Keen Eye, Intimidate (Not compatible with Sweet Scent) - // -2 ESV - // -1 Level - // 0 Level Adequate Check !(Random() % 2 == 1) rejects -- rand%2==1 is adequate - // 1 Nature - // Note: if this check fails, the encounter generation routine is aborted. - if (max) // same result as above, no need to recalculate - { - lead = LeadRequired.IntimidateKeenEye; - yield return info.GetFrame(prev2, lead, (ushort)p2, (ushort)p1, prev3); - } - - // Static or Magnet Pull - // -2 SlotProc (Random % 2 == 0) - // -1 ESV (select slot) - // 0 Level - // 1 Nature - bool force = p2 % 2 == 0; - if (force) - { - // Since a failed proc is indistinguishable from the default frame calls, only generate if it succeeds. - lead = LeadRequired.StaticMagnet; - yield return info.GetFrame(prev2, lead, (ushort)p1, (ushort)p0, prev3); - } - } - - private static IEnumerable RefineFrames4(IEnumerable frames, FrameGenerator info) - { - foreach (var f in frames) - { - // Current Seed of the frame is the ESV. - var rand = (ushort)(f.Seed >> 16); - f.RandESV = rand; - f.RandLevel = rand; // unused - f.OriginSeed = LCRNG.Prev(f.Seed); - yield return f; - - if (f.Lead == LeadRequired.None) - { - var leadframes = GenerateLeadSpecificFrames4(f, info); - foreach (var frame in leadframes) - yield return frame; - } - - // Create a copy for level; shift ESV and origin back - var esv = f.OriginSeed >> 16; - var origin = LCRNG.Prev(f.OriginSeed); - var withLevel = info.GetFrame(f.Seed, f.Lead | LeadRequired.UsesLevelCall, (ushort)esv, f.RandLevel, origin); - yield return withLevel; - - if (f.Lead == LeadRequired.None) - { - var leadframes = GenerateLeadSpecificFrames4(withLevel, info); - foreach (var frame in leadframes) - yield return frame; - } - } - } - - private static IEnumerable GenerateLeadSpecificFrames4(Frame f, FrameGenerator info) - { - LeadRequired lead; - var prev0 = f.Seed; // 0 - var prev1 = LCRNG.Prev(f.Seed); // -1 - var prev2 = LCRNG.Prev(prev1); // -2 - var prev3 = LCRNG.Prev(prev2); // -3 - - // Rand call raw values - var p0 = prev0 >> 16; - var p1 = prev1 >> 16; - var p2 = prev2 >> 16; - - // Cute Charm - // -2 ESV - // -1 Level (Optional) - // 0 CC Proc (Random() % 3 != 0) - // 1 Nature - if (info.Gendered) - { - bool cc = (info.DPPt ? p0 / 0x5556 : p0 % 3) != 0; - if (f.Lead == LeadRequired.CuteCharm) // 100% required for frame base - { - if (!cc) yield break; - yield return info.GetFrame(prev2, LeadRequired.CuteCharm, (ushort)p1, (ushort)p1, prev2); - yield return info.GetFrame(prev2, LeadRequired.CuteCharm | LeadRequired.UsesLevelCall, (ushort)p2, (ushort)p1, prev3); - yield break; - } - lead = cc ? LeadRequired.CuteCharm : LeadRequired.CuteCharmFail; - yield return info.GetFrame(prev2, lead, (ushort)p1, (ushort)p1, prev2); - yield return info.GetFrame(prev2, lead | LeadRequired.UsesLevelCall, (ushort)p2, (ushort)p1, prev3); - } - if (f.Lead == LeadRequired.CuteCharm) - yield break; - - // Pressure, Hustle, Vital Spirit = Force Maximum Level from slot - // -2 ESV - // -1 Level (Optional) - // 0 LevelMax proc (Random() & 1) - // 1 Nature - bool max = (info.DPPt ? p0 >> 15 : p0 & 1) == 1; - lead = max ? LeadRequired.PressureHustleSpirit : LeadRequired.PressureHustleSpiritFail; - yield return info.GetFrame(prev2, lead, (ushort)p1, (ushort)p1, prev2); - yield return info.GetFrame(prev2, lead | LeadRequired.UsesLevelCall, (ushort)p2, (ushort)p1, prev3); - - // Keen Eye, Intimidate (Not compatible with Sweet Scent) - // -2 ESV - // -1 Level (Optional) - // 0 Level Adequate Check !(Random() % 2 == 1) rejects -- rand%2==1 is adequate - // 1 Nature - // Note: if this check fails, the encounter generation routine is aborted. - if (max) // same result as above, no need to recalculate - { - lead = LeadRequired.IntimidateKeenEye; - yield return info.GetFrame(prev2, lead, (ushort)p1, (ushort)p1, prev2); - yield return info.GetFrame(prev2, lead | LeadRequired.UsesLevelCall, (ushort)p2, (ushort)p1, prev3); - } - - // Static or Magnet Pull - // -2 SlotProc (Random % 2 == 0) - // -1 ESV (select slot) - // 0 Level (Optional) - // 1 Nature - var force1 = (info.DPPt ? p1 >> 15 : p1 & 1) == 1; - lead = force1 ? LeadRequired.StaticMagnet : LeadRequired.StaticMagnetFail; - yield return info.GetFrame(prev2, lead, (ushort)p0, (ushort)p0, prev3); - - var force2 = (info.DPPt ? p2 >> 15 : p2 & 1) == 1; - lead = (force2 ? LeadRequired.StaticMagnet : LeadRequired.StaticMagnetFail) | LeadRequired.UsesLevelCall; - yield return info.GetFrame(prev2, lead, (ushort)p1, (ushort)p0, prev3); - } - - /// - /// Filters the input according to a Nature Lock frame generation pattern. - /// - /// Seed Information for the frame - /// Search Info for the frame - /// Possible matches to the Nature Lock frame generation pattern - private static IEnumerable FilterNatureSync(IEnumerable seeds, FrameGenerator info) - { - foreach (var seed in seeds) - { - var s = seed.Seed; - - if (info.Safari3) - { - // successful pokeblock activation - bool result = IsValidPokeBlockNature(s, info.Nature, out uint blockSeed); - if (result) - yield return info.GetFrame(blockSeed, seed.Charm3 ? LeadRequired.CuteCharm : LeadRequired.None); - - // if no pokeblocks present (or failed call), fall out of the safari specific code and generate via the other scenarios - } - - var rand = s >> 16; - bool sync = info.AllowLeads && !seed.Charm3 && (info.DPPt ? rand >> 15 : rand & 1) == 0; - bool reg = (info.DPPt ? rand / 0xA3E : rand % 25) == info.Nature; - if (!sync && !reg) // doesn't generate nature frame - continue; - - uint prev = LCRNG.Prev(s); - if (info.AllowLeads && reg) // check for failed sync - { - var failsync = (info.DPPt ? prev >> 31 : (prev >> 16) & 1) != 1; - if (failsync) - yield return info.GetFrame(LCRNG.Prev(prev), LeadRequired.SynchronizeFail); - } - if (sync) - yield return info.GetFrame(prev, LeadRequired.Synchronize); - if (reg) - { - if (seed.Charm3) - { - yield return info.GetFrame(prev, LeadRequired.CuteCharm); - } - else - { - if (info.Safari3) - prev = LCRNG.Prev(prev); // wasted RNG call - yield return info.GetFrame(prev, LeadRequired.None); - } - } - } - } - - private static bool IsValidPokeBlockNature(uint seed, uint nature, out uint natureOrigin) - { - if (nature % 6 == 0) // neutral - { - natureOrigin = 0; - return false; - } - - // unroll the RNG to a stack of seeds - var stack = new Stack(); - for (uint i = 0; i < 25; i++) - { - for (uint j = 1 + i; j < 25; j++) - stack.Push(seed = LCRNG.Prev(seed)); - } - - natureOrigin = LCRNG.Prev(stack.Peek()); - if (natureOrigin >> (16 % 100) >= 80) // failed proc - return false; - - // init natures - Span natures = stackalloc byte[25]; - for (byte i = 0; i < 25; i++) - natures[i] = i; - - // shuffle nature list - for (int i = 0; i < 25; i++) - { - for (int j = 1 + i; j < 25; j++) - { - var s = stack.Pop(); - if (((s >> 16) & 1) == 0) - continue; // only swap if 1 - - (natures[i], natures[j]) = (natures[j], natures[i]); - } - } - - var likes = Pokeblock.GetLikedBlockFlavor(nature); - // best case scenario is a perfect flavored pokeblock for the nature. - // has liked flavor, and all other non-disliked flavors are present. - // is it possible to skip this step? - for (int i = 0; i < 25; i++) - { - var n = natures[i]; - if (n == nature) - break; - - var nl = Pokeblock.GetLikedBlockFlavor(natures[i]); - if (nl == likes) // next random nature likes the same block as the desired nature - return false; // current nature is chosen instead, fail! - } - // unroll once more to hit the level calc (origin with respect for beginning the nature calcs) - natureOrigin = LCRNG.Prev(natureOrigin); - return true; - } - - /// - /// Filters the input according to a Cute Charm frame generation pattern. - /// - /// Seed Information for the frame - /// Search Info for the frame - /// Possible matches to the Cute Charm frame generation pattern - private static IEnumerable FilterCuteCharm(IEnumerable seeds, FrameGenerator info) - { - foreach (var seed in seeds) - { - var s = seed.Seed; - - var rand = s >> 16; - var nature = info.DPPt ? rand / 0xA3E : rand % 25; - if (nature != info.Nature) - continue; - - var prev = LCRNG.Prev(s); - var proc = prev >> 16; - bool charmProc = (info.DPPt ? proc / 0x5556 : proc % 3) != 0; // 2/3 odds - if (!charmProc) - continue; - - yield return info.GetFrame(LCRNG.Prev(prev), LeadRequired.CuteCharm); - } - } -} diff --git a/PKHeX.Core/Legality/RNG/Frame/FrameGenerator.cs b/PKHeX.Core/Legality/RNG/Frame/FrameGenerator.cs deleted file mode 100644 index 528c00ecc..000000000 --- a/PKHeX.Core/Legality/RNG/Frame/FrameGenerator.cs +++ /dev/null @@ -1,98 +0,0 @@ -using System; -using static PKHeX.Core.GameVersion; - -namespace PKHeX.Core; - -/// -/// Generator information for Gen3/4 Frame patterns -/// -public readonly struct FrameGenerator -{ - public required byte Nature { get; init; } - public readonly byte GenderHigh; - public readonly byte GenderLow; - public readonly FrameType FrameType; - public readonly bool DPPt; - public readonly bool AllowLeads; - public readonly bool Gendered; - public readonly bool Safari3; - - public Frame GetFrame(uint seed, LeadRequired lead) => new(seed, FrameType, lead); - public Frame GetFrame(uint seed, LeadRequired lead, ushort esv, uint origin) => GetFrame(seed, lead, esv, esv, origin); - - public Frame GetFrame(uint seed, LeadRequired lead, ushort esv, ushort lvl, uint origin) => new(seed, FrameType, lead) - { - RandESV = esv, - RandLevel = lvl, - OriginSeed = origin, - }; - - /// - /// Gets the Search Criteria parameters necessary for generating and objects for Gen3/4 mainline games. - /// - /// object containing various accessible information required for the encounter. - /// Object containing search criteria to be passed by reference to search/filter methods. - public FrameGenerator(PKM pk) - { - var version = (GameVersion)pk.Version; - switch (version) - { - // Method H - case R or S or E or FR or LG: - DPPt = false; - FrameType = FrameType.MethodH; - Safari3 = pk.Ball == 5 && version is not (FR or LG); - - if (version != E) - return; - - AllowLeads = true; - - // Cute Charm waits for gender too! - var gender = pk.Gender; - bool gendered = gender != 2; - if (!gendered) - return; - - var gr = pk.PersonalInfo.Gender; - Gendered = true; - (GenderLow, GenderHigh) = GetGenderMinMax(gender, gr); - return; - - // Method J - case D or P or Pt: - DPPt = true; - AllowLeads = true; - FrameType = FrameType.MethodJ; - return; - - // Method K - case HG or SS: - DPPt = false; - AllowLeads = true; - FrameType = FrameType.MethodK; - return; - default: - throw new ArgumentOutOfRangeException(nameof(version), version, "Unknown version."); - } - } - - /// - /// Gets the span of values for a given Gender - /// - /// Gender - /// Gender Ratio - /// Returns the maximum or minimum gender value that corresponds to the input gender ratio. - private static (byte Min, byte Max) GetGenderMinMax(int gender, byte ratio) => ratio switch - { - PersonalInfo.RatioMagicMale => (0, 255), - PersonalInfo.RatioMagicFemale => (0, 255), - PersonalInfo.RatioMagicGenderless => (0, 255), - _ => gender switch - { - 0 => (ratio, 255), // male - 1 => (0, --ratio), // female - _ => (0, 255), - }, - }; -} diff --git a/PKHeX.Core/Legality/RNG/Frame/FrameType.cs b/PKHeX.Core/Legality/RNG/Frame/FrameType.cs deleted file mode 100644 index 1a3917b4d..000000000 --- a/PKHeX.Core/Legality/RNG/Frame/FrameType.cs +++ /dev/null @@ -1,18 +0,0 @@ -namespace PKHeX.Core; - -/// -/// Type of PID-Nature roll algorithm the frame is obtained from. -/// -public enum FrameType : byte -{ - None, - - /// Generation 3 PID-Nature roll algorithm - MethodH, - - /// Generation 4 PID-Nature roll algorithm present for D/P/Pt - MethodJ, - - /// Generation 4 PID-Nature roll algorithm present for HG/SS - MethodK, -} diff --git a/PKHeX.Core/Legality/RNG/Frame/LeadRequired.cs b/PKHeX.Core/Legality/RNG/Frame/LeadRequired.cs index 79782fcbc..de53650e5 100644 --- a/PKHeX.Core/Legality/RNG/Frame/LeadRequired.cs +++ b/PKHeX.Core/Legality/RNG/Frame/LeadRequired.cs @@ -1,52 +1,94 @@ -using System; +using static PKHeX.Core.LeadRequired; namespace PKHeX.Core; /// /// Indicates the requirement of the player's lead Pokémon, first sent out when starting a battle. /// -[Flags] +/// Ordered by increasing preference. public enum LeadRequired : byte { - /// No Lead ability effect is present, or is not checked for this type of frame. - None = 0, + /// Sentinel value for invalid/impossible to yield lead conditions. + Invalid = 0, - /// - CuteCharm = 1 << 0, - /// - Synchronize = 1 << 1, + // Illuminate can't "fail" to apply. + // Suction Cups failing will fail to yield the encounter, otherwise we'd have no lead required. + // Intimidate succeeding will fail to yield the encounter. - // Slot Modifiers - /// or - StaticMagnet = 1 << 2, + /// + StaticMagnetFail, + /// + CuteCharmFail, + /// + SynchronizeFail, + /// + PressureHustleSpiritFail, + + /// or failed to activate. + IntimidateKeenEyeFail, + + /// or + Illuminate, + /// or + SuctionCups, - // Level Modifiers - /// or - IntimidateKeenEye = 1 << 3, /// or or - PressureHustleSpirit = 1 << 4, - /// - SuctionCups = 1 << 5, + PressureHustleSpirit, + /// + MagnetPull, + /// + Static, + /// + CuteCharm, + /// + Synchronize, - // Compatibility Flags - UsesLevelCall = 1 << 6, - Fail = 1 << 7, - - /// - CuteCharmFail = CuteCharm | Fail, - /// - SynchronizeFail = Synchronize | Fail, - /// - StaticMagnetFail = StaticMagnet | Fail, - /// - PressureHustleSpiritFail = PressureHustleSpirit | Fail, - - AllFlags = UsesLevelCall | Fail, + /// No Lead ability effect is present, or is not checked for this type of frame. + None = byte.MaxValue, } -public static partial class Extensions +public static class LeadRequiredExtensions { - internal static bool IsLevelOrSlotModified(this LeadRequired lead) => lead.RemoveFlags() > LeadRequired.Synchronize; - internal static LeadRequired RemoveFlags(this LeadRequired lead) => lead & ~LeadRequired.AllFlags; - internal static bool NeedsLevelCall(this LeadRequired lead) => (lead & LeadRequired.UsesLevelCall) != 0; + public static bool IsFailTuple(this LeadRequired lr) => lr + is PressureHustleSpiritFail + or SynchronizeFail + or CuteCharmFail + or StaticMagnetFail; + + public static LeadRequired GetRegular(this LeadRequired lr) => lr switch + { + PressureHustleSpiritFail => PressureHustleSpirit, + SynchronizeFail => Synchronize, + CuteCharmFail => CuteCharm, + StaticMagnetFail => Static, + _ => None, + }; + + public static Ability GetAbility(this LeadRequired lr) => lr switch + { + Synchronize => Ability.Synchronize, + CuteCharm => Ability.CuteCharm, + Static => Ability.Static, + MagnetPull => Ability.MagnetPull, + PressureHustleSpirit => Ability.Pressure, + SuctionCups => Ability.SuctionCups, + Illuminate => Ability.Illuminate, + IntimidateKeenEyeFail => Ability.Intimidate, + _ => Ability.None, + }; + + public static (Ability Ability, bool IsFail) GetDisplayAbility(this LeadRequired lr) + { + var isFail = false; + if (lr.IsFailTuple()) + { + isFail = true; + lr = lr.GetRegular(); + } + else if (lr is IntimidateKeenEyeFail) + { + isFail = true; + } + return (lr.GetAbility(), isFail); + } } diff --git a/PKHeX.Core/Legality/RNG/Frame/Pokeblock.cs b/PKHeX.Core/Legality/RNG/Frame/Pokeblock.cs deleted file mode 100644 index 9e1e87c70..000000000 --- a/PKHeX.Core/Legality/RNG/Frame/Pokeblock.cs +++ /dev/null @@ -1,19 +0,0 @@ -namespace PKHeX.Core; - -/// -/// Logic for Poké Blocks used in generation 3/4. -/// -public static class Pokeblock -{ - public static Flavor GetLikedBlockFlavor(uint nature) => (Flavor)(nature/5); - public static Flavor GetDislikedBlockFlavor(uint nature) => (Flavor)(nature%5); - - public enum Flavor - { - Spicy, - Sour, - Sweet, - Dry, - Bitter, - } -} diff --git a/PKHeX.Core/Legality/RNG/Frame/SeedInfo.cs b/PKHeX.Core/Legality/RNG/Frame/SeedInfo.cs deleted file mode 100644 index 7f9bba6b5..000000000 --- a/PKHeX.Core/Legality/RNG/Frame/SeedInfo.cs +++ /dev/null @@ -1,119 +0,0 @@ -using System.Collections.Generic; - -namespace PKHeX.Core; - -/// -/// Seed result value storage for passing frame seeds & conditions. -/// -public readonly record struct SeedInfo(uint Seed, bool Charm3 = false) -{ - /// - /// Yields an enumerable list of seeds until another valid PID breaks the chain. - /// - /// Seed and RNG data - /// Verification information - /// Seed information data, which needs to be unrolled once for the nature call. - public static IEnumerable GetSeedsUntilNature(PIDIV pidiv, FrameGenerator info) - { - var seed = pidiv.OriginSeed; - yield return new SeedInfo(seed); - - var s1 = seed; - var s2 = LCRNG.Prev(s1); - bool charm3 = false; - while (true) - { - var a = s2 >> 16; - var b = s1 >> 16; - - var pid = b << 16 | a; - - // Process Conditions - switch (VerifyPIDCriteria(pid, info)) - { - case LockInfo.Pass: - yield break; - case LockInfo.Gender: - charm3 = true; - break; - } - - s1 = LCRNG.Prev(s2); - s2 = LCRNG.Prev(s1); - - yield return new SeedInfo(s1, charm3); - } - } - - /// - /// Yields an enumerable list of seeds until another valid PID breaks the chain. - /// - /// Entity data created from the ambiguous cute charm seeds. - /// Seed information data, which needs to be unrolled once for the nature call. - public static IEnumerable GetSeedsUntilNature4Cute(PKM pk) - { - // We cannot rely on a PID-IV origin seed. Since IVs are 2^30, they are not strong enough to assume a single seed was the source. - // We must reverse the IVs to find all seeds that could generate this. - // ESV,Proc,Nature,IV1,IV2; these do not do the nature loop for Method J/K so each seed originates a single seed frame. - - var seeds = new uint[LCRNG.MaxCountSeedsIV]; - int ctr = LCRNGReversal.GetSeedsIVs(seeds, (uint)pk.IV_HP, (uint)pk.IV_ATK, (uint)pk.IV_DEF, (uint)pk.IV_SPA, (uint)pk.IV_SPD, (uint)pk.IV_SPE); - for (int i = 0; i < ctr; i++) - yield return new SeedInfo(seeds[i]); - } - - /// - /// Yields an enumerable list of seeds until another valid PID breaks the chain. - /// - /// Seed and RNG data - /// Verification information - /// Unown Form lock value - /// Seed information data, which needs to be unrolled once for the nature call. - public static IEnumerable GetSeedsUntilUnownForm(PIDIV pidiv, FrameGenerator info, byte form) - { - var seed = pidiv.OriginSeed; - yield return new SeedInfo(seed); - - var s1 = seed; - var s2 = LCRNG.Prev(s1); - while (true) - { - var a = s2 >> 16; - var b = s1 >> 16; - // PID is in reverse for FRLG Unown - var pid = (a << 16) | b; - - // Process Conditions - if (EntityPID.GetUnownForm3(pid) == form) // matches form, does it match nature? - { - switch (VerifyPIDCriteria(pid, info)) - { - case LockInfo.Pass: // yes - yield break; - } - } - - s1 = LCRNG.Prev(s2); - s2 = LCRNG.Prev(s1); - - yield return new SeedInfo(s1); - } - } - - private static LockInfo VerifyPIDCriteria(uint pid, FrameGenerator info) - { - // Nature locks are always a given - var nval = pid % 25; - if (nval != info.Nature) - return LockInfo.Nature; - - if (!info.Gendered) - return LockInfo.Pass; - - var gender = pid & 0xFF; - if (info.GenderLow > gender || gender > info.GenderHigh) - return LockInfo.Gender; - - return LockInfo.Pass; - } -} diff --git a/PKHeX.Core/Legality/RNG/Frame/SlotNumber.cs b/PKHeX.Core/Legality/RNG/Frame/SlotNumber.cs deleted file mode 100644 index 7fb98a6c6..000000000 --- a/PKHeX.Core/Legality/RNG/Frame/SlotNumber.cs +++ /dev/null @@ -1,146 +0,0 @@ -namespace PKHeX.Core; - -/// -/// Converts a slot random roll [0, 100) to a slot number. -/// -public static class SlotNumber -{ - private const int Invalid = -1; - - /// - /// Calculates the encounter slot index based on the roll for a Gen3 Old Rod encounter. - /// - /// [0,100) - public static int GetHOldRod(uint roll) => roll switch - { - < 70 => 0, // 00,69 (70%) - <=99 => 1, // 70,99 (30%) - _ => Invalid, - }; - - /// - /// Calculates the encounter slot index based on the roll for a Gen3 Good Rod encounter. - /// - /// [0,100) - public static int GetHGoodRod(uint roll) => roll switch - { - < 60 => 0, // 00,59 (60%) - < 80 => 1, // 60,79 (20%) - <=99 => 2, // 80,99 (20%) - _ => Invalid, - }; - - /// - /// Calculates the encounter slot index based on the roll for a Gen3 Super Rod encounter. - /// - /// [0,100) - public static int GetHSuperRod(uint roll) => roll switch - { - < 40 => 0, // 00,39 (40%) - < 80 => 1, // 40,69 (40%) - < 95 => 2, // 70,94 (15%) - < 99 => 3, // 95,98 ( 4%) - 99 => 4, // 99 ( 1%) - _ => Invalid, - }; - - /// - /// Calculates the encounter slot index based on the roll for a Gen3 Surf encounter. - /// - /// [0,100) - public static int GetHSurf(uint roll) => roll switch - { - < 60 => 0, // 00,59 (60%) - < 90 => 1, // 60,89 (30%) - < 95 => 2, // 90,94 ( 5%) - < 99 => 3, // 95,98 ( 4%) - 99 => 4, // 99 ( 1%) - _ => Invalid, - }; - - /// - /// Calculates the encounter slot index based on the roll for a Gen3 Wild encounter. - /// - /// [0,100) - public static int GetHRegular(uint roll) => roll switch - { - < 20 => 0, // 00,19 (20%) - < 40 => 1, // 20,39 (20%) - < 50 => 2, // 40,49 (10%) - < 60 => 3, // 50,59 (10%) - < 70 => 4, // 60,69 (10%) - < 80 => 5, // 70,79 (10%) - < 85 => 6, // 80,84 ( 5%) - < 90 => 7, // 85,89 ( 5%) - < 94 => 8, // 90,93 ( 4%) - < 98 => 9, // 94,97 ( 4%) - < 99 => 10,// 98,98 ( 1%) - 99 => 11,// 99 ( 1%) - _ => Invalid, - }; - - /// - /// Calculates the encounter slot index based on the roll for a D/P/Pt Super Rod encounter. - /// - /// [0,100) - public static int GetJSuperRod(uint roll) => roll switch - { - < 40 => 0, // 00,39 (40%) - < 80 => 1, // 40,79 (40%) - < 95 => 2, // 80,94 (15%) - < 99 => 3, // 95,98 ( 4%) - 99 => 4, // 99 ( 1%) - _ => Invalid, - }; - - /// - /// Calculates the encounter slot index based on the roll for a HG/SS Super Rod encounter. - /// - /// [0,100) - public static int GetKSuperRod(uint roll) => roll switch - { - < 40 => 0, // 00,39 (40%) - < 70 => 1, // 40,69 (30%) - < 85 => 2, // 70,84 (15%) - < 95 => 3, // 85,94 (10%) - 99 => 4, // 95 ( 5%) - _ => Invalid, - }; - - /// - /// Calculates the encounter slot index based on the roll for a Bug Catching Contest encounter. - /// - /// [0,100) - /// - /// Slot indexes are reversed for the Bug Catching Contest. - /// - public static int GetKBCC(uint roll) => roll switch - { - < 05 => 9, // 00,04 ( 5%) - < 10 => 8, // 05,09 ( 5%) - < 15 => 7, // 10,14 ( 5%) - < 20 => 6, // 15,19 ( 5%) - < 30 => 5, // 20,29 (10%) - < 40 => 4, // 30,39 (10%) - < 50 => 3, // 40,49 (10%) - < 60 => 2, // 50,59 (10%) - < 80 => 1, // 60,79 (20%) - < 100=> 0, // 80,99 (20%) - _ => Invalid, - }; - - /// - /// Calculates the encounter slot index based on the roll for a HG/SS Headbutt encounter. - /// - /// [0,100) - public static int GetKHeadbutt(uint roll) => roll switch - { - < 50 => 0, // 00,49 (50%) - < 65 => 1, // 50,64 (15%) - < 80 => 2, // 65,79 (15%) - < 90 => 3, // 80,89 (10%) - < 95 => 4, // 90,94 ( 5%) - <=99 => 5, // 95,99 ( 5%) - _ => Invalid, - }; -} diff --git a/PKHeX.Core/Legality/RNG/Frame/SlotRange.cs b/PKHeX.Core/Legality/RNG/Frame/SlotRange.cs deleted file mode 100644 index 85ab04b1f..000000000 --- a/PKHeX.Core/Legality/RNG/Frame/SlotRange.cs +++ /dev/null @@ -1,162 +0,0 @@ -using static PKHeX.Core.SlotType; -using static PKHeX.Core.SlotNumber; - -namespace PKHeX.Core; - -/// -/// RNG Encounter Slot Ranges to convert the [0,100) value into a slot index. -/// -public static class SlotRange -{ - private const int Invalid = -1; // all slots are [0,X], unsigned. This will always result in a non-match. - - /// - /// Gets the from the raw 16bit seed half. - /// - public static int GetSlot(SlotType type, uint rand, FrameType t) => t switch - { - FrameType.MethodH => HSlot(type, rand), - FrameType.MethodJ => JSlot(type, rand), - FrameType.MethodK => KSlot(type, rand), - _ => Invalid, - }; - - /// - /// Gets the from the raw 16bit seed half. - /// - private static int HSlot(SlotType type, uint rand) - { - var ESV = rand % 100; - if ((type & Swarm) != 0) - return ESV < 50 ? 0 : Invalid; - - return type switch - { - Old_Rod => GetHOldRod(ESV), - Good_Rod => GetHGoodRod(ESV), - Super_Rod => GetHSuperRod(ESV), - Rock_Smash => GetHSurf(ESV), - Surf => GetHSurf(ESV), - _ => GetHRegular(ESV), - }; - } - - /// - /// Gets the from the raw 16bit seed half. - /// - private static int KSlot(SlotType type, uint rand) - { - var ESV = rand % 100; - return type switch - { - Rock_Smash or Surf => GetHSurf(ESV), - Old_Rod or Good_Rod or Super_Rod => GetKSuperRod(ESV), - BugContest => GetKBCC(ESV), - Headbutt or (Headbutt | Special) => GetKHeadbutt(ESV), - _ => GetHRegular(ESV), - }; - } - - /// - /// Gets the from the raw 16bit seed half. - /// - private static int JSlot(SlotType type, uint rand) - { - uint ESV = rand / 656; - return type switch - { - Old_Rod or Rock_Smash or Surf => GetHSurf(ESV), - Good_Rod or Super_Rod => GetJSuperRod(ESV), - HoneyTree => 0, - _ => GetHRegular(ESV), - }; - } - - /// - /// Calculates the level for the given slot. - /// - /// Slot type - /// Slot reference - /// Player's lead Pokémon - /// Random value to use for level calculation - /// Actual level of the encounter - public static int GetLevel(T slot, LeadRequired lead, uint lvlrand) where T : ILevelRange - { - if ((lead & LeadRequired.PressureHustleSpiritFail) == LeadRequired.PressureHustleSpirit) - return slot.LevelMax; - if (slot.IsFixedLevel()) - return slot.LevelMin; - int delta = slot.LevelMax - slot.LevelMin + 1; - var adjust = (int)(lvlrand % delta); - - return slot.LevelMin + adjust; - } - -#pragma warning disable IDE0060, RCS1163 // Unused parameter. - public static bool GetIsEncounterable(T slot, FrameType frameType, int rand, LeadRequired lead) where T : ISlotRNGType -#pragma warning restore IDE0060, RCS1163 // Unused parameter. - { - var type = slot.Type; - if (type.IsSweetScentType()) - return true; - if (type is HoneyTree) - return true; - return true; // todo - //return GetCanEncounter(slot, frameType, rand, lead); - } - - // ReSharper disable once UnusedMember.Global - public static bool GetCanEncounter(T slot, FrameType frameType, int rand, LeadRequired lead) where T : ISlotRNGType - { - int proc = frameType == FrameType.MethodJ ? rand / 656 : rand % 100; - var stype = slot.Type; - if (stype == Rock_Smash) - return proc < 60; - if (frameType == FrameType.MethodH) - return true; // fishing encounters are disjointed by the hooked message. - return GetCanEncounterFish(lead, stype, proc); - } - - private static bool GetCanEncounterFish(LeadRequired lead, SlotType stype, int proc) => stype switch - { - // Lead:None => can be suction cups - Old_Rod => proc switch - { - < 25 => true, - < 50 => lead == LeadRequired.None, - _ => false, - }, - Good_Rod => proc switch - { - < 50 => true, - < 75 => lead == LeadRequired.None, - _ => false, - }, - Super_Rod => proc < 75 || lead == LeadRequired.None, - - _ => false, - }; - - /// - /// Checks both Static and Magnet Pull ability type selection encounters to see if the encounter can be selected. - /// - /// Slot Data - /// Rand16 value for the call - /// Slot number from the slot data if the slot is selected on this frame, else an invalid slot value. - internal static int GetSlotStaticMagnet(T slot, uint esv) where T : IMagnetStatic, INumberedSlot - { - if (slot.IsStaticSlot) - { - var index = esv % slot.StaticCount; - if (index == slot.StaticIndex) - return slot.SlotNumber; - } - if (slot.IsMagnetSlot) - { - var index = esv % slot.MagnetPullCount; - if (index == slot.MagnetPullIndex) - return slot.SlotNumber; - } - return Invalid; - } -} diff --git a/PKHeX.Core/Legality/RNG/MethodFinder.cs b/PKHeX.Core/Legality/RNG/MethodFinder.cs index 3122f16d1..b6c9ab091 100644 --- a/PKHeX.Core/Legality/RNG/MethodFinder.cs +++ b/PKHeX.Core/Legality/RNG/MethodFinder.cs @@ -1,5 +1,6 @@ using System; using System.Runtime.CompilerServices; +using static PKHeX.Core.GameVersion; using static PKHeX.Core.PIDType; namespace PKHeX.Core; @@ -83,6 +84,44 @@ private static bool GetModified8BitMatch(PKM pk, uint pid, out PIDIV pidiv) : GetG5MGShinyMatch(pk, pid, out pidiv) || (pid <= 0xFF && GetCuteCharmMatch(pk, pid, out pidiv)); } + public static bool GetLCRNGMethod1Match(PKM pk, out uint result) + { + var pid = pk.EncryptionConstant; + + var top = pid & 0xFFFF0000; + var bot = pid << 16; + + Span temp = stackalloc uint[6]; + for (int i = 0; i < 6; i++) + temp[i] = (uint)pk.GetIV(i); + ReadOnlySpan IVs = temp; + + const int maxResults = LCRNG.MaxCountSeedsIV; + Span seeds = stackalloc uint[maxResults]; + var count = LCRNGReversal.GetSeeds(seeds, bot, top); + var reg = seeds[..count]; + var iv1 = GetIVChunk(IVs[..3]); + var iv2 = GetIVChunk(IVs[3..]); + + foreach (var seed in reg) + { + var C = LCRNG.Next3(seed); + var ivC = C >> 16 & 0x7FFF; + if (iv1 != ivC) + continue; + var D = LCRNG.Next(C); + var ivD = D >> 16 & 0x7FFF; + if (iv2 != ivD) + continue; + // ABCD + result = seed; + return true; + } + + result = default; + return false; + } + private static bool GetLCRNGMatch(Span seeds, uint top, uint bot, ReadOnlySpan IVs, out PIDIV pidiv) { var count = LCRNGReversal.GetSeeds(seeds, bot, top); @@ -258,7 +297,7 @@ private static bool GetXDRNGMatch(Span seeds, PKM pk, uint top, uint bot, var lo = B >> 16; if (IVsMatch(hi, lo, IVs)) { - pidiv = new PIDIV(CXD, XDRNG.Prev(A)); + pidiv = new PIDIV(PIDType.CXD, XDRNG.Prev(A)); return true; } @@ -297,8 +336,8 @@ private static bool GetXDRNGMatch(Span seeds, PKM pk, uint top, uint bot, private static bool GetChannelMatch(Span seeds, uint top, uint bot, ReadOnlySpan IVs, out PIDIV pidiv, PKM pk) { - var ver = pk.Version; - if (ver is not ((int)GameVersion.R or (int)GameVersion.S)) + var version = pk.Version; + if (version is not (R or S)) return GetNonMatch(out pidiv); var undo = (top >> 16) ^ 0x8000; @@ -313,11 +352,11 @@ private static bool GetChannelMatch(Span seeds, uint top, uint bot, ReadOn // no checks, held item can be swapped var D = XDRNG.Next(C); // Version - if ((D >> 31) + 1 != ver) // (0-Sapphire, 1-Ruby) + if ((D >> 31) + 1 != (byte)version) // (0-Sapphire, 1-Ruby) continue; var E = XDRNG.Next(D); // OT Gender - if (E >> 31 != pk.OT_Gender) + if (E >> 31 != pk.OriginalTrainerGender) continue; if (!XDRNG.GetSequentialIVsUInt32(E, IVs)) @@ -386,12 +425,20 @@ private static bool GetG5MGShinyMatch(PKM pk, uint pid, out PIDIV pidiv) return GetNonMatch(out pidiv); } - internal static bool GetCuteCharmMatch(PKM pk, uint pid, out PIDIV pidiv) + private static bool GetCuteCharmMatch(PKM pk, uint pid, out PIDIV pidiv) + { + if (!IsCuteCharm(pk, pid)) + return GetNonMatch(out pidiv); + pidiv = PIDIV.CuteCharm; + return true; + } + + public static bool IsCuteCharm(PKM pk, uint pid) { if (pid > 0xFF) - return GetNonMatch(out pidiv); + return false; - (var species, int genderValue) = GetCuteCharmGenderSpecies(pk, pid, pk.Species); + var (species, gender) = GetCuteCharmGenderSpecies(pk, pid, pk.Species); static byte getRatio(ushort species) { return species <= Legal.MaxSpeciesID_4 @@ -399,30 +446,27 @@ static byte getRatio(ushort species) : PKX.Personal[species].Gender; } - switch (genderValue) + const uint n = 25; + switch (gender) { - case 2: break; // can't cute charm a genderless pk + // case 2: break; // can't cute charm a genderless pk case 0: // male var gr = getRatio(species); if (gr >= PersonalInfo.RatioMagicFemale) // no modification for PID break; - var rate = 25*((gr / 25) + 1); // buffered - var nature = pid % 25; + var rate = n * ((gr / n) + 1); // buffered + var nature = pid % n; if (nature + rate != pid) break; - - pidiv = PIDIV.CuteCharm; return true; case 1: // female - if (pid >= 25) + if (pid >= n) break; // nope, this isn't a valid nature if (getRatio(species) >= PersonalInfo.RatioMagicFemale) // no modification for PID break; - - pidiv = PIDIV.CuteCharm; return true; } - return GetNonMatch(out pidiv); + return false; } private static bool GetChainShinyMatch(Span seeds, PKM pk, uint pid, ReadOnlySpan IVs, out PIDIV pidiv) @@ -577,10 +621,10 @@ private static bool IsAzurillEdgeCaseM(PKM pk, uint nature, uint oldpid) private static bool GetColoStarterMatch(Span seeds, PKM pk, uint top, uint bot, ReadOnlySpan IVs, out PIDIV pidiv) { - bool starter = pk.Version == (int)GameVersion.CXD && pk.Species switch + bool starter = pk.Version == GameVersion.CXD && pk.Species switch { - (int)Species.Espeon when pk.Met_Level >= 25 => true, - (int)Species.Umbreon when pk.Met_Level >= 26 => true, + (int)Species.Espeon when pk.MetLevel >= 25 => true, + (int)Species.Umbreon when pk.MetLevel >= 26 => true, _ => false, }; if (!starter) @@ -618,7 +662,7 @@ private static bool GetNonMatch(out PIDIV pidiv) /// /// Checks if the PID is a match. /// - /// ^ + /// ^ /// Full actual PID /// Low portion of PID (B) /// First RNG call @@ -626,7 +670,7 @@ private static bool GetNonMatch(out PIDIV pidiv) /// True/False if the PID matches /// First RNG call is unrolled once if the PID is valid with this correlation [MethodImpl(MethodImplOptions.AggressiveInlining)] - private static bool IsBACD_U_S(uint idxor, uint pid, uint low, ref uint A, ref PIDType type) + private static bool IsBACD_U_S(uint idXor, uint pid, uint low, ref uint A, ref PIDType type) { // 0-Origin // 1-PIDH @@ -635,7 +679,7 @@ private static bool IsBACD_U_S(uint idxor, uint pid, uint low, ref uint A, ref P // PID = PIDH << 16 | (SID16 ^ TID16 ^ PIDH) var X = LCRNG.Prev(A); // unroll once as there's 3 calls instead of 2 - uint PID = (X & 0xFFFF0000) | (idxor ^ X >> 16); + uint PID = (X & 0xFFFF0000) | (idXor ^ X >> 16); PID &= 0xFFFFFFF8; PID |= low & 0x7; // lowest 3 bits @@ -767,7 +811,7 @@ public static bool IsPokeSpotActivation(int slot, uint seed, out uint s) internal static bool IsCuteCharm4Valid(ISpeciesForm enc, PKM pk) { if (pk.Gender is not (0 or 1)) - return false; + return pk.Species == (ushort)Species.Shedinja; if (pk.Species is not ((int)Species.Marill or (int)Species.Azumarill)) return true; if (!IsCuteCharmAzurillMale(pk.PID)) // recognized as not Azurill @@ -780,7 +824,7 @@ internal static bool IsCuteCharm4Valid(ISpeciesForm enc, PKM pk) /// /// There are some edge cases when the gender ratio changes across evolutions. /// - private static (ushort Species, int Gender) GetCuteCharmGenderSpecies(PKM pk, uint pid, ushort currentSpecies) => currentSpecies switch + private static (ushort Species, byte Gender) GetCuteCharmGenderSpecies(PKM pk, uint pid, ushort currentSpecies) => currentSpecies switch { // Nincada evo chain travels from M/F -> Genderless Shedinja (int)Species.Shedinja => ((int)Species.Nincada, EntityGender.GetFromPID((int)Species.Nincada, pid)), @@ -799,11 +843,20 @@ internal static bool IsCuteCharm4Valid(ISpeciesForm enc, PKM pk) (int)Species.Marill or (int)Species.Azumarill when IsCuteCharmAzurillMale(pid) => ((int)Species.Azurill, 0), // Future evolutions - (int)Species.Sylveon => ((int)Species.Eevee, pk.Gender), - (int)Species.MrRime => ((int)Species.MimeJr, pk.Gender), - (int)Species.Kleavor => ((int)Species.Scyther, pk.Gender), + _ => GetCuteCharmSpeciesGen4(currentSpecies, pk.Gender), + }; - _ => (currentSpecies, pk.Gender), + private static (ushort Species, byte Gender) GetCuteCharmSpeciesGen4(ushort species, byte gender) => species switch + { + <= Legal.MaxSpeciesID_4 => (species, gender), // has a valid personal reference, all good + (int)Species.Sylveon => ((int)Species.Eevee, gender), + (int)Species.MrRime => ((int)Species.MrMime, gender), + (int)Species.Wyrdeer => ((int)Species.Stantler, gender), + (int)Species.Kleavor => ((int)Species.Scyther, gender), + (int)Species.Sneasler => ((int)Species.Sneasel, gender), + (int)Species.Ursaluna => ((int)Species.Ursaring, gender), + (int)Species.Annihilape => ((int)Species.Primeape, gender), + _ => (species, gender), // throw an exception? Hitting here is an invalid case. }; public static PIDIV GetPokeSpotSeedFirst(PKM pk, byte slot) diff --git a/PKHeX.Core/Legality/RNG/Methods/Gen8/Overworld8RNG.cs b/PKHeX.Core/Legality/RNG/Methods/Gen8/Overworld8RNG.cs index b6f251ad0..b509e6f41 100644 --- a/PKHeX.Core/Legality/RNG/Methods/Gen8/Overworld8RNG.cs +++ b/PKHeX.Core/Legality/RNG/Methods/Gen8/Overworld8RNG.cs @@ -88,8 +88,8 @@ private static bool TryApplyFromSeed(PKM pk, EncounterCriteria criteria, Shiny s // Remainder var scale = (IScaledSize) pk; - scale.HeightScalar = (byte)((int) xoro.NextInt(0x81) + (int) xoro.NextInt(0x80)); - scale.WeightScalar = (byte)((int) xoro.NextInt(0x81) + (int) xoro.NextInt(0x80)); + scale.HeightScalar = (byte)(xoro.NextInt(0x81) + xoro.NextInt(0x80)); + scale.WeightScalar = (byte)(xoro.NextInt(0x81) + xoro.NextInt(0x80)); return true; } @@ -188,10 +188,10 @@ private static int GetIsMatchEnd(PKM pk, Xoroshiro128Plus xoro, int start = 0, i if (pk is not IScaledSize s) continue; - var height = (int) copy.NextInt(0x81) + (int) copy.NextInt(0x80); + var height = copy.NextInt(0x81) + copy.NextInt(0x80); if (s.HeightScalar != height) continue; - var weight = (int) copy.NextInt(0x81) + (int) copy.NextInt(0x80); + var weight = copy.NextInt(0x81) + copy.NextInt(0x80); if (s.WeightScalar != weight) continue; diff --git a/PKHeX.Core/Legality/RNG/Methods/Gen8/RaidRNG.cs b/PKHeX.Core/Legality/RNG/Methods/Gen8/RaidRNG.cs index 1cffcc2b7..fa3978b05 100644 --- a/PKHeX.Core/Legality/RNG/Methods/Gen8/RaidRNG.cs +++ b/PKHeX.Core/Legality/RNG/Methods/Gen8/RaidRNG.cs @@ -77,16 +77,16 @@ public static bool Verify(PKM pk, ulong seed, Span ivs, in GenerateParam8 p if (pk.IV_SPE != ivs[5]) return false; - int abil = param.Ability switch + int ability = param.Ability switch { AbilityPermission.Any12H => (int)rng.NextInt(3), AbilityPermission.Any12 => (int)rng.NextInt(2), _ => param.Ability.GetSingleValue(), }; - abil <<= 1; // 1/2/4 + ability <<= 1; // 1/2/4 var current = pk.AbilityNumber; - if (abil == 4) + if (ability == 4) { if (current != 4 && pk is PK8) return false; @@ -114,17 +114,17 @@ public static bool Verify(PKM pk, ulong seed, Span ivs, in GenerateParam8 p break; } - int nature = param.Nature != Nature.Random ? (int)param.Nature + var nature = param.Nature != Nature.Random ? param.Nature : param.Species == (int)Species.Toxtricity ? ToxtricityUtil.GetRandomNature(ref rng, pk.Form) - : (byte)rng.NextInt(25); + : (Nature)rng.NextInt(25); if (pk.Nature != nature) return false; if (pk is IScaledSize s) { - var height = (int)rng.NextInt(0x81) + (int)rng.NextInt(0x80); - var weight = (int)rng.NextInt(0x81) + (int)rng.NextInt(0x80); + var height = rng.NextInt(0x81) + rng.NextInt(0x80); + var weight = rng.NextInt(0x81) + rng.NextInt(0x80); if (height == 0 && weight == 0 && pk is IHomeTrack { HasTracker: true}) { // HOME rerolls height/weight if both are 0 @@ -219,34 +219,34 @@ public static bool TryApply(PK8 pk, ulong seed, Span ivs, in GenerateParam8 pk.IV_SPD = ivs[4]; pk.IV_SPE = ivs[5]; - int abil = param.Ability switch + int ability = param.Ability switch { AbilityPermission.Any12H => (int)rng.NextInt(3), AbilityPermission.Any12 => (int)rng.NextInt(2), _ => param.Ability.GetSingleValue(), }; - pk.RefreshAbility(abil); + pk.RefreshAbility(ability); - var gender = param.GenderRatio switch + byte gender = param.GenderRatio switch { PersonalInfo.RatioMagicGenderless => 2, PersonalInfo.RatioMagicFemale => 1, PersonalInfo.RatioMagicMale => 0, - _ => (int) rng.NextInt(253) + 1 < param.GenderRatio ? 1 : 0, + _ => rng.NextInt(253) + 1 < param.GenderRatio ? (byte)1 : (byte)0, }; - if (criteria.Gender != FixedGenderUtil.GenderRandom && gender != criteria.Gender) + if (!criteria.IsGenderSatisfied(gender)) return false; pk.Gender = gender; - int nature = param.Nature != Nature.Random ? (byte)param.Nature + var nature = param.Nature != Nature.Random ? param.Nature : param.Species == (int)Species.Toxtricity ? ToxtricityUtil.GetRandomNature(ref rng, pk.Form) - : (byte)rng.NextInt(25); + : (Nature)rng.NextInt(25); pk.Nature = pk.StatNature = nature; - var height = (int)rng.NextInt(0x81) + (int)rng.NextInt(0x80); - var weight = (int)rng.NextInt(0x81) + (int)rng.NextInt(0x80); + var height = rng.NextInt(0x81) + rng.NextInt(0x80); + var weight = rng.NextInt(0x81) + rng.NextInt(0x80); pk.HeightScalar = (byte)height; pk.WeightScalar = (byte)weight; diff --git a/PKHeX.Core/Legality/RNG/Methods/Gen8a/Overworld8aRNG.cs b/PKHeX.Core/Legality/RNG/Methods/Gen8a/Overworld8aRNG.cs index 7aab3eb1d..d6e45aaa1 100644 --- a/PKHeX.Core/Legality/RNG/Methods/Gen8a/Overworld8aRNG.cs +++ b/PKHeX.Core/Legality/RNG/Methods/Gen8a/Overworld8aRNG.cs @@ -161,24 +161,24 @@ public static bool TryApplyFromSeed(PKM pk, EncounterCriteria criteria, in Overw pk.RefreshAbility((int)rand.NextInt(2)); - int gender = para.GenderRatio switch + byte gender = para.GenderRatio switch { PersonalInfo.RatioMagicGenderless => 2, PersonalInfo.RatioMagicFemale => 1, PersonalInfo.RatioMagicMale => 0, - _ => (int)rand.NextInt(252) + 1 < para.GenderRatio ? 1 : 0, + _ => rand.NextInt(252) + 1 < para.GenderRatio ? (byte)1 : (byte)0, }; - if (gender != criteria.Gender && criteria.Gender != FixedGenderUtil.GenderRandom) + if (!criteria.IsGenderSatisfied(gender)) return false; pk.Gender = gender; - int nature = (int)rand.NextInt(25); + var nature = (Nature)rand.NextInt(25); pk.Nature = pk.StatNature = nature; var (height, weight) = para.IsAlpha ? (byte.MaxValue, byte.MaxValue) - : ((byte)((int)rand.NextInt(0x81) + (int)rand.NextInt(0x80)), - (byte)((int)rand.NextInt(0x81) + (int)rand.NextInt(0x80))); + : ((byte)(rand.NextInt(0x81) + rand.NextInt(0x80)), + (byte)(rand.NextInt(0x81) + rand.NextInt(0x80))); if (pk is IScaledSize s) { @@ -261,32 +261,32 @@ public static bool Verify(PKM pk, ulong seed, in OverworldParam8a para) if (pk.IV_SPE != ivs[5]) return false; - int abil = (int)rand.NextInt(2); - abil <<= 1; // 1/2/4 + int ability = (int)rand.NextInt(2); + ability <<= 1; // 1/2/4 var current = pk.AbilityNumber; - if (abil == 4 && current != 4) + if (ability == 4 && current != 4) return false; // else, for things that were made Hidden Ability, defer to Ability Checks (Ability Patch) - int gender = para.GenderRatio switch + byte gender = para.GenderRatio switch { PersonalInfo.RatioMagicGenderless => 2, PersonalInfo.RatioMagicFemale => 1, PersonalInfo.RatioMagicMale => 0, - _ => (int)rand.NextInt(252) + 1 < para.GenderRatio ? 1 : 0, + _ => rand.NextInt(252) + 1 < para.GenderRatio ? (byte)1 : (byte)0, }; if (pk.Gender != gender) return false; - var nature = (int)rand.NextInt(25); + var nature = (Nature)rand.NextInt(25); if (pk.Nature != nature) return false; var (height, weight) = para.IsAlpha ? (byte.MaxValue, byte.MaxValue) - : ((byte)((int)rand.NextInt(0x81) + (int)rand.NextInt(0x80)), - (byte)((int)rand.NextInt(0x81) + (int)rand.NextInt(0x80))); + : ((byte)(rand.NextInt(0x81) + rand.NextInt(0x80)), + (byte)(rand.NextInt(0x81) + rand.NextInt(0x80))); if (pk is IScaledSize s) { @@ -299,13 +299,13 @@ public static bool Verify(PKM pk, ulong seed, in OverworldParam8a para) return true; } - public static int GetRandomLevel(ulong slotSeed, byte LevelMin, byte LevelMax) + public static byte GetRandomLevel(ulong slotSeed, byte min, byte max) { - var delta = LevelMax - LevelMin; - var xoro = new Xoroshiro128Plus(slotSeed); - xoro.Next(); - xoro.Next(); // slot, entitySeed - var amp = (int)xoro.NextInt((ulong)delta + 1); - return LevelMin + amp; + var delta = 1ul + max - min; + var rnd = new Xoroshiro128Plus(slotSeed); + rnd.Next(); + rnd.Next(); // slot, entitySeed + var amp = (byte)rnd.NextInt(delta); + return (byte)(min + amp); } } diff --git a/PKHeX.Core/Legality/RNG/Methods/Gen8b/Roaming8bRNG.cs b/PKHeX.Core/Legality/RNG/Methods/Gen8b/Roaming8bRNG.cs index bbddafd6d..ae6ef0064 100644 --- a/PKHeX.Core/Legality/RNG/Methods/Gen8b/Roaming8bRNG.cs +++ b/PKHeX.Core/Legality/RNG/Methods/Gen8b/Roaming8bRNG.cs @@ -21,8 +21,8 @@ public static void ApplyDetails(PKM pk, EncounterCriteria criteria, Shiny shiny flawless = 0; // Since the inner methods do not set Gender (only fixed Genders are applicable) and Nature (assume Synchronize used), set them here. - pk.Gender = pk.Species == (int)Species.Cresselia ? 1 : 2; // Mesprit - pk.Nature = pk.StatNature = (int)criteria.GetNature(); + pk.Gender = (byte)(pk.Species == (int)Species.Cresselia ? 1 : 2); // Mesprit + pk.Nature = pk.StatNature = criteria.GetNature(); int ctr = 0; var rnd = Util.Rand; @@ -101,8 +101,8 @@ private static bool TryApplyFromSeed(PKM pk, EncounterCriteria criteria, Shiny s // Remainder var scale = (IScaledSize)pk; - scale.HeightScalar = (byte)((int)xoro.NextUInt(0x81) + (int)xoro.NextUInt(0x80)); - scale.WeightScalar = (byte)((int)xoro.NextUInt(0x81) + (int)xoro.NextUInt(0x80)); + scale.HeightScalar = (byte)(xoro.NextUInt(0x81) + xoro.NextUInt(0x80)); + scale.WeightScalar = (byte)(xoro.NextUInt(0x81) + xoro.NextUInt(0x80)); return true; } @@ -180,7 +180,7 @@ private static bool GetIsMatchEnd(PKM pk, Xoroshiro128Plus8b xoro) } // Check that the nature matches - if (pk.Nature != (int)xoro.NextUInt(25)) + if (pk.Nature != (Nature)xoro.NextUInt(25)) return false; return GetIsHeightWeightMatch(pk, xoro); @@ -192,7 +192,7 @@ private static bool GetIsMatchEndWithCuteCharm(PKM pk, Xoroshiro128Plus8b xoro) // Assume that the gender is a match due to cute charm. // Check that the nature matches - if (pk.Nature != (int)xoro.NextUInt(25)) + if (pk.Nature != (Nature)xoro.NextUInt(25)) return false; return GetIsHeightWeightMatch(pk, xoro); diff --git a/PKHeX.Core/Legality/RNG/Methods/Gen8b/Wild8bRNG.cs b/PKHeX.Core/Legality/RNG/Methods/Gen8b/Wild8bRNG.cs index 8eef9016c..37986e1c2 100644 --- a/PKHeX.Core/Legality/RNG/Methods/Gen8b/Wild8bRNG.cs +++ b/PKHeX.Core/Legality/RNG/Methods/Gen8b/Wild8bRNG.cs @@ -121,22 +121,22 @@ public static bool TryApplyFromSeed(PKM pk, EncounterCriteria criteria, Shiny sh } else { - var next = (((int)xors.NextUInt(253) + 1 < genderRatio) ? 1 : 0); - if (criteria.Gender is 0 or 1 && next != criteria.Gender) + byte gender = xors.NextUInt(253) + 1 < genderRatio ? (byte)1 : (byte)0; + if (!criteria.IsGenderSatisfied(gender)) return false; - pk.Gender = next; + pk.Gender = gender; } - if (criteria.Nature is Nature.Random) - pk.Nature = (int)xors.NextUInt(25); + if (!criteria.IsSpecifiedNature()) + pk.Nature = (Nature)xors.NextUInt(25); else // Skip nature, assuming Synchronize - pk.Nature = (int)criteria.Nature; + pk.Nature = criteria.Nature; pk.StatNature = pk.Nature; // Remainder var scale = (IScaledSize)pk; - scale.HeightScalar = (byte)((int)xors.NextUInt(0x81) + (int)xors.NextUInt(0x80)); - scale.WeightScalar = (byte)((int)xors.NextUInt(0x81) + (int)xors.NextUInt(0x80)); + scale.HeightScalar = (byte)(xors.NextUInt(0x81) + xors.NextUInt(0x80)); + scale.WeightScalar = (byte)(xors.NextUInt(0x81) + xors.NextUInt(0x80)); // Item, don't care return true; diff --git a/PKHeX.Core/Legality/RNG/Methods/Gen9/Encounter9RNG.cs b/PKHeX.Core/Legality/RNG/Methods/Gen9/Encounter9RNG.cs index 3287850bb..6e032851b 100644 --- a/PKHeX.Core/Legality/RNG/Methods/Gen9/Encounter9RNG.cs +++ b/PKHeX.Core/Legality/RNG/Methods/Gen9/Encounter9RNG.cs @@ -27,7 +27,7 @@ public static bool TryApply32(this TEnc enc, PK9 pk, in ulong init, in Gen var type = Tera9RNG.GetTeraType(seed, enc.TeraType, enc.Species, enc.Form); pk.TeraTypeOriginal = (MoveType)type; - if (criteria.TeraType != -1 && type != criteria.TeraType && TeraTypeUtil.CanChangeTeraType(enc.Species)) + if (criteria.IsSpecifiedTeraType() && type != criteria.TeraType && TeraTypeUtil.CanChangeTeraType(enc.Species)) pk.SetTeraType((MoveType)criteria.TeraType); // sets the override type return true; // done. } @@ -47,7 +47,7 @@ public static bool TryApply64(this TEnc enc, PK9 pk, in ulong init, in Gen var type = Tera9RNG.GetTeraType(seed, enc.TeraType, enc.Species, enc.Form); pk.TeraTypeOriginal = (MoveType)type; - if (criteria.TeraType != -1 && type != criteria.TeraType && TeraTypeUtil.CanChangeTeraType(enc.Species)) + if (criteria.IsSpecifiedTeraType() && type != criteria.TeraType && TeraTypeUtil.CanChangeTeraType(enc.Species)) pk.SetTeraType((MoveType)criteria.TeraType); // sets the override type return true; // done. } @@ -98,30 +98,30 @@ public static bool GenerateData(PK9 pk, in GenerateParam9 enc, EncounterCriteria pk.IV_SPD = ivs[4]; pk.IV_SPE = ivs[5]; - int abil = enc.Ability switch + int ability = enc.Ability switch { AbilityPermission.Any12H => (int)rand.NextInt(3) << 1, AbilityPermission.Any12 => (int)rand.NextInt(2) << 1, _ => (int)enc.Ability, }; - pk.RefreshAbility(abil >> 1); + pk.RefreshAbility(ability >> 1); var gender_ratio = enc.GenderRatio; - int gender = gender_ratio switch + byte gender = gender_ratio switch { PersonalInfo.RatioMagicGenderless => 2, PersonalInfo.RatioMagicFemale => 1, PersonalInfo.RatioMagicMale => 0, _ => GetGender(gender_ratio, rand.NextInt(100)), }; - if (criteria.Gender != FixedGenderUtil.GenderRandom && gender != criteria.Gender) + if (!criteria.IsGenderSatisfied(gender)) return false; pk.Gender = gender; - byte nature = enc.Nature != Nature.Random ? (byte)enc.Nature : enc.Species == (int)Species.Toxtricity + var nature = enc.Nature != Nature.Random ? enc.Nature : enc.Species == (int)Species.Toxtricity ? ToxtricityUtil.GetRandomNature(ref rand, pk.Form) - : (byte)rand.NextInt(25); - if (criteria.Nature != Nature.Random && nature != (int)criteria.Nature) + : (Nature)rand.NextInt(25); + if (criteria.Nature != Nature.Random && nature != criteria.Nature) return false; pk.Nature = pk.StatNature = nature; @@ -182,7 +182,7 @@ public static bool IsMatch(PKM pk, in GenerateParam9 enc, in ulong seed) // Ability can be changed by Capsule/Patch. // Defer this check to later. // ReSharper disable once UnusedVariable - int abil = enc.Ability switch + int ability = enc.Ability switch { AbilityPermission.Any12H => (int)rand.NextInt(3) << 1, AbilityPermission.Any12 => (int)rand.NextInt(2) << 1, @@ -190,7 +190,7 @@ public static bool IsMatch(PKM pk, in GenerateParam9 enc, in ulong seed) }; var gender_ratio = enc.GenderRatio; - int gender = gender_ratio switch + byte gender = gender_ratio switch { PersonalInfo.RatioMagicGenderless => 2, PersonalInfo.RatioMagicFemale => 1, @@ -200,21 +200,21 @@ public static bool IsMatch(PKM pk, in GenerateParam9 enc, in ulong seed) if (pk.Gender != gender) return false; - byte nature = enc.Nature != Nature.Random ? (byte)enc.Nature : enc.Species == (int)Species.Toxtricity + var nature = enc.Nature != Nature.Random ? enc.Nature : enc.Species == (int)Species.Toxtricity ? ToxtricityUtil.GetRandomNature(ref rand, pk.Form) - : (byte)rand.NextInt(25); + : (Nature)rand.NextInt(25); if (pk.Nature != nature) return false; if (enc.Height == 0) { - var value = (int)rand.NextInt(0x81) + (int)rand.NextInt(0x80); + var value = (byte)(rand.NextInt(0x81) + rand.NextInt(0x80)); if (!IsHeightMatchSV(pk, value)) return false; } if (enc.Weight == 0) { - var value = (int)rand.NextInt(0x81) + (int)rand.NextInt(0x80); + var value = (byte)(rand.NextInt(0x81) + rand.NextInt(0x80)); if (pk is IScaledSize s && s.WeightScalar != value) return false; } @@ -235,7 +235,7 @@ public static bool IsMatch(PKM pk, in GenerateParam9 enc, in ulong seed) return true; } - public static bool IsHeightMatchSV(PKM pk, int value) + public static bool IsHeightMatchSV(PKM pk, byte value) { // HOME copies Scale to Height. Untouched by HOME must match the value. // Viewing the save file in HOME will alter it too. Tracker definitely indicates it was viewed. @@ -296,13 +296,13 @@ private static uint GetAdaptedPID(ref Xoroshiro128Plus rand, PKM pk, in Generate return pid; } - public static int GetGender(in int ratio, in ulong rand100) => ratio switch + public static byte GetGender(in int ratio, in ulong rand100) => ratio switch { - 0x1F => rand100 < 12 ? 1 : 0, // 12.5% - 0x3F => rand100 < 25 ? 1 : 0, // 25% - 0x7F => rand100 < 50 ? 1 : 0, // 50% - 0xBF => rand100 < 75 ? 1 : 0, // 75% - 0xE1 => rand100 < 89 ? 1 : 0, // 87.5% + 0x1F => rand100 < 12 ? (byte)1 : (byte)0, // 12.5% + 0x3F => rand100 < 25 ? (byte)1 : (byte)0, // 25% + 0x7F => rand100 < 50 ? (byte)1 : (byte)0, // 50% + 0xBF => rand100 < 75 ? (byte)1 : (byte)0, // 75% + 0xE1 => rand100 < 89 ? (byte)1 : (byte)0, // 87.5% _ => throw new ArgumentOutOfRangeException(nameof(ratio)), }; diff --git a/PKHeX.Core/Legality/RNG/PIDGenerator.cs b/PKHeX.Core/Legality/RNG/PIDGenerator.cs index 102996ed7..6021bbc8c 100644 --- a/PKHeX.Core/Legality/RNG/PIDGenerator.cs +++ b/PKHeX.Core/Legality/RNG/PIDGenerator.cs @@ -144,9 +144,9 @@ private static void SetValuesFromSeedChannel(PKM pk, uint seed) if ((pid2 > 7 ? 0 : 1) != (pid1 ^ SID16 ^ TID16)) pid ^= 0x80000000; pk.PID = pid; - pk.HeldItem = (int)(C >> 31) + 169; // 0-Ganlon, 1-Salac - pk.Version = (int)(D >> 31) + 1; // 0-Sapphire, 1-Ruby - pk.OT_Gender = (int)(E >> 31); + pk.HeldItem = (ushort)(C >> 31) + 169; // 0-Ganlon, 1-Salac + pk.Version = GameVersion.S + (byte)(D >> 31); // 0-Sapphire, 1-Ruby + pk.OriginalTrainerGender = (byte)(E >> 31); Span ivs = stackalloc int[6]; XDRNG.GetSequentialIVsInt32(E, ivs); pk.SetIVs(ivs); @@ -225,7 +225,7 @@ private static void SetRandomPokeSpotPID(PKM pk, uint seed) pk.PID = (D & 0xFFFF0000) | (E >> 16); } - public static void SetRandomPokeSpotPID(PKM pk, int nature, int gender, int ability, int slot) + public static void SetRandomPokeSpotPID(PKM pk, Nature nature, byte gender, int ability, int slot) { var rnd = Util.Rand; while (true) @@ -260,7 +260,7 @@ public static void SetValuesFromSeedMG5Shiny(PKM pk, uint seed) SetRandomIVs(pk); } - public static void SetRandomWildPID4(PKM pk, int nature, int ability, int gender, PIDType type) + public static uint SetRandomWildPID4(PKM pk, Nature nature, int ability, byte gender, PIDType type) { pk.RefreshAbility(ability); pk.Gender = gender; @@ -269,14 +269,15 @@ public static void SetRandomWildPID4(PKM pk, int nature, int ability, int gender var rnd = Util.Rand; while (true) { - method(pk, rnd.Rand32()); + var seed = rnd.Rand32(); + method(pk, seed); if (!IsValidCriteria4(pk, nature, ability, gender)) continue; - return; + return seed; } } - public static bool IsValidCriteria4(PKM pk, int nature, int ability, int gender) + public static bool IsValidCriteria4(PKM pk, Nature nature, int ability, byte gender) { if (pk.GetSaneGender() != gender) return false; @@ -290,7 +291,7 @@ public static bool IsValidCriteria4(PKM pk, int nature, int ability, int gender) return true; } - public static void SetRandomWildPID5(PKM pk, int nature, int ability, int gender, PIDType specific = PIDType.None) + public static void SetRandomWildPID5(PKM pk, Nature nature, int ability, byte gender, PIDType specific = PIDType.None) { var tidbit = (pk.TID16 ^ pk.SID16) & 1; pk.RefreshAbility(ability); diff --git a/PKHeX.Core/Legality/RNG/PIDIV.cs b/PKHeX.Core/Legality/RNG/PIDIV.cs index e76c9ad0f..78765547e 100644 --- a/PKHeX.Core/Legality/RNG/PIDIV.cs +++ b/PKHeX.Core/Legality/RNG/PIDIV.cs @@ -1,22 +1,58 @@ -namespace PKHeX.Core; +using System.Runtime.InteropServices; + +namespace PKHeX.Core; /// /// Stores details about a (PID) and any associated details being traced to a known correlation. /// -/// Type of PIDIV correlation -/// The RNG seed which immediately generates the PIDIV (starting with PID or IVs, whichever comes first) -public readonly record struct PIDIV(PIDType Type, uint OriginSeed = 0) +[StructLayout(LayoutKind.Explicit, Size = 10)] +public readonly struct PIDIV { internal static readonly PIDIV None = new(); - internal static readonly PIDIV CuteCharm = new(PIDType.CuteCharm); + internal static readonly PIDIV CuteCharm = new(PIDType.CuteCharm); // can be one of many seeds! internal static readonly PIDIV Pokewalker = new(PIDType.Pokewalker); internal static readonly PIDIV G5MGShiny = new(PIDType.G5MGShiny); - /// Indicates that there is no to refer to. + /// The RNG seed which immediately generates the PIDIV (starting with PID or IVs, whichever comes first) + [field: FieldOffset(0)] + public uint OriginSeed { get; } + /// The RNG seed which starts the encounter generation routine. + [field: FieldOffset(4)] + public uint EncounterSeed { get; init; } + + /// The RNG seed which immediately generates the PIDIV (starting with PID or IVs, whichever comes first) + [field: FieldOffset(0)] + public ulong Seed64 { get; } + + /// Type of PIDIV correlation + [field: FieldOffset(8)] + public PIDType Type { get; } + + [field: FieldOffset(9)] + public LeadRequired Lead { get; init; } + + public PIDIV(PIDType type, uint seed = 0) + { + Type = type; + OriginSeed = seed; + } + + public PIDIV(PIDType type, ulong seed) + { + Type = type; + Seed64 = seed; + } + /// Some PIDIVs may be generated without a single seed, but may follow a traceable pattern. - public bool NoSeed => Type is PIDType.None or PIDType.CuteCharm or PIDType.Pokewalker or PIDType.G5MGShiny; + /// Indicates that there is no to refer to. + public bool NoSeed => Type is PIDType.None or PIDType.Pokewalker or PIDType.G5MGShiny; #if DEBUG public override string ToString() => NoSeed ? Type.ToString() : $"{Type} - 0x{OriginSeed:X8}"; #endif + public bool IsClassicMethod() => Type.IsClassicMethod(); + + public bool IsSeed64() => false; + + public PIDIV AsEncounteredVia(LeadSeed condition) => this with { Lead = condition.Lead, EncounterSeed = condition.Seed }; } diff --git a/PKHeX.Core/Legality/RNG/PIDType.cs b/PKHeX.Core/Legality/RNG/PIDType.cs index 0ac273108..08b21af60 100644 --- a/PKHeX.Core/Legality/RNG/PIDType.cs +++ b/PKHeX.Core/Legality/RNG/PIDType.cs @@ -1,10 +1,12 @@ +using static PKHeX.Core.PIDType; + namespace PKHeX.Core; /// /// PID + IV correlation. /// /// This is just a catch-all enumeration to describe the different correlations. -public enum PIDType +public enum PIDType : byte { /// No relationship between the PID and IVs None, @@ -27,19 +29,19 @@ public enum PIDType /// Method_4, - /// Method H1_Unown (FRLG) + /// Method H1_Unown (FR/LG) /// Method_1_Unown, - /// Method H2_Unown (FRLG) + /// Method H2_Unown (FR/LG) /// Method_2_Unown, - /// Method H3_Unown (FRLG) + /// Method H3_Unown (FR/LG) /// Method_3_Unown, - /// Method H4_Unown (FRLG) + /// Method H4_Unown (FR/LG) /// Method_4_Unown, @@ -60,13 +62,13 @@ public enum PIDType BACD_U, /// - /// Event Reversed Order PID restricted to 16bit Origin Seed, antishiny. + /// Event Reversed Order PID restricted to 16bit Origin Seed, anti-shiny. /// /// seed is clamped to 16bits. BACD_R_A, /// - /// Event Reversed Order PID without Origin Seed restrictions, antishiny. + /// Event Reversed Order PID without Origin Seed restrictions, anti-shiny. /// /// BACD_U_A, @@ -84,13 +86,13 @@ public enum PIDType BACD_U_S, /// - /// Event Reversed Order PID restricted to 16bit Origin Seed, antishiny (nyx) + /// Event Reversed Order PID restricted to 16bit Origin Seed, anti-shiny (nyx) /// /// seed is clamped to 16bits. BACD_R_AX, /// - /// Event Reversed Order PID without Origin Seed restrictions, antishiny (nyx) + /// Event Reversed Order PID without Origin Seed restrictions, anti-shiny (nyx) /// /// BACD_U_AX, @@ -195,3 +197,13 @@ public enum PIDType #endregion } + +public static class PIDTypeExtensions +{ + /// + /// Checks if the provided PIDType is one of the in-game Method-X types for Gen3. + /// + public static bool IsClassicMethod(this PIDType type) => type + is Method_1 or Method_2 or Method_3 or Method_4 + or Method_1_Unown or Method_2_Unown or Method_3_Unown or Method_4_Unown; +} diff --git a/PKHeX.Core/Legality/RNG/Util/ToxtricityUtil.cs b/PKHeX.Core/Legality/RNG/Util/ToxtricityUtil.cs index 7ba2684fc..58f7c5d6b 100644 --- a/PKHeX.Core/Legality/RNG/Util/ToxtricityUtil.cs +++ b/PKHeX.Core/Legality/RNG/Util/ToxtricityUtil.cs @@ -18,10 +18,10 @@ public static class ToxtricityUtil /// Random number generator /// Desired Toxtricity form /// 0 for Amped, 1 for Low Key - public static byte GetRandomNature(ref Xoroshiro128Plus rand, byte form) + public static Nature GetRandomNature(ref Xoroshiro128Plus rand, byte form) { var table = form == 0 ? Nature0 : Nature1; - return table[(int)rand.NextInt((uint)table.Length)]; + return (Nature)table[(int)rand.NextInt((uint)table.Length)]; } /// @@ -29,11 +29,11 @@ public static byte GetRandomNature(ref Xoroshiro128Plus rand, byte form) /// /// Entity nature /// 0 for Amped, 1 for Low Key - public static int GetAmpLowKeyResult(int nature) + public static int GetAmpLowKeyResult(Nature nature) { var index = nature - 1; if ((uint)index > 22) return 0; - return (0b_0101_1011_1100_1010_0101_0001 >> index) & 1; + return (0b_0101_1011_1100_1010_0101_0001 >> (int)index) & 1; } } diff --git a/PKHeX.Core/Legality/Restrictions/GBRestrictions.cs b/PKHeX.Core/Legality/Restrictions/GBRestrictions.cs index ef96205e1..5155f906c 100644 --- a/PKHeX.Core/Legality/Restrictions/GBRestrictions.cs +++ b/PKHeX.Core/Legality/Restrictions/GBRestrictions.cs @@ -101,7 +101,7 @@ private static bool RateMatchesEither(byte rate, ushort species) private static bool GetCatchRateMatchesPreEvolution(PK1 pk, byte rate) { // For species catch rate, discard any species that has no valid encounters and a different catch rate than their pre-evolutions - var head = new EvoCriteria { Species = pk.Species, Form = pk.Form, LevelMax = (byte)pk.CurrentLevel }; // as struct to avoid boxing + var head = new EvoCriteria { Species = pk.Species, Form = pk.Form, LevelMax = pk.CurrentLevel }; // as struct to avoid boxing do { var species = head.Species; diff --git a/PKHeX.Core/Legality/Restrictions/Memories/MemoryContext.cs b/PKHeX.Core/Legality/Restrictions/Memories/MemoryContext.cs index 2f41e99c9..fd5c71d6a 100644 --- a/PKHeX.Core/Legality/Restrictions/Memories/MemoryContext.cs +++ b/PKHeX.Core/Legality/Restrictions/Memories/MemoryContext.cs @@ -19,7 +19,7 @@ public abstract class MemoryContext public abstract bool CanObtainMemoryOT(GameVersion pkmVersion, byte memory); public abstract bool CanObtainMemoryHT(GameVersion pkmVersion, byte memory); - public abstract bool HasPokeCenter(GameVersion version, int location); + public abstract bool HasPokeCenter(GameVersion version, ushort location); public abstract bool IsInvalidGeneralLocationMemoryValue(byte memory, ushort variable, IEncounterTemplate enc, PKM pk); public abstract bool IsInvalidMiscMemory(byte memory, ushort variable); diff --git a/PKHeX.Core/Legality/Restrictions/Memories/MemoryContext6.cs b/PKHeX.Core/Legality/Restrictions/Memories/MemoryContext6.cs index 7eed98c64..bfac88b47 100644 --- a/PKHeX.Core/Legality/Restrictions/Memories/MemoryContext6.cs +++ b/PKHeX.Core/Legality/Restrictions/Memories/MemoryContext6.cs @@ -38,7 +38,7 @@ private static ReadOnlySpan GetPokeCenterLocations(GameVersion game) return GameVersion.XY.Contains(game) ? LocationsWithPokeCenter_XY : LocationsWithPokeCenter_AO; } - public static bool GetHasPokeCenterLocation(GameVersion game, int loc) + public static bool GetHasPokeCenterLocation(GameVersion game, ushort loc) { if (game == GameVersion.Any) return GetHasPokeCenterLocation(GameVersion.X, loc) || GetHasPokeCenterLocation(GameVersion.AS, loc); @@ -84,7 +84,7 @@ public override IEnumerable GetMemoryItemParams() }; public override bool CanObtainMemory(byte memory) => memory <= MAX_MEMORY_ID_AO; - public override bool HasPokeCenter(GameVersion version, int location) => GetHasPokeCenterLocation(version, location); + public override bool HasPokeCenter(GameVersion version, ushort location) => GetHasPokeCenterLocation(version, location); public override bool IsInvalidGeneralLocationMemoryValue(byte memory, ushort variable, IEncounterTemplate enc, PKM pk) { diff --git a/PKHeX.Core/Legality/Restrictions/Memories/MemoryContext6Data.cs b/PKHeX.Core/Legality/Restrictions/Memories/MemoryContext6Data.cs index 57cd78114..559f9e640 100644 --- a/PKHeX.Core/Legality/Restrictions/Memories/MemoryContext6Data.cs +++ b/PKHeX.Core/Legality/Restrictions/Memories/MemoryContext6Data.cs @@ -173,6 +173,9 @@ public partial class MemoryContext6 0001, 0033, 0050, 0051, 0053, ]; + /// + /// Bitflag array with set bits indicating if the species ID can be captured in . + /// public static ReadOnlySpan CaptureFlagsX => [ 0xB6, 0x75, 0xE1, 0x7B, 0xCB, 0x5A, 0x4A, 0xF5, 0x6C, 0xAD, 0x9C, 0xAA, 0x65, 0x93, 0xFF, 0xFF, @@ -183,6 +186,9 @@ public partial class MemoryContext6 0x00, 0x6C, 0x7B, 0x7F, 0xB7, 0x54, 0x73, 0xE5, 0x7B, 0x55, ]; + /// + /// Bitflag array with set bits indicating if the species ID can be captured in . + /// public static ReadOnlySpan CaptureFlagsY => [ 0xB6, 0x7D, 0xE1, 0x7B, 0xCB, 0x5A, 0x4A, 0xF5, 0x6C, 0xAD, 0x9C, 0xAE, 0x65, 0x93, 0xFF, 0xFC, @@ -193,6 +199,9 @@ public partial class MemoryContext6 0x00, 0x6C, 0x7B, 0x7F, 0xB7, 0x54, 0x4F, 0xE5, 0x7B, 0x65, ]; + /// + /// Bitflag array with set bits indicating if the species ID can be captured in . + /// public static ReadOnlySpan CaptureFlagsAS => [ 0x00, 0x40, 0x1A, 0x0A, 0xA8, 0x5E, 0x66, 0x85, 0x04, 0xAF, 0xD2, 0x81, 0x36, 0xA0, 0xF4, 0x81, @@ -203,6 +212,9 @@ public partial class MemoryContext6 0x75, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x05, 0x18, ]; + /// + /// Bitflag array with set bits indicating if the species ID can be captured in . + /// public static ReadOnlySpan CaptureFlagsOR => [ 0x00, 0x40, 0x1A, 0x0A, 0xA8, 0x5E, 0x66, 0x85, 0x04, 0xAF, 0xD2, 0x81, 0x36, 0xA0, 0xF4, 0x81, diff --git a/PKHeX.Core/Legality/Restrictions/Memories/MemoryContext8.cs b/PKHeX.Core/Legality/Restrictions/Memories/MemoryContext8.cs index 71ebdda8b..01648db8d 100644 --- a/PKHeX.Core/Legality/Restrictions/Memories/MemoryContext8.cs +++ b/PKHeX.Core/Legality/Restrictions/Memories/MemoryContext8.cs @@ -55,7 +55,7 @@ public override IEnumerable GetMemoryItemParams() public override bool CanObtainMemoryHT(GameVersion pkmVersion, byte memory) => CanObtainMemorySWSH(memory); public override bool CanObtainMemory(byte memory) => CanObtainMemorySWSH(memory); - public override bool HasPokeCenter(GameVersion version, int location) => location == 9; // in a Pokémon Center + public override bool HasPokeCenter(GameVersion version, ushort location) => location == 9; // in a Pokémon Center public override bool IsInvalidGeneralLocationMemoryValue(byte memory, ushort variable, IEncounterTemplate enc, PKM pk) { @@ -64,7 +64,7 @@ public override bool IsInvalidGeneralLocationMemoryValue(byte memory, ushort var return false; if (memory is 1 or 2 or 3) // Encounter only - return IsInvalidGenLoc8(memory, pk.Met_Location, pk.Egg_Location, variable, pk, enc); + return IsInvalidGenLoc8(memory, pk.MetLocation, pk.EggLocation, variable, pk, enc); return IsInvalidGenLoc8Other(memory, variable); } @@ -89,7 +89,7 @@ public override bool IsInvalidMiscMemory(byte memory, ushort variable) _ => ItemStorage8SWSH.IsTechRecord((ushort)item) || PurchaseItemsNoTR.BinarySearch((ushort)item) >= 0, }; - private static bool IsInvalidGenLoc8(byte memory, int loc, int egg, ushort variable, PKM pk, IEncounterTemplate enc) + private static bool IsInvalidGenLoc8(byte memory, ushort loc, int egg, ushort variable, PKM pk, IEncounterTemplate enc) { if (variable > 255) return true; diff --git a/PKHeX.Core/Legality/Restrictions/Memories/MemoryContext8Data.cs b/PKHeX.Core/Legality/Restrictions/Memories/MemoryContext8Data.cs index 07b14c72d..f54fbb403 100644 --- a/PKHeX.Core/Legality/Restrictions/Memories/MemoryContext8Data.cs +++ b/PKHeX.Core/Legality/Restrictions/Memories/MemoryContext8Data.cs @@ -101,13 +101,13 @@ public partial class MemoryContext8 private static ReadOnlySpan MultiLoc206 => [ 04, 37 ]; // town of Freezington: someone’s house, snowcapped town private static ReadOnlySpan MultiLoc220 => [ 53, 65 ];// at the Crown Shrine: on a snow-swept road, in a mystical place - private static bool IsMultiGenLocArea(int location, out ReadOnlySpan expect) + private static bool IsMultiGenLocArea(ushort location, out ReadOnlySpan expect) { expect = GetMultiGenLocAreaList(location); return expect.Length != 0; } - private static ReadOnlySpan GetMultiGenLocAreaList(int location) => location switch + private static ReadOnlySpan GetMultiGenLocAreaList(ushort location) => location switch { 006 => MultiLoc006, 014 => MultiLoc014, @@ -128,7 +128,7 @@ private static bool IsMultiGenLocArea(int location, out ReadOnlySpan expec _ => [], }; - private static bool IsSingleGenLocArea(int location, out byte expect) + private static bool IsSingleGenLocArea(ushort location, out byte expect) { var arr = SingleGenLocAreas; if ((location & 1) != 0 || (uint)(location >>= 1) >= arr.Length) @@ -316,6 +316,9 @@ private static bool IsSingleGenLocArea(int location, out byte expect) 0x8FFBFA, 0x8CDFFA, 0xFCE9EF, 0x8F6F7B, 0x826AB0, 0x866AB0, 0x8C69FE, 0x776AB0, 0x8CFB7A, 0x0CFEBA, ]; + /// + /// Bitflag array with set bits indicating if the species ID can be captured in . + /// public static ReadOnlySpan CaptureFlagsSW => [ 0xFE, 0x1F, 0x00, 0xFE, 0xFF, 0x3F, 0xFC, 0xFC, 0x1F, 0xE3, 0x0F, 0xFC, 0xCC, 0xFF, 0xFF, 0xFF, @@ -328,6 +331,9 @@ private static bool IsSingleGenLocArea(int location, out byte expect) 0x07, ]; + /// + /// Bitflag array with set bits indicating if the species ID can be captured in . + /// public static ReadOnlySpan CaptureFlagsSH => [ 0xFE, 0x1F, 0x00, 0xFE, 0xFF, 0x3F, 0xFC, 0xFC, 0x1F, 0xE3, 0x0F, 0xFC, 0xCC, 0xFF, 0xFF, 0xFF, diff --git a/PKHeX.Core/Legality/Restrictions/Memories/MemoryPermissions.cs b/PKHeX.Core/Legality/Restrictions/Memories/MemoryPermissions.cs index f2cd58c0c..46f16e4b2 100644 --- a/PKHeX.Core/Legality/Restrictions/Memories/MemoryPermissions.cs +++ b/PKHeX.Core/Legality/Restrictions/Memories/MemoryPermissions.cs @@ -169,16 +169,16 @@ public static bool GetCanKnowMove(IEncounterTemplate enc, ushort move, Evolution return result[0].Valid; } - public static bool GetCanBeCaptured(ushort species, EntityContext gen, GameVersion version) => gen switch + public static bool GetCanBeCaptured(ushort species, EntityContext context, GameVersion version) => context switch { EntityContext.Gen6 => MemoryContext6.GetCanBeCaptured(species, version), EntityContext.Gen8 => MemoryContext8.GetCanBeCaptured(species, version), _ => false, }; - public static bool GetCanDynamaxTrainer(ushort species, int gen, GameVersion version) + public static bool GetCanDynamaxTrainer(ushort species, byte generation, GameVersion version) { - if (gen != 8) + if (generation != 8) return false; return version switch diff --git a/PKHeX.Core/Legality/Restrictions/Memories/MemoryRules.cs b/PKHeX.Core/Legality/Restrictions/Memories/MemoryRules.cs index f19b02d78..0ac6c5258 100644 --- a/PKHeX.Core/Legality/Restrictions/Memories/MemoryRules.cs +++ b/PKHeX.Core/Legality/Restrictions/Memories/MemoryRules.cs @@ -40,7 +40,7 @@ public static MemorySource ReviseSourcesHandler(PKM pk, MemorySource sources, IE // Traded eggs in SW/SH set HT memory but not HT Name. if (enc is { Context: EntityContext.Gen8, EggEncounter: true } && pk.Context is EntityContext.Gen8) { - var loc = pk.IsEgg ? pk.Met_Location : pk.Egg_Location; + var loc = pk.IsEgg ? pk.MetLocation : pk.EggLocation; if (loc == Locations.LinkTrade6) return sources; // OK } @@ -49,7 +49,7 @@ public static MemorySource ReviseSourcesHandler(PKM pk, MemorySource sources, IE } // Any Gen6 or Bank specific memory on Switch must have no HT language or else it would be replaced/erased. - if (pk is IHandlerLanguage { HT_Language: not 0 }) // Gen8+ Memory Required + if (pk is IHandlerLanguage { HandlingTrainerLanguage: not 0 }) // Gen8+ Memory Required sources &= ~(MemorySource.Gen6 | MemorySource.Bank); return sources; diff --git a/PKHeX.Core/Legality/Restrictions/Memories/MemoryVariableSet.cs b/PKHeX.Core/Legality/Restrictions/Memories/MemoryVariableSet.cs index 2dc6cc4a6..5faa64026 100644 --- a/PKHeX.Core/Legality/Restrictions/Memories/MemoryVariableSet.cs +++ b/PKHeX.Core/Legality/Restrictions/Memories/MemoryVariableSet.cs @@ -14,8 +14,8 @@ namespace PKHeX.Core; { public static MemoryVariableSet Read(ITrainerMemories pk, int handler) => handler switch { - 0 => new(L_XOT, pk.OT_Memory, pk.OT_TextVar, pk.OT_Intensity, pk.OT_Feeling), // OT - 1 => new(L_XHT, pk.HT_Memory, pk.HT_TextVar, pk.HT_Intensity, pk.HT_Feeling), // HT + 0 => new(L_XOT, pk.OriginalTrainerMemory, pk.OriginalTrainerMemoryVariable, pk.OriginalTrainerMemoryIntensity, pk.OriginalTrainerMemoryFeeling), // OT + 1 => new(L_XHT, pk.HandlingTrainerMemory, pk.HandlingTrainerMemoryVariable, pk.HandlingTrainerMemoryIntensity, pk.HandlingTrainerMemoryFeeling), // HT _ => new(L_XOT, 0, 0, 0, 0), }; } diff --git a/PKHeX.Core/Legality/Structures/CheckIdentifier.cs b/PKHeX.Core/Legality/Structures/CheckIdentifier.cs index 2ab32dfd9..ee9945a5e 100644 --- a/PKHeX.Core/Legality/Structures/CheckIdentifier.cs +++ b/PKHeX.Core/Legality/Structures/CheckIdentifier.cs @@ -54,7 +54,7 @@ public enum CheckIdentifier : byte Nickname, /// - /// The pertains to the , , or . + /// The pertains to the , , or . /// Trainer, @@ -64,7 +64,7 @@ public enum CheckIdentifier : byte IVs, /// - /// The pertains to the or . + /// The pertains to the or . /// Level, @@ -150,7 +150,7 @@ public enum CheckIdentifier : byte GVs, /// - /// The pertains to values. + /// The pertains to . /// Marking, diff --git a/PKHeX.Core/Legality/Structures/LegalInfo.cs b/PKHeX.Core/Legality/Structures/LegalInfo.cs index 2b3cfb14b..1777744d8 100644 --- a/PKHeX.Core/Legality/Structures/LegalInfo.cs +++ b/PKHeX.Core/Legality/Structures/LegalInfo.cs @@ -11,7 +11,7 @@ public sealed class LegalInfo : IGeneration public readonly PKM Entity; /// The generation of games the originated from. - public int Generation { get; private set; } + public byte Generation { get; private set; } /// The matched Encounter details for the . public IEncounterable EncounterMatch @@ -62,13 +62,9 @@ internal set public bool PIDParsed { get; private set; } private PIDIV _pidiv; - /// Indicates whether the can originate from the . - /// This boolean is true until all valid encounters are tested, after which it is false. - public bool PIDIVMatches { get; internal set; } = true; - - /// Indicates whether the can originate from the with explicit RNG matching. - /// This boolean is true until all valid entries are tested for all possible matches, after which it is false. - public bool FrameMatches { get; internal set; } = true; + public EncounterYieldFlag ManualFlag { get; internal set; } + public bool FrameMatches => ManualFlag != EncounterYieldFlag.InvalidFrame; + public bool PIDIVMatches => ManualFlag != EncounterYieldFlag.InvalidPIDIV; public LegalInfo(PKM pk, List parse) { @@ -82,9 +78,16 @@ public LegalInfo(PKM pk, List parse) /// Additionally, We need to call this for each Gen1/2 encounter as Version is not stored for those origins. /// /// Encounter generation - internal void StoreMetadata(int generation) => Generation = generation switch + internal void StoreMetadata(byte generation) => Generation = generation switch { - -1 when Entity is PK9 { IsUnhatchedEgg: true } => 9, + 0 when Entity is PK9 { IsUnhatchedEgg: true } => 9, _ => generation, }; } + +public enum EncounterYieldFlag : byte +{ + None = 0, + InvalidPIDIV, + InvalidFrame, +} diff --git a/PKHeX.Core/Legality/Tables/FormChangeUtil.cs b/PKHeX.Core/Legality/Tables/FormChangeUtil.cs index d5322b46a..c0a822e75 100644 --- a/PKHeX.Core/Legality/Tables/FormChangeUtil.cs +++ b/PKHeX.Core/Legality/Tables/FormChangeUtil.cs @@ -14,7 +14,7 @@ public static class FormChangeUtil /// Entity form /// Generation we're checking in /// Conditions we're checking with - public static bool ShouldIterateForms(ushort species, byte form, int generation, LearnOption option) + public static bool ShouldIterateForms(ushort species, byte form, byte generation, LearnOption option) { if (option.IsPast()) return IsFormChangeDifferentMoves(species, generation); @@ -37,7 +37,7 @@ public static bool ShouldIterateForms(ushort species, byte form, int generation, /// /// Species that can change between their forms and get access to form-specific moves. /// - private static bool IsFormChangeDifferentMoves(ushort species, int generation) => species switch + private static bool IsFormChangeDifferentMoves(ushort species, byte generation) => species switch { (int)Species.Deoxys => generation >= 6, (int)Species.Giratina => generation >= 6, diff --git a/PKHeX.Core/Legality/Tables/FormInfo.cs b/PKHeX.Core/Legality/Tables/FormInfo.cs index 3e591eaa8..423b5ee25 100644 --- a/PKHeX.Core/Legality/Tables/FormInfo.cs +++ b/PKHeX.Core/Legality/Tables/FormInfo.cs @@ -16,7 +16,7 @@ public static class FormInfo /// Entity form /// Current generation format /// True if it can only exist in a battle, false if it can exist outside of battle. - public static bool IsBattleOnlyForm(ushort species, byte form, int format) => BattleOnly.Contains(species) && species switch + public static bool IsBattleOnlyForm(ushort species, byte form, byte format) => BattleOnly.Contains(species) && species switch { // Only continue checking if the species is in the list of Battle Only forms. // Some species have battle only forms as well as out-of-battle forms (other than base form). @@ -38,7 +38,7 @@ public static class FormInfo /// Entity form /// Current generation format /// Suggested alt form value. - public static byte GetOutOfBattleForm(ushort species, byte form, int format) => species switch + public static byte GetOutOfBattleForm(ushort species, byte form, byte format) => species switch { (ushort)Darmanitan => (byte)(form & 2), (ushort)Zygarde when format > 6 => 3, @@ -56,7 +56,7 @@ public static class FormInfo /// Entity form argument /// Current generation format /// True if trading should be disallowed. - public static bool IsUntradable(ushort species, byte form, uint formArg, int format) => species switch + public static bool IsUntradable(ushort species, byte form, uint formArg, byte format) => species switch { (ushort)Koraidon or (int)Miraidon => formArg == 1, // Ride-able Box Legend (ushort)Pikachu => format == 7 && form == 8, // Let's Go Pikachu Starter @@ -71,7 +71,7 @@ public static class FormInfo /// Entity form /// Current generation format /// True if it is a fused species-form, false if it is not fused. - public static bool IsFusedForm(ushort species, byte form, int format) => species switch + public static bool IsFusedForm(ushort species, byte form, byte format) => species switch { (ushort)Kyurem => form != 0 && format >= 5, (ushort)Necrozma => form != 0 && format >= 7, @@ -332,7 +332,7 @@ public static bool IsLordForm(ushort species, byte form, EntityContext context) /// Entity form /// Current generation format /// - public static bool IsValidOutOfBoundsForm(ushort species, byte form, int format) => (Species) species switch + public static bool IsValidOutOfBoundsForm(ushort species, byte form, byte format) => (Species) species switch { Unown => form < (format == 2 ? 26 : 28), // A-Z : A-Z?! Mothim => form < 3, // Burmy base form is kept @@ -350,7 +350,7 @@ public static bool IsLordForm(ushort species, byte form, EntityContext context) /// ID /// ID /// True if it has forms that can be provided by , otherwise false for none. - public static bool HasFormSelection(IPersonalFormInfo pi, ushort species, int format) + public static bool HasFormSelection(IPersonalFormInfo pi, ushort species, byte format) { if (format <= 3 && species != (int)Unown) return false; diff --git a/PKHeX.Core/Legality/Tables/FormItem.cs b/PKHeX.Core/Legality/Tables/FormItem.cs index b2eec090a..a9dfa4b39 100644 --- a/PKHeX.Core/Legality/Tables/FormItem.cs +++ b/PKHeX.Core/Legality/Tables/FormItem.cs @@ -17,7 +17,7 @@ public static class FormItem /// Held Item /// Generation/Format of the entity /// Form ID - public static byte GetFormArceus(int item, int format) => item switch + public static byte GetFormArceus(int item, byte format) => item switch { (>= 777 and <= 793) => GetFormArceusZCrystal(item), (>= 298 and <= 313) or 644 => GetFormArceusPlate(item, format), @@ -37,7 +37,7 @@ public static class FormItem /// Held Item /// Generation/Format of the entity /// Held Item - public static byte GetFormArceusPlate(int item, int format) + public static byte GetFormArceusPlate(int item, byte format) { byte form = (byte)(Arceus_PlateIDs.IndexOf((ushort)item) + 1); if (format != 4) // No need to consider Curse type @@ -53,7 +53,7 @@ public static byte GetFormArceusPlate(int item, int format) /// Form ID /// Generation/Format of the entity /// Held Item - public static ushort GetItemArceus(byte form, int format) + public static ushort GetItemArceus(byte form, byte format) { var index = form - 1; if (format == 4 && form > 8) @@ -162,7 +162,7 @@ public static ushort GetItemGenesect(byte form) /// Generation/Format of the entity /// Expected Form ID /// True if the form is required - public static bool TryGetForm(ushort species, int item, int format, out byte form) + public static bool TryGetForm(ushort species, int item, byte format, out byte form) { switch (species) { diff --git a/PKHeX.Core/Legality/Verifiers/Ability/AbilityVerifier.cs b/PKHeX.Core/Legality/Verifiers/Ability/AbilityVerifier.cs index 6b7a2d187..68da61c6b 100644 --- a/PKHeX.Core/Legality/Verifiers/Ability/AbilityVerifier.cs +++ b/PKHeX.Core/Legality/Verifiers/Ability/AbilityVerifier.cs @@ -36,7 +36,7 @@ private CheckResult VerifyAbility(LegalityAnalysis data) if (abilIndex < 0) return GetInvalid(LAbilityUnexpected); - int format = pk.Format; + byte format = pk.Format; if (format >= 6) { var bitNum = pk.AbilityNumber; @@ -49,7 +49,7 @@ private CheckResult VerifyAbility(LegalityAnalysis data) return INVALID; // Check AbilityNumber for transfers without unique abilities - int gen = data.Info.Generation; + var gen = data.Info.Generation; if (gen is 3 or 4 or 5 && bitNum != 4) { // To determine AbilityNumber [PK5->PK6], check if the first ability in Personal matches the ability. @@ -136,7 +136,7 @@ private CheckResult VerifyAbility(LegalityAnalysis data, IPersonalAbility12 abil private CheckResult VerifyAbility345(LegalityAnalysis data, IEncounterable enc, IPersonalAbility12 abilities, int abilIndex) { var pk = data.Entity; - int format = pk.Format; + byte format = pk.Format; var state = AbilityState.MustMatch; if (format is (3 or 4 or 5) && !abilities.GetIsAbility12Same()) // 3-4/5 and have 2 distinct abilities now state = VerifyAbilityPreCapsule(data, abilities); @@ -150,7 +150,7 @@ private CheckResult VerifyAbility345(LegalityAnalysis data, IEncounterable enc, return VerifyFixedAbility(data, abilities, state, encounterAbility, abilIndex); } - int gen = enc.Generation; + var gen = enc.Generation; if (gen == 5) return VerifyAbility5(data, enc, abilities); @@ -221,7 +221,7 @@ private AbilityState VerifyAbilityPreCapsule(LegalityAnalysis data, IPersonalAbi // CXD Pokémon can have any ability without matching PID if (format == 3) { - if (pk.Version == (int)GameVersion.CXD) + if (pk.Version == GameVersion.CXD) return AbilityState.CanMismatch; return AbilityState.MustMatch; } @@ -245,7 +245,7 @@ private AbilityState VerifyAbilityGen3Transfer(LegalityAnalysis data, IPersonalA var pk = data.Entity; var pers = PersonalTable.E[maxGen3Species]; if (pers.Ability1 != pers.Ability2) // Excluding Colosseum/XD, a Gen3 pk must match PID if it has 2 unique abilities - return pk.Version == (int) GameVersion.CXD ? AbilityState.CanMismatch : AbilityState.MustMatch; + return pk.Version == GameVersion.CXD ? AbilityState.CanMismatch : AbilityState.MustMatch; if (pk.Species != maxGen3Species) // it has evolved in either gen 4 or gen 5; the ability must match PID return AbilityState.MustMatch; @@ -390,12 +390,12 @@ private CheckResult VerifyAbility8BDSP(LegalityAnalysis data, IEncounterable enc /// /// Pokémon /// Current abilities - /// Generation + /// Generation /// Permissive to allow ability to deviate under special circumstances /// Encounter template the was matched to. - private CheckResult CheckMatch(PKM pk, IPersonalAbility12 abilities, int gen, AbilityState state, IEncounterTemplate enc) + private CheckResult CheckMatch(PKM pk, IPersonalAbility12 abilities, byte generation, AbilityState state, IEncounterTemplate enc) { - if (gen is (3 or 4) && pk.AbilityNumber == 4) + if (generation is (3 or 4) && pk.AbilityNumber == 4) return GetInvalid(LAbilityHiddenUnavailable); // other cases of hidden ability already flagged, all that is left is 1/2 mismatching @@ -420,7 +420,7 @@ private CheckResult CheckMatch(PKM pk, IPersonalAbility12 abilities, int gen, Ab // Gen3 mainline origin sets the Ability index based on the PID, but only if it has two abilities. // Version value check isn't factually correct, but there are no C/XD gifts with (Version!=15) that have two abilities. // Pikachu, Celebi, Ho-Oh - if (pk.Version != (int)GameVersion.CXD && abit != ((pk.EncryptionConstant & 1) == 1)) + if (pk.Version != GameVersion.CXD && abit != ((pk.EncryptionConstant & 1) == 1)) return GetInvalid(LAbilityMismatchPID, CheckIdentifier.PID); } } @@ -457,14 +457,14 @@ private static bool IsAbilityCapsuleModified(PKM pk, AbilityPermission encounter return true; } - public static bool CanAbilityCapsule(int format, IPersonalAbility12 abilities) + public static bool CanAbilityCapsule(byte format, IPersonalAbility12 abilities) { if (format < 6) // Ability Capsule does not exist return false; return !abilities.GetIsAbility12Same(); // Cannot alter ability index if it is the same as the other ability. } - public static bool CanAbilityPatch(int format, IPersonalAbility12H abilities, ushort species) + public static bool CanAbilityPatch(byte format, IPersonalAbility12H abilities, ushort species) { if (format < 8) // Ability Patch does not exist return false; diff --git a/PKHeX.Core/Legality/Verifiers/Ball/BallContextHOME.cs b/PKHeX.Core/Legality/Verifiers/Ball/BallContextHOME.cs index b9eca73a3..95d2bf212 100644 --- a/PKHeX.Core/Legality/Verifiers/Ball/BallContextHOME.cs +++ b/PKHeX.Core/Legality/Verifiers/Ball/BallContextHOME.cs @@ -36,7 +36,7 @@ public bool CanBreedWithBall(ushort species, byte form, Ball ball) /// Original encounter species /// True if the restriction can be ignored, false if not. /// Ability Patch can be used on any species that has a Hidden Ability distinct from its regular ability. - public static bool IsAbilityPatchPossible(int format, ushort species) + public static bool IsAbilityPatchPossible(byte format, ushort species) { if (format <= 7) return false; diff --git a/PKHeX.Core/Legality/Verifiers/Ball/BallUseLegality.cs b/PKHeX.Core/Legality/Verifiers/Ball/BallUseLegality.cs index 8beb5858b..300bc3ec1 100644 --- a/PKHeX.Core/Legality/Verifiers/Ball/BallUseLegality.cs +++ b/PKHeX.Core/Legality/Verifiers/Ball/BallUseLegality.cs @@ -14,14 +14,14 @@ internal static class BallUseLegality /// True if it is impossible to capture in a ball. public static bool IsAlolanCaptureNoHeavyBall(ushort species) => species is (int)Species.Beldum or (int)Species.TapuKoko or (int)Species.TapuLele or (int)Species.TapuBulu or (int)Species.TapuFini; - public static bool IsBallPermitted(ulong permit, int ball) + public static bool IsBallPermitted(ulong permit, byte ball) { - if ((uint)ball >= 64) + if (ball >= 64) return false; return (permit & (1ul << ball)) != 0; } - public static ulong GetWildBalls(int generation, GameVersion game) => generation switch + public static ulong GetWildBalls(byte generation, GameVersion game) => generation switch { 1 => WildPokeBalls1, 2 => WildPokeBalls2, diff --git a/PKHeX.Core/Legality/Verifiers/Ball/BallVerifier.cs b/PKHeX.Core/Legality/Verifiers/Ball/BallVerifier.cs index 4cd1450b8..c866df098 100644 --- a/PKHeX.Core/Legality/Verifiers/Ball/BallVerifier.cs +++ b/PKHeX.Core/Legality/Verifiers/Ball/BallVerifier.cs @@ -18,7 +18,7 @@ public override void Verify(LegalityAnalysis data) data.AddLine(result); } - private static int IsReplacedBall(IVersion enc, PKM pk) => pk switch + private static byte IsReplacedBall(IVersion enc, PKM pk) => pk switch { // Trading from PLA origin -> SW/SH will replace the Legends: Arceus ball with a regular Poké Ball PK8 when enc.Version == GameVersion.PLA => (int)Poke, @@ -183,14 +183,6 @@ private CheckResult VerifyBallEggGen9(LegalityAnalysis data) if (species is >= (int)Species.Sprigatito and <= (int)Species.Quaquaval) return VerifyBallEquals(ball, BallUseLegality.WildPokeballs8g_WithoutRaid); - // PLA Voltorb: Only via PLA (transfer only, not wild) and GO - if (enc is { Species: (ushort)Species.Voltorb, Form: 1 }) - return VerifyBallEquals(ball, BallUseLegality.WildPokeballs8g_WithRaid); - - // S/V Tauros forms > 1: Only local Wild Balls for Blaze/Aqua breeds -- can't inherit balls from Kantonian/Combat. - if (enc is { Species: (ushort)Species.Tauros, Form: > 1 }) - return VerifyBallEquals(ball, BallUseLegality.WildPokeballs9); - var instance = BallContextHOME.Instance; if (ball > Beast) return GetInvalid(LBallUnavailable); @@ -204,8 +196,8 @@ private CheckResult VerifyBallEggGen9(LegalityAnalysis data) }; } - private CheckResult VerifyBallEquals(LegalityAnalysis data, int ball) => GetResult(ball == data.Entity.Ball); - private CheckResult VerifyBallEquals(Ball ball, ulong permit) => GetResult(BallUseLegality.IsBallPermitted(permit, (int)ball)); + private CheckResult VerifyBallEquals(LegalityAnalysis data, byte ball) => GetResult(ball == data.Entity.Ball); + private CheckResult VerifyBallEquals(Ball ball, ulong permit) => GetResult(BallUseLegality.IsBallPermitted(permit, (byte)ball)); private CheckResult GetResult(bool valid) => valid ? GetValid(LBallEnc) : GetInvalid(LBallEncMismatch); } diff --git a/PKHeX.Core/Legality/Verifiers/CXDVerifier.cs b/PKHeX.Core/Legality/Verifiers/CXDVerifier.cs index 78a03983b..2377f9723 100644 --- a/PKHeX.Core/Legality/Verifiers/CXDVerifier.cs +++ b/PKHeX.Core/Legality/Verifiers/CXDVerifier.cs @@ -17,7 +17,7 @@ public override void Verify(LegalityAnalysis data) else if (data.EncounterMatch is EncounterStatic3XD { Species: (ushort)Species.Eevee }) VerifyStarterXD(data); - if (pk.OT_Gender == 1) + if (pk.OriginalTrainerGender == 1) data.AddLine(GetInvalid(LG3OTGender, CheckIdentifier.Trainer)); } @@ -32,23 +32,24 @@ private static void VerifyStarterColo(LegalityAnalysis data) private static void VerifyStarterXD(LegalityAnalysis data) { - var (type, seed) = data.Info.PIDIV; - if (type is not (PIDType.CXD or PIDType.CXDAnti or PIDType.CXD_ColoStarter)) + var info = data.Info.PIDIV; + if (info.Type is not (PIDType.CXD or PIDType.CXDAnti or PIDType.CXD_ColoStarter)) return; // already flagged as invalid bool valid; var pk = data.Entity; - if (type == PIDType.CXD_ColoStarter && pk.Species == (int)Species.Umbreon) + if (info.Type == PIDType.CXD_ColoStarter && pk.Species == (int)Species.Umbreon) { // reset pidiv type to be CXD -- ColoStarter is same correlation as Eevee->Umbreon - data.Info.PIDIV = new PIDIV(PIDType.CXD, seed); + data.Info.PIDIV = new PIDIV(PIDType.CXD, info.OriginSeed); valid = true; } else { + var seed = info.OriginSeed; valid = LockFinder.IsXDStarterValid(seed, pk.TID16, pk.SID16); if (valid) // unroll seed to origin that generated TID16/SID16->pkm - data.Info.PIDIV = new PIDIV(PIDType.CXD, XDRNG.Prev4(seed)); + data.Info.PIDIV = new PIDIV(PIDType.CXD, seed) { EncounterSeed = XDRNG.Prev4(seed) }; } if (!valid) data.AddLine(GetInvalid(LEncConditionBadRNGFrame, CheckIdentifier.PID)); diff --git a/PKHeX.Core/Legality/Verifiers/ContestStatVerifier.cs b/PKHeX.Core/Legality/Verifiers/ContestStatVerifier.cs index 3ca4d44e0..64d8e2365 100644 --- a/PKHeX.Core/Legality/Verifiers/ContestStatVerifier.cs +++ b/PKHeX.Core/Legality/Verifiers/ContestStatVerifier.cs @@ -35,7 +35,7 @@ public override void Verify(LegalityAnalysis data) { // We can get contest stat values, but we can't get any for Sheen. // Any combination of non-sheen is ok, but nonzero sheen is illegal. - if (s.CNT_Sheen != 0) + if (s.ContestSheen != 0) data.AddLine(GetInvalid(LContestZeroSheen)); } else if (correlation == CorrelateSheen) @@ -49,12 +49,12 @@ public override void Verify(LegalityAnalysis data) var initial = GetReferenceTemplate(data.Info.EncounterMatch); var minSheen = CalculateMinimumSheen(s, initial, pk, method); - if (s.CNT_Sheen < minSheen) + if (s.ContestSheen < minSheen) data.AddLine(GetInvalid(string.Format(LContestSheenTooLow_0, minSheen))); // Check for sheen values that are too high. var maxSheen = CalculateMaximumSheen(s, pk.Nature, initial, gen3); - if (s.CNT_Sheen > maxSheen) + if (s.ContestSheen > maxSheen) data.AddLine(GetInvalid(string.Format(LContestSheenTooHigh_0, maxSheen))); } else if (correlation == Mixed) @@ -64,7 +64,7 @@ public override void Verify(LegalityAnalysis data) // Check for sheen values that are too high. var initial = GetReferenceTemplate(data.Info.EncounterMatch); var maxSheen = CalculateMaximumSheen(s, pk.Nature, initial, gen3); - if (s.CNT_Sheen > maxSheen) + if (s.ContestSheen > maxSheen) data.AddLine(GetInvalid(string.Format(LContestSheenTooHigh_0, maxSheen))); } } diff --git a/PKHeX.Core/Legality/Verifiers/EffortValueVerifier.cs b/PKHeX.Core/Legality/Verifiers/EffortValueVerifier.cs index 97bf3164f..662217f17 100644 --- a/PKHeX.Core/Legality/Verifiers/EffortValueVerifier.cs +++ b/PKHeX.Core/Legality/Verifiers/EffortValueVerifier.cs @@ -9,10 +9,7 @@ namespace PKHeX.Core; public sealed class EffortValueVerifier : Verifier { protected override CheckIdentifier Identifier => CheckIdentifier.EVs; - - private const int totalMax = 510; // Total Max - private const int vitaMax = 100; // Vitamin Max for consideration in Gen3 & Gen4. - + public override void Verify(LegalityAnalysis data) { var pk = data.Entity; @@ -24,12 +21,12 @@ public override void Verify(LegalityAnalysis data) } // In Generation 1 & 2, when a Pokémon is taken out of the Day Care, its experience will lower to the minimum value for its current level. - int format = pk.Format; + byte format = pk.Format; if (format < 3) // Can abuse daycare for EV training without EXP gain return; int sum = pk.EVTotal; - if (sum > totalMax) // format >= 3 + if (sum > EffortValues.Max510) // format >= 3 data.AddLine(GetInvalid(LEffortAbove510)); var enc = data.EncounterMatch; @@ -51,7 +48,7 @@ public override void Verify(LegalityAnalysis data) private void VerifyGainedEVs34(LegalityAnalysis data, IEncounterTemplate enc, Span evs, PKM pk) { - bool anyAbove100 = evs.Find(static ev => ev > vitaMax) != default; + bool anyAbove100 = evs.Find(static ev => ev > EffortValues.MaxVitamins34) != default; if (!anyAbove100) return; @@ -66,7 +63,7 @@ private void VerifyGainedEVs34(LegalityAnalysis data, IEncounterTemplate enc, Sp var growth = PersonalTable.HGSS[enc.Species].EXPGrowth; var baseEXP = Experience.GetEXP(enc.LevelMin, growth); if (baseEXP == pk.EXP) - data.AddLine(GetInvalid(string.Format(LEffortUntrainedCap, vitaMax))); + data.AddLine(GetInvalid(string.Format(LEffortUntrainedCap, EffortValues.MaxVitamins34))); } } } diff --git a/PKHeX.Core/Legality/Verifiers/Egg/EggStateLegality.cs b/PKHeX.Core/Legality/Verifiers/Egg/EggStateLegality.cs index 8afe53a96..d142357d5 100644 --- a/PKHeX.Core/Legality/Verifiers/Egg/EggStateLegality.cs +++ b/PKHeX.Core/Legality/Verifiers/Egg/EggStateLegality.cs @@ -15,7 +15,7 @@ public static class EggStateLegality /// True if valid, false if invalid. public static bool GetIsEggHatchCyclesValid(PKM pk, IEncounterTemplate enc) { - var hatchCounter = pk.OT_Friendship; + var hatchCounter = pk.OriginalTrainerFriendship; var max = GetMaximumEggHatchCycles(pk, enc); if (hatchCounter > max) return false; @@ -63,7 +63,7 @@ public static int GetMaximumEggHatchCycles(PKM pk, IEncounterTemplate enc) /// Level which eggs are given to the player. /// /// Generation the egg is given in - public static byte GetEggLevel(int generation) => generation >= 4 ? (byte)1 : (byte)5; + public static byte GetEggLevel(byte generation) => generation >= 4 ? (byte)1 : (byte)5; public const byte EggMetLevel34 = 0; public const byte EggMetLevel = 1; @@ -73,22 +73,22 @@ public static int GetMaximumEggHatchCycles(PKM pk, IEncounterTemplate enc) /// /// Game the egg is obtained in /// Generation the egg is given in - public static int GetEggLevelMet(GameVersion version, int generation) => generation switch + public static byte GetEggLevelMet(GameVersion version, byte generation) => generation switch { - 2 => version is C ? EggMetLevel : 0, // GS do not store met data + 2 => version is C ? EggMetLevel : (byte)0, // GS do not store met data 3 or 4 => EggMetLevel34, _ => EggMetLevel, }; /// - /// Checks if the and associated details can be set for the provided egg . + /// Checks if the and associated details can be set for the provided egg . /// /// Egg Entity /// True if valid, false if invalid. public static bool IsValidHTEgg(PKM pk) => pk switch { - PB8 { Met_Location: Locations.LinkTrade6NPC } pb8 when pb8.HT_Friendship == PersonalTable.BDSP[pb8.Species].BaseFriendship => true, - PK9 { Met_Location: Locations.LinkTrade6, HT_Language: not 0 } => true, // fine regardless of handler (trade-back) + PB8 { MetLocation: Locations.LinkTrade6NPC } pb8 when pb8.HandlingTrainerFriendship == PersonalTable.BDSP[pb8.Species].BaseFriendship => true, + PK9 { MetLocation: Locations.LinkTrade6, HandlingTrainerLanguage: not 0 } => true, // fine regardless of handler (trade-back) _ => false, }; @@ -123,9 +123,9 @@ public static int GetMaximumEggHatchCycles(PKM pk, IEncounterTemplate enc) public static bool IsNicknameFlagSet(PKM pk) => IsNicknameFlagSet(new LegalityAnalysis(pk).EncounterMatch, pk); /// - /// Gets a valid for an egg hatched in the origin game, accounting for future format transfers altering the data. + /// Gets a valid for an egg hatched in the origin game, accounting for future format transfers altering the data. /// - public static int GetEggHatchLocation(GameVersion game, int format) => game switch + public static ushort GetEggHatchLocation(GameVersion game, byte format) => game switch { R or S or E or FR or LG => format switch { @@ -151,6 +151,6 @@ public static int GetMaximumEggHatchCycles(PKM pk, IEncounterTemplate enc) BD or SP => Locations.HatchLocation8b, SL or VL => Locations.HatchLocation9, - _ => -1, + _ => 0, }; } diff --git a/PKHeX.Core/Legality/Verifiers/FormArgumentVerifier.cs b/PKHeX.Core/Legality/Verifiers/FormArgumentVerifier.cs index b7b0bde55..c15d8695c 100644 --- a/PKHeX.Core/Legality/Verifiers/FormArgumentVerifier.cs +++ b/PKHeX.Core/Legality/Verifiers/FormArgumentVerifier.cs @@ -93,7 +93,7 @@ private CheckResult VerifyFormArgument(LegalityAnalysis data, IFormArgument f) // Without being leveled up at least once, it cannot have a form arg value. >= 999 => GetInvalid(LFormArgumentHigh), 0 => GetValid(LFormArgumentValid), - _ => pk.CurrentLevel != pk.Met_Level ? GetValid(LFormArgumentValid) : GetInvalid(LFormArgumentNotAllowed), + _ => pk.CurrentLevel != pk.MetLevel ? GetValid(LFormArgumentValid) : GetInvalid(LFormArgumentNotAllowed), }, Runerigus => VerifyFormArgumentRange(enc.Species, Runerigus, arg, 49, 9999), Alcremie => VerifyFormArgumentRange(enc.Species, Alcremie, arg, 0, (uint)AlcremieDecoration.Ribbon), diff --git a/PKHeX.Core/Legality/Verifiers/GenderVerifier.cs b/PKHeX.Core/Legality/Verifiers/GenderVerifier.cs index 24788d7c0..4296bcb52 100644 --- a/PKHeX.Core/Legality/Verifiers/GenderVerifier.cs +++ b/PKHeX.Core/Legality/Verifiers/GenderVerifier.cs @@ -16,14 +16,14 @@ public override void Verify(LegalityAnalysis data) if (pi.Genderless != (pk.Gender == 2)) { // D/P/Pt & HG/SS Shedinja glitch -- only generation 4 spawns - bool ignore = pk is { Format: 4, Species: (int)Species.Shedinja } && pk.Met_Level != pk.CurrentLevel; + bool ignore = pk is { Format: 4, Species: (int)Species.Shedinja } && pk.MetLevel != pk.CurrentLevel; if (!ignore) data.AddLine(GetInvalid(LGenderInvalidNone)); return; } // Check for PID relationship to Gender & Nature if applicable - int gen = data.Info.Generation; + var gen = data.Info.Generation; if (gen is 3 or 4 or 5) { // Gender-PID & Nature-PID relationship check @@ -49,7 +49,7 @@ private static void VerifyNaturePID(LegalityAnalysis data) data.AddLine(result); } - private static uint GetExpectedNature(PKM pk) => pk.EncryptionConstant % 25; + private static Nature GetExpectedNature(PKM pk) => (Nature)(pk.EncryptionConstant % 25); private static bool IsValidGenderPID(LegalityAnalysis data) { diff --git a/PKHeX.Core/Legality/Verifiers/HistoryVerifier.cs b/PKHeX.Core/Legality/Verifiers/HistoryVerifier.cs index e6435dbb1..6bb8f17ee 100644 --- a/PKHeX.Core/Legality/Verifiers/HistoryVerifier.cs +++ b/PKHeX.Core/Legality/Verifiers/HistoryVerifier.cs @@ -39,9 +39,9 @@ private void VerifyTradeState(LegalityAnalysis data) if (pk.CurrentHandler != 0) // Badly edited; PKHeX doesn't trip this. data.AddLine(GetInvalid(LMemoryHTFlagInvalid)); - else if (pk.HT_Friendship != 0) + else if (pk.HandlingTrainerFriendship != 0) data.AddLine(GetInvalid(LMemoryStatFriendshipHT0)); - else if (pk is IAffection {HT_Affection: not 0}) + else if (pk is IAffection {HandlingTrainerAffection: not 0}) data.AddLine(GetInvalid(LMemoryStatAffectionHT0)); // Don't check trade evolutions if Untraded. The Evolution Chain already checks for trade evolutions. @@ -70,9 +70,9 @@ private void VerifyHandlerState(LegalityAnalysis data, bool neverOT) if (flag == 1) { - if (pk.HT_Name != tr.OT) + if (pk.HandlingTrainerName != tr.OT) data.AddLine(GetInvalid(LTransferHTMismatchName)); - if (pk is IHandlerLanguage h && h.HT_Language != tr.Language) + if (pk is IHandlerLanguage h && h.HandlingTrainerLanguage != tr.Language) data.AddLine(Get(LTransferHTMismatchLanguage, Severity.Fishy)); } } @@ -91,7 +91,7 @@ private void VerifyHandlerState(LegalityAnalysis data, bool neverOT) }; /// - /// Checks the non-Memory data for the details. + /// Checks the non-Memory data for the details. /// private void VerifyOTMisc(LegalityAnalysis data, bool neverOT) { @@ -117,7 +117,7 @@ private void VerifyOTFriendship(LegalityAnalysis data, bool neverOT, int origin, { // Verify the original friendship value since it cannot change from the value it was assigned in the original generation. // If none match, then it is not a valid OT friendship. - var fs = pk.OT_Friendship; + var fs = pk.OriginalTrainerFriendship; var enc = data.Info.EncounterMatch; if (GetBaseFriendship(enc) != fs) data.AddLine(GetInvalid(LMemoryStatFriendshipOTBaseEvent)); @@ -130,7 +130,7 @@ private void VerifyOTFriendshipVC12(LegalityAnalysis data, PKM pk) // Since some evolutions have different base friendship values, check all possible evolutions for a match. // If none match, then it is not a valid OT friendship. // VC transfers use S/M personal info - var any = IsMatchFriendship(data.Info.EvoChainsAllGens.Gen7, pk.OT_Friendship); + var any = IsMatchFriendship(data.Info.EvoChainsAllGens.Gen7, pk.OriginalTrainerFriendship); if (!any) data.AddLine(GetInvalid(LMemoryStatFriendshipOTBaseEvent)); } @@ -158,7 +158,7 @@ private void VerifyOTAffection(LegalityAnalysis data, bool neverOT, int origin, { // Can gain affection in Gen6 via the Contest glitch applying affection to OT rather than HT. // VC encounters cannot obtain OT affection since they can't visit Gen6. - if ((origin <= 2 && a.OT_Affection != 0) || IsInvalidContestAffection(a)) + if ((origin <= 2 && a.OriginalTrainerAffection != 0) || IsInvalidContestAffection(a)) data.AddLine(GetInvalid(LMemoryStatAffectionOT0)); } else if (neverOT) @@ -167,7 +167,7 @@ private void VerifyOTAffection(LegalityAnalysis data, bool neverOT, int origin, { if (pk is { IsUntraded: true, XY: true }) { - if (a.OT_Affection != 0) + if (a.OriginalTrainerAffection != 0) data.AddLine(GetInvalid(LMemoryStatAffectionOT0)); } else if (IsInvalidContestAffection(a)) @@ -177,19 +177,19 @@ private void VerifyOTAffection(LegalityAnalysis data, bool neverOT, int origin, } else { - if (a.OT_Affection != 0) + if (a.OriginalTrainerAffection != 0) data.AddLine(GetInvalid(LMemoryStatAffectionOT0)); } } } /// - /// Checks the non-Memory data for the details. + /// Checks the non-Memory data for the details. /// private void VerifyHTMisc(LegalityAnalysis data) { var pk = data.Entity; - var htGender = pk.HT_Gender; + var htGender = pk.HandlingTrainerGender; if (htGender > 1 || (pk.IsUntraded && htGender != 0)) data.AddLine(GetInvalid(string.Format(LMemoryHTGender, htGender))); } @@ -206,9 +206,9 @@ private void VerifyGeoLocationData(LegalityAnalysis data, IGeoTrack t, PKM pk) } // OR/AS contests mistakenly apply 20 affection to the OT instead of the current handler's value - private static bool IsInvalidContestAffection(IAffection pk) => pk.OT_Affection != 255 && pk.OT_Affection % 20 != 0; + private static bool IsInvalidContestAffection(IAffection pk) => pk.OriginalTrainerAffection != 255 && pk.OriginalTrainerAffection % 20 != 0; - public static bool GetCanOTHandle(IEncounterTemplate enc, PKM pk, int generation) + public static bool GetCanOTHandle(IEncounterTemplate enc, PKM pk, byte generation) { // Handlers introduced in Generation 6. OT Handling was always the case for Generation 3-5 data. if (generation < 6) @@ -218,8 +218,8 @@ public static bool GetCanOTHandle(IEncounterTemplate enc, PKM pk, int generation { IFixedTrainer { IsFixedTrainer: true } => false, EncounterSlot8GO => false, - WC6 { OT_Name.Length: > 0 } => false, - WC7 { OT_Name.Length: > 0, TID16: not 18075 } => false, // Ash Pikachu QR Gift doesn't set Current Handler + WC6 { OriginalTrainerName.Length: > 0 } => false, + WC7 { OriginalTrainerName.Length: > 0, TID16: not 18075 } => false, // Ash Pikachu QR Gift doesn't set Current Handler WB7 wb7 when wb7.GetHasOT(pk.Language) => false, WC8 wc8 when wc8.GetHasOT(pk.Language) => false, WB8 wb8 when wb8.GetHasOT(pk.Language) => false, @@ -231,7 +231,7 @@ public static bool GetCanOTHandle(IEncounterTemplate enc, PKM pk, int generation private static int GetBaseFriendship(IEncounterTemplate enc) => enc switch { - IFixedOTFriendship f => f.OT_Friendship, + IFixedOTFriendship f => f.OriginalTrainerFriendship, _ => GetBaseFriendship(enc.Context, enc.Species, enc.Form), }; diff --git a/PKHeX.Core/Legality/Verifiers/IndividualValueVerifier.cs b/PKHeX.Core/Legality/Verifiers/IndividualValueVerifier.cs index e7a7ee552..281ffa9a7 100644 --- a/PKHeX.Core/Legality/Verifiers/IndividualValueVerifier.cs +++ b/PKHeX.Core/Legality/Verifiers/IndividualValueVerifier.cs @@ -28,15 +28,16 @@ public override void Verify(LegalityAnalysis data) break; } var pk = data.Entity; - var hpiv = pk.IV_HP; - if (hpiv < 30 && AllIVsEqual(pk, hpiv)) - data.AddLine(Get(string.Format(LIVAllEqual_0, hpiv), Severity.Fishy)); + var hp = pk.IV_HP; + if (hp < 30 && AllIVsEqual(pk, hp)) + data.AddLine(Get(string.Format(LIVAllEqual_0, hp), Severity.Fishy)); } - private static bool AllIVsEqual(PKM pk, int hpiv) - { - return (pk.IV_ATK == hpiv) && (pk.IV_DEF == hpiv) && (pk.IV_SPA == hpiv) && (pk.IV_SPD == hpiv) && (pk.IV_SPE == hpiv); - } + private static bool AllIVsEqual(PKM pk, int hp) => pk.IV_ATK == hp + && pk.IV_DEF == hp + && pk.IV_SPA == hp + && pk.IV_SPD == hp + && pk.IV_SPE == hp; private void VerifyIVsMystery(LegalityAnalysis data, MysteryGift g) { diff --git a/PKHeX.Core/Legality/Verifiers/LanguageVerifier.cs b/PKHeX.Core/Legality/Verifiers/LanguageVerifier.cs index 125939d66..f291c973f 100644 --- a/PKHeX.Core/Legality/Verifiers/LanguageVerifier.cs +++ b/PKHeX.Core/Legality/Verifiers/LanguageVerifier.cs @@ -12,9 +12,9 @@ public sealed class LanguageVerifier : Verifier public override void Verify(LegalityAnalysis data) { var pk = data.Entity; - int originalGeneration = data.Info.Generation; - int currentLanguage = pk.Language; - int maxLanguageID = Legal.GetMaxLanguageID(originalGeneration); + var originalGeneration = data.Info.Generation; + var currentLanguage = pk.Language; + var maxLanguageID = Legal.GetMaxLanguageID(originalGeneration); var enc = data.EncounterMatch; if (!IsValidLanguageID(currentLanguage, maxLanguageID, pk, enc)) { @@ -37,11 +37,11 @@ public override void Verify(LegalityAnalysis data) if (originalGeneration <= 2) { // Korean Crystal does not exist, neither do Korean VC1 - if (pk.Korean && !GameVersion.GS.Contains((GameVersion)pk.Version)) + if (pk.Korean && !GameVersion.GS.Contains(pk.Version)) data.AddLine(GetInvalid(string.Format(LOTLanguage, $"!={(LanguageID)currentLanguage}", (LanguageID)currentLanguage))); // Japanese VC is language locked; cannot obtain Japanese-Blue version as other languages. - if (pk is { Version: (int)GameVersion.BU, Japanese: false }) + if (pk is { Version: GameVersion.BU, Japanese: false }) data.AddLine(GetInvalid(string.Format(LOTLanguage, nameof(LanguageID.Japanese), (LanguageID)currentLanguage))); } } diff --git a/PKHeX.Core/Legality/Verifiers/LegendsArceusVerifier.cs b/PKHeX.Core/Legality/Verifiers/LegendsArceusVerifier.cs index ae83966db..3f52539cd 100644 --- a/PKHeX.Core/Legality/Verifiers/LegendsArceusVerifier.cs +++ b/PKHeX.Core/Legality/Verifiers/LegendsArceusVerifier.cs @@ -88,9 +88,9 @@ private static int LoadBareMinimumMoveset(ISpeciesForm enc, EvolutionHistory h, var ls = LearnSource8LA.Instance; var moveset = ls.GetLearnset(enc.Species, enc.Form); if (enc is IMasteryInitialMoveShop8 ms) - ms.LoadInitialMoveset(pa, moves, moveset, pa.Met_Level); + ms.LoadInitialMoveset(pa, moves, moveset, pa.MetLevel); else - moveset.SetEncounterMoves(pa.Met_Level, moves); + moveset.SetEncounterMoves(pa.MetLevel, moves); var count = moves.IndexOf((ushort)0); if ((uint)count >= 4) return 4; @@ -105,7 +105,7 @@ private static int LoadBareMinimumMoveset(ISpeciesForm enc, EvolutionHistory h, // Level up to current level var level = pa.CurrentLevel; - moveset.SetLevelUpMoves(pa.Met_Level, level, moves, purchased, count); + moveset.SetLevelUpMoves(pa.MetLevel, level, moves, purchased, count); count = moves.IndexOf((ushort)0); if ((uint)count >= 4) return 4; @@ -155,7 +155,7 @@ private static int AddMasteredMissing(PA8 pa, Span current, int ctr, Lea // Check if we can swap it into the moveset after it evolves. var move = purchased[i]; var baseLevel = baseLearn.GetLevelLearnMove(move); - var mustKnow = baseLevel is not -1 && baseLevel <= pa.Met_Level; + var mustKnow = baseLevel is not -1 && baseLevel <= pa.MetLevel; if (!mustKnow && currentLearn.GetLevelLearnMove(move) != level) continue; @@ -239,7 +239,7 @@ private static bool CanLearnMoveByLevelUp(LegalityAnalysis data, PA8 pa, int i, private void VerifyAlphaMove(LegalityAnalysis data, PA8 pa, ushort alphaMove, IPermitRecord permit) { - if (!pa.IsAlpha || data.EncounterMatch is EncounterSlot8a { Type: SlotType.Landmark }) + if (!pa.IsAlpha || data.EncounterMatch is EncounterSlot8a { Type: SlotType8a.Landmark }) { data.AddLine(GetInvalid(LMoveShopAlphaMoveShouldBeZero)); return; @@ -263,7 +263,7 @@ private void VerifyAlphaMoveZero(LegalityAnalysis data) if (enc is not IAlpha { IsAlpha: true }) return; // okay - if (enc is EncounterSlot8a { Type: SlotType.Landmark }) + if (enc is EncounterSlot8a { Type: SlotType8a.Landmark }) return; // okay var pi = PersonalTable.LA.GetFormEntry(enc.Species, enc.Form); diff --git a/PKHeX.Core/Legality/Verifiers/LevelVerifier.cs b/PKHeX.Core/Legality/Verifiers/LevelVerifier.cs index e6f67bb67..48aa1c472 100644 --- a/PKHeX.Core/Legality/Verifiers/LevelVerifier.cs +++ b/PKHeX.Core/Legality/Verifiers/LevelVerifier.cs @@ -29,22 +29,21 @@ public override void Verify(LegalityAnalysis data) if (pk.IsEgg) { - int elvl = enc.LevelMin; - if (elvl != pk.CurrentLevel) + if (pk.CurrentLevel != enc.LevelMin) { - data.AddLine(GetInvalid(string.Format(LEggFMetLevel_0, elvl))); + data.AddLine(GetInvalid(string.Format(LEggFMetLevel_0, enc.LevelMin))); return; } var reqEXP = enc is EncounterStatic2 { DizzyPunchEgg: true } ? 125 // Gen2 Dizzy Punch gifts always have 125 EXP, even if it's more than the Lv5 exp required. - : Experience.GetEXP(elvl, pk.PersonalInfo.EXPGrowth); + : Experience.GetEXP(enc.LevelMin, pk.PersonalInfo.EXPGrowth); if (reqEXP != pk.EXP) data.AddLine(GetInvalid(LEggEXP)); return; } - int lvl = pk.CurrentLevel; + var lvl = pk.CurrentLevel; if (lvl >= 100) { var expect = Experience.GetEXP(100, pk.PersonalInfo.EXPGrowth); @@ -52,7 +51,7 @@ public override void Verify(LegalityAnalysis data) data.AddLine(GetInvalid(LLevelEXPTooHigh)); } - if (lvl < pk.Met_Level) + if (lvl < pk.MetLevel) data.AddLine(GetInvalid(LLevelMetBelow)); else if (!enc.IsWithinEncounterRange(pk) && lvl != 100 && pk.EXP == Experience.GetEXP(lvl, pk.PersonalInfo.EXPGrowth)) data.AddLine(Get(LLevelEXPThreshold, Severity.Fishy)); @@ -62,16 +61,16 @@ public override void Verify(LegalityAnalysis data) private static bool IsMetLevelMatchEncounter(MysteryGift gift, PKM pk) { - if (gift.Level == pk.Met_Level) + if (gift.Level == pk.MetLevel) return true; if (!pk.HasOriginalMetLocation) return true; return gift switch { - WC3 wc3 when wc3.Met_Level == pk.Met_Level || wc3.IsEgg => true, - WC7 wc7 when wc7.MetLevel == pk.Met_Level => true, - PGT { IsManaphyEgg: true } when pk.Met_Level == 0 => true, + WC3 wc3 when wc3.MetLevel == pk.MetLevel || wc3.IsEgg => true, + WC7 wc7 when wc7.MetLevel == pk.MetLevel => true, + PGT { IsManaphyEgg: true } when pk.MetLevel == 0 => true, _ => false, }; } @@ -87,10 +86,10 @@ public void VerifyG1(LegalityAnalysis data) data.AddLine(GetInvalid(string.Format(LEggFMetLevel_0, elvl))); return; } - if (pk.Met_Location != 0) // crystal + if (pk.MetLocation != 0) // crystal { int lvl = pk.CurrentLevel; - if (lvl < pk.Met_Level) + if (lvl < pk.MetLevel) data.AddLine(GetInvalid(LLevelMetBelow)); } diff --git a/PKHeX.Core/Legality/Verifiers/MemoryVerifier.cs b/PKHeX.Core/Legality/Verifiers/MemoryVerifier.cs index 63484c81c..230ae418a 100644 --- a/PKHeX.Core/Legality/Verifiers/MemoryVerifier.cs +++ b/PKHeX.Core/Legality/Verifiers/MemoryVerifier.cs @@ -9,7 +9,7 @@ namespace PKHeX.Core; /// -/// Verifies the , , and associated values. +/// Verifies the , , and associated values. /// public sealed class MemoryVerifier : Verifier { @@ -83,7 +83,7 @@ private void VerifyHTLanguage(LegalityAnalysis data, MemorySource source) var pk = data.Entity; if (pk is not IHandlerLanguage h) return; - if (!GetIsHTLanguageValid(data.EncounterMatch, pk, h.HT_Language, source)) + if (!GetIsHTLanguageValid(data.EncounterMatch, pk, h.HandlingTrainerLanguage, source)) data.AddLine(GetInvalid(LMemoryHTLanguage)); } @@ -100,7 +100,7 @@ private static bool GetIsHTLanguageValid(IEncounterTemplate enc, PKM pk, byte la // Some encounters erroneously set the HT flag. if (enc is EncounterStatic9 { GiftWithLanguage: true }) { - // Must be the SAV language or another-with-HT_Name. + // Must be the SAV language or another-with-HandlingTrainerName. if (language == 0) return false; if (pk.IsUntraded) @@ -166,7 +166,7 @@ private CheckResult VerifyCommonMemory(PKM pk, int handler, LegalInfo info, Memo // Dynamaxing // {0} battled at {1}’s side against {2} that Dynamaxed. {4} that {3}. - case 71 when !GetCanDynamaxTrainer(memory.Variable, 8, handler == 0 ? (GameVersion)pk.Version : GameVersion.Any): + case 71 when !GetCanDynamaxTrainer(memory.Variable, 8, handler == 0 ? pk.Version : GameVersion.Any): // {0} battled {2} and Dynamaxed upon {1}’s instruction. {4} that {3}. case 72 when !PersonalTable.SWSH.IsSpeciesInGame(memory.Variable): return GetInvalid(string.Format(LMemoryArgBadSpecies, memory.Handler)); @@ -179,7 +179,7 @@ private CheckResult VerifyCommonMemory(PKM pk, int handler, LegalInfo info, Memo // Species // With {1}, {0} went fishing, and they caught {2}. {4} that {3}. - case 7 when !GetCanFishSpecies(memory.Variable, mem.Context, handler == 0 ? (GameVersion)pk.Version : GameVersion.Any): + case 7 when !GetCanFishSpecies(memory.Variable, mem.Context, handler == 0 ? pk.Version : GameVersion.Any): return GetInvalid(string.Format(LMemoryArgBadSpecies, memory.Handler)); // {0} saw {1} paying attention to {2}. {4} that {3}. @@ -200,7 +200,7 @@ private CheckResult VerifyCommonMemory(PKM pk, int handler, LegalInfo info, Memo // Item // {0} went to a Pokémon Center with {1} to buy {2}. {4} that {3}. - case 5 when !CanBuyItem(mem.Context, memory.Variable, handler == 0 ? (GameVersion)pk.Version : GameVersion.Any): + case 5 when !CanBuyItem(mem.Context, memory.Variable, handler == 0 ? pk.Version : GameVersion.Any): // {1} used {2} when {0} was in trouble. {4} that {3}. case 15 when !CanUseItem(mem.Context, memory.Variable, pk.Species): // {0} saw {1} using {2}. {4} that {3}. @@ -270,19 +270,19 @@ private CheckResult VerifyCommonMemoryEtc(MemoryVariableSet memory, MemoryContex private void VerifyOTMemoryIs(LegalityAnalysis data, byte m, byte i, ushort t, byte f) { var pk = (ITrainerMemories)data.Entity; - if (pk.OT_Memory != m) + if (pk.OriginalTrainerMemory != m) data.AddLine(GetInvalid(string.Format(LMemoryIndexID, L_XOT, m))); - if (pk.OT_Intensity != i) + if (pk.OriginalTrainerMemoryIntensity != i) data.AddLine(GetInvalid(string.Format(LMemoryIndexIntensity, L_XOT, i))); - if (pk.OT_TextVar != t) + if (pk.OriginalTrainerMemoryVariable != t) data.AddLine(GetInvalid(string.Format(LMemoryIndexVar, L_XOT, t))); - if (pk.OT_Feeling != f) + if (pk.OriginalTrainerMemoryFeeling != f) data.AddLine(GetInvalid(string.Format(LMemoryIndexFeel, L_XOT, f))); } private void VerifyHTMemoryNone(LegalityAnalysis data, ITrainerMemories pk) { - if (pk.HT_Memory != 0 || pk.HT_TextVar != 0 || pk.HT_Intensity != 0 || pk.HT_Feeling != 0) + if (pk.HandlingTrainerMemory != 0 || pk.HandlingTrainerMemoryVariable != 0 || pk.HandlingTrainerMemoryIntensity != 0 || pk.HandlingTrainerMemoryFeeling != 0) data.AddLine(GetInvalid(string.Format(LMemoryCleared, L_XHT))); } @@ -297,27 +297,27 @@ private void VerifyOTMemory(LegalityAnalysis data) switch (data.EncounterMatch) { case WC6 {IsEgg: false} g when g.OTGender != 3: - VerifyOTMemoryIs(data, g.OT_Memory, g.OT_Intensity, g.OT_TextVar, g.OT_Feeling); + VerifyOTMemoryIs(data, g.OriginalTrainerMemory, g.OriginalTrainerMemoryIntensity, g.OriginalTrainerMemoryVariable, g.OriginalTrainerMemoryFeeling); return; case WC7 {IsEgg: false} g when g.OTGender != 3: - VerifyOTMemoryIs(data, g.OT_Memory, g.OT_Intensity, g.OT_TextVar, g.OT_Feeling); + VerifyOTMemoryIs(data, g.OriginalTrainerMemory, g.OriginalTrainerMemoryIntensity, g.OriginalTrainerMemoryVariable, g.OriginalTrainerMemoryFeeling); return; case WC8 {IsEgg: false} g when g.OTGender != 3: - VerifyOTMemoryIs(data, g.OT_Memory, g.OT_Intensity, g.OT_TextVar, g.OT_Feeling); + VerifyOTMemoryIs(data, g.OriginalTrainerMemory, g.OriginalTrainerMemoryIntensity, g.OriginalTrainerMemoryVariable, g.OriginalTrainerMemoryFeeling); return; case IMemoryOTReadOnly t and not MysteryGift: // Ignore Mystery Gift cases (covered above) - VerifyOTMemoryIs(data, t.OT_Memory, t.OT_Intensity, t.OT_TextVar, t.OT_Feeling); + VerifyOTMemoryIs(data, t.OriginalTrainerMemory, t.OriginalTrainerMemoryIntensity, t.OriginalTrainerMemoryVariable, t.OriginalTrainerMemoryFeeling); return; } - var memory = mem.OT_Memory; + var memory = mem.OriginalTrainerMemory; if (pk.IsEgg) { // Traded unhatched eggs in Gen8 have OT link trade memory applied erroneously. // They can also have the box-inspect memory! - if (context != Gen8 || !((pk.Met_Location == Locations.LinkTrade6 && memory == 4) || memory == 85)) + if (context != Gen8 || !((pk.MetLocation == Locations.LinkTrade6 && memory == 4) || memory == 85)) { VerifyOTMemoryIs(data, 0, 0, 0, 0); // empty return; @@ -331,7 +331,7 @@ private void VerifyOTMemory(LegalityAnalysis data) // Bounds checking var mc = Memories.GetContext(context); - if (!mc.CanObtainMemoryOT((GameVersion)pk.Version, memory)) + if (!mc.CanObtainMemoryOT(pk.Version, memory)) data.AddLine(GetInvalid(string.Format(LMemoryArgBadID, L_XOT))); // Verify memory if specific to OT @@ -354,13 +354,13 @@ private void VerifyOTMemory(LegalityAnalysis data) return; // {0} went to the Pokémon Center in {2} with {1} and had its tired body healed there. {4} that {3}. - case 6 when !mc.HasPokeCenter((GameVersion)pk.Version, mem.OT_TextVar): + case 6 when !mc.HasPokeCenter(pk.Version, mem.OriginalTrainerMemoryVariable): data.AddLine(GetInvalid(string.Format(LMemoryArgBadLocation, L_XOT))); return; // {0} was with {1} when {1} caught {2}. {4} that {3}. case 14: - var result = GetCanBeCaptured(mem.OT_TextVar, mc.Context, (GameVersion)pk.Version) // Any Game in the Handling Trainer's generation + var result = GetCanBeCaptured(mem.OriginalTrainerMemoryVariable, mc.Context, pk.Version) // Any Game in the Handling Trainer's generation ? GetValid(string.Format(LMemoryArgSpecies, L_XOT)) : GetInvalid(string.Format(LMemoryArgBadSpecies, L_XOT)); data.AddLine(result); @@ -384,7 +384,7 @@ private static bool CanHaveMemoryForOT(PKM pk, EntityContext origin, int memory) { Gen1 or Gen2 or Gen7 => memory == 4, // VC transfers can only have Bank memory. Gen6 => true, - Gen8 => !(pk.GO_HOME || pk.Met_Location == Locations.HOME8), // HOME does not set memories. + Gen8 => !(pk.GO_HOME || pk.MetLocation == Locations.HOME8), // HOME does not set memories. _ => false, }; } @@ -394,7 +394,7 @@ private void VerifyHTMemory(LegalityAnalysis data, EntityContext memoryGen) var pk = data.Entity; var mem = (ITrainerMemories)pk; - var memory = mem.HT_Memory; + var memory = mem.HandlingTrainerMemory; if (pk.IsUntraded) { @@ -418,7 +418,7 @@ private void VerifyHTMemory(LegalityAnalysis data, EntityContext memoryGen) // Bounds checking var mc = Memories.GetContext(memoryGen); - if (!mc.CanObtainMemoryHT((GameVersion)pk.Version, memory)) + if (!mc.CanObtainMemoryHT(pk.Version, memory)) data.AddLine(GetInvalid(string.Format(LMemoryArgBadID, L_XHT))); // Verify memory if specific to HT @@ -448,13 +448,13 @@ private void VerifyHTMemory(LegalityAnalysis data, EntityContext memoryGen) return; // {0} went to the Pokémon Center in {2} with {1} and had its tired body healed there. {4} that {3}. - case 6 when !mc.HasPokeCenter(GameVersion.Any, mem.HT_TextVar): + case 6 when !mc.HasPokeCenter(GameVersion.Any, mem.HandlingTrainerMemoryVariable): data.AddLine(GetInvalid(string.Format(LMemoryArgBadLocation, L_XHT))); return; // {0} was with {1} when {1} caught {2}. {4} that {3}. case 14: - var result = GetCanBeCaptured(mem.HT_TextVar, mc.Context, GameVersion.Any) // Any Game in the Handling Trainer's generation + var result = GetCanBeCaptured(mem.HandlingTrainerMemoryVariable, mc.Context, GameVersion.Any) // Any Game in the Handling Trainer's generation ? GetValid(string.Format(LMemoryArgSpecies, L_XHT)) : GetInvalid(string.Format(LMemoryArgBadSpecies, L_XHT)); data.AddLine(result); @@ -465,14 +465,14 @@ private void VerifyHTMemory(LegalityAnalysis data, EntityContext memoryGen) data.AddLine(commonResult); } - private static bool WasTradedSWSHEgg(PKM pk) => pk.SWSH && (!pk.IsEgg ? pk.Egg_Location : pk.Met_Location) is Locations.LinkTrade6; + private static bool WasTradedSWSHEgg(PKM pk) => pk.SWSH && (!pk.IsEgg ? pk.EggLocation : pk.MetLocation) is Locations.LinkTrade6; private void VerifyHTMemoryTransferTo7(LegalityAnalysis data, PKM pk, LegalInfo Info) { var mem = (ITrainerMemories)pk; // Bank Transfer adds in the Link Trade Memory. // Trading 7<->7 between games (not Bank) clears this data. - if (mem.HT_Memory == 0) + if (mem.HandlingTrainerMemory == 0) { VerifyHTMemoryNone(data, mem); return; @@ -480,17 +480,17 @@ private void VerifyHTMemoryTransferTo7(LegalityAnalysis data, PKM pk, LegalInfo // Transfer 6->7 & withdraw to same HT => keeps past gen memory // Don't require link trade memory for these past gen cases - int gen = Info.Generation; + var gen = Info.Generation; if (gen is >= 3 and < 7 && pk.CurrentHandler == 1) return; - if (mem.HT_Memory != 4) + if (mem.HandlingTrainerMemory != 4) data.AddLine(Severity.Invalid, LMemoryIndexLinkHT, CheckIdentifier.Memory); - if (mem.HT_TextVar != 0) + if (mem.HandlingTrainerMemoryVariable != 0) data.AddLine(Severity.Invalid, LMemoryIndexArgHT, CheckIdentifier.Memory); - if (mem.HT_Intensity != 1) + if (mem.HandlingTrainerMemoryIntensity != 1) data.AddLine(Severity.Invalid, LMemoryIndexIntensityHT1, CheckIdentifier.Memory); - if (mem.HT_Feeling > 10) + if (mem.HandlingTrainerMemoryFeeling > 10) data.AddLine(Severity.Invalid, LMemoryIndexFeelHT09, CheckIdentifier.Memory); } } diff --git a/PKHeX.Core/Legality/Verifiers/Misc/ContestStatGrantingSheen.cs b/PKHeX.Core/Legality/Verifiers/Misc/ContestStatGrantingSheen.cs index 75eaae419..ab33df6eb 100644 --- a/PKHeX.Core/Legality/Verifiers/Misc/ContestStatGrantingSheen.cs +++ b/PKHeX.Core/Legality/Verifiers/Misc/ContestStatGrantingSheen.cs @@ -1,7 +1,7 @@ namespace PKHeX.Core; /// -/// Rules for how is obtained. +/// Rules for how is obtained. /// public enum ContestStatGrantingSheen { diff --git a/PKHeX.Core/Legality/Verifiers/Misc/ContestStatInfo.cs b/PKHeX.Core/Legality/Verifiers/Misc/ContestStatInfo.cs index f9ba3b18e..099ad9612 100644 --- a/PKHeX.Core/Legality/Verifiers/Misc/ContestStatInfo.cs +++ b/PKHeX.Core/Legality/Verifiers/Misc/ContestStatInfo.cs @@ -42,7 +42,7 @@ public static void SetSuggestedContestStats(this PKM pk, IEncounterTemplate enc, if (restrict == None || pk.Species is not (int)Species.Milotic) baseStat.CopyContestStatsTo(s); // reset else - s.SetAllContestStatsTo(MaxContestStat, restrict == NoSheen ? baseStat.CNT_Sheen : MaxContestStat); + s.SetAllContestStatsTo(MaxContestStat, restrict == NoSheen ? baseStat.ContestSheen : MaxContestStat); } public static void SetMaxContestStats(this PKM pk, IEncounterTemplate enc, EvolutionHistory h) @@ -53,10 +53,10 @@ public static void SetMaxContestStats(this PKM pk, IEncounterTemplate enc, Evolu var baseStat = GetReferenceTemplate(enc); if (restrict == None) return; - s.SetAllContestStatsTo(MaxContestStat, restrict == NoSheen ? baseStat.CNT_Sheen : MaxContestStat); + s.SetAllContestStatsTo(MaxContestStat, restrict == NoSheen ? baseStat.ContestSheen : MaxContestStat); } - public static ContestStatGranting GetContestStatRestriction(PKM pk, int origin, EvolutionHistory h) => origin switch + public static ContestStatGranting GetContestStatRestriction(PKM pk, byte origin, EvolutionHistory h) => origin switch { 3 => pk.Format < 6 ? CorrelateSheen : Mixed, 4 => pk.Format < 6 ? CorrelateSheen : Mixed, @@ -67,20 +67,20 @@ public static void SetMaxContestStats(this PKM pk, IEncounterTemplate enc, Evolu _ => h.HasVisitedBDSP ? CorrelateSheen : None, // BD/SP Contests }; - public static int CalculateMaximumSheen(IContestStatsReadOnly s, int nature, IContestStatsReadOnly initial, bool pokeBlock3) + public static int CalculateMaximumSheen(IContestStatsReadOnly s, Nature nature, IContestStatsReadOnly initial, bool pokeBlock3) { if (s.IsAnyContestStatMax()) return MaxContestStat; if (s.IsContestEqual(initial)) - return initial.CNT_Sheen; + return initial.ContestSheen; if (pokeBlock3) return CalculateMaximumSheen3(s, nature, initial); var avg = GetAverageFeel(s, nature, initial); if (avg <= 0) - return initial.CNT_Sheen; + return initial.ContestSheen; if (avg <= 2) return 59; @@ -98,54 +98,54 @@ public static int CalculateMaximumSheen(IContestStatsReadOnly s, int nature, ICo }; // BD/SP has a slightly better stat:sheen ratio than Gen4; prefer if it has visited. - public static int CalculateMinimumSheen8b(IContestStatsReadOnly s, int nature, IContestStatsReadOnly initial) + public static int CalculateMinimumSheen8b(IContestStatsReadOnly s, Nature nature, IContestStatsReadOnly initial) { if (s.IsContestEqual(initial)) - return initial.CNT_Sheen; + return initial.ContestSheen; var rawAvg = GetAverageFeel(s, 0, initial); if (rawAvg == MaxContestStat) return BestSheenStat8b; - var avg = Math.Max(1, nature % 6 == 0 ? rawAvg : GetAverageFeel(s, nature, initial)); + var avg = Math.Max(1, (byte)nature % 6 == 0 ? rawAvg : GetAverageFeel(s, nature, initial)); avg = Math.Min(rawAvg, avg); // be generous avg = (BestSheenStat8b * avg) / MaxContestStat; return Math.Clamp(avg, LowestFeelPoffin8b, BestSheenStat8b); } - public static int CalculateMinimumSheen3(IContestStatsReadOnly s, int nature, IContestStatsReadOnly initial) + public static int CalculateMinimumSheen3(IContestStatsReadOnly s, Nature nature, IContestStatsReadOnly initial) { if (s.IsContestEqual(initial)) - return initial.CNT_Sheen; + return initial.ContestSheen; var rawAvg = GetAverageFeel(s, 0, initial); if (rawAvg == MaxContestStat) return BestSheenStat3; - var avg = Math.Max(1, nature % 6 == 0 ? rawAvg : GetAverageFeel(s, nature, initial)); + var avg = Math.Max(1, (byte)nature % 6 == 0 ? rawAvg : GetAverageFeel(s, nature, initial)); avg = Math.Min(rawAvg, avg); // be generous avg = (BestSheenStat3 * avg) / MaxContestStat; return Math.Clamp(avg, LowestFeelBlock3, BestSheenStat3); } - public static int CalculateMinimumSheen4(IContestStatsReadOnly s, int nature, IContestStatsReadOnly initial) + public static int CalculateMinimumSheen4(IContestStatsReadOnly s, Nature nature, IContestStatsReadOnly initial) { if (s.IsContestEqual(initial)) - return initial.CNT_Sheen; + return initial.ContestSheen; var rawAvg = GetAverageFeel(s, 0, initial); if (rawAvg == MaxContestStat) return MaxContestStat; - var avg = Math.Max(1, nature % 6 == 0 ? rawAvg : GetAverageFeel(s, nature, initial)); + var avg = Math.Max(1, (byte)nature % 6 == 0 ? rawAvg : GetAverageFeel(s, nature, initial)); avg = Math.Min(rawAvg, avg); // be generous return Math.Clamp(avg, LowestFeelPoffin4, MaxContestStat); } - private static int CalculateMaximumSheen3(IContestStatsReadOnly s, int nature, IContestStatsReadOnly initial) + private static int CalculateMaximumSheen3(IContestStatsReadOnly s, Nature nature, IContestStatsReadOnly initial) { // By using Enigma and Lansat and a 25 +1/-1, can get a +9/+19s at minimum RPM // By using Strib, Chilan, Niniku, or Topo, can get a black +2/2/2 & 83 block (6:83) at minimum RPM. @@ -155,11 +155,11 @@ private static int CalculateMaximumSheen3(IContestStatsReadOnly s, int nature, I return 0; static int Gained2(byte a, byte b) => a - b >= 2 ? 1 : 0; - int gained = Gained2(s.CNT_Cool, initial.CNT_Cool) - + Gained2(s.CNT_Beauty, initial.CNT_Beauty) - + Gained2(s.CNT_Cute, initial.CNT_Cute) - + Gained2(s.CNT_Smart, initial.CNT_Smart) - + Gained2(s.CNT_Tough, initial.CNT_Tough); + int gained = Gained2(s.ContestCool, initial.ContestCool) + + Gained2(s.ContestBeauty, initial.ContestBeauty) + + Gained2(s.ContestCute, initial.ContestCute) + + Gained2(s.ContestSmart, initial.ContestSmart) + + Gained2(s.ContestTough, initial.ContestTough); bool has3 = gained >= 3; // Prefer the bad-black-block correlation if more than 3 stats have gains >= 2. @@ -167,7 +167,7 @@ private static int CalculateMaximumSheen3(IContestStatsReadOnly s, int nature, I return Math.Clamp(permit, LowestFeelBlock3, MaxContestStat); } - private static int GetAverageFeel(IContestStatsReadOnly s, int nature, IContestStatsReadOnly initial) + private static int GetAverageFeel(IContestStatsReadOnly s, Nature nature, IContestStatsReadOnly initial) { var sum = GetGainedSum(s, nature, initial); return (int)Math.Ceiling(sum / 5f); @@ -180,15 +180,15 @@ private static int GetAverageFeel(IContestStatsReadOnly s, int nature, IContestS private const int AmpIndexSmart = 3; // Bitter private const int AmpIndexCute = 4; // Sweet - private static int GetGainedSum(IContestStatsReadOnly s, int nature, IContestStatsReadOnly initial) + private static int GetGainedSum(IContestStatsReadOnly s, Nature nature, IContestStatsReadOnly initial) { var span = NatureAmp.GetAmps(nature); int sum = 0; - sum += GetAmpedStat(span, AmpIndexCool, s.CNT_Cool, initial.CNT_Cool); - sum += GetAmpedStat(span, AmpIndexTough, s.CNT_Tough, initial.CNT_Tough); - sum += GetAmpedStat(span, AmpIndexBeauty, s.CNT_Beauty, initial.CNT_Beauty); - sum += GetAmpedStat(span, AmpIndexSmart, s.CNT_Smart, initial.CNT_Smart); - sum += GetAmpedStat(span, AmpIndexCute, s.CNT_Cute, initial.CNT_Cute); + sum += GetAmpedStat(span, AmpIndexCool, s.ContestCool, initial.ContestCool); + sum += GetAmpedStat(span, AmpIndexTough, s.ContestTough, initial.ContestTough); + sum += GetAmpedStat(span, AmpIndexBeauty, s.ContestBeauty, initial.ContestBeauty); + sum += GetAmpedStat(span, AmpIndexSmart, s.ContestSmart, initial.ContestSmart); + sum += GetAmpedStat(span, AmpIndexCute, s.ContestCute, initial.ContestCute); return sum; } @@ -228,11 +228,11 @@ static int Boost(int stat, int factor) private sealed class DummyContestNone : IContestStatsReadOnly { - public byte CNT_Cool => 0; - public byte CNT_Beauty => 0; - public byte CNT_Cute => 0; - public byte CNT_Smart => 0; - public byte CNT_Tough => 0; - public byte CNT_Sheen => 0; + public byte ContestCool => 0; + public byte ContestBeauty => 0; + public byte ContestCute => 0; + public byte ContestSmart => 0; + public byte ContestTough => 0; + public byte ContestSheen => 0; } } diff --git a/PKHeX.Core/Legality/Verifiers/MiscVerifier.cs b/PKHeX.Core/Legality/Verifiers/MiscVerifier.cs index 4a168b88a..8c2213a32 100644 --- a/PKHeX.Core/Legality/Verifiers/MiscVerifier.cs +++ b/PKHeX.Core/Legality/Verifiers/MiscVerifier.cs @@ -77,7 +77,7 @@ public override void Verify(LegalityAnalysis data) var enc = data.EncounterMatch; if (enc is IEncounterServerDate { IsDateRestricted: true } serverGift) { - var date = new DateOnly(pk.Met_Year + 2000, pk.Met_Month, pk.Met_Day); + var date = new DateOnly(pk.MetYear + 2000, pk.MetMonth, pk.MetDay); // HOME Gifts for Sinnoh/Hisui starters were forced JPN until May 20, 2022 (UTC). if (enc is WB8 { CardID: 9015 or 9016 or 9017 } or WA8 { CardID: 9018 or 9019 or 9020 }) @@ -168,7 +168,7 @@ private void VerifySVStats(LegalityAnalysis data, PK9 pk9) if (!pk9.IsBattleVersionValid(data.Info.EvoChainsAllGens)) data.AddLine(GetInvalid(LStatBattleVersionInvalid)); - if (!IsObedienceLevelValid(pk9, pk9.Obedience_Level, pk9.Met_Level)) + if (!IsObedienceLevelValid(pk9, pk9.Obedience_Level, pk9.MetLevel)) data.AddLine(GetInvalid(LTransferObedienceLevel)); if (pk9.IsEgg) { @@ -224,7 +224,7 @@ private void VerifySVStats(LegalityAnalysis data, PK9 pk9) data.AddLine(GetInvalid(LTransferBad)); } - if (!Locations9.IsAccessiblePreDLC((ushort)pk9.Met_Location)) + if (!Locations9.IsAccessiblePreDLC(pk9.MetLocation)) { if (enc is { Species: (int)Species.Larvesta, Form: 0 } and not EncounterEgg) DisallowLevelUpMove(24, (ushort)Move.BugBite, pk9, data); @@ -295,8 +295,8 @@ private void VerifyMiscPokerus(LegalityAnalysis data) if (pk.Format == 1) return; - var strain = pk.PKRS_Strain; - var days = pk.PKRS_Days; + var strain = pk.PokerusStrain; + var days = pk.PokerusDays; bool strainValid = Pokerus.IsStrainValid(pk, strain, days); if (!strainValid) data.AddLine(GetInvalid(string.Format(LPokerusStrainUnobtainable_0, strain))); @@ -316,7 +316,7 @@ public void VerifyMiscG1(LegalityAnalysis data) { if (pk is ICaughtData2 { CaughtData: not 0 } t) { - var time = t.Met_TimeOfDay; + var time = t.MetTimeOfDay; bool valid = data.EncounterOriginal switch { EncounterGift2 g2 when (!g2.EggEncounter || pk.IsEgg) => time == 0, @@ -417,7 +417,7 @@ private static void VerifyMiscFatefulEncounter(LegalityAnalysis data) // Hatching in Gen3 doesn't change the origin version. if (pk.Format != 3) return; // possible hatched in either game, don't bother checking - if (Locations.IsMetLocation3RS((ushort)pk.Met_Location)) // hatched in RS or Emerald + if (Locations.IsMetLocation3RS(pk.MetLocation)) // hatched in RS or Emerald return; // possible hatched in either game, don't bother checking // else, ensure fateful is active (via below) } @@ -548,7 +548,7 @@ private static void VerifyFatefulMysteryGift(LegalityAnalysis data, MysteryGift { var Info = data.Info; Info.PIDIV = MethodFinder.Analyze(pk); - if (Info.PIDIV.Type != PIDType.G5MGShiny && pk.Egg_Location != Locations.LinkTrade5) + if (Info.PIDIV.Type != PIDType.G5MGShiny && pk.EggLocation != Locations.LinkTrade5) data.AddLine(GetInvalid(LPIDTypeMismatch, PID)); } @@ -608,8 +608,8 @@ public void VerifyVersionEvolution(LegalityAnalysis data) case (int)Species.Lycanroc when pk.Format == 7 && ((pk.Form == 0 && Moon()) || (pk.Form == 1 && Sun())): case (int)Species.Solgaleo when Moon(): case (int)Species.Lunala when Sun(): - bool Sun() => (pk.Version & 1) == 0; - bool Moon() => (pk.Version & 1) == 1; + bool Sun() => ((uint)pk.Version & 1) == 0; + bool Moon() => ((uint)pk.Version & 1) == 1; if (pk.IsUntraded) data.AddLine(GetInvalid(LEvoTradeRequired, Evolution)); break; @@ -796,8 +796,8 @@ private static bool CheckHeightWeightOdds(IEncounterTemplate enc) private void VerifyStatNature(LegalityAnalysis data, PKM pk) { - var sn = pk.StatNature; - if (sn == pk.Nature) + var sn = (byte)pk.StatNature; + if (sn == (byte)pk.Nature) return; // Only allow Serious nature (12); disallow all other neutral natures. if (sn != 12 && (sn > 24 || sn % 6 == 0)) diff --git a/PKHeX.Core/Legality/Verifiers/NicknameVerifier.cs b/PKHeX.Core/Legality/Verifiers/NicknameVerifier.cs index 959ab19be..f2aa274b1 100644 --- a/PKHeX.Core/Legality/Verifiers/NicknameVerifier.cs +++ b/PKHeX.Core/Legality/Verifiers/NicknameVerifier.cs @@ -213,7 +213,7 @@ private static bool CanNicknameForeign8Plus(LegalityAnalysis data, PKM pk) return false; } - private static int GetForeignNicknameLength(PKM pk, IEncounterTemplate match, int origin) + private static int GetForeignNicknameLength(PKM pk, IEncounterTemplate match, byte origin) { // HOME gifts already verified prior to reaching here. System.Diagnostics.Debug.Assert(match is not WC8 {IsHOMEGift:true}); @@ -236,7 +236,7 @@ private static int GetForeignNicknameLength(PKM pk, IEncounterTemplate match, in private static bool IsNicknameValid(PKM pk, IEncounterTemplate enc, ReadOnlySpan nickname) { ushort species = pk.Species; - int format = pk.Format; + byte format = pk.Format; int language = pk.Language; var expect = SpeciesName.GetSpeciesNameGeneration(species, language, format); if (nickname.SequenceEqual(expect)) @@ -348,7 +348,7 @@ private static void VerifyTrade8b(LegalityAnalysis data, EncounterTrade8b t) return; } - lang = t.DetectMeisterMagikarpLanguage(pk.Nickname, pk.OT_Name, lang); + lang = t.DetectMeisterMagikarpLanguage(pk.Nickname, pk.OriginalTrainerName, lang); if (lang == -1) // err data.AddLine(GetInvalid(string.Format(LOTLanguage, $"{Japanese}/{German}", $"{(LanguageID)pk.Language}"), CheckIdentifier.Language)); } @@ -385,7 +385,7 @@ private static CheckResult CheckTradeOTOnly(LegalityAnalysis data, IFixedTrainer if (pk.IsNicknamed && (pk.Format < 8 || pk.FatefulEncounter)) return GetInvalid(LEncTradeChangedNickname, CheckIdentifier.Nickname); int lang = pk.Language; - if (!t.IsTrainerMatch(pk, pk.OT_Name, lang)) + if (!t.IsTrainerMatch(pk, pk.OriginalTrainerName, lang)) return GetInvalid(LEncTradeIndexBad, CheckIdentifier.Trainer); return GetValid(LEncTradeUnchanged, CheckIdentifier.Nickname); } @@ -410,7 +410,7 @@ private static void VerifyNickname(LegalityAnalysis data, IFixedNickname fn, int private static void VerifyTrainerName(LegalityAnalysis data, IFixedTrainer ft, int language) { var pk = data.Entity; - if (!ft.IsTrainerMatch(pk, pk.OT_Name, language)) + if (!ft.IsTrainerMatch(pk, pk.OriginalTrainerName, language)) data.AddLine(GetInvalid(LEncTradeChangedOT, CheckIdentifier.Trainer)); } } diff --git a/PKHeX.Core/Legality/Verifiers/PIDVerifier.cs b/PKHeX.Core/Legality/Verifiers/PIDVerifier.cs index 7da5e2734..4c497ca54 100644 --- a/PKHeX.Core/Legality/Verifiers/PIDVerifier.cs +++ b/PKHeX.Core/Legality/Verifiers/PIDVerifier.cs @@ -23,7 +23,7 @@ public override void Verify(LegalityAnalysis data) if (pk.PID == 0) data.AddLine(Get(LPIDZero, Severity.Fishy)); - if (pk.Nature >= 25) // out of range + if (!pk.Nature.IsFixed()) // out of range data.AddLine(GetInvalid(LPIDNatureMismatch)); VerifyShiny(data); @@ -161,8 +161,8 @@ private static void VerifyEC(LegalityAnalysis data) /// True if the is appropriate to use. public static bool GetTransferEC(PKM pk, out uint ec) { - var ver = pk.Version; - if (ver is 0 or >= (int)GameVersion.X) // Gen6+ ignored + var version = pk.Version; + if (version is 0 or >= GameVersion.X) // Gen6+ ignored { ec = 0; return false; diff --git a/PKHeX.Core/Legality/Verifiers/ParseSettings.cs b/PKHeX.Core/Legality/Verifiers/ParseSettings.cs index 19efa4a1c..a526e22be 100644 --- a/PKHeX.Core/Legality/Verifiers/ParseSettings.cs +++ b/PKHeX.Core/Legality/Verifiers/ParseSettings.cs @@ -28,10 +28,11 @@ public static class ParseSettings public static Severity NicknamedTrade { get; private set; } = Severity.Invalid; public static Severity NicknamedMysteryGift { get; private set; } = Severity.Fishy; - public static Severity RNGFrameNotFound { get; private set; } = Severity.Fishy; + public static Severity RNGFrameNotFound3 { get; private set; } = Severity.Fishy; + public static Severity RNGFrameNotFound4 { get; private set; } = Severity.Invalid; public static Severity Gen7TransferStarPID { get; private set; } = Severity.Fishy; public static Severity Gen8MemoryMissingHT { get; private set; } = Severity.Fishy; - public static Severity Gen8TransferTrackerNotPresent { get; private set; } = Severity.Fishy; + public static Severity HOMETransferTrackerNotPresent { 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; @@ -95,7 +96,7 @@ public static bool InitFromSaveFileData(SaveFile sav) }; } - internal static bool IgnoreTransferIfNoTracker => Gen8TransferTrackerNotPresent == Severity.Invalid; + internal static bool IgnoreTransferIfNoTracker => HOMETransferTrackerNotPresent == Severity.Invalid; public static void InitFromSettings(IParseSettings settings) { @@ -103,9 +104,10 @@ public static void InitFromSettings(IParseSettings settings) AllowGen1Tradeback = settings.AllowGen1Tradeback; NicknamedTrade = settings.NicknamedTrade; NicknamedMysteryGift = settings.NicknamedMysteryGift; - RNGFrameNotFound = settings.RNGFrameNotFound; + RNGFrameNotFound3 = settings.RNGFrameNotFound3; + RNGFrameNotFound4 = settings.RNGFrameNotFound4; Gen7TransferStarPID = settings.Gen7TransferStarPID; - Gen8TransferTrackerNotPresent = settings.Gen8TransferTrackerNotPresent; + HOMETransferTrackerNotPresent = settings.HOMETransferTrackerNotPresent; Gen8MemoryMissingHT = settings.Gen8MemoryMissingHT; NicknamedAnotherSpecies = settings.NicknamedAnotherSpecies; ZeroHeightWeight = settings.ZeroHeightWeight; @@ -122,10 +124,11 @@ public interface IParseSettings Severity NicknamedTrade { get; } Severity NicknamedMysteryGift { get; } - Severity RNGFrameNotFound { get; } + Severity RNGFrameNotFound3 { get; } + Severity RNGFrameNotFound4 { get; } Severity Gen7TransferStarPID { get; } Severity Gen8MemoryMissingHT { get; } - Severity Gen8TransferTrackerNotPresent { get; } + Severity HOMETransferTrackerNotPresent { get; } Severity NicknamedAnotherSpecies { get; } Severity ZeroHeightWeight { get; } Severity CurrentHandlerMismatch { get; } diff --git a/PKHeX.Core/Legality/Verifiers/Ribbons/MarkRules.cs b/PKHeX.Core/Legality/Verifiers/Ribbons/MarkRules.cs index 37ecadae0..ece7af882 100644 --- a/PKHeX.Core/Legality/Verifiers/Ribbons/MarkRules.cs +++ b/PKHeX.Core/Legality/Verifiers/Ribbons/MarkRules.cs @@ -48,7 +48,7 @@ public static bool IsEncounterMarkLost(IEncounterTemplate enc, PKM pk) { MarkCurry when !IsMarkAllowedCurry(pk, x) => false, MarkFishing when !IsMarkAllowedFishing(x) => false, - MarkMisty when x.Generation == 8 && pk.Met_Level < EncounterArea8.BoostLevel && EncounterArea8.IsBoostedArea60Fog(pk.Met_Location) => false, + MarkMisty when x.Generation == 8 && pk.MetLevel < EncounterArea8.BoostLevel && EncounterArea8.IsBoostedArea60Fog(pk.MetLocation) => false, MarkDestiny => x is EncounterSlot9, // Capture on Birthday >= MarkCloudy and <= MarkMisty => IsWeatherPermitted8(mark, x), _ => true, @@ -79,7 +79,7 @@ public static bool IsEncounterMarkLost(IEncounterTemplate enc, PKM pk) MarkFishing => false, MarkDestiny => true, // Capture on Birthday >= MarkLunchtime and <= MarkDawn => true, // no time restrictions - >= MarkCloudy and <= MarkMisty => pk is PK8 || EncounterSlot9.CanSpawnInWeather(mark, (byte)pk.Met_Location), + >= MarkCloudy and <= MarkMisty => pk is PK8 || EncounterSlot9.CanSpawnInWeather(mark, (byte)pk.MetLocation), _ => true, }; diff --git a/PKHeX.Core/Legality/Verifiers/Ribbons/RibbonRules.cs b/PKHeX.Core/Legality/Verifiers/Ribbons/RibbonRules.cs index 66fe59d37..e4d0c36e0 100644 --- a/PKHeX.Core/Legality/Verifiers/Ribbons/RibbonRules.cs +++ b/PKHeX.Core/Legality/Verifiers/Ribbons/RibbonRules.cs @@ -50,8 +50,8 @@ public static bool IsRibbonValidAlolaChamp(IRibbonSetCommon7 s7, IEncounterTempl { HasVisitedBDSP: true } => true, // Max Friendship { HasVisitedGen9: true } => true, // Max Friendship - { HasVisitedGen6: true } when pk is not PK6 { IsUntraded: true, OT_Affection: < 255 } => true, - { HasVisitedGen7: true } when pk is not PK7 { IsUntraded: true, OT_Affection: < 255 } => true, + { HasVisitedGen6: true } when pk is not PK6 { IsUntraded: true, OriginalTrainerAffection: < 255 } => true, + { HasVisitedGen7: true } when pk is not PK7 { IsUntraded: true, OriginalTrainerAffection: < 255 } => true, _ => false, }; @@ -69,7 +69,7 @@ public static bool IsRibbonValidFootprint(PKM pk, EvolutionHistory evos) return false; // Gen6/7: Increase level by 30 from original level - static bool IsWellTraveled30(PKM pk) => pk.CurrentLevel - pk.Met_Level >= 30; + static bool IsWellTraveled30(PKM pk) => pk.CurrentLevel - pk.MetLevel >= 30; if ((evos.HasVisitedGen6 || evos.HasVisitedGen7) && IsWellTraveled30(pk)) return true; @@ -174,7 +174,7 @@ public static bool IsRibbonValidWinning(PKM pk, IEncounterTemplate enc, Evolutio // Can only obtain if the current level on receiving the ribbon is <= level 50. if (pk.Format == 3) // Stored value is not yet overwritten (G3->G4), check directly. - return pk.Met_Level <= 50; + return pk.MetLevel <= 50; // Most encounter types can be below level 50; only Shadow Dragonite & Tyranitar, and select Gen3 Event Gifts. // These edge cases can't be obtained below level 50, unlike some wild Pokémon which can be encountered at different locations for lower levels. diff --git a/PKHeX.Core/Legality/Verifiers/Ribbons/RibbonVerifierCommon6.cs b/PKHeX.Core/Legality/Verifiers/Ribbons/RibbonVerifierCommon6.cs index 90c5cd299..9dc692297 100644 --- a/PKHeX.Core/Legality/Verifiers/Ribbons/RibbonVerifierCommon6.cs +++ b/PKHeX.Core/Legality/Verifiers/Ribbons/RibbonVerifierCommon6.cs @@ -37,7 +37,7 @@ public static void Parse(this IRibbonSetCommon6 r, in RibbonVerifierArguments ar { // Winning a contest in Gen6 adds 20 to OT affection. Each ribbon, add 20 to our expected minimum. if (pk is IAffection a) // False in Gen8+ - FlagContestAffection(r, ref list, a.OT_Affection); + FlagContestAffection(r, ref list, a.OriginalTrainerAffection); // Winning all contests grants the Contest Star ribbon. // If we have all ribbons and the star is not present, flag it as missing. @@ -99,7 +99,7 @@ private static void GetInvalidRibbons6Memory(IRibbonSetMemory6 r, in RibbonVerif list.Add(CountMemoryBattle); } - private static bool IsCountFlagValid(byte count, bool state, int format, byte max) + private static bool IsCountFlagValid(byte count, bool state, byte format, byte max) { if (count > max) return false; @@ -173,7 +173,7 @@ private static bool GetHasGen6ChampMemory(PKM pk, IEncounterTemplate enc) // Gen6 can get the memory with any party member when defeating the champion. const int memChampion = 27; - return (enc.Generation == 6 && m.OT_Memory == memChampion) - || (pk.Format < 8 && m.HT_Memory == memChampion); + return (enc.Generation == 6 && m.OriginalTrainerMemory == memChampion) + || (pk.Format < 8 && m.HandlingTrainerMemory == memChampion); } } diff --git a/PKHeX.Core/Legality/Verifiers/Ribbons/RibbonVerifierCommon8.cs b/PKHeX.Core/Legality/Verifiers/Ribbons/RibbonVerifierCommon8.cs index 2f16c964e..93035c61a 100644 --- a/PKHeX.Core/Legality/Verifiers/Ribbons/RibbonVerifierCommon8.cs +++ b/PKHeX.Core/Legality/Verifiers/Ribbons/RibbonVerifierCommon8.cs @@ -34,8 +34,8 @@ public static void Parse(this IRibbonSetCommon8 r, in RibbonVerifierArguments ar if (!r.RibbonChampionGalar) { const int memChampion = 27; - bool hasChampMemory = (enc.Generation == 8 && pk is IMemoryOT { OT_Memory: memChampion }) - || (pk.Format == 8 && pk is IMemoryHT { HT_Memory: memChampion }); + bool hasChampMemory = (enc.Generation == 8 && pk is IMemoryOT { OriginalTrainerMemory: memChampion }) + || (pk.Format == 8 && pk is IMemoryHT { HandlingTrainerMemory: memChampion }); if (hasChampMemory) list.Add(ChampionGalar, true); } @@ -48,7 +48,7 @@ public static void Parse(this IRibbonSetCommon8 r, in RibbonVerifierArguments ar // If the Tower Master ribbon is not present but a memory hint implies it should... // This memory can also be applied in Gen6/7 via defeating the Chatelaines, where legends are disallowed. const int strongest = 30; - if (pk is IMemoryOT { OT_Memory: strongest } or IMemoryHT { HT_Memory: strongest }) + if (pk is IMemoryOT { OriginalTrainerMemory: strongest } or IMemoryHT { HandlingTrainerMemory: strongest }) { if (enc.Generation == 8 || !RibbonRules.IsAllowedBattleFrontier(pk.Species) || pk is IRibbonSetCommon6 { RibbonBattlerSkillful: false }) list.Add(TowerMaster, true); diff --git a/PKHeX.Core/Legality/Verifiers/TrainerIDVerifier.cs b/PKHeX.Core/Legality/Verifiers/TrainerIDVerifier.cs index 7a9d40b22..25e73952e 100644 --- a/PKHeX.Core/Legality/Verifiers/TrainerIDVerifier.cs +++ b/PKHeX.Core/Legality/Verifiers/TrainerIDVerifier.cs @@ -3,7 +3,7 @@ namespace PKHeX.Core; /// -/// Verifies the . +/// Verifies the . /// public sealed class TrainerIDVerifier : Verifier { diff --git a/PKHeX.Core/Legality/Verifiers/TrainerNameVerifier.cs b/PKHeX.Core/Legality/Verifiers/TrainerNameVerifier.cs index d28b8295e..5ab54e58b 100644 --- a/PKHeX.Core/Legality/Verifiers/TrainerNameVerifier.cs +++ b/PKHeX.Core/Legality/Verifiers/TrainerNameVerifier.cs @@ -4,7 +4,7 @@ namespace PKHeX.Core; /// -/// Verifies the . +/// Verifies the . /// public sealed class TrainerNameVerifier : Verifier { @@ -23,7 +23,7 @@ public override void Verify(LegalityAnalysis data) if (!IsPlayerOriginalTrainer(enc)) return; // already verified - var ot = pk.OT_Name; + var ot = pk.OriginalTrainerName; if (ot.Length == 0) data.AddLine(GetInvalid(LOTShort)); @@ -49,7 +49,7 @@ public override void Verify(LegalityAnalysis data) if (ContainsTooManyNumbers(ot, data.Info.Generation)) data.AddLine(GetInvalid("Word Filter: Too many numbers.")); - if (WordFilter.IsFiltered(pk.HT_Name, out badPattern)) + if (WordFilter.IsFiltered(pk.HandlingTrainerName, out badPattern)) data.AddLine(GetInvalid($"Word Filter: {badPattern}")); } } @@ -69,7 +69,7 @@ public static bool IsEdgeCaseLength(PKM pk, IEncounterTemplate e, ReadOnlySpanGen7 won't have OT Gender in PK1, nor will PK1 originated encounters. // GSC Trades already checked for OT Gender matching. @@ -101,7 +101,7 @@ public void VerifyOTGB(LegalityAnalysis data) if (enc is IFixedTrainer { IsFixedTrainer: true }) return; // already verified - string tr = pk.OT_Name; + string tr = pk.OriginalTrainerName; if (tr.Length == 0) { if (pk is SK2 {TID16: 0, IsRental: true}) diff --git a/PKHeX.Core/Legality/Verifiers/TransferVerifier.cs b/PKHeX.Core/Legality/Verifiers/TransferVerifier.cs index 034498903..084c5eecb 100644 --- a/PKHeX.Core/Legality/Verifiers/TransferVerifier.cs +++ b/PKHeX.Core/Legality/Verifiers/TransferVerifier.cs @@ -26,14 +26,14 @@ public void VerifyTransferLegalityG12(LegalityAnalysis data) private void VerifyVCOTGender(LegalityAnalysis data) { var pk = data.Entity; - if (pk.OT_Gender == 1 && pk.Version != (int)GameVersion.C) + if (pk.OriginalTrainerGender == 1 && pk.Version != GameVersion.C) data.AddLine(GetInvalid(LG2OTGender)); } private void VerifyVCNatureEXP(LegalityAnalysis data) { var pk = data.Entity; - var met = pk.Met_Level; + var met = pk.MetLevel; if (met == 100) // check for precise match, can't receive EXP after transfer. { @@ -53,12 +53,12 @@ private void VerifyVCNatureEXP(LegalityAnalysis data) } } - private static bool VerifyVCNature(int growth, int nature) => growth switch + private static bool VerifyVCNature(byte growth, Nature nature) => growth switch { // exp % 25 with a limited amount of EXP does not allow for every nature - 0 => (0x01FFFF03 & (1 << nature)) != 0, // MediumFast -- Can't be Brave, Adamant, Naughty, Bold, Docile, or Relaxed - 4 => (0x001FFFC0 & (1 << nature)) != 0, // Fast -- Can't be Gentle, Sassy, Careful, Quirky, Hardy, Lonely, Brave, Adamant, Naughty, or Bold - 5 => (0x01FFFCFF & (1 << nature)) != 0, // Slow -- Can't be Impish or Lax + 0 => (0x01FFFF03u & (1u << (byte)nature)) != 0, // MediumFast -- Can't be Brave, Adamant, Naughty, Bold, Docile, or Relaxed + 4 => (0x001FFFC0u & (1u << (byte)nature)) != 0, // Fast -- Can't be Gentle, Sassy, Careful, Quirky, Hardy, Lonely, Brave, Adamant, Naughty, or Bold + 5 => (0x01FFFCFFu & (1u << (byte)nature)) != 0, // Slow -- Can't be Impish or Lax _ => true, }; @@ -87,12 +87,12 @@ public void VerifyTransferLegalityG3(LegalityAnalysis data) var pk = data.Entity; if (pk.Format == 4) // Pal Park (3->4) { - if (pk.Met_Location != Locations.Transfer3) + if (pk.MetLocation != Locations.Transfer3) data.AddLine(GetInvalid(LEggLocationPalPark)); } else // Transporter (4->5) { - if (pk.Met_Location != Locations.Transfer4) + if (pk.MetLocation != Locations.Transfer4) data.AddLine(GetInvalid(LTransferEggLocationTransporter)); } } @@ -100,7 +100,7 @@ public void VerifyTransferLegalityG3(LegalityAnalysis data) public void VerifyTransferLegalityG4(LegalityAnalysis data) { var pk = data.Entity; - int loc = pk.Met_Location; + ushort loc = pk.MetLocation; if (loc == Locations.Transfer4) return; @@ -190,7 +190,7 @@ private void VerifyHOMETracker(LegalityAnalysis data, PKM pk) // Can't validate the actual values (we aren't the server), so we can only check against zero. if (pk is IHomeTrack { HasTracker: false }) { - data.AddLine(Get(LTransferTrackerMissing, ParseSettings.Gen8TransferTrackerNotPresent)); + data.AddLine(Get(LTransferTrackerMissing, ParseSettings.HOMETransferTrackerNotPresent)); // To the reader: It seems like the best course of action for setting a tracker is: // - Transfer a 0-Tracker pk to HOME to get assigned a valid Tracker // - Don't make one up. @@ -199,11 +199,11 @@ private void VerifyHOMETracker(LegalityAnalysis data, PKM pk) public void VerifyVCEncounter(PKM pk, IEncounterTemplate original, EncounterTransfer7 transfer, LegalityAnalysis data) { - if (pk.Met_Location != transfer.Location) + if (pk.MetLocation != transfer.Location) data.AddLine(GetInvalid(LTransferMetLocation)); - var expecteEgg = pk is PB8 ? Locations.Default8bNone : transfer.EggLocation; - if (pk.Egg_Location != expecteEgg) + var expectEgg = pk is PB8 ? Locations.Default8bNone : transfer.EggLocation; + if (pk.EggLocation != expectEgg) data.AddLine(GetInvalid(LEggLocationNone)); // Flag Moves that cannot be transferred @@ -228,13 +228,13 @@ public void VerifyVCEncounter(PKM pk, IEncounterTemplate original, EncounterTran } } - private static void FlagIncompatibleTransferMove(PKM pk, Span parse, ushort move, int gen) + private static void FlagIncompatibleTransferMove(PKM pk, Span parse, ushort move, byte generation) { int index = pk.GetMoveIndex(move); if (index < 0) return; // doesn't have move - if (parse[index].Generation == gen) // not obtained from a future gen + if (parse[index].Generation == generation) // not obtained from a future gen parse[index] = MoveResult.Unobtainable(0); } } diff --git a/PKHeX.Core/Moves/MoveInfo.cs b/PKHeX.Core/Moves/MoveInfo.cs index d13a2bb94..961e26388 100644 --- a/PKHeX.Core/Moves/MoveInfo.cs +++ b/PKHeX.Core/Moves/MoveInfo.cs @@ -230,7 +230,7 @@ private static byte GetType(ushort move, ReadOnlySpan types) return types[move]; } - public static bool IsAnyFromGeneration(int generation, ReadOnlySpan moves) + public static bool IsAnyFromGeneration(byte generation, ReadOnlySpan moves) { foreach (var move in moves) { diff --git a/PKHeX.Core/MysteryGifts/MysteryGift.cs b/PKHeX.Core/MysteryGifts/MysteryGift.cs index 43cf9c2ff..4775300a6 100644 --- a/PKHeX.Core/MysteryGifts/MysteryGift.cs +++ b/PKHeX.Core/MysteryGifts/MysteryGift.cs @@ -6,7 +6,7 @@ namespace PKHeX.Core; /// /// Mystery Gift Template File /// -public abstract class MysteryGift : IEncounterable, IMoveset, IRelearn, ITrainerID32, IFatefulEncounterReadOnly, IEncounterMatch +public abstract class MysteryGift : IEncounterable, IMoveset, ITrainerID32, IFatefulEncounterReadOnly, IEncounterMatch { /// /// Determines whether the given length of bytes is valid for a mystery gift. @@ -80,7 +80,8 @@ public abstract class MysteryGift : IEncounterable, IMoveset, IRelearn, ITrainer public string Extension => GetType().Name.ToLowerInvariant(); public string FileName => $"{CardHeader}.{Extension}"; - public abstract int Generation { get; } + public abstract byte Generation { get; } + public abstract GameVersion Version { get; } public abstract EntityContext Context { get; } public abstract bool FatefulEncounter { get; } @@ -120,14 +121,8 @@ public EncounterMatchRating GetMatchRating(PKM pk) /// public string LongName => $"{Name} ({Type})"; - public virtual GameVersion Version - { - get => GameUtil.GetVersion(Generation); - set { } - } - // Properties - public virtual ushort Species { get => 0; set { } } + public abstract ushort Species { get; set; } public abstract AbilityPermission Ability { get; } public abstract bool GiftUsed { get; set; } public abstract string CardTitle { get; set; } @@ -144,8 +139,6 @@ public virtual GameVersion Version // Search Properties public virtual Moveset Moves { get => default; set { } } - public virtual Moveset Relearn { get => default; set { } } - public virtual int[] IVs { get => []; set { } } public virtual bool HasFixedIVs => true; public virtual void GetIVs(Span value) { } public virtual bool IsShiny => false; @@ -159,25 +152,25 @@ public virtual Shiny Shiny public virtual bool IsEgg { get => false; set { } } public virtual int HeldItem { get => -1; set { } } public virtual int AbilityType { get => -1; set { } } - public abstract int Gender { get; set; } + public abstract byte Gender { get; set; } public abstract byte Form { get; set; } public abstract uint ID32 { get; set; } public abstract ushort TID16 { get; set; } public abstract ushort SID16 { get; set; } - public abstract string OT_Name { get; set; } - public abstract int Location { get; set; } + public abstract string OriginalTrainerName { get; set; } + public abstract ushort Location { get; set; } public abstract byte Level { get; set; } public byte LevelMin => Level; public byte LevelMax => Level; - public abstract int Ball { get; set; } + public abstract byte Ball { get; set; } public virtual bool EggEncounter => IsEgg; - public abstract int EggLocation { get; set; } + public abstract ushort EggLocation { get; set; } protected virtual bool IsMatchEggLocation(PKM pk) { var expect = EggEncounter ? EggLocation : pk is PB8 ? Locations.Default8bNone : 0; - return pk.Egg_Location == expect; + return pk.EggLocation == expect; } public Ball FixedBall => (Ball)Ball; diff --git a/PKHeX.Core/MysteryGifts/MysteryUtil.cs b/PKHeX.Core/MysteryGifts/MysteryUtil.cs index 0917d020c..15bbff93c 100644 --- a/PKHeX.Core/MysteryGifts/MysteryUtil.cs +++ b/PKHeX.Core/MysteryGifts/MysteryUtil.cs @@ -107,7 +107,7 @@ private static void AddLinesPKM(MysteryGift gift, IBasicStrings strings, List= 0 ? gift.HeldItem : 0]} --- " - + (gift.IsEgg ? strings.EggName : $"{gift.OT_Name} - {id}"); + + (gift.IsEgg ? strings.EggName : $"{gift.OriginalTrainerName} - {id}"); result.Add(first); result.Add(gift.Moves.GetMovesetLine(strings.Move)); @@ -140,13 +140,11 @@ public static bool IsCardCompatible(this MysteryGift g, SaveFile sav, out string return false; } - if (g is WC6 { CardID: 2048, ItemID: 726 }) // Eon Ticket (OR/AS) + if (g is WC6 { CardID: 2048, ItemID: 726 } && sav is not SAV6AO) { - if (sav is not SAV6AO) - { - message = MsgMysteryGiftSlotSpecialReject; - return false; - } + // Eon Ticket (OR/AS) + message = MsgMysteryGiftSlotSpecialReject; + return false; } message = string.Empty; diff --git a/PKHeX.Core/MysteryGifts/PCD.cs b/PKHeX.Core/MysteryGifts/PCD.cs index 3e160edae..6b5253c4a 100644 --- a/PKHeX.Core/MysteryGifts/PCD.cs +++ b/PKHeX.Core/MysteryGifts/PCD.cs @@ -18,10 +18,10 @@ public sealed class PCD(byte[] Data) public PCD() : this(new byte[Size]) { } public const int Size = 0x358; // 856 - public override int Generation => 4; + public override byte Generation => 4; public override EntityContext Context => EntityContext.Gen4; public override bool FatefulEncounter => Gift.PK.FatefulEncounter; - public override GameVersion Version { get=> Gift.Version; set => Gift.Version = value; } + public override GameVersion Version => Gift.Version; public override byte Level { @@ -29,7 +29,7 @@ public override byte Level set => Gift.Level = value; } - public override int Ball + public override byte Ball { get => Gift.Ball; set => Gift.Ball = value; @@ -86,19 +86,19 @@ public override string CardTitle public override bool IsShiny => Gift.IsShiny; public override Shiny Shiny => Gift.Shiny; public override bool IsEgg { get => Gift.IsEgg; set => Gift.IsEgg = value; } - public override int Gender { get => Gift.Gender; set => Gift.Gender = value; } + public override byte Gender { get => Gift.Gender; set => Gift.Gender = value; } public override byte Form { get => Gift.Form; set => Gift.Form = value; } public override uint ID32 { get => Gift.ID32; set => Gift.ID32 = value; } public override ushort TID16 { get => Gift.TID16; set => Gift.TID16 = value; } public override ushort SID16 { get => Gift.SID16; set => Gift.SID16 = value; } - public override string OT_Name { get => Gift.OT_Name; set => Gift.OT_Name = value; } + public override string OriginalTrainerName { get => Gift.OriginalTrainerName; set => Gift.OriginalTrainerName = value; } public override AbilityPermission Ability => Gift.Ability; public override bool HasFixedIVs => Gift.HasFixedIVs; public override void GetIVs(Span value) => Gift.GetIVs(value); // ILocation overrides - public override int Location { get => IsEgg ? 0 : Gift.EggLocation + 3000; set { } } - public override int EggLocation { get => IsEgg ? Gift.EggLocation + 3000 : 0; set { } } + public override ushort Location { get => (ushort)(IsEgg ? 0 : Gift.EggLocation + 3000); set { } } + public override ushort EggLocation { get => (ushort)(IsEgg ? Gift.EggLocation + 3000 : 0); set { } } public bool IsCompatible(PIDType val, PKM pk) => Gift.IsCompatible(val, pk); public PIDType GetSuggestedCorrelation() => Gift.GetSuggestedCorrelation(); @@ -130,7 +130,7 @@ public override PK4 ConvertToPKM(ITrainerInfo tr, EncounterCriteria criteria) return Gift.ConvertToPKM(tr, criteria); } - public bool CanBeReceivedByVersion(int pkmVersion) => (byte)Version == pkmVersion; + public bool CanBeReceivedByVersion(GameVersion version) => Version == version; public override bool IsMatchExact(PKM pk, EvoCriteria evo) { @@ -139,28 +139,28 @@ public override bool IsMatchExact(PKM pk, EvoCriteria evo) { if (wc.TID16 != pk.TID16) return false; if (wc.SID16 != pk.SID16) return false; - if (wc.OT_Name != pk.OT_Name) return false; - if (wc.OT_Gender != pk.OT_Gender) return false; + if (wc.OriginalTrainerName != pk.OriginalTrainerName) return false; + if (wc.OriginalTrainerGender != pk.OriginalTrainerGender) return false; if (wc.Language != 0 && wc.Language != pk.Language) return false; if (pk.Format != 4) // transferred { // met location: deferred to general transfer check - if (wc.CurrentLevel > pk.Met_Level) return false; + if (wc.CurrentLevel > pk.MetLevel) return false; if (!IsMatchEggLocation(pk)) return false; } else { - if (wc.Egg_Location + 3000 != pk.Met_Location) return false; - if (wc.CurrentLevel != pk.Met_Level) return false; + if (wc.EggLocation + 3000 != pk.MetLocation) return false; + if (wc.CurrentLevel != pk.MetLevel) return false; } } else // Egg { - if (wc.Egg_Location + 3000 != pk.Egg_Location && pk.Egg_Location != Locations.LinkTrade4) // traded + if (wc.EggLocation + 3000 != pk.EggLocation && pk.EggLocation != Locations.LinkTrade4) // traded return false; - if (wc.CurrentLevel != pk.Met_Level) + if (wc.CurrentLevel != pk.MetLevel) return false; if (pk is { IsEgg: true, IsNative: false }) return false; @@ -170,7 +170,7 @@ public override bool IsMatchExact(PKM pk, EvoCriteria evo) return false; if (wc.Ball != pk.Ball) return false; - if (wc.OT_Gender < 3 && wc.OT_Gender != pk.OT_Gender) return false; + if (wc.OriginalTrainerGender < 3 && wc.OriginalTrainerGender != pk.OriginalTrainerGender) return false; // Milotic is the only gift to come with Contest stats. if (wc.Species == (int)Core.Species.Milotic && pk is IContestStatsReadOnly s && s.IsContestBelow(wc)) diff --git a/PKHeX.Core/MysteryGifts/PGF.cs b/PKHeX.Core/MysteryGifts/PGF.cs index 798aa946f..6f7ee8b56 100644 --- a/PKHeX.Core/MysteryGifts/PGF.cs +++ b/PKHeX.Core/MysteryGifts/PGF.cs @@ -13,14 +13,15 @@ public sealed class PGF(byte[] Data) : DataMysteryGift(Data), IRibbonSetEvent3, public const int Size = 0xCC; public const int SizeFull = 0x2D0; - public override int Generation => 5; + public override byte Generation => 5; public override EntityContext Context => EntityContext.Gen5; + public override GameVersion Version => OriginGame == 0 ? GameVersion.Gen5 : (GameVersion)OriginGame; public override bool FatefulEncounter => true; public override uint ID32 { get => ReadUInt32LittleEndian(Data.AsSpan(0x00)); set => WriteUInt32LittleEndian(Data.AsSpan(0x00), value); } public override ushort TID16 { get => ReadUInt16LittleEndian(Data.AsSpan(0x00)); set => WriteUInt16LittleEndian(Data.AsSpan(0x00), value); } public override ushort SID16 { get => ReadUInt16LittleEndian(Data.AsSpan(0x02)); set => WriteUInt16LittleEndian(Data.AsSpan(0x02), value); } - public int OriginGame { get => Data[0x04]; set => Data[0x04] = (byte)value; } + public byte OriginGame { get => Data[0x04]; set => Data[0x04] = value; } // Unused 0x05 0x06, 0x07 public uint PID { get => ReadUInt32LittleEndian(Data.AsSpan(0x08)); set => WriteUInt32LittleEndian(Data.AsSpan(0x08), value); } @@ -43,7 +44,7 @@ public sealed class PGF(byte[] Data) : DataMysteryGift(Data), IRibbonSetEvent3, public bool RibbonChampionWorld { get => (RIB1 & (1 << 6)) == 1 << 6; set => RIB1 = (byte)((RIB1 & ~(1 << 6)) | (value ? 1 << 6 : 0)); } public bool RIB1_7 { get => (RIB1 & (1 << 7)) == 1 << 7; set => RIB1 = (byte)((RIB1 & ~(1 << 7)) | (value ? 1 << 7 : 0)); } - public override int Ball { get => Data[0x0E]; set => Data[0x0E] = (byte)value; } + public override byte Ball { get => Data[0x0E]; set => Data[0x0E] = value; } public override int HeldItem { get => ReadUInt16LittleEndian(Data.AsSpan(0x10)); set => WriteUInt16LittleEndian(Data.AsSpan(0x10), (ushort)value); } public ushort Move1 { get => ReadUInt16LittleEndian(Data.AsSpan(0x12)); set => WriteUInt16LittleEndian(Data.AsSpan(0x12), value); } public ushort Move2 { get => ReadUInt16LittleEndian(Data.AsSpan(0x14)); set => WriteUInt16LittleEndian(Data.AsSpan(0x14), value); } @@ -59,19 +60,19 @@ public string Nickname set => StringConverter5.SetString(Data.AsSpan(0x1E, 11 * 2), value, 11, StringConverterOption.ClearFF); } - public int Nature { get => (sbyte)Data[0x34]; set => Data[0x34] = (byte)value; } - public override int Gender { get => Data[0x35]; set => Data[0x35] = (byte)value; } + public Nature Nature { get => (Nature)Data[0x34]; set => Data[0x34] = (byte)value; } + public override byte Gender { get => Data[0x35]; set => Data[0x35] = value; } public override int AbilityType { get => Data[0x36]; set => Data[0x36] = (byte)value; } public int PIDType { get => Data[0x37]; set => Data[0x37] = (byte)value; } - public override int EggLocation { get => ReadUInt16LittleEndian(Data.AsSpan(0x38)); set => WriteUInt16LittleEndian(Data.AsSpan(0x38), (ushort)value); } - public ushort MetLocation { get => ReadUInt16LittleEndian(Data.AsSpan(0x3A)); set => WriteUInt16LittleEndian(Data.AsSpan(0x3A), value); } - public int MetLevel { get => Data[0x3C]; set => Data[0x3C] = (byte)value; } - public byte CNT_Cool { get => Data[0x3D]; set => Data[0x3D] = value; } - public byte CNT_Beauty { get => Data[0x3E]; set => Data[0x3E] = value; } - public byte CNT_Cute { get => Data[0x3F]; set => Data[0x3F] = value; } - public byte CNT_Smart { get => Data[0x40]; set => Data[0x40] = value; } - public byte CNT_Tough { get => Data[0x41]; set => Data[0x41] = value; } - public byte CNT_Sheen { get => Data[0x42]; set => Data[0x42] = value; } + public override ushort EggLocation { get => ReadUInt16LittleEndian(Data.AsSpan(0x38)); set => WriteUInt16LittleEndian(Data.AsSpan(0x38), value); } + public override ushort Location { get => ReadUInt16LittleEndian(Data.AsSpan(0x3A)); set => WriteUInt16LittleEndian(Data.AsSpan(0x3A), value); } + public byte MetLevel { get => Data[0x3C]; set => Data[0x3C] = value; } + public byte ContestCool { get => Data[0x3D]; set => Data[0x3D] = value; } + public byte ContestBeauty { get => Data[0x3E]; set => Data[0x3E] = value; } + public byte ContestCute { get => Data[0x3F]; set => Data[0x3F] = value; } + public byte ContestSmart { get => Data[0x40]; set => Data[0x40] = value; } + public byte ContestTough { get => Data[0x41]; set => Data[0x41] = value; } + public byte ContestSheen { get => Data[0x42]; set => Data[0x42] = value; } public int IV_HP { get => Data[0x43]; set => Data[0x43] = (byte)value; } public int IV_ATK { get => Data[0x44]; set => Data[0x44] = (byte)value; } public int IV_DEF { get => Data[0x45]; set => Data[0x45] = (byte)value; } @@ -79,13 +80,13 @@ public string Nickname public int IV_SPA { get => Data[0x47]; set => Data[0x47] = (byte)value; } public int IV_SPD { get => Data[0x48]; set => Data[0x48] = (byte)value; } // Unused 0x49 - public override string OT_Name + public override string OriginalTrainerName { get => StringConverter5.GetString(Data.AsSpan(0x4A, 8 * 2)); set => StringConverter5.SetString(Data.AsSpan(0x4A, 8 * 2), value, 8, StringConverterOption.ClearFF); } - public int OTGender { get => Data[0x5A]; set => Data[0x5A] = (byte)value; } + public byte OTGender { get => Data[0x5A]; set => Data[0x5A] = value; } public override byte Level { get => Data[0x5B]; set => Data[0x5C] = value; } public override bool IsEgg { get => Data[0x5C] == 1; set => Data[0x5C] = value ? (byte)1 : (byte)0; } // Unused 0x5D 0x5E 0x5F @@ -147,7 +148,7 @@ public override int CardID public bool MultiObtain { get => Data[0xB4] == 1; set => Data[0xB4] = value ? (byte)1 : (byte)0; } // Meta Accessible Properties - public override int[] IVs + public int[] IVs { get => [IV_HP, IV_ATK, IV_DEF, IV_SPE, IV_SPA, IV_SPD]; set @@ -173,7 +174,6 @@ public override void GetIVs(Span value) public bool IsNicknamed => Nickname.Length > 0; public override bool IsShiny => PIDType == 2; - public override int Location { get => MetLocation; set => MetLocation = (ushort)value; } public override Moveset Moves => new(Move1, Move2, Move3, Move4); public override bool IsEntity { get => CardType == 1; set { if (value) CardType = 1; } } public override bool IsItem { get => CardType == 2; set { if (value) CardType = 2; } } @@ -194,14 +194,14 @@ public override PK5 ConvertToPKM(ITrainerInfo tr, EncounterCriteria criteria) Year = (byte)dt.Year; } - int currentLevel = Level > 0 ? Level : 1 + rnd.Next(100); + byte currentLevel = Level > 0 ? Level : (byte)(1 + rnd.Next(100)); var pi = PersonalTable.B2W2.GetFormEntry(Species, Form); PK5 pk = new() { Species = Species, HeldItem = HeldItem, - Met_Level = currentLevel, - Nature = Nature != -1 ? Nature : rnd.Next(25), + MetLevel = currentLevel, + Nature = (sbyte)Nature != -1 ? Nature : (Nature)rnd.Next(25), Form = Form, Version = GetVersion(tr, rnd), Language = Language == 0 ? tr.Language : Language, @@ -210,15 +210,15 @@ public override PK5 ConvertToPKM(ITrainerInfo tr, EncounterCriteria criteria) Move2 = Move2, Move3 = Move3, Move4 = Move4, - Met_Location = MetLocation, + MetLocation = Location, MetDate = Date, - Egg_Location = EggLocation, - CNT_Cool = CNT_Cool, - CNT_Beauty = CNT_Beauty, - CNT_Cute = CNT_Cute, - CNT_Smart = CNT_Smart, - CNT_Tough = CNT_Tough, - CNT_Sheen = CNT_Sheen, + EggLocation = EggLocation, + ContestCool = ContestCool, + ContestBeauty = ContestBeauty, + ContestCute = ContestCute, + ContestSmart = ContestSmart, + ContestTough = ContestTough, + ContestSheen = ContestSheen, EXP = Experience.GetEXP(currentLevel, pi.EXPGrowth), @@ -246,7 +246,7 @@ public override PK5 ConvertToPKM(ITrainerInfo tr, EncounterCriteria criteria) if (Move1 == 0) // No moves defined { Span moves = stackalloc ushort[4]; - var source = GameData.GetLearnSource((GameVersion)pk.Version); + var source = GameData.GetLearnSource(pk.Version); source.SetEncounterMoves(Species, Form, Level, moves); pk.SetMoves(moves); } @@ -259,15 +259,15 @@ public override PK5 ConvertToPKM(ITrainerInfo tr, EncounterCriteria criteria) { pk.TID16 = tr.TID16; pk.SID16 = tr.SID16; - pk.OT_Name = tr.OT; - pk.OT_Gender = tr.Gender; + pk.OriginalTrainerName = tr.OT; + pk.OriginalTrainerGender = tr.Gender; } else // Hardcoded { pk.TID16 = TID16; pk.SID16 = SID16; - pk.OT_Name = OT_Name; - pk.OT_Gender = (OTGender == 3 ? tr.Gender : OTGender) & 1; // some events have variable gender based on receiving SaveFile + pk.OriginalTrainerName = OriginalTrainerName; + pk.OriginalTrainerGender = (byte)((OTGender == 3 ? tr.Gender : OTGender) & 1); // some events have variable gender based on receiving SaveFile } pk.IsNicknamed = IsNicknamed; @@ -284,21 +284,21 @@ public override PK5 ConvertToPKM(ITrainerInfo tr, EncounterCriteria criteria) return pk; } - private int GetVersion(ITrainerInfo tr, Random rnd) + private GameVersion GetVersion(ITrainerInfo tr, Random rnd) { if (OriginGame != 0) - return OriginGame; + return (GameVersion)OriginGame; if (tr.Generation <= 5) - return tr.Game; + return tr.Version; // Gen6+, give random Gen5 game var bias = rnd.Next(4); for (int i = 0; i < 4; i++) { - var ver = (int)GameVersion.W + ((bias + i) % 4); - if (CanBeReceivedByVersion(ver)) - return ver; + var version = GameVersion.W + (byte)((bias + i) % 4); + if (CanBeReceivedByVersion(version)) + return version; } - return (int)GameVersion.W; // should never hit this for any distributed card + return GameVersion.W; // should never hit this for any distributed card } private void SetEggMetDetails(PK5 pk) @@ -312,8 +312,8 @@ private void SetEggMetDetails(PK5 pk) private void SetPINGA(PK5 pk, EncounterCriteria criteria) { var pi = PersonalTable.B2W2.GetFormEntry(Species, Form); - pk.Nature = (int)criteria.GetNature((Nature)Nature); - pk.Gender = pi.Genderless ? 2 : Gender != 2 ? Gender : criteria.GetGender(pi); + pk.Nature = criteria.GetNature(Nature); + pk.Gender = pi.Genderless ? (byte)2 : Gender != 2 ? Gender : criteria.GetGender(pi); var av = GetAbilityIndex(criteria); SetPID(pk, av); pk.RefreshAbility(av); @@ -390,22 +390,22 @@ public override bool IsMatchExact(PKM pk, EvoCriteria evo) { if (SID16 != pk.SID16) return false; if (TID16 != pk.TID16) return false; - if (OT_Name != pk.OT_Name) return false; - if (OTGender < 3 && OTGender != pk.OT_Gender) return false; + if (OriginalTrainerName != pk.OriginalTrainerName) return false; + if (OTGender < 3 && OTGender != pk.OriginalTrainerGender) return false; if (PID != 0 && pk.PID != PID) return false; if (PIDType == 0 && pk.IsShiny) return false; if (PIDType == 2 && !pk.IsShiny) return false; - if (OriginGame != 0 && OriginGame != pk.Version) return false; + if (OriginGame != 0 && (GameVersion)OriginGame != pk.Version) return false; if (Language != 0 && Language != pk.Language) return false; if (!IsMatchEggLocation(pk)) return false; - if (MetLocation != pk.Met_Location) return false; + if (Location != pk.MetLocation) return false; } else { - if (EggLocation != pk.Egg_Location) // traded + if (EggLocation != pk.EggLocation) // traded { - if (pk.Egg_Location != Locations.LinkTrade5) + if (pk.EggLocation != Locations.LinkTrade5) return false; } else if (PIDType == 0 && pk.IsShiny) @@ -420,9 +420,9 @@ public override bool IsMatchExact(PKM pk, EvoCriteria evo) if (Form != evo.Form && !FormInfo.IsFormChangeable(Species, Form, pk.Form, Context, pk.Context)) return false; - if (Level != pk.Met_Level) return false; + if (Level != pk.MetLevel) return false; if (Ball != pk.Ball) return false; - if (Nature != -1 && pk.Nature != Nature) + if ((sbyte)Nature != -1 && pk.Nature != Nature) return false; if (Gender != 2 && Gender != pk.Gender) return false; @@ -435,5 +435,5 @@ public override bool IsMatchExact(PKM pk, EvoCriteria evo) protected override bool IsMatchDeferred(PKM pk) => false; protected override bool IsMatchPartial(PKM pk) => !CanBeReceivedByVersion(pk.Version); - public bool CanBeReceivedByVersion(int game) => OriginGame == 0 || OriginGame == game; + public bool CanBeReceivedByVersion(GameVersion game) => OriginGame == 0 || (GameVersion)OriginGame == game; } diff --git a/PKHeX.Core/MysteryGifts/PGT.cs b/PKHeX.Core/MysteryGifts/PGT.cs index e4f720869..150111073 100644 --- a/PKHeX.Core/MysteryGifts/PGT.cs +++ b/PKHeX.Core/MysteryGifts/PGT.cs @@ -11,20 +11,20 @@ public sealed class PGT(byte[] Data) : DataMysteryGift(Data), IRibbonSetEvent3, public PGT() : this(new byte[Size]) { } public const int Size = 0x104; // 260 - public override int Generation => 4; + public override byte Generation => 4; public override EntityContext Context => EntityContext.Gen4; public override bool FatefulEncounter => IsManaphyEgg || PK.FatefulEncounter; - public override GameVersion Version { get => IsManaphyEgg ? GameVersion.Gen4 : (GameVersion)PK.Version; set => PK.Version = (int)value; } + public override GameVersion Version => IsManaphyEgg ? GameVersion.Gen4 : PK.Version; public override byte Level { - get => IsManaphyEgg ? (byte)1 : IsEntity ? (byte)PK.Met_Level : (byte)0; - set { if (IsEntity) PK.Met_Level = value; } + get => IsManaphyEgg ? (byte)1 : IsEntity ? PK.MetLevel : (byte)0; + set { if (IsEntity) PK.MetLevel = value; } } - public override int Ball + public override byte Ball { - get => IsManaphyEgg ? 4 : IsEntity ? PK.Ball : 0; + get => IsManaphyEgg ? (byte)4 : IsEntity ? PK.Ball : (byte)0; set { if (IsEntity) PK.Ball = value; } } @@ -115,14 +115,14 @@ private void EncryptPK() public override Moveset Moves { get => new(PK.Move1, PK.Move2, PK.Move3, PK.Move4); set => PK.SetMoves(value); } public override int HeldItem { get => PK.HeldItem; set => PK.HeldItem = value; } public override bool IsShiny => PK.IsShiny; - public override int Gender { get => PK.Gender; set => PK.Gender = value; } + public override byte Gender { get => PK.Gender; set => PK.Gender = value; } public override byte Form { get => PK.Form; set => PK.Form = value; } public override uint ID32 { get => PK.ID32; set => PK.ID32= value; } public override ushort TID16 { get => PK.TID16; set => PK.TID16 = value; } public override ushort SID16 { get => PK.SID16; set => PK.SID16 = value; } - public override string OT_Name { get => PK.OT_Name; set => PK.OT_Name = value; } - public override int Location { get => PK.Met_Location; set => PK.Met_Location = value; } - public override int EggLocation { get => PK.Egg_Location; set => PK.Egg_Location = value; } + public override string OriginalTrainerName { get => PK.OriginalTrainerName; set => PK.OriginalTrainerName = value; } + public override ushort Location { get => PK.MetLocation; set => PK.MetLocation = value; } + public override ushort EggLocation { get => PK.EggLocation; set => PK.EggLocation = value; } public override bool HasFixedIVs => (PK.IV32 & 0x3FFF_FFFFu) != 0; public override void GetIVs(Span value) { @@ -139,10 +139,10 @@ public override PK4 ConvertToPKM(ITrainerInfo tr, EncounterCriteria criteria) PK4 pk4 = new((byte[])PK.Data.Clone()) { Sanity = 0 }; if (!IsHatched && Detail == 0) { - pk4.OT_Name = tr.OT; + pk4.OriginalTrainerName = tr.OT; pk4.TID16 = tr.TID16; pk4.SID16 = tr.SID16; - pk4.OT_Gender = tr.Gender; + pk4.OriginalTrainerGender = tr.Gender; pk4.Language = tr.Language; } @@ -163,14 +163,14 @@ private void SetMetData(PK4 pk4, ITrainerInfo trainer) { if (!EggEncounter) { - pk4.Met_Location = pk4.Egg_Location + 3000; - pk4.Egg_Location = 0; + pk4.MetLocation = (ushort)(pk4.EggLocation + 3000); + pk4.EggLocation = 0; pk4.MetDate = EncounterDate.GetDateNDS(); pk4.IsEgg = false; } else { - pk4.Egg_Location += 3000; + pk4.EggLocation += 3000; if (trainer.Generation == 4) SetUnhatchedEggDetails(pk4); else @@ -190,12 +190,12 @@ private static void SetDefaultManaphyEggDetails(PK4 pk4, ITrainerInfo trainer) pk4.Ability = (int)Core.Ability.Hydration; pk4.FatefulEncounter = true; pk4.Ball = (int)Core.Ball.Poke; - pk4.Version = GameVersion.Gen4.Contains(trainer.Game) ? trainer.Game : (int)GameVersion.D; + pk4.Version = GameVersion.Gen4.Contains(trainer.Version) ? trainer.Version : GameVersion.D; var lang = trainer.Language < (int)LanguageID.Korean ? trainer.Language : (int)LanguageID.English; pk4.Language = lang; - pk4.Egg_Location = 1; // Ranger (will be +3000 later) + pk4.EggLocation = 1; // Ranger (will be +3000 later) pk4.Nickname = SpeciesName.GetSpeciesNameGeneration((int)Core.Species.Manaphy, lang, 4); - pk4.Met_Location = pk4.Version is (int)GameVersion.HG or (int)GameVersion.SS ? Locations.HatchLocationHGSS : Locations.HatchLocationDPPt; + pk4.MetLocation = pk4.Version is GameVersion.HG or GameVersion.SS ? Locations.HatchLocationHGSS : Locations.HatchLocationDPPt; pk4.MetDate = EncounterDate.GetDateNDS(); } @@ -226,7 +226,7 @@ private uint SetPID(PK4 pk4, EncounterCriteria criteria) // The games don't decide the Nature/Gender up-front, but we can try to honor requests. // Pre-determine the result values, and generate something. - var n = (int)criteria.GetNature(); + var n = criteria.GetNature(); // Gender is already pre-determined in the template. while (true) { @@ -272,13 +272,13 @@ public static bool IsRangerManaphy(PKM pk) if (pk.Language >= (int)LanguageID.Korean) // never korean return false; - var egg = pk.Egg_Location; + var egg = pk.EggLocation; if (!pk.IsEgg) // Link Trade Egg or Ranger return egg is Locations.LinkTrade4 or Locations.Ranger4; if (egg != Locations.Ranger4) return false; - var met = pk.Met_Location; + var met = pk.MetLocation; return met is Locations.LinkTrade4 or 0; } diff --git a/PKHeX.Core/MysteryGifts/PL6.cs b/PKHeX.Core/MysteryGifts/PL6.cs index 8ed7aa12d..dd4f2b585 100644 --- a/PKHeX.Core/MysteryGifts/PL6.cs +++ b/PKHeX.Core/MysteryGifts/PL6.cs @@ -31,10 +31,12 @@ public byte Flags public bool Enabled { get => (Flags & 0x80) != 0; set => Flags = value ? (byte)(1 << 7) : (byte)0; } + private Span Source => Data.AsSpan(0x01, 110); + /// /// Name of data source /// - public string Origin { get => StringConverter6.GetString(Data.AsSpan(0x01, 110)); set => StringConverter6.SetString(Data.AsSpan(0x01, 110), value, 54, StringConverterOption.ClearZero); } + public string Origin { get => StringConverter6.GetString(Source); set => StringConverter6.SetString(Source, value, 54, StringConverterOption.ClearZero); } // Pokemon transfer flags? public uint Flags_1 { get => ReadUInt32LittleEndian(Data.AsSpan(0x099)); set => WriteUInt32LittleEndian(Data.AsSpan(0x099), value); } @@ -78,7 +80,7 @@ public byte Flags /// This template object is only present in Generation 6 save files. /// public sealed class PL6_PKM(byte[] Data) : IRibbonSetEvent3, IRibbonSetEvent4, IEncounterInfo, IMoveset, IRelearn, - IContestStats, IMemoryOT, ITrainerID32 + IContestStats, IMemoryOT, ITrainerID32, ILocation { internal const int Size = 0xA0; @@ -91,9 +93,9 @@ public sealed class PL6_PKM(byte[] Data) : IRibbonSetEvent3, IRibbonSetEvent4, I public uint ID32 { get => ReadUInt32LittleEndian(Data.AsSpan(0x00)); set => WriteUInt32LittleEndian(Data.AsSpan(0x00), value); } public ushort TID16 { get => ReadUInt16LittleEndian(Data.AsSpan(0x00)); set => WriteUInt16LittleEndian(Data.AsSpan(0x00), value); } public ushort SID16 { get => ReadUInt16LittleEndian(Data.AsSpan(0x02)); set => WriteUInt16LittleEndian(Data.AsSpan(0x02), value); } - public int OriginGame { get => Data[0x04]; set => Data[0x04] = (byte)value; } + public byte OriginGame { get => Data[0x04]; set => Data[0x04] = value; } public uint EncryptionConstant { get => ReadUInt32LittleEndian(Data.AsSpan(0x08)); set => WriteUInt32LittleEndian(Data.AsSpan(0x08), value); } - public int Ball { get => Data[0xE]; set => Data[0xE] = (byte)value; } + public byte Ball { get => Data[0xE]; set => Data[0xE] = value; } public int HeldItem { get => ReadUInt16LittleEndian(Data.AsSpan(0x10)); set => WriteUInt16LittleEndian(Data.AsSpan(0x10), (ushort)value); } public ushort Move1 { get => ReadUInt16LittleEndian(Data.AsSpan(0x12)); set => WriteUInt16LittleEndian(Data.AsSpan(0x12), value); } public ushort Move2 { get => ReadUInt16LittleEndian(Data.AsSpan(0x14)); set => WriteUInt16LittleEndian(Data.AsSpan(0x14), value); } @@ -109,20 +111,20 @@ public string Nickname set => StringConverter6.SetString(Data.AsSpan(0x1E, 0x1A), value, 12, StringConverterOption.ClearZero); } - public int Nature { get => Data[0x38]; set => Data[0x38] = (byte)value; } - public int Gender { get => Data[0x39]; set => Data[0x39] = (byte)value; } + public Nature Nature { get => (Nature)Data[0x38]; set => Data[0x38] = (byte)value; } + public byte Gender { get => Data[0x39]; set => Data[0x39] = value; } public int AbilityType { get => Data[0x3A]; set => Data[0x3A] = (byte)value; } public int PIDType { get => Data[0x3B]; set => Data[0x3B] = (byte)value; } - public int EggLocation { get => ReadUInt16LittleEndian(Data.AsSpan(0x3C)); set => WriteUInt16LittleEndian(Data.AsSpan(0x3C), (ushort)value); } - public int MetLocation { get => ReadUInt16LittleEndian(Data.AsSpan(0x3E)); set => WriteUInt16LittleEndian(Data.AsSpan(0x3E), (ushort)value); } + public ushort EggLocation { get => ReadUInt16LittleEndian(Data.AsSpan(0x3C)); set => WriteUInt16LittleEndian(Data.AsSpan(0x3C), value); } + public ushort Location { get => ReadUInt16LittleEndian(Data.AsSpan(0x3E)); set => WriteUInt16LittleEndian(Data.AsSpan(0x3E), value); } public byte MetLevel { get => Data[0x40]; set => Data[0x40] = value; } - public byte CNT_Cool { get => Data[0x41]; set => Data[0x41] = value; } - public byte CNT_Beauty { get => Data[0x42]; set => Data[0x42] = value; } - public byte CNT_Cute { get => Data[0x43]; set => Data[0x43] = value; } - public byte CNT_Smart { get => Data[0x44]; set => Data[0x44] = value; } - public byte CNT_Tough { get => Data[0x45]; set => Data[0x45] = value; } - public byte CNT_Sheen { get => Data[0x46]; set => Data[0x46] = value; } + public byte ContestCool { get => Data[0x41]; set => Data[0x41] = value; } + public byte ContestBeauty { get => Data[0x42]; set => Data[0x42] = value; } + public byte ContestCute { get => Data[0x43]; set => Data[0x43] = value; } + public byte ContestSmart { get => Data[0x44]; set => Data[0x44] = value; } + public byte ContestTough { get => Data[0x45]; set => Data[0x45] = value; } + public byte ContestSheen { get => Data[0x46]; set => Data[0x46] = value; } public int IV_HP { get => Data[0x47]; set => Data[0x47] = (byte)value; } public int IV_ATK { get => Data[0x48]; set => Data[0x48] = (byte)value; } @@ -131,7 +133,7 @@ public string Nickname public int IV_SPA { get => Data[0x4B]; set => Data[0x4B] = (byte)value; } public int IV_SPD { get => Data[0x4C]; set => Data[0x4C] = (byte)value; } - public int OTGender { get => Data[0x4D]; set => Data[0x4D] = (byte)value; } + public byte OTGender { get => Data[0x4D]; set => Data[0x4D] = value; } public string OT { @@ -146,10 +148,10 @@ public string OT public ushort RelearnMove2 { get => ReadUInt16LittleEndian(Data.AsSpan(0x72)); set => WriteUInt16LittleEndian(Data.AsSpan(0x72), value); } public ushort RelearnMove3 { get => ReadUInt16LittleEndian(Data.AsSpan(0x74)); set => WriteUInt16LittleEndian(Data.AsSpan(0x74), value); } public ushort RelearnMove4 { get => ReadUInt16LittleEndian(Data.AsSpan(0x76)); set => WriteUInt16LittleEndian(Data.AsSpan(0x76), value); } - public byte OT_Intensity { get => Data[0x78]; set => Data[0x78] = value; } - public byte OT_Memory { get => Data[0x79]; set => Data[0x79] = value; } - public ushort OT_TextVar { get => ReadUInt16LittleEndian(Data.AsSpan(0x7A)); set => WriteUInt16LittleEndian(Data.AsSpan(0x7A), value); } - public byte OT_Feeling { get => Data[0x7C]; set => Data[0x7C] = value; } + public byte OriginalTrainerMemoryIntensity { get => Data[0x78]; set => Data[0x78] = value; } + public byte OriginalTrainerMemory { get => Data[0x79]; set => Data[0x79] = value; } + public ushort OriginalTrainerMemoryVariable { get => ReadUInt16LittleEndian(Data.AsSpan(0x7A)); set => WriteUInt16LittleEndian(Data.AsSpan(0x7A), value); } + public byte OriginalTrainerMemoryFeeling { get => Data[0x7C]; set => Data[0x7C] = value; } private byte RIB0 { get => Data[0x0C]; set => Data[0x0C] = value; } private byte RIB1 { get => Data[0x0D]; set => Data[0x0D] = value; } @@ -198,7 +200,7 @@ public Moveset Relearn } } - public int Generation => 6; + public byte Generation => 6; public bool IsShiny => false; public bool EggEncounter => false; public GameVersion Version => GameVersion.Gen6; diff --git a/PKHeX.Core/MysteryGifts/WA8.cs b/PKHeX.Core/MysteryGifts/WA8.cs index cbbeca578..f79b50a28 100644 --- a/PKHeX.Core/MysteryGifts/WA8.cs +++ b/PKHeX.Core/MysteryGifts/WA8.cs @@ -8,7 +8,7 @@ namespace PKHeX.Core; /// Generation 8 Mystery Gift Template File, same as with fields at the end. /// public sealed class WA8(byte[] Data) : DataMysteryGift(Data), ILangNick, INature, IGigantamax, IDynamaxLevel, - IRibbonIndex, IMemoryOT, IEncounterServerDate, + IRibbonIndex, IMemoryOT, IRelearn, IEncounterServerDate, ILangNicknamedTemplate, IGanbaru, IAlpha, IRibbonSetEvent3, IRibbonSetEvent4, IRibbonSetCommon3, IRibbonSetCommon4, IRibbonSetCommon6, IRibbonSetCommon7, IRibbonSetCommon8, IRibbonSetMark8 @@ -17,7 +17,7 @@ public sealed class WA8(byte[] Data) : DataMysteryGift(Data), ILangNick, INature public const int Size = 0x2C8; - public override int Generation => 8; + public override byte Generation => 8; public override EntityContext Context => EntityContext.Gen8a; public override bool FatefulEncounter => true; @@ -29,7 +29,8 @@ public enum GiftType : byte Clothing = 3, } - public bool CanBeReceivedByVersion(int v, PKM pk) => v is (int) GameVersion.PLA || (pk is PK8 && v is (int)GameVersion.SW); + public bool CanBeReceivedByVersion(GameVersion version, PKM pk) => version is GameVersion.PLA + || (pk is PK8 && version is GameVersion.SW); public bool IsDateRestricted => true; public bool IsEquivalentFixedECPID => EncryptionConstant != 0 && PIDType == ShinyType8.FixedValue && PID == EncryptionConstant; @@ -144,13 +145,13 @@ public uint PID } // Nicknames, OT Names 0x30 - 0x228 - public override int EggLocation { get => ReadUInt16LittleEndian(Data.AsSpan(0x220)); set => WriteUInt16LittleEndian(Data.AsSpan(0x220), (ushort)value); } - public int MetLocation { get => ReadUInt16LittleEndian(Data.AsSpan(0x222)); set => WriteUInt16LittleEndian(Data.AsSpan(0x222), (ushort)value); } + public override ushort EggLocation { get => ReadUInt16LittleEndian(Data.AsSpan(0x220)); set => WriteUInt16LittleEndian(Data.AsSpan(0x220), value); } + public override ushort Location { get => ReadUInt16LittleEndian(Data.AsSpan(0x222)); set => WriteUInt16LittleEndian(Data.AsSpan(0x222), value); } - public override int Ball + public override byte Ball { - get => ReadUInt16LittleEndian(Data.AsSpan(0x224)); - set => WriteUInt16LittleEndian(Data.AsSpan(0x224), (ushort)value); + get => (byte)ReadUInt16LittleEndian(Data.AsSpan(0x224)); + set => WriteUInt16LittleEndian(Data.AsSpan(0x224), value); } public override int HeldItem @@ -170,10 +171,10 @@ public override int HeldItem public override ushort Species { get => ReadUInt16LittleEndian(Data.AsSpan(0x238)); set => WriteUInt16LittleEndian(Data.AsSpan(0x238), value); } public override byte Form { get => Data[0x23A]; set => Data[0x23A] = value; } - public override int Gender { get => Data[0x23B]; set => Data[0x23B] = (byte)value; } + public override byte Gender { get => Data[0x23B]; set => Data[0x23B] = value; } public override byte Level { get => Data[0x23C]; set => Data[0x23C] = value; } public override bool IsEgg { get => Data[0x23D] == 1; set => Data[0x23D] = value ? (byte)1 : (byte)0; } - public int Nature { get => (sbyte)Data[0x23E]; set => Data[0x23E] = (byte)value; } + public Nature Nature { get => (Nature)Data[0x23E]; set => Data[0x23E] = (byte)value; } public override int AbilityType { get => Data[0x23F]; set => Data[0x23F] = (byte)value; } private byte PIDTypeValue => Data[0x240]; @@ -188,7 +189,7 @@ public override int HeldItem _ => throw new ArgumentOutOfRangeException(nameof(PIDType)), }; - public int MetLevel { get => Data[0x241]; set => Data[0x241] = (byte)value; } + public byte MetLevel { get => Data[0x241]; set => Data[0x241] = value; } public byte DynamaxLevel { get => Data[0x242]; set => Data[0x242] = value; } public bool CanGigantamax { get => Data[0x243] != 0; set => Data[0x243] = value ? (byte)1 : (byte)0; } @@ -233,7 +234,7 @@ public void SetRibbonAtIndex(int byteIndex, byte ribbonIndex) public int IV_SPA { get => Data[0x268]; set => Data[0x268] = (byte)value; } public int IV_SPD { get => Data[0x269]; set => Data[0x269] = (byte)value; } - public int OTGender { get => Data[0x26A]; set => Data[0x26A] = (byte)value; } + public byte OTGender { get => Data[0x26A]; set => Data[0x26A] = value; } public int EV_HP { get => Data[0x26B]; set => Data[0x26B] = (byte)value; } public int EV_ATK { get => Data[0x26C]; set => Data[0x26C] = (byte)value; } @@ -242,10 +243,10 @@ public void SetRibbonAtIndex(int byteIndex, byte ribbonIndex) public int EV_SPA { get => Data[0x26F]; set => Data[0x26F] = (byte)value; } public int EV_SPD { get => Data[0x270]; set => Data[0x270] = (byte)value; } - public byte OT_Intensity { get => Data[0x271]; set => Data[0x271] = value; } - public byte OT_Memory { get => Data[0x272]; set => Data[0x272] = value; } - public byte OT_Feeling { get => Data[0x273]; set => Data[0x273] = value; } - public ushort OT_TextVar { get => ReadUInt16LittleEndian(Data.AsSpan(0x274)); set => WriteUInt16LittleEndian(Data.AsSpan(0x274), value); } + public byte OriginalTrainerMemoryIntensity { get => Data[0x271]; set => Data[0x271] = value; } + public byte OriginalTrainerMemory { get => Data[0x272]; set => Data[0x272] = value; } + public byte OriginalTrainerMemoryFeeling { get => Data[0x273]; set => Data[0x273] = value; } + public ushort OriginalTrainerMemoryVariable { get => ReadUInt16LittleEndian(Data.AsSpan(0x274)); set => WriteUInt16LittleEndian(Data.AsSpan(0x274), value); } // Only derivations to WC8 public byte GV_HP { get => Data[0x276]; set => Data[0x276] = value; } @@ -256,7 +257,7 @@ public void SetRibbonAtIndex(int byteIndex, byte ribbonIndex) public byte GV_SPD { get => Data[0x27B]; set => Data[0x27B] = value; } // Meta Accessible Properties - public override int[] IVs + public int[] IVs { get => [IV_HP, IV_ATK, IV_DEF, IV_SPE, IV_SPA, IV_SPD]; set @@ -337,8 +338,6 @@ private static int GetLanguageIndex(int language) return lang < LanguageID.UNUSED_6 ? language - 1 : language - 2; } - public override int Location { get => MetLocation; set => MetLocation = (ushort)value; } - public override Moveset Moves { get => new(Move1, Move2, Move3, Move4); @@ -351,7 +350,7 @@ public override Moveset Moves } } - public override Moveset Relearn + public Moveset Relearn { get => new(RelearnMove1, RelearnMove2, RelearnMove3, RelearnMove4); set @@ -363,7 +362,7 @@ public override Moveset Relearn } } - public override string OT_Name + public override string OriginalTrainerName { get => GetOT(Language); set @@ -401,11 +400,7 @@ private static int GetOTOffset(int language) public bool CanHandleOT(int language) => !GetHasOT(language); - public override GameVersion Version - { - get => OriginGame != 0 ? (GameVersion)OriginGame : GameVersion.PLA; - set { } - } + public override GameVersion Version => OriginGame != 0 ? (GameVersion)OriginGame : GameVersion.PLA; public bool IsAlpha { get => false; set { } } @@ -414,22 +409,23 @@ public override PA8 ConvertToPKM(ITrainerInfo tr, EncounterCriteria criteria) if (!IsEntity) throw new ArgumentException(nameof(IsEntity)); - int currentLevel = Level > 0 ? Level : 1 + Util.Rand.Next(100); - int metLevel = MetLevel > 0 ? MetLevel : currentLevel; + var rnd = Util.Rand; + byte currentLevel = Level > 0 ? Level : (byte)(1 + rnd.Next(100)); + var metLevel = MetLevel > 0 ? MetLevel : currentLevel; var pi = PersonalTable.LA.GetFormEntry(Species, Form); var language = tr.Language; bool hasOT = GetHasOT(language); var pk = new PA8 { - EncryptionConstant = EncryptionConstant != 0 ? EncryptionConstant : Util.Rand32(), + EncryptionConstant = EncryptionConstant != 0 ? EncryptionConstant : rnd.Rand32(), TID16 = TID16, SID16 = SID16, Species = Species, Form = Form, CurrentLevel = currentLevel, - Ball = Ball != 0 ? Ball : (int)Core.Ball.LAPoke, // Default is Pokeball - Met_Level = metLevel, + Ball = Ball != 0 ? Ball : (byte)Core.Ball.LAPoke, // Default is Pokeball + MetLevel = metLevel, HeldItem = HeldItem, EXP = Experience.GetEXP(currentLevel, pi.EXPGrowth), @@ -443,20 +439,20 @@ public override PA8 ConvertToPKM(ITrainerInfo tr, EncounterCriteria criteria) RelearnMove3 = RelearnMove3, RelearnMove4 = RelearnMove4, - Version = OriginGame != 0 ? OriginGame : tr.Game, + Version = OriginGame != 0 ? (GameVersion)OriginGame : tr.Version, - OT_Name = hasOT ? GetOT(language) : tr.OT, - OT_Gender = OTGender < 2 ? OTGender : tr.Gender, - HT_Name = hasOT ? tr.OT : string.Empty, - HT_Gender = hasOT ? tr.Gender : 0, - HT_Language = hasOT ? (byte)language : (byte)0, - CurrentHandler = hasOT ? 1 : 0, - OT_Friendship = pi.BaseFriendship, + OriginalTrainerName = hasOT ? GetOT(language) : tr.OT, + OriginalTrainerGender = OTGender < 2 ? OTGender : tr.Gender, + HandlingTrainerName = hasOT ? tr.OT : string.Empty, + HandlingTrainerGender = hasOT ? tr.Gender : default, + HandlingTrainerLanguage = hasOT ? (byte)language : default, + CurrentHandler = hasOT ? (byte)1 : (byte)0, + OriginalTrainerFriendship = pi.BaseFriendship, - OT_Intensity = OT_Intensity, - OT_Memory = OT_Memory, - OT_TextVar = OT_TextVar, - OT_Feeling = OT_Feeling, + OriginalTrainerMemoryIntensity = OriginalTrainerMemoryIntensity, + OriginalTrainerMemory = OriginalTrainerMemory, + OriginalTrainerMemoryVariable = OriginalTrainerMemoryVariable, + OriginalTrainerMemoryFeeling = OriginalTrainerMemoryFeeling, FatefulEncounter = true, EV_HP = EV_HP, @@ -476,13 +472,13 @@ public override PA8 ConvertToPKM(ITrainerInfo tr, EncounterCriteria criteria) //CanGigantamax = CanGigantamax, //DynamaxLevel = DynamaxLevel, - Met_Location = MetLocation, - Egg_Location = EggLocation, + MetLocation = Location, + EggLocation = EggLocation, }; pk.SetMaximumPPCurrent(); if ((tr.Generation > Generation && OriginGame == 0) || !CanBeReceivedByVersion(pk.Version, pk)) - pk.Version = (int)GameVersion.PLA; + pk.Version = GameVersion.PLA; if (OTGender >= 2) { @@ -494,7 +490,7 @@ public override PA8 ConvertToPKM(ITrainerInfo tr, EncounterCriteria criteria) // HOME Gifts for Sinnoh/Hisui starters were forced JPN until May 20, 2022 (UTC). if (CardID is 9018 or 9019 or 9020) - pk.Met_Day = 20; + pk.MetDay = 20; var nickname_language = GetLanguage(language); pk.Language = nickname_language != 0 ? nickname_language : tr.Language; @@ -514,8 +510,8 @@ public override PA8 ConvertToPKM(ITrainerInfo tr, EncounterCriteria criteria) SetEggMetData(pk); pk.CurrentFriendship = pk.IsEgg ? pi.HatchCycles : pi.BaseFriendship; - pk.HeightScalar = PokeSizeUtil.GetRandomScalar(); - pk.WeightScalar = PokeSizeUtil.GetRandomScalar(); + pk.HeightScalar = PokeSizeUtil.GetRandomScalar(rnd); + pk.WeightScalar = PokeSizeUtil.GetRandomScalar(rnd); pk.Scale = pk.HeightScalar; pk.ResetHeight(); pk.ResetWeight(); @@ -536,7 +532,7 @@ private void SetEggMetData(PA8 pk) private void SetPINGA(PA8 pk, EncounterCriteria criteria) { var pi = pk.PersonalInfo; - pk.Nature = pk.StatNature = (int)criteria.GetNature(Nature == -1 ? Core.Nature.Random : (Nature)Nature); + pk.Nature = pk.StatNature = criteria.GetNature((sbyte)Nature == -1 ? Nature.Random : Nature); pk.Gender = criteria.GetGender(Gender, pi); var av = GetAbilityIndex(criteria); pk.RefreshAbility(av); @@ -634,19 +630,19 @@ public override bool IsMatchExact(PKM pk, EvoCriteria evo) { if (SID16 != pk.SID16) return false; if (TID16 != pk.TID16) return false; - if (OTGender != pk.OT_Gender) return false; + if (OTGender != pk.OriginalTrainerGender) return false; } if (!CanBeAnyLanguage() && !CanHaveLanguage(pk.Language)) return false; var OT = GetOT(pk.Language); // May not be guaranteed to work. - if (!string.IsNullOrEmpty(OT) && OT != pk.OT_Name) + if (!string.IsNullOrEmpty(OT) && OT != pk.OriginalTrainerName) return false; - if (OriginGame != 0 && OriginGame != pk.Version) + if (OriginGame != 0 && (GameVersion)OriginGame != pk.Version) { - if (OriginGame is (int)GameVersion.PLA && !(pk.Version is (int)GameVersion.SW && pk.Met_Location == LocationsHOME.SWLA)) + if ((GameVersion)OriginGame is GameVersion.PLA && !(pk.Version is GameVersion.SW && pk.MetLocation == LocationsHOME.SWLA)) return false; } if (EncryptionConstant != 0) @@ -665,19 +661,19 @@ public override bool IsMatchExact(PKM pk, EvoCriteria evo) if (!IsMatchEggLocation(pk)) return false; if (pk is PK8) { - if (pk.Met_Location != LocationsHOME.SWLA) + if (pk.MetLocation != LocationsHOME.SWLA) return false; } else { - if (MetLocation != pk.Met_Location) + if (Location != pk.MetLocation) return false; } } - if (MetLevel != 0 && MetLevel != pk.Met_Level) return false; - if (OTGender < 2 && OTGender != pk.OT_Gender) return false; - if (Nature != -1 && pk.Nature != Nature) return false; + if (MetLevel != 0 && MetLevel != pk.MetLevel) return false; + if (OTGender < 2 && OTGender != pk.OriginalTrainerGender) return false; + if ((sbyte)Nature != -1 && pk.Nature != Nature) return false; if (Gender != 3 && Gender != pk.Gender) return false; const int poke = (int)Core.Ball.LAPoke; diff --git a/PKHeX.Core/MysteryGifts/WB7.cs b/PKHeX.Core/MysteryGifts/WB7.cs index 5af9c4c9c..145d8bdb3 100644 --- a/PKHeX.Core/MysteryGifts/WB7.cs +++ b/PKHeX.Core/MysteryGifts/WB7.cs @@ -7,7 +7,7 @@ namespace PKHeX.Core; /// Generation 7 Mystery Gift Template File (LGP/E) /// public sealed class WB7(byte[] Data) - : DataMysteryGift(Data), ILangNick, IAwakened, INature, ILangNicknamedTemplate, IRestrictVersion + : DataMysteryGift(Data), ILangNick, IAwakened, IRelearn, INature, ILangNicknamedTemplate, IRestrictVersion { public WB7() : this(new byte[SizeFull]) { } @@ -16,19 +16,19 @@ public sealed class WB7(byte[] Data) private const int CardStart = SizeFull - Size; public override bool FatefulEncounter => true; - public override int Generation => 7; + public override byte Generation => 7; public override EntityContext Context => EntityContext.Gen7b; - public override GameVersion Version { get => GameVersion.GG; set { } } + public override GameVersion Version => GameVersion.GG; public byte RestrictVersion { get => Data[0]; set => Data[0] = value; } - public bool CanBeReceivedByVersion(int v) + public bool CanBeReceivedByVersion(GameVersion version) { - if (v is not ((int)GameVersion.GP or (int)GameVersion.GE)) + if (version is not (GameVersion.GP or GameVersion.GE)) return false; if (RestrictVersion == 0) return true; // no data - var bitIndex = v - (int)GameVersion.GP; + var bitIndex = version - GameVersion.GP; var bit = 1 << bitIndex; return (RestrictVersion & bit) != 0; } @@ -172,10 +172,10 @@ public int OriginGame set => WriteUInt32LittleEndian(Data.AsSpan(CardStart + 0x70), value); } - public override int Ball + public override byte Ball { get => Data[CardStart + 0x76]; - set => Data[CardStart + 0x76] = (byte)value; } + set => Data[CardStart + 0x76] = value; } public override int HeldItem // no references { @@ -198,13 +198,13 @@ public override int Ball // set => Encoding.Unicode.GetBytes(value.PadRight(12 + 1, '\0')).CopyTo(Data, CardStart + 0x86); // } - public int Nature { get => (sbyte)Data[CardStart + 0xA0]; set => Data[CardStart + 0xA0] = (byte)value; } - public override int Gender { get => Data[CardStart + 0xA1]; set => Data[CardStart + 0xA1] = (byte)value; } + public Nature Nature { get => (Nature)Data[CardStart + 0xA0]; set => Data[CardStart + 0xA0] = (byte)value; } + public override byte Gender { get => Data[CardStart + 0xA1]; set => Data[CardStart + 0xA1] = value; } public override int AbilityType { get => 3; set => Data[CardStart + 0xA2] = (byte)value; } // no references, always ability 0/1 public ShinyType6 PIDType { get => (ShinyType6)Data[CardStart + 0xA3]; set => Data[CardStart + 0xA3] = (byte)value; } - public override int EggLocation { get => ReadUInt16LittleEndian(Data.AsSpan(CardStart + 0xA4)); set => WriteUInt16LittleEndian(Data.AsSpan(CardStart + 0xA4), (ushort)value); } - public int MetLocation { get => ReadUInt16LittleEndian(Data.AsSpan(CardStart + 0xA6)); set => WriteUInt16LittleEndian(Data.AsSpan(CardStart + 0xA6), (ushort)value); } - public int MetLevel { get => Data[CardStart + 0xA8]; set => Data[CardStart + 0xA8] = (byte)value; } + public override ushort EggLocation { get => ReadUInt16LittleEndian(Data.AsSpan(CardStart + 0xA4)); set => WriteUInt16LittleEndian(Data.AsSpan(CardStart + 0xA4), value); } + public override ushort Location { get => ReadUInt16LittleEndian(Data.AsSpan(CardStart + 0xA6)); set => WriteUInt16LittleEndian(Data.AsSpan(CardStart + 0xA6), value); } + public byte MetLevel { get => Data[CardStart + 0xA8]; set => Data[CardStart + 0xA8] = value; } public int IV_HP { get => Data[CardStart + 0xAF]; set => Data[CardStart + 0xAF] = (byte)value; } public int IV_ATK { get => Data[CardStart + 0xB0]; set => Data[CardStart + 0xB0] = (byte)value; } @@ -213,9 +213,9 @@ public override int Ball public int IV_SPA { get => Data[CardStart + 0xB3]; set => Data[CardStart + 0xB3] = (byte)value; } public int IV_SPD { get => Data[CardStart + 0xB4]; set => Data[CardStart + 0xB4] = (byte)value; } - public int OTGender { get => Data[CardStart + 0xB5]; set => Data[CardStart + 0xB5] = (byte)value; } + public byte OTGender { get => Data[CardStart + 0xB5]; set => Data[CardStart + 0xB5] = value; } - // public override string OT_Name + // public override string OriginalTrainerName // { // get => Util.TrimFromZero(Encoding.Unicode.GetString(Data, CardStart + 0xB6, 0x1A)); // set => Encoding.Unicode.GetBytes(value.PadRight(value.Length + 1, '\0')).CopyTo(Data, CardStart + 0xB6); @@ -239,7 +239,7 @@ public override int Ball public byte AV_SPD { get => Data[CardStart + 0xEA]; set => Data[CardStart + 0xEA] = value; } // Meta Accessible Properties - public override int[] IVs + public int[] IVs { get => [IV_HP, IV_ATK, IV_DEF, IV_SPE, IV_SPA, IV_SPD]; set @@ -272,8 +272,6 @@ private static int GetLanguageIndex(int language) return lang < LanguageID.UNUSED_6 ? language - 1 : language - 2; } - public override int Location { get => MetLocation; set => MetLocation = (ushort)value; } - public override Moveset Moves { get => new(Move1, Move2, Move3, Move4); @@ -286,7 +284,7 @@ public override Moveset Moves } } - public override Moveset Relearn + public Moveset Relearn { get => new(RelearnMove1, RelearnMove2, RelearnMove3, RelearnMove4); set @@ -298,7 +296,7 @@ public override Moveset Relearn } } - public override string OT_Name + public override string OriginalTrainerName { get => GetOT(Language); set @@ -354,8 +352,8 @@ public override PB7 ConvertToPKM(ITrainerInfo tr, EncounterCriteria criteria) var rnd = Util.Rand; - int currentLevel = Level > 0 ? Level : (1 + rnd.Next(100)); - int metLevel = MetLevel > 0 ? MetLevel : currentLevel; + byte currentLevel = Level > 0 ? Level : (byte)(1 + rnd.Next(100)); + var metLevel = MetLevel > 0 ? MetLevel : currentLevel; var pi = PersonalTable.GG.GetFormEntry(Species, Form); var redeemLanguage = tr.Language; @@ -368,10 +366,10 @@ public override PB7 ConvertToPKM(ITrainerInfo tr, EncounterCriteria criteria) HeldItem = HeldItem, TID16 = TID16, SID16 = SID16, - Met_Level = metLevel, + MetLevel = metLevel, Form = Form, - EncryptionConstant = EncryptionConstant != 0 ? EncryptionConstant : Util.Rand32(), - Version = OriginGame != 0 ? OriginGame : tr.Game, + EncryptionConstant = EncryptionConstant != 0 ? EncryptionConstant : rnd.Rand32(), + Version = OriginGame != 0 ? (GameVersion)OriginGame : tr.Version, Language = language, Ball = Ball, Move1 = Move1, @@ -382,8 +380,8 @@ public override PB7 ConvertToPKM(ITrainerInfo tr, EncounterCriteria criteria) RelearnMove2 = RelearnMove2, RelearnMove3 = RelearnMove3, RelearnMove4 = RelearnMove4, - Met_Location = MetLocation, - Egg_Location = EggLocation, + MetLocation = Location, + EggLocation = EggLocation, AV_HP = AV_HP, AV_ATK = AV_ATK, AV_DEF = AV_DEF, @@ -391,19 +389,19 @@ public override PB7 ConvertToPKM(ITrainerInfo tr, EncounterCriteria criteria) AV_SPA = AV_SPA, AV_SPD = AV_SPD, - OT_Name = hasOT ? GetOT(redeemLanguage) : tr.OT, - OT_Gender = OTGender != 3 ? OTGender % 2 : tr.Gender, + OriginalTrainerName = hasOT ? GetOT(redeemLanguage) : tr.OT, + OriginalTrainerGender = (byte)(OTGender != 3 ? OTGender % 2 : tr.Gender), EXP = Experience.GetEXP(currentLevel, pi.EXPGrowth), - OT_Friendship = pi.BaseFriendship, + OriginalTrainerFriendship = pi.BaseFriendship, FatefulEncounter = true, }; if (hasOT) { - pk.HT_Name = tr.OT; - pk.HT_Gender = tr.Gender; + pk.HandlingTrainerName = tr.OT; + pk.HandlingTrainerGender = tr.Gender; pk.CurrentHandler = 1; } @@ -412,7 +410,7 @@ public override PB7 ConvertToPKM(ITrainerInfo tr, EncounterCriteria criteria) if ((tr.Generation > Generation && OriginGame == 0) || !CanBeReceivedByVersion(pk.Version)) { // give random valid game - do { pk.Version = (int)GameVersion.GP + rnd.Next(2); } + do { pk.Version = GameVersion.GP + (byte)rnd.Next(2); } while (!CanBeReceivedByVersion(pk.Version)); } @@ -451,7 +449,7 @@ private void SetEggMetData(PB7 pk) private void SetPINGA(PB7 pk, EncounterCriteria criteria) { var pi = pk.PersonalInfo; - pk.Nature = (int)criteria.GetNature((Nature)Nature); + pk.Nature = criteria.GetNature(Nature); pk.Gender = criteria.GetGender(Gender, pi); var av = GetAbilityIndex(criteria); pk.RefreshAbility(av); @@ -555,11 +553,11 @@ public override bool IsMatchExact(PKM pk, EvoCriteria evo) { if (SID16 != pk.SID16) return false; if (TID16 != pk.TID16) return false; - if (OTGender != pk.OT_Gender) return false; + if (OTGender != pk.OriginalTrainerGender) return false; } var OT = GetOT(pk.Language); - if (!string.IsNullOrEmpty(OT) && OT != pk.OT_Name) return false; - if (OriginGame != 0 && OriginGame != pk.Version) return false; + if (!string.IsNullOrEmpty(OT) && OT != pk.OriginalTrainerName) return false; + if (OriginGame != 0 && (GameVersion)OriginGame != pk.Version) return false; if (EncryptionConstant != 0 && EncryptionConstant != pk.EncryptionConstant) return false; if (!IsMatchEggLocation(pk)) return false; @@ -572,9 +570,9 @@ public override bool IsMatchExact(PKM pk, EvoCriteria evo) if (IsEgg) { - if (EggLocation != pk.Egg_Location) // traded + if (EggLocation != pk.EggLocation) // traded { - if (pk.Egg_Location != Locations.LinkTrade6) + if (pk.EggLocation != Locations.LinkTrade6) return false; } else if (PIDType == 0 && pk.IsShiny) @@ -589,13 +587,13 @@ public override bool IsMatchExact(PKM pk, EvoCriteria evo) { if (!Shiny.IsValid(pk)) return false; if (!IsMatchEggLocation(pk)) return false; - if (MetLocation != pk.Met_Location) return false; + if (Location != pk.MetLocation) return false; } - if (MetLevel != pk.Met_Level) return false; + if (MetLevel != pk.MetLevel) return false; if (Ball != pk.Ball) return false; - if (OTGender < 3 && OTGender != pk.OT_Gender) return false; - if (Nature != -1 && pk.Nature != Nature) return false; + if (OTGender < 3 && OTGender != pk.OriginalTrainerGender) return false; + if ((sbyte)Nature != -1 && pk.Nature != Nature) return false; if (Gender != 3 && Gender != pk.Gender) return false; if (pk is IAwakened s && s.IsAwakeningBelow(this)) diff --git a/PKHeX.Core/MysteryGifts/WB8.cs b/PKHeX.Core/MysteryGifts/WB8.cs index a753e282d..6cfa5aafd 100644 --- a/PKHeX.Core/MysteryGifts/WB8.cs +++ b/PKHeX.Core/MysteryGifts/WB8.cs @@ -8,7 +8,7 @@ namespace PKHeX.Core; /// Generation 8b Mystery Gift Template File /// public sealed class WB8(byte[] Data) : DataMysteryGift(Data), - ILangNick, INature, IRibbonIndex, IContestStatsReadOnly, + ILangNick, INature, IRibbonIndex, IContestStatsReadOnly, IRelearn, ILangNicknamedTemplate, IEncounterServerDate, IRibbonSetEvent3, IRibbonSetEvent4, IRibbonSetCommon3, IRibbonSetCommon4, IRibbonSetCommon6, IRibbonSetCommon7, IRibbonSetCommon8, IRibbonSetMark8 @@ -18,7 +18,7 @@ public sealed class WB8(byte[] Data) : DataMysteryGift(Data), public const int Size = 0x2DC; public const int CardStart = 0x0; - public override int Generation => 8; + public override byte Generation => 8; public override EntityContext Context => EntityContext.Gen8b; public override bool FatefulEncounter => true; @@ -38,7 +38,8 @@ public enum GiftType : byte // TODO: public byte RestrictVersion? - public bool CanBeReceivedByVersion(int v, PKM pk) => v is (int) GameVersion.BD or (int) GameVersion.SP || (pk is PK8 && LocationsHOME.IsValidMetBDSP((ushort)pk.Met_Location, pk.Version)); + public bool CanBeReceivedByVersion(GameVersion version, PKM pk) => version is GameVersion.BD or GameVersion.SP + || (pk is PK8 && LocationsHOME.IsValidMetBDSP(pk.MetLocation, pk.Version)); // General Card Properties @@ -155,13 +156,13 @@ public uint PID } // Nicknames, OT Names 0x30 - 0x270 - public override int EggLocation { get => ReadUInt16LittleEndian(Data.AsSpan(CardStart + 0x270)); set => WriteUInt16LittleEndian(Data.AsSpan(CardStart + 0x270), (ushort)value); } - public int MetLocation { get => ReadUInt16LittleEndian(Data.AsSpan(CardStart + 0x272)); set => WriteUInt16LittleEndian(Data.AsSpan(CardStart + 0x272), (ushort)value); } + public override ushort EggLocation { get => ReadUInt16LittleEndian(Data.AsSpan(CardStart + 0x270)); set => WriteUInt16LittleEndian(Data.AsSpan(CardStart + 0x270), value); } + public override ushort Location { get => ReadUInt16LittleEndian(Data.AsSpan(CardStart + 0x272)); set => WriteUInt16LittleEndian(Data.AsSpan(CardStart + 0x272), value); } - public override int Ball + public override byte Ball { - get => ReadUInt16LittleEndian(Data.AsSpan(CardStart + 0x274)); - set => WriteUInt16LittleEndian(Data.AsSpan(CardStart + 0x274), (ushort)value); + get => (byte)ReadUInt16LittleEndian(Data.AsSpan(CardStart + 0x274)); + set => WriteUInt16LittleEndian(Data.AsSpan(CardStart + 0x274), value); } public override int HeldItem @@ -181,17 +182,17 @@ public override int HeldItem public override ushort Species { get => ReadUInt16LittleEndian(Data.AsSpan(CardStart + 0x288)); set => WriteUInt16LittleEndian(Data.AsSpan(CardStart + 0x288), value); } public override byte Form { get => Data[CardStart + 0x28A]; set => Data[CardStart + 0x28A] = value; } - public override int Gender { get => Data[CardStart + 0x28B]; set => Data[CardStart + 0x28B] = (byte)value; } + public override byte Gender { get => Data[CardStart + 0x28B]; set => Data[CardStart + 0x28B] = value; } public override byte Level { get => Data[CardStart + 0x28C]; set => Data[CardStart + 0x28C] = value; } public override bool IsEgg { get => Data[CardStart + 0x28D] == 1; set => Data[CardStart + 0x28D] = value ? (byte)1 : (byte)0; } - public int Nature { get => (sbyte)Data[CardStart + 0x28E]; set => Data[CardStart + 0x28E] = (byte)value; } + public Nature Nature { get => (Nature)Data[CardStart + 0x28E]; set => Data[CardStart + 0x28E] = (byte)value; } public override int AbilityType { get => Data[CardStart + 0x28F]; set => Data[CardStart + 0x28F] = (byte)value; } private byte PIDTypeValue => Data[CardStart + 0x290]; public ShinyType8 PIDType => (ShinyType8)PIDTypeValue; - public int MetLevel { get => Data[CardStart + 0x291]; set => Data[CardStart + 0x291] = (byte)value; } + public byte MetLevel { get => Data[CardStart + 0x291]; set => Data[CardStart + 0x291] = value; } // Ribbons 0x292-0x2B2 private const int RibbonBytesOffset = 0x292; @@ -234,7 +235,7 @@ public void SetRibbonAtIndex(int byteIndex, byte ribbonIndex) public int IV_SPA { get => Data[CardStart + 0x2B6]; set => Data[CardStart + 0x2B6] = (byte)value; } public int IV_SPD { get => Data[CardStart + 0x2B7]; set => Data[CardStart + 0x2B7] = (byte)value; } - public int OTGender { get => Data[CardStart + 0x2B8]; set => Data[CardStart + 0x2B8] = (byte)value; } + public byte OTGender { get => Data[CardStart + 0x2B8]; set => Data[CardStart + 0x2B8] = value; } public int EV_HP { get => Data[CardStart + 0x2B9]; set => Data[CardStart + 0x2B9] = (byte)value; } public int EV_ATK { get => Data[CardStart + 0x2BA]; set => Data[CardStart + 0x2BA] = (byte)value; } @@ -243,15 +244,15 @@ public void SetRibbonAtIndex(int byteIndex, byte ribbonIndex) public int EV_SPA { get => Data[CardStart + 0x2BD]; set => Data[CardStart + 0x2BD] = (byte)value; } public int EV_SPD { get => Data[CardStart + 0x2BE]; set => Data[CardStart + 0x2BE] = (byte)value; } - public byte CNT_Cool { get => Data[0x2BF]; set => Data[0x2BF] = value; } - public byte CNT_Beauty { get => Data[0x2C0]; set => Data[0x2C0] = value; } - public byte CNT_Cute { get => Data[0x2C1]; set => Data[0x2C1] = value; } - public byte CNT_Smart { get => Data[0x2C2]; set => Data[0x2C2] = value; } - public byte CNT_Tough { get => Data[0x2C3]; set => Data[0x2C3] = value; } - public byte CNT_Sheen { get => Data[0x2C4]; set => Data[0x2C4] = value; } + public byte ContestCool { get => Data[0x2BF]; set => Data[0x2BF] = value; } + public byte ContestBeauty { get => Data[0x2C0]; set => Data[0x2C0] = value; } + public byte ContestCute { get => Data[0x2C1]; set => Data[0x2C1] = value; } + public byte ContestSmart { get => Data[0x2C2]; set => Data[0x2C2] = value; } + public byte ContestTough { get => Data[0x2C3]; set => Data[0x2C3] = value; } + public byte ContestSheen { get => Data[0x2C4]; set => Data[0x2C4] = value; } // Meta Accessible Properties - public override int[] IVs + public int[] IVs { get => [IV_HP, IV_ATK, IV_DEF, IV_SPE, IV_SPA, IV_SPD]; set @@ -331,8 +332,6 @@ private static int GetLanguageIndex(int language) return lang < LanguageID.UNUSED_6 ? language - 1 : language - 2; } - public override int Location { get => MetLocation; set => MetLocation = (ushort)value; } - public override Moveset Moves { get => new(Move1, Move2, Move3, Move4); @@ -345,7 +344,7 @@ public override Moveset Moves } } - public override Moveset Relearn + public Moveset Relearn { get => new(RelearnMove1, RelearnMove2, RelearnMove3, RelearnMove4); set @@ -357,7 +356,7 @@ public override Moveset Relearn } } - public override string OT_Name + public override string OriginalTrainerName { get => GetOT(Language); set @@ -395,33 +394,30 @@ private static int GetOTOffset(int language) public bool CanHandleOT(int language) => !GetHasOT(language); - public override GameVersion Version - { - get => OriginGame != 0 ? (GameVersion)OriginGame : GameVersion.BDSP; - set { } - } + public override GameVersion Version => OriginGame != 0 ? (GameVersion)OriginGame : GameVersion.BDSP; public override PB8 ConvertToPKM(ITrainerInfo tr, EncounterCriteria criteria) { if (!IsEntity) throw new ArgumentException(nameof(IsEntity)); - int currentLevel = Level > 0 ? Level : 1 + Util.Rand.Next(100); - int metLevel = MetLevel > 0 ? MetLevel : currentLevel; + var rnd = Util.Rand; + byte currentLevel = Level > 0 ? Level : (byte)(1 + rnd.Next(100)); + var metLevel = MetLevel > 0 ? MetLevel : currentLevel; var pi = PersonalTable.BDSP.GetFormEntry(Species, Form); var language = tr.Language; bool hasOT = GetHasOT(language); var pk = new PB8 { - EncryptionConstant = EncryptionConstant != 0 ? EncryptionConstant : Util.Rand32(), + EncryptionConstant = EncryptionConstant != 0 ? EncryptionConstant : rnd.Rand32(), TID16 = TID16, SID16 = SID16, Species = Species, Form = Form, CurrentLevel = currentLevel, - Ball = Ball != 0 ? Ball : 4, // Default is Pokeball - Met_Level = metLevel, + Ball = Ball != 0 ? Ball : (byte)4, // Default is Pokeball + MetLevel = metLevel, HeldItem = HeldItem, EXP = Experience.GetEXP(currentLevel, pi.EXPGrowth), @@ -435,15 +431,15 @@ public override PB8 ConvertToPKM(ITrainerInfo tr, EncounterCriteria criteria) RelearnMove3 = RelearnMove3, RelearnMove4 = RelearnMove4, - Version = OriginGame != 0 ? OriginGame : tr.Game, + Version = OriginGame != 0 ? (GameVersion)OriginGame : tr.Version, - OT_Name = hasOT ? GetOT(language) : tr.OT, - OT_Gender = OTGender < 2 ? OTGender : tr.Gender, - HT_Name = hasOT ? tr.OT : string.Empty, - HT_Gender = hasOT ? tr.Gender : 0, - HT_Language = (byte)(hasOT ? language : 0), - CurrentHandler = hasOT ? 1 : 0, - OT_Friendship = pi.BaseFriendship, + OriginalTrainerName = hasOT ? GetOT(language) : tr.OT, + OriginalTrainerGender = OTGender < 2 ? OTGender : tr.Gender, + HandlingTrainerName = hasOT ? tr.OT : string.Empty, + HandlingTrainerGender = hasOT ? tr.Gender : default, + HandlingTrainerLanguage = (byte)(hasOT ? language : default), + CurrentHandler = hasOT ? (byte)1 : (byte)0, + OriginalTrainerFriendship = pi.BaseFriendship, FatefulEncounter = true, @@ -454,23 +450,23 @@ public override PB8 ConvertToPKM(ITrainerInfo tr, EncounterCriteria criteria) EV_SPA = EV_SPA, EV_SPD = EV_SPD, - CNT_Cool = CNT_Cool, - CNT_Beauty = CNT_Beauty, - CNT_Cute = CNT_Cute, - CNT_Smart = CNT_Smart, - CNT_Tough = CNT_Tough, - CNT_Sheen = CNT_Sheen, + ContestCool = ContestCool, + ContestBeauty = ContestBeauty, + ContestCute = ContestCute, + ContestSmart = ContestSmart, + ContestTough = ContestTough, + ContestSheen = ContestSheen, - Met_Location = MetLocation, - Egg_Location = EggLocation, + MetLocation = Location, + EggLocation = EggLocation, }; if (EggLocation == 0) - pk.Egg_Location = Locations.Default8bNone; + pk.EggLocation = Locations.Default8bNone; if (Species == (int)Core.Species.Manaphy && IsEgg) { - pk.Egg_Location = MetLocation; - pk.Met_Location = Locations.Default8bNone; + pk.EggLocation = Location; + pk.MetLocation = Locations.Default8bNone; pk.IsNicknamed = false; } pk.SetMaximumPPCurrent(); @@ -478,8 +474,7 @@ public override PB8 ConvertToPKM(ITrainerInfo tr, EncounterCriteria criteria) if ((tr.Generation > Generation && OriginGame == 0) || !CanBeReceivedByVersion(pk.Version, pk)) { // give random valid game - var rnd = Util.Rand; - do { pk.Version = (int)GameVersion.BD + rnd.Next(2); } + do { pk.Version = GameVersion.BD + (byte)rnd.Next(2); } while (!CanBeReceivedByVersion(pk.Version, pk)); } @@ -492,7 +487,7 @@ public override PB8 ConvertToPKM(ITrainerInfo tr, EncounterCriteria criteria) pk.MetDate = IsDateRestricted && EncounterServerDate.WB8Gifts.TryGetValue(CardID, out var dt) ? dt.Start : EncounterDate.GetDateSwitch(); // HOME Gifts for Sinnoh/Hisui starters were forced JPN until May 20, 2022 (UTC). if (CardID is 9015 or 9016 or 9017) - pk.Met_Day = 20; + pk.MetDay = 20; var nickname_language = GetLanguage(language); pk.Language = nickname_language != 0 ? nickname_language : tr.Language; @@ -512,8 +507,8 @@ public override PB8 ConvertToPKM(ITrainerInfo tr, EncounterCriteria criteria) SetEggMetData(pk); pk.CurrentFriendship = pk.IsEgg ? pi.HatchCycles : pi.BaseFriendship; - pk.HeightScalar = PokeSizeUtil.GetRandomScalar(); - pk.WeightScalar = PokeSizeUtil.GetRandomScalar(); + pk.HeightScalar = PokeSizeUtil.GetRandomScalar(rnd); + pk.WeightScalar = PokeSizeUtil.GetRandomScalar(rnd); pk.ResetPartyStats(); pk.RefreshChecksum(); @@ -531,7 +526,7 @@ private void SetEggMetData(PB8 pk) private void SetPINGA(PB8 pk, EncounterCriteria criteria) { var pi = pk.PersonalInfo; - pk.Nature = pk.StatNature = (int)criteria.GetNature(Nature == -1 ? Core.Nature.Random : (Nature)Nature); + pk.Nature = pk.StatNature = criteria.GetNature((sbyte)Nature == -1 ? Nature.Random : Nature); pk.Gender = criteria.GetGender(Gender, pi); var av = GetAbilityIndex(criteria); pk.RefreshAbility(av); @@ -629,19 +624,19 @@ public override bool IsMatchExact(PKM pk, EvoCriteria evo) { if (SID16 != pk.SID16) return false; if (TID16 != pk.TID16) return false; - if (OTGender != pk.OT_Gender) return false; + if (OTGender != pk.OriginalTrainerGender) return false; } if (!CanBeAnyLanguage() && !CanHaveLanguage(pk.Language)) return false; var OT = GetOT(pk.Language); // May not be guaranteed to work. - if (!string.IsNullOrEmpty(OT) && OT != pk.OT_Name) return false; - if (OriginGame != 0 && OriginGame != pk.Version) + if (!string.IsNullOrEmpty(OT) && OT != pk.OriginalTrainerName) return false; + if (OriginGame != 0 && (GameVersion)OriginGame != pk.Version) { - if (OriginGame is (int)GameVersion.BD && !(pk.Version is (int)GameVersion.SW && pk.Met_Location == LocationsHOME.SWBD)) + if ((GameVersion)OriginGame is GameVersion.BD && !(pk.Version is GameVersion.SW && pk.MetLocation == LocationsHOME.SWBD)) return false; - if (OriginGame is (int)GameVersion.SP && !(pk.Version is (int)GameVersion.SH && pk.Met_Location == LocationsHOME.SHSP)) + if ((GameVersion)OriginGame is GameVersion.SP && !(pk.Version is GameVersion.SH && pk.MetLocation == LocationsHOME.SHSP)) return false; } if (EncryptionConstant != 0) @@ -656,10 +651,10 @@ public override bool IsMatchExact(PKM pk, EvoCriteria evo) if (IsEgg) { - var eggloc = Species == (int)Core.Species.Manaphy ? MetLocation : EggLocation; - if (eggloc != pk.Egg_Location) // traded + var eggLoc = Species == (int)Core.Species.Manaphy ? Location : EggLocation; + if (eggLoc != pk.EggLocation) // traded { - if (pk.Egg_Location != Locations.LinkTrade6NPC) + if (pk.EggLocation != Locations.LinkTrade6NPC) return false; if (PIDType == ShinyType8.Random && pk is { IsShiny: true, ShinyXor: > 1 }) return false; // shiny traded egg will always have xor0/1. @@ -679,10 +674,10 @@ public override bool IsMatchExact(PKM pk, EvoCriteria evo) if (!IsMatchLocation(pk)) return false; } - if (MetLevel != 0 && MetLevel != pk.Met_Level) return false; + if (MetLevel != 0 && MetLevel != pk.MetLevel) return false; if ((Ball == 0 ? 4 : Ball) != pk.Ball) return false; - if (OTGender < 2 && OTGender != pk.OT_Gender) return false; - if (Nature != -1 && pk.Nature != Nature) return false; + if (OTGender < 2 && OTGender != pk.OriginalTrainerGender) return false; + if ((sbyte)Nature != -1 && pk.Nature != Nature) return false; if (Gender != 3 && Gender != pk.Gender) return false; // PID Types 0 and 1 do not use the fixed PID value. @@ -697,7 +692,7 @@ public override bool IsMatchExact(PKM pk, EvoCriteria evo) protected override bool IsMatchEggLocation(PKM pk) { var expect = pk is PB8 ? Locations.Default8bNone : 0; - return pk.Egg_Location == expect; + return pk.EggLocation == expect; } private bool IsMatchLocation(PKM pk) @@ -710,15 +705,15 @@ private bool IsMatchLocation(PKM pk) return IsMatchLocationExact(pk) || IsMatchLocationRemapped(pk); } - private bool IsMatchLocationExact(PKM pk) => pk.Met_Location == Location; + private bool IsMatchLocationExact(PKM pk) => pk.MetLocation == this.Location; private bool IsMatchLocationRemapped(PKM pk) { - var met = (ushort)pk.Met_Location; + var met = pk.MetLocation; var version = pk.Version; if (pk.Context == EntityContext.Gen8) return LocationsHOME.IsValidMetBDSP(met, version); - return LocationsHOME.GetMetSWSH((ushort)Location, version) == met; + return LocationsHOME.GetMetSWSH(this.Location, version) == met; } protected override bool IsMatchDeferred(PKM pk) => false; diff --git a/PKHeX.Core/MysteryGifts/WC3.cs b/PKHeX.Core/MysteryGifts/WC3.cs index 0bd6b1f97..6572d2f59 100644 --- a/PKHeX.Core/MysteryGifts/WC3.cs +++ b/PKHeX.Core/MysteryGifts/WC3.cs @@ -9,7 +9,7 @@ namespace PKHeX.Core; /// This is fabricated data built to emulate the future generation Mystery Gift objects. /// Data here is not stored in any save file and cannot be naturally exported. /// -public sealed class WC3(bool Fateful = false) +public sealed class WC3(GameVersion Version, bool Fateful = false) : MysteryGift, IRibbonSetEvent3, ILangNicknamedTemplate, IRandomCorrelation { public override MysteryGift Clone() => (WC3)MemberwiseClone(); @@ -32,27 +32,27 @@ public bool IsCompatible(PIDType type, PKM pk) private const ushort UnspecifiedID = ushort.MaxValue; - public override string OT_Name { get; set; } = string.Empty; - public int OT_Gender { get; init; } = 3; + public override string OriginalTrainerName { get; set; } = string.Empty; + public byte OriginalTrainerGender { get; init; } = 3; public override uint ID32 { get => (uint)(SID16 << 16 | TID16); set => (SID16, TID16) = ((ushort)(value >> 16), (ushort)value); } public override ushort TID16 { get; set; } = UnspecifiedID; public override ushort SID16 { get; set; } = UnspecifiedID; - public override int Location { get; set; } = 255; - public override int EggLocation { get => 0; set {} } - public override GameVersion Version { get; set; } - public int Language { get; init; } = -1; + public override ushort Location { get; set; } = 255; // Event + public override ushort EggLocation { get => 0; set {} } + public byte Language { get; init; } // default 0 for eggs public override ushort Species { get; set; } public override bool IsEgg { get; set; } public override Moveset Moves { get; set; } public bool NotDistributed { get; init; } public override Shiny Shiny { get; init; } + public override GameVersion Version { get; } = Version; public override bool FatefulEncounter { get; } = Fateful; // Obedience Flag // Mystery Gift Properties - public override int Generation => 3; + public override byte Generation => 3; public override EntityContext Context => EntityContext.Gen3; public override byte Level { get; set; } - public override int Ball { get; set; } = 4; + public override byte Ball { get; set; } = 4; public override bool IsShiny => Shiny == Shiny.Always; public override bool HasFixedIVs => false; public bool RibbonEarth { get; set; } @@ -75,15 +75,15 @@ public bool IsCompatible(PIDType type, PKM pk) public override int ItemID { get; set; } public override bool IsEntity { get; set; } = true; public override bool Empty => false; - public override int Gender { get; set; } + public override byte Gender { get; set; } public override byte Form { get; set; } // Synthetic - private readonly int? _metLevel; + private readonly byte? _metLevel; - public int Met_Level + public byte MetLevel { - get => _metLevel ?? (IsEgg ? 0 : Level); + get => _metLevel ?? (IsEgg ? (byte)0 : Level); init => _metLevel = value; } @@ -94,8 +94,8 @@ public override PK3 ConvertToPKM(ITrainerInfo tr, EncounterCriteria criteria) PK3 pk = new() { Species = Species, - Met_Level = Met_Level, - Met_Location = Location, + MetLevel = MetLevel, + MetLocation = Location, Ball = 4, // Ribbons @@ -119,23 +119,23 @@ public override PK3 ConvertToPKM(ITrainerInfo tr, EncounterCriteria criteria) } else { - pk.OT_Gender = OT_Gender != 3 ? OT_Gender & 1 : tr.Gender; + pk.OriginalTrainerGender = OriginalTrainerGender != 3 ? (byte)(OriginalTrainerGender & 1): tr.Gender; pk.TID16 = TID16; pk.SID16 = SID16; pk.Language = (int)GetSafeLanguage((LanguageID)tr.Language); - pk.OT_Name = !string.IsNullOrWhiteSpace(OT_Name) ? OT_Name : tr.OT; + pk.OriginalTrainerName = !string.IsNullOrWhiteSpace(OriginalTrainerName) ? OriginalTrainerName : tr.OT; if (IsEgg) { pk.IsEgg = true; // lang should be set to japanese already - if (pk.OT_Trash[0] == 0xFF) - pk.OT_Name = "ゲーフリ"; + if (pk.OriginalTrainerTrash[0] == 0xFF) + pk.OriginalTrainerName = "ゲーフリ"; } } pk.Nickname = Nickname ?? SpeciesName.GetSpeciesNameGeneration(Species, pk.Language, 3); // will be set to Egg nickname if appropriate by PK3 setter var pi = pk.PersonalInfo; - pk.OT_Friendship = pk.IsEgg ? pi.HatchCycles : pi.BaseFriendship; + pk.OriginalTrainerFriendship = pk.IsEgg ? pi.HatchCycles : pi.BaseFriendship; // Generate PIDIV SetPINGA(pk, criteria); @@ -151,36 +151,36 @@ public override PK3 ConvertToPKM(ITrainerInfo tr, EncounterCriteria criteria) private void SetForceHatchDetails(PK3 pk, ITrainerInfo sav) { pk.Language = (int)GetSafeLanguageNotEgg((LanguageID)sav.Language); - pk.OT_Name = sav.OT; + pk.OriginalTrainerName = sav.OT; // ugly workaround for character table interactions - if (string.IsNullOrWhiteSpace(pk.OT_Name)) + if (string.IsNullOrWhiteSpace(pk.OriginalTrainerName)) { pk.Language = (int)LanguageID.English; - pk.OT_Name = "PKHeX"; + pk.OriginalTrainerName = "PKHeX"; } - pk.OT_Gender = sav.Gender; + pk.OriginalTrainerGender = sav.Gender; pk.TID16 = sav.TID16; pk.SID16 = sav.SID16; - pk.Met_Location = pk.FRLG ? 146 /* Four Island */ : 32; // Route 117 + pk.MetLocation = pk.FRLG ? Locations.HatchLocationFRLG : Locations.HatchLocationRSE; pk.FatefulEncounter &= pk.FRLG; // clear flag for RSE - pk.Met_Level = 0; // hatched + pk.MetLevel = 0; // hatched } - private int GetVersion(ITrainerInfo sav) + private GameVersion GetVersion(ITrainerInfo sav) { if (Version != 0) - return (int) GetRandomVersion(Version); - bool gen3 = sav.Game <= 15 && GameVersion.Gen3.Contains((GameVersion)sav.Game); - return gen3 ? sav.Game : (int)GameVersion.R; + return GetRandomVersion(Version); + bool gen3 = sav.Version <= GameVersion.CXD && GameVersion.Gen3.Contains(sav.Version); + return gen3 ? sav.Version : GameVersion.R; } private void SetMoves(PK3 pk) { if (!Moves.HasMoves) // not completely defined { - var ver = (GameVersion)pk.Version; - ILearnSource ls = ver switch + var version = pk.Version; + ILearnSource ls = version switch { GameVersion.R or GameVersion.S => LearnSource3RS.Instance, GameVersion.FR => LearnSource3FR.Instance, @@ -222,7 +222,7 @@ private LanguageID GetSafeLanguage(LanguageID hatchLang) private LanguageID GetSafeLanguageNotEgg(LanguageID hatchLang) { - if (Language != -1) + if (Language != 0) return (LanguageID) Language; if (hatchLang < LanguageID.Korean && hatchLang != LanguageID.Hacked) return hatchLang; @@ -246,7 +246,7 @@ private static GameVersion GetRandomVersion(GameVersion version) public override bool IsMatchExact(PKM pk, EvoCriteria evo) { // Gen3 Version MUST match. - if (Version != 0 && !Version.Contains((GameVersion)pk.Version)) + if (Version != 0 && !Version.Contains(pk.Version)) return false; bool hatchedEgg = IsEgg && !pk.IsEgg; @@ -254,16 +254,16 @@ public override bool IsMatchExact(PKM pk, EvoCriteria evo) { if (SID16 != UnspecifiedID && SID16 != pk.SID16) return false; if (TID16 != UnspecifiedID && TID16 != pk.TID16) return false; - if (OT_Gender < 3 && OT_Gender != pk.OT_Gender) return false; - var wcOT = OT_Name; + if (OriginalTrainerGender < 3 && OriginalTrainerGender != pk.OriginalTrainerGender) return false; + var wcOT = OriginalTrainerName; if (!string.IsNullOrEmpty(wcOT)) { if (wcOT.Length > 7) // Colosseum MATTLE Ho-Oh { - if (!GetIsValidOTMattleHoOh(wcOT, pk.OT_Name, pk is CK3)) + if (!GetIsValidOTMattleHoOh(wcOT, pk.OriginalTrainerName, pk is CK3)) return false; } - else if (wcOT != pk.OT_Name) + else if (wcOT != pk.OriginalTrainerName) { return false; } @@ -273,7 +273,7 @@ public override bool IsMatchExact(PKM pk, EvoCriteria evo) if (Form != evo.Form && !FormInfo.IsFormChangeable(Species, Form, pk.Form, Context, pk.Context)) return false; - if (Language != -1 && Language != pk.Language) return false; + if (Language != 0 && Language != pk.Language) return false; if (Ball != pk.Ball) return false; if (FatefulEncounter != pk.FatefulEncounter && !IsEgg) return false; @@ -282,18 +282,18 @@ public override bool IsMatchExact(PKM pk, EvoCriteria evo) { if (hatchedEgg) return true; // defer egg specific checks to later. - if (Met_Level != pk.Met_Level) + if (MetLevel != pk.MetLevel) return false; - if (Location != pk.Met_Location) + if (Location != pk.MetLocation) return false; } else { if (pk.IsEgg) return false; - if (Level > pk.Met_Level) + if (Level > pk.MetLevel) return false; - if (pk.Egg_Location != LocationEdits.GetNoneLocation(pk.Context)) + if (pk.EggLocation != LocationEdits.GetNoneLocation(pk.Context)) return false; } return true; diff --git a/PKHeX.Core/MysteryGifts/WC6.cs b/PKHeX.Core/MysteryGifts/WC6.cs index ec2f3c694..a99b48172 100644 --- a/PKHeX.Core/MysteryGifts/WC6.cs +++ b/PKHeX.Core/MysteryGifts/WC6.cs @@ -6,26 +6,28 @@ namespace PKHeX.Core; /// /// Generation 6 Mystery Gift Template File /// -public sealed class WC6(byte[] Data) : DataMysteryGift(Data), IRibbonSetEvent3, IRibbonSetEvent4, ILangNick, IContestStats, INature, IMemoryOT, IRestrictVersion +public sealed class WC6(byte[] Data) : DataMysteryGift(Data), IRibbonSetEvent3, IRibbonSetEvent4, + ILangNick, IContestStats, INature, IMemoryOT, IRelearn, IRestrictVersion { public WC6() : this(new byte[Size]) { } public const int Size = 0x108; public const uint EonTicketConst = 0x225D73C2; - public override int Generation => 6; + public override byte Generation => 6; public override EntityContext Context => EntityContext.Gen6; public override bool FatefulEncounter => !IsLinkGift; // Link gifts do not set fateful encounter + public bool IsLinkGift => Location == Locations.LinkGift6; public int RestrictLanguage { get; set; } // None public byte RestrictVersion { get; set; } // Permit All - public bool CanBeReceivedByVersion(int v) + public bool CanBeReceivedByVersion(GameVersion version) { - if (v is < (int)GameVersion.X or > (int)GameVersion.OR) + if (version is < GameVersion.X or > GameVersion.OR) return false; if (RestrictVersion == 0) return true; // no data - var bitIndex = v - (int) GameVersion.X; + var bitIndex = (int)(version - GameVersion.X); var bit = 1 << bitIndex; return (RestrictVersion & bit) != 0; } @@ -151,9 +153,9 @@ private uint GetShinyXor() public override uint ID32 { get => ReadUInt32LittleEndian(Data.AsSpan(0x68)); set => WriteUInt32LittleEndian(Data.AsSpan(0x68), value); } public override ushort TID16 { get => ReadUInt16LittleEndian(Data.AsSpan(0x68)); set => WriteUInt16LittleEndian(Data.AsSpan(0x68), value); } public override ushort SID16 { get => ReadUInt16LittleEndian(Data.AsSpan(0x6A)); set => WriteUInt16LittleEndian(Data.AsSpan(0x6A), value); } - public int OriginGame { get => Data[0x6C]; set => Data[0x6C] = (byte)value; } + public byte OriginGame { get => Data[0x6C]; set => Data[0x6C] = value; } public uint EncryptionConstant { get => ReadUInt32LittleEndian(Data.AsSpan(0x70)); set => WriteUInt32LittleEndian(Data.AsSpan(0x70), value); } - public override int Ball { get => Data[0x76]; set => Data[0x76] = (byte)value; } + public override byte Ball { get => Data[0x76]; set => Data[0x76] = value; } public override int HeldItem { get => ReadUInt16LittleEndian(Data.AsSpan(0x78)); set => WriteUInt16LittleEndian(Data.AsSpan(0x78), (ushort)value); } public ushort Move1 { get => ReadUInt16LittleEndian(Data.AsSpan(0x7A)); set => WriteUInt16LittleEndian(Data.AsSpan(0x7A), value); } @@ -171,19 +173,19 @@ public string Nickname set => StringConverter6.SetString(Data.AsSpan(0x86, 0x1A), value, 12, StringConverterOption.ClearZero); } - public int Nature { get => (sbyte)Data[0xA0]; set => Data[0xA0] = (byte)value; } - public override int Gender { get => Data[0xA1]; set => Data[0xA1] = (byte)value; } + public Nature Nature { get => (Nature)Data[0xA0]; set => Data[0xA0] = (byte)value; } + public override byte Gender { get => Data[0xA1]; set => Data[0xA1] = value; } public override int AbilityType { get => Data[0xA2]; set => Data[0xA2] = (byte)value; } public ShinyType6 PIDType { get => (ShinyType6)Data[0xA3]; set => Data[0xA3] = (byte)value; } - public override int EggLocation { get => ReadUInt16LittleEndian(Data.AsSpan(0xA4)); set => WriteUInt16LittleEndian(Data.AsSpan(0xA4), (ushort)value); } - public int MetLocation { get => ReadUInt16LittleEndian(Data.AsSpan(0xA6)); set => WriteUInt16LittleEndian(Data.AsSpan(0xA6), (ushort)value); } + public override ushort EggLocation { get => ReadUInt16LittleEndian(Data.AsSpan(0xA4)); set => WriteUInt16LittleEndian(Data.AsSpan(0xA4), value); } + public override ushort Location { get => ReadUInt16LittleEndian(Data.AsSpan(0xA6)); set => WriteUInt16LittleEndian(Data.AsSpan(0xA6), value); } - public byte CNT_Cool { get => Data[0xA9]; set => Data[0xA9] = value; } - public byte CNT_Beauty { get => Data[0xAA]; set => Data[0xAA] = value; } - public byte CNT_Cute { get => Data[0xAB]; set => Data[0xAB] = value; } - public byte CNT_Smart { get => Data[0xAC]; set => Data[0xAC] = value; } - public byte CNT_Tough { get => Data[0xAD]; set => Data[0xAD] = value; } - public byte CNT_Sheen { get => Data[0xAE]; set => Data[0xAE] = value; } + public byte ContestCool { get => Data[0xA9]; set => Data[0xA9] = value; } + public byte ContestBeauty { get => Data[0xAA]; set => Data[0xAA] = value; } + public byte ContestCute { get => Data[0xAB]; set => Data[0xAB] = value; } + public byte ContestSmart { get => Data[0xAC]; set => Data[0xAC] = value; } + public byte ContestTough { get => Data[0xAD]; set => Data[0xAD] = value; } + public byte ContestSheen { get => Data[0xAE]; set => Data[0xAE] = value; } public int IV_HP { get => Data[0xAF]; set => Data[0xAF] = (byte)value; } public int IV_ATK { get => Data[0xB0]; set => Data[0xB0] = (byte)value; } @@ -192,9 +194,9 @@ public string Nickname public int IV_SPA { get => Data[0xB3]; set => Data[0xB3] = (byte)value; } public int IV_SPD { get => Data[0xB4]; set => Data[0xB4] = (byte)value; } - public int OTGender { get => Data[0xB5]; set => Data[0xB5] = (byte)value; } + public byte OTGender { get => Data[0xB5]; set => Data[0xB5] = value; } - public override string OT_Name + public override string OriginalTrainerName { get => StringConverter6.GetString(Data.AsSpan(0xB6, 0x1A)); set => StringConverter6.SetString(Data.AsSpan(0xB6, 0x1A), value, 12, StringConverterOption.ClearZero); @@ -209,10 +211,10 @@ public override string OT_Name public ushort RelearnMove3 { get => ReadUInt16LittleEndian(Data.AsSpan(0xDC)); set => WriteUInt16LittleEndian(Data.AsSpan(0xDC), value); } public ushort RelearnMove4 { get => ReadUInt16LittleEndian(Data.AsSpan(0xDE)); set => WriteUInt16LittleEndian(Data.AsSpan(0xDE), value); } - public byte OT_Intensity { get => Data[0xE0]; set => Data[0xE0] = value; } - public byte OT_Memory { get => Data[0xE1]; set => Data[0xE1] = value; } - public ushort OT_TextVar { get => ReadUInt16LittleEndian(Data.AsSpan(0xE2)); set => WriteUInt16LittleEndian(Data.AsSpan(0xE2), value); } - public byte OT_Feeling { get => Data[0xE4]; set => Data[0xE4] = value; } + public byte OriginalTrainerMemoryIntensity { get => Data[0xE0]; set => Data[0xE0] = value; } + public byte OriginalTrainerMemory { get => Data[0xE1]; set => Data[0xE1] = value; } + public ushort OriginalTrainerMemoryVariable { get => ReadUInt16LittleEndian(Data.AsSpan(0xE2)); set => WriteUInt16LittleEndian(Data.AsSpan(0xE2), value); } + public byte OriginalTrainerMemoryFeeling { get => Data[0xE4]; set => Data[0xE4] = value; } public int EV_HP { get => Data[0xE5]; set => Data[0xE5] = (byte)value; } public int EV_ATK { get => Data[0xE6]; set => Data[0xE6] = (byte)value; } @@ -241,7 +243,7 @@ public override string OT_Name public bool RIB1_7 { get => (RIB1 & (1 << 7)) == 1 << 7; set => RIB1 = (byte)((RIB1 & ~(1 << 7)) | (value ? 1 << 7 : 0)); } // Meta Accessible Properties - public override int[] IVs + public int[] IVs { get => [IV_HP, IV_ATK, IV_DEF, IV_SPE, IV_SPA, IV_SPD]; set @@ -266,7 +268,6 @@ public int[] EVs } public bool IsNicknamed => Nickname.Length > 0; - public override int Location { get => MetLocation; set => MetLocation = (ushort)value; } public override Moveset Moves { @@ -280,7 +281,7 @@ public override Moveset Moves } } - public override Moveset Relearn + public Moveset Relearn { get => new(RelearnMove1, RelearnMove2, RelearnMove3, RelearnMove4); set @@ -292,16 +293,13 @@ public override Moveset Relearn } } - public bool IsLinkGift => MetLocation == Locations.LinkGift6; - public override PK6 ConvertToPKM(ITrainerInfo tr, EncounterCriteria criteria) { if (!IsEntity) throw new ArgumentException(nameof(IsEntity)); var rnd = Util.Rand; - - int currentLevel = Level > 0 ? Level : (1 + rnd.Next(100)); + byte currentLevel = Level > 0 ? Level : (byte)(1 + rnd.Next(100)); var pi = PersonalTable.AO.GetFormEntry(Species, Form); PK6 pk = new() { @@ -309,29 +307,29 @@ public override PK6 ConvertToPKM(ITrainerInfo tr, EncounterCriteria criteria) HeldItem = HeldItem, TID16 = TID16, SID16 = SID16, - Met_Level = currentLevel, + MetLevel = currentLevel, Form = Form, - EncryptionConstant = EncryptionConstant != 0 ? EncryptionConstant : Util.Rand32(), - Version = OriginGame != 0 ? OriginGame : tr.Game, + EncryptionConstant = EncryptionConstant != 0 ? EncryptionConstant : rnd.Rand32(), + Version = OriginGame != 0 ? (GameVersion)OriginGame : tr.Version, Language = Language != 0 ? Language : tr.Language, Ball = Ball, Move1 = Move1, Move2 = Move2, Move3 = Move3, Move4 = Move4, RelearnMove1 = RelearnMove1, RelearnMove2 = RelearnMove2, RelearnMove3 = RelearnMove3, RelearnMove4 = RelearnMove4, - Met_Location = MetLocation, - Egg_Location = EggLocation, - CNT_Cool = CNT_Cool, - CNT_Beauty = CNT_Beauty, - CNT_Cute = CNT_Cute, - CNT_Smart = CNT_Smart, - CNT_Tough = CNT_Tough, - CNT_Sheen = CNT_Sheen, + MetLocation = Location, + EggLocation = EggLocation, + ContestCool = ContestCool, + ContestBeauty = ContestBeauty, + ContestCute = ContestCute, + ContestSmart = ContestSmart, + ContestTough = ContestTough, + ContestSheen = ContestSheen, - OT_Name = OT_Name.Length > 0 ? OT_Name : tr.OT, - OT_Gender = OTGender != 3 ? OTGender % 2 : tr.Gender, - HT_Name = OT_Name.Length > 0 ? tr.OT : string.Empty, - HT_Gender = OT_Name.Length > 0 ? tr.Gender : 0, - CurrentHandler = OT_Name.Length > 0 ? 1 : 0, + OriginalTrainerName = OriginalTrainerName.Length > 0 ? OriginalTrainerName : tr.OT, + OriginalTrainerGender = OTGender != 3 ? (byte)(OTGender % 2) : tr.Gender, + HandlingTrainerName = OriginalTrainerName.Length > 0 ? tr.OT : string.Empty, + HandlingTrainerGender = OriginalTrainerName.Length > 0 ? tr.Gender : default, + CurrentHandler = OriginalTrainerName.Length > 0 ? (byte)1 : (byte)0, EXP = Experience.GetEXP(Level, pi.EXPGrowth), @@ -354,11 +352,11 @@ public override PK6 ConvertToPKM(ITrainerInfo tr, EncounterCriteria criteria) RibbonChampionNational = RibbonChampionNational, RibbonChampionWorld = RibbonChampionWorld, - OT_Friendship = pi.BaseFriendship, - OT_Intensity = OT_Intensity, - OT_Memory = OT_Memory, - OT_TextVar = OT_TextVar, - OT_Feeling = OT_Feeling, + OriginalTrainerFriendship = pi.BaseFriendship, + OriginalTrainerMemoryIntensity = OriginalTrainerMemoryIntensity, + OriginalTrainerMemory = OriginalTrainerMemory, + OriginalTrainerMemoryVariable = OriginalTrainerMemoryVariable, + OriginalTrainerMemoryFeeling = OriginalTrainerMemoryFeeling, FatefulEncounter = FatefulEncounter, EV_HP = EV_HP, @@ -387,7 +385,7 @@ public override PK6 ConvertToPKM(ITrainerInfo tr, EncounterCriteria criteria) if ((tr.Generation > Generation && OriginGame == 0) || !CanBeReceivedByVersion(pk.Version)) { // give random valid game - do { pk.Version = (int)GameVersion.X + rnd.Next(4); } + do { pk.Version = GameVersion.X + (byte)rnd.Next(4); } while (!CanBeReceivedByVersion(pk.Version)); } @@ -395,18 +393,18 @@ public override PK6 ConvertToPKM(ITrainerInfo tr, EncounterCriteria criteria) { if (pk.CurrentHandler == 0) // OT { - pk.OT_Memory = 3; - pk.OT_TextVar = 9; - pk.OT_Intensity = 1; - pk.OT_Feeling = MemoryContext6.GetRandomFeeling6(pk.OT_Memory, 10); // 0-9 + pk.OriginalTrainerMemory = 3; + pk.OriginalTrainerMemoryVariable = 9; + pk.OriginalTrainerMemoryIntensity = 1; + pk.OriginalTrainerMemoryFeeling = MemoryContext6.GetRandomFeeling6(pk.OriginalTrainerMemory, 10); // 0-9 } else { - pk.HT_Memory = 3; - pk.HT_TextVar = 9; - pk.HT_Intensity = 1; - pk.HT_Feeling = MemoryContext6.GetRandomFeeling6(pk.HT_Memory, 10); // 0-9 - pk.HT_Friendship = pk.OT_Friendship; + pk.HandlingTrainerMemory = 3; + pk.HandlingTrainerMemoryVariable = 9; + pk.HandlingTrainerMemoryIntensity = 1; + pk.HandlingTrainerMemoryFeeling = MemoryContext6.GetRandomFeeling6(pk.HandlingTrainerMemory, 10); // 0-9 + pk.HandlingTrainerFriendship = pk.OriginalTrainerFriendship; } } @@ -434,7 +432,7 @@ private void SetEggMetData(PK6 pk) private void SetPINGA(PK6 pk, EncounterCriteria criteria) { var pi = pk.PersonalInfo; - pk.Nature = (int)criteria.GetNature((Nature)Nature); + pk.Nature = criteria.GetNature(Nature); pk.Gender = criteria.GetGender(Gender, pi); var av = GetAbilityIndex(criteria); pk.RefreshAbility(av); @@ -531,12 +529,12 @@ public override bool IsMatchExact(PKM pk, EvoCriteria evo) if (SID16 != pk.SID16) return false; if (TID16 != pk.TID16) return false; } - if (OTGender != pk.OT_Gender) return false; + if (OTGender != pk.OriginalTrainerGender) return false; } - if (!string.IsNullOrEmpty(OT_Name) && OT_Name != pk.OT_Name) return false; + if (!string.IsNullOrEmpty(OriginalTrainerName) && OriginalTrainerName != pk.OriginalTrainerName) return false; if (PIDType == ShinyType6.FixedValue && pk.PID != PID) return false; if (!Shiny.IsValid(pk)) return false; - if (OriginGame != 0 && OriginGame != pk.Version) return false; + if (OriginGame != 0 && (GameVersion)OriginGame != pk.Version) return false; if (EncryptionConstant != 0 && EncryptionConstant != pk.EncryptionConstant) return false; if (Language != 0 && Language != pk.Language) return false; } @@ -545,9 +543,9 @@ public override bool IsMatchExact(PKM pk, EvoCriteria evo) if (IsEgg) { - if (EggLocation != pk.Egg_Location) // traded + if (EggLocation != pk.EggLocation) // traded { - if (pk.Egg_Location != Locations.LinkTrade6) + if (pk.EggLocation != Locations.LinkTrade6) return false; } else if (PIDType == 0 && pk.IsShiny) @@ -561,13 +559,13 @@ public override bool IsMatchExact(PKM pk, EvoCriteria evo) else { if (!IsMatchEggLocation(pk)) return false; - if (MetLocation != pk.Met_Location) return false; + if (Location != pk.MetLocation) return false; } - if (Level != pk.Met_Level) return false; + if (Level != pk.MetLevel) return false; if (Ball != pk.Ball) return false; - if (OTGender < 3 && OTGender != pk.OT_Gender) return false; - if (Nature != -1 && pk.Nature != Nature) return false; + if (OTGender < 3 && OTGender != pk.OriginalTrainerGender) return false; + if ((sbyte)Nature != -1 && pk.Nature != Nature) return false; if (Gender != 3 && Gender != pk.Gender) return false; if (pk is IContestStatsReadOnly s && s.IsContestBelow(this)) @@ -587,20 +585,16 @@ protected override bool IsMatchDeferred(PKM pk) return Species != pk.Species; } - public override GameVersion Version + public override GameVersion Version => RestrictVersion switch { - get => RestrictVersion switch - { - 1 => GameVersion.X, - 2 => GameVersion.Y, - 3 => GameVersion.XY, - 4 => GameVersion.AS, - 8 => GameVersion.OR, - 12 => GameVersion.ORAS, - _ => GameVersion.Gen6, - }; - set { } - } + 1 => GameVersion.X, + 2 => GameVersion.Y, + 3 => GameVersion.XY, + 4 => GameVersion.AS, + 8 => GameVersion.OR, + 12 => GameVersion.ORAS, + _ => GameVersion.Gen6, + }; protected override bool IsMatchPartial(PKM pk) { @@ -610,7 +604,7 @@ protected override bool IsMatchPartial(PKM pk) { if (!IsEgg || pk.IsEgg) return true; - if (pk.Egg_Location != Locations.LinkTrade6) + if (pk.EggLocation != Locations.LinkTrade6) return true; } return false; diff --git a/PKHeX.Core/MysteryGifts/WC7.cs b/PKHeX.Core/MysteryGifts/WC7.cs index 25a7bcac9..68144f218 100644 --- a/PKHeX.Core/MysteryGifts/WC7.cs +++ b/PKHeX.Core/MysteryGifts/WC7.cs @@ -7,27 +7,27 @@ namespace PKHeX.Core; /// Generation 7 Mystery Gift Template File /// public sealed class WC7(byte[] Data) : DataMysteryGift(Data), IRibbonSetEvent3, IRibbonSetEvent4, ILangNick, - IContestStats, INature, IMemoryOT, IRestrictVersion + IContestStats, INature, IMemoryOT, IRelearn, IRestrictVersion { public WC7() : this(new byte[Size]) { } public const int Size = 0x108; - public override int Generation => 7; + public override byte Generation => 7; public override EntityContext Context => EntityContext.Gen7; public override bool FatefulEncounter => true; public int RestrictLanguage { get; set; } // None public byte RestrictVersion { get; set; } // Permit All - public bool CanBeReceivedByVersion(int v) + public bool CanBeReceivedByVersion(GameVersion version) { - if (v is < (int)GameVersion.SN or > (int)GameVersion.UM) + if (version is < GameVersion.SN or > GameVersion.UM) return false; if (CardID is 2046) - return v is (int)GameVersion.SN or (int)GameVersion.MN; + return version is GameVersion.SN or GameVersion.MN; if (RestrictVersion == 0) return true; // no data - var bitIndex = v - (int)GameVersion.SN; + var bitIndex = version - GameVersion.SN; var bit = 1 << bitIndex; return (RestrictVersion & bit) != 0; } @@ -184,10 +184,10 @@ public override ushort SID16 set => WriteUInt16LittleEndian(Data.AsSpan(0x6A), value); } - public int OriginGame + public byte OriginGame { get => Data[0x6C]; - set => Data[0x6C] = (byte)value; + set => Data[0x6C] = value; } public uint EncryptionConstant { @@ -195,10 +195,10 @@ public int OriginGame set => WriteUInt32LittleEndian(Data.AsSpan(0x70), value); } - public override int Ball + public override byte Ball { get => Data[0x76]; - set => Data[0x76] = (byte)value; } + set => Data[0x76] = value; } public override int HeldItem { @@ -220,20 +220,20 @@ public string Nickname set => StringConverter7.SetString(Data.AsSpan(0x86, 0x1A), value, 12, Language, StringConverterOption.ClearZero); } - public int Nature { get => (sbyte)Data[0xA0]; set => Data[0xA0] = (byte)value; } - public override int Gender { get => Data[0xA1]; set => Data[0xA1] = (byte)value; } + public Nature Nature { get => (Nature)Data[0xA0]; set => Data[0xA0] = (byte)value; } + public override byte Gender { get => Data[0xA1]; set => Data[0xA1] = value; } public override int AbilityType { get => Data[0xA2]; set => Data[0xA2] = (byte)value; } public ShinyType6 PIDType { get => (ShinyType6)Data[0xA3]; set => Data[0xA3] = (byte)value; } - public override int EggLocation { get => ReadUInt16LittleEndian(Data.AsSpan(0xA4)); set => WriteUInt16LittleEndian(Data.AsSpan(0xA4), (ushort)value); } - public int MetLocation { get => ReadUInt16LittleEndian(Data.AsSpan(0xA6)); set => WriteUInt16LittleEndian(Data.AsSpan(0xA6), (ushort)value); } - public int MetLevel { get => Data[0xA8]; set => Data[0xA8] = (byte)value; } + public override ushort EggLocation { get => ReadUInt16LittleEndian(Data.AsSpan(0xA4)); set => WriteUInt16LittleEndian(Data.AsSpan(0xA4), value); } + public override ushort Location { get => ReadUInt16LittleEndian(Data.AsSpan(0xA6)); set => WriteUInt16LittleEndian(Data.AsSpan(0xA6), value); } + public byte MetLevel { get => Data[0xA8]; set => Data[0xA8] = value; } - public byte CNT_Cool { get => Data[0xA9]; set => Data[0xA9] = value; } - public byte CNT_Beauty { get => Data[0xAA]; set => Data[0xAA] = value; } - public byte CNT_Cute { get => Data[0xAB]; set => Data[0xAB] = value; } - public byte CNT_Smart { get => Data[0xAC]; set => Data[0xAC] = value; } - public byte CNT_Tough { get => Data[0xAD]; set => Data[0xAD] = value; } - public byte CNT_Sheen { get => Data[0xAE]; set => Data[0xAE] = value; } + public byte ContestCool { get => Data[0xA9]; set => Data[0xA9] = value; } + public byte ContestBeauty { get => Data[0xAA]; set => Data[0xAA] = value; } + public byte ContestCute { get => Data[0xAB]; set => Data[0xAB] = value; } + public byte ContestSmart { get => Data[0xAC]; set => Data[0xAC] = value; } + public byte ContestTough { get => Data[0xAD]; set => Data[0xAD] = value; } + public byte ContestSheen { get => Data[0xAE]; set => Data[0xAE] = value; } public int IV_HP { get => Data[0xAF]; set => Data[0xAF] = (byte)value; } public int IV_ATK { get => Data[0xB0]; set => Data[0xB0] = (byte)value; } @@ -242,9 +242,9 @@ public string Nickname public int IV_SPA { get => Data[0xB3]; set => Data[0xB3] = (byte)value; } public int IV_SPD { get => Data[0xB4]; set => Data[0xB4] = (byte)value; } - public int OTGender { get => Data[0xB5]; set => Data[0xB5] = (byte)value; } + public byte OTGender { get => Data[0xB5]; set => Data[0xB5] = value; } - public override string OT_Name + public override string OriginalTrainerName { get => StringConverter7.GetString(Data.AsSpan(0xB6, 0x1A)); set => StringConverter7.SetString(Data.AsSpan(0xB6, 0x1A), value, 12, Language, StringConverterOption.ClearZero); @@ -260,10 +260,10 @@ public override string OT_Name public ushort RelearnMove3 { get => ReadUInt16LittleEndian(Data.AsSpan(0xDC)); set => WriteUInt16LittleEndian(Data.AsSpan(0xDC), value); } public ushort RelearnMove4 { get => ReadUInt16LittleEndian(Data.AsSpan(0xDE)); set => WriteUInt16LittleEndian(Data.AsSpan(0xDE), value); } - public byte OT_Intensity { get => Data[0xE0]; set => Data[0xE0] = value; } - public byte OT_Memory { get => Data[0xE1]; set => Data[0xE1] = value; } - public ushort OT_TextVar { get => ReadUInt16LittleEndian(Data.AsSpan(0xE2)); set => WriteUInt16LittleEndian(Data.AsSpan(0xE2), value); } - public byte OT_Feeling { get => Data[0xE4]; set => Data[0xE4] = value; } + public byte OriginalTrainerMemoryIntensity { get => Data[0xE0]; set => Data[0xE0] = value; } + public byte OriginalTrainerMemory { get => Data[0xE1]; set => Data[0xE1] = value; } + public ushort OriginalTrainerMemoryVariable { get => ReadUInt16LittleEndian(Data.AsSpan(0xE2)); set => WriteUInt16LittleEndian(Data.AsSpan(0xE2), value); } + public byte OriginalTrainerMemoryFeeling { get => Data[0xE4]; set => Data[0xE4] = value; } public int EV_HP { get => Data[0xE5]; set => Data[0xE5] = (byte)value; } public int EV_ATK { get => Data[0xE6]; set => Data[0xE6] = (byte)value; } @@ -292,7 +292,7 @@ public override string OT_Name public bool RIB1_7 { get => (RIB1 & (1 << 7)) == 1 << 7; set => RIB1 = (byte)((RIB1 & ~(1 << 7)) | (value ? 1 << 7 : 0)); } // Meta Accessible Properties - public override int[] IVs + public int[] IVs { get => [IV_HP, IV_ATK, IV_DEF, IV_SPE, IV_SPA, IV_SPD]; set @@ -329,7 +329,6 @@ public int[] EVs } public bool IsNicknamed => Nickname.Length > 0 || IsEgg; - public override int Location { get => MetLocation; set => MetLocation = (ushort)value; } public override Moveset Moves { @@ -343,7 +342,7 @@ public override Moveset Moves } } - public override Moveset Relearn + public Moveset Relearn { get => new(RelearnMove1, RelearnMove2, RelearnMove3, RelearnMove4); set @@ -361,11 +360,10 @@ public override PK7 ConvertToPKM(ITrainerInfo tr, EncounterCriteria criteria) throw new ArgumentException(nameof(IsEntity)); var rnd = Util.Rand; - - int currentLevel = Level > 0 ? Level : (1 + rnd.Next(100)); - int metLevel = MetLevel > 0 ? MetLevel : currentLevel; - var version = OriginGame != 0 ? OriginGame : (int)this.GetCompatibleVersion((GameVersion)tr.Game); - var language = Language != 0 ? Language : (int)Core.Language.GetSafeLanguage(Generation, (LanguageID)tr.Language, (GameVersion)version); + byte currentLevel = Level > 0 ? Level : (byte)(1 + rnd.Next(100)); + var metLevel = MetLevel > 0 ? MetLevel : currentLevel; + var version = OriginGame != 0 ? (GameVersion)OriginGame : this.GetCompatibleVersion(tr.Version); + var language = Language != 0 ? Language : (int)Core.Language.GetSafeLanguage(Generation, (LanguageID)tr.Language, version); var pi = PersonalTable.USUM.GetFormEntry(Species, Form); PK7 pk = new() @@ -374,7 +372,7 @@ public override PK7 ConvertToPKM(ITrainerInfo tr, EncounterCriteria criteria) HeldItem = HeldItem, TID16 = TID16, SID16 = SID16, - Met_Level = metLevel, + MetLevel = metLevel, Form = Form, EncryptionConstant = EncryptionConstant != 0 ? EncryptionConstant : Util.Rand32(), Version = version, @@ -383,20 +381,20 @@ public override PK7 ConvertToPKM(ITrainerInfo tr, EncounterCriteria criteria) Move1 = Move1, Move2 = Move2, Move3 = Move3, Move4 = Move4, RelearnMove1 = RelearnMove1, RelearnMove2 = RelearnMove2, RelearnMove3 = RelearnMove3, RelearnMove4 = RelearnMove4, - Met_Location = MetLocation, - Egg_Location = EggLocation, - CNT_Cool = CNT_Cool, - CNT_Beauty = CNT_Beauty, - CNT_Cute = CNT_Cute, - CNT_Smart = CNT_Smart, - CNT_Tough = CNT_Tough, - CNT_Sheen = CNT_Sheen, + MetLocation = Location, + EggLocation = EggLocation, + ContestCool = ContestCool, + ContestBeauty = ContestBeauty, + ContestCute = ContestCute, + ContestSmart = ContestSmart, + ContestTough = ContestTough, + ContestSheen = ContestSheen, - OT_Name = OT_Name.Length > 0 ? OT_Name : tr.OT, - OT_Gender = OTGender != 3 ? OTGender % 2 : tr.Gender, - HT_Name = OT_Name.Length > 0 ? tr.OT : string.Empty, - HT_Gender = OT_Name.Length > 0 ? tr.Gender : 0, - CurrentHandler = OT_Name.Length > 0 ? 1 : 0, + OriginalTrainerName = OriginalTrainerName.Length > 0 ? OriginalTrainerName : tr.OT, + OriginalTrainerGender = OTGender != 3 ? (byte)(OTGender % 2) : tr.Gender, + HandlingTrainerName = OriginalTrainerName.Length > 0 ? tr.OT : string.Empty, + HandlingTrainerGender = OriginalTrainerName.Length > 0 ? tr.Gender : default, + CurrentHandler = OriginalTrainerName.Length > 0 ? (byte)1 : (byte)0, EXP = Experience.GetEXP(currentLevel, pi.EXPGrowth), @@ -419,11 +417,11 @@ public override PK7 ConvertToPKM(ITrainerInfo tr, EncounterCriteria criteria) RibbonChampionNational = RibbonChampionNational, RibbonChampionWorld = RibbonChampionWorld, - OT_Friendship = pi.BaseFriendship, - OT_Intensity = OT_Intensity, - OT_Memory = OT_Memory, - OT_TextVar = OT_TextVar, - OT_Feeling = OT_Feeling, + OriginalTrainerFriendship = pi.BaseFriendship, + OriginalTrainerMemoryIntensity = OriginalTrainerMemoryIntensity, + OriginalTrainerMemory = OriginalTrainerMemory, + OriginalTrainerMemoryVariable = OriginalTrainerMemoryVariable, + OriginalTrainerMemoryFeeling = OriginalTrainerMemoryFeeling, FatefulEncounter = true, EV_HP = EV_HP, @@ -450,7 +448,7 @@ public override PK7 ConvertToPKM(ITrainerInfo tr, EncounterCriteria criteria) if ((tr.Generation > Generation && OriginGame == 0) || !CanBeReceivedByVersion(pk.Version)) { // give random valid game - do { pk.Version = (int)GameVersion.SN + rnd.Next(4); } + do { pk.Version = GameVersion.SN + (byte)rnd.Next(4); } while (!CanBeReceivedByVersion(pk.Version)); } @@ -486,7 +484,7 @@ private void SetEggMetData(PK7 pk) private void SetPINGA(PK7 pk, EncounterCriteria criteria) { var pi = pk.PersonalInfo; - pk.Nature = (int)criteria.GetNature((Nature)Nature); + pk.Nature = criteria.GetNature(Nature); pk.Gender = criteria.GetGender(Gender, pi); var av = GetAbilityIndex(criteria); pk.RefreshAbility(av); @@ -572,10 +570,10 @@ public override bool IsMatchExact(PKM pk, EvoCriteria evo) { if (SID16 != pk.SID16) return false; if (TID16 != pk.TID16) return false; - if (OTGender != pk.OT_Gender) return false; + if (OTGender != pk.OriginalTrainerGender) return false; } - if (!string.IsNullOrEmpty(OT_Name) && OT_Name != pk.OT_Name) return false; - if (OriginGame != 0 && OriginGame != pk.Version) return false; + if (!string.IsNullOrEmpty(OriginalTrainerName) && OriginalTrainerName != pk.OriginalTrainerName) return false; + if (OriginGame != 0 && (GameVersion)OriginGame != pk.Version) return false; if (EncryptionConstant != 0 && EncryptionConstant != pk.EncryptionConstant) return false; if (Language != 0 && Language != pk.Language) return false; } @@ -585,9 +583,9 @@ public override bool IsMatchExact(PKM pk, EvoCriteria evo) if (IsEgg) { - if (EggLocation != pk.Egg_Location) // traded + if (EggLocation != pk.EggLocation) // traded { - if (pk.Egg_Location != Locations.LinkTrade6) + if (pk.EggLocation != Locations.LinkTrade6) return false; } else if (PIDType == 0 && pk.IsShiny) @@ -602,13 +600,13 @@ public override bool IsMatchExact(PKM pk, EvoCriteria evo) { if (!Shiny.IsValid(pk)) return false; if (!IsMatchEggLocation(pk)) return false; - if (MetLocation != pk.Met_Location) return false; + if (Location != pk.MetLocation) return false; } - if (MetLevel != pk.Met_Level) return false; + if (MetLevel != pk.MetLevel) return false; if (Ball != pk.Ball) return false; - if (OTGender < 3 && OTGender != pk.OT_Gender) return false; - if (Nature != -1 && pk.Nature != Nature) return false; + if (OTGender < 3 && OTGender != pk.OriginalTrainerGender) return false; + if ((sbyte)Nature != -1 && pk.Nature != Nature) return false; if (Gender != 3 && Gender != pk.Gender) return false; if (pk is IContestStatsReadOnly s && s.IsContestBelow(this)) @@ -622,25 +620,16 @@ public override bool IsMatchExact(PKM pk, EvoCriteria evo) return PIDType != 0 || pk.PID == PID; } - public override GameVersion Version + public override GameVersion Version => CardID == 2046 ? GameVersion.SM : RestrictVersion switch { - get - { - if (CardID == 2046) - return GameVersion.SM; - return RestrictVersion switch - { - 1 => GameVersion.SN, - 2 => GameVersion.MN, - 3 => GameVersion.SM, - 4 => GameVersion.US, - 8 => GameVersion.UM, - 12 => GameVersion.USUM, - _ => GameVersion.Gen7, - }; - } - set { } - } + 1 => GameVersion.SN, + 2 => GameVersion.MN, + 3 => GameVersion.SM, + 4 => GameVersion.US, + 8 => GameVersion.UM, + 12 => GameVersion.USUM, + _ => GameVersion.Gen7, + }; protected override bool IsMatchDeferred(PKM pk) => false; @@ -652,7 +641,7 @@ protected override bool IsMatchPartial(PKM pk) { if (!IsEgg || pk.IsEgg) return true; - if (pk.Egg_Location != Locations.LinkTrade6) + if (pk.EggLocation != Locations.LinkTrade6) return true; } return false; diff --git a/PKHeX.Core/MysteryGifts/WC8.cs b/PKHeX.Core/MysteryGifts/WC8.cs index a8bbf735d..06ef586da 100644 --- a/PKHeX.Core/MysteryGifts/WC8.cs +++ b/PKHeX.Core/MysteryGifts/WC8.cs @@ -7,7 +7,7 @@ namespace PKHeX.Core; /// /// Generation 8 Mystery Gift Template File /// -public sealed class WC8(byte[] Data) : DataMysteryGift(Data), ILangNick, INature, IGigantamax, IDynamaxLevel, IRibbonIndex, IMemoryOT, ILangNicknamedTemplate, IEncounterServerDate, IRestrictVersion, +public sealed class WC8(byte[] Data) : DataMysteryGift(Data), ILangNick, INature, IGigantamax, IDynamaxLevel, IRibbonIndex, IMemoryOT, ILangNicknamedTemplate, IRelearn, IEncounterServerDate, IRestrictVersion, IRibbonSetEvent3, IRibbonSetEvent4, IRibbonSetCommon3, IRibbonSetCommon4, IRibbonSetCommon6, IRibbonSetCommon7, IRibbonSetCommon8, IRibbonSetMark8 { public WC8() : this(new byte[Size]) { } @@ -15,7 +15,7 @@ public sealed class WC8(byte[] Data) : DataMysteryGift(Data), ILangNick, INature public const int Size = 0x2D0; public const int CardStart = 0x0; - public override int Generation => 8; + public override byte Generation => 8; public override EntityContext Context => EntityContext.Gen8; public override bool FatefulEncounter => true; @@ -30,12 +30,12 @@ public enum GiftType : byte public byte RestrictVersion { get => Data[0xE]; set => Data[0xE] = value; } - public bool CanBeReceivedByVersion(int v) => RestrictVersion switch + public bool CanBeReceivedByVersion(GameVersion version) => RestrictVersion switch { 0 when !IsEntity => true, // Whatever, essentially unrestricted for SW/SH receipt. No Entity gifts are 0. - 1 => v is (int)GameVersion.SW, - 2 => v is (int)GameVersion.SH, - 3 => v is (int)GameVersion.SW or (int)GameVersion.SH, + 1 => version is GameVersion.SW, + 2 => version is GameVersion.SH, + 3 => version is GameVersion.SW or GameVersion.SH, _ => throw new ArgumentOutOfRangeException(nameof(RestrictVersion), RestrictVersion, null), }; @@ -152,13 +152,13 @@ public uint PID } // Nicknames, OT Names 0x30 - 0x228 - public override int EggLocation { get => ReadUInt16LittleEndian(Data.AsSpan(CardStart + 0x228)); set => WriteUInt16LittleEndian(Data.AsSpan(CardStart + 0x228), (ushort)value); } - public int MetLocation { get => ReadUInt16LittleEndian(Data.AsSpan(CardStart + 0x22A)); set => WriteUInt16LittleEndian(Data.AsSpan(CardStart + 0x22A), (ushort)value); } + public override ushort EggLocation { get => ReadUInt16LittleEndian(Data.AsSpan(CardStart + 0x228)); set => WriteUInt16LittleEndian(Data.AsSpan(CardStart + 0x228), value); } + public override ushort Location { get => ReadUInt16LittleEndian(Data.AsSpan(CardStart + 0x22A)); set => WriteUInt16LittleEndian(Data.AsSpan(CardStart + 0x22A), value); } - public override int Ball + public override byte Ball { - get => ReadUInt16LittleEndian(Data.AsSpan(CardStart + 0x22C)); - set => WriteUInt16LittleEndian(Data.AsSpan(CardStart + 0x22C), (ushort)value); + get => (byte)ReadUInt16LittleEndian(Data.AsSpan(CardStart + 0x22C)); + set => WriteUInt16LittleEndian(Data.AsSpan(CardStart + 0x22C), value); } public override int HeldItem @@ -178,15 +178,15 @@ public override int HeldItem public override ushort Species { get => ReadUInt16LittleEndian(Data.AsSpan(CardStart + 0x240)); set => WriteUInt16LittleEndian(Data.AsSpan(CardStart + 0x240), value); } public override byte Form { get => Data[CardStart + 0x242]; set => Data[CardStart + 0x242] = value; } - public override int Gender { get => Data[CardStart + 0x243]; set => Data[CardStart + 0x243] = (byte)value; } + public override byte Gender { get => Data[CardStart + 0x243]; set => Data[CardStart + 0x243] = value; } public override byte Level { get => Data[CardStart + 0x244]; set => Data[CardStart + 0x244] = value; } public override bool IsEgg { get => Data[CardStart + 0x245] == 1; set => Data[CardStart + 0x245] = value ? (byte)1 : (byte)0; } - public int Nature { get => (sbyte)Data[CardStart + 0x246]; set => Data[CardStart + 0x246] = (byte)value; } + public Nature Nature { get => (Nature)Data[CardStart + 0x246]; set => Data[CardStart + 0x246] = (byte)value; } public override int AbilityType { get => Data[CardStart + 0x247]; set => Data[CardStart + 0x247] = (byte)value; } public ShinyType8 PIDType { get => (ShinyType8)Data[CardStart + 0x248]; set => Data[CardStart + 0x248] = (byte)value; } - public int MetLevel { get => Data[CardStart + 0x249]; set => Data[CardStart + 0x249] = (byte)value; } + public byte MetLevel { get => Data[CardStart + 0x249]; set => Data[CardStart + 0x249] = value; } public byte DynamaxLevel { get => Data[CardStart + 0x24A]; set => Data[CardStart + 0x24A] = value; } public bool CanGigantamax { get => Data[CardStart + 0x24B] != 0; set => Data[CardStart + 0x24B] = value ? (byte)1 : (byte)0; } @@ -232,7 +232,7 @@ public void SetRibbonAtIndex(int byteIndex, byte ribbonIndex) public int IV_SPA { get => Data[CardStart + 0x270]; set => Data[CardStart + 0x270] = (byte)value; } public int IV_SPD { get => Data[CardStart + 0x271]; set => Data[CardStart + 0x271] = (byte)value; } - public int OTGender { get => Data[CardStart + 0x272]; set => Data[CardStart + 0x272] = (byte)value; } + public byte OTGender { get => Data[CardStart + 0x272]; set => Data[CardStart + 0x272] = value; } public int EV_HP { get => Data[CardStart + 0x273]; set => Data[CardStart + 0x273] = (byte)value; } public int EV_ATK { get => Data[CardStart + 0x274]; set => Data[CardStart + 0x274] = (byte)value; } @@ -241,15 +241,15 @@ public void SetRibbonAtIndex(int byteIndex, byte ribbonIndex) public int EV_SPA { get => Data[CardStart + 0x277]; set => Data[CardStart + 0x277] = (byte)value; } public int EV_SPD { get => Data[CardStart + 0x278]; set => Data[CardStart + 0x278] = (byte)value; } - public byte OT_Intensity { get => Data[CardStart + 0x279]; set => Data[CardStart + 0x279] = value; } - public byte OT_Memory { get => Data[CardStart + 0x27A]; set => Data[CardStart + 0x27A] = value; } - public byte OT_Feeling { get => Data[CardStart + 0x27B]; set => Data[CardStart + 0x27B] = value; } - public ushort OT_TextVar { get => ReadUInt16LittleEndian(Data.AsSpan(CardStart + 0x27C)); set => WriteUInt16LittleEndian(Data.AsSpan(CardStart + 0x27C), value); } + public byte OriginalTrainerMemoryIntensity { get => Data[CardStart + 0x279]; set => Data[CardStart + 0x279] = value; } + public byte OriginalTrainerMemory { get => Data[CardStart + 0x27A]; set => Data[CardStart + 0x27A] = value; } + public byte OriginalTrainerMemoryFeeling { get => Data[CardStart + 0x27B]; set => Data[CardStart + 0x27B] = value; } + public ushort OriginalTrainerMemoryVariable { get => ReadUInt16LittleEndian(Data.AsSpan(CardStart + 0x27C)); set => WriteUInt16LittleEndian(Data.AsSpan(CardStart + 0x27C), value); } public ushort Checksum => ReadUInt16LittleEndian(Data.AsSpan(0x2CC)); // Meta Accessible Properties - public override int[] IVs + public int[] IVs { get => [IV_HP, IV_ATK, IV_DEF, IV_SPE, IV_SPA, IV_SPD]; set @@ -330,8 +330,6 @@ private static int GetLanguageIndex(int language) return lang < LanguageID.UNUSED_6 ? language - 1 : language - 2; } - public override int Location { get => MetLocation; set => MetLocation = (ushort)value; } - public override Moveset Moves { get => new(Move1, Move2, Move3, Move4); @@ -344,7 +342,7 @@ public override Moveset Moves } } - public override Moveset Relearn + public Moveset Relearn { get => new(RelearnMove1, RelearnMove2, RelearnMove3, RelearnMove4); set @@ -356,7 +354,7 @@ public override Moveset Relearn } } - public override string OT_Name + public override string OriginalTrainerName { get => GetOT(Language); set @@ -394,23 +392,20 @@ private static int GetOTOffset(int language) public bool CanHandleOT(int language) => !GetHasOT(language); - public override GameVersion Version - { - get => OriginGame != 0 ? (GameVersion)OriginGame : GameVersion.SWSH; - set { } - } + public override GameVersion Version => OriginGame != 0 ? (GameVersion)OriginGame : GameVersion.SWSH; public override PK8 ConvertToPKM(ITrainerInfo tr, EncounterCriteria criteria) { if (!IsEntity) throw new ArgumentException(nameof(IsEntity)); - int currentLevel = Level > 0 ? Level : 1 + Util.Rand.Next(100); - int metLevel = MetLevel > 0 ? MetLevel : currentLevel; + var rnd = Util.Rand; + byte currentLevel = Level > 0 ? Level : (byte)(1 + rnd.Next(100)); + var metLevel = MetLevel > 0 ? MetLevel : currentLevel; var pi = PersonalTable.SWSH.GetFormEntry(Species, Form); var language = tr.Language; bool hasOT = GetHasOT(language); - var version = OriginGame != 0 ? OriginGame : (int)this.GetCompatibleVersion((GameVersion)tr.Game); + var version = OriginGame != 0 ? (GameVersion)OriginGame : this.GetCompatibleVersion(tr.Version); var pk = new PK8 { @@ -420,8 +415,8 @@ public override PK8 ConvertToPKM(ITrainerInfo tr, EncounterCriteria criteria) Species = Species, Form = Form, CurrentLevel = currentLevel, - Ball = Ball != 0 ? Ball : 4, // Default is Pokeball - Met_Level = metLevel, + Ball = Ball != 0 ? Ball : (byte)4, // Default is Pokeball + MetLevel = metLevel, HeldItem = HeldItem, EXP = Experience.GetEXP(currentLevel, pi.EXPGrowth), @@ -437,18 +432,18 @@ public override PK8 ConvertToPKM(ITrainerInfo tr, EncounterCriteria criteria) Version = version, - OT_Name = hasOT ? GetOT(language) : tr.OT, - OT_Gender = OTGender < 2 ? OTGender : tr.Gender, - HT_Name = hasOT ? tr.OT : string.Empty, - HT_Gender = hasOT ? tr.Gender : 0, - HT_Language = (byte)(hasOT ? language : 0), - CurrentHandler = hasOT ? 1 : 0, - OT_Friendship = pi.BaseFriendship, + OriginalTrainerName = hasOT ? GetOT(language) : tr.OT, + OriginalTrainerGender = OTGender < 2 ? OTGender : tr.Gender, + HandlingTrainerName = hasOT ? tr.OT : string.Empty, + HandlingTrainerGender = hasOT ? tr.Gender : default, + HandlingTrainerLanguage = (byte)(hasOT ? language : default), + CurrentHandler = hasOT ? (byte)1 : (byte)0, + OriginalTrainerFriendship = pi.BaseFriendship, - OT_Intensity = OT_Intensity, - OT_Memory = OT_Memory, - OT_TextVar = OT_TextVar, - OT_Feeling = OT_Feeling, + OriginalTrainerMemoryIntensity = OriginalTrainerMemoryIntensity, + OriginalTrainerMemory = OriginalTrainerMemory, + OriginalTrainerMemoryVariable = OriginalTrainerMemoryVariable, + OriginalTrainerMemoryFeeling = OriginalTrainerMemoryFeeling, FatefulEncounter = true, EV_HP = EV_HP, @@ -461,16 +456,15 @@ public override PK8 ConvertToPKM(ITrainerInfo tr, EncounterCriteria criteria) CanGigantamax = CanGigantamax, DynamaxLevel = DynamaxLevel, - Met_Location = MetLocation, - Egg_Location = EggLocation, + MetLocation = Location, + EggLocation = EggLocation, }; pk.SetMaximumPPCurrent(); if ((tr.Generation > Generation && OriginGame == 0) || !CanBeReceivedByVersion(pk.Version)) { // give random valid game - var rnd = Util.Rand; - do { pk.Version = (int)GameVersion.SW + rnd.Next(2); } + do { pk.Version = GameVersion.SW + (byte)rnd.Next(2); } while (!CanBeReceivedByVersion(pk.Version)); } @@ -518,8 +512,8 @@ public override PK8 ConvertToPKM(ITrainerInfo tr, EncounterCriteria criteria) if (!IsHOMEGiftOld(date)) { - pk.HeightScalar = PokeSizeUtil.GetRandomScalar(); - pk.WeightScalar = PokeSizeUtil.GetRandomScalar(); + pk.HeightScalar = PokeSizeUtil.GetRandomScalar(rnd); + pk.WeightScalar = PokeSizeUtil.GetRandomScalar(rnd); } pk.ResetPartyStats(); @@ -556,7 +550,7 @@ private void SetEggMetData(PK8 pk) private void SetPINGA(PK8 pk, EncounterCriteria criteria) { var pi = pk.PersonalInfo; - pk.Nature = pk.StatNature = (int)criteria.GetNature(Nature == -1 ? Core.Nature.Random : (Nature)Nature); + pk.Nature = pk.StatNature = criteria.GetNature((sbyte)Nature == -1 ? Nature.Random : Nature); pk.Gender = criteria.GetGender(Gender, pi); var av = GetAbilityIndex(criteria); pk.RefreshAbility(av); @@ -654,15 +648,15 @@ public override bool IsMatchExact(PKM pk, EvoCriteria evo) { if (SID16 != pk.SID16) return false; if (TID16 != pk.TID16) return false; - if (OTGender != pk.OT_Gender) return false; + if (OTGender != pk.OriginalTrainerGender) return false; } if (!CanBeAnyLanguage() && !CanHaveLanguage(pk.Language)) return false; var OT = GetOT(pk.Language); // May not be guaranteed to work. - if (!string.IsNullOrEmpty(OT) && OT != pk.OT_Name) return false; - if (OriginGame != 0 && OriginGame != pk.Version) return false; + if (!string.IsNullOrEmpty(OT) && OT != pk.OriginalTrainerName) return false; + if (OriginGame != 0 && (GameVersion)OriginGame != pk.Version) return false; if (EncryptionConstant != 0) { if (EncryptionConstant != pk.EncryptionConstant) @@ -698,9 +692,9 @@ public override bool IsMatchExact(PKM pk, EvoCriteria evo) shinyType = FixedShinyType(); if (IsEgg) { - if (EggLocation != pk.Egg_Location) // traded + if (EggLocation != pk.EggLocation) // traded { - if (pk.Egg_Location != Locations.LinkTrade6) + if (pk.EggLocation != Locations.LinkTrade6) return false; if (PIDType == ShinyType8.Random && pk is { IsShiny: true, ShinyXor: > 1 }) return false; // shiny traded egg will always have xor0/1. @@ -717,13 +711,13 @@ public override bool IsMatchExact(PKM pk, EvoCriteria evo) { if (!shinyType.IsValid(pk)) return false; if (!IsMatchEggLocation(pk)) return false; - if (MetLocation != pk.Met_Location) return false; + if (Location != pk.MetLocation) return false; } - if (MetLevel != 0 && MetLevel != pk.Met_Level) return false; + if (MetLevel != 0 && MetLevel != pk.MetLevel) return false; if ((Ball == 0 ? 4 : Ball) != pk.Ball) return false; - if (OTGender < 2 && OTGender != pk.OT_Gender) return false; - if (Nature != -1 && pk.Nature != Nature) return false; + if (OTGender < 2 && OTGender != pk.OriginalTrainerGender) return false; + if ((sbyte)Nature != -1 && pk.Nature != Nature) return false; if (Gender != 3 && Gender != pk.Gender) return false; if (pk is PK8 and IGigantamax g && g.CanGigantamax != CanGigantamax && !Gigantamax.CanToggle(pk.Species, pk.Form, Species, Form)) diff --git a/PKHeX.Core/MysteryGifts/WC9.cs b/PKHeX.Core/MysteryGifts/WC9.cs index 3cca56a1b..1e0e3e7a5 100644 --- a/PKHeX.Core/MysteryGifts/WC9.cs +++ b/PKHeX.Core/MysteryGifts/WC9.cs @@ -8,7 +8,7 @@ namespace PKHeX.Core; /// Generation 9 Mystery Gift Template File /// public sealed class WC9(byte[] Data) : DataMysteryGift(Data), ILangNick, INature, ITeraType, IRibbonIndex, IMemoryOT, - ILangNicknamedTemplate, IEncounterServerDate, + ILangNicknamedTemplate, IEncounterServerDate, IRelearn, IRibbonSetEvent3, IRibbonSetEvent4, IRibbonSetCommon3, IRibbonSetCommon4, IRibbonSetCommon6, IRibbonSetCommon7, IRibbonSetCommon8, IRibbonSetMark8, IRibbonSetCommon9, IRibbonSetMark9, IEncounterMarkExtra { @@ -17,7 +17,7 @@ public sealed class WC9(byte[] Data) : DataMysteryGift(Data), ILangNick, INature public const int Size = 0x2C8; public const int CardStart = 0x0; - public override int Generation => 9; + public override byte Generation => 9; public override EntityContext Context => EntityContext.Gen9; public override bool FatefulEncounter => true; @@ -35,9 +35,9 @@ public enum GiftType : byte public bool CanBeReceivedByVersion(PKM pk) => RestrictVersion switch { 0 when !IsEntity => true, // Whatever, essentially unrestricted for SL/VL receipt. No Entity gifts are 0. - 1 => pk.Version is (int)GameVersion.SL || pk.Met_Location == LocationsHOME.SWSL, - 2 => pk.Version is (int)GameVersion.VL || pk.Met_Location == LocationsHOME.SHVL, - 3 => pk.Version is (int)GameVersion.SL or (int)GameVersion.VL || pk.Met_Location is LocationsHOME.SWSL or LocationsHOME.SHVL, + 1 => pk.Version is GameVersion.SL || pk.MetLocation == LocationsHOME.SWSL, + 2 => pk.Version is GameVersion.VL || pk.MetLocation == LocationsHOME.SHVL, + 3 => pk.Version is GameVersion.SL or GameVersion.VL || pk.MetLocation is LocationsHOME.SWSL or LocationsHOME.SHVL, _ => throw new ArgumentOutOfRangeException(nameof(RestrictVersion), RestrictVersion, null), }; @@ -169,13 +169,13 @@ public uint PID } // Nicknames, OT Names 0x28 - 0x220 - public override int EggLocation { get => ReadUInt16LittleEndian(Data.AsSpan(CardStart + 0x220)); set => WriteUInt16LittleEndian(Data.AsSpan(CardStart + 0x220), (ushort)value); } - public int MetLocation { get => ReadUInt16LittleEndian(Data.AsSpan(CardStart + 0x222)); set => WriteUInt16LittleEndian(Data.AsSpan(CardStart + 0x222), (ushort)value); } + public override ushort EggLocation { get => ReadUInt16LittleEndian(Data.AsSpan(CardStart + 0x220)); set => WriteUInt16LittleEndian(Data.AsSpan(CardStart + 0x220), value); } + public override ushort Location { get => ReadUInt16LittleEndian(Data.AsSpan(CardStart + 0x222)); set => WriteUInt16LittleEndian(Data.AsSpan(CardStart + 0x222), value); } - public override int Ball + public override byte Ball { - get => ReadUInt16LittleEndian(Data.AsSpan(CardStart + 0x224)); - set => WriteUInt16LittleEndian(Data.AsSpan(CardStart + 0x224), (ushort)value); + get => (byte)ReadUInt16LittleEndian(Data.AsSpan(CardStart + 0x224)); + set => WriteUInt16LittleEndian(Data.AsSpan(CardStart + 0x224), value); } public override int HeldItem @@ -195,15 +195,15 @@ public override int HeldItem public override ushort Species { get => SpeciesConverter.GetNational9(ReadUInt16LittleEndian(Data.AsSpan(CardStart + 0x238))); set => WriteUInt16LittleEndian(Data.AsSpan(CardStart + 0x238), SpeciesConverter.GetInternal9(value)); } public override byte Form { get => Data[CardStart + 0x23A]; set => Data[CardStart + 0x23A] = value; } - public override int Gender { get => Data[CardStart + 0x23B]; set => Data[CardStart + 0x23B] = (byte)value; } + public override byte Gender { get => Data[CardStart + 0x23B]; set => Data[CardStart + 0x23B] = value; } public override byte Level { get => Data[CardStart + 0x23C]; set => Data[CardStart + 0x23C] = value; } public override bool IsEgg { get => Data[CardStart + 0x23D] == 1; set => Data[CardStart + 0x23D] = value ? (byte)1 : (byte)0; } - public int Nature { get => (sbyte)Data[CardStart + 0x23E]; set => Data[CardStart + 0x23E] = (byte)value; } + public Nature Nature { get => (Nature)Data[CardStart + 0x23E]; set => Data[CardStart + 0x23E] = (byte)value; } public override int AbilityType { get => Data[CardStart + 0x23F]; set => Data[CardStart + 0x23F] = (byte)value; } public ShinyType8 PIDType { get => (ShinyType8)Data[CardStart + 0x240]; set => Data[CardStart + 0x240] = (byte)value; } - public int MetLevel { get => Data[CardStart + 0x241]; set => Data[CardStart + 0x241] = (byte)value; } + public byte MetLevel { get => Data[CardStart + 0x241]; set => Data[CardStart + 0x241] = value; } public MoveType TeraTypeOriginal { get => (MoveType)Data[CardStart + 0x242]; set => Data[CardStart + 0x242] = (byte)value; } public MoveType TeraTypeOverride { @@ -267,7 +267,7 @@ public void SetRibbonAtIndex(int byteIndex, byte ribbonIndex) public int IV_SPA { get => Data[CardStart + 0x26C]; set => Data[CardStart + 0x26C] = (byte)value; } public int IV_SPD { get => Data[CardStart + 0x26D]; set => Data[CardStart + 0x26D] = (byte)value; } - public int OTGender { get => Data[CardStart + 0x26E]; set => Data[CardStart + 0x26E] = (byte)value; } + public byte OTGender { get => Data[CardStart + 0x26E]; set => Data[CardStart + 0x26E] = value; } public int EV_HP { get => Data[CardStart + 0x26F]; set => Data[CardStart + 0x26F] = (byte)value; } public int EV_ATK { get => Data[CardStart + 0x270]; set => Data[CardStart + 0x270] = (byte)value; } @@ -276,15 +276,15 @@ public void SetRibbonAtIndex(int byteIndex, byte ribbonIndex) public int EV_SPA { get => Data[CardStart + 0x273]; set => Data[CardStart + 0x273] = (byte)value; } public int EV_SPD { get => Data[CardStart + 0x274]; set => Data[CardStart + 0x274] = (byte)value; } - public byte OT_Intensity { get => Data[CardStart + 0x275]; set => Data[CardStart + 0x275] = value; } - public byte OT_Memory { get => Data[CardStart + 0x276]; set => Data[CardStart + 0x276] = value; } - public byte OT_Feeling { get => Data[CardStart + 0x277]; set => Data[CardStart + 0x277] = value; } - public ushort OT_TextVar { get => ReadUInt16LittleEndian(Data.AsSpan(CardStart + 0x278)); set => WriteUInt16LittleEndian(Data.AsSpan(CardStart + 0x278), value); } + public byte OriginalTrainerMemoryIntensity { get => Data[CardStart + 0x275]; set => Data[CardStart + 0x275] = value; } + public byte OriginalTrainerMemory { get => Data[CardStart + 0x276]; set => Data[CardStart + 0x276] = value; } + public byte OriginalTrainerMemoryFeeling { get => Data[CardStart + 0x277]; set => Data[CardStart + 0x277] = value; } + public ushort OriginalTrainerMemoryVariable { get => ReadUInt16LittleEndian(Data.AsSpan(CardStart + 0x278)); set => WriteUInt16LittleEndian(Data.AsSpan(CardStart + 0x278), value); } public ushort Checksum => ReadUInt16LittleEndian(Data.AsSpan(0x2C4)); // Meta Accessible Properties - public override int[] IVs + public int[] IVs { get => [IV_HP, IV_ATK, IV_DEF, IV_SPE, IV_SPA, IV_SPD]; set @@ -365,8 +365,6 @@ private static int GetLanguageIndex(int language) return lang < LanguageID.UNUSED_6 ? language - 1 : language - 2; } - public override int Location { get => MetLocation; set => MetLocation = (ushort)value; } - public override Moveset Moves { get => new(Move1, Move2, Move3, Move4); @@ -379,7 +377,7 @@ public override Moveset Moves } } - public override Moveset Relearn + public Moveset Relearn { get => new(RelearnMove1, RelearnMove2, RelearnMove3, RelearnMove4); set @@ -391,7 +389,7 @@ public override Moveset Relearn } } - public override string OT_Name + public override string OriginalTrainerName { get => GetOT(Language); set @@ -429,11 +427,7 @@ private static int GetOTOffset(int language) public bool CanHandleOT(int language) => !GetHasOT(language); - public override GameVersion Version - { - get => OriginGame != 0 ? (GameVersion)OriginGame : GameVersion.SV; - set { } - } + public override GameVersion Version => OriginGame != 0 ? (GameVersion)OriginGame : GameVersion.SV; public override PK9 ConvertToPKM(ITrainerInfo tr, EncounterCriteria criteria) { @@ -441,12 +435,12 @@ public override PK9 ConvertToPKM(ITrainerInfo tr, EncounterCriteria criteria) throw new ArgumentException(nameof(IsEntity)); var rnd = Util.Rand; - int currentLevel = Level > 0 ? Level : 1 + rnd.Next(100); - int metLevel = MetLevel > 0 ? MetLevel : currentLevel; + byte currentLevel = Level > 0 ? Level : (byte)(1 + rnd.Next(100)); + var metLevel = MetLevel > 0 ? MetLevel : currentLevel; var pi = PersonalTable.SV.GetFormEntry(Species, Form); var language = tr.Language; bool hasOT = GetHasOT(language); - var version = OriginGame != 0 ? OriginGame : (int)this.GetCompatibleVersion((GameVersion)tr.Game); + var version = OriginGame != 0 ? (GameVersion)OriginGame : this.GetCompatibleVersion(tr.Version); var pk = new PK9 { @@ -455,8 +449,8 @@ public override PK9 ConvertToPKM(ITrainerInfo tr, EncounterCriteria criteria) Species = Species, Form = Form, CurrentLevel = currentLevel, - Ball = Ball != 0 ? Ball : 4, // Default is Pokeball - Met_Level = metLevel, + Ball = Ball != 0 ? Ball : (byte)4, // Default is Poké Ball + MetLevel = metLevel, HeldItem = HeldItem, EXP = Experience.GetEXP(currentLevel, pi.EXPGrowth), @@ -472,18 +466,18 @@ public override PK9 ConvertToPKM(ITrainerInfo tr, EncounterCriteria criteria) Version = version, - OT_Name = hasOT ? GetOT(language) : tr.OT, - OT_Gender = OTGender < 2 ? OTGender : tr.Gender, - HT_Name = hasOT ? tr.OT : string.Empty, - HT_Gender = hasOT ? tr.Gender : 0, - HT_Language = (byte)(hasOT ? language : 0), - CurrentHandler = hasOT ? 1 : 0, - OT_Friendship = pi.BaseFriendship, + OriginalTrainerName = hasOT ? GetOT(language) : tr.OT, + OriginalTrainerGender = OTGender < 2 ? OTGender : tr.Gender, + HandlingTrainerName = hasOT ? tr.OT : string.Empty, + HandlingTrainerGender = hasOT ? tr.Gender : default, + HandlingTrainerLanguage = (byte)(hasOT ? language : 0), + CurrentHandler = hasOT ? (byte)1 : (byte)0, + OriginalTrainerFriendship = pi.BaseFriendship, - OT_Intensity = OT_Intensity, - OT_Memory = OT_Memory, - OT_TextVar = OT_TextVar, - OT_Feeling = OT_Feeling, + OriginalTrainerMemoryIntensity = OriginalTrainerMemoryIntensity, + OriginalTrainerMemory = OriginalTrainerMemory, + OriginalTrainerMemoryVariable = OriginalTrainerMemoryVariable, + OriginalTrainerMemoryFeeling = OriginalTrainerMemoryFeeling, FatefulEncounter = true, EV_HP = EV_HP, @@ -493,8 +487,8 @@ public override PK9 ConvertToPKM(ITrainerInfo tr, EncounterCriteria criteria) EV_SPA = EV_SPA, EV_SPD = EV_SPD, - Met_Location = MetLocation, - Egg_Location = EggLocation, + MetLocation = Location, + EggLocation = EggLocation, TeraTypeOriginal = TeraTypeOriginal, //TeraTypeOverride = TeraTypeOverride, }; @@ -504,7 +498,7 @@ public override PK9 ConvertToPKM(ITrainerInfo tr, EncounterCriteria criteria) if ((tr.Generation > Generation && OriginGame == 0) || !CanBeReceivedByVersion(pk)) { // give random valid game - do { pk.Version = (int)GameVersion.SL + rnd.Next(2); } + do { pk.Version = GameVersion.SL + (byte)rnd.Next(2); } while (!CanBeReceivedByVersion(pk)); } @@ -585,7 +579,7 @@ private void SetEggMetData(PK9 pk) private void SetPINGA(PK9 pk, EncounterCriteria criteria) { var pi = pk.PersonalInfo; - pk.Nature = pk.StatNature = (int)criteria.GetNature(Nature == -1 ? Core.Nature.Random : (Nature)Nature); + pk.Nature = pk.StatNature = criteria.GetNature((sbyte)Nature == -1 ? Nature.Random : Nature); pk.Gender = criteria.GetGender(Gender, pi); var av = GetAbilityIndex(criteria); pk.RefreshAbility(av); @@ -681,15 +675,15 @@ public override bool IsMatchExact(PKM pk, EvoCriteria evo) { var expect = pk.MetDate is { } x && IsBeforePatch200(x) ? ID32Old : ID32; if (expect != pk.ID32) return false; - if (OTGender != pk.OT_Gender) return false; + if (OTGender != pk.OriginalTrainerGender) return false; } if (!CanBeAnyLanguage() && !CanHaveLanguage(pk.Language)) return false; var OT = GetOT(pk.Language); // May not be guaranteed to work. - if (!string.IsNullOrEmpty(OT) && OT != pk.OT_Name) return false; - if (OriginGame != 0 && OriginGame != pk.Version) return false; + if (!string.IsNullOrEmpty(OT) && OT != pk.OriginalTrainerName) return false; + if (OriginGame != 0 && (GameVersion)OriginGame != pk.Version) return false; if (EncryptionConstant != 0) { if (EncryptionConstant != pk.EncryptionConstant) @@ -708,9 +702,9 @@ public override bool IsMatchExact(PKM pk, EvoCriteria evo) shinyType = FixedShinyType(); if (IsEgg) { - if (EggLocation != pk.Egg_Location) // traded + if (EggLocation != pk.EggLocation) // traded { - if (pk.Egg_Location != Locations.LinkTrade6) + if (pk.EggLocation != Locations.LinkTrade6) return false; if (PIDType == ShinyType8.Random && pk is { IsShiny: true, ShinyXor: > 1 }) return false; // shiny traded egg will always have xor0/1. @@ -730,15 +724,15 @@ public override bool IsMatchExact(PKM pk, EvoCriteria evo) if (!IsMatchLocation(pk)) return false; } - if (MetLevel != 0 && MetLevel != pk.Met_Level) return false; + if (MetLevel != 0 && MetLevel != pk.MetLevel) return false; if ((Ball == 0 ? 4 : Ball) != pk.Ball) return false; - if (OTGender < 2 && OTGender != pk.OT_Gender) return false; - if (Nature != -1 && pk.Nature != Nature) return false; + if (OTGender < 2 && OTGender != pk.OriginalTrainerGender) return false; + if ((sbyte)Nature != -1 && pk.Nature != Nature) return false; if (Gender != 3 && Gender != pk.Gender) return false; if (pk is IScaledSize s) { - if (!Encounter9RNG.IsHeightMatchSV(pk, HeightValue)) + if (!Encounter9RNG.IsHeightMatchSV(pk, (byte)HeightValue)) return false; if (s.WeightScalar != WeightValue) return false; @@ -774,15 +768,15 @@ private bool IsMatchLocation(PKM pk) return IsMatchLocationExact(pk) || IsMatchLocationRemapped(pk); } - private bool IsMatchLocationExact(PKM pk) => pk.Met_Location == Location; + private bool IsMatchLocationExact(PKM pk) => pk.MetLocation == Location; private bool IsMatchLocationRemapped(PKM pk) { - var met = (ushort)pk.Met_Location; + var met = pk.MetLocation; var version = pk.Version; if (pk.Context == EntityContext.Gen8) return LocationsHOME.IsValidMetSV(met, version); - return LocationsHOME.GetMetSWSH((ushort)Location, version) == met; + return LocationsHOME.GetMetSWSH(Location, version) == met; } public bool IsDateRestricted => true; diff --git a/PKHeX.Core/MysteryGifts/WR7.cs b/PKHeX.Core/MysteryGifts/WR7.cs index af585ac51..c9b415f43 100644 --- a/PKHeX.Core/MysteryGifts/WR7.cs +++ b/PKHeX.Core/MysteryGifts/WR7.cs @@ -15,11 +15,11 @@ public sealed class WR7(byte[] Data) : DataMysteryGift(Data) public WR7() : this(new byte[Size]) { } public const int Size = 0x140; - public override int Generation => 7; + public override byte Generation => 7; public override EntityContext Context => EntityContext.Gen7; public override bool FatefulEncounter => true; - public override GameVersion Version { get => GameVersion.GG; set { } } + public override GameVersion Version => GameVersion.GG; public override AbilityPermission Ability => AbilityPermission.Any12H; // undefined @@ -84,13 +84,13 @@ public override ushort Species public ushort ItemSet6Item { get => ReadUInt16LittleEndian(Data.AsSpan(0x124)); set => WriteUInt16LittleEndian(Data.AsSpan(0x124), value); } public ushort ItemSet6Count { get => ReadUInt16LittleEndian(Data.AsSpan(0x126)); set => WriteUInt16LittleEndian(Data.AsSpan(0x126), value); } - public override int Gender { get; set; } + public override byte Gender { get; set; } public override byte Form { get; set; } public override uint ID32 { get; set; } public override ushort TID16 { get; set; } public override ushort SID16 { get; set; } - public override string OT_Name + public override string OriginalTrainerName { get => StringConverter8.GetString(Data.AsSpan(0x120, 0x1A)); set => StringConverter8.SetString(Data.AsSpan(0x120, 0x1A), value, 12, StringConverterOption.ClearZero); @@ -108,11 +108,11 @@ public LanguageID LanguageReceived protected override bool IsMatchPartial(PKM pk) => false; public override Shiny Shiny => Shiny.Never; - public override int Location { get; set; } - public override int EggLocation { get; set; } - public override int Ball { get; set; } = 4; + public override ushort Location { get; set; } + public override ushort EggLocation { get; set; } + public override byte Ball { get; set; } = 4; - public override string CardTitle { get => $"{nameof(WB7)} Record ({OT_Name}) [{LanguageReceived}]"; set { } } + public override string CardTitle { get => $"{nameof(WB7)} Record ({OriginalTrainerName}) [{LanguageReceived}]"; set { } } public override bool IsItem { @@ -143,11 +143,11 @@ public override PB7 ConvertToPKM(ITrainerInfo tr, EncounterCriteria criteria) // we'll just generate something as close as we can, since we must return something! var pk = new PB7(); tr.ApplyTo(pk); - if (!GameVersion.GG.Contains((GameVersion) tr.Game)) - pk.Version = (int) GameVersion.GP; + if (!GameVersion.GG.Contains(tr.Version)) + pk.Version = GameVersion.GP; pk.Species = Species; - pk.Met_Level = pk.CurrentLevel = Level; + pk.MetLevel = pk.CurrentLevel = Level; pk.MetDate = Date; return pk; // can't really do much more, just return the rough data diff --git a/PKHeX.Core/PKM/BK4.cs b/PKHeX.Core/PKM/BK4.cs index 2a7d06912..a98ee838c 100644 --- a/PKHeX.Core/PKM/BK4.cs +++ b/PKHeX.Core/PKM/BK4.cs @@ -61,7 +61,7 @@ public override uint EXP set => WriteUInt32BigEndian(Data.AsSpan(0x10), value); } - public override int OT_Friendship { get => Data[0x14]; set => Data[0x14] = (byte)value; } + public override byte OriginalTrainerFriendship { get => Data[0x14]; set => Data[0x14] = value; } public override int Ability { get => Data[0x15]; set => Data[0x15] = (byte)value; } public override byte MarkingValue { get => Data[0x16]; set => Data[0x16] = value; } public override int Language { get => Data[0x17]; set => Data[0x17] = (byte)value; } @@ -71,12 +71,12 @@ public override uint EXP public override int EV_SPE { get => Data[0x1B]; set => Data[0x1B] = (byte)value; } public override int EV_SPA { get => Data[0x1C]; set => Data[0x1C] = (byte)value; } public override int EV_SPD { get => Data[0x1D]; set => Data[0x1D] = (byte)value; } - public override byte CNT_Cool { get => Data[0x1E]; set => Data[0x1E] = value; } - public override byte CNT_Beauty { get => Data[0x1F]; set => Data[0x1F] = value; } - public override byte CNT_Cute { get => Data[0x20]; set => Data[0x20] = value; } - public override byte CNT_Smart { get => Data[0x21]; set => Data[0x21] = value; } - public override byte CNT_Tough { get => Data[0x22]; set => Data[0x22] = value; } - public override byte CNT_Sheen { get => Data[0x23]; set => Data[0x23] = value; } + public override byte ContestCool { get => Data[0x1E]; set => Data[0x1E] = value; } + public override byte ContestBeauty { get => Data[0x1F]; set => Data[0x1F] = value; } + public override byte ContestCute { get => Data[0x20]; set => Data[0x20] = value; } + public override byte ContestSmart { get => Data[0x21]; set => Data[0x21] = value; } + public override byte ContestTough { get => Data[0x22]; set => Data[0x22] = value; } + public override byte ContestSheen { get => Data[0x23]; set => Data[0x23] = value; } private byte RIB3 { get => Data[0x24]; set => Data[0x24] = value; } // Unova 2 private byte RIB2 { get => Data[0x25]; set => Data[0x25] = value; } // Unova 1 @@ -133,7 +133,7 @@ public override uint EXP public override int Move2_PPUps { get => Data[0x35]; set => Data[0x35] = (byte)value; } public override int Move3_PPUps { get => Data[0x36]; set => Data[0x36] = (byte)value; } public override int Move4_PPUps { get => Data[0x37]; set => Data[0x37] = (byte)value; } - protected internal override uint IV32 { get => ReadUInt32BigEndian(Data.AsSpan(0x38)); set => WriteUInt32BigEndian(Data.AsSpan(0x38), value); } + public override uint IV32 { get => ReadUInt32BigEndian(Data.AsSpan(0x38)); set => WriteUInt32BigEndian(Data.AsSpan(0x38), value); } public override int IV_SPD { get => (int)(IV32 >> 02) & 0x1F; set => IV32 = (IV32 & ~(0x1Fu << 02)) | ((value > 31 ? 31u : (uint)value) << 02); } public override int IV_SPA { get => (int)(IV32 >> 07) & 0x1F; set => IV32 = (IV32 & ~(0x1Fu << 07)) | ((value > 31 ? 31u : (uint)value) << 07); } public override int IV_SPE { get => (int)(IV32 >> 12) & 0x1F; set => IV32 = (IV32 & ~(0x1Fu << 12)) | ((value > 31 ? 31u : (uint)value) << 12); } @@ -181,18 +181,18 @@ public override uint EXP public override bool RibbonWorld { get => (RIB7 & (1 << 7)) == 1 << 7; set => RIB7 = (byte)((RIB7 & ~(1 << 7)) | (value ? 1 << 7 : 0)); } public override bool FatefulEncounter { get => (Data[0x40] & 0x80) == 0x80; set => Data[0x40] = (byte)((Data[0x40] & ~0x80) | (value ? 0x80 : 0)); } - public override int Gender { get => (Data[0x40] >> 5) & 0x3; set => Data[0x40] = (byte)((Data[0x40] & ~0x60) | ((value & 3) << 5)); } + public override byte Gender { get => (byte)((Data[0x40] >> 5) & 0x3); set => Data[0x40] = (byte)((Data[0x40] & ~0x60) | ((value & 3) << 5)); } public override byte Form { get => (byte)(Data[0x40] & 0x1F); set => Data[0x40] = (byte)((Data[0x40] & ~0x1F) | (value & 0x1F)); } public override int ShinyLeaf { get => Data[0x41]; set => Data[0x41] = (byte)value; } // 0x42-0x43 Unused - public override ushort Egg_LocationExtended + public override ushort EggLocationExtended { get => ReadUInt16BigEndian(Data.AsSpan(0x44)); set => WriteUInt16BigEndian(Data.AsSpan(0x44), value); } - public override ushort Met_LocationExtended + public override ushort MetLocationExtended { get => ReadUInt16BigEndian(Data.AsSpan(0x46)); set => WriteUInt16BigEndian(Data.AsSpan(0x46), value); @@ -200,9 +200,9 @@ public override ushort Met_LocationExtended #endregion #region Block C - public override string Nickname { get => StringConverter4GC.GetString(Nickname_Trash); set => StringConverter4GC.SetString(Nickname_Trash, value, 10, StringConverterOption.None); } + public override string Nickname { get => StringConverter4GC.GetString(NicknameTrash); set => StringConverter4GC.SetString(NicknameTrash, value, 10, StringConverterOption.None); } // 0x5E unused - public override int Version { get => Data[0x5F]; set => Data[0x5F] = (byte)value; } + public override GameVersion Version { get => (GameVersion)Data[0x5F]; set => Data[0x5F] = (byte)value; } private byte RIB8 { get => Data[0x60]; set => Data[0x60] = value; } // Sinnoh 3 private byte RIB9 { get => Data[0x61]; set => Data[0x61] = value; } // Sinnoh 4 private byte RIBA { get => Data[0x62]; set => Data[0x62] = value; } // Sinnoh 5 @@ -243,31 +243,31 @@ public override ushort Met_LocationExtended #endregion #region Block D - public override string OT_Name { get => StringConverter4GC.GetString(OT_Trash); set => StringConverter4GC.SetString(OT_Trash, value, 7, StringConverterOption.None); } - public override int Egg_Year { get => Data[0x78]; set => Data[0x78] = (byte)value; } - public override int Egg_Month { get => Data[0x79]; set => Data[0x79] = (byte)value; } - public override int Egg_Day { get => Data[0x7A]; set => Data[0x7A] = (byte)value; } - public override int Met_Year { get => Data[0x7B]; set => Data[0x7B] = (byte)value; } - public override int Met_Month { get => Data[0x7C]; set => Data[0x7C] = (byte)value; } - public override int Met_Day { get => Data[0x7D]; set => Data[0x7D] = (byte)value; } + public override string OriginalTrainerName { get => StringConverter4GC.GetString(OriginalTrainerTrash); set => StringConverter4GC.SetString(OriginalTrainerTrash, value, 7, StringConverterOption.None); } + public override byte EggYear { get => Data[0x78]; set => Data[0x78] = value; } + public override byte EggMonth { get => Data[0x79]; set => Data[0x79] = value; } + public override byte EggDay { get => Data[0x7A]; set => Data[0x7A] = value; } + public override byte MetYear { get => Data[0x7B]; set => Data[0x7B] = value; } + public override byte MetMonth { get => Data[0x7C]; set => Data[0x7C] = value; } + public override byte MetDay { get => Data[0x7D]; set => Data[0x7D] = value; } - public override ushort Egg_LocationDP + public override ushort EggLocationDP { get => ReadUInt16BigEndian(Data.AsSpan(0x7E)); set => WriteUInt16BigEndian(Data.AsSpan(0x7E), value); } - public override ushort Met_LocationDP + public override ushort MetLocationDP { get => ReadUInt16BigEndian(Data.AsSpan(0x80)); set => WriteUInt16BigEndian(Data.AsSpan(0x80), value); } - private byte PKRS { get => Data[0x82]; set => Data[0x82] = value; } - public override int PKRS_Days { get => PKRS & 0xF; set => PKRS = (byte)((PKRS & ~0xF) | value); } - public override int PKRS_Strain { get => PKRS >> 4; set => PKRS = (byte)((PKRS & 0xF) | (value << 4)); } + public override byte PokerusState { get => Data[0x82]; set => Data[0x82] = value; } + public override int PokerusDays { get => PokerusState & 0xF; set => PokerusState = (byte)((PokerusState & ~0xF) | value); } + public override int PokerusStrain { get => PokerusState >> 4; set => PokerusState = (byte)((PokerusState & 0xF) | (value << 4)); } public override byte BallDPPt { get => Data[0x83]; set => Data[0x83] = value; } - public override int Met_Level { get => Data[0x84] >> 1; set => Data[0x84] = (byte)((Data[0x84] & 0x1) | (value << 1)); } - public override int OT_Gender { get => Data[0x84] & 1; set => Data[0x84] = (byte)((Data[0x84] & ~0x1) | (value & 1)); } + public override byte MetLevel { get => (byte)(Data[0x84] >> 1); set => Data[0x84] = (byte)((Data[0x84] & 0x1) | (value << 1)); } + public override byte OriginalTrainerGender { get => (byte)(Data[0x84] & 1); set => Data[0x84] = (byte)((Data[0x84] & ~0x1) | (value & 1)); } public override GroundTileType GroundTile { get => (GroundTileType)Data[0x85]; set => Data[0x85] = (byte)value; } public override byte BallHGSS { get => Data[0x86]; set => Data[0x86] = value; } public override byte PokeathlonStat { get => Data[0x87]; set => Data[0x87] = value; } @@ -275,7 +275,7 @@ public override ushort Met_LocationDP // Not stored public override int Status_Condition { get; set; } - public override int Stat_Level { get => CurrentLevel; set {} } + public override byte Stat_Level { get => CurrentLevel; set {} } public override int Stat_HPCurrent { get; set; } public override int Stat_HPMax { get; set; } public override int Stat_ATK { get; set; } diff --git a/PKHeX.Core/PKM/CK3.cs b/PKHeX.Core/PKM/CK3.cs index 00d51a401..579d828a5 100644 --- a/PKHeX.Core/PKM/CK3.cs +++ b/PKHeX.Core/PKM/CK3.cs @@ -25,8 +25,8 @@ public sealed class CK3(byte[] Data) : G3PKM(Data), IShadowCapture public override CK3 Clone() => new((byte[])Data.Clone()); // Trash Bytes - public override Span OT_Trash => Data.AsSpan(0x18, 22); - public override Span Nickname_Trash => Data.AsSpan(0x2E, 22); + public override Span OriginalTrainerTrash => Data.AsSpan(0x18, 22); + public override Span NicknameTrash => Data.AsSpan(0x2E, 22); public Span NicknameCopy_Trash => Data.AsSpan(0x44, 22); // Future Attributes @@ -34,22 +34,22 @@ public sealed class CK3(byte[] Data) : G3PKM(Data), IShadowCapture public override ushort Species { get => SpeciesConverter.GetNational3(SpeciesInternal); set => SpeciesInternal = SpeciesConverter.GetInternal3(value); } // 02-04 unused public override uint PID { get => ReadUInt32BigEndian(Data.AsSpan(0x04)); set => WriteUInt32BigEndian(Data.AsSpan(0x04), value); } - public override int Version { get => GetGBAVersionID(Data[0x08]); set => Data[0x08] = GetGCVersionID(value); } + public override GameVersion Version { get => GetGBAVersionID((GCVersion)Data[0x08]); set => Data[0x08] = (byte)GetGCVersionID(value); } public int CurrentRegion { get => Data[0x09]; set => Data[0x09] = (byte)value; } public int OriginalRegion { get => Data[0x0A]; set => Data[0x0A] = (byte)value; } public override int Language { get => Core.Language.GetMainLangIDfromGC(Data[0x0B]); set => Data[0x0B] = Core.Language.GetGCLangIDfromMain((byte)value); } - public override int Met_Location { get => ReadUInt16BigEndian(Data.AsSpan(0x0C)); set => WriteUInt16BigEndian(Data.AsSpan(0x0C), (ushort)value); } - public override int Met_Level { get => Data[0x0E]; set => Data[0x0E] = (byte)value; } - public override int Ball { get => Data[0x0F]; set => Data[0x0F] = (byte)value; } - public override int OT_Gender { get => Data[0x10]; set => Data[0x10] = (byte)value; } + public override ushort MetLocation { get => ReadUInt16BigEndian(Data.AsSpan(0x0C)); set => WriteUInt16BigEndian(Data.AsSpan(0x0C), value); } + public override byte MetLevel { get => Data[0x0E]; set => Data[0x0E] = value; } + public override byte Ball { get => Data[0x0F]; set => Data[0x0F] = value; } + public override byte OriginalTrainerGender { get => Data[0x10]; set => Data[0x10] = value; } public override uint ID32 { get => ReadUInt32BigEndian(Data.AsSpan(0x14)); set => WriteUInt32BigEndian(Data.AsSpan(0x14), value); } public override ushort SID16 { get => ReadUInt16BigEndian(Data.AsSpan(0x14)); set => WriteUInt16BigEndian(Data.AsSpan(0x14), value); } public override ushort TID16 { get => ReadUInt16BigEndian(Data.AsSpan(0x16)); set => WriteUInt16BigEndian(Data.AsSpan(0x16), value); } - public override string OT_Name { get => StringConverter3GC.GetString(OT_Trash); set => StringConverter3GC.SetString(OT_Trash, value, 10, StringConverterOption.None); } - public override string Nickname { get => StringConverter3GC.GetString(Nickname_Trash); set { StringConverter3GC.SetString(Nickname_Trash, value, 10, StringConverterOption.None); NicknameCopy = value; } } + public override string OriginalTrainerName { get => StringConverter3GC.GetString(OriginalTrainerTrash); set => StringConverter3GC.SetString(OriginalTrainerTrash, value, 10, StringConverterOption.None); } + public override string Nickname { get => StringConverter3GC.GetString(NicknameTrash); set { StringConverter3GC.SetString(NicknameTrash, value, 10, StringConverterOption.None); NicknameCopy = value; } } public string NicknameCopy { get => StringConverter3GC.GetString(NicknameCopy_Trash); set => StringConverter3GC.SetString(NicknameCopy_Trash, value, 10, StringConverterOption.None); } public override uint EXP { get => ReadUInt32BigEndian(Data.AsSpan(0x5C)); set => WriteUInt32BigEndian(Data.AsSpan(0x5C), value); } - public override int Stat_Level { get => Data[0x60]; set => Data[0x60] = (byte)value; } + public override byte Stat_Level { get => Data[0x60]; set => Data[0x60] = value; } // 0x64-0x77 are battle/status related public override int Status_Condition { get; set; } // where are we @@ -131,23 +131,23 @@ public sealed class CK3(byte[] Data) : G3PKM(Data), IShadowCapture get => Math.Min((ushort)31, ReadUInt16BigEndian(Data.AsSpan(0xAE))); set => WriteUInt16BigEndian(Data.AsSpan(0xAE), (ushort)(value & 0x1F)); } - public override int OT_Friendship { - get => Math.Min((ushort)0xFF, ReadUInt16BigEndian(Data.AsSpan(0xB0))); + public override byte OriginalTrainerFriendship { + get => (byte)Math.Min((ushort)0xFF, ReadUInt16BigEndian(Data.AsSpan(0xB0))); set => WriteUInt16BigEndian(Data.AsSpan(0xB0), (ushort)(value & 0xFF)); } // Contest - public override byte CNT_Cool { get => Data[0xB2]; set => Data[0xB2] = value; } - public override byte CNT_Beauty { get => Data[0xB3]; set => Data[0xB3] = value; } - public override byte CNT_Cute { get => Data[0xB4]; set => Data[0xB4] = value; } - public override byte CNT_Smart { get => Data[0xB5]; set => Data[0xB5] = value; } - public override byte CNT_Tough { get => Data[0xB6]; set => Data[0xB6] = value; } + public override byte ContestCool { get => Data[0xB2]; set => Data[0xB2] = value; } + public override byte ContestBeauty { get => Data[0xB3]; set => Data[0xB3] = value; } + public override byte ContestCute { get => Data[0xB4]; set => Data[0xB4] = value; } + public override byte ContestSmart { get => Data[0xB5]; set => Data[0xB5] = value; } + public override byte ContestTough { get => Data[0xB6]; set => Data[0xB6] = value; } public override byte RibbonCountG3Cool { get => Data[0xB7]; set => Data[0xB7] = value; } public override byte RibbonCountG3Beauty { get => Data[0xB8]; set => Data[0xB8] = value; } public override byte RibbonCountG3Cute { get => Data[0xB9]; set => Data[0xB9] = value; } public override byte RibbonCountG3Smart { get => Data[0xBA]; set => Data[0xBA] = value; } public override byte RibbonCountG3Tough { get => Data[0xBB]; set => Data[0xBB] = value; } - public override byte CNT_Sheen { get => Data[0xBC]; set => Data[0xBC] = value; } + public override byte ContestSheen { get => Data[0xBC]; set => Data[0xBC] = value; } // Ribbons public override bool RibbonChampionG3 { get => Data[0xBD] == 1; set => Data[0xBD] = value ? (byte)1 : (byte)0; } @@ -169,13 +169,13 @@ public sealed class CK3(byte[] Data) : G3PKM(Data), IShadowCapture private bool FatefulEncounterJPN { get => ((Data[0xC9] >> 4) & 1) == 1; set => Data[0xC9] = (byte)((Data[0xC9] &~16) | (value ?16 : 0)); } public override int RibbonCount => Data.AsSpan(0xBD, 12).Count(1) + RibbonCountG3Cool + RibbonCountG3Beauty + RibbonCountG3Cute + RibbonCountG3Smart + RibbonCountG3Tough; - public override int PKRS_Strain { get => Data[0xCA] & 0xF; set => Data[0xCA] = (byte)(value & 0xF); } + public override int PokerusStrain { get => Data[0xCA] & 0xF; set => Data[0xCA] = (byte)(value & 0xF); } public override bool IsEgg { get => Data[0xCB] == 1; set => Data[0xCB] = value ? (byte)1 : (byte)0; } public override bool AbilityBit { get => Data[0xCC] == 1; set => Data[0xCC] = value ? (byte)1 : (byte)0; } public override bool Valid { get => Data[0xCD] == 0; set => Data[0xCD] = !value ? (byte)1 : (byte)0; } public override byte MarkingValue { get => (byte)SwapBits(Data[0xCF], 1, 2); set => Data[0xCF] = (byte)SwapBits(value, 1, 2); } - public override int PKRS_Days { get => Math.Max((sbyte)Data[0xD0], (sbyte)0); set => Data[0xD0] = (byte)(value == 0 ? 0xFF : value & 0xF); } + public override int PokerusDays { get => Math.Max((sbyte)Data[0xD0], (sbyte)0); set => Data[0xD0] = (byte)(value == 0 ? 0xFF : value & 0xF); } public int PartySlot { get => Data[0xD7]; set => Data[0xD7] = (byte)value; } // or not; only really used while in party? public ushort ShadowID { get => ReadUInt16BigEndian(Data.AsSpan(0xD8)); set => WriteUInt16BigEndian(Data.AsSpan(0xD8), value); } diff --git a/PKHeX.Core/PKM/Enums/PokeSize.cs b/PKHeX.Core/PKM/Enums/PokeSize.cs index 30cd9922d..ec1c01d13 100644 --- a/PKHeX.Core/PKM/Enums/PokeSize.cs +++ b/PKHeX.Core/PKM/Enums/PokeSize.cs @@ -40,7 +40,7 @@ public static class PokeSizeUtil AV => (byte)(rnd.Next(0xA0) + 0x30), L => (byte)(rnd.Next(0x20) + 0xD0), XL => (byte)(rnd.Next(0x10) + 0xF0), - _ => GetRandomScalar(), + _ => GetRandomScalar(rnd), }; /// diff --git a/PKHeX.Core/PKM/Enums/PokeSizeDetailed.cs b/PKHeX.Core/PKM/Enums/PokeSizeDetailed.cs index c03094e9d..307cc8c5e 100644 --- a/PKHeX.Core/PKM/Enums/PokeSizeDetailed.cs +++ b/PKHeX.Core/PKM/Enums/PokeSizeDetailed.cs @@ -28,12 +28,12 @@ public static class PokeSizeDetailedUtil public static PokeSizeDetailed GetSizeRating(byte scalar) => scalar switch { 0 => XXXS, // 1:256 - <= 24 => XXS, // 23:256 - <= 59 => XS, // 34:256 - < 100 => S, // 39:256 - <= 155 => AV, // 55:256 - <= 195 => L, // 39:256 - <= 230 => XL, // 34:256 + < 25 => XXS, // 23:256 + < 60 => XS, // 35:256 + < 100 => S, // 40:256 + <= 155 => AV, // 56:256 + <= 195 => L, // 40:256 + <= 230 => XL, // 35:256 < 255 => XXL, // 23:256 _ => XXXL, // 1:256 }; diff --git a/PKHeX.Core/PKM/Enums/PokeblockFlavor.cs b/PKHeX.Core/PKM/Enums/PokeblockFlavor.cs new file mode 100644 index 000000000..5791b6b92 --- /dev/null +++ b/PKHeX.Core/PKM/Enums/PokeblockFlavor.cs @@ -0,0 +1,24 @@ +namespace PKHeX.Core; + +/// +/// Flavor of Pokeblock +/// +public enum PokeblockFlavor : byte +{ + Spicy = 0, + Sour = 1, + Sweet = 2, + Dry = 3, + Bitter = 4, +} + +/// +/// Logic for Poké Blocks used in generation 3/4. +/// +public static class PokeblockUtil +{ + private const int Flavors = 5; + + public static PokeblockFlavor GetLikedBlockFlavor(uint nature) => (PokeblockFlavor)(nature / Flavors); + public static PokeblockFlavor GetDislikedBlockFlavor(uint nature) => (PokeblockFlavor)(nature % Flavors); +} diff --git a/PKHeX.Core/PKM/HOME/GameDataCore.cs b/PKHeX.Core/PKM/HOME/GameDataCore.cs index 19362b89b..cf7ef8809 100644 --- a/PKHeX.Core/PKM/HOME/GameDataCore.cs +++ b/PKHeX.Core/PKM/HOME/GameDataCore.cs @@ -42,10 +42,10 @@ public int WriteTo(Span result) public bool IsFavorite { get => Data[0x17] != 0; set => Data[0x17] = (byte)(value ? 1 : 0); } public ushort MarkingValue { get => ReadUInt16LittleEndian(Data[0x18..]); set => WriteUInt16LittleEndian(Data[0x18..], value); } public uint PID { get => ReadUInt32LittleEndian(Data[0x1A..]); set => WriteUInt32LittleEndian(Data[0x1A..], value); } - public int Nature { get => Data[0x1E]; set => Data[0x1E] = (byte)value; } - public int StatNature { get => Data[0x1F]; set => Data[0x1F] = (byte)value; } + public Nature Nature { get => (Nature)Data[0x1E]; set => Data[0x1E] = (byte)value; } + public Nature StatNature { get => (Nature)Data[0x1F]; set => Data[0x1F] = (byte)value; } public bool FatefulEncounter { get => Data[0x20] != 0; set => Data[0x20] = (byte)(value ? 1 : 0); } - public int Gender { get => Data[0x21]; set => Data[0x21] = (byte)value; } + public byte Gender { get => Data[0x21]; set => Data[0x21] = value; } public byte Form { get => Data[0x22]; set => WriteUInt16LittleEndian(Data[0x22..], value); } public int EV_HP { get => Data[0x24]; set => Data[0x24] = (byte)value; } public int EV_ATK { get => Data[0x25]; set => Data[0x25] = (byte)value; } @@ -53,12 +53,12 @@ public int WriteTo(Span result) public int EV_SPE { get => Data[0x27]; set => Data[0x27] = (byte)value; } public int EV_SPA { get => Data[0x28]; set => Data[0x28] = (byte)value; } public int EV_SPD { get => Data[0x29]; set => Data[0x29] = (byte)value; } - public byte CNT_Cool { get => Data[0x2A]; set => Data[0x2A] = value; } - public byte CNT_Beauty { get => Data[0x2B]; set => Data[0x2B] = value; } - public byte CNT_Cute { get => Data[0x2C]; set => Data[0x2C] = value; } - public byte CNT_Smart { get => Data[0x2D]; set => Data[0x2D] = value; } - public byte CNT_Tough { get => Data[0x2E]; set => Data[0x2E] = value; } - public byte CNT_Sheen { get => Data[0x2F]; set => Data[0x2F] = value; } + public byte ContestCool { get => Data[0x2A]; set => Data[0x2A] = value; } + public byte ContestBeauty { get => Data[0x2B]; set => Data[0x2B] = value; } + public byte ContestCute { get => Data[0x2C]; set => Data[0x2C] = value; } + public byte ContestSmart { get => Data[0x2D]; set => Data[0x2D] = value; } + public byte ContestTough { get => Data[0x2E]; set => Data[0x2E] = value; } + public byte ContestSheen { get => Data[0x2F]; set => Data[0x2F] = value; } private bool GetFlag(int offset, int bit) => FlagUtil.GetFlag(Data, offset, bit); private void SetFlag(int offset, int bit, bool value) => FlagUtil.SetFlag(Data, offset, bit, value); @@ -227,12 +227,12 @@ public int WriteTo(Span result) public byte HeightScalar { get => Data[0x42]; set => Data[0x42] = value; } public byte WeightScalar { get => Data[0x43]; set => Data[0x43] = value; } - public Span Nickname_Trash => Data.Slice(0x44, 26); + public Span NicknameTrash => Data.Slice(0x44, 26); public string Nickname { - get => StringConverter8.GetString(Nickname_Trash); - set => StringConverter8.SetString(Nickname_Trash, value, 12, StringConverterOption.None); + get => StringConverter8.GetString(NicknameTrash); + set => StringConverter8.SetString(NicknameTrash, value, 12, StringConverterOption.None); } public int Stat_HPCurrent { get => ReadUInt16LittleEndian(Data[0x5E..]); set => WriteUInt16LittleEndian(Data[0x5E..], (ushort)value); } @@ -245,48 +245,48 @@ public string Nickname public bool IsEgg { get => Data[0x66] != 0; set => Data[0x66] = (byte)(value ? 1 : 0); } public bool IsNicknamed { get => Data[0x67] != 0; set => Data[0x67] = (byte)(value ? 1 : 0); } public int Status_Condition { get => ReadInt32LittleEndian(Data[0x68..]); set => WriteInt32LittleEndian(Data[0x68..], value); } - public Span HT_Trash => Data.Slice(0x6C, 26); - public string HT_Name + public Span HandlingTrainerTrash => Data.Slice(0x6C, 26); + public string HandlingTrainerName { - get => StringConverter8.GetString(HT_Trash); - set => StringConverter8.SetString(HT_Trash, value, 12, StringConverterOption.None); + get => StringConverter8.GetString(HandlingTrainerTrash); + set => StringConverter8.SetString(HandlingTrainerTrash, value, 12, StringConverterOption.None); } - public int HT_Gender { get => Data[0x86]; set => Data[0x86] = (byte)value; } - public byte HT_Language { get => Data[0x87]; set => Data[0x87] = value; } - public int CurrentHandler { get => Data[0x88]; set => Data[0x88] = (byte)value; } - public int HT_TrainerID { get => ReadUInt16LittleEndian(Data[0x89..]); set => WriteUInt16LittleEndian(Data[0x89..], (ushort)value); } // unused? - public int HT_Friendship { get => Data[0x8B]; set => Data[0x8B] = (byte)value; } - public byte HT_Intensity { get => Data[0x8C]; set => Data[0x8C] = value; } - public byte HT_Memory { get => Data[0x8D]; set => Data[0x8D] = value; } - public byte HT_Feeling { get => Data[0x8E]; set => Data[0x8E] = value; } - public ushort HT_TextVar { get => ReadUInt16LittleEndian(Data[0x8F..]); set => WriteUInt16LittleEndian(Data[0x8F..], value); } - public int Version { get => Data[0x91]; set => Data[0x91] = (byte)value; } - public byte BattleVersion { get => Data[0x92]; set => Data[0x92] = value; } + public byte HandlingTrainerGender { get => Data[0x86]; set => Data[0x86] = value; } + public byte HandlingTrainerLanguage { get => Data[0x87]; set => Data[0x87] = value; } + public byte CurrentHandler { get => Data[0x88]; set => Data[0x88] = value; } + public ushort HandlingTrainerID { get => ReadUInt16LittleEndian(Data[0x89..]); set => WriteUInt16LittleEndian(Data[0x89..], value); } // unused? + public byte HandlingTrainerFriendship { get => Data[0x8B]; set => Data[0x8B] = value; } + public byte HandlingTrainerMemoryIntensity { get => Data[0x8C]; set => Data[0x8C] = value; } + public byte HandlingTrainerMemory { get => Data[0x8D]; set => Data[0x8D] = value; } + public byte HandlingTrainerMemoryFeeling { get => Data[0x8E]; set => Data[0x8E] = value; } + public ushort HandlingTrainerMemoryVariable { get => ReadUInt16LittleEndian(Data[0x8F..]); set => WriteUInt16LittleEndian(Data[0x8F..], value); } + public GameVersion Version { get => (GameVersion)Data[0x91]; set => Data[0x91] = (byte)value; } + public GameVersion BattleVersion { get => (GameVersion)Data[0x92]; set => Data[0x92] = (byte)value; } public int Language { get => Data[0x93]; set => Data[0x93] = (byte)value; } public uint FormArgument { get => ReadUInt32LittleEndian(Data[0x94..]); set => WriteUInt32LittleEndian(Data[0x94..], value); } public byte FormArgumentRemain { get => (byte)FormArgument; set => FormArgument = (FormArgument & ~0xFFu) | value; } public byte FormArgumentElapsed { get => (byte)(FormArgument >> 8); set => FormArgument = (FormArgument & ~0xFF00u) | (uint)(value << 8); } public byte FormArgumentMaximum { get => (byte)(FormArgument >> 16); set => FormArgument = (FormArgument & ~0xFF0000u) | (uint)(value << 16); } public sbyte AffixedRibbon { get => (sbyte)Data[0x98]; set => Data[0x98] = (byte)value; } // selected ribbon - public Span OT_Trash => Data.Slice(0x99, 26); - public string OT_Name + public Span OriginalTrainerTrash => Data.Slice(0x99, 26); + public string OriginalTrainerName { - get => StringConverter8.GetString(OT_Trash); - set => StringConverter8.SetString(OT_Trash, value, 12, StringConverterOption.None); + get => StringConverter8.GetString(OriginalTrainerTrash); + set => StringConverter8.SetString(OriginalTrainerTrash, value, 12, StringConverterOption.None); } - public int OT_Friendship { get => Data[0xB3]; set => Data[0xB3] = (byte)value; } - public byte OT_Intensity { get => Data[0xB4]; set => Data[0xB4] = value; } - public byte OT_Memory { get => Data[0xB5]; set => Data[0xB5] = value; } - public ushort OT_TextVar { get => ReadUInt16LittleEndian(Data[0xB6..]); set => WriteUInt16LittleEndian(Data[0xB6..], value); } - public byte OT_Feeling { get => Data[0xB8]; set => Data[0xB8] = value; } - public int Egg_Year { get => Data[0xB9]; set => Data[0xB9] = (byte)value; } - public int Egg_Month { get => Data[0xBA]; set => Data[0xBA] = (byte)value; } - public int Egg_Day { get => Data[0xBB]; set => Data[0xBB] = (byte)value; } - public int Met_Year { get => Data[0xBC]; set => Data[0xBC] = (byte)value; } - public int Met_Month { get => Data[0xBD]; set => Data[0xBD] = (byte)value; } - public int Met_Day { get => Data[0xBE]; set => Data[0xBE] = (byte)value; } - public int Met_Level { get => Data[0xBF]; set => Data[0xBF] = (byte)value; } - public int OT_Gender { get => Data[0xC0]; set => Data[0xC0] = (byte)value; } + public byte OriginalTrainerFriendship { get => Data[0xB3]; set => Data[0xB3] = value; } + public byte OriginalTrainerMemoryIntensity { get => Data[0xB4]; set => Data[0xB4] = value; } + public byte OriginalTrainerMemory { get => Data[0xB5]; set => Data[0xB5] = value; } + public ushort OriginalTrainerMemoryVariable { get => ReadUInt16LittleEndian(Data[0xB6..]); set => WriteUInt16LittleEndian(Data[0xB6..], value); } + public byte OriginalTrainerMemoryFeeling { get => Data[0xB8]; set => Data[0xB8] = value; } + public byte EggYear { get => Data[0xB9]; set => Data[0xB9] = value; } + public byte EggMonth { get => Data[0xBA]; set => Data[0xBA] = value; } + public byte EggDay { get => Data[0xBB]; set => Data[0xBB] = value; } + public byte MetYear { get => Data[0xBC]; set => Data[0xBC] = value; } + public byte MetMonth { get => Data[0xBD]; set => Data[0xBD] = value; } + public byte MetDay { get => Data[0xBE]; set => Data[0xBE] = value; } + public byte MetLevel { get => Data[0xBF]; set => Data[0xBF] = value; } + public byte OriginalTrainerGender { get => Data[0xC0]; set => Data[0xC0] = value; } public byte HyperTrainFlags { get => Data[0xC1]; set => Data[0xC1] = value; } public bool HT_HP { get => ((HyperTrainFlags >> 0) & 1) == 1; set => HyperTrainFlags = (byte)((HyperTrainFlags & ~(1 << 0)) | ((value ? 1 : 0) << 0)); } public bool HT_ATK { get => ((HyperTrainFlags >> 1) & 1) == 1; set => HyperTrainFlags = (byte)((HyperTrainFlags & ~(1 << 1)) | ((value ? 1 : 0) << 1)); } @@ -297,7 +297,7 @@ public string OT_Name public int HeldItem { get => ReadUInt16LittleEndian(Data[0xC2..]); set => WriteUInt16LittleEndian(Data[0xC2..], (ushort)value); } - public TrainerIDFormat TrainerIDDisplayFormat => ((GameVersion)Version).GetGeneration() >= 7 ? TrainerIDFormat.SixDigit : TrainerIDFormat.SixteenBit; + public TrainerIDFormat TrainerIDDisplayFormat => (Version).GetGeneration() >= 7 ? TrainerIDFormat.SixDigit : TrainerIDFormat.SixteenBit; public int MarkingCount => 6; @@ -353,29 +353,29 @@ public void CopyFrom(PKM pk) EV_SPA = pk.EV_SPA; EV_SPD = pk.EV_SPD; - HT_Gender = pk.HT_Gender; + HandlingTrainerGender = pk.HandlingTrainerGender; CurrentHandler = pk.CurrentHandler; - // pk.HT_TrainerID - HT_Friendship = pk.HT_Friendship; + // pk.HandlingTrainerID + HandlingTrainerFriendship = pk.HandlingTrainerFriendship; Version = pk.Version; Language = pk.Language; - OT_Friendship = pk.OT_Friendship; - Egg_Year = pk.Egg_Year; - Egg_Month = pk.Egg_Month; - Egg_Day = pk.Egg_Day; - Met_Year = pk.Met_Year; - Met_Month = pk.Met_Month; - Met_Day = pk.Met_Day; - Met_Level = pk.Met_Level; - OT_Gender = pk.OT_Gender; + OriginalTrainerFriendship = pk.OriginalTrainerFriendship; + EggYear = pk.EggYear; + EggMonth = pk.EggMonth; + EggDay = pk.EggDay; + MetYear = pk.MetYear; + MetMonth = pk.MetMonth; + MetDay = pk.MetDay; + MetLevel = pk.MetLevel; + OriginalTrainerGender = pk.OriginalTrainerGender; CopyConditionalInterfaceFrom(pk); - pk.OT_Trash.CopyTo(OT_Trash); - pk.Nickname_Trash.CopyTo(Nickname_Trash); - pk.HT_Trash.CopyTo(HT_Trash); + pk.OriginalTrainerTrash.CopyTo(OriginalTrainerTrash); + pk.NicknameTrash.CopyTo(NicknameTrash); + pk.HandlingTrainerTrash.CopyTo(HandlingTrainerTrash); CopyConditionalRibbonMarkFrom(pk); } @@ -411,29 +411,29 @@ public void CopyTo(PKM pk) pk.EV_SPA = EV_SPA; pk.EV_SPD = EV_SPD; - pk.HT_Gender = HT_Gender; + pk.HandlingTrainerGender = HandlingTrainerGender; pk.CurrentHandler = CurrentHandler; - // pk.HT_TrainerID - pk.HT_Friendship = HT_Friendship; + // pk.HandlingTrainerID + pk.HandlingTrainerFriendship = HandlingTrainerFriendship; pk.Version = Version; pk.Language = Language; - pk.OT_Friendship = OT_Friendship; - pk.Egg_Year = Egg_Year; - pk.Egg_Month = Egg_Month; - pk.Egg_Day = Egg_Day; - pk.Met_Year = Met_Year; - pk.Met_Month = Met_Month; - pk.Met_Day = Met_Day; - pk.Met_Level = Met_Level; - pk.OT_Gender = OT_Gender; + pk.OriginalTrainerFriendship = OriginalTrainerFriendship; + pk.EggYear = EggYear; + pk.EggMonth = EggMonth; + pk.EggDay = EggDay; + pk.MetYear = MetYear; + pk.MetMonth = MetMonth; + pk.MetDay = MetDay; + pk.MetLevel = MetLevel; + pk.OriginalTrainerGender = OriginalTrainerGender; CopyConditionalInterfaceTo(pk); - OT_Trash.CopyTo(pk.OT_Trash); - Nickname_Trash.CopyTo(pk.Nickname_Trash); - HT_Trash.CopyTo(pk.HT_Trash); + OriginalTrainerTrash.CopyTo(pk.OriginalTrainerTrash); + NicknameTrash.CopyTo(pk.NicknameTrash); + HandlingTrainerTrash.CopyTo(pk.HandlingTrainerTrash); CopyConditionalRibbonMarkTo(pk); } @@ -448,20 +448,20 @@ private void CopyConditionalInterfaceTo(PKM pk) if (pk is IMemoryOT ot) { - ot.OT_Intensity = OT_Intensity; - ot.OT_Memory = OT_Memory; - ot.OT_TextVar = OT_TextVar; - ot.OT_Feeling = OT_Feeling; + ot.OriginalTrainerMemoryIntensity = OriginalTrainerMemoryIntensity; + ot.OriginalTrainerMemory = OriginalTrainerMemory; + ot.OriginalTrainerMemoryVariable = OriginalTrainerMemoryVariable; + ot.OriginalTrainerMemoryFeeling = OriginalTrainerMemoryFeeling; } if (pk is IMemoryHT hm) { - hm.HT_Intensity = HT_Intensity; - hm.HT_Memory = HT_Memory; - hm.HT_Feeling = HT_Feeling; - hm.HT_TextVar = HT_TextVar; + hm.HandlingTrainerMemoryIntensity = HandlingTrainerMemoryIntensity; + hm.HandlingTrainerMemory = HandlingTrainerMemory; + hm.HandlingTrainerMemoryFeeling = HandlingTrainerMemoryFeeling; + hm.HandlingTrainerMemoryVariable = HandlingTrainerMemoryVariable; } if (pk is IHandlerLanguage hl) - hl.HT_Language = HT_Language; + hl.HandlingTrainerLanguage = HandlingTrainerLanguage; if (pk is IContestStats cm) this.CopyContestStatsTo(cm); @@ -489,20 +489,20 @@ private void CopyConditionalInterfaceFrom(PKM pk) if (pk is IMemoryOT ot) { - OT_Intensity = ot.OT_Intensity; - OT_Memory = ot.OT_Memory; - OT_TextVar = ot.OT_TextVar; - OT_Feeling = ot.OT_Feeling; + OriginalTrainerMemoryIntensity = ot.OriginalTrainerMemoryIntensity; + OriginalTrainerMemory = ot.OriginalTrainerMemory; + OriginalTrainerMemoryVariable = ot.OriginalTrainerMemoryVariable; + OriginalTrainerMemoryFeeling = ot.OriginalTrainerMemoryFeeling; } if (pk is IMemoryHT ht) { - HT_Intensity = ht.HT_Intensity; - HT_Memory = ht.HT_Memory; - HT_Feeling = ht.HT_Feeling; - HT_TextVar = ht.HT_TextVar; + HandlingTrainerMemoryIntensity = ht.HandlingTrainerMemoryIntensity; + HandlingTrainerMemory = ht.HandlingTrainerMemory; + HandlingTrainerMemoryFeeling = ht.HandlingTrainerMemoryFeeling; + HandlingTrainerMemoryVariable = ht.HandlingTrainerMemoryVariable; } if (pk is IHandlerLanguage hl) - HT_Language = hl.HT_Language; + HandlingTrainerLanguage = hl.HandlingTrainerLanguage; if (pk is IContestStats cm) cm.CopyContestStatsTo(this); diff --git a/PKHeX.Core/PKM/HOME/GameDataPA8.cs b/PKHeX.Core/PKM/HOME/GameDataPA8.cs index 4606c0e47..ff1d28eb7 100644 --- a/PKHeX.Core/PKM/HOME/GameDataPA8.cs +++ b/PKHeX.Core/PKM/HOME/GameDataPA8.cs @@ -45,7 +45,7 @@ public sealed class GameDataPA8 : HomeOptional1, IGameDataSide, IScaledSize public byte GV_SPD { get => Data[0x1E]; set => Data[0x1E] = value; } public float HeightAbsolute { get => ReadSingleLittleEndian(Data[0x1F..]); set => WriteSingleLittleEndian(Data[0x1F..], value); } public float WeightAbsolute { get => ReadSingleLittleEndian(Data[0x23..]); set => WriteSingleLittleEndian(Data[0x23..], value); } - public int Ball { get => Data[0x27]; set => Data[0x27] = (byte)value; } + public byte Ball { get => Data[0x27]; set => Data[0x27] = value; } private Span PurchasedRecord => Data.Slice(0x28, 8); public bool GetPurchasedRecordFlag(int index) => FlagUtil.GetFlag(PurchasedRecord, index >> 3, index & 7); @@ -58,10 +58,10 @@ public sealed class GameDataPA8 : HomeOptional1, IGameDataSide, IScaledSize public void SetMasteredRecordFlag(int index, bool value) => FlagUtil.SetFlag(MasteredRecord, index >> 3, index & 7, value); public bool GetMasteredRecordFlagAny() => MasteredRecord.ContainsAnyExcept(0); - public int Egg_Location { get => ReadUInt16LittleEndian(Data[0x38..]); set => WriteUInt16LittleEndian(Data[0x38..], (ushort)value); } - public int Met_Location { get => ReadUInt16LittleEndian(Data[0x3A..]); set => WriteUInt16LittleEndian(Data[0x3A..], (ushort)value); } + public ushort EggLocation { get => ReadUInt16LittleEndian(Data[0x38..]); set => WriteUInt16LittleEndian(Data[0x38..], value); } + public ushort MetLocation { get => ReadUInt16LittleEndian(Data[0x3A..]); set => WriteUInt16LittleEndian(Data[0x3A..], value); } - public byte PKRS { get => Data[0x3C]; set => Data[0x3C] = value; } + public byte PokerusState { get => Data[0x3C]; set => Data[0x3C] = value; } public ushort Ability { get => ReadUInt16LittleEndian(Data[0x3D..]); set => WriteUInt16LittleEndian(Data[0x3D..], value); } public byte AbilityNumber { get => Data[0x3F]; set => Data[0x3F] = value; } @@ -93,7 +93,7 @@ public void CopyTo(PA8 pk, PKH pkh) pk.GV_SPD = GV_SPD; PurchasedRecord.CopyTo(pk.PurchasedRecord); MasteredRecord.CopyTo(pk.MasteredRecord); - pk.PKRS = PKRS; + pk.PokerusState = PokerusState; pk.AbilityNumber = AbilityNumber; pk.Ability = Ability; } @@ -115,7 +115,7 @@ public void CopyFrom(PA8 pk, PKH pkh) GV_SPD = pk.GV_SPD; pk.PurchasedRecord.CopyTo(PurchasedRecord); pk.MasteredRecord.CopyTo(MasteredRecord); - PKRS = pk.PKRS; + PokerusState = pk.PokerusState; AbilityNumber = (byte)pk.AbilityNumber; Ability = (ushort)pk.Ability; @@ -170,15 +170,15 @@ public PA8 ConvertToPKM(PKH pkh) public void InitializeFrom(IGameDataSide side, PKH pkh) { Ball = GetLegendBall(side.Ball, pkh.LA); - Met_Location = side.Met_Location == Locations.Default8bNone ? 0 : side.Met_Location; - Egg_Location = side.Egg_Location == Locations.Default8bNone ? 0 : side.Egg_Location; + MetLocation = side.MetLocation != Locations.Default8bNone ? side.MetLocation : (ushort)0; + EggLocation = side.EggLocation != Locations.Default8bNone ? side.EggLocation : (ushort)0; if (side is IScaledSize3 s3) Scale = s3.Scale; else Scale = pkh.HeightScalar; if (side is IPokerusStatus p) - PKRS = p.PKRS; + PokerusState = p.PokerusState; if (side is IGameDataSplitAbility a) AbilityNumber = a.AbilityNumber; else @@ -187,7 +187,7 @@ public void InitializeFrom(IGameDataSide side, PKH pkh) PopulateFromCore(pkh); } - private static int GetLegendBall(int ball, bool wasLA) + private static byte GetLegendBall(byte ball, bool wasLA) { if (!wasLA) return ball; diff --git a/PKHeX.Core/PKM/HOME/GameDataPB7.cs b/PKHeX.Core/PKM/HOME/GameDataPB7.cs index 5c12797d0..ca97b9175 100644 --- a/PKHeX.Core/PKM/HOME/GameDataPB7.cs +++ b/PKHeX.Core/PKM/HOME/GameDataPB7.cs @@ -52,18 +52,18 @@ public sealed class GameDataPB7 : HomeOptional1, IGameDataSide, IScaledSize public byte FieldEventFatigue2 { get => Data[0x28]; set => Data[0x28] = value; } public byte Fullness { get => Data[0x29]; set => Data[0x29] = value; } public byte Rank { get => Data[0x2A]; set => Data[0x2A] = value; } - public int OT_Affection { get => Data[0x2B]; set => Data[0x2B] = (byte)value; } - public byte OT_Intensity { get => Data[0x2C]; set => Data[0x2C] = value; } - public byte OT_Memory { get => Data[0x2D]; set => Data[0x2D] = value; } - public ushort OT_TextVar { get => ReadUInt16LittleEndian(Data[0x2E..]); set => WriteUInt16LittleEndian(Data[0x2E..], value); } - public byte OT_Feeling { get => Data[0x30]; set => Data[0x30] = value; } + public int OriginalTrainerAffection { get => Data[0x2B]; set => Data[0x2B] = (byte)value; } + public byte OriginalTrainerMemoryIntensity { get => Data[0x2C]; set => Data[0x2C] = value; } + public byte OriginalTrainerMemory { get => Data[0x2D]; set => Data[0x2D] = value; } + public ushort OriginalTrainerMemoryVariable { get => ReadUInt16LittleEndian(Data[0x2E..]); set => WriteUInt16LittleEndian(Data[0x2E..], value); } + public byte OriginalTrainerMemoryFeeling { get => Data[0x30]; set => Data[0x30] = value; } public byte Enjoyment { get => Data[0x31]; set => Data[0x31] = value; } public uint GeoPadding { get => ReadUInt32LittleEndian(Data[0x32..]); set => WriteUInt32LittleEndian(Data[0x32..], value); } - public int Ball { get => Data[0x36]; set => Data[0x36] = (byte)value; } - public int Egg_Location { get => ReadUInt16LittleEndian(Data[0x37..]); set => WriteUInt16LittleEndian(Data[0x37..], (ushort)value); } - public int Met_Location { get => ReadUInt16LittleEndian(Data[0x39..]); set => WriteUInt16LittleEndian(Data[0x39..], (ushort)value); } + public byte Ball { get => Data[0x36]; set => Data[0x36] = value; } + public ushort EggLocation { get => ReadUInt16LittleEndian(Data[0x37..]); set => WriteUInt16LittleEndian(Data[0x37..], value); } + public ushort MetLocation { get => ReadUInt16LittleEndian(Data[0x39..]); set => WriteUInt16LittleEndian(Data[0x39..], value); } - public byte PKRS { get => Data[0x3B]; set => Data[0x3B] = value; } + public byte PokerusState { get => Data[0x3B]; set => Data[0x3B] = value; } public ushort Ability { get => ReadUInt16LittleEndian(Data[0x3C..]); set => WriteUInt16LittleEndian(Data[0x3C..], value); } public byte AbilityNumber { get => Data[0x3E]; set => Data[0x3E] = value; } @@ -91,11 +91,11 @@ public void CopyTo(PB7 pk, PKH pkh) pk.FieldEventFatigue2 = FieldEventFatigue2; pk.Fullness = Fullness; // pk.Rank = Rank; - // pk.OT_Affection - // pk.OT_Intensity - // pk.OT_Memory - // pk.OT_TextVar - // pk.OT_Feeling + // pk.OriginalTrainerAffection + // pk.OriginalTrainerMemoryIntensity + // pk.OriginalTrainerMemory + // pk.OriginalTrainerMemoryVariable + // pk.OriginalTrainerMemoryFeeling pk.Enjoyment = Enjoyment; // pk.GeoPadding = GeoPadding; pk.AbilityNumber = AbilityNumber; @@ -120,19 +120,19 @@ public void CopyFrom(PB7 pk, PKH pkh) FieldEventFatigue2 = pk.FieldEventFatigue2; Fullness = pk.Fullness; // Rank = pk.Rank; - // OT_Affection - // OT_Intensity - // OT_Memory - // OT_TextVar - // OT_Feeling + // OriginalTrainerAffection + // OriginalTrainerMemoryIntensity + // OriginalTrainerMemory + // OriginalTrainerMemoryVariable + // OriginalTrainerMemoryFeeling Enjoyment = pk.Enjoyment; // GeoPadding = pk.GeoPadding; AbilityNumber = (byte)pk.AbilityNumber; Ability = (ushort)pk.Ability; // All other side formats have HT Language. Just fake a value. - if (pkh is { HT_Language: 0, IsUntraded: false }) - pkh.HT_Language = (byte)pk.Language; + if (pkh is { HandlingTrainerLanguage: 0, IsUntraded: false }) + pkh.HandlingTrainerLanguage = (byte)pk.Language; } public PB7 ConvertToPKM(PKH pkh) @@ -172,10 +172,10 @@ public PB7 ConvertToPKM(PKH pkh) return null; var ball = side.Ball; - if (pkh.Version is (int)GameVersion.GO) - return new GameDataPB7 { Ball = ball, Met_Location = Locations.GO7 }; - if (pkh.Version is (int)GameVersion.GP or (int)GameVersion.GE) - return new GameDataPB7 { Ball = ball, Met_Location = side.Met_Location }; + if (pkh.Version is GameVersion.GO) + return new GameDataPB7 { Ball = ball, MetLocation = Locations.GO7 }; + if (pkh.Version is GameVersion.GP or GameVersion.GE) + return new GameDataPB7 { Ball = ball, MetLocation = side.MetLocation }; var result = new GameDataPB7(); result.InitializeFrom(side, pkh); @@ -184,8 +184,8 @@ public PB7 ConvertToPKM(PKH pkh) public void InitializeFrom(IGameDataSide side, PKH pkh) { - Met_Location = side.Met_Location == Locations.Default8bNone ? 0 : side.Met_Location; - Egg_Location = side.Egg_Location == Locations.Default8bNone ? 0 : side.Egg_Location; + MetLocation = side.MetLocation != Locations.Default8bNone ? side.MetLocation : (ushort)0; + EggLocation = side.EggLocation != Locations.Default8bNone ? side.EggLocation : (ushort)0; if (side is IGameDataSplitAbility a) AbilityNumber = a.AbilityNumber; @@ -202,14 +202,14 @@ private void PopulateFromCore(PKH pkh) } private static IGameDataSide? GetNearestNeighbor(PKH pkh) => pkh.DataPK9 as IGameDataSide - ?? pkh.DataPB8 as IGameDataSide - ?? pkh.DataPK8 as IGameDataSide - ?? pkh.DataPB7; + ?? pkh.DataPB8 as IGameDataSide + ?? pkh.DataPK8 as IGameDataSide + ?? pkh.DataPB7; public static T Create(GameDataPB7 data) where T : IGameDataSide, new() => new() { Ball = data.Ball, - Met_Location = data.Met_Location, - Egg_Location = data.Egg_Location, + MetLocation = data.MetLocation, + EggLocation = data.EggLocation, }; } diff --git a/PKHeX.Core/PKM/HOME/GameDataPB8.cs b/PKHeX.Core/PKM/HOME/GameDataPB8.cs index 316bb85b8..d9a53ff67 100644 --- a/PKHeX.Core/PKM/HOME/GameDataPB8.cs +++ b/PKHeX.Core/PKM/HOME/GameDataPB8.cs @@ -44,12 +44,12 @@ public sealed class GameDataPB8 : HomeOptional1, IGameDataSide, IGameDataSp public bool GetMoveRecordFlagAny() => RecordFlag.ContainsAnyExcept(0); public void ClearMoveRecordFlags() => RecordFlag.Clear(); - public int Ball { get => Data[0x26]; set => Data[0x26] = (byte)value; } - public int Egg_Location { get => ReadUInt16LittleEndian(Data[0x27..]); set => WriteUInt16LittleEndian(Data[0x27..], (ushort)value); } - public int Met_Location { get => ReadUInt16LittleEndian(Data[0x29..]); set => WriteUInt16LittleEndian(Data[0x29..], (ushort)value); } + public byte Ball { get => Data[0x26]; set => Data[0x26] = value; } + public ushort EggLocation { get => ReadUInt16LittleEndian(Data[0x27..]); set => WriteUInt16LittleEndian(Data[0x27..], value); } + public ushort MetLocation { get => ReadUInt16LittleEndian(Data[0x29..]); set => WriteUInt16LittleEndian(Data[0x29..], value); } // Rev2 Additions - public byte PKRS { get => Data[0x2B]; set => Data[0x2B] = value; } + public byte PokerusState { get => Data[0x2B]; set => Data[0x2B] = value; } public ushort Ability { get => ReadUInt16LittleEndian(Data[0x2C..]); set => WriteUInt16LittleEndian(Data[0x2C..], value); } public byte AbilityNumber { get => Data[0x2E]; set => Data[0x2E] = value; } @@ -63,7 +63,7 @@ public void CopyTo(PB8 pk, PKH pkh) { this.CopyTo(pk); // Move Records are not settable in PB8; do not copy even if nonzero (illegal). - pk.PKRS = PKRS; + pk.PokerusState = PokerusState; pk.AbilityNumber = AbilityNumber; pk.Ability = Ability; } @@ -72,7 +72,7 @@ public void CopyFrom(PB8 pk, PKH pkh) { this.CopyFrom(pk); // Move Records are not settable in PB8; do not copy even if nonzero (illegal). - PKRS = pk.PKRS; + PokerusState = pk.PokerusState; AbilityNumber = (byte)pk.AbilityNumber; Ability = (ushort)pk.Ability; } @@ -110,11 +110,11 @@ public PB8 ConvertToPKM(PKH pkh) public void InitializeFrom(IGameDataSide side, PKH pkh) { Ball = side.Ball; - Met_Location = side.Met_Location == 0 ? Locations.Default8bNone : side.Met_Location; - Egg_Location = side.Egg_Location == 0 ? Locations.Default8bNone : side.Egg_Location; + MetLocation = side.MetLocation == 0 ? Locations.Default8bNone : side.MetLocation; + EggLocation = side.EggLocation == 0 ? Locations.Default8bNone : side.EggLocation; if (side is IPokerusStatus p) - PKRS = p.PKRS; + PokerusState = p.PokerusState; if (side is IGameDataSplitAbility a) AbilityNumber = a.AbilityNumber; else diff --git a/PKHeX.Core/PKM/HOME/GameDataPK8.cs b/PKHeX.Core/PKM/HOME/GameDataPK8.cs index 6b6cf3602..6c620c660 100644 --- a/PKHeX.Core/PKM/HOME/GameDataPK8.cs +++ b/PKHeX.Core/PKM/HOME/GameDataPK8.cs @@ -57,12 +57,12 @@ public sealed class GameDataPK8 : HomeOptional1, IGameDataSide, IGigantamax public void ClearMoveRecordFlags() => RecordFlags.Clear(); public int Palma { get => ReadInt32LittleEndian(Data[0x3B..]); set => WriteInt32LittleEndian(Data[0x3B..], value); } - public int Ball { get => Data[0x3F]; set => Data[0x3F] = (byte)value; } - public int Egg_Location { get => ReadUInt16LittleEndian(Data[0x40..]); set => WriteUInt16LittleEndian(Data[0x40..], (ushort)value); } - public int Met_Location { get => ReadUInt16LittleEndian(Data[0x42..]); set => WriteUInt16LittleEndian(Data[0x42..], (ushort)value); } + public byte Ball { get => Data[0x3F]; set => Data[0x3F] = value; } + public ushort EggLocation { get => ReadUInt16LittleEndian(Data[0x40..]); set => WriteUInt16LittleEndian(Data[0x40..], value); } + public ushort MetLocation { get => ReadUInt16LittleEndian(Data[0x42..]); set => WriteUInt16LittleEndian(Data[0x42..], value); } // Rev2 Additions - public byte PKRS { get => Data[0x44]; set => Data[0x44] = value; } + public byte PokerusState { get => Data[0x44]; set => Data[0x44] = value; } public ushort Ability { get => ReadUInt16LittleEndian(Data[0x45..]); set => WriteUInt16LittleEndian(Data[0x45..], value); } public byte AbilityNumber { get => Data[0x47]; set => Data[0x47] = value; } @@ -82,11 +82,11 @@ public void CopyTo(PK8 pk, PKH pkh) pk.Palma = Palma; PokeJob.CopyTo(pk.PokeJob); RecordFlags.CopyTo(pk.RecordFlags); - pk.PKRS = PKRS; + pk.PokerusState = PokerusState; pk.AbilityNumber = AbilityNumber; pk.Ability = Ability; - if (!IsOriginallySWSH(pkh.Version, pk.Met_Location)) + if (!IsOriginallySWSH(pkh.Version, pk.MetLocation)) pk.Version = LocationsHOME.GetVersionSWSH(pkh.Version); } @@ -100,7 +100,7 @@ public void CopyFrom(PK8 pk, PKH pkh) Palma = pk.Palma; pk.PokeJob.CopyTo(PokeJob); pk.RecordFlags.CopyTo(RecordFlags); - PKRS = pk.PKRS; + PokerusState = pk.PokerusState; AbilityNumber = (byte)pk.AbilityNumber; Ability = (ushort)pk.Ability; } @@ -108,7 +108,7 @@ public void CopyFrom(PK8 pk, PKH pkh) public void CopyFrom(PK7 pk, PKH pkh) { this.CopyFrom(pk); - PKRS = pk.PKRS; + PokerusState = pk.PokerusState; AbilityNumber = (byte)pk.AbilityNumber; Ability = (ushort)pk.Ability; @@ -173,20 +173,20 @@ public void InitializeFrom(IGameDataSide side, PKH pkh) { // BD/SP->SW/SH: Set the Met Location to the magic Location, set the Egg Location to 0 if -1, otherwise BDSPEgg // (0 is a valid location, but no eggs can be EggMet there -- only hatched.) - // PLA->SWSH: Set the Met Location to the magic Location, set the Egg Location to 0 (no eggs in game). - var ver = pkh.Version; - var met = side.Met_Location; + // PLA->SW/SH: Set the Met Location to the magic Location, set the Egg Location to 0 (no eggs in game). + var version = pkh.Version; + var met = side.MetLocation; var ball = GetBall(side.Ball); - var egg = GetEggLocation(side.Egg_Location); - if (!IsOriginallySWSH(ver, met)) - RemapMetEgg(ver, ref met, ref egg); + var egg = GetEggLocation(side.EggLocation); + if (!IsOriginallySWSH(version, met)) + RemapMetEgg(version, ref met, ref egg); Ball = ball; - Met_Location = met; - Egg_Location = egg; + MetLocation = met; + EggLocation = egg; if (side is IGameDataSplitAbility a) AbilityNumber = a.AbilityNumber; if (side is IPokerusStatus p) - PKRS = p.PKRS; + PokerusState = p.PokerusState; PopulateFromCore(pkh); } @@ -197,18 +197,18 @@ private void PopulateFromCore(PKH pkh) Ability = (ushort)pi.GetAbilityAtIndex(AbilityNumber >> 1); } - private static void RemapMetEgg(int ver, ref int met, ref int egg) + private static void RemapMetEgg(GameVersion version, ref ushort met, ref ushort egg) { - var remap = LocationsHOME.GetMetSWSH((ushort)met, ver); + var remap = LocationsHOME.GetMetSWSH(met, version); if (remap == met) return; met = remap; - egg = egg is 0 or Locations.Default8bNone ? 0 : LocationsHOME.SWSHEgg; + egg = egg is not (0 or Locations.Default8bNone) ? LocationsHOME.SWSHEgg : (ushort)0; } - private static bool IsOriginallySWSH(int ver, int loc) => ver is (int)GameVersion.SW or (int)GameVersion.SH && !IsFakeMetLocation(loc); - private static bool IsFakeMetLocation(int met) => LocationsHOME.IsLocationSWSH(met); - private static int GetBall(int ball) => ball > (int)Core.Ball.Beast ? 4 : ball; - private static int GetEggLocation(int egg) => egg == Locations.Default8bNone ? 0 : egg; + private static bool IsOriginallySWSH(GameVersion version, ushort loc) => version is GameVersion.SW or GameVersion.SH && !IsFakeMetLocation(loc); + private static bool IsFakeMetLocation(ushort met) => LocationsHOME.IsLocationSWSH(met); + private static byte GetBall(byte ball) => ball > (byte)Core.Ball.Beast ? (byte)4 : ball; + private static ushort GetEggLocation(ushort egg) => egg != Locations.Default8bNone ? egg : (ushort)0; } diff --git a/PKHeX.Core/PKM/HOME/GameDataPK9.cs b/PKHeX.Core/PKM/HOME/GameDataPK9.cs index d372e5033..5f9637dcd 100644 --- a/PKHeX.Core/PKM/HOME/GameDataPK9.cs +++ b/PKHeX.Core/PKM/HOME/GameDataPK9.cs @@ -40,9 +40,9 @@ public sealed class GameDataPK9 : HomeOptional1, IGameDataSide, IScaledSize public ushort RelearnMove4 { get => ReadUInt16LittleEndian(Data[0x17..]); set => WriteUInt16LittleEndian(Data[0x17..], value); } public MoveType TeraTypeOriginal { get => (MoveType)Data[0x19]; set => Data[0x19] = (byte)value; } public MoveType TeraTypeOverride { get => (MoveType)Data[0x1A]; set => Data[0x1A] = (byte)value; } - public int Ball { get => Data[0x1B]; set => Data[0x1B] = (byte)value; } - public int Egg_Location { get => ReadUInt16LittleEndian(Data[0x1C..]); set => WriteUInt16LittleEndian(Data[0x1C..], (ushort)value); } - public int Met_Location { get => ReadUInt16LittleEndian(Data[0x1E..]); set => WriteUInt16LittleEndian(Data[0x1E..], (ushort)value); } + public byte Ball { get => Data[0x1B]; set => Data[0x1B] = (byte)value; } + public ushort EggLocation { get => ReadUInt16LittleEndian(Data[0x1C..]); set => WriteUInt16LittleEndian(Data[0x1C..], value); } + public ushort MetLocation { get => ReadUInt16LittleEndian(Data[0x1E..]); set => WriteUInt16LittleEndian(Data[0x1E..], value); } private const int RecordStartBase = 0x20; internal const int COUNT_RECORD_BASE = PK9.COUNT_RECORD_BASE; // Up to 200 TM flags, but not all are used. @@ -188,8 +188,8 @@ public PK9 ConvertToPKM(PKH pkh) public void InitializeFrom(IGameDataSide side, PKH pkh) { Ball = side.Ball; - Met_Location = side.Met_Location == Locations.Default8bNone ? 0 : side.Met_Location; - Egg_Location = side.Egg_Location == Locations.Default8bNone ? 0 : side.Egg_Location; + MetLocation = side.MetLocation != Locations.Default8bNone ? side.MetLocation : (ushort)0; + EggLocation = side.EggLocation != Locations.Default8bNone ? side.EggLocation : (ushort)0; if (side is IScaledSize3 s3) Scale = s3.Scale; @@ -205,7 +205,7 @@ public void InitializeFrom(IGameDataSide side, PKH pkh) private void PopulateFromCore(PKH pkh) { - Obedience_Level = (byte)pkh.Met_Level; + Obedience_Level = pkh.MetLevel; var pi = PersonalTable.SV.GetFormEntry(pkh.Species, pkh.Form); Ability = (ushort)pi.GetAbilityAtIndex(AbilityNumber >> 1); diff --git a/PKHeX.Core/PKM/HOME/HomeCrypto.cs b/PKHeX.Core/PKM/HOME/HomeCrypto.cs index b3fe06a43..c7d4c870f 100644 --- a/PKHeX.Core/PKM/HOME/HomeCrypto.cs +++ b/PKHeX.Core/PKM/HOME/HomeCrypto.cs @@ -157,11 +157,11 @@ private static bool IsEncryptedCore1(ReadOnlySpan data) // Strings should be \0000 terminated if decrypted. // Any non-zero value is a sign of encryption. if (ReadUInt16LittleEndian(core[0xB5..]) != 0) // OT - return true; // OT_Name final terminator should be 0 if decrypted. + return true; // OriginalTrainerName final terminator should be 0 if decrypted. if (ReadUInt16LittleEndian(core[0x60..]) != 0) // Nick return true; // Nickname final terminator should be 0 if decrypted. if (ReadUInt16LittleEndian(core[0x88..]) != 0) // HT - return true; // HT_Name final terminator should be 0 if decrypted. + return true; // HandlingTrainerName final terminator should be 0 if decrypted. //// Fall back to checksum. //return ReadUInt32LittleEndian(data[0xA..0xE]) == GetChecksum1(data); @@ -172,11 +172,11 @@ private static bool IsEncryptedCore2(ReadOnlySpan data) { var core = data.Slice(SIZE_1HEADER + 2, SIZE_2CORE); if (ReadUInt16LittleEndian(core[0xB1..]) != 0) - return true; // OT_Name final terminator should be 0 if decrypted. + return true; // OriginalTrainerName final terminator should be 0 if decrypted. if (ReadUInt16LittleEndian(core[0x5C..]) != 0) return true; // Nickname final terminator should be 0 if decrypted. if (ReadUInt16LittleEndian(core[0x84..]) != 0) - return true; // HT_Name final terminator should be 0 if decrypted. + return true; // HandlingTrainerName final terminator should be 0 if decrypted. //// Fall back to checksum. //return ReadUInt32LittleEndian(data[0xA..0xE]) == GetChecksum1(data); diff --git a/PKHeX.Core/PKM/HOME/IGameDataSide.cs b/PKHeX.Core/PKM/HOME/IGameDataSide.cs index 15444623b..a8369ca5e 100644 --- a/PKHeX.Core/PKM/HOME/IGameDataSide.cs +++ b/PKHeX.Core/PKM/HOME/IGameDataSide.cs @@ -45,9 +45,9 @@ public interface IGameDataSide ushort Move2 { get; set; } int Move2_PP { get; set; } int Move2_PPUps { get; set; } ushort RelearnMove2 { get; set; } ushort Move3 { get; set; } int Move3_PP { get; set; } int Move3_PPUps { get; set; } ushort RelearnMove3 { get; set; } ushort Move4 { get; set; } int Move4_PP { get; set; } int Move4_PPUps { get; set; } ushort RelearnMove4 { get; set; } - int Ball { get; set; } - int Met_Location { get; set; } - int Egg_Location { get; set; } + byte Ball { get; set; } + ushort MetLocation { get; set; } + ushort EggLocation { get; set; } /// /// Gets the personal info for the input arguments. @@ -69,8 +69,8 @@ public static void CopyTo(this IGameDataSide data, PKM pk) pk.Move3 = data.Move3; pk.Move3_PP = data.Move3_PP; pk.Move3_PPUps = data.Move3_PPUps; pk.RelearnMove3 = data.RelearnMove3; pk.Move4 = data.Move4; pk.Move4_PP = data.Move4_PP; pk.Move4_PPUps = data.Move4_PPUps; pk.RelearnMove4 = data.RelearnMove4; pk.Ball = data.Ball; - pk.Met_Location = data.Met_Location; - pk.Egg_Location = data.Egg_Location; + pk.MetLocation = data.MetLocation; + pk.EggLocation = data.EggLocation; } /// @@ -85,8 +85,8 @@ public static void CopyTo(this IGameDataSide data, IGameDataSide pk) pk.Move3 = data.Move3; pk.Move3_PP = data.Move3_PP; pk.Move3_PPUps = data.Move3_PPUps; pk.RelearnMove3 = data.RelearnMove3; pk.Move4 = data.Move4; pk.Move4_PP = data.Move4_PP; pk.Move4_PPUps = data.Move4_PPUps; pk.RelearnMove4 = data.RelearnMove4; pk.Ball = data.Ball; - pk.Met_Location = data.Met_Location; - pk.Egg_Location = data.Egg_Location; + pk.MetLocation = data.MetLocation; + pk.EggLocation = data.EggLocation; } /// @@ -101,8 +101,8 @@ public static void CopyFrom(this IGameDataSide data, PKM pk) data.Move3 = pk.Move3; data.Move3_PP = pk.Move3_PP; data.Move3_PPUps = pk.Move3_PPUps; data.RelearnMove3 = pk.RelearnMove3; data.Move4 = pk.Move4; data.Move4_PP = pk.Move4_PP; data.Move4_PPUps = pk.Move4_PPUps; data.RelearnMove4 = pk.RelearnMove4; data.Ball = pk.Ball; - data.Met_Location = pk.Met_Location; - data.Egg_Location = pk.Egg_Location; + data.MetLocation = pk.MetLocation; + data.EggLocation = pk.EggLocation; } /// diff --git a/PKHeX.Core/PKM/HOME/IPokerusStatus.cs b/PKHeX.Core/PKM/HOME/IPokerusStatus.cs index 23e771e3c..397faaac9 100644 --- a/PKHeX.Core/PKM/HOME/IPokerusStatus.cs +++ b/PKHeX.Core/PKM/HOME/IPokerusStatus.cs @@ -8,5 +8,5 @@ public interface IPokerusStatus /// /// Pokerus Strain and Duration /// - byte PKRS { get; set; } + byte PokerusState { get; set; } } diff --git a/PKHeX.Core/PKM/HOME/PKH.cs b/PKHeX.Core/PKM/HOME/PKH.cs index 97756e61f..54fa84071 100644 --- a/PKHeX.Core/PKM/HOME/PKH.cs +++ b/PKHeX.Core/PKM/HOME/PKH.cs @@ -78,10 +78,10 @@ private static byte[] DecryptHome(byte[] data) private const int GameDataStart = HomeCrypto.SIZE_1HEADER + 2 + HomeCrypto.SIZE_CORE + 2; - public override Span Nickname_Trash => Core.Nickname_Trash; - public override Span OT_Trash => Core.OT_Trash; - public override Span HT_Trash => Core.HT_Trash; - public override bool IsUntraded => ReadUInt16LittleEndian(HT_Trash) == 0; // immediately terminated HT_Name data (\0) + public override Span NicknameTrash => Core.NicknameTrash; + public override Span OriginalTrainerTrash => Core.OriginalTrainerTrash; + public override Span HandlingTrainerTrash => Core.HandlingTrainerTrash; + public override bool IsUntraded => ReadUInt16LittleEndian(HandlingTrainerTrash) == 0; // immediately terminated HandlingTrainerName data (\0) #region Core @@ -96,10 +96,10 @@ private static byte[] DecryptHome(byte[] data) public bool Favorite { get => Core.IsFavorite; set => Core.IsFavorite = value; } public ushort MarkingValue { get => Core.MarkingValue; set => Core.MarkingValue = value; } public override uint PID { get => Core.PID; set => Core.PID = value; } - public override int Nature { get => Core.Nature; set => Core.Nature = value; } - public override int StatNature { get => Core.StatNature; set => Core.StatNature = value; } + public override Nature Nature { get => Core.Nature; set => Core.Nature = value; } + public override Nature StatNature { get => Core.StatNature; set => Core.StatNature = value; } public override bool FatefulEncounter { get => Core.FatefulEncounter; set => Core.FatefulEncounter = value; } - public override int Gender { get => Core.Gender; set => Core.Gender = value; } + public override byte Gender { get => Core.Gender; set => Core.Gender = value; } public override byte Form { get => Core.Form; set => Core.Form = value; } public override int EV_HP { get => Core.EV_HP; set => Core.EV_HP = value; } public override int EV_ATK { get => Core.EV_ATK; set => Core.EV_ATK = value; } @@ -107,12 +107,12 @@ private static byte[] DecryptHome(byte[] data) public override int EV_SPE { get => Core.EV_SPE; set => Core.EV_SPE = value; } public override int EV_SPA { get => Core.EV_SPA; set => Core.EV_SPA = value; } public override int EV_SPD { get => Core.EV_SPD; set => Core.EV_SPD = value; } - public byte CNT_Cool { get => Core.CNT_Cool; set => Core.CNT_Cool = value; } - public byte CNT_Beauty { get => Core.CNT_Beauty; set => Core.CNT_Beauty = value; } - public byte CNT_Cute { get => Core.CNT_Cute; set => Core.CNT_Cute = value; } - public byte CNT_Smart { get => Core.CNT_Smart; set => Core.CNT_Smart = value; } - public byte CNT_Tough { get => Core.CNT_Tough; set => Core.CNT_Tough = value; } - public byte CNT_Sheen { get => Core.CNT_Sheen; set => Core.CNT_Sheen = value; } + public byte ContestCool { get => Core.ContestCool; set => Core.ContestCool = value; } + public byte ContestBeauty { get => Core.ContestBeauty; set => Core.ContestBeauty = value; } + public byte ContestCute { get => Core.ContestCute; set => Core.ContestCute = value; } + public byte ContestSmart { get => Core.ContestSmart; set => Core.ContestSmart = value; } + public byte ContestTough { get => Core.ContestTough; set => Core.ContestTough = value; } + public byte ContestSheen { get => Core.ContestSheen; set => Core.ContestSheen = value; } public byte HeightScalar { get => Core.HeightScalar; set => Core.HeightScalar = value; } public byte WeightScalar { get => Core.WeightScalar; set => Core.WeightScalar = value; } public override int Stat_HPCurrent { get => Core.Stat_HPCurrent; set => Core.Stat_HPCurrent = value; } @@ -125,36 +125,36 @@ private static byte[] DecryptHome(byte[] data) public override bool IsEgg { get => Core.IsEgg; set => Core.IsEgg = value; } public override bool IsNicknamed { get => Core.IsNicknamed; set => Core.IsNicknamed = value; } public override int Status_Condition { get => Core.Status_Condition; set => Core.Status_Condition = value; } - public override int HT_Gender { get => Core.HT_Gender; set => Core.HT_Gender = value; } - public byte HT_Language { get => Core.HT_Language; set => Core.HT_Language = value; } - public override int CurrentHandler { get => Core.CurrentHandler; set => Core.CurrentHandler = value; } - public int HT_TrainerID { get => Core.HT_TrainerID; set => Core.HT_TrainerID = value; } - public override int HT_Friendship { get => Core.HT_Friendship; set => Core.HT_Friendship = value; } - public byte HT_Intensity { get => Core.HT_Intensity; set => Core.HT_Intensity = value; } - public byte HT_Memory { get => Core.HT_Memory; set => Core.HT_Memory = value; } - public byte HT_Feeling { get => Core.HT_Feeling; set => Core.HT_Feeling = value; } - public ushort HT_TextVar { get => Core.HT_TextVar; set => Core.HT_TextVar = value; } - public override int Version { get => Core.Version; set => Core.Version = value; } - public byte BattleVersion { get => Core.BattleVersion; set => Core.BattleVersion = value; } + public override byte HandlingTrainerGender { get => Core.HandlingTrainerGender; set => Core.HandlingTrainerGender = value; } + public byte HandlingTrainerLanguage { get => Core.HandlingTrainerLanguage; set => Core.HandlingTrainerLanguage = value; } + public override byte CurrentHandler { get => Core.CurrentHandler; set => Core.CurrentHandler = value; } + public ushort HandlingTrainerID { get => Core.HandlingTrainerID; set => Core.HandlingTrainerID = value; } + public override byte HandlingTrainerFriendship { get => Core.HandlingTrainerFriendship; set => Core.HandlingTrainerFriendship = value; } + public byte HandlingTrainerMemoryIntensity { get => Core.HandlingTrainerMemoryIntensity; set => Core.HandlingTrainerMemoryIntensity = value; } + public byte HandlingTrainerMemory { get => Core.HandlingTrainerMemory; set => Core.HandlingTrainerMemory = value; } + public byte HandlingTrainerMemoryFeeling { get => Core.HandlingTrainerMemoryFeeling; set => Core.HandlingTrainerMemoryFeeling = value; } + public ushort HandlingTrainerMemoryVariable { get => Core.HandlingTrainerMemoryVariable; set => Core.HandlingTrainerMemoryVariable = value; } + public override GameVersion Version { get => Core.Version; set => Core.Version = value; } + public GameVersion BattleVersion { get => Core.BattleVersion; set => Core.BattleVersion = value; } public override int Language { get => Core.Language; set => Core.Language = value; } public uint FormArgument { get => Core.FormArgument; set => Core.FormArgument = value; } public byte FormArgumentRemain { get => Core.FormArgumentRemain; set => Core.FormArgumentRemain = value; } public byte FormArgumentElapsed { get => Core.FormArgumentElapsed; set => Core.FormArgumentElapsed = value; } public byte FormArgumentMaximum { get => Core.FormArgumentMaximum; set => Core.FormArgumentMaximum = value; } public sbyte AffixedRibbon { get => Core.AffixedRibbon; set => Core.AffixedRibbon = value; } - public override int OT_Friendship { get => Core.OT_Friendship; set => Core.OT_Friendship = value; } - public byte OT_Intensity { get => Core.OT_Intensity; set => Core.OT_Intensity = value; } - public byte OT_Memory { get => Core.OT_Memory; set => Core.OT_Memory = value; } - public ushort OT_TextVar { get => Core.OT_TextVar; set => Core.OT_TextVar = value; } - public byte OT_Feeling { get => Core.OT_Feeling; set => Core.OT_Feeling = value; } - public override int Egg_Year { get => Core.Egg_Year; set => Core.Egg_Year = value; } - public override int Egg_Month { get => Core.Egg_Month; set => Core.Egg_Month = value; } - public override int Egg_Day { get => Core.Egg_Day; set => Core.Egg_Day = value; } - public override int Met_Year { get => Core.Met_Year; set => Core.Met_Year = value; } - public override int Met_Month { get => Core.Met_Month; set => Core.Met_Month = value; } - public override int Met_Day { get => Core.Met_Day; set => Core.Met_Day = value; } - public override int Met_Level { get => Core.Met_Level; set => Core.Met_Level = value; } - public override int OT_Gender { get => Core.OT_Gender; set => Core.OT_Gender = value; } + public override byte OriginalTrainerFriendship { get => Core.OriginalTrainerFriendship; set => Core.OriginalTrainerFriendship = value; } + public byte OriginalTrainerMemoryIntensity { get => Core.OriginalTrainerMemoryIntensity; set => Core.OriginalTrainerMemoryIntensity = value; } + public byte OriginalTrainerMemory { get => Core.OriginalTrainerMemory; set => Core.OriginalTrainerMemory = value; } + public ushort OriginalTrainerMemoryVariable { get => Core.OriginalTrainerMemoryVariable; set => Core.OriginalTrainerMemoryVariable = value; } + public byte OriginalTrainerMemoryFeeling { get => Core.OriginalTrainerMemoryFeeling; set => Core.OriginalTrainerMemoryFeeling = value; } + public override byte EggYear { get => Core.EggYear; set => Core.EggYear = value; } + public override byte EggMonth { get => Core.EggMonth; set => Core.EggMonth = value; } + public override byte EggDay { get => Core.EggDay; set => Core.EggDay = value; } + public override byte MetYear { get => Core.MetYear; set => Core.MetYear = value; } + public override byte MetMonth { get => Core.MetMonth; set => Core.MetMonth = value; } + public override byte MetDay { get => Core.MetDay; set => Core.MetDay = value; } + public override byte MetLevel { get => Core.MetLevel; set => Core.MetLevel = value; } + public override byte OriginalTrainerGender { get => Core.OriginalTrainerGender; set => Core.OriginalTrainerGender = value; } public byte HyperTrainFlags { get => Core.HyperTrainFlags; set => Core.HyperTrainFlags = value; } public bool HT_HP { get => Core.HT_HP; set => Core.HT_HP = value; } public bool HT_ATK { get => Core.HT_ATK; set => Core.HT_ATK = value; } @@ -165,8 +165,8 @@ private static byte[] DecryptHome(byte[] data) public override int HeldItem { get => Core.HeldItem; set => Core.HeldItem = value; } public override string Nickname { get => Core.Nickname; set => Core.Nickname = value; } - public override string OT_Name { get => Core.OT_Name; set => Core.OT_Name = value; } - public override string HT_Name { get => Core.HT_Name; set => Core.HT_Name = value; } + public override string OriginalTrainerName { get => Core.OriginalTrainerName; set => Core.OriginalTrainerName = value; } + public override string HandlingTrainerName { get => Core.HandlingTrainerName; set => Core.HandlingTrainerName = value; } public int MarkingCount => Core.MarkingCount; public int RibbonCount => Core.RibbonCount; @@ -185,14 +185,14 @@ private static byte[] DecryptHome(byte[] data) #endregion // Used to be in Core, now we just don't bother. - public override int PKRS_Days { get => 0; set { } } - public override int PKRS_Strain { get => 0; set { } } + public override int PokerusDays { get => 0; set { } } + public override int PokerusStrain { get => 0; set { } } public override int Ability { get => 0; set { } } public override int AbilityNumber { get => 0; set { } } #region Calculated - public override int CurrentFriendship { get => CurrentHandler == 0 ? OT_Friendship : HT_Friendship; set { if (CurrentHandler == 0) OT_Friendship = value; else HT_Friendship = value; } } + public override byte CurrentFriendship { get => CurrentHandler == 0 ? OriginalTrainerFriendship : HandlingTrainerFriendship; set { if (CurrentHandler == 0) OriginalTrainerFriendship = value; else HandlingTrainerFriendship = value; } } public override uint PSV => ((PID >> 16) ^ (PID & 0xFFFF)) >> 4; public override uint TSV => (uint)(TID16 ^ SID16) >> 4; @@ -215,13 +215,13 @@ private static byte[] DecryptHome(byte[] data) public override int Move3_PPUps { get => LatestGameData.Move3_PPUps; set => LatestGameData.Move3_PPUps = value; } public override int Move4_PPUps { get => LatestGameData.Move4_PPUps; set => LatestGameData.Move4_PPUps = value; } - public override int Ball { get => LatestGameData.Ball; set => LatestGameData.Ball = value; } - public override int Met_Location { get => LatestGameData.Met_Location; set => LatestGameData.Met_Location = value; } - public override int Egg_Location { get => LatestGameData.Egg_Location; set => LatestGameData.Egg_Location = value; } + public override byte Ball { get => LatestGameData.Ball; set => LatestGameData.Ball = value; } + public override ushort MetLocation { get => LatestGameData.MetLocation; set => LatestGameData.MetLocation = value; } + public override ushort EggLocation { get => LatestGameData.EggLocation; set => LatestGameData.EggLocation = value; } #endregion - public override int Stat_Level { get => CurrentLevel; set => CurrentLevel = value; } + public override byte Stat_Level { get => CurrentLevel; set => CurrentLevel = value; } public override int Stat_HPMax { get => 0; set { } } public override int Stat_ATK { get => 0; set { } } public override int Stat_DEF { get => 0; set { } } @@ -240,7 +240,7 @@ private static byte[] DecryptHome(byte[] data) public override int MaxAbilityID => Legal.MaxAbilityID_8a; public override int MaxItemID => Legal.MaxItemID_8a; public override int MaxBallID => Legal.MaxBallID_8a; - public override int MaxGameID => Legal.MaxGameID_HOME; + public override GameVersion MaxGameID => Legal.MaxGameID_HOME; #endregion @@ -324,27 +324,27 @@ public override PKH Clone() => new((byte[])Data.Clone()) private IGameDataSide CreateFallback() => Version switch { - (int)GP or (int)GE => DataPB7 ??= new(), - (int)BD or (int)SP => DataPB8 ??= new(), - (int)PLA => DataPA8 ??= new(), - (int)SL or (int)VL => DataPK9 ??= new(), + GP or GE => DataPB7 ??= new(), + BD or SP => DataPB8 ??= new(), + PLA => DataPA8 ??= new(), + SL or VL => DataPK9 ??= new(), _ => DataPK8 ??= new(), }; private IGameDataSide? OriginalGameData() => Version switch { - (int)GameVersion.GO when DataPB7 is not null => DataPB7, - (int)GP or (int)GE => DataPB7, - (int)BD or (int)SP => DataPB8, - (int)PLA => DataPA8, - (int)SL or (int)VL => DataPK9, + GameVersion.GO when DataPB7 is not null => DataPB7, + GP or GE => DataPB7, + BD or SP => DataPB8, + PLA => DataPA8, + SL or VL => DataPK9, // SW/SH can be confused with others if we didn't seed with the original transfer data. - (int)SW or (int)SH => DataPK8 switch + SW or SH => DataPK8 switch { - { Met_Location: LocationsHOME.SWLA } => DataPA8, - { Met_Location: LocationsHOME.SWBD or LocationsHOME.SHSP } => DataPB8, - { Met_Location: LocationsHOME.SWSL or LocationsHOME.SHVL } => DataPK9, + { MetLocation: LocationsHOME.SWLA } => DataPA8, + { MetLocation: LocationsHOME.SWBD or LocationsHOME.SHSP } => DataPB8, + { MetLocation: LocationsHOME.SWSL or LocationsHOME.SHVL } => DataPK9, _ => DataPK8, }, diff --git a/PKHeX.Core/PKM/Interfaces/IAffection.cs b/PKHeX.Core/PKM/Interfaces/IAffection.cs index 3dfb7a606..3410aef3f 100644 --- a/PKHeX.Core/PKM/Interfaces/IAffection.cs +++ b/PKHeX.Core/PKM/Interfaces/IAffection.cs @@ -1,10 +1,10 @@ namespace PKHeX.Core; /// -/// Exposes and properties used by Gen6/7. +/// Exposes and properties used by Gen6/7. /// public interface IAffection { - byte OT_Affection { get; set; } - byte HT_Affection { get; set; } + byte OriginalTrainerAffection { get; set; } + byte HandlingTrainerAffection { get; set; } } diff --git a/PKHeX.Core/PKM/Interfaces/IAwakened.cs b/PKHeX.Core/PKM/Interfaces/IAwakened.cs index 287f75816..3841dcac7 100644 --- a/PKHeX.Core/PKM/Interfaces/IAwakened.cs +++ b/PKHeX.Core/PKM/Interfaces/IAwakened.cs @@ -233,11 +233,11 @@ public static void SetExpectedMinimumAVs(Span result, PB7 pk) { // GO Park transfers start with 2 AVs for all stats. // Every other encounter is either all 0, or can legally start at 0 (trades). - if (pk.Version == (int)GameVersion.GO) + if (pk.Version == GameVersion.GO) result.Fill(GP1.InitialAV); // Leveling up in-game adds 1 AV to a "random" index. - var start = pk.Met_Level; + var start = pk.MetLevel; var end = pk.CurrentLevel; if (start == end) return; diff --git a/PKHeX.Core/PKM/Interfaces/IBattleVersion.cs b/PKHeX.Core/PKM/Interfaces/IBattleVersion.cs index 4b8e26a71..84f30c892 100644 --- a/PKHeX.Core/PKM/Interfaces/IBattleVersion.cs +++ b/PKHeX.Core/PKM/Interfaces/IBattleVersion.cs @@ -10,7 +10,7 @@ public interface IBattleVersion /// /// Indicates which the Pokémon's moves were reset on. /// - byte BattleVersion { get; set; } + GameVersion BattleVersion { get; set; } } public static class BattleVersionExtensions @@ -21,7 +21,7 @@ public static class BattleVersionExtensions public static bool IsBattleVersionValid(this T pk, EvolutionHistory h) where T : PKM, IBattleVersion => pk.BattleVersion switch { 0 => true, - (int)GameVersion.SW or (int)GameVersion.SH => h.HasVisitedSWSH && LocationsHOME.GetVersionSWSH(pk.Version) is not ((int)GameVersion.SW or (int)GameVersion.SH), + GameVersion.SW or GameVersion.SH => h.HasVisitedSWSH && LocationsHOME.GetVersionSWSH(pk.Version) is not (GameVersion.SW or GameVersion.SH), _ => false, }; @@ -42,7 +42,7 @@ public static void AdaptToBattleVersion(this IBattleVersion v, PKM pk, GameVersi source.SetEncounterMoves(pk.Species, pk.Form, pk.CurrentLevel, moves); pk.SetMoves(moves); pk.FixMoves(); - v.BattleVersion = (byte)version; + v.BattleVersion = version; } /// @@ -50,13 +50,12 @@ public static void AdaptToBattleVersion(this IBattleVersion v, PKM pk, GameVersi /// public static int GetMinGeneration(this IBattleVersion v) { - var ver = v.BattleVersion; - if (ver == 0) + var version = v.BattleVersion; + if (version == 0) return 1; - var game = (GameVersion) ver; - if (!game.IsValidSavedVersion()) + if (!version.IsValidSavedVersion()) return -1; - var gen = game.GetGeneration(); + var gen = version.GetGeneration(); if (gen >= 8) return gen; return -1; diff --git a/PKHeX.Core/PKM/Interfaces/ICaughtData2.cs b/PKHeX.Core/PKM/Interfaces/ICaughtData2.cs index 4280130c0..1d69caa64 100644 --- a/PKHeX.Core/PKM/Interfaces/ICaughtData2.cs +++ b/PKHeX.Core/PKM/Interfaces/ICaughtData2.cs @@ -6,8 +6,8 @@ public interface ICaughtData2 { ushort CaughtData { get; set; } - int Met_TimeOfDay { get; set; } - int Met_Level { get; set; } - int OT_Gender { get; set; } - int Met_Location { get; set; } + int MetTimeOfDay { get; set; } + byte MetLevel { get; set; } + byte OriginalTrainerGender { get; set; } + ushort MetLocation { get; set; } } diff --git a/PKHeX.Core/PKM/Interfaces/IContestStats.cs b/PKHeX.Core/PKM/Interfaces/IContestStats.cs index db6756792..7a4d2c229 100644 --- a/PKHeX.Core/PKM/Interfaces/IContestStats.cs +++ b/PKHeX.Core/PKM/Interfaces/IContestStats.cs @@ -5,10 +5,10 @@ namespace PKHeX.Core; /// public interface IContestStats : IContestStatsReadOnly { - new byte CNT_Cool { get; set; } - new byte CNT_Beauty { get; set; } - new byte CNT_Cute { get; set; } - new byte CNT_Smart { get; set; } - new byte CNT_Tough { get; set; } - new byte CNT_Sheen { get; set; } + new byte ContestCool { get; set; } + new byte ContestBeauty { get; set; } + new byte ContestCute { get; set; } + new byte ContestSmart { get; set; } + new byte ContestTough { get; set; } + new byte ContestSheen { get; set; } } diff --git a/PKHeX.Core/PKM/Interfaces/IFormArgument.cs b/PKHeX.Core/PKM/Interfaces/IFormArgument.cs index 160159eb1..50e9839ad 100644 --- a/PKHeX.Core/PKM/Interfaces/IFormArgument.cs +++ b/PKHeX.Core/PKM/Interfaces/IFormArgument.cs @@ -113,7 +113,7 @@ public static void ChangeFormArgument(this IFormArgument f, ushort species, byte /// Context to check with. public static uint GetFormArgumentMax(ushort species, byte form, EntityContext context) { - int gen = context.Generation(); + var gen = context.Generation(); if (gen <= 5) return 0; diff --git a/PKHeX.Core/PKM/Interfaces/IHandlerLanguage.cs b/PKHeX.Core/PKM/Interfaces/IHandlerLanguage.cs index f059ea096..a4c51506d 100644 --- a/PKHeX.Core/PKM/Interfaces/IHandlerLanguage.cs +++ b/PKHeX.Core/PKM/Interfaces/IHandlerLanguage.cs @@ -8,5 +8,5 @@ public interface IHandlerLanguage /// /// Trainer game language of the latest handler (not OT). /// - byte HT_Language { get; set; } + byte HandlingTrainerLanguage { get; set; } } diff --git a/PKHeX.Core/PKM/Interfaces/IHyperTrain.cs b/PKHeX.Core/PKM/Interfaces/IHyperTrain.cs index fa1a1a84b..dd413feeb 100644 --- a/PKHeX.Core/PKM/Interfaces/IHyperTrain.cs +++ b/PKHeX.Core/PKM/Interfaces/IHyperTrain.cs @@ -138,7 +138,7 @@ public static void SetSuggestedHyperTrainingData(this PKM pk) }; /// - public static bool IsHyperTrainingAvailable(this EntityContext c, int currentLevel) + public static bool IsHyperTrainingAvailable(this EntityContext c, byte currentLevel) { var min = GetHyperTrainMinLevel(c); return currentLevel >= min; diff --git a/PKHeX.Core/PKM/Interfaces/IMemoryHT.cs b/PKHeX.Core/PKM/Interfaces/IMemoryHT.cs index a4cc21f7d..df64ef605 100644 --- a/PKHeX.Core/PKM/Interfaces/IMemoryHT.cs +++ b/PKHeX.Core/PKM/Interfaces/IMemoryHT.cs @@ -5,10 +5,10 @@ /// public interface IMemoryHT { - byte HT_Memory { get; set; } - ushort HT_TextVar { get; set; } - byte HT_Feeling { get; set; } - byte HT_Intensity { get; set; } + byte HandlingTrainerMemory { get; set; } + ushort HandlingTrainerMemoryVariable { get; set; } + byte HandlingTrainerMemoryFeeling { get; set; } + byte HandlingTrainerMemoryIntensity { get; set; } } public static partial class Extensions @@ -18,10 +18,10 @@ public static partial class Extensions /// public static void SetTradeMemoryHT6(this IMemoryHT ht, bool bank) { - ht.HT_Memory = 4; // Link trade to [VAR: General Location] - ht.HT_TextVar = bank ? (byte)0 : (byte)9; // Somewhere (Bank) : Pokécenter (Trade) - ht.HT_Intensity = 1; - ht.HT_Feeling = MemoryContext6.GetRandomFeeling6(4, bank ? 10 : 20); // 0-9 Bank, 0-19 Trade + ht.HandlingTrainerMemory = 4; // Link trade to [VAR: General Location] + ht.HandlingTrainerMemoryVariable = bank ? (byte)0 : (byte)9; // Somewhere (Bank) : Pokécenter (Trade) + ht.HandlingTrainerMemoryIntensity = 1; + ht.HandlingTrainerMemoryFeeling = MemoryContext6.GetRandomFeeling6(4, bank ? 10 : 20); // 0-9 Bank, 0-19 Trade } /// @@ -29,10 +29,10 @@ public static void SetTradeMemoryHT6(this IMemoryHT ht, bool bank) /// public static void SetTradeMemoryHT8(this IMemoryHT ht) { - ht.HT_Memory = 4; // Link trade to [VAR: General Location] - ht.HT_TextVar = 9; // Pokécenter (Trade) - ht.HT_Intensity = 1; - ht.HT_Feeling = MemoryContext8.GetRandomFeeling8(4, 20); // 0-19 Trade + ht.HandlingTrainerMemory = 4; // Link trade to [VAR: General Location] + ht.HandlingTrainerMemoryVariable = 9; // Pokécenter (Trade) + ht.HandlingTrainerMemoryIntensity = 1; + ht.HandlingTrainerMemoryFeeling = MemoryContext8.GetRandomFeeling8(4, 20); // 0-19 Trade } /// @@ -40,6 +40,6 @@ public static void SetTradeMemoryHT8(this IMemoryHT ht) /// public static void ClearMemoriesHT(this IMemoryHT ht) { - ht.HT_TextVar = ht.HT_Memory = ht.HT_Feeling = ht.HT_Intensity = 0; + ht.HandlingTrainerMemoryVariable = ht.HandlingTrainerMemory = ht.HandlingTrainerMemoryFeeling = ht.HandlingTrainerMemoryIntensity = 0; } } diff --git a/PKHeX.Core/PKM/Interfaces/IMemoryOT.cs b/PKHeX.Core/PKM/Interfaces/IMemoryOT.cs index b443b2758..e6bf20341 100644 --- a/PKHeX.Core/PKM/Interfaces/IMemoryOT.cs +++ b/PKHeX.Core/PKM/Interfaces/IMemoryOT.cs @@ -5,10 +5,10 @@ namespace PKHeX.Core; /// public interface IMemoryOT : IMemoryOTReadOnly { - new byte OT_Memory { get; set; } - new byte OT_Intensity { get; set; } - new byte OT_Feeling { get; set; } - new ushort OT_TextVar { get; set; } + new byte OriginalTrainerMemory { get; set; } + new byte OriginalTrainerMemoryIntensity { get; set; } + new byte OriginalTrainerMemoryFeeling { get; set; } + new ushort OriginalTrainerMemoryVariable { get; set; } } public static partial class Extensions @@ -18,6 +18,6 @@ public static partial class Extensions /// public static void ClearMemoriesOT(this IMemoryOT ot) { - ot.OT_TextVar = ot.OT_Memory = ot.OT_Feeling = ot.OT_Intensity = 0; + ot.OriginalTrainerMemoryVariable = ot.OriginalTrainerMemory = ot.OriginalTrainerMemoryFeeling = ot.OriginalTrainerMemoryIntensity = 0; } } diff --git a/PKHeX.Core/PKM/Interfaces/INature.cs b/PKHeX.Core/PKM/Interfaces/INature.cs index b173d0145..8f056e9c6 100644 --- a/PKHeX.Core/PKM/Interfaces/INature.cs +++ b/PKHeX.Core/PKM/Interfaces/INature.cs @@ -8,5 +8,5 @@ public interface INature : INatureReadOnly /// /// Nature the entity has. /// - new int Nature { get; set; } + new Nature Nature { get; set; } } diff --git a/PKHeX.Core/PKM/Interfaces/IObedienceLevel.cs b/PKHeX.Core/PKM/Interfaces/IObedienceLevel.cs index 4ae5704fc..ceff93ecb 100644 --- a/PKHeX.Core/PKM/Interfaces/IObedienceLevel.cs +++ b/PKHeX.Core/PKM/Interfaces/IObedienceLevel.cs @@ -20,8 +20,8 @@ public static byte GetSuggestedObedienceLevel(this IObedienceLevelReadOnly _, PK { if (entity.Species is (int)Species.Koraidon or (int)Species.Miraidon && entity is PK9 { FormArgument: not 0 }) return 0; // Box Legend ride-able is default 0. Everything else is met level! - if (entity.Version is not ((int)GameVersion.SL or (int)GameVersion.VL)) - return (byte)entity.CurrentLevel; // foreign, play it safe. + if (entity.Version is not (GameVersion.SL or GameVersion.VL)) + return entity.CurrentLevel; // foreign, play it safe. // Can just assume min-level return (byte)originalMet; } diff --git a/PKHeX.Core/PKM/Interfaces/ITrainerID32.cs b/PKHeX.Core/PKM/Interfaces/ITrainerID32.cs index 8a7c8854e..1f512a23f 100644 --- a/PKHeX.Core/PKM/Interfaces/ITrainerID32.cs +++ b/PKHeX.Core/PKM/Interfaces/ITrainerID32.cs @@ -33,12 +33,12 @@ public static class ITrainerID32Extensions /// /// Possessing trainer /// - /// Generation of origin. + /// Generation of origin. /// True if shiny, false if not. - public static bool IsShiny(this ITrainerID32 tr, uint pid, int gen = 7) + public static bool IsShiny(this ITrainerID32 tr, uint pid, byte generation = 7) { var xor = GetShinyXor(tr, pid); - var threshold = (gen >= 7 ? ShinyXorThreshold7 : ShinyXorThreshold36); + var threshold = (generation >= 7 ? ShinyXorThreshold7 : ShinyXorThreshold36); return xor < threshold; } diff --git a/PKHeX.Core/PKM/Interfaces/Metadata/IGameValueLimit.cs b/PKHeX.Core/PKM/Interfaces/Metadata/IGameValueLimit.cs index ef510d76f..124de589d 100644 --- a/PKHeX.Core/PKM/Interfaces/Metadata/IGameValueLimit.cs +++ b/PKHeX.Core/PKM/Interfaces/Metadata/IGameValueLimit.cs @@ -33,12 +33,12 @@ public interface IGameValueLimit /// /// Maximum Version ID value that can exist. /// - int MaxGameID { get; } + GameVersion MaxGameID { get; } /// /// Minimum Version ID value that can exist. /// - int MinGameID { get; } + GameVersion MinGameID { get; } /// /// Maximum IV value that is possible. diff --git a/PKHeX.Core/PKM/Interfaces/Metadata/IGeneration.cs b/PKHeX.Core/PKM/Interfaces/Metadata/IGeneration.cs index 2a9c90975..66d32dfd5 100644 --- a/PKHeX.Core/PKM/Interfaces/Metadata/IGeneration.cs +++ b/PKHeX.Core/PKM/Interfaces/Metadata/IGeneration.cs @@ -1,4 +1,4 @@ -namespace PKHeX.Core; +namespace PKHeX.Core; /// /// Interface that exposes a to see which canonical generation the data originated in. @@ -8,5 +8,5 @@ public interface IGeneration /// /// The canonical generation the data originated in. /// - int Generation { get; } + byte Generation { get; } } diff --git a/PKHeX.Core/Legality/Encounters/Templates/Interfaces/Properties/IVersion.cs b/PKHeX.Core/PKM/Interfaces/Metadata/IVersion.cs similarity index 63% rename from PKHeX.Core/Legality/Encounters/Templates/Interfaces/Properties/IVersion.cs rename to PKHeX.Core/PKM/Interfaces/Metadata/IVersion.cs index a827b33f2..268d0c410 100644 --- a/PKHeX.Core/Legality/Encounters/Templates/Interfaces/Properties/IVersion.cs +++ b/PKHeX.Core/PKM/Interfaces/Metadata/IVersion.cs @@ -13,29 +13,35 @@ public interface IVersion public static partial class Extensions { - private static bool CanBeReceivedBy(this IVersion ver, GameVersion game) => ver.Version.Contains(game); + private static bool CanBeReceivedBy(this IVersion version, GameVersion game) => version.Version.Contains(game); - public static GameVersion GetCompatibleVersion(this IVersion ver, GameVersion prefer) + public static GameVersion GetCompatibleVersion(this IVersion version, GameVersion prefer) { - if (ver.CanBeReceivedBy(prefer) || ver.Version == GameVersion.Any) + if (version.CanBeReceivedBy(prefer) || version.Version == GameVersion.Any) return prefer; - return ver.GetSingleVersion(); + return version.GetSingleVersion(); } - public static GameVersion GetSingleVersion(this IVersion ver) + public static GameVersion GetSingleVersion(this IVersion version) { - const int max = (int)GameUtil.HighestGameID; - var v = ver.Version; + var v = version.Version; if (v.IsValidSavedVersion()) return v; + return v.GetSingleVersion(); + } + + public static GameVersion GetSingleVersion(this GameVersion lump) + { + const int max = (int)GameUtil.HighestGameID; var rnd = Util.Rand; while (true) // this isn't optimal, but is low maintenance { var game = (GameVersion)rnd.Next(1, max); + if (!lump.Contains(game)) + continue; if (game == GameVersion.BU) continue; // Ignore this one; only can be Japanese language. - if (ver.CanBeReceivedBy(game)) - return game; + return game; } } } diff --git a/PKHeX.Core/PKM/Interfaces/Templates/IContestStatsReadOnly.cs b/PKHeX.Core/PKM/Interfaces/Templates/IContestStatsReadOnly.cs index 7c5125f31..518d63e7e 100644 --- a/PKHeX.Core/PKM/Interfaces/Templates/IContestStatsReadOnly.cs +++ b/PKHeX.Core/PKM/Interfaces/Templates/IContestStatsReadOnly.cs @@ -5,12 +5,12 @@ namespace PKHeX.Core; /// public interface IContestStatsReadOnly { - byte CNT_Cool { get; } - byte CNT_Beauty { get; } - byte CNT_Cute { get; } - byte CNT_Smart { get; } - byte CNT_Tough { get; } - byte CNT_Sheen { get; } + byte ContestCool { get; } + byte ContestBeauty { get; } + byte ContestCute { get; } + byte ContestSmart { get; } + byte ContestTough { get; } + byte ContestSheen { get; } } public static partial class Extensions @@ -22,17 +22,17 @@ public static partial class Extensions /// True if it has any nonzero contest stat, false if all are zero. public static bool HasContestStats(this IContestStatsReadOnly stats) { - if (stats.CNT_Cool != 0) + if (stats.ContestCool != 0) return true; - if (stats.CNT_Beauty != 0) + if (stats.ContestBeauty != 0) return true; - if (stats.CNT_Cute != 0) + if (stats.ContestCute != 0) return true; - if (stats.CNT_Smart != 0) + if (stats.ContestSmart != 0) return true; - if (stats.CNT_Tough != 0) + if (stats.ContestTough != 0) return true; - if (stats.CNT_Sheen != 0) + if (stats.ContestSheen != 0) return true; return false; } @@ -41,68 +41,68 @@ public static bool HasContestStats(this IContestStatsReadOnly stats) public static bool IsContestAboveOrEqual(this IContestStatsReadOnly current, IContestStatsReadOnly initial) { - if (current.CNT_Cool < initial.CNT_Cool) + if (current.ContestCool < initial.ContestCool) return false; - if (current.CNT_Beauty < initial.CNT_Beauty) + if (current.ContestBeauty < initial.ContestBeauty) return false; - if (current.CNT_Cute < initial.CNT_Cute) + if (current.ContestCute < initial.ContestCute) return false; - if (current.CNT_Smart < initial.CNT_Smart) + if (current.ContestSmart < initial.ContestSmart) return false; - if (current.CNT_Tough < initial.CNT_Tough) + if (current.ContestTough < initial.ContestTough) return false; - if (current.CNT_Sheen < initial.CNT_Sheen) + if (current.ContestSheen < initial.ContestSheen) return false; return true; } public static bool IsContestEqual(this IContestStatsReadOnly current, IContestStatsReadOnly initial) { - if (current.CNT_Cool != initial.CNT_Cool) + if (current.ContestCool != initial.ContestCool) return false; - if (current.CNT_Beauty != initial.CNT_Beauty) + if (current.ContestBeauty != initial.ContestBeauty) return false; - if (current.CNT_Cute != initial.CNT_Cute) + if (current.ContestCute != initial.ContestCute) return false; - if (current.CNT_Smart != initial.CNT_Smart) + if (current.ContestSmart != initial.ContestSmart) return false; - if (current.CNT_Tough != initial.CNT_Tough) + if (current.ContestTough != initial.ContestTough) return false; - if (current.CNT_Sheen != initial.CNT_Sheen) + if (current.ContestSheen != initial.ContestSheen) return false; return true; } public static void CopyContestStatsTo(this IContestStatsReadOnly source, IContestStats dest) { - dest.CNT_Cool = source.CNT_Cool; - dest.CNT_Beauty = source.CNT_Beauty; - dest.CNT_Cute = source.CNT_Cute; - dest.CNT_Smart = source.CNT_Smart; - dest.CNT_Tough = source.CNT_Tough; - dest.CNT_Sheen = source.CNT_Sheen; + dest.ContestCool = source.ContestCool; + dest.ContestBeauty = source.ContestBeauty; + dest.ContestCute = source.ContestCute; + dest.ContestSmart = source.ContestSmart; + dest.ContestTough = source.ContestTough; + dest.ContestSheen = source.ContestSheen; } public static void SetAllContestStatsTo(this IContestStats dest, byte value, byte sheen) { - dest.CNT_Cool = value; - dest.CNT_Beauty = value; - dest.CNT_Cute = value; - dest.CNT_Smart = value; - dest.CNT_Tough = value; - dest.CNT_Sheen = sheen; + dest.ContestCool = value; + dest.ContestBeauty = value; + dest.ContestCute = value; + dest.ContestSmart = value; + dest.ContestTough = value; + dest.ContestSheen = sheen; } private const byte CONTEST_MAX = 255; /// - /// Check if any contest stat besides is equal to . + /// Check if any contest stat besides is equal to . /// /// Entity to check /// True if any equals - public static bool IsAnyContestStatMax(this IContestStatsReadOnly s) => CONTEST_MAX == s.CNT_Cool - || CONTEST_MAX == s.CNT_Beauty - || CONTEST_MAX == s.CNT_Cute - || CONTEST_MAX == s.CNT_Smart - || CONTEST_MAX == s.CNT_Tough; + public static bool IsAnyContestStatMax(this IContestStatsReadOnly s) => CONTEST_MAX == s.ContestCool + || CONTEST_MAX == s.ContestBeauty + || CONTEST_MAX == s.ContestCute + || CONTEST_MAX == s.ContestSmart + || CONTEST_MAX == s.ContestTough; } diff --git a/PKHeX.Core/PKM/Interfaces/Templates/IFixedOTFriendship.cs b/PKHeX.Core/PKM/Interfaces/Templates/IFixedOTFriendship.cs index 0e6e990eb..50baa8e1f 100644 --- a/PKHeX.Core/PKM/Interfaces/Templates/IFixedOTFriendship.cs +++ b/PKHeX.Core/PKM/Interfaces/Templates/IFixedOTFriendship.cs @@ -5,5 +5,5 @@ /// public interface IFixedOTFriendship { - byte OT_Friendship { get; } + byte OriginalTrainerFriendship { get; } } diff --git a/PKHeX.Core/PKM/Interfaces/Templates/IMemoryOTReadOnly.cs b/PKHeX.Core/PKM/Interfaces/Templates/IMemoryOTReadOnly.cs index cbae5ca59..622b98158 100644 --- a/PKHeX.Core/PKM/Interfaces/Templates/IMemoryOTReadOnly.cs +++ b/PKHeX.Core/PKM/Interfaces/Templates/IMemoryOTReadOnly.cs @@ -2,8 +2,8 @@ namespace PKHeX.Core; public interface IMemoryOTReadOnly { - byte OT_Memory { get; } - byte OT_Intensity { get; } - byte OT_Feeling { get; } - ushort OT_TextVar { get; } + byte OriginalTrainerMemory { get; } + byte OriginalTrainerMemoryIntensity { get; } + byte OriginalTrainerMemoryFeeling { get; } + ushort OriginalTrainerMemoryVariable { get; } } diff --git a/PKHeX.Core/PKM/Interfaces/Templates/INatureReadOnly.cs b/PKHeX.Core/PKM/Interfaces/Templates/INatureReadOnly.cs index eb126f5bf..2645659f2 100644 --- a/PKHeX.Core/PKM/Interfaces/Templates/INatureReadOnly.cs +++ b/PKHeX.Core/PKM/Interfaces/Templates/INatureReadOnly.cs @@ -8,5 +8,5 @@ public interface INatureReadOnly /// /// Nature the entity has. /// - int Nature { get; } + Nature Nature { get; } } diff --git a/PKHeX.Core/PKM/PA8.cs b/PKHeX.Core/PKM/PA8.cs index c9f9462a4..890c4c22f 100644 --- a/PKHeX.Core/PKM/PA8.cs +++ b/PKHeX.Core/PKM/PA8.cs @@ -52,19 +52,19 @@ private static byte[] DecryptParty(byte[] data) // Simple Generated Attributes - public override int CurrentFriendship + public override byte CurrentFriendship { - get => CurrentHandler == 0 ? OT_Friendship : HT_Friendship; - set { if (CurrentHandler == 0) OT_Friendship = value; else HT_Friendship = value; } + get => CurrentHandler == 0 ? OriginalTrainerFriendship : HandlingTrainerFriendship; + set { if (CurrentHandler == 0) OriginalTrainerFriendship = value; else HandlingTrainerFriendship = value; } } public override void RefreshChecksum() => Checksum = CalculateChecksum(); public override bool Valid { get => Sanity == 0 && ChecksumValid; set { if (!value) return; Sanity = 0; RefreshChecksum(); } } // Trash Bytes - public override Span Nickname_Trash => Data.AsSpan(0x60, 26); - public override Span HT_Trash => Data.AsSpan(0xB8, 26); - public override Span OT_Trash => Data.AsSpan(0x110, 26); + public override Span NicknameTrash => Data.AsSpan(0x60, 26); + public override Span HandlingTrainerTrash => Data.AsSpan(0xB8, 26); + public override Span OriginalTrainerTrash => Data.AsSpan(0x110, 26); // Maximums public override int MaxIV => 31; @@ -74,7 +74,7 @@ public override int CurrentFriendship public override uint PSV => ((PID >> 16) ^ (PID & 0xFFFF)) >> 4; public override uint TSV => (uint)(TID16 ^ SID16) >> 4; - public override bool IsUntraded => Data[0xB8] == 0 && Data[0xB8 + 1] == 0 && Format == Generation; // immediately terminated HT_Name data (\0) + public override bool IsUntraded => Data[0xB8] == 0 && Data[0xB8 + 1] == 0 && Format == Generation; // immediately terminated HandlingTrainerName data (\0) // Complex Generated Attributes public override int Characteristic => EntityCharacteristic.GetCharacteristic(EncryptionConstant, IV32); @@ -134,11 +134,11 @@ public void FixRelearn() // 0x1A alignment unused // 0x1B alignment unused public override uint PID { get => ReadUInt32LittleEndian(Data.AsSpan(0x1C)); set => WriteUInt32LittleEndian(Data.AsSpan(0x1C), value); } - public override int Nature { get => Data[0x20]; set => Data[0x20] = (byte)value; } - public override int StatNature { get => Data[0x21]; set => Data[0x21] = (byte)value; } + public override Nature Nature { get => (Nature)Data[0x20]; set => Data[0x20] = (byte)value; } + public override Nature StatNature { get => (Nature)Data[0x21]; set => Data[0x21] = (byte)value; } public override bool FatefulEncounter { get => (Data[0x22] & 1) == 1; set => Data[0x22] = (byte)((Data[0x22] & ~0x01) | (value ? 1 : 0)); } public bool Flag2 { get => (Data[0x22] & 2) == 2; set => Data[0x22] = (byte)((Data[0x22] & ~0x02) | (value ? 2 : 0)); } - public override int Gender { get => (Data[0x22] >> 2) & 0x3; set => Data[0x22] = (byte)((Data[0x22] & 0xF3) | (value << 2)); } + public override byte Gender { get => (byte)((Data[0x22] >> 2) & 0x3); set => Data[0x22] = (byte)((Data[0x22] & 0xF3) | (value << 2)); } // 0x23 alignment unused public override byte Form { get => Data[0x24]; set => WriteUInt16LittleEndian(Data.AsSpan(0x24), value); } @@ -148,15 +148,15 @@ public void FixRelearn() public override int EV_SPE { get => Data[0x29]; set => Data[0x29] = (byte)value; } public override int EV_SPA { get => Data[0x2A]; set => Data[0x2A] = (byte)value; } public override int EV_SPD { get => Data[0x2B]; set => Data[0x2B] = (byte)value; } - public byte CNT_Cool { get => Data[0x2C]; set => Data[0x2C] = value; } - public byte CNT_Beauty { get => Data[0x2D]; set => Data[0x2D] = value; } - public byte CNT_Cute { get => Data[0x2E]; set => Data[0x2E] = value; } - public byte CNT_Smart { get => Data[0x2F]; set => Data[0x2F] = value; } - public byte CNT_Tough { get => Data[0x30]; set => Data[0x30] = value; } - public byte CNT_Sheen { get => Data[0x31]; set => Data[0x31] = value; } - public byte PKRS { get => Data[0x32]; set => Data[0x32] = value; } - public override int PKRS_Days { get => PKRS & 0xF; set => PKRS = (byte)((PKRS & ~0xF) | value); } - public override int PKRS_Strain { get => PKRS >> 4; set => PKRS = (byte)((PKRS & 0xF) | (value << 4)); } + public byte ContestCool { get => Data[0x2C]; set => Data[0x2C] = value; } + public byte ContestBeauty { get => Data[0x2D]; set => Data[0x2D] = value; } + public byte ContestCute { get => Data[0x2E]; set => Data[0x2E] = value; } + public byte ContestSmart { get => Data[0x2F]; set => Data[0x2F] = value; } + public byte ContestTough { get => Data[0x30]; set => Data[0x30] = value; } + public byte ContestSheen { get => Data[0x31]; set => Data[0x31] = value; } + public byte PokerusState { get => Data[0x32]; set => Data[0x32] = value; } + public override int PokerusDays { get => PokerusState & 0xF; set => PokerusState = (byte)((PokerusState & ~0xF) | value); } + public override int PokerusStrain { get => PokerusState >> 4; set => PokerusState = (byte)((PokerusState & 0xF) | (value << 4)); } // 0x33 unused padding // ribbon u32 @@ -345,8 +345,8 @@ public void FixRelearn() #region Block B public override string Nickname { - get => StringConverter8.GetString(Nickname_Trash); - set => StringConverter8.SetString(Nickname_Trash, value, 12, StringConverterOption.None); + get => StringConverter8.GetString(NicknameTrash); + set => StringConverter8.SetString(NicknameTrash, value, 12, StringConverterOption.None); } // 2 bytes for \0, automatically handled above @@ -362,7 +362,7 @@ public override string Nickname public override ushort RelearnMove4 { get => ReadUInt16LittleEndian(Data.AsSpan(0x90)); set => WriteUInt16LittleEndian(Data.AsSpan(0x90), value); } public override int Stat_HPCurrent { get => ReadUInt16LittleEndian(Data.AsSpan(0x92)); set => WriteUInt16LittleEndian(Data.AsSpan(0x92), (ushort)value); } - private uint IV32 { get => ReadUInt32LittleEndian(Data.AsSpan(0x94)); set => WriteUInt32LittleEndian(Data.AsSpan(0x94), value); } + public uint IV32 { get => ReadUInt32LittleEndian(Data.AsSpan(0x94)); set => WriteUInt32LittleEndian(Data.AsSpan(0x94), value); } public override int IV_HP { get => (int)(IV32 >> 00) & 0x1F; set => IV32 = (IV32 & ~(0x1Fu << 00)) | ((value > 31 ? 31u : (uint)value) << 00); } public override int IV_ATK { get => (int)(IV32 >> 05) & 0x1F; set => IV32 = (IV32 & ~(0x1Fu << 05)) | ((value > 31 ? 31u : (uint)value) << 05); } public override int IV_DEF { get => (int)(IV32 >> 10) & 0x1F; set => IV32 = (IV32 & ~(0x1Fu << 10)) | ((value > 31 ? 31u : (uint)value) << 10); } @@ -392,29 +392,29 @@ public override string Nickname #endregion #region Block C - public override string HT_Name + public override string HandlingTrainerName { - get => StringConverter8.GetString(HT_Trash); - set => StringConverter8.SetString(HT_Trash, value, 12, StringConverterOption.None); + get => StringConverter8.GetString(HandlingTrainerTrash); + set => StringConverter8.SetString(HandlingTrainerTrash, value, 12, StringConverterOption.None); } - public override int HT_Gender { get => Data[0xD2]; set => Data[0xD2] = (byte)value; } - public byte HT_Language { get => Data[0xD3]; set => Data[0xD3] = value; } - public override int CurrentHandler { get => Data[0xD4]; set => Data[0xD4] = (byte)value; } + public override byte HandlingTrainerGender { get => Data[0xD2]; set => Data[0xD2] = value; } + public byte HandlingTrainerLanguage { get => Data[0xD3]; set => Data[0xD3] = value; } + public override byte CurrentHandler { get => Data[0xD4]; set => Data[0xD4] = value; } // 0xD5 unused (alignment) - public int HT_TrainerID { get => ReadUInt16LittleEndian(Data.AsSpan(0xD6)); set => WriteUInt16LittleEndian(Data.AsSpan(0xD6), (ushort)value); } // unused? - public override int HT_Friendship { get => Data[0xD8]; set => Data[0xD8] = (byte)value; } - public byte HT_Intensity { get => Data[0xD9]; set => Data[0xD9] = value; } - public byte HT_Memory { get => Data[0xDA]; set => Data[0xDA] = value; } - public byte HT_Feeling { get => Data[0xDB]; set => Data[0xDB] = value; } - public ushort HT_TextVar { get => ReadUInt16LittleEndian(Data.AsSpan(0xDC)); set => WriteUInt16LittleEndian(Data.AsSpan(0xDC), value); } + public ushort HandlingTrainerID { get => ReadUInt16LittleEndian(Data.AsSpan(0xD6)); set => WriteUInt16LittleEndian(Data.AsSpan(0xD6), value); } // unused? + public override byte HandlingTrainerFriendship { get => Data[0xD8]; set => Data[0xD8] = value; } + public byte HandlingTrainerMemoryIntensity { get => Data[0xD9]; set => Data[0xD9] = value; } + public byte HandlingTrainerMemory { get => Data[0xDA]; set => Data[0xDA] = value; } + public byte HandlingTrainerMemoryFeeling { get => Data[0xDB]; set => Data[0xDB] = value; } + public ushort HandlingTrainerMemoryVariable { get => ReadUInt16LittleEndian(Data.AsSpan(0xDC)); set => WriteUInt16LittleEndian(Data.AsSpan(0xDC), value); } // 0xDE-0xEB unused public override byte Fullness { get => Data[0xEC]; set => Data[0xEC] = value; } public override byte Enjoyment { get => Data[0xED]; set => Data[0xED] = value; } - public override int Version { get => Data[0xEE]; set => Data[0xEE] = (byte)value; } - public byte BattleVersion { get => Data[0xEF]; set => Data[0xEF] = value; } + public override GameVersion Version { get => (GameVersion)Data[0xEE]; set => Data[0xEE] = (byte)value; } + public GameVersion BattleVersion { get => (GameVersion)Data[0xEF]; set => Data[0xEF] = (byte)value; } // public override byte Region { get => Data[0xF0]; set => Data[0xF0] = (byte)value; } // public override byte ConsoleRegion { get => Data[0xF1]; set => Data[0xF1] = (byte)value; } public override int Language { get => Data[0xF2]; set => Data[0xF2] = (byte)value; } @@ -427,30 +427,30 @@ public override string HT_Name // remainder unused #endregion #region Block D - public override string OT_Name + public override string OriginalTrainerName { - get => StringConverter8.GetString(OT_Trash); - set => StringConverter8.SetString(OT_Trash, value, 12, StringConverterOption.None); + get => StringConverter8.GetString(OriginalTrainerTrash); + set => StringConverter8.SetString(OriginalTrainerTrash, value, 12, StringConverterOption.None); } - public override int OT_Friendship { get => Data[0x12A]; set => Data[0x12A] = (byte)value; } - public byte OT_Intensity { get => Data[0x12B]; set => Data[0x12B] = value; } - public byte OT_Memory { get => Data[0x12C]; set => Data[0x12C] = value; } + public override byte OriginalTrainerFriendship { get => Data[0x12A]; set => Data[0x12A] = value; } + public byte OriginalTrainerMemoryIntensity { get => Data[0x12B]; set => Data[0x12B] = value; } + public byte OriginalTrainerMemory { get => Data[0x12C]; set => Data[0x12C] = value; } // 0x12D unused align - public ushort OT_TextVar { get => ReadUInt16LittleEndian(Data.AsSpan(0x12E)); set => WriteUInt16LittleEndian(Data.AsSpan(0x12E), value); } - public byte OT_Feeling { get => Data[0x130]; set => Data[0x130] = value; } - public override int Egg_Year { get => Data[0x131]; set => Data[0x131] = (byte)value; } - public override int Egg_Month { get => Data[0x132]; set => Data[0x132] = (byte)value; } - public override int Egg_Day { get => Data[0x133]; set => Data[0x133] = (byte)value; } - public override int Met_Year { get => Data[0x134]; set => Data[0x134] = (byte)value; } - public override int Met_Month { get => Data[0x135]; set => Data[0x135] = (byte)value; } - public override int Met_Day { get => Data[0x136]; set => Data[0x136] = (byte)value; } - public override int Ball { get => Data[0x137]; set => Data[0x137] = (byte)value; } - public override int Egg_Location { get => ReadUInt16LittleEndian(Data.AsSpan(0x138)); set => WriteUInt16LittleEndian(Data.AsSpan(0x138), (ushort)value); } - public override int Met_Location { get => ReadUInt16LittleEndian(Data.AsSpan(0x13A)); set => WriteUInt16LittleEndian(Data.AsSpan(0x13A), (ushort)value); } + public ushort OriginalTrainerMemoryVariable { get => ReadUInt16LittleEndian(Data.AsSpan(0x12E)); set => WriteUInt16LittleEndian(Data.AsSpan(0x12E), value); } + public byte OriginalTrainerMemoryFeeling { get => Data[0x130]; set => Data[0x130] = value; } + public override byte EggYear { get => Data[0x131]; set => Data[0x131] = value; } + public override byte EggMonth { get => Data[0x132]; set => Data[0x132] = value; } + public override byte EggDay { get => Data[0x133]; set => Data[0x133] = value; } + public override byte MetYear { get => Data[0x134]; set => Data[0x134] = value; } + public override byte MetMonth { get => Data[0x135]; set => Data[0x135] = value; } + public override byte MetDay { get => Data[0x136]; set => Data[0x136] = value; } + public override byte Ball { get => Data[0x137]; set => Data[0x137] = value; } + public override ushort EggLocation { get => ReadUInt16LittleEndian(Data.AsSpan(0x138)); set => WriteUInt16LittleEndian(Data.AsSpan(0x138), value); } + public override ushort MetLocation { get => ReadUInt16LittleEndian(Data.AsSpan(0x13A)); set => WriteUInt16LittleEndian(Data.AsSpan(0x13A), value); } // 0x13C unused align - public override int Met_Level { get => Data[0x13D] & ~0x80; set => Data[0x13D] = (byte)((Data[0x13D] & 0x80) | value); } - public override int OT_Gender { get => Data[0x13D] >> 7; set => Data[0x13D] = (byte)((Data[0x13D] & ~0x80) | (value << 7)); } + public override byte MetLevel { get => (byte)(Data[0x13D] & ~0x80); set => Data[0x13D] = (byte)((Data[0x13D] & 0x80) | value); } + public override byte OriginalTrainerGender { get => (byte)(Data[0x13D] >> 7); set => Data[0x13D] = (byte)((Data[0x13D] & ~0x80) | (value << 7)); } public byte HyperTrainFlags { get => Data[0x13E]; set => Data[0x13E] = value; } public bool HT_HP { get => ((HyperTrainFlags >> 0) & 1) == 1; set => HyperTrainFlags = (byte)((HyperTrainFlags & ~(1 << 0)) | ((value ? 1 : 0) << 0)); } public bool HT_ATK { get => ((HyperTrainFlags >> 1) & 1) == 1; set => HyperTrainFlags = (byte)((HyperTrainFlags & ~(1 << 1)) | ((value ? 1 : 0) << 1)); } @@ -498,7 +498,7 @@ public ulong Tracker #endregion #region Battle Stats - public override int Stat_Level { get => Data[0x168]; set => Data[0x168] = (byte)value; } + public override byte Stat_Level { get => Data[0x168]; set => Data[0x168] = value; } // 0x149 unused alignment public override int Stat_HPMax { get => ReadUInt16LittleEndian(Data.AsSpan(0x16A)); set => WriteUInt16LittleEndian(Data.AsSpan(0x16A), (ushort)value); } public override int Stat_ATK { get => ReadUInt16LittleEndian(Data.AsSpan(0x16C)); set => WriteUInt16LittleEndian(Data.AsSpan(0x16C), (ushort)value); } @@ -511,7 +511,7 @@ public ulong Tracker public override void LoadStats(IBaseStat p, Span stats) { int level = CurrentLevel; - int nature = StatNature; + var nature = StatNature; stats[0] = (ushort)(GetGanbaruStat(p.HP, HT_HP ? 31 : IV_HP, GV_HP, level) + GetStatHp(p.HP, level)); stats[1] = (ushort)(GetGanbaruStat(p.ATK, HT_ATK ? 31 : IV_ATK, GV_ATK, level) + GetStat(p.ATK, level, nature, 0)); @@ -523,8 +523,8 @@ public override void LoadStats(IBaseStat p, Span stats) public static int GetGanbaruStat(int baseStat, int iv, byte gv, int level) { - int mul = GanbaruExtensions.GetGanbaruMultiplier(gv, iv); - double step1 = Math.Abs(Math.Sqrt((float)baseStat)) * mul; // The game does abs after sqrt; should be before. It's fine because baseStat is never negative. + var mul = GanbaruExtensions.GetGanbaruMultiplier(gv, iv); + double step1 = Math.Abs(Math.Sqrt(baseStat)) * mul; // The game does abs after sqrt; should be before. It's fine because baseStat is never negative. var result = ((float)step1 + level) / 2.5f; return (int)Math.Round(result, MidpointRounding.AwayFromZero); } @@ -534,7 +534,7 @@ public static int GetStatHp(int baseStat, int level) return (int)((((level / 100.0f) + 1.0f) * baseStat) + level); } - public static int GetStat(int baseStat, int level, int nature, int statIndex) + public static int GetStat(int baseStat, int level, Nature nature, int statIndex) { var initial = (int)((((level / 50.0f) + 1.0f) * baseStat) / 1.5f); return NatureAmp.AmplifyStat(nature, statIndex, initial); @@ -581,30 +581,30 @@ public void FixMemories() { if (LA) { - OT_TextVar = OT_Memory = OT_Intensity = OT_Feeling = 0; - HT_TextVar = HT_Memory = HT_Intensity = HT_Feeling = 0; // future inter-format conversion? + OriginalTrainerMemoryVariable = OriginalTrainerMemory = OriginalTrainerMemoryIntensity = OriginalTrainerMemoryFeeling = 0; + HandlingTrainerMemoryVariable = HandlingTrainerMemory = HandlingTrainerMemoryIntensity = HandlingTrainerMemoryFeeling = 0; // future inter-format conversion? } if (IsEgg) // No memories if is egg. { - HT_TextVar = HT_Memory = HT_Intensity = HT_Feeling = 0; - OT_TextVar = OT_Memory = OT_Intensity = OT_Feeling = 0; + HandlingTrainerMemoryVariable = HandlingTrainerMemory = HandlingTrainerMemoryIntensity = HandlingTrainerMemoryFeeling = 0; + OriginalTrainerMemoryVariable = OriginalTrainerMemory = OriginalTrainerMemoryIntensity = OriginalTrainerMemoryFeeling = 0; // Clear Handler if (!IsTradedEgg) { - HT_Friendship = HT_Gender = HT_Language = 0; - HT_Trash.Clear(); + HandlingTrainerFriendship = HandlingTrainerGender = HandlingTrainerLanguage = 0; + HandlingTrainerTrash.Clear(); } return; } if (IsUntraded) - HT_Gender = HT_Friendship = HT_TextVar = HT_Memory = HT_Intensity = HT_Feeling = HT_Language = 0; + HandlingTrainerMemoryVariable = HandlingTrainerGender = HandlingTrainerFriendship = HandlingTrainerMemory = HandlingTrainerMemoryIntensity = HandlingTrainerMemoryFeeling = HandlingTrainerLanguage = 0; - int gen = Generation; + var gen = Generation; if (gen < 6) - OT_TextVar = OT_Memory = OT_Intensity = OT_Feeling = 0; + OriginalTrainerMemoryVariable = OriginalTrainerMemory = OriginalTrainerMemoryIntensity = OriginalTrainerMemoryFeeling = 0; // if (gen != 8) // must be transferred via HOME, and must have memories // this.SetTradeMemoryHT8(); // not faking HOME tracker. } @@ -612,7 +612,7 @@ public void FixMemories() private bool TradeOT(ITrainerInfo tr) { // Check to see if the OT matches the SAV's OT info. - if (!(tr.ID32 == ID32 && tr.Gender == OT_Gender && tr.OT == OT_Name)) + if (!(tr.ID32 == ID32 && tr.Gender == OriginalTrainerGender && tr.OT == OriginalTrainerName)) return false; CurrentHandler = 0; @@ -621,14 +621,14 @@ private bool TradeOT(ITrainerInfo tr) private void TradeHT(ITrainerInfo tr) { - if (HT_Name != tr.OT) + if (HandlingTrainerName != tr.OT) { - HT_Friendship = PersonalInfo.BaseFriendship; - HT_Name = tr.OT; + HandlingTrainerFriendship = PersonalInfo.BaseFriendship; + HandlingTrainerName = tr.OT; } CurrentHandler = 1; - HT_Gender = tr.Gender; - HT_Language = (byte)tr.Language; + HandlingTrainerGender = tr.Gender; + HandlingTrainerLanguage = (byte)tr.Language; } // Maximums @@ -637,7 +637,7 @@ private void TradeHT(ITrainerInfo tr) public override int MaxAbilityID => Legal.MaxAbilityID_8a; public override int MaxItemID => Legal.MaxItemID_8a; public override int MaxBallID => Legal.MaxBallID_8a; - public override int MaxGameID => Legal.MaxGameID_HOME; + public override GameVersion MaxGameID => Legal.MaxGameID_HOME; public float HeightRatio => GetHeightRatio(HeightScalar); public float WeightRatio => GetWeightRatio(WeightScalar); diff --git a/PKHeX.Core/PKM/PB7.cs b/PKHeX.Core/PKM/PB7.cs index 44ecec93d..341367fbe 100644 --- a/PKHeX.Core/PKM/PB7.cs +++ b/PKHeX.Core/PKM/PB7.cs @@ -106,9 +106,9 @@ public override uint PID set => WriteUInt32LittleEndian(Data.AsSpan(0x18), value); } - public override int Nature { get => Data[0x1C]; set => Data[0x1C] = (byte)value; } + public override Nature Nature { get => (Nature)Data[0x1C]; set => Data[0x1C] = (byte)value; } public override bool FatefulEncounter { get => (Data[0x1D] & 1) == 1; set => Data[0x1D] = (byte)((Data[0x1D] & ~0x01) | (value ? 1 : 0)); } - public override int Gender { get => (Data[0x1D] >> 1) & 0x3; set => Data[0x1D] = (byte)((Data[0x1D] & ~0x06) | (value << 1)); } + public override byte Gender { get => (byte)((Data[0x1D] >> 1) & 0x3); set => Data[0x1D] = (byte)((Data[0x1D] & ~0x06) | (value << 1)); } public override byte Form { get => (byte)(Data[0x1D] >> 3); set => Data[0x1D] = (byte)((Data[0x1D] & 0x07) | (value << 3)); } public override int EV_HP { get => Data[0x1E]; set => Data[0x1E] = (byte)value; } public override int EV_ATK { get => Data[0x1F]; set => Data[0x1F] = (byte)value; } @@ -123,9 +123,9 @@ public override uint PID public byte AV_SPA { get => Data[0x28]; set => Data[0x28] = value; } public byte AV_SPD { get => Data[0x29]; set => Data[0x29] = value; } public ResortEventState ResortEventStatus { get => (ResortEventState)Data[0x2A]; set => Data[0x2A] = (byte)value; } - private byte PKRS { get => Data[0x2B]; set => Data[0x2B] = value; } - public override int PKRS_Days { get => PKRS & 0xF; set => PKRS = (byte)((PKRS & ~0xF) | value); } - public override int PKRS_Strain { get => PKRS >> 4; set => PKRS = (byte)((PKRS & 0xF) | (value << 4)); } + public byte PokerusState { get => Data[0x2B]; set => Data[0x2B] = value; } + public override int PokerusDays { get => PokerusState & 0xF; set => PokerusState = (byte)((PokerusState & ~0xF) | value); } + public override int PokerusStrain { get => PokerusState >> 4; set => PokerusState = (byte)((PokerusState & 0xF) | (value << 4)); } public float HeightAbsolute { get => ReadSingleLittleEndian(Data.AsSpan(0x2C)); set => WriteSingleLittleEndian(Data.AsSpan(0x2C), value); } // 0x38 Unused // 0x39 Unused @@ -140,8 +140,8 @@ public override uint PID #region Block B public override string Nickname { - get => StringConverter8.GetString(Nickname_Trash); - set => StringConverter8.SetString(Nickname_Trash, value, 12, StringConverterOption.None); + get => StringConverter8.GetString(NicknameTrash); + set => StringConverter8.SetString(NicknameTrash, value, 12, StringConverterOption.None); } public override ushort Move1 @@ -203,7 +203,7 @@ public override ushort RelearnMove4 // 0x72 Unused // 0x73 Unused - protected override uint IV32 { get => ReadUInt32LittleEndian(Data.AsSpan(0x74)); set => WriteUInt32LittleEndian(Data.AsSpan(0x74), value); } + public override uint IV32 { get => ReadUInt32LittleEndian(Data.AsSpan(0x74)); set => WriteUInt32LittleEndian(Data.AsSpan(0x74), value); } public override int IV_HP { get => (int)(IV32 >> 00) & 0x1F; set => IV32 = (IV32 & ~(0x1Fu << 00)) | ((value > 31 ? 31u : (uint)value) << 00); } public override int IV_ATK { get => (int)(IV32 >> 05) & 0x1F; set => IV32 = (IV32 & ~(0x1Fu << 05)) | ((value > 31 ? 31u : (uint)value) << 05); } public override int IV_DEF { get => (int)(IV32 >> 10) & 0x1F; set => IV32 = (IV32 & ~(0x1Fu << 10)) | ((value > 31 ? 31u : (uint)value) << 10); } @@ -214,14 +214,14 @@ public override ushort RelearnMove4 public override bool IsNicknamed { get => ((IV32 >> 31) & 1) == 1; set => IV32 = (IV32 & 0x7FFFFFFFu) | (value ? 0x80000000u : 0u); } #endregion #region Block C - public override string HT_Name + public override string HandlingTrainerName { - get => StringConverter8.GetString(HT_Trash); - set => StringConverter8.SetString(HT_Trash, value, 12, StringConverterOption.None); + get => StringConverter8.GetString(HandlingTrainerTrash); + set => StringConverter8.SetString(HandlingTrainerTrash, value, 12, StringConverterOption.None); } - public override int HT_Gender { get => Data[0x92]; set => Data[0x92] = (byte)value; } - public override int CurrentHandler { get => Data[0x93]; set => Data[0x93] = (byte)value; } + public override byte HandlingTrainerGender { get => Data[0x92]; set => Data[0x92] = value; } + public override byte CurrentHandler { get => Data[0x93]; set => Data[0x93] = value; } // 0x94 Unused // 0x95 Unused // 0x96 Unused @@ -236,13 +236,13 @@ public override string HT_Name // 0x9F Unused // 0xA0 Unused // 0xA1 Unused - public override int HT_Friendship { get => Data[0xA2]; set => Data[0xA2] = (byte)value; } - // 0xA1 HT_Affection Unused - public int HT_Intensity { get => Data[0xA4]; set => Data[0xA4] = (byte)value; } - public int HT_Memory { get => Data[0xA5]; set => Data[0xA5] = (byte)value; } - public int HT_Feeling { get => Data[0xA6]; set => Data[0xA6] = (byte)value; } + public override byte HandlingTrainerFriendship { get => Data[0xA2]; set => Data[0xA2] = value; } + // 0xA1 HandlingTrainerAffection Unused + public byte HT_Intensity { get => Data[0xA4]; set => Data[0xA4] = value; } + public byte HT_Memory { get => Data[0xA5]; set => Data[0xA5] = value; } + public byte HT_Feeling { get => Data[0xA6]; set => Data[0xA6] = value; } // 0xA7 Unused - public int HT_TextVar { get => ReadUInt16LittleEndian(Data.AsSpan(0xA8)); set => WriteUInt16LittleEndian(Data.AsSpan(0xA8), (ushort)value); } + public ushort HT_TextVar { get => ReadUInt16LittleEndian(Data.AsSpan(0xA8)); set => WriteUInt16LittleEndian(Data.AsSpan(0xA8), value); } // 0xAA Unused // 0xAB Unused public byte FieldEventFatigue1 { get => Data[0xAC]; set => Data[0xAC] = value; } @@ -251,31 +251,31 @@ public override string HT_Name public override byte Enjoyment { get => Data[0xAF]; set => Data[0xAF] = value; } #endregion #region Block D - public override string OT_Name + public override string OriginalTrainerName { - get => StringConverter8.GetString(OT_Trash); - set => StringConverter8.SetString(OT_Trash, value, 12, StringConverterOption.None); + get => StringConverter8.GetString(OriginalTrainerTrash); + set => StringConverter8.SetString(OriginalTrainerTrash, value, 12, StringConverterOption.None); } - public override int OT_Friendship { get => Data[0xCA]; set => Data[0xCA] = (byte)value; } + public override byte OriginalTrainerFriendship { get => Data[0xCA]; set => Data[0xCA] = value; } // 0xCB Unused // 0xCC Unused // 0xCD Unused // 0xCE Unused // 0xCF Unused // 0xD0 Unused - public override int Egg_Year { get => Data[0xD1]; set => Data[0xD1] = (byte)value; } - public override int Egg_Month { get => Data[0xD2]; set => Data[0xD2] = (byte)value; } - public override int Egg_Day { get => Data[0xD3]; set => Data[0xD3] = (byte)value; } - public override int Met_Year { get => Data[0xD4]; set => Data[0xD4] = (byte)value; } - public override int Met_Month { get => Data[0xD5]; set => Data[0xD5] = (byte)value; } - public override int Met_Day { get => Data[0xD6]; set => Data[0xD6] = (byte)value; } + public override byte EggYear { get => Data[0xD1]; set => Data[0xD1] = value; } + public override byte EggMonth { get => Data[0xD2]; set => Data[0xD2] = value; } + public override byte EggDay { get => Data[0xD3]; set => Data[0xD3] = value; } + public override byte MetYear { get => Data[0xD4]; set => Data[0xD4] = value; } + public override byte MetMonth { get => Data[0xD5]; set => Data[0xD5] = value; } + public override byte MetDay { get => Data[0xD6]; set => Data[0xD6] = value; } public int Rank { get => Data[0xD7]; set => Data[0xD7] = (byte)value; } // unused but fetched for stat calcs, and set for trpoke data? - public override int Egg_Location { get => ReadUInt16LittleEndian(Data.AsSpan(0xD8)); set => WriteUInt16LittleEndian(Data.AsSpan(0xD8), (ushort)value); } - public override int Met_Location { get => ReadUInt16LittleEndian(Data.AsSpan(0xDA)); set => WriteUInt16LittleEndian(Data.AsSpan(0xDA), (ushort)value); } - public override int Ball { get => Data[0xDC]; set => Data[0xDC] = (byte)value; } - public override int Met_Level { get => Data[0xDD] & ~0x80; set => Data[0xDD] = (byte)((Data[0xDD] & 0x80) | value); } - public override int OT_Gender { get => Data[0xDD] >> 7; set => Data[0xDD] = (byte)((Data[0xDD] & ~0x80) | (value << 7)); } + public override ushort EggLocation { get => ReadUInt16LittleEndian(Data.AsSpan(0xD8)); set => WriteUInt16LittleEndian(Data.AsSpan(0xD8), value); } + public override ushort MetLocation { get => ReadUInt16LittleEndian(Data.AsSpan(0xDA)); set => WriteUInt16LittleEndian(Data.AsSpan(0xDA), value); } + public override byte Ball { get => Data[0xDC]; set => Data[0xDC] = value; } + public override byte MetLevel { get => (byte)(Data[0xDD] & ~0x80); set => Data[0xDD] = (byte)((Data[0xDD] & 0x80) | value); } + public override byte OriginalTrainerGender { get => (byte)(Data[0xDD] >> 7); set => Data[0xDD] = (byte)((Data[0xDD] & ~0x80) | (value << 7)); } public byte HyperTrainFlags { get => Data[0xDE]; set => Data[0xDE] = value; } public bool HT_HP { get => ((HyperTrainFlags >> 0) & 1) == 1; set => HyperTrainFlags = (byte)((HyperTrainFlags & ~(1 << 0)) | ((value ? 1 : 0) << 0)); } public bool HT_ATK { get => ((HyperTrainFlags >> 1) & 1) == 1; set => HyperTrainFlags = (byte)((HyperTrainFlags & ~(1 << 1)) | ((value ? 1 : 0) << 1)); } @@ -283,7 +283,7 @@ public override string OT_Name public bool HT_SPA { get => ((HyperTrainFlags >> 3) & 1) == 1; set => HyperTrainFlags = (byte)((HyperTrainFlags & ~(1 << 3)) | ((value ? 1 : 0) << 3)); } public bool HT_SPD { get => ((HyperTrainFlags >> 4) & 1) == 1; set => HyperTrainFlags = (byte)((HyperTrainFlags & ~(1 << 4)) | ((value ? 1 : 0) << 4)); } public bool HT_SPE { get => ((HyperTrainFlags >> 5) & 1) == 1; set => HyperTrainFlags = (byte)((HyperTrainFlags & ~(1 << 5)) | ((value ? 1 : 0) << 5)); } - public override int Version { get => Data[0xDF]; set => Data[0xDF] = (byte)value; } + public override GameVersion Version { get => (GameVersion)Data[0xDF]; set => Data[0xDF] = (byte)value; } // 0xE0 Unused // 0xE1 Unused // 0xE2 Unused @@ -292,7 +292,7 @@ public override string OT_Name #endregion #region Battle Stats public override int Status_Condition { get => ReadInt32LittleEndian(Data.AsSpan(0xE8)); set => WriteInt32LittleEndian(Data.AsSpan(0xE8), value); } - public override int Stat_Level { get => Data[0xEC]; set => Data[0xEC] = (byte)value; } + public override byte Stat_Level { get => Data[0xEC]; set => Data[0xEC] = value; } public byte DirtType { get => Data[0xED]; set => Data[0xED] = value; } public byte DirtLocation { get => Data[0xEE]; set => Data[0xEE] = value; } // 0xEF unused @@ -336,7 +336,7 @@ public void SetMarking(int index, MarkingColor value) protected override bool TradeOT(ITrainerInfo tr) { // Check to see if the OT matches the SAV's OT info. - if (!(tr.ID32 == ID32 && tr.Gender == OT_Gender && tr.OT == OT_Name)) + if (!(tr.ID32 == ID32 && tr.Gender == OriginalTrainerGender && tr.OT == OriginalTrainerName)) return false; CurrentHandler = 0; @@ -345,19 +345,19 @@ protected override bool TradeOT(ITrainerInfo tr) protected override void TradeHT(ITrainerInfo tr) { - if (HT_Name != tr.OT) + if (HandlingTrainerName != tr.OT) { - HT_Friendship = CurrentFriendship; // copy friendship instead of resetting (don't alter CP) - HT_Name = tr.OT; + HandlingTrainerFriendship = CurrentFriendship; // copy friendship instead of resetting (don't alter CP) + HandlingTrainerName = tr.OT; } CurrentHandler = 1; - HT_Gender = tr.Gender; + HandlingTrainerGender = tr.Gender; } public void FixMemories() { if (IsUntraded) - HT_Friendship = HT_TextVar = HT_Memory = HT_Intensity = HT_Feeling = 0; + HT_TextVar = HandlingTrainerFriendship = HT_Memory = HT_Intensity = HT_Feeling = 0; } // Maximums @@ -366,12 +366,12 @@ public void FixMemories() public override int MaxAbilityID => Legal.MaxAbilityID_7_USUM; public override int MaxItemID => Legal.MaxItemID_7_USUM; public override int MaxBallID => Legal.MaxBallID_7; - public override int MaxGameID => Legal.MaxGameID_7b; + public override GameVersion MaxGameID => Legal.MaxGameID_7b; public override void LoadStats(IBaseStat p, Span stats) { int level = CurrentLevel; - int nature = Nature; + var nature = Nature; int friend = CurrentFriendship; // stats +10% depending on friendship! int scalar = (int)(((friend / 255.0f / 10.0f) + 1.0f) * 100.0f); stats[0] = (ushort)(AV_HP + GetStat(p.HP, HT_HP ? 31 : IV_HP, level) + 10 + level); @@ -400,7 +400,7 @@ public override void LoadStats(IBaseStat p, Span stats) /// /// Stat amp index in the nature amp table /// Initial Stat with nature amplification applied. - private static int GetStat(int baseStat, int iv, int level, int nature, int statIndex) + private static int GetStat(int baseStat, int iv, int level, Nature nature, int statIndex) { int initial = GetStat(baseStat, iv, level) + 5; return NatureAmp.AmplifyStat(nature, statIndex, initial); @@ -414,7 +414,7 @@ public int BaseCP { var p = PersonalInfo; int level = CurrentLevel; - int nature = Nature; + var nature = Nature; int scalar = CPScalar; // Calculate stats for all, then sum together. @@ -553,7 +553,7 @@ public static byte GetWeightScalar(float height, float weight, int avgHeight, in return (byte)unsigned; } - public static int GetRandomIndex(int bits, int characterIndex, int nature) + public static int GetRandomIndex(int bits, int characterIndex, Nature nature) { if (bits is 6 or 7) return GetRandomIndex(characterIndex); diff --git a/PKHeX.Core/PKM/PB8.cs b/PKHeX.Core/PKM/PB8.cs index 0f00707af..c286b5afa 100644 --- a/PKHeX.Core/PKM/PB8.cs +++ b/PKHeX.Core/PKM/PB8.cs @@ -32,7 +32,7 @@ public sealed class PB8 : G8PKM public PB8() { - Egg_Location = Met_Location = Locations.Default8bNone; + EggLocation = MetLocation = Locations.Default8bNone; AffixedRibbon = -1; // 00 would make it show Kalos Champion :) } @@ -50,7 +50,7 @@ public void Trade(ITrainerInfo tr, int Day = 1, int Month = 1, int Year = 2015) if (IsEgg) { // Apply link trade data, only if it left the OT (ignore if dumped & imported, or cloned, etc.) - if ((tr.TID16 != TID16) || (tr.SID16 != SID16) || (tr.Gender != OT_Gender) || (tr.OT != OT_Name)) + if ((tr.TID16 != TID16) || (tr.SID16 != SID16) || (tr.Gender != OriginalTrainerGender) || (tr.OT != OriginalTrainerName)) SetLinkTradeEgg(Day, Month, Year, Locations.LinkTrade6NPC); // Unfortunately, BD/SP doesn't return if it's an egg, and can update the HT details & handler. @@ -67,30 +67,30 @@ public void FixMemories() { if (BDSP) { - OT_TextVar = OT_Memory = OT_Intensity = OT_Feeling = 0; - HT_TextVar = HT_Memory = HT_Intensity = HT_Feeling = 0; // future inter-format conversion? + OriginalTrainerMemoryVariable = OriginalTrainerMemory = OriginalTrainerMemoryIntensity = OriginalTrainerMemoryFeeling = 0; + HandlingTrainerMemoryVariable = HandlingTrainerMemory = HandlingTrainerMemoryIntensity = HandlingTrainerMemoryFeeling = 0; // future inter-format conversion? } if (IsEgg) // No memories if is egg. { - HT_TextVar = HT_Memory = HT_Intensity = HT_Feeling = 0; - OT_TextVar = OT_Memory = OT_Intensity = OT_Feeling = 0; + HandlingTrainerMemoryVariable = HandlingTrainerMemory = HandlingTrainerMemoryIntensity = HandlingTrainerMemoryFeeling = 0; + OriginalTrainerMemoryVariable = OriginalTrainerMemory = OriginalTrainerMemoryIntensity = OriginalTrainerMemoryFeeling = 0; // Clear Handler if (!IsTradedEgg) { - HT_Friendship = HT_Gender = HT_Language = 0; - HT_Trash.Clear(); + HandlingTrainerFriendship = HandlingTrainerGender = HandlingTrainerLanguage = 0; + HandlingTrainerTrash.Clear(); } return; } if (IsUntraded) - HT_Gender = HT_Friendship = HT_TextVar = HT_Memory = HT_Intensity = HT_Feeling = HT_Language = 0; + HandlingTrainerMemoryVariable = HandlingTrainerGender = HandlingTrainerFriendship = HandlingTrainerMemory = HandlingTrainerMemoryIntensity = HandlingTrainerMemoryFeeling = HandlingTrainerLanguage = 0; - int gen = Generation; + var gen = Generation; if (gen < 6) - OT_TextVar = OT_Memory = OT_Intensity = OT_Feeling = 0; + OriginalTrainerMemoryVariable = OriginalTrainerMemory = OriginalTrainerMemoryIntensity = OriginalTrainerMemoryFeeling = 0; // if (gen != 8) // must be transferred via HOME, and must have memories // this.SetTradeMemoryHT8(); // not faking HOME tracker. } @@ -98,7 +98,7 @@ public void FixMemories() private bool TradeOT(ITrainerInfo tr) { // Check to see if the OT matches the SAV's OT info. - if (!(tr.ID32 == ID32 && tr.Gender == OT_Gender && tr.OT == OT_Name)) + if (!(tr.ID32 == ID32 && tr.Gender == OriginalTrainerGender && tr.OT == OriginalTrainerName)) return false; CurrentHandler = 0; @@ -107,14 +107,14 @@ private bool TradeOT(ITrainerInfo tr) private void TradeHT(ITrainerInfo tr) { - if (HT_Name != tr.OT) + if (HandlingTrainerName != tr.OT) { - HT_Friendship = PersonalInfo.BaseFriendship; - HT_Name = tr.OT; + HandlingTrainerFriendship = PersonalInfo.BaseFriendship; + HandlingTrainerName = tr.OT; } CurrentHandler = 1; - HT_Gender = tr.Gender; - HT_Language = (byte)tr.Language; + HandlingTrainerGender = tr.Gender; + HandlingTrainerLanguage = (byte)tr.Language; //this.SetTradeMemoryHT8(); } @@ -124,9 +124,9 @@ private void TradeHT(ITrainerInfo tr) public override int MaxAbilityID => Legal.MaxAbilityID_8b; public override int MaxItemID => Legal.MaxItemID_8b; public override int MaxBallID => Legal.MaxBallID_8b; - public override int MaxGameID => Legal.MaxGameID_HOME; + public override GameVersion MaxGameID => Legal.MaxGameID_HOME; - public override bool WasEgg => IsEgg || Egg_Day != 0; + public override bool WasEgg => IsEgg || EggDay != 0; - public override bool HasOriginalMetLocation => base.HasOriginalMetLocation && !(LA && Met_Location == LocationsHOME.SWLA); + public override bool HasOriginalMetLocation => base.HasOriginalMetLocation && !(LA && MetLocation == LocationsHOME.SWLA); } diff --git a/PKHeX.Core/PKM/PK1.cs b/PKHeX.Core/PKM/PK1.cs index 9a0b1604b..d60d07c19 100644 --- a/PKHeX.Core/PKM/PK1.cs +++ b/PKHeX.Core/PKM/PK1.cs @@ -29,8 +29,8 @@ private static byte[] EnsurePartySize(byte[] data) public override PK1 Clone() { PK1 clone = new((byte[])Data.Clone(), Japanese); - OT_Trash.CopyTo(clone.OT_Trash); - Nickname_Trash.CopyTo(clone.Nickname_Trash); + OriginalTrainerTrash.CopyTo(clone.OriginalTrainerTrash); + NicknameTrash.CopyTo(clone.NicknameTrash); return clone; } @@ -68,7 +68,7 @@ public override PK1 Clone() #endregion #region Party Attributes - public override int Stat_Level { get => Data[0x21]; set => Stat_LevelBox = Data[0x21] = (byte)value; } + public override byte Stat_Level { get => Data[0x21]; set => Stat_LevelBox = Data[0x21] = value; } public override int Stat_HPMax { get => ReadUInt16BigEndian(Data.AsSpan(0x22)); set => WriteUInt16BigEndian(Data.AsSpan(0x22), (ushort)value); } public override int Stat_ATK { get => ReadUInt16BigEndian(Data.AsSpan(0x24)); set => WriteUInt16BigEndian(Data.AsSpan(0x24), (ushort)value); } public override int Stat_DEF { get => ReadUInt16BigEndian(Data.AsSpan(0x26)); set => WriteUInt16BigEndian(Data.AsSpan(0x26), (ushort)value); } @@ -91,20 +91,20 @@ private static bool IsCatchRatePreEvolutionRate(int baseSpecies, int finalSpecie return false; } - private void SetSpeciesValues(ushort value) + private void SetSpeciesValues(ushort species) { - var updated = SpeciesConverter.GetInternal1(value); - if (SpeciesInternal == updated) + var internalID = SpeciesConverter.GetInternal1(species); + if (SpeciesInternal == internalID) return; - SpeciesInternal = updated; + SpeciesInternal = internalID; - var pi = PersonalTable.RB[value]; + var pi = PersonalTable.RB[species]; Type1 = pi.Type1; Type2 = pi.Type2; // Before updating catch rate, check if non-standard - if (IsValidCatchRateAnyPreEvo((byte)value, CatchRate)) + if (IsValidCatchRateAnyPreEvo((byte)species, CatchRate)) return; // Matches nothing possible; just reset to current Species' rate. @@ -126,17 +126,17 @@ private static bool IsValidCatchRateAnyPreEvo(byte species, byte rate) return IsCatchRatePreEvolutionRate(baby, species, rate); } - public override int Version { get => (int)GameVersion.RBY; set { } } - public override int PKRS_Strain { get => 0; set { } } - public override int PKRS_Days { get => 0; set { } } + public override GameVersion Version { get => GameVersion.RBY; set { } } + public override int PokerusStrain { get => 0; set { } } + public override int PokerusDays { get => 0; set { } } public override bool CanHoldItem(ReadOnlySpan valid) => false; - public override int Met_Location { get => 0; set { } } - public override int OT_Gender { get => 0; set { } } - public override int Met_Level { get => 0; set { } } - public override int CurrentFriendship { get => 0; set { } } + public override ushort MetLocation { get => 0; set { } } + public override byte OriginalTrainerGender { get => 0; set { } } + public override byte MetLevel { get => 0; set { } } + public override byte CurrentFriendship { get => 0; set { } } public override bool IsEgg { get => false; set { } } public override int HeldItem { get => 0; set { } } - public override int OT_Friendship { get => 0; set { } } + public override byte OriginalTrainerFriendship { get => 0; set { } } // Maximums public override ushort MaxMoveID => Legal.MaxMoveID_1; @@ -145,14 +145,14 @@ private static bool IsValidCatchRateAnyPreEvo(byte species, byte rate) public override int MaxItemID => Legal.MaxItemID_1; // Extra - public int Gen2Item => ItemConverter.GetItemFuture1(CatchRate); + public byte Gen2Item => ItemConverter.GetItemFuture1(CatchRate); public PK2 ConvertToPK2() { PK2 pk2 = new(Japanese) {Species = Species}; Data.AsSpan(7, 0x1A).CopyTo(pk2.Data.AsSpan(1)); - OT_Trash.CopyTo(pk2.OT_Trash); - Nickname_Trash.CopyTo(pk2.Nickname_Trash); + OriginalTrainerTrash.CopyTo(pk2.OriginalTrainerTrash); + NicknameTrash.CopyTo(pk2.NicknameTrash); pk2.HeldItem = Gen2Item; pk2.CurrentFriendship = pk2.PersonalInfo.BaseFriendship; @@ -165,14 +165,14 @@ public PK7 ConvertToPK7() { var rnd = Util.Rand; var lang = TransferLanguage(RecentTrainerCache.Language); - var version = (byte)EntityConverter.VirtualConsoleSourceGen1; + var version = EntityConverter.VirtualConsoleSourceGen1; if ((lang == 1) != Japanese) lang = Japanese ? 1 : 2; - if (version == (byte)GameVersion.BU && !Japanese) - version = (byte)GameVersion.RD; + if (version == GameVersion.BU && !Japanese) + version = GameVersion.RD; var pi = PersonalTable.SM[Species]; - int abil = TransporterLogic.IsHiddenDisallowedVC1(Species) ? 0 : 2; // Hidden + int ability = TransporterLogic.IsHiddenDisallowedVC1(Species) ? 0 : 2; // Hidden var pk7 = new PK7 { EncryptionConstant = rnd.Rand32(), @@ -180,7 +180,7 @@ public PK7 ConvertToPK7() TID16 = TID16, CurrentLevel = CurrentLevel, EXP = EXP, - Met_Level = CurrentLevel, + MetLevel = CurrentLevel, Nature = Experience.GetNatureVC(EXP), PID = rnd.Rand32(), Ball = 4, @@ -194,22 +194,22 @@ public PK7 ConvertToPK7() Move2_PPUps = Move2_PPUps, Move3_PPUps = Move3_PPUps, Move4_PPUps = Move4_PPUps, - Met_Location = Locations.Transfer1, // "Kanto region", hardcoded. + MetLocation = Locations.Transfer1, // "Kanto region", hardcoded. Gender = Gender, IsNicknamed = false, CurrentHandler = 1, - HT_Name = RecentTrainerCache.OT_Name, - HT_Gender = RecentTrainerCache.OT_Gender, + HandlingTrainerName = RecentTrainerCache.OriginalTrainerName, + HandlingTrainerGender = RecentTrainerCache.OriginalTrainerGender, Language = lang, Nickname = SpeciesName.GetSpeciesNameGeneration(Species, lang, 7), - OT_Name = GetTransferTrainerName(lang), - OT_Friendship = pi.BaseFriendship, - HT_Friendship = pi.BaseFriendship, + OriginalTrainerName = GetTransferTrainerName(lang), + OriginalTrainerFriendship = pi.BaseFriendship, + HandlingTrainerFriendship = pi.BaseFriendship, - Ability = pi.GetAbilityAtIndex(abil), - AbilityNumber = 1 << abil, + Ability = pi.GetAbilityAtIndex(ability), + AbilityNumber = 1 << ability, }; bool special = Species == (int)Core.Species.Mew; @@ -225,7 +225,7 @@ public PK7 ConvertToPK7() else if (IsNicknamedBank) { pk7.IsNicknamed = true; - pk7.Nickname = StringConverter12Transporter.GetString(Nickname_Trash, Japanese); + pk7.Nickname = StringConverter12Transporter.GetString(NicknameTrash, Japanese); } pk7.HealPP(); @@ -235,8 +235,8 @@ public PK7 ConvertToPK7() private string GetTransferTrainerName(int lang) { - if (OT_Trash[0] == StringConverter12.G1TradeOTCode) // In-game Trade + if (OriginalTrainerTrash[0] == StringConverter12.G1TradeOTCode) // In-game Trade return StringConverter12Transporter.GetTradeNameGen1(lang); - return StringConverter12Transporter.GetString(OT_Trash, Japanese); + return StringConverter12Transporter.GetString(OriginalTrainerTrash, Japanese); } } diff --git a/PKHeX.Core/PKM/PK2.cs b/PKHeX.Core/PKM/PK2.cs index a0575914f..3f573fc98 100644 --- a/PKHeX.Core/PKM/PK2.cs +++ b/PKHeX.Core/PKM/PK2.cs @@ -13,7 +13,7 @@ public sealed class PK2 : GBPKML, ICaughtData2 public override int SIZE_PARTY => PokeCrypto.SIZE_2PARTY; public override int SIZE_STORED => PokeCrypto.SIZE_2STORED; - public override bool Korean => !Japanese && OT_Trash[0] <= 0xB; + public override bool Korean => !Japanese && OriginalTrainerTrash[0] <= 0xB; public override EntityContext Context => EntityContext.Gen2; @@ -30,8 +30,8 @@ private static byte[] EnsurePartySize(byte[] data) public override PK2 Clone() { PK2 clone = new((byte[])Data.Clone(), Japanese) { IsEgg = IsEgg }; - OT_Trash.CopyTo(clone.OT_Trash); - Nickname_Trash.CopyTo(clone.Nickname_Trash); + OriginalTrainerTrash.CopyTo(clone.OriginalTrainerTrash); + NicknameTrash.CopyTo(clone.NicknameTrash); return clone; } @@ -61,21 +61,21 @@ public override PK2 Clone() public override int Move2_PPUps { get => (Data[0x18] & 0xC0) >> 6; set => Data[0x18] = (byte)((Data[0x18] & 0x3F) | ((value & 0x3) << 6)); } public override int Move3_PPUps { get => (Data[0x19] & 0xC0) >> 6; set => Data[0x19] = (byte)((Data[0x19] & 0x3F) | ((value & 0x3) << 6)); } public override int Move4_PPUps { get => (Data[0x1A] & 0xC0) >> 6; set => Data[0x1A] = (byte)((Data[0x1A] & 0x3F) | ((value & 0x3) << 6)); } - public override int CurrentFriendship { get => Data[0x1B]; set => Data[0x1B] = (byte)value; } - private byte PKRS { get => Data[0x1C]; set => Data[0x1C] = value; } - public override int PKRS_Days { get => PKRS & 0xF; set => PKRS = (byte)((PKRS & ~0xF) | value); } - public override int PKRS_Strain { get => PKRS >> 4; set => PKRS = (byte)((PKRS & 0xF) | (value << 4)); } + public override byte CurrentFriendship { get => Data[0x1B]; set => Data[0x1B] = value; } + public byte PokerusState { get => Data[0x1C]; set => Data[0x1C] = value; } + public override int PokerusDays { get => PokerusState & 0xF; set => PokerusState = (byte)((PokerusState & ~0xF) | value); } + public override int PokerusStrain { get => PokerusState >> 4; set => PokerusState = (byte)((PokerusState & 0xF) | (value << 4)); } // Crystal only Caught Data public ushort CaughtData { get => ReadUInt16BigEndian(Data.AsSpan(0x1D)); set => WriteUInt16BigEndian(Data.AsSpan(0x1D), value); } - public int Met_TimeOfDay { get => (CaughtData >> 14) & 0x3; set => CaughtData = (ushort)((CaughtData & 0x3FFF) | ((value & 0x3) << 14)); } - public override int Met_Level { get => (CaughtData >> 8) & 0x3F; set => CaughtData = (ushort)((CaughtData & 0xC0FF) | ((value & 0x3F) << 8)); } - public override int OT_Gender { get => (CaughtData >> 7) & 1; set => CaughtData = (ushort)((CaughtData & 0xFF7F) | ((value & 1) << 7)); } - public override int Met_Location { get => CaughtData & 0x7F; set => CaughtData = (ushort)((CaughtData & 0xFF80) | (value & 0x7F)); } + public int MetTimeOfDay { get => (CaughtData >> 14) & 0x3; set => CaughtData = (ushort)((CaughtData & 0x3FFF) | ((value & 0x3) << 14)); } + public override byte MetLevel { get => (byte)((CaughtData >> 8) & 0x3F); set => CaughtData = (ushort)((CaughtData & 0xC0FF) | ((value & 0x3F) << 8)); } + public override byte OriginalTrainerGender { get => (byte)((CaughtData >> 7) & 1); set => CaughtData = (ushort)((CaughtData & 0xFF7F) | ((value & 1) << 7)); } + public override ushort MetLocation { get => (byte)(CaughtData & 0x7F); set => CaughtData = (ushort)((CaughtData & 0xFF80) | (value & 0x7F)); } - public override int Stat_Level + public override byte Stat_Level { get => Data[0x1F]; - set => Data[0x1F] = (byte)value; + set => Data[0x1F] = value; } #endregion @@ -93,9 +93,9 @@ public override int Stat_Level #endregion public override bool IsEgg { get; set; } - public override int OT_Friendship { get => CurrentFriendship; set => CurrentFriendship = value; } + public override byte OriginalTrainerFriendship { get => CurrentFriendship; set => CurrentFriendship = value; } public override bool HasOriginalMetLocation => CaughtData != 0; - public override int Version { get => (int)GameVersion.GSC; set { } } + public override GameVersion Version { get => GameVersion.GSC; set { } } // Maximums public override ushort MaxMoveID => Legal.MaxMoveID_2; @@ -121,8 +121,8 @@ public PK1 ConvertToPK1() pk1.Stat_Level = Stat_Level; } // Status = 0 - OT_Trash.CopyTo(pk1.OT_Trash); - Nickname_Trash.CopyTo(pk1.Nickname_Trash); + OriginalTrainerTrash.CopyTo(pk1.OriginalTrainerTrash); + NicknameTrash.CopyTo(pk1.NicknameTrash); pk1.ClearInvalidMoves(); @@ -136,7 +136,7 @@ public PK7 ConvertToPK7() if ((lang == 1) != Japanese) lang = Japanese ? 1 : 2; var pi = PersonalTable.SM[Species]; - int abil = TransporterLogic.IsHiddenDisallowedVC2(Species) ? 0 : 2; // Hidden + int ability = TransporterLogic.IsHiddenDisallowedVC2(Species) ? 0 : 2; // Hidden var pk7 = new PK7 { EncryptionConstant = rnd.Rand32(), @@ -144,12 +144,12 @@ public PK7 ConvertToPK7() TID16 = TID16, CurrentLevel = CurrentLevel, EXP = EXP, - Met_Level = CurrentLevel, + MetLevel = CurrentLevel, Nature = Experience.GetNatureVC(EXP), PID = rnd.Rand32(), Ball = 4, MetDate = EncounterDate.GetDate3DS(), - Version = HasOriginalMetLocation ? (byte)GameVersion.C : (byte)EntityConverter.VirtualConsoleSourceGen2, + Version = HasOriginalMetLocation ? GameVersion.C : EntityConverter.VirtualConsoleSourceGen2, Move1 = Move1, Move2 = Move2, Move3 = Move3, @@ -158,24 +158,24 @@ public PK7 ConvertToPK7() Move2_PPUps = Move2_PPUps, Move3_PPUps = Move3_PPUps, Move4_PPUps = Move4_PPUps, - Met_Location = Locations.Transfer2, // "Johto region", hardcoded. + MetLocation = Locations.Transfer2, // "Johto region", hardcoded. Gender = Gender, IsNicknamed = false, Form = Form, CurrentHandler = 1, - HT_Name = RecentTrainerCache.OT_Name, - HT_Gender = RecentTrainerCache.OT_Gender, + HandlingTrainerName = RecentTrainerCache.OriginalTrainerName, + HandlingTrainerGender = RecentTrainerCache.OriginalTrainerGender, Language = lang, Nickname = SpeciesName.GetSpeciesNameGeneration(Species, lang, 7), - OT_Name = GetTransferTrainerName(lang), - OT_Gender = OT_Gender, // Crystal - OT_Friendship = pi.BaseFriendship, - HT_Friendship = pi.BaseFriendship, + OriginalTrainerName = GetTransferTrainerName(lang), + OriginalTrainerGender = OriginalTrainerGender, // Crystal + OriginalTrainerFriendship = pi.BaseFriendship, + HandlingTrainerFriendship = pi.BaseFriendship, - Ability = pi.GetAbilityAtIndex(abil), - AbilityNumber = 1 << abil, + Ability = pi.GetAbilityAtIndex(ability), + AbilityNumber = 1 << ability, }; var special = Species is 151 or 251; @@ -191,7 +191,7 @@ public PK7 ConvertToPK7() else if (IsNicknamedBank) { pk7.IsNicknamed = true; - pk7.Nickname = Korean ? Nickname : StringConverter12Transporter.GetString(Nickname_Trash, Japanese); + pk7.Nickname = Korean ? Nickname : StringConverter12Transporter.GetString(NicknameTrash, Japanese); } // Dizzy Punch cannot be transferred @@ -209,11 +209,11 @@ public PK7 ConvertToPK7() private string GetTransferTrainerName(int lang) { - if (OT_Trash[0] == StringConverter12.G1TradeOTCode) // In-game Trade + if (OriginalTrainerTrash[0] == StringConverter12.G1TradeOTCode) // In-game Trade return StringConverter12Transporter.GetTradeNameGen1(lang); if (Korean) - return OT_Name; - return StringConverter12Transporter.GetString(OT_Trash, Japanese); + return OriginalTrainerName; + return StringConverter12Transporter.GetString(OriginalTrainerTrash, Japanese); } public SK2 ConvertToSK2() => new(Japanese) @@ -243,12 +243,11 @@ public SK2 ConvertToSK2() => new(Japanese) CurrentFriendship = CurrentFriendship, IsEgg = IsEgg, Stat_Level = Stat_Level, - PKRS_Days = PKRS_Days, - PKRS_Strain = PKRS_Strain, + PokerusState = PokerusState, CaughtData = CaughtData, // Only copies until first 0x50 terminator, but just copy everything Nickname = Nickname, - OT_Name = OT_Name, + OriginalTrainerName = OriginalTrainerName, }; } diff --git a/PKHeX.Core/PKM/PK3.cs b/PKHeX.Core/PKM/PK3.cs index 6edcf4244..d0aed0e04 100644 --- a/PKHeX.Core/PKM/PK3.cs +++ b/PKHeX.Core/PKM/PK3.cs @@ -36,8 +36,8 @@ public override PK3 Clone() private const string EggNameJapanese = "タマゴ"; // Trash Bytes - public override Span Nickname_Trash => Data.AsSpan(0x08, 10); // no inaccessible terminator - public override Span OT_Trash => Data.AsSpan(0x14, 7); // no inaccessible terminator + public override Span NicknameTrash => Data.AsSpan(0x08, 10); // no inaccessible terminator + public override Span OriginalTrainerTrash => Data.AsSpan(0x14, 7); // no inaccessible terminator // At top for System.Reflection execution order hack @@ -48,17 +48,17 @@ public override PK3 Clone() public override ushort SID16 { get => ReadUInt16LittleEndian(Data.AsSpan(0x06)); set => WriteUInt16LittleEndian(Data.AsSpan(0x06), value); } public override string Nickname { - get => StringConverter3.GetString(Nickname_Trash, Japanese); - set => StringConverter3.SetString(Nickname_Trash, IsEgg ? EggNameJapanese : value, 10, Japanese, StringConverterOption.None); + get => StringConverter3.GetString(NicknameTrash, Japanese); + set => StringConverter3.SetString(NicknameTrash, IsEgg ? EggNameJapanese : value, 10, Japanese, StringConverterOption.None); } public override int Language { get => Data[0x12]; set => Data[0x12] = (byte)value; } public bool FlagIsBadEgg { get => (Data[0x13] & 1) != 0; set => Data[0x13] = (byte)((Data[0x13] & ~1) | (value ? 1 : 0)); } public bool FlagHasSpecies { get => (Data[0x13] & 2) != 0; set => Data[0x13] = (byte)((Data[0x13] & ~2) | (value ? 2 : 0)); } public bool FlagIsEgg { get => (Data[0x13] & 4) != 0; set => Data[0x13] = (byte)((Data[0x13] & ~4) | (value ? 4 : 0)); } - public override string OT_Name + public override string OriginalTrainerName { - get => StringConverter3.GetString(OT_Trash, Japanese); - set => StringConverter3.SetString(OT_Trash, value, 7, Japanese, StringConverterOption.None); + get => StringConverter3.GetString(OriginalTrainerTrash, Japanese); + set => StringConverter3.SetString(OriginalTrainerTrash, value, 7, Japanese, StringConverterOption.None); } public override byte MarkingValue { get => (byte)SwapBits(Data[0x1B], 1, 2); set => Data[0x1B] = (byte)SwapBits(value, 1, 2); } public ushort Checksum { get => ReadUInt16LittleEndian(Data.AsSpan(0x1C)); set => WriteUInt16LittleEndian(Data.AsSpan(0x1C), value); } @@ -86,7 +86,7 @@ public override ushort Species public override int Move2_PPUps { get => (PPUps >> 2) & 3; set => PPUps = (byte)((PPUps & ~(3 << 2)) | (value << 2)); } public override int Move3_PPUps { get => (PPUps >> 4) & 3; set => PPUps = (byte)((PPUps & ~(3 << 4)) | (value << 4)); } public override int Move4_PPUps { get => (PPUps >> 6) & 3; set => PPUps = (byte)((PPUps & ~(3 << 6)) | (value << 6)); } - public override int OT_Friendship { get => Data[0x29]; set => Data[0x29] = (byte)value; } + public override byte OriginalTrainerFriendship { get => Data[0x29]; set => Data[0x29] = value; } // Unused 0x2A 0x2B #endregion @@ -108,27 +108,27 @@ public override ushort Species public override int EV_SPE { get => Data[0x3B]; set => Data[0x3B] = (byte)value; } public override int EV_SPA { get => Data[0x3C]; set => Data[0x3C] = (byte)value; } public override int EV_SPD { get => Data[0x3D]; set => Data[0x3D] = (byte)value; } - public override byte CNT_Cool { get => Data[0x3E]; set => Data[0x3E] = value; } - public override byte CNT_Beauty { get => Data[0x3F]; set => Data[0x3F] = value; } - public override byte CNT_Cute { get => Data[0x40]; set => Data[0x40] = value; } - public override byte CNT_Smart { get => Data[0x41]; set => Data[0x41] = value; } - public override byte CNT_Tough { get => Data[0x42]; set => Data[0x42] = value; } - public override byte CNT_Sheen { get => Data[0x43]; set => Data[0x43] = value; } + public override byte ContestCool { get => Data[0x3E]; set => Data[0x3E] = value; } + public override byte ContestBeauty { get => Data[0x3F]; set => Data[0x3F] = value; } + public override byte ContestCute { get => Data[0x40]; set => Data[0x40] = value; } + public override byte ContestSmart { get => Data[0x41]; set => Data[0x41] = value; } + public override byte ContestTough { get => Data[0x42]; set => Data[0x42] = value; } + public override byte ContestSheen { get => Data[0x43]; set => Data[0x43] = value; } #endregion #region Block D - private byte PKRS { get => Data[0x44]; set => Data[0x44] = value; } - public override int PKRS_Days { get => PKRS & 0xF; set => PKRS = (byte)((PKRS & ~0xF) | value); } - public override int PKRS_Strain { get => PKRS >> 4; set => PKRS = (byte)((PKRS & 0xF) | (value << 4)); } - public override int Met_Location { get => Data[0x45]; set => Data[0x45] = (byte)value; } + public byte PokerusState { get => Data[0x44]; set => Data[0x44] = value; } + public override int PokerusDays { get => PokerusState & 0xF; set => PokerusState = (byte)((PokerusState & ~0xF) | value); } + public override int PokerusStrain { get => PokerusState >> 4; set => PokerusState = (byte)((PokerusState & 0xF) | (value << 4)); } + public override ushort MetLocation { get => Data[0x45]; set => Data[0x45] = (byte)value; } // Origins private ushort Origins { get => ReadUInt16LittleEndian(Data.AsSpan(0x46)); set => WriteUInt16LittleEndian(Data.AsSpan(0x46), value); } - public override int Met_Level { get => Origins & 0x7F; set => Origins = (ushort)((Origins & ~0x7F) | value); } - public override int Version { get => (Origins >> 7) & 0xF; set => Origins = (ushort)((Origins & ~0x780) | ((value & 0xF) << 7)); } - public override int Ball { get => (Origins >> 11) & 0xF; set => Origins = (ushort)((Origins & ~0x7800) | ((value & 0xF) << 11)); } - public override int OT_Gender { get => (Origins >> 15) & 1; set => Origins = (ushort)((Origins & ~(1 << 15)) | ((value & 1) << 15)); } + public override byte MetLevel { get => (byte)(Origins & 0x7F); set => Origins = (ushort)((Origins & ~0x7F) | value); } + public override GameVersion Version { get => (GameVersion)((Origins >> 7) & 0xF); set => Origins = (ushort)((Origins & ~0x780) | (((byte)value & 0xF) << 7)); } + public override byte Ball { get => (byte)((Origins >> 11) & 0xF); set => Origins = (ushort)((Origins & ~0x7800) | ((value & 0xF) << 11)); } + public override byte OriginalTrainerGender { get => (byte)((Origins >> 15) & 1); set => Origins = (ushort)((Origins & ~(1 << 15)) | ((value & 1) << 15)); } - private uint IV32 { get => ReadUInt32LittleEndian(Data.AsSpan(0x48)); set => WriteUInt32LittleEndian(Data.AsSpan(0x48), value); } + public uint IV32 { get => ReadUInt32LittleEndian(Data.AsSpan(0x48)); set => WriteUInt32LittleEndian(Data.AsSpan(0x48), value); } public override int IV_HP { get => (int)(IV32 >> 00) & 0x1F; set => IV32 = (IV32 & ~(0x1Fu << 00)) | ((value > 31 ? 31u : (uint)value) << 00); } public override int IV_ATK { get => (int)(IV32 >> 05) & 0x1F; set => IV32 = (IV32 & ~(0x1Fu << 05)) | ((value > 31 ? 31u : (uint)value) << 05); } public override int IV_DEF { get => (int)(IV32 >> 10) & 0x1F; set => IV32 = (IV32 & ~(0x1Fu << 10)) | ((value > 31 ? 31u : (uint)value) << 10); } @@ -182,7 +182,7 @@ public override bool IsEgg #region Battle Stats public override int Status_Condition { get => ReadInt32LittleEndian(Data.AsSpan(0x50)); set => WriteInt32LittleEndian(Data.AsSpan(0x50), value); } - public override int Stat_Level { get => Data[0x54]; set => Data[0x54] = (byte)value; } + public override byte Stat_Level { get => Data[0x54]; set => Data[0x54] = value; } public sbyte HeldMailID { get => (sbyte)Data[0x55]; set => Data[0x55] = (byte)value; } public override int Stat_HPCurrent { get => ReadUInt16LittleEndian(Data.AsSpan(0x56)); set => WriteUInt16LittleEndian(Data.AsSpan(0x56), (ushort)value); } public override int Stat_HPMax { get => ReadUInt16LittleEndian(Data.AsSpan(0x58)); set => WriteUInt16LittleEndian(Data.AsSpan(0x58), (ushort)value); } @@ -221,7 +221,7 @@ public PK4 ConvertToPK4() Gender = EntityGender.GetFromPID(Species, PID), Form = Form, // IsEgg = false, -- already false - OT_Friendship = 70, + OriginalTrainerFriendship = 70, MarkingValue = (byte)(MarkingValue & 0b1111), Language = Language, EV_HP = EV_HP, @@ -230,12 +230,12 @@ public PK4 ConvertToPK4() EV_SPA = EV_SPA, EV_SPD = EV_SPD, EV_SPE = EV_SPE, - CNT_Cool = CNT_Cool, - CNT_Beauty = CNT_Beauty, - CNT_Cute = CNT_Cute, - CNT_Smart = CNT_Smart, - CNT_Tough = CNT_Tough, - CNT_Sheen = CNT_Sheen, + ContestCool = ContestCool, + ContestBeauty = ContestBeauty, + ContestCute = ContestCute, + ContestSmart = ContestSmart, + ContestTough = ContestTough, + ContestSheen = ContestSheen, Move1 = Move1, Move2 = Move2, Move3 = Move3, @@ -244,21 +244,15 @@ public PK4 ConvertToPK4() Move2_PPUps = Move2_PPUps, Move3_PPUps = Move3_PPUps, Move4_PPUps = Move4_PPUps, - IV_HP = IV_HP, - IV_ATK = IV_ATK, - IV_DEF = IV_DEF, - IV_SPA = IV_SPA, - IV_SPD = IV_SPD, - IV_SPE = IV_SPE, + IV32 = IV32 & 0x3FFFFFFF, // keep low 30 bits for all IVs to copy. Nickname set later. Ability = Ability, Version = Version, Ball = Ball, - PKRS_Strain = PKRS_Strain, - PKRS_Days = PKRS_Days, - OT_Gender = OT_Gender, + PokerusState = PokerusState, + OriginalTrainerGender = OriginalTrainerGender, MetDate = EncounterDate.GetDateNDS(), - Met_Level = CurrentLevel, - Met_Location = Locations.Transfer3, // Pal Park + MetLevel = CurrentLevel, + MetLocation = Locations.Transfer3, // Pal Park RibbonChampionG3 = RibbonChampionG3, RibbonWinning = RibbonWinning, @@ -305,19 +299,20 @@ public PK4 ConvertToPK4() // Yay for reusing string buffers! The game allocates a buffer and reuses it when creating strings. // Trash from the {unknown source} is currently in buffer. Set it to the Nickname region. var trash = StringConverter345.GetTrashBytes(pk4.Language); - var nickTrash = pk4.Nickname_Trash[4..]; // min of 1 char and terminator, ignore first 2. + var nickTrash = pk4.NicknameTrash[4..]; // min of 1 char and terminator, ignore first 2. trash.CopyTo(nickTrash); pk4.Nickname = IsEgg ? SpeciesName.GetSpeciesNameGeneration(pk4.Species, pk4.Language, 4) : Nickname; pk4.IsNicknamed = !IsEgg && IsNicknamed; // Trash from the current string (Nickname) is in our string buffer. Slap the OT name over-top. - var destOT = pk4.OT_Trash; + var destOT = pk4.OriginalTrainerTrash; nickTrash[..destOT.Length].CopyTo(destOT); - pk4.OT_Name = OT_Name; + pk4.OriginalTrainerName = OriginalTrainerName; - if (HeldItem > 0) + var item = (ushort)HeldItem; + if (item != 0) { - ushort item = ItemConverter.GetItemFuture3((ushort)HeldItem); + item = ItemConverter.GetItemFuture3(item); if (ItemConverter.IsItemTransferable34(item)) pk4.HeldItem = item; } diff --git a/PKHeX.Core/PKM/PK4.cs b/PKHeX.Core/PKM/PK4.cs index 292b21921..4f2e6748e 100644 --- a/PKHeX.Core/PKM/PK4.cs +++ b/PKHeX.Core/PKM/PK4.cs @@ -41,7 +41,7 @@ private static byte[] DecryptParty(byte[] data) public override ushort TID16 { get => ReadUInt16LittleEndian(Data.AsSpan(0x0C)); set => WriteUInt16LittleEndian(Data.AsSpan(0x0C), value); } public override ushort SID16 { get => ReadUInt16LittleEndian(Data.AsSpan(0x0E)); set => WriteUInt16LittleEndian(Data.AsSpan(0x0E), value); } public override uint EXP { get => ReadUInt32LittleEndian(Data.AsSpan(0x10)); set => WriteUInt32LittleEndian(Data.AsSpan(0x10), value); } - public override int OT_Friendship { get => Data[0x14]; set => Data[0x14] = (byte)value; } + public override byte OriginalTrainerFriendship { get => Data[0x14]; set => Data[0x14] = value; } public override int Ability { get => Data[0x15]; set => Data[0x15] = (byte)value; } public override byte MarkingValue { get => Data[0x16]; set => Data[0x16] = value; } public override int Language { get => Data[0x17]; set => Data[0x17] = (byte)value; } @@ -51,12 +51,12 @@ private static byte[] DecryptParty(byte[] data) public override int EV_SPE { get => Data[0x1B]; set => Data[0x1B] = (byte)value; } public override int EV_SPA { get => Data[0x1C]; set => Data[0x1C] = (byte)value; } public override int EV_SPD { get => Data[0x1D]; set => Data[0x1D] = (byte)value; } - public override byte CNT_Cool { get => Data[0x1E]; set => Data[0x1E] = value; } - public override byte CNT_Beauty { get => Data[0x1F]; set => Data[0x1F] = value; } - public override byte CNT_Cute { get => Data[0x20]; set => Data[0x20] = value; } - public override byte CNT_Smart { get => Data[0x21]; set => Data[0x21] = value; } - public override byte CNT_Tough { get => Data[0x22]; set => Data[0x22] = value; } - public override byte CNT_Sheen { get => Data[0x23]; set => Data[0x23] = value; } + public override byte ContestCool { get => Data[0x1E]; set => Data[0x1E] = value; } + public override byte ContestBeauty { get => Data[0x1F]; set => Data[0x1F] = value; } + public override byte ContestCute { get => Data[0x20]; set => Data[0x20] = value; } + public override byte ContestSmart { get => Data[0x21]; set => Data[0x21] = value; } + public override byte ContestTough { get => Data[0x22]; set => Data[0x22] = value; } + public override byte ContestSheen { get => Data[0x23]; set => Data[0x23] = value; } private byte RIB0 { get => Data[0x24]; set => Data[0x24] = value; } // Sinnoh 1 private byte RIB1 { get => Data[0x25]; set => Data[0x25] = value; } // Sinnoh 2 @@ -113,7 +113,7 @@ private static byte[] DecryptParty(byte[] data) public override int Move2_PPUps { get => Data[0x35]; set => Data[0x35] = (byte)value; } public override int Move3_PPUps { get => Data[0x36]; set => Data[0x36] = (byte)value; } public override int Move4_PPUps { get => Data[0x37]; set => Data[0x37] = (byte)value; } - protected internal override uint IV32 { get => ReadUInt32LittleEndian(Data.AsSpan(0x38)); set => WriteUInt32LittleEndian(Data.AsSpan(0x38), value); } + public override uint IV32 { get => ReadUInt32LittleEndian(Data.AsSpan(0x38)); set => WriteUInt32LittleEndian(Data.AsSpan(0x38), value); } public override int IV_HP { get => (int)(IV32 >> 00) & 0x1F; set => IV32 = (IV32 & ~(0x1Fu << 00)) | ((value > 31 ? 31u : (uint)value) << 00); } public override int IV_ATK { get => (int)(IV32 >> 05) & 0x1F; set => IV32 = (IV32 & ~(0x1Fu << 05)) | ((value > 31 ? 31u : (uint)value) << 05); } public override int IV_DEF { get => (int)(IV32 >> 10) & 0x1F; set => IV32 = (IV32 & ~(0x1Fu << 10)) | ((value > 31 ? 31u : (uint)value) << 10); } @@ -161,17 +161,17 @@ private static byte[] DecryptParty(byte[] data) public override bool RibbonWorld { get => (RIB7 & (1 << 7)) == 1 << 7; set => RIB7 = (byte)((RIB7 & ~(1 << 7)) | (value ? 1 << 7 : 0)); } public override bool FatefulEncounter { get => (Data[0x40] & 1) == 1; set => Data[0x40] = (byte)((Data[0x40] & ~0x01) | (value ? 1 : 0)); } - public override int Gender { get => (Data[0x40] >> 1) & 0x3; set => Data[0x40] = (byte)((Data[0x40] & ~0x06) | (value << 1)); } + public override byte Gender { get => (byte)((Data[0x40] >> 1) & 0x3); set => Data[0x40] = (byte)((Data[0x40] & ~0x06) | (value << 1)); } public override byte Form { get => (byte)(Data[0x40] >> 3); set => Data[0x40] = (byte)((Data[0x40] & 0x07) | (value << 3)); } public override int ShinyLeaf { get => Data[0x41]; set => Data[0x41] = (byte) value; } // 0x42-0x43 Unused - public override ushort Egg_LocationExtended + public override ushort EggLocationExtended { get => ReadUInt16LittleEndian(Data.AsSpan(0x44)); set => WriteUInt16LittleEndian(Data.AsSpan(0x44), value); } - public override ushort Met_LocationExtended + public override ushort MetLocationExtended { get => ReadUInt16LittleEndian(Data.AsSpan(0x46)); set => WriteUInt16LittleEndian(Data.AsSpan(0x46), value); @@ -182,12 +182,12 @@ public override ushort Met_LocationExtended #region Block C public override string Nickname { - get => StringConverter4.GetString(Nickname_Trash); - set => StringConverter4.SetString(Nickname_Trash, value, 10, StringConverterOption.None); + get => StringConverter4.GetString(NicknameTrash); + set => StringConverter4.SetString(NicknameTrash, value, 10, StringConverterOption.None); } // 0x5E unused - public override int Version { get => Data[0x5F]; set => Data[0x5F] = (byte)value; } + public override GameVersion Version { get => (GameVersion)Data[0x5F]; set => Data[0x5F] = (byte)value; } private byte RIB8 { get => Data[0x60]; set => Data[0x60] = value; } // Sinnoh 3 private byte RIB9 { get => Data[0x61]; set => Data[0x61] = value; } // Sinnoh 4 private byte RIBA { get => Data[0x62]; set => Data[0x62] = value; } // Sinnoh 5 @@ -228,36 +228,36 @@ public override string Nickname #endregion #region Block D - public override string OT_Name + public override string OriginalTrainerName { - get => StringConverter4.GetString(OT_Trash); - set => StringConverter4.SetString(OT_Trash, value, 7, StringConverterOption.None); + get => StringConverter4.GetString(OriginalTrainerTrash); + set => StringConverter4.SetString(OriginalTrainerTrash, value, 7, StringConverterOption.None); } - public override int Egg_Year { get => Data[0x78]; set => Data[0x78] = (byte)value; } - public override int Egg_Month { get => Data[0x79]; set => Data[0x79] = (byte)value; } - public override int Egg_Day { get => Data[0x7A]; set => Data[0x7A] = (byte)value; } - public override int Met_Year { get => Data[0x7B]; set => Data[0x7B] = (byte)value; } - public override int Met_Month { get => Data[0x7C]; set => Data[0x7C] = (byte)value; } - public override int Met_Day { get => Data[0x7D]; set => Data[0x7D] = (byte)value; } + public override byte EggYear { get => Data[0x78]; set => Data[0x78] = value; } + public override byte EggMonth { get => Data[0x79]; set => Data[0x79] = value; } + public override byte EggDay { get => Data[0x7A]; set => Data[0x7A] = value; } + public override byte MetYear { get => Data[0x7B]; set => Data[0x7B] = value; } + public override byte MetMonth { get => Data[0x7C]; set => Data[0x7C] = value; } + public override byte MetDay { get => Data[0x7D]; set => Data[0x7D] = value; } - public override ushort Egg_LocationDP + public override ushort EggLocationDP { get => ReadUInt16LittleEndian(Data.AsSpan(0x7E)); set => WriteUInt16LittleEndian(Data.AsSpan(0x7E), value); } - public override ushort Met_LocationDP + public override ushort MetLocationDP { get => ReadUInt16LittleEndian(Data.AsSpan(0x80)); set => WriteUInt16LittleEndian(Data.AsSpan(0x80), value); } - private byte PKRS { get => Data[0x82]; set => Data[0x82] = value; } - public override int PKRS_Days { get => PKRS & 0xF; set => PKRS = (byte)((PKRS & ~0xF) | value); } - public override int PKRS_Strain { get => PKRS >> 4; set => PKRS = (byte)((PKRS & 0xF) | (value << 4)); } + public override byte PokerusState { get => Data[0x82]; set => Data[0x82] = value; } + public override int PokerusDays { get => PokerusState & 0xF; set => PokerusState = (byte)((PokerusState & ~0xF) | value); } + public override int PokerusStrain { get => PokerusState >> 4; set => PokerusState = (byte)((PokerusState & 0xF) | (value << 4)); } public override byte BallDPPt { get => Data[0x83]; set => Data[0x83] = value; } - public override int Met_Level { get => Data[0x84] & ~0x80; set => Data[0x84] = (byte)((Data[0x84] & 0x80) | value); } - public override int OT_Gender { get => Data[0x84] >> 7; set => Data[0x84] = (byte)((Data[0x84] & ~0x80) | (value << 7)); } + public override byte MetLevel { get => (byte)(Data[0x84] & ~0x80); set => Data[0x84] = (byte)((Data[0x84] & 0x80) | value); } + public override byte OriginalTrainerGender { get => (byte)(Data[0x84] >> 7); set => Data[0x84] = (byte)((Data[0x84] & ~0x80) | (value << 7)); } public override GroundTileType GroundTile { get => (GroundTileType)Data[0x85]; set => Data[0x85] = (byte)value; } public override byte BallHGSS { get => Data[0x86]; set => Data[0x86] = value; } public override byte PokeathlonStat { get => Data[0x87]; set => Data[0x87] = value; } @@ -265,7 +265,7 @@ public override ushort Met_LocationDP #region Battle Stats public override int Status_Condition { get => ReadInt32LittleEndian(Data.AsSpan(0x88)); set => WriteInt32LittleEndian(Data.AsSpan(0x88), value); } - public override int Stat_Level { get => Data[0x8C]; set => Data[0x8C] = (byte)value; } + public override byte Stat_Level { get => Data[0x8C]; set => Data[0x8C] = value; } public byte BallCapsuleIndex { get => Data[0x8D]; set => Data[0x8D] = value; } public override int Stat_HPCurrent { get => ReadUInt16LittleEndian(Data.AsSpan(0x8E)); set => WriteUInt16LittleEndian(Data.AsSpan(0x8E), (ushort)value); } public override int Stat_HPMax { get => ReadUInt16LittleEndian(Data.AsSpan(0x90)); set => WriteUInt16LittleEndian(Data.AsSpan(0x90), (ushort)value); } @@ -298,10 +298,8 @@ public BK4 ConvertToBK4() public RK4 ConvertToRK4() { - byte[] data = Data.AsSpan(0, PokeCrypto.SIZE_4RSTORED).ToArray(); - for (int i = PokeCrypto.SIZE_4STORED; i < PokeCrypto.SIZE_4RSTORED; i++) - data[i] = 0; - + var data = new byte[PokeCrypto.SIZE_4STORED]; + Data.AsSpan(0, PokeCrypto.SIZE_4RSTORED).CopyTo(data); var rk4 = new RK4(data) { OwnershipType = RanchOwnershipType.Hayley }; rk4.RefreshChecksum(); @@ -311,13 +309,13 @@ public RK4 ConvertToRK4() public PK5 ConvertToPK5() { // Double Check Location Data to see if we're already a PK5 - if (Data[0x5F] < 0x10 && ReadUInt16LittleEndian(Data.AsSpan(0x80)) > 0x4000) + if (Version <= GameVersion.CXD && MetLocationDP > 0x4000) return new PK5(Data); PK5 pk5 = new(Data.AsSpan(0, PokeCrypto.SIZE_5PARTY).ToArray()) // Convert away! { JunkByte = 0, - OT_Friendship = 70, + OriginalTrainerFriendship = 70, // Apply new met date MetDate = EncounterDate.GetDateNDS(), }; @@ -344,21 +342,21 @@ public PK5 ConvertToPK5() pk5.Data.AsSpan(0x44, 4).Clear(); // Met / Crown Data Detection - pk5.Met_Location = PK5.GetTransferMetLocation4(pk5); + pk5.MetLocation = PK5.GetTransferMetLocation4(pk5); // Egg Location is not modified; when clearing Pt/HGSS egg data, the location will revert to Faraway Place - // pk5.Egg_Location = Egg_Location; + // pk5.EggLocation = EggLocation; // Delete HG/S Data pk5.Data.AsSpan(0x86, 2).Clear(); pk5.Ball = Ball; // Transfer Nickname and OT Name, update encoding - pk5.Nickname = Nickname; - pk5.OT_Name = OT_Name; + TransferTrash(NicknameTrash, pk5.NicknameTrash); + TransferTrash(OriginalTrainerTrash, pk5.OriginalTrainerTrash); // Fix Level - pk5.Met_Level = pk5.CurrentLevel; + pk5.MetLevel = pk5.CurrentLevel; // Remove HM moves; Defog should be kept if both are learned. // If it has Defog, remove Whirlpool. @@ -377,4 +375,11 @@ public PK5 ConvertToPK5() pk5.RefreshChecksum(); return pk5; } + + public static void TransferTrash(ReadOnlySpan src, Span dest) + { + Span temp = stackalloc char[13]; + var len = StringConverter4.LoadString(src, temp); + StringConverter5.SetString(dest, temp[..len], len); + } } diff --git a/PKHeX.Core/PKM/PK5.cs b/PKHeX.Core/PKM/PK5.cs index a203ae1b3..da5abb937 100644 --- a/PKHeX.Core/PKM/PK5.cs +++ b/PKHeX.Core/PKM/PK5.cs @@ -41,13 +41,13 @@ private static byte[] DecryptParty(byte[] data) private ushort CalculateChecksum() => Checksums.Add16(Data.AsSpan()[8..PokeCrypto.SIZE_4STORED]); // Trash Bytes - public override Span Nickname_Trash => Data.AsSpan(0x48, 22); - public override Span OT_Trash => Data.AsSpan(0x68, 16); + public override Span NicknameTrash => Data.AsSpan(0x48, 22); + public override Span OriginalTrainerTrash => Data.AsSpan(0x68, 16); // Future Attributes public override uint EncryptionConstant { get => PID; set { } } - public override int CurrentFriendship { get => OT_Friendship; set => OT_Friendship = value; } - public override int CurrentHandler { get => 0; set { } } + public override byte CurrentFriendship { get => OriginalTrainerFriendship; set => OriginalTrainerFriendship = value; } + public override byte CurrentHandler { get => 0; set { } } public override int AbilityNumber { get => HiddenAbility ? 4 : 1 << PIDAbility; set { } } // Structure @@ -62,7 +62,7 @@ private static byte[] DecryptParty(byte[] data) public override ushort TID16 { get => ReadUInt16LittleEndian(Data.AsSpan(0x0C)); set => WriteUInt16LittleEndian(Data.AsSpan(0x0C), value); } public override ushort SID16 { get => ReadUInt16LittleEndian(Data.AsSpan(0x0E)); set => WriteUInt16LittleEndian(Data.AsSpan(0x0E), value); } public override uint EXP { get => ReadUInt32LittleEndian(Data.AsSpan(0x10)); set => WriteUInt32LittleEndian(Data.AsSpan(0x10), value); } - public override int OT_Friendship { get => Data[0x14]; set => Data[0x14] = (byte)value; } + public override byte OriginalTrainerFriendship { get => Data[0x14]; set => Data[0x14] = value; } public override int Ability { get => Data[0x15]; set => Data[0x15] = (byte)value; } public byte MarkingValue { get => Data[0x16]; set => Data[0x16] = value; } public override int Language { get => Data[0x17]; set => Data[0x17] = (byte)value; } @@ -72,12 +72,12 @@ private static byte[] DecryptParty(byte[] data) public override int EV_SPE { get => Data[0x1B]; set => Data[0x1B] = (byte)value; } public override int EV_SPA { get => Data[0x1C]; set => Data[0x1C] = (byte)value; } public override int EV_SPD { get => Data[0x1D]; set => Data[0x1D] = (byte)value; } - public byte CNT_Cool { get => Data[0x1E]; set => Data[0x1E] = value; } - public byte CNT_Beauty { get => Data[0x1F]; set => Data[0x1F] = value; } - public byte CNT_Cute { get => Data[0x20]; set => Data[0x20] = value; } - public byte CNT_Smart { get => Data[0x21]; set => Data[0x21] = value; } - public byte CNT_Tough { get => Data[0x22]; set => Data[0x22] = value; } - public byte CNT_Sheen { get => Data[0x23]; set => Data[0x23] = value; } + public byte ContestCool { get => Data[0x1E]; set => Data[0x1E] = value; } + public byte ContestBeauty { get => Data[0x1F]; set => Data[0x1F] = value; } + public byte ContestCute { get => Data[0x20]; set => Data[0x20] = value; } + public byte ContestSmart { get => Data[0x21]; set => Data[0x21] = value; } + public byte ContestTough { get => Data[0x22]; set => Data[0x22] = value; } + public byte ContestSheen { get => Data[0x23]; set => Data[0x23] = value; } private byte RIB0 { get => Data[0x24]; set => Data[0x24] = value; } // Sinnoh 1 private byte RIB1 { get => Data[0x25]; set => Data[0x25] = value; } // Sinnoh 2 @@ -134,7 +134,7 @@ private static byte[] DecryptParty(byte[] data) public override int Move2_PPUps { get => Data[0x35]; set => Data[0x35] = (byte)value; } public override int Move3_PPUps { get => Data[0x36]; set => Data[0x36] = (byte)value; } public override int Move4_PPUps { get => Data[0x37]; set => Data[0x37] = (byte)value; } - private uint IV32 { get => ReadUInt32LittleEndian(Data.AsSpan(0x38)); set => WriteUInt32LittleEndian(Data.AsSpan(0x38), value); } + public uint IV32 { get => ReadUInt32LittleEndian(Data.AsSpan(0x38)); set => WriteUInt32LittleEndian(Data.AsSpan(0x38), value); } public override int IV_HP { get => (int)(IV32 >> 00) & 0x1F; set => IV32 = (IV32 & ~(0x1Fu << 00)) | ((value > 31 ? 31u : (uint)value) << 00); } public override int IV_ATK { get => (int)(IV32 >> 05) & 0x1F; set => IV32 = (IV32 & ~(0x1Fu << 05)) | ((value > 31 ? 31u : (uint)value) << 05); } public override int IV_DEF { get => (int)(IV32 >> 10) & 0x1F; set => IV32 = (IV32 & ~(0x1Fu << 10)) | ((value > 31 ? 31u : (uint)value) << 10); } @@ -182,18 +182,18 @@ private static byte[] DecryptParty(byte[] data) public bool RibbonWorld { get => (RIB7 & (1 << 7)) == 1 << 7; set => RIB7 = (byte)((RIB7 & ~(1 << 7)) | (value ? 1 << 7 : 0)); } public override bool FatefulEncounter { get => (Data[0x40] & 1) == 1; set => Data[0x40] = (byte)((Data[0x40] & ~0x01) | (value ? 1 : 0)); } - public override int Gender { get => (Data[0x40] >> 1) & 0x3; set => Data[0x40] = (byte)((Data[0x40] & ~0x06) | (value << 1)); } + public override byte Gender { get => (byte)((Data[0x40] >> 1) & 0x3); set => Data[0x40] = (byte)((Data[0x40] & ~0x06) | (value << 1)); } public override byte Form { get => (byte)(Data[0x40] >> 3); set => Data[0x40] = (byte)((Data[0x40] & 0x07) | (value << 3)); } - public override int Nature { get => Data[0x41]; set => Data[0x41] = (byte)value; } + public override Nature Nature { get => (Nature)Data[0x41]; set => Data[0x41] = (byte)value; } public bool HiddenAbility { get => (Data[0x42] & 1) == 1; set => Data[0x42] = (byte)((Data[0x42] & ~0x01) | (value ? 1 : 0)); } public bool NSparkle { get => (Data[0x42] & 2) == 2; set => Data[0x42] = (byte)((Data[0x42] & ~0x02) | (value ? 2 : 0)); } // 0x43-0x47 Unused #endregion #region Block C - public override string Nickname { get => StringConverter5.GetString(Nickname_Trash); set => StringConverter5.SetString(Nickname_Trash, value, 10, StringConverterOption.None); } + public override string Nickname { get => StringConverter5.GetString(NicknameTrash); set => StringConverter5.SetString(NicknameTrash, value, 10, StringConverterOption.None); } // 0x5E unused - public override int Version { get => Data[0x5F]; set => Data[0x5F] = (byte)value; } + public override GameVersion Version { get => (GameVersion)Data[0x5F]; set => Data[0x5F] = (byte)value; } private byte RIB8 { get => Data[0x60]; set => Data[0x60] = value; } // Sinnoh 3 private byte RIB9 { get => Data[0x61]; set => Data[0x61] = value; } // Sinnoh 4 private byte RIBA { get => Data[0x62]; set => Data[0x62] = value; } // Sinnoh 5 @@ -234,21 +234,21 @@ private static byte[] DecryptParty(byte[] data) #endregion #region Block D - public override string OT_Name { get => StringConverter5.GetString(OT_Trash); set => StringConverter5.SetString(OT_Trash, value, 7, StringConverterOption.None); } - public override int Egg_Year { get => Data[0x78]; set => Data[0x78] = (byte)value; } - public override int Egg_Month { get => Data[0x79]; set => Data[0x79] = (byte)value; } - public override int Egg_Day { get => Data[0x7A]; set => Data[0x7A] = (byte)value; } - public override int Met_Year { get => Data[0x7B]; set => Data[0x7B] = (byte)value; } - public override int Met_Month { get => Data[0x7C]; set => Data[0x7C] = (byte)value; } - public override int Met_Day { get => Data[0x7D]; set => Data[0x7D] = (byte)value; } - public override int Egg_Location { get => ReadUInt16LittleEndian(Data.AsSpan(0x7E)); set => WriteUInt16LittleEndian(Data.AsSpan(0x7E), (ushort)value); } - public override int Met_Location { get => ReadUInt16LittleEndian(Data.AsSpan(0x80)); set => WriteUInt16LittleEndian(Data.AsSpan(0x80), (ushort)value); } - private byte PKRS { get => Data[0x82]; set => Data[0x82] = value; } - public override int PKRS_Days { get => PKRS & 0xF; set => PKRS = (byte)((PKRS & ~0xF) | value); } - public override int PKRS_Strain { get => PKRS >> 4; set => PKRS = (byte)((PKRS & 0xF) | (value << 4)); } - public override int Ball { get => Data[0x83]; set => Data[0x83] = (byte)value; } - public override int Met_Level { get => Data[0x84] & ~0x80; set => Data[0x84] = (byte)((Data[0x84] & 0x80) | value); } - public override int OT_Gender { get => Data[0x84] >> 7; set => Data[0x84] = (byte)((Data[0x84] & ~0x80) | (value << 7)); } + public override string OriginalTrainerName { get => StringConverter5.GetString(OriginalTrainerTrash); set => StringConverter5.SetString(OriginalTrainerTrash, value, 7, StringConverterOption.None); } + public override byte EggYear { get => Data[0x78]; set => Data[0x78] = value; } + public override byte EggMonth { get => Data[0x79]; set => Data[0x79] = value; } + public override byte EggDay { get => Data[0x7A]; set => Data[0x7A] = value; } + public override byte MetYear { get => Data[0x7B]; set => Data[0x7B] = value; } + public override byte MetMonth { get => Data[0x7C]; set => Data[0x7C] = value; } + public override byte MetDay { get => Data[0x7D]; set => Data[0x7D] = value; } + public override ushort EggLocation { get => ReadUInt16LittleEndian(Data.AsSpan(0x7E)); set => WriteUInt16LittleEndian(Data.AsSpan(0x7E), value); } + public override ushort MetLocation { get => ReadUInt16LittleEndian(Data.AsSpan(0x80)); set => WriteUInt16LittleEndian(Data.AsSpan(0x80), value); } + public byte PokerusState { get => Data[0x82]; set => Data[0x82] = value; } + public override int PokerusDays { get => PokerusState & 0xF; set => PokerusState = (byte)((PokerusState & ~0xF) | value); } + public override int PokerusStrain { get => PokerusState >> 4; set => PokerusState = (byte)((PokerusState & 0xF) | (value << 4)); } + public override byte Ball { get => Data[0x83]; set => Data[0x83] = value; } + public override byte MetLevel { get => (byte)(Data[0x84] & ~0x80); set => Data[0x84] = (byte)((Data[0x84] & 0x80) | value); } + public override byte OriginalTrainerGender { get => (byte)(Data[0x84] >> 7); set => Data[0x84] = (byte)((Data[0x84] & ~0x80) | (value << 7)); } public GroundTileType GroundTile { get => (GroundTileType)Data[0x85]; set => Data[0x85] = (byte)value; } // 0x86 Unused public byte PokeStarFame { get => Data[0x87]; set => Data[0x87] = value; } @@ -257,7 +257,7 @@ private static byte[] DecryptParty(byte[] data) #region Battle Stats public override int Status_Condition { get => ReadInt32LittleEndian(Data.AsSpan(0x88)); set => WriteInt32LittleEndian(Data.AsSpan(0x88), value); } - public override int Stat_Level { get => Data[0x8C]; set => Data[0x8C] = (byte)value; } + public override byte Stat_Level { get => Data[0x8C]; set => Data[0x8C] = value; } public byte JunkByte { get => Data[0x8D]; set => Data[0x8D] = value; } public override int Stat_HPCurrent { get => ReadUInt16LittleEndian(Data.AsSpan(0x8E)); set => WriteUInt16LittleEndian(Data.AsSpan(0x8E), (ushort)value); } public override int Stat_HPMax { get => ReadUInt16LittleEndian(Data.AsSpan(0x90)); set => WriteUInt16LittleEndian(Data.AsSpan(0x90), (ushort)value); } @@ -283,7 +283,7 @@ private static byte[] DecryptParty(byte[] data) public override int MaxAbilityID => Legal.MaxAbilityID_5; public override int MaxItemID => Legal.MaxItemID_5_B2W2; public override int MaxBallID => Legal.MaxBallID_5; - public override int MaxGameID => Legal.MaxGameID_5; // B2 + public override GameVersion MaxGameID => Legal.MaxGameID_5; // B2 public override int MaxIV => 31; public override int MaxEV => EffortValues.Max255; public override int MaxStringLengthOT => 7; @@ -299,7 +299,7 @@ protected override byte[] Encrypt() // Synthetic Trading Logic public bool Trade(string SAV_Trainer, uint savID32, int SAV_GENDER, int Day = 1, int Month = 1, int Year = 2013) { - if (IsEgg && !(SAV_Trainer == OT_Name && savID32 == ID32 && SAV_GENDER == OT_Gender)) + if (IsEgg && !(SAV_Trainer == OriginalTrainerName && savID32 == ID32 && SAV_GENDER == OriginalTrainerGender)) { SetLinkTradeEgg(Day, Month, Year, Locations.LinkTrade5); return true; @@ -351,12 +351,12 @@ public PK6 ConvertToPK6() MarkingValue = MarkingValue, Language = Math.Max((int)LanguageID.Japanese, Language), // Hacked or Bad IngameTrade (Japanese B/W) - CNT_Cool = CNT_Cool, - CNT_Beauty = CNT_Beauty, - CNT_Cute = CNT_Cute, - CNT_Smart = CNT_Smart, - CNT_Tough = CNT_Tough, - CNT_Sheen = CNT_Sheen, + ContestCool = ContestCool, + ContestBeauty = ContestBeauty, + ContestCute = ContestCute, + ContestSmart = ContestSmart, + ContestTough = ContestTough, + ContestSheen = ContestSheen, // Cap EVs -- anything above 252 is dropped down to 252. EV_HP = Math.Min(EV_HP , EffortValues.Max252), @@ -376,14 +376,7 @@ public PK6 ConvertToPK6() Move3_PPUps = Move3_PPUps, Move4_PPUps = Move4_PPUps, - IV_HP = IV_HP, - IV_ATK = IV_ATK, - IV_DEF = IV_DEF, - IV_SPA = IV_SPA, - IV_SPD = IV_SPD, - IV_SPE = IV_SPE, - IsEgg = IsEgg, - IsNicknamed = IsNicknamed, + IV32 = IV32, FatefulEncounter = FatefulEncounter, Gender = Gender, @@ -391,28 +384,27 @@ public PK6 ConvertToPK6() Nature = Nature, Version = Version, - OT_Name = OT_Name, + OriginalTrainerName = OriginalTrainerName, // Dates are kept upon transfer MetDate = MetDate, EggMetDate = EggMetDate, // Locations are kept upon transfer - Met_Location = Met_Location, - Egg_Location = Egg_Location, + MetLocation = MetLocation, + EggLocation = EggLocation, - PKRS_Strain = PKRS_Strain, - PKRS_Days = PKRS_Days, + PokerusState = PokerusState, Ball = Ball, // OT Gender & Encounter Level - Met_Level = Met_Level, - OT_Gender = OT_Gender, + MetLevel = MetLevel, + OriginalTrainerGender = OriginalTrainerGender, GroundTile = GroundTile, // Fill the Ribbon Counter Bytes - RibbonCountMemoryContest = CountContestRibbons(), - RibbonCountMemoryBattle = CountBattleRibbons(), + RibbonCountMemoryContest = CountContestRibbons(Data), + RibbonCountMemoryBattle = CountBattleRibbons(Data), // Copy Ribbons to their new locations. RibbonChampionG3 = RibbonChampionG3, @@ -454,11 +446,11 @@ public PK6 ConvertToPK6() // Write the Memories, Friendship, and Origin! CurrentHandler = 1, - HT_Name = RecentTrainerCache.OT_Name, - HT_Gender = RecentTrainerCache.OT_Gender, - HT_Intensity = 1, - HT_Memory = 4, - HT_Feeling = MemoryContext6.GetRandomFeeling6(4, 10), + HandlingTrainerName = RecentTrainerCache.OriginalTrainerName, + HandlingTrainerGender = RecentTrainerCache.OriginalTrainerGender, + HandlingTrainerMemoryIntensity = 1, + HandlingTrainerMemory = 4, + HandlingTrainerMemoryFeeling = MemoryContext6.GetRandomFeeling6(4, 10), }; // Write Transfer Location - location is dependent on 3DS system that transfers. @@ -474,7 +466,7 @@ public PK6 ConvertToPK6() pk6.Nickname = Nickname; // When transferred, friendship gets reset. - pk6.OT_Friendship = pk6.HT_Friendship = PersonalInfo.BaseFriendship; + pk6.OriginalTrainerFriendship = pk6.HandlingTrainerFriendship = PersonalInfo.BaseFriendship; // Gen6 changed the shiny correlation to have 2x the rate. // If the current PID would be shiny with those increased odds, fix it. @@ -488,8 +480,8 @@ public PK6 ConvertToPK6() pk6.HealPP(); // Fix Name Strings - StringConverter345.TransferGlyphs56(pk6.Nickname_Trash); - StringConverter345.TransferGlyphs56(pk6.OT_Trash); + StringConverter345.TransferGlyphs56(pk6.NicknameTrash); + StringConverter345.TransferGlyphs56(pk6.OriginalTrainerTrash); // Fix Checksum pk6.RefreshChecksum(); @@ -497,38 +489,19 @@ public PK6 ConvertToPK6() return pk6; // Done! } - private byte CountBattleRibbons() + private static byte CountBattleRibbons(ReadOnlySpan data) { - byte count = 0; - if (RibbonWinning) count++; - if (RibbonVictory) count++; - for (int i = 1; i < 7; i++) // Sinnoh Battle Ribbons - { - if (((Data[0x24] >> i) & 1) == 1) - count++; - } - - return count; + var bits1 = data[0x24] & 0b0111_1111u; // Battle Ribbons + var bits2 = data[0x3E] & 0b0110_0000u; // Winning & Victory Ribbons + return (byte)BitOperations.PopCount(bits1 | (bits2 << 2)); } - private byte CountContestRibbons() + private static byte CountContestRibbons(ReadOnlySpan data) { - byte count = 0; - for (int i = 0; i < 8; i++) // Sinnoh 3, Hoenn 1 - { - if (((Data[0x60] >> i) & 1) == 1) count++; - if (((Data[0x61] >> i) & 1) == 1) count++; - if (((Data[0x3C] >> i) & 1) == 1) count++; - if (((Data[0x3D] >> i) & 1) == 1) count++; - } - - for (int i = 0; i < 4; i++) // Sinnoh 4, Hoenn 2 - { - if (((Data[0x62] >> i) & 1) == 1) count++; - if (((Data[0x3E] >> i) & 1) == 1) count++; - } - - return count; + // Gather all 40 bits into a single ulong and PopCount rather than looping each byte. + var bits1 = ReadUInt32LittleEndian(data[0x60..]) & 0b1111_11111111_11111111; + var bits2 = ReadUInt32LittleEndian(data[0x3C..]) & 0b1111_11111111_11111111; + return (byte)BitOperations.PopCount(((ulong)bits1 << 20) | bits2); } private int CalculateAbilityIndex() @@ -547,11 +520,11 @@ private int CalculateAbilityIndex() return (int)(pid & 1); } - internal static int GetTransferMetLocation4(PKM pk) + internal static ushort GetTransferMetLocation4(PKM pk) { // Everything except for crown beasts and Celebi get the default transfer location. // Crown beasts and Celebi are 100% identifiable by the species ID and fateful encounter, originating from Gen4. - if (!pk.Gen4 || !pk.FatefulEncounter) + if (!pk.FatefulEncounter || !pk.Gen4) return Locations.Transfer4; // Pokétransfer return pk.Species switch diff --git a/PKHeX.Core/PKM/PK6.cs b/PKHeX.Core/PKM/PK6.cs index 0d30c3d3e..0b3089ed5 100644 --- a/PKHeX.Core/PKM/PK6.cs +++ b/PKHeX.Core/PKM/PK6.cs @@ -96,9 +96,9 @@ public override uint PID set => WriteUInt32LittleEndian(Data.AsSpan(0x18), value); } - public override int Nature { get => Data[0x1C]; set => Data[0x1C] = (byte)value; } + public override Nature Nature { get => (Nature)Data[0x1C]; set => Data[0x1C] = (byte)value; } public override bool FatefulEncounter { get => (Data[0x1D] & 1) == 1; set => Data[0x1D] = (byte)((Data[0x1D] & ~0x01) | (value ? 1 : 0)); } - public override int Gender { get => (Data[0x1D] >> 1) & 0x3; set => Data[0x1D] = (byte)((Data[0x1D] & ~0x06) | (value << 1)); } + public override byte Gender { get => (byte)((Data[0x1D] >> 1) & 0x3); set => Data[0x1D] = (byte)((Data[0x1D] & ~0x06) | (value << 1)); } public override byte Form { get => (byte)(Data[0x1D] >> 3); set => Data[0x1D] = (byte)((Data[0x1D] & 0x07) | (value << 3)); } public override int EV_HP { get => Data[0x1E]; set => Data[0x1E] = (byte)value; } public override int EV_ATK { get => Data[0x1F]; set => Data[0x1F] = (byte)value; } @@ -106,16 +106,16 @@ public override uint PID public override int EV_SPE { get => Data[0x21]; set => Data[0x21] = (byte)value; } public override int EV_SPA { get => Data[0x22]; set => Data[0x22] = (byte)value; } public override int EV_SPD { get => Data[0x23]; set => Data[0x23] = (byte)value; } - public byte CNT_Cool { get => Data[0x24]; set => Data[0x24] = value; } - public byte CNT_Beauty { get => Data[0x25]; set => Data[0x25] = value; } - public byte CNT_Cute { get => Data[0x26]; set => Data[0x26] = value; } - public byte CNT_Smart { get => Data[0x27]; set => Data[0x27] = value; } - public byte CNT_Tough { get => Data[0x28]; set => Data[0x28] = value; } - public byte CNT_Sheen { get => Data[0x29]; set => Data[0x29] = value; } + public byte ContestCool { get => Data[0x24]; set => Data[0x24] = value; } + public byte ContestBeauty { get => Data[0x25]; set => Data[0x25] = value; } + public byte ContestCute { get => Data[0x26]; set => Data[0x26] = value; } + public byte ContestSmart { get => Data[0x27]; set => Data[0x27] = value; } + public byte ContestTough { get => Data[0x28]; set => Data[0x28] = value; } + public byte ContestSheen { get => Data[0x29]; set => Data[0x29] = value; } public byte MarkingValue { get => Data[0x2A]; set => Data[0x2A] = value; } - private byte PKRS { get => Data[0x2B]; set => Data[0x2B] = value; } - public override int PKRS_Days { get => PKRS & 0xF; set => PKRS = (byte)((PKRS & ~0xF) | value); } - public override int PKRS_Strain { get => PKRS >> 4; set => PKRS = (byte)((PKRS & 0xF) | (value << 4)); } + public byte PokerusState { get => Data[0x2B]; set => Data[0x2B] = value; } + public override int PokerusDays { get => PokerusState & 0xF; set => PokerusState = (byte)((PokerusState & ~0xF) | value); } + public override int PokerusStrain { get => PokerusState >> 4; set => PokerusState = (byte)((PokerusState & 0xF) | (value << 4)); } private byte ST1 { get => Data[0x2C]; set => Data[0x2C] = value; } public bool Unused0 { get => (ST1 & (1 << 0)) == 1 << 0; set => ST1 = (byte)((ST1 & ~(1 << 0)) | (value ? 1 << 0 : 0)); } public bool Unused1 { get => (ST1 & (1 << 1)) == 1 << 1; set => ST1 = (byte)((ST1 & ~(1 << 1)) | (value ? 1 << 1 : 0)); } @@ -226,8 +226,8 @@ public override uint PID #region Block B public override string Nickname { - get => StringConverter6.GetString(Nickname_Trash); - set => StringConverter6.SetString(Nickname_Trash, value, 12, StringConverterOption.None); + get => StringConverter6.GetString(NicknameTrash); + set => StringConverter6.SetString(NicknameTrash, value, 12, StringConverterOption.None); } public override ushort Move1 @@ -290,7 +290,7 @@ public override ushort RelearnMove4 public bool SecretSuperTrainingUnlocked { get => (Data[0x72] & 1) == 1; set => Data[0x72] = (byte)((Data[0x72] & ~1) | (value ? 1 : 0)); } public bool SecretSuperTrainingComplete { get => (Data[0x72] & 2) == 2; set => Data[0x72] = (byte)((Data[0x72] & ~2) | (value ? 2 : 0)); } // 0x73 Unused - protected override uint IV32 { get => ReadUInt32LittleEndian(Data.AsSpan(0x74)); set => WriteUInt32LittleEndian(Data.AsSpan(0x74), value); } + public override uint IV32 { get => ReadUInt32LittleEndian(Data.AsSpan(0x74)); set => WriteUInt32LittleEndian(Data.AsSpan(0x74), value); } public override int IV_HP { get => (int)(IV32 >> 00) & 0x1F; set => IV32 = (IV32 & ~(0x1Fu << 00)) | ((value > 31 ? 31u : (uint)value) << 00); } public override int IV_ATK { get => (int)(IV32 >> 05) & 0x1F; set => IV32 = (IV32 & ~(0x1Fu << 05)) | ((value > 31 ? 31u : (uint)value) << 05); } public override int IV_DEF { get => (int)(IV32 >> 10) & 0x1F; set => IV32 = (IV32 & ~(0x1Fu << 10)) | ((value > 31 ? 31u : (uint)value) << 10); } @@ -301,13 +301,13 @@ public override ushort RelearnMove4 public override bool IsNicknamed { get => ((IV32 >> 31) & 1) == 1; set => IV32 = (IV32 & 0x7FFFFFFFu) | (value ? 0x80000000u : 0u); } #endregion #region Block C - public override string HT_Name + public override string HandlingTrainerName { - get => StringConverter6.GetString(HT_Trash); - set => StringConverter6.SetString(HT_Trash, value, 12, StringConverterOption.None); + get => StringConverter6.GetString(HandlingTrainerTrash); + set => StringConverter6.SetString(HandlingTrainerTrash, value, 12, StringConverterOption.None); } - public override int HT_Gender { get => Data[0x92]; set => Data[0x92] = (byte)value; } - public override int CurrentHandler { get => Data[0x93]; set => Data[0x93] = (byte)value; } + public override byte HandlingTrainerGender { get => Data[0x92]; set => Data[0x92] = value; } + public override byte CurrentHandler { get => Data[0x93]; set => Data[0x93] = value; } public byte Geo1_Region { get => Data[0x94]; set => Data[0x94] = value; } public byte Geo1_Country { get => Data[0x95]; set => Data[0x95] = value; } public byte Geo2_Region { get => Data[0x96]; set => Data[0x96] = value; } @@ -322,13 +322,13 @@ public override string HT_Name // 0x9F Unused // 0xA0 Unused // 0xA1 Unused - public override int HT_Friendship { get => Data[0xA2]; set => Data[0xA2] = (byte)value; } - public byte HT_Affection { get => Data[0xA3]; set => Data[0xA3] = value; } - public byte HT_Intensity { get => Data[0xA4]; set => Data[0xA4] = value; } - public byte HT_Memory { get => Data[0xA5]; set => Data[0xA5] = value; } - public byte HT_Feeling { get => Data[0xA6]; set => Data[0xA6] = value; } + public override byte HandlingTrainerFriendship { get => Data[0xA2]; set => Data[0xA2] = value; } + public byte HandlingTrainerAffection { get => Data[0xA3]; set => Data[0xA3] = value; } + public byte HandlingTrainerMemoryIntensity { get => Data[0xA4]; set => Data[0xA4] = value; } + public byte HandlingTrainerMemory { get => Data[0xA5]; set => Data[0xA5] = value; } + public byte HandlingTrainerMemoryFeeling { get => Data[0xA6]; set => Data[0xA6] = value; } // 0xA7 Unused - public ushort HT_TextVar { get => ReadUInt16LittleEndian(Data.AsSpan(0xA8)); set => WriteUInt16LittleEndian(Data.AsSpan(0xA8), value); } + public ushort HandlingTrainerMemoryVariable { get => ReadUInt16LittleEndian(Data.AsSpan(0xA8)); set => WriteUInt16LittleEndian(Data.AsSpan(0xA8), value); } // 0xAA Unused // 0xAB Unused // 0xAC Unused @@ -337,31 +337,31 @@ public override string HT_Name public override byte Enjoyment { get => Data[0xAF]; set => Data[0xAF] = value; } #endregion #region Block D - public override string OT_Name + public override string OriginalTrainerName { - get => StringConverter6.GetString(OT_Trash); - set => StringConverter6.SetString(OT_Trash, value, 12, StringConverterOption.None); + get => StringConverter6.GetString(OriginalTrainerTrash); + set => StringConverter6.SetString(OriginalTrainerTrash, value, 12, StringConverterOption.None); } - public override int OT_Friendship { get => Data[0xCA]; set => Data[0xCA] = (byte)value; } - public byte OT_Affection { get => Data[0xCB]; set => Data[0xCB] = value; } - public byte OT_Intensity { get => Data[0xCC]; set => Data[0xCC] = value; } - public byte OT_Memory { get => Data[0xCD]; set => Data[0xCD] = value; } - public ushort OT_TextVar { get => ReadUInt16LittleEndian(Data.AsSpan(0xCE)); set => WriteUInt16LittleEndian(Data.AsSpan(0xCE), value); } - public byte OT_Feeling { get => Data[0xD0]; set => Data[0xD0] = value; } - public override int Egg_Year { get => Data[0xD1]; set => Data[0xD1] = (byte)value; } - public override int Egg_Month { get => Data[0xD2]; set => Data[0xD2] = (byte)value; } - public override int Egg_Day { get => Data[0xD3]; set => Data[0xD3] = (byte)value; } - public override int Met_Year { get => Data[0xD4]; set => Data[0xD4] = (byte)value; } - public override int Met_Month { get => Data[0xD5]; set => Data[0xD5] = (byte)value; } - public override int Met_Day { get => Data[0xD6]; set => Data[0xD6] = (byte)value; } + public override byte OriginalTrainerFriendship { get => Data[0xCA]; set => Data[0xCA] = value; } + public byte OriginalTrainerAffection { get => Data[0xCB]; set => Data[0xCB] = value; } + public byte OriginalTrainerMemoryIntensity { get => Data[0xCC]; set => Data[0xCC] = value; } + public byte OriginalTrainerMemory { get => Data[0xCD]; set => Data[0xCD] = value; } + public ushort OriginalTrainerMemoryVariable { get => ReadUInt16LittleEndian(Data.AsSpan(0xCE)); set => WriteUInt16LittleEndian(Data.AsSpan(0xCE), value); } + public byte OriginalTrainerMemoryFeeling { get => Data[0xD0]; set => Data[0xD0] = value; } + public override byte EggYear { get => Data[0xD1]; set => Data[0xD1] = value; } + public override byte EggMonth { get => Data[0xD2]; set => Data[0xD2] = value; } + public override byte EggDay { get => Data[0xD3]; set => Data[0xD3] = value; } + public override byte MetYear { get => Data[0xD4]; set => Data[0xD4] = value; } + public override byte MetMonth { get => Data[0xD5]; set => Data[0xD5] = value; } + public override byte MetDay { get => Data[0xD6]; set => Data[0xD6] = value; } // 0xD7 Unused - public override int Egg_Location { get => ReadUInt16LittleEndian(Data.AsSpan(0xD8)); set => WriteUInt16LittleEndian(Data.AsSpan(0xD8), (ushort)value); } - public override int Met_Location { get => ReadUInt16LittleEndian(Data.AsSpan(0xDA)); set => WriteUInt16LittleEndian(Data.AsSpan(0xDA), (ushort)value); } - public override int Ball { get => Data[0xDC]; set => Data[0xDC] = (byte)value; } - public override int Met_Level { get => Data[0xDD] & ~0x80; set => Data[0xDD] = (byte)((Data[0xDD] & 0x80) | value); } - public override int OT_Gender { get => Data[0xDD] >> 7; set => Data[0xDD] = (byte)((Data[0xDD] & ~0x80) | (value << 7)); } + public override ushort EggLocation { get => ReadUInt16LittleEndian(Data.AsSpan(0xD8)); set => WriteUInt16LittleEndian(Data.AsSpan(0xD8), value); } + public override ushort MetLocation { get => ReadUInt16LittleEndian(Data.AsSpan(0xDA)); set => WriteUInt16LittleEndian(Data.AsSpan(0xDA), value); } + public override byte Ball { get => Data[0xDC]; set => Data[0xDC] = value; } + public override byte MetLevel { get => (byte)(Data[0xDD] & ~0x80); set => Data[0xDD] = (byte)((Data[0xDD] & 0x80) | value); } + public override byte OriginalTrainerGender { get => (byte)(Data[0xDD] >> 7); set => Data[0xDD] = (byte)((Data[0xDD] & ~0x80) | (value << 7)); } public GroundTileType GroundTile { get => (GroundTileType)Data[0xDE]; set => Data[0xDE] = (byte)value; } - public override int Version { get => Data[0xDF]; set => Data[0xDF] = (byte)value; } + public override GameVersion Version { get => (GameVersion)Data[0xDF]; set => Data[0xDF] = (byte)value; } public byte Country { get => Data[0xE0]; set => Data[0xE0] = value; } public byte Region { get => Data[0xE1]; set => Data[0xE1] = value; } public byte ConsoleRegion { get => Data[0xE2]; set => Data[0xE2] = value; } @@ -369,7 +369,7 @@ public override string OT_Name #endregion #region Battle Stats public override int Status_Condition { get => ReadInt32LittleEndian(Data.AsSpan(0xE8)); set => WriteInt32LittleEndian(Data.AsSpan(0xE8), value); } - public override int Stat_Level { get => Data[0xEC]; set => Data[0xEC] = (byte)value; } + public override byte Stat_Level { get => Data[0xEC]; set => Data[0xEC] = value; } public byte FormArgumentRemain { get => Data[0xED]; set => Data[0xED] = value; } public byte FormArgumentElapsed { get => Data[0xEE]; set => Data[0xEE] = value; } public override int Stat_HPCurrent { get => ReadUInt16LittleEndian(Data.AsSpan(0xF0)); set => WriteUInt16LittleEndian(Data.AsSpan(0xF0), (ushort)value); } @@ -384,7 +384,7 @@ public override string OT_Name private const int MedalCount = 30; public int SuperTrainingMedalCount(int lowBitCount = MedalCount) => BitOperations.PopCount((SuperTrainBitFlags >> 2) & (uint.MaxValue >> (MedalCount - lowBitCount))); - public bool IsUntradedEvent6 => Geo1_Country == 0 && Geo1_Region == 0 && Met_Location / 10000 == 4 && Gen6; + public bool IsUntradedEvent6 => Geo1_Country == 0 && Geo1_Region == 0 && MetLocation / 10000 == 4 && Gen6; // Complex Generated Attributes @@ -394,18 +394,18 @@ public void FixMemories() { Geo1_Country = Geo2_Country = Geo3_Country = Geo4_Country = Geo5_Country = Geo1_Region = Geo2_Region = Geo3_Region = Geo4_Region = Geo5_Region = 0; - HT_Friendship = HT_TextVar = HT_Memory = HT_Intensity = HT_Feeling = 0; - /* OT_Friendship */ OT_TextVar = OT_Memory = OT_Intensity = OT_Feeling = OT_Affection = HT_Affection = 0; + HandlingTrainerMemoryVariable = HandlingTrainerFriendship = HandlingTrainerMemory = HandlingTrainerMemoryIntensity = HandlingTrainerMemoryFeeling = 0; + /* OriginalTrainerFriendship */ OriginalTrainerMemoryVariable = OriginalTrainerMemory = OriginalTrainerMemoryIntensity = OriginalTrainerMemoryFeeling = OriginalTrainerAffection = HandlingTrainerAffection = 0; // Clear Handler - HT_Trash.Clear(); + HandlingTrainerTrash.Clear(); return; } if (IsUntraded) - HT_Friendship = HT_TextVar = HT_Memory = HT_Intensity = HT_Feeling = HT_Affection = 0; + HandlingTrainerMemoryVariable = HandlingTrainerFriendship = HandlingTrainerMemory = HandlingTrainerMemoryIntensity = HandlingTrainerMemoryFeeling = HandlingTrainerAffection = 0; if (!Gen6) - OT_TextVar = OT_Memory = OT_Intensity = OT_Feeling = 0; // Don't clear OT affection; OR/AS Contest Glitch + OriginalTrainerMemoryVariable = OriginalTrainerMemory = OriginalTrainerMemoryIntensity = OriginalTrainerMemoryFeeling = 0; // Don't clear OT affection; OR/AS Contest Glitch this.SanitizeGeoLocationData(); } @@ -413,7 +413,7 @@ public void FixMemories() protected override bool TradeOT(ITrainerInfo tr) { // Check to see if the OT matches the SAV's OT info. - if (!(tr.ID32 == ID32 && tr.Gender == OT_Gender && tr.OT == OT_Name)) + if (!(tr.ID32 == ID32 && tr.Gender == OriginalTrainerGender && tr.OT == OriginalTrainerName)) return false; CurrentHandler = 0; @@ -428,23 +428,23 @@ protected override bool TradeOT(ITrainerInfo tr) protected override void TradeHT(ITrainerInfo tr) { - if (tr.OT != HT_Name || tr.Gender != HT_Gender || (Geo1_Country == 0 && Geo1_Region == 0 && !IsUntradedEvent6)) + if (tr.OT != HandlingTrainerName || tr.Gender != HandlingTrainerGender || (Geo1_Country == 0 && Geo1_Region == 0 && !IsUntradedEvent6)) { if (tr is IRegionOrigin o) this.TradeGeoLocation(o.Country, o.Region); } - if (tr.OT != HT_Name) + if (tr.OT != HandlingTrainerName) { - HT_Friendship = PersonalInfo.BaseFriendship; - HT_Affection = 0; - HT_Name = tr.OT; + HandlingTrainerFriendship = PersonalInfo.BaseFriendship; + HandlingTrainerAffection = 0; + HandlingTrainerName = tr.OT; } CurrentHandler = 1; - HT_Gender = tr.Gender; + HandlingTrainerGender = tr.Gender; // Make a memory if no memory already exists. Pretty terrible way of doing this, but I'd rather not overwrite existing memories. - if (HT_Memory == 0) + if (HandlingTrainerMemory == 0) this.SetTradeMemoryHT6(false); } @@ -454,7 +454,7 @@ protected override void TradeHT(ITrainerInfo tr) public override int MaxAbilityID => Legal.MaxAbilityID_6_AO; public override int MaxItemID => Legal.MaxItemID_6_AO; public override int MaxBallID => Legal.MaxBallID_6; - public override int MaxGameID => Legal.MaxGameID_6; // OR + public override GameVersion MaxGameID => Legal.MaxGameID_6; // OR public int MarkingCount => 6; public bool GetMarking(int index) diff --git a/PKHeX.Core/PKM/PK7.cs b/PKHeX.Core/PKM/PK7.cs index ca34176fb..7f88022ea 100644 --- a/PKHeX.Core/PKM/PK7.cs +++ b/PKHeX.Core/PKM/PK7.cs @@ -96,9 +96,9 @@ public override uint PID set => WriteUInt32LittleEndian(Data.AsSpan(0x18), value); } - public override int Nature { get => Data[0x1C]; set => Data[0x1C] = (byte)value; } + public override Nature Nature { get => (Nature)Data[0x1C]; set => Data[0x1C] = (byte)value; } public override bool FatefulEncounter { get => (Data[0x1D] & 1) == 1; set => Data[0x1D] = (byte)((Data[0x1D] & ~0x01) | (value ? 1 : 0)); } - public override int Gender { get => (Data[0x1D] >> 1) & 0x3; set => Data[0x1D] = (byte)((Data[0x1D] & ~0x06) | (value << 1)); } + public override byte Gender { get => (byte)((Data[0x1D] >> 1) & 0x3); set => Data[0x1D] = (byte)((Data[0x1D] & ~0x06) | (value << 1)); } public override byte Form { get => (byte)(Data[0x1D] >> 3); set => Data[0x1D] = (byte)((Data[0x1D] & 0x07) | (value << 3)); } public override int EV_HP { get => Data[0x1E]; set => Data[0x1E] = (byte)value; } public override int EV_ATK { get => Data[0x1F]; set => Data[0x1F] = (byte)value; } @@ -106,16 +106,16 @@ public override uint PID public override int EV_SPE { get => Data[0x21]; set => Data[0x21] = (byte)value; } public override int EV_SPA { get => Data[0x22]; set => Data[0x22] = (byte)value; } public override int EV_SPD { get => Data[0x23]; set => Data[0x23] = (byte)value; } - public byte CNT_Cool { get => Data[0x24]; set => Data[0x24] = value; } - public byte CNT_Beauty { get => Data[0x25]; set => Data[0x25] = value; } - public byte CNT_Cute { get => Data[0x26]; set => Data[0x26] = value; } - public byte CNT_Smart { get => Data[0x27]; set => Data[0x27] = value; } - public byte CNT_Tough { get => Data[0x28]; set => Data[0x28] = value; } - public byte CNT_Sheen { get => Data[0x29]; set => Data[0x29] = value; } + public byte ContestCool { get => Data[0x24]; set => Data[0x24] = value; } + public byte ContestBeauty { get => Data[0x25]; set => Data[0x25] = value; } + public byte ContestCute { get => Data[0x26]; set => Data[0x26] = value; } + public byte ContestSmart { get => Data[0x27]; set => Data[0x27] = value; } + public byte ContestTough { get => Data[0x28]; set => Data[0x28] = value; } + public byte ContestSheen { get => Data[0x29]; set => Data[0x29] = value; } public ResortEventState ResortEventStatus { get => (ResortEventState)Data[0x2A]; set => Data[0x2A] = (byte)value; } - public byte PKRS { get => Data[0x2B]; set => Data[0x2B] = value; } - public override int PKRS_Days { get => PKRS & 0xF; set => PKRS = (byte)((PKRS & ~0xF) | value); } - public override int PKRS_Strain { get => PKRS >> 4; set => PKRS = (byte)((PKRS & 0xF) | (value << 4)); } + public byte PokerusState { get => Data[0x2B]; set => Data[0x2B] = value; } + public override int PokerusDays { get => PokerusState & 0xF; set => PokerusState = (byte)((PokerusState & ~0xF) | value); } + public override int PokerusStrain { get => PokerusState >> 4; set => PokerusState = (byte)((PokerusState & 0xF) | (value << 4)); } private byte ST1 { get => Data[0x2C]; set => Data[0x2C] = value; } public bool Unused0 { get => (ST1 & (1 << 0)) == 1 << 0; set => ST1 = (byte)((ST1 & ~(1 << 0)) | (value ? 1 << 0 : 0)); } public bool Unused1 { get => (ST1 & (1 << 1)) == 1 << 1; set => ST1 = (byte)((ST1 & ~(1 << 1)) | (value ? 1 << 1 : 0)); } @@ -238,7 +238,7 @@ public override uint PID #region Block B public override string Nickname { - get => StringConverter7.GetString(Nickname_Trash); + get => StringConverter7.GetString(NicknameTrash); set { // For Pokémon with no nickname, and match their Chinese species name, we need to use the private codepoint range instead of unicode. @@ -250,11 +250,11 @@ public override string Nickname int lang = SpeciesName.GetSpeciesNameLanguage(Species, Language, value, 7); if (lang is (int)LanguageID.ChineseS or (int)LanguageID.ChineseT) { - StringConverter7.SetString(Nickname_Trash, value, 12, lang, StringConverterOption.None, chinese: true); + StringConverter7.SetString(NicknameTrash, value, 12, lang, StringConverterOption.None, chinese: true); return; } } - StringConverter7.SetString(Nickname_Trash, value, 12, 0, StringConverterOption.None); + StringConverter7.SetString(NicknameTrash, value, 12, 0, StringConverterOption.None); } } @@ -318,7 +318,7 @@ public override ushort RelearnMove4 public bool SecretSuperTrainingUnlocked { get => (Data[0x72] & 1) == 1; set => Data[0x72] = (byte)((Data[0x72] & ~1) | (value ? 1 : 0)); } public bool SecretSuperTrainingComplete { get => (Data[0x72] & 2) == 2; set => Data[0x72] = (byte)((Data[0x72] & ~2) | (value ? 2 : 0)); } // 0x73 Unused - protected override uint IV32 { get => ReadUInt32LittleEndian(Data.AsSpan(0x74)); set => WriteUInt32LittleEndian(Data.AsSpan(0x74), value); } + public override uint IV32 { get => ReadUInt32LittleEndian(Data.AsSpan(0x74)); set => WriteUInt32LittleEndian(Data.AsSpan(0x74), value); } public override int IV_HP { get => (int)(IV32 >> 00) & 0x1F; set => IV32 = (IV32 & ~(0x1Fu << 00)) | ((value > 31 ? 31u : (uint)value) << 00); } public override int IV_ATK { get => (int)(IV32 >> 05) & 0x1F; set => IV32 = (IV32 & ~(0x1Fu << 05)) | ((value > 31 ? 31u : (uint)value) << 05); } public override int IV_DEF { get => (int)(IV32 >> 10) & 0x1F; set => IV32 = (IV32 & ~(0x1Fu << 10)) | ((value > 31 ? 31u : (uint)value) << 10); } @@ -329,14 +329,14 @@ public override ushort RelearnMove4 public override bool IsNicknamed { get => ((IV32 >> 31) & 1) == 1; set => IV32 = (IV32 & 0x7FFFFFFFu) | (value ? 0x80000000u : 0u); } #endregion #region Block C - public override string HT_Name + public override string HandlingTrainerName { - get => StringConverter7.GetString(HT_Trash); - set => StringConverter7.SetString(HT_Trash, value, 12, 0, StringConverterOption.None); + get => StringConverter7.GetString(HandlingTrainerTrash); + set => StringConverter7.SetString(HandlingTrainerTrash, value, 12, 0, StringConverterOption.None); } - public override int HT_Gender { get => Data[0x92]; set => Data[0x92] = (byte)value; } - public override int CurrentHandler { get => Data[0x93]; set => Data[0x93] = (byte)value; } + public override byte HandlingTrainerGender { get => Data[0x92]; set => Data[0x92] = value; } + public override byte CurrentHandler { get => Data[0x93]; set => Data[0x93] = value; } public byte Geo1_Region { get => Data[0x94]; set => Data[0x94] = value; } public byte Geo1_Country { get => Data[0x95]; set => Data[0x95] = value; } public byte Geo2_Region { get => Data[0x96]; set => Data[0x96] = value; } @@ -351,13 +351,13 @@ public override string HT_Name // 0x9F Unused // 0xA0 Unused // 0xA1 Unused - public override int HT_Friendship { get => Data[0xA2]; set => Data[0xA2] = (byte)value; } - public byte HT_Affection { get => Data[0xA3]; set => Data[0xA3] = value; } - public byte HT_Intensity { get => Data[0xA4]; set => Data[0xA4] = value; } - public byte HT_Memory { get => Data[0xA5]; set => Data[0xA5] = value; } - public byte HT_Feeling { get => Data[0xA6]; set => Data[0xA6] = value; } + public override byte HandlingTrainerFriendship { get => Data[0xA2]; set => Data[0xA2] = value; } + public byte HandlingTrainerAffection { get => Data[0xA3]; set => Data[0xA3] = value; } + public byte HandlingTrainerMemoryIntensity { get => Data[0xA4]; set => Data[0xA4] = value; } + public byte HandlingTrainerMemory { get => Data[0xA5]; set => Data[0xA5] = value; } + public byte HandlingTrainerMemoryFeeling { get => Data[0xA6]; set => Data[0xA6] = value; } // 0xA7 Unused - public ushort HT_TextVar { get => ReadUInt16LittleEndian(Data.AsSpan(0xA8)); set => WriteUInt16LittleEndian(Data.AsSpan(0xA8), value); } + public ushort HandlingTrainerMemoryVariable { get => ReadUInt16LittleEndian(Data.AsSpan(0xA8)); set => WriteUInt16LittleEndian(Data.AsSpan(0xA8), value); } // 0xAA Unused // 0xAB Unused // 0xAC Unused @@ -366,30 +366,30 @@ public override string HT_Name public override byte Enjoyment { get => Data[0xAF]; set => Data[0xAF] = value; } #endregion #region Block D - public override string OT_Name + public override string OriginalTrainerName { - get => StringConverter7.GetString(OT_Trash); - set => StringConverter7.SetString(OT_Trash, value, 12, 0, StringConverterOption.None); + get => StringConverter7.GetString(OriginalTrainerTrash); + set => StringConverter7.SetString(OriginalTrainerTrash, value, 12, 0, StringConverterOption.None); } - public override int OT_Friendship { get => Data[0xCA]; set => Data[0xCA] = (byte)value; } - public byte OT_Affection { get => Data[0xCB]; set => Data[0xCB] = value; } - public byte OT_Intensity { get => Data[0xCC]; set => Data[0xCC] = value; } - public byte OT_Memory { get => Data[0xCD]; set => Data[0xCD] = value; } - public ushort OT_TextVar { get => ReadUInt16LittleEndian(Data.AsSpan(0xCE)); set => WriteUInt16LittleEndian(Data.AsSpan(0xCE), value); } - public byte OT_Feeling { get => Data[0xD0]; set => Data[0xD0] = value; } - public override int Egg_Year { get => Data[0xD1]; set => Data[0xD1] = (byte)value; } - public override int Egg_Month { get => Data[0xD2]; set => Data[0xD2] = (byte)value; } - public override int Egg_Day { get => Data[0xD3]; set => Data[0xD3] = (byte)value; } - public override int Met_Year { get => Data[0xD4]; set => Data[0xD4] = (byte)value; } - public override int Met_Month { get => Data[0xD5]; set => Data[0xD5] = (byte)value; } - public override int Met_Day { get => Data[0xD6]; set => Data[0xD6] = (byte)value; } + public override byte OriginalTrainerFriendship { get => Data[0xCA]; set => Data[0xCA] = value; } + public byte OriginalTrainerAffection { get => Data[0xCB]; set => Data[0xCB] = value; } + public byte OriginalTrainerMemoryIntensity { get => Data[0xCC]; set => Data[0xCC] = value; } + public byte OriginalTrainerMemory { get => Data[0xCD]; set => Data[0xCD] = value; } + public ushort OriginalTrainerMemoryVariable { get => ReadUInt16LittleEndian(Data.AsSpan(0xCE)); set => WriteUInt16LittleEndian(Data.AsSpan(0xCE), value); } + public byte OriginalTrainerMemoryFeeling { get => Data[0xD0]; set => Data[0xD0] = value; } + public override byte EggYear { get => Data[0xD1]; set => Data[0xD1] = value; } + public override byte EggMonth { get => Data[0xD2]; set => Data[0xD2] = value; } + public override byte EggDay { get => Data[0xD3]; set => Data[0xD3] = value; } + public override byte MetYear { get => Data[0xD4]; set => Data[0xD4] = value; } + public override byte MetMonth { get => Data[0xD5]; set => Data[0xD5] = value; } + public override byte MetDay { get => Data[0xD6]; set => Data[0xD6] = value; } // Unused 0xD7 - public override int Egg_Location { get => ReadUInt16LittleEndian(Data.AsSpan(0xD8)); set => WriteUInt16LittleEndian(Data.AsSpan(0xD8), (ushort)value); } - public override int Met_Location { get => ReadUInt16LittleEndian(Data.AsSpan(0xDA)); set => WriteUInt16LittleEndian(Data.AsSpan(0xDA), (ushort)value); } - public override int Ball { get => Data[0xDC]; set => Data[0xDC] = (byte)value; } - public override int Met_Level { get => Data[0xDD] & ~0x80; set => Data[0xDD] = (byte)((Data[0xDD] & 0x80) | value); } - public override int OT_Gender { get => Data[0xDD] >> 7; set => Data[0xDD] = (byte)((Data[0xDD] & ~0x80) | (value << 7)); } + public override ushort EggLocation { get => ReadUInt16LittleEndian(Data.AsSpan(0xD8)); set => WriteUInt16LittleEndian(Data.AsSpan(0xD8), value); } + public override ushort MetLocation { get => ReadUInt16LittleEndian(Data.AsSpan(0xDA)); set => WriteUInt16LittleEndian(Data.AsSpan(0xDA), value); } + public override byte Ball { get => Data[0xDC]; set => Data[0xDC] = value; } + public override byte MetLevel { get => (byte)(Data[0xDD] & ~0x80); set => Data[0xDD] = (byte)((Data[0xDD] & 0x80) | value); } + public override byte OriginalTrainerGender { get => (byte)(Data[0xDD] >> 7); set => Data[0xDD] = (byte)((Data[0xDD] & ~0x80) | (value << 7)); } public byte HyperTrainFlags { get => Data[0xDE]; set => Data[0xDE] = value; } public bool HT_HP { get => ((HyperTrainFlags >> 0) & 1) == 1; set => HyperTrainFlags = (byte)((HyperTrainFlags & ~(1 << 0)) | ((value ? 1 : 0) << 0)); } public bool HT_ATK { get => ((HyperTrainFlags >> 1) & 1) == 1; set => HyperTrainFlags = (byte)((HyperTrainFlags & ~(1 << 1)) | ((value ? 1 : 0) << 1)); } @@ -397,7 +397,7 @@ public override string OT_Name public bool HT_SPA { get => ((HyperTrainFlags >> 3) & 1) == 1; set => HyperTrainFlags = (byte)((HyperTrainFlags & ~(1 << 3)) | ((value ? 1 : 0) << 3)); } public bool HT_SPD { get => ((HyperTrainFlags >> 4) & 1) == 1; set => HyperTrainFlags = (byte)((HyperTrainFlags & ~(1 << 4)) | ((value ? 1 : 0) << 4)); } public bool HT_SPE { get => ((HyperTrainFlags >> 5) & 1) == 1; set => HyperTrainFlags = (byte)((HyperTrainFlags & ~(1 << 5)) | ((value ? 1 : 0) << 5)); } - public override int Version { get => Data[0xDF]; set => Data[0xDF] = (byte)value; } + public override GameVersion Version { get => (GameVersion)Data[0xDF]; set => Data[0xDF] = (byte)value; } public byte Country { get => Data[0xE0]; set => Data[0xE0] = value; } public byte Region { get => Data[0xE1]; set => Data[0xE1] = value; } public byte ConsoleRegion { get => Data[0xE2]; set => Data[0xE2] = value; } @@ -405,7 +405,7 @@ public override string OT_Name #endregion #region Battle Stats public override int Status_Condition { get => ReadInt32LittleEndian(Data.AsSpan(0xE8)); set => WriteInt32LittleEndian(Data.AsSpan(0xE8), value); } - public override int Stat_Level { get => Data[0xEC]; set => Data[0xEC] = (byte)value; } + public override byte Stat_Level { get => Data[0xEC]; set => Data[0xEC] = value; } public byte DirtType { get => Data[0xED]; set => Data[0xED] = value; } public byte DirtLocation { get => Data[0xEE]; set => Data[0xEE] = value; } // 0xEF unused @@ -421,7 +421,7 @@ public override string OT_Name private const int MedalCount = 30; public int SuperTrainingMedalCount(int lowBitCount = MedalCount) => BitOperations.PopCount((SuperTrainBitFlags >> 2) & (uint.MaxValue >> (MedalCount - lowBitCount))); - public bool IsUntradedEvent6 => Geo1_Country == 0 && Geo1_Region == 0 && Met_Location / 10000 == 4 && Gen6; + public bool IsUntradedEvent6 => Geo1_Country == 0 && Geo1_Region == 0 && MetLocation / 10000 == 4 && Gen6; public int MarkingCount => 6; @@ -451,19 +451,19 @@ public void FixMemories() { if (IsEgg) // No memories if is egg. { - HT_Friendship = HT_TextVar = HT_Memory = HT_Intensity = HT_Feeling = 0; - /* OT_Friendship */ OT_TextVar = OT_Memory = OT_Intensity = OT_Feeling = HT_Affection = OT_Affection = 0; + HandlingTrainerMemoryVariable = HandlingTrainerFriendship = HandlingTrainerMemory = HandlingTrainerMemoryIntensity = HandlingTrainerMemoryFeeling = 0; + /* OriginalTrainerFriendship */ OriginalTrainerMemoryVariable = OriginalTrainerMemory = OriginalTrainerMemoryIntensity = OriginalTrainerMemoryFeeling = HandlingTrainerAffection = OriginalTrainerAffection = 0; this.ClearGeoLocationData(); // Clear Handler - HT_Trash.Clear(); + HandlingTrainerTrash.Clear(); return; } if (IsUntraded) - HT_Friendship = HT_TextVar = HT_Memory = HT_Intensity = HT_Feeling = HT_Affection = 0; + HandlingTrainerMemoryVariable = HandlingTrainerFriendship = HandlingTrainerMemory = HandlingTrainerMemoryIntensity = HandlingTrainerMemoryFeeling = HandlingTrainerAffection = 0; if (Generation < 6) - /* OT_Affection = */ OT_TextVar = OT_Memory = OT_Intensity = OT_Feeling = 0; + /* OriginalTrainerAffection = */ OriginalTrainerMemoryVariable = OriginalTrainerMemory = OriginalTrainerMemoryIntensity = OriginalTrainerMemoryFeeling = 0; this.SanitizeGeoLocationData(); @@ -477,7 +477,7 @@ public void FixMemories() protected override bool TradeOT(ITrainerInfo tr) { // Check to see if the OT matches the SAV's OT info. - if (!(tr.ID32 == ID32 && tr.Gender == OT_Gender && tr.OT == OT_Name)) + if (!(tr.ID32 == ID32 && tr.Gender == OriginalTrainerGender && tr.OT == OriginalTrainerName)) return false; CurrentHandler = 0; @@ -486,20 +486,20 @@ protected override bool TradeOT(ITrainerInfo tr) protected override void TradeHT(ITrainerInfo tr) { - if (tr.OT != HT_Name || tr.Gender != HT_Gender || (Geo1_Country == 0 && Geo1_Region == 0 && !IsUntradedEvent6)) + if (tr.OT != HandlingTrainerName || tr.Gender != HandlingTrainerGender || (Geo1_Country == 0 && Geo1_Region == 0 && !IsUntradedEvent6)) { // No geolocations are set ingame -- except for bank transfers. Don't emulate bank transfers // this.TradeGeoLocation(tr.Country, tr.SubRegion); } - if (HT_Name != tr.OT) + if (HandlingTrainerName != tr.OT) { - HT_Friendship = PersonalInfo.BaseFriendship; - HT_Affection = 0; - HT_Name = tr.OT; + HandlingTrainerFriendship = PersonalInfo.BaseFriendship; + HandlingTrainerAffection = 0; + HandlingTrainerName = tr.OT; } CurrentHandler = 1; - HT_Gender = tr.Gender; + HandlingTrainerGender = tr.Gender; } // Maximums @@ -508,7 +508,7 @@ protected override void TradeHT(ITrainerInfo tr) public override int MaxAbilityID => Legal.MaxAbilityID_7_USUM; public override int MaxItemID => Legal.MaxItemID_7_USUM; public override int MaxBallID => Legal.MaxBallID_7; - public override int MaxGameID => Legal.MaxGameID_7; + public override GameVersion MaxGameID => Legal.MaxGameID_7; internal void SetTransferLocale(int lang) { diff --git a/PKHeX.Core/PKM/PK8.cs b/PKHeX.Core/PKM/PK8.cs index 3dc393fd3..edaa11581 100644 --- a/PKHeX.Core/PKM/PK8.cs +++ b/PKHeX.Core/PKM/PK8.cs @@ -41,7 +41,7 @@ public void Trade(ITrainerInfo tr, int Day = 1, int Month = 1, int Year = 2015) { // Eggs do not have any modifications done if they are traded // Apply link trade data, only if it left the OT (ignore if dumped & imported, or cloned, etc.) - if ((tr.TID16 != TID16) || (tr.SID16 != SID16) || (tr.Gender != OT_Gender) || (tr.OT != OT_Name)) + if ((tr.TID16 != TID16) || (tr.SID16 != SID16) || (tr.Gender != OriginalTrainerGender) || (tr.OT != OriginalTrainerName)) SetLinkTradeEgg(Day, Month, Year, Locations.LinkTrade6); return; } @@ -57,20 +57,20 @@ public void FixMemories() { if (IsEgg) // No memories if is egg. { - HT_Friendship = HT_TextVar = HT_Memory = HT_Intensity = HT_Feeling = HT_Language = 0; - /* OT_Friendship */ OT_TextVar = OT_Memory = OT_Intensity = OT_Feeling = 0; + HandlingTrainerMemoryVariable = HandlingTrainerFriendship = HandlingTrainerMemory = HandlingTrainerMemoryIntensity = HandlingTrainerMemoryFeeling = HandlingTrainerLanguage = 0; + /* OriginalTrainerFriendship */ OriginalTrainerMemoryVariable = OriginalTrainerMemory = OriginalTrainerMemoryIntensity = OriginalTrainerMemoryFeeling = 0; // Clear Handler - HT_Trash.Clear(); + HandlingTrainerTrash.Clear(); return; } if (IsUntraded) - HT_Friendship = HT_TextVar = HT_Memory = HT_Intensity = HT_Feeling = HT_Language = 0; + HandlingTrainerMemoryVariable = HandlingTrainerFriendship = HandlingTrainerMemory = HandlingTrainerMemoryIntensity = HandlingTrainerMemoryFeeling = HandlingTrainerLanguage = 0; - int gen = Generation; + var gen = Generation; if (gen < 6) - OT_TextVar = OT_Memory = OT_Intensity = OT_Feeling = 0; + OriginalTrainerMemoryVariable = OriginalTrainerMemory = OriginalTrainerMemoryIntensity = OriginalTrainerMemoryFeeling = 0; if (gen != 8) // must be transferred via HOME, and must have memories this.SetTradeMemoryHT8(); // not faking HOME tracker. } @@ -78,7 +78,7 @@ public void FixMemories() private bool TradeOT(ITrainerInfo tr) { // Check to see if the OT matches the SAV's OT info. - if (!(tr.ID32 == ID32 && tr.Gender == OT_Gender && tr.OT == OT_Name)) + if (!(tr.ID32 == ID32 && tr.Gender == OriginalTrainerGender && tr.OT == OriginalTrainerName)) return false; CurrentHandler = 0; @@ -87,14 +87,14 @@ private bool TradeOT(ITrainerInfo tr) private void TradeHT(ITrainerInfo tr) { - if (HT_Name != tr.OT) + if (HandlingTrainerName != tr.OT) { - HT_Friendship = 50; - HT_Name = tr.OT; + HandlingTrainerFriendship = 50; + HandlingTrainerName = tr.OT; } CurrentHandler = 1; - HT_Gender = tr.Gender; - HT_Language = (byte)tr.Language; + HandlingTrainerGender = tr.Gender; + HandlingTrainerLanguage = (byte)tr.Language; this.SetTradeMemoryHT8(); } @@ -104,10 +104,10 @@ private void TradeHT(ITrainerInfo tr) public override int MaxAbilityID => Legal.MaxAbilityID_8; public override int MaxItemID => Legal.MaxItemID_8; public override int MaxBallID => Legal.MaxBallID_8; - public override int MaxGameID => Legal.MaxGameID_8; - public bool IsSideTransfer => LocationsHOME.IsLocationSWSH(Met_Location); - public override bool SV => Met_Location is LocationsHOME.SWSL or LocationsHOME.SHVL; - public override bool BDSP => Met_Location is LocationsHOME.SWBD or LocationsHOME.SHSP; - public override bool LA => Met_Location is LocationsHOME.SWLA; + public override GameVersion MaxGameID => Legal.MaxGameID_8; + public bool IsSideTransfer => LocationsHOME.IsLocationSWSH(MetLocation); + public override bool SV => MetLocation is LocationsHOME.SWSL or LocationsHOME.SHVL; + public override bool BDSP => MetLocation is LocationsHOME.SWBD or LocationsHOME.SHSP; + public override bool LA => MetLocation is LocationsHOME.SWLA; public override bool HasOriginalMetLocation => base.HasOriginalMetLocation && !(BDSP || LA); } diff --git a/PKHeX.Core/PKM/PK9.cs b/PKHeX.Core/PKM/PK9.cs index 78794be86..c7699449e 100644 --- a/PKHeX.Core/PKM/PK9.cs +++ b/PKHeX.Core/PKM/PK9.cs @@ -49,10 +49,10 @@ private static byte[] DecryptParty(byte[] data) private ushort CalculateChecksum() => Checksums.Add16(Data.AsSpan()[8..PokeCrypto.SIZE_9STORED]); // Simple Generated Attributes - public override int CurrentFriendship + public override byte CurrentFriendship { - get => CurrentHandler == 0 ? OT_Friendship : HT_Friendship; - set { if (CurrentHandler == 0) OT_Friendship = value; else HT_Friendship = value; } + get => CurrentHandler == 0 ? OriginalTrainerFriendship : HandlingTrainerFriendship; + set { if (CurrentHandler == 0) OriginalTrainerFriendship = value; else HandlingTrainerFriendship = value; } } public override int SIZE_PARTY => PokeCrypto.SIZE_9PARTY; @@ -63,9 +63,9 @@ public override int CurrentFriendship public override bool Valid { get => Sanity == 0 && ChecksumValid; set { if (!value) return; Sanity = 0; RefreshChecksum(); } } // Trash Bytes - public override Span Nickname_Trash => Data.AsSpan(0x58, 26); - public override Span HT_Trash => Data.AsSpan(0xA8, 26); - public override Span OT_Trash => Data.AsSpan(0xF8, 26); + public override Span NicknameTrash => Data.AsSpan(0x58, 26); + public override Span HandlingTrainerTrash => Data.AsSpan(0xA8, 26); + public override Span OriginalTrainerTrash => Data.AsSpan(0xF8, 26); // Maximums public override int MaxIV => 31; @@ -75,7 +75,7 @@ public override int CurrentFriendship public override uint PSV => ((PID >> 16) ^ (PID & 0xFFFF)) >> 4; public override uint TSV => (uint)(TID16 ^ SID16) >> 4; - public override bool IsUntraded => Data[0xA8] == 0 && Data[0xA8 + 1] == 0 && (IsUnhatchedEgg || Format == Generation); // immediately terminated HT_Name data (\0) + public override bool IsUntraded => Data[0xA8] == 0 && Data[0xA8 + 1] == 0 && (IsUnhatchedEgg || Format == Generation); // immediately terminated HandlingTrainerName data (\0) public bool IsUnhatchedEgg => Version == 0 && IsEgg; // Complex Generated Attributes @@ -134,10 +134,10 @@ public void FixRelearn() // 0x1A alignment unused // 0x1B alignment unused public override uint PID { get => ReadUInt32LittleEndian(Data.AsSpan(0x1C)); set => WriteUInt32LittleEndian(Data.AsSpan(0x1C), value); } - public override int Nature { get => Data[0x20]; set => Data[0x20] = (byte)value; } - public override int StatNature { get => Data[0x21]; set => Data[0x21] = (byte)value; } + public override Nature Nature { get => (Nature)Data[0x20]; set => Data[0x20] = (byte)value; } + public override Nature StatNature { get => (Nature)Data[0x21]; set => Data[0x21] = (byte)value; } public override bool FatefulEncounter { get => (Data[0x22] & 1) == 1; set => Data[0x22] = (byte)((Data[0x22] & ~0x01) | (value ? 1 : 0)); } - public override int Gender { get => (Data[0x22] >> 1) & 0x3; set => Data[0x22] = (byte)((Data[0x22] & 0xF9) | (value << 1)); } + public override byte Gender { get => (byte)((Data[0x22] >> 1) & 0x3); set => Data[0x22] = (byte)((Data[0x22] & 0xF9) | (value << 1)); } // 0x23 alignment unused public override byte Form { get => Data[0x24]; set => WriteUInt16LittleEndian(Data.AsSpan(0x24), value); } public override int EV_HP { get => Data[0x26]; set => Data[0x26] = (byte)value; } @@ -146,15 +146,15 @@ public void FixRelearn() public override int EV_SPE { get => Data[0x29]; set => Data[0x29] = (byte)value; } public override int EV_SPA { get => Data[0x2A]; set => Data[0x2A] = (byte)value; } public override int EV_SPD { get => Data[0x2B]; set => Data[0x2B] = (byte)value; } - public byte CNT_Cool { get => Data[0x2C]; set => Data[0x2C] = value; } - public byte CNT_Beauty { get => Data[0x2D]; set => Data[0x2D] = value; } - public byte CNT_Cute { get => Data[0x2E]; set => Data[0x2E] = value; } - public byte CNT_Smart { get => Data[0x2F]; set => Data[0x2F] = value; } - public byte CNT_Tough { get => Data[0x30]; set => Data[0x30] = value; } - public byte CNT_Sheen { get => Data[0x31]; set => Data[0x31] = value; } - private byte PKRS { get => Data[0x32]; set => Data[0x32] = value; } - public override int PKRS_Days { get => PKRS & 0xF; set => PKRS = (byte)((PKRS & ~0xF) | value); } - public override int PKRS_Strain { get => PKRS >> 4; set => PKRS = (byte)((PKRS & 0xF) | (value << 4)); } + public byte ContestCool { get => Data[0x2C]; set => Data[0x2C] = value; } + public byte ContestBeauty { get => Data[0x2D]; set => Data[0x2D] = value; } + public byte ContestCute { get => Data[0x2E]; set => Data[0x2E] = value; } + public byte ContestSmart { get => Data[0x2F]; set => Data[0x2F] = value; } + public byte ContestTough { get => Data[0x30]; set => Data[0x30] = value; } + public byte ContestSheen { get => Data[0x31]; set => Data[0x31] = value; } + public byte PokerusState { get => Data[0x32]; set => Data[0x32] = value; } + public override int PokerusDays { get => PokerusState & 0xF; set => PokerusState = (byte)((PokerusState & ~0xF) | value); } + public override int PokerusStrain { get => PokerusState >> 4; set => PokerusState = (byte)((PokerusState & 0xF) | (value << 4)); } // 0x33 unused padding // ribbon u32 @@ -330,8 +330,8 @@ public void FixRelearn() #region Block B public override string Nickname { - get => StringConverter8.GetString(Nickname_Trash); - set => StringConverter8.SetString(Nickname_Trash, value, 12, StringConverterOption.None); + get => StringConverter8.GetString(NicknameTrash); + set => StringConverter8.SetString(NicknameTrash, value, 12, StringConverterOption.None); } // 2 bytes for \0, automatically handled above @@ -357,7 +357,7 @@ public override string Nickname public override int Stat_HPCurrent { get => ReadUInt16LittleEndian(Data.AsSpan(0x8A)); set => WriteUInt16LittleEndian(Data.AsSpan(0x8A), (ushort)value); } - private uint IV32 { get => ReadUInt32LittleEndian(Data.AsSpan(0x8C)); set => WriteUInt32LittleEndian(Data.AsSpan(0x8C), value); } + public uint IV32 { get => ReadUInt32LittleEndian(Data.AsSpan(0x8C)); set => WriteUInt32LittleEndian(Data.AsSpan(0x8C), value); } public override int IV_HP { get => (int)(IV32 >> 00) & 0x1F; set => IV32 = (IV32 & ~(0x1Fu << 00)) | ((value > 31 ? 31u : (uint)value) << 00); } public override int IV_ATK { get => (int)(IV32 >> 05) & 0x1F; set => IV32 = (IV32 & ~(0x1Fu << 05)) | ((value > 31 ? 31u : (uint)value) << 05); } public override int IV_DEF { get => (int)(IV32 >> 10) & 0x1F; set => IV32 = (IV32 & ~(0x1Fu << 10)) | ((value > 31 ? 31u : (uint)value) << 10); } @@ -375,24 +375,24 @@ public override string Nickname #endregion #region Block C - public override string HT_Name + public override string HandlingTrainerName { - get => StringConverter8.GetString(HT_Trash); - set => StringConverter8.SetString(HT_Trash, value, 12, StringConverterOption.None); + get => StringConverter8.GetString(HandlingTrainerTrash); + set => StringConverter8.SetString(HandlingTrainerTrash, value, 12, StringConverterOption.None); } - public override int HT_Gender { get => Data[0xC2]; set => Data[0xC2] = (byte)value; } - public byte HT_Language { get => Data[0xC3]; set => Data[0xC3] = value; } - public override int CurrentHandler { get => Data[0xC4]; set => Data[0xC4] = (byte)value; } + public override byte HandlingTrainerGender { get => Data[0xC2]; set => Data[0xC2] = value; } + public byte HandlingTrainerLanguage { get => Data[0xC3]; set => Data[0xC3] = value; } + public override byte CurrentHandler { get => Data[0xC4]; set => Data[0xC4] = value; } // 0xC5 unused (alignment) - public int HT_TrainerID { get => ReadUInt16LittleEndian(Data.AsSpan(0xC6)); set => WriteUInt16LittleEndian(Data.AsSpan(0xC6), (ushort)value); } // unused? - public override int HT_Friendship { get => Data[0xC8]; set => Data[0xC8] = (byte)value; } - public byte HT_Intensity { get => Data[0xC9]; set => Data[0xC9] = value; } - public byte HT_Memory { get => Data[0xCA]; set => Data[0xCA] = value; } - public byte HT_Feeling { get => Data[0xCB]; set => Data[0xCB] = value; } - public ushort HT_TextVar { get => ReadUInt16LittleEndian(Data.AsSpan(0xCC)); set => WriteUInt16LittleEndian(Data.AsSpan(0xCC), value); } - public override int Version { get => Data[0xCE]; set => Data[0xCE] = (byte)value; } - public byte BattleVersion { get => Data[0xCF]; set => Data[0xCF] = value; } + public ushort HandlingTrainerID { get => ReadUInt16LittleEndian(Data.AsSpan(0xC6)); set => WriteUInt16LittleEndian(Data.AsSpan(0xC6), value); } // unused? + public override byte HandlingTrainerFriendship { get => Data[0xC8]; set => Data[0xC8] = value; } + public byte HandlingTrainerMemoryIntensity { get => Data[0xC9]; set => Data[0xC9] = value; } + public byte HandlingTrainerMemory { get => Data[0xCA]; set => Data[0xCA] = value; } + public byte HandlingTrainerMemoryFeeling { get => Data[0xCB]; set => Data[0xCB] = value; } + public ushort HandlingTrainerMemoryVariable { get => ReadUInt16LittleEndian(Data.AsSpan(0xCC)); set => WriteUInt16LittleEndian(Data.AsSpan(0xCC), value); } + public override GameVersion Version { get => (GameVersion)Data[0xCE]; set => Data[0xCE] = (byte)value; } + public GameVersion BattleVersion { get => (GameVersion)Data[0xCF]; set => Data[0xCF] = (byte)value; } public uint FormArgument { get => ReadUInt32LittleEndian(Data.AsSpan(0xD0)); set => WriteUInt32LittleEndian(Data.AsSpan(0xD0), value); } public byte FormArgumentRemain { get => (byte)FormArgument; set => FormArgument = (FormArgument & ~0xFFu) | value; } public byte FormArgumentElapsed { get => (byte)(FormArgument >> 8); set => FormArgument = (FormArgument & ~0xFF00u) | (uint)(value << 8); } @@ -404,30 +404,30 @@ public override string HT_Name #endregion #region Block D - public override string OT_Name + public override string OriginalTrainerName { - get => StringConverter8.GetString(OT_Trash); - set => StringConverter8.SetString(OT_Trash, value, 12, StringConverterOption.None); + get => StringConverter8.GetString(OriginalTrainerTrash); + set => StringConverter8.SetString(OriginalTrainerTrash, value, 12, StringConverterOption.None); } - public override int OT_Friendship { get => Data[0x112]; set => Data[0x112] = (byte)value; } - public byte OT_Intensity { get => Data[0x113]; set => Data[0x113] = value; } - public byte OT_Memory { get => Data[0x114]; set => Data[0x114] = value; } + public override byte OriginalTrainerFriendship { get => Data[0x112]; set => Data[0x112] = value; } + public byte OriginalTrainerMemoryIntensity { get => Data[0x113]; set => Data[0x113] = value; } + public byte OriginalTrainerMemory { get => Data[0x114]; set => Data[0x114] = value; } // 0x115 unused align - public ushort OT_TextVar { get => ReadUInt16LittleEndian(Data.AsSpan(0x116)); set => WriteUInt16LittleEndian(Data.AsSpan(0x116), value); } - public byte OT_Feeling { get => Data[0x118]; set => Data[0x118] = value; } - public override int Egg_Year { get => Data[0x119]; set => Data[0x119] = (byte)value; } - public override int Egg_Month { get => Data[0x11A]; set => Data[0x11A] = (byte)value; } - public override int Egg_Day { get => Data[0x11B]; set => Data[0x11B] = (byte)value; } - public override int Met_Year { get => Data[0x11C]; set => Data[0x11C] = (byte)value; } - public override int Met_Month { get => Data[0x11D]; set => Data[0x11D] = (byte)value; } - public override int Met_Day { get => Data[0x11E]; set => Data[0x11E] = (byte)value; } + public ushort OriginalTrainerMemoryVariable { get => ReadUInt16LittleEndian(Data.AsSpan(0x116)); set => WriteUInt16LittleEndian(Data.AsSpan(0x116), value); } + public byte OriginalTrainerMemoryFeeling { get => Data[0x118]; set => Data[0x118] = value; } + public override byte EggYear { get => Data[0x119]; set => Data[0x119] = value; } + public override byte EggMonth { get => Data[0x11A]; set => Data[0x11A] = value; } + public override byte EggDay { get => Data[0x11B]; set => Data[0x11B] = value; } + public override byte MetYear { get => Data[0x11C]; set => Data[0x11C] = value; } + public override byte MetMonth { get => Data[0x11D]; set => Data[0x11D] = value; } + public override byte MetDay { get => Data[0x11E]; set => Data[0x11E] = value; } public byte Obedience_Level { get => Data[0x11F]; set => Data[0x11F] = value; } - public override int Egg_Location { get => ReadUInt16LittleEndian(Data.AsSpan(0x120)); set => WriteUInt16LittleEndian(Data.AsSpan(0x120), (ushort)value); } - public override int Met_Location { get => ReadUInt16LittleEndian(Data.AsSpan(0x122)); set => WriteUInt16LittleEndian(Data.AsSpan(0x122), (ushort)value); } - public override int Ball { get => Data[0x124]; set => Data[0x124] = (byte)value; } - public override int Met_Level { get => Data[0x125] & ~0x80; set => Data[0x125] = (byte)((Data[0x125] & 0x80) | value); } - public override int OT_Gender { get => Data[0x125] >> 7; set => Data[0x125] = (byte)((Data[0x125] & ~0x80) | (value << 7)); } + public override ushort EggLocation { get => ReadUInt16LittleEndian(Data.AsSpan(0x120)); set => WriteUInt16LittleEndian(Data.AsSpan(0x120), value); } + public override ushort MetLocation { get => ReadUInt16LittleEndian(Data.AsSpan(0x122)); set => WriteUInt16LittleEndian(Data.AsSpan(0x122), value); } + public override byte Ball { get => Data[0x124]; set => Data[0x124] = value; } + public override byte MetLevel { get => (byte)(Data[0x125] & ~0x80); set => Data[0x125] = (byte)((Data[0x125] & 0x80) | value); } + public override byte OriginalTrainerGender { get => (byte)(Data[0x125] >> 7); set => Data[0x125] = (byte)((Data[0x125] & ~0x80) | (value << 7)); } public byte HyperTrainFlags { get => Data[0x126]; set => Data[0x126] = value; } public bool HT_HP { get => ((HyperTrainFlags >> 0) & 1) == 1; set => HyperTrainFlags = (byte)((HyperTrainFlags & ~(1 << 0)) | ((value ? 1 : 0) << 0)); } public bool HT_ATK { get => ((HyperTrainFlags >> 1) & 1) == 1; set => HyperTrainFlags = (byte)((HyperTrainFlags & ~(1 << 1)) | ((value ? 1 : 0) << 1)); } @@ -502,7 +502,7 @@ public void ClearMoveRecordFlags() #endregion #region Battle Stats - public override int Stat_Level { get => Data[0x148]; set => Data[0x148] = (byte)value; } + public override byte Stat_Level { get => Data[0x148]; set => Data[0x148] = value; } // 0x149 unused alignment public override int Stat_HPMax { get => ReadUInt16LittleEndian(Data.AsSpan(0x14A)); set => WriteUInt16LittleEndian(Data.AsSpan(0x14A), (ushort)value); } public override int Stat_ATK { get => ReadUInt16LittleEndian(Data.AsSpan(0x14C)); set => WriteUInt16LittleEndian(Data.AsSpan(0x14C), (ushort)value); } @@ -553,27 +553,27 @@ public void Trade(ITrainerInfo tr, int Day = 1, int Month = 1, int Year = 2015) { if (IsEgg) { - if (Egg_Location == 60005 && tr.Gender == OT_Gender && tr.Language == Language && tr.OT == OT_Name) + if (EggLocation == 60005 && tr.Gender == OriginalTrainerGender && tr.Language == Language && tr.OT == OriginalTrainerName) return; // Jacq gift, don't change. // Apply link trade data, only if it left the OT (ignore if dumped & imported, or cloned, etc.) // If not matching the trainer details, mark as a traded egg. - if (!IsTradedEgg && tr.Gender == OT_Gender && tr.Language == Language && tr.OT == OT_Name) + if (!IsTradedEgg && tr.Gender == OriginalTrainerGender && tr.Language == Language && tr.OT == OriginalTrainerName) { - OT_Trash.Clear(); - Nickname_Trash.Clear(); - HT_Trash.Clear(); + OriginalTrainerTrash.Clear(); + NicknameTrash.Clear(); + HandlingTrainerTrash.Clear(); CurrentHandler = 0; Language = tr.Language; Nickname = SpeciesName.GetEggName(tr.Language, 9); - OT_Name = tr.OT; - HT_Language = 0; + OriginalTrainerName = tr.OT; + HandlingTrainerLanguage = 0; } else { - HT_Name = tr.OT; - HT_Gender = tr.Gender; - HT_Language = (byte)tr.Language; + HandlingTrainerName = tr.OT; + HandlingTrainerGender = tr.Gender; + HandlingTrainerLanguage = (byte)tr.Language; SetLinkTradeEgg(Day, Month, Year, Locations.LinkTrade6); CurrentHandler = 1; } @@ -590,9 +590,9 @@ public void FixMemories() if (IsEgg) // No memories if is egg. { // HT_Language is set for eggs - HT_Friendship = HT_TextVar = HT_Memory = HT_Intensity = HT_Feeling = 0; - /* OT_Friendship */ - OT_TextVar = OT_Memory = OT_Intensity = OT_Feeling = 0; + HandlingTrainerMemoryVariable = HandlingTrainerFriendship = HandlingTrainerMemory = HandlingTrainerMemoryIntensity = HandlingTrainerMemoryFeeling = 0; + /* OriginalTrainerFriendship */ + OriginalTrainerMemoryVariable = OriginalTrainerMemory = OriginalTrainerMemoryIntensity = OriginalTrainerMemoryFeeling = 0; return; } @@ -600,18 +600,18 @@ public void FixMemories() { // HT_Language is set for gifts // Skip clearing that. - HT_Friendship = HT_TextVar = HT_Memory = HT_Intensity = HT_Feeling = 0; + HandlingTrainerMemoryVariable = HandlingTrainerFriendship = HandlingTrainerMemory = HandlingTrainerMemoryIntensity = HandlingTrainerMemoryFeeling = 0; } - int gen = Generation; + var gen = Generation; if (gen < 6) - OT_TextVar = OT_Memory = OT_Intensity = OT_Feeling = 0; + OriginalTrainerMemoryVariable = OriginalTrainerMemory = OriginalTrainerMemoryIntensity = OriginalTrainerMemoryFeeling = 0; } private bool TradeOT(ITrainerInfo tr) { // Check to see if the OT matches the SAV's OT info. - if (!(tr.ID32 == ID32 && tr.Gender == OT_Gender && tr.OT == OT_Name)) + if (!(tr.ID32 == ID32 && tr.Gender == OriginalTrainerGender && tr.OT == OriginalTrainerName)) return false; CurrentHandler = 0; @@ -620,16 +620,16 @@ private bool TradeOT(ITrainerInfo tr) private void TradeHT(ITrainerInfo tr) { - if (HT_Name != tr.OT) + if (HandlingTrainerName != tr.OT) { - HT_Friendship = 50; - HT_Name = tr.OT; + HandlingTrainerFriendship = 50; + HandlingTrainerName = tr.OT; } CurrentHandler = 1; - HT_Gender = tr.Gender; - if (HT_Language == 0) + HandlingTrainerGender = tr.Gender; + if (HandlingTrainerLanguage == 0) this.ClearMemoriesHT(); - HT_Language = (byte)tr.Language; + HandlingTrainerLanguage = (byte)tr.Language; } // Maximums @@ -638,5 +638,5 @@ private void TradeHT(ITrainerInfo tr) public override int MaxAbilityID => Legal.MaxAbilityID_9; public override int MaxItemID => Legal.MaxItemID_9; public override int MaxBallID => Legal.MaxBallID_9; - public override int MaxGameID => Legal.MaxGameID_HOME; + public override GameVersion MaxGameID => Legal.MaxGameID_HOME; } diff --git a/PKHeX.Core/PKM/PKM.cs b/PKHeX.Core/PKM/PKM.cs index 094120932..e8f8601f4 100644 --- a/PKHeX.Core/PKM/PKM.cs +++ b/PKHeX.Core/PKM/PKM.cs @@ -40,13 +40,13 @@ public abstract class PKM : ISpeciesForm, ITrainerID32, IGeneration, IShiny, ILa public abstract bool Valid { get; set; } // Trash Bytes - public abstract Span Nickname_Trash { get; } - public abstract Span OT_Trash { get; } - public virtual Span HT_Trash => []; + public abstract Span NicknameTrash { get; } + public abstract Span OriginalTrainerTrash { get; } + public virtual Span HandlingTrainerTrash => []; protected abstract byte[] Encrypt(); public abstract EntityContext Context { get; } - public int Format => Context.Generation(); + public byte Format => Context.Generation(); public TrainerIDFormat TrainerIDDisplayFormat => this.GetTrainerIDFormat(); private byte[] Write() @@ -59,21 +59,21 @@ private byte[] Write() public abstract ushort Species { get; set; } public abstract string Nickname { get; set; } public abstract int HeldItem { get; set; } - public abstract int Gender { get; set; } - public abstract int Nature { get; set; } - public virtual int StatNature { get => Nature; set => Nature = value; } + public abstract byte Gender { get; set; } + public abstract Nature Nature { get; set; } + public virtual Nature StatNature { get => Nature; set => Nature = value; } public abstract int Ability { get; set; } - public abstract int CurrentFriendship { get; set; } + public abstract byte CurrentFriendship { get; set; } public abstract byte Form { get; set; } public abstract bool IsEgg { get; set; } public abstract bool IsNicknamed { get; set; } public abstract uint EXP { get; set; } public abstract ushort TID16 { get; set; } public abstract ushort SID16 { get; set; } - public abstract string OT_Name { get; set; } - public abstract int OT_Gender { get; set; } - public abstract int Ball { get; set; } - public abstract int Met_Level { get; set; } + public abstract string OriginalTrainerName { get; set; } + public abstract byte OriginalTrainerGender { get; set; } + public abstract byte Ball { get; set; } + public abstract byte MetLevel { get; set; } // Aliases of ID32 public uint TrainerTID7 { get => this.GetTrainerTID7(); set => this.SetTrainerTID7(value); } @@ -107,7 +107,7 @@ private byte[] Write() public abstract int IV_SPA { get; set; } public abstract int IV_SPD { get; set; } public abstract int Status_Condition { get; set; } - public abstract int Stat_Level { get; set; } + public abstract byte Stat_Level { get; set; } public abstract int Stat_HPMax { get; set; } public abstract int Stat_HPCurrent { get; set; } public abstract int Stat_ATK { get; set; } @@ -117,10 +117,10 @@ private byte[] Write() public abstract int Stat_SPD { get; set; } // Hidden Properties - public abstract int Version { get; set; } + public abstract GameVersion Version { get; set; } public abstract uint ID32 { get; set; } - public abstract int PKRS_Strain { get; set; } - public abstract int PKRS_Days { get; set; } + public abstract int PokerusStrain { get; set; } + public abstract int PokerusDays { get; set; } public abstract uint EncryptionConstant { get; set; } public abstract uint PID { get; set; } @@ -131,19 +131,19 @@ private byte[] Write() public abstract uint TSV { get; } public abstract uint PSV { get; } public abstract int Characteristic { get; } - public abstract int Met_Location { get; set; } - public abstract int Egg_Location { get; set; } - public abstract int OT_Friendship { get; set; } + public abstract ushort MetLocation { get; set; } + public abstract ushort EggLocation { get; set; } + public abstract byte OriginalTrainerFriendship { get; set; } public virtual bool Japanese => Language == (int)LanguageID.Japanese; public virtual bool Korean => Language == (int)LanguageID.Korean; // Future Properties - public virtual int Met_Year { get => 0; set { } } - public virtual int Met_Month { get => 0; set { } } - public virtual int Met_Day { get => 0; set { } } - public virtual string HT_Name { get => string.Empty; set { } } - public virtual int HT_Gender { get => 0; set { } } - public virtual int HT_Friendship { get => 0; set { } } + public virtual byte MetYear { get => 0; set { } } + public virtual byte MetMonth { get => 0; set { } } + public virtual byte MetDay { get => 0; set { } } + public virtual string HandlingTrainerName { get => string.Empty; set { } } + public virtual byte HandlingTrainerGender { get => 0; set { } } + public virtual byte HandlingTrainerFriendship { get => 0; set { } } public virtual byte Enjoyment { get => 0; set { } } public virtual byte Fullness { get => 0; set { } } public virtual int AbilityNumber { get => 0; set { } } @@ -163,33 +163,33 @@ private byte[] Write() get { // Check to see if date is valid - if (!DateUtil.IsDateValid(2000 + Met_Year, Met_Month, Met_Day)) + if (!DateUtil.IsDateValid(2000 + MetYear, MetMonth, MetDay)) return null; - return new DateOnly(2000 + Met_Year, Met_Month, Met_Day); + return new DateOnly(2000 + MetYear, MetMonth, MetDay); } set { if (value.HasValue) { // Only update the properties if a value is provided. - Met_Year = value.Value.Year - 2000; - Met_Month = value.Value.Month; - Met_Day = value.Value.Day; + MetYear = (byte)(value.Value.Year - 2000); + MetMonth = (byte)value.Value.Month; + MetDay = (byte)value.Value.Day; } else { // Clear the Met Date. // If code tries to access MetDate again, null will be returned. - Met_Year = 0; - Met_Month = 0; - Met_Day = 0; + MetYear = 0; + MetMonth = 0; + MetDay = 0; } } } - public virtual int Egg_Year { get => 0; set { } } - public virtual int Egg_Month { get => 0; set { } } - public virtual int Egg_Day { get => 0; set { } } + public virtual byte EggYear { get => 0; set { } } + public virtual byte EggMonth { get => 0; set { } } + public virtual byte EggDay { get => 0; set { } } /// /// The date a Pokémon was met as an egg. @@ -206,26 +206,26 @@ private byte[] Write() get { // Check to see if date is valid - if (!DateUtil.IsDateValid(2000 + Egg_Year, Egg_Month, Egg_Day)) + if (!DateUtil.IsDateValid(2000 + EggYear, EggMonth, EggDay)) return null; - return new DateOnly(2000 + Egg_Year, Egg_Month, Egg_Day); + return new DateOnly(2000 + EggYear, EggMonth, EggDay); } set { if (value.HasValue) { // Only update the properties if a value is provided. - Egg_Year = value.Value.Year - 2000; - Egg_Month = value.Value.Month; - Egg_Day = value.Value.Day; + EggYear = (byte)(value.Value.Year - 2000); + EggMonth = (byte)value.Value.Month; + EggDay = (byte)value.Value.Day; } else { // Clear the Met Date. // If code tries to access MetDate again, null will be returned. - Egg_Year = 0; - Egg_Month = 0; - Egg_Day = 0; + EggYear = 0; + EggMonth = 0; + EggDay = 0; } } } @@ -236,7 +236,7 @@ private byte[] Write() public virtual ushort RelearnMove4 { get => 0; set { } } // Exposed but not Present in all - public abstract int CurrentHandler { get; set; } + public abstract byte CurrentHandler { get; set; } // Maximums public abstract ushort MaxMoveID { get; } @@ -244,8 +244,8 @@ private byte[] Write() public abstract int MaxItemID { get; } public abstract int MaxAbilityID { get; } public abstract int MaxBallID { get; } - public abstract int MaxGameID { get; } - public virtual int MinGameID => 0; + public abstract GameVersion MaxGameID { get; } + public virtual GameVersion MinGameID => 0; public abstract int MaxIV { get; } public abstract int MaxEV { get; } public abstract int MaxStringLengthOT { get; } @@ -264,41 +264,41 @@ public ushort ShinyXor } } - public bool E => Version == (int)GameVersion.E; - public bool FRLG => Version is (int)FR or (int)LG; - public bool Pt => (int)GameVersion.Pt == Version; - public bool HGSS => Version is (int)HG or (int)SS; - public bool BW => Version is (int)B or (int)W; - public bool B2W2 => Version is (int)B2 or (int)W2; - public bool XY => Version is (int)X or (int)Y; - public bool AO => Version is (int)AS or (int)OR; - public bool SM => Version is (int)SN or (int)MN; - public bool USUM => Version is (int)US or (int)UM; - public bool GO => Version is (int)GameVersion.GO; - public bool VC1 => Version is >= (int)RD and <= (int)YW; - public bool VC2 => Version is >= (int)GD and <= (int)C; - public bool LGPE => Version is (int)GP or (int)GE; - public bool SWSH => Version is (int)SW or (int)SH; - public virtual bool BDSP => Version is (int)BD or (int)SP; - public virtual bool LA => Version is (int)PLA; - public virtual bool SV => Version is (int)SL or (int)VL; + public bool E => Version == GameVersion.E; + public bool FRLG => Version is FR or LG; + public bool Pt => GameVersion.Pt == Version; + public bool HGSS => Version is HG or SS; + public bool BW => Version is B or W; + public bool B2W2 => Version is B2 or W2; + public bool XY => Version is X or Y; + public bool AO => Version is AS or OR; + public bool SM => Version is SN or MN; + public bool USUM => Version is US or UM; + public bool GO => Version is GameVersion.GO; + public bool VC1 => Version is >= RD and <= YW; + public bool VC2 => Version is >= GD and <= C; + public bool LGPE => Version is GP or GE; + public bool SWSH => Version is SW or SH; + public virtual bool BDSP => Version is BD or SP; + public virtual bool LA => Version is PLA; + public virtual bool SV => Version is SL or VL; - public bool GO_LGPE => GO && Met_Location == Locations.GO7; - public bool GO_HOME => GO && Met_Location == Locations.GO8; + public bool GO_LGPE => GO && MetLocation == Locations.GO7; + public bool GO_HOME => GO && MetLocation == Locations.GO8; public bool VC => VC1 || VC2; public bool GG => LGPE || GO_LGPE; public bool Gen9 => SV; - public bool Gen8 => Version is >= 44 and <= 49 || GO_HOME; - public bool Gen7 => Version is >= 30 and <= 33 || GG; - public bool Gen6 => Version is >= 24 and <= 29; - public bool Gen5 => Version is >= 20 and <= 23; - public bool Gen4 => Version is (>= 7 and <= 12) and not 9; - public bool Gen3 => Version is (>= 1 and <= 5) or 15; - public bool Gen2 => Version == (int)GSC; // Fixed value set by the Gen2 PKM classes - public bool Gen1 => Version == (int)RBY; // Fixed value set by the Gen1 PKM classes + public bool Gen8 => Version is >= SW and <= SP || GO_HOME; + public bool Gen7 => Version is >= SN and <= UM || GG; + public bool Gen6 => Version is >= X and <= OR; + public bool Gen5 => Version is >= W and <= B2; + public bool Gen4 => Version is HG or SS or D or P or GameVersion.Pt; + public bool Gen3 => Version is (>= S and <= LG) or CXD; + public bool Gen2 => Version == GSC; // Fixed value set by the Gen2 PKM classes + public bool Gen1 => Version == RBY; // Fixed value set by the Gen1 PKM classes public bool GenU => Generation <= 0; - public int Generation + public byte Generation { get { @@ -313,23 +313,23 @@ public int Generation if (Gen1) return Format; // 1 if (VC1) return 1; if (VC2) return 2; - return -1; + return 0; } } - public bool PKRS_Infected { get => PKRS_Days != 0 || PKRS_Strain != 0; set => PKRS_Strain = value ? Math.Max(PKRS_Strain, 1) : 0; } + public bool IsPokerusInfected { get => PokerusDays != 0 || PokerusStrain != 0; set => PokerusStrain = value ? Math.Max(PokerusStrain, 1) : 0; } - public bool PKRS_Cured + public bool IsPokerusCured { - get => PKRS_Days == 0 && PKRS_Strain > 0; + get => PokerusDays == 0 && PokerusStrain > 0; set { - PKRS_Days = value ? 0 : 1; - PKRS_Infected = true; + PokerusDays = value ? 0 : 1; + IsPokerusInfected = true; } } - public int CurrentLevel { get => Experience.GetLevel(EXP, PersonalInfo.EXPGrowth); set => EXP = Experience.GetEXP(Stat_Level = value, PersonalInfo.EXPGrowth); } + public byte CurrentLevel { get => Experience.GetLevel(EXP, PersonalInfo.EXPGrowth); set => EXP = Experience.GetEXP(Stat_Level = value, PersonalInfo.EXPGrowth); } public int IVTotal => IV_HP + IV_ATK + IV_DEF + IV_SPA + IV_SPD + IV_SPE; public int EVTotal => EV_HP + EV_ATK + EV_DEF + EV_SPA + EV_SPD + EV_SPE; public int MaximumIV => Math.Max(Math.Max(Math.Max(Math.Max(Math.Max(IV_HP, IV_ATK), IV_DEF), IV_SPA), IV_SPD), IV_SPE); @@ -516,7 +516,7 @@ public int PIDAbility if (Generation > 5 || Format > 5) return -1; - if (Version == (int) CXD) + if (Version == CXD) return PersonalInfo.GetIndexOfAbility(Ability); // Can mismatch; not tied to PID return (int)((Gen5 ? PID >> 16 : PID) & 1); } @@ -532,8 +532,7 @@ public virtual int HPType get => 15 * HPBitValType / 63; set { - var arr = HiddenPower.DefaultLowBits; - var bits = (uint)value >= arr.Length ? 0 : arr[value]; + var bits = HiddenPower.GetLowBits(value); IV_HP = (IV_HP & ~1) + ((bits >> 0) & 1); IV_ATK = (IV_ATK & ~1) + ((bits >> 1) & 1); IV_DEF = (IV_DEF & ~1) + ((bits >> 2) & 1); @@ -544,10 +543,10 @@ public virtual int HPType } // Misc Egg Facts - public virtual bool WasEgg => IsEgg || Egg_Day != 0; - public bool WasTradedEgg => Egg_Location == GetTradedEggLocation(); - public bool IsTradedEgg => Met_Location == GetTradedEggLocation(); - private int GetTradedEggLocation() => Locations.TradedEggLocation(Generation, (GameVersion)Version); + public virtual bool WasEgg => IsEgg || EggDay != 0; + public bool WasTradedEgg => EggLocation == GetTradedEggLocation(); + public bool IsTradedEgg => MetLocation == GetTradedEggLocation(); + private int GetTradedEggLocation() => Locations.TradedEggLocation(Generation, Version); public virtual bool IsUntraded => false; public virtual bool IsNative => Generation == Format; @@ -565,7 +564,7 @@ public virtual int HPType /// True if valid, False if invalid. public virtual bool IsGenderValid() { - int gender = Gender; + byte gender = Gender; var gv = PersonalInfo.Gender; if (gv == PersonalInfo.RatioMagicGenderless) return gender == 2; @@ -574,7 +573,7 @@ public virtual bool IsGenderValid() if (gv == PersonalInfo.RatioMagicMale) return gender == 0; - int gen = Generation; + var gen = Generation; if (gen is not (3 or 4 or 5)) return gender == (gender & 1); @@ -800,12 +799,12 @@ public bool ForcePartyData() /// Month the was traded. /// Day the was traded. /// Link Trade location value. - protected void SetLinkTradeEgg(int day, int month, int y, int location) + protected void SetLinkTradeEgg(int day, int month, int y, ushort location) { - Met_Day = day; - Met_Month = month; - Met_Year = y - 2000; - Met_Location = location; + MetDay = (byte)day; + MetMonth = (byte)month; + MetYear = (byte)(y - 2000); + MetLocation = location; } /// @@ -866,7 +865,7 @@ public void SetShinySID(Shiny shiny = Shiny.Random) /// /// If a originated in a generation prior to Generation 6, the is updated. /// - public void SetPIDGender(int gender) + public void SetPIDGender(byte gender) { var rnd = Util.Rand; do PID = EntityPID.GetRandomPID(rnd, Species, gender, Version, Nature, Form, PID); @@ -882,7 +881,7 @@ public void SetPIDGender(int gender) /// /// If a originated in a generation prior to Generation 6, the is updated. /// - public void SetPIDNature(int nature) + public void SetPIDNature(Nature nature) { var rnd = Util.Rand; do PID = EntityPID.GetRandomPID(rnd, Species, Gender, Version, nature, Form, PID); @@ -934,7 +933,7 @@ public void SetRandomIVs(Span ivs, in IndividualValueSet template) /// Count of flawless IVs to set. If none provided, a count will be detected. public void SetRandomIVs(Span ivs, int minFlawless = 0) { - if (Version == (int)GameVersion.GO) + if (Version == GameVersion.GO) { SetRandomIVsGO(ivs); return; diff --git a/PKHeX.Core/PKM/RK4.cs b/PKHeX.Core/PKM/RK4.cs index af156ecd3..5e601f138 100644 --- a/PKHeX.Core/PKM/RK4.cs +++ b/PKHeX.Core/PKM/RK4.cs @@ -44,7 +44,7 @@ private static byte[] Decrypt(byte[] data) public override ushort TID16 { get => ReadUInt16LittleEndian(Data.AsSpan(0x0C)); set => WriteUInt16LittleEndian(Data.AsSpan(0x0C), value); } public override ushort SID16 { get => ReadUInt16LittleEndian(Data.AsSpan(0x0E)); set => WriteUInt16LittleEndian(Data.AsSpan(0x0E), value); } public override uint EXP { get => ReadUInt32LittleEndian(Data.AsSpan(0x10)); set => WriteUInt32LittleEndian(Data.AsSpan(0x10), value); } - public override int OT_Friendship { get => Data[0x14]; set => Data[0x14] = (byte)value; } + public override byte OriginalTrainerFriendship { get => Data[0x14]; set => Data[0x14] = value; } public override int Ability { get => Data[0x15]; set => Data[0x15] = (byte)value; } public override byte MarkingValue { get => Data[0x16]; set => Data[0x16] = value; } public override int Language { get => Data[0x17]; set => Data[0x17] = (byte)value; } @@ -54,12 +54,12 @@ private static byte[] Decrypt(byte[] data) public override int EV_SPE { get => Data[0x1B]; set => Data[0x1B] = (byte)value; } public override int EV_SPA { get => Data[0x1C]; set => Data[0x1C] = (byte)value; } public override int EV_SPD { get => Data[0x1D]; set => Data[0x1D] = (byte)value; } - public override byte CNT_Cool { get => Data[0x1E]; set => Data[0x1E] = value; } - public override byte CNT_Beauty { get => Data[0x1F]; set => Data[0x1F] = value; } - public override byte CNT_Cute { get => Data[0x20]; set => Data[0x20] = value; } - public override byte CNT_Smart { get => Data[0x21]; set => Data[0x21] = value; } - public override byte CNT_Tough { get => Data[0x22]; set => Data[0x22] = value; } - public override byte CNT_Sheen { get => Data[0x23]; set => Data[0x23] = value; } + public override byte ContestCool { get => Data[0x1E]; set => Data[0x1E] = value; } + public override byte ContestBeauty { get => Data[0x1F]; set => Data[0x1F] = value; } + public override byte ContestCute { get => Data[0x20]; set => Data[0x20] = value; } + public override byte ContestSmart { get => Data[0x21]; set => Data[0x21] = value; } + public override byte ContestTough { get => Data[0x22]; set => Data[0x22] = value; } + public override byte ContestSheen { get => Data[0x23]; set => Data[0x23] = value; } private byte RIB0 { get => Data[0x24]; set => Data[0x24] = value; } // Sinnoh 1 private byte RIB1 { get => Data[0x25]; set => Data[0x25] = value; } // Sinnoh 2 @@ -116,7 +116,7 @@ private static byte[] Decrypt(byte[] data) public override int Move2_PPUps { get => Data[0x35]; set => Data[0x35] = (byte)value; } public override int Move3_PPUps { get => Data[0x36]; set => Data[0x36] = (byte)value; } public override int Move4_PPUps { get => Data[0x37]; set => Data[0x37] = (byte)value; } - protected internal override uint IV32 { get => ReadUInt32LittleEndian(Data.AsSpan(0x38)); set => WriteUInt32LittleEndian(Data.AsSpan(0x38), value); } + public override uint IV32 { get => ReadUInt32LittleEndian(Data.AsSpan(0x38)); set => WriteUInt32LittleEndian(Data.AsSpan(0x38), value); } public override int IV_HP { get => (int)(IV32 >> 00) & 0x1F; set => IV32 = (IV32 & ~(0x1Fu << 00)) | ((value > 31 ? 31u : (uint)value) << 00); } public override int IV_ATK { get => (int)(IV32 >> 05) & 0x1F; set => IV32 = (IV32 & ~(0x1Fu << 05)) | ((value > 31 ? 31u : (uint)value) << 05); } public override int IV_DEF { get => (int)(IV32 >> 10) & 0x1F; set => IV32 = (IV32 & ~(0x1Fu << 10)) | ((value > 31 ? 31u : (uint)value) << 10); } @@ -164,17 +164,17 @@ private static byte[] Decrypt(byte[] data) public override bool RibbonWorld { get => (RIB7 & (1 << 7)) == 1 << 7; set => RIB7 = (byte)((RIB7 & ~(1 << 7)) | (value ? 1 << 7 : 0)); } public override bool FatefulEncounter { get => (Data[0x40] & 1) == 1; set => Data[0x40] = (byte)((Data[0x40] & ~0x01) | (value ? 1 : 0)); } - public override int Gender { get => (Data[0x40] >> 1) & 0x3; set => Data[0x40] = (byte)((Data[0x40] & ~0x06) | (value << 1)); } + public override byte Gender { get => (byte)((Data[0x40] >> 1) & 0x3); set => Data[0x40] = (byte)((Data[0x40] & ~0x06) | (value << 1)); } public override byte Form { get => (byte)(Data[0x40] >> 3); set => Data[0x40] = (byte)((Data[0x40] & 0x07) | (value << 3)); } public override int ShinyLeaf { get => Data[0x41]; set => Data[0x41] = (byte)value; } // 0x42-0x43 Unused - public override ushort Egg_LocationExtended + public override ushort EggLocationExtended { get => ReadUInt16LittleEndian(Data.AsSpan(0x44)); set => WriteUInt16LittleEndian(Data.AsSpan(0x44), value); } - public override ushort Met_LocationExtended + public override ushort MetLocationExtended { get => ReadUInt16LittleEndian(Data.AsSpan(0x46)); set => WriteUInt16LittleEndian(Data.AsSpan(0x46), value); @@ -185,12 +185,12 @@ public override ushort Met_LocationExtended #region Block C public override string Nickname { - get => StringConverter4.GetString(Nickname_Trash); - set => StringConverter4.SetString(Nickname_Trash, value, 10, StringConverterOption.None); + get => StringConverter4.GetString(NicknameTrash); + set => StringConverter4.SetString(NicknameTrash, value, 10, StringConverterOption.None); } // 0x5E unused - public override int Version { get => Data[0x5F]; set => Data[0x5F] = (byte)value; } + public override GameVersion Version { get => (GameVersion)Data[0x5F]; set => Data[0x5F] = (byte)value; } private byte RIB8 { get => Data[0x60]; set => Data[0x60] = value; } // Sinnoh 3 private byte RIB9 { get => Data[0x61]; set => Data[0x61] = value; } // Sinnoh 4 private byte RIBA { get => Data[0x62]; set => Data[0x62] = value; } // Sinnoh 5 @@ -231,36 +231,36 @@ public override string Nickname #endregion #region Block D - public override string OT_Name + public override string OriginalTrainerName { - get => StringConverter4.GetString(OT_Trash); - set => StringConverter4.SetString(OT_Trash, value, 7, StringConverterOption.None); + get => StringConverter4.GetString(OriginalTrainerTrash); + set => StringConverter4.SetString(OriginalTrainerTrash, value, 7, StringConverterOption.None); } - public override int Egg_Year { get => Data[0x78]; set => Data[0x78] = (byte)value; } - public override int Egg_Month { get => Data[0x79]; set => Data[0x79] = (byte)value; } - public override int Egg_Day { get => Data[0x7A]; set => Data[0x7A] = (byte)value; } - public override int Met_Year { get => Data[0x7B]; set => Data[0x7B] = (byte)value; } - public override int Met_Month { get => Data[0x7C]; set => Data[0x7C] = (byte)value; } - public override int Met_Day { get => Data[0x7D]; set => Data[0x7D] = (byte)value; } + public override byte EggYear { get => Data[0x78]; set => Data[0x78] = value; } + public override byte EggMonth { get => Data[0x79]; set => Data[0x79] = value; } + public override byte EggDay { get => Data[0x7A]; set => Data[0x7A] = value; } + public override byte MetYear { get => Data[0x7B]; set => Data[0x7B] = value; } + public override byte MetMonth { get => Data[0x7C]; set => Data[0x7C] = value; } + public override byte MetDay { get => Data[0x7D]; set => Data[0x7D] = value; } - public override ushort Egg_LocationDP + public override ushort EggLocationDP { get => ReadUInt16LittleEndian(Data.AsSpan(0x7E)); set => WriteUInt16LittleEndian(Data.AsSpan(0x7E), value); } - public override ushort Met_LocationDP + public override ushort MetLocationDP { get => ReadUInt16LittleEndian(Data.AsSpan(0x80)); set => WriteUInt16LittleEndian(Data.AsSpan(0x80), value); } - private byte PKRS { get => Data[0x82]; set => Data[0x82] = value; } - public override int PKRS_Days { get => PKRS & 0xF; set => PKRS = (byte)((PKRS & ~0xF) | value); } - public override int PKRS_Strain { get => PKRS >> 4; set => PKRS = (byte)((PKRS & 0xF) | (value << 4)); } + public override byte PokerusState { get => Data[0x82]; set => Data[0x82] = value; } + public override int PokerusDays { get => PokerusState & 0xF; set => PokerusState = (byte)((PokerusState & ~0xF) | value); } + public override int PokerusStrain { get => PokerusState >> 4; set => PokerusState = (byte)((PokerusState & 0xF) | (value << 4)); } public override byte BallDPPt { get => Data[0x83]; set => Data[0x83] = value; } - public override int Met_Level { get => Data[0x84] & ~0x80; set => Data[0x84] = (byte)((Data[0x84] & 0x80) | value); } - public override int OT_Gender { get => Data[0x84] >> 7; set => Data[0x84] = (byte)((Data[0x84] & ~0x80) | (value << 7)); } + public override byte MetLevel { get => (byte)(Data[0x84] & ~0x80); set => Data[0x84] = (byte)((Data[0x84] & 0x80) | value); } + public override byte OriginalTrainerGender { get => (byte)(Data[0x84] >> 7); set => Data[0x84] = (byte)((Data[0x84] & ~0x80) | (value << 7)); } public override GroundTileType GroundTile { get => (GroundTileType)Data[0x85]; set => Data[0x85] = (byte)value; } public override byte BallHGSS { get => Data[0x86]; set => Data[0x86] = value; } public override byte PokeathlonStat { get => Data[0x87]; set => Data[0x87] = value; } @@ -268,7 +268,7 @@ public override ushort Met_LocationDP #region Battle Stats public override int Status_Condition { get => 0; set { } } - public override int Stat_Level { get => CurrentLevel; set { } } + public override byte Stat_Level { get => CurrentLevel; set { } } public override int Stat_HPCurrent { get => PersonalInfo.HP; set { } } public override int Stat_HPMax { get => PersonalInfo.HP; set { } } public override int Stat_ATK { get => PersonalInfo.ATK; set { } } @@ -307,14 +307,14 @@ public RanchOwnershipStatus OwnershipStatus set => WriteUInt16BigEndian(Data.AsSpan(0x8A), (ushort)value); } - public ushort HT_TID { get => ReadUInt16LittleEndian(Data.AsSpan(0x8C)); set => WriteUInt16LittleEndian(Data.AsSpan(0x8C), value); } - public ushort HT_SID { get => ReadUInt16LittleEndian(Data.AsSpan(0x8E)); set => WriteUInt16LittleEndian(Data.AsSpan(0x8E), value); } + public ushort HandlingTrainerTID { get => ReadUInt16LittleEndian(Data.AsSpan(0x8C)); set => WriteUInt16LittleEndian(Data.AsSpan(0x8C), value); } + public ushort HandlingTrainerSID { get => ReadUInt16LittleEndian(Data.AsSpan(0x8E)); set => WriteUInt16LittleEndian(Data.AsSpan(0x8E), value); } - public override Span HT_Trash => Data.AsSpan(0x90, 0x10); - public override string HT_Name + public override Span HandlingTrainerTrash => Data.AsSpan(0x90, 0x10); + public override string HandlingTrainerName { - get => StringConverter4.GetString(HT_Trash); - set => StringConverter4.SetString(HT_Trash, value, 7, StringConverterOption.None); + get => StringConverter4.GetString(HandlingTrainerTrash); + set => StringConverter4.SetString(HandlingTrainerTrash, value, 7, StringConverterOption.None); } #endregion diff --git a/PKHeX.Core/PKM/SK2.cs b/PKHeX.Core/PKM/SK2.cs index 6e5d1eac6..011c50afb 100644 --- a/PKHeX.Core/PKM/SK2.cs +++ b/PKHeX.Core/PKM/SK2.cs @@ -56,9 +56,9 @@ public override SK2 Clone() => new((byte[])Data.Clone(), Japanese) public override int Move2_PPUps { get => (Data[0x19] & 0xC0) >> 6; set => Data[0x19] = (byte)((Data[0x19] & 0x3F) | ((value & 0x3) << 6)); } public override int Move3_PPUps { get => (Data[0x1A] & 0xC0) >> 6; set => Data[0x1A] = (byte)((Data[0x1A] & 0x3F) | ((value & 0x3) << 6)); } public override int Move4_PPUps { get => (Data[0x1B] & 0xC0) >> 6; set => Data[0x1B] = (byte)((Data[0x1B] & 0x3F) | ((value & 0x3) << 6)); } - public override int CurrentFriendship { get => Data[0x1C]; set => Data[0x1C] = (byte)value; } + public override byte CurrentFriendship { get => Data[0x1C]; set => Data[0x1C] = value; } - public override int Stat_Level { get => Data[0x1D]; set => Data[0x1D] = (byte)value; } + public override byte Stat_Level { get => Data[0x1D]; set => Data[0x1D] = value; } public override bool IsEgg { get => (Data[0x1E] & 1) == 1; set => Data[0x1E] = (byte)((Data[0x1E] & ~1) | (value ? 1 : 0)); } public bool IsRental @@ -73,46 +73,47 @@ public bool IsRental } Data[0x1E] |= 4; - OT_Name = string.Empty; + // Rentals do not have an OT name, so clear it + OriginalTrainerTrash.Clear(); } } // 0x1F - private byte PKRS { get => Data[0x20]; set => Data[0x20] = value; } + public byte PokerusState { get => Data[0x20]; set => Data[0x20] = value; } // Crystal only Caught Data - public override int PKRS_Days { get => PKRS & 0xF; set => PKRS = (byte)((PKRS & ~0xF) | value); } - public override int PKRS_Strain { get => PKRS >> 4; set => PKRS = (byte)((PKRS & 0xF) | (value << 4)); } + public override int PokerusDays { get => PokerusState & 0xF; set => PokerusState = (byte)((PokerusState & ~0xF) | value); } + public override int PokerusStrain { get => PokerusState >> 4; set => PokerusState = (byte)((PokerusState & 0xF) | (value << 4)); } public ushort CaughtData { get => ReadUInt16BigEndian(Data.AsSpan(0x21)); set => WriteUInt16BigEndian(Data.AsSpan(0x21), value); } - public int Met_TimeOfDay { get => (CaughtData >> 14) & 0x3; set => CaughtData = (ushort)((CaughtData & 0x3FFF) | ((value & 0x3) << 14)); } - public override int Met_Level { get => (CaughtData >> 8) & 0x3F; set => CaughtData = (ushort)((CaughtData & 0xC0FF) | ((value & 0x3F) << 8)); } - public override int OT_Gender { get => (CaughtData >> 7) & 1; set => CaughtData = (ushort)((CaughtData & 0xFF7F) | ((value & 1) << 7)); } - public override int Met_Location { get => CaughtData & 0x7F; set => CaughtData = (ushort)((CaughtData & 0xFF80) | (value & 0x7F)); } + public int MetTimeOfDay { get => (CaughtData >> 14) & 0x3; set => CaughtData = (ushort)((CaughtData & 0x3FFF) | ((value & 0x3) << 14)); } + public override byte MetLevel { get => (byte)((CaughtData >> 8) & 0x3F); set => CaughtData = (ushort)((CaughtData & 0xC0FF) | ((value & 0x3F) << 8)); } + public override byte OriginalTrainerGender { get => (byte)((CaughtData >> 7) & 1); set => CaughtData = (ushort)((CaughtData & 0xFF7F) | ((value & 1) << 7)); } + public override ushort MetLocation { get => (ushort)(CaughtData & 0x7F); set => CaughtData = (ushort)((CaughtData & 0xFF80) | (value & 0x7F)); } public override string Nickname { - get => StringConverter12.GetString(Nickname_Trash, Japanese); - set => StringConverter12.SetString(Nickname_Trash, value, StringLength, Japanese, StringConverterOption.None); + get => StringConverter12.GetString(NicknameTrash, Japanese); + set => StringConverter12.SetString(NicknameTrash, value, StringLength, Japanese, StringConverterOption.None); } - public override string OT_Name + public override string OriginalTrainerName { - get => StringConverter12.GetString(OT_Trash, Japanese); + get => StringConverter12.GetString(OriginalTrainerTrash, Japanese); set { if (IsRental) { - OT_Trash.Clear(); + OriginalTrainerTrash.Clear(); return; } - StringConverter12.SetString(OT_Trash, value, StringLength, Japanese, StringConverterOption.None); + StringConverter12.SetString(OriginalTrainerTrash, value, StringLength, Japanese, StringConverterOption.None); } } - public override Span Nickname_Trash => Data.AsSpan(0x24, StringLength); - public override Span OT_Trash => Data.AsSpan(0x30, StringLength); + public override Span NicknameTrash => Data.AsSpan(0x24, StringLength); + public override Span OriginalTrainerTrash => Data.AsSpan(0x30, StringLength); #endregion @@ -127,9 +128,9 @@ public override string OT_Name public override int Stat_SPD { get; set; } #endregion - public override int OT_Friendship { get => CurrentFriendship; set => CurrentFriendship = value; } + public override byte OriginalTrainerFriendship { get => CurrentFriendship; set => CurrentFriendship = value; } public override bool HasOriginalMetLocation => CaughtData != 0; - public override int Version { get => (int)GameVersion.GSC; set { } } + public override GameVersion Version { get => GameVersion.GSC; set { } } protected override void GetNonNickname(int language, Span data) { @@ -137,7 +138,7 @@ protected override void GetNonNickname(int language, Span data) StringConverter12.SetString(data, name, data.Length, Japanese, StringConverterOption.Clear50); } - public override void SetNotNicknamed(int language) => GetNonNickname(language, Nickname_Trash); + public override void SetNotNicknamed(int language) => GetNonNickname(language, NicknameTrash); // Maximums public override ushort MaxMoveID => Legal.MaxMoveID_2; @@ -172,13 +173,12 @@ public PK2 ConvertToPK2() => new(Japanese) CurrentFriendship = CurrentFriendship, Stat_Level = Stat_Level, IsEgg = IsEgg, - PKRS_Days = PKRS_Days, - PKRS_Strain = PKRS_Strain, + PokerusState = PokerusState, CaughtData = CaughtData, // Only copies until first 0x50 terminator, but just copy everything Nickname = Nickname, - OT_Name = IsRental ? Japanese ? "1337" : "PKHeX" : OT_Name, + OriginalTrainerName = IsRental ? Japanese ? "1337" : "PKHeX" : OriginalTrainerName, }; private static bool IsJapanese(ReadOnlySpan data) diff --git a/PKHeX.Core/PKM/Searching/SearchSettings.cs b/PKHeX.Core/PKM/Searching/SearchSettings.cs index 55ffd954c..907cbb433 100644 --- a/PKHeX.Core/PKM/Searching/SearchSettings.cs +++ b/PKHeX.Core/PKM/Searching/SearchSettings.cs @@ -11,13 +11,13 @@ namespace PKHeX.Core.Searching; /// public sealed class SearchSettings { - public int Format { get; init; } - public int Generation { get; init; } + public byte Format { get; init; } + public byte Generation { get; init; } public required ushort Species { get; init; } public int Ability { get; init; } = -1; - public int Nature { get; init; } = -1; + public Nature Nature { get; init; } = Nature.Random; public int Item { get; init; } = -1; - public int Version { get; init; } = -1; + public GameVersion Version { get; init; } public int HiddenPowerType { get; init; } = -1; public SearchComparison SearchFormat { get; init; } @@ -153,11 +153,11 @@ private bool SearchSimple(PKM pk) return false; if (Ability > -1 && pk.Ability != Ability) return false; - if (Nature > -1 && pk.StatNature != Nature) + if (Nature.IsFixed() && pk.StatNature != Nature) return false; if (Item > -1 && pk.HeldItem != Item) return false; - if (Version > -1 && pk.Version != Version) + if (Version > 0 && pk.Version != Version) return false; return true; } @@ -209,7 +209,7 @@ private bool FilterResultEgg(PKM pk) public IReadOnlyList GetVersions(SaveFile sav, GameVersion fallback) { if (Version > 0) - return [(GameVersion) Version]; + return [Version]; return Generation switch { @@ -224,7 +224,7 @@ public IReadOnlyList GetVersions(SaveFile sav, GameVersion fallback private static GameVersion GetFallbackVersion(ITrainerInfo sav) { - var parent = GameUtil.GetMetLocationVersionGroup((GameVersion)sav.Game); + var parent = GameUtil.GetMetLocationVersionGroup(sav.Version); if (parent == Invalid) parent = GameUtil.GetMetLocationVersionGroup(GameUtil.GetVersion(sav.Generation)); return parent; diff --git a/PKHeX.Core/PKM/Searching/SearchUtil.cs b/PKHeX.Core/PKM/Searching/SearchUtil.cs index eb951df7e..ab5c54715 100644 --- a/PKHeX.Core/PKM/Searching/SearchUtil.cs +++ b/PKHeX.Core/PKM/Searching/SearchUtil.cs @@ -9,7 +9,7 @@ namespace PKHeX.Core.Searching; public static class SearchUtil { // Future: Might need to clamp down further for generations that cannot exist in the current format. - public static bool SatisfiesFilterFormat(PKM pk, int format, SearchComparison formatOperand) => formatOperand switch + public static bool SatisfiesFilterFormat(PKM pk, byte format, SearchComparison formatOperand) => formatOperand switch { SearchComparison.GreaterThanEquals when pk.Format < format => false, SearchComparison.Equals when pk.Format != format => false, @@ -20,7 +20,7 @@ public static class SearchUtil _ => true, }; - public static bool SatisfiesFilterGeneration(PKM pk, int generation) => generation switch + public static bool SatisfiesFilterGeneration(PKM pk, byte generation) => generation switch { 1 => pk.VC || pk.Format < 3, 2 => pk.VC || pk.Format < 3, diff --git a/PKHeX.Core/PKM/Shared/G3PKM.cs b/PKHeX.Core/PKM/Shared/G3PKM.cs index 17b12194b..06a8ee60e 100644 --- a/PKHeX.Core/PKM/Shared/G3PKM.cs +++ b/PKHeX.Core/PKM/Shared/G3PKM.cs @@ -19,7 +19,7 @@ public abstract class G3PKM : PKM, IRibbonSetEvent3, IRibbonSetCommon3, IRibbonS public sealed override int MaxAbilityID => Legal.MaxAbilityID_3; public sealed override int MaxItemID => Legal.MaxItemID_3; public sealed override int MaxBallID => Legal.MaxBallID_3; - public sealed override int MaxGameID => Legal.MaxGameID_3; + public sealed override GameVersion MaxGameID => Legal.MaxGameID_3; public sealed override int MaxIV => 31; public sealed override int MaxEV => EffortValues.Max255; public sealed override int MaxStringLengthOT => 7; @@ -32,13 +32,13 @@ public abstract class G3PKM : PKM, IRibbonSetEvent3, IRibbonSetCommon3, IRibbonS public sealed override int Ability { get => PersonalInfo.GetAbility(AbilityBit); set { } } public sealed override uint EncryptionConstant { get => PID; set { } } - public sealed override int Nature { get => (int)(PID % 25); set { } } + public sealed override Nature Nature { get => (Nature)(PID % 25); set { } } public sealed override bool IsNicknamed { get => SpeciesName.IsNicknamed(Species, Nickname, Language, 3); set { } } - public sealed override int Gender { get => EntityGender.GetFromPID(Species, PID); set { } } + public sealed override byte Gender { get => EntityGender.GetFromPID(Species, PID); set { } } public sealed override int Characteristic => -1; - public sealed override int CurrentFriendship { get => OT_Friendship; set => OT_Friendship = value; } - public sealed override int CurrentHandler { get => 0; set { } } - public sealed override int Egg_Location { get => 0; set { } } + public sealed override byte CurrentFriendship { get => OriginalTrainerFriendship; set => OriginalTrainerFriendship = value; } + public sealed override byte CurrentHandler { get => 0; set { } } + public sealed override ushort EggLocation { get => 0; set { } } public int MarkingCount => 4; public abstract byte MarkingValue { get; set; } @@ -113,12 +113,12 @@ public sealed override void RefreshAbility(int n) public abstract bool Unused4 { get; set; } public abstract int RibbonCount { get; } - public abstract byte CNT_Cool { get; set; } - public abstract byte CNT_Beauty { get; set; } - public abstract byte CNT_Cute { get; set; } - public abstract byte CNT_Smart { get; set; } - public abstract byte CNT_Tough { get; set; } - public abstract byte CNT_Sheen { get; set; } + public abstract byte ContestCool { get; set; } + public abstract byte ContestBeauty { get; set; } + public abstract byte ContestCute { get; set; } + public abstract byte ContestSmart { get; set; } + public abstract byte ContestTough { get; set; } + public abstract byte ContestSheen { get; set; } /// /// Swaps bits at a given position @@ -137,8 +137,8 @@ protected static int SwapBits(int value, int p1, int p2) return value ^ x; } - protected static byte GetGBAVersionID(byte gc) => (byte)((GCVersion)gc).GetG3VersionID(); - protected static byte GetGCVersionID(int gba) => (byte)((GameVersion)gba).GetCXDVersionID(); + protected static GameVersion GetGBAVersionID(GCVersion gc) => gc.GetG3VersionID(); + protected static GCVersion GetGCVersionID(GameVersion gba) => gba.GetCXDVersionID(); /// /// Interconversion for Generation 3 formats. @@ -158,15 +158,15 @@ protected T ConvertTo() where T : G3PKM, new() => new() IsEgg = IsEgg, FatefulEncounter = FatefulEncounter, - Met_Location = Met_Location, - Met_Level = Met_Level, + MetLocation = MetLocation, + MetLevel = MetLevel, Version = Version, Ball = Ball, Nickname = Nickname, - OT_Name = OT_Name, - OT_Gender = OT_Gender, - OT_Friendship = OT_Friendship, + OriginalTrainerName = OriginalTrainerName, + OriginalTrainerGender = OriginalTrainerGender, + OriginalTrainerFriendship = OriginalTrainerFriendship, Move1_PPUps = Move1_PPUps, Move2_PPUps = Move2_PPUps, @@ -193,15 +193,15 @@ protected T ConvertTo() where T : G3PKM, new() => new() EV_SPE = EV_SPE, EV_SPA = EV_SPA, EV_SPD = EV_SPD, - CNT_Cool = CNT_Cool, - CNT_Beauty = CNT_Beauty, - CNT_Cute = CNT_Cute, - CNT_Smart = CNT_Smart, - CNT_Tough = CNT_Tough, - CNT_Sheen = CNT_Sheen, + ContestCool = ContestCool, + ContestBeauty = ContestBeauty, + ContestCute = ContestCute, + ContestSmart = ContestSmart, + ContestTough = ContestTough, + ContestSheen = ContestSheen, - PKRS_Days = PKRS_Days, - PKRS_Strain = PKRS_Strain, + PokerusDays = PokerusDays, + PokerusStrain = PokerusStrain, // Transfer Ribbons RibbonCountG3Cool = RibbonCountG3Cool, diff --git a/PKHeX.Core/PKM/Shared/G4PKM.cs b/PKHeX.Core/PKM/Shared/G4PKM.cs index e9ebc7ff5..1b2e2da76 100644 --- a/PKHeX.Core/PKM/Shared/G4PKM.cs +++ b/PKHeX.Core/PKM/Shared/G4PKM.cs @@ -1,5 +1,6 @@ using System; using System.Diagnostics.CodeAnalysis; +using System.Runtime.InteropServices; namespace PKHeX.Core; @@ -16,7 +17,7 @@ public abstract class G4PKM : PKM, public sealed override int MaxAbilityID => Legal.MaxAbilityID_4; public sealed override int MaxItemID => Legal.MaxItemID_4_HGSS; public sealed override int MaxBallID => Legal.MaxBallID_4; - public sealed override int MaxGameID => Legal.MaxGameID_4; + public sealed override GameVersion MaxGameID => Legal.MaxGameID_4; public sealed override int MaxIV => 31; public sealed override int MaxEV => EffortValues.Max255; public sealed override int MaxStringLengthOT => 7; @@ -26,7 +27,7 @@ public abstract class G4PKM : PKM, public sealed override uint TSV => (uint)(TID16 ^ SID16) >> 3; protected bool PtHGSS => Pt || HGSS; - protected internal abstract uint IV32 { get; set; } + public abstract uint IV32 { get; set; } public override int Characteristic => EntityCharacteristic.GetCharacteristic(PID, IV32); public abstract ushort Sanity { get; set; } @@ -37,16 +38,17 @@ public abstract class G4PKM : PKM, protected virtual ushort CalculateChecksum() => Checksums.Add16(Data.AsSpan()[8..PokeCrypto.SIZE_4STORED]); // Trash Bytes - public sealed override Span Nickname_Trash => Data.AsSpan(0x48, 22); - public sealed override Span OT_Trash => Data.AsSpan(0x68, 16); + public sealed override Span NicknameTrash => Data.AsSpan(0x48, 22); + public sealed override Span OriginalTrainerTrash => Data.AsSpan(0x68, 16); // Future Attributes public sealed override uint EncryptionConstant { get => PID; set { } } - public sealed override int Nature { get => (int)(PID % 25); set { } } - public sealed override int CurrentFriendship { get => OT_Friendship; set => OT_Friendship = value; } - public sealed override int CurrentHandler { get => 0; set { } } + public sealed override Nature Nature { get => (Nature)(PID % 25); set { } } + public sealed override byte CurrentFriendship { get => OriginalTrainerFriendship; set => OriginalTrainerFriendship = value; } + public sealed override byte CurrentHandler { get => 0; set { } } public sealed override int AbilityNumber { get => 1 << PIDAbility; set { } } + public abstract byte PokerusState { get; set; } public abstract int ShinyLeaf { get; set; } #region Ribbons @@ -151,12 +153,12 @@ public abstract class G4PKM : PKM, public abstract bool RIBB_7 { get; set; } #endregion - public abstract byte CNT_Cool { get; set; } - public abstract byte CNT_Beauty { get; set; } - public abstract byte CNT_Cute { get; set; } - public abstract byte CNT_Smart { get; set; } - public abstract byte CNT_Tough { get; set; } - public abstract byte CNT_Sheen { get; set; } + public abstract byte ContestCool { get; set; } + public abstract byte ContestBeauty { get; set; } + public abstract byte ContestCute { get; set; } + public abstract byte ContestSmart { get; set; } + public abstract byte ContestTough { get; set; } + public abstract byte ContestSheen { get; set; } public abstract GroundTileType GroundTile { get; set; } public abstract byte BallDPPt { get; set; } @@ -186,72 +188,72 @@ public void SetMarking(int index, bool value) public bool MarkingStar { get => GetMarking(4); set => SetMarking(4, value); } public bool MarkingDiamond { get => GetMarking(5); set => SetMarking(5, value); } - public abstract ushort Egg_LocationDP { get; set; } - public abstract ushort Egg_LocationExtended { get; set; } - public abstract ushort Met_LocationDP { get; set; } - public abstract ushort Met_LocationExtended { get; set; } + public abstract ushort EggLocationDP { get; set; } + public abstract ushort EggLocationExtended { get; set; } + public abstract ushort MetLocationDP { get; set; } + public abstract ushort MetLocationExtended { get; set; } - public sealed override int Egg_Location + public sealed override ushort EggLocation { get { - ushort hgssloc = Egg_LocationExtended; + ushort hgssloc = EggLocationExtended; if (hgssloc != 0) return hgssloc; - return Egg_LocationDP; + return EggLocationDP; } set { if (value == 0) { - Egg_LocationDP = Egg_LocationExtended = 0; + EggLocationDP = EggLocationExtended = 0; } else if (Locations.IsPtHGSSLocation(value) || Locations.IsPtHGSSLocationEgg(value)) { // Met location not in DP, set to Faraway Place - Egg_LocationDP = Locations.Faraway4; - Egg_LocationExtended = (ushort)value; + EggLocationDP = Locations.Faraway4; + EggLocationExtended = value; } else { int pthgss = PtHGSS ? value : 0; // only set to PtHGSS loc if encountered in game - Egg_LocationDP = (ushort)value; - Egg_LocationExtended = (ushort)pthgss; + EggLocationDP = value; + EggLocationExtended = (ushort)pthgss; } } } - public sealed override int Met_Location + public sealed override ushort MetLocation { get { - ushort hgssloc = Met_LocationExtended; + ushort hgssloc = MetLocationExtended; if (hgssloc != 0) return hgssloc; - return Met_LocationDP; + return MetLocationDP; } set { if (value == 0) { - Met_LocationDP = Met_LocationExtended = 0; + MetLocationDP = MetLocationExtended = 0; } else if (Locations.IsPtHGSSLocation(value) || Locations.IsPtHGSSLocationEgg(value)) { // Met location not in DP, set to Faraway Place - Met_LocationDP = Locations.Faraway4; - Met_LocationExtended = (ushort)value; + MetLocationDP = Locations.Faraway4; + MetLocationExtended = value; } else { int pthgss = PtHGSS ? value : 0; // only set to PtHGSS loc if encountered in game - Met_LocationDP = (ushort)value; - Met_LocationExtended = (ushort)pthgss; + MetLocationDP = value; + MetLocationExtended = (ushort)pthgss; } } } - public sealed override int Ball + public sealed override byte Ball { // HG/SS added new ball IDs mid-generation, and the previous Gen4 games couldn't handle invalid ball values. // Pokémon obtained in HG/SS have the HG/SS ball value set (@0x86) to the capture ball. @@ -280,7 +282,7 @@ public sealed override int Ball public bool Trade(string SAV_Trainer, uint savID32, int SAV_GENDER, int Day = 1, int Month = 1, int Year = 2009) { // Eggs do not have any modifications done if they are traded - if (IsEgg && !(SAV_Trainer == OT_Name && savID32 == ID32 && SAV_GENDER == OT_Gender)) + if (IsEgg && !(SAV_Trainer == OriginalTrainerName && savID32 == ID32 && SAV_GENDER == OriginalTrainerGender)) { SetLinkTradeEgg(Day, Month, Year, Locations.LinkTrade4); return true; @@ -307,13 +309,13 @@ protected T ConvertTo() where T : G4PKM, new() TID16 = TID16, SID16 = SID16, EXP = EXP, - OT_Friendship = OT_Friendship, + OriginalTrainerFriendship = OriginalTrainerFriendship, Ability = Ability, Language = Language, IsEgg = IsEgg, IsNicknamed = IsNicknamed, - OT_Gender = OT_Gender, + OriginalTrainerGender = OriginalTrainerGender, IV_HP = IV_HP, IV_ATK = IV_ATK, @@ -327,12 +329,12 @@ protected T ConvertTo() where T : G4PKM, new() EV_SPE = EV_SPE, EV_SPA = EV_SPA, EV_SPD = EV_SPD, - CNT_Cool = CNT_Cool, - CNT_Beauty = CNT_Beauty, - CNT_Cute = CNT_Cute, - CNT_Smart = CNT_Smart, - CNT_Tough = CNT_Tough, - CNT_Sheen = CNT_Sheen, + ContestCool = ContestCool, + ContestBeauty = ContestBeauty, + ContestCute = ContestCute, + ContestSmart = ContestSmart, + ContestTough = ContestTough, + ContestSheen = ContestSheen, Move1 = Move1, Move2 = Move2, @@ -351,24 +353,24 @@ protected T ConvertTo() where T : G4PKM, new() Form = Form, ShinyLeaf = ShinyLeaf, Version = Version, - PKRS_Days = PKRS_Days, - PKRS_Strain = PKRS_Strain, + PokerusDays = PokerusDays, + PokerusStrain = PokerusStrain, BallDPPt = BallDPPt, BallHGSS = BallHGSS, GroundTile = GroundTile, PokeathlonStat = PokeathlonStat, FatefulEncounter = FatefulEncounter, - Met_Level = Met_Level, - Met_Location = Met_Location, - Met_Year = Met_Year, - Met_Month = Met_Month, - Met_Day = Met_Day, + MetLevel = MetLevel, + MetLocation = MetLocation, + MetYear = MetYear, + MetMonth = MetMonth, + MetDay = MetDay, - Egg_Location = Egg_Location, - Egg_Year = Egg_Year, - Egg_Month = Egg_Month, - Egg_Day = Egg_Day, + EggLocation = EggLocation, + EggYear = EggYear, + EggMonth = EggMonth, + EggDay = EggDay, #region Ribbons RibbonChampionSinnoh = RibbonChampionSinnoh, @@ -471,16 +473,16 @@ protected T ConvertTo() where T : G4PKM, new() }; // Transfer Trash Bytes - for (int i = 0; i < 11; i++) // Nickname - { - pk.Data[0x48 + (2 * i)] = Data[0x48 + (2 * i) + 1]; - pk.Data[0x48 + (2 * i) + 1] = Data[0x48 + (2 * i)]; - } - for (int i = 0; i < 8; i++) // OT_Name - { - pk.Data[0x68 + (2 * i)] = Data[0x68 + (2 * i) + 1]; - pk.Data[0x68 + (2 * i) + 1] = Data[0x68 + (2 * i)]; - } + TransferTrashSwap(NicknameTrash, pk.NicknameTrash); + TransferTrashSwap(OriginalTrainerTrash, pk.OriginalTrainerTrash); return pk; } + + private static void TransferTrashSwap(ReadOnlySpan src, Span dest) + { + // Strings need to change between Little Endian and Big Endian + var s = MemoryMarshal.Cast(src); + var d = MemoryMarshal.Cast(dest); + System.Buffers.Binary.BinaryPrimitives.ReverseEndianness(s, d); + } } diff --git a/PKHeX.Core/PKM/Shared/G6PKM.cs b/PKHeX.Core/PKM/Shared/G6PKM.cs index 409bbc21f..fe8f7bce8 100644 --- a/PKHeX.Core/PKM/Shared/G6PKM.cs +++ b/PKHeX.Core/PKM/Shared/G6PKM.cs @@ -12,9 +12,9 @@ public abstract class G6PKM : PKM, ISanityChecksum protected G6PKM([ConstantExpected] int size) : base(size) { } // Trash Bytes - public sealed override Span Nickname_Trash => Data.AsSpan(0x40, 26); - public sealed override Span HT_Trash => Data.AsSpan(0x78, 26); - public sealed override Span OT_Trash => Data.AsSpan(0xB0, 26); + public sealed override Span NicknameTrash => Data.AsSpan(0x40, 26); + public sealed override Span HandlingTrainerTrash => Data.AsSpan(0x78, 26); + public sealed override Span OriginalTrainerTrash => Data.AsSpan(0xB0, 26); public abstract ushort Sanity { get; set; } public abstract ushort Checksum { get; set; } @@ -25,24 +25,24 @@ public abstract class G6PKM : PKM, ISanityChecksum private ushort CalculateChecksum() => Checksums.Add16(Data.AsSpan()[8..PokeCrypto.SIZE_6STORED]); // Simple Generated Attributes - public sealed override int CurrentFriendship + public sealed override byte CurrentFriendship { - get => CurrentHandler == 0 ? OT_Friendship : HT_Friendship; - set { if (CurrentHandler == 0) OT_Friendship = value; else HT_Friendship = value; } + get => CurrentHandler == 0 ? OriginalTrainerFriendship : HandlingTrainerFriendship; + set { if (CurrentHandler == 0) OriginalTrainerFriendship = value; else HandlingTrainerFriendship = value; } } - public int OppositeFriendship + public byte OppositeFriendship { - get => CurrentHandler == 1 ? OT_Friendship : HT_Friendship; - set { if (CurrentHandler == 1) OT_Friendship = value; else HT_Friendship = value; } + get => CurrentHandler == 1 ? OriginalTrainerFriendship : HandlingTrainerFriendship; + set { if (CurrentHandler == 1) OriginalTrainerFriendship = value; else HandlingTrainerFriendship = value; } } public sealed override uint PSV => ((PID >> 16) ^ (PID & 0xFFFF)) >> 4; public sealed override uint TSV => (uint)(TID16 ^ SID16) >> 4; - public sealed override bool IsUntraded => Data[0x78] == 0 && Data[0x78 + 1] == 0 && Format == Generation; // immediately terminated HT_Name data (\0) + public sealed override bool IsUntraded => Data[0x78] == 0 && Data[0x78 + 1] == 0 && Format == Generation; // immediately terminated HandlingTrainerName data (\0) // Complex Generated Attributes - protected abstract uint IV32 { get; set; } + public abstract uint IV32 { get; set; } public override int Characteristic => EntityCharacteristic.GetCharacteristic(EncryptionConstant, IV32); // Methods @@ -85,7 +85,7 @@ public void Trade(ITrainerInfo tr, int Day = 1, int Month = 1, int Year = 2015) { // Eggs do not have any modifications done if they are traded // Apply link trade data, only if it left the OT (ignore if dumped & imported, or cloned, etc.) - if ((tr.TID16 != TID16) || (tr.SID16 != SID16) || (tr.Gender != OT_Gender) || (tr.OT != OT_Name)) + if ((tr.TID16 != TID16) || (tr.SID16 != SID16) || (tr.Gender != OriginalTrainerGender) || (tr.OT != OriginalTrainerName)) SetLinkTradeEgg(Day, Month, Year, Locations.LinkTrade6); return; } diff --git a/PKHeX.Core/PKM/Shared/G8PKM.cs b/PKHeX.Core/PKM/Shared/G8PKM.cs index 774ee2b09..fc05d7265 100644 --- a/PKHeX.Core/PKM/Shared/G8PKM.cs +++ b/PKHeX.Core/PKM/Shared/G8PKM.cs @@ -24,10 +24,10 @@ private static byte[] DecryptParty(byte[] data) // Simple Generated Attributes public abstract IPermitRecord Permit { get; } // PersonalInfo derived metadata - public override int CurrentFriendship + public override byte CurrentFriendship { - get => CurrentHandler == 0 ? OT_Friendship : HT_Friendship; - set { if (CurrentHandler == 0) OT_Friendship = value; else HT_Friendship = value; } + get => CurrentHandler == 0 ? OriginalTrainerFriendship : HandlingTrainerFriendship; + set { if (CurrentHandler == 0) OriginalTrainerFriendship = value; else HandlingTrainerFriendship = value; } } public override int SIZE_PARTY => PokeCrypto.SIZE_8PARTY; @@ -38,9 +38,9 @@ public override int CurrentFriendship public sealed override bool Valid { get => Sanity == 0 && ChecksumValid; set { if (!value) return; Sanity = 0; RefreshChecksum(); } } // Trash Bytes - public override Span Nickname_Trash => Data.AsSpan(0x58, 26); - public override Span HT_Trash => Data.AsSpan(0xA8, 26); - public override Span OT_Trash => Data.AsSpan(0xF8, 26); + public override Span NicknameTrash => Data.AsSpan(0x58, 26); + public override Span HandlingTrainerTrash => Data.AsSpan(0xA8, 26); + public override Span OriginalTrainerTrash => Data.AsSpan(0xF8, 26); // Maximums public override int MaxIV => 31; @@ -50,7 +50,7 @@ public override int CurrentFriendship public override uint PSV => ((PID >> 16) ^ (PID & 0xFFFF)) >> 4; public override uint TSV => (uint)(TID16 ^ SID16) >> 4; - public override bool IsUntraded => Data[0xA8] == 0 && Data[0xA8 + 1] == 0 && Format == Generation; // immediately terminated HT_Name data (\0) + public override bool IsUntraded => Data[0xA8] == 0 && Data[0xA8 + 1] == 0 && Format == Generation; // immediately terminated HandlingTrainerName data (\0) // Complex Generated Attributes public override int Characteristic => EntityCharacteristic.GetCharacteristic(EncryptionConstant, IV32); @@ -108,11 +108,11 @@ public void FixRelearn() // 0x1A alignment unused // 0x1B alignment unused public override uint PID { get => ReadUInt32LittleEndian(Data.AsSpan(0x1C)); set => WriteUInt32LittleEndian(Data.AsSpan(0x1C), value); } - public override int Nature { get => Data[0x20]; set => Data[0x20] = (byte)value; } - public override int StatNature { get => Data[0x21]; set => Data[0x21] = (byte)value; } + public override Nature Nature { get => (Nature)Data[0x20]; set => Data[0x20] = (byte)value; } + public override Nature StatNature { get => (Nature)Data[0x21]; set => Data[0x21] = (byte)value; } public override bool FatefulEncounter { get => (Data[0x22] & 1) == 1; set => Data[0x22] = (byte)((Data[0x22] & ~0x01) | (value ? 1 : 0)); } public bool Flag2 { get => (Data[0x22] & 2) == 2; set => Data[0x22] = (byte)((Data[0x22] & ~0x02) | (value ? 2 : 0)); } - public override int Gender { get => (Data[0x22] >> 2) & 0x3; set => Data[0x22] = (byte)((Data[0x22] & 0xF3) | (value << 2)); } + public override byte Gender { get => (byte)((Data[0x22] >> 2) & 0x3); set => Data[0x22] = (byte)((Data[0x22] & 0xF3) | (value << 2)); } // 0x23 alignment unused public override byte Form { get => Data[0x24]; set => WriteUInt16LittleEndian(Data.AsSpan(0x24), value); } @@ -122,15 +122,15 @@ public void FixRelearn() public override int EV_SPE { get => Data[0x29]; set => Data[0x29] = (byte)value; } public override int EV_SPA { get => Data[0x2A]; set => Data[0x2A] = (byte)value; } public override int EV_SPD { get => Data[0x2B]; set => Data[0x2B] = (byte)value; } - public byte CNT_Cool { get => Data[0x2C]; set => Data[0x2C] = value; } - public byte CNT_Beauty { get => Data[0x2D]; set => Data[0x2D] = value; } - public byte CNT_Cute { get => Data[0x2E]; set => Data[0x2E] = value; } - public byte CNT_Smart { get => Data[0x2F]; set => Data[0x2F] = value; } - public byte CNT_Tough { get => Data[0x30]; set => Data[0x30] = value; } - public byte CNT_Sheen { get => Data[0x31]; set => Data[0x31] = value; } - public byte PKRS { get => Data[0x32]; set => Data[0x32] = value; } - public override int PKRS_Days { get => PKRS & 0xF; set => PKRS = (byte)((PKRS & ~0xF) | value); } - public override int PKRS_Strain { get => PKRS >> 4; set => PKRS = (byte)((PKRS & 0xF) | (value << 4)); } + public byte ContestCool { get => Data[0x2C]; set => Data[0x2C] = value; } + public byte ContestBeauty { get => Data[0x2D]; set => Data[0x2D] = value; } + public byte ContestCute { get => Data[0x2E]; set => Data[0x2E] = value; } + public byte ContestSmart { get => Data[0x2F]; set => Data[0x2F] = value; } + public byte ContestTough { get => Data[0x30]; set => Data[0x30] = value; } + public byte ContestSheen { get => Data[0x31]; set => Data[0x31] = value; } + public byte PokerusState { get => Data[0x32]; set => Data[0x32] = value; } + public override int PokerusDays { get => PokerusState & 0xF; set => PokerusState = (byte)((PokerusState & ~0xF) | value); } + public override int PokerusStrain { get => PokerusState >> 4; set => PokerusState = (byte)((PokerusState & 0xF) | (value << 4)); } // 0x33 unused padding // ribbon u32 @@ -309,8 +309,8 @@ public void FixRelearn() #region Block B public override string Nickname { - get => StringConverter8.GetString(Nickname_Trash); - set => StringConverter8.SetString(Nickname_Trash, value, 12, StringConverterOption.None); + get => StringConverter8.GetString(NicknameTrash); + set => StringConverter8.SetString(NicknameTrash, value, 12, StringConverterOption.None); } // 2 bytes for \0, automatically handled above @@ -336,7 +336,7 @@ public override string Nickname public override int Stat_HPCurrent { get => ReadUInt16LittleEndian(Data.AsSpan(0x8A)); set => WriteUInt16LittleEndian(Data.AsSpan(0x8A), (ushort)value); } - private uint IV32 { get => ReadUInt32LittleEndian(Data.AsSpan(0x8C)); set => WriteUInt32LittleEndian(Data.AsSpan(0x8C), value); } + public uint IV32 { get => ReadUInt32LittleEndian(Data.AsSpan(0x8C)); set => WriteUInt32LittleEndian(Data.AsSpan(0x8C), value); } public override int IV_HP { get => (int)(IV32 >> 00) & 0x1F; set => IV32 = (IV32 & ~(0x1Fu << 00)) | ((value > 31 ? 31u : (uint)value) << 00); } public override int IV_ATK { get => (int)(IV32 >> 05) & 0x1F; set => IV32 = (IV32 & ~(0x1Fu << 05)) | ((value > 31 ? 31u : (uint)value) << 05); } public override int IV_DEF { get => (int)(IV32 >> 10) & 0x1F; set => IV32 = (IV32 & ~(0x1Fu << 10)) | ((value > 31 ? 31u : (uint)value) << 10); } @@ -357,22 +357,22 @@ public override string Nickname #endregion #region Block C - public override string HT_Name + public override string HandlingTrainerName { - get => StringConverter8.GetString(HT_Trash); - set => StringConverter8.SetString(HT_Trash, value, 12, StringConverterOption.None); + get => StringConverter8.GetString(HandlingTrainerTrash); + set => StringConverter8.SetString(HandlingTrainerTrash, value, 12, StringConverterOption.None); } - public override int HT_Gender { get => Data[0xC2]; set => Data[0xC2] = (byte)value; } - public byte HT_Language { get => Data[0xC3]; set => Data[0xC3] = value; } - public override int CurrentHandler { get => Data[0xC4]; set => Data[0xC4] = (byte)value; } + public override byte HandlingTrainerGender { get => Data[0xC2]; set => Data[0xC2] = value; } + public byte HandlingTrainerLanguage { get => Data[0xC3]; set => Data[0xC3] = value; } + public override byte CurrentHandler { get => Data[0xC4]; set => Data[0xC4] = value; } // 0xC5 unused (alignment) - public int HT_TrainerID { get => ReadUInt16LittleEndian(Data.AsSpan(0xC6)); set => WriteUInt16LittleEndian(Data.AsSpan(0xC6), (ushort)value); } // unused? - public override int HT_Friendship { get => Data[0xC8]; set => Data[0xC8] = (byte)value; } - public byte HT_Intensity { get => Data[0xC9]; set => Data[0xC9] = value; } - public byte HT_Memory { get => Data[0xCA]; set => Data[0xCA] = value; } - public byte HT_Feeling { get => Data[0xCB]; set => Data[0xCB] = value; } - public ushort HT_TextVar { get => ReadUInt16LittleEndian(Data.AsSpan(0xCC)); set => WriteUInt16LittleEndian(Data.AsSpan(0xCC), value); } + public ushort HandlingTrainerID { get => ReadUInt16LittleEndian(Data.AsSpan(0xC6)); set => WriteUInt16LittleEndian(Data.AsSpan(0xC6), value); } // unused? + public override byte HandlingTrainerFriendship { get => Data[0xC8]; set => Data[0xC8] = value; } + public byte HandlingTrainerMemoryIntensity { get => Data[0xC9]; set => Data[0xC9] = value; } + public byte HandlingTrainerMemory { get => Data[0xCA]; set => Data[0xCA] = value; } + public byte HandlingTrainerMemoryFeeling { get => Data[0xCB]; set => Data[0xCB] = value; } + public ushort HandlingTrainerMemoryVariable { get => ReadUInt16LittleEndian(Data.AsSpan(0xCC)); set => WriteUInt16LittleEndian(Data.AsSpan(0xCC), value); } public Span PokeJob => Data.AsSpan(0xCE, 14); public bool GetPokeJobFlag(int index) => FlagUtil.GetFlag(PokeJob, index >> 3, index & 7); @@ -382,8 +382,8 @@ public override string HT_Name public override byte Fullness { get => Data[0xDC]; set => Data[0xDC] = value; } public override byte Enjoyment { get => Data[0xDD]; set => Data[0xDD] = value; } - public override int Version { get => Data[0xDE]; set => Data[0xDE] = (byte)value; } - public byte BattleVersion { get => Data[0xDF]; set => Data[0xDF] = value; } + public override GameVersion Version { get => (GameVersion)Data[0xDE]; set => Data[0xDE] = (byte)value; } + public GameVersion BattleVersion { get => (GameVersion)Data[0xDF]; set => Data[0xDF] = (byte)value; } // public override byte Region { get => Data[0xE0]; set => Data[0xE0] = (byte)value; } // public override byte ConsoleRegion { get => Data[0xE1]; set => Data[0xE1] = (byte)value; } public override int Language { get => Data[0xE2]; set => Data[0xE2] = (byte)value; } @@ -397,30 +397,30 @@ public override string HT_Name #endregion #region Block D - public override string OT_Name + public override string OriginalTrainerName { - get => StringConverter8.GetString(OT_Trash); - set => StringConverter8.SetString(OT_Trash, value, 12, StringConverterOption.None); + get => StringConverter8.GetString(OriginalTrainerTrash); + set => StringConverter8.SetString(OriginalTrainerTrash, value, 12, StringConverterOption.None); } - public override int OT_Friendship { get => Data[0x112]; set => Data[0x112] = (byte)value; } - public byte OT_Intensity { get => Data[0x113]; set => Data[0x113] = value; } - public byte OT_Memory { get => Data[0x114]; set => Data[0x114] = value; } + public override byte OriginalTrainerFriendship { get => Data[0x112]; set => Data[0x112] = value; } + public byte OriginalTrainerMemoryIntensity { get => Data[0x113]; set => Data[0x113] = value; } + public byte OriginalTrainerMemory { get => Data[0x114]; set => Data[0x114] = value; } // 0x115 unused align - public ushort OT_TextVar { get => ReadUInt16LittleEndian(Data.AsSpan(0x116)); set => WriteUInt16LittleEndian(Data.AsSpan(0x116), value); } - public byte OT_Feeling { get => Data[0x118]; set => Data[0x118] = value; } - public override int Egg_Year { get => Data[0x119]; set => Data[0x119] = (byte)value; } - public override int Egg_Month { get => Data[0x11A]; set => Data[0x11A] = (byte)value; } - public override int Egg_Day { get => Data[0x11B]; set => Data[0x11B] = (byte)value; } - public override int Met_Year { get => Data[0x11C]; set => Data[0x11C] = (byte)value; } - public override int Met_Month { get => Data[0x11D]; set => Data[0x11D] = (byte)value; } - public override int Met_Day { get => Data[0x11E]; set => Data[0x11E] = (byte)value; } + public ushort OriginalTrainerMemoryVariable { get => ReadUInt16LittleEndian(Data.AsSpan(0x116)); set => WriteUInt16LittleEndian(Data.AsSpan(0x116), value); } + public byte OriginalTrainerMemoryFeeling { get => Data[0x118]; set => Data[0x118] = value; } + public override byte EggYear { get => Data[0x119]; set => Data[0x119] = value; } + public override byte EggMonth { get => Data[0x11A]; set => Data[0x11A] = value; } + public override byte EggDay { get => Data[0x11B]; set => Data[0x11B] = value; } + public override byte MetYear { get => Data[0x11C]; set => Data[0x11C] = value; } + public override byte MetMonth { get => Data[0x11D]; set => Data[0x11D] = value; } + public override byte MetDay { get => Data[0x11E]; set => Data[0x11E] = value; } // 0x11F unused align - public override int Egg_Location { get => ReadUInt16LittleEndian(Data.AsSpan(0x120)); set => WriteUInt16LittleEndian(Data.AsSpan(0x120), (ushort)value); } - public override int Met_Location { get => ReadUInt16LittleEndian(Data.AsSpan(0x122)); set => WriteUInt16LittleEndian(Data.AsSpan(0x122), (ushort)value); } - public override int Ball { get => Data[0x124]; set => Data[0x124] = (byte)value; } - public override int Met_Level { get => Data[0x125] & ~0x80; set => Data[0x125] = (byte)((Data[0x125] & 0x80) | value); } - public override int OT_Gender { get => Data[0x125] >> 7; set => Data[0x125] = (byte)((Data[0x125] & ~0x80) | (value << 7)); } + public override ushort EggLocation { get => ReadUInt16LittleEndian(Data.AsSpan(0x120)); set => WriteUInt16LittleEndian(Data.AsSpan(0x120), value); } + public override ushort MetLocation { get => ReadUInt16LittleEndian(Data.AsSpan(0x122)); set => WriteUInt16LittleEndian(Data.AsSpan(0x122), value); } + public override byte Ball { get => Data[0x124]; set => Data[0x124] = value; } + public override byte MetLevel { get => (byte)(Data[0x125] & ~0x80); set => Data[0x125] = (byte)((Data[0x125] & 0x80) | value); } + public override byte OriginalTrainerGender { get => (byte)(Data[0x125] >> 7); set => Data[0x125] = (byte)((Data[0x125] & ~0x80) | (value << 7)); } public byte HyperTrainFlags { get => Data[0x126]; set => Data[0x126] = value; } public bool HT_HP { get => ((HyperTrainFlags >> 0) & 1) == 1; set => HyperTrainFlags = (byte)((HyperTrainFlags & ~(1 << 0)) | ((value ? 1 : 0) << 0)); } public bool HT_ATK { get => ((HyperTrainFlags >> 1) & 1) == 1; set => HyperTrainFlags = (byte)((HyperTrainFlags & ~(1 << 1)) | ((value ? 1 : 0) << 1)); } @@ -444,7 +444,7 @@ public ulong Tracker #endregion #region Battle Stats - public override int Stat_Level { get => Data[0x148]; set => Data[0x148] = (byte)value; } + public override byte Stat_Level { get => Data[0x148]; set => Data[0x148] = value; } // 0x149 unused alignment public override int Stat_HPMax { get => ReadUInt16LittleEndian(Data.AsSpan(0x14A)); set => WriteUInt16LittleEndian(Data.AsSpan(0x14A), (ushort)value); } public override int Stat_ATK { get => ReadUInt16LittleEndian(Data.AsSpan(0x14C)); set => WriteUInt16LittleEndian(Data.AsSpan(0x14C), (ushort)value); } diff --git a/PKHeX.Core/PKM/Shared/GBPKM.cs b/PKHeX.Core/PKM/Shared/GBPKM.cs index c14f77b0c..ba520a7ff 100644 --- a/PKHeX.Core/PKM/Shared/GBPKM.cs +++ b/PKHeX.Core/PKM/Shared/GBPKM.cs @@ -13,8 +13,8 @@ namespace PKHeX.Core; public abstract class GBPKM : PKM { public sealed override int MaxBallID => -1; - public sealed override int MinGameID => (int)GameVersion.RD; - public sealed override int MaxGameID => (int)GameVersion.C; + public sealed override GameVersion MinGameID => GameVersion.RD; + public sealed override GameVersion MaxGameID => GameVersion.C; public sealed override int MaxIV => 15; public sealed override int MaxEV => EffortValues.Max12; @@ -41,7 +41,7 @@ public sealed override bool IsNicknamed if (_isnicknamed is {} actual) return actual; - var current = Nickname_Trash; + var current = NicknameTrash; Span expect = stackalloc byte[current.Length]; var language = GuessedLanguage(); GetNonNickname(language, expect); @@ -74,7 +74,7 @@ public sealed override int Language return (int)LanguageID.Japanese; if (Korean) return (int)LanguageID.Korean; - if (StringConverter12.IsG12German(OT_Trash)) + if (StringConverter12.IsG12German(OriginalTrainerTrash)) return (int)LanguageID.German; // german int lang = SpeciesName.GetSpeciesNameLanguage(Species, Nickname, Format); if (lang > 0) @@ -94,7 +94,7 @@ public sealed override int Language } } - public sealed override int Gender + public sealed override byte Gender { get { @@ -104,7 +104,7 @@ public sealed override int Gender PersonalInfo.RatioMagicGenderless => 2, PersonalInfo.RatioMagicFemale => 1, PersonalInfo.RatioMagicMale => 0, - _ => IV_ATK > gv >> 4 ? 0 : 1, + _ => IV_ATK > gv >> 4 ? (byte)0 : (byte)1, }; } set { } @@ -114,16 +114,16 @@ public sealed override int Gender public sealed override bool IsGenderValid() => true; // not a separate property, derived via IVs public sealed override uint EncryptionConstant { get => 0; set { } } public sealed override uint PID { get => 0; set { } } - public sealed override int Nature { get => 0; set { } } + public sealed override Nature Nature { get => 0; set { } } public sealed override bool ChecksumValid => true; public sealed override bool FatefulEncounter { get => false; set { } } public sealed override uint TSV => 0x0000; public sealed override uint PSV => 0xFFFF; public sealed override int Characteristic => -1; public sealed override int Ability { get => -1; set { } } - public sealed override int CurrentHandler { get => 0; set { } } - public sealed override int Egg_Location { get => 0; set { } } - public sealed override int Ball { get => 0; set { } } + public sealed override byte CurrentHandler { get => 0; set { } } + public sealed override ushort EggLocation { get => 0; set { } } + public sealed override byte Ball { get => 0; set { } } public sealed override uint ID32 { get => TID16; set => TID16 = (ushort)value; } public sealed override ushort SID16 { get => 0; set { } } #endregion @@ -253,7 +253,7 @@ public sealed override void SetShiny() internal void ImportFromFuture(PKM pk) { Nickname = pk.Nickname; - OT_Name = pk.OT_Name; + OriginalTrainerName = pk.OriginalTrainerName; IV_ATK = pk.IV_ATK / 2; IV_DEF = pk.IV_DEF / 2; IV_SPC = pk.IV_SPA / 2; diff --git a/PKHeX.Core/PKM/Shared/GBPKML.cs b/PKHeX.Core/PKM/Shared/GBPKML.cs index 1ce3a2493..56b52974a 100644 --- a/PKHeX.Core/PKM/Shared/GBPKML.cs +++ b/PKHeX.Core/PKM/Shared/GBPKML.cs @@ -6,7 +6,7 @@ namespace PKHeX.Core; /// /// Mainline format for Generation 1 & 2 objects. /// -/// This format stores and in buffers separate from the rest of the details. +/// This format stores and in buffers separate from the rest of the details. public abstract class GBPKML : GBPKM { internal const int StringLengthJapanese = 6; @@ -19,8 +19,8 @@ public abstract class GBPKML : GBPKM private readonly byte[] RawNickname; // Trash Bytes - public sealed override Span Nickname_Trash => RawNickname; - public sealed override Span OT_Trash => RawOT; + public sealed override Span NicknameTrash => RawNickname; + public sealed override Span OriginalTrainerTrash => RawOT; protected GBPKML([ConstantExpected] int size, bool jp = false) : base(size) { @@ -29,8 +29,8 @@ protected GBPKML([ConstantExpected] int size, bool jp = false) : base(size) // initialize string buffers RawOT = new byte[strLen]; RawNickname = new byte[strLen]; - OT_Trash.Fill(StringConverter12.G1TerminatorCode); - Nickname_Trash.Fill(StringConverter12.G1TerminatorCode); + OriginalTrainerTrash.Fill(StringConverter12.G1TerminatorCode); + NicknameTrash.Fill(StringConverter12.G1TerminatorCode); } protected GBPKML(byte[] data, bool jp = false) : base(data) @@ -40,8 +40,8 @@ protected GBPKML(byte[] data, bool jp = false) : base(data) // initialize string buffers RawOT = new byte[strLen]; RawNickname = new byte[strLen]; - OT_Trash.Fill(StringConverter12.G1TerminatorCode); - Nickname_Trash.Fill(StringConverter12.G1TerminatorCode); + OriginalTrainerTrash.Fill(StringConverter12.G1TerminatorCode); + NicknameTrash.Fill(StringConverter12.G1TerminatorCode); } public override void SetNotNicknamed(int language) => GetNonNickname(language, RawNickname); @@ -77,24 +77,24 @@ private int SetString(ReadOnlySpan value, Span destBuffer, int maxLe public sealed override string Nickname { - get => GetString(Nickname_Trash); + get => GetString(NicknameTrash); set { if (!IsNicknamed && Nickname == value) return; - SetStringKeepTerminatorStyle(value, Nickname_Trash); + SetStringKeepTerminatorStyle(value, NicknameTrash); } } - public sealed override string OT_Name + public sealed override string OriginalTrainerName { - get => GetString(OT_Trash); + get => GetString(OriginalTrainerTrash); set { - if (value == OT_Name) + if (value == OriginalTrainerName) return; - SetStringKeepTerminatorStyle(value, OT_Trash); + SetStringKeepTerminatorStyle(value, OriginalTrainerTrash); } } diff --git a/PKHeX.Core/PKM/Shared/PokeList1.cs b/PKHeX.Core/PKM/Shared/PokeList1.cs index bd6b8b51e..6b1b75b1d 100644 --- a/PKHeX.Core/PKM/Shared/PokeList1.cs +++ b/PKHeX.Core/PKM/Shared/PokeList1.cs @@ -11,8 +11,8 @@ public sealed class PokeList1 : PokeListGB protected override PK1 GetEntry(byte[] dat, ReadOnlySpan otname, ReadOnlySpan nick, bool egg) { var result = new PK1(dat, Japanese); // no eggs - otname.CopyTo(result.OT_Trash); - nick.CopyTo(result.Nickname_Trash); + otname.CopyTo(result.OriginalTrainerTrash); + nick.CopyTo(result.NicknameTrash); return result; } diff --git a/PKHeX.Core/PKM/Shared/PokeList2.cs b/PKHeX.Core/PKM/Shared/PokeList2.cs index 5a21188a6..4ac866df0 100644 --- a/PKHeX.Core/PKM/Shared/PokeList2.cs +++ b/PKHeX.Core/PKM/Shared/PokeList2.cs @@ -11,8 +11,8 @@ public sealed class PokeList2 : PokeListGB protected override PK2 GetEntry(byte[] dat, ReadOnlySpan otname, ReadOnlySpan nick, bool egg) { var result = new PK2(dat, Japanese) { IsEgg = egg }; - otname.CopyTo(result.OT_Trash); - nick.CopyTo(result.Nickname_Trash); + otname.CopyTo(result.OriginalTrainerTrash); + nick.CopyTo(result.NicknameTrash); return result; } diff --git a/PKHeX.Core/PKM/Shared/PokeListGB.cs b/PKHeX.Core/PKM/Shared/PokeListGB.cs index 860f7d19f..69d75e913 100644 --- a/PKHeX.Core/PKM/Shared/PokeListGB.cs +++ b/PKHeX.Core/PKM/Shared/PokeListGB.cs @@ -22,7 +22,7 @@ public abstract class PokeListGB where T : GBPKML private readonly int StringLength; private readonly byte[] Data; private readonly byte Capacity; - private readonly int Entry_Size; + private readonly int EntrySize; protected readonly bool Japanese; public readonly T[] Pokemon; @@ -38,10 +38,10 @@ protected PokeListGB(byte[]? d, PokeListType c = PokeListType.Single, bool jp = { Japanese = jp; Capacity = (byte)c; - Entry_Size = GetEntrySize(); + EntrySize = GetEntrySize(); StringLength = GetStringLength(jp); byte[] data = d ?? GetEmptyList(c, jp); - var dataSize = 1 + 1 + (Capacity * (Entry_Size + 1 + (2 * StringLength))); + var dataSize = 1 + 1 + (Capacity * (EntrySize + 1 + (2 * StringLength))); Array.Resize(ref data, dataSize); Data = data; @@ -81,7 +81,7 @@ private byte[] GetEmptyList(PokeListType c, bool jp = false) return result; } - private int GetOffsetPKMData(int base_ofs, int index) => base_ofs + (Entry_Size * index); + private int GetOffsetPKMData(int base_ofs, int index) => base_ofs + (EntrySize * index); private int GetOffsetPKMOT(int base_ofs, int index) => GetOffsetPKMData(base_ofs, Capacity) + (StringLength * index); private int GetOffsetPKMNickname(int base_ofs, int index) => GetOffsetPKMOT(base_ofs, Capacity) + (StringLength * index); @@ -140,7 +140,7 @@ private T GetEntry(int base_ofs, int index) int otOfs = GetOffsetPKMOT(base_ofs, index); int nkOfs = GetOffsetPKMNickname(base_ofs, index); - var dat = Data.AsSpan(pkOfs, Entry_Size).ToArray(); + var dat = Data.AsSpan(pkOfs, EntrySize).ToArray(); var otname = Data.AsSpan(otOfs, StringLength); var nick = Data.AsSpan(nkOfs, StringLength); @@ -154,8 +154,8 @@ private void SetEntry(int base_ofs, int index) int nkOfs = GetOffsetPKMNickname(base_ofs, index); var pk = Pokemon[index]; - Array.Copy(pk.Data, 0, Data, pkOfs, Entry_Size); - pk.OT_Trash.CopyTo(Data.AsSpan(otOfs)); - pk.Nickname_Trash.CopyTo(Data.AsSpan(nkOfs)); + Array.Copy(pk.Data, 0, Data, pkOfs, EntrySize); + pk.OriginalTrainerTrash.CopyTo(Data.AsSpan(otOfs)); + pk.NicknameTrash.CopyTo(Data.AsSpan(nkOfs)); } } diff --git a/PKHeX.Core/PKM/Strings/StringConverter.cs b/PKHeX.Core/PKM/Strings/StringConverter.cs index d2b734af6..c1a1bd2c2 100644 --- a/PKHeX.Core/PKM/Strings/StringConverter.cs +++ b/PKHeX.Core/PKM/Strings/StringConverter.cs @@ -15,7 +15,7 @@ public static class StringConverter /// Encoding is Japanese /// Encoding is Big Endian /// Decoded string. - public static string GetString(ReadOnlySpan data, int generation, bool jp, bool isBigEndian = false) => generation switch + public static string GetString(ReadOnlySpan data, byte generation, bool jp, bool isBigEndian = false) => generation switch { 3 when isBigEndian => StringConverter3GC.GetString(data), 4 when isBigEndian => StringConverter4GC.GetString(data), @@ -40,7 +40,7 @@ public static class StringConverter /// Encoding is Japanese /// Encoding is Big Endian /// Decoded string. - public static int LoadString(ReadOnlySpan data, Span result, int generation, bool jp, bool isBigEndian = false) => generation switch + public static int LoadString(ReadOnlySpan data, Span result, byte generation, bool jp, bool isBigEndian = false) => generation switch { 3 when isBigEndian => StringConverter3GC.LoadString(data, result), 4 when isBigEndian => StringConverter4GC.LoadString(data, result), @@ -69,7 +69,7 @@ public static class StringConverter /// Language specific conversion (Chinese) /// Count of bytes written to the . public static int SetString(Span destBuffer, ReadOnlySpan value, int maxLength, StringConverterOption option, - int generation, bool jp, bool isBigEndian, int language = 0) => generation switch + byte generation, bool jp, bool isBigEndian, int language = 0) => generation switch { 3 when isBigEndian => StringConverter3GC.SetString(destBuffer, value, maxLength, option), 4 when isBigEndian => StringConverter4GC.SetString(destBuffer, value, maxLength, option), diff --git a/PKHeX.Core/PKM/Strings/StringConverter12Transporter.cs b/PKHeX.Core/PKM/Strings/StringConverter12Transporter.cs index 1db6f974f..39ab70647 100644 --- a/PKHeX.Core/PKM/Strings/StringConverter12Transporter.cs +++ b/PKHeX.Core/PKM/Strings/StringConverter12Transporter.cs @@ -161,9 +161,9 @@ private static bool IsAnyKataOnly(ReadOnlySpan chars) /// /// Language to localize with /// Version transferred from to Bank - public static string GetFilteredOT(int language, int version) => version switch + public static string GetFilteredOT(int language, GameVersion version) => version switch { - (int)GameVersion.RD => language switch + GameVersion.RD => language switch { 1 => "レッド.", 2 => "Red*", @@ -173,7 +173,7 @@ private static bool IsAnyKataOnly(ReadOnlySpan chars) 7 => "Rojo*", _ => string.Empty, }, - (int)GameVersion.GN => language switch + GameVersion.GN => language switch { 1 => "グリーン.", 2 => "Blue*", @@ -183,12 +183,12 @@ private static bool IsAnyKataOnly(ReadOnlySpan chars) 7 => "Azul*", _ => string.Empty, }, - (int)GameVersion.BU => language switch + GameVersion.BU => language switch { 1 => "ブルー.", _ => string.Empty, }, - (int)GameVersion.YW => language switch + GameVersion.YW => language switch { 1 => "イエロー.", 2 => "Yellow*", @@ -198,7 +198,7 @@ private static bool IsAnyKataOnly(ReadOnlySpan chars) 7 => "Amarillo*", _ => string.Empty, }, - (int)GameVersion.GD => language switch + GameVersion.GD => language switch { 1 => "ゴールド.", 2 => "Gold*", @@ -209,7 +209,7 @@ private static bool IsAnyKataOnly(ReadOnlySpan chars) 8 => "금.", _ => string.Empty, }, - (int)GameVersion.SI => language switch + GameVersion.SI => language switch { 1 => "シルバー.", 2 => "Silver*", @@ -220,7 +220,7 @@ private static bool IsAnyKataOnly(ReadOnlySpan chars) 8 => "은.", _ => string.Empty, }, - (int)GameVersion.C => language switch + GameVersion.C => language switch { 1 => "クリスタル.", 2 => "Crystal*", diff --git a/PKHeX.Core/PKM/Util/Conversion/EntityConverter.cs b/PKHeX.Core/PKM/Util/Conversion/EntityConverter.cs index 82d65eadc..f44f4ce39 100644 --- a/PKHeX.Core/PKM/Util/Conversion/EntityConverter.cs +++ b/PKHeX.Core/PKM/Util/Conversion/EntityConverter.cs @@ -57,7 +57,7 @@ public static GameVersion VirtualConsoleSourceGen2 /// /// /// True if it can be converted to the requested format value. - public static bool IsConvertibleToFormat(PKM pk, int format) + public static bool IsConvertibleToFormat(PKM pk, byte format) { if (pk.Format >= 3 && pk.Format > format && format < 8) return false; // pk3->upward can't go backwards until Gen8+ @@ -249,8 +249,8 @@ private static void MakeCompatible(PKM pk, IGameValueLimit limit) if (pk.Nickname.Length > limit.MaxStringLengthNickname) pk.Nickname = pk.Nickname[..pk.MaxStringLengthNickname]; - if (pk.OT_Name.Length > limit.MaxStringLengthOT) - pk.OT_Name = pk.OT_Name[..pk.MaxStringLengthOT]; + if (pk.OriginalTrainerName.Length > limit.MaxStringLengthOT) + pk.OriginalTrainerName = pk.OriginalTrainerName[..pk.MaxStringLengthOT]; if (pk.Move1 > limit.MaxMoveID || pk.Move2 > limit.MaxMoveID || pk.Move3 > limit.MaxMoveID || pk.Move4 > limit.MaxMoveID) pk.ClearInvalidMoves(); diff --git a/PKHeX.Core/PKM/Util/Conversion/FormConverter.cs b/PKHeX.Core/PKM/Util/Conversion/FormConverter.cs index e686b6352..af7026cec 100644 --- a/PKHeX.Core/PKM/Util/Conversion/FormConverter.cs +++ b/PKHeX.Core/PKM/Util/Conversion/FormConverter.cs @@ -22,7 +22,7 @@ public static class FormConverter /// A list of strings corresponding to the forms that a Pokémon can have. public static string[] GetFormList(ushort species, IReadOnlyList types, IReadOnlyList forms, IReadOnlyList genders, EntityContext context) { - int generation = context.Generation(); + byte generation = context.Generation(); // Mega List if (context.IsMegaGeneration() && IsFormListSingleMega(species)) @@ -52,7 +52,7 @@ public static string[] GetFormList(ushort species, IReadOnlyList types, private static string[] GetFormsGen1(ushort species, IReadOnlyList types, IReadOnlyList forms, EntityContext context) { - int generation = context.Generation(); + byte generation = context.Generation(); return (Species)species switch { Charizard or Mewtwo when context.IsMegaGeneration() => GetMegaXY(types, forms), @@ -74,7 +74,7 @@ private static string[] GetFormsGen1(ushort species, IReadOnlyList types private static string[] GetFormsGen2(ushort species, IReadOnlyList types, IReadOnlyList forms, EntityContext context) { - int generation = context.Generation(); + byte generation = context.Generation(); return (Species)species switch { Pichu when context is Gen4 => GetFormsPichu(types, forms), @@ -86,7 +86,7 @@ private static string[] GetFormsGen2(ushort species, IReadOnlyList types }; } - private static string[] GetFormsGen3(ushort species, IReadOnlyList types, IReadOnlyList forms, int generation) + private static string[] GetFormsGen3(ushort species, IReadOnlyList types, IReadOnlyList forms, byte generation) { return (Species)species switch { @@ -111,7 +111,7 @@ private static string[] GetFormsGen3(ushort species, IReadOnlyList types }; } - private static string[] GetFormsGen4(ushort species, IReadOnlyList types, IReadOnlyList forms, int generation) + private static string[] GetFormsGen4(ushort species, IReadOnlyList types, IReadOnlyList forms, byte generation) { return (Species)species switch { @@ -153,7 +153,7 @@ private static string[] GetFormsGen4(ushort species, IReadOnlyList types }; } - private static string[] GetFormsGen5(ushort species, IReadOnlyList types, IReadOnlyList forms, int generation) + private static string[] GetFormsGen5(ushort species, IReadOnlyList types, IReadOnlyList forms, byte generation) { return (Species)species switch { @@ -212,7 +212,7 @@ private static string[] GetFormsGen5(ushort species, IReadOnlyList types }; } - private static string[] GetFormsGen6(ushort species, IReadOnlyList types, IReadOnlyList forms, IReadOnlyList genders, int generation) + private static string[] GetFormsGen6(ushort species, IReadOnlyList types, IReadOnlyList forms, IReadOnlyList genders, byte generation) { return (Species)species switch { @@ -308,7 +308,7 @@ private static string[] GetFormsGen6(ushort species, IReadOnlyList types }; } - private static string[] GetFormsGen7(ushort species, IReadOnlyList types, IReadOnlyList forms, int generation) + private static string[] GetFormsGen7(ushort species, IReadOnlyList types, IReadOnlyList forms, byte generation) { return (Species)species switch { @@ -372,7 +372,7 @@ private static string[] GetFormsGen7(ushort species, IReadOnlyList types }; } - private static string[] GetFormsGen8(ushort species, int generation, IReadOnlyList types, IReadOnlyList forms, IReadOnlyList genders) + private static string[] GetFormsGen8(ushort species, byte generation, IReadOnlyList types, IReadOnlyList forms, IReadOnlyList genders) { return (Species)species switch { @@ -449,7 +449,7 @@ private static string[] GetFormsGen8(ushort species, int generation, IReadOnlyLi }; } - private static string[] GetFormsGen9(ushort species, int generation, IReadOnlyList types, IReadOnlyList forms, IReadOnlyList genders) + private static string[] GetFormsGen9(ushort species, byte generation, IReadOnlyList types, IReadOnlyList forms, IReadOnlyList genders) { return (Species)species switch { @@ -527,7 +527,7 @@ private static string[] GetFormsGen9(ushort species, int generation, IReadOnlyLi private static string[] GetFormsAlolan(EntityContext context, IReadOnlyList types, IReadOnlyList forms, ushort species) { - int generation = context.Generation(); + byte generation = context.Generation(); if (generation < 7) return EMPTY; @@ -559,7 +559,7 @@ or Exeggutor private static string[] GetFormsPikachu(EntityContext context, IReadOnlyList types, IReadOnlyList forms) { - int generation = context.Generation(); + byte generation = context.Generation(); return generation switch { 6 => [ @@ -617,7 +617,7 @@ private static string[] GetFormsPichu(IReadOnlyList types, IReadOnlyList ]; } - private static string[] GetFormsArceus(ushort species, int generation, IReadOnlyList types, IReadOnlyList forms) + private static string[] GetFormsArceus(ushort species, byte generation, IReadOnlyList types, IReadOnlyList forms) { return generation switch { @@ -727,7 +727,7 @@ private static string[] GetFormsArceus(ushort species, int generation, IReadOnly ], }; - private static string[] GetFormsUnown(int generation) => generation switch + private static string[] GetFormsUnown(byte generation) => generation switch { 2 => [ @@ -790,7 +790,7 @@ private static string[] GetFormsGalar(IReadOnlyList types, IReadOnlyList ]; } - private static string[] GetFormsHisui(ushort species, int generation, IReadOnlyList types, IReadOnlyList forms) => generation switch + private static string[] GetFormsHisui(ushort species, byte generation, IReadOnlyList types, IReadOnlyList forms) => generation switch { 8 => (Species)species switch { diff --git a/PKHeX.Core/PKM/Util/Conversion/IEntityRejuvenator.cs b/PKHeX.Core/PKM/Util/Conversion/IEntityRejuvenator.cs index d16ee7aca..bb11a3f4f 100644 --- a/PKHeX.Core/PKM/Util/Conversion/IEntityRejuvenator.cs +++ b/PKHeX.Core/PKM/Util/Conversion/IEntityRejuvenator.cs @@ -31,12 +31,12 @@ public void Rejuvenate(PKM result, PKM original) private static void ResetOutboundSWSH(PKM result, PK8 pk8) { - var ver = result.Version; - if (ver is (int)GameVersion.BD or (int)GameVersion.SP) + var version = result.Version; + if (version is GameVersion.BD or GameVersion.SP) RejuvenateBDSP(result, pk8); - else if (ver is (int)GameVersion.PLA) + else if (version is GameVersion.PLA) RejuvenatePLA(result, pk8); - else if (ver is (int)GameVersion.SL or (int)GameVersion.VL) + else if (version is GameVersion.SL or GameVersion.VL) RejuvenateSV(result, pk8); } @@ -65,7 +65,7 @@ private static void ResetSideways(PKM pk) // Try to restore original Tera type / override instead of HOME's double override to current Type1. TeraTypeUtil.ResetTeraType(pk9, la.EncounterMatch); } - else if (pk is PK8 pk8 && !LocationsHOME.IsLocationSWSH(pk8.Met_Location)) + else if (pk is PK8 pk8 && !LocationsHOME.IsLocationSWSH(pk8.MetLocation)) { // Gen8 and below (Gen6/7) need their original relearn moves // We can always set a Battle Version for non Gen8 origins, but most users won't be making stuff battle ready after. @@ -91,8 +91,8 @@ private static void RejuvenatePLA(PKM result, PK8 original) // No egg encounters. Always not-egg. { - result.Met_Location = enc.Location; - result.Egg_Location = 0; + result.MetLocation = enc.Location; + result.EggLocation = 0; } // Try again with rectified locations. @@ -109,9 +109,9 @@ private static void ResetBallPLA(PKM result, IEncounterable enc) if (result.Ball is >= (int)Ball.LAPoke and <= (int)Ball.LAOrigin) return; if (enc is IFixedBall { FixedBall: not Ball.None } f) - result.Ball = (int)f.FixedBall; + result.Ball = (byte)f.FixedBall; else - result.Ball = result.Species == (int)Species.Unown ? (int)Ball.LAJet : (int)Ball.LAPoke; + result.Ball = result.Species == (int)Species.Unown ? (byte)Ball.LAJet : (byte)Ball.LAPoke; } private static void ResetDataPLA(LegalityAnalysis la, IEncounterable enc, PA8 pa8) @@ -133,13 +133,13 @@ private static void RejuvenateBDSP(PKM result, PK8 original) if (enc is { EggEncounter: true }) { - result.Met_Location = Locations.HatchLocation8b; - result.Egg_Location = Locations.LinkTrade6NPC; + result.MetLocation = Locations.HatchLocation8b; + result.EggLocation = Locations.LinkTrade6NPC; } else { - result.Met_Location = enc.Location; - result.Egg_Location = Locations.Default8bNone; + result.MetLocation = enc.Location; + result.EggLocation = Locations.Default8bNone; } // Try again with rectified locations. @@ -156,13 +156,13 @@ private static void RejuvenateSV(PKM result, PK8 original) if (enc is { EggEncounter: true }) { - result.Met_Location = Locations.HatchLocation9; - result.Egg_Location = Locations.LinkTrade6NPC; + result.MetLocation = Locations.HatchLocation9; + result.EggLocation = Locations.LinkTrade6NPC; } else { - result.Met_Location = enc.Location; - result.Egg_Location = 0; + result.MetLocation = enc.Location; + result.EggLocation = 0; } // Try again with rectified locations. diff --git a/PKHeX.Core/PKM/Util/Conversion/ItemConverter.cs b/PKHeX.Core/PKM/Util/Conversion/ItemConverter.cs index e6c5a9486..68687c539 100644 --- a/PKHeX.Core/PKM/Util/Conversion/ItemConverter.cs +++ b/PKHeX.Core/PKM/Util/Conversion/ItemConverter.cs @@ -41,7 +41,9 @@ public static ushort GetItemOld3(ushort item) if (item == NaN) return 0; int index = Item3to4.IndexOf(item); - return (ushort)Math.Max(0, index); + if (index == -1) + return 0; + return (ushort)index; } /// @@ -54,7 +56,9 @@ public static byte GetItemOld2(ushort item) if (item == NaN) return 0; int index = Item2to4.IndexOf(item); - return (byte)Math.Max(0, index); + if (index == -1) + return 0; + return (byte)index; } #region Item Mapping Tables @@ -139,7 +143,7 @@ public static byte GetItemOld2(ushort item) ///
https://github.com/pret/pokecrystal/blob/edb624c20ceb50eef9d73a5df0ac041cc156dd32/engine/link/link.asm#L1093-L1115
///
https://github.com/pret/pokecrystal/blob/edb624c20ceb50eef9d73a5df0ac041cc156dd32/data/items/catch_rate_items.asm#L5-L17
/// - private static int GetTeruSamaItem(byte value) => value switch + private static byte GetTeruSamaItem(byte value) => value switch { 0x19 => 0x92, // Leftovers 0x2D => 0x53, // Bitter Berry @@ -153,7 +157,7 @@ public static byte GetItemOld2(ushort item) ///
/// Gen1 Item /// Gen2 Item - public static int GetItemFuture1(byte value) + public static byte GetItemFuture1(byte value) { if (!IsItemTransferable12(value)) return GetTeruSamaItem(value); @@ -208,7 +212,7 @@ public static int GetItemForFormat(int srcItem, EntityContext srcFormat, EntityC /// Item ID /// Generation the exists in /// True if is an HM - public static bool IsItemHM(ushort item, int generation) => generation switch + public static bool IsItemHM(ushort item, byte generation) => generation switch { 1 => item is (>= 196 and <= 200), 2 => item is (>= 243 and <= 249), diff --git a/PKHeX.Core/PKM/Util/EffortValues.cs b/PKHeX.Core/PKM/Util/EffortValues.cs index 022986299..f7a2e6cc8 100644 --- a/PKHeX.Core/PKM/Util/EffortValues.cs +++ b/PKHeX.Core/PKM/Util/EffortValues.cs @@ -19,13 +19,15 @@ public static class EffortValues public const ushort MaxEffective = 508; /// The leftover EVs if two stats are . public const byte LeftoverDual252 = 6; + /// Vitamin Max for consideration in Gen3 & Gen4. + public const ushort MaxVitamins34 = 100; /// /// Gets randomized EVs for a given generation format /// /// Array to store the resulting EVs /// Generation specific formatting option - public static void SetRandom(Span evs, int generation) + public static void SetRandom(Span evs, byte generation) { var rnd = Util.Rand; if (generation > 2) diff --git a/PKHeX.Core/PKM/Util/EntityBlank.cs b/PKHeX.Core/PKM/Util/EntityBlank.cs index caca0d4eb..7b5d87b14 100644 --- a/PKHeX.Core/PKM/Util/EntityBlank.cs +++ b/PKHeX.Core/PKM/Util/EntityBlank.cs @@ -44,12 +44,12 @@ public static PKM GetBlank(TypeInfo type) return x; } - public static PKM GetBlank(int gen, GameVersion ver) => gen switch + public static PKM GetBlank(byte gen, GameVersion version) => gen switch { - 1 when ver == GameVersion.BU => new PK1(true), - 7 when GameVersion.Gen7b.Contains(ver) => new PB7(), - 8 when GameVersion.BDSP.Contains(ver) => new PB8(), - 8 when GameVersion.PLA == ver => new PA8(), + 1 when version == GameVersion.BU => new PK1(true), + 7 when GameVersion.Gen7b.Contains(version) => new PB7(), + 8 when GameVersion.BDSP.Contains(version) => new PB8(), + 8 when GameVersion.PLA == version => new PA8(), _ => GetBlank(gen), }; @@ -60,14 +60,11 @@ public static PKM GetBlank(ITrainerInfo tr) { if (tr is SaveFile s) return s.BlankPKM; - return GetBlank(tr.Generation, tr.Game); + return GetBlank(tr.Generation, tr.Version); } /// - public static PKM GetBlank(int gen, int ver) => GetBlank(gen, (GameVersion)ver); - - /// - public static PKM GetBlank(int gen) + public static PKM GetBlank(byte gen) { var type = Type.GetType($"PKHeX.Core.PK{gen}"); ArgumentNullException.ThrowIfNull(type); diff --git a/PKHeX.Core/PKM/Util/EntityContext.cs b/PKHeX.Core/PKM/Util/EntityContext.cs index 89e5842b1..b2f1555bf 100644 --- a/PKHeX.Core/PKM/Util/EntityContext.cs +++ b/PKHeX.Core/PKM/Util/EntityContext.cs @@ -47,11 +47,11 @@ public static class EntityContextExtensions /// /// Get the generation number of the context. /// - public static int Generation(this EntityContext value) => value < SplitInvalid ? (int)value : value switch + public static byte Generation(this EntityContext value) => value < SplitInvalid ? (byte)value : value switch { - Gen7b => 7, - Gen8a => 8, - Gen8b => 8, + Gen7b => (byte)7, + Gen8a => (byte)8, + Gen8b => (byte)8, _ => throw new ArgumentOutOfRangeException(nameof(value), value, null), }; diff --git a/PKHeX.Core/PKM/Util/EntityFormat.cs b/PKHeX.Core/PKM/Util/EntityFormat.cs index e7c4d3f83..6238fd3f0 100644 --- a/PKHeX.Core/PKM/Util/EntityFormat.cs +++ b/PKHeX.Core/PKM/Util/EntityFormat.cs @@ -69,7 +69,7 @@ private static EntityFormatDetected GetFormat45(ReadOnlySpan data) if (data[0x5F] < 0x10 && ReadUInt16LittleEndian(data[0x80..]) < 0x3333) return FormatPK4; // Gen3/4 version origin, not Transporter if (ReadUInt16LittleEndian(data[0x46..]) != 0) - return FormatPK4; // PK4.Met_LocationExtended (unused in PK5) + return FormatPK4; // PK4.MetLocationExtended (unused in PK5) return FormatPK5; } @@ -148,7 +148,7 @@ private static EntityFormatDetected IsFormatReally7(PK6 pk) { if (pk.Version > Legal.MaxGameID_6) { - if (pk.Version is ((int)GameVersion.GP or (int)GameVersion.GE or (int)GameVersion.GO)) + if (pk.Version is (GameVersion.GP or GameVersion.GE or GameVersion.GO)) return FormatPB7; return FormatPK7; } diff --git a/PKHeX.Core/PKM/Util/EntityGender.cs b/PKHeX.Core/PKM/Util/EntityGender.cs index 667effa25..7b10bfd24 100644 --- a/PKHeX.Core/PKM/Util/EntityGender.cs +++ b/PKHeX.Core/PKM/Util/EntityGender.cs @@ -9,7 +9,7 @@ public static class EntityGender ///
/// Gender string /// Gender integer - public static int GetFromString(ReadOnlySpan s) + public static byte GetFromString(ReadOnlySpan s) { if (s.Length != 1) return 2; @@ -19,7 +19,7 @@ public static int GetFromString(ReadOnlySpan s) /// /// Translates a Gender char to Gender integer. /// - public static int GetFromChar(char c) => c switch + public static byte GetFromChar(char c) => c switch { '♂' or 'M' => 0, '♀' or 'F' => 1, @@ -33,17 +33,17 @@ public static int GetFromString(ReadOnlySpan s) /// Personality ID. /// Gender ID (0/1/2) /// This method should only be used for Generations 3-5 origin. - public static int GetFromPID(ushort species, uint pid) + public static byte GetFromPID(ushort species, uint pid) { var gt = PKX.Personal[species].Gender; return GetFromPIDAndRatio(pid, gt); } - public static int GetFromPIDAndRatio(uint pid, byte gr) => gr switch + public static byte GetFromPIDAndRatio(uint pid, byte gr) => gr switch { PersonalInfo.RatioMagicGenderless => 2, PersonalInfo.RatioMagicFemale => 1, PersonalInfo.RatioMagicMale => 0, - _ => (pid & 0xFF) < gr ? 1 : 0, + _ => (pid & 0xFF) < gr ? (byte)1 : (byte)0, }; } diff --git a/PKHeX.Core/PKM/Util/EntityPID.cs b/PKHeX.Core/PKM/Util/EntityPID.cs index 47afa253c..ebbcbc1f4 100644 --- a/PKHeX.Core/PKM/Util/EntityPID.cs +++ b/PKHeX.Core/PKM/Util/EntityPID.cs @@ -16,26 +16,26 @@ public static class EntityPID /// Current PID /// Used to retain ability bits. /// Rerolled PID. - public static uint GetRandomPID(Random rnd, ushort species, int gender, int origin, int nature, byte form, uint oldPID) + public static uint GetRandomPID(Random rnd, ushort species, byte gender, GameVersion origin, Nature nature, byte form, uint oldPID) { // Gen6+ (and VC) PIDs do not tie PID to Nature/Gender/Ability - if (origin is 0 or >= 24) + if (origin is 0 or >= GameVersion.X) return rnd.Rand32(); // Below logic handles Gen3-5. // No need to get form specific entry, as Gen3-5 do not have that feature. var gt = PersonalTable.B2W2[species].Gender; - bool g34 = origin <= 15; + bool g34 = origin <= GameVersion.CXD; uint abilBitVal = g34 ? oldPID & 0x0000_0001 : oldPID & 0x0001_0000; - bool g3unown = origin <= 5 && species == (int)Species.Unown; + bool g3unown = origin is GameVersion.FR or GameVersion.LG && species == (int)Species.Unown; bool singleGender = PersonalInfo.IsSingleGender(gt); // single gender, skip gender check while (true) // Loop until we find a suitable PID { uint pid = rnd.Rand32(); // Gen 3/4: Nature derived from PID - if (g34 && pid % 25 != nature) + if (g34 && pid % 25 != (byte)nature) continue; // Gen 3 Unown: Letter/form derived from PID diff --git a/PKHeX.Core/PKM/Util/EntitySorting.cs b/PKHeX.Core/PKM/Util/EntitySorting.cs index 58ef917af..a7df26b06 100644 --- a/PKHeX.Core/PKM/Util/EntitySorting.cs +++ b/PKHeX.Core/PKM/Util/EntitySorting.cs @@ -111,8 +111,8 @@ public static IEnumerable OrderBySpeciesName(this IEnumerable list, IR public static IEnumerable OrderByOwnership(this IEnumerable list, ITrainerInfo trainer) { return list.InitialSortBy() - .ThenByDescending(p => trainer.IsOriginalHandler(p, ((GameVersion)trainer.Game).IsValidSavedVersion())) // true first - .ThenByDescending(p => string.Equals(p.OT_Name, trainer.OT, StringComparison.OrdinalIgnoreCase)) + .ThenByDescending(p => trainer.IsOriginalHandler(p, trainer.Version.IsValidSavedVersion())) // true first + .ThenByDescending(p => string.Equals(p.OriginalTrainerName, trainer.OT, StringComparison.OrdinalIgnoreCase)) .OrderByTrainer() .ThenBy(p => p.Species) .FinalSortBy(); @@ -215,8 +215,8 @@ private static IOrderedEnumerable FinalSortBy(this IOrderedEnumerable /// Output list of data. private static IOrderedEnumerable OrderByTrainer(this IOrderedEnumerable list) { - return list.ThenBy(p => p.OT_Name) - .ThenBy(p => p.OT_Gender) + return list.ThenBy(p => p.OriginalTrainerName) + .ThenBy(p => p.OriginalTrainerGender) .ThenBy(p => p.TID16) .ThenBy(p => p.SID16); } @@ -232,13 +232,13 @@ public static bool IsOriginalHandler(this ITrainerInfo trainer, PKM pk, bool che { if (pk.Format >= 6) return pk.CurrentHandler != 1; - if (checkGame && trainer.Game != pk.Version) + if (checkGame && trainer.Version != pk.Version) return false; if (trainer.TID16 != pk.TID16 || trainer.SID16 != pk.SID16) return false; - if (trainer.Gender != pk.OT_Gender) + if (trainer.Gender != pk.OriginalTrainerGender) return false; - return trainer.OT == pk.OT_Name; + return trainer.OT == pk.OriginalTrainerName; } /// diff --git a/PKHeX.Core/PKM/Util/Experience.cs b/PKHeX.Core/PKM/Util/Experience.cs index 13517406e..e4baff687 100644 --- a/PKHeX.Core/PKM/Util/Experience.cs +++ b/PKHeX.Core/PKM/Util/Experience.cs @@ -14,7 +14,7 @@ public static class Experience /// Experience points /// Experience growth rate /// Current level of the species. - public static int GetLevel(uint exp, byte growth) + public static byte GetLevel(uint exp, byte growth) { var table = GetTable(growth); return GetLevel(exp, table); @@ -26,7 +26,7 @@ public static int GetLevel(uint exp, byte growth) /// Experience points /// Experience growth table /// Current level of the species. - public static int GetLevel(uint exp, ReadOnlySpan table) + public static byte GetLevel(uint exp, ReadOnlySpan table) { // Eagerly return 100 if the exp is at max // Also avoids overflow issues with the table in the event EXP is out of bounds @@ -35,7 +35,7 @@ public static int GetLevel(uint exp, ReadOnlySpan table) // Most will be below level 50, so start from the bottom // Don't bother with binary search, as the table is small - int tl = 1; // Initial Level. Iterate upwards to find the level + byte tl = 1; // Initial Level. Iterate upwards to find the level while (exp >= table[tl]) ++tl; return tl; @@ -47,7 +47,7 @@ public static int GetLevel(uint exp, ReadOnlySpan table) /// Current level /// Growth Rate type /// Experience points needed to have specified level. - public static uint GetEXP(int level, byte growth) + public static uint GetEXP(byte level, byte growth) { if (level <= 1) return 0; @@ -66,7 +66,7 @@ public static uint GetEXP(int level, byte growth) /// Experience points needed to have specified level. /// No bounds checking is performed. [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static uint GetEXP(int level, ReadOnlySpan table) => table[level - 1]; + public static uint GetEXP(byte level, ReadOnlySpan table) => table[level - 1]; /// /// Gets the minimum Experience points for all levels possible. @@ -90,7 +90,7 @@ public static uint GetEXP(int level, byte growth) /// /// Current Experience /// Nature ID () - public static int GetNatureVC(uint experience) => (int)(experience % 25); + public static Nature GetNatureVC(uint experience) => (Nature)(experience % 25); /// /// Gets the amount of EXP to be earned until the next level-up occurs. @@ -98,13 +98,13 @@ public static uint GetEXP(int level, byte growth) /// Current Level /// Growth Rate type /// EXP to level up - public static uint GetEXPToLevelUp(int level, byte growth) + public static uint GetEXPToLevelUp(byte level, byte growth) { - if ((uint)level >= 100) + if (level >= 100) return 0; var table = GetTable(growth); var current = GetEXP(level, table); - var next = GetEXP(level + 1, table); + var next = GetEXP(++level, table); return next - current; } @@ -115,14 +115,14 @@ public static uint GetEXPToLevelUp(int level, byte growth) /// Current Experience /// Growth Rate type /// Percentage [0,1.00) - public static double GetEXPToLevelUpPercentage(int level, uint exp, byte growth) + public static double GetEXPToLevelUpPercentage(byte level, uint exp, byte growth) { - if ((uint)level >= 100) + if (level >= 100) return 0; var table = GetTable(growth); var current = GetEXP(level, table); - var next = GetEXP(level + 1, table); + var next = GetEXP(++level, table); var amount = next - current; double progress = exp - current; return progress / amount; diff --git a/PKHeX.Core/PKM/Util/Language.cs b/PKHeX.Core/PKM/Util/Language.cs index 9adff01b4..7bc6a135e 100644 --- a/PKHeX.Core/PKM/Util/Language.cs +++ b/PKHeX.Core/PKM/Util/Language.cs @@ -34,7 +34,7 @@ public static class Language /// /// Generation to check. /// Available languages for the given generation. - public static ReadOnlySpan GetAvailableGameLanguages(int generation = PKX.Generation) => generation switch + public static ReadOnlySpan GetAvailableGameLanguages(byte generation = PKX.Generation) => generation switch { 1 => Languages_3, // No KOR 2 => Languages_GB, @@ -52,7 +52,7 @@ public static class Language /// Preferred language. /// Game version to check. /// Language that is safe to use for the given generation. - public static LanguageID GetSafeLanguage(int generation, LanguageID prefer, GameVersion game = GameVersion.Any) => generation switch + public static LanguageID GetSafeLanguage(byte generation, LanguageID prefer, GameVersion game = GameVersion.Any) => generation switch { 1 when game == GameVersion.BU => Japanese, 1 => HasLanguage(Languages_3, (byte)prefer) ? prefer : SafeLanguage, diff --git a/PKHeX.Core/PKM/Util/PKX.cs b/PKHeX.Core/PKM/Util/PKX.cs index 5ecb4d42a..e77f8e3af 100644 --- a/PKHeX.Core/PKM/Util/PKX.cs +++ b/PKHeX.Core/PKM/Util/PKX.cs @@ -8,5 +8,5 @@ public static class PKX internal static IPersonalTable Personal => PersonalTable.SV; public const EntityContext Context = EntityContext.Gen9; public const GameVersion Version = GameVersion.SL; - public const int Generation = 9; + public const byte Generation = 9; } diff --git a/PKHeX.Core/PKM/Util/RecentTrainerCache.cs b/PKHeX.Core/PKM/Util/RecentTrainerCache.cs index c79f8808e..42a70a457 100644 --- a/PKHeX.Core/PKM/Util/RecentTrainerCache.cs +++ b/PKHeX.Core/PKM/Util/RecentTrainerCache.cs @@ -12,19 +12,19 @@ public static class RecentTrainerCache private static IRegionOrigin GetTrainer3DS(ITrainerInfo tr) => tr as IRegionOrigin ?? Trainer67; /// Most recently loaded . - public static string OT_Name => Trainer.OT; + public static string OriginalTrainerName => Trainer.OT; /// Most recently loaded . - public static int OT_Gender => Trainer.Gender; + public static byte OriginalTrainerGender => Trainer.Gender; /// Most recently loaded . public static int Language => Trainer.Language; /// Most recently loaded . - public static int Format => Trainer.Generation; + public static byte Format => Trainer.Generation; - /// Most recently loaded . - public static int Game => Trainer.Game; + /// Most recently loaded . + public static GameVersion Version => Trainer.Version; /// Most recently loaded . public static EntityContext Context => Trainer.Context; diff --git a/PKHeX.Core/PKM/Util/SpeciesName.cs b/PKHeX.Core/PKM/Util/SpeciesName.cs index e310b1ee7..7ac56a830 100644 --- a/PKHeX.Core/PKM/Util/SpeciesName.cs +++ b/PKHeX.Core/PKM/Util/SpeciesName.cs @@ -104,7 +104,7 @@ public static string GetSpeciesName(ushort species, int language) /// Language ID of the Pokémon /// Generation specific formatting option /// Generation specific default species name - public static string GetSpeciesNameGeneration(ushort species, int language, int generation) => generation switch + public static string GetSpeciesNameGeneration(ushort species, int language, byte generation) => generation switch { <= 4 => GetSpeciesName1234(species, language, generation), 7 when language == (int) LanguageID.ChineseS => GetSpeciesName7ZH(species, language), @@ -116,13 +116,13 @@ public static string GetSpeciesName(ushort species, int language) /// /// Language ID of the Pokémon /// Generation specific formatting option - public static string GetEggName(int language, int generation = LatestGeneration) => generation switch + public static string GetEggName(int language, byte generation = LatestGeneration) => generation switch { <= 4 => GetEggName1234(0, language, generation), _ => (uint)language >= EggNames.Length ? string.Empty : EggNames[language], }; - private static string GetSpeciesName1234(ushort species, int language, int generation) + private static string GetSpeciesName1234(ushort species, int language, byte generation) { if (species == 0) return GetEggName1234(species, language, generation); @@ -169,7 +169,7 @@ private static string GetSpeciesName1234(ushort species, int language, int gener return new string(result); } - private static string GetEggName1234(ushort species, int language, int generation) + private static string GetEggName1234(ushort species, int language, byte generation) { if (generation == 3) return "タマゴ"; // All Gen3 eggs are treated as JPN eggs. @@ -225,7 +225,7 @@ private static string GetEggName1234(ushort species, int language, int generatio /// Current name /// Generation specific formatting option /// True if it does not match any language name, False if not nicknamed - public static bool IsNicknamedAnyLanguage(ushort species, ReadOnlySpan nickname, int generation = LatestGeneration) + public static bool IsNicknamedAnyLanguage(ushort species, ReadOnlySpan nickname, byte generation = LatestGeneration) { var langs = Language.GetAvailableGameLanguages(generation); foreach (var language in langs) @@ -244,7 +244,7 @@ public static bool IsNicknamedAnyLanguage(ushort species, ReadOnlySpan nic /// Language ID of the Pokémon /// Generation specific formatting option /// True if it does not match the language name, False if not nicknamed (matches). - public static bool IsNicknamed(ushort species, ReadOnlySpan nickname, int language, int generation = LatestGeneration) + public static bool IsNicknamed(ushort species, ReadOnlySpan nickname, int language, byte generation = LatestGeneration) { var expect = GetSpeciesNameGeneration(species, language, generation); return !nickname.SequenceEqual(expect); @@ -258,7 +258,7 @@ public static bool IsNicknamed(ushort species, ReadOnlySpan nickname, int /// Current name /// Generation specific formatting option /// Language ID if it does not match any language name, -1 if no matches - public static int GetSpeciesNameLanguage(ushort species, int priorityLanguage, ReadOnlySpan nickname, int generation = LatestGeneration) + public static int GetSpeciesNameLanguage(ushort species, int priorityLanguage, ReadOnlySpan nickname, byte generation = LatestGeneration) { var langs = Language.GetAvailableGameLanguages(generation); var priorityIndex = langs.IndexOf((byte)priorityLanguage); @@ -279,13 +279,13 @@ public static int GetSpeciesNameLanguage(ushort species, int priorityLanguage, R /// Current name /// Generation specific formatting option /// Language ID if it does not match any language name, -1 if no matches - public static int GetSpeciesNameLanguage(ushort species, ReadOnlySpan nickname, int generation = LatestGeneration) + public static int GetSpeciesNameLanguage(ushort species, ReadOnlySpan nickname, byte generation = LatestGeneration) { var langs = Language.GetAvailableGameLanguages(generation); return GetSpeciesNameLanguage(species, nickname, generation, langs); } - private static int GetSpeciesNameLanguage(ushort species, ReadOnlySpan nickname, int generation, ReadOnlySpan langs) + private static int GetSpeciesNameLanguage(ushort species, ReadOnlySpan nickname, byte generation, ReadOnlySpan langs) { foreach (var lang in langs) { diff --git a/PKHeX.Core/PKM/XK3.cs b/PKHeX.Core/PKM/XK3.cs index e4251ace6..2bf6dde42 100644 --- a/PKHeX.Core/PKM/XK3.cs +++ b/PKHeX.Core/PKM/XK3.cs @@ -25,8 +25,8 @@ public sealed class XK3 : G3PKM, IShadowCapture public override void RefreshChecksum() => Valid = true; // Trash Bytes - public override Span OT_Trash => Data.AsSpan(0x38, 22); - public override Span Nickname_Trash => Data.AsSpan(0x4E, 22); + public override Span OriginalTrainerTrash => Data.AsSpan(0x38, 22); + public override Span NicknameTrash => Data.AsSpan(0x4E, 22); public Span NicknameCopy_Trash => Data.AsSpan(0x64, 22); public override ushort SpeciesInternal { get => ReadUInt16BigEndian(Data.AsSpan(0x00)); set => WriteUInt16BigEndian(Data.AsSpan(0x00), value); } // raw access @@ -34,18 +34,18 @@ public sealed class XK3 : G3PKM, IShadowCapture public override int SpriteItem => ItemConverter.GetItemFuture3((ushort)HeldItem); public override int HeldItem { get => ReadUInt16BigEndian(Data.AsSpan(0x02)); set => WriteUInt16BigEndian(Data.AsSpan(0x02), (ushort)value); } public override int Stat_HPCurrent { get => ReadUInt16BigEndian(Data.AsSpan(0x04)); set => WriteUInt16BigEndian(Data.AsSpan(0x04), (ushort)value); } - public override int OT_Friendship { get => ReadUInt16BigEndian(Data.AsSpan(0x06)); set => WriteUInt16BigEndian(Data.AsSpan(0x06), (ushort)value); } - public override int Met_Location { get => ReadUInt16BigEndian(Data.AsSpan(0x08)); set => WriteUInt16BigEndian(Data.AsSpan(0x08), (ushort)value); } + public override byte OriginalTrainerFriendship { get => (byte)ReadUInt16BigEndian(Data.AsSpan(0x06)); set => WriteUInt16BigEndian(Data.AsSpan(0x06), value); } + public override ushort MetLocation { get => ReadUInt16BigEndian(Data.AsSpan(0x08)); set => WriteUInt16BigEndian(Data.AsSpan(0x08), value); } // 0x0A-0x0B Unknown // 0x0C-0x0D Unknown - public override int Met_Level { get => Data[0x0E]; set => Data[0x0E] = (byte)value; } - public override int Ball { get => Data[0x0F]; set => Data[0x0F] = (byte)value; } - public override int OT_Gender { get => Data[0x10]; set => Data[0x10] = (byte)value; } - public override int Stat_Level { get => Data[0x11]; set => Data[0x11] = (byte)value; } - public override byte CNT_Sheen { get => Data[0x12]; set => Data[0x12] = value; } - public override int PKRS_Strain { get => Data[0x13] & 0xF; set => Data[0x13] = (byte)(value & 0xF); } + public override byte MetLevel { get => Data[0x0E]; set => Data[0x0E] = value; } + public override byte Ball { get => Data[0x0F]; set => Data[0x0F] = value; } + public override byte OriginalTrainerGender { get => Data[0x10]; set => Data[0x10] = value; } + public override byte Stat_Level { get => Data[0x11]; set => Data[0x11] = value; } + public override byte ContestSheen { get => Data[0x12]; set => Data[0x12] = value; } + public override int PokerusStrain { get => Data[0x13] & 0xF; set => Data[0x13] = (byte)(value & 0xF); } public override byte MarkingValue { get => (byte)SwapBits(Data[0x14], 1, 2); set => Data[0x14] = (byte)SwapBits(value, 1, 2); } - public override int PKRS_Days { get => Math.Max((sbyte)Data[0x15], (sbyte)0); set => Data[0x15] = (byte)(value == 0 ? 0xFF : value & 0xF); } + public override int PokerusDays { get => Math.Max((sbyte)Data[0x15], (sbyte)0); set => Data[0x15] = (byte)(value == 0 ? 0xFF : value & 0xF); } // 0x16-0x1C Battle Related private int XDPKMFLAGS { get => Data[0x1D]; set => Data[0x1D] = (byte)value; } public bool UnusedFlag0 { get => (XDPKMFLAGS & (1 << 0)) == 1 << 0; set => XDPKMFLAGS = (XDPKMFLAGS & ~(1 << 0)) | (value ? 1 << 0 : 0); } @@ -83,12 +83,12 @@ public override bool FatefulEncounter } } - public override int Version { get => GetGBAVersionID(Data[0x34]); set => Data[0x34] = GetGCVersionID(value); } + public override GameVersion Version { get => GetGBAVersionID((GCVersion)Data[0x34]); set => Data[0x34] = (byte)GetGCVersionID(value); } public int CurrentRegion { get => Data[0x35]; set => Data[0x35] = (byte)value; } public int OriginalRegion { get => Data[0x36]; set => Data[0x36] = (byte)value; } public override int Language { get => Core.Language.GetMainLangIDfromGC(Data[0x37]); set => Data[0x37] = Core.Language.GetGCLangIDfromMain((byte)value); } - public override string OT_Name { get => StringConverter3GC.GetString(OT_Trash); set => StringConverter3GC.SetString(OT_Trash, value, 10, StringConverterOption.None); } - public override string Nickname { get => StringConverter3GC.GetString(Nickname_Trash); set { StringConverter3GC.SetString(Nickname_Trash, value, 10, StringConverterOption.None); NicknameCopy = value; } } + public override string OriginalTrainerName { get => StringConverter3GC.GetString(OriginalTrainerTrash); set => StringConverter3GC.SetString(OriginalTrainerTrash, value, 10, StringConverterOption.None); } + public override string Nickname { get => StringConverter3GC.GetString(NicknameTrash); set { StringConverter3GC.SetString(NicknameTrash, value, 10, StringConverterOption.None); NicknameCopy = value; } } public string NicknameCopy { get => StringConverter3GC.GetString(NicknameCopy_Trash); set => StringConverter3GC.SetString(NicknameCopy_Trash, value, 10, StringConverterOption.None); } // 0x7A-0x7B Unknown private ushort RIB0 { get => ReadUInt16BigEndian(Data.AsSpan(0x7C)); set => WriteUInt16BigEndian(Data.AsSpan(0x7C), value); } @@ -179,11 +179,11 @@ public override int EV_SPE public override int IV_SPE { get => Data[0xAD]; set => Data[0xAD] = (byte)(value & 0x1F); } // Contest - public override byte CNT_Cool { get => Data[0xAE]; set => Data[0xAE] = value; } - public override byte CNT_Beauty { get => Data[0xAF]; set => Data[0xAF] = value; } - public override byte CNT_Cute { get => Data[0xB0]; set => Data[0xB0] = value; } - public override byte CNT_Smart { get => Data[0xB1]; set => Data[0xB1] = value; } - public override byte CNT_Tough { get => Data[0xB2]; set => Data[0xB2] = value; } + public override byte ContestCool { get => Data[0xAE]; set => Data[0xAE] = value; } + public override byte ContestBeauty { get => Data[0xAF]; set => Data[0xAF] = value; } + public override byte ContestCute { get => Data[0xB0]; set => Data[0xB0] = value; } + public override byte ContestSmart { get => Data[0xB1]; set => Data[0xB1] = value; } + public override byte ContestTough { get => Data[0xB2]; set => Data[0xB2] = value; } public override byte RibbonCountG3Cool { get => Data[0xB3]; set => Data[0xB3] = value; } public override byte RibbonCountG3Beauty { get => Data[0xB4]; set => Data[0xB4] = value; } public override byte RibbonCountG3Cute { get => Data[0xB5]; set => Data[0xB5] = value; } @@ -208,7 +208,7 @@ protected override byte[] Encrypt() public PK3 ConvertToPK3() { var pk = ConvertTo(); - if (Version == 15) + if (Version == GameVersion.CXD) { // Transferring XK3 to PK3 when it originates from XD sets the fateful encounter (obedience) flag. if (ShadowID != 0) @@ -216,7 +216,7 @@ public PK3 ConvertToPK3() pk.RibbonNational = true; // must be purified before trading away; force purify pk.FatefulEncounter = true; } - else if (IsGiftXD(Met_Location)) + else if (IsGiftXD(MetLocation)) { pk.FatefulEncounter = true; } @@ -226,7 +226,7 @@ public PK3 ConvertToPK3() return pk; } - private static bool IsGiftXD(int met) => met switch + private static bool IsGiftXD(ushort met) => met switch { 0 or 16 => true, // Starter Eevee / Hordel Gift 90 or 91 or 92 => true, // Pokespot: Rock / Oasis / Cave diff --git a/PKHeX.Core/PersonalInfo/Info/PersonalInfo1.cs b/PKHeX.Core/PersonalInfo/Info/PersonalInfo1.cs index dc762fd0c..bb02d4fb0 100644 --- a/PKHeX.Core/PersonalInfo/Info/PersonalInfo1.cs +++ b/PKHeX.Core/PersonalInfo/Info/PersonalInfo1.cs @@ -44,8 +44,8 @@ public sealed class PersonalInfo1(byte[] Data) : PersonalInfo, IPersonalInfoTM public override int GetIndexOfAbility(int abilityID) => -1; public override int GetAbilityAtIndex(int abilityIndex) => -1; public override int AbilityCount => 0; - public override int HatchCycles { get => 0; set { } } - public override int BaseFriendship { get => 0; set { } } + public override byte HatchCycles { get => 0; set { } } + public override byte BaseFriendship { get => 0; set { } } public override int EscapeRate { get => 0; set { } } public override int Color { get => 0; set { } } diff --git a/PKHeX.Core/PersonalInfo/Info/PersonalInfo2.cs b/PKHeX.Core/PersonalInfo/Info/PersonalInfo2.cs index 1f17ab0cc..a052bf2f8 100644 --- a/PKHeX.Core/PersonalInfo/Info/PersonalInfo2.cs +++ b/PKHeX.Core/PersonalInfo/Info/PersonalInfo2.cs @@ -25,7 +25,7 @@ public sealed class PersonalInfo2(byte[] Data) : PersonalInfo, IPersonalInfoTM, public int Item1 { get => Data[0xB]; set => Data[0xB] = (byte)value; } public int Item2 { get => Data[0xC]; set => Data[0xC] = (byte)value; } public override byte Gender { get => Data[0xD]; set => Data[0xD] = value; } - public override int HatchCycles { get => Data[0xF]; set => Data[0xF] = (byte)value; } + public override byte HatchCycles { get => Data[0xF]; set => Data[0xF] = value; } public override byte EXPGrowth { get => Data[0x16]; set => Data[0x16] = value; } public override int EggGroup1 { get => Data[0x17] & 0xF; set => Data[0x17] = (byte)((Data[0x17] & 0xF0) | value); } public override int EggGroup2 { get => Data[0x17] >> 4; set => Data[0x17] = (byte)((Data[0x17] & 0x0F) | (value << 4)); } @@ -42,7 +42,7 @@ public sealed class PersonalInfo2(byte[] Data) : PersonalInfo, IPersonalInfoTM, public override int GetIndexOfAbility(int abilityID) => -1; public override int GetAbilityAtIndex(int abilityIndex) => -1; public override int AbilityCount => 0; - public override int BaseFriendship { get => 70; set { } } + public override byte BaseFriendship { get => 70; set { } } public override int EscapeRate { get => 0; set { } } public override int Color { get => 0; set { } } diff --git a/PKHeX.Core/PersonalInfo/Info/PersonalInfo3.cs b/PKHeX.Core/PersonalInfo/Info/PersonalInfo3.cs index ee72dce83..c9d9073a6 100644 --- a/PKHeX.Core/PersonalInfo/Info/PersonalInfo3.cs +++ b/PKHeX.Core/PersonalInfo/Info/PersonalInfo3.cs @@ -32,8 +32,8 @@ public sealed class PersonalInfo3(byte[] Data) : PersonalInfo, IPersonalAbility1 public int Item1 { get => ReadInt16LittleEndian(Data.AsSpan(0xC)); set => WriteInt16LittleEndian(Data.AsSpan(0xC), (short)value); } public int Item2 { get => ReadInt16LittleEndian(Data.AsSpan(0xE)); set => WriteInt16LittleEndian(Data.AsSpan(0xE), (short)value); } public override byte Gender { get => Data[0x10]; set => Data[0x10] = value; } - public override int HatchCycles { get => Data[0x11]; set => Data[0x11] = (byte)value; } - public override int BaseFriendship { get => Data[0x12]; set => Data[0x12] = (byte)value; } + public override byte HatchCycles { get => Data[0x11]; set => Data[0x11] = value; } + public override byte BaseFriendship { get => Data[0x12]; set => Data[0x12] = value; } public override byte EXPGrowth { get => Data[0x13]; set => Data[0x13] = value; } public override int EggGroup1 { get => Data[0x14]; set => Data[0x14] = (byte)value; } public override int EggGroup2 { get => Data[0x15]; set => Data[0x15] = (byte)value; } diff --git a/PKHeX.Core/PersonalInfo/Info/PersonalInfo4.cs b/PKHeX.Core/PersonalInfo/Info/PersonalInfo4.cs index b9325291a..a608d09aa 100644 --- a/PKHeX.Core/PersonalInfo/Info/PersonalInfo4.cs +++ b/PKHeX.Core/PersonalInfo/Info/PersonalInfo4.cs @@ -32,8 +32,8 @@ public sealed class PersonalInfo4(byte[] Data) : PersonalInfo, IPersonalAbility1 public int Item1 { get => ReadInt16LittleEndian(Data.AsSpan(0xC)); set => WriteInt16LittleEndian(Data.AsSpan(0xC), (short)value); } public int Item2 { get => ReadInt16LittleEndian(Data.AsSpan(0xE)); set => WriteInt16LittleEndian(Data.AsSpan(0xE), (short)value); } public override byte Gender { get => Data[0x10]; set => Data[0x10] = value; } - public override int HatchCycles { get => Data[0x11]; set => Data[0x11] = (byte)value; } - public override int BaseFriendship { get => Data[0x12]; set => Data[0x12] = (byte)value; } + public override byte HatchCycles { get => Data[0x11]; set => Data[0x11] = value; } + public override byte BaseFriendship { get => Data[0x12]; set => Data[0x12] = value; } public override byte EXPGrowth { get => Data[0x13]; set => Data[0x13] = value; } public override int EggGroup1 { get => Data[0x14]; set => Data[0x14] = (byte)value; } public override int EggGroup2 { get => Data[0x15]; set => Data[0x15] = (byte)value; } diff --git a/PKHeX.Core/PersonalInfo/Info/PersonalInfo5B2W2.cs b/PKHeX.Core/PersonalInfo/Info/PersonalInfo5B2W2.cs index 2e019f4a4..698d2c1c0 100644 --- a/PKHeX.Core/PersonalInfo/Info/PersonalInfo5B2W2.cs +++ b/PKHeX.Core/PersonalInfo/Info/PersonalInfo5B2W2.cs @@ -34,8 +34,8 @@ public sealed class PersonalInfo5B2W2(byte[] Data) : PersonalInfo, IPersonalAbil public int Item2 { get => ReadInt16LittleEndian(Data.AsSpan(0x0E)); set => WriteInt16LittleEndian(Data.AsSpan(0x0E), (short)value); } public int Item3 { get => ReadInt16LittleEndian(Data.AsSpan(0x10)); set => WriteInt16LittleEndian(Data.AsSpan(0x10), (short)value); } public override byte Gender { get => Data[0x12]; set => Data[0x12] = value; } - public override int HatchCycles { get => Data[0x13]; set => Data[0x13] = (byte)value; } - public override int BaseFriendship { get => Data[0x14]; set => Data[0x14] = (byte)value; } + public override byte HatchCycles { get => Data[0x13]; set => Data[0x13] = value; } + public override byte BaseFriendship { get => Data[0x14]; set => Data[0x14] = value; } public override byte EXPGrowth { get => Data[0x15]; set => Data[0x15] = value; } public override int EggGroup1 { get => Data[0x16]; set => Data[0x16] = (byte)value; } public override int EggGroup2 { get => Data[0x17]; set => Data[0x17] = (byte)value; } diff --git a/PKHeX.Core/PersonalInfo/Info/PersonalInfo5BW.cs b/PKHeX.Core/PersonalInfo/Info/PersonalInfo5BW.cs index 285c3576c..252a6fdcf 100644 --- a/PKHeX.Core/PersonalInfo/Info/PersonalInfo5BW.cs +++ b/PKHeX.Core/PersonalInfo/Info/PersonalInfo5BW.cs @@ -34,8 +34,8 @@ public sealed class PersonalInfo5BW(byte[] Data) : PersonalInfo, IPersonalAbilit public int Item2 { get => ReadInt16LittleEndian(Data.AsSpan(0x0E)); set => WriteInt16LittleEndian(Data.AsSpan(0x0E), (short)value); } public int Item3 { get => ReadInt16LittleEndian(Data.AsSpan(0x10)); set => WriteInt16LittleEndian(Data.AsSpan(0x10), (short)value); } public override byte Gender { get => Data[0x12]; set => Data[0x12] = value; } - public override int HatchCycles { get => Data[0x13]; set => Data[0x13] = (byte)value; } - public override int BaseFriendship { get => Data[0x14]; set => Data[0x14] = (byte)value; } + public override byte HatchCycles { get => Data[0x13]; set => Data[0x13] = value; } + public override byte BaseFriendship { get => Data[0x14]; set => Data[0x14] = value; } public override byte EXPGrowth { get => Data[0x15]; set => Data[0x15] = value; } public override int EggGroup1 { get => Data[0x16]; set => Data[0x16] = (byte)value; } public override int EggGroup2 { get => Data[0x17]; set => Data[0x17] = (byte)value; } diff --git a/PKHeX.Core/PersonalInfo/Info/PersonalInfo6AO.cs b/PKHeX.Core/PersonalInfo/Info/PersonalInfo6AO.cs index 4ed251f3a..5b6063207 100644 --- a/PKHeX.Core/PersonalInfo/Info/PersonalInfo6AO.cs +++ b/PKHeX.Core/PersonalInfo/Info/PersonalInfo6AO.cs @@ -34,8 +34,8 @@ public sealed class PersonalInfo6AO(byte[] Data) : PersonalInfo, IPersonalAbilit public int Item2 { get => ReadInt16LittleEndian(Data.AsSpan(0x0E)); set => WriteInt16LittleEndian(Data.AsSpan(0x0E), (short)value); } public int Item3 { get => ReadInt16LittleEndian(Data.AsSpan(0x10)); set => WriteInt16LittleEndian(Data.AsSpan(0x10), (short)value); } public override byte Gender { get => Data[0x12]; set => Data[0x12] = value; } - public override int HatchCycles { get => Data[0x13]; set => Data[0x13] = (byte)value; } - public override int BaseFriendship { get => Data[0x14]; set => Data[0x14] = (byte)value; } + public override byte HatchCycles { get => Data[0x13]; set => Data[0x13] = value; } + public override byte BaseFriendship { get => Data[0x14]; set => Data[0x14] = value; } public override byte EXPGrowth { get => Data[0x15]; set => Data[0x15] = value; } public override int EggGroup1 { get => Data[0x16]; set => Data[0x16] = (byte)value; } public override int EggGroup2 { get => Data[0x17]; set => Data[0x17] = (byte)value; } diff --git a/PKHeX.Core/PersonalInfo/Info/PersonalInfo6XY.cs b/PKHeX.Core/PersonalInfo/Info/PersonalInfo6XY.cs index 29441aef4..587cc1019 100644 --- a/PKHeX.Core/PersonalInfo/Info/PersonalInfo6XY.cs +++ b/PKHeX.Core/PersonalInfo/Info/PersonalInfo6XY.cs @@ -34,8 +34,8 @@ public sealed class PersonalInfo6XY(byte[] Data) : PersonalInfo, IPersonalAbilit public int Item2 { get => ReadInt16LittleEndian(Data.AsSpan(0x0E)); set => WriteInt16LittleEndian(Data.AsSpan(0x0E), (short)value); } public int Item3 { get => ReadInt16LittleEndian(Data.AsSpan(0x10)); set => WriteInt16LittleEndian(Data.AsSpan(0x10), (short)value); } public override byte Gender { get => Data[0x12]; set => Data[0x12] = value; } - public override int HatchCycles { get => Data[0x13]; set => Data[0x13] = (byte)value; } - public override int BaseFriendship { get => Data[0x14]; set => Data[0x14] = (byte)value; } + public override byte HatchCycles { get => Data[0x13]; set => Data[0x13] = value; } + public override byte BaseFriendship { get => Data[0x14]; set => Data[0x14] = value; } public override byte EXPGrowth { get => Data[0x15]; set => Data[0x15] = value; } public override int EggGroup1 { get => Data[0x16]; set => Data[0x16] = (byte)value; } public override int EggGroup2 { get => Data[0x17]; set => Data[0x17] = (byte)value; } diff --git a/PKHeX.Core/PersonalInfo/Info/PersonalInfo7.cs b/PKHeX.Core/PersonalInfo/Info/PersonalInfo7.cs index 91aed13b8..3e78f6761 100644 --- a/PKHeX.Core/PersonalInfo/Info/PersonalInfo7.cs +++ b/PKHeX.Core/PersonalInfo/Info/PersonalInfo7.cs @@ -35,8 +35,8 @@ public sealed class PersonalInfo7(byte[] Data) public int Item2 { get => ReadInt16LittleEndian(Data.AsSpan(0x0E)); set => WriteInt16LittleEndian(Data.AsSpan(0x0E), (short)value); } public int Item3 { get => ReadInt16LittleEndian(Data.AsSpan(0x10)); set => WriteInt16LittleEndian(Data.AsSpan(0x10), (short)value); } public override byte Gender { get => Data[0x12]; set => Data[0x12] = value; } - public override int HatchCycles { get => Data[0x13]; set => Data[0x13] = (byte)value; } - public override int BaseFriendship { get => Data[0x14]; set => Data[0x14] = (byte)value; } + public override byte HatchCycles { get => Data[0x13]; set => Data[0x13] = value; } + public override byte BaseFriendship { get => Data[0x14]; set => Data[0x14] = value; } public override byte EXPGrowth { get => Data[0x15]; set => Data[0x15] = value; } public override int EggGroup1 { get => Data[0x16]; set => Data[0x16] = (byte)value; } public override int EggGroup2 { get => Data[0x17]; set => Data[0x17] = (byte)value; } diff --git a/PKHeX.Core/PersonalInfo/Info/PersonalInfo7GG.cs b/PKHeX.Core/PersonalInfo/Info/PersonalInfo7GG.cs index 9309fecb4..2773c1848 100644 --- a/PKHeX.Core/PersonalInfo/Info/PersonalInfo7GG.cs +++ b/PKHeX.Core/PersonalInfo/Info/PersonalInfo7GG.cs @@ -34,8 +34,8 @@ public sealed class PersonalInfo7GG(byte[] Data) : PersonalInfo, IPersonalAbilit public int Item2 { get => ReadInt16LittleEndian(Data.AsSpan(0x0E)); set => WriteInt16LittleEndian(Data.AsSpan(0x0E), (short)value); } public int Item3 { get => ReadInt16LittleEndian(Data.AsSpan(0x10)); set => WriteInt16LittleEndian(Data.AsSpan(0x10), (short)value); } public override byte Gender { get => Data[0x12]; set => Data[0x12] = value; } - public override int HatchCycles { get => Data[0x13]; set => Data[0x13] = (byte)value; } - public override int BaseFriendship { get => Data[0x14]; set => Data[0x14] = (byte)value; } + public override byte HatchCycles { get => Data[0x13]; set => Data[0x13] = value; } + public override byte BaseFriendship { get => Data[0x14]; set => Data[0x14] = value; } public override byte EXPGrowth { get => Data[0x15]; set => Data[0x15] = value; } public override int EggGroup1 { get => Data[0x16]; set => Data[0x16] = (byte)value; } public override int EggGroup2 { get => Data[0x17]; set => Data[0x17] = (byte)value; } diff --git a/PKHeX.Core/PersonalInfo/Info/PersonalInfo8BDSP.cs b/PKHeX.Core/PersonalInfo/Info/PersonalInfo8BDSP.cs index 3a6959465..33c96f4ff 100644 --- a/PKHeX.Core/PersonalInfo/Info/PersonalInfo8BDSP.cs +++ b/PKHeX.Core/PersonalInfo/Info/PersonalInfo8BDSP.cs @@ -39,8 +39,8 @@ public sealed class PersonalInfo8BDSP(byte[] Data) public int Item2 { get => ReadInt16LittleEndian(Data.AsSpan(0x0E)); set => WriteInt16LittleEndian(Data.AsSpan(0x0E), (short)value); } public int Item3 { get => ReadInt16LittleEndian(Data.AsSpan(0x10)); set => WriteInt16LittleEndian(Data.AsSpan(0x10), (short)value); } public override byte Gender { get => Data[0x12]; set => Data[0x12] = value; } - public override int HatchCycles { get => Data[0x13]; set => Data[0x13] = (byte)value; } - public override int BaseFriendship { get => Data[0x14]; set => Data[0x14] = (byte)value; } + public override byte HatchCycles { get => Data[0x13]; set => Data[0x13] = value; } + public override byte BaseFriendship { get => Data[0x14]; set => Data[0x14] = value; } public override byte EXPGrowth { get => Data[0x15]; set => Data[0x15] = value; } public override int EggGroup1 { get => Data[0x16]; set => Data[0x16] = (byte)value; } public override int EggGroup2 { get => Data[0x17]; set => Data[0x17] = (byte)value; } diff --git a/PKHeX.Core/PersonalInfo/Info/PersonalInfo8LA.cs b/PKHeX.Core/PersonalInfo/Info/PersonalInfo8LA.cs index f57465dfe..2a7935a03 100644 --- a/PKHeX.Core/PersonalInfo/Info/PersonalInfo8LA.cs +++ b/PKHeX.Core/PersonalInfo/Info/PersonalInfo8LA.cs @@ -33,8 +33,8 @@ public sealed class PersonalInfo8LA(byte[] Data) : PersonalInfo, IPersonalAbilit public int Item2 { get => ReadInt16LittleEndian(Data.AsSpan(0x0E)); set => WriteInt16LittleEndian(Data.AsSpan(0x0E), (short)value); } public int Item3 { get => ReadInt16LittleEndian(Data.AsSpan(0x10)); set => WriteInt16LittleEndian(Data.AsSpan(0x10), (short)value); } public override byte Gender { get => Data[0x12]; set => Data[0x12] = value; } - public override int HatchCycles { get => Data[0x13]; set => Data[0x13] = (byte)value; } - public override int BaseFriendship { get => Data[0x14]; set => Data[0x14] = (byte)value; } + public override byte HatchCycles { get => Data[0x13]; set => Data[0x13] = value; } + public override byte BaseFriendship { get => Data[0x14]; set => Data[0x14] = value; } public override byte EXPGrowth { get => Data[0x15]; set => Data[0x15] = value; } public override int EggGroup1 { get => Data[0x16]; set => Data[0x16] = (byte)value; } public override int EggGroup2 { get => Data[0x17]; set => Data[0x17] = (byte)value; } @@ -82,6 +82,10 @@ public sealed class PersonalInfo8LA(byte[] Data) : PersonalInfo, IPersonalAbilit public int GetMoveShopCount() => System.Numerics.BitOperations.PopCount(MoveShopBits); + /// + /// Gets the absolute index of the n-th set-bit of the Move Shop Permit bitflags. + /// + /// n-th set-bit to find public int GetMoveShopIndex(int randIndexFromCount) { // Return a count of true indexes from Tutors @@ -98,10 +102,7 @@ public int GetMoveShopIndex(int randIndexFromCount) throw new ArgumentOutOfRangeException(nameof(randIndexFromCount), randIndexFromCount, "Insufficient bits set in the permission list."); } - public bool IsRecordPermitted(int index) - { - return (MoveShopBits & (1ul << index)) != 0; - } + public bool IsRecordPermitted(int index) => (MoveShopBits & (1ul << index)) != 0; public bool GetIsLearnMoveShop(ushort move) { diff --git a/PKHeX.Core/PersonalInfo/Info/PersonalInfo8SWSH.cs b/PKHeX.Core/PersonalInfo/Info/PersonalInfo8SWSH.cs index 905a4d03c..2bedb22ff 100644 --- a/PKHeX.Core/PersonalInfo/Info/PersonalInfo8SWSH.cs +++ b/PKHeX.Core/PersonalInfo/Info/PersonalInfo8SWSH.cs @@ -34,8 +34,8 @@ public sealed class PersonalInfo8SWSH(byte[] Data) : PersonalInfo, IPersonalAbil public int Item2 { get => ReadInt16LittleEndian(Data.AsSpan(0x0E)); set => WriteInt16LittleEndian(Data.AsSpan(0x0E), (short)value); } public int Item3 { get => ReadInt16LittleEndian(Data.AsSpan(0x10)); set => WriteInt16LittleEndian(Data.AsSpan(0x10), (short)value); } public override byte Gender { get => Data[0x12]; set => Data[0x12] = value; } - public override int HatchCycles { get => Data[0x13]; set => Data[0x13] = (byte)value; } - public override int BaseFriendship { get => Data[0x14]; set => Data[0x14] = (byte)value; } + public override byte HatchCycles { get => Data[0x13]; set => Data[0x13] = value; } + public override byte BaseFriendship { get => Data[0x14]; set => Data[0x14] = value; } public override byte EXPGrowth { get => Data[0x15]; set => Data[0x15] = value; } public override int EggGroup1 { get => Data[0x16]; set => Data[0x16] = (byte)value; } public override int EggGroup2 { get => Data[0x17]; set => Data[0x17] = (byte)value; } diff --git a/PKHeX.Core/PersonalInfo/Info/PersonalInfo9SV.cs b/PKHeX.Core/PersonalInfo/Info/PersonalInfo9SV.cs index 4cd38a457..204ae4a8c 100644 --- a/PKHeX.Core/PersonalInfo/Info/PersonalInfo9SV.cs +++ b/PKHeX.Core/PersonalInfo/Info/PersonalInfo9SV.cs @@ -30,8 +30,8 @@ public sealed class PersonalInfo9SV(byte[] Data) : PersonalInfo, IPersonalAbilit public override int EV_SPA { get => (EVYield >> 8) & 0x3; set => EVYield = (EVYield & ~(0x3 << 8)) | ((value & 0x3) << 8); } public override int EV_SPD { get => (EVYield >> 10) & 0x3; set => EVYield = (EVYield & ~(0x3 << 10)) | ((value & 0x3) << 10); } public override byte Gender { get => Data[0x0C]; set => Data[0x0C] = value; } - public override int HatchCycles { get => Data[0x0D]; set => Data[0x0D] = (byte)value; } - public override int BaseFriendship { get => Data[0x0E]; set => Data[0x0E] = (byte)value; } + public override byte HatchCycles { get => Data[0x0D]; set => Data[0x0D] = value; } + public override byte BaseFriendship { get => Data[0x0E]; set => Data[0x0E] = value; } public override byte EXPGrowth { get => Data[0x0F]; set => Data[0x0F] = value; } public override int EggGroup1 { get => Data[0x10]; set => Data[0x10] = (byte)value; } public override int EggGroup2 { get => Data[0x11]; set => Data[0x11] = (byte)value; } diff --git a/PKHeX.Core/PersonalInfo/Interfaces/IGenderDetail.cs b/PKHeX.Core/PersonalInfo/Interfaces/IGenderDetail.cs index ad8c7ddb9..8f30182c2 100644 --- a/PKHeX.Core/PersonalInfo/Interfaces/IGenderDetail.cs +++ b/PKHeX.Core/PersonalInfo/Interfaces/IGenderDetail.cs @@ -1,3 +1,5 @@ +using System; + namespace PKHeX.Core; /// @@ -31,7 +33,7 @@ public static class GenderDetailExtensions /// /// Gets a random valid gender for the entry. /// - public static int RandomGender(this IGenderDetail detail) + public static byte RandomGender(this IGenderDetail detail) { if (detail.Genderless) return 2; @@ -39,10 +41,10 @@ public static int RandomGender(this IGenderDetail detail) return 1; if (detail.OnlyMale) return 0; - return Util.Rand.Next(2); + return (byte)Util.Rand.Next(2); } - public static int FixedGender(this IGenderDetail detail) + public static byte FixedGender(this IGenderDetail detail) { if (detail.Genderless) return 2; @@ -50,6 +52,6 @@ public static int FixedGender(this IGenderDetail detail) return 1; if (detail.OnlyMale) return 0; - return -1; + throw new ArgumentOutOfRangeException(nameof(detail)); } } diff --git a/PKHeX.Core/PersonalInfo/Interfaces/IPersonalEncounter.cs b/PKHeX.Core/PersonalInfo/Interfaces/IPersonalEncounter.cs index ca8f99c83..2d08e63fe 100644 --- a/PKHeX.Core/PersonalInfo/Interfaces/IPersonalEncounter.cs +++ b/PKHeX.Core/PersonalInfo/Interfaces/IPersonalEncounter.cs @@ -13,7 +13,7 @@ public interface IPersonalEncounter /// /// Amount of Hatching Step Cycles required to hatch if in an egg. /// - int HatchCycles { get; set; } + byte HatchCycles { get; set; } /// /// Catch Rate @@ -23,7 +23,7 @@ public interface IPersonalEncounter /// /// Initial Friendship when captured or received. /// - int BaseFriendship { get; set; } + byte BaseFriendship { get; set; } /// /// Escape factor used for fleeing the Safari Zone or calling for help in SOS Battles. diff --git a/PKHeX.Core/PersonalInfo/Interfaces/IPersonalInfoTM.cs b/PKHeX.Core/PersonalInfo/Interfaces/IPersonalInfoTM.cs new file mode 100644 index 000000000..a3ce1cb2c --- /dev/null +++ b/PKHeX.Core/PersonalInfo/Interfaces/IPersonalInfoTM.cs @@ -0,0 +1,7 @@ +namespace PKHeX.Core; + +public interface IPersonalInfoTM +{ + bool GetIsLearnTM(int index); + void SetIsLearnTM(int index, bool value); +} diff --git a/PKHeX.Core/PersonalInfo/Interfaces/IPersonalInfoTR.cs b/PKHeX.Core/PersonalInfo/Interfaces/IPersonalInfoTR.cs new file mode 100644 index 000000000..92a17de0b --- /dev/null +++ b/PKHeX.Core/PersonalInfo/Interfaces/IPersonalInfoTR.cs @@ -0,0 +1,7 @@ +namespace PKHeX.Core; + +public interface IPersonalInfoTR +{ + bool GetIsLearnTR(int index); + void SetIsLearnTR(int index, bool value); +} diff --git a/PKHeX.Core/PersonalInfo/Interfaces/IPersonalInfoTutorType.cs b/PKHeX.Core/PersonalInfo/Interfaces/IPersonalInfoTutorType.cs new file mode 100644 index 000000000..ad8ec8a1f --- /dev/null +++ b/PKHeX.Core/PersonalInfo/Interfaces/IPersonalInfoTutorType.cs @@ -0,0 +1,7 @@ +namespace PKHeX.Core; + +public interface IPersonalInfoTutorType +{ + bool GetIsLearnTutorType(int index); + void SetIsLearnTutorType(int index, bool value); +} diff --git a/PKHeX.Core/PersonalInfo/PersonalInfo.cs b/PKHeX.Core/PersonalInfo/PersonalInfo.cs index ddfc37681..62626f28e 100644 --- a/PKHeX.Core/PersonalInfo/PersonalInfo.cs +++ b/PKHeX.Core/PersonalInfo/PersonalInfo.cs @@ -25,8 +25,8 @@ public abstract class PersonalInfo : IPersonalInfo public abstract byte CatchRate { get; set; } public virtual int EvoStage { get; set; } public abstract byte Gender { get; set; } - public abstract int HatchCycles { get; set; } - public abstract int BaseFriendship { get; set; } + public abstract byte HatchCycles { get; set; } + public abstract byte BaseFriendship { get; set; } public abstract byte EXPGrowth { get; set; } public abstract int GetIndexOfAbility(int abilityID); public abstract int GetAbilityAtIndex(int abilityIndex); @@ -80,22 +80,23 @@ public bool IsFormWithinRange(byte form) return true; return form < FormCount; } -} -public interface IPersonalInfoTM -{ - bool GetIsLearnTM(int index); - void SetIsLearnTM(int index, bool value); -} - -public interface IPersonalInfoTutorType -{ - bool GetIsLearnTutorType(int index); - void SetIsLearnTutorType(int index, bool value); -} - -public interface IPersonalInfoTR -{ - bool GetIsLearnTR(int index); - void SetIsLearnTR(int index, bool value); + /// + /// Gets the span of values for a given Gender + /// + /// Gender + /// Gender Ratio + /// Returns the maximum or minimum gender value that corresponds to the input gender ratio. + public static (byte Min, byte Max) GetGenderMinMax(byte gender, byte ratio) => ratio switch + { + RatioMagicMale => (0, 255), + RatioMagicFemale => (0, 255), + RatioMagicGenderless => (0, 255), + _ => gender switch + { + 0 => (ratio, 255), // male + 1 => (0, --ratio), // female + _ => (0, 255), + }, + }; } diff --git a/PKHeX.Core/Resources/legality/checks/LegalityCheckStrings_de.txt b/PKHeX.Core/Resources/legality/checks/LegalityCheckStrings_de.txt index 231124874..79bafb3a8 100644 --- a/PKHeX.Core/Resources/legality/checks/LegalityCheckStrings_de.txt +++ b/PKHeX.Core/Resources/legality/checks/LegalityCheckStrings_de.txt @@ -348,7 +348,7 @@ LPIDGenderMatch = Gender matches PID. LPIDGenderMismatch = PID-Gender mismatch. LPIDNatureMatch = Nature matches PID. LPIDNatureMismatch = PID-Nature mismatch. -LPIDTypeMismatch = Encounter Type PID mismatch. +LPIDTypeMismatch = PID+ correlation does not match what was expected for the Encounter's type. LPIDZero = PID is not set. LPokerusDaysTooHigh_0 = Pokérus Days Remaining value is too high; expected <= {0}. LPokerusStrainUnobtainable_0 = Pokérus Strain {0} cannot be obtained. diff --git a/PKHeX.Core/Resources/legality/checks/LegalityCheckStrings_en.txt b/PKHeX.Core/Resources/legality/checks/LegalityCheckStrings_en.txt index 5b719e211..860a0725c 100644 --- a/PKHeX.Core/Resources/legality/checks/LegalityCheckStrings_en.txt +++ b/PKHeX.Core/Resources/legality/checks/LegalityCheckStrings_en.txt @@ -348,7 +348,7 @@ LPIDGenderMatch = Gender matches PID. LPIDGenderMismatch = PID-Gender mismatch. LPIDNatureMatch = Nature matches PID. LPIDNatureMismatch = PID-Nature mismatch. -LPIDTypeMismatch = Encounter Type PID mismatch. +LPIDTypeMismatch = PID+ correlation does not match what was expected for the Encounter's type. LPIDZero = PID is not set. LPokerusDaysTooHigh_0 = Pokérus Days Remaining value is too high; expected <= {0}. LPokerusStrainUnobtainable_0 = Pokérus Strain {0} cannot be obtained. diff --git a/PKHeX.Core/Resources/legality/checks/LegalityCheckStrings_it.txt b/PKHeX.Core/Resources/legality/checks/LegalityCheckStrings_it.txt index e934f6ba6..fbe395763 100644 --- a/PKHeX.Core/Resources/legality/checks/LegalityCheckStrings_it.txt +++ b/PKHeX.Core/Resources/legality/checks/LegalityCheckStrings_it.txt @@ -348,7 +348,7 @@ LPIDGenderMatch = Il sesso combacia con il PID. LPIDGenderMismatch = Il sesso non combacia con il PID. LPIDNatureMatch = La Natura combacia il PID. LPIDNatureMismatch = La Natura non combacia con il PID. -LPIDTypeMismatch = Encounter Type PID mismatch. +LPIDTypeMismatch = PID+ correlation does not match what was expected for the Encounter's type. LPIDZero = Il PID non è impostato. LPokerusDaysTooHigh_0 = I giorni di Pokérus rimanenti sono troppi, previsto <= {0}. LPokerusStrainUnobtainable_0 = Pokérus Strain {0} non può essere ottenuta. diff --git a/PKHeX.Core/Resources/legality/wild/Gen1/encounter_blue.pkl b/PKHeX.Core/Resources/legality/wild/Gen1/encounter_blue.pkl index 7950f31f68facb2f50f4de97298aa48aefc781ab..c00c6464aebb2b91376d6fc76181e8b373de8166 100644 GIT binary patch literal 5836 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 Xl`92fXJ^v9dbMa>y*f3rl}i0Tyc6b- delta 1193 zcmZvaPe>F|9LL}6+u8p%yE^M2f&^Y1w%CHO4i<)&1p_5Ilxrz##zrLKYO7YCg2@x zfY5~_OkId}xB!zd538^NA|S*OXoq1aK?PP|2Y$fepb*EP7iM4?wjmZ0;uKtkIrsoy zzzlO948ua$p;MA?;E!++^ui1*!#2dC90cc}1Ql3^J!py1I84GktinY;DP#D}Dh#=QE7UJm=0}^k7`!;k2-$yDOs*WJKv^xJaiml{Lr^}pYK6K|8+Fq+nFc?&J0x6v&Ia{lbSgY!0!N~(|6_5D5HrBWBHR=G#T3EJ{Lx`~dW>5whQ&~m8SjslhMRVzi| zbNj+-&%ybWsJyOP8RxXEaO$j2S3PI6NF>8dGm_j-u9F8$GZSoT%7mJmGvSt&@hbCw zz$u*(HH!jsRM-6w=Y2%=(#`!9HOm_CS=N}etO+WO(SvvL2zTl~_c89*s4X3|BbL%M zcf^aYVz!*Z>#VWmH2S7S)joM~7q5)Bcu0AhUX+H)(}pc)s6^xH>7*A2y!bM%I(6w? z-C8RX=;E(>%33F();fs>cP$Z@&v4SU%E@}M?8PN7Zq-(s{46_m>(q|jx(2u1tW~F( dNjGoSdzmetvm%>RE6QG6N>-cN3sx2D?VnDUzM}vD diff --git a/PKHeX.Core/Resources/legality/wild/Gen1/encounter_blue_jp.pkl b/PKHeX.Core/Resources/legality/wild/Gen1/encounter_blue_jp.pkl index d28fe5dea4f99915557e4ed006ff22b9a327893f..dad4d3b1c5bffdf584280bdf52ff26b2757d144c 100644 GIT binary patch delta 1371 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 T^Uj@ub?45weD+M(&z}817P#fR delta 1193 zcmZvaPe>F|9LL}6+u8p%yE^M2f&^Y1w%CHO4i<)&1p_5Ilxrz##zrLKYO7YCg2@x zfY5~_OkId}xB!zd538^NA|S*OXoq1aK?PP|2Y$fepb*EP7iM4?wjmZ0;uKtkIrsoy zzzlO948ua$p;MA?;E!++^ui1*!#2dC90cc}1Ql3^J!py1I84GktinY;DP#D}Dh#=QE7UJm=0}^k7`!;k2-$yDOs*WJKv^xJaiml{Lr^}pYK6K|8+Fq+nFc?&J0x6v&Ia{lbSgY!0!N~(|6_5D5HrBWBHR=G#T3EJ{Lx`~dW>5whQ&~m8SjslhMRVzi| zbNj+-&%ybWsJyOP8RxXEaO$j2S3PI6NF>8dGm_j-u9F8$GZSoT%7mJmGvSt&@hbCw zz$u*(HH!jsRM-6w=Y2%=(#`!9HOm_CS=N}etO+WO(SvvL2zTl~_c89*s4X3|BbL%M zcf^aYVz!*Z>#VWmH2S7S)joM~7q5)Bcu0AhUX+H)(}pc)s6^xH>7*A2y!bM%I(6w? z-C8RX=;E(>%33F();fs>cP$Z@&v4SU%E@}M?8PN7Zq-(s{46_m>(q|jx(2u1tW~F( dNjGoSdzmetvm%>RE6QG6N>-cN3sx2D?VnDUzM}vD diff --git a/PKHeX.Core/Resources/legality/wild/Gen1/encounter_yellow.pkl b/PKHeX.Core/Resources/legality/wild/Gen1/encounter_yellow.pkl index 25051356c0258d31dcf0f8e5f6d8fcef3dbc2ca2..e412a00c3f85e6066fb6b758017f6fd6c6f7ffc7 100644 GIT binary patch literal 5988 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 Z)hl-P{7*PM4fpWjmaNsjBh$-;&jE2o?STLQ diff --git a/PKHeX.Core/Resources/legality/wild/Gen2/encounter_crystal.pkl b/PKHeX.Core/Resources/legality/wild/Gen2/encounter_crystal.pkl index 9a627c2f595e8e5b64caa2c4725ae8c36b08aab1..a854741a150bbe4f69dd39684acfcdfc2a0d1b18 100644 GIT binary patch literal 19972 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 literal 20040 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

LoW1t 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 literal 19864 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 BbLId5 literal 19864 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 diff --git a/PKHeX.Core/Resources/legality/wild/Gen3/encounter_e.pkl b/PKHeX.Core/Resources/legality/wild/Gen3/encounter_e.pkl index 68c6840167f2b876dca0da09c2b8289ba4a57ea0..ed753412dd87b7fd0b9aa171b8e72af75c2c4668 100644 GIT binary patch literal 16316 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 diff --git a/PKHeX.Core/Resources/legality/wild/Gen3/encounter_lg.pkl b/PKHeX.Core/Resources/legality/wild/Gen3/encounter_lg.pkl index 94b0ad6c33992c9b29e37a0c8d1476c947cf1c1c..780186b9e317f57fc81bf10f41efa6d9146315d1 100644 GIT binary patch literal 21712 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 literal 21712 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 VDB>Q9xQ8O{p@@4Z;y&Bs{$JfhopS&H diff --git a/PKHeX.Core/Resources/legality/wild/Gen3/encounter_r.pkl b/PKHeX.Core/Resources/legality/wild/Gen3/encounter_r.pkl index c2d042018af797b582a62d88ba3e5e8ca5856556..6bbae1b17cf3cc484e6bf5d12ae116fb4970a1ac 100644 GIT binary patch literal 15172 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 literal 15172 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 diff --git a/PKHeX.Core/Resources/legality/wild/Gen3/encounter_rse_swarm.pkl b/PKHeX.Core/Resources/legality/wild/Gen3/encounter_rse_swarm.pkl index d92f59f7967bb924da3de26b2625c14bbbb6d3ff..106c04b2a4c176e4ab2e4e53120882656b086af8 100644 GIT binary patch delta 31 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 gbqAJ&()0*v2I-dU>-cQ4lKez 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 diff --git a/PKHeX.Core/Resources/legality/wild/Gen4/encounter_d.pkl b/PKHeX.Core/Resources/legality/wild/Gen4/encounter_d.pkl index da94fc6aacec9d3412b0e51f21413968ff53c26c..f44e1c712716307dcf89f1b56ad62304de598fbd 100644 GIT binary patch delta 6586 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 diff --git a/PKHeX.Core/Resources/legality/wild/Gen4/encounter_hg.pkl b/PKHeX.Core/Resources/legality/wild/Gen4/encounter_hg.pkl index e658237385d5dad8ea59eb9ad78025ebdc977a6f..f18d73ba8e7ce2d2ed116faa3dd2f2b23c61c27b 100644 GIT binary patch delta 12250 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 SX~+I^#J-9iP3yCf-230qhfe7L delta 17266 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 X>P2Id|DW{;2In$*4!Ljjk|qBQd-uWd diff --git a/PKHeX.Core/Resources/legality/wild/Gen4/encounter_p.pkl b/PKHeX.Core/Resources/legality/wild/Gen4/encounter_p.pkl index 7128790538dc7731571174e394e19485e1e1829e..765d8cd634c5590e281c2bf07c5c8245e3066989 100644 GIT binary patch delta 6477 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 TF~5D5ppU*Te~;XH{ri6bGyFn$ diff --git a/PKHeX.Core/Resources/legality/wild/Gen4/encounter_pt.pkl b/PKHeX.Core/Resources/legality/wild/Gen4/encounter_pt.pkl index a0417d2c6d3ce70bb904322aec96dbe953fdd6e9..8273f162c4605f2f531f340b1f6df85e903f38e0 100644 GIT binary patch delta 5523 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 delta 5294 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 delta 17202 zcmcgz3v`vmwVpZuc_b%+fCG_-YkX;sGuukKr28w-Gq3rM2KOfLVQ&w#Qi;lsOTlc0?gM~;NBE%BV z!0!w3E6~ge7zJ8)1B@LFqd}3IU<7Ch=pg7Us9+50gI0`*K?q>U&9EHgAB%=SGeKuT zTW^6epmyVh7zbJcN}GT>6NN~ggoZ))gSLVeOhzw3=Rn1`3ULSMGf=^8(D5VaxE(q` zOF-{|hTQ=ju_>?)v;eddbPiNKRfryU!yBLtpd+BjG$EFPuDb``0xg&UdC)mf@k}%Z z`V6$;Cy)n4?uA~^0#HIVIyMU(1I+~;1Pz=GkAY${=b)#ccjgKq9z?^S`$0QF*F1#Y z&V!|(d7w8zXF)R`MsF6t&7jK1;SErW8X=wp?FW6e7&;WZ0y+UIUV=KHO`xNooTpF^ zv~(%P|NW(~@EJ4)ss^0{9b5s0E74ofT+lB-JyxM?HI%J^GSGXV9&1qsdgnP9zYgC) zRiM+LHS00SHo)K)Fa$4Ryg@5K`$3f((KzV3%^3f8Hp3M!qsOnJ0Z?%*+zDC(ItXg9 z6@s9-pfTIf@P9$cn;5%a!i}K&L0duZgWlT#eQ%+cpmn>1I1Ebr6+8%<2Ri&VhUQ(! z{0|J;2LofjgYpmInvdYNBPjR;J@^!Ye}M@dOoo zjwh(#EDQma{0;R%qN=$Rr$OUVq<9BZ(n5+gprfF5S4feTCdDw&JkXnf3_5TKr=y`Ku1A2IWi_D=18#=bQpB7wG{iKsFW|oK+yf5t)LU2O>I#Ll+#X% zO3*@3@|F1B0fu*i0iDrcp%mAF=7N3!It}XBMT&OCQbfB!wgj@>(J9aZ(9Z5LDb4{D zmq}636T-bAd^LpoN-?G%8X5rMK@bM*1f2u*xfZ(4&gQ&5P8j%!3=l9@~I?n19MmjUg;LJT8=vzp|GGi@# zDRaejaA4cEQVqOFPpLev;TYK$Q@#*i8jRL8Tj(MTwp%$c7}lXi#3eRHTOa@r!) z+JbN7GAhr@CE3-vR8G@=vDQlE=v?e6A=CV#1)BHy$cQ+4&hoIxO{ucT^8A+Pzg%9x zYDvXDBDvwzCJ+>wQZ!Y8=~~K_1Vc<}}Zt<_x+tZ!MNO>x(0p5a$KF(m}#N z6dMG81i3hl;F<WJ?WtPW8)6jXjI=NH9n~gD!)hA<^$AUK~M};h{#DYs3-i8XjsS z*}4Xyu0cXPMGKh541<9WwQ+JQm6JX$^t7JQKUX92b8F8=Z;%57O%Jx2#w&morbpOe z1XseV!~-&NKt_%n9SEpiZ7NlHn+i~+LviB|cjl@4GseYS-B>GBW@T}Nju;-AH;9^I zIm^?_NAvXZVPxf+Ns;>~ZJ%5)zC{4ItvtF;6o3PUVDH zCa{I7M+-{zCQr_ybHy?^tEiBib$cOqW>S~2wFA3km{`!VrSXyPiYq*CF(PkqDS68x zBS+r4;tDmqs8Wq8ssNF{))#RTYm0xXHWi=Z@kqr$^LS{#(8xH9E^dM4!1LKsM=k6+ zS}pEc0V4gMc8$eoizbacd`+P%?Jz%UQ4u3J9urV<191c`hKITap{_xw3q*qkxeh+t za3h4Pj^WivHMd)(^KWGyKepBOI3Fynrn=2&Hkvvq*qv5Lz>+6_|Po z;`nV*s(PhcYMXSdQ}zN%;waJb64mx@S!EClTUHz;SzaR~#7Z0?dzW~Jy_Iyr!lGTN z7j0>mRd$nTflUoJSh$|&7JBcqJjcwp?WG;nw9+febq~TkF&{wSU;|J^*eaJ+Q;f4E zDw+-gHBz>#31#3lwyAsfUhoV2)<}hVr27x@{9ZGXkhaw4M>lns5P}bM?;wNfSZT+w z#|#A3+3vl+wPO3SC=Rc^OG=$ph*YsMFCMOfYfqJx>EOAxM=^yz#F+rQNPXO6>Sb{H z#Ap}hFiBe_SEe9pQN2ZL!>N(Gc+qkVnBdol!k;!q2SVa;_ydpDlxbHz)ARcFmsdwU z*>lw8i;kwa(UXq-=dUhx*65ui-*=Bxr*r9sx~9Pm6$Mr0Ik9`tbH0OO-k2LIcm{!I zZ>VeZ4HX=7Lxq$<;F)_Vc#UqT)B;~Y_n`$w)PhDi^=_zO+8gQ`obw)3AC=FJt<~!& zAI)Z9Hx{BPM1hb?DG)Nc$JS^K^O)BZqCjZt8icwA<*Va;6Ju!8$1-t5F)%ZeEJB1c z2>Kn{QX@n$(bh1iB^=DWI9gYq7eFcP?kFaRzjbPFzx0G)I+msoyHs7D^n{T26;#unq^<}Tt&RQ(I z-n~ol#8tQ4Y<+$D)voH>Rr21)y{2WvdTH-tM0+2X0vWH;GP0$P+Ih`r_3LXYK(zN| z_wyQ9tIGTD{SNg92ax`;17cFv9vU#y91OCv$&qAwj!tcm>5RzqtSl-e(^-y8x22F% z{RdU5YX?<;Ncr+Xq&)lD#>#VZO*0N7Qf?L1Q*KKkryd$ysU8_z0jeaM2RByxui1RP zw)uJ_CBpTS64Sh-#CnP%Ln!`IK5RXv!J#1o5Y+RAX8U~M#aSiJ21rnXVS}D7^yK`> z3j%H!wgWeBE%t&Dd%=jkV8ue}jp5|8-XnDG=6nTBK+4^`2vIuNy$DfC7`=$eS9fQ= z`fB8Oh>snm#aBm4olQE_(UW)JO{jo`ORtx7kA_XHlGBMg{5wx32PaL5g!=q@y+9_Hv8iZ)UTH*+;8Qx$D7q*H)P-reG zXvCnd7NIo2HBf3$SJm~#bSIdYs5aji@%P2)NR{81)d}GQ*B9y^-VVi4B5!!$88k@k zy)m^6(zwZ9?u(%(q$|)_W-A6a?=G?hS#Y^eoyyHkCGN#Z@O^4}dG3gPsN3*_0iHQw z0NE49)&?gGlr=hG>{G9lrzh1rP^jj2=O){8!&Vx%yUAm9cYEU&3en7^0MGrU0B?GZ zHE)q*ISTNW2RU`^bd1|{jN5cQZqsoy%k+zhP{~W8DMVp~ODU`{iddA2kdl-H1$579 zgec5#DTNtEsA~{fi}`HBjS$6|p=#aJ+}DMX`U z>l%c*2B9_ej~SsDp2q2ML_@-Xl7@s4S}?9|3ek|*8U{_okTCBXPynSg(NP>w%Vsnf zn9Vb?+F?^jU=`0<#3O`ic%P%ks?W?w5Q5?6&DHjqkxXL(ind`u zw%{8_&TSZuyr0ktT>TSo1+oTOfjk9h1u~*j5SIcOXVMC^rI1s>>Pi)^t^m;roKUTo zclAtj^tAW3CU0<7QIj_~HE`BwHDneR_bk1*XYn*Dfj{`V-4vpW9G8;yj4V&5b~R6@ zaT!^;CV6{pYq+MxBr61Lgy_D?rQ|F|9*d2Gf5d>-pMrr}HWu$xJ2}xje~X7(5f`z%y|kJkBQRLmbC8)%>BHadf;AiR?@ulcNMm zV&1>80eacgum|*J#_}5X;KD;W(QoU4>h;qf$ON_Qq0ZUbErA5j89_oiwH8WHCx6-v zl=vM>mf(j7gImf{XFDA;@Vb6G29ff)+cChnO$N5>jMSfc=BaiMk8eZCdH7!N0KE%` zFapoZ>gPPt9tSZPZZgyAz{6cziEk1eRbLcZ67(!?Fy@wL#{63>Sn>$vZ;S1;fh}QH zp^iQ>InR&pI)N?;X)AqxuLFp)&ML>aSh38<8&>puYN6Sl4Iov zv7EC52Zvqry@SIJxR`GEJK$p6@B=&G;)m7VC4<$81>N`A$+ipmj4%WhIj_|eqN664(ovJq_bnQVrkK|hqNAp*YY^%h zgw|pv841`3(P@)&estPoghosS3$MAP6K`Mc;sEvt_x9kq~cT ziBpE@Ei?b#;`xW~$PU)f>GDvGcXZ_+aM12$k@+bHjyUyxLcpbT?6C-Ps{bNn2Nxkb zxQNb|%NOz7xdC&BfBq9k>nxAvPMbFPDroL7!s*=9z*a7~Zc~WnPJX_rYY^(18bIo$ z#o?IGDm92^O*Bf?Xx1=-u*0gFLNsgg@=OhbAm_Jrn?eDuLH9yHHEeMtSb!K5jjG*% z*aSo1P6R~QN@&wYOJfllVPC93d5s*m6pFd+;vWgO`{+ z*x7}V-Lr%aI3u3o15UH2?^Dg6HgD2f(fc)>A>c$h9V~f%(;#yw0g^07gUoV3jym`B zXm#P~3K0EDq!r@V?7)8`KNwZtUwTFjUs|oopD9X${;kkJd$p>5rrhn)Ql>kB?l#+L9;_`C!*zySC-E+&!@OcQI{3EYlqqU(c=;W~_Cqpe;5e0e!-zj=#sPM|D zMPW5;Wx7K)e6+GizYZXmcR>6T;x>4ky{9&PatPnpCu6)kK|i zpf0v=4~+?{^F}(@)56rIB&36=&*NcjGLP1#wa8~{cnIz{JQ%8`t(%(Bc zn?}_GKR=`9{JdICd)~$(O1-HK&zGwYo{wP9JN|q;5K&4-J-MM=y}lum8%$%>$+%4k zYDBiw@luH22w8h-!w$;YZ+Wpywcc0-Yw|XhL0iqnn;bko-Q1fVZC~BuLvniG)?+d3 zDkGsnAD8_GVcZPz*SqZzFMjXSNK)PSy$^^+A3S|4tcOUBZ;I3gAtQ(Tz2ru~^x;JT zO%uLBStLEg(@vM_!6L*{mXHo>x~|V}YMANSvL#Jp!?TE{=P2|aRmf^C_Q4oN4jW^x zc;GQ2V>HsnXrxWh$f1UTOmjfG5zTX0GkAVzo@2Dso_?*n6Trav@uFdOUhS~gm+5i( zWe0ksyfv8~Gk!IK9=qOt7o%2N^BX_@^*|4sz6eNiDWRraAHR9qLGXEl0AKKMm|;s` z&x6NEdPv{eHP1&{655fVLu!Z#H#4GsGopUiM&7$19rR6Q?_PL21_;j4I<)IdMdlfY zfoB{hIIN?T5!GcxBTtCOmJp99A!_u?-FsxrS5QFgdvPED!k%ywiJju0DU3mB{0M~{NMMZ>q`qjr-T*^M>Ef z$LAsaIr+eR94(F?h~abU@96Wm{+xPHV|@D6)Zf$Ras4^b=ATrn3!m8PZQDYo$I){2!=qGv_R$8_qsPkCkYlJ$ho56-)W^rF z)$UJib=^e5XXUEfXLQ6G`kB5`;q!RpZG{hYlR<~@JY2G#r>HSrG(=cqSywb_f_O#gz9hV(6{ z>b}TE6X(B(yNlj(sWs=z)o;$jUDzXT`Ra@s|5ddb{txReI+41?j?7ZC{?S6c`j0da z-0s$NlYMK$7slG7D;HtaKP@8jf-a{!Ia2uk?U=YB6ii;))(K#UR;2h0WWfC#y%i86L0 zCYPYYAE#2ALbqf1xs*;R7a^=%!@CG=b5p`HeV|Ds(GieSO3>sbml`070d(T#-aE!-1{G7@1#2#3Xlshn>#5PD`!h_bR`tc#t*Z=odzQq-(5(Z9emUtb%9if7mk|uCNySJJx^L#7(PKHPYuFQo28^wqpM24vIagflR&|s)ZdDu1iB-s= z(nll(p2GEA2)>)V@9u3c^WE`nGyP!1I$D@gegDtDj9=O?_O2UC_T^^#Bz68fsEkCMtsKR zUyNWOnAB1nQ9$8R3LY0B4gG1{#rJ(+q3 zj5Gfx6-N|fSObl>ZPetWg$N=6_hvktpx^JFgv%&~gxqPw zN^l%^R-r_$2xZBIh$Lty4CWKSnQ(*o_n|n#|N093kB8p!K8#lKiZI5!ybp_@TT>*l zNVaV(syAvnlvH%ZsLkpsaWm@3qZWz6)nX{T+&Z6-5FeBJuCx^Ozvq2S>bsG8_a=HE zigl}}w*KZx;pg5Gs_AZ_2hXZH%&NRnSr(Hieu0>0CO{lLXL*C{^my8$MHZok`GHa# zp|0Vfu0g145b7F)upTo54rmZ68`K{I&i{Gzwnexyn%_vp5o#D7YM6iVK@EeT+0R|nssI0+8@L8XNXwVfO))Y%Si zP!w973SBBZQ8#grS`-(DE-s=if(}AA>Co>a?^K6$IQKjE-0z-yzH{!v)WX#2Rhgoi zL$y+M2-WmErm_3r2x9&0_!?G4PSK4QCAvY#<_2@Jd=H$JGHE?>#+8C=&Q=`2qhxiU zyu3AU$3w1ln|$he%;apP9W=9*0jt&Hv=6MTmlIkuRUav;`B0E$_>2-e;cWFHg=Ic0 zmpJ8FfK#posS-^}wMVGdQYcE4jqnK+?Lx^LQ84n!9-v$+LfVs2(*7{|4J*`{^)&~$ z(+f@mxZspOQQ0fp zB76-byN%Q4JDkC-vot@X{nr0ArLTe2yBn{)3hTJ>C%5+KZd$=3#fB>J$Yi-R`*eV nfKL#Q0=KcRG2mq2#DM!i4LAm@0(ODu2O7Wt@D%Y7FoykKX0zB3 delta 957 zcmZ`%JxE(o6u!^!Vl*+ai8sF{Py0k$G^YL}FH)<5U@DqTR%yw57$x!NoPd+vA7J>NNZd3Jer>q1pj zbEH8!oI*7N&Ux$>ogu6n&drD_@``RuR_F#Hn+MG4%CF$8tI`^EC6tnDE>s=BqhyVs zyr^EX<6-xXO+IsvF*#Rb2hChf&}#R(>;o(32uq=k< zDyRGzw-3T_9u|#2t5>C4Pt#k2q|Pz$Np7_by>~%PeT67SSuu8&0uOk!f(AG*Z7Gqp~U7 zBAfw|-N0$cXo5#R%0 o6gZA}47iVdy#Xf+Cl34u)PT=`wZI+_13&{91fC%t2F9_!1Ov<9=l}o! diff --git a/PKHeX.Core/Resources/legality/wild/Gen5/encounter_b2.pkl b/PKHeX.Core/Resources/legality/wild/Gen5/encounter_b2.pkl index bd8b748456a3c5976b07dce786be159d56fcaf80..74d8ef46b70415bae3b2150fe4eff4975879cf7b 100644 GIT binary patch delta 1490 zcmZ`(O-vI}5Pr*6p_EYm7HDZH0?HQ9!U{BKp+ajxsKqD=)nI}iJgOmzCO}q^Ac-*= z*NE|;30@2yKsPb|a3FGNgb))wcrcd43sGV)G4bj*-F?ad53}E!neWZan>TM0(?Vie znCr?AM9tSAiQAc|J&H=&<%}1w{7jd$u=N2}Nox_lzpWkk1~X~hmpP0t?YU^|xnn!y z5LrTy1E-lBNC-;g12bd@1l2YS?;yM<;2ngQ%O!YyF-eoN%#`}CtWp87DZ8A#VrJO^ zn%zES+UM<@JekAE`h4zDzHcGVqRaVCQ`O@I4+W&xka|~|9MDi0mntUe_CkM}8Thut zq74*3-=x(#-a+%olGs92XSYx5 z5FrVf0h3Dym?iF~X1Xz?OS-$M@U6Of4P@0OX>rdOHc+!RJp9r&JQjVSEXKQ0S-yfG z0Vex#dVhc^e`NweY!yppfb|OMHXW7hNw=h}RepoT?v(VkofAA*<>ZDyXRsEfm2Q3R+Ks^Z| z5c$Fk@gPd*5WN+e!Vze}F0PHHG>6{Xtx!|w*Q2JAa>5m8G>dbG=})xPBvpgqi_!Dj zoSX_EDTQ}2M!&USPmwAzdY%*|i6^>hN;b2wV|Yk;z-Pb$;51MIE&>aIErRSX2D*R_ zU@z=Wpak6oEQIa`E(1NlH^4IBDPTG9EqDspdUC2dd;+}1 Kw(03d+Jrx@412Qx delta 1490 zcmZ`(O-vI}5PnNrp_EYm7HDZH0?HQ9!U{C#LWS0XP>WF#s=)+3cvM3aO@I`UAc-*= z*NE|;30@2yKsPb|a3FGNgb))wcrcd43sGV)G4bj*-F?ad53}E!neWZan>TM0GeTlU znD5FEEUK?TH0@v(^-)AruVlP{8mbm6cqkyfiqyN)Bt=DGT&kEwvlsf)jKH@Y zW_6(W`4+9#@eZ0t5=|{cb#@E&78XM!UF2{K(MYbcfA$m5xxlX8DEW#Y=Uvpf>n>`= zEFvT!vtV-R0JFsX)JQjubV+wN6~0|puYnx5iE7L`qZz-!;j@l~tM5sj7P^Djf)J zH6js_s)%@Htm0nsOnZ6gwQ93EQqB7ss^OL9)biEmS}Jn83Au@4XhJ^i;U~SYmkJH| zC`X@f8eht6uA>O8m@&HKR?HZeAR>IP@hUo(8m0q!HM<{(d>)kcRMVv>x*%0o<6xDc(F*1geve#uZqeLkQ=UmiWP_>vcutGrkzUcYL4mU1>L*=>r+1 zrSkh7>mCVuMS`0Dp5U6DuS9_D&hs*W8Hn<02bYDx4D3a21~g|nm=rvx7J8~66Gwsc z6vBr>@=SFq-FBNSDe?rwvLKEFNhj$iqOl}XH>08+-i&H|HTKEFZ5%JD7>4sYu9NHA z#19ZZpi5Q6Bq5!o0^*zGBCMOZy$B(c{X7HfWa_=Bvd}|~I|VO#4xyCO;DytV1#dOI z4(&mPCh#mHCctZ1ueOKaJ!evdZXGDXdcC&}D^2<)vhJUF7pxi%Fcp65h}^33(Gso50$%q2w#PxHZC@Ue!EYR+*U{@~PW!u%1b1qfI_MTD z1?%L9mvutqxpZ9SDHNr)Q}mkIS$J)h+_sAT$tZI;5*#MfZI4HfER#C;APyWfNMDS h3_}@(k_LVOW`VQ75by+uVX_0Gz;Xmwn z7FXFlW?EUFX%R}%n9Ao2oeyZUU|fUc6@+kJX^IbwnpRU(KJAU-d*AyF-xXE2Cy%6+ zrph0+t-B=X7741phk|RgzZC(t+b_!ihCjk@99U1ibm~9>)|=fmSZUI?k@fJzJ768^kvYO9<#37;LLYa{ zgNE0$9)2nNMiji2YvZZh>*mSc%I(Mr{yA18b=s@9>XfLjxmtSb2u{0wGVMlQPGuwC z%YXFGyA*L2UYH8Mb3$%a>12^s#A(}OAk(%l56IxRPSNY=^)#o$T}XgCF-RSBij;(P ze8|l@Ci2XjmU;38sr@gw&Fmt)Hj7SMMgL?5)?b#}Rvo8|!wV0bH!{ssc9)r@pO7z# zIrf+J?~9);vI!Qj0>JA^!0G_50Xu>Ja32P)0CnI;+(&`iILCokfC=DL+$Vu+ICl*~ f8HSPqeg|fNv%nzm42U7J10z5c7-NfkY2@i1<-rjD diff --git a/PKHeX.Core/Resources/legality/wild/Gen5/encounter_w2.pkl b/PKHeX.Core/Resources/legality/wild/Gen5/encounter_w2.pkl index fec126a284ef27ded10dcb5cadddd97d54ad83ee..f2d217ba483c96d2255a6de71fe74bb091fb2fcd 100644 GIT binary patch delta 1381 zcmZux%S%*I7{9kWOda1Nl#5vu(gSgoBvFytZ~Xx7XA0wy)H$4nLQJtkz8q%UYV(n$DN!Sg584KF-&}nAt&AVo1{{jC zA$x;YByVs-_C-HR2Hir8u#@rGH1e3KWXf$wRJ)l?OWKdgP*CF1^esIoQ;K1dram_1 zYwAnmq)lZAV{I+-yy>U8vV@c;vn*OXdrn3%9EF^)d4n8<2=YjZmX;GZWCo7snSpt! zgHkU9n9_*Ui5{l8@@ptc98nDNMdOG>G!B!Y0&4w1!LHu6J8)AnXhU`fh{CX$EF6K& z??ST7EqZPyn1E)xlxfK#J;DEGHVKokQ?&0Yw(z9$1>9*!;IwsDOw7zxLWS>_P>vM0 zxWYZRXlGi__61sMYV-KCa2)i|EmOx2VFD$u_I`zga#WwB`&Ru-c?8|aNfGv9nV8pX zxrJAhi<*9w3;CN0N<33Z<*0VX*DEK?n0=?VFsgC$QpWW$(kSI?961`QM7MiYWEa9F z(dC7(NrIZGm1U-&+Qu3>4u!~_9@Kou zcu>UCb2yGY=@YHObE#E$-ieA+OPkRmQ`+H$CV8ZtBx(nFc{(U2t;;C1&MpTJcD^?yV|Z20 zt}bekk|xZgPr60G`;a7h=rK@d0 z&KLb`Qo3Z3E=bk delta 1381 zcmZux%S%*I7{9l1avTS*rbiteo6)gme5Fl|<71o|Q^)rR)nXQf^gvuCNmQgZzOY&; zoJApm;Gz}@Y8OICC~6}mD)a{wxJW8;f|f%4zI*SX7A?N}JKy_pzH^tCEtn6#Y}e~QEWywHEBC8LqUm4Gq$y$%v21Mbmg%j zUsqo0Cv`eg7^~}9=M6vAl`W(^nVq7>bLM3f!%@gdt2f9|h#-$-R?~9>M~uMnd?PR~ zwNvWF05dfqb)uK4u7X;M5=RuBe9<@}5lz5ksE}HJP`IbH?GD_MblQ~N0irN$rW_-% z`RyRfyrSnuf=Ot0N|~B0(h~e{W>YW;J4O4h;uM~AzJNOo37op&iiw%IN~rLI63UV4 z7FW3M7VXSv*}gzaO>Lc+5srf%x@GG4Axxm;HQuj~P>z~1x^KnLOpl-&DHCBYm5X`J zRiyCB3Q^Oq3L$?}Nr`8xs2s({_(s*F5%c1yZH#KdxReQPj5JF5I!BJiYSHa}HQ9x* zNpyK3Y?7cBYNbZljh-euveC&Gy$oBT4A@=siJDu_P(`%mnUK@2M$VE%@l%Z+|B7~j z-rx;n{C97&V13{hQFd$ffszkh-d5m;802ofXnvvL?pz`?Mk?v(%`ufr$j^%$p{tkx|zJFk?+kS-}*Vy(BmqA$70JK`J?4R zaAdjKO8P{b@LX;ao_C|-)Y`7M$V?sZLX$kwK@z2tygZ#0lh$PvT4%SN2fN-Ik}bJgT`40-9c&-2d diff --git a/PKHeX.Core/Resources/legality/wild/Gen6/encounter_as.pkl b/PKHeX.Core/Resources/legality/wild/Gen6/encounter_as.pkl index 45ac6db12ce785428c6540efd73c715720848992..ba26e0162491ba7907bdc0ee9d815cbef26fcc0d 100644 GIT binary patch delta 710 zcmX|-KS%;$7{)V%Zn(igqeRH9jLMQ*?VveONIn0YY2K;lsd0nQXhXZ;+Zfm&v;;ad zIy5*+G&l;iHP+T**gYTj-SY8!-sk<^_xZlz!ZTcW#%~v%4N7?9B&LE6>5RH5#nJvW zoM@WsDbpXW?quNiGVptu04+0THpz;zzOhD+N|?rqK(ERsvm^cNkqy|`%JPj$o&y^p(SWInPtf^XUA}vn|O&n92o#tOAA)3MlqfiF~R+lFCM^xcJ1*mC7!aixOEy zf$ocF7!}d5ss<=@iTtHYu4ham@p*}-8#;7Kf2D1^8*Zx1-Dj7)SG=aW^x~3O;jZq| zq!PrxeO4s;sR&-5#};8tqGQb!dvvSeog)nq2f7_u-)9sdOJ_fz!}(=rq6+@b2WV2o z!&X()hZZ4IY|Hx%IzW@F2-uv(RpRxXDZ18pvo1=U@M`Cd)B!^L_sD)ZO zgp)bs`i1GQNViq^z6#%0lQdEH0#Y<>c5a65v=j|Afu6N_W~aMHTLEBW^N4SJiD>zl z*V+-iGWtHoe5J%we3Z~RF0m~IJw;Vrpq7r|JsriaAydK-NH*9=0~hbvIW^d&swq>; z6zIl8!=s6YX)Q_1W#q4vxqf9DiT5i!T|cB<`l~Dk-EfOl?mk2mKjAeaqNj*Ni@Q!l zLu(2DHnL>;v4nUc7KoHB)3zOnHM+9#&PN*&drlD9S!a}{mcxF)f%D7Gd<{GA+di-*%FB^7NEWDqRDreHE<=GFw1w-R5-=%&MBWP zd1%de&>2s`v)(Y-Vw(mCe!S`A%S=>GnJul6bN3 E519he761SM diff --git a/PKHeX.Core/Resources/legality/wild/Gen6/encounter_or.pkl b/PKHeX.Core/Resources/legality/wild/Gen6/encounter_or.pkl index 84a6d5bed2ca8e502b5ecd95c0bbfae9c3f6140c..be4e833233089da9852a89850858c9290287122e 100644 GIT binary patch delta 710 zcmX|-KS%;$7{)V%Zn(igqeRH9jLMQ*?VveONIn0YY2K;lsd0nQXhXZ;+Zfm&v;;ad zIy5*+G&l;iHP+T**gYTj-SY8!-sk<^_xZlz!ZTcW#%~v%4N7?9B&LE6>5RH5#nJvW zoM@WsDbpXW?quNiGVptu04+0THpz;zzOhD+N|?rqK(ERsvm^cNkqy|`%JPj$o&y^p(SWInPtf^XUA}vn|O&n92o#tOAA)3MlqfiF~R+lFCM^xcJ1*mC7!aixOEy zf$ocF7!}d5ss<=@iTtHYu4ham@p*}-8#;7Kf2D1^8*Zx1-Dj7)SG=aW^x~3O;jZq| zq!PrxeO4s;sR&-5#};8tqGQb!dvvSeog)nq2f7_u-)9sdOJ_fz!}(=rq6+@b2WV2o z!&X()hZZ4IY|Hx%IzW@F2-uv(RpRxXDZ18pvo1=U@M`Cd)B!^L_sD)ZO zgp)bs`i1GQNViq^z6#%0lQdEH0#Y<>c5a65v=j|Afu6N_W~aMHTLEBW^N4SJiD>zl z*V+-iGWtHoe5J%we3Z~RF0m~IJw;Vrpq7r|JsriaAydK-NH*9=0~hbvIW^d&swq>; z6zIl8!=s6YX)Q_1W#q4vxqf9DiT5i!T|cB<`l~Dk-EfOl?mk2mKjAeaqNj*Ni@Q!l zLu(2DHnL>;v4nUc7KoHB)3zOnHM+9#&PN*&drlD9S!a}{mcxF)f%D7Gd<{GA+di-*%FB^7NEWDqRDreHE<=GFw1w-R5-=%&MBWP zd1%de&>2s`v)(Y-Vw(mCe!S`A%S=>GnJul6bN3 E519he761SM diff --git a/PKHeX.Core/Resources/legality/wild/Gen6/encounter_x.pkl b/PKHeX.Core/Resources/legality/wild/Gen6/encounter_x.pkl index c1cb9fa52f86706d4cf0040b66ecf5a4b36d0841..54a62250826e31e068bb8d57d5f2bace444c2a43 100644 GIT binary patch delta 313 zcmX@o!FZ&Dal<7`CU%C&8yIa^_!yuJ0T@FB%3zjZV4r;1${wat1tzWr6rXGj6KB=} za)oVRToyf;G9!?78+%5etSyKPwuPx-wgX8axGq3$upM013nXg?)@TnG3<3&HMsOp5 zTww>eYz#=&0i@+Jm=tyd+vo^akO49iEGX;*7c2njLU7waW;%mq4ID%!XEeYz#=&0i@+Jm=tyd+vo^akO49iEGX;*7c2njLU7waW;%mq4ID%!XEeYz#=&0i@+Jm=tyd+vo^akO49iEGX;*7c2njLU7waW;%m4I>XdVzTjK}0K|_- AEdT%j delta 308 zcmX@o!FZ&Dal<7`CSHcg8yIa^_!yuJ0T@FB%3zjZ;GKNg${wat1tzWr6rXGj6KB=} za)oVRToyf;G9!?78+%5etSyKPwuPx-wgX8axGq3$upM013nXg?)@TnG3<3&HMsOp5 zTww>eYz#=&0i@+Jm=tyd+vo^akO49iEGX;*7c2njLU7waW;%m4I>XdVzTjK}08j2o A9RL6T diff --git a/PKHeX.Core/Resources/legality/wild/Gen7/encounter_mn.pkl b/PKHeX.Core/Resources/legality/wild/Gen7/encounter_mn.pkl index ade355d4c93f8fa3b0634085442d4b9bfa2317d2..a174a8666a6b268f8f92280420e8455ba9d16346 100644 GIT binary patch delta 684 zcmXYuKWG#|6vp4%<+$6u{X4sJtDcuTl924(f(tpky3D4nVYn4*2Ks2AeJhnrbL5H=yJ8y;vKQg*62rU|$ir-R;W zP8XWyWVYjs!Rc-jI_aKJId>ej$5FeRtG1c0ktwc%b8L!vK=3Cq!5laRPJ<;1qfc5G z)v*#di{1Nfgl>_i{=9(ij;C&A%~NN4?9C#&jOcGq-NHm6C=msvI=F~_myv1uYNk~` zfo22U@>R#pyv%<24qPf^=82(!D?__Ny~cH+PPiph?H8f`wlB&C(+%{!iN2eKgV}V@ zLi|cF0$mTfKGRoC({H2V4!Db|KS5Gwx`(f2s?^Sd2KcB|YNlSP5&V7R9)O3ao()rU z>Kih<6(0NVc0v^VQQq7UddAv)rFx4TN>O951o>X`8S*q!O%EdEG&(ZNEcm+17 u)oy@hq17g=uMtyo5@~wGadLs;uDKcMC4$@RIWa5dz!jn?6fDxDi{G3Uzi+;M@6DSxvwP`Y`h2daaW-F^ zfcA=OP&Q;XWe>wG+0)R+1MSa=}PHkods?=AG*C>+eD zf)?UegAwRj(Dj+V>AGyo#{Tl7O7IZ2pZs%Ua46|rAF`%kb4Lop?W4v z(W!6B>~?tkzuOKixSg;H%}X^$DrfOunuW;@(PZZt_VuKClP^+D|4YuFV|sy(ufS`t wPOWwWGz+aZVSR&`nv+O3A}vmqDNdf6ak2#eQIC_i$iD;c!3W}(z0zgvF9ZI6b^rhX diff --git a/PKHeX.Core/Resources/legality/wild/Gen7/encounter_sn.pkl b/PKHeX.Core/Resources/legality/wild/Gen7/encounter_sn.pkl index 3a1cd0f6dfde6f6e76f0c625685f8cbf91bd6ec4..cc1c936b91bc223bc6430c7e12dec461868c689d 100644 GIT binary patch delta 766 zcmXw%KWGzi6vyBD1?hQza=F|ku{OC&BATQJp5`=Z$e@^^MQsBLcB#$g-_0(9V6})2 zf{FnvD!8e2QB-WvViX+;4vrZLIuvOT9K=D;#qTfT@cF)X?|pyo?%rK5=mk$FH0E|w zt3t16^H5Kh`J}!FI^Wl>9weB?$c!i1jIRJf?hvtMVx$X4B^gQBiPBbCjRxd!(SprD=Ugdh@XXq zsA;Q0M2JLW2l{24tw!rOI}<$s?ez0M(GYoHHe}r_Y+%|8-+j}Q4l`Ag@5Qtq90XJ3 zq&^5IRYD{%f!c4@&F?}tFOY8j00a(Uh8goP?Fh0kCU-RxD?snYMp2zcbv-6`Q&#LG zk)14o6PR`i9p94A)Utf&Rm&e_nj_V{2)+r`)gr2k9l2-V{A6u`=cg5Bn7#-%mtr^9 zBsWLEQQX`bYG>hV#N{_T7q4ShL8QGuYe_05{?KXg5ksw{SI0ne0(84Bm@OR*ht` zg#0#ocfdWkt4@GP$DJm0(UIHl_Vt$|x8@}d8%&`xQYRXzKZbucA$QtI$bVrqF*(lk z43l1fmtcV^wP6q{l^P)~q4xh@NO93WMn(VO#-iUs{!SGASLiQ;H{dPt^V#G{{tKbS BgFyfQ delta 766 zcmXw%O=uHg5Qb;JAYJz-lg)0j)+W12M3Z#E)vP8BIVk4P;!gt#_M*+r-?9BVkewl1P?1zshb%i@E zy#~Fc&qIAf=2ONF==?x?MwnunAWo(gPA&mL?htoIOxamSOzS}gc%Xnz+bnKp+C`e# z7n(V)Xr_VK1%%orxDL^fwxA4YWkdo?poEjJ%@Mr0XNFsuR>Z&FX86mb>J?Sh3GuVg z5p{i8h!~NGZ9%_+v$c2wXJ_Jjpxr_KCmtaWxhd;hT*I^zzPs#82fOvb@1or}zjtsa z$NeB2w@i*pU=p?8ioxH7!RN@}AArDq%;1ENX$O%-3AwA8L=k#BF^=jqs;ddPn~G|u ziR^S49K*B|=meI$Q`-ulm#tu!X^u4SJoqLwPmgIHcI2Ic^OLm!o}X5fW%?q#ysLQm z7I}FBj_T!CP&*A@Gb#VGGsy;K6-CC6)QsO&GX5f%0B7Z_WN{?$UnwB`G++JVI+cYOtpYv4LuAMIwD=?0#rDVsYCM!|cL&1tc0 zj*#C(?-sZNcg+bg>8R6!zHsFBdjtLD$gTOQ113|Xjx~tJ8V}*0P05{hQ}SC_PEGA& zdV)#Mz;m!b)%qxi)M}j&U!wN^TX2<9aD+<1{k5f_jr^S`1+UOw1aH7w;-|CenNZqM zG9jJ*dDZF969twaho=?l!_yAcf=a#_UELyG-CL*+g*~5=tz=W-3XWOdrsi_EK=yn6 z+#lIXJ{>uWu0<+%cj6t4dU~}$I5)J5C5B-S?1Kr3+fR+ST_EN`U_bSi1gxJ%!1}8K z)*13&AaHCK*?-j3^^rYqs0#l$Ie%%4G@B(#4uk!Ehr$a-Tc>y^x`H%VNCVK_~H zDLIJmWU|k%X~#&-=^pCN*0)O2kyc=t^(+e z7e={q9CYVBIx}u&M#&0atq^o-i^`VI8SF)9?9;x7%@o#D^MG9oU z*U$aYz2uGPS#&L0!MhW0HRkEnf|0(VT`VySdte_-NZfvE#O(qx4+8tCwhpPa( zK!3({TrhBjUIMi`183J0Hpa59T@Nm+%VSz*~3+ n@8JV{gcbM%U*Iczhaa%b^qV^jzd1%6X+3ZQKGlBa?)LoyKRuF_ diff --git a/PKHeX.Core/Resources/legality/wild/Gen7/encounter_us.pkl b/PKHeX.Core/Resources/legality/wild/Gen7/encounter_us.pkl index a6c597b4464631d6aa977a386d50d6b40668aecc..9379b0fbf53fd8560a4961075380d7746d1ea061 100644 GIT binary patch delta 780 zcmXw%-Ahwp9LImpS<|!Ga&tS|IeY1xHe$}Lgp9N%*hPe8Bo>sQIif&F$nJJg)J0KJ zP||^l2!slvE;K5-k|rb~6(JHC84gU1_FQu zD7irPBE5;k2)zc=`#fc{98t2YX}+t>j>B~lm(1Z!N^anW#Lgap7C5Tx>`Tqg27Pu` z@VA)14R=_Pvb<-nT6RXseXUSRs6uIyx+sOxgFvAq)Vt)aH5l%^b%1Ot>7Cz`tneP% z^p3JfNBI$n%38}^NbY7Xk!nM0_~WU|q@HlrGk8vFCFQ;QMA|;5WSZU!n1K$>O84tl zx|7-`R$5?={yc2sulfH6y~4kNx3B<<@DAR?2lxn|;4^%Iukamy!dBg{@6h~uKeaC? OeqG>~sHe5`9`z4kCz3h< delta 780 zcmXw%%WD%+7{$Mtm}HWg-n=F=lbPv^36f3{Ef}%U3Dkv1HDalP7FrubAz;C}%RK~Ae=N7v7o$sFSp8J@`L}jA#bSfe+ zZ#q(du12mw>zzH&+nwXkAmiF#XGKQdY((`XiFqtqkQu4OC=CqI1u~c!i1KY(8)R=X z8qgSxP$2YJ2!tF|0t=uUx#?&Qxs~W}gwb~~7$ypax1!${%la8@!>Ar}k!boidGoP6 zM*r4)AzsC}5x)p+$6aK1BkLxz@U=u?GoyaoWIs3nMo3oYMOn?GI)K1IetJSj{!OBQ z^+({_iDCGoNq(Z2Jb~^g?@lw7 zLX0jUdl|i^GKOA<%0G{*x-mwpqUgJh*-3B{i7RS-3!__bqhw`{fjl@aSeZG|%7lGZ zhT!jD{w}zO6}rZsy`fnqqlcnXR0O9ug}O{m@lnVr66$^AZgj}rqIL*bJnlU74 zMg?_{G=snb`io!({+jha=r#OX@D412W$+$+03X38@ELpoU%@x<1N;KpCBL*w^h-mi RgJJSZ1b!2H-ZJ(H{{cyQm<9j< diff --git a/PKHeX.Core/Resources/legality/wild/Gen9/encounter_outbreak_paldea.pkl b/PKHeX.Core/Resources/legality/wild/Gen9/encounter_outbreak_paldea.pkl index 502776f5758cbd27100828be148fd801f0eac5d7..a710eb534bba5b25d5c22d8077613cff8f429073 100644 GIT binary patch delta 3088 zcmZ{mNl#o?5QY0S-GCee&Ct*T&Z5X8Nok(mG;$PtQHiH3QDT9;P z&MzRAvbB*VGbD6lvW;XD|ALTRHpxw$Q&ml}cr2i}b*k$2efNC*&h~PD)${eAlCz0q zJ=}U;&8=rLF`Rr_>OgSeV%)w_9AVfM+cWaBx+K2}i1cSYynbHIQxP72HpH?wy5sgv zk>SPe7;2Y_(tK^ND!)J4t8%@oSJo44-QB0HGnvG@))B0SXRLW?H9cc7Y+6mhYt}LY zUZgb(`{r_hFWZ$ks?OPg-VYkit&Tpdc zhlkep$8WT6Wh92VoM|3W^Q&vd?w308B&xO89-h_u^BMdX3R~#(&d=6q>%Mjxk>l*i z`_WMI*fjUPRmtc?47Xi!M#=au*5(t_j8De!hig9A#;9%A{BD}b=@@Rd+o%(2k|XQ0 z`kl_2nu+0sYnJYz&#fbz`WHufI@52(aHB)7)%3hvpWkq;UQ_e8X=bj(uw$AxMZa6) z)obwTHEiOe?@PSWR~G!SWHL+kT(a_4?i~wWHgxdZRk?SaI(S~on&6B2W-ldN4jy@R*cJi^og5qR;hbxI`c0_r1=*;`o*&^v~>1BN4SkS zLTt)#${-K&P~#>s%R zk%1%T7v(;ybh)Wg1H?F_X@EfPYPj=Y2zz_lw7m%>xVJP)plb2De5MKRZT7e#->^vw z7KrT&T^1D<%%{MDIfDgb`&v&N7FcvxAPxeHHVMMUUYV1f7D%Sif`vj07M@z6;{wSv zTrj7&VC~Aj4s~9zF?fN%ctPQ=2^|>7rvZaG1qN&94s?hUgF`?J1WpVtp785GX%Pd9 zX~aOzh`}j6hdRZP!G=Hv0!IcH^<^MwA%lxR1_DP07xk4u7XR}~Add{lK;Dr-t-cr} zEo5*J$Uxx8K&-C^vetS%kd{COl8y{k>q|n?LIxLs3kTIX{y$_fqWV_kRvx(x!bhu0USuBfde@M2Mgzp%l`u2EO?y& delta 11 Scmey-!201ROT!k%4@v+eFa>@9 diff --git a/PKHeX.Core/Saves/Abstractions/ITrainerInfo.cs b/PKHeX.Core/Saves/Abstractions/ITrainerInfo.cs index 814153aa2..3f5e11203 100644 --- a/PKHeX.Core/Saves/Abstractions/ITrainerInfo.cs +++ b/PKHeX.Core/Saves/Abstractions/ITrainerInfo.cs @@ -6,11 +6,11 @@ namespace PKHeX.Core; public interface ITrainerInfo : ITrainerID32 { string OT { get; } - int Gender { get; } - int Game { get; } + byte Gender { get; } + GameVersion Version { get; } int Language { get; } - int Generation { get; } + byte Generation { get; } EntityContext Context { get; } } @@ -26,12 +26,12 @@ public static class TrainerInfoExtensions /// Pokémon to copy to public static void ApplyTo(this ITrainerInfo info, PKM pk) { - pk.OT_Name = info.OT; + pk.OriginalTrainerName = info.OT; pk.TID16 = info.TID16; - pk.SID16 = pk.Format < 3 || pk.VC ? (ushort)0 : info.SID16; - pk.OT_Gender = info.Gender; + pk.SID16 = pk.Format < 3 || pk.VC ? default : info.SID16; + pk.OriginalTrainerGender = info.Gender; pk.Language = info.Language; - pk.Version = info.Game; + pk.Version = info.Version; if (pk is not IRegionOrigin tr) return; @@ -52,12 +52,12 @@ public static void ApplyHandlingTrainerInfo(this ITrainerInfo sav, PKM pk, bool if (pk.Format == sav.Generation && !force) return; - pk.HT_Name = sav.OT; - pk.HT_Gender = sav.Gender; - pk.HT_Friendship = pk.OT_Friendship; + pk.HandlingTrainerName = sav.OT; + pk.HandlingTrainerGender = sav.Gender; + pk.HandlingTrainerFriendship = pk.OriginalTrainerFriendship; pk.CurrentHandler = 1; if (pk is IHandlerLanguage h) - h.HT_Language = (byte)sav.Language; + h.HandlingTrainerLanguage = (byte)sav.Language; if (pk is PK6 pk6 && sav is IRegionOrigin o) { @@ -82,7 +82,7 @@ public static bool IsFromTrainer(this ITrainerInfo tr, PKM pk) if (pk.IsEgg) return tr.IsFromTrainerEgg(pk); - if (tr.Game == (int)GameVersion.Any) + if (tr.Version == GameVersion.Any) return true; if (!IsFromTrainerNoVersion(tr, pk)) @@ -101,13 +101,13 @@ public static bool IsFromTrainerNoVersion(ITrainerInfo tr, PKM pk) { if (tr.ID32 != pk.ID32) return false; - if (tr.OT != pk.OT_Name) + if (tr.OT != pk.OriginalTrainerName) return false; if (pk.Format == 3) return true; // Generation 3 does not check ot gender nor pokemon version - if (tr.Gender != pk.OT_Gender) + if (tr.Gender != pk.OriginalTrainerGender) { if (pk.Format == 2) return pk is ICaughtData2 { CaughtData: 0 }; @@ -127,17 +127,17 @@ public static bool IsFromTrainerEgg(this ITrainerInfo tr, PKM pk) return false; if (tr.ID32 != pk.ID32) return false; - if (tr.Gender != pk.OT_Gender) + if (tr.Gender != pk.OriginalTrainerGender) return false; - if (tr.Game != pk.Version) + if (tr.Version != pk.Version) { // PK9 does not store version for Picnic eggs. if (pk is PK9 { Version: 0 }) { } else { return false; } } - if (tr.OT != pk.OT_Name) + if (tr.OT != pk.OriginalTrainerName) return false; return true; @@ -145,10 +145,10 @@ public static bool IsFromTrainerEgg(this ITrainerInfo tr, PKM pk) private static bool IsMatchVersion(ITrainerInfo tr, PKM pk) { - if (tr.Game == pk.Version) + if (tr.Version == pk.Version) return true; if (pk.GO_LGPE) - return tr.Game is (int)GameVersion.GP or (int)GameVersion.GE; + return tr.Version is GameVersion.GP or GameVersion.GE; return false; } } diff --git a/PKHeX.Core/Saves/Abstractions/SimpleTrainerInfo.cs b/PKHeX.Core/Saves/Abstractions/SimpleTrainerInfo.cs index f3341ec8a..84baf4928 100644 --- a/PKHeX.Core/Saves/Abstractions/SimpleTrainerInfo.cs +++ b/PKHeX.Core/Saves/Abstractions/SimpleTrainerInfo.cs @@ -8,7 +8,7 @@ public sealed record SimpleTrainerInfo : ITrainerInfo, IRegionOrigin public string OT { get; set; } = "PKHeX"; public ushort TID16 { get; set; } = 12345; public ushort SID16 { get; set; } = 54321; - public int Gender { get; set; } + public byte Gender { get; set; } public int Language { get; set; } = (int)LanguageID.English; public uint ID32 { get => (uint)(TID16 | (SID16 << 16)); set => (TID16, SID16) = ((ushort)value, (ushort)(value >> 16)); } public TrainerIDFormat TrainerIDDisplayFormat => this.GetTrainerIDFormat(); @@ -18,13 +18,13 @@ public sealed record SimpleTrainerInfo : ITrainerInfo, IRegionOrigin public byte Region { get; set; } = 7; // California public byte Country { get; set; } = 49; // USA - public int Game { get; } - public int Generation { get; init; } = PKX.Generation; + public GameVersion Version { get; } + public byte Generation { get; init; } = PKX.Generation; public EntityContext Context { get; init; } = PKX.Context; public SimpleTrainerInfo(GameVersion game = PKX.Version) { - Game = (int) game; + Version = game; SanityCheckRegionOrigin(game); } @@ -34,7 +34,7 @@ private void SanityCheckRegionOrigin(GameVersion game) this.ClearRegionOrigin(); } - public SimpleTrainerInfo(ITrainerInfo other) : this((GameVersion)other.Game) + public SimpleTrainerInfo(ITrainerInfo other) : this(other.Version) { OT = other.OT; TID16 = other.TID16; @@ -47,6 +47,6 @@ public SimpleTrainerInfo(ITrainerInfo other) : this((GameVersion)other.Game) if (other is IRegionOrigin r) r.CopyRegionOrigin(this); - SanityCheckRegionOrigin((GameVersion)Game); + SanityCheckRegionOrigin(Version); } } diff --git a/PKHeX.Core/Saves/Access/SaveBlockAccessor9SV.cs b/PKHeX.Core/Saves/Access/SaveBlockAccessor9SV.cs index 96a145308..dcf03f6e7 100644 --- a/PKHeX.Core/Saves/Access/SaveBlockAccessor9SV.cs +++ b/PKHeX.Core/Saves/Access/SaveBlockAccessor9SV.cs @@ -70,10 +70,11 @@ public SaveBlockAccessor9SV(SAV9SV sav) RaidBlueberry = new RaidSpawnList9(sav, fake, default, RaidSpawnList9.RaidCountLegal_T2, false); } - if (TryGetBlock(KSevenStarRaidsDefeat, out var kSevenStarDefeated)) - RaidSevenStar = new RaidSevenStar9(sav, GetBlock(KSevenStarRaidsCapture), kSevenStarDefeated); - else - RaidSevenStar = new RaidSevenStar9(sav, GetBlock(KSevenStarRaidsCapture), GetFakeBlock()); + var captured = GetBlock(KSevenStarRaidsCapture); + var s7 = TryGetBlock(KSevenStarRaidsDefeat, out var defeated); + if (!s7) + defeated = GetFakeBlock(); + RaidSevenStar = new RaidSevenStar9(sav, captured, defeated!); EnrollmentDate = new Epoch1900DateValue(GetBlock(KEnrollmentDate)); BlueberryQuestRecord = new BlueberryQuestRecord9(sav, GetBlockSafe(KBlueberryQuestRecords)); diff --git a/PKHeX.Core/Saves/SAV1.cs b/PKHeX.Core/Saves/SAV1.cs index aaea10a5d..1d7f74467 100644 --- a/PKHeX.Core/Saves/SAV1.cs +++ b/PKHeX.Core/Saves/SAV1.cs @@ -232,14 +232,14 @@ private int GetBoxRawDataOffset(int box) public override int MaxAbilityID => Legal.MaxAbilityID_1; public override int MaxItemID => Legal.MaxItemID_1; public override int MaxBallID => 0; // unused - public override int MaxGameID => 99; // unused + public override GameVersion MaxGameID => GameVersion.RBY; // unused public override int MaxMoney => 999999; public override int MaxCoins => 9999; public override int BoxCount => Japanese ? 8 : 12; public override int MaxEV => EffortValues.Max12; public override int MaxIV => 15; - public override int Generation => 1; + public override byte Generation => 1; public override EntityContext Context => EntityContext.Gen1; protected override int GiftCountMax => 0; public override int MaxStringLengthOT => Japanese ? 5 : 7; @@ -258,15 +258,15 @@ private int GetBoxRawDataOffset(int box) private byte GetRBYChecksum(int start, int end) { - byte chksum = 0; - for (int i = start; i < end; i++) - chksum += Data[i]; - chksum ^= 0xFF; - return chksum; + var span = Data.AsSpan(start, end - start); + byte result = 0; + foreach (ref var b in span) + result += b; + return (byte)~result; } // Trainer Info - public override GameVersion Version { get; protected set; } + public override GameVersion Version { get; set; } public override string OT { @@ -274,9 +274,9 @@ public override string OT set => SetString(Data.AsSpan(Offsets.OT, MaxStringLengthOT + 1), value, MaxStringLengthOT, StringConverterOption.ClearZero); } - public Span OT_Trash { get => Data.AsSpan(Offsets.OT, StringLength); set { if (value.Length == StringLength) value.CopyTo(Data.AsSpan(Offsets.OT)); } } + public Span OriginalTrainerTrash { get => Data.AsSpan(Offsets.OT, StringLength); set { if (value.Length == StringLength) value.CopyTo(Data.AsSpan(Offsets.OT)); } } - public override int Gender + public override byte Gender { get => 0; set { } diff --git a/PKHeX.Core/Saves/SAV1Stadium.cs b/PKHeX.Core/Saves/SAV1Stadium.cs index 641b15bec..da4f02ccf 100644 --- a/PKHeX.Core/Saves/SAV1Stadium.cs +++ b/PKHeX.Core/Saves/SAV1Stadium.cs @@ -1,4 +1,5 @@ using System; +using System.Diagnostics.CodeAnalysis; using static System.Buffers.Binary.BinaryPrimitives; namespace PKHeX.Core; @@ -14,11 +15,11 @@ public sealed class SAV1Stadium : SAV_STADIUM public override PersonalTable1 Personal => PersonalTable.Y; public override int MaxEV => EffortValues.Max12; public override ReadOnlySpan HeldItems => []; - public override GameVersion Version { get; protected set; } = GameVersion.Stadium; + public override GameVersion Version { get => GameVersion.Stadium; set { } } protected override SAV1Stadium CloneInternal() => new((byte[])Data.Clone(), Japanese); - public override int Generation => 1; + public override byte Generation => 1; public override EntityContext Context => EntityContext.Gen1; private int StringLength => Japanese ? StringLengthJ : StringLengthU; private const int StringLengthJ = 6; @@ -113,8 +114,8 @@ protected override PK1 GetPKM(byte[] data) var nick = data.AsSpan(PokeCrypto.SIZE_1STORED, len); var ot = data.AsSpan(PokeCrypto.SIZE_1STORED + len, len); var pk1 = new PK1(data[..PokeCrypto.SIZE_1STORED], Japanese); - nick.CopyTo(pk1.Nickname_Trash); - ot.CopyTo(pk1.OT_Trash); + nick.CopyTo(pk1.NicknameTrash); + ot.CopyTo(pk1.OriginalTrainerTrash); return pk1; } @@ -126,8 +127,8 @@ public override byte[] GetDataForFormatStored(PKM pk) var data = pk.Data; int len = StringLength; data.CopyTo(result, 0); - gb.Nickname_Trash.CopyTo(result.AsSpan(PokeCrypto.SIZE_1STORED)); - gb.OT_Trash.CopyTo(result.AsSpan(PokeCrypto.SIZE_1STORED + len)); + gb.NicknameTrash.CopyTo(result.AsSpan(PokeCrypto.SIZE_1STORED)); + gb.OriginalTrainerTrash.CopyTo(result.AsSpan(PokeCrypto.SIZE_1STORED + len)); return result; } @@ -288,7 +289,7 @@ private static bool GetIsSwap(ReadOnlySpan data, bool japanese) return result == StadiumSaveType.Swapped; } - private static StadiumSaveType IsStadium(ReadOnlySpan data, int teamSize, int boxSize) + private static StadiumSaveType IsStadium(ReadOnlySpan data, [ConstantExpected] int teamSize, [ConstantExpected] int boxSize) { var isTeam = StadiumUtil.IsMagicPresentEither(data, teamSize, MAGIC_FOOTER, 10); if (isTeam != StadiumSaveType.None) diff --git a/PKHeX.Core/Saves/SAV1StadiumJ.cs b/PKHeX.Core/Saves/SAV1StadiumJ.cs index 039f18c36..2cced5116 100644 --- a/PKHeX.Core/Saves/SAV1StadiumJ.cs +++ b/PKHeX.Core/Saves/SAV1StadiumJ.cs @@ -15,11 +15,11 @@ public sealed class SAV1StadiumJ : SAV_STADIUM public override PersonalTable1 Personal => PersonalTable.Y; public override int MaxEV => EffortValues.Max12; public override ReadOnlySpan HeldItems => []; - public override GameVersion Version { get; protected set; } = GameVersion.StadiumJ; + public override GameVersion Version { get => GameVersion.StadiumJ; set { } } protected override SAV1StadiumJ CloneInternal() => new((byte[])Data.Clone()); - public override int Generation => 1; + public override byte Generation => 1; public override EntityContext Context => EntityContext.Gen1; private const int StringLength = 6; // Japanese Only public override int MaxStringLengthOT => StringLength; @@ -87,8 +87,8 @@ protected override PK1 GetPKM(byte[] data) var ot = data.AsSpan(0x21 + len, len); data = data[..0x21]; var pk1 = new PK1(data, true); - nick.CopyTo(pk1.Nickname_Trash); - ot.CopyTo(pk1.OT_Trash); + nick.CopyTo(pk1.NicknameTrash); + ot.CopyTo(pk1.OriginalTrainerTrash); return pk1; } @@ -100,8 +100,8 @@ public override byte[] GetDataForFormatStored(PKM pk) var data = pk.Data; const int len = StringLength; data.CopyTo(result, 0); - gb.Nickname_Trash.CopyTo(result.AsSpan(PokeCrypto.SIZE_1STORED)); - gb.OT_Trash.CopyTo(result.AsSpan(PokeCrypto.SIZE_1STORED + len)); + gb.NicknameTrash.CopyTo(result.AsSpan(PokeCrypto.SIZE_1STORED)); + gb.OriginalTrainerTrash.CopyTo(result.AsSpan(PokeCrypto.SIZE_1STORED + len)); return result; } diff --git a/PKHeX.Core/Saves/SAV2.cs b/PKHeX.Core/Saves/SAV2.cs index a18766f87..aafade509 100644 --- a/PKHeX.Core/Saves/SAV2.cs +++ b/PKHeX.Core/Saves/SAV2.cs @@ -156,8 +156,8 @@ private PK2 ReadPKMFromOffset(int offset) var nick = span[..stringLength]; var ot = span.Slice(stringLength, stringLength); - nick.CopyTo(pk.Nickname_Trash); - ot.CopyTo(pk.OT_Trash); + nick.CopyTo(pk.NicknameTrash); + ot.CopyTo(pk.OriginalTrainerTrash); return pk; } @@ -270,7 +270,7 @@ protected override byte[] GetFinalData() public override int MaxAbilityID => Legal.MaxAbilityID_2; public override int MaxItemID => Legal.MaxItemID_2; public override int MaxBallID => 0; // unused - public override int MaxGameID => 99; // unused + public override GameVersion MaxGameID => GameVersion.Gen2; // unused public override int MaxMoney => 999999; public override int MaxCoins => 9999; @@ -282,7 +282,7 @@ protected override byte[] GetFinalData() public override int BoxCount => Japanese ? 9 : 14; public override int MaxEV => EffortValues.Max12; public override int MaxIV => 15; - public override int Generation => 2; + public override byte Generation => 2; public override EntityContext Context => EntityContext.Gen2; protected override int GiftCountMax => 0; public override int MaxStringLengthOT => Japanese || Korean ? 5 : 7; @@ -327,7 +327,7 @@ public override string ChecksumInfo } // Trainer Info - public override GameVersion Version { get; protected set; } + public override GameVersion Version { get; set; } public override string OT { @@ -335,7 +335,7 @@ public override string OT set => SetString(Data.AsSpan(Offsets.Trainer1 + 2, (Korean ? 2 : 1) * MaxStringLengthOT), value, 8, StringConverterOption.Clear50); } - public Span OT_Trash + public Span OriginalTrainerTrash { get => Data.AsSpan(Offsets.Trainer1 + 2, StringLength); set { if (value.Length == StringLength) value.CopyTo(Data.AsSpan(Offsets.Trainer1 + 2)); } @@ -353,15 +353,15 @@ public Span Rival_Trash set { if (value.Length == StringLength) value.CopyTo(Data.AsSpan(Offsets.Rival)); } } - public override int Gender + public override byte Gender { - get => Version == GameVersion.C ? Data[Offsets.Gender] : 0; + get => Version == GameVersion.C ? Data[Offsets.Gender] : (byte)0; set { if (Version != GameVersion.C) return; - Data[Offsets.Gender] = (byte) value; - Data[Offsets.Palette] = (byte) value; + Data[Offsets.Gender] = value; + Data[Offsets.Palette] = value; } } diff --git a/PKHeX.Core/Saves/SAV2Stadium.cs b/PKHeX.Core/Saves/SAV2Stadium.cs index 0bc77e435..35dfc360c 100644 --- a/PKHeX.Core/Saves/SAV2Stadium.cs +++ b/PKHeX.Core/Saves/SAV2Stadium.cs @@ -14,11 +14,11 @@ public sealed class SAV2Stadium : SAV_STADIUM public override PersonalTable2 Personal => PersonalTable.C; public override int MaxEV => EffortValues.Max12; public override ReadOnlySpan HeldItems => Legal.HeldItems_GSC; - public override GameVersion Version { get; protected set; } = GameVersion.Stadium2; + public override GameVersion Version { get => GameVersion.Stadium2; set { } } protected override SAV2Stadium CloneInternal() => new((byte[])Data.Clone(), Japanese); - public override int Generation => 2; + public override byte Generation => 2; public override EntityContext Context => EntityContext.Gen2; private const int StringLength = 12; public override int MaxStringLengthOT => StringLength; @@ -194,10 +194,11 @@ private static bool GetIsSwap(ReadOnlySpan data, bool japanese) var teamSwap = StadiumUtil.IsMagicPresentSwap(data, TeamSize, MAGIC_FOOTER, 1); if (teamSwap) return true; - var boxSwap = StadiumUtil.IsMagicPresentSwap(data[BoxStart..], japanese ? BoxSizeJ : BoxSizeU, MAGIC_FOOTER, 1); - if (boxSwap) - return true; - return false; + + var boxSpan = data[BoxStart..]; + if (japanese) + return StadiumUtil.IsMagicPresentSwap(boxSpan, BoxSizeJ, MAGIC_FOOTER, 1); + return StadiumUtil.IsMagicPresentSwap(boxSpan, BoxSizeU, MAGIC_FOOTER, 1); } } diff --git a/PKHeX.Core/Saves/SAV3.cs b/PKHeX.Core/Saves/SAV3.cs index 9251c5409..e5ad6e60c 100644 --- a/PKHeX.Core/Saves/SAV3.cs +++ b/PKHeX.Core/Saves/SAV3.cs @@ -162,7 +162,7 @@ public void WriteBothSaveSlots(Span data) public sealed override int MaxAbilityID => Legal.MaxAbilityID_3; public override int MaxItemID => Legal.MaxItemID_3; public sealed override int MaxBallID => Legal.MaxBallID_3; - public sealed override int MaxGameID => Legal.MaxGameID_3; + public sealed override GameVersion MaxGameID => Legal.MaxGameID_3; public abstract int EventFlagCount { get; } public abstract int EventWorkCount { get; } @@ -186,7 +186,7 @@ public void WriteBothSaveSlots(Span data) public sealed override int BoxCount => 14; public sealed override int MaxEV => EffortValues.Max255; - public sealed override int Generation => 3; + public sealed override byte Generation => 3; public sealed override EntityContext Context => EntityContext.Gen3; protected sealed override int GiftCountMax => 1; public sealed override int MaxStringLengthOT => 7; @@ -325,10 +325,10 @@ public sealed override string OT } } - public sealed override int Gender + public sealed override byte Gender { get => Small[8]; - set => Small[8] = (byte)value; + set => Small[8] = value; } public sealed override uint ID32 diff --git a/PKHeX.Core/Saves/SAV3Colosseum.cs b/PKHeX.Core/Saves/SAV3Colosseum.cs index e6958f408..b7d7b88b2 100644 --- a/PKHeX.Core/Saves/SAV3Colosseum.cs +++ b/PKHeX.Core/Saves/SAV3Colosseum.cs @@ -146,10 +146,10 @@ private byte[] GetInnerData() public override int MaxAbilityID => Legal.MaxAbilityID_3; public override int MaxBallID => Legal.MaxBallID_3; public override int MaxItemID => Legal.MaxItemID_3_COLO; - public override int MaxGameID => Legal.MaxGameID_3; + public override GameVersion MaxGameID => Legal.MaxGameID_3; public override int MaxEV => EffortValues.Max255; - public override int Generation => 3; + public override byte Generation => 3; public override EntityContext Context => EntityContext.Gen3; protected override int GiftCountMax => 1; public override int MaxStringLengthOT => 10; // as evident by Mattle Ho-Oh @@ -268,7 +268,7 @@ public override string ChecksumInfo } // Trainer Info - public override GameVersion Version { get => GameVersion.COLO; protected set { } } + public override GameVersion Version { get => GameVersion.COLO; set { } } // Storage public override int GetPartyOffset(int slot) @@ -377,7 +377,7 @@ public override int PlayedSeconds public override ushort SID16 { get => ReadUInt16BigEndian(Data.AsSpan(0xA4)); set => WriteUInt16BigEndian(Data.AsSpan(0xA4), value); } public override ushort TID16 { get => ReadUInt16BigEndian(Data.AsSpan(0xA6)); set => WriteUInt16BigEndian(Data.AsSpan(0xA6), value); } - public override int Gender { get => Data[0xAF8]; set => Data[0xAF8] = (byte)value; } + public override byte Gender { get => Data[0xAF8]; set => Data[0xAF8] = value; } public override uint Money { get => ReadUInt32BigEndian(Data.AsSpan(0xAFC)); set => WriteUInt32BigEndian(Data.AsSpan(0xAFC), value); } public uint Coupons { get => ReadUInt32BigEndian(Data.AsSpan(0xB00)); set => WriteUInt32BigEndian(Data.AsSpan(0xB00), value); } public string RUI_Name { get => GetString(Data.AsSpan(0xB3A, 20)); set => SetString(Data.AsSpan(0xB3A, 20), value, 10, StringConverterOption.ClearZero); } diff --git a/PKHeX.Core/Saves/SAV3E.cs b/PKHeX.Core/Saves/SAV3E.cs index d8f3ed7e4..869e4a52c 100644 --- a/PKHeX.Core/Saves/SAV3E.cs +++ b/PKHeX.Core/Saves/SAV3E.cs @@ -12,7 +12,7 @@ public sealed class SAV3E : SAV3, IGen3Hoenn, IGen3Joyful, IGen3Wonder { // Configuration protected override SAV3E CloneInternal() => new(Write()); - public override GameVersion Version { get => GameVersion.E; protected set { } } + public override GameVersion Version { get => GameVersion.E; set { } } public override PersonalTable3 Personal => PersonalTable.E; public override int EventFlagCount => 8 * 300; @@ -157,13 +157,14 @@ public PokeBlock3Case PokeBlocks public DecorationInventory3 Decorations => new(Large.AsSpan(0x2734, DecorationInventory3.SIZE)); + private Span SwarmSpan => Large.AsSpan(0x2B90, Swarm3.SIZE); public Swarm3 Swarm { - get => new(Large.AsSpan(0x2B90, Swarm3.SIZE).ToArray()); - set => SetData(Large.AsSpan(0x2B90), value.Data); + get => new(SwarmSpan.ToArray()); + set => SetData(SwarmSpan, value.Data); } - private void ClearSwarm() => Large.AsSpan(0x2B90, Swarm3.SIZE).Clear(); + private void ClearSwarm() => SwarmSpan.Clear(); public IReadOnlyList DefaultSwarms => Swarm3Details.Swarms_E; diff --git a/PKHeX.Core/Saves/SAV3FRLG.cs b/PKHeX.Core/Saves/SAV3FRLG.cs index cf1112b6a..d9956616b 100644 --- a/PKHeX.Core/Saves/SAV3FRLG.cs +++ b/PKHeX.Core/Saves/SAV3FRLG.cs @@ -11,7 +11,7 @@ public sealed class SAV3FRLG : SAV3, IGen3Joyful, IGen3Wonder { // Configuration protected override SAV3FRLG CloneInternal() => new(Write()); - public override GameVersion Version { get; protected set; } = GameVersion.FR; // allow mutation + public override GameVersion Version { get; set; } = GameVersion.FR; // allow mutation private PersonalTable3 _personal = PersonalTable.FR; public override PersonalTable3 Personal => _personal; diff --git a/PKHeX.Core/Saves/SAV3GCMemoryCard.cs b/PKHeX.Core/Saves/SAV3GCMemoryCard.cs index 09cbca8fa..0ec05fb00 100644 --- a/PKHeX.Core/Saves/SAV3GCMemoryCard.cs +++ b/PKHeX.Core/Saves/SAV3GCMemoryCard.cs @@ -237,22 +237,22 @@ public GCMemoryCardState GetMemoryCardState() continue; var header = Data.AsSpan(offset, 4); - var ver = SaveHandlerGCI.GetGameCode(header); - if (ver == GameVersion.COLO) + var version = SaveHandlerGCI.GetGameCode(header); + if (version == GameVersion.COLO) { if (HasCOLO) // another entry already exists return GCMemoryCardState.DuplicateCOLO; EntryCOLO = i; SaveGameCount++; } - else if (ver == GameVersion.XD) + else if (version == GameVersion.XD) { if (HasXD) // another entry already exists return GCMemoryCardState.DuplicateXD; EntryXD = i; SaveGameCount++; } - else if (ver == GameVersion.RSBOX) + else if (version == GameVersion.RSBOX) { if (HasRSBOX) // another entry already exists return GCMemoryCardState.DuplicateRSBOX; diff --git a/PKHeX.Core/Saves/SAV3RS.cs b/PKHeX.Core/Saves/SAV3RS.cs index e3cb0e5de..7956cc545 100644 --- a/PKHeX.Core/Saves/SAV3RS.cs +++ b/PKHeX.Core/Saves/SAV3RS.cs @@ -12,7 +12,7 @@ public sealed class SAV3RS : SAV3, IGen3Hoenn { // Configuration protected override SAV3RS CloneInternal() => new(Write()); - public override GameVersion Version { get => GameVersion.RS; protected set { } } + public override GameVersion Version { get => GameVersion.RS; set { } } public override PersonalTable3 Personal => PersonalTable.RS; public override int EventFlagCount => 8 * 288; diff --git a/PKHeX.Core/Saves/SAV3RSBox.cs b/PKHeX.Core/Saves/SAV3RSBox.cs index 213da60d2..1c590a894 100644 --- a/PKHeX.Core/Saves/SAV3RSBox.cs +++ b/PKHeX.Core/Saves/SAV3RSBox.cs @@ -110,10 +110,10 @@ private byte[] GetInnerData() public override int MaxAbilityID => Legal.MaxAbilityID_3; public override int MaxItemID => Legal.MaxItemID_3; public override int MaxBallID => Legal.MaxBallID_3; - public override int MaxGameID => Legal.MaxGameID_3; + public override GameVersion MaxGameID => Legal.MaxGameID_3; public override int MaxEV => EffortValues.Max255; - public override int Generation => 3; + public override byte Generation => 3; public override EntityContext Context => EntityContext.Gen3; protected override int GiftCountMax => 1; public override int MaxStringLengthOT => 7; @@ -131,7 +131,7 @@ private byte[] GetInnerData() public override string ChecksumInfo => Blocks.GetChecksumInfo(Data); // Trainer Info - public override GameVersion Version { get => GameVersion.RSBOX; protected set { } } + public override GameVersion Version { get => GameVersion.RSBOX; set { } } // Storage public override int GetPartyOffset(int slot) => -1; diff --git a/PKHeX.Core/Saves/SAV3XD.cs b/PKHeX.Core/Saves/SAV3XD.cs index db6a8aea3..194622709 100644 --- a/PKHeX.Core/Saves/SAV3XD.cs +++ b/PKHeX.Core/Saves/SAV3XD.cs @@ -186,10 +186,10 @@ private byte[] GetInnerData() public override int MaxAbilityID => Legal.MaxAbilityID_3; public override int MaxBallID => Legal.MaxBallID_3; public override int MaxItemID => Legal.MaxItemID_3_XD; - public override int MaxGameID => Legal.MaxGameID_3; + public override GameVersion MaxGameID => Legal.MaxGameID_3; public override int MaxEV => EffortValues.Max255; - public override int Generation => 3; + public override byte Generation => 3; public override EntityContext Context => EntityContext.Gen3; protected override int GiftCountMax => 1; public override int MaxStringLengthOT => 7; @@ -320,13 +320,13 @@ public override int PlayedSeconds } // Trainer Info - public override GameVersion Version { get => GameVersion.XD; protected set { } } + public override GameVersion Version { get => GameVersion.XD; set { } } public override string OT { get => GetString(Data.AsSpan(Trainer1 + 0x00, 20)); set => SetString(Data.AsSpan(Trainer1 + 0x00, 20), value, 10, StringConverterOption.ClearZero); } public override uint ID32 { get => ReadUInt32BigEndian(Data.AsSpan(Trainer1 + 0x2C)); set => WriteUInt32BigEndian(Data.AsSpan(Trainer1 + 0x2C), value); } public override ushort SID16 { get => ReadUInt16BigEndian(Data.AsSpan(Trainer1 + 0x2C)); set => WriteUInt16BigEndian(Data.AsSpan(Trainer1 + 0x2C), value); } public override ushort TID16 { get => ReadUInt16BigEndian(Data.AsSpan(Trainer1 + 0x2E)); set => WriteUInt16BigEndian(Data.AsSpan(Trainer1 + 0x2E), value); } - public override int Gender { get => Data[Trainer1 + 0x8E0]; set => Data[Trainer1 + 0x8E0] = (byte)value; } + public override byte Gender { get => Data[Trainer1 + 0x8E0]; set => Data[Trainer1 + 0x8E0] = value; } public override uint Money { get => ReadUInt32BigEndian(Data.AsSpan(Trainer1 + 0x8E4)); set => WriteUInt32BigEndian(Data.AsSpan(Trainer1 + 0x8E4), value); } public uint Coupons { get => ReadUInt32BigEndian(Data.AsSpan(Trainer1 + 0x8E8)); set => WriteUInt32BigEndian(Data.AsSpan(Trainer1 + 0x8E8), value); } diff --git a/PKHeX.Core/Saves/SAV4.cs b/PKHeX.Core/Saves/SAV4.cs index 55a743e70..43fd813e2 100644 --- a/PKHeX.Core/Saves/SAV4.cs +++ b/PKHeX.Core/Saves/SAV4.cs @@ -91,7 +91,7 @@ public sealed override void CopyChangesFrom(SaveFile sav) public sealed override int BoxCount => 18; public sealed override int MaxEV => EffortValues.Max255; - public sealed override int Generation => 4; + public sealed override byte Generation => 4; public override EntityContext Context => EntityContext.Gen4; public int EventFlagCount => 0xB60; // 2912 public int EventWorkCount => (EventFlag - EventWork) >> 1; @@ -106,7 +106,7 @@ public sealed override void CopyChangesFrom(SaveFile sav) // MaxItemID public sealed override int MaxAbilityID => Legal.MaxAbilityID_4; public sealed override int MaxBallID => Legal.MaxBallID_4; - public sealed override int MaxGameID => Legal.MaxGameID_4; // Colo/XD + public sealed override GameVersion MaxGameID => Legal.MaxGameID_4; // Colo/XD // Checksums protected abstract int FooterSize { get; } @@ -255,10 +255,10 @@ public override uint Money set => WriteUInt32LittleEndian(General[(Trainer1 + 0x14)..], value); } - public override int Gender + public override byte Gender { get => General[Trainer1 + 0x18]; - set => General[Trainer1 + 0x18] = (byte)value; + set => General[Trainer1 + 0x18] = value; } public override int Language diff --git a/PKHeX.Core/Saves/SAV4BR.cs b/PKHeX.Core/Saves/SAV4BR.cs index d045d48fe..bd99cfab5 100644 --- a/PKHeX.Core/Saves/SAV4BR.cs +++ b/PKHeX.Core/Saves/SAV4BR.cs @@ -102,10 +102,10 @@ public int CurrentSlot public override int MaxAbilityID => Legal.MaxAbilityID_4; public override int MaxItemID => Legal.MaxItemID_4_HGSS; public override int MaxBallID => Legal.MaxBallID_4; - public override int MaxGameID => Legal.MaxGameID_4; + public override GameVersion MaxGameID => Legal.MaxGameID_4; public override int MaxEV => EffortValues.Max255; - public override int Generation => 4; + public override byte Generation => 4; public override EntityContext Context => EntityContext.Gen4; protected override int GiftCountMax => 1; public override int MaxStringLengthOT => 7; @@ -154,7 +154,7 @@ public static bool IsChecksumsValid(Span sav) } // Trainer Info - public override GameVersion Version { get => GameVersion.BATREV; protected set { } } + public override GameVersion Version { get => GameVersion.BATREV; set { } } private string GetOTName(int slot) { diff --git a/PKHeX.Core/Saves/SAV5.cs b/PKHeX.Core/Saves/SAV5.cs index 83b19cf08..8b00573e6 100644 --- a/PKHeX.Core/Saves/SAV5.cs +++ b/PKHeX.Core/Saves/SAV5.cs @@ -13,7 +13,7 @@ public abstract class SAV5 : SaveFile, ISaveBlock5BW, IEventFlag37 protected override PK5 GetPKM(byte[] data) => new(data); protected override byte[] DecryptPKM(byte[] data) => PokeCrypto.DecryptArray45(data); - protected internal override string ShortSummary => $"{OT} ({(GameVersion)Game}) - {PlayTimeString}"; + protected internal override string ShortSummary => $"{OT} ({Version}) - {PlayTimeString}"; public override string Extension => ".sav"; public override ReadOnlySpan HeldItems => Legal.HeldItems_BW; @@ -24,7 +24,7 @@ public abstract class SAV5 : SaveFile, ISaveBlock5BW, IEventFlag37 public override int BoxCount => 24; public override int MaxEV => EffortValues.Max255; - public override int Generation => 5; + public override byte Generation => 5; public override EntityContext Context => EntityContext.Gen5; public override int MaxStringLengthOT => 7; public override int MaxStringLengthNickname => 10; @@ -38,7 +38,7 @@ public abstract class SAV5 : SaveFile, ISaveBlock5BW, IEventFlag37 public override ushort MaxSpeciesID => Legal.MaxSpeciesID_5; public override int MaxAbilityID => Legal.MaxAbilityID_5; public override int MaxBallID => Legal.MaxBallID_5; - public override int MaxGameID => Legal.MaxGameID_5; // B2 + public override GameVersion MaxGameID => Legal.MaxGameID_5; // B2 protected SAV5([ConstantExpected] int size) : base(size) { @@ -51,12 +51,6 @@ protected SAV5(byte[] data) : base(data) Initialize(); } - public override GameVersion Version - { - get => (GameVersion)Game; - protected set => Game = (int)value; - } - private void Initialize() { Box = 0x400; @@ -128,8 +122,8 @@ protected override void SetPKM(PKM pk, bool isParty = false) public int Country { get => PlayerData.Country; set => PlayerData.Country = value; } public int Region { get => PlayerData.Region; set => PlayerData.Region = value; } public override int Language { get => PlayerData.Language; set => PlayerData.Language = value; } - public override int Game { get => PlayerData.Game; set => PlayerData.Game = value; } - public override int Gender { get => PlayerData.Gender; set => PlayerData.Gender = value; } + public override GameVersion Version { get => (GameVersion)PlayerData.Game; set => PlayerData.Game = (byte)value; } + public override byte Gender { get => PlayerData.Gender; set => PlayerData.Gender = value; } public override int PlayedHours { get => PlayerData.PlayedHours; set => PlayerData.PlayedHours = value; } public override int PlayedMinutes { get => PlayerData.PlayedMinutes; set => PlayerData.PlayedMinutes = value; } public override int PlayedSeconds { get => PlayerData.PlayedSeconds; set => PlayerData.PlayedSeconds = value; } diff --git a/PKHeX.Core/Saves/SAV6.cs b/PKHeX.Core/Saves/SAV6.cs index 21c6fd0bf..8a5356b56 100644 --- a/PKHeX.Core/Saves/SAV6.cs +++ b/PKHeX.Core/Saves/SAV6.cs @@ -25,7 +25,7 @@ public abstract class SAV6 : SAV_BEEF, ITrainerStatRecord, ISaveBlock6Core, IReg public override int BoxCount => 31; public override int MaxEV => EffortValues.Max252; - public override int Generation => 6; + public override byte Generation => 6; public override EntityContext Context => EntityContext.Gen6; protected override int GiftCountMax => 24; protected override int GiftFlagMax => 0x100 * 8; @@ -38,7 +38,7 @@ public abstract class SAV6 : SAV_BEEF, ITrainerStatRecord, ISaveBlock6Core, IReg public override ushort MaxSpeciesID => Legal.MaxSpeciesID_6; public override int MaxBallID => Legal.MaxBallID_6; - public override int MaxGameID => Legal.MaxGameID_6; // OR + public override GameVersion MaxGameID => Legal.MaxGameID_6; // OR protected override PK6 GetPKM(byte[] data) => new(data); protected override byte[] DecryptPKM(byte[] data) => PokeCrypto.DecryptArray6(data); @@ -62,8 +62,8 @@ public abstract class SAV6 : SAV_BEEF, ITrainerStatRecord, ISaveBlock6Core, IReg public override uint ID32 { get => Status.ID32; set => Status.ID32 = value; } public override ushort TID16 { get => Status.TID16; set => Status.TID16 = value; } public override ushort SID16 { get => Status.SID16; set => Status.SID16 = value; } - public override int Game { get => Status.Game; set => Status.Game = value; } - public override int Gender { get => Status.Gender; set => Status.Gender = value; } + public override GameVersion Version { get => (GameVersion)Status.Game; set => Status.Game = (byte)value; } + public override byte Gender { get => Status.Gender; set => Status.Gender = value; } public override int Language { get => Status.Language; set => Status.Language = value; } public override string OT { get => Status.OT; set => Status.OT = value; } public byte Region { get => Status.Region; set => Status.Region = value; } @@ -117,10 +117,8 @@ protected override void SetPKM(PKM pk, bool isParty = false) if (CT != pk6.CurrentHandler) // Logic updated Friendship { // Copy over the Friendship Value only under certain circumstances - if (pk6.HasMove(216)) // Return + if (pk6.HasMove((int)Move.Return) || pk6.HasMove((int)Move.Frustration)) pk6.CurrentFriendship = pk6.OppositeFriendship; - else if (pk6.HasMove(218)) // Frustration - pk.CurrentFriendship = pk6.OppositeFriendship; } pk6.FormArgumentElapsed = pk6.FormArgumentMaximum = 0; diff --git a/PKHeX.Core/Saves/SAV6AO.cs b/PKHeX.Core/Saves/SAV6AO.cs index ae207991d..b19cec6d0 100644 --- a/PKHeX.Core/Saves/SAV6AO.cs +++ b/PKHeX.Core/Saves/SAV6AO.cs @@ -86,12 +86,7 @@ private void Initialize() public SecretBase6Block SecretBase => Blocks.SecretBase; #endregion - public override GameVersion Version => Game switch - { - (int) GameVersion.AS => GameVersion.AS, - (int) GameVersion.OR => GameVersion.OR, - _ => GameVersion.Invalid, - }; + public override bool IsVersionValid() => Version is GameVersion.AS or GameVersion.OR; public override bool GetCaught(ushort species) => Blocks.Zukan.GetCaught(species); public override bool GetSeen(ushort species) => Blocks.Zukan.GetSeen(species); diff --git a/PKHeX.Core/Saves/SAV6AODemo.cs b/PKHeX.Core/Saves/SAV6AODemo.cs index c3c5f089a..3a82e72eb 100644 --- a/PKHeX.Core/Saves/SAV6AODemo.cs +++ b/PKHeX.Core/Saves/SAV6AODemo.cs @@ -36,12 +36,7 @@ private void Initialize() Party = 0x03E00; } - public override GameVersion Version => Game switch - { - (int) GameVersion.AS => GameVersion.AS, - (int) GameVersion.OR => GameVersion.OR, - _ => GameVersion.Invalid, - }; + public override bool IsVersionValid() => Version is GameVersion.AS or GameVersion.OR; public override uint Money { get => Blocks.Misc.Money; set => Blocks.Misc.Money = value; } public override int Vivillon { get => Blocks.Misc.Vivillon; set => Blocks.Misc.Vivillon = value; } // unused diff --git a/PKHeX.Core/Saves/SAV6XY.cs b/PKHeX.Core/Saves/SAV6XY.cs index c874eb1b7..dc66888ff 100644 --- a/PKHeX.Core/Saves/SAV6XY.cs +++ b/PKHeX.Core/Saves/SAV6XY.cs @@ -130,12 +130,7 @@ public void UnlockAllFriendSafariSlots() State.Edited = true; } - public override GameVersion Version => Game switch - { - (int) GameVersion.X => GameVersion.X, - (int) GameVersion.Y => GameVersion.Y, - _ => GameVersion.Invalid, - }; + public override bool IsVersionValid() => Version is GameVersion.X or GameVersion.Y; protected override bool[] MysteryGiftReceivedFlags { get => Blocks.MysteryGift.GetReceivedFlags(); set => Blocks.MysteryGift.SetReceivedFlags(value); } protected override DataMysteryGift[] MysteryGiftCards { get => Blocks.MysteryGift.GetGifts(); set => Blocks.MysteryGift.SetGifts(value); } diff --git a/PKHeX.Core/Saves/SAV7.cs b/PKHeX.Core/Saves/SAV7.cs index 77465b974..6764941ac 100644 --- a/PKHeX.Core/Saves/SAV7.cs +++ b/PKHeX.Core/Saves/SAV7.cs @@ -72,7 +72,7 @@ protected void ReloadBattleTeams() public override int BoxCount => 32; public override int MaxEV => EffortValues.Max252; - public override int Generation => 7; + public override byte Generation => 7; public override EntityContext Context => EntityContext.Gen7; protected override int GiftCountMax => 48; protected override int GiftFlagMax => 0x100 * 8; @@ -84,7 +84,7 @@ protected void ReloadBattleTeams() public override int MaxStringLengthNickname => 12; public override int MaxBallID => Legal.MaxBallID_7; // 26 - public override int MaxGameID => Legal.MaxGameID_7; + public override GameVersion MaxGameID => Legal.MaxGameID_7; protected override PK7 GetPKM(byte[] data) => new(data); protected override byte[] DecryptPKM(byte[] data) => PokeCrypto.DecryptArray6(data); @@ -111,14 +111,8 @@ protected override byte[] GetFinalData() return result; } - public override GameVersion Version => Game switch - { - (int)GameVersion.SN => GameVersion.SN, - (int)GameVersion.MN => GameVersion.MN, - (int)GameVersion.US => GameVersion.US, - (int)GameVersion.UM => GameVersion.UM, - _ => GameVersion.Invalid, - }; + public override bool IsVersionValid() => + Version is GameVersion.SN or GameVersion.MN or GameVersion.US or GameVersion.UM; public sealed override string GetString(ReadOnlySpan data) => StringConverter7.GetString(data); @@ -131,8 +125,8 @@ public sealed override int SetString(Span destBuffer, ReadOnlySpan v public override uint ID32 { get => MyStatus.ID32; set => MyStatus.ID32 = value; } public override ushort TID16 { get => MyStatus.TID16; set => MyStatus.TID16 = value; } public override ushort SID16 { get => MyStatus.SID16; set => MyStatus.SID16 = value; } - public override int Game { get => MyStatus.Game; set => MyStatus.Game = value; } - public override int Gender { get => MyStatus.Gender; set => MyStatus.Gender = value; } + public override GameVersion Version { get => (GameVersion)MyStatus.Game; set => MyStatus.Game = (byte)value; } + public override byte Gender { get => MyStatus.Gender; set => MyStatus.Gender = value; } public int GameSyncIDSize => MyStatus7.GameSyncIDSize; // 64 bits public string GameSyncID { get => MyStatus.GameSyncID; set => MyStatus.GameSyncID = value; } public byte Region { get => MyStatus.Region; set => MyStatus.Region = value; } @@ -181,10 +175,8 @@ protected override void SetPKM(PKM pk, bool isParty = false) if (CT != pk7.CurrentHandler) // Logic updated Friendship { // Copy over the Friendship Value only under certain circumstances - if (pk7.HasMove(216)) // Return + if (pk7.HasMove((int)Move.Return) || pk7.HasMove((int)Move.Frustration)) pk7.CurrentFriendship = pk7.OppositeFriendship; - else if (pk7.HasMove(218)) // Frustration - pk.CurrentFriendship = pk7.OppositeFriendship; } pk7.FormArgumentElapsed = pk7.FormArgumentMaximum = 0; diff --git a/PKHeX.Core/Saves/SAV7b.cs b/PKHeX.Core/Saves/SAV7b.cs index aebe7e232..827736a0c 100644 --- a/PKHeX.Core/Saves/SAV7b.cs +++ b/PKHeX.Core/Saves/SAV7b.cs @@ -65,13 +65,13 @@ private void Initialize() public override IReadOnlyList Inventory { get => Blocks.Items.Inventory; set => Blocks.Items.Inventory = value; } // Feature Overrides - public override int Generation => 7; + public override byte Generation => 7; public override EntityContext Context => EntityContext.Gen7b; public override ushort MaxMoveID => Legal.MaxMoveID_7b; public override ushort MaxSpeciesID => Legal.MaxSpeciesID_7b; public override int MaxItemID => Legal.MaxItemID_7b; public override int MaxBallID => Legal.MaxBallID_7b; - public override int MaxGameID => Legal.MaxGameID_7b; + public override GameVersion MaxGameID => Legal.MaxGameID_7b; public override int MaxAbilityID => Legal.MaxAbilityID_7b; public override int MaxIV => 31; @@ -134,19 +134,14 @@ public override int SetString(Span destBuffer, ReadOnlySpan value, i return StringConverter8.SetString(destBuffer, value, maxLength); } - public override GameVersion Version => Game switch - { - (int)GameVersion.GP => GameVersion.GP, - (int)GameVersion.GE => GameVersion.GE, - _ => GameVersion.Invalid, - }; + public override bool IsVersionValid() => Version is GameVersion.GP or GameVersion.GE; // Player Information public override uint ID32 { get => Blocks.Status.ID32; set => Blocks.Status.ID32 = value; } public override ushort TID16 { get => Blocks.Status.TID16; set => Blocks.Status.TID16 = value; } public override ushort SID16 { get => Blocks.Status.SID16; set => Blocks.Status.SID16 = value; } - public override int Game { get => Blocks.Status.Game; set => Blocks.Status.Game = value; } - public override int Gender { get => Blocks.Status.Gender; set => Blocks.Status.Gender = value; } + public override GameVersion Version { get => (GameVersion)Blocks.Status.Game; set => Blocks.Status.Game = (byte)value; } + public override byte Gender { get => Blocks.Status.Gender; set => Blocks.Status.Gender = value; } public override int Language { get => Blocks.Status.Language; set => Blocks.Config.Language = Blocks.Status.Language = value; } // stored in multiple places public override string OT { get => Blocks.Status.OT; set => Blocks.Status.OT = value; } public override uint Money { get => Blocks.Misc.Money; set => Blocks.Misc.Money = value; } diff --git a/PKHeX.Core/Saves/SAV8BS.cs b/PKHeX.Core/Saves/SAV8BS.cs index 7dd9622d4..bd57bef71 100644 --- a/PKHeX.Core/Saves/SAV8BS.cs +++ b/PKHeX.Core/Saves/SAV8BS.cs @@ -108,7 +108,7 @@ private void Initialize() public override int BoxCount => BoxLayout8b.BoxCount; public override int MaxEV => EffortValues.Max252; - public override int Generation => 8; + public override byte Generation => 8; public override EntityContext Context => EntityContext.Gen8b; public override PersonalTable8BDSP Personal => PersonalTable.BDSP; public override int MaxStringLengthOT => 12; @@ -117,7 +117,7 @@ private void Initialize() public override ushort MaxSpeciesID => Legal.MaxSpeciesID_8b; public override int MaxItemID => Legal.MaxItemID_8b; public override int MaxBallID => Legal.MaxBallID_8b; - public override int MaxGameID => Legal.MaxGameID_HOME; + public override GameVersion MaxGameID => Legal.MaxGameID_HOME; public override int MaxAbilityID => Legal.MaxAbilityID_8b; public bool HasFirstSaveFileExpansion => (Gem8Version)SaveRevision >= Gem8Version.V1_1; @@ -234,12 +234,7 @@ public static bool GetIsHashValid(ReadOnlySpan data, ReadOnlySpan cu public MysteryBlock8b MysteryRecords { get; } #endregion - public override GameVersion Version => Game switch - { - (int)GameVersion.BD => GameVersion.BD, - (int)GameVersion.SP => GameVersion.SP, - _ => GameVersion.Invalid, - }; + public override bool IsVersionValid() => Version is GameVersion.BD or GameVersion.SP; public override string GetString(ReadOnlySpan data) => StringConverter8.GetString(data); @@ -256,8 +251,8 @@ public override int SetString(Span destBuffer, ReadOnlySpan value, i public override uint ID32 { get => MyStatus.ID32; set => MyStatus.ID32 = value; } public override ushort TID16 { get => MyStatus.TID16; set => MyStatus.TID16 = value; } public override ushort SID16 { get => MyStatus.SID16; set => MyStatus.SID16 = value; } - public override int Game { get => MyStatus.Game; set => MyStatus.Game = value; } - public override int Gender { get => MyStatus.Male ? 0 : 1; set => MyStatus.Male = value == 0; } + public override GameVersion Version { get => MyStatus.Game; set => MyStatus.Game = value; } + public override byte Gender { get => MyStatus.Male ? (byte)0 : (byte)1; set => MyStatus.Male = value == 0; } public override int Language { get => Config.Language; set => Config.Language = value; } public override string OT { get => MyStatus.OT; set => MyStatus.OT = value; } public override uint Money { get => MyStatus.Money; set => MyStatus.Money = value; } diff --git a/PKHeX.Core/Saves/SAV8LA.cs b/PKHeX.Core/Saves/SAV8LA.cs index eccff20f0..473cf9b2e 100644 --- a/PKHeX.Core/Saves/SAV8LA.cs +++ b/PKHeX.Core/Saves/SAV8LA.cs @@ -61,7 +61,7 @@ public override void CopyChangesFrom(SaveFile sav) public override PA8 BlankPKM => new(); public override Type PKMType => typeof(PA8); public override int MaxEV => EffortValues.Max252; - public override int Generation => 8; + public override byte Generation => 8; public override EntityContext Context => EntityContext.Gen8a; public override int MaxStringLengthOT => 12; public override int MaxStringLengthNickname => 12; @@ -72,16 +72,12 @@ public override void CopyChangesFrom(SaveFile sav) public override uint ID32 { get => MyStatus.ID32; set => MyStatus.ID32 = value; } public override ushort TID16 { get => MyStatus.TID16; set => MyStatus.TID16 = value; } public override ushort SID16 { get => MyStatus.SID16; set => MyStatus.SID16 = value; } - public override int Game { get => MyStatus.Game; set => MyStatus.Game = value; } - public override int Gender { get => MyStatus.Gender; set => MyStatus.Gender = value; } + public override GameVersion Version { get => (GameVersion)MyStatus.Game; set => MyStatus.Game = (byte)value; } + public override byte Gender { get => MyStatus.Gender; set => MyStatus.Gender = value; } public override int Language { get => MyStatus.Language; set => MyStatus.Language = value; } public override string OT { get => MyStatus.OT; set => MyStatus.OT = value; } - public override GameVersion Version => Game switch - { - (int)GameVersion.PLA => GameVersion.PLA, - _ => GameVersion.Invalid, - }; + public override bool IsVersionValid() => Version is GameVersion.PLA; protected override void SetChecksums() { } // None! protected override byte[] GetFinalData() => SwishCrypto.Encrypt(AllBlocks); @@ -101,7 +97,7 @@ protected override SAV8LA CloneInternal() public override ushort MaxSpeciesID => Legal.MaxSpeciesID_8a; public override int MaxItemID => Legal.MaxItemID_8a; public override int MaxBallID => Legal.MaxBallID_8a; - public override int MaxGameID => Legal.MaxGameID_HOME; + public override GameVersion MaxGameID => Legal.MaxGameID_HOME; public override int MaxAbilityID => Legal.MaxAbilityID_8a; #region Blocks diff --git a/PKHeX.Core/Saves/SAV8SWSH.cs b/PKHeX.Core/Saves/SAV8SWSH.cs index fd9783297..b0d793637 100644 --- a/PKHeX.Core/Saves/SAV8SWSH.cs +++ b/PKHeX.Core/Saves/SAV8SWSH.cs @@ -96,7 +96,7 @@ protected override SAV8SWSH CloneInternal() public override ushort MaxSpeciesID => m_spec; public override int MaxItemID => m_item; public override int MaxBallID => Legal.MaxBallID_8; - public override int MaxGameID => Legal.MaxGameID_8; + public override GameVersion MaxGameID => Legal.MaxGameID_8; public override int MaxAbilityID => m_abil; private void Initialize() @@ -149,19 +149,14 @@ private void Initialize() public override int BoxCount => BoxLayout8.BoxCount; public override int MaxEV => EffortValues.Max252; - public override int Generation => 8; + public override byte Generation => 8; public override EntityContext Context => EntityContext.Gen8; public override int MaxStringLengthOT => 12; public override int MaxStringLengthNickname => 12; protected override PK8 GetPKM(byte[] data) => new(data); protected override byte[] DecryptPKM(byte[] data) => PokeCrypto.DecryptArray8(data); - public override GameVersion Version => Game switch - { - (int)GameVersion.SW => GameVersion.SW, - (int)GameVersion.SH => GameVersion.SH, - _ => GameVersion.Invalid, - }; + public override bool IsVersionValid() => Version is GameVersion.SW or GameVersion.SH; public override string GetString(ReadOnlySpan data) => StringConverter8.GetString(data); public override int SetString(Span destBuffer, ReadOnlySpan value, int maxLength, StringConverterOption option) @@ -171,8 +166,8 @@ public override int SetString(Span destBuffer, ReadOnlySpan value, i public override uint ID32 { get => MyStatus.ID32; set => MyStatus.ID32 = value; } public override ushort TID16 { get => MyStatus.TID16; set => MyStatus.TID16 = value; } public override ushort SID16 { get => MyStatus.SID16; set => MyStatus.SID16 = value; } - public override int Game { get => MyStatus.Game; set => MyStatus.Game = value; } - public override int Gender { get => MyStatus.Gender; set => MyStatus.Gender = value; } + public override GameVersion Version { get => (GameVersion)MyStatus.Game; set => MyStatus.Game = (byte)value; } + public override byte Gender { get => MyStatus.Gender; set => MyStatus.Gender = value; } public override int Language { get => MyStatus.Language; set => MyStatus.Language = value; } public override string OT { get => MyStatus.OT; set => MyStatus.OT = value; } public override uint Money { get => Misc.Money; set => Misc.Money = value; } diff --git a/PKHeX.Core/Saves/SAV9SV.cs b/PKHeX.Core/Saves/SAV9SV.cs index 02ad65a8a..a6e0074b3 100644 --- a/PKHeX.Core/Saves/SAV9SV.cs +++ b/PKHeX.Core/Saves/SAV9SV.cs @@ -98,7 +98,7 @@ protected override SAV9SV CloneInternal() private ushort m_spec, m_item, m_move, m_abil; public override int MaxBallID => Legal.MaxBallID_9; - public override int MaxGameID => Legal.MaxGameID_HOME; + public override GameVersion MaxGameID => Legal.MaxGameID_HOME; public override ushort MaxMoveID => m_move; public override ushort MaxSpeciesID => m_spec; public override int MaxItemID => m_item; @@ -154,19 +154,14 @@ private void Initialize() public override int BoxCount => BoxLayout9.BoxCount; public override int MaxEV => EffortValues.Max252; - public override int Generation => 9; + public override byte Generation => 9; public override EntityContext Context => EntityContext.Gen9; public override int MaxStringLengthOT => 12; public override int MaxStringLengthNickname => 12; protected override PK9 GetPKM(byte[] data) => new(data); protected override byte[] DecryptPKM(byte[] data) => PokeCrypto.DecryptArray9(data); - public override GameVersion Version => Game switch - { - (int)GameVersion.SL => GameVersion.SL, - (int)GameVersion.VL => GameVersion.VL, - _ => GameVersion.Invalid, - }; + public override bool IsVersionValid() => Version is GameVersion.SL or GameVersion.VL; public override string GetString(ReadOnlySpan data) => StringConverter8.GetString(data); public override int SetString(Span destBuffer, ReadOnlySpan value, int maxLength, StringConverterOption option) @@ -176,8 +171,8 @@ public override int SetString(Span destBuffer, ReadOnlySpan value, i public override uint ID32 { get => MyStatus.ID32; set => MyStatus.ID32 = value; } public override ushort TID16 { get => MyStatus.TID16; set => MyStatus.TID16 = value; } public override ushort SID16 { get => MyStatus.SID16; set => MyStatus.SID16 = value; } - public override int Game { get => MyStatus.Game; set => MyStatus.Game = value; } - public override int Gender { get => MyStatus.Gender; set => MyStatus.Gender = value; } + public override GameVersion Version { get => (GameVersion)MyStatus.Game; set => MyStatus.Game = (byte)value; } + public override byte Gender { get => MyStatus.Gender; set => MyStatus.Gender = value; } public override int Language { get => MyStatus.Language; set => MyStatus.Language = value; } public override string OT { get => MyStatus.OT; set => MyStatus.OT = value; } public override uint Money { get => (uint)Blocks.GetBlockValue(SaveBlockAccessor9SV.KMoney); set => Blocks.SetBlockValue(SaveBlockAccessor9SV.KMoney, value); } diff --git a/PKHeX.Core/Saves/SAV_STADIUM.cs b/PKHeX.Core/Saves/SAV_STADIUM.cs index 3c4ffa3b9..7beabb192 100644 --- a/PKHeX.Core/Saves/SAV_STADIUM.cs +++ b/PKHeX.Core/Saves/SAV_STADIUM.cs @@ -19,7 +19,7 @@ public abstract class SAV_STADIUM : SaveFile, ILangDeviantSave public bool Korean => false; public sealed override int MaxBallID => 0; // unused - public sealed override int MaxGameID => 99; // unused + public sealed override GameVersion MaxGameID => GameVersion.Gen1; // unused public sealed override int MaxMoney => 999999; public sealed override int MaxCoins => 9999; diff --git a/PKHeX.Core/Saves/SaveFile.cs b/PKHeX.Core/Saves/SaveFile.cs index d4f35c684..9ca3b413a 100644 --- a/PKHeX.Core/Saves/SaveFile.cs +++ b/PKHeX.Core/Saves/SaveFile.cs @@ -60,10 +60,11 @@ protected virtual byte[] GetFinalData() #region Metadata & Limits public virtual string MiscSaveInfo() => string.Empty; - public virtual GameVersion Version { get; protected set; } + public virtual bool IsVersionValid() => true; + public virtual GameVersion Version { get => default; set { } } public abstract bool ChecksumsValid { get; } public abstract string ChecksumInfo { get; } - public abstract int Generation { get; } + public abstract byte Generation { get; } public abstract EntityContext Context { get; } #endregion @@ -93,8 +94,8 @@ public void SetData(Span dest, ReadOnlySpan input) public abstract int MaxAbilityID { get; } public abstract int MaxItemID { get; } public abstract int MaxBallID { get; } - public abstract int MaxGameID { get; } - public virtual int MinGameID => 0; + public abstract GameVersion MaxGameID { get; } + public virtual GameVersion MinGameID => 0; #endregion ///

@@ -136,9 +137,8 @@ public virtual MysteryGiftAlbum GiftAlbum #endregion #region Player Info - public virtual int Gender { get; set; } + public virtual byte Gender { get; set; } public virtual int Language { get => -1; set { } } - public virtual int Game { get => (int)GameVersion.Any; set { } } public virtual uint ID32 { get; set; } public virtual ushort TID16 { get; set; } public virtual ushort SID16 { get; set; } diff --git a/PKHeX.Core/Saves/Storage/BulkStorage.cs b/PKHeX.Core/Saves/Storage/BulkStorage.cs index 25bbd9795..47912b2b7 100644 --- a/PKHeX.Core/Saves/Storage/BulkStorage.cs +++ b/PKHeX.Core/Saves/Storage/BulkStorage.cs @@ -34,14 +34,14 @@ protected BulkStorage(byte[] data, Type t, int start, int slotsPerBox = 30) : ba protected override int SIZE_STORED => blank.SIZE_STORED; protected override int SIZE_PARTY => blank.SIZE_PARTY; public sealed override int MaxEV => blank.MaxEV; - public sealed override int Generation => blank.Format; + public sealed override byte Generation => blank.Format; public sealed override EntityContext Context => blank.Context; public sealed override ushort MaxMoveID => blank.MaxMoveID; public sealed override ushort MaxSpeciesID => blank.MaxSpeciesID; public sealed override int MaxAbilityID => blank.MaxAbilityID; public sealed override int MaxItemID => blank.MaxItemID; public sealed override int MaxBallID => blank.MaxBallID; - public sealed override int MaxGameID => blank.MaxGameID; + public sealed override GameVersion MaxGameID => blank.MaxGameID; public sealed override int MaxStringLengthOT => blank.MaxStringLengthOT; public sealed override int MaxStringLengthNickname => blank.MaxStringLengthNickname; public bool IsBigEndian => blank is BK4 or XK3 or CK3; diff --git a/PKHeX.Core/Saves/Storage/SAV4Ranch.cs b/PKHeX.Core/Saves/Storage/SAV4Ranch.cs index 4ed6e4dea..561b8f394 100644 --- a/PKHeX.Core/Saves/Storage/SAV4Ranch.cs +++ b/PKHeX.Core/Saves/Storage/SAV4Ranch.cs @@ -187,9 +187,9 @@ public void WriteBoxSlotInternal(PKM pk, Span data, string htName = "", us { RK4 rk = (RK4)this.GetCompatiblePKM(pk); rk.OwnershipType = type; - rk.HT_TID = htTID; - rk.HT_SID = htSID; - rk.HT_Name = htName; + rk.HandlingTrainerTID = htTID; + rk.HandlingTrainerSID = htSID; + rk.HandlingTrainerName = htName; WriteBoxSlot(rk, data); } diff --git a/PKHeX.Core/Saves/Substructures/Battle Videos/BV3.cs b/PKHeX.Core/Saves/Substructures/Battle Videos/BV3.cs index 4c2939281..41eec2308 100644 --- a/PKHeX.Core/Saves/Substructures/Battle Videos/BV3.cs +++ b/PKHeX.Core/Saves/Substructures/Battle Videos/BV3.cs @@ -12,7 +12,7 @@ public sealed class BV3(byte[] Data) : BattleVideo public readonly byte[] Data = (byte[])Data.Clone(); internal const int SIZE = 0xF80; - public override int Generation => 3; + public override byte Generation => 3; public override IReadOnlyList BattlePKMs => PlayerTeams.SelectMany(z => z).ToArray(); diff --git a/PKHeX.Core/Saves/Substructures/Battle Videos/BV6.cs b/PKHeX.Core/Saves/Substructures/Battle Videos/BV6.cs index e76111e27..152074d84 100644 --- a/PKHeX.Core/Saves/Substructures/Battle Videos/BV6.cs +++ b/PKHeX.Core/Saves/Substructures/Battle Videos/BV6.cs @@ -15,7 +15,7 @@ public sealed class BV6(byte[] Data) : BattleVideo private const int PlayerCount = 4; public override IReadOnlyList BattlePKMs => PlayerTeams.SelectMany(t => t).ToArray(); - public override int Generation => 6; + public override byte Generation => 6; internal new static bool IsValid(ReadOnlySpan data) { diff --git a/PKHeX.Core/Saves/Substructures/Battle Videos/BV7.cs b/PKHeX.Core/Saves/Substructures/Battle Videos/BV7.cs index 263c35f51..c17366456 100644 --- a/PKHeX.Core/Saves/Substructures/Battle Videos/BV7.cs +++ b/PKHeX.Core/Saves/Substructures/Battle Videos/BV7.cs @@ -11,7 +11,7 @@ public sealed class BV7(byte[] data) : BattleVideo private const string NPC = "NPC"; private const int PlayerCount = 4; - public override int Generation => 7; + public override byte Generation => 7; private readonly byte[] Data = (byte[])data.Clone(); public override IReadOnlyList BattlePKMs => PlayerTeams.SelectMany(t => t).ToArray(); diff --git a/PKHeX.Core/Saves/Substructures/Battle Videos/BattleVideo.cs b/PKHeX.Core/Saves/Substructures/Battle Videos/BattleVideo.cs index 456a5c613..0663ccafe 100644 --- a/PKHeX.Core/Saves/Substructures/Battle Videos/BattleVideo.cs +++ b/PKHeX.Core/Saves/Substructures/Battle Videos/BattleVideo.cs @@ -6,7 +6,7 @@ namespace PKHeX.Core; public abstract class BattleVideo : IPokeGroup { public abstract IReadOnlyList BattlePKMs { get; } - public abstract int Generation { get; } + public abstract byte Generation { get; } public IEnumerable Contents => BattlePKMs; diff --git a/PKHeX.Core/Saves/Substructures/Gen3/CXD/ShadowInfoEntryColo.cs b/PKHeX.Core/Saves/Substructures/Gen3/CXD/ShadowInfoEntryColo.cs index 4950c8e26..7883d59c2 100644 --- a/PKHeX.Core/Saves/Substructures/Gen3/CXD/ShadowInfoEntryColo.cs +++ b/PKHeX.Core/Saves/Substructures/Gen3/CXD/ShadowInfoEntryColo.cs @@ -12,6 +12,6 @@ public sealed class ShadowInfoEntryColo public ShadowInfoEntryColo(byte[] data) => Data = data; public uint PID { get => ReadUInt32BigEndian(Data.AsSpan(0x00)); set => WriteUInt32BigEndian(Data.AsSpan(0x00), value); } - public int Met_Location { get => ReadUInt16BigEndian(Data.AsSpan(0x06)); set => WriteUInt16BigEndian(Data.AsSpan(0x06), (ushort)value); } + public ushort MetLocation { get => ReadUInt16BigEndian(Data.AsSpan(0x06)); set => WriteUInt16BigEndian(Data.AsSpan(0x06), value); } public uint Unk08 { get => ReadUInt32BigEndian(Data.AsSpan(0x08)); set => WriteUInt32BigEndian(Data.AsSpan(0x08), value); } } diff --git a/PKHeX.Core/Saves/Substructures/Gen3/HallFame3.cs b/PKHeX.Core/Saves/Substructures/Gen3/HallFame3.cs index a7e5db3bb..eab3151e3 100644 --- a/PKHeX.Core/Saves/Substructures/Gen3/HallFame3.cs +++ b/PKHeX.Core/Saves/Substructures/Gen3/HallFame3.cs @@ -56,8 +56,8 @@ public sealed class HallFame3PKM(byte[] Data, int Offset, bool Japanese) : ISpec public uint PID { get => ReadUInt32LittleEndian(Data.AsSpan(4 + Offset)); set => WriteUInt32LittleEndian(Data.AsSpan(4 + Offset), value); } private int SpecLevel { get => ReadUInt16LittleEndian(Data.AsSpan(8 + Offset)); set => WriteUInt16LittleEndian(Data.AsSpan(8 + Offset), (ushort)value); } - private Span Nickname_Trash => Data.AsSpan(10 + Offset, 10); - public string Nickname { get => StringConverter3.GetString(Nickname_Trash, Japanese); set => StringConverter3.SetString(Nickname_Trash, value, 10, Japanese, StringConverterOption.ClearZero); } + private Span NicknameTrash => Data.AsSpan(10 + Offset, 10); + public string Nickname { get => StringConverter3.GetString(NicknameTrash, Japanese); set => StringConverter3.SetString(NicknameTrash, value, 10, Japanese, StringConverterOption.ClearZero); } public ushort Species { get => (ushort)(SpecLevel & 0x1FF); set => SpecLevel = (SpecLevel & 0xFE00) | value; } public byte Form => 0; // no forms; derive Unown's from PID else use the Version for Deoxys. diff --git a/PKHeX.Core/Saves/Substructures/Gen3/Record3.cs b/PKHeX.Core/Saves/Substructures/Gen3/Record3.cs index 6d524c9af..8bce54507 100644 --- a/PKHeX.Core/Saves/Substructures/Gen3/Record3.cs +++ b/PKHeX.Core/Saves/Substructures/Gen3/Record3.cs @@ -16,30 +16,30 @@ private int GetRecordOffset(int record) return offset; } - public static int GetOffset(GameVersion ver) => ver switch + public static int GetOffset(GameVersion version) => version switch { GameVersion.RS or GameVersion.R or GameVersion.S => 0x1540, GameVersion.E => 0x159C, GameVersion.FRLG or GameVersion.FR or GameVersion.LG => 0x1200, - _ => throw new ArgumentOutOfRangeException(nameof(ver), ver, null), + _ => throw new ArgumentOutOfRangeException(nameof(version), version, null), }; - private static Type GetEnumType(GameVersion ver) => ver switch + private static Type GetEnumType(GameVersion version) => version switch { GameVersion.RS or GameVersion.R or GameVersion.S => typeof(RecID3RuSa), GameVersion.FRLG or GameVersion.FR or GameVersion.LG => typeof(RecID3FRLG), GameVersion.E => typeof(RecID3Emerald), - _ => throw new ArgumentOutOfRangeException(nameof(ver), ver, null), + _ => throw new ArgumentOutOfRangeException(nameof(version), version, null), }; - public static int[] GetEnumValues(GameVersion ver) => (int[])Enum.GetValues(GetEnumType(ver)); - public static string[] GetEnumNames(GameVersion ver) => Enum.GetNames(GetEnumType(ver)); + public static int[] GetEnumValues(GameVersion version) => (int[])Enum.GetValues(GetEnumType(version)); + public static string[] GetEnumNames(GameVersion version) => Enum.GetNames(GetEnumType(version)); public static IList GetItems(SAV3 sav) { - var ver = sav.Version; - var names = GetEnumNames(ver); - var values = GetEnumValues(ver); + var version = sav.Version; + var names = GetEnumNames(version); + var values = GetEnumValues(version); var result = new ComboItem[values.Length]; for (int i = 0; i < result.Length; i++) diff --git a/PKHeX.Core/Saves/Substructures/Gen3/Roamer3.cs b/PKHeX.Core/Saves/Substructures/Gen3/Roamer3.cs index c50f7984d..94caa4eaa 100644 --- a/PKHeX.Core/Saves/Substructures/Gen3/Roamer3.cs +++ b/PKHeX.Core/Saves/Substructures/Gen3/Roamer3.cs @@ -22,7 +22,7 @@ public Roamer3(SAV3 sav) IsGlitched = sav.Version != GameVersion.E; } - private uint IV32 + public uint IV32 { get => ReadUInt32LittleEndian(Data.AsSpan(Offset)); set => WriteUInt32LittleEndian(Data.AsSpan(Offset), value); @@ -46,20 +46,20 @@ public int HP_Current set => WriteInt16LittleEndian(Data.AsSpan(Offset + 10), (short)value); } - public int CurrentLevel + public byte CurrentLevel { get => Data[Offset + 12]; - set => Data[Offset + 12] = (byte)value; + set => Data[Offset + 12] = value; } public int Status { get => Data[Offset + 0x0D]; set => Data[Offset + 0x0D] = (byte)value; } - public byte CNT_Cool { get => Data[Offset + 0x0E]; set => Data[Offset + 0x0E] = value; } - public byte CNT_Beauty { get => Data[Offset + 0x0F]; set => Data[Offset + 0x0F] = value; } - public byte CNT_Cute { get => Data[Offset + 0x10]; set => Data[Offset + 0x10] = value; } - public byte CNT_Smart { get => Data[Offset + 0x11]; set => Data[Offset + 0x11] = value; } - public byte CNT_Tough { get => Data[Offset + 0x12]; set => Data[Offset + 0x12] = value; } - public byte CNT_Sheen { get => 0; set { } } + public byte ContestCool { get => Data[Offset + 0x0E]; set => Data[Offset + 0x0E] = value; } + public byte ContestBeauty { get => Data[Offset + 0x0F]; set => Data[Offset + 0x0F] = value; } + public byte ContestCute { get => Data[Offset + 0x10]; set => Data[Offset + 0x10] = value; } + public byte ContestSmart { get => Data[Offset + 0x11]; set => Data[Offset + 0x11] = value; } + public byte ContestTough { get => Data[Offset + 0x12]; set => Data[Offset + 0x12] = value; } + public byte ContestSheen { get => 0; set { } } public bool Active { get => Data[Offset + 0x13] == 1; set => Data[Offset + 0x13] = value ? (byte)1 : (byte)0; } // Derived Properties diff --git a/PKHeX.Core/Saves/Substructures/Gen3/SecretBase3.cs b/PKHeX.Core/Saves/Substructures/Gen3/SecretBase3.cs index 962f091f4..e3c25676a 100644 --- a/PKHeX.Core/Saves/Substructures/Gen3/SecretBase3.cs +++ b/PKHeX.Core/Saves/Substructures/Gen3/SecretBase3.cs @@ -9,9 +9,9 @@ public sealed class SecretBase3(byte[] Data, int Offset) public int SecretBaseLocation { get => Data[Offset + 0]; set => Data[Offset + 0] = (byte) value; } - public int OT_Gender + public byte OriginalTrainerGender { - get => (Data[Offset + 1] >> 4) & 1; + get => (byte)((Data[Offset + 1] >> 4) & 1); set => Data[Offset + 1] = (byte) ((Data[Offset + 1] & 0xEF) | ((value & 1) << 4)); } @@ -27,7 +27,7 @@ public int RegistryStatus set => Data[Offset + 1] = (byte)((Data[Offset + 1] & 0x3F) | ((value & 3) << 6)); } - public string OT_Name + public string OriginalTrainerName { get => StringConverter3.GetString(Data.AsSpan(Offset + 2, 7), Japanese); set => StringConverter3.SetString(Data.AsSpan(Offset + 2, 7), value, 7, Japanese, StringConverterOption.ClearFF); diff --git a/PKHeX.Core/Saves/Substructures/Gen3/SecretBase3PKM.cs b/PKHeX.Core/Saves/Substructures/Gen3/SecretBase3PKM.cs index 731c16919..20e241ecb 100644 --- a/PKHeX.Core/Saves/Substructures/Gen3/SecretBase3PKM.cs +++ b/PKHeX.Core/Saves/Substructures/Gen3/SecretBase3PKM.cs @@ -18,7 +18,7 @@ public sealed class SecretBase3PKM : ISpeciesForm private PersonalInfo3 PersonalInfo => PersonalTable.E.GetFormEntry(Species, Form); public byte Form => Species == (int)Core.Species.Unown ? EntityPID.GetUnownForm3(PID) : (byte)0; - public int Gender => EntityGender.GetFromPIDAndRatio(PID, PersonalInfo.Gender); + public byte Gender => EntityGender.GetFromPIDAndRatio(PID, PersonalInfo.Gender); public void GetMoves(Span moves) { diff --git a/PKHeX.Core/Saves/Substructures/Gen3/Swarm3.cs b/PKHeX.Core/Saves/Substructures/Gen3/Swarm3.cs index e53a30529..628743e00 100644 --- a/PKHeX.Core/Saves/Substructures/Gen3/Swarm3.cs +++ b/PKHeX.Core/Saves/Substructures/Gen3/Swarm3.cs @@ -44,6 +44,10 @@ public Swarm3(Species species, byte level, byte map, Move m1, Move m2 = 0, Move public static class Swarm3Details { + /// + /// Hardcoded templates available to set to the save file. + /// + /// Ruby/Sapphire public static readonly Swarm3[] Swarms_RS = [ new(Surskit, 03, 0x11, Bubble, QuickAttack), // Route 102 @@ -53,6 +57,10 @@ public static class Swarm3Details new(Skitty, 15, 0x1F, Growl, Tackle), // Route 116 ]; + /// + /// Hardcoded templates available to set to the save file. + /// + /// public static readonly Swarm3[] Swarms_E = [ new(Seedot, 03, 0x11, Bide, Harden, LeechSeed), // Route 102 diff --git a/PKHeX.Core/Saves/Substructures/Gen4/Dendou4.cs b/PKHeX.Core/Saves/Substructures/Gen4/Dendou4.cs index 5ff57a7b7..44df49979 100644 --- a/PKHeX.Core/Saves/Substructures/Gen4/Dendou4.cs +++ b/PKHeX.Core/Saves/Substructures/Gen4/Dendou4.cs @@ -98,17 +98,17 @@ private Dendou4Entity GetEntity(int index) public uint PID { get => ReadUInt32LittleEndian(Data[4..]); set => WriteUInt32LittleEndian(Data[4..], value); } public uint ID32 { get => ReadUInt32LittleEndian(Data[8..]); set => WriteUInt32LittleEndian(Data[8..], value); } - public Span Nickname_Trash => Data.Slice(0x0C, 22); - public Span OT_Trash => Data.Slice(0x22, 16); + public Span NicknameTrash => Data.Slice(0x0C, 22); + public Span OriginalTrainerTrash => Data.Slice(0x22, 16); public string Nickname { - get => StringConverter4.GetString(Nickname_Trash); - set => StringConverter4.SetString(Nickname_Trash, value, 10, StringConverterOption.None); + get => StringConverter4.GetString(NicknameTrash); + set => StringConverter4.SetString(NicknameTrash, value, 10, StringConverterOption.None); } - public string OT_Name + public string OriginalTrainerName { - get => StringConverter4.GetString(OT_Trash); - set => StringConverter4.SetString(OT_Trash, value, 7, StringConverterOption.None); + get => StringConverter4.GetString(OriginalTrainerTrash); + set => StringConverter4.SetString(OriginalTrainerTrash, value, 7, StringConverterOption.None); } public ushort Move1 { get => ReadUInt16LittleEndian(Data[0x32..]); set => WriteUInt16LittleEndian(Data[0x32..], value); } diff --git a/PKHeX.Core/Saves/Substructures/Gen5/Color15Bit.cs b/PKHeX.Core/Saves/Substructures/Gen5/Color15Bit.cs index ad93a802a..045ad17e5 100644 --- a/PKHeX.Core/Saves/Substructures/Gen5/Color15Bit.cs +++ b/PKHeX.Core/Saves/Substructures/Gen5/Color15Bit.cs @@ -31,11 +31,11 @@ public static int GetColorExpand(ushort val) /// /// Converts a 32-bit color value to a 15-bit color value /// - public static ushort GetColorCompress(int v) + public static ushort GetColorCompress(int rgb) { - var R = (byte)(v >> 16); - var G = (byte)(v >> 8); - var B = (byte)(v >> 0); + var R = (byte)(rgb >> 16); + var G = (byte)(rgb >> 8); + var B = (byte)(rgb >> 0); int val = 0; val |= Convert8to5(R) << 0; @@ -47,12 +47,12 @@ public static ushort GetColorCompress(int v) /// /// Converts a color value from 8-bit to 5-bit /// - /// 8-bit color value + /// 8-bit color value /// 5-bit color value - private static byte Convert8to5(int colorval) + private static byte Convert8to5(byte value) { byte i = 0; - while (colorval > Convert5To8[i]) + while (value > Convert5To8[i]) i++; return i; } diff --git a/PKHeX.Core/Saves/Substructures/Gen5/Entree/EntreeSlot.cs b/PKHeX.Core/Saves/Substructures/Gen5/Entree/EntreeSlot.cs index a9e6bf8b7..816d3bfe1 100644 --- a/PKHeX.Core/Saves/Substructures/Gen5/Entree/EntreeSlot.cs +++ b/PKHeX.Core/Saves/Substructures/Gen5/Entree/EntreeSlot.cs @@ -29,9 +29,9 @@ public sealed class EntreeSlot(Memory Data) : ISpeciesForm /// /// index /// - public int Gender // bits 21-22 + public byte Gender // bits 21-22 { - get => (int)(RawValue & 0x0060_0000) >> 21; + get => (byte)((RawValue & 0x0060_0000) >> 21); set => RawValue = (RawValue & 0xFF9F_FFFF) | ((uint)(value & 0x3) << 21); } diff --git a/PKHeX.Core/Saves/Substructures/Gen5/PlayerData5.cs b/PKHeX.Core/Saves/Substructures/Gen5/PlayerData5.cs index ca62f62e6..2a6da93fa 100644 --- a/PKHeX.Core/Saves/Substructures/Gen5/PlayerData5.cs +++ b/PKHeX.Core/Saves/Substructures/Gen5/PlayerData5.cs @@ -11,12 +11,12 @@ public sealed class PlayerData5 : SaveBlock public PlayerData5(SAV5BW sav, int offset) : base(sav) => Offset = offset; public PlayerData5(SAV5B2W2 sav, int offset) : base(sav) => Offset = offset; - private Span OT_Trash => Data.AsSpan(Offset + 4, 0x10); + private Span OriginalTrainerTrash => Data.AsSpan(Offset + 4, 0x10); public string OT { - get => SAV.GetString(OT_Trash); - set => SAV.SetString(OT_Trash, value, SAV.MaxStringLengthOT, StringConverterOption.ClearZero); + get => SAV.GetString(OriginalTrainerTrash); + set => SAV.SetString(OriginalTrainerTrash, value, SAV.MaxStringLengthOT, StringConverterOption.ClearZero); } public uint ID32 @@ -55,16 +55,16 @@ public int Language set => Data[Offset + 0x1E] = (byte)value; } - public int Game + public byte Game { get => Data[Offset + 0x1F]; - set => Data[Offset + 0x1F] = (byte)value; + set => Data[Offset + 0x1F] = value; } - public int Gender + public byte Gender { get => Data[Offset + 0x21]; - set => Data[Offset + 0x21] = (byte)value; + set => Data[Offset + 0x21] = value; } // 22,23 ?? diff --git a/PKHeX.Core/Saves/Substructures/Gen6/Encount6.cs b/PKHeX.Core/Saves/Substructures/Gen6/Encount6.cs index 255f5bf22..5c587e16d 100644 --- a/PKHeX.Core/Saves/Substructures/Gen6/Encount6.cs +++ b/PKHeX.Core/Saves/Substructures/Gen6/Encount6.cs @@ -118,7 +118,7 @@ public sealed class Roamer6(Memory Data) public bool Flag1 { get => SpecForm >> 14 != 0; set => SpecForm = (ushort)((SpecForm & 0xBFFF) | (value ? (1 << 14) : 0)); } public bool Flag2 { get => SpecForm >> 15 != 0; set => SpecForm = (ushort)((SpecForm & 0x7FFF) | (value ? (1 << 15) : 0)); } - public int CurrentLevel { get => Span[4]; set => Span[4] = (byte)value; } + public byte CurrentLevel { get => Span[4]; set => Span[4] = value; } private int Status { get => Span[7]; set => Span[7] = (byte)value; } public Roamer6State RoamStatus { get => (Roamer6State)((Status >> 4) & 0xF); set => Status = (Status & 0x0F) | (((int)value << 4) & 0xF0); } diff --git a/PKHeX.Core/Saves/Substructures/Gen6/HallFame6Entity.cs b/PKHeX.Core/Saves/Substructures/Gen6/HallFame6Entity.cs index 59e98c171..5c1a134dc 100644 --- a/PKHeX.Core/Saves/Substructures/Gen6/HallFame6Entity.cs +++ b/PKHeX.Core/Saves/Substructures/Gen6/HallFame6Entity.cs @@ -27,14 +27,14 @@ namespace PKHeX.Core; public uint Level { get => (Pack >> 07) & 0x7Fu; set => Pack = (Pack & ~(0x7Fu << 07)) | ((value & 0x7F) << 07); } private uint Shiny { get => (Pack >> 14) & 0x01u; set => Pack = (Pack & ~(0x01u << 14)) | ((value & 0x01) << 14); } private uint Nick { get => (Pack >> 15) & 0x01u; set => Pack = (Pack & ~(0x01u << 15)) | ((value & 0x01) << 15); } - public uint OT_Gender { get => (Pack >> 16) & 0x01u; set => Pack = (Pack & ~(0x01u << 16)) | ((value & 0x01) << 16); } + public uint OriginalTrainerGender { get => (Pack >> 16) & 0x01u; set => Pack = (Pack & ~(0x01u << 16)) | ((value & 0x01) << 16); } // remaining bits unused public bool IsNicknamed { get => Nick == 1; set => Nick = value ? 1u : 0u; } public bool IsShiny { get => Shiny == 1; set => Shiny = value ? 1u : 0u; } private Span Nick_Trash => Data.Slice(0x18, 24); - private Span OT_Trash => Data.Slice(0x30, 24); + private Span OriginalTrainerTrash => Data.Slice(0x30, 24); // Don't mimic in-game behavior of not clearing strings. First entry should always have clean trash. private const StringConverterOption Option = StringConverterOption.ClearZero; @@ -42,7 +42,7 @@ namespace PKHeX.Core; public void ClearTrash() { Nick_Trash.Clear(); - OT_Trash.Clear(); + OriginalTrainerTrash.Clear(); } public string Nickname @@ -51,9 +51,9 @@ public string Nickname set => StringConverter6.SetString(Nick_Trash, value, 12, Option); } - public string OT_Name + public string OriginalTrainerName { - get => StringConverter6.GetString(OT_Trash); - set => StringConverter6.SetString(OT_Trash, value, 12, Option); + get => StringConverter6.GetString(OriginalTrainerTrash); + set => StringConverter6.SetString(OriginalTrainerTrash, value, 12, Option); } } diff --git a/PKHeX.Core/Saves/Substructures/Gen6/MyStatus6.cs b/PKHeX.Core/Saves/Substructures/Gen6/MyStatus6.cs index cd798f8ad..f0d7a2d6a 100644 --- a/PKHeX.Core/Saves/Substructures/Gen6/MyStatus6.cs +++ b/PKHeX.Core/Saves/Substructures/Gen6/MyStatus6.cs @@ -28,16 +28,16 @@ public ushort SID16 set => WriteUInt16LittleEndian(Data.AsSpan(Offset + 2), value); } - public int Game + public byte Game { get => Data[Offset + 4]; - set => Data[Offset + 4] = (byte)value; + set => Data[Offset + 4] = value; } - public int Gender + public byte Gender { get => Data[Offset + 5]; - set => Data[Offset + 5] = (byte)value; + set => Data[Offset + 5] = value; } public int MultiplayerSpriteID_1 @@ -103,12 +103,12 @@ public int Language set => Data[Offset + 0x2D] = (byte)value; } - private Span OT_Trash => Data.AsSpan(Offset + 0x48, 0x1A); + private Span OriginalTrainerTrash => Data.AsSpan(Offset + 0x48, 0x1A); public string OT { - get => SAV.GetString(OT_Trash); - set => SAV.SetString(OT_Trash, value, SAV.MaxStringLengthOT, StringConverterOption.ClearZero); + get => SAV.GetString(OriginalTrainerTrash); + set => SAV.SetString(OriginalTrainerTrash, value, SAV.MaxStringLengthOT, StringConverterOption.ClearZero); } private Span GetSayingSpan(int say) => Data.AsSpan(GetSayingOffset(say), SAV6.LongStringLength); diff --git a/PKHeX.Core/Saves/Substructures/Gen6/MyStatus6XY.cs b/PKHeX.Core/Saves/Substructures/Gen6/MyStatus6XY.cs index c5c15d5d3..496cab982 100644 --- a/PKHeX.Core/Saves/Substructures/Gen6/MyStatus6XY.cs +++ b/PKHeX.Core/Saves/Substructures/Gen6/MyStatus6XY.cs @@ -15,12 +15,12 @@ public TrainerFashion6 Fashion set => value.Write(Data, Offset + 0x30); } - private Span Nickname_Trash => Data.AsSpan(Offset + 0x62, SAV6.ShortStringLength); + private Span NicknameTrash => Data.AsSpan(Offset + 0x62, SAV6.ShortStringLength); - public string OT_Nick + public string Nickname { - get => SAV.GetString(Nickname_Trash); - set => SAV.SetString(Nickname_Trash, value, 12, StringConverterOption.ClearZero); + get => SAV.GetString(NicknameTrash); + set => SAV.SetString(NicknameTrash, value, 12, StringConverterOption.ClearZero); } public short EyeColor diff --git a/PKHeX.Core/Saves/Substructures/Gen6/PSS6.cs b/PKHeX.Core/Saves/Substructures/Gen6/PSS6.cs index a3d080adf..03b8e4aa7 100644 --- a/PKHeX.Core/Saves/Substructures/Gen6/PSS6.cs +++ b/PKHeX.Core/Saves/Substructures/Gen6/PSS6.cs @@ -60,11 +60,11 @@ private static bool ReadTrainer(List result, ReadOnlySpan data) // uint unk4 = ReadUInt16LittleEndian(data[0x54..]); byte regionID = data[0x56]; byte countryID = data[0x57]; - byte game = data[0x5A]; + var game = (GameVersion)data[0x5A]; // ulong outfit = ReadUInt64LittleEndian(data.AsSpan(ofs + 0x5C)); int favpkm = ReadUInt16LittleEndian(data[0x9C..]) & 0x7FF; - string gamename = GetGameName(game); + var gamename = GetGameName(game); var (country, region) = GeoLocation.GetCountryRegionText(countryID, regionID, GameInfo.CurrentLanguage); result.Add($"OT: {otname}"); result.Add($"Message: {message}"); @@ -75,14 +75,12 @@ private static bool ReadTrainer(List result, ReadOnlySpan data) return false; } - private static string GetGameName(int game) + private static string GetGameName(GameVersion game) { const string unk = "UNKNOWN GAME"; - if (game < 0) + if (!GameVersion.Gen6.Contains(game)) return unk; var list = GameInfo.Strings.gamelist; - if (game >= list.Length) - return unk; - return list[game]; + return list[(byte)game]; } } diff --git a/PKHeX.Core/Saves/Substructures/Gen6/SecretBase/SecretBase6PKM.cs b/PKHeX.Core/Saves/Substructures/Gen6/SecretBase/SecretBase6PKM.cs index fa4253224..bf980fd4c 100644 --- a/PKHeX.Core/Saves/Substructures/Gen6/SecretBase/SecretBase6PKM.cs +++ b/PKHeX.Core/Saves/Substructures/Gen6/SecretBase/SecretBase6PKM.cs @@ -50,10 +50,10 @@ public uint PID set => WriteUInt32LittleEndian(Data.AsSpan(0x10), value); } - public int Nature { get => Data[0x14]; set => Data[0x14] = (byte)value; } + public Nature Nature { get => (Nature)Data[0x14]; set => Data[0x14] = (byte)value; } public bool FatefulEncounter { get => (Data[0x15] & 1) == 1; set => Data[0x15] = (byte)((Data[0x15] & ~0x01) | (value ? 1 : 0)); } - public int Gender { get => (Data[0x15] >> 1) & 0x3; set => Data[0x15] = (byte)((Data[0x15] & ~0x06) | (value << 1)); } + public byte Gender { get => (byte)((Data[0x15] >> 1) & 0x3); set => Data[0x15] = (byte)((Data[0x15] & ~0x06) | (value << 1)); } public byte Form { get => (byte)(Data[0x15] >> 3); set => Data[0x15] = (byte)((Data[0x15] & 0x07) | (value << 3)); } public int EV_HP { get => Data[0x16]; set => Data[0x16] = (byte)value; } @@ -103,7 +103,7 @@ public ushort Move4 public bool IsShiny { get => ((Data[0x2D] >> 5) & 1) == 1; set => Data[0x2D] = (byte)((Data[0x2D] & ~32) | (value ? 32 : 0)); } public int CurrentFriendship { get => Data[0x2E]; set => Data[0x2E] = (byte)value; } - public int Ball { get => Data[0x2F]; set => Data[0x2F] = (byte)value; } - public int CurrentLevel { get => Data[0x30]; set => Data[0x30] = (byte)value; } + public byte Ball { get => Data[0x2F]; set => Data[0x2F] = value; } + public byte CurrentLevel { get => Data[0x30]; set => Data[0x30] = value; } // 0x31,0x32,0x33 unused (alignment padding to u32) } diff --git a/PKHeX.Core/Saves/Substructures/Gen6/SuperTrainBlock.cs b/PKHeX.Core/Saves/Substructures/Gen6/SuperTrainBlock.cs index 018d658f6..e9a6580e8 100644 --- a/PKHeX.Core/Saves/Substructures/Gen6/SuperTrainBlock.cs +++ b/PKHeX.Core/Saves/Substructures/Gen6/SuperTrainBlock.cs @@ -329,6 +329,6 @@ public void LoadFrom(PKM pk) { Species = pk.Species; Form = pk.Form; - Gender = (byte)pk.Gender; + Gender = pk.Gender; } } diff --git a/PKHeX.Core/Saves/Substructures/Gen6/TrainerFashion6.cs b/PKHeX.Core/Saves/Substructures/Gen6/TrainerFashion6.cs index 1673956bb..ecba7f411 100644 --- a/PKHeX.Core/Saves/Substructures/Gen6/TrainerFashion6.cs +++ b/PKHeX.Core/Saves/Substructures/Gen6/TrainerFashion6.cs @@ -20,7 +20,7 @@ private TrainerFashion6(ReadOnlySpan span) data3 = ReadUInt32LittleEndian(span[12..]); } - public static TrainerFashion6 GetFashion(byte[] data, int offset, int gender) + public static TrainerFashion6 GetFashion(byte[] data, int offset, byte gender) { if (gender == 0) // m return new Fashion6Male(data, offset); diff --git a/PKHeX.Core/Saves/Substructures/Gen7/FestaFacility.cs b/PKHeX.Core/Saves/Substructures/Gen7/FestaFacility.cs index 1ab5e3d3e..034526ea0 100644 --- a/PKHeX.Core/Saves/Substructures/Gen7/FestaFacility.cs +++ b/PKHeX.Core/Saves/Substructures/Gen7/FestaFacility.cs @@ -22,8 +22,8 @@ public FestaFacility(SAV7 sav, int index) public int Type { get => Data[0x00]; set => Data[0x00] = (byte)value; } public int Color { get => Data[0x01]; set => Data[0x01] = (byte)value; } public bool IsIntroduced { get => Data[0x02] != 0; set => Data[0x02] = value ? (byte)1 : (byte)0; } - public int Gender { get => Data[0x03]; set => Data[0x03] = (byte)value; } - public string OT_Name { get => StringConverter7.GetString(Data.AsSpan(0x04, 0x1A)); set => StringConverter7.SetString(Data.AsSpan(0x04, 0x1A), value, 12, Language, StringConverterOption.ClearZero); } + public byte Gender { get => Data[0x03]; set => Data[0x03] = value; } + public string OriginalTrainerName { get => StringConverter7.GetString(Data.AsSpan(0x04, 0x1A)); set => StringConverter7.SetString(Data.AsSpan(0x04, 0x1A), value, 12, Language, StringConverterOption.ClearZero); } private int MessageMeet { get => ReadUInt16LittleEndian(Data.AsSpan(0x1E)); set => WriteUInt16LittleEndian(Data.AsSpan(0x1E), (ushort)value); } private int MessagePart { get => ReadUInt16LittleEndian(Data.AsSpan(0x20)); set => WriteUInt16LittleEndian(Data.AsSpan(0x20), (ushort)value); } diff --git a/PKHeX.Core/Saves/Substructures/Gen7/LGPE/GP1.cs b/PKHeX.Core/Saves/Substructures/Gen7/LGPE/GP1.cs index 58babb732..bcf1752e3 100644 --- a/PKHeX.Core/Saves/Substructures/Gen7/LGPE/GP1.cs +++ b/PKHeX.Core/Saves/Substructures/Gen7/LGPE/GP1.cs @@ -18,7 +18,7 @@ public sealed class GP1(byte[] Data) public bool EggEncounter => false; public byte LevelMin => Level; public byte LevelMax => Level; - public int Generation => 7; + public byte Generation => 7; public EntityContext Context => EntityContext.Gen7b; public AbilityPermission Ability => AbilityPermission.Any12; @@ -105,7 +105,7 @@ public byte WeightScalar public int Month => (Date / 1_00) % 1_00; public int Day => Date % 1_00; - public int Gender => Data[0x70] - 1; // M=1, F=2, G=3 ;; shift down by 1. + public byte Gender => (byte)(Data[0x70] - 1); // M=1, F=2, G=3 ;; shift down by 1. public byte Form => Data[0x72]; public bool IsShiny => Data[0x73] == 1; @@ -155,18 +155,18 @@ public PB7 ConvertToPKM(ITrainerInfo sav, EncounterCriteria criteria) { EncryptionConstant = rnd.Rand32(), PID = rnd.Rand32(), - Version = (int) GameVersion.GO, + Version = GameVersion.GO, Species = Species, Form = Form, - Met_Location = 50, // Go complex - Met_Year = Year - 2000, - Met_Month = Month, - Met_Day = Day, + MetLocation = 50, // Go complex + MetYear = (byte)(Year - 2000), + MetMonth = (byte)Month, + MetDay = (byte)Day, CurrentLevel = Level, - Met_Level = Level, + MetLevel = Level, TID16 = sav.TID16, SID16 = sav.SID16, - OT_Name = sav.OT, + OriginalTrainerName = sav.OT, Ball = 4, Language = sav.Language, }; @@ -189,7 +189,7 @@ public PB7 ConvertToPKM(ITrainerInfo sav, EncounterCriteria criteria) var pi = pk.PersonalInfo; pk.Gender = criteria.GetGender(Gender, pi); - pk.Nature = (int)criteria.GetNature(); + pk.Nature = criteria.GetNature(); pk.RefreshAbility(criteria.GetAbilityFromNumber(Ability)); bool isShiny = pk.IsShiny; @@ -206,7 +206,7 @@ public PB7 ConvertToPKM(ITrainerInfo sav, EncounterCriteria criteria) Span moves = stackalloc ushort[4]; ((ILearnSource)LearnSource7GG.Instance).SetEncounterMoves(Species, Form, Level, moves); pk.SetMoves(moves); - pk.OT_Friendship = pk.PersonalInfo.BaseFriendship; + pk.OriginalTrainerFriendship = pk.PersonalInfo.BaseFriendship; pk.HeightScalar = HeightScalar; pk.WeightScalar = WeightScalar; diff --git a/PKHeX.Core/Saves/Substructures/Gen7/LGPE/MyStatus7b.cs b/PKHeX.Core/Saves/Substructures/Gen7/LGPE/MyStatus7b.cs index e25a98c5f..cba2401d9 100644 --- a/PKHeX.Core/Saves/Substructures/Gen7/LGPE/MyStatus7b.cs +++ b/PKHeX.Core/Saves/Substructures/Gen7/LGPE/MyStatus7b.cs @@ -29,16 +29,16 @@ public ushort SID16 set => WriteUInt16LittleEndian(Data.AsSpan(Offset + 2), value); } - public int Game + public byte Game { get => Data[Offset + 4]; - set => Data[Offset + 4] = (byte)value; + set => Data[Offset + 4] = value; } - public int Gender + public byte Gender { get => Data[Offset + 5]; - set => Data[Offset + 5] = OverworldGender = (byte)value; + set => Data[Offset + 5] = OverworldGender = value; } public const int GameSyncIDSize = 16; // 8 bytes @@ -61,12 +61,12 @@ public int Language set => Data[Offset + 0x35] = (byte)value; } - private Span OT_Trash => Data.AsSpan(Offset + 0x38, 0x1A); + private Span OriginalTrainerTrash => Data.AsSpan(Offset + 0x38, 0x1A); public string OT { - get => SAV.GetString(OT_Trash); - set => SAV.SetString(OT_Trash, value, SAV.MaxStringLengthOT, StringConverterOption.ClearZero); + get => SAV.GetString(OriginalTrainerTrash); + set => SAV.SetString(OriginalTrainerTrash, value, SAV.MaxStringLengthOT, StringConverterOption.ClearZero); } // The value here corresponds to a Trainer Class string (ranging from 000 to 383, use pkNX to get a full list). diff --git a/PKHeX.Core/Saves/Substructures/Gen7/MyStatus7.cs b/PKHeX.Core/Saves/Substructures/Gen7/MyStatus7.cs index 22ef5af97..913a58b10 100644 --- a/PKHeX.Core/Saves/Substructures/Gen7/MyStatus7.cs +++ b/PKHeX.Core/Saves/Substructures/Gen7/MyStatus7.cs @@ -28,16 +28,16 @@ public ushort SID16 set => WriteUInt16LittleEndian(Data.AsSpan(Offset + 2), value); } - public int Game + public byte Game { get => Data[Offset + 4]; - set => Data[Offset + 4] = (byte)value; + set => Data[Offset + 4] = value; } - public int Gender + public byte Gender { get => Data[Offset + 5]; - set => Data[Offset + 5] = (byte)value; + set => Data[Offset + 5] = value; } public string GameSyncID @@ -94,12 +94,12 @@ public int Language set => Data[Offset + 0x35] = (byte)value; } - private Span OT_Trash => Data.AsSpan(Offset + 0x38, 0x1A); + private Span OriginalTrainerTrash => Data.AsSpan(Offset + 0x38, 0x1A); public string OT { - get => SAV.GetString(OT_Trash); - set => SAV.SetString(OT_Trash, value, SAV.MaxStringLengthOT, StringConverterOption.ClearZero); + get => SAV.GetString(OriginalTrainerTrash); + set => SAV.SetString(OriginalTrainerTrash, value, SAV.MaxStringLengthOT, StringConverterOption.ClearZero); } public int DressUpSkinColor @@ -126,7 +126,7 @@ public bool ZMoveUnlocked set => Data[Offset + 0x78] = (byte)((Data[Offset + 0x78] & ~2) | (value ? 2 : 0)); // in battle } - public int BallThrowType + public byte BallThrowType { get => Data[Offset + 0x7A]; set => Data[Offset + 0x7A] = (byte)(value > 8 ? 0 : value); diff --git a/PKHeX.Core/Saves/Substructures/Gen7/QR7.cs b/PKHeX.Core/Saves/Substructures/Gen7/QR7.cs index beeb8c12c..b6e6888bf 100644 --- a/PKHeX.Core/Saves/Substructures/Gen7/QR7.cs +++ b/PKHeX.Core/Saves/Substructures/Gen7/QR7.cs @@ -86,7 +86,7 @@ public static void SetQRData(PK7 pk7, Span span, int box = 0, int slot = 0 WriteInt32LittleEndian(span[0x10..], num_copies); // No need to check max num_copies, payload parser handles it on-console. pk7.EncryptedPartyData.CopyTo(span[0x30..]); // Copy in pokemon data - GetRawQR(span[0x140..], pk7.Species, pk7.Form, pk7.IsShiny, (byte)pk7.Gender); + GetRawQR(span[0x140..], pk7.Species, pk7.Form, pk7.IsShiny, pk7.Gender); var chk = Checksums.CRC16Invert(span[..0x1A0]); WriteUInt16LittleEndian(span[0x1A0..], chk); diff --git a/PKHeX.Core/Saves/Substructures/Gen8/BS/MyStatus8b.cs b/PKHeX.Core/Saves/Substructures/Gen8/BS/MyStatus8b.cs index 51222dc12..979c59197 100644 --- a/PKHeX.Core/Saves/Substructures/Gen8/BS/MyStatus8b.cs +++ b/PKHeX.Core/Saves/Substructures/Gen8/BS/MyStatus8b.cs @@ -16,12 +16,12 @@ public sealed class MyStatus8b : SaveBlock public MyStatus8b(SAV8BS sav, int offset) : base(sav) => Offset = offset; - private Span OT_Trash => Data.AsSpan(Offset + 0, 0x1A); + private Span OriginalTrainerTrash => Data.AsSpan(Offset + 0, 0x1A); public string OT { - get => SAV.GetString(OT_Trash); - set => SAV.SetString(OT_Trash, value, SAV.MaxStringLengthOT, StringConverterOption.ClearZero); + get => SAV.GetString(OriginalTrainerTrash); + set => SAV.SetString(OriginalTrainerTrash, value, SAV.MaxStringLengthOT, StringConverterOption.ClearZero); } public uint ID32 @@ -78,15 +78,15 @@ public MoveType StarterType // end structure! - public int Game + public GameVersion Game { get => ROMCode switch { - 0 => (int)GameVersion.BD, - 1 => (int)GameVersion.SP, + 0 => GameVersion.BD, + 1 => GameVersion.SP, _ => throw new ArgumentOutOfRangeException(nameof(Game)), }; - set => ROMCode = (GameVersion)value switch + set => ROMCode = value switch { GameVersion.BD => 0, GameVersion.SP => 1, diff --git a/PKHeX.Core/Saves/Substructures/Gen8/BS/MysteryBlock8b.cs b/PKHeX.Core/Saves/Substructures/Gen8/BS/MysteryBlock8b.cs index 19369b987..362be6243 100644 --- a/PKHeX.Core/Saves/Substructures/Gen8/BS/MysteryBlock8b.cs +++ b/PKHeX.Core/Saves/Substructures/Gen8/BS/MysteryBlock8b.cs @@ -182,7 +182,7 @@ public string OT set => StringConverter8.SetString(Data.AsSpan(Offset + 0x1E, 0x1A), value, 12, StringConverterOption.ClearZero); } - public byte OT_Gender { get => Data[Offset + 0x38]; set => Data[Offset + 0x38] = value; } + public byte OriginalTrainerGender { get => Data[Offset + 0x38]; set => Data[Offset + 0x38] = value; } public byte IsEgg { get => Data[Offset + 0x39]; set => Data[Offset + 0x39] = value; } public byte TwoRibbon { get => Data[Offset + 0x3A]; set => Data[Offset + 0x3A] = value; } public byte Gender { get => Data[Offset + 0x3B]; set => Data[Offset + 0x3B] = value; } diff --git a/PKHeX.Core/Saves/Substructures/Gen8/BS/Zukan8b.cs b/PKHeX.Core/Saves/Substructures/Gen8/BS/Zukan8b.cs index 1a0e52426..6aa43144e 100644 --- a/PKHeX.Core/Saves/Substructures/Gen8/BS/Zukan8b.cs +++ b/PKHeX.Core/Saves/Substructures/Gen8/BS/Zukan8b.cs @@ -348,7 +348,7 @@ public override void SetDex(PKM pk) SAV.ZukanExtra.SetDex(originalState, pk.EncryptionConstant, pk.Gender, shiny); } - private void SetGenderFlag(ushort species, int gender, bool shiny) + private void SetGenderFlag(ushort species, byte gender, bool shiny) { switch (gender) { diff --git a/PKHeX.Core/Saves/Substructures/Gen8/BS/ZukanSpinda8b.cs b/PKHeX.Core/Saves/Substructures/Gen8/BS/ZukanSpinda8b.cs index 91d265c08..abae26828 100644 --- a/PKHeX.Core/Saves/Substructures/Gen8/BS/ZukanSpinda8b.cs +++ b/PKHeX.Core/Saves/Substructures/Gen8/BS/ZukanSpinda8b.cs @@ -11,33 +11,33 @@ public sealed class ZukanSpinda8b : SaveBlock { public ZukanSpinda8b(SAV8BS sav, int offset) : base(sav) => Offset = offset; - public uint GetSeen(int gender, bool shiny) + public uint GetSeen(byte gender, bool shiny) { var ofs = GetOffset(gender, shiny); return ReadUInt32LittleEndian(Data.AsSpan(Offset + ofs)); } - public uint GetCaught(int gender, bool shiny) + public uint GetCaught(byte gender, bool shiny) { var ofs = GetOffset(gender, shiny); return ReadUInt32LittleEndian(Data.AsSpan(Offset + 0x10 + ofs)); } - public void SetSeen(int gender, bool shiny, uint value) + public void SetSeen(byte gender, bool shiny, uint value) { var ofs = GetOffset(gender, shiny); WriteUInt32LittleEndian(Data.AsSpan(Offset + ofs), value); } - public void SetCaught(int gender, bool shiny, uint value) + public void SetCaught(byte gender, bool shiny, uint value) { var ofs = GetOffset(gender, shiny); WriteUInt32LittleEndian(Data.AsSpan(Offset + 0x10 + ofs), value); } - private static int GetOffset(int gender, bool shiny) => 4 * ((gender & 1) + (shiny ? 2 : 0)); + private static int GetOffset(byte gender, bool shiny) => 4 * ((gender & 1) + (shiny ? 2 : 0)); - public void SetDex(ZukanState8b state, uint ec, int gender, bool shiny) + public void SetDex(ZukanState8b state, uint ec, byte gender, bool shiny) { if (state < ZukanState8b.Seen) // not seen yet SetSeen(gender, shiny, ec); diff --git a/PKHeX.Core/Saves/Substructures/Gen8/LA/MyStatus8a.cs b/PKHeX.Core/Saves/Substructures/Gen8/LA/MyStatus8a.cs index a3a7f065b..16187b057 100644 --- a/PKHeX.Core/Saves/Substructures/Gen8/LA/MyStatus8a.cs +++ b/PKHeX.Core/Saves/Substructures/Gen8/LA/MyStatus8a.cs @@ -28,16 +28,16 @@ public ushort SID16 set => WriteUInt16LittleEndian(Data.AsSpan(0x12), value); } - public int Game + public byte Game { get => Data[0x14]; - set => Data[0x14] = (byte)value; + set => Data[0x14] = value; } - public int Gender + public byte Gender { get => Data[0x15]; - set => Data[0x15] = (byte)value; + set => Data[0x15] = value; } // A6 @@ -57,12 +57,12 @@ public int Language } } - private Span OT_Trash => Data.AsSpan(0x20, 0x1A); + private Span OriginalTrainerTrash => Data.AsSpan(0x20, 0x1A); public string OT { - get => SAV.GetString(OT_Trash); - set => SAV.SetString(OT_Trash, value, SAV.MaxStringLengthOT, StringConverterOption.ClearZero); + get => SAV.GetString(OriginalTrainerTrash); + set => SAV.SetString(OriginalTrainerTrash, value, SAV.MaxStringLengthOT, StringConverterOption.ClearZero); } public byte Unk_0x50 diff --git a/PKHeX.Core/Saves/Substructures/Gen8/LA/Pokedex/PokedexSave8a.cs b/PKHeX.Core/Saves/Substructures/Gen8/LA/Pokedex/PokedexSave8a.cs index 4d0045d09..41f7d976d 100644 --- a/PKHeX.Core/Saves/Substructures/Gen8/LA/Pokedex/PokedexSave8a.cs +++ b/PKHeX.Core/Saves/Substructures/Gen8/LA/Pokedex/PokedexSave8a.cs @@ -816,7 +816,7 @@ public void OnPokeGet_Caller1(PKM pk) // 1.0.1: sub_7101283760 // Is this on receiving an egg? - // var metLoc = pk.Met_Location; + // var metLoc = pk.MetLocation; // if (!GetCurrentTime()) // return; // SetMetOrEggLocation(pk, metLoc, calendarTime); diff --git a/PKHeX.Core/Saves/Substructures/Gen8/SWSH/MyStatus8.cs b/PKHeX.Core/Saves/Substructures/Gen8/SWSH/MyStatus8.cs index 0fb3ffe7f..a4097a883 100644 --- a/PKHeX.Core/Saves/Substructures/Gen8/SWSH/MyStatus8.cs +++ b/PKHeX.Core/Saves/Substructures/Gen8/SWSH/MyStatus8.cs @@ -136,16 +136,16 @@ public ushort SID16 set => WriteUInt16LittleEndian(Data.AsSpan(0xA2), value); } - public int Game + public byte Game { get => Data[0xA4]; - set => Data[0xA4] = (byte)value; + set => Data[0xA4] = value; } - public int Gender + public byte Gender { get => Data[0xA5]; - set => Data[0xA5] = (byte)value; + set => Data[0xA5] = value; } // A6 @@ -165,12 +165,12 @@ public int Language } } - private Span OT_Trash => Data.AsSpan(0xB0, 0x1A); + private Span OriginalTrainerTrash => Data.AsSpan(0xB0, 0x1A); public string OT { - get => SAV.GetString(OT_Trash); - set => SAV.SetString(OT_Trash, value, SAV.MaxStringLengthOT, StringConverterOption.ClearZero); + get => SAV.GetString(OriginalTrainerTrash); + set => SAV.SetString(OriginalTrainerTrash, value, SAV.MaxStringLengthOT, StringConverterOption.ClearZero); } // D0 diff --git a/PKHeX.Core/Saves/Substructures/Gen8/SWSH/TitleScreen8.cs b/PKHeX.Core/Saves/Substructures/Gen8/SWSH/TitleScreen8.cs index 676590320..c496eb2de 100644 --- a/PKHeX.Core/Saves/Substructures/Gen8/SWSH/TitleScreen8.cs +++ b/PKHeX.Core/Saves/Substructures/Gen8/SWSH/TitleScreen8.cs @@ -49,9 +49,9 @@ public byte Form set => WriteInt32LittleEndian(Data.AsSpan(Offset + 0x04), value); } - public int Gender + public byte Gender { - get => ReadInt32LittleEndian(Data.AsSpan(Offset + 0x08)); + get => (byte)ReadInt32LittleEndian(Data.AsSpan(Offset + 0x08)); set => WriteInt32LittleEndian(Data.AsSpan(Offset + 0x08), value); } diff --git a/PKHeX.Core/Saves/Substructures/Gen8/SWSH/TrainerCard8.cs b/PKHeX.Core/Saves/Substructures/Gen8/SWSH/TrainerCard8.cs index 505aa25a7..56c760a06 100644 --- a/PKHeX.Core/Saves/Substructures/Gen8/SWSH/TrainerCard8.cs +++ b/PKHeX.Core/Saves/Substructures/Gen8/SWSH/TrainerCard8.cs @@ -7,12 +7,12 @@ namespace PKHeX.Core; public sealed class TrainerCard8(SAV8SWSH sav, SCBlock block) : SaveBlock(sav, block.Data) { - private Span OT_Trash => Data.AsSpan(0x00, 0x1A); + private Span OriginalTrainerTrash => Data.AsSpan(0x00, 0x1A); public string OT { - get => SAV.GetString(OT_Trash); - set => SAV.SetString(OT_Trash, value, SAV.MaxStringLengthOT, StringConverterOption.ClearZero); + get => SAV.GetString(OriginalTrainerTrash); + set => SAV.SetString(OriginalTrainerTrash, value, SAV.MaxStringLengthOT, StringConverterOption.ClearZero); } public byte Language @@ -103,10 +103,10 @@ public bool CrownDexComplete set => Data[Offset + 0x1B5] = value ? (byte)1 : (byte)0; } - public int Gender + public byte Gender { get => Data[0x38]; - set => Data[0x38] = (byte)value; + set => Data[0x38] = value; } public string Number @@ -289,9 +289,9 @@ public byte Form set => WriteInt32LittleEndian(Data.AsSpan(Offset + 0x04), value); } - public int Gender + public byte Gender { - get => ReadInt32LittleEndian(Data.AsSpan(Offset + 0x08)); + get => (byte)ReadInt32LittleEndian(Data.AsSpan(Offset + 0x08)); set => WriteInt32LittleEndian(Data.AsSpan(Offset + 0x08), value); } diff --git a/PKHeX.Core/Saves/Substructures/Gen9/MyStatus9.cs b/PKHeX.Core/Saves/Substructures/Gen9/MyStatus9.cs index 6105940aa..36169d57a 100644 --- a/PKHeX.Core/Saves/Substructures/Gen9/MyStatus9.cs +++ b/PKHeX.Core/Saves/Substructures/Gen9/MyStatus9.cs @@ -23,16 +23,16 @@ public ushort SID16 set => WriteUInt16LittleEndian(Data.AsSpan(0x02), value); } - public int Game + public byte Game { get => Data[0x04]; - set => Data[0x04] = (byte)value; + set => Data[0x04] = value; } - public int Gender + public byte Gender { get => Data[0x05]; - set => Data[0x05] = (byte)value; + set => Data[0x05] = value; } // A6 @@ -78,12 +78,12 @@ private enum RuntimeLanguage ChineseT = 8, } - private Span OT_Trash => Data.AsSpan(0x10, 0x1A); + private Span OriginalTrainerTrash => Data.AsSpan(0x10, 0x1A); public string OT { - get => SAV.GetString(OT_Trash); - set => SAV.SetString(OT_Trash, value, SAV.MaxStringLengthOT, StringConverterOption.ClearZero); + get => SAV.GetString(OriginalTrainerTrash); + set => SAV.SetString(OriginalTrainerTrash, value, SAV.MaxStringLengthOT, StringConverterOption.ClearZero); } public byte BirthMonth { get => Data[0x5A]; set => Data[0x5A] = value; } diff --git a/PKHeX.Core/Saves/Substructures/Gen9/PlayerFashionUnlock9.cs b/PKHeX.Core/Saves/Substructures/Gen9/PlayerFashionUnlock9.cs index 6f769c089..27d59a193 100644 --- a/PKHeX.Core/Saves/Substructures/Gen9/PlayerFashionUnlock9.cs +++ b/PKHeX.Core/Saves/Substructures/Gen9/PlayerFashionUnlock9.cs @@ -173,7 +173,7 @@ private static int AddItems(Span data, IEnumerable missing) return added; } - public static int UnlockBase(SCBlockAccessor acc, int gender) + public static int UnlockBase(SCBlockAccessor acc, byte gender) { int count = 0; count += Add(acc, KFashionUnlockedBag, Bag); diff --git a/PKHeX.Core/Saves/Substructures/Gen9/RaidSevenStar9.cs b/PKHeX.Core/Saves/Substructures/Gen9/RaidSevenStar9.cs index 778e878e3..d2c2c0cf5 100644 --- a/PKHeX.Core/Saves/Substructures/Gen9/RaidSevenStar9.cs +++ b/PKHeX.Core/Saves/Substructures/Gen9/RaidSevenStar9.cs @@ -31,9 +31,11 @@ public sealed class SevenStarRaidDetail(SevenStarRaidCapturedDetail captured, Se public uint Identifier { get => captured.Identifier; - set { + set + { captured.Identifier = value; - if (defeated != null) defeated.Identifier = value; + if (defeated != null) + defeated.Identifier = value; } } @@ -47,8 +49,9 @@ public bool Captured [Category(General), Description("Indicates if this Tera Raid Boss has been defeated at least once by the player.")] public bool Defeated { - get => defeated != null ? defeated.Defeated : captured.Defeated; - set { + get => defeated?.Defeated ?? captured.Defeated; + set + { if (defeated != null) defeated.Defeated = value; else diff --git a/PKHeX.Core/Saves/Substructures/Mail/Mail4.cs b/PKHeX.Core/Saves/Substructures/Mail/Mail4.cs index 1e16a7b1a..3a6fa28de 100644 --- a/PKHeX.Core/Saves/Substructures/Mail/Mail4.cs +++ b/PKHeX.Core/Saves/Substructures/Mail/Mail4.cs @@ -11,10 +11,10 @@ public sealed class Mail4 : MailDetail public Mail4(byte[] data) : base(data, -1) { } - public Mail4(byte? lang, byte? ver) : base(new byte[SIZE]) + public Mail4(byte? lang, byte? version) : base(new byte[SIZE]) { if (lang != null) AuthorLanguage = (byte)lang; - if (ver != null) AuthorVersion = (byte)ver; + if (version != null) AuthorVersion = (byte)version; ResetData(); } @@ -59,10 +59,10 @@ private void ResetData() public override void SetBlank() => SetBlank(0, 0); - public void SetBlank(byte lang, byte ver) + public void SetBlank(byte lang, byte version) { Array.Clear(Data, 0, Data.Length); AuthorLanguage = lang; - AuthorVersion = ver; + AuthorVersion = version; } } diff --git a/PKHeX.Core/Saves/Substructures/Mail/Mail5.cs b/PKHeX.Core/Saves/Substructures/Mail/Mail5.cs index 6d8857f31..7cabda297 100644 --- a/PKHeX.Core/Saves/Substructures/Mail/Mail5.cs +++ b/PKHeX.Core/Saves/Substructures/Mail/Mail5.cs @@ -9,10 +9,10 @@ public sealed class Mail5 : MailDetail public Mail5(byte[] data, int ofs = -1) : base(data, ofs) { } - public Mail5(byte? lang, byte? ver) : base(new byte[SIZE]) + public Mail5(byte? lang, byte? version) : base(new byte[SIZE]) { if (lang != null) AuthorLanguage = (byte)lang; - if (ver != null) AuthorVersion = (byte)ver; + if (version != null) AuthorVersion = (byte)version; ResetData(); } @@ -55,5 +55,5 @@ private void ResetData() }; public override void SetBlank() => SetBlank(null, null); - public void SetBlank(byte? lang, byte? ver) => new Mail5(lang: lang, ver: ver).Data.CopyTo(Data, 0); + public void SetBlank(byte? lang, byte? version) => new Mail5(lang: lang, version: version).Data.CopyTo(Data, 0); } diff --git a/PKHeX.Core/Saves/Substructures/PokeDex/Gen9/PokeDexEntry9Kitakami.cs b/PKHeX.Core/Saves/Substructures/PokeDex/Gen9/PokeDexEntry9Kitakami.cs index d414b7b85..ed53846c9 100644 --- a/PKHeX.Core/Saves/Substructures/PokeDex/Gen9/PokeDexEntry9Kitakami.cs +++ b/PKHeX.Core/Saves/Substructures/PokeDex/Gen9/PokeDexEntry9Kitakami.cs @@ -142,8 +142,8 @@ public void SetLanguageFlag(int langIndex, bool value) FlagsLanguage &= (ushort)~mask; } - public bool GetIsGenderSeen(int gender) => GetFlag(ref FlagsGenderSeen, gender); - public void SetIsGenderSeen(int gender, bool value) => SetFlag(ref FlagsGenderSeen, gender, value); + public bool GetIsGenderSeen(byte gender) => GetFlag(ref FlagsGenderSeen, gender); + public void SetIsGenderSeen(byte gender, bool value) => SetFlag(ref FlagsGenderSeen, gender, value); public bool GetIsModelSeen(bool shiny) => GetFlag(ref FlagsShinySeen, shiny ? 1 : 0); public void SetIsModelSeen(bool shiny, bool value) => SetFlag(ref FlagsShinySeen, shiny ? 1 : 0, value); diff --git a/PKHeX.Core/Saves/Substructures/PokeDex/Gen9/PokeDexEntry9Paldea.cs b/PKHeX.Core/Saves/Substructures/PokeDex/Gen9/PokeDexEntry9Paldea.cs index 1bce04894..a3fefce86 100644 --- a/PKHeX.Core/Saves/Substructures/PokeDex/Gen9/PokeDexEntry9Paldea.cs +++ b/PKHeX.Core/Saves/Substructures/PokeDex/Gen9/PokeDexEntry9Paldea.cs @@ -67,9 +67,9 @@ public void SetSeen(bool value) SetState(newValue); } - public bool GetIsGenderSeen(int gender) => (FlagsGenderSeen & (1u << gender)) != 0; + public bool GetIsGenderSeen(byte gender) => (FlagsGenderSeen & (1u << gender)) != 0; - public void SetIsGenderSeen(int gender, bool value) + public void SetIsGenderSeen(byte gender, bool value) { if (value) FlagsGenderSeen |= (ushort)(1u << gender); diff --git a/PKHeX.Core/Saves/Substructures/PokeDex/Gen9/Zukan9.cs b/PKHeX.Core/Saves/Substructures/PokeDex/Gen9/Zukan9.cs index b1085f4a6..ac96a48be 100644 --- a/PKHeX.Core/Saves/Substructures/PokeDex/Gen9/Zukan9.cs +++ b/PKHeX.Core/Saves/Substructures/PokeDex/Gen9/Zukan9.cs @@ -18,10 +18,7 @@ public Zukan9(SAV9SV sav, SCBlock paldea, SCBlock kitakami) : base(sav, 0) DexKitakami = new(sav, kitakami); // Starting in 2.0.1, the developers have dummied out the old Paldea Pokédex block and exclusively use the new Kitakami block. - if (kitakami.Data.Length != 0) - Mode = Kitakami; - else - Mode = Paldea; + Mode = kitakami.Data.Length != 0 ? Kitakami : Paldea; } /// diff --git a/PKHeX.Core/Saves/Substructures/PokeDex/Gen9/Zukan9Kitakami.cs b/PKHeX.Core/Saves/Substructures/PokeDex/Gen9/Zukan9Kitakami.cs index 87c2a948f..9951267f6 100644 --- a/PKHeX.Core/Saves/Substructures/PokeDex/Gen9/Zukan9Kitakami.cs +++ b/PKHeX.Core/Saves/Substructures/PokeDex/Gen9/Zukan9Kitakami.cs @@ -146,7 +146,7 @@ private static void SetSeen(PokeDexEntry9Kitakami entry, PersonalInfo9SV pi, byt } else { - var displayGender = (byte)pi.FixedGender(); + var displayGender = pi.FixedGender(); entry.SetIsGenderSeen(displayGender, true); } @@ -194,7 +194,7 @@ public void SetAllCaught(ushort species, bool value = true, bool shinyToo = fals continue; SetSeen(entry, pi, form, true, shinyToo); entry.SetObtainedForm(form, true); - entry.SetLocalStates(pi, form, (byte)pi.RandomGender(), shinyToo); + entry.SetLocalStates(pi, form, pi.RandomGender(), shinyToo); } entry.SetAllLanguageFlags(); } @@ -244,7 +244,7 @@ public void Register(PKM pk, ushort species, byte form) SetSeen(entry, pi, form, true, isShiny); entry.SetObtainedForm(form, true); - entry.SetLocalStates(pi, form, (byte)pi.RandomGender(), isShiny); + entry.SetLocalStates(pi, form, pi.RandomGender(), isShiny); if (isShiny) entry.SetIsModelSeen(true, true); entry.SetLanguageFlag(pk.Language, true); diff --git a/PKHeX.Core/Saves/Substructures/PokeDex/Zukan.cs b/PKHeX.Core/Saves/Substructures/PokeDex/Zukan.cs index 11f1d5df4..b1e4b7036 100644 --- a/PKHeX.Core/Saves/Substructures/PokeDex/Zukan.cs +++ b/PKHeX.Core/Saves/Substructures/PokeDex/Zukan.cs @@ -96,7 +96,7 @@ protected Zukan(T sav, int dex, int langflag) : base(sav, dex) protected abstract bool GetSaneFormsToIterate(ushort species, out int formStart, out int formEnd, int formIn); protected virtual void SetSpindaDexData(PKM pk, bool alreadySeen) { } protected abstract void SetAllDexFlagsLanguage(int bit, int lang, bool value = true); - protected abstract void SetAllDexSeenFlags(int baseBit, byte b, int gender, bool isShiny, bool value = true); + protected abstract void SetAllDexSeenFlags(int baseBit, byte b, byte gender, bool isShiny, bool value = true); protected bool GetFlag(int ofs, int bitIndex) => SAV.GetFlag(PokeDex + ofs + (bitIndex >> 3), bitIndex); protected void SetFlag(int ofs, int bitIndex, bool value = true) => SAV.SetFlag(PokeDex + ofs + (bitIndex >> 3), bitIndex, value); @@ -138,7 +138,7 @@ public virtual void SetSeen(ushort species, bool value = true) if (GetFlag(OFS_SEEN + (i * BitSeenSize), species - 1)) return; } - var gender = SAV.Personal[species].RandomGender() & 1; + byte gender = (byte)(SAV.Personal[species].RandomGender() & 1); SetAllDexSeenFlags(species - 1, 0, gender, false); } @@ -162,20 +162,20 @@ public override void SetDex(PKM pk) int bit = pk.Species - 1; var form = pk.Form; - int gender = pk.Gender & 1; + byte gender = (byte)(pk.Gender & 1); bool shiny = pk.IsShiny; int lang = pk.Language; SetDex(species, bit, form, gender, shiny, lang); } - protected virtual void SetDex(ushort species, int bit, byte form, int gender, bool shiny, int lang) + protected virtual void SetDex(ushort species, int bit, byte form, byte gender, bool shiny, int lang) { SetCaught(species); // Set the Owned Flag SetAllDexSeenFlags(bit, form, gender, shiny); // genderless -> male SetAllDexFlagsLanguage(bit, lang); } - protected void SetDexFlags(int baseBit, int formBit, int gender, int shiny, bool value = true) + protected void SetDexFlags(int baseBit, int formBit, byte gender, int shiny, bool value = true) { int shift = (gender & 1) | (shiny << 1); diff --git a/PKHeX.Core/Saves/Substructures/PokeDex/Zukan4.cs b/PKHeX.Core/Saves/Substructures/PokeDex/Zukan4.cs index d5c026412..ca964fec3 100644 --- a/PKHeX.Core/Saves/Substructures/PokeDex/Zukan4.cs +++ b/PKHeX.Core/Saves/Substructures/PokeDex/Zukan4.cs @@ -289,7 +289,7 @@ public override void SetDex(PKM pk) SetDex(species, gender, form, language); } - private void SetDex(ushort species, int gender, byte form, int language) + private void SetDex(ushort species, byte gender, byte form, int language) { SetCaught(species); SetSeenGender(species, gender); @@ -298,7 +298,7 @@ private void SetDex(ushort species, int gender, byte form, int language) SetLanguage(species, language); } - public void SetSeenGender(ushort species, int gender) + public void SetSeenGender(ushort species, byte gender) { if (!GetSeen(species)) SetSeenGenderNewFlag(species, gender); @@ -306,7 +306,7 @@ public void SetSeenGender(ushort species, int gender) SetSeenGenderSecond(species, gender); } - public void SetSeenGenderNewFlag(ushort species, int gender) + public void SetSeenGenderNewFlag(ushort species, byte gender) { SetSeenGenderFirst(species, gender); SetSeenGenderSecond(species, gender); @@ -318,7 +318,7 @@ public void SetSeenGenderNeither(ushort species) SetSeenGenderSecond(species, 0); } - private void SetForms(ushort species, byte form, int gender) + private void SetForms(ushort species, byte form, byte gender) { if (species == (int)Species.Unown) // Unown { @@ -332,7 +332,7 @@ private void SetForms(ushort species, byte form, int gender) if (species == (int)Species.Pichu && HGSS) // Pichu (HGSS Only) { - var formID = form == 1 ? (byte)2 : (byte)gender; + var formID = form == 1 ? (byte)2 : gender; if (TryInsertForm(forms, formID)) SetForms(species, forms); } @@ -471,7 +471,7 @@ private void CompleteSeen(ushort species) } else { - SetSeenGenderNewFlag(species, pi.FixedGender() & 1); + SetSeenGenderNewFlag(species, (byte)(pi.FixedGender() & 1)); } } diff --git a/PKHeX.Core/Saves/Substructures/PokeDex/Zukan5.cs b/PKHeX.Core/Saves/Substructures/PokeDex/Zukan5.cs index 3593c3eac..7d383ea3e 100644 --- a/PKHeX.Core/Saves/Substructures/PokeDex/Zukan5.cs +++ b/PKHeX.Core/Saves/Substructures/PokeDex/Zukan5.cs @@ -58,7 +58,7 @@ protected override void SetAllDexFlagsLanguage(int bit, int lang, bool value = t SetFlag(PokeDexLanguageFlags, lbit, value); } - protected override void SetAllDexSeenFlags(int baseBit, byte form, int gender, bool isShiny, bool value = true) + protected override void SetAllDexSeenFlags(int baseBit, byte form, byte gender, bool isShiny, bool value = true) { var shiny = isShiny ? 1 : 0; SetDexFlags(baseBit, baseBit, gender, shiny); diff --git a/PKHeX.Core/Saves/Substructures/PokeDex/Zukan6.cs b/PKHeX.Core/Saves/Substructures/PokeDex/Zukan6.cs index 61e0d681d..a4112c547 100644 --- a/PKHeX.Core/Saves/Substructures/PokeDex/Zukan6.cs +++ b/PKHeX.Core/Saves/Substructures/PokeDex/Zukan6.cs @@ -60,7 +60,7 @@ protected override void SetAllDexFlagsLanguage(int bit, int lang, bool value = t SetFlag(PokeDexLanguageFlags, lbit, value); } - protected override void SetAllDexSeenFlags(int baseBit, byte form, int gender, bool isShiny, bool value = true) + protected override void SetAllDexSeenFlags(int baseBit, byte form, byte gender, bool isShiny, bool value = true) { var shiny = isShiny ? 1 : 0; SetDexFlags(baseBit, baseBit, gender, shiny); @@ -83,7 +83,7 @@ public override void SetDex(PKM pk) SetFormFlags(pk); } - protected abstract void SetCaughtFlag(int bit, int origin); + protected abstract void SetCaughtFlag(int bit, GameVersion origin); private int FormLen => SAV is SAV6XY ? 0x18 : 0x26; private int FormDex => 0x8 + (BitSeenSize * 9); @@ -188,7 +188,7 @@ public Zukan6AO(SAV6AO sav, int dex, int langflag) : base(sav, dex, langflag) SpindaOffset = 0x680; } - protected override void SetCaughtFlag(int bit, int origin) + protected override void SetCaughtFlag(int bit, GameVersion origin) { SetFlag(OFS_CAUGHT, bit); if (GetEncounterCount(bit) == 0) @@ -218,10 +218,10 @@ public Zukan6XY(SAV6XY sav, int dex, int langflag) : base(sav, dex, langflag) SpindaOffset = 0x648; } - protected override void SetCaughtFlag(int bit, int origin) + protected override void SetCaughtFlag(int bit, GameVersion origin) { // Species: 1-649 for X/Y, and not for OR/AS; Set the Foreign Owned Flag - if (origin < (int)GameVersion.X && bit < (int)Species.Genesect) + if (origin < GameVersion.X && bit < (int)Species.Genesect) SetForeignFlag(bit); else SetFlag(OFS_CAUGHT, bit); diff --git a/PKHeX.Core/Saves/Substructures/PokeDex/Zukan7.cs b/PKHeX.Core/Saves/Substructures/PokeDex/Zukan7.cs index 62303b8ad..a3e9f8f71 100644 --- a/PKHeX.Core/Saves/Substructures/PokeDex/Zukan7.cs +++ b/PKHeX.Core/Saves/Substructures/PokeDex/Zukan7.cs @@ -29,33 +29,30 @@ public class Zukan7 : Zukan public Zukan7(SAV7USUM sav, int dex, int langflag) : this(sav, dex, langflag, DexFormUtil.GetDexFormIndexUSUM) { } protected Zukan7(SAV7b sav, int dex, int langflag) : this(sav, dex, langflag, DexFormUtil.GetDexFormIndexGG) { } - private Zukan7(SaveFile sav, int dex, int langflag, Func form) : base(sav, dex, langflag) + private Zukan7(SaveFile sav, int dex, int langflag, Func form) : base(sav, dex, langflag) { - DexFormIndexFetcher = form; + GetCountFormsPriorTo = form; FormBaseSpecies = GetFormIndexBaseSpeciesList(); Debug.Assert(!SAV.State.Exportable || ReadUInt32LittleEndian(SAV.Data.AsSpan(PokeDex)) == MAGIC); } - public Func DexFormIndexFetcher { get; } + public Func GetCountFormsPriorTo { get; } - protected sealed override void SetAllDexSeenFlags(int baseBit, byte form, int gender, bool isShiny, bool value = true) + protected sealed override void SetAllDexSeenFlags(int baseBit, byte form, byte gender, bool isShiny, bool value = true) { var species = (ushort)(baseBit + 1); if (species == (int)Species.Castform) isShiny = false; // Starting with Gen7, form bits are stored in the same region as the species flags. - int formstart = form; - int formend = form; - bool reset = GetSaneFormsToIterate(species, out int fs, out int fe, formstart); + int formStart = form; + int formEnd = form; + bool reset = GetSaneFormsToIterate(species, out var fs, out var fe, form); if (reset) - { - formstart = fs; - formend = fe; - } + (formStart, formEnd) = (fs, fe); int shiny = isShiny ? 1 : 0; - for (int f = formstart; f <= formend; f++) + for (int f = formStart; f <= formEnd; f++) { int formBit = baseBit; if (f > 0) // Override the bit to overwrite @@ -63,9 +60,9 @@ protected sealed override void SetAllDexSeenFlags(int baseBit, byte form, int ge var fc = SAV.Personal[species].FormCount; if (fc > 1) // actually has forms { - int index = DexFormIndexFetcher(species, fc, SAV.MaxSpeciesID - 1); + int index = GetCountFormsPriorTo(species, fc); if (index >= 0) // bit index valid - formBit = index + f; + formBit = SAV.MaxSpeciesID + index + (f - 1); } } SetDexFlags(baseBit, formBit, gender, shiny, value); @@ -192,10 +189,10 @@ public IEnumerable GetAllFormEntries(ushort species) public int GetDexFormIndex(ushort species, byte formCount, int form) { - var index = DexFormIndexFetcher(species, formCount, form); + var index = GetCountFormsPriorTo(species, formCount); if (index < 0) return index; - return index + SAV.MaxSpeciesID - 1; + return SAV.MaxSpeciesID + index + (form - 1); } public IList GetEntryNames(IReadOnlyList speciesNames) @@ -254,12 +251,13 @@ public byte GetBaseSpeciesGenderValue(int index) return SAV.Personal[species].Gender; } - public ushort GetBaseSpecies(ushort index) + public ushort GetBaseSpecies(int index) { - if (index <= SAV.MaxSpeciesID) - return index; + if (index < SAV.MaxSpeciesID) + return (ushort)(index + 1); - return FormBaseSpecies[index - SAV.MaxSpeciesID - 1]; + var species = index - SAV.MaxSpeciesID; + return FormBaseSpecies[species]; } protected sealed override void SetAllDexFlagsLanguage(int bit, int lang, bool value = true) @@ -315,4 +313,20 @@ private bool[] GetBlankLanguageBits(bool value) result[i] = value; return result; } + + public int GetEntryIndex(ushort species, byte form) + { + if (form <= 0) + return species - 1; + var fc = SAV.Personal[species].FormCount; + if (fc <= 1) // no forms at all + return species - 1; + + int previous = GetCountFormsPriorTo(species, fc); + if (previous < 0) // no dex forms + return species - 1; + + // bit index valid + return (SAV.MaxSpeciesID + previous + (form - 1)); + } } diff --git a/PKHeX.Core/Saves/Substructures/PokeDex/Zukan7b.cs b/PKHeX.Core/Saves/Substructures/PokeDex/Zukan7b.cs index 7b5911625..5e7b3b3c7 100644 --- a/PKHeX.Core/Saves/Substructures/PokeDex/Zukan7b.cs +++ b/PKHeX.Core/Saves/Substructures/PokeDex/Zukan7b.cs @@ -25,7 +25,7 @@ public override void SetDex(PKM pk) base.SetDex(pk); } - protected override void SetDex(ushort species, int bit, byte form, int gender, bool shiny, int lang) + protected override void SetDex(ushort species, int bit, byte form, byte gender, bool shiny, int lang) { if (IsBuddy(species, form)) form = 0; @@ -226,22 +226,6 @@ protected override bool GetSaneFormsToIterate(ushort species, out int formStart, return count < formIn; } } - - public ushort GetSpecies(ushort species, byte form) - { - if (form <= 0) - return species; - var fc = SAV.Personal[species].FormCount; - if (fc <= 1) - return species; - - // actually has forms - int f = DexFormIndexFetcher(species, fc, SAV.MaxSpeciesID - 1); - if (f >= 0) // bit index valid - return (ushort)(f + form + 1); - - return species; - } } public enum DexSizeType diff --git a/PKHeX.Core/Saves/Substructures/PokeDex/Zukan8.cs b/PKHeX.Core/Saves/Substructures/PokeDex/Zukan8.cs index b1aebd440..8bd835e4b 100644 --- a/PKHeX.Core/Saves/Substructures/PokeDex/Zukan8.cs +++ b/PKHeX.Core/Saves/Substructures/PokeDex/Zukan8.cs @@ -610,7 +610,7 @@ private void SetAllCaught(ushort species, bool value = true, bool shinyToo = fal if (shinyToo) SetDisplayShiny(species); - SetGenderDisplayed(species, (uint)pi.RandomGender()); + SetGenderDisplayed(species, pi.RandomGender()); } else { diff --git a/PKHeX.Core/Saves/Util/DexFormUtil.cs b/PKHeX.Core/Saves/Util/DexFormUtil.cs index d9bb8207c..e5a142423 100644 --- a/PKHeX.Core/Saves/Util/DexFormUtil.cs +++ b/PKHeX.Core/Saves/Util/DexFormUtil.cs @@ -7,116 +7,112 @@ namespace PKHeX.Core; /// public static class DexFormUtil { - public static int GetDexFormIndexSM(ushort species, byte formCount, int start) => GetDexFormBitIndex(species, formCount, start, formtable_SM); - public static int GetDexFormIndexUSUM(ushort species, byte formCount, int start) => GetDexFormBitIndex(species, formCount, start, formtable_USUM); - public static int GetDexFormIndexGG(ushort species, byte formCount, int start) => GetDexFormBitIndex(species, formCount, start, formtable_GG); - public static int GetDexFormCountSM(ushort species) => GetDexFormCount(species, formtable_SM); - public static int GetDexFormCountUSUM(ushort species) => GetDexFormCount(species, formtable_USUM); - public static int GetDexFormCountGG(ushort species) => GetDexFormCount(species, formtable_GG); + public static int GetDexFormIndexSM(ushort species, byte formCount) + => GetDexFormBitIndex(species, formCount, DexSpeciesWithForm_SM, DexSpeciesCount_SM); + public static int GetDexFormIndexUSUM(ushort species, byte formCount) + => GetDexFormBitIndex(species, formCount, DexSpeciesWithForm_USUM, DexSpeciesCount_USUM); + public static int GetDexFormIndexGG(ushort species, byte formCount) + => GetDexFormBitIndex(species, formCount, DexSpeciesWithForm_GG, DexSpeciesCount_GG); - private static ReadOnlySpan formtable_SM => // u16 species, u16 formcount - [ - 0x0003, 0x0002, 0x0006, 0x0003, 0x0009, 0x0002, 0x000F, 0x0002, - 0x0012, 0x0002, 0x0013, 0x0002, 0x0014, 0x0003, 0x0019, 0x0007, - 0x001A, 0x0002, 0x001B, 0x0002, 0x001C, 0x0002, 0x0025, 0x0002, - 0x0026, 0x0002, 0x0032, 0x0002, 0x0033, 0x0002, 0x0034, 0x0002, - 0x0035, 0x0002, 0x0041, 0x0002, 0x004A, 0x0002, 0x004B, 0x0002, - 0x004C, 0x0002, 0x0050, 0x0002, 0x0058, 0x0002, 0x0059, 0x0002, - 0x005E, 0x0002, 0x0067, 0x0002, 0x0069, 0x0002, 0x0073, 0x0002, - 0x007F, 0x0002, 0x0082, 0x0002, 0x008E, 0x0002, 0x0096, 0x0003, - 0x00B5, 0x0002, 0x00C9, 0x001C, 0x00D0, 0x0002, 0x00D4, 0x0002, - 0x00D6, 0x0002, 0x00E5, 0x0002, 0x00F8, 0x0002, 0x00FE, 0x0002, - 0x0101, 0x0002, 0x0104, 0x0002, 0x011A, 0x0002, 0x012E, 0x0002, - 0x012F, 0x0002, 0x0132, 0x0002, 0x0134, 0x0002, 0x0136, 0x0002, - 0x013F, 0x0002, 0x0143, 0x0002, 0x014E, 0x0002, 0x015F, 0x0004, - 0x0162, 0x0002, 0x0167, 0x0002, 0x016A, 0x0002, 0x0175, 0x0002, - 0x0178, 0x0002, 0x017C, 0x0002, 0x017D, 0x0002, 0x017E, 0x0002, - 0x017F, 0x0002, 0x0180, 0x0002, 0x0182, 0x0004, 0x019C, 0x0003, - 0x019D, 0x0003, 0x01A5, 0x0002, 0x01A6, 0x0002, 0x01A7, 0x0002, - 0x01AC, 0x0002, 0x01BD, 0x0002, 0x01C0, 0x0002, 0x01CC, 0x0002, - 0x01DB, 0x0002, 0x01DF, 0x0006, 0x01E7, 0x0002, 0x01EC, 0x0002, - 0x01ED, 0x0012, 0x0213, 0x0002, 0x0226, 0x0002, 0x022B, 0x0002, - 0x0249, 0x0004, 0x024A, 0x0004, 0x0281, 0x0002, 0x0282, 0x0002, - 0x0285, 0x0002, 0x0286, 0x0003, 0x0287, 0x0002, 0x0288, 0x0002, - 0x0289, 0x0005, 0x0292, 0x0003, 0x029A, 0x0014, 0x029D, 0x0005, - 0x029E, 0x0006, 0x029F, 0x0005, 0x02A4, 0x000A, 0x02A6, 0x0002, - 0x02A9, 0x0002, 0x02C6, 0x0004, 0x02C7, 0x0004, 0x02CC, 0x0002, - 0x02CE, 0x0005, 0x02CF, 0x0002, 0x02D0, 0x0002, 0x02DF, 0x0002, - 0x02E2, 0x0002, 0x02E5, 0x0004, 0x02E9, 0x0002, 0x02EA, 0x0002, - 0x02F2, 0x0002, 0x02F6, 0x0002, 0x0305, 0x0012, 0x0306, 0x000E, - 0x030A, 0x0004, 0x0310, 0x0002, 0x0321, 0x0002, - ]; - - private static ReadOnlySpan formtable_USUM => // u16 species, u16 formcount - [ - 0x0003, 0x0002, 0x0006, 0x0003, 0x0009, 0x0002, 0x000F, 0x0002, - 0x0012, 0x0002, 0x0013, 0x0002, 0x0014, 0x0003, 0x0019, 0x0008, - 0x001A, 0x0002, 0x001B, 0x0002, 0x001C, 0x0002, 0x0025, 0x0002, - 0x0026, 0x0002, 0x0032, 0x0002, 0x0033, 0x0002, 0x0034, 0x0002, - 0x0035, 0x0002, 0x0041, 0x0002, 0x004A, 0x0002, 0x004B, 0x0002, - 0x004C, 0x0002, 0x0050, 0x0002, 0x0058, 0x0002, 0x0059, 0x0002, - 0x005E, 0x0002, 0x0067, 0x0002, 0x0069, 0x0003, 0x0073, 0x0002, - 0x007F, 0x0002, 0x0082, 0x0002, 0x008E, 0x0002, 0x0096, 0x0003, - 0x00B5, 0x0002, 0x00C9, 0x001C, 0x00D0, 0x0002, 0x00D4, 0x0002, - 0x00D6, 0x0002, 0x00E5, 0x0002, 0x00F8, 0x0002, 0x00FE, 0x0002, - 0x0101, 0x0002, 0x0104, 0x0002, 0x011A, 0x0002, 0x012E, 0x0002, - 0x012F, 0x0002, 0x0132, 0x0002, 0x0134, 0x0002, 0x0136, 0x0002, - 0x013F, 0x0002, 0x0143, 0x0002, 0x014E, 0x0002, 0x015F, 0x0004, - 0x0162, 0x0002, 0x0167, 0x0002, 0x016A, 0x0002, 0x0175, 0x0002, - 0x0178, 0x0002, 0x017C, 0x0002, 0x017D, 0x0002, 0x017E, 0x0002, - 0x017F, 0x0002, 0x0180, 0x0002, 0x0182, 0x0004, 0x019C, 0x0003, - 0x019D, 0x0003, 0x019E, 0x0003, 0x01A5, 0x0002, 0x01A6, 0x0002, - 0x01A7, 0x0002, 0x01AC, 0x0002, 0x01BD, 0x0002, 0x01C0, 0x0002, - 0x01CC, 0x0002, 0x01DB, 0x0002, 0x01DF, 0x0006, 0x01E7, 0x0002, - 0x01EC, 0x0002, 0x01ED, 0x0012, 0x0213, 0x0002, 0x0226, 0x0002, - 0x022B, 0x0002, 0x0249, 0x0004, 0x024A, 0x0004, 0x0281, 0x0002, - 0x0282, 0x0002, 0x0285, 0x0002, 0x0286, 0x0003, 0x0287, 0x0002, - 0x0288, 0x0002, 0x0289, 0x0005, 0x0292, 0x0003, 0x0298, 0x0014, - 0x0299, 0x0014, 0x029A, 0x0014, 0x029D, 0x0005, 0x029E, 0x0006, - 0x029F, 0x0005, 0x02A4, 0x000A, 0x02A6, 0x0002, 0x02A9, 0x0002, - 0x02C6, 0x0004, 0x02C7, 0x0004, 0x02CC, 0x0002, 0x02CE, 0x0005, - 0x02CF, 0x0002, 0x02D0, 0x0002, 0x02DF, 0x0002, 0x02E2, 0x0002, - 0x02E5, 0x0004, 0x02E7, 0x0002, 0x02E8, 0x0002, 0x02E9, 0x0003, - 0x02EA, 0x0002, 0x02F0, 0x0002, 0x02F2, 0x0002, 0x02F6, 0x0002, - 0x0305, 0x0012, 0x0306, 0x000E, 0x0309, 0x0002, 0x030A, 0x0004, - 0x0310, 0x0002, 0x0320, 0x0004, 0x0321, 0x0002, - ]; - - private static ReadOnlySpan formtable_GG => // u16 species, u16 formcount - [ - 0x0003, 0x0002, 0x0006, 0x0003, 0x0009, 0x0002, 0x000F, 0x0002, - 0x0012, 0x0002, 0x0013, 0x0002, 0x0014, 0x0003, 0x0019, 0x0009, - 0x001A, 0x0002, 0x001B, 0x0002, 0x001C, 0x0002, 0x0025, 0x0002, - 0x0026, 0x0002, 0x0032, 0x0002, 0x0033, 0x0002, 0x0034, 0x0002, - 0x0035, 0x0002, 0x0041, 0x0002, 0x004A, 0x0002, 0x004B, 0x0002, - 0x004C, 0x0002, 0x0050, 0x0002, 0x0058, 0x0002, 0x0059, 0x0002, - 0x005E, 0x0002, 0x0067, 0x0002, 0x0069, 0x0003, 0x0073, 0x0002, - 0x007F, 0x0002, 0x0082, 0x0002, 0x008E, 0x0002, 0x0096, 0x0003, - ]; - - private static int GetDexFormBitIndex(ushort species, byte formCount, int start, ReadOnlySpan formTable) + public static int GetDexFormCountSM(ushort species) { - int formIndex = start; - for (int i = 0; i < formTable.Length; i += 2) - { - int s = formTable[i]; - int f = formTable[i + 1]; - if (s == species) - return f > formCount ? -1 : formIndex; - - formIndex += f - 1; - } - return -1; + var index = DexSpeciesWithForm_SM.BinarySearch(species); + if (index < 0) + return 0; + return DexSpeciesCount_SM[index]; } - private static int GetDexFormCount(ushort species, ReadOnlySpan formTable) + public static int GetDexFormCountUSUM(ushort species) { - for (int i = 0; i < formTable.Length; i += 2) - { - if (formTable[i] == species) - return formTable[i + 1]; - } - return 0; + var index = DexSpeciesWithForm_USUM.BinarySearch(species); + if (index < 0) + return 0; + return DexSpeciesCount_USUM[index]; + } + + public static int GetDexFormCountGG(ushort species) + { + var index = DexSpeciesWithForm_GG.BinarySearch(species); + if (index < 0) + return 0; + return DexSpeciesCount_GG[index]; + } + + private static ReadOnlySpan DexSpeciesWithForm_SM => + [ + 003, 006, 009, 015, 018, 019, 020, 025, 026, 027, 028, 037, 038, 050, 051, 052, + 053, 065, 074, 075, 076, 080, 088, 089, 094, 103, 105, 115, 127, 130, 142, 150, + 181, 201, 208, 212, 214, 229, 248, 254, 257, 260, 282, 302, 303, 306, 308, 310, + 319, 323, 334, 351, 354, 359, 362, 373, 376, 380, 381, 382, 383, 384, 386, 412, + 413, 421, 422, 423, 428, 445, 448, 460, 475, 479, 487, 492, 493, 531, 550, 555, + 585, 586, 641, 642, 645, 646, 647, 648, 649, 658, 666, 669, 670, 671, 676, 678, + 681, 710, 711, 716, 718, 719, 720, 735, 738, 741, 745, 746, 754, 758, 773, 774, + 778, 784, 801, + ]; + + private static ReadOnlySpan DexSpeciesCount_SM => + [ + 02,03,02,02,02,02,03,07,02,02,02,02,02,02,02,02, + 02,02,02,02,02,02,02,02,02,02,02,02,02,02,02,03, + 02,28,02,02,02,02,02,02,02,02,02,02,02,02,02,02, + 02,02,02,04,02,02,02,02,02,02,02,02,02,02,04,03, + 03,02,02,02,02,02,02,02,02,06,02,02,18,02,02,02, + 04,04,02,02,02,03,02,02,05,03,20,05,06,05,10,02, + 02,04,04,02,05,02,02,02,02,04,02,02,02,02,18,14, + 04,02,02, + ]; + + private static ReadOnlySpan DexSpeciesWithForm_USUM => + [ + 003, 006, 009, 015, 018, 019, 020, 025, 026, 027, 028, 037, 038, 050, 051, 052, + 053, 065, 074, 075, 076, 080, 088, 089, 094, 103, 105, 115, 127, 130, 142, 150, + 181, 201, 208, 212, 214, 229, 248, 254, 257, 260, 282, 302, 303, 306, 308, 310, + 319, 323, 334, 351, 354, 359, 362, 373, 376, 380, 381, 382, 383, 384, 386, 412, + 413, 414, 421, 422, 423, 428, 445, 448, 460, 475, 479, 487, 492, 493, 531, 550, + 555, 585, 586, 641, 642, 645, 646, 647, 648, 649, 658, 664, 665, 666, 669, 670, + 671, 676, 678, 681, 710, 711, 716, 718, 719, 720, 735, 738, 741, 743, 744, 745, + 746, 752, 754, 758, 773, 774, 777, 778, 784, 800, 801, + ]; + + private static ReadOnlySpan DexSpeciesCount_USUM => + [ + 02,03,02,02,02,02,03,08,02,02,02,02,02,02,02,02, + 02,02,02,02,02,02,02,02,02,02,03,02,02,02,02,03, + 02,28,02,02,02,02,02,02,02,02,02,02,02,02,02,02, + 02,02,02,04,02,02,02,02,02,02,02,02,02,02,04,03, + 03,03,02,02,02,02,02,02,02,02,06,02,02,18,02,02, + 02,04,04,02,02,02,03,02,02,05,03,20,20,20,05,06, + 05,10,02,02,04,04,02,05,02,02,02,02,04,02,02,03, + 02,02,02,02,18,14,02,04,02,04,02, + ]; + + private static ReadOnlySpan DexSpeciesWithForm_GG => + [ + 003, 006, 009, 015, 018, 019, 020, 025, 026, 027, 028, 037, 038, 050, 051, 052, + 053, 065, 074, 075, 076, 080, 088, 089, 094, 103, 105, 115, 127, 130, 142, 150, + ]; + + private static ReadOnlySpan DexSpeciesCount_GG => + [ + 02,03,02,02,02,02,03,09,02,02,02,02,02,02,02,02, + 02,02,02,02,02,02,02,02,02,02,03,02,02,02,02,03, + ]; + + private static int GetDexFormBitIndex(ushort species, byte formCount, ReadOnlySpan withForm, ReadOnlySpan count) + { + var index = withForm.BinarySearch(species); + if (index < 0) + return -1; + + var c = count[index]; + if (c > formCount) + return -1; + + // account for base form (0) occupying the arr[species] indexes... + int prior = -index; // -1 * (count) + foreach (var p in count[..index]) + prior += p; + return prior; } public static int GetDexFormIndexBW(ushort species, byte formCount) diff --git a/PKHeX.Core/Saves/Util/SaveExtensions.cs b/PKHeX.Core/Saves/Util/SaveExtensions.cs index ef4496c95..944058f69 100644 --- a/PKHeX.Core/Saves/Util/SaveExtensions.cs +++ b/PKHeX.Core/Saves/Util/SaveExtensions.cs @@ -51,7 +51,7 @@ private static List GetSaveFileErrata(this SaveFile sav, PKM pk, IBasicS msg = MsgIndexItemHeld; if (msg != null) { - var itemstr = GameInfo.Strings.GetItemStrings(pk.Context, (GameVersion)pk.Version); + var itemstr = GameInfo.Strings.GetItemStrings(pk.Context, pk.Version); errata.Add($"{msg} {(held >= itemstr.Length ? held.ToString() : itemstr[held])}"); } } diff --git a/PKHeX.Core/Saves/Util/SaveUtil.cs b/PKHeX.Core/Saves/Util/SaveUtil.cs index cb48045fe..4a2850ffc 100644 --- a/PKHeX.Core/Saves/Util/SaveUtil.cs +++ b/PKHeX.Core/Saves/Util/SaveUtil.cs @@ -220,21 +220,21 @@ public static class SaveUtil /// Version Identifier or Invalid if type cannot be determined. private static GameVersion GetSAVType(ReadOnlySpan data) { - GameVersion ver; - if ((ver = GetIsG1SAV(data)) != Invalid) - return ver; - if ((ver = GetIsG2SAV(data)) != Invalid) - return ver; - if ((ver = GetIsG3SAV(data)) != Invalid) - return ver; - if ((ver = GetIsG4SAV(data)) != Invalid) - return ver; - if ((ver = GetIsG5SAV(data)) != Invalid) - return ver; - if ((ver = GetIsG6SAV(data)) != Invalid) - return ver; - if ((ver = GetIsG7SAV(data)) != Invalid) - return ver; + GameVersion version; + if ((version = GetIsG1SAV(data)) != Invalid) + return version; + if ((version = GetIsG2SAV(data)) != Invalid) + return version; + if ((version = GetIsG3SAV(data)) != Invalid) + return version; + if ((version = GetIsG4SAV(data)) != Invalid) + return version; + if ((version = GetIsG5SAV(data)) != Invalid) + return version; + if ((version = GetIsG6SAV(data)) != Invalid) + return version; + if ((version = GetIsG7SAV(data)) != Invalid) + return version; if (GetIsBelugaSAV(data) != Invalid) return GG; @@ -262,14 +262,14 @@ private static GameVersion GetSAVType(ReadOnlySpan data) if (SAV1StadiumJ.IsStadium(data)) return StadiumJ; - if ((ver = GetIsG8SAV(data)) != Invalid) - return ver; - if ((ver = GetIsG8SAV_BDSP(data)) != Invalid) - return ver; - if ((ver = GetIsG8SAV_LA(data)) != Invalid) - return ver; - if ((ver = GetIsG9SAV(data)) != Invalid) - return ver; + if ((version = GetIsG8SAV(data)) != Invalid) + return version; + if ((version = GetIsG8SAV_BDSP(data)) != Invalid) + return version; + if ((version = GetIsG8SAV_LA(data)) != Invalid) + return version; + if ((version = GetIsG9SAV(data)) != Invalid) + return version; return Invalid; } @@ -609,8 +609,8 @@ private static GameVersion GetIsG8SAV_BDSP(ReadOnlySpan data) if (data.Length is not (SIZE_G8BDSP or SIZE_G8BDSP_1 or SIZE_G8BDSP_2 or SIZE_G8BDSP_3)) return Invalid; - var ver = (Gem8Version)ReadUInt32LittleEndian(data); - if (ver is not (Gem8Version.V1_0 or Gem8Version.V1_1 or Gem8Version.V1_2 or Gem8Version.V1_3)) + var version = (Gem8Version)ReadUInt32LittleEndian(data); + if (version is not (Gem8Version.V1_0 or Gem8Version.V1_1 or Gem8Version.V1_2 or Gem8Version.V1_3)) return Invalid; return BDSP; @@ -820,7 +820,7 @@ private static GameVersion GetIsG9SAV(ReadOnlySpan data) public static SaveFile GetBlankSAV(GameVersion game, string trainerName, LanguageID language = LanguageID.English) { var sav = GetBlankSAV(game, language); - sav.Game = (int)game; + sav.Version = game; sav.OT = trainerName; if (sav.Generation >= 4) sav.Language = (int)language; @@ -895,8 +895,8 @@ public static SaveFile GetBlankSAV(GameVersion game, string trainerName, Languag /// Save File for that generation. public static SaveFile GetBlankSAV(EntityContext context, string trainerName, LanguageID language = LanguageID.English) { - var ver = context.GetSingleGameVersion(); - return GetBlankSAV(ver, trainerName, language); + var version = context.GetSingleGameVersion(); + return GetBlankSAV(version, trainerName, language); } /// diff --git a/PKHeX.Core/Saves/Util/StadiumUtil.cs b/PKHeX.Core/Saves/Util/StadiumUtil.cs index ae6229fec..98fa74e15 100644 --- a/PKHeX.Core/Saves/Util/StadiumUtil.cs +++ b/PKHeX.Core/Saves/Util/StadiumUtil.cs @@ -1,4 +1,5 @@ using System; +using System.Diagnostics.CodeAnalysis; using static PKHeX.Core.StadiumSaveType; using static System.Buffers.Binary.BinaryPrimitives; @@ -12,7 +13,7 @@ public static class StadiumUtil /// /// Checks if the value is present either with or without byte-swapping. /// - public static StadiumSaveType IsMagicPresentEither(ReadOnlySpan data, int size, uint magic, int count) + public static StadiumSaveType IsMagicPresentEither(ReadOnlySpan data, [ConstantExpected] int size, [ConstantExpected] uint magic, [ConstantExpected] int count) { if (IsMagicPresent(data, size, magic, count)) return Regular; @@ -26,7 +27,7 @@ public static StadiumSaveType IsMagicPresentEither(ReadOnlySpan data, int /// /// Checks if the value is present without byte-swapping. /// - public static bool IsMagicPresent(ReadOnlySpan data, int size, uint magic, int count) + public static bool IsMagicPresent(ReadOnlySpan data, [ConstantExpected] int size, [ConstantExpected] uint magic, [ConstantExpected] int count) { // Check footers of first few chunks to see if the magic value is there. for (int i = 0; i < count; i++) @@ -41,7 +42,7 @@ public static bool IsMagicPresent(ReadOnlySpan data, int size, uint magic, /// /// Checks if the value is present either with byte-swapping. /// - public static bool IsMagicPresentSwap(ReadOnlySpan data, int size, uint magic, int count) + public static bool IsMagicPresentSwap(ReadOnlySpan data, [ConstantExpected] int size, [ConstantExpected] uint magic, [ConstantExpected] int count) { // Check footers of first few chunks to see if the magic value is there. var right = ReverseEndianness((ushort)(magic >> 16)); @@ -63,7 +64,7 @@ public static bool IsMagicPresentSwap(ReadOnlySpan data, int size, uint ma /// Checks if the value is present either with or without byte-swapping. /// /// Only checks for a single instance of the magic value. - public static StadiumSaveType IsMagicPresentAbsolute(ReadOnlySpan data, int offset, uint magic) + public static StadiumSaveType IsMagicPresentAbsolute(ReadOnlySpan data, [ConstantExpected] int offset, [ConstantExpected] uint magic) { var actual = ReadUInt32LittleEndian(data[offset..]); if (actual == magic) // POKE diff --git a/PKHeX.Drawing.Misc/Util/TypeSpriteUtil.cs b/PKHeX.Drawing.Misc/Util/TypeSpriteUtil.cs index eb4f4341f..a4d8098cd 100644 --- a/PKHeX.Drawing.Misc/Util/TypeSpriteUtil.cs +++ b/PKHeX.Drawing.Misc/Util/TypeSpriteUtil.cs @@ -8,21 +8,21 @@ public static class TypeSpriteUtil { private static Bitmap? Get(string name) => Resources.ResourceManager.GetObject(name) as Bitmap; - public static Bitmap? GetTypeSpriteWide(byte type, int generation = PKX.Generation) + public static Bitmap? GetTypeSpriteWide(byte type, byte generation = PKX.Generation) { if (generation <= 2) type = (byte)((MoveType)type).GetMoveTypeGeneration(generation); return Get($"type_wide_{type:00}"); } - public static Bitmap? GetTypeSpriteIcon(byte type, int generation = PKX.Generation) + public static Bitmap? GetTypeSpriteIcon(byte type, byte generation = PKX.Generation) { if (generation <= 2) type = (byte)((MoveType)type).GetMoveTypeGeneration(generation); return Get($"type_icon_{type:00}"); } - public static Bitmap? GetTypeSpriteIconSmall(byte type, int generation = PKX.Generation) + public static Bitmap? GetTypeSpriteIconSmall(byte type, byte generation = PKX.Generation) { if (generation <= 2) type = (byte)((MoveType)type).GetMoveTypeGeneration(generation); diff --git a/PKHeX.Drawing.PokeSprite/Builder/SpriteBuilder.cs b/PKHeX.Drawing.PokeSprite/Builder/SpriteBuilder.cs index fb23cfb42..25d2126b6 100644 --- a/PKHeX.Drawing.PokeSprite/Builder/SpriteBuilder.cs +++ b/PKHeX.Drawing.PokeSprite/Builder/SpriteBuilder.cs @@ -53,8 +53,8 @@ public abstract class SpriteBuilder : ISpriteBuilder protected abstract string GetSpriteStringSpeciesOnly(ushort species); - protected abstract string GetSpriteAll(ushort species, byte form, int gender, uint formarg, bool shiny, EntityContext context); - protected abstract string GetSpriteAllSecondary(ushort species, byte form, int gender, uint formarg, bool shiny, EntityContext context); + protected abstract string GetSpriteAll(ushort species, byte form, byte gender, uint formarg, bool shiny, EntityContext context); + protected abstract string GetSpriteAllSecondary(ushort species, byte form, byte gender, uint formarg, bool shiny, EntityContext context); protected abstract string GetItemResourceName(int item); protected abstract Bitmap Unknown { get; } protected abstract Bitmap GetEggSprite(ushort species); @@ -104,7 +104,7 @@ public void Initialize(SaveFile sav) /// Is currently in an egg /// Is it shiny /// Context the sprite is for - public Bitmap GetSprite(ushort species, byte form, int gender, uint formarg, int heldItem, bool isEgg, Shiny shiny = Shiny.Never, EntityContext context = EntityContext.None) + public Bitmap GetSprite(ushort species, byte form, byte gender, uint formarg, int heldItem, bool isEgg, Shiny shiny = Shiny.Never, EntityContext context = EntityContext.None) { if (species == 0) return None; @@ -133,7 +133,7 @@ public Bitmap GetSprite(Bitmap baseSprite, ushort species, int heldItem, bool is return baseSprite; } - private Bitmap GetBaseImage(ushort species, byte form, int gender, uint formarg, bool shiny, EntityContext context) + private Bitmap GetBaseImage(ushort species, byte form, byte gender, uint formarg, bool shiny, EntityContext context) { var img = FormInfo.IsTotemForm(species, form, context) ? GetBaseImageTotem(species, form, gender, formarg, shiny, context) @@ -141,7 +141,7 @@ private Bitmap GetBaseImage(ushort species, byte form, int gender, uint formarg, return img ?? GetBaseImageFallback(species, form, gender, formarg, shiny, context); } - private Bitmap? GetBaseImageTotem(ushort species, byte form, int gender, uint formarg, bool shiny, EntityContext context) + private Bitmap? GetBaseImageTotem(ushort species, byte form, byte gender, uint formarg, bool shiny, EntityContext context) { var baseform = FormInfo.GetTotemBaseForm(species, form); var b = GetBaseImageDefault(species, baseform, gender, formarg, shiny, context); @@ -153,7 +153,7 @@ private Bitmap GetBaseImage(ushort species, byte form, int gender, uint formarg, return ImageUtil.LayerImage(b, layer, 0, 0); } - private Bitmap? GetBaseImageDefault(ushort species, byte form, int gender, uint formarg, bool shiny, EntityContext context) + private Bitmap? GetBaseImageDefault(ushort species, byte form, byte gender, uint formarg, bool shiny, EntityContext context) { var file = GetSpriteAll(species, form, gender, formarg, shiny, context); var resource = (Bitmap?)Resources.ResourceManager.GetObject(file); @@ -165,7 +165,7 @@ private Bitmap GetBaseImage(ushort species, byte form, int gender, uint formarg, return resource; } - private Bitmap GetBaseImageFallback(ushort species, byte form, int gender, uint formarg, bool shiny, EntityContext context) + private Bitmap GetBaseImageFallback(ushort species, byte form, byte gender, uint formarg, bool shiny, EntityContext context) { if (shiny) // try again without shiny { diff --git a/PKHeX.Drawing.PokeSprite/Builder/SpriteBuilder5668.cs b/PKHeX.Drawing.PokeSprite/Builder/SpriteBuilder5668.cs index 2d8e6ef92..150c3fe35 100644 --- a/PKHeX.Drawing.PokeSprite/Builder/SpriteBuilder5668.cs +++ b/PKHeX.Drawing.PokeSprite/Builder/SpriteBuilder5668.cs @@ -20,8 +20,8 @@ public sealed class SpriteBuilder5668s : SpriteBuilder public override bool HasFallbackMethod => true; protected override string GetSpriteStringSpeciesOnly(ushort species) => 'b' + $"_{species}"; - protected override string GetSpriteAll(ushort species, byte form, int gender, uint formarg, bool shiny, EntityContext context) => 'b' + SpriteName.GetResourceStringSprite(species, form, gender, formarg, context, shiny); - protected override string GetSpriteAllSecondary(ushort species, byte form, int gender, uint formarg, bool shiny, EntityContext context) => 'c' + SpriteName.GetResourceStringSprite(species, form, gender, formarg, context, shiny); + protected override string GetSpriteAll(ushort species, byte form, byte gender, uint formarg, bool shiny, EntityContext context) => 'b' + SpriteName.GetResourceStringSprite(species, form, gender, formarg, context, shiny); + protected override string GetSpriteAllSecondary(ushort species, byte form, byte gender, uint formarg, bool shiny, EntityContext context) => 'c' + SpriteName.GetResourceStringSprite(species, form, gender, formarg, context, shiny); protected override string GetItemResourceName(int item) => 'b' + $"item_{item}"; protected override Bitmap Unknown => Resources.b_unknown; protected override Bitmap GetEggSprite(ushort species) => species == (int)Species.Manaphy ? Resources.b_490_e : Resources.b_egg; diff --git a/PKHeX.Drawing.PokeSprite/Builder/SpriteBuilder5668a.cs b/PKHeX.Drawing.PokeSprite/Builder/SpriteBuilder5668a.cs index 5eb7b09c3..abae3d71f 100644 --- a/PKHeX.Drawing.PokeSprite/Builder/SpriteBuilder5668a.cs +++ b/PKHeX.Drawing.PokeSprite/Builder/SpriteBuilder5668a.cs @@ -20,8 +20,8 @@ public sealed class SpriteBuilder5668a : SpriteBuilder public override bool HasFallbackMethod => true; protected override string GetSpriteStringSpeciesOnly(ushort species) => 'a' + $"_{species}"; - protected override string GetSpriteAll(ushort species, byte form, int gender, uint formarg, bool shiny, EntityContext context) => 'a' + SpriteName.GetResourceStringSprite(species, form, gender, formarg, context, shiny); - protected override string GetSpriteAllSecondary(ushort species, byte form, int gender, uint formarg, bool shiny, EntityContext context) => 'b' + SpriteName.GetResourceStringSprite(species, form, gender, formarg, context, shiny); + protected override string GetSpriteAll(ushort species, byte form, byte gender, uint formarg, bool shiny, EntityContext context) => 'a' + SpriteName.GetResourceStringSprite(species, form, gender, formarg, context, shiny); + protected override string GetSpriteAllSecondary(ushort species, byte form, byte gender, uint formarg, bool shiny, EntityContext context) => 'b' + SpriteName.GetResourceStringSprite(species, form, gender, formarg, context, shiny); protected override string GetItemResourceName(int item) => 'a' + $"item_{item}"; protected override Bitmap Unknown => Resources.b_unknown; protected override Bitmap GetEggSprite(ushort species) => species == (int)Species.Manaphy ? Resources.a_490_e : Resources.a_egg; diff --git a/PKHeX.Drawing.PokeSprite/Builder/SpriteBuilder5668c.cs b/PKHeX.Drawing.PokeSprite/Builder/SpriteBuilder5668c.cs index b2096896b..493203f71 100644 --- a/PKHeX.Drawing.PokeSprite/Builder/SpriteBuilder5668c.cs +++ b/PKHeX.Drawing.PokeSprite/Builder/SpriteBuilder5668c.cs @@ -20,8 +20,8 @@ public sealed class SpriteBuilder5668c : SpriteBuilder public override bool HasFallbackMethod => true; protected override string GetSpriteStringSpeciesOnly(ushort species) => 'c' + $"_{species}"; - protected override string GetSpriteAll(ushort species, byte form, int gender, uint formarg, bool shiny, EntityContext context) => 'c' + SpriteName.GetResourceStringSprite(species, form, gender, formarg, context, shiny); - protected override string GetSpriteAllSecondary(ushort species, byte form, int gender, uint formarg, bool shiny, EntityContext context) => 'b' + SpriteName.GetResourceStringSprite(species, form, gender, formarg, context, shiny); + protected override string GetSpriteAll(ushort species, byte form, byte gender, uint formarg, bool shiny, EntityContext context) => 'c' + SpriteName.GetResourceStringSprite(species, form, gender, formarg, context, shiny); + protected override string GetSpriteAllSecondary(ushort species, byte form, byte gender, uint formarg, bool shiny, EntityContext context) => 'b' + SpriteName.GetResourceStringSprite(species, form, gender, formarg, context, shiny); protected override string GetItemResourceName(int item) => 'b' + $"item_{item}"; protected override Bitmap Unknown => Resources.b_unknown; protected override Bitmap GetEggSprite(ushort species) => species == (int)Species.Manaphy ? Resources.b_490_e : Resources.b_egg; diff --git a/PKHeX.Drawing.PokeSprite/Util/SpriteName.cs b/PKHeX.Drawing.PokeSprite/Util/SpriteName.cs index d395cb289..a372fc487 100644 --- a/PKHeX.Drawing.PokeSprite/Util/SpriteName.cs +++ b/PKHeX.Drawing.PokeSprite/Util/SpriteName.cs @@ -17,12 +17,12 @@ public static class SpriteName /// /// Gets the resource name of the sprite. /// - public static string GetResourceStringBall(int ball) => $"_ball{ball}"; + public static string GetResourceStringBall(byte ball) => $"_ball{ball}"; /// /// Gets the resource name of the Pokémon sprite. /// - public static string GetResourceStringSprite(ushort species, byte form, int gender, uint formarg, EntityContext context = PKX.Context, bool shiny = false) + public static string GetResourceStringSprite(ushort species, byte form, byte gender, uint formarg, EntityContext context = PKX.Context, bool shiny = false) { if (SpeciesDefaultFormSprite.Contains(species)) // Species who show their default sprite regardless of Form form = 0; diff --git a/PKHeX.Drawing.PokeSprite/Util/SpriteUtil.cs b/PKHeX.Drawing.PokeSprite/Util/SpriteUtil.cs index f9a938ee8..18d5a8a71 100644 --- a/PKHeX.Drawing.PokeSprite/Util/SpriteUtil.cs +++ b/PKHeX.Drawing.PokeSprite/Util/SpriteUtil.cs @@ -52,7 +52,7 @@ public static void Initialize(SaveFile sav) Spriter.Initialize(sav); } - public static Bitmap GetBallSprite(int ball) + public static Bitmap GetBallSprite(byte ball) { string resource = SpriteName.GetResourceStringBall(ball); return (Bitmap?)Resources.ResourceManager.GetObject(resource) ?? Resources._ball4; // Poké Ball (default) @@ -60,7 +60,7 @@ public static Bitmap GetBallSprite(int ball) public static Bitmap? GetItemSprite(int item) => Resources.ResourceManager.GetObject($"item_{item}") as Bitmap; - public static Bitmap GetSprite(ushort species, byte form, int gender, uint formarg, int item, bool isegg, Shiny shiny, EntityContext context = EntityContext.None) + public static Bitmap GetSprite(ushort species, byte form, byte gender, uint formarg, int item, bool isegg, Shiny shiny, EntityContext context = EntityContext.None) { return Spriter.GetSprite(species, form, gender, formarg, item, isegg, shiny, context); } @@ -204,7 +204,7 @@ private static Bitmap ApplyExperience(PKM pk, Bitmap img, IEncounterTemplate? en if (pct is not 0) return ImageUtil.WritePixels(img, Color.DodgerBlue, start, start + (int)(SpriteWidth * pct * bpp)); - var encLevel = enc is { EggEncounter: true } ? enc.LevelMin : pk.Met_Level; + var encLevel = enc is { EggEncounter: true } ? enc.LevelMin : pk.MetLevel; var color = level != encLevel && pk.HasOriginalMetLocation ? Color.DarkOrange : Color.Yellow; return ImageUtil.WritePixels(img, color, start, start + (SpriteWidth * bpp)); } @@ -257,10 +257,11 @@ public static Bitmap Sprite(this IEncounterTemplate enc) if (enc is MysteryGift g) return GetMysteryGiftPreviewPoke(g); var gender = GetDisplayGender(enc); - var img = GetSprite(enc.Species, enc.Form, gender, 0, 0, enc.EggEncounter, enc.IsShiny ? Shiny.Always : Shiny.Never, enc.Context); + var shiny = enc.IsShiny ? Shiny.Always : Shiny.Never; + var img = GetSprite(enc.Species, enc.Form, gender, 0, 0, enc.EggEncounter, shiny, enc.Context); if (SpriteBuilder.ShowEncounterBall && enc is IFixedBall {FixedBall: not Ball.None} b) { - var ballSprite = GetBallSprite((int)b.FixedBall); + var ballSprite = GetBallSprite((byte)b.FixedBall); img = ImageUtil.LayerImage(img, ballSprite, 0, img.Height - ballSprite.Height); } if (enc is IGigantamaxReadOnly {CanGigantamax: true}) @@ -278,10 +279,10 @@ public static Bitmap Sprite(this IEncounterTemplate enc) return img; } - public static int GetDisplayGender(IEncounterTemplate enc) => enc switch + public static byte GetDisplayGender(IEncounterTemplate enc) => enc switch { - IFixedGender { IsFixedGender: true } s => Math.Max(0, (int)s.Gender), - IPogoSlot g => (int)g.Gender & 1, + IFixedGender { IsFixedGender: true } s => Math.Max((byte)0, s.Gender), + IPogoSlot g => (byte)((int)g.Gender & 1), _ => 0, }; @@ -293,12 +294,12 @@ public static Bitmap GetMysteryGiftPreviewPoke(MysteryGift gift) if (gift is { IsEgg: true, Species: (int)Species.Manaphy }) // Manaphy Egg return GetSprite((int)Species.Manaphy, 0, 2, 0, 0, true, Shiny.Never, gift.Context); - var gender = Math.Max(0, gift.Gender); + var gender = Math.Max((byte)0, gift.Gender); var img = GetSprite(gift.Species, gift.Form, gender, 0, gift.HeldItem, gift.IsEgg, gift.IsShiny ? Shiny.Always : Shiny.Never, gift.Context); if (SpriteBuilder.ShowEncounterBall && gift is IFixedBall { FixedBall: not Ball.None } b) { - var ballSprite = GetBallSprite((int)b.FixedBall); + var ballSprite = GetBallSprite((byte)b.FixedBall); img = ImageUtil.LayerImage(img, ballSprite, 0, img.Height - ballSprite.Height); } diff --git a/PKHeX.WinForms/Controls/PKM Editor/BallBrowser.cs b/PKHeX.WinForms/Controls/PKM Editor/BallBrowser.cs index cf41bdaaa..a8f128c88 100644 --- a/PKHeX.WinForms/Controls/PKM Editor/BallBrowser.cs +++ b/PKHeX.WinForms/Controls/PKM Editor/BallBrowser.cs @@ -12,7 +12,8 @@ public partial class BallBrowser : Form { public BallBrowser() => InitializeComponent(); - public int BallChoice { get; private set; } = -1; + public bool WasBallChosen { get; private set; } + public byte BallChoice { get; private set; } public void LoadBalls(PKM pk) { @@ -29,7 +30,7 @@ private void LoadBalls(IEnumerable legal, int max) int countLegal = 0; List controls = []; var names = GameInfo.BallDataSource; - for (int ballID = 1; ballID < flags.Length; ballID++) + for (byte ballID = 1; ballID < flags.Length; ballID++) { var name = GetBallName(ballID, names); var pb = GetBallView(ballID, name, flags[ballID]); @@ -52,7 +53,7 @@ private void LoadBalls(IEnumerable legal, int max) } } - private static string GetBallName(int ballID, IEnumerable names) + private static string GetBallName(byte ballID, IEnumerable names) { foreach (var x in names) { @@ -62,7 +63,7 @@ private static string GetBallName(int ballID, IEnumerable names) throw new ArgumentOutOfRangeException(nameof(ballID)); } - private SelectablePictureBox GetBallView(int ballID, string name, bool valid) + private SelectablePictureBox GetBallView(byte ballID, string name, bool valid) { var img = SpriteUtil.GetBallSprite(ballID); var pb = new SelectablePictureBox @@ -87,9 +88,10 @@ private SelectablePictureBox GetBallView(int ballID, string name, bool valid) return pb; } - private void SelectBall(int b) + private void SelectBall(byte b) { BallChoice = b; + WasBallChosen = true; Close(); } } diff --git a/PKHeX.WinForms/Controls/PKM Editor/ContestStat.cs b/PKHeX.WinForms/Controls/PKM Editor/ContestStat.cs index ea814f3dd..d984ebe4e 100644 --- a/PKHeX.WinForms/Controls/PKM Editor/ContestStat.cs +++ b/PKHeX.WinForms/Controls/PKM Editor/ContestStat.cs @@ -11,37 +11,37 @@ public ContestStat() InitializeComponent(); } - public byte CNT_Cool + public byte ContestCool { get => (byte)Util.ToInt32(TB_Cool.Text); set => TB_Cool.Text = value.ToString(); } - public byte CNT_Beauty + public byte ContestBeauty { get => (byte)Util.ToInt32(TB_Beauty.Text); set => TB_Beauty.Text = value.ToString(); } - public byte CNT_Cute + public byte ContestCute { get => (byte)Util.ToInt32(TB_Cute.Text); set => TB_Cute.Text = value.ToString(); } - public byte CNT_Smart + public byte ContestSmart { get => (byte)Util.ToInt32(TB_Smart.Text); set => TB_Smart.Text = value.ToString(); } - public byte CNT_Tough + public byte ContestTough { get => (byte)Util.ToInt32(TB_Tough.Text); set => TB_Tough.Text = value.ToString(); } - public byte CNT_Sheen + public byte ContestSheen { get => (byte)Util.ToInt32(TB_Sheen.Text); set => TB_Sheen.Text = value.ToString(); diff --git a/PKHeX.WinForms/Controls/PKM Editor/DrawConfig.cs b/PKHeX.WinForms/Controls/PKM Editor/DrawConfig.cs index a92c28dd6..acda8877e 100644 --- a/PKHeX.WinForms/Controls/PKM Editor/DrawConfig.cs +++ b/PKHeX.WinForms/Controls/PKM Editor/DrawConfig.cs @@ -73,7 +73,7 @@ public sealed class DrawConfig : IDisposable public DrawConfig() => LoadBrushes(); - public Color GetGenderColor(int gender) => gender switch + public Color GetGenderColor(byte gender) => gender switch { 0 => Male, 1 => Female, diff --git a/PKHeX.WinForms/Controls/PKM Editor/EditPK2.cs b/PKHeX.WinForms/Controls/PKM Editor/EditPK2.cs index ec13807e3..7b435a6f3 100644 --- a/PKHeX.WinForms/Controls/PKM Editor/EditPK2.cs +++ b/PKHeX.WinForms/Controls/PKM Editor/EditPK2.cs @@ -19,9 +19,9 @@ private void PopulateFieldsPK2() LoadMisc2(pk2); TID_Trainer.LoadIDValues(pk2, pk2.Format); - TB_MetLevel.Text = c2.Met_Level.ToString(); - CB_MetLocation.SelectedValue = c2.Met_Location; - CB_MetTimeOfDay.SelectedIndex = c2.Met_TimeOfDay; + TB_MetLevel.Text = c2.MetLevel.ToString(); + CB_MetLocation.SelectedValue = (int)c2.MetLocation; + CB_MetTimeOfDay.SelectedIndex = c2.MetTimeOfDay; // Attempt to detect language CB_Language.SelectedValue = pk2.GuessedLanguage(); @@ -59,9 +59,9 @@ private GBPKM PreparePK2() SaveMisc1(pk2); SaveMisc2(pk2); - c2.Met_Level = Util.ToInt32(TB_MetLevel.Text); - c2.Met_Location = WinFormsUtil.GetIndex(CB_MetLocation); - c2.Met_TimeOfDay = CB_MetTimeOfDay.SelectedIndex; + c2.MetLevel = (byte)Util.ToInt32(TB_MetLevel.Text); + c2.MetLocation = (ushort)WinFormsUtil.GetIndex(CB_MetLocation); + c2.MetTimeOfDay = CB_MetTimeOfDay.SelectedIndex; SavePartyStats(pk2); pk2.FixMoves(); diff --git a/PKHeX.WinForms/Controls/PKM Editor/EntityInstructionBuilder.cs b/PKHeX.WinForms/Controls/PKM Editor/EntityInstructionBuilder.cs index 333a9aa54..43f5407ed 100644 --- a/PKHeX.WinForms/Controls/PKM Editor/EntityInstructionBuilder.cs +++ b/PKHeX.WinForms/Controls/PKM Editor/EntityInstructionBuilder.cs @@ -36,7 +36,7 @@ private void CB_Format_SelectedIndexChanged(object sender, EventArgs e) if (currentFormat == CB_Format.SelectedIndex) return; - int format = CB_Format.SelectedIndex; + byte format = (byte)CB_Format.SelectedIndex; CB_Property.Items.Clear(); CB_Property.Items.AddRange(BatchEditing.Properties[format]); CB_Property.SelectedIndex = 0; diff --git a/PKHeX.WinForms/Controls/PKM Editor/GenderToggle.cs b/PKHeX.WinForms/Controls/PKM Editor/GenderToggle.cs index 308e0a448..0913c76f7 100644 --- a/PKHeX.WinForms/Controls/PKM Editor/GenderToggle.cs +++ b/PKHeX.WinForms/Controls/PKM Editor/GenderToggle.cs @@ -14,9 +14,9 @@ public partial class GenderToggle : UserControl, IGenderToggle private string? InitialAccessible; public static int FocusBorderDeflate { get; set; } - public int Gender + public byte Gender { - get => Value; + get => (byte)Value; set => Value = SetGender(value); } @@ -118,7 +118,7 @@ public interface IGenderToggle /// /// Get or set the value the control displays. /// - int Gender { get; set; } + byte Gender { get; set; } /// /// Manually flips the gender state if possible. diff --git a/PKHeX.WinForms/Controls/PKM Editor/IMainEditor.cs b/PKHeX.WinForms/Controls/PKM Editor/IMainEditor.cs index ac28435e0..ebb782177 100644 --- a/PKHeX.WinForms/Controls/PKM Editor/IMainEditor.cs +++ b/PKHeX.WinForms/Controls/PKM Editor/IMainEditor.cs @@ -9,7 +9,7 @@ public interface IMainEditor : IPKMView SaveFile RequestSaveFile { get; } void UpdateIVsGB(bool skipForm); - void ChangeNature(int newNature); + void ChangeNature(Nature newNature); } [Flags] diff --git a/PKHeX.WinForms/Controls/PKM Editor/LoadSave.cs b/PKHeX.WinForms/Controls/PKM Editor/LoadSave.cs index 2cfc5b6da..60a292d00 100644 --- a/PKHeX.WinForms/Controls/PKM Editor/LoadSave.cs +++ b/PKHeX.WinForms/Controls/PKM Editor/LoadSave.cs @@ -38,38 +38,38 @@ private void SaveSpeciesLevelEXP(PKM pk) { pk.Species = (ushort)WinFormsUtil.GetIndex(CB_Species); pk.EXP = Util.ToUInt32(TB_EXP.Text); - pk.Stat_Level = Math.Max(1, Util.ToInt32(TB_Level.Text)); + pk.Stat_Level = (byte)Math.Max(1, Util.ToInt32(TB_Level.Text)); } private void LoadOT(PKM pk) { GB_OT.BackgroundImage = null; // clear the Current Handler indicator just in case we switched formats. - TB_OT.Text = pk.OT_Name; - UC_OTGender.Gender = pk.OT_Gender & 1; + TB_OT.Text = pk.OriginalTrainerName; + UC_OTGender.Gender = (byte)(pk.OriginalTrainerGender & 1); } private void SaveOT(PKM pk) { - pk.OT_Name = TB_OT.Text; - pk.OT_Gender = UC_OTGender.Gender; + pk.OriginalTrainerName = TB_OT.Text; + pk.OriginalTrainerGender = UC_OTGender.Gender; } - private void LoadPKRS(PKM pk) + private void LoadPokerus(PKM pk) { - var infected = pk.PKRS_Infected; - var cured = pk.PKRS_Cured; + var infected = pk.IsPokerusInfected; + var cured = pk.IsPokerusCured; CHK_Infected.Checked = Label_PKRS.Visible = CB_PKRSStrain.Visible = infected; Label_PKRSdays.Visible = CB_PKRSDays.Visible = !cured && infected; CHK_Cured.Checked = cured; - ChangePKRSstrainDropDownLists(CB_PKRSStrain.SelectedIndex, pk.PKRS_Strain, 0); - LoadClamp(CB_PKRSStrain, pk.PKRS_Strain); - LoadClamp(CB_PKRSDays, pk.PKRS_Days); // clamp to valid day values for the current strain + ChangePKRSstrainDropDownLists(CB_PKRSStrain.SelectedIndex, pk.PokerusStrain, 0); + LoadClamp(CB_PKRSStrain, pk.PokerusStrain); + LoadClamp(CB_PKRSDays, pk.PokerusDays); // clamp to valid day values for the current strain } - private void SavePKRS(PKM pk) + private void SavePokerus(PKM pk) { - pk.PKRS_Days = CB_PKRSDays.SelectedIndex; - pk.PKRS_Strain = CB_PKRSStrain.SelectedIndex; + pk.PokerusDays = CB_PKRSDays.SelectedIndex; + pk.PokerusStrain = CB_PKRSStrain.SelectedIndex; } private void LoadIVs(PKM pk) @@ -197,7 +197,7 @@ private void SaveMisc1(PKM pk) private void LoadMisc2(PKM pk) { - LoadPKRS(pk); + LoadPokerus(pk); CHK_IsEgg.Checked = pk.IsEgg; CB_HeldItem.SelectedValue = pk.HeldItem; LoadClamp(CB_Form, pk.Form); @@ -212,41 +212,41 @@ private void LoadMisc2(PKM pk) private void ReloadToFriendshipTextBox(PKM pk) { // Show OT friendship always if it is an egg. - var fs = (pk.IsEgg ? pk.OT_Friendship : pk.CurrentFriendship); + var fs = (pk.IsEgg ? pk.OriginalTrainerFriendship : pk.CurrentFriendship); TB_Friendship.Text = fs.ToString(); } private void SaveMisc2(PKM pk) { - SavePKRS(pk); + SavePokerus(pk); pk.IsEgg = CHK_IsEgg.Checked; pk.HeldItem = WinFormsUtil.GetIndex(CB_HeldItem); pk.Form = (byte)(CB_Form.Enabled ? CB_Form.SelectedIndex & 0x1F : 0); if (Entity is IFormArgument f) FA_Form.SaveArgument(f); - var friendship = Util.ToInt32(TB_Friendship.Text); + var friendship = (byte)Util.ToInt32(TB_Friendship.Text); UpdateFromFriendshipTextBox(pk, friendship); } - private static void UpdateFromFriendshipTextBox(PKM pk, int friendship) + private static void UpdateFromFriendshipTextBox(PKM pk, byte friendship) { if (pk.IsEgg) - pk.OT_Friendship = friendship; + pk.OriginalTrainerFriendship = friendship; else pk.CurrentFriendship = friendship; } private void LoadMisc3(PKM pk) { - TB_PID.Text = $"{pk.PID:X8}"; + TB_PID.Text = pk.PID.ToString("X8"); UC_Gender.Gender = pk.Gender; - CB_Nature.SelectedValue = pk.Nature; + CB_Nature.SelectedValue = (int)pk.Nature; CB_Language.SelectedValue = pk.Language; - CB_GameOrigin.SelectedValue = pk.Version; - CB_Ball.SelectedValue = pk.Ball; - CB_MetLocation.SelectedValue = pk.Met_Location; - TB_MetLevel.Text = pk.Met_Level.ToString(); + CB_GameOrigin.SelectedValue = (int)pk.Version; + CB_Ball.SelectedValue = (int)pk.Ball; + CB_MetLocation.SelectedValue = (int)pk.MetLocation; + TB_MetLevel.Text = pk.MetLevel.ToString(); CHK_Fateful.Checked = pk.FatefulEncounter; if (pk is IContestStatsReadOnly s) @@ -263,18 +263,18 @@ private void LoadMisc3(PKM pk) private void SaveMisc3(PKM pk) { pk.PID = Util.GetHexValue(TB_PID.Text); - pk.Nature = WinFormsUtil.GetIndex(CB_Nature); + pk.Nature = (Nature)WinFormsUtil.GetIndex(CB_Nature); pk.Gender = UC_Gender.Gender; if (pk is IContestStats s) Contest.CopyContestStatsTo(s); pk.FatefulEncounter = CHK_Fateful.Checked; - pk.Ball = WinFormsUtil.GetIndex(CB_Ball); - pk.Version = WinFormsUtil.GetIndex(CB_GameOrigin); - pk.Language = WinFormsUtil.GetIndex(CB_Language); - pk.Met_Level = Util.ToInt32(TB_MetLevel.Text); - pk.Met_Location = WinFormsUtil.GetIndex(CB_MetLocation); + pk.Ball = (byte)WinFormsUtil.GetIndex(CB_Ball); + pk.Version = (GameVersion)WinFormsUtil.GetIndex(CB_GameOrigin); + pk.Language = (byte)WinFormsUtil.GetIndex(CB_Language); + pk.MetLevel = (byte)Util.ToInt32(TB_MetLevel.Text); + pk.MetLocation = (ushort)WinFormsUtil.GetIndex(CB_MetLocation); } private void LoadMisc4(PKM pk) @@ -291,7 +291,7 @@ private void LoadMisc4(PKM pk) CHK_AsEgg.Checked = GB_EggConditions.Enabled = true; CAL_EggDate.Value = pk.EggMetDate?.ToDateTime(new TimeOnly()) ?? new(2000, 1, 1); } - CB_EggLocation.SelectedValue = pk.Egg_Location; + CB_EggLocation.SelectedValue = (int)pk.EggLocation; } private void SaveMisc4(PKM pk) @@ -299,16 +299,16 @@ private void SaveMisc4(PKM pk) if (CHK_AsEgg.Checked) // If encountered as an egg, load the Egg Met data from fields. { pk.EggMetDate = DateOnly.FromDateTime(CAL_EggDate.Value); - pk.Egg_Location = WinFormsUtil.GetIndex(CB_EggLocation); + pk.EggLocation = (ushort)WinFormsUtil.GetIndex(CB_EggLocation); } else // Default Dates { pk.EggMetDate = null; // clear - pk.Egg_Location = LocationEdits.GetNoneLocation(pk); + pk.EggLocation = LocationEdits.GetNoneLocation(pk); } // Met Data - if (pk.IsEgg && pk.Met_Location == LocationEdits.GetNoneLocation(pk)) // If still an egg, it has no hatch location/date. Zero it! + if (pk.IsEgg && pk.MetLocation == LocationEdits.GetNoneLocation(pk)) // If still an egg, it has no hatch location/date. Zero it! pk.MetDate = null; // clear else pk.MetDate = DateOnly.FromDateTime(CAL_MetDate.Value); @@ -318,7 +318,7 @@ private void SaveMisc4(PKM pk) private void LoadMisc6(PKM pk) { - TB_EC.Text = $"{pk.EncryptionConstant:X8}"; + TB_EC.Text = pk.EncryptionConstant.ToString("X8"); DEV_Ability.SelectedValue = pk.Ability; // with some simple error handling @@ -365,8 +365,8 @@ private void SaveGeolocation(IRegionOrigin pk) private void LoadHandlingTrainer(PKM pk) { - var handler = pk.HT_Name; - int gender = pk.HT_Gender & 1; + var handler = pk.HandlingTrainerName; + byte gender = (byte)(pk.HandlingTrainerGender & 1); TB_HT.Text = handler; UC_HTGender.Gender = gender; @@ -399,8 +399,8 @@ private void UpadteHandlingTrainerBackground(int handler) private void SaveHandlingTrainer(PKM pk) { - pk.HT_Name = TB_HT.Text; - pk.HT_Gender = UC_HTGender.Gender; + pk.HandlingTrainerName = TB_HT.Text; + pk.HandlingTrainerGender = UC_HTGender.Gender; } private void LoadAbility4(PKM pk) @@ -426,48 +426,48 @@ private static int GetAbilityIndex4(PKM pk) private void LoadMisc8(PK8 pk8) { - CB_StatNature.SelectedValue = pk8.StatNature; + CB_StatNature.SelectedValue = (int)pk8.StatNature; LoadClamp(Stats.CB_DynamaxLevel, pk8.DynamaxLevel); Stats.CHK_Gigantamax.Checked = pk8.CanGigantamax; - CB_HTLanguage.SelectedValue = (int)pk8.HT_Language; + CB_HTLanguage.SelectedValue = (int)pk8.HandlingTrainerLanguage; TB_HomeTracker.Text = pk8.Tracker.ToString("X16"); CB_BattleVersion.SelectedValue = (int)pk8.BattleVersion; } private void SaveMisc8(PK8 pk8) { - pk8.StatNature = WinFormsUtil.GetIndex(CB_StatNature); + pk8.StatNature = (Nature)WinFormsUtil.GetIndex(CB_StatNature); pk8.DynamaxLevel = (byte)Math.Max(0, Stats.CB_DynamaxLevel.SelectedIndex); pk8.CanGigantamax = Stats.CHK_Gigantamax.Checked; - pk8.HT_Language = (byte)WinFormsUtil.GetIndex(CB_HTLanguage); - pk8.BattleVersion = (byte)WinFormsUtil.GetIndex(CB_BattleVersion); + pk8.HandlingTrainerLanguage = (byte)WinFormsUtil.GetIndex(CB_HTLanguage); + pk8.BattleVersion = (GameVersion)WinFormsUtil.GetIndex(CB_BattleVersion); } private void LoadMisc8(PB8 pk8) { - CB_StatNature.SelectedValue = pk8.StatNature; + CB_StatNature.SelectedValue = (int)pk8.StatNature; LoadClamp(Stats.CB_DynamaxLevel, pk8.DynamaxLevel); Stats.CHK_Gigantamax.Checked = pk8.CanGigantamax; - CB_HTLanguage.SelectedValue = (int)pk8.HT_Language; + CB_HTLanguage.SelectedValue = (int)pk8.HandlingTrainerLanguage; TB_HomeTracker.Text = pk8.Tracker.ToString("X16"); CB_BattleVersion.SelectedValue = (int)pk8.BattleVersion; } private void SaveMisc8(PB8 pk8) { - pk8.StatNature = WinFormsUtil.GetIndex(CB_StatNature); + pk8.StatNature = (Nature)WinFormsUtil.GetIndex(CB_StatNature); pk8.DynamaxLevel = (byte)Math.Max(0, Stats.CB_DynamaxLevel.SelectedIndex); pk8.CanGigantamax = Stats.CHK_Gigantamax.Checked; - pk8.HT_Language = (byte)WinFormsUtil.GetIndex(CB_HTLanguage); - pk8.BattleVersion = (byte)WinFormsUtil.GetIndex(CB_BattleVersion); + pk8.HandlingTrainerLanguage = (byte)WinFormsUtil.GetIndex(CB_HTLanguage); + pk8.BattleVersion = (GameVersion)WinFormsUtil.GetIndex(CB_BattleVersion); } private void LoadMisc8(PA8 pk8) { - CB_StatNature.SelectedValue = pk8.StatNature; + CB_StatNature.SelectedValue = (int)pk8.StatNature; LoadClamp(Stats.CB_DynamaxLevel, pk8.DynamaxLevel); Stats.CHK_Gigantamax.Checked = pk8.CanGigantamax; - CB_HTLanguage.SelectedValue = (int)pk8.HT_Language; + CB_HTLanguage.SelectedValue = (int)pk8.HandlingTrainerLanguage; TB_HomeTracker.Text = pk8.Tracker.ToString("X16"); CB_BattleVersion.SelectedValue = (int)pk8.BattleVersion; Stats.CHK_IsAlpha.Checked = pk8.IsAlpha; @@ -477,11 +477,11 @@ private void LoadMisc8(PA8 pk8) private void SaveMisc8(PA8 pk8) { - pk8.StatNature = WinFormsUtil.GetIndex(CB_StatNature); + pk8.StatNature = (Nature)WinFormsUtil.GetIndex(CB_StatNature); pk8.DynamaxLevel = (byte)Math.Max(0, Stats.CB_DynamaxLevel.SelectedIndex); pk8.CanGigantamax = Stats.CHK_Gigantamax.Checked; - pk8.HT_Language = (byte)WinFormsUtil.GetIndex(CB_HTLanguage); - pk8.BattleVersion = (byte)WinFormsUtil.GetIndex(CB_BattleVersion); + pk8.HandlingTrainerLanguage = (byte)WinFormsUtil.GetIndex(CB_HTLanguage); + pk8.BattleVersion = (GameVersion)WinFormsUtil.GetIndex(CB_BattleVersion); pk8.IsAlpha = Stats.CHK_IsAlpha.Checked; pk8.IsNoble = Stats.CHK_IsNoble.Checked; pk8.AlphaMove = (ushort)WinFormsUtil.GetIndex(CB_AlphaMastered); @@ -489,8 +489,8 @@ private void SaveMisc8(PA8 pk8) private void LoadMisc9(PK9 pk9) { - CB_StatNature.SelectedValue = pk9.StatNature; - CB_HTLanguage.SelectedValue = (int)pk9.HT_Language; + CB_StatNature.SelectedValue = (int)pk9.StatNature; + CB_HTLanguage.SelectedValue = (int)pk9.HandlingTrainerLanguage; TB_HomeTracker.Text = pk9.Tracker.ToString("X16"); CB_BattleVersion.SelectedValue = (int)pk9.BattleVersion; Stats.CB_TeraTypeOriginal.SelectedValue = (int)pk9.TeraTypeOriginal; @@ -500,9 +500,9 @@ private void LoadMisc9(PK9 pk9) private void SaveMisc9(PK9 pk9) { - pk9.StatNature = WinFormsUtil.GetIndex(CB_StatNature); - pk9.HT_Language = (byte)WinFormsUtil.GetIndex(CB_HTLanguage); - pk9.BattleVersion = (byte)WinFormsUtil.GetIndex(CB_BattleVersion); + pk9.StatNature = (Nature)WinFormsUtil.GetIndex(CB_StatNature); + pk9.HandlingTrainerLanguage = (byte)WinFormsUtil.GetIndex(CB_HTLanguage); + pk9.BattleVersion = (GameVersion)WinFormsUtil.GetIndex(CB_BattleVersion); pk9.TeraTypeOriginal = (MoveType)WinFormsUtil.GetIndex(Stats.CB_TeraTypeOriginal); pk9.TeraTypeOverride = (MoveType)WinFormsUtil.GetIndex(Stats.CB_TeraTypeOverride); pk9.Obedience_Level = (byte)Util.ToInt32(TB_ObedienceLevel.Text); diff --git a/PKHeX.WinForms/Controls/PKM Editor/PKMEditor.Designer.cs b/PKHeX.WinForms/Controls/PKM Editor/PKMEditor.Designer.cs index da1b29a2f..63a691a0c 100644 --- a/PKHeX.WinForms/Controls/PKM Editor/PKMEditor.Designer.cs +++ b/PKHeX.WinForms/Controls/PKM Editor/PKMEditor.Designer.cs @@ -2095,12 +2095,12 @@ private void InitializeComponent() // Contest // Contest.Anchor = ((global::System.Windows.Forms.AnchorStyles)(((global::System.Windows.Forms.AnchorStyles.Bottom) | (global::System.Windows.Forms.AnchorStyles.Left)) | (global::System.Windows.Forms.AnchorStyles.Right))); - Contest.CNT_Beauty = ((global::System.Byte)(0)); - Contest.CNT_Cool = ((global::System.Byte)(0)); - Contest.CNT_Cute = ((global::System.Byte)(0)); - Contest.CNT_Sheen = ((global::System.Byte)(0)); - Contest.CNT_Smart = ((global::System.Byte)(0)); - Contest.CNT_Tough = ((global::System.Byte)(0)); + Contest.ContestBeauty = ((global::System.Byte)(0)); + Contest.ContestCool = ((global::System.Byte)(0)); + Contest.ContestCute = ((global::System.Byte)(0)); + Contest.ContestSheen = ((global::System.Byte)(0)); + Contest.ContestSmart = ((global::System.Byte)(0)); + Contest.ContestTough = ((global::System.Byte)(0)); Contest.Location = (new global::System.Drawing.Point(4, 328)); Contest.Margin = (new global::System.Windows.Forms.Padding(0)); Contest.Name = ("Contest"); diff --git a/PKHeX.WinForms/Controls/PKM Editor/PKMEditor.cs b/PKHeX.WinForms/Controls/PKM Editor/PKMEditor.cs index 516545ae9..8d1912285 100644 --- a/PKHeX.WinForms/Controls/PKM Editor/PKMEditor.cs +++ b/PKHeX.WinForms/Controls/PKM Editor/PKMEditor.cs @@ -49,14 +49,14 @@ public PKMEditor() ValidatedControls = [ new(Moves, _ => true, z => Criteria(((MoveChoice)z).CB_Move)), - new(new[] {CB_Species}, _ => true, Criteria), - new(new[] {CB_HeldItem}, pk => pk.Format >= 2, Criteria), - new(new[] {CB_Ability, CB_Nature, CB_MetLocation, CB_Ball}, pk => pk.Format >= 3, Criteria), - new(new[] {CB_EggLocation}, pk => pk.Format >= 4, Criteria), - new(new[] {CB_Country, CB_SubRegion}, pk => pk is PK6 or PK7, Criteria), + new([CB_Species], _ => true, Criteria), + new([CB_HeldItem], pk => pk.Format >= 2, Criteria), + new([CB_Ability, CB_Nature, CB_MetLocation, CB_Ball], pk => pk.Format >= 3, Criteria), + new([CB_EggLocation], pk => pk.Format >= 4, Criteria), + new([CB_Country, CB_SubRegion], pk => pk is PK6 or PK7, Criteria), new(Relearn, pk => pk.Format >= 6, Criteria), - new(new[] {CB_StatNature}, pk => pk.Format >= 8, Criteria), - new(new[] {CB_AlphaMastered}, pk => pk is PA8, Criteria), + new([CB_StatNature], pk => pk.Format >= 8, Criteria), + new([CB_AlphaMastered], pk => pk is PA8, Criteria), ]; foreach (var c in WinFormsUtil.GetAllControlsOfType(this)) @@ -390,11 +390,11 @@ private void SetDetailsOT(ITrainerInfo tr) // Get Save Information TB_OT.Text = tr.OT; - UC_OTGender.Gender = tr.Gender & 1; + UC_OTGender.Gender = (byte)(tr.Gender & 1); TID_Trainer.LoadInfo(tr); - if (tr.Game >= 0) - CB_GameOrigin.SelectedValue = tr.Game; + if (tr.Version != 0) + CB_GameOrigin.SelectedValue = (int)tr.Version; var lang = tr.Language; if (lang <= 0) @@ -408,8 +408,8 @@ private void SetDetailsOT(ITrainerInfo tr) } // Copy OT trash bytes for sensitive games (Gen1/2) - if (tr is SAV1 s1 && Entity is PK1 p1) s1.OT_Trash.CopyTo(p1.OT_Trash); - else if (tr is SAV2 s2 && Entity is PK2 p2) s2.OT_Trash.CopyTo(p2.OT_Trash); + if (tr is SAV1 s1 && Entity is PK1 p1) s1.OriginalTrainerTrash.CopyTo(p1.OriginalTrainerTrash); + else if (tr is SAV2 s2 && Entity is PK2 p2) s2.OriginalTrainerTrash.CopyTo(p2.OriginalTrainerTrash); UpdateNickname(this, EventArgs.Empty); } @@ -423,7 +423,7 @@ private void SetDetailsHT(ITrainerInfo tr) if (!tr.IsOriginalHandler(Entity, false)) { TB_HT.Text = trainer; - UC_HTGender.Gender = tr.Gender & 1; + UC_HTGender.Gender = (byte)(tr.Gender & 1); if (Entity is IHandlerLanguage) CB_HTLanguage.SelectedValue = tr.Language; } @@ -472,13 +472,13 @@ private void SetAbilityList() if (Entity.Format > 3 && FieldsLoaded) // has forms Entity.Form = (byte)CB_Form.SelectedIndex; // update pk field for form specific abilities - int abil = CB_Ability.SelectedIndex; + int ability = CB_Ability.SelectedIndex; bool tmp = FieldsLoaded; FieldsLoaded = false; var items = GameInfo.FilteredSources.GetAbilityList(Entity); CB_Ability.DataSource = items; - CB_Ability.SelectedIndex = Math.Clamp(abil, 0, items.Count - 1); // restore original index if available + CB_Ability.SelectedIndex = Math.Clamp(ability, 0, items.Count - 1); // restore original index if available FieldsLoaded = tmp; } @@ -586,8 +586,8 @@ private void ClickGender(object sender, EventArgs e) } else if (Entity.Format <= 4) { - Entity.Version = WinFormsUtil.GetIndex(CB_GameOrigin); - Entity.Nature = WinFormsUtil.GetIndex(CB_Nature); + Entity.Version = (GameVersion)WinFormsUtil.GetIndex(CB_GameOrigin); + Entity.Nature = (Nature)WinFormsUtil.GetIndex(CB_Nature); Entity.Form = (byte)CB_Form.SelectedIndex; Entity.SetPIDGender(gender); @@ -640,7 +640,7 @@ private void ClickFavorite(object sender, EventArgs e) private void ClickBall(object sender, EventArgs e) { - Entity.Ball = WinFormsUtil.GetIndex(CB_Ball); + Entity.Ball = (byte)WinFormsUtil.GetIndex(CB_Ball); if ((ModifierKeys & Keys.Alt) != 0) { CB_Ball.SelectedValue = (int)Ball.Poke; @@ -648,15 +648,15 @@ private void ClickBall(object sender, EventArgs e) } if ((ModifierKeys & Keys.Shift) != 0) { - CB_Ball.SelectedValue = BallApplicator.ApplyBallLegalByColor(Entity); + CB_Ball.SelectedValue = (int)BallApplicator.ApplyBallLegalByColor(Entity); return; } using var frm = new BallBrowser(); frm.LoadBalls(Entity); frm.ShowDialog(); - if (frm.BallChoice >= 0) - CB_Ball.SelectedValue = frm.BallChoice; + if (frm.WasBallChosen) + CB_Ball.SelectedValue = (int)frm.BallChoice; } private void ClickMetLocation(object sender, EventArgs e) @@ -680,7 +680,7 @@ private void ClickGT(object? sender, EventArgs e) if (!GB_nOT.Visible) return; - int handler = 0; + byte handler = 0; if (sender == GB_OT) handler = 0; else if (TB_HT.Text.Length > 0) @@ -690,10 +690,10 @@ private void ClickGT(object? sender, EventArgs e) private void ChangeHandlerIndex(object sender, EventArgs e) { - UpdateHandlerSelected(CB_Handler.SelectedIndex & 1); + UpdateHandlerSelected((byte)(CB_Handler.SelectedIndex & 1)); } - private void UpdateHandlerSelected(int handler) + private void UpdateHandlerSelected(byte handler) { Entity.CurrentHandler = handler; UpadteHandlingTrainerBackground(Entity.CurrentHandler); @@ -818,32 +818,32 @@ private static string GetMoveListPrint(Span moves, ReadOnlySpan private bool SetSuggestedMetLocation(bool silent = false) { var encounter = EncounterSuggestion.GetSuggestedMetInfo(Entity); - if (encounter == null || (Entity.Format >= 3 && encounter.Location < 0)) + if (encounter == null || (Entity.Format >= 3 && encounter.Location == 0)) { if (!silent) WinFormsUtil.Alert(MsgPKMSuggestionNone); return false; } - int level = encounter.LevelMin; - int location = encounter.Location; - int minlvl = EncounterSuggestion.GetLowestLevel(Entity, encounter.LevelMin); - if (minlvl == 0) - minlvl = level; + var level = encounter.LevelMin; + int minLevel = EncounterSuggestion.GetLowestLevel(Entity, level); + if (minLevel == 0) + minLevel = level; + ushort location = encounter.Location; if (Entity.Format < 3 && encounter.Encounter is { } x && !x.Version.Contains(GameVersion.C)) location = 0; - if (Entity.CurrentLevel >= minlvl && Entity.Met_Level == level && Entity.Met_Location == location) + if (Entity.CurrentLevel >= minLevel && Entity.MetLevel == level && Entity.MetLocation == location) { if (!encounter.HasGroundTile(Entity.Format) || WinFormsUtil.GetIndex(CB_GroundTile) == (int)encounter.GetSuggestedGroundTile()) return false; } - if (minlvl < level) - minlvl = level; + if (minLevel < level) + minLevel = level; if (!silent) { - var suggestions = EntitySuggestionUtil.GetMetLocationSuggestionMessage(Entity, level, location, minlvl, encounter.Encounter); + var suggestions = EntitySuggestionUtil.GetMetLocationSuggestionMessage(Entity, level, location, minLevel, encounter.Encounter); if (suggestions.Count <= 1) // no suggestion return false; @@ -854,9 +854,9 @@ private bool SetSuggestedMetLocation(bool silent = false) if (Entity.Format >= 3) { - Entity.Met_Location = location; + Entity.MetLocation = location; TB_MetLevel.Text = encounter.GetSuggestedMetLevel(Entity).ToString(); - CB_MetLocation.SelectedValue = location; + CB_MetLocation.SelectedValue = (int)location; if (encounter.HasGroundTile(Entity.Format)) CB_GroundTile.SelectedValue = (int)encounter.GetSuggestedGroundTile(); @@ -866,9 +866,9 @@ private bool SetSuggestedMetLocation(bool silent = false) } else { - Entity.Met_Location = location; + Entity.MetLocation = location; TB_MetLevel.Text = encounter.GetSuggestedMetLevel(Entity).ToString(); - CB_MetLocation.SelectedValue = location; + CB_MetLocation.SelectedValue = (int)location; var timeIndex = 0; if (encounter.Encounter is { } enc && location is < 253 and not 0) { @@ -880,8 +880,8 @@ private bool SetSuggestedMetLocation(bool silent = false) CB_MetTimeOfDay.SelectedIndex = timeIndex; } - if (Entity.CurrentLevel < minlvl) - TB_Level.Text = minlvl.ToString(); + if (Entity.CurrentLevel < minLevel) + TB_Level.Text = minLevel.ToString(); return true; } @@ -900,7 +900,7 @@ public void UpdateIVsGB(bool skipForm) private void UpdateBall(object sender, EventArgs e) { - PB_Ball.Image = SpriteUtil.GetBallSprite(WinFormsUtil.GetIndex(CB_Ball)); + PB_Ball.Image = SpriteUtil.GetBallSprite((byte)WinFormsUtil.GetIndex(CB_Ball)); } private void UpdateEXPLevel(object sender, EventArgs e) @@ -927,9 +927,8 @@ private void UpdateEXPLevel(object sender, EventArgs e) else { // Change the XP - int input = Util.ToInt32(TB_Level.Text); - int level = Math.Max(1, Math.Min(input, 100)); - + var input = Util.ToInt32(TB_Level.Text); + var level = (byte)Math.Clamp(input, 1, 100); if (input != level && !string.IsNullOrWhiteSpace(TB_Level.Text)) TB_Level.Text = level.ToString(); TB_EXP.Text = Experience.GetEXP(level, Entity.PersonalInfo.EXPGrowth).ToString(); @@ -950,8 +949,8 @@ private void UpdateRandomPID(object sender, EventArgs e) if (sender == UC_Gender) Entity.SetPIDGender(Entity.Gender); - else if (sender == CB_Nature && Entity.Nature != WinFormsUtil.GetIndex(CB_Nature)) - Entity.SetPIDNature(WinFormsUtil.GetIndex(CB_Nature)); + else if (sender == CB_Nature && Entity.Nature != (Nature)WinFormsUtil.GetIndex(CB_Nature)) + Entity.SetPIDNature((Nature)WinFormsUtil.GetIndex(CB_Nature)); else if (sender == BTN_RerollPID) Entity.SetPIDGender(Entity.Gender); else if (sender == CB_Ability && CB_Ability.SelectedIndex != Entity.PIDAbility && Entity.PIDAbility > -1) @@ -982,7 +981,7 @@ private void Update255_MTB(object sender, EventArgs e) tb.Text = "255"; if (sender == TB_Friendship && int.TryParse(TB_Friendship.Text, out var value)) { - UpdateFromFriendshipTextBox(Entity, value); + UpdateFromFriendshipTextBox(Entity, (byte)value); UpdateStats(); } } @@ -1028,7 +1027,7 @@ private void UpdateForm(object sender, EventArgs e) { if (CB_Form.Items.Count == 2) // actually M/F; Pumpkaboo forms in German are S,M,L,XL { - Entity.Gender = CB_Form.SelectedIndex; + Entity.Gender = (byte)CB_Form.SelectedIndex; UC_Gender.Gender = Entity.GetSaneGender(); } } @@ -1061,7 +1060,7 @@ private void UpdatePKRSstrain(object sender, EventArgs e) if (!FieldsLoaded) return; - // Change the PKRS Days to the legal bounds. + // Change the PokerusState Days to the legal bounds. ChangePKRSstrainDropDownLists(-1, CB_PKRSStrain.SelectedIndex, CB_PKRSDays.SelectedIndex); } @@ -1202,7 +1201,7 @@ private void UpdateOriginGame(object sender, EventArgs e) { CheckMetLocationChange(version, Entity.Context); if (FieldsLoaded) - Entity.Version = (byte)version; + Entity.Version = version; } // Visibility logic for Gen 4 ground tile; only show for Gen 4 Pokémon. @@ -1258,13 +1257,13 @@ static int GetWidth(IReadOnlyCollection items, Font f) if (FieldsLoaded) { SetMarkings(); // Set/Remove the Nativity marking when gamegroup changes too - int metLoc = EncounterSuggestion.GetSuggestedTransferLocation(Entity); - int eggLoc = CHK_AsEgg.Checked + var metLoc = EncounterSuggestion.TryGetSuggestedTransferLocation(Entity); + var eggLoc = CHK_AsEgg.Checked ? EncounterSuggestion.GetSuggestedEncounterEggLocationEgg(Entity, true) : LocationEdits.GetNoneLocation(Entity); - CB_MetLocation.SelectedValue = Math.Max(0, metLoc); - CB_EggLocation.SelectedValue = eggLoc; + CB_MetLocation.SelectedValue = (int)Math.Max((ushort)0, metLoc); + CB_EggLocation.SelectedValue = (int)eggLoc; } else { @@ -1297,16 +1296,16 @@ private void UpdateExtraByteIndex(object sender, EventArgs e) TB_ExtraByte.Text = Entity.Data[offset].ToString(); } - public void ChangeNature(int newNature) + public void ChangeNature(Nature newNature) { if (Entity.Format < 3) return; var cb = Entity.Format >= 8 ? CB_StatNature : CB_Nature; - cb.SelectedValue = newNature; + cb.SelectedValue = (int)newNature; } - private void UpdateNatureModification(ComboBox cb, int nature) + private void UpdateNatureModification(ComboBox cb, Nature nature) { string text = Stats.UpdateNatureModification(nature); NatureTip.SetToolTip(cb, text); @@ -1389,17 +1388,17 @@ private void UpdateNicknameClick(object sender, MouseEventArgs e) if (tb == TB_Nickname) { Entity.Nickname = tb.Text; - trash = Entity.Nickname_Trash; + trash = Entity.NicknameTrash; } else if (tb == TB_OT) { - Entity.OT_Name = tb.Text; - trash = Entity.OT_Trash; + Entity.OriginalTrainerName = tb.Text; + trash = Entity.OriginalTrainerTrash; } else if (tb == TB_HT) { - Entity.HT_Name = tb.Text; - trash = Entity.HT_Trash; + Entity.HandlingTrainerName = tb.Text; + trash = Entity.HandlingTrainerTrash; } else { @@ -1440,7 +1439,7 @@ private void UpdateIsEgg(object sender, EventArgs e) return; if (Entity.Format == 3 && CHK_IsEgg.Checked) - Entity.OT_Name = TB_OT.Text; // going to be remapped + Entity.OriginalTrainerName = TB_OT.Text; // going to be remapped Entity.IsEgg = CHK_IsEgg.Checked; if (CHK_IsEgg.Checked) @@ -1461,12 +1460,12 @@ private void UpdateIsEgg(object sender, EventArgs e) var loc = isTraded ? Locations.TradedEggLocation(sav.Generation, sav.Version) : LocationEdits.GetNoneLocation(Entity); - CB_MetLocation.SelectedValue = loc; + CB_MetLocation.SelectedValue = (int)loc; } else if (Entity.Format == 3) { CB_Language.SelectedValue = Entity.Language; // JPN - TB_OT.Text = Entity.OT_Name; + TB_OT.Text = Entity.OriginalTrainerName; } CHK_NicknamedFlag.Checked = EggStateLegality.IsNicknameFlagSet(Entity); @@ -1496,7 +1495,7 @@ private void UpdateIsEgg(object sender, EventArgs e) else { CAL_MetDate.Value = CAL_EggDate.Value; - CB_MetLocation.SelectedValue = EncounterSuggestion.GetSuggestedEggMetLocation(Entity); + CB_MetLocation.SelectedValue = (int)EncounterSuggestion.GetSuggestedEggMetLocation(Entity); } var nick = SpeciesName.GetEggName(WinFormsUtil.GetIndex(CB_Language), Entity.Format); @@ -1518,14 +1517,14 @@ private void UpdateMetAsEgg(object sender, EventArgs e) CAL_EggDate.Value = DateTime.Now; - bool isTradedEgg = Entity.IsEgg && Entity.Version != (int)RequestSaveFile.Version; + bool isTradedEgg = Entity.IsEgg && Entity.Version != RequestSaveFile.Version; CB_EggLocation.SelectedValue = EncounterSuggestion.GetSuggestedEncounterEggLocationEgg(Entity, isTradedEgg); return; } // Remove egg met data CHK_IsEgg.Checked = false; CAL_EggDate.Value = new DateTime(2000, 01, 01); - CB_EggLocation.SelectedValue = LocationEdits.GetNoneLocation(Entity); + CB_EggLocation.SelectedValue = (int)LocationEdits.GetNoneLocation(Entity); UpdateLegality(); } @@ -1539,10 +1538,10 @@ private void UpdateShinyPID(object sender, EventArgs e) private void UpdateShiny(bool changePID) { Entity.PID = Util.GetHexValue(TB_PID.Text); - Entity.Nature = WinFormsUtil.GetIndex(CB_Nature); + Entity.Nature = (Nature)WinFormsUtil.GetIndex(CB_Nature); Entity.Gender = UC_Gender.Gender; Entity.Form = (byte)CB_Form.SelectedIndex; - Entity.Version = WinFormsUtil.GetIndex(CB_GameOrigin); + Entity.Version = (GameVersion)WinFormsUtil.GetIndex(CB_GameOrigin); if (Entity.Format > 2) { @@ -1557,7 +1556,7 @@ private void UpdateShiny(bool changePID) CommonEdits.SetShiny(Entity, type); TB_PID.Text = Entity.PID.ToString("X8"); - int gen = Entity.Generation; + var gen = Entity.Generation; bool pre3DS = gen is 3 or 4 or 5; if (pre3DS && Entity.Format >= 6) TB_EC.Text = TB_PID.Text; @@ -1598,7 +1597,7 @@ private void Update_ID(object? sender, EventArgs e) { if (!FieldsLoaded) return; - // Trim out nonhex characters + // Trim out non-hexadecimal characters TB_PID.Text = (Entity.PID = Util.GetHexValue(TB_PID.Text)).ToString("X8"); TB_EC.Text = (Entity.EncryptionConstant = Util.GetHexValue(TB_EC.Text)).ToString("X8"); @@ -1609,7 +1608,7 @@ private void Update_ID(object? sender, EventArgs e) { FieldsLoaded = false; Entity.PID = Util.GetHexValue(TB_PID.Text); - CB_Nature.SelectedValue = Entity.Nature; + CB_Nature.SelectedValue = (int)Entity.Nature; UC_Gender.Gender = Entity.Gender; UpdateNatureModification(CB_Nature, Entity.Nature); FieldsLoaded = true; @@ -1694,14 +1693,14 @@ private void ValidateComboBox2(object? sender, EventArgs e) { if (Entity.Format <= 4) UpdateRandomPID(sender, e); - Entity.Nature = WinFormsUtil.GetIndex(CB_Nature); + Entity.Nature = (Nature)WinFormsUtil.GetIndex(CB_Nature); UpdateNatureModification(CB_Nature, Entity.Nature); Stats.UpdateIVs(sender, EventArgs.Empty); // updating Nature will trigger stats to update as well UpdateLegality(); } else if (sender == CB_StatNature) { - Entity.StatNature = WinFormsUtil.GetIndex(CB_StatNature); + Entity.StatNature = (Nature)WinFormsUtil.GetIndex(CB_StatNature); UpdateNatureModification(CB_StatNature, Entity.StatNature); Stats.UpdateIVs(sender, EventArgs.Empty); // updating Nature will trigger stats to update as well UpdateLegality(); @@ -1798,8 +1797,8 @@ private void ValidateLocation(object sender, EventArgs e) return; ValidateComboBox((ComboBox)sender); - Entity.Met_Location = WinFormsUtil.GetIndex(CB_MetLocation); - Entity.Egg_Location = WinFormsUtil.GetIndex(CB_EggLocation); + Entity.MetLocation = (ushort)WinFormsUtil.GetIndex(CB_MetLocation); + Entity.EggLocation = (ushort)WinFormsUtil.GetIndex(CB_EggLocation); UpdateLegality(); } @@ -1846,10 +1845,10 @@ private void OpenMedals(object sender, EventArgs e) private void OpenHistory(object sender, EventArgs e) { // Write back current values - Entity.HT_Name = TB_HT.Text; - Entity.OT_Name = TB_OT.Text; + Entity.HandlingTrainerName = TB_HT.Text; + Entity.OriginalTrainerName = TB_OT.Text; Entity.IsEgg = CHK_IsEgg.Checked; - UpdateFromFriendshipTextBox(Entity, Util.ToInt32(TB_Friendship.Text)); + UpdateFromFriendshipTextBox(Entity, (byte)Util.ToInt32(TB_Friendship.Text)); using var form = new MemoryAmie(Entity); form.ShowDialog(); ReloadToFriendshipTextBox(Entity); @@ -1910,22 +1909,22 @@ public bool ToggleInterface(SaveFile sav, PKM pk) private void ToggleInterface(PKM t) { var pb7 = t is PB7; - int gen = t.Format; + var format = t.Format; FLP_Purification.Visible = FLP_ShadowID.Visible = t is IShadowCapture; - bool sizeCP = gen >= 8 || pb7; + bool sizeCP = format >= 8 || pb7; SizeCP.Visible = SizeCP.TabStop = sizeCP; if (sizeCP) SizeCP.ToggleVisibility(t); PB_Favorite.Visible = t is IFavorite; PB_BattleVersion.Visible = FLP_BattleVersion.Visible = t is IBattleVersion; - BTN_History.Visible = gen >= 6 && !pb7; - BTN_Ribbons.Visible = gen >= 3 && !pb7; - BTN_Medals.Visible = gen is 6 or 7 && !pb7; + BTN_History.Visible = format >= 6 && !pb7; + BTN_Ribbons.Visible = format >= 3 && !pb7; + BTN_Medals.Visible = format is 6 or 7 && !pb7; FLP_Country.Visible = FLP_SubRegion.Visible = FLP_3DSRegion.Visible = t is IRegionOrigin; - FLP_OriginalNature.Visible = gen >= 8; + FLP_OriginalNature.Visible = format >= 8; B_RelearnFlags.Visible = t is ITechRecord; B_MoveShop.Visible = t is IMoveShop8Mastery; - FLP_HTLanguage.Visible = gen >= 8; + FLP_HTLanguage.Visible = format >= 8; L_AlphaMastered.Visible = CB_AlphaMastered.Visible = t is PA8; FLP_ObedienceLevel.Visible = t is IObedienceLevel; Contest.ToggleInterface(Entity, Entity.Context); @@ -1935,51 +1934,51 @@ private void ToggleInterface(PKM t) ToggleInterface(Entity.Format); } - private void ToggleSecrets(bool hidden, int gen) + private void ToggleSecrets(bool hidden, byte format) { - Label_EncryptionConstant.Visible = BTN_RerollEC.Visible = TB_EC.Visible = gen >= 6 && !hidden; - BTN_RerollPID.Visible = Label_PID.Visible = TB_PID.Visible = gen >= 3 && !hidden; - TB_HomeTracker.Visible = L_HomeTracker.Visible = gen >= 8 && !hidden; + Label_EncryptionConstant.Visible = BTN_RerollEC.Visible = TB_EC.Visible = format >= 6 && !hidden; + BTN_RerollPID.Visible = Label_PID.Visible = TB_PID.Visible = format >= 3 && !hidden; + TB_HomeTracker.Visible = L_HomeTracker.Visible = format >= 8 && !hidden; } - private void ToggleInterface(int gen) + private void ToggleInterface(byte format) { - ToggleSecrets(HideSecretValues, gen); - FLP_Handler.Visible = GB_nOT.Visible = FLP_HT.Visible = GB_RelearnMoves.Visible = gen >= 6; + ToggleSecrets(HideSecretValues, format); + FLP_Handler.Visible = GB_nOT.Visible = FLP_HT.Visible = GB_RelearnMoves.Visible = format >= 6; - PB_Origin.Visible = gen >= 6; - FLP_NSparkle.Visible = L_NSparkle.Visible = CHK_NSparkle.Visible = gen == 5; + PB_Origin.Visible = format >= 6; + FLP_NSparkle.Visible = L_NSparkle.Visible = CHK_NSparkle.Visible = format == 5; - CHK_AsEgg.Visible = GB_EggConditions.Visible = PB_Mark5.Visible = PB_Mark6.Visible = gen >= 4; - ShinyLeaf.Visible = gen == 4; + CHK_AsEgg.Visible = GB_EggConditions.Visible = PB_Mark5.Visible = PB_Mark6.Visible = format >= 4; + ShinyLeaf.Visible = format == 4; - DEV_Ability.Enabled = DEV_Ability.Visible = DEV_Ability.TabStop = gen > 3 && HaX; - CB_Ability.Visible = CB_Ability.TabStop = !DEV_Ability.Enabled && gen >= 3; - FLP_Nature.Visible = gen >= 3; - FLP_Ability.Visible = gen >= 3; - FLP_ExtraBytes.Visible = gen >= 3; - GB_Markings.Visible = GB_Markings.TabStop = gen >= 3; - CB_Form.Enabled = gen >= 3; - FA_Form.Visible = FA_Form.TabStop = gen >= 6; + DEV_Ability.Enabled = DEV_Ability.Visible = DEV_Ability.TabStop = format > 3 && HaX; + CB_Ability.Visible = CB_Ability.TabStop = !DEV_Ability.Enabled && format >= 3; + FLP_Nature.Visible = format >= 3; + FLP_Ability.Visible = format >= 3; + FLP_ExtraBytes.Visible = format >= 3; + GB_Markings.Visible = GB_Markings.TabStop = format >= 3; + CB_Form.Enabled = format >= 3; + FA_Form.Visible = FA_Form.TabStop = format >= 6; - FLP_Friendship.Visible = FLP_Form.Visible = gen >= 2; - FLP_HeldItem.Visible = gen >= 2; - CHK_IsEgg.Visible = CHK_IsEgg.TabStop = gen >= 2; - FLP_PKRS.Visible = FLP_EggPKRSRight.Visible = gen >= 2; - UC_Gender.Visible = UC_OTGender.Visible = UC_OTGender.TabStop = gen >= 2; - FLP_CatchRate.Visible = gen == 1; + FLP_Friendship.Visible = FLP_Form.Visible = format >= 2; + FLP_HeldItem.Visible = format >= 2; + CHK_IsEgg.Visible = CHK_IsEgg.TabStop = format >= 2; + FLP_PKRS.Visible = FLP_EggPKRSRight.Visible = format >= 2; + UC_Gender.Visible = UC_OTGender.Visible = UC_OTGender.TabStop = format >= 2; + FLP_CatchRate.Visible = format == 1; // HaX override, needs to be after DEV_Ability enabled assignment. - TB_AbilityNumber.Visible = gen >= 6 && DEV_Ability.Enabled; + TB_AbilityNumber.Visible = format >= 6 && DEV_Ability.Enabled; // Met Tab - FLP_MetDate.Visible = gen >= 4; - CHK_Fateful.Visible = FLP_Ball.Visible = FLP_OriginGame.Visible = gen >= 3; - FLP_MetLocation.Visible = FLP_MetLevel.Visible = gen >= 2; - FLP_GroundTile.Visible = gen is 4 or 5 or 6; - FLP_TimeOfDay.Visible = gen == 2; + FLP_MetDate.Visible = format >= 4; + CHK_Fateful.Visible = FLP_Ball.Visible = FLP_OriginGame.Visible = format >= 3; + FLP_MetLocation.Visible = FLP_MetLevel.Visible = format >= 2; + FLP_GroundTile.Visible = format is 4 or 5 or 6; + FLP_TimeOfDay.Visible = format == 2; - Stats.ToggleInterface(Entity, gen); + Stats.ToggleInterface(Entity, format); CenterSubEditors(); } @@ -2076,7 +2075,7 @@ private void CB_BattleVersion_SelectedValueChanged(object sender, EventArgs e) { if (Entity is not IBattleVersion b) return; - var value = (byte)WinFormsUtil.GetIndex(CB_BattleVersion); + var value = (GameVersion)WinFormsUtil.GetIndex(CB_BattleVersion); if (FieldsLoaded) b.BattleVersion = value; PB_BattleVersion.Image = GetMarkSprite(PB_BattleVersion, value != 0); @@ -2156,7 +2155,7 @@ private void PopulateFilteredDataSources(ITrainerInfo sav, bool force = false) if (sav.Generation >= 2) { - var game = (GameVersion)sav.Game; + var game = sav.Version; if (game <= 0) game = Entity.Context.GetSingleGameVersion(); CheckMetLocationChange(game, sav.Context); @@ -2196,7 +2195,7 @@ private void PopulateFilteredDataSources(ITrainerInfo sav, bool force = false) private void ChangeSelectedTabIndex(object? sender, EventArgs e) { - // flip to the tabless control's tab + // flip to the tab-less control's tab Hidden_TC.SelectedIndex = TC_Editor.SelectedIndex; // reset focus back to the vertical tab selection rather than the inaccessible tab TC_Editor.Focus(); diff --git a/PKHeX.WinForms/Controls/PKM Editor/StatEditor.cs b/PKHeX.WinForms/Controls/PKM Editor/StatEditor.cs index ff2b42e34..d7de357d7 100644 --- a/PKHeX.WinForms/Controls/PKM Editor/StatEditor.cs +++ b/PKHeX.WinForms/Controls/PKM Editor/StatEditor.cs @@ -48,7 +48,7 @@ public bool Valid return true; if (Entity is IAwakened a) return a.AwakeningAllValid(); - return Convert.ToUInt32(TB_EVTotal.Text) <= 510; + return Convert.ToUInt32(TB_EVTotal.Text) <= EffortValues.Max510; } } @@ -337,7 +337,7 @@ private void ClickStatLabel(object sender, MouseEventArgs e) }; var newNature = request.GetNewNature(index, Entity.StatNature); - if (newNature == -1) + if (newNature == Nature.Random) return; MainEditor.ChangeNature(newNature); @@ -487,7 +487,7 @@ private void UpdateCharacteristic(int characteristic) L_Characteristic.Text = GameInfo.Strings.characteristics[characteristic]; } - public string UpdateNatureModification(int nature) + public string UpdateNatureModification(Nature nature) { // Reset Label Colors foreach (var l in L_Stats) @@ -505,7 +505,7 @@ public string UpdateNatureModification(int nature) return $"+{incr.Text} / -{decr.Text}".Replace(":", ""); } - public void SetATKIVGender(int gender) + public void SetATKIVGender(byte gender) { Entity.SetAttackIVFromGender(gender); TB_IVATK.Text = Entity.IV_ATK.ToString(); @@ -644,19 +644,19 @@ private void SetStatOrder(StatEditorStatOrder order) StatOrder = order; } - public void ToggleInterface(PKM pk, int gen) + public void ToggleInterface(PKM pk, byte format) { - FLP_StatsTotal.Visible = gen >= 3; - FLP_Characteristic.Visible = gen >= 3; - FLP_HPType.Visible = gen <= 7 || pk is PB8; + FLP_StatsTotal.Visible = format >= 3; + FLP_Characteristic.Visible = format >= 3; + FLP_HPType.Visible = format <= 7 || pk is PB8; FLP_TeraType.Visible = FLP_TeraInner.Visible = pk is ITeraType; - Label_HiddenPowerPower.Visible = gen <= 5; - FLP_DynamaxLevel.Visible = gen == 8; + Label_HiddenPowerPower.Visible = format <= 5; + FLP_DynamaxLevel.Visible = format == 8; FLP_AlphaNoble.Visible = pk is PA8; - SetStatOrder(gen == 1 ? StatEditorStatOrder.Gen1Special : StatEditorStatOrder.Current); + SetStatOrder(format == 1 ? StatEditorStatOrder.Gen1Special : StatEditorStatOrder.Current); - switch (gen) + switch (format) { case 1: TB_IVHP.Enabled = false; diff --git a/PKHeX.WinForms/Controls/PKM Editor/TrainerID.cs b/PKHeX.WinForms/Controls/PKM Editor/TrainerID.cs index f7ca502e1..17b962db0 100644 --- a/PKHeX.WinForms/Controls/PKM Editor/TrainerID.cs +++ b/PKHeX.WinForms/Controls/PKM Editor/TrainerID.cs @@ -46,7 +46,7 @@ private uint GetTSV() return xor >> 4; } - public void LoadIDValues(ITrainerID32 tr, int format) + public void LoadIDValues(ITrainerID32 tr, byte format) { Trainer = tr; var display = tr.GetTrainerIDFormat(); @@ -87,7 +87,7 @@ private void LoadTID7(ITrainerID32 tr) TB_SID7.Text = tr.GetTrainerSID7().ToString(TrainerIDExtensions.SID7); } - private void SetFormat(TrainerIDFormat display, int format) + private void SetFormat(TrainerIDFormat display, byte format) { if ((display, format) == (DisplayType, XorFormat)) return; diff --git a/PKHeX.WinForms/Controls/Slots/PokePreview.cs b/PKHeX.WinForms/Controls/Slots/PokePreview.cs index c5c39798d..1814d3387 100644 --- a/PKHeX.WinForms/Controls/Slots/PokePreview.cs +++ b/PKHeX.WinForms/Controls/Slots/PokePreview.cs @@ -67,7 +67,7 @@ private static string GetNameTitle(PKM pk) private void PopulateBall(PKM pk) { - int ball = (int)Ball.Poke; + var ball = (byte)Ball.Poke; if (pk.Format >= 3) ball = pk.Ball; PB_Ball.Image = Drawing.PokeSprite.SpriteUtil.GetBallSprite(ball); diff --git a/PKHeX.WinForms/MainWindow/Main.cs b/PKHeX.WinForms/MainWindow/Main.cs index 92b9aada2..e87e08779 100644 --- a/PKHeX.WinForms/MainWindow/Main.cs +++ b/PKHeX.WinForms/MainWindow/Main.cs @@ -175,17 +175,17 @@ private void FormLoadInitialFiles(StartupArguments args) ErrorWindow.ShowErrorDialog(MsgFileLoadFailAuto, ex, true); } - private void LoadBlankSaveFile(GameVersion ver) + private void LoadBlankSaveFile(GameVersion version) { var current = C_SAV?.SAV; var lang = SaveUtil.GetSafeLanguage(current); var tr = SaveUtil.GetSafeTrainerName(current, lang); - var sav = SaveUtil.GetBlankSAV(ver, tr, lang); + var sav = SaveUtil.GetBlankSAV(version, tr, lang); if (sav.Version == GameVersion.Invalid) // will fail to load { var max = GameInfo.VersionDataSource.MaxBy(z => z.Value) ?? throw new Exception(); - ver = (GameVersion)max.Value; - sav = SaveUtil.GetBlankSAV(ver, tr, lang); + version = (GameVersion)max.Value; + sav = SaveUtil.GetBlankSAV(version, tr, lang); } OpenSAV(sav, string.Empty); C_SAV!.SAV.State.Edited = false; // Prevents form close warning from showing until changes are made @@ -212,9 +212,9 @@ private void FormLoadCheckForUpdates() }); } - private void NotifyNewVersionAvailable(Version ver) + private void NotifyNewVersionAvailable(Version version) { - var date = $"{2000 + ver.Major:00}{ver.Minor:00}{ver.Build:00}"; + var date = $"{2000 + version.Major:00}{version.Minor:00}{version.Build:00}"; var lbl = L_UpdateAvailable; lbl.Text = $"{MsgProgramUpdateAvailable} {date}"; lbl.Click += (_, _) => Process.Start(new ProcessStartInfo(ThreadPath) { UseShellExecute = true }); @@ -232,7 +232,7 @@ private static void FormLoadConfig(out bool BAKprompt, out bool showChangelog) bool parsed = Version.TryParse(Settings.Startup.Version, out var lastrev); showChangelog = parsed && lastrev < Program.CurrentVersion; } - Settings.Startup.Version = Program.CurrentVersion.ToString(); // set current ver so this doesn't happen until the user updates next time + Settings.Startup.Version = Program.CurrentVersion.ToString(); // set current version so this doesn't happen until the user updates next time // BAK Prompt if (!Settings.Backup.BAKPrompt) @@ -746,7 +746,7 @@ private static void StoreLegalSaveGameData(SaveFile sav) private bool OpenSAV(SaveFile sav, string path) { - if (sav.Version == GameVersion.Invalid) + if (!sav.IsVersionValid()) { WinFormsUtil.Error(MsgFileLoadSaveLoadFail, path); return true; @@ -840,8 +840,8 @@ private static string GetProgramTitle() var date = File.GetLastWriteTime(Environment.ProcessPath!); string version = $"d-{date:yyyyMMdd}"; #else - var ver = Program.CurrentVersion; - string version = $"{2000+ver.Major:00}{ver.Minor:00}{ver.Build:00}"; + var v = Program.CurrentVersion; + string version = $"{2000+v.Major:00}{v.Minor:00}{v.Build:00}"; #endif return $"PKH{(HaX ? "a" : "e")}X ({version})"; } @@ -851,11 +851,11 @@ private static string GetProgramTitle(SaveFile sav) string title = GetProgramTitle() + $" - {sav.GetType().Name}: "; if (sav is ISaveFileRevision rev) title = title.Insert(title.Length - 2, rev.SaveRevisionString); - var ver = GameInfo.GetVersionName(sav.Version); + var version = GameInfo.GetVersionName(sav.Version); if (Settings.Privacy.HideSAVDetails) - return title + $"[{ver}]"; + return title + $"[{version}]"; if (!sav.State.Exportable) // Blank save file - return title + $"{sav.Metadata.FileName} [{sav.OT} ({ver})]"; + return title + $"{sav.Metadata.FileName} [{sav.OT} ({version})]"; return title + Path.GetFileNameWithoutExtension(Util.CleanFileName(sav.Metadata.BAKName)); // more descriptive } diff --git a/PKHeX.WinForms/Misc/QR.cs b/PKHeX.WinForms/Misc/QR.cs index 085d238bd..45f2f0857 100644 --- a/PKHeX.WinForms/Misc/QR.cs +++ b/PKHeX.WinForms/Misc/QR.cs @@ -66,8 +66,11 @@ private void RefreshImage() { SuspendLayout(); ResumeLayout(); - Font font = !Main.Unicode ? Font : FontUtil.GetPKXFont(8.25f); - var img = QRImageUtil.GetQRImageExtended(font, qr, icon, Math.Max(qr.Width, 370), qr.Height + 50, Lines, extraText); + var font = !Main.Unicode ? Font : FontUtil.GetPKXFont(8.25f); + + var width = Math.Max(qr.Width, 370); + var height = qr.Height + 50; + var img = QRImageUtil.GetQRImageExtended(font, qr, icon, width, height, Lines, extraText); PB_QR.Image = img; } diff --git a/PKHeX.WinForms/Properties/PKHeXSettings.cs b/PKHeX.WinForms/Properties/PKHeXSettings.cs index 3e24f7389..ad33f33ed 100644 --- a/PKHeX.WinForms/Properties/PKHeXSettings.cs +++ b/PKHeX.WinForms/Properties/PKHeXSettings.cs @@ -215,8 +215,11 @@ public sealed class LegalitySettings : IParseSettings [LocalizedDescription("Severity to flag a Legality Check if it is a nicknamed Mystery Gift the player cannot normally nickname.")] public Severity NicknamedMysteryGift { get; set; } = Severity.Fishy; - [LocalizedDescription("Severity to flag a Legality Check if the RNG Frame Checking logic does not find a match.")] - public Severity RNGFrameNotFound { get; set; } = Severity.Fishy; + [LocalizedDescription("Severity to flag a Legality Check if the RNG Frame Checking logic does not find a match for Generation 3 encounters.")] + public Severity RNGFrameNotFound3 { get; set; } = Severity.Fishy; + + [LocalizedDescription("Severity to flag a Legality Check if the RNG Frame Checking logic does not find a match for Generation 4 encounters.")] + public Severity RNGFrameNotFound4 { get; set; } = Severity.Invalid; [LocalizedDescription("Severity to flag a Legality Check if Pokémon from Gen1/2 has a Star Shiny PID.")] public Severity Gen7TransferStarPID { get; set; } = Severity.Fishy; @@ -225,7 +228,7 @@ public sealed class LegalitySettings : IParseSettings public Severity Gen8MemoryMissingHT { get; set; } = Severity.Fishy; [LocalizedDescription("Severity to flag a Legality Check if the HOME Tracker is Missing")] - public Severity Gen8TransferTrackerNotPresent { get; set; } = Severity.Fishy; + public Severity HOMETransferTrackerNotPresent { get; set; } = Severity.Invalid; [LocalizedDescription("Severity to flag a Legality Check if Pokémon has a Nickname matching another Species.")] public Severity NicknamedAnotherSpecies { get; set; } = Severity.Fishy; diff --git a/PKHeX.WinForms/Resources/text/changelog_2018.txt b/PKHeX.WinForms/Resources/text/changelog_2018.txt index 43d416827..c4fa94720 100644 --- a/PKHeX.WinForms/Resources/text/changelog_2018.txt +++ b/PKHeX.WinForms/Resources/text/changelog_2018.txt @@ -361,7 +361,7 @@ - - Added: Gen2 headbutt encounters are now checked for headbutt legality. Thanks @javierhimura! - - Added: Transferring a pk from XD to any other game will now receive a Fateful Encounter flag if appropriate. - Added: WC3 (gen3 event template) -> pk conversion. Use the Mystery Gift Database. - - Added: Ability to batch edit trash bytes (.Nickname_Trash=$[]43,00,...) + - Added: Ability to batch edit trash bytes (.NicknameTrash=$[]43,00,...) - Added: Inventory items can now be sorted by index number. - Changed: Event Flag/Constant editor redesigned to separate tabs. - Changed: Deoxys in Gen3 now shows up with the game-specific form. @@ -934,8 +934,8 @@ - Fixed: Trash Bytes now are no longer cleared when saving data. Thanks SciresM & Lunarcookies! - Fixed: Re-ordered controls to make tabbing flow down the form. Thanks Favna! - Fixed: Vivillon Form selection in the Trainer Info editor will now function with refactored code. Thanks KingGengar & Favna! - - Fixed: New PKRS capping code will now behave properly. Thanks Favna and evandixon! - - Changed: PKRS Days capped at legal limits. + - Fixed: New PokerusState capping code will now behave properly. Thanks Favna and evandixon! + - Changed: PokerusState Days capped at legal limits. - Changed: Forms drop-down and label will be hidden if a Pokémon has no forms. - Hotfix: Changing the exe name to auto-load a language will now function properly. Thanks supercarotte! - Hotfix: Wonder Card QRs with non-held items will no longer error out. Thanks ShinyMeganium! @@ -990,7 +990,7 @@ 15/01/28 - New Update: (9900) - Added: Save editing for retail games. Load ramsav.bin and export with Export SAV button in the SAV tab. - - Change the target RAM binary by holding shift while exporting. - - Fixed: PKRS display logic should now behave as intended. + - Fixed: PokerusState display logic should now behave as intended. - Changed: Gender/Game changing in Trainer Info has been disabled (it's not a simple 'switch'). - Improved: Loading Box/Debug binaries will display the boxes if they are not visible. - Update (b): Added 2 more types of XY RAMSav types. @@ -1027,7 +1027,7 @@ - Added: Viewing of the second daycare in ORAS; click anywhere in the groupbox to trigger the switching code. Thanks Leanny! - Added: More verbosity to Box Report. - Improved: Data loading speeds (boxes, etc). - - Improved: PKRS information will only appear if it has been infected/cured; checkboxes to alter are still always visible. + - Improved: PokerusState information will only appear if it has been infected/cured; checkboxes to alter are still always visible. - Fixed: Pumpkaboo form names. Thanks Pkmnninja! - Fixed: Checksum detection should now trigger when loading pkx files. Oops. - Fixed: Translation shouldn't error out if the translation file is malformed. @@ -1287,7 +1287,7 @@ - Fixed: Pokerus infection/curing logic. - Fixed: Memory loading now doesn't error out with no data, and has all memory types and locations. - Added: DE/FR (early) language translations. - - Added: Shiny/PKRS Cured/Pentagon sprites to marking. + - Added: Shiny/PokerusState Cured/Pentagon sprites to marking. - Added: Ribbon sprites from ingame; Expert Battler (Super Maison ribbon) now has proper sprite. Also added the 40/8 complete Memory ribbons. - Added: Base friendships for Kalos Pokemon. - Added: Clicking Friendship Label now toggles between Base & Max; pressing with Control resets it. diff --git a/PKHeX.WinForms/Resources/text/changelog_2022.txt b/PKHeX.WinForms/Resources/text/changelog_2022.txt index 3e7b7bdb2..4126be1dc 100644 --- a/PKHeX.WinForms/Resources/text/changelog_2022.txt +++ b/PKHeX.WinForms/Resources/text/changelog_2022.txt @@ -345,7 +345,7 @@ http://projectpokemon.org/pkhex/ - Fixed: BDSP Batch editor now works for the PB8 format. - Fixed: BDSP encounter database now yields Shining Pearl egg encounters. - Fixed: Toggling egg state in the PKM Editor GUI now sets the correct met location values. - - Changed: Editing the HT_Friendship value for eggs in the Memories editor is now possible if it is a HT-handled egg, rather than being greyed out. + - Changed: Editing the HandlingTrainerFriendship value for eggs in the Memories editor is now possible if it is a HT-handled egg, rather than being greyed out. 21/11/19 - New Update: (41229) [4140044] - Introducing Brilliant Diamond & Shining Pearl Support! Thanks @SciresM, @sora10pls, @Lusamine, @architdate, @ReignOfComputer for troubleshooting! diff --git a/PKHeX.WinForms/Resources/text/lang_es.txt b/PKHeX.WinForms/Resources/text/lang_es.txt index 358d774e4..899dba950 100644 --- a/PKHeX.WinForms/Resources/text/lang_es.txt +++ b/PKHeX.WinForms/Resources/text/lang_es.txt @@ -116,8 +116,8 @@ LocalizedDescription.Gen8TransferTrackerNotPresent=En la validación de Legalida LocalizedDescription.GlowFinal=Hovering over a PKM color 2. LocalizedDescription.GlowInitial=Hovering over a PKM color 1. LocalizedDescription.HiddenPowerOnChangeMaxPower=Cuando se cambia el tipo de Poder Oculto, automáticamente maximixar los IVs para resultar con el mayor Poder Base. De otra forma mantener lo más cerca posible al original. -LocalizedDescription.HideEvent8Contains=Ocultar eventos que contengan alguna de las palabras (separadas por comas) siguientes en el nombre. Elimina de la interfaz los valores de los eventos que no le interesa ver al usuario. -LocalizedDescription.HideEventTypeBelow=Ocultar variables de evento por debajo de este valor de tipo de evento. Elimina de la interfaz los valores de los eventos que no le interesa ver al usuario. +LocalizedDescription.HideEvent8Contains=Ocultar eventos que contengan alguna de las palabras (separadas por comas) siguientes en el nombre. Elimina de la interfaz los valores de los eventos que no le interesa version al usuario. +LocalizedDescription.HideEventTypeBelow=Ocultar variables de evento por debajo de este valor de tipo de evento. Elimina de la interfaz los valores de los eventos que no le interesa version al usuario. LocalizedDescription.HideSAVDetails=Ocultar detalles de partidas guardadas en el título del programa LocalizedDescription.HideSecretDetails=Ocultar detalles secretos en los editores LocalizedDescription.HoverSlotGlowEdges=Mostrar brillo PKM al pasar el ratón diff --git a/PKHeX.WinForms/Subforms/PKM Editors/MemoryAmie.cs b/PKHeX.WinForms/Subforms/PKM Editors/MemoryAmie.cs index 9046418c6..c0c7fe7c2 100644 --- a/PKHeX.WinForms/Subforms/PKM Editors/MemoryAmie.cs +++ b/PKHeX.WinForms/Subforms/PKM Editors/MemoryAmie.cs @@ -67,13 +67,13 @@ private void LoadFields() M_Fullness.Text = Entity.Fullness.ToString(); M_Enjoyment.Text = Entity.Enjoyment.ToString(); - M_OT_Friendship.Text = Entity.OT_Friendship.ToString(); - M_CT_Friendship.Text = Entity.HT_Friendship.ToString(); + M_OT_Friendship.Text = Entity.OriginalTrainerFriendship.ToString(); + M_CT_Friendship.Text = Entity.HandlingTrainerFriendship.ToString(); if (Entity is IAffection a) { - M_OT_Affection.Text = a.OT_Affection.ToString(); - M_CT_Affection.Text = a.HT_Affection.ToString(); + M_OT_Affection.Text = a.OriginalTrainerAffection.ToString(); + M_CT_Affection.Text = a.HandlingTrainerAffection.ToString(); } if (Entity is ISociability s) @@ -82,23 +82,23 @@ private void LoadFields() if (Entity is ITrainerMemories m) { // Load the OT Memories - CB_OTQual.SelectedIndex = m.OT_Intensity; - CB_OTMemory.SelectedValue = (int)m.OT_Memory; - CB_OTVar.SelectedValue = (int)m.OT_TextVar; - CB_OTFeel.SelectedIndex = m.OT_Feeling; + CB_OTQual.SelectedIndex = m.OriginalTrainerMemoryIntensity; + CB_OTMemory.SelectedValue = (int)m.OriginalTrainerMemory; + CB_OTVar.SelectedValue = (int)m.OriginalTrainerMemoryVariable; + CB_OTFeel.SelectedIndex = m.OriginalTrainerMemoryFeeling; // Load the HT Memories - CB_CTQual.SelectedIndex = m.HT_Intensity; - CB_CTMemory.SelectedValue = (int)m.HT_Memory; - CB_CTVar.SelectedValue = (int)m.HT_TextVar; - CB_CTFeel.SelectedIndex = m.HT_Feeling; + CB_CTQual.SelectedIndex = m.HandlingTrainerMemoryIntensity; + CB_CTMemory.SelectedValue = (int)m.HandlingTrainerMemory; + CB_CTVar.SelectedValue = (int)m.HandlingTrainerMemoryVariable; + CB_CTFeel.SelectedIndex = m.HandlingTrainerMemoryFeeling; } CB_Handler.Items.Clear(); - CB_Handler.Items.Add($"{Entity.OT_Name} ({TextArgs.OT})"); // OTNAME : OT + CB_Handler.Items.Add($"{Entity.OriginalTrainerName} ({TextArgs.OT})"); // OTNAME : OT - if (!string.IsNullOrEmpty(Entity.HT_Name)) - CB_Handler.Items.Add(Entity.HT_Name); + if (!string.IsNullOrEmpty(Entity.HandlingTrainerName)) + CB_Handler.Items.Add(Entity.HandlingTrainerName); else Entity.CurrentHandler = 0; @@ -107,7 +107,7 @@ private void LoadFields() GB_M_OT.Enabled = GB_M_CT.Enabled = GB_Residence.Enabled = BTN_Save.Enabled = M_Fullness.Enabled = M_Enjoyment.Enabled = L_Sociability.Enabled = MT_Sociability.Enabled = - L_Fullness.Enabled = L_Enjoyment.Enabled = Entity is not { IsEgg: true, IsUntraded: true, HT_Friendship: 0 }; + L_Fullness.Enabled = L_Enjoyment.Enabled = Entity is not { IsEgg: true, IsUntraded: true, HandlingTrainerFriendship: 0 }; if (!Entity.IsEgg) { @@ -115,8 +115,8 @@ private void LoadFields() if (Entity.Generation < 6) { // Previous Generation Mon - GB_M_OT.Text = $"{TextArgs.PastGen} {Entity.OT_Name}: {TextArgs.OT}"; // Past Gen OT : OTNAME - GB_M_CT.Text = $"{TextArgs.MemoriesWith} {Entity.HT_Name}"; // Memories with : HTNAME + GB_M_OT.Text = $"{TextArgs.PastGen} {Entity.OriginalTrainerName}: {TextArgs.OT}"; // Past Gen OT : OTNAME + GB_M_CT.Text = $"{TextArgs.MemoriesWith} {Entity.HandlingTrainerName}"; // Memories with : HTNAME enable = false; // Reset to no memory -- don't reset affection as OR/AS can raise it (+20 * n) via Contests CB_OTQual.SelectedIndex = CB_OTFeel.SelectedIndex = 0; @@ -125,9 +125,9 @@ private void LoadFields() else { enable = true; - GB_M_OT.Text = $"{TextArgs.MemoriesWith} {Entity.OT_Name} ({TextArgs.OT})"; // Memories with : OTNAME - GB_M_CT.Text = $"{TextArgs.MemoriesWith} {Entity.HT_Name}"; // Memories with : HTNAME - if (Entity.HT_Name.Length == 0) + GB_M_OT.Text = $"{TextArgs.MemoriesWith} {Entity.OriginalTrainerName} ({TextArgs.OT})"; // Memories with : OTNAME + GB_M_CT.Text = $"{TextArgs.MemoriesWith} {Entity.HandlingTrainerName}"; // Memories with : HTNAME + if (Entity.HandlingTrainerName.Length == 0) { CB_Country1.Enabled = CB_Country2.Enabled = CB_Country3.Enabled = CB_Country4.Enabled = CB_Region1.Enabled = CB_Region2.Enabled = CB_Region3.Enabled = CB_Region4.Enabled = @@ -136,7 +136,7 @@ private void LoadFields() } else { - GB_M_CT.Text = $"{TextArgs.MemoriesWith} {Entity.HT_Name}"; + GB_M_CT.Text = $"{TextArgs.MemoriesWith} {Entity.HandlingTrainerName}"; } } RTB_OT.Visible = CB_OTQual.Enabled = CB_OTMemory.Enabled = CB_OTFeel.Enabled = CB_OTVar.Enabled = enable; @@ -150,8 +150,8 @@ private void LoadFields() init = true; // Manually load the Memory Parse - RTB_CT.Text = GetMemoryString(CB_CTMemory, CB_CTVar, CB_CTQual, CB_CTFeel, Entity.HT_Name); - RTB_OT.Text = GetMemoryString(CB_OTMemory, CB_OTVar, CB_OTQual, CB_OTFeel, Entity.OT_Name); + RTB_CT.Text = GetMemoryString(CB_CTMemory, CB_CTVar, CB_CTQual, CB_CTFeel, Entity.HandlingTrainerName); + RTB_OT.Text = GetMemoryString(CB_OTMemory, CB_OTVar, CB_OTQual, CB_OTFeel, Entity.OriginalTrainerName); // Affection no longer stored in Gen8+, so only show in Gen6/7. L_OT_Affection.Visible = L_CT_Affection.Visible = M_OT_Affection.Visible = M_CT_Affection.Visible = Entity.Format <= 7; @@ -176,13 +176,13 @@ private void SaveFields() } // Save 0-255 stats - Entity.HT_Friendship = Util.ToInt32(M_CT_Friendship.Text); - Entity.OT_Friendship = Util.ToInt32(M_OT_Friendship.Text); + Entity.HandlingTrainerFriendship = (byte)Util.ToInt32(M_CT_Friendship.Text); + Entity.OriginalTrainerFriendship = (byte)Util.ToInt32(M_OT_Friendship.Text); if (Entity is IAffection a) { - a.OT_Affection = (byte)Util.ToInt32(M_OT_Affection.Text); - a.HT_Affection = (byte)Util.ToInt32(M_CT_Affection.Text); + a.OriginalTrainerAffection = (byte)Util.ToInt32(M_OT_Affection.Text); + a.HandlingTrainerAffection = (byte)Util.ToInt32(M_CT_Affection.Text); } Entity.Fullness = (byte)Util.ToInt32(M_Fullness.Text); Entity.Enjoyment = (byte)Util.ToInt32(M_Enjoyment.Text); @@ -190,15 +190,15 @@ private void SaveFields() // Save Memories if (Entity is ITrainerMemories m) { - m.OT_Memory = (byte)WinFormsUtil.GetIndex(CB_OTMemory); - m.OT_TextVar = CB_OTVar.Enabled ? (ushort)WinFormsUtil.GetIndex(CB_OTVar) : (ushort)0; - m.OT_Intensity = CB_OTFeel.Enabled ? (byte)CB_OTQual.SelectedIndex : (byte)0; - m.OT_Feeling = CB_OTFeel.Enabled ? (byte)CB_OTFeel.SelectedIndex : (byte)0; + m.OriginalTrainerMemory = (byte)WinFormsUtil.GetIndex(CB_OTMemory); + m.OriginalTrainerMemoryVariable = CB_OTVar.Enabled ? (ushort)WinFormsUtil.GetIndex(CB_OTVar) : (ushort)0; + m.OriginalTrainerMemoryIntensity = CB_OTFeel.Enabled ? (byte)CB_OTQual.SelectedIndex : (byte)0; + m.OriginalTrainerMemoryFeeling = CB_OTFeel.Enabled ? (byte)CB_OTFeel.SelectedIndex : (byte)0; - m.HT_Memory = (byte)WinFormsUtil.GetIndex(CB_CTMemory); - m.HT_TextVar = CB_CTVar.Enabled ? (ushort)WinFormsUtil.GetIndex(CB_CTVar) : (ushort)0; - m.HT_Intensity = CB_CTFeel.Enabled ? (byte)CB_CTQual.SelectedIndex : (byte)0; - m.HT_Feeling = CB_CTFeel.Enabled ? (byte)CB_CTFeel.SelectedIndex : (byte)0; + m.HandlingTrainerMemory = (byte)WinFormsUtil.GetIndex(CB_CTMemory); + m.HandlingTrainerMemoryVariable = CB_CTVar.Enabled ? (ushort)WinFormsUtil.GetIndex(CB_CTVar) : (ushort)0; + m.HandlingTrainerMemoryIntensity = CB_CTFeel.Enabled ? (byte)CB_CTQual.SelectedIndex : (byte)0; + m.HandlingTrainerMemoryFeeling = CB_CTFeel.Enabled ? (byte)CB_CTFeel.SelectedIndex : (byte)0; } if (Entity is G8PKM pk8) @@ -249,16 +249,16 @@ private void UpdateMemoryDisplay(object sender) if (sender == CB_OTMemory) { int memoryGen = Entity.Generation; - if (memoryGen < 0) + if (memoryGen == 0) memoryGen = Entity.Format; var memory = (byte)WinFormsUtil.GetIndex((ComboBox)sender); var memIndex = Memories.GetMemoryArgType(memory, memoryGen); - var argvals = MemStrings.GetArgumentStrings(memIndex, memoryGen); + var args = MemStrings.GetArgumentStrings(memIndex, memoryGen); CB_OTVar.InitializeBinding(); - CB_OTVar.DataSource = new BindingSource(argvals, null); + CB_OTVar.DataSource = new BindingSource(args, null); LOTV.Text = TextArgs.GetMemoryCategory(memIndex, memoryGen); - LOTV.Visible = CB_OTVar.Visible = CB_OTVar.Enabled = argvals.Count > 1; + LOTV.Visible = CB_OTVar.Visible = CB_OTVar.Enabled = args.Count > 1; } else { @@ -312,8 +312,8 @@ private void ChangeMemory(object sender, EventArgs e) if (!init) return; - RTB_OT.Text = GetMemoryString(CB_OTMemory, CB_OTVar, CB_OTQual, CB_OTFeel, Entity.OT_Name); - RTB_CT.Text = GetMemoryString(CB_CTMemory, CB_CTVar, CB_CTQual, CB_CTFeel, Entity.HT_Name); + RTB_OT.Text = GetMemoryString(CB_OTMemory, CB_OTVar, CB_OTQual, CB_OTFeel, Entity.OriginalTrainerName); + RTB_CT.Text = GetMemoryString(CB_CTMemory, CB_CTVar, CB_CTQual, CB_CTFeel, Entity.HandlingTrainerName); } private void ChangeCountryIndex(object sender, EventArgs e) diff --git a/PKHeX.WinForms/Subforms/PKM Editors/Text.cs b/PKHeX.WinForms/Subforms/PKM Editors/Text.cs index 45a05b89d..c30dda04d 100644 --- a/PKHeX.WinForms/Subforms/PKM Editors/Text.cs +++ b/PKHeX.WinForms/Subforms/PKM Editors/Text.cs @@ -153,7 +153,7 @@ private void B_ApplyTrash_Click(object sender, EventArgs e) { var species = (ushort)WinFormsUtil.GetIndex(CB_Species); var language = WinFormsUtil.GetIndex(CB_Language); - var gen = (int)NUD_Generation.Value; + var gen = (byte)NUD_Generation.Value; string speciesName = SpeciesName.GetSpeciesNameGeneration(species, language, gen); if (string.IsNullOrEmpty(speciesName)) // no result @@ -205,7 +205,7 @@ private static NumericUpDown GetNUD(byte min, byte max, bool hex) => new() Margin = new Padding(0), }; - private static ReadOnlySpan GetChars(int generation) => generation switch + private static ReadOnlySpan GetChars(byte generation) => generation switch { 5 => SpecialCharsGen5, 6 => SpecialCharsGen67, diff --git a/PKHeX.WinForms/Subforms/SAV_Database.cs b/PKHeX.WinForms/Subforms/SAV_Database.cs index fa91e2be3..1bcb75074 100644 --- a/PKHeX.WinForms/Subforms/SAV_Database.cs +++ b/PKHeX.WinForms/Subforms/SAV_Database.cs @@ -86,7 +86,7 @@ public SAV_Database(PKMEditor f1, SAVEditor saveditor) { if (sender is not PictureBox pb) return; - var index = Array.IndexOf(PKXBOXES, sender); + var index = Array.IndexOf(PKXBOXES, pb); if (index < 0) return; index += (SCR_Box.Value * RES_MIN); @@ -529,16 +529,16 @@ private SearchSettings GetSearchSettings() { var settings = new SearchSettings { - Format = MAXFORMAT - CB_Format.SelectedIndex + 1, // 0->(n-1) => 1->n + Format = (byte)(MAXFORMAT - CB_Format.SelectedIndex + 1), // 0->(n-1) => 1->n SearchFormat = (SearchComparison)CB_FormatComparator.SelectedIndex, - Generation = CB_Generation.SelectedIndex, + Generation = (byte)CB_Generation.SelectedIndex, - Version = WinFormsUtil.GetIndex(CB_GameOrigin), + Version = (GameVersion)WinFormsUtil.GetIndex(CB_GameOrigin), HiddenPowerType = WinFormsUtil.GetIndex(CB_HPType), Species = GetU16(CB_Species), Ability = WinFormsUtil.GetIndex(CB_Ability), - Nature = WinFormsUtil.GetIndex(CB_Nature), + Nature = (Nature)WinFormsUtil.GetIndex(CB_Nature), Item = WinFormsUtil.GetIndex(CB_HeldItem), BatchInstructions = RTB_Instructions.Text, diff --git a/PKHeX.WinForms/Subforms/SAV_Encounters.cs b/PKHeX.WinForms/Subforms/SAV_Encounters.cs index 50f4f30f9..9d1b6b2f0 100644 --- a/PKHeX.WinForms/Subforms/SAV_Encounters.cs +++ b/PKHeX.WinForms/Subforms/SAV_Encounters.cs @@ -72,7 +72,7 @@ public SAV_Encounters(PKMEditor f1, TrainerDatabase db) { if (sender is not PictureBox pb) return; - var index = Array.IndexOf(PKXBOXES, sender); + var index = Array.IndexOf(PKXBOXES, pb); if (index < 0) return; index += (SCR_Box.Value * RES_MIN); @@ -88,7 +88,7 @@ public SAV_Encounters(PKMEditor f1, TrainerDatabase db) } Counter = L_Count.Text; - L_Viewed.Text = string.Empty; // invis for now + L_Viewed.Text = string.Empty; // invisible for now L_Viewed.MouseEnter += (sender, e) => hover.SetToolTip(L_Viewed, L_Viewed.Text); PopulateComboBoxes(); @@ -358,7 +358,7 @@ private SearchSettings GetSearchSettings() Species = GetU16(CB_Species), BatchInstructions = RTB_Instructions.Text, - Version = WinFormsUtil.GetIndex(CB_GameOrigin), + Version = (GameVersion)WinFormsUtil.GetIndex(CB_GameOrigin), }; static ushort GetU16(ListControl cb) diff --git a/PKHeX.WinForms/Subforms/SAV_MysteryGiftDB.cs b/PKHeX.WinForms/Subforms/SAV_MysteryGiftDB.cs index 55ce995b0..fd330e58e 100644 --- a/PKHeX.WinForms/Subforms/SAV_MysteryGiftDB.cs +++ b/PKHeX.WinForms/Subforms/SAV_MysteryGiftDB.cs @@ -50,12 +50,12 @@ public SAV_MysteryGiftDB(PKMEditor tabs, SAVEditor sav) grid.SetBackground(Resources.box_wp_clean); var newWidth = grid.Width; var newHeight = grid.Height; - var wdelta = newWidth - smallWidth; - if (wdelta != 0) - Width += wdelta; - var hdelta = newHeight - smallHeight; - if (hdelta != 0) - Height += hdelta; + var wDelta = newWidth - smallWidth; + if (wDelta != 0) + Width += wDelta; + var hDelta = newHeight - smallHeight; + if (hDelta != 0) + Height += hDelta; PKXBOXES = [.. grid.Entries]; @@ -75,7 +75,7 @@ public SAV_MysteryGiftDB(PKMEditor tabs, SAVEditor sav) { if (sender is not PictureBox pb) return; - var index = Array.IndexOf(PKXBOXES, sender); + var index = Array.IndexOf(PKXBOXES, pb); if (index < 0) return; index += (SCR_Box.Value * RES_MIN); @@ -305,7 +305,7 @@ private void B_Search_Click(object sender, EventArgs e) // Populate Search Query Result IEnumerable res = RawDB; - int format = MAXFORMAT + 1 - CB_Format.SelectedIndex; + byte format = (byte)(MAXFORMAT + 1 - CB_Format.SelectedIndex); switch (CB_FormatComparator.SelectedIndex) { @@ -429,11 +429,11 @@ protected override void OnMouseWheel(MouseEventArgs e) { if (!MysteryPokeGrid.RectangleToScreen(MysteryPokeGrid.ClientRectangle).Contains(MousePosition)) return; - int oldval = SCR_Box.Value; - int newval = oldval + (e.Delta < 0 ? 1 : -1); - if (newval < SCR_Box.Minimum || SCR_Box.Maximum < newval) + int oldVal = SCR_Box.Value; + int newVal = oldVal + (e.Delta < 0 ? 1 : -1); + if (newVal < SCR_Box.Minimum || SCR_Box.Maximum < newVal) return; - FillPKXBoxes(SCR_Box.Value = newval); + FillPKXBoxes(SCR_Box.Value = newVal); ShowSet.Clear(); } @@ -454,7 +454,8 @@ private void ChangeFormatFilter(object sender, EventArgs e) private void ShowHoverTextForSlot(object sender, EventArgs e) { - var pb = (PictureBox)sender; + if (sender is not PictureBox pb) + return; int index = Array.IndexOf(PKXBOXES, pb); if (!GetShiftedIndex(ref index)) return; diff --git a/PKHeX.WinForms/Subforms/Save Editors/Gen3/SAV_Roamer3.cs b/PKHeX.WinForms/Subforms/Save Editors/Gen3/SAV_Roamer3.cs index b45d78f62..c8c5b84bf 100644 --- a/PKHeX.WinForms/Subforms/Save Editors/Gen3/SAV_Roamer3.cs +++ b/PKHeX.WinForms/Subforms/Save Editors/Gen3/SAV_Roamer3.cs @@ -22,7 +22,7 @@ public SAV_Roamer3(SAV3 sav) private void LoadData() { - TB_PID.Text = $"{Reader.PID:X8}"; + TB_PID.Text = Reader.PID.ToString("X8"); CHK_Shiny.Checked = Reader.IsShiny(Reader.PID); CB_Species.SelectedValue = (int)Reader.Species; @@ -50,7 +50,7 @@ private void SaveData() Util.ToInt32(TB_SPDIV.Text), ]); Reader.Active = CHK_Active.Checked; - Reader.CurrentLevel = (int)NUD_Level.Value; + Reader.CurrentLevel = (byte)NUD_Level.Value; } private void B_Save_Click(object sender, EventArgs e) diff --git a/PKHeX.WinForms/Subforms/Save Editors/Gen4/SAV_Pokedex4.cs b/PKHeX.WinForms/Subforms/Save Editors/Gen4/SAV_Pokedex4.cs index dab11ad8e..83549fff9 100644 --- a/PKHeX.WinForms/Subforms/Save Editors/Gen4/SAV_Pokedex4.cs +++ b/PKHeX.WinForms/Subforms/Save Editors/Gen4/SAV_Pokedex4.cs @@ -169,7 +169,7 @@ private void SetEntry() if (LB_Gender.Items.Count != 0) { var femaleFirst = LB_Gender.Items[0].ToString() == FEMALE; - var firstGender = femaleFirst ? 1 : 0; + var firstGender = femaleFirst ? (byte)1: (byte)0; dex.SetSeenGenderNewFlag(species, firstGender); if (LB_Gender.Items.Count != 1) dex.SetSeenGenderSecond(species, firstGender ^ 1); diff --git a/PKHeX.WinForms/Subforms/Save Editors/Gen5/SAV_Misc5.cs b/PKHeX.WinForms/Subforms/Save Editors/Gen5/SAV_Misc5.cs index 4062b7196..bccea5d35 100644 --- a/PKHeX.WinForms/Subforms/Save Editors/Gen5/SAV_Misc5.cs +++ b/PKHeX.WinForms/Subforms/Save Editors/Gen5/SAV_Misc5.cs @@ -583,7 +583,7 @@ private void UpdateSlotValue(object sender, EventArgs e) } else if (sender == CB_Gender) { - CurrentSlot.Gender = WinFormsUtil.GetIndex(CB_Gender); + CurrentSlot.Gender = (byte)WinFormsUtil.GetIndex(CB_Gender); } else if (sender == CB_Form) { diff --git a/PKHeX.WinForms/Subforms/Save Editors/Gen6/SAV_HallOfFame.cs b/PKHeX.WinForms/Subforms/Save Editors/Gen6/SAV_HallOfFame.cs index 479fe584d..b7602af86 100644 --- a/PKHeX.WinForms/Subforms/Save Editors/Gen6/SAV_HallOfFame.cs +++ b/PKHeX.WinForms/Subforms/Save Editors/Gen6/SAV_HallOfFame.cs @@ -154,8 +154,8 @@ private void AddEntryDescription(List s, HallFame6Entity entry) s.Add($"Move 3: {str.Move[entry.Move3]}"); s.Add($"Move 4: {str.Move[entry.Move4]}"); - string OTGender = gendersymbols[(int)entry.OT_Gender]; - s.Add($"OT: {entry.OT_Name} ({OTGender}) ({entry.TID16}/{entry.SID16})"); + string OTGender = gendersymbols[(int)entry.OriginalTrainerGender]; + s.Add($"OT: {entry.OriginalTrainerName} ({OTGender}) ({entry.TID16}/{entry.SID16})"); s.Add(string.Empty); } @@ -182,18 +182,18 @@ private void NUP_PartyIndex_ValueChanged(object sender, EventArgs e) TB_SID.Text = entry.SID16.ToString("00000"); TB_Nickname.Text = entry.Nickname; - TB_OT.Text = entry.OT_Name; + TB_OT.Text = entry.OriginalTrainerName; CHK_Shiny.Checked = entry.IsShiny; TB_Level.Text = entry.Level.ToString("000"); CHK_Nicknamed.Checked = entry.IsNicknamed; SetForms(); CB_Form.SelectedIndex = entry.Form; - SetGenderLabel((int)entry.Gender); - Label_OTGender.Text = gendersymbols[(int)entry.OT_Gender]; + SetGenderLabel((byte)entry.Gender); + Label_OTGender.Text = gendersymbols[(int)entry.OriginalTrainerGender]; UpdateNickname(sender, e); var shiny = entry.IsShiny ? Shiny.Always : Shiny.Never; - bpkx.Image = SpriteUtil.GetSprite(entry.Species, entry.Form, (int)entry.Gender, 0, entry.HeldItem, false, shiny, EntityContext.Gen6); + bpkx.Image = SpriteUtil.GetSprite(entry.Species, entry.Form, (byte)entry.Gender, 0, entry.HeldItem, false, shiny, EntityContext.Gen6); editing = true; } @@ -225,8 +225,8 @@ private void Write_Entry(object sender, EventArgs e) IsShiny = CHK_Shiny.Checked, IsNicknamed = CHK_Nicknamed.Checked, Nickname = TB_Nickname.Text, - OT_Name = TB_OT.Text, - OT_Gender = (uint)EntityGender.GetFromString(Label_OTGender.Text) & 1, + OriginalTrainerName = TB_OT.Text, + OriginalTrainerGender = (uint)EntityGender.GetFromString(Label_OTGender.Text) & 1, }; offset = index * StructureSize; @@ -244,7 +244,7 @@ private void Write_Entry(object sender, EventArgs e) WriteUInt32LittleEndian(data.AsSpan(offset + 0x1B0), vnd); var shiny = entry.IsShiny ? Shiny.Always : Shiny.Never; - bpkx.Image = SpriteUtil.GetSprite(entry.Species, entry.Form, (int)entry.Gender, 0, entry.HeldItem, false, shiny, EntityContext.Gen6); + bpkx.Image = SpriteUtil.GetSprite(entry.Species, entry.Form, (byte)entry.Gender, 0, entry.HeldItem, false, shiny, EntityContext.Gen6); DisplayEntry(this, EventArgs.Empty); // refresh text view } @@ -318,7 +318,8 @@ private void UpdateGender(object sender, EventArgs e) if (pi.IsDualGender) { var fg = EntityGender.GetFromString(Label_Gender.Text); - fg = (fg ^ 1) & 1; + fg ^= 1; + fg &= 1; Label_Gender.Text = gendersymbols[fg]; } else @@ -340,7 +341,7 @@ private void UpdateGender(object sender, EventArgs e) Write_Entry(this, EventArgs.Empty); } - private void SetGenderLabel(int gender) + private void SetGenderLabel(byte gender) { Label_Gender.Text = gender switch { diff --git a/PKHeX.WinForms/Subforms/Save Editors/Gen6/SAV_SecretBase.cs b/PKHeX.WinForms/Subforms/Save Editors/Gen6/SAV_SecretBase.cs index 14c591204..f6e05c7f6 100644 --- a/PKHeX.WinForms/Subforms/Save Editors/Gen6/SAV_SecretBase.cs +++ b/PKHeX.WinForms/Subforms/Save Editors/Gen6/SAV_SecretBase.cs @@ -187,7 +187,7 @@ private void SavePKM(SecretBase6PKM pk) pk.HeldItem = WinFormsUtil.GetIndex(CB_HeldItem); pk.Ability = WinFormsUtil.GetIndex(CB_Ability); pk.AbilityNumber = CB_Ability.SelectedIndex << 1; - pk.Nature = WinFormsUtil.GetIndex(CB_Nature); + pk.Nature = (Nature)WinFormsUtil.GetIndex(CB_Nature); pk.Gender = EntityGender.GetFromString(Label_Gender.Text); pk.Form = (byte)CB_Form.SelectedIndex; pk.EV_HP = Math.Clamp(Convert.ToInt32(TB_HPEV.Text) , 0, EffortValues.Max252); @@ -212,7 +212,7 @@ private void SavePKM(SecretBase6PKM pk) pk.IV_SPE = Convert.ToByte(TB_SPEIV.Text) & 0x1F; pk.IsShiny = CHK_Shiny.Checked; pk.CurrentFriendship = Convert.ToByte(TB_Friendship.Text); - pk.Ball = WinFormsUtil.GetIndex(CB_Ball); + pk.Ball = (byte)WinFormsUtil.GetIndex(CB_Ball); pk.CurrentLevel = Convert.ToByte(TB_Level.Text); } @@ -226,9 +226,9 @@ private void LoadPKM(SecretBase6PKM pk) CB_Species.SelectedValue = (int)pk.Species; CB_HeldItem.SelectedValue = pk.HeldItem; CB_Form.SelectedIndex = pk.Form; - - CB_Nature.SelectedValue = pk.Nature; - CB_Ball.SelectedValue = pk.Ball; + + CB_Nature.SelectedValue = (int)pk.Nature; + CB_Ball.SelectedValue = (int)pk.Ball; TB_HPIV.Text = pk.IV_HP.ToString(); TB_ATKIV.Text = pk.IV_ATK.ToString(); @@ -343,9 +343,10 @@ private void UpdateSpecies(object sender, EventArgs e) var species = WinFormsUtil.GetIndex(CB_Species); // Set a sane gender - var gender = SAV.Personal[species].RandomGender(); - if (gender == -1) - gender = EntityGender.GetFromString(Label_Gender.Text); + var pi = SAV.Personal[species]; + var gender = pi.IsDualGender + ? EntityGender.GetFromString(Label_Gender.Text) + : pi.FixedGender(); SetGenderLabel(gender); SetAbilityList(); @@ -364,15 +365,15 @@ private void Label_Gender_Click(object sender, EventArgs e) { var species = WinFormsUtil.GetIndex(CB_Species); var pi = SAV.Personal[species]; - int gender; + byte gender; if (pi.IsDualGender) // dual gender - gender = (EntityGender.GetFromString(Label_Gender.Text) ^ 1) & 1; + gender = (byte)((EntityGender.GetFromString(Label_Gender.Text) ^ 1) & 1); else gender = pi.FixedGender(); Label_Gender.Text = Main.GenderSymbols[gender]; } - private void SetGenderLabel(int gender) + private void SetGenderLabel(byte gender) { var symbols = Main.GenderSymbols; if ((uint)gender >= symbols.Count) diff --git a/PKHeX.WinForms/Subforms/Save Editors/Gen6/SAV_Trainer.cs b/PKHeX.WinForms/Subforms/Save Editors/Gen6/SAV_Trainer.cs index db525835b..746054f76 100644 --- a/PKHeX.WinForms/Subforms/Save Editors/Gen6/SAV_Trainer.cs +++ b/PKHeX.WinForms/Subforms/Save Editors/Gen6/SAV_Trainer.cs @@ -105,7 +105,7 @@ private void GetTextBoxes() // Get Data string OT_NAME = SAV.OT; - CB_Game.SelectedIndex = SAV.Game - 0x18; + CB_Game.SelectedIndex = (int)(SAV.Version - 0x18); CB_Gender.SelectedIndex = SAV.Gender; // Display Data @@ -166,7 +166,7 @@ private void GetTextBoxes() { var xystat = (MyStatus6XY)xy.Status; PG_CurrentAppearance.SelectedObject = xystat.Fashion; - TB_TRNick.Text = xystat.OT_Nick; + TB_TRNick.Text = xystat.Nickname; } CB_Vivillon.SelectedIndex = SAV.Vivillon; @@ -191,7 +191,7 @@ private void GetTextBoxes() private void Save() { - SAV.Game = (byte)(CB_Game.SelectedIndex + 0x18); + SAV.Version = (GameVersion)(CB_Game.SelectedIndex + 0x18); SAV.Gender = (byte)CB_Gender.SelectedIndex; SAV.TID16 = (ushort)Util.ToUInt32(MT_TID.Text); @@ -256,7 +256,7 @@ private void Save() { var xystat = (MyStatus6XY)xy.Status; xystat.Fashion = (TrainerFashion6)PG_CurrentAppearance.SelectedObject; - xystat.OT_Nick = TB_TRNick.Text; + xystat.Nickname = TB_TRNick.Text; } // Vivillon @@ -308,8 +308,10 @@ private void B_Save_Click(object sender, EventArgs e) private void Change255(object sender, EventArgs e) { MaskedTextBox box = (MaskedTextBox)sender; - if (box.Text.Length == 0) box.Text = "0"; - if (Util.ToInt32(box.Text) > 255) box.Text = "255"; + if (box.Text.Length == 0) + box.Text = "0"; + else if (Util.ToInt32(box.Text) > 255) + box.Text = "255"; } private void ChangeFFFF(object sender, EventArgs e) diff --git a/PKHeX.WinForms/Subforms/Save Editors/Gen7/SAV_FestivalPlaza.cs b/PKHeX.WinForms/Subforms/Save Editors/Gen7/SAV_FestivalPlaza.cs index 39a0cf8dd..cf8017a1d 100644 --- a/PKHeX.WinForms/Subforms/Save Editors/Gen7/SAV_FestivalPlaza.cs +++ b/PKHeX.WinForms/Subforms/Save Editors/Gen7/SAV_FestivalPlaza.cs @@ -264,7 +264,7 @@ private void LoadFacility() ? facility.NPC : 0; CHK_FacilityIntroduced.Checked = facility.IsIntroduced; - TB_OTName.Text = facility.OT_Name; + TB_OTName.Text = facility.OriginalTrainerName; LoadOTlabel(facility.Gender); if (CB_FacilityMessage.SelectedIndex >= 0) LoadFMessage(CB_FacilityMessage.SelectedIndex); @@ -556,7 +556,7 @@ private void SaveFacility() if (CB_FacilityType.SelectedIndex >= 0) facility.Type = CB_FacilityType.SelectedIndex; facility.Color = (byte)NUD_FacilityColor.Value; - facility.OT_Name = TB_OTName.Text; + facility.OriginalTrainerName = TB_OTName.Text; if (CB_FacilityNPC.SelectedIndex >= 0) facility.NPC = CB_FacilityNPC.SelectedIndex; facility.IsIntroduced = CHK_FacilityIntroduced.Checked; @@ -646,7 +646,7 @@ private void TB_OTName_TextChanged(object sender, EventArgs e) if (entry < 0) return; - f[entry].OT_Name = TB_OTName.Text; + f[entry].OriginalTrainerName = TB_OTName.Text; } private void LB_FacilityIndex_SelectedIndexChanged(object sender, EventArgs e) @@ -681,7 +681,7 @@ private void B_DelVisitor_Click(object sender, EventArgs e) if (facility.IsIntroduced) facility.ClearTrainerFesID(); facility.IsIntroduced = false; - facility.OT_Name = string.Empty; + facility.OriginalTrainerName = string.Empty; facility.Gender = 0; for (int i = 0; i < 4; i++) facility.SetMessage(i, 0); diff --git a/PKHeX.WinForms/Subforms/Save Editors/Gen7/SAV_PokedexGG.cs b/PKHeX.WinForms/Subforms/Save Editors/Gen7/SAV_PokedexGG.cs index 956d85561..44b770a80 100644 --- a/PKHeX.WinForms/Subforms/Save Editors/Gen7/SAV_PokedexGG.cs +++ b/PKHeX.WinForms/Subforms/Save Editors/Gen7/SAV_PokedexGG.cs @@ -49,7 +49,6 @@ public SAV_PokedexGG(SAV7b sav) private readonly Zukan7b Dex; private bool editing; private bool allModifying; - private ushort currentSpecies = ushort.MaxValue; private readonly CheckBox[] CP, CL; private readonly CheckBox[] RecordUsed, RecordFlag; @@ -68,8 +67,8 @@ private void ChangeCBSpecies(object sender, EventArgs e) SetEntry(); editing = true; - currentSpecies = (ushort)WinFormsUtil.GetIndex(CB_Species); - LB_Species.SelectedIndex = currentSpecies - 1; // Since we don't allow index0 in combobox, everything is shifted by 1 + var species = (ushort)WinFormsUtil.GetIndex(CB_Species); + SetCurrentIndex(species - 1); LB_Species.TopIndex = LB_Species.SelectedIndex; if (!allModifying) FillLBForms(); @@ -77,6 +76,10 @@ private void ChangeCBSpecies(object sender, EventArgs e) editing = false; } + private int currentIndex = -1; + private int GetCurrentIndex() => currentIndex; + private void SetCurrentIndex(int index) => LB_Species.SelectedIndex = currentIndex = index; + private void ChangeLBSpecies(object sender, EventArgs e) { if (editing) @@ -84,8 +87,10 @@ private void ChangeLBSpecies(object sender, EventArgs e) SetEntry(); editing = true; - currentSpecies = (ushort)(LB_Species.SelectedIndex + 1); - CB_Species.SelectedValue = (int)currentSpecies; + SetCurrentIndex(LB_Species.SelectedIndex); + var index = GetCurrentIndex(); + var species = Dex.GetBaseSpecies(index); + CB_Species.SelectedValue = (int)species; if (!allModifying) FillLBForms(); GetEntry(); @@ -101,65 +106,64 @@ private void ChangeLBForms(object sender, EventArgs e) SetEntry(); editing = true; - var fspecies = (ushort)(LB_Species.SelectedIndex + 1); - var bspecies = Dex.GetBaseSpecies(fspecies); + var index = GetCurrentIndex(); + var species = Dex.GetBaseSpecies(index); var form = (byte)LB_Forms.SelectedIndex; - currentSpecies = Dex.GetSpecies(bspecies, form); + index = Dex.GetEntryIndex(species, form); + SetCurrentIndex(index); - CB_Species.SelectedValue = (int)currentSpecies; - LB_Species.SelectedIndex = currentSpecies - 1; - LB_Species.TopIndex = LB_Species.SelectedIndex; + CB_Species.SelectedValue = (int)species; + LB_Species.TopIndex = index; GetEntry(); editing = false; } - private bool FillLBForms() + private void FillLBForms() { if (allModifying) - return false; + return; LB_Forms.DataSource = null; LB_Forms.Items.Clear(); - var fspecies = (ushort)(LB_Species.SelectedIndex + 1); - var bspecies = Dex.GetBaseSpecies(fspecies); - bool hasForms = FormInfo.HasFormSelection(SAV.Personal[bspecies], bspecies, 7); + var index = GetCurrentIndex(); + var species = Dex.GetBaseSpecies(index); + bool hasForms = FormInfo.HasFormSelection(SAV.Personal[species], species, 7); LB_Forms.Enabled = hasForms; if (!hasForms) - return false; - var ds = FormConverter.GetFormList(bspecies, GameInfo.Strings.types, GameInfo.Strings.forms, Main.GenderSymbols, SAV.Context).ToList(); + return; + var ds = FormConverter.GetFormList(species, GameInfo.Strings.types, GameInfo.Strings.forms, Main.GenderSymbols, SAV.Context).ToList(); if (ds.Count == 1 && string.IsNullOrEmpty(ds[0])) { // empty LB_Forms.Enabled = false; - return false; + return; } // sanity check forms -- GG does not have totem form dex bits - int count = SAV.Personal[bspecies].FormCount; + int count = SAV.Personal[species].FormCount; if (count < ds.Count) ds.RemoveAt(count); // remove last LB_Forms.DataSource = ds; - if (fspecies <= SAV.MaxSpeciesID) + if (index < SAV.MaxSpeciesID) { LB_Forms.SelectedIndex = 0; } else { - var fc = SAV.Personal[bspecies].FormCount; + var fc = SAV.Personal[species].FormCount; if (fc <= 1) - return true; + return; - int f = Dex.DexFormIndexFetcher(bspecies, fc, SAV.MaxSpeciesID - 1); + int f = Dex.GetCountFormsPriorTo(species, fc); if (f < 0) - return true; // bit index valid - - if (f > fspecies - LB_Forms.Items.Count - 1) - LB_Forms.SelectedIndex = fspecies - f - 1; + return; // bit index valid + var form = index - f - (SAV.MaxSpeciesID - 1); + if (form < LB_Forms.Items.Count) + LB_Forms.SelectedIndex = form; else LB_Forms.SelectedIndex = -1; } - return true; } private void ChangeDisplayed(object sender, EventArgs e) @@ -199,59 +203,65 @@ private void ChangeEncountered(object sender, EventArgs e) private void GetEntry() { - var pk = (ushort)(currentSpecies - 1); + var index = GetCurrentIndex(); + var species = (ushort)(index + 1); + bool isSpeciesEntry = species <= SAV.MaxSpeciesID; editing = true; - CHK_P1.Enabled = currentSpecies <= SAV.MaxSpeciesID; - CHK_P1.Checked = CHK_P1.Enabled && Dex.GetCaught(currentSpecies); - var gt = Dex.GetBaseSpeciesGenderValue(LB_Species.SelectedIndex); + CHK_P1.Enabled = isSpeciesEntry; + CHK_P1.Checked = CHK_P1.Enabled && Dex.GetCaught(species); + var gt = Dex.GetBaseSpeciesGenderValue(index); bool canBeMale = gt != PersonalInfo.RatioMagicFemale; bool canBeFemale = gt is not (PersonalInfo.RatioMagicMale or PersonalInfo.RatioMagicGenderless); CHK_P2.Enabled = CHK_P4.Enabled = CHK_P6.Enabled = CHK_P8.Enabled = canBeMale; // Not Female-Only CHK_P3.Enabled = CHK_P5.Enabled = CHK_P7.Enabled = CHK_P9.Enabled = canBeFemale; // Not Male-Only and Not Genderless for (int i = 0; i < 4; i++) - CP[i + 1].Checked = Dex.GetSeen(currentSpecies, i); + CP[i + 1].Checked = Dex.GetSeen(species, i); for (int i = 0; i < 4; i++) - CP[i + 5].Checked = Dex.GetDisplayed(currentSpecies - 1, i); + CP[i + 5].Checked = Dex.GetDisplayed(index, i); for (int i = 0; i < 9; i++) { - CL[i].Enabled = currentSpecies <= SAV.MaxSpeciesID; - CL[i].Checked = CL[i].Enabled && Dex.GetLanguageFlag(pk, i); + CL[i].Enabled = isSpeciesEntry; + CL[i].Checked = CL[i].Enabled && Dex.GetLanguageFlag(index, i); } - var speciesID = Dex.GetBaseSpecies(currentSpecies); - LoadRecord(speciesID, (byte)Math.Max(0, LB_Forms.SelectedIndex)); + if (!isSpeciesEntry) + species = Dex.GetBaseSpecies(index); + LoadRecord(species, (byte)Math.Max(0, LB_Forms.SelectedIndex)); editing = false; } private void SetEntry() { - if (currentSpecies == 0) + if (currentIndex < 0) return; - int pk = currentSpecies - 1; + var index = GetCurrentIndex(); + var species = (ushort)(index + 1); + var isSpeciesEntry = species <= SAV.MaxSpeciesID; for (int i = 0; i < 4; i++) - Dex.SetSeen(currentSpecies, i, CP[i + 1].Checked); + Dex.SetSeen(species, i, CP[i + 1].Checked); for (int i = 0; i < 4; i++) - Dex.SetDisplayed(pk, i, CP[i + 5].Checked); + Dex.SetDisplayed(index, i, CP[i + 5].Checked); - if (currentSpecies > SAV.MaxSpeciesID) + if (!isSpeciesEntry) return; - Dex.SetCaught(currentSpecies, CHK_P1.Checked); + Dex.SetCaught(species, CHK_P1.Checked); for (int i = 0; i < 9; i++) - Dex.SetLanguageFlag(pk, i, CL[i].Checked); + Dex.SetLanguageFlag(index, i, CL[i].Checked); - var speciesID = Dex.GetBaseSpecies(currentSpecies); - SetRecord(speciesID, (byte)Math.Max(0, LB_Forms.SelectedIndex)); + if (!isSpeciesEntry) + species = Dex.GetBaseSpecies(index); + SetRecord(species, (byte)Math.Max(0, LB_Forms.SelectedIndex)); } private void LoadRecord(ushort species, byte form) @@ -306,10 +316,7 @@ private void CHK_RUsed_CheckedChanged(object sender, EventArgs e) w.Value = Zukan7b.DefaultEntryValueW; } - private void B_Cancel_Click(object sender, EventArgs e) - { - Close(); - } + private void B_Cancel_Click(object sender, EventArgs e) => Close(); private void B_Save_Click(object sender, EventArgs e) { @@ -321,26 +328,18 @@ private void B_Save_Click(object sender, EventArgs e) private void B_GiveAll_Click(object sender, EventArgs e) { + var index = GetCurrentIndex(); if (CHK_L1.Enabled) { - CHK_L1.Checked = - CHK_L2.Checked = - CHK_L3.Checked = - CHK_L4.Checked = - CHK_L5.Checked = - CHK_L6.Checked = - CHK_L7.Checked = - CHK_L8.Checked = - CHK_L9.Checked = ModifierKeys != Keys.Control; + foreach (var cb in CL) + cb.Checked = ModifierKeys != Keys.Control; } if (CHK_P1.Enabled) - { CHK_P1.Checked = ModifierKeys != Keys.Control; - } - byte gt = Dex.GetBaseSpeciesGenderValue(LB_Species.SelectedIndex); - bool canBeMale = gt != PersonalInfo.RatioMagicFemale; - bool canBeFemale = gt is not (PersonalInfo.RatioMagicMale or PersonalInfo.RatioMagicGenderless); + var gt = Dex.GetBaseSpeciesGenderValue(index); + var canBeMale = gt != PersonalInfo.RatioMagicFemale; + var canBeFemale = gt is not (PersonalInfo.RatioMagicMale or PersonalInfo.RatioMagicGenderless); CHK_P2.Checked = CHK_P4.Checked = canBeMale && ModifierKeys != Keys.Control; CHK_P3.Checked = CHK_P5.Checked = canBeFemale && ModifierKeys != Keys.Control; diff --git a/PKHeX.WinForms/Subforms/Save Editors/Gen7/SAV_PokedexSM.cs b/PKHeX.WinForms/Subforms/Save Editors/Gen7/SAV_PokedexSM.cs index af76d80b2..f83173d1c 100644 --- a/PKHeX.WinForms/Subforms/Save Editors/Gen7/SAV_PokedexSM.cs +++ b/PKHeX.WinForms/Subforms/Save Editors/Gen7/SAV_PokedexSM.cs @@ -43,7 +43,6 @@ public SAV_PokedexSM(SAV7 sav) private readonly Zukan7 Dex; private bool editing; private bool allModifying; - private ushort currentSpecies = ushort.MaxValue; private readonly CheckBox[] CP, CL; private void ChangeCBSpecies(object sender, EventArgs e) @@ -53,14 +52,18 @@ private void ChangeCBSpecies(object sender, EventArgs e) SetEntry(); editing = true; - currentSpecies = (ushort)WinFormsUtil.GetIndex(CB_Species); - LB_Species.SelectedIndex = currentSpecies - 1; // Since we don't allow index0 in combobox, everything is shifted by 1 + var species = (ushort)WinFormsUtil.GetIndex(CB_Species); + SetCurrentIndex(species - 1); LB_Species.TopIndex = LB_Species.SelectedIndex; if (!allModifying) FillLBForms(); GetEntry(); editing = false; } + private int currentIndex = -1; + private int GetCurrentIndex() => currentIndex; + private void SetCurrentIndex(int index) => LB_Species.SelectedIndex = currentIndex = index; + private void ChangeLBSpecies(object sender, EventArgs e) { if (editing) @@ -68,8 +71,10 @@ private void ChangeLBSpecies(object sender, EventArgs e) SetEntry(); editing = true; - currentSpecies = (ushort)(LB_Species.SelectedIndex + 1); - CB_Species.SelectedValue = (int)currentSpecies; + SetCurrentIndex(LB_Species.SelectedIndex); + var index = GetCurrentIndex(); + var species = Dex.GetBaseSpecies(index); + CB_Species.SelectedValue = (int)species; if (!allModifying) FillLBForms(); GetEntry(); @@ -83,82 +88,64 @@ private void ChangeLBForms(object sender, EventArgs e) SetEntry(); editing = true; - var fspecies = (ushort)(LB_Species.SelectedIndex + 1); - var bspecies = Dex.GetBaseSpecies(fspecies); - int form = LB_Forms.SelectedIndex; - if (form > 0) - { - var fc = SAV.Personal[bspecies].FormCount; - if (fc > 1) // actually has forms - { - int f = Dex.GetDexFormIndex(bspecies, fc, form); - currentSpecies = f >= 0 ? (ushort)(f + 1) : bspecies; - } - else - { - currentSpecies = bspecies; - } - } - else - { - currentSpecies = bspecies; - } + var index = GetCurrentIndex(); + var species = Dex.GetBaseSpecies(index); + var form = (byte)LB_Forms.SelectedIndex; + index = Dex.GetEntryIndex(species, form); + SetCurrentIndex(index); - CB_Species.SelectedValue = currentSpecies; - LB_Species.SelectedIndex = currentSpecies - 1; - LB_Species.TopIndex = LB_Species.SelectedIndex; + CB_Species.SelectedValue = (int)species; + LB_Species.TopIndex = index; GetEntry(); editing = false; } - private bool FillLBForms() + private void FillLBForms() { if (allModifying) - return false; + return; LB_Forms.DataSource = null; LB_Forms.Items.Clear(); - var fspecies = (ushort)(LB_Species.SelectedIndex + 1); - var bspecies = Dex.GetBaseSpecies(fspecies); - bool hasForms = FormInfo.HasFormSelection(SAV.Personal[bspecies], bspecies, 7); + var index = GetCurrentIndex(); + var species = Dex.GetBaseSpecies(index); + bool hasForms = FormInfo.HasFormSelection(SAV.Personal[species], species, 7); LB_Forms.Enabled = hasForms; if (!hasForms) - return false; - var ds = FormConverter.GetFormList(bspecies, GameInfo.Strings.types, GameInfo.Strings.forms, Main.GenderSymbols, SAV.Context).ToList(); + return; + var ds = FormConverter.GetFormList(species, GameInfo.Strings.types, GameInfo.Strings.forms, Main.GenderSymbols, SAV.Context).ToList(); if (ds.Count == 1 && string.IsNullOrEmpty(ds[0])) { // empty LB_Forms.Enabled = false; - return false; + return; } // sanity check forms -- S/M does not have totem form dex bits - int count = SAV.Personal[bspecies].FormCount; + int count = SAV.Personal[species].FormCount; if (count < ds.Count) ds.RemoveAt(count); // remove last LB_Forms.DataSource = ds; - if (fspecies <= SAV.MaxSpeciesID) + if (index < SAV.MaxSpeciesID) { LB_Forms.SelectedIndex = 0; } else { - var fc = SAV.Personal[bspecies].FormCount; + var fc = SAV.Personal[species].FormCount; if (fc <= 1) - return true; + return; - int f = Dex.GetDexFormIndex(bspecies, fc, 0); + int f = Dex.GetCountFormsPriorTo(species, fc); if (f < 0) - return true; // bit index valid - - var findex = fspecies - f - 1; - if (findex < LB_Forms.Items.Count) - LB_Forms.SelectedIndex = findex; + return; // bit index valid + var form = index - f - (SAV.MaxSpeciesID - 1); + if (form < LB_Forms.Items.Count) + LB_Forms.SelectedIndex = form; else LB_Forms.SelectedIndex = -1; } - return true; } private void ChangeDisplayed(object sender, EventArgs e) @@ -198,58 +185,56 @@ private void ChangeEncountered(object sender, EventArgs e) private void GetEntry() { - int pk = currentSpecies - 1; + var index = GetCurrentIndex(); + var species = (ushort)(index + 1); + bool isSpeciesEntry = species <= SAV.MaxSpeciesID; editing = true; - CHK_P1.Enabled = currentSpecies <= SAV.MaxSpeciesID; - CHK_P1.Checked = CHK_P1.Enabled && Dex.GetCaught(currentSpecies); - byte gt = Dex.GetBaseSpeciesGenderValue(LB_Species.SelectedIndex); - - bool canBeMale = gt != PersonalInfo.RatioMagicFemale; - bool canBeFemale = gt is not (PersonalInfo.RatioMagicMale or PersonalInfo.RatioMagicGenderless); + var gt = Dex.GetBaseSpeciesGenderValue(index); + var canBeMale = gt != PersonalInfo.RatioMagicFemale; + var canBeFemale = gt is not (PersonalInfo.RatioMagicMale or PersonalInfo.RatioMagicGenderless); CHK_P2.Enabled = CHK_P4.Enabled = CHK_P6.Enabled = CHK_P8.Enabled = canBeMale; // Not Female-Only CHK_P3.Enabled = CHK_P5.Enabled = CHK_P7.Enabled = CHK_P9.Enabled = canBeFemale; // Not Male-Only and Not Genderless for (int i = 0; i < 4; i++) - CP[i + 1].Checked = Dex.GetSeen(currentSpecies, i); + CP[i + 1].Checked = Dex.GetSeen(species, i); for (int i = 0; i < 4; i++) - CP[i + 5].Checked = Dex.GetDisplayed(pk, i); + CP[i + 5].Checked = Dex.GetDisplayed(index, i); for (int i = 0; i < 9; i++) { - CL[i].Enabled = currentSpecies <= SAV.MaxSpeciesID; - CL[i].Checked = CL[i].Enabled && Dex.GetLanguageFlag(pk, i); + CL[i].Enabled = isSpeciesEntry; + CL[i].Checked = CL[i].Enabled && Dex.GetLanguageFlag(index, i); } editing = false; } private void SetEntry() { - if (currentSpecies == 0) + if (currentIndex < 0) return; - int bit = currentSpecies - 1; + var index = GetCurrentIndex(); + var species = (ushort)(index + 1); + bool isSpeciesEntry = species <= SAV.MaxSpeciesID; for (int i = 0; i < 4; i++) - Dex.SetSeen(currentSpecies, i, CP[i + 1].Checked); + Dex.SetSeen(species, i, CP[i + 1].Checked); for (int i = 0; i < 4; i++) - Dex.SetDisplayed(bit, i, CP[i + 5].Checked); + Dex.SetDisplayed(index, i, CP[i + 5].Checked); - if (currentSpecies > SAV.MaxSpeciesID) + if (!isSpeciesEntry) return; - Dex.SetCaught(currentSpecies, CHK_P1.Checked); + Dex.SetCaught(species, CHK_P1.Checked); for (int i = 0; i < 9; i++) - Dex.SetLanguageFlag(bit, i, CL[i].Checked); + Dex.SetLanguageFlag(index, i, CL[i].Checked); } - private void B_Cancel_Click(object sender, EventArgs e) - { - Close(); - } + private void B_Cancel_Click(object sender, EventArgs e) => Close(); private void B_Save_Click(object sender, EventArgs e) { @@ -260,26 +245,18 @@ private void B_Save_Click(object sender, EventArgs e) private void B_GiveAll_Click(object sender, EventArgs e) { + var index = GetCurrentIndex(); if (CHK_L1.Enabled) { - CHK_L1.Checked = - CHK_L2.Checked = - CHK_L3.Checked = - CHK_L4.Checked = - CHK_L5.Checked = - CHK_L6.Checked = - CHK_L7.Checked = - CHK_L8.Checked = - CHK_L9.Checked = ModifierKeys != Keys.Control; + foreach (var cb in CL) + cb.Checked = ModifierKeys != Keys.Control; } if (CHK_P1.Enabled) - { CHK_P1.Checked = ModifierKeys != Keys.Control; - } - byte gt = Dex.GetBaseSpeciesGenderValue(LB_Species.SelectedIndex); - bool canBeMale = gt != PersonalInfo.RatioMagicFemale; - bool canBeFemale = gt is not (PersonalInfo.RatioMagicMale or PersonalInfo.RatioMagicGenderless); + var gt = Dex.GetBaseSpeciesGenderValue(index); + var canBeMale = gt != PersonalInfo.RatioMagicFemale; + var canBeFemale = gt is not (PersonalInfo.RatioMagicMale or PersonalInfo.RatioMagicGenderless); CHK_P2.Checked = CHK_P4.Checked = canBeMale && ModifierKeys != Keys.Control; CHK_P3.Checked = CHK_P5.Checked = canBeFemale && ModifierKeys != Keys.Control; diff --git a/PKHeX.WinForms/Subforms/Save Editors/Gen7/SAV_Trainer7.cs b/PKHeX.WinForms/Subforms/Save Editors/Gen7/SAV_Trainer7.cs index 8531808ab..982131a98 100644 --- a/PKHeX.WinForms/Subforms/Save Editors/Gen7/SAV_Trainer7.cs +++ b/PKHeX.WinForms/Subforms/Save Editors/Gen7/SAV_Trainer7.cs @@ -98,7 +98,7 @@ private static ComboItem[] GetAlolaTimeList() private void GetTextBoxes() { // Get Data - CB_Game.SelectedIndex = SAV.Game - (int)GameVersion.SN; + CB_Game.SelectedIndex = SAV.Version - GameVersion.SN; CB_Gender.SelectedIndex = SAV.Gender; // Display Data @@ -322,7 +322,7 @@ private void Save() private void SaveTrainerInfo() { - SAV.Game = (byte)(CB_Game.SelectedIndex + 30); + SAV.Version = (GameVersion)(CB_Game.SelectedIndex + 30); SAV.Gender = (byte)CB_Gender.SelectedIndex; SAV.Money = Util.ToUInt32(MT_Money.Text); @@ -396,7 +396,7 @@ private void SaveBattleTree() private void SaveTrainerAppearance() { // Skin changed && (gender matches || override) - int gender = CB_Gender.SelectedIndex & 1; + byte gender = (byte)(CB_Gender.SelectedIndex & 1); int skin = CB_SkinColor.SelectedIndex & 1; var gStr = CB_Gender.Items[gender]!.ToString(); var sStr = CB_Gender.Items[skin]!.ToString(); @@ -411,7 +411,7 @@ private void SaveTrainerAppearance() private void SaveThrowType() { if (CB_BallThrowType.SelectedIndex >= 0) - SAV.MyStatus.BallThrowType = CB_BallThrowType.SelectedIndex; + SAV.MyStatus.BallThrowType = (byte)CB_BallThrowType.SelectedIndex; if (SAV is not SAV7SM) // unlock flags are in flag editor instead return; diff --git a/PKHeX.WinForms/Subforms/Save Editors/Gen7/SAV_Trainer7GG.cs b/PKHeX.WinForms/Subforms/Save Editors/Gen7/SAV_Trainer7GG.cs index 5e8326a24..4d6e81e46 100644 --- a/PKHeX.WinForms/Subforms/Save Editors/Gen7/SAV_Trainer7GG.cs +++ b/PKHeX.WinForms/Subforms/Save Editors/Gen7/SAV_Trainer7GG.cs @@ -71,7 +71,7 @@ private void LoadTrainerInfo() CB_Language.SelectedValue = SAV.Language; MT_Money.Text = SAV.Blocks.Misc.Money.ToString(); - CB_Game.SelectedValue = SAV.Game; + CB_Game.SelectedValue = (int)SAV.Version; CB_Gender.SelectedIndex = SAV.Gender; trainerID1.LoadIDValues(SAV, SAV.Generation); @@ -102,7 +102,7 @@ private void Save() private void SaveTrainerInfo() { - SAV.Game = WinFormsUtil.GetIndex(CB_Game); + SAV.Version = (GameVersion)WinFormsUtil.GetIndex(CB_Game); SAV.Gender = (byte)CB_Gender.SelectedIndex; SAV.Money = Util.ToUInt32(MT_Money.Text); diff --git a/PKHeX.WinForms/Subforms/Save Editors/Gen8/SAV_Trainer8.cs b/PKHeX.WinForms/Subforms/Save Editors/Gen8/SAV_Trainer8.cs index f46b98fa9..2cb73f8b3 100644 --- a/PKHeX.WinForms/Subforms/Save Editors/Gen8/SAV_Trainer8.cs +++ b/PKHeX.WinForms/Subforms/Save Editors/Gen8/SAV_Trainer8.cs @@ -55,7 +55,7 @@ private void GetComboBoxes() private void GetTextBoxes() { // Get Data - CB_Game.SelectedIndex = SAV.Game - (int)GameVersion.SW; + CB_Game.SelectedIndex = SAV.Version - GameVersion.SW; CB_Gender.SelectedIndex = SAV.Gender; // Display Data @@ -136,7 +136,7 @@ private void Save() private void SaveTrainerInfo() { - SAV.Game = (byte)(CB_Game.SelectedIndex + (int)GameVersion.SW); + SAV.Version = (GameVersion)(CB_Game.SelectedIndex + (int)GameVersion.SW); SAV.Gender = (byte)CB_Gender.SelectedIndex; SAV.Money = Util.ToUInt32(MT_Money.Text); diff --git a/PKHeX.WinForms/Subforms/Save Editors/Gen8/SAV_Trainer8b.cs b/PKHeX.WinForms/Subforms/Save Editors/Gen8/SAV_Trainer8b.cs index 5370794c2..dfc89b0f1 100644 --- a/PKHeX.WinForms/Subforms/Save Editors/Gen8/SAV_Trainer8b.cs +++ b/PKHeX.WinForms/Subforms/Save Editors/Gen8/SAV_Trainer8b.cs @@ -46,7 +46,7 @@ private void GetComboBoxes() private void GetTextBoxes() { // Get Data - CB_Game.SelectedIndex = Math.Clamp(SAV.Game - (int)GameVersion.BD, 0, 1); + CB_Game.SelectedIndex = Math.Clamp((byte)SAV.Version - (byte)GameVersion.BD, 0, 1); CB_Gender.SelectedIndex = SAV.Gender; NUD_BP.Value = SAV.BattleTower.BP; @@ -103,7 +103,7 @@ private void Save() private void SaveTrainerInfo() { - SAV.Game = (byte)(CB_Game.SelectedIndex + (int)GameVersion.BD); + SAV.Version = (GameVersion)(CB_Game.SelectedIndex + (int)GameVersion.BD); SAV.Gender = (byte)CB_Gender.SelectedIndex; SAV.Money = Util.ToUInt32(MT_Money.Text); diff --git a/PKHeX.WinForms/Subforms/Save Editors/Gen9/SAV_Trainer9.cs b/PKHeX.WinForms/Subforms/Save Editors/Gen9/SAV_Trainer9.cs index a47653346..1481e888c 100644 --- a/PKHeX.WinForms/Subforms/Save Editors/Gen9/SAV_Trainer9.cs +++ b/PKHeX.WinForms/Subforms/Save Editors/Gen9/SAV_Trainer9.cs @@ -106,7 +106,7 @@ private void GetComboBoxes() private void GetTextBoxes() { // Get Data - CB_Game.SelectedIndex = SAV.Game - (int)GameVersion.SL; + CB_Game.SelectedIndex = SAV.Version - GameVersion.SL; CB_Gender.SelectedIndex = SAV.Gender; // Display Data @@ -152,7 +152,7 @@ private void SaveMap() private void SaveTrainerInfo() { - SAV.Game = (byte)(CB_Game.SelectedIndex + (int)GameVersion.SL); + SAV.Version = (GameVersion)(CB_Game.SelectedIndex + (byte)GameVersion.SL); SAV.Gender = (byte)CB_Gender.SelectedIndex; SAV.Money = Util.ToUInt32(MT_Money.Text); diff --git a/PKHeX.WinForms/Subforms/Save Editors/SAV_MailBox.cs b/PKHeX.WinForms/Subforms/Save Editors/SAV_MailBox.cs index 010f127f9..d2844217a 100644 --- a/PKHeX.WinForms/Subforms/Save Editors/SAV_MailBox.cs +++ b/PKHeX.WinForms/Subforms/Save Editors/SAV_MailBox.cs @@ -11,12 +11,27 @@ public partial class SAV_MailBox : Form private readonly SaveFile Origin; private readonly SaveFile SAV; + private readonly MailDetail[] m = null!; + private bool editing; + private int entry; + private readonly NumericUpDown[][] Messages; + private readonly NumericUpDown[] PKMNUDs, Miscs; + private readonly Label[] PKMLabels, PKMHeldItems; + private readonly ComboBox[] AppearPKMs; + private readonly byte Generation; + private readonly byte ResetVer, ResetLang; + private readonly int PartyBoxCount; + private string loadedLBItemLabel = null!; + private bool LabelValue_GenderF; + private readonly int[] MailItemID = null!; + private readonly IList p; + public SAV_MailBox(SaveFile sav) { InitializeComponent(); WinFormsUtil.TranslateInterface(this, Main.CurrentLanguage); SAV = (Origin = sav).Clone(); - Gen = SAV.Generation; + Generation = SAV.Generation; p = SAV.PartyData; editing = true; @@ -32,20 +47,20 @@ public SAV_MailBox(SaveFile sav) AppearPKMs = [CB_AppearPKM1, CB_AppearPKM2, CB_AppearPKM3]; Miscs = [NUD_Misc1, NUD_Misc2, NUD_Misc3]; - NUD_BoxSize.Visible = L_BoxSize.Visible = Gen == 2; - GB_MessageTB.Visible = Gen == 2; - GB_MessageNUD.Visible = Gen != 2; - Messages[0][3].Visible = Messages[1][3].Visible = Messages[2][3].Visible = Gen is 4 or 5; - NUD_AuthorSID.Visible = Gen != 2; - Label_OTGender.Visible = CB_AuthorLang.Visible = CB_AuthorVersion.Visible = Gen is 4 or 5; - L_AppearPKM.Visible = AppearPKMs[0].Visible = Gen != 5; - AppearPKMs[1].Visible = AppearPKMs[2].Visible = Gen == 4; - NUD_MessageEnding.Visible = Gen == 5; - L_MiscValue.Visible = NUD_Misc1.Visible = NUD_Misc2.Visible = NUD_Misc3.Visible = Gen == 5; + NUD_BoxSize.Visible = L_BoxSize.Visible = Generation == 2; + GB_MessageTB.Visible = Generation == 2; + GB_MessageNUD.Visible = Generation != 2; + Messages[0][3].Visible = Messages[1][3].Visible = Messages[2][3].Visible = Generation is 4 or 5; + NUD_AuthorSID.Visible = Generation != 2; + Label_OTGender.Visible = CB_AuthorLang.Visible = CB_AuthorVersion.Visible = Generation is 4 or 5; + L_AppearPKM.Visible = AppearPKMs[0].Visible = Generation != 5; + AppearPKMs[1].Visible = AppearPKMs[2].Visible = Generation == 4; + NUD_MessageEnding.Visible = Generation == 5; + L_MiscValue.Visible = NUD_Misc1.Visible = NUD_Misc2.Visible = NUD_Misc3.Visible = Generation == 5; for (int i = p.Count; i < 6; i++) PKMNUDs[i].Visible = PKMLabels[i].Visible = PKMHeldItems[i].Visible = false; - if (Gen != 3) + if (Generation != 3) { for (int i = 0; i < PKMNUDs.Length; i++) { @@ -101,14 +116,14 @@ public SAV_MailBox(SaveFile sav) MakePartyList(); MakePCList(); - if (Gen is 2 or 3) + if (Generation is 2 or 3) { CB_AppearPKM1.Items.Clear(); CB_AppearPKM1.InitializeBinding(); CB_AppearPKM1.DataSource = new BindingSource(GameInfo.FilteredSources.Species.ToList(), null); B_PartyUp.Visible = B_PartyDown.Visible = B_BoxUp.Visible = B_BoxDown.Visible = true; } - else if (Gen is 4 or 5) + else if (Generation is 4 or 5) { var species = GameInfo.FilteredSources.Species.ToList(); foreach (ComboBox a in AppearPKMs) @@ -120,7 +135,7 @@ public SAV_MailBox(SaveFile sav) CB_AuthorVersion.Items.Clear(); CB_AuthorVersion.InitializeBinding(); - CB_AuthorVersion.DataSource = new BindingSource(Gen == 4 + CB_AuthorVersion.DataSource = new BindingSource(Generation == 4 ? new[] { new ComboItem("Diamond", (int)GameVersion.D), new ComboItem("Pearl", (int)GameVersion.P), @@ -183,7 +198,7 @@ private void MakePCList() { LB_PCBOX.BeginUpdate(); LB_PCBOX.Items.Clear(); - if (Gen == 2) + if (Generation == 2) { for (int i = PartyBoxCount, j = 0, boxsize = (int)NUD_BoxSize.Value; i < m.Length; i++, j++) { @@ -208,7 +223,7 @@ private void LoadPKM(bool isInit) PKMLabels[i].Text = GetSpeciesNameFromCB(p[i].Species); int j = Array.IndexOf(MailItemID, p[i].HeldItem); PKMHeldItems[i].Text = j >= 0 ? CB_MailType.Items[j + 1]!.ToString() : "(not Mail)"; - if (Gen != 3) + if (Generation != 3) continue; int k = ((PK3)p[i]).HeldMailID; PKMNUDs[i].Value = k is >= -1 and <= 5 ? k : -1; @@ -216,24 +231,9 @@ private void LoadPKM(bool isInit) editing = false; } - private readonly MailDetail[] m = null!; - private bool editing; - private int entry; - private readonly NumericUpDown[][] Messages; - private readonly NumericUpDown[] PKMNUDs, Miscs; - private readonly Label[] PKMLabels, PKMHeldItems; - private readonly ComboBox[] AppearPKMs; - private readonly int Gen; - private readonly byte ResetVer, ResetLang; - private readonly int PartyBoxCount; - private string loadedLBItemLabel = null!; - private bool LabelValue_GenderF; - private readonly int[] MailItemID = null!; - private readonly IList p; - private void Save() { - switch (Gen) + switch (Generation) { case 2: foreach (var n in m) n.CopyTo(SAV); @@ -274,19 +274,19 @@ private void TempSave() mail.MailType = CBIndexToMailType(CB_MailType.SelectedIndex); // ReSharper disable once ConstantNullCoalescingCondition var species = (ushort)WinFormsUtil.GetIndex(CB_AppearPKM1); - if (Gen == 2) + if (Generation == 2) { mail.AppearPKM = species; mail.SetMessage(TB_MessageBody21.Text, TB_MessageBody22.Text); return; } mail.AuthorSID = (ushort)NUD_AuthorSID.Value; - for (int y = 0, xc = Gen == 3 ? 3 : 4; y < 3; y++) + for (int y = 0, xc = Generation == 3 ? 3 : 4; y < 3; y++) { for (int x = 0; x < xc; x++) mail.SetMessage(y, x, (ushort)Messages[y][x].Value); } - if (Gen == 3) + if (Generation == 3) { mail.AppearPKM = SpeciesConverter.GetInternal3(species); return; @@ -330,7 +330,7 @@ private List CheckValid() // C: held item is not mail, but heldMailID is not -1. it should be -1, or held mail and mail not empty. // D: other pk have same heldMailID. it should be different. // E: mail is not empty, but no pk refer to the mail. it should be empty, or someone refer to the mail. - if (Gen == 3) + if (Generation == 3) { Span heldMailIDs = stackalloc int[p.Count]; for (int i = 0; i < p.Count; i++) @@ -361,7 +361,7 @@ private List CheckValid() // Gen2, Gen4 // P: held item is mail, but mail is empty(invalid mail type. g2:not 181 to 189, g4:12 to 255). it should be not empty or held not mail. // Q: held item is not mail, but mail is not empty. it should be empty or held mail. - else if (Gen is 2 or 4) + else if (Generation is 2 or 4) { for (int i = 0; i < p.Count; i++) { @@ -379,7 +379,7 @@ private List CheckValid() // Gen5 // P // Gen5, move mail to pc will not erase mail data, still remains, duplicates. - else if (Gen == 5) + else if (Generation == 5) { for (int i = 0; i < p.Count; i++) { @@ -416,8 +416,8 @@ private void B_Save_Click(object sender, EventArgs e) private string GetLBLabel(int index) => m[index].IsEmpty != true ? $"{index}: From {m[index].AuthorName}" : $"{index}: (empty)"; private bool ItemIsMail(int itemID) => Array.IndexOf(MailItemID, itemID) >= 0; - private int MailTypeToCBIndex(MailDetail mail) => Gen <= 3 ? 1 + Array.IndexOf(MailItemID, mail.MailType) : (mail.IsEmpty == false ? 1 + mail.MailType : 0); - private int CBIndexToMailType(int cbindex) => Gen <= 3 ? (cbindex > 0 ? MailItemID[cbindex - 1] : 0) : (cbindex > 0 ? cbindex - 1 : 0xFF); + private int MailTypeToCBIndex(MailDetail mail) => Generation <= 3 ? 1 + Array.IndexOf(MailItemID, mail.MailType) : (mail.IsEmpty == false ? 1 + mail.MailType : 0); + private int CBIndexToMailType(int cbindex) => Generation <= 3 ? (cbindex > 0 ? MailItemID[cbindex - 1] : 0) : (cbindex > 0 ? cbindex - 1 : 0xFF); private string GetSpeciesNameFromCB(int index) { @@ -442,7 +442,7 @@ private DialogResult ModifyHeldItem() continue; pk.HeldItem = 0; - if (Gen == 3) + if (Generation == 3) ((PK3)pk).HeldMailID = -1; } LoadPKM(false); @@ -513,7 +513,7 @@ private void LoadMail() NUD_AuthorTID.Value = mail.AuthorTID; CB_MailType.SelectedIndex = MailTypeToCBIndex(mail); var species = mail.AppearPKM; - if (Gen == 2) + if (Generation == 2) { AppearPKMs[0].SelectedValue = (int)species; TB_MessageBody21.Text = mail.GetMessage(false); @@ -522,12 +522,12 @@ private void LoadMail() return; } NUD_AuthorSID.Value = mail.AuthorSID; - for (int y = 0, xc = Gen == 3 ? 3 : 4; y < 3; y++) + for (int y = 0, xc = Generation == 3 ? 3 : 4; y < 3; y++) { for (int x = 0; x < xc; x++) Messages[y][x].Value = mail.GetMessage(y, x); } - if (Gen == 3) + if (Generation == 3) { AppearPKMs[0].SelectedValue = (int)SpeciesConverter.GetNational3(species); editing = false; @@ -557,7 +557,7 @@ private void LoadMail() private void LoadOTlabel() { Label_OTGender.Text = gendersymbols[LabelValue_GenderF ? 1 : 0]; - Label_OTGender.ForeColor = Main.Draw.GetGenderColor(LabelValue_GenderF ? 1 : 0); + Label_OTGender.ForeColor = Main.Draw.GetGenderColor((byte)(LabelValue_GenderF ? 1 : 0)); } private void Label_OTGender_Click(object sender, EventArgs e) @@ -570,7 +570,7 @@ private void Label_OTGender_Click(object sender, EventArgs e) private void NUD_MailIDn_ValueChanged(object sender, EventArgs e) { - if (editing || Gen != 3) + if (editing || Generation != 3) return; int index = Array.IndexOf(PKMNUDs, (NumericUpDown)sender); if (index < 0 || index >= p.Count) diff --git a/PKHeX.WinForms/Subforms/Save Editors/SAV_Wondercard.cs b/PKHeX.WinForms/Subforms/Save Editors/SAV_Wondercard.cs index 98c7b62ef..8a9ebe093 100644 --- a/PKHeX.WinForms/Subforms/Save Editors/SAV_Wondercard.cs +++ b/PKHeX.WinForms/Subforms/Save Editors/SAV_Wondercard.cs @@ -64,7 +64,7 @@ public SAV_Wondercard(SaveFile sav, DataMysteryGift? g = null) ViewGiftData(g); } - private List GetGiftPictureBoxes(int generation) => generation switch + private List GetGiftPictureBoxes(byte generation) => generation switch { 4 => PopulateViewGiftsG4(), 5 or 6 or 7 => PopulateViewGiftsG567(), diff --git a/Tests/PKHeX.Core.Tests/General/MarshalTests.cs b/Tests/PKHeX.Core.Tests/General/MarshalTests.cs index 9fcd6e5c0..984feea9d 100644 --- a/Tests/PKHeX.Core.Tests/General/MarshalTests.cs +++ b/Tests/PKHeX.Core.Tests/General/MarshalTests.cs @@ -8,7 +8,7 @@ namespace PKHeX.Core.Tests.General; public class MarshalTests { [Theory] - [InlineData(8, typeof(PIDIV))] + [InlineData(10, typeof(PIDIV))] [InlineData(8, typeof(MoveResult))] [InlineData(8, typeof(EvolutionMethod))] [InlineData(8, typeof(Moveset))] @@ -19,6 +19,7 @@ public class MarshalTests public void MarshalSizeExact(int expect, Type t) => Marshal.SizeOf(t).Should().Be(expect); [Theory] + [InlineData( 8, typeof(LeadSeed))] [InlineData( 8, typeof(NPCLock))] [InlineData( 8, typeof(IndividualValueSet))] [InlineData( 8, typeof(EvolutionOrigin))] diff --git a/Tests/PKHeX.Core.Tests/Legality/Legal/Generation 6/350 - Milobellus - 2CFF3D0BA012 transfer minlevel evo.pk6 b/Tests/PKHeX.Core.Tests/Legality/Legal/Generation 6/350 - Milobellus - 2CFF3D0BA012 transfer minlevel evo.pk6 deleted file mode 100644 index 22716e1aa31aa33aa77c7ff16b432b7f85aabe9c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 232 zcmWeyz-`OG@Lwm6k%57W0SJs380>*;A&@u|NB}?ZWyoa6VaR7lVn_wjISi!?#ZV2? z7!<)Q4P|r_EGG!tM>3QFb>#tJDw;GSBLmQW1aM0#&@N{<51HWx=SVPd0@;S8 OED{XNhU|<4eE|Tkq!54r literal 0 HcmV?d00001 diff --git a/Tests/PKHeX.Core.Tests/Legality/Legal/Generation 7 Transfer/266 ★ - Silcoon - 319000000002.pk7 b/Tests/PKHeX.Core.Tests/Legality/Legal/Generation 7 Transfer/266 ★ - Silcoon - 319000000002.pk7 deleted file mode 100644 index fa98c614ade4c6bb5d270b74354f4e999dff2ee2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 232 zcmZQ#0D%dHT#O71Objdx2SOPbY{6_Gp9w69mk4IaWXNGiX2=J^JQS5#P@Wu$D2Ve< zZlbXI|DgY_K5_XT;mxSY=LZcpeQ>NSQ0Pc%#g@X%#h5G4}^IrDzl(GITTS4 z=Ume=8TJ1`|6PI5?>~k#&~{|t#=yt|at#Fd!5A2{8(c(?nG?u1ER~RDU}t0kdJ6~u DEI|-Q diff --git a/Tests/PKHeX.Core.Tests/Legality/Legal/Generation 7 Transfer/269 ★ - Dustox - C03700000003.pk7 b/Tests/PKHeX.Core.Tests/Legality/Legal/Generation 7 Transfer/269 ★ - Dustox - C03700000003.pk7 deleted file mode 100644 index ea9f2de1fa9673c840b103a1fdefbe3e843c1ad4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 232 zcmZQ(00Hv@yo?MCObjdx@g)ol!az1NP?VVoEQyzJVJKxNW+-9EXQ)6^_lCiSL5QJ{ zfmK9A4pnMyrXI8U|DgY_K diff --git a/Tests/PKHeX.Core.Tests/Legality/LegalityRules.cs b/Tests/PKHeX.Core.Tests/Legality/LegalityRules.cs index 9f9214374..f13106782 100644 --- a/Tests/PKHeX.Core.Tests/Legality/LegalityRules.cs +++ b/Tests/PKHeX.Core.Tests/Legality/LegalityRules.cs @@ -9,7 +9,7 @@ public class LegalityRules [InlineData(GameVersion.B)] public void HasOriginalMetLocation5(GameVersion g) { - var pk5 = new PK5 {Version = (int) g}; + var pk5 = new PK5 { Version = g }; pk5.HasOriginalMetLocation.Should().BeTrue(); } @@ -18,7 +18,7 @@ public void HasOriginalMetLocation5(GameVersion g) [InlineData(GameVersion.X)] public void HasOriginalMetLocation6(GameVersion g) { - var pk5 = new PK6 { Version = (int)g }; + var pk5 = new PK6 { Version = g }; pk5.HasOriginalMetLocation.Should().BeTrue(); } @@ -28,7 +28,7 @@ public void HasOriginalMetLocation6(GameVersion g) [InlineData(GameVersion.SN)] public void HasOriginalMetLocation7(GameVersion g) { - var pk5 = new PK7 { Version = (int)g }; + var pk5 = new PK7 { Version = g }; pk5.HasOriginalMetLocation.Should().BeTrue(); } } diff --git a/Tests/PKHeX.Core.Tests/Legality/RNG/MethodJChecks.cs b/Tests/PKHeX.Core.Tests/Legality/RNG/MethodJChecks.cs new file mode 100644 index 000000000..18c169fae --- /dev/null +++ b/Tests/PKHeX.Core.Tests/Legality/RNG/MethodJChecks.cs @@ -0,0 +1,69 @@ +using FluentAssertions; +using Xunit; + +namespace PKHeX.Core.Tests; + +public static class MethodJChecks +{ + [Theory] + [InlineData(0x00000000, 0x64e86d5e, 05)] + [InlineData(0x00000001, 0x1250e055, 14)] + [InlineData(0x00000002, 0x746d2fae, 10)] + public static void CheckRangeJ(uint prePID, uint seed0, int frames) + { + var pid = ClassicEraRNG.GetSequentialPID(prePID); + var nature = (byte)(pid % 25); + var count = MethodJ.GetReversalWindow(prePID, nature); + var origin = LCRNG.Reverse(prePID, count * 2); + + count.Should().Be(frames); + origin.Should().Be(seed0); + } + + // Seeds that generate well-known PIDs. + private const uint TimidFlawless = 0xC69FB838; + private const uint ModestFlawless = TimidFlawless ^ 0x80000000u; + + [Theory] + [InlineData(TimidFlawless, 0)] + [InlineData(TimidFlawless, 1)] + [InlineData(TimidFlawless, 2)] + [InlineData(TimidFlawless, 3)] + [InlineData(TimidFlawless, 4)] + [InlineData(TimidFlawless, 5)] + [InlineData(TimidFlawless, 7)] + [InlineData(TimidFlawless, 8)] + [InlineData(ModestFlawless, 0)] + [InlineData(ModestFlawless, 1)] + [InlineData(ModestFlawless, 2)] + [InlineData(ModestFlawless, 4, LeadRequired.SynchronizeFail)] + [InlineData(ModestFlawless, 5)] + [InlineData(ModestFlawless, 8)] + [InlineData(ModestFlawless, 9)] + [InlineData(ModestFlawless, 10)] + [InlineData(ModestFlawless, 6, LeadRequired.None)] // Not Sync + public static void CheckPossibleJ(uint prePID, byte slotIndex, + LeadRequired expectLead = LeadRequired.Synchronize) + { + var fake = new MockSlot4(slotIndex); + var (seed, lead) = MethodJ.GetSeed(fake, prePID, 4); + lead.Should().Be(expectLead); + seed.Should().BeInRange(0, uint.MaxValue); + } + + [Theory] + [InlineData(TimidFlawless, 6)] + [InlineData(TimidFlawless, 9)] + [InlineData(TimidFlawless, 10)] + [InlineData(TimidFlawless, 11)] + [InlineData(ModestFlawless, 3)] + [InlineData(ModestFlawless, 7)] + [InlineData(ModestFlawless, 11)] + public static void CheckImpossibleJ(uint prePID, byte slotIndex) + { + var fake = new MockSlot4(slotIndex); + var lead = MethodJ.GetSeed(fake, prePID, 4); + lead.IsValid().Should().BeFalse(); + lead.Seed.Should().BeInRange(0, uint.MaxValue); + } +} diff --git a/Tests/PKHeX.Core.Tests/Legality/RNG/MockSlot4.cs b/Tests/PKHeX.Core.Tests/Legality/RNG/MockSlot4.cs new file mode 100644 index 000000000..4a2476f18 --- /dev/null +++ b/Tests/PKHeX.Core.Tests/Legality/RNG/MockSlot4.cs @@ -0,0 +1,29 @@ +namespace PKHeX.Core.Tests; + +public record MockSlot4 : IEncounterSlot4 +{ + public MockSlot4() { } + + public MockSlot4(byte slotNumber, byte levelMin = 5, byte levelMax = 5, SlotType4 type = SlotType4.Grass) + { + SlotNumber = slotNumber; + LevelMin = levelMin; + LevelMax = levelMax; + Type = type; + } + + public byte SlotNumber { get; init; } + public byte LevelMin { get; init; } + public byte LevelMax { get; init; } + public SlotType4 Type { get; init; } + + public byte StaticIndex { get; init; } + public byte MagnetPullIndex { get; init; } + public byte StaticCount { get; init; } + public byte MagnetPullCount { get; init; } + public byte AreaRate { get; init; } + + public byte PressureLevel => LevelMax; + public ushort Species => 0; + public byte Form => 0; +} diff --git a/Tests/PKHeX.Core.Tests/Legality/RaidTests.cs b/Tests/PKHeX.Core.Tests/Legality/RNG/RaidTests.cs similarity index 100% rename from Tests/PKHeX.Core.Tests/Legality/RaidTests.cs rename to Tests/PKHeX.Core.Tests/Legality/RNG/RaidTests.cs diff --git a/Tests/PKHeX.Core.Tests/Legality/ShadowTests.cs b/Tests/PKHeX.Core.Tests/Legality/RNG/ShadowTests.cs similarity index 78% rename from Tests/PKHeX.Core.Tests/Legality/ShadowTests.cs rename to Tests/PKHeX.Core.Tests/Legality/RNG/ShadowTests.cs index 86f7d29cd..1b34a338b 100644 --- a/Tests/PKHeX.Core.Tests/Legality/ShadowTests.cs +++ b/Tests/PKHeX.Core.Tests/Legality/RNG/ShadowTests.cs @@ -12,40 +12,40 @@ public static class ValidityTests public static IEnumerable Lock1() { // Zubat (F) (Serious) - yield return new object[] { Poochyena, 0xAF4E3161, new[] { 11, 29, 25, 6, 23, 10 } }; + yield return [Poochyena, 0xAF4E3161, new[] { 11, 29, 25, 6, 23, 10 }]; // Murkrow (M) (Docile) - yield return new object[] { Pineco, 0xC3A0F1E5, new[] { 30, 3, 9, 10, 27, 30 } }; + yield return [Pineco, 0xC3A0F1E5, new[] { 30, 3, 9, 10, 27, 30 }]; } public static IEnumerable Lock2() { // Goldeen (F) (Serious) // Horsea (M) (Quirky) - yield return new object[] { Spheal, 0xA459BF44, new[] { 0, 11, 4, 28, 6, 13 } }; + yield return [Spheal, 0xA459BF44, new[] { 0, 11, 4, 28, 6, 13 }]; // Kirlia (M) (Hardy) // Linoone (F) (Hardy) - yield return new object[] { Natu, 0x8E14DAB6, new[] { 29, 24, 30, 16, 3, 18 } }; + yield return [Natu, 0x8E14DAB6, new[] { 29, 24, 30, 16, 3, 18 }]; // Remoraid (M) (Docile) -- 73DB58CC // Golbat (M) (Bashful) -- F6B04390 - yield return new object[] { Roselia, 0x30E87CC7, new[] { 22, 11, 8, 26, 4, 29 } }; + yield return [Roselia, 0x30E87CC7, new[] { 22, 11, 8, 26, 4, 29 }]; // 519AEF0E // Duskull (M) (Quirky) -- 45BE3B97 // Spinarak (F) (Hardy) -- E18F5A3E - yield return new object[] { ColoMakuhita, 0xC252FEBA, new[] { 15, 9, 17, 16, 24, 22 } }; + yield return [ColoMakuhita, 0xC252FEBA, new[] { 15, 9, 17, 16, 24, 22 }]; // 559C5F72 -- Quirky F => skip // Duskull (M) (Quirky) -- A5AC2CCB // Spinarak (F) (Hardy) -- D08FF135 - yield return new object[] { ColoMakuhita, 0x61C676FC, new[] { 20, 28, 21, 18, 9, 1 } }; + yield return [ColoMakuhita, 0x61C676FC, new[] { 20, 28, 21, 18, 9, 1 }]; // 3CCB97BA -- Quirky F => skip * 2, Hardy Skip // Duskull (M) (Quirky) -- 7F0D6783 @ 161 // Spinarak (F) (Hardy) -- 6C03F545 @ 182 - yield return new object[] { ColoMakuhita, 0x3B27608D, new[] { 7, 12, 5, 19, 3, 7 } }; + yield return [ColoMakuhita, 0x3B27608D, new[] { 7, 12, 5, 19, 3, 7 }]; } public static IEnumerable Lock3() @@ -53,17 +53,17 @@ public static IEnumerable Lock3() // Luvdisc (F) (Docile) // Beautifly (M) (Hardy) // Roselia (M) (Quirky) - yield return new object[] { Delcatty, 0x9BECA2A6, new[] { 31, 31, 25, 13, 22, 1 } }; + yield return [Delcatty, 0x9BECA2A6, new[] { 31, 31, 25, 13, 22, 1 }]; // Kadabra (M) (Docile) // Sneasel (F) (Hardy) // Misdreavus (F) (Bashful) - yield return new object[] { Meowth, 0x77D87601, new[] { 10, 27, 26, 13, 30, 19 } }; + yield return [Meowth, 0x77D87601, new[] { 10, 27, 26, 13, 30, 19 }]; // Ralts (M) (Docile) // Voltorb (-) (Hardy) // Bagon (F) (Quirky) - yield return new object[] { Numel, 0x37F95B26, new[] { 11, 8, 5, 10, 28, 14 } }; + yield return [Numel, 0x37F95B26, new[] { 11, 8, 5, 10, 28, 14 }]; } public static IEnumerable Lock4() @@ -72,25 +72,25 @@ public static IEnumerable Lock4() // Jumpluff (M) (Docile) // Azumarill (F) (Hardy) // Shadow Tangela - yield return new object[] { Butterfree, 0x2E49AC34, new[] { 15, 24, 7, 2, 11, 2 } }; + yield return [Butterfree, 0x2E49AC34, new[] { 15, 24, 7, 2, 11, 2 }]; // Huntail (M) (Docile) // Cacturne (F) (Hardy) // Weezing (F) (Serious) // Ursaring (F) (Bashful) - yield return new object[] { Arbok, 0x1973FD07, new[] { 13, 30, 3, 16, 20, 9 } }; + yield return [Arbok, 0x1973FD07, new[] { 13, 30, 3, 16, 20, 9 }]; // Lairon (F) (Bashful) // Sealeo (F) (Serious) // Slowking (F) (Docile) // Ursaring (M) (Quirky) - yield return new object[] { Primeape, 0x33893D4C, new[] { 26, 25, 24, 28, 29, 30 } }; + yield return [Primeape, 0x33893D4C, new[] { 26, 25, 24, 28, 29, 30 }]; } public static IEnumerable Lock5() { // many prior, all non-shadow - yield return new object[] { Seedot, 0x8CBD29DB, new[] { 19, 29, 30, 0, 7, 2 } }; + yield return [Seedot, 0x8CBD29DB, new[] { 19, 29, 30, 0, 7, 2 }]; } [Theory] @@ -113,11 +113,11 @@ public static class PIDTests { public static IEnumerable TestData() { - yield return new object[] - { - new[] + yield return + [ + new uint[][] { - new uint[] {0xD118BA52, 0xA3127782, 0x16D95FA5, 0x31538B48}, + [0xD118BA52, 0xA3127782, 0x16D95FA5, 0x31538B48], [0x7D5FFE3E, 0x1D5720ED, 0xE0D89C99, 0x3494CDA1], [0xAEB0C3A6, 0x956DC2FD, 0x3C11DCE8, 0xC93DF897], [0xACCE2655, 0xFF2BA0A2, 0x22A8A7E6, 0x5F5380F4], @@ -128,13 +128,13 @@ public static IEnumerable TestData() [0xF2AC8419, 0xADA208E3, 0xDB3A0BA6, 0x5EEF1076], [0x9D28899D, 0xA3ECC9F0, 0x606EC6F0, 0x451FAE3C], }, - Delcatty, - }; - yield return new object[] - { - new[] + Delcatty + ]; + yield return + [ + new uint[][] { - new uint[] {0x4D6BE487, 0xBB3EFBFB, 0x6FD7EE06, 0x289D435F, 0x0EC25CE5}, + [0x4D6BE487, 0xBB3EFBFB, 0x6FD7EE06, 0x289D435F, 0x0EC25CE5], [0xB04DF5B3, 0x661E499C, 0x94EB752D, 0xC5FA9DE5, 0x0A8C9738], [0xCBB9A3B0, 0x9AC1A0B8, 0xCA3CAD46, 0x54FFCA27, 0x1D5AEC4F], [0xB2AF145E, 0x455155C9, 0xB5CE4932, 0x4B8C6554, 0x55CE5E4B], @@ -145,8 +145,8 @@ public static IEnumerable TestData() [0xC7315E32, 0x76566AA1, 0xC0CE436E, 0x98C45DA8, 0x9D1BDC4A], [0xB687F0AF, 0xC01DB6C6, 0xAD6DEC75, 0xDB041314, 0x0D949325], }, - Butterfree, - }; + Butterfree + ]; } [Theory] diff --git a/Tests/PKHeX.Core.Tests/Legality/Wild8aRNGTests.cs b/Tests/PKHeX.Core.Tests/Legality/RNG/Wild8aRNGTests.cs similarity index 100% rename from Tests/PKHeX.Core.Tests/Legality/Wild8aRNGTests.cs rename to Tests/PKHeX.Core.Tests/Legality/RNG/Wild8aRNGTests.cs diff --git a/Tests/PKHeX.Core.Tests/Legality/Wild8bRNGTests.cs b/Tests/PKHeX.Core.Tests/Legality/RNG/Wild8bRNGTests.cs similarity index 100% rename from Tests/PKHeX.Core.Tests/Legality/Wild8bRNGTests.cs rename to Tests/PKHeX.Core.Tests/Legality/RNG/Wild8bRNGTests.cs diff --git a/Tests/PKHeX.Core.Tests/PKM/HiddenPowerTests.cs b/Tests/PKHeX.Core.Tests/PKM/HiddenPowerTests.cs index aeab335c3..d7d94e8f8 100644 --- a/Tests/PKHeX.Core.Tests/PKM/HiddenPowerTests.cs +++ b/Tests/PKHeX.Core.Tests/PKM/HiddenPowerTests.cs @@ -32,7 +32,10 @@ public void HiddenPowerTestGen2(int atk, int def, MoveType type) int expect = (int)type - 1; // no normal type, down-shift by 1 var pk2 = new PK2 { IV_ATK = atk, IV_DEF = def }; pk2.HPType.Should().Be(expect); - HiddenPower.GetTypeGB(pk2.IVs).Should().Be(expect); HiddenPower.GetTypeGB(pk2.DV16).Should().Be(expect); + + Span ivs = stackalloc int[6]; + pk2.GetIVs(ivs); + HiddenPower.GetTypeGB(ivs).Should().Be(expect); } } diff --git a/Tests/PKHeX.Core.Tests/PKM/PIDIVTests.cs b/Tests/PKHeX.Core.Tests/PKM/PIDIVTests.cs index dbda8072e..0f21a92e7 100644 --- a/Tests/PKHeX.Core.Tests/PKM/PIDIVTests.cs +++ b/Tests/PKHeX.Core.Tests/PKM/PIDIVTests.cs @@ -55,11 +55,11 @@ public void PIDIVMatchingTest3MiscCXD() { // Colosseum / XD var pk3 = new PK3 {PID = 0x0985A297, IVs = [06, 01, 00, 07, 17, 07]}; - var (type, seed) = MethodFinder.Analyze(pk3); - type.Should().Be(PIDType.CXD); + var pv = MethodFinder.Analyze(pk3); + pv.Type.Should().Be(PIDType.CXD); var gk3 = new PK3(); - PIDGenerator.SetValuesFromSeed(gk3, PIDType.CXD, seed); + PIDGenerator.SetValuesFromSeed(gk3, PIDType.CXD, pv.OriginSeed); gk3.PID.Should().Be(pk3.PID); gk3.IVs.SequenceEqual(pk3.IVs).Should().BeTrue(); } @@ -68,12 +68,12 @@ public void PIDIVMatchingTest3MiscCXD() public void PIDIVMatchingTest3MiscChannel() { // Channel Jirachi - var pkC = new PK3 {PID = 0x264750D9, IVs = [06, 31, 14, 27, 05, 27], SID16 = 45819, OT_Gender = 1, Version = (int)GameVersion.R}; - var (type, seed) = MethodFinder.Analyze(pkC); - type.Should().Be(PIDType.Channel); + var pkC = new PK3 {PID = 0x264750D9, IVs = [06, 31, 14, 27, 05, 27], SID16 = 45819, OriginalTrainerGender = 1, Version = GameVersion.R}; + var pv = MethodFinder.Analyze(pkC); + pv.Type.Should().Be(PIDType.Channel); var gkC = new PK3(); - PIDGenerator.SetValuesFromSeed(gkC, PIDType.Channel, seed); + PIDGenerator.SetValuesFromSeed(gkC, PIDType.Channel, pv.OriginSeed); gkC.PID.Should().Be(pkC.PID); gkC.IVs.SequenceEqual(pkC.IVs).Should().BeTrue(); } @@ -183,46 +183,6 @@ public void PIDIVPokewalkerTest() MethodFinder.Analyze(pk).Type.Should().Be(PIDType.Pokewalker); } - [Fact] - public void PIDIVEncounterSlotTest() - { - // Modest Method 1 - var pk = new PK3 {PID = 0x6937DA48, IVs = [31, 31, 31, 31, 31, 31]}; - var pidiv = MethodFinder.Analyze(pk); - pidiv.Type.Should().Be(PIDType.Method_1); - - // Test for Method J - { - // Pearl - pk.Version = (int) GameVersion.P; - var results = FrameFinder.GetFrames(pidiv, pk).ToArray(); - - var failSync = results.Where(z => z.Lead == LeadRequired.SynchronizeFail); - var noSync = results.Where(z => z.Lead == LeadRequired.None); - var sync = results.Where(z => z.Lead == LeadRequired.Synchronize); - - failSync.Should().HaveCount(1); - sync.Should().HaveCount(37); - noSync.Should().HaveCount(2); - - const SlotType type = SlotType.Grass; - Span slots = [ 0, 1, 2, 3, 4, 5, 6, 7, 9 ]; - foreach (var slot in slots) - results.Any(z => z.GetSlot(type) == slot).Should().BeTrue("Required slot not present."); - var slotsForType = results - .Where(z => !z.LevelSlotModified).Select(z => z.GetSlot(type)) - .Distinct(); - foreach (var slot in slotsForType) - slots.Contains((byte)slot).Should().BeTrue(); - } - // Test for Method H and K - { - // Sapphire - // pk.Version = (int)GameVersion.S; - // var results = FrameFinder.GetFrames(pidiv, pk); - } - } - [Theory] [InlineData(0x00001234, 0x4DCB, 0xE161)] [InlineData(0x00005678, 0x734D, 0xC596)] @@ -246,19 +206,17 @@ public void PIDIVMethod4IVs() // See if any origin seed for the IVs matches what we expect // Load the IVs - uint rand1 = 0; // HP/ATK/DEF - uint rand3 = 0; // SPE/SPA/SPD - var IVs = pk4.IVs; - for (int i = 0; i < 3; i++) - { - rand1 |= (uint)IVs[i] << (5 * i); - rand3 |= (uint)IVs[i+3] << (5 * i); - } + var iv32 = pk4.IV32; + uint rand1 = iv32 & 0x7FFF; // HP/ATK/DEF + uint rand3 = (iv32 >> 15) & 0x7FFF; // SPE/SPA/SPD Span seeds = stackalloc uint[LCRNG.MaxCountSeedsIV]; int count = LCRNGReversalSkip.GetSeedsIVs(seeds, rand1 << 16, rand3 << 16); + // Seeds need to be unrolled twice to account for the 2 PID rolls before IVs. + var reg = seeds[..count]; - reg.IndexOf(0xFEE7047C).Should().NotBe(-1); + var index = reg.IndexOf(LCRNG.Next2(0x48FBAA42u)); + index.Should().NotBe(-1); } [Fact] diff --git a/Tests/PKHeX.Core.Tests/PKM/PKMTests.cs b/Tests/PKHeX.Core.Tests/PKM/PKMTests.cs index 3e018b4ff..5602305c3 100644 --- a/Tests/PKHeX.Core.Tests/PKM/PKMTests.cs +++ b/Tests/PKHeX.Core.Tests/PKM/PKMTests.cs @@ -11,9 +11,9 @@ public void MetDateNullWhenDateComponentsAreAllZero() { var pk = new PK7 { - Met_Day = 0, - Met_Month = 0, - Met_Year = 0, + MetDay = 0, + MetMonth = 0, + MetYear = 0, }; pk.MetDate.HasValue.Should().BeFalse(); @@ -24,9 +24,9 @@ public void MetDateReturnsCorrectDate() { var pk = new PK7 { - Met_Day = 10, - Met_Month = 8, - Met_Year = 16, + MetDay = 10, + MetMonth = 8, + MetYear = 16, }; pk.MetDate.GetValueOrDefault().Should().Be(new DateOnly(2016, 8, 10)); @@ -37,9 +37,9 @@ public void MetDateCalculatesYear0Correctly() { var pk = new PK7 { - Met_Day = 1, - Met_Month = 1, - Met_Year = 0, + MetDay = 1, + MetMonth = 1, + MetYear = 0, }; pk.MetDate.GetValueOrDefault().Year.Should().Be(2000); @@ -50,20 +50,20 @@ public void SettingToNullZerosComponents() { var pk = new PK7 { - Met_Day = 12, - Met_Month = 12, - Met_Year = 12, + MetDay = 12, + MetMonth = 12, + MetYear = 12, }; - pk.Met_Day.Should().Be(12); - pk.Met_Month.Should().Be(12); - pk.Met_Year.Should().Be(12); + pk.MetDay.Should().Be(12); + pk.MetMonth.Should().Be(12); + pk.MetYear.Should().Be(12); pk.MetDate = null; - pk.Met_Day.Should().Be(0); - pk.Met_Month.Should().Be(0); - pk.Met_Year.Should().Be(0); + pk.MetDay.Should().Be(0); + pk.MetMonth.Should().Be(0); + pk.MetYear.Should().Be(0); } [Fact] @@ -71,20 +71,20 @@ public void SettingMetDateSetsComponents() { var pk = new PK7 { - Met_Day = 12, - Met_Month = 12, - Met_Year = 12, + MetDay = 12, + MetMonth = 12, + MetYear = 12, }; - pk.Met_Day.Should().Be(12); - pk.Met_Month.Should().Be(12); - pk.Met_Year.Should().Be(12); + pk.MetDay.Should().Be(12); + pk.MetMonth.Should().Be(12); + pk.MetYear.Should().Be(12); pk.MetDate = new DateOnly(2005, 5, 5); - pk.Met_Day.Should().Be(5); - pk.Met_Month.Should().Be(5); - pk.Met_Year.Should().Be(5); + pk.MetDay.Should().Be(5); + pk.MetMonth.Should().Be(5); + pk.MetYear.Should().Be(5); } } @@ -95,9 +95,9 @@ public void EggMetDateNullWhenDateComponentsAreAllZero() { var pk = new PK7 { - Egg_Day = 0, - Egg_Month = 0, - Egg_Year = 0, + EggDay = 0, + EggMonth = 0, + EggYear = 0, }; pk.EggMetDate.HasValue.Should().BeFalse(); @@ -108,9 +108,9 @@ public void EggMetDateReturnsCorrectDate() { var pk = new PK7 { - Egg_Day = 10, - Egg_Month = 8, - Egg_Year = 16, + EggDay = 10, + EggMonth = 8, + EggYear = 16, }; pk.EggMetDate.GetValueOrDefault().Should().Be(new DateOnly(2016, 8, 10)); @@ -121,9 +121,9 @@ public void EggMetDateCalculatesYear0Correctly() { var pk = new PK7 { - Egg_Day = 1, - Egg_Month = 1, - Egg_Year = 0, + EggDay = 1, + EggMonth = 1, + EggYear = 0, }; pk.EggMetDate.GetValueOrDefault().Year.Should().Be(2000); @@ -134,20 +134,20 @@ public void SettingEggMetDateToNullZerosComponents() { var pk = new PK7 { - Egg_Day = 12, - Egg_Month = 12, - Egg_Year = 12, + EggDay = 12, + EggMonth = 12, + EggYear = 12, }; - pk.Egg_Day.Should().Be(12); - pk.Egg_Month.Should().Be(12); - pk.Egg_Year.Should().Be(12); + pk.EggDay.Should().Be(12); + pk.EggMonth.Should().Be(12); + pk.EggYear.Should().Be(12); pk.EggMetDate = null; - pk.Egg_Day.Should().Be(0); - pk.Egg_Month.Should().Be(0); - pk.Egg_Year.Should().Be(0); + pk.EggDay.Should().Be(0); + pk.EggMonth.Should().Be(0); + pk.EggYear.Should().Be(0); } [Fact] @@ -155,19 +155,19 @@ public void SettingEggMetDateSetsComponents() { var pk = new PK7 { - Egg_Day = 12, - Egg_Month = 12, - Egg_Year = 12, + EggDay = 12, + EggMonth = 12, + EggYear = 12, }; - pk.Egg_Day.Should().Be(12); - pk.Egg_Month.Should().Be(12); - pk.Egg_Year.Should().Be(12); + pk.EggDay.Should().Be(12); + pk.EggMonth.Should().Be(12); + pk.EggYear.Should().Be(12); pk.EggMetDate = new DateOnly(2005, 5, 5); - pk.Egg_Day.Should().Be(5); - pk.Egg_Month.Should().Be(5); - pk.Egg_Year.Should().Be(5); + pk.EggDay.Should().Be(5); + pk.EggMonth.Should().Be(5); + pk.EggYear.Should().Be(5); } } diff --git a/Tests/PKHeX.Core.Tests/PKM/StringTests.cs b/Tests/PKHeX.Core.Tests/PKM/StringTests.cs index 2d708b433..c634418ab 100644 --- a/Tests/PKHeX.Core.Tests/PKM/StringTests.cs +++ b/Tests/PKHeX.Core.Tests/PKM/StringTests.cs @@ -10,7 +10,7 @@ public class StringTests public void EncodesOTNameCorrectly() { const string name_fabian = "Fabian♂"; - var pk = new PK7 { OT_Name = name_fabian }; + var pk = new PK7 { OriginalTrainerName = name_fabian }; Span byte_fabian = [ 0x46, 0x00, // F @@ -22,7 +22,7 @@ public void EncodesOTNameCorrectly() 0x8E, 0xE0, // ♂ 0x00, 0x00, // \0 terminator ]; - CheckStringGetSet(nameof(pk.OT_Name), name_fabian, pk.OT_Name, byte_fabian, pk.OT_Trash); + CheckStringGetSet(nameof(pk.OriginalTrainerName), name_fabian, pk.OriginalTrainerName, byte_fabian, pk.OriginalTrainerTrash); } [Fact] @@ -39,7 +39,7 @@ public void EncodesNicknameCorrectly() 0x40, 0x26, // ♀ 0x00, 0x00, // \0 terminator ]; - CheckStringGetSet(nameof(pk.Nickname), name_nidoran, pk.Nickname, byte_nidoran, pk.Nickname_Trash); + CheckStringGetSet(nameof(pk.Nickname), name_nidoran, pk.Nickname, byte_nidoran, pk.NicknameTrash); } private static void CheckStringGetSet(string check, string instr, string outstr, ReadOnlySpan indata, ReadOnlySpan outdata) diff --git a/Tests/PKHeX.Core.Tests/Simulator/GeneratorTests.cs b/Tests/PKHeX.Core.Tests/Simulator/GeneratorTests.cs index 321cb92ec..2c2adfb4d 100644 --- a/Tests/PKHeX.Core.Tests/Simulator/GeneratorTests.cs +++ b/Tests/PKHeX.Core.Tests/Simulator/GeneratorTests.cs @@ -3,6 +3,9 @@ using System.Linq; using FluentAssertions; using Xunit; +using static PKHeX.Core.GameVersion; +using PT = PKHeX.Core.PersonalTable; +using TR = PKHeX.Core.SimpleTrainerInfo; #pragma warning disable xUnit1004 // Test methods should not be skipped namespace PKHeX.Core.Tests.Simulator; @@ -12,19 +15,19 @@ public class GeneratorTests private const string SkipReasonLong = "Long duration test, run manually & very infrequently."; static GeneratorTests() => TestUtil.InitializeLegality(); - public static IEnumerable GetSpecies17() => GetSpecies(PersonalTable.USUM, new SimpleTrainerInfo(GameVersion.US), () => new PK7(), []); - public static IEnumerable GetSpeciesLGPE() => GetSpecies(PersonalTable.GG, new SimpleTrainerInfo(GameVersion.GP), () => new PB7(), [GameVersion.GP, GameVersion.GE]); - public static IEnumerable GetSpeciesSWSH() => GetSpecies(PersonalTable.SWSH, new SimpleTrainerInfo(GameVersion.SW), () => new PK8(), [GameVersion.SW, GameVersion.SH]); - public static IEnumerable GetSpeciesPLA() => GetSpecies(PersonalTable.LA, new SimpleTrainerInfo(GameVersion.PLA), () => new PA8(), [GameVersion.PLA]); - public static IEnumerable GetSpeciesBDSP() => GetSpecies(PersonalTable.BDSP, new SimpleTrainerInfo(GameVersion.BD), () => new PB8(), [GameVersion.BD, GameVersion.SP]); - public static IEnumerable GetSpeciesSV() => GetSpecies(PersonalTable.SV, new SimpleTrainerInfo(GameVersion.SL), () => new PK9(), [GameVersion.SL, GameVersion.VL]); + public static IEnumerable GetSpecies17() => GetSpecies(PT.USUM, new TR(US), () => new PK7(), []); + public static IEnumerable GetSpeciesLGPE() => GetSpecies(PT.GG, new TR(GP), () => new PB7(), [GP, GE]); + public static IEnumerable GetSpeciesSWSH() => GetSpecies(PT.SWSH, new TR(SW), () => new PK8(), [SW, SH]); + public static IEnumerable GetSpeciesPLA() => GetSpecies(PT.LA, new TR(PLA), () => new PA8(), [PLA]); + public static IEnumerable GetSpeciesBDSP() => GetSpecies(PT.BDSP, new TR(BD), () => new PB8(), [BD, SP]); + public static IEnumerable GetSpeciesSV() => GetSpecies(PT.SV, new TR(SL), () => new PK9(), [SL, VL]); - private static IEnumerable GetSpecies(T table, SimpleTrainerInfo tr, Func ctor, GameVersion[] games) where T : IPersonalTable + private static IEnumerable GetSpecies(T table, TR tr, Func ctor, GameVersion[] games) where T : IPersonalTable { for (ushort i = 1; i <= table.MaxSpeciesID; i++) { if (table.IsSpeciesInGame(i)) - yield return new object[] { (Species)i, tr, ctor(), games }; + yield return [(Species)i, tr, ctor(), games]; } } @@ -35,7 +38,7 @@ public class GeneratorTests [MemberData(nameof(GetSpeciesPLA))] [MemberData(nameof(GetSpeciesBDSP))] [MemberData(nameof(GetSpeciesSV))] - public void PokemonGenerationReturnsLegalPokemon(Species species, SimpleTrainerInfo tr, Core.PKM template, GameVersion[] games) + public void PokemonGenerationReturnsLegalPokemon(Species species, TR tr, Core.PKM template, GameVersion[] games) { int count = 0; template.Species = (ushort)species; @@ -57,11 +60,12 @@ public void CanGenerateMG5Case() { const Species species = Species.Haxorus; var pk5 = new PK5 {Species = (int) species}; - var ez = EncounterMovesetGenerator.GenerateEncounters(pk5, pk5.Moves, GameVersion.W2).OfType().First(); + var moves = ReadOnlyMemory.Empty; + var ez = EncounterMovesetGenerator.GenerateEncounters(pk5, moves, W2).OfType().First(); ez.Should().NotBeNull("Shiny Haxorus stationary encounter exists for B2/W2"); var criteria = EncounterCriteria.Unrestricted; - var tr = new SimpleTrainerInfo(GameVersion.B2) + var tr = new TR(B2) { TID16 = 57600, SID16 = 62446, @@ -71,7 +75,7 @@ public void CanGenerateMG5Case() { criteria = criteria with {Nature = nature}; var pk = ez.ConvertToPKM(tr, criteria); - pk.Nature.Should().Be((int)nature, "not nature locked"); + pk.Nature.Should().Be(nature, "not nature locked"); pk.IsShiny.Should().BeTrue("encounter is shiny locked"); pk.TID16.Should().Be(tr.TID16); pk.SID16.Should().Be(tr.SID16); diff --git a/Tests/PKHeX.Core.Tests/Simulator/ShowdownSetTests.cs b/Tests/PKHeX.Core.Tests/Simulator/ShowdownSetTests.cs index 16e3e0a01..8c0a3a3e1 100644 --- a/Tests/PKHeX.Core.Tests/Simulator/ShowdownSetTests.cs +++ b/Tests/PKHeX.Core.Tests/Simulator/ShowdownSetTests.cs @@ -25,7 +25,7 @@ public void SimulatorGetEncounters() var pk7 = new PK7 {Species = set.Species, Form = set.Form, Moves = set.Moves}; var encounters = EncounterMovesetGenerator.GenerateEncounters(pk7, set.Moves, GameVersion.MN); Assert.True(!encounters.Any()); - pk7.HT_Name = "PKHeX"; + pk7.HandlingTrainerName = "PKHeX"; encounters = EncounterMovesetGenerator.GenerateEncounters(pk7, set.Moves, GameVersion.MN); var first = encounters.FirstOrDefault(); Assert.NotNull(first); @@ -38,7 +38,7 @@ public void SimulatorGetEncounters() var la = new LegalityAnalysis(pk); la.Valid.Should().BeTrue($"Encounter should have generated legally: {egg} {la.Report()}"); - var test = EncounterMovesetGenerator.GenerateEncounters(pk7, info, pk7.Moves).ToList(); + var test = EncounterMovesetGenerator.GenerateEncounters(pk7, info, set.Moves).ToList(); for (var i = 0; i < test.Count; i++) { var t = test[i]; @@ -100,7 +100,7 @@ public void SimulatorGetCelebi() public void SimulatorGetSplitBreed() { var set = new ShowdownSet(SetMunchSnorLax); - var pk7 = new PK7 { Species = set.Species, Form = set.Form, Moves = set.Moves, HT_Name = "PKHeX" }; // !! specify the HT name, we need tutors for this one + var pk7 = new PK7 { Species = set.Species, Form = set.Form, Moves = set.Moves, HandlingTrainerName = "PKHeX" }; // !! specify the HT name, we need tutors for this one var encs = EncounterMovesetGenerator.GenerateEncounters(pk7, set.Moves, GameVersion.SN).ToList(); Assert.True(encs.Count > 0); Assert.True(encs.All(z => z.Species > 150)); @@ -117,7 +117,7 @@ public void SimulatorGetSplitBreed() public void SimulatorGetVCEgg1() { var set = new ShowdownSet(SetSlowpoke12); - var pk7 = new PK7 { Species = set.Species, Form = set.Form, Moves = set.Moves, HT_Name = "PKHeX" }; + var pk7 = new PK7 { Species = set.Species, Form = set.Form, Moves = set.Moves, HandlingTrainerName = "PKHeX" }; var encs = EncounterMovesetGenerator.GenerateEncounters(pk7, set.Moves, GameVersion.GD).ToList(); Assert.True(encs.Count > 0); @@ -196,7 +196,7 @@ public void BadFriendshipNotParsed(int value) { string input = $@"Eevee\nFriendship: {value}"; var set = new ShowdownSet(input); - set.Friendship.Should().NotBe(value); + value.Should().NotBe(set.Friendship); } [Theory] @@ -207,7 +207,7 @@ public void BadLevelNotParsed(int value) { string input = $@"Eevee\nLevel: {value}"; var set = new ShowdownSet(input); - set.Level.Should().NotBe(value); + value.Should().NotBe(set.Level); } private const string LowLevelElectrode =