diff --git a/PKHeX.Core/Game/Enums/Ball.cs b/PKHeX.Core/Game/Enums/Ball.cs index e369a55de..c79dff294 100644 --- a/PKHeX.Core/Game/Enums/Ball.cs +++ b/PKHeX.Core/Game/Enums/Ball.cs @@ -48,23 +48,5 @@ public static class BallExtensions /// Ball ID /// True if Apricorn, false if not. public static bool IsApricornBall(this Ball ball) => Ball.Fast <= ball && ball <= Ball.Moon; - - public static Ball GetRequiredBallValueWild(int gen, int loc) - { - return gen switch - { - // For Gen3 Safari Zones, we've already deferred partial match encounters. - 3 when Locations.IsSafariZoneLocation3(loc) => Ball.Safari, - - // For Gen4 Safari Zones and BCC, we've already deferred partial match encounters. - 4 when Locations.IsSafariZoneLocation4(loc) => Ball.Safari, - 4 when Locations.BugCatchingContest4 == loc => Ball.Sport, - - // Poké Pelago - 7 when loc == 30016 => Ball.Poke, - - _ => Ball.None, - }; - } } -} \ No newline at end of file +} diff --git a/PKHeX.Core/Legality/Encounters/EncounterSlot/EncounterSlot.cs b/PKHeX.Core/Legality/Encounters/EncounterSlot/EncounterSlot.cs index 07976c943..cfbf4e069 100644 --- a/PKHeX.Core/Legality/Encounters/EncounterSlot/EncounterSlot.cs +++ b/PKHeX.Core/Legality/Encounters/EncounterSlot/EncounterSlot.cs @@ -94,7 +94,7 @@ protected virtual void ApplyDetails(ITrainerInfo sav, EncounterCriteria criteria pk.Version = (int)version; pk.Nickname = SpeciesName.GetSpeciesNameGeneration(Species, lang, Generation); - var ball = BallExtensions.GetRequiredBallValueWild(Generation, Location); + var ball = Area.Type.GetRequiredBallValueWild(Generation, Location); pk.Ball = (int)(ball == Ball.None ? Ball.Poke : ball); pk.Language = lang; pk.OT_Friendship = pk.PersonalInfo.BaseFriendship; diff --git a/PKHeX.Core/Legality/Encounters/EncounterStatic/EncounterStatic.cs b/PKHeX.Core/Legality/Encounters/EncounterStatic/EncounterStatic.cs index c4068afef..7dac4f40a 100644 --- a/PKHeX.Core/Legality/Encounters/EncounterStatic/EncounterStatic.cs +++ b/PKHeX.Core/Legality/Encounters/EncounterStatic/EncounterStatic.cs @@ -317,9 +317,7 @@ protected virtual bool IsMatchLevel(PKM pkm, DexLevel evo) public virtual bool IsMatchDeferred(PKM pkm) { - if (pkm.FatefulEncounter != Fateful) - return true; - return false; + return pkm.FatefulEncounter != Fateful; } } } diff --git a/PKHeX.Core/Legality/Encounters/Generator/EncounterEggGenerator.cs b/PKHeX.Core/Legality/Encounters/Generator/EncounterEggGenerator.cs index 50e9a8a8b..9ed55b0f2 100644 --- a/PKHeX.Core/Legality/Encounters/Generator/EncounterEggGenerator.cs +++ b/PKHeX.Core/Legality/Encounters/Generator/EncounterEggGenerator.cs @@ -134,24 +134,14 @@ private static bool GetCanBeEgg2(PKM pkm) { if (pkm.Met_Level < 5) return false; - if (pkm.FatefulEncounter) - return false; - if (pkm.Ball != 4) - return false; } else { if (pkm.Met_Location != 0 && pkm.Met_Level != 1) // 2->1->2 clears met info return false; - if (pkm.CurrentLevel < 5) - return false; } - int lvl = pkm.CurrentLevel; - if (lvl < 5) - return false; - - return true; + return pkm.CurrentLevel >= 5; } } } diff --git a/PKHeX.Core/Legality/Encounters/Generator/EncounterSlotGenerator.cs b/PKHeX.Core/Legality/Encounters/Generator/EncounterSlotGenerator.cs index 0472b191d..02f72642b 100644 --- a/PKHeX.Core/Legality/Encounters/Generator/EncounterSlotGenerator.cs +++ b/PKHeX.Core/Legality/Encounters/Generator/EncounterSlotGenerator.cs @@ -92,13 +92,6 @@ private static bool IsDeferred(this EncounterSlot slot, int currentSpecies, PKM private static bool IsDeferredSport(this ILocation slot, bool IsSportBall) => IsSportBall != (slot.Location == Locations.BugCatchingContest4); private static bool IsDeferredHiddenAbility(this EncounterSlot slot, bool IsHidden) => IsHidden && !slot.IsHiddenAbilitySlot(); - private static IEnumerable GetValidEncounterSlots(PKM pkm, EncounterArea loc, IReadOnlyList chain) - { - if (pkm.Egg_Location != 0) - return Enumerable.Empty(); - return loc.GetMatchingSlots(pkm, chain); - } - public static IEnumerable GetEncounterSlots(PKM pkm, GameVersion gameSource = GameVersion.Any) { if (gameSource == GameVersion.Any) diff --git a/PKHeX.Core/Legality/Enums/SlotType.cs b/PKHeX.Core/Legality/Enums/SlotType.cs index 00eaf9ec2..da515ee34 100644 --- a/PKHeX.Core/Legality/Enums/SlotType.cs +++ b/PKHeX.Core/Legality/Enums/SlotType.cs @@ -90,5 +90,20 @@ internal static bool IsSweetScentType(this SlotType t) _ => false, }; } + + public static Ball GetRequiredBallValueWild(this SlotType t, int gen, int loc) + { + return gen switch + { + 3 when Locations.IsSafariZoneLocation3(loc) => Ball.Safari, + 4 when Locations.IsSafariZoneLocation4(loc) => Ball.Safari, + 4 when t == SlotType.BugContest => Ball.Sport, + + // Poké Pelago + 7 when loc == 30016 => Ball.Poke, + + _ => Ball.None, + }; + } } } diff --git a/PKHeX.Core/Legality/Evolutions/EvolutionChain.cs b/PKHeX.Core/Legality/Evolutions/EvolutionChain.cs index 13834498c..b1fc27e82 100644 --- a/PKHeX.Core/Legality/Evolutions/EvolutionChain.cs +++ b/PKHeX.Core/Legality/Evolutions/EvolutionChain.cs @@ -234,7 +234,6 @@ private static void CheckLastEncounterRemoval(IEncounterable enc, IReadOnlyList< } } - internal static List GetValidPreEvolutions(PKM pkm, int maxspeciesorigin = -1, int maxLevel = -1, int minLevel = 1, bool skipChecks = false) { if (maxLevel < 0) diff --git a/PKHeX.Core/Legality/RNG/RNG.cs b/PKHeX.Core/Legality/RNG/RNG.cs index 28a68b6f4..c8883f9a9 100644 --- a/PKHeX.Core/Legality/RNG/RNG.cs +++ b/PKHeX.Core/Legality/RNG/RNG.cs @@ -4,10 +4,20 @@ namespace PKHeX.Core { + /// + /// 32 Bit Linear Congruential Random Number Generator + /// + /// + /// Provides common RNG algorithms used by Generation 3 & 4. + /// https://en.wikipedia.org/wiki/Linear_congruential_generator + /// public sealed class RNG { + /// LCRNG used for Encryption and mainline game RNG calls. public static readonly RNG LCRNG = new RNG(0x41C64E6D, 0x00006073, 0xEEB9EB65, 0x0A3561A1); + /// LCRNG used by Colosseum & XD for game RNG calls. public static readonly RNG XDRNG = new RNG(0x000343FD, 0x00269EC3, 0xB9B33155, 0xA170F641); + /// Alternate LCRNG used by mainline game RNG calls to disassociate the seed from the , for anti-shiny and other purposes. public static readonly RNG ARNG = new RNG(0x6C078965, 0x00000001, 0x9638806D, 0x69C77F93); private readonly uint Mult, Add, rMult, rAdd; @@ -69,12 +79,28 @@ private static void SetFlagData(uint i, uint mult, uint add, bool[] f, byte[] v) // now the search only has to access the flags array once per loop. } + /// + /// Advances the RNG seed to the next state value. + /// + /// Current seed + /// Seed advanced a single time. [MethodImpl(MethodImplOptions.AggressiveInlining)] public uint Next(uint seed) => (seed * Mult) + Add; + /// + /// Reverses the RNG seed to the previous state value. + /// + /// Current seed + /// Seed reversed a single time. [MethodImpl(MethodImplOptions.AggressiveInlining)] public uint Prev(uint seed) => (seed * rMult) + rAdd; + /// + /// Advances the RNG seed to the next state value a specified amount of times. + /// + /// Current seed + /// Amount of times to advance. + /// Seed advanced the specified amount of times. [MethodImpl(MethodImplOptions.AggressiveInlining)] public uint Advance(uint seed, int frames) { @@ -83,6 +109,12 @@ public uint Advance(uint seed, int frames) return seed; } + /// + /// Reverses the RNG seed to the previous state value a specified amount of times. + /// + /// Current seed + /// Amount of times to reverse. + /// Seed reversed the specified amount of times. [MethodImpl(MethodImplOptions.AggressiveInlining)] public uint Reverse(uint seed, int frames) { @@ -95,7 +127,7 @@ public uint Reverse(uint seed, int frames) /// Generates an IV for each RNG call using the top 5 bits of frame seeds. /// /// RNG seed - /// Array of 6 IVs + /// Array of 6 IVs as . [MethodImpl(MethodImplOptions.AggressiveInlining)] internal uint[] GetSequentialIVsUInt32(uint seed) { @@ -108,6 +140,11 @@ internal uint[] GetSequentialIVsUInt32(uint seed) return ivs; } + /// + /// Generates an IV for each RNG call using the top 5 bits of frame seeds. + /// + /// RNG seed + /// Array of 6 IVs as . [MethodImpl(MethodImplOptions.AggressiveInlining)] internal int[] GetSequentialIVsInt32(uint seed) { @@ -223,9 +260,16 @@ private IEnumerable GetPossibleSeedsEuclid(uint first, uint second, int bi public enum RNGType { + /// No RNG type specified None, + + /// LCRNG, + + /// XDRNG, + + /// ARNG, } diff --git a/PKHeX.Core/Legality/Tables/Tables8.cs b/PKHeX.Core/Legality/Tables/Tables8.cs index b40bd4de9..a510aaed1 100644 --- a/PKHeX.Core/Legality/Tables/Tables8.cs +++ b/PKHeX.Core/Legality/Tables/Tables8.cs @@ -352,7 +352,6 @@ public static partial class Legal 01, 01, 01, 05, 05, 10, 10, 10, 20, 10, 10, 10, 05, 05, 20, 10, 10, 10, 01, 05, 15, 05, 01, 01, 01, 01, 01, 01, 10, 15, 15, 20, 20, 20, 20, 15, 15, 10, 10, 05, 20, 05, 10, 05, 15, 10, 10, 05, 15, 20, 10, 10, 15, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 05, 10, 15, 10, 15, 05, 05, 05, 10, 15, 40, 10, 10, 10, 15, 10, 10, 10, 10, 05, 05, 05, 10, 05, 20, 10, 10, 05, 20, 20, 10, 10, 05, 05, 05, 40, 10, 20, 10, 10, 10, 10, 05, 05 - }; internal static readonly HashSet Ban_NoHidden8 = new HashSet(); // none as of DLC 1! diff --git a/PKHeX.Core/Legality/Verifiers/BallVerifier.cs b/PKHeX.Core/Legality/Verifiers/BallVerifier.cs index f31a87dec..592325f13 100644 --- a/PKHeX.Core/Legality/Verifiers/BallVerifier.cs +++ b/PKHeX.Core/Legality/Verifiers/BallVerifier.cs @@ -74,27 +74,9 @@ private CheckResult VerifyBallStatic(LegalityAnalysis data, EncounterStatic s) return VerifyBallEquals(data, Legal.GetWildBalls(data.Info.Generation, data.Info.Game)); } - private static Ball GetRequiredBallValue(int gen, int loc) - { - return gen switch - { - // For Gen3 Safari Zones, we've already deferred partial match encounters. - 3 when Locations.IsSafariZoneLocation3(loc) => Safari, - - // For Gen4 Safari Zones and BCC, we've already deferred partial match encounters. - 4 when Locations.IsSafariZoneLocation4(loc) => Safari, - 4 when Locations.BugCatchingContest4 == loc => Sport, - - // Poké Pelago - 7 when loc == 30016 => Poke, - - _ => None, - }; - } - private CheckResult VerifyBallWild(LegalityAnalysis data, EncounterSlot w) { - var req = BallExtensions.GetRequiredBallValueWild(w.Generation, w.Location); + var req = w.Area.Type.GetRequiredBallValueWild(w.Generation, w.Location); if (req != None) return VerifyBallEquals(data, (int) req); diff --git a/PKHeX.Core/MysteryGifts/PCD.cs b/PKHeX.Core/MysteryGifts/PCD.cs index 65dcd24b8..f0176ef9b 100644 --- a/PKHeX.Core/MysteryGifts/PCD.cs +++ b/PKHeX.Core/MysteryGifts/PCD.cs @@ -167,6 +167,10 @@ protected override bool IsMatchExact(PKM pkm, DexLevel evo) if (wc.Ball != pkm.Ball) return false; if (wc.OT_Gender < 3 && wc.OT_Gender != pkm.OT_Gender) return false; + // Milotic is the only gift to come with Contest stats. + if (wc.Species == (int)Core.Species.Milotic && pkm is IContestStats s && s.IsContestBelow(wc)) + return false; + if (wc.PID == 1) { // Random PID, never shiny @@ -184,10 +188,6 @@ protected override bool IsMatchExact(PKM pkm, DexLevel evo) return false; } - // Milotic is the only gift to come with Contest stats. - if (wc.Species == (int)Core.Species.Milotic && pkm is IContestStats s && s.IsContestBelow(wc)) - return false; - return true; } diff --git a/PKHeX.Core/MysteryGifts/PGT.cs b/PKHeX.Core/MysteryGifts/PGT.cs index 73191c4c3..3d02f075c 100644 --- a/PKHeX.Core/MysteryGifts/PGT.cs +++ b/PKHeX.Core/MysteryGifts/PGT.cs @@ -201,7 +201,7 @@ private void SetPINGA(PK4 pk4, EncounterCriteria criteria) seed = Util.Rand32(); // reseed, do not have method 1 correlation // Generate IVs - if (pk4.IV32 == 0) + if (pk4.IV32 == 0) // Ignore Nickname/Egg flag bits; none are set for varied-IV gifts. { uint iv1 = ((seed = RNG.LCRNG.Next(seed)) >> 16) & 0x7FFF; uint iv2 = ((RNG.LCRNG.Next(seed)) >> 16) & 0x7FFF; diff --git a/PKHeX.Core/PKM/PK7.cs b/PKHeX.Core/PKM/PK7.cs index aca11f584..a19558a4c 100644 --- a/PKHeX.Core/PKM/PK7.cs +++ b/PKHeX.Core/PKM/PK7.cs @@ -4,7 +4,7 @@ namespace PKHeX.Core { /// Generation 7 format. - public sealed class PK7 : G6PKM, IRibbonSetEvent3, IRibbonSetEvent4, IRibbonSetCommon3, IRibbonSetCommon4, IRibbonSetCommon6, IRibbonSetCommon7, + public sealed class PK7 : G6PKM, IRibbonSetEvent3, IRibbonSetEvent4, IRibbonSetCommon3, IRibbonSetCommon4, IRibbonSetCommon6, IRibbonSetCommon7, IContestStats, IHyperTrain, IGeoTrack, ISuperTrain, IFormArgument, ITrainerMemories, IAffection { private static readonly ushort[] Unused = diff --git a/PKHeX.Core/PKM/Shared/IDynamaxLevel.cs b/PKHeX.Core/PKM/Shared/IDynamaxLevel.cs index 82a4d9672..45fb8f26d 100644 --- a/PKHeX.Core/PKM/Shared/IDynamaxLevel.cs +++ b/PKHeX.Core/PKM/Shared/IDynamaxLevel.cs @@ -13,8 +13,16 @@ public static bool CanHaveDynamaxLevel(this IDynamaxLevel _, PKM pkm) { if (pkm.IsEgg) return false; - var species = pkm.Species; - if (species == (int)Zacian || species == (int)Zamazenta || species == (int)Eternatus) + return CanHaveDynamaxLevel(pkm.Species); + } + + private static bool CanHaveDynamaxLevel(int species) + { + if (species == (int)Zacian) + return false; + if (species == (int)Zamazenta) + return false; + if (species == (int)Eternatus) return false; return true; } diff --git a/PKHeX.Core/Saves/Access/SaveBlockAccessor8SWSH.cs b/PKHeX.Core/Saves/Access/SaveBlockAccessor8SWSH.cs index 48448b63f..b06325639 100644 --- a/PKHeX.Core/Saves/Access/SaveBlockAccessor8SWSH.cs +++ b/PKHeX.Core/Saves/Access/SaveBlockAccessor8SWSH.cs @@ -157,7 +157,7 @@ public SaveBlockAccessor8SWSH(SAV8SWSH sav) public const uint KDojoWattDonationTotal = 0xC7161487; // U32 Amount of Watts donated to Master Dojo public const uint KDiggingPaWattStreak = 0x68BBA8B1; // U32 Most Watts dug up by the Digging Pa public const uint KAlolanDiglettFound = 0x4AEA5A7E; // U32 Amount of Alolan Diglett found on Isle of Armor - + public const uint KSparringStreakNormal = 0xDB5E16CB; // U32 Best Normal-Type Restricted Sparring Streak public const uint KSparringNormalPartySlot1Species = 0x7BF09DD3; // U16 Species ID of 1st PKM used in party public const uint KSparringNormalPartySlot2Species = 0x7AF09C40; // U16 Species ID of 2nd PKM used in party @@ -171,7 +171,7 @@ public SaveBlockAccessor8SWSH(SAV8SWSH sav) public const uint KSparringNormalPartySlot1EC = 0xE95199D1; // U32 Encryption Constant of 1st PKM used in party public const uint KSparringNormalPartySlot2EC = 0xE851983E; // U32 Encryption Constant of 2nd PKM used in party public const uint KSparringNormalPartySlot3EC = 0xE75196AB; // U32 Encryption Constant of 3rd PKM used in party - + public const uint KSparringStreakFire = 0xD25E08A0; // U32 Best Fire-Type Restricted Sparring Streak public const uint KSparringFirePartySlot1Species = 0x455C523A; // U16 Species ID of 1st PKM used in party public const uint KSparringFirePartySlot2Species = 0x465C53CD; // U16 Species ID of 2nd PKM used in party @@ -185,7 +185,7 @@ public SaveBlockAccessor8SWSH(SAV8SWSH sav) public const uint KSparringFirePartySlot1EC = 0x1F637658; // U32 Encryption Constant of 1st PKM used in party public const uint KSparringFirePartySlot2EC = 0x206377EB; // U32 Encryption Constant of 2nd PKM used in party public const uint KSparringFirePartySlot3EC = 0x2163797E; // U32 Encryption Constant of 3rd PKM used in party - + public const uint KSparringStreakWater = 0xD55BCEC2; // U32 Best Water-Type Restricted Sparring Streak public const uint KSparringWaterPartySlot1Species = 0x30396510; // U16 Species ID of 1st PKM used in party public const uint KSparringWaterPartySlot2Species = 0x313966A3; // U16 Species ID of 2nd PKM used in party @@ -199,7 +199,7 @@ public SaveBlockAccessor8SWSH(SAV8SWSH sav) public const uint KSparringWaterPartySlot1EC = 0x1DE9496E; // U32 Encryption Constant of 1st PKM used in party public const uint KSparringWaterPartySlot2EC = 0x1EE94B01; // U32 Encryption Constant of 2nd PKM used in party public const uint KSparringWaterPartySlot3EC = 0x1BE94648; // U32 Encryption Constant of 3rd PKM used in party - + public const uint KSparringStreakElectric = 0xD35BCB9C; // U32 Best Electric-Type Restricted Sparring Streak public const uint KSparringElectricPartySlot1Species = 0x1E5FB12E; // U16 Species ID of 1st PKM used in party public const uint KSparringElectricPartySlot2Species = 0x1F5FB2C1; // U16 Species ID of 2nd PKM used in party @@ -213,7 +213,7 @@ public SaveBlockAccessor8SWSH(SAV8SWSH sav) public const uint KSparringElectricPartySlot1EC = 0x2FC2FD50; // U32 Encryption Constant of 1st PKM used in party public const uint KSparringElectricPartySlot2EC = 0x30C2FEE3; // U32 Encryption Constant of 2nd PKM used in party public const uint KSparringElectricPartySlot3EC = 0x31C30076; // U32 Encryption Constant of 3rd PKM used in party - + public const uint KSparringStreakGrass = 0xD65BD055; // U32 Best Grass-Type Restricted Sparring Streak public const uint KSparringGrassPartySlot1Species = 0x70973021; // U16 Species ID of 1st PKM used in party public const uint KSparringGrassPartySlot2Species = 0x6F972E8E; // U16 Species ID of 2nd PKM used in party @@ -255,7 +255,7 @@ public SaveBlockAccessor8SWSH(SAV8SWSH sav) public const uint KSparringFightingPartySlot1EC = 0x62A0A180; // U32 Encryption Constant of 1st PKM used in party public const uint KSparringFightingPartySlot2EC = 0x63A0A313; // U32 Encryption Constant of 2nd PKM used in party public const uint KSparringFightingPartySlot3EC = 0x64A0A4A6; // U32 Encryption Constant of 3rd PKM used in party - + public const uint KSparringStreakPoison = 0xDC5E185E; // U32 Best Poison-Type Restricted Sparring Streak public const uint KSparringPoisonPartySlot1Species = 0x3BFF8084; // U16 Species ID of 1st PKM used in party public const uint KSparringPoisonPartySlot2Species = 0x3CFF8217; // U16 Species ID of 2nd PKM used in party @@ -269,7 +269,7 @@ public SaveBlockAccessor8SWSH(SAV8SWSH sav) public const uint KSparringPoisonPartySlot1EC = 0x171AE45E; // U32 Encryption Constant of 1st PKM used in party public const uint KSparringPoisonPartySlot2EC = 0x181AE5F1; // U32 Encryption Constant of 2nd PKM used in party public const uint KSparringPoisonPartySlot3EC = 0x151AE138; // U32 Encryption Constant of 3rd PKM used in party - + public const uint KSparringStreakGround = 0xDF5E1D17; // U32 Best Ground-Type Restricted Sparring Streak public const uint KSparringGroundPartySlot1Species = 0x29BC6D6F; // U16 Species ID of 1st PKM used in party public const uint KSparringGroundPartySlot2Species = 0x28BC6BDC; // U16 Species ID of 2nd PKM used in party @@ -283,7 +283,7 @@ public SaveBlockAccessor8SWSH(SAV8SWSH sav) public const uint KSparringGroundPartySlot1EC = 0xBA495F35; // U32 Encryption Constant of 1st PKM used in party public const uint KSparringGroundPartySlot2EC = 0xB9495DA2; // U32 Encryption Constant of 2nd PKM used in party public const uint KSparringGroundPartySlot3EC = 0xB8495C0F; // U32 Encryption Constant of 3rd PKM used in party - + public const uint KSparringStreakFlying = 0xDD5E19F1; // U32 Best Flying-Type Restricted Sparring Streak public const uint KSparringFlyingPartySlot1Species = 0xA17311F5; // U16 Species ID of 1st PKM used in party public const uint KSparringFlyingPartySlot2Species = 0xA0731062; // U16 Species ID of 2nd PKM used in party @@ -297,7 +297,7 @@ public SaveBlockAccessor8SWSH(SAV8SWSH sav) public const uint KSparringFlyingPartySlot1EC = 0x4292BAAF; // U32 Encryption Constant of 1st PKM used in party public const uint KSparringFlyingPartySlot2EC = 0x4192B91C; // U32 Encryption Constant of 2nd PKM used in party public const uint KSparringFlyingPartySlot3EC = 0x4492BDD5; // U32 Encryption Constant of 3rd PKM used in party - + public const uint KSparringStreakPsychic = 0xD45BCD2F; // U32 Best Psychic-Type Restricted Sparring Streak public const uint KSparringPsychicPartySlot1Species = 0x04C18EBF; // U16 Species ID of 1st PKM used in party public const uint KSparringPsychicPartySlot2Species = 0x03C18D2C; // U16 Species ID of 2nd PKM used in party @@ -311,7 +311,7 @@ public SaveBlockAccessor8SWSH(SAV8SWSH sav) public const uint KSparringPsychicPartySlot1EC = 0x896D7D61; // U32 Encryption Constant of 1st PKM used in party public const uint KSparringPsychicPartySlot2EC = 0x886D7BCE; // U32 Encryption Constant of 2nd PKM used in party public const uint KSparringPsychicPartySlot3EC = 0x876D7A3B; // U32 Encryption Constant of 3rd PKM used in party - + public const uint KSparringStreakBug = 0xE15E203D; // U32 Best Bug-Type Restricted Sparring Streak public const uint KSparringBugPartySlot1Species = 0xE9C80191; // U16 Species ID of 1st PKM used in party public const uint KSparringBugPartySlot2Species = 0xE8C7FFFE; // U16 Species ID of 2nd PKM used in party @@ -325,7 +325,7 @@ public SaveBlockAccessor8SWSH(SAV8SWSH sav) public const uint KSparringBugPartySlot1EC = 0x7B7A3613; // U32 Encryption Constant of 1st PKM used in party public const uint KSparringBugPartySlot2EC = 0x7A7A3480; // U32 Encryption Constant of 2nd PKM used in party public const uint KSparringBugPartySlot3EC = 0x7D7A3939; // U32 Encryption Constant of 3rd PKM used in party - + public const uint KSparringStreakRock = 0xDE5E1B84; // U32 Best Rock-Type Restricted Sparring Streak public const uint KSparringRockPartySlot1Species = 0xFE44971E; // U16 Species ID of 1st PKM used in party public const uint KSparringRockPartySlot2Species = 0xFF4498B1; // U16 Species ID of 2nd PKM used in party @@ -339,7 +339,7 @@ public SaveBlockAccessor8SWSH(SAV8SWSH sav) public const uint KSparringRockPartySlot1EC = 0x54D5CDC4; // U32 Encryption Constant of 1st PKM used in party public const uint KSparringRockPartySlot2EC = 0x55D5CF57; // U32 Encryption Constant of 2nd PKM used in party public const uint KSparringRockPartySlot3EC = 0x56D5D0EA; // U32 Encryption Constant of 3rd PKM used in party - + public const uint KSparringStreakGhost = 0xE05E1EAA; // U32 Best Ghost-Type Restricted Sparring Streak public const uint KSparringGhostPartySlot1Species = 0x63170940; // U16 Species ID of 1st PKM used in party public const uint KSparringGhostPartySlot2Species = 0x64170AD3; // U16 Species ID of 2nd PKM used in party @@ -353,7 +353,7 @@ public SaveBlockAccessor8SWSH(SAV8SWSH sav) public const uint KSparringGhostPartySlot1EC = 0x14C97022; // U32 Encryption Constant of 1st PKM used in party public const uint KSparringGhostPartySlot2EC = 0x15C971B5; // U32 Encryption Constant of 2nd PKM used in party public const uint KSparringGhostPartySlot3EC = 0x12C96CFC; // U32 Encryption Constant of 3rd PKM used in party - + public const uint KSparringStreakDragon = 0xD25BCA09; // U32 Best Dragon-Type Restricted Sparring Streak public const uint KSparringDragonPartySlot1Species = 0xC18E2C05; // U16 Species ID of 1st PKM used in party public const uint KSparringDragonPartySlot2Species = 0xC08E2A72; // U16 Species ID of 2nd PKM used in party @@ -367,7 +367,7 @@ public SaveBlockAccessor8SWSH(SAV8SWSH sav) public const uint KSparringDragonPartySlot1EC = 0x1B9619A3; // U32 Encryption Constant of 1st PKM used in party public const uint KSparringDragonPartySlot2EC = 0x1A961810; // U32 Encryption Constant of 2nd PKM used in party public const uint KSparringDragonPartySlot3EC = 0x1D961CC9; // U32 Encryption Constant of 3rd PKM used in party - + public const uint KSparringStreakDark = 0xCF5BC550; // U32 Best Dark-Type Restricted Sparring Streak public const uint KSparringDarkPartySlot1Species = 0xD6F84432; // U16 Species ID of 1st PKM used in party public const uint KSparringDarkPartySlot2Species = 0xD7F845C5; // U16 Species ID of 2nd PKM used in party diff --git a/PKHeX.Core/Saves/SAV4HGSS.cs b/PKHeX.Core/Saves/SAV4HGSS.cs index 617685888..6330f1d70 100644 --- a/PKHeX.Core/Saves/SAV4HGSS.cs +++ b/PKHeX.Core/Saves/SAV4HGSS.cs @@ -213,7 +213,7 @@ public void PokeGearUnlockAllCallersNoTrainers() public bool[] PokewalkerCoursesUnlocked { - get => ArrayUtil.GitBitFlagArray(General, OFS_WALKER + 0x8, 32); + get => ArrayUtil.GitBitFlagArray(General, OFS_WALKER + 0x8, 32); set => ArrayUtil.SetBitFlagArray(General, OFS_WALKER + 0x8, value); } diff --git a/PKHeX.Core/Saves/Substructures/Gen8/TrainerCard8.cs b/PKHeX.Core/Saves/Substructures/Gen8/TrainerCard8.cs index be3baafff..3a9ff9af7 100644 --- a/PKHeX.Core/Saves/Substructures/Gen8/TrainerCard8.cs +++ b/PKHeX.Core/Saves/Substructures/Gen8/TrainerCard8.cs @@ -91,7 +91,7 @@ public bool PokeDexComplete get => Data[Offset + 0x30] == 1; set => Data[Offset + 0x30] = (byte)(value ? 1 : 0); } - + public bool ArmorDexComplete { get => Data[Offset + 0x1B4] == 1; diff --git a/PKHeX.Core/Saves/Substructures/PokeDex/Zukan8.cs b/PKHeX.Core/Saves/Substructures/PokeDex/Zukan8.cs index 86ed1ae6b..65a7de0f8 100644 --- a/PKHeX.Core/Saves/Substructures/PokeDex/Zukan8.cs +++ b/PKHeX.Core/Saves/Substructures/PokeDex/Zukan8.cs @@ -76,21 +76,7 @@ private byte[] GetDexBlock(Zukan8Type infoDexType) return lookup; } - public class Zukan8EntryInfo - { - public readonly int Species; - public readonly Zukan8Index Entry; - - public Zukan8EntryInfo(int species, Zukan8Index entry) - { - Species = species; - Entry = entry; - } - - public string GetEntryName(IReadOnlyList speciesNames) => Entry.GetEntryName(speciesNames, Species); - } - - public List GetRawIndexes(PersonalTable pt, int dexRevision) + public static List GetRawIndexes(PersonalTable pt, int dexRevision) { var result = new List(); for (int i = 1; i <= pt.MaxSpeciesID; i++) @@ -738,11 +724,11 @@ private int GetSavedIndex() if (index < 1) throw new IndexOutOfRangeException(); - return (index - 1); + return index - 1; } public int Offset => GetSavedIndex() * Zukan8.EntrySize; - + private const int GalarCount = 400; private const int Rigel1Count = 211; private const int Rigel2Count = 2; @@ -787,6 +773,26 @@ public string GetEntryName(IReadOnlyList speciesNames, int species) { return $"{DexPrefix}.{Index:000} - {speciesNames[species]}"; } + + public override bool Equals(object obj) => obj is Zukan8Index x && x.Equals(this); + public bool Equals(Zukan8Index obj) => obj.Index == Index && obj.DexType == DexType; + public override int GetHashCode() => (int)DexType ^ (Index << 3); + public static bool operator ==(Zukan8Index left, Zukan8Index right) => left.Equals(right); + public static bool operator !=(Zukan8Index left, Zukan8Index right) => !(left == right); + } + + public class Zukan8EntryInfo + { + public readonly int Species; + public readonly Zukan8Index Entry; + + public Zukan8EntryInfo(int species, Zukan8Index entry) + { + Species = species; + Entry = entry; + } + + public string GetEntryName(IReadOnlyList speciesNames) => Entry.GetEntryName(speciesNames, Species); } public enum Zukan8Type : sbyte diff --git a/PKHeX.Drawing/Names/SpriteName.cs b/PKHeX.Drawing/Names/SpriteName.cs index bfcc1ab1f..c464b70f0 100644 --- a/PKHeX.Drawing/Names/SpriteName.cs +++ b/PKHeX.Drawing/Names/SpriteName.cs @@ -41,7 +41,9 @@ public static string GetResourceStringSprite(int species, int form, int gender, gender = 1; // Cosplay Pikachu gift can only be Female, but personal entries are set to be either Gender } else if (form == 8) + { sb.Append(GGStarter); + } } else if (species == (int) Species.Eevee) { diff --git a/PKHeX.WinForms/Subforms/PKM Editors/MemoryAmie.cs b/PKHeX.WinForms/Subforms/PKM Editors/MemoryAmie.cs index 93828293e..a2eab7f33 100644 --- a/PKHeX.WinForms/Subforms/PKM Editors/MemoryAmie.cs +++ b/PKHeX.WinForms/Subforms/PKM Editors/MemoryAmie.cs @@ -85,7 +85,6 @@ private void LoadFields() CB_CTFeel.SelectedIndex = m.HT_Feeling; } - CB_Handler.Items.Clear(); CB_Handler.Items.Add($"{pkm.OT_Name} ({TextArgs.OT})"); // OTNAME : OT diff --git a/PKHeX.WinForms/Subforms/PKM Editors/SuperTrainingEditor.cs b/PKHeX.WinForms/Subforms/PKM Editors/SuperTrainingEditor.cs index 665ef73c4..892f93f19 100644 --- a/PKHeX.WinForms/Subforms/PKM Editors/SuperTrainingEditor.cs +++ b/PKHeX.WinForms/Subforms/PKM Editors/SuperTrainingEditor.cs @@ -62,14 +62,10 @@ private void B_Save_Click(object sender, EventArgs e) Close(); } - private void PopulateRegimens(string Type, TableLayoutPanel TLP, List list) + private void PopulateRegimens(string propertyPrefix, TableLayoutPanel TLP, List list) { // Get a list of all Regimen Attregutes in the PKM - var RegimenNames = ReflectUtil.GetPropertiesStartWithPrefix(pkm.GetType(), Type); - list.AddRange(from RegimenName in RegimenNames - let RegimenValue = ReflectUtil.GetValue(pkm, RegimenName) - where RegimenValue is bool - select new RegimenInfo(RegimenName, (bool) RegimenValue)); + list.AddRange(GetBooleanRegimenNames(pkm, propertyPrefix)); TLP.ColumnCount = 1; TLP.RowCount = 0; @@ -84,6 +80,17 @@ private void PopulateRegimens(string Type, TableLayoutPanel TLP, List GetBooleanRegimenNames(ISuperTrain pkm, string propertyPrefix) + { + var names = ReflectUtil.GetPropertiesStartWithPrefix(pkm.GetType(), propertyPrefix); + foreach (var name in names) + { + var value = ReflectUtil.GetValue(pkm, name); + if (value is bool state) + yield return new RegimenInfo(name, state); + } + } + private static void AddRegimenChoice(RegimenInfo reg, TableLayoutPanel TLP) { // Get row we add to diff --git a/PKHeX.WinForms/Subforms/Save Editors/Gen6/SAV_HallOfFame.cs b/PKHeX.WinForms/Subforms/Save Editors/Gen6/SAV_HallOfFame.cs index edd472fc2..1316443a9 100644 --- a/PKHeX.WinForms/Subforms/Save Editors/Gen6/SAV_HallOfFame.cs +++ b/PKHeX.WinForms/Subforms/Save Editors/Gen6/SAV_HallOfFame.cs @@ -415,7 +415,7 @@ private void B_Delete_Click(object sender, EventArgs e) private void ChangeNickname(object sender, MouseEventArgs e) { - TextBox tb = !(sender is TextBox) ? TB_Nickname : (TextBox) sender; + TextBox tb = sender is TextBox box ? box : TB_Nickname; // Special Character Form if (ModifierKeys != Keys.Control) return; diff --git a/PKHeX.WinForms/Subforms/Save Editors/Gen8/SAV_PokedexSWSH.cs b/PKHeX.WinForms/Subforms/Save Editors/Gen8/SAV_PokedexSWSH.cs index 96f8d6788..1ba2faf6f 100644 --- a/PKHeX.WinForms/Subforms/Save Editors/Gen8/SAV_PokedexSWSH.cs +++ b/PKHeX.WinForms/Subforms/Save Editors/Gen8/SAV_PokedexSWSH.cs @@ -14,7 +14,7 @@ public partial class SAV_PokedexSWSH : Form private readonly Zukan8 Dex; private readonly CheckBox[] CL; private readonly CheckedListBox[] CHK; - private readonly IReadOnlyList Indexes; + private readonly IReadOnlyList Indexes; private int lastIndex = -1; private readonly bool CanSave; @@ -26,7 +26,7 @@ public SAV_PokedexSWSH(SAV8SWSH sav) WinFormsUtil.TranslateInterface(this, Main.CurrentLanguage); SAV = (SAV8SWSH)(Origin = sav).Clone(); Dex = SAV.Blocks.Zukan; - var indexes = Dex.GetRawIndexes(PersonalTable.SWSH, Dex.GetRevision()); + var indexes = Zukan8.GetRawIndexes(PersonalTable.SWSH, Dex.GetRevision()); var speciesNames = GameInfo.Strings.Species; Indexes = indexes.OrderBy(z => z.GetEntryName(speciesNames)).ToArray(); CL = new[] {CHK_L1, CHK_L2, CHK_L3, CHK_L4, CHK_L5, CHK_L6, CHK_L7, CHK_L8, CHK_L9}; @@ -112,7 +112,6 @@ private void GetEntry(int index) } else { - c.Items[63] = "Gigantamax"; } }