From 78d4fc8d8fac4f19cec3e07ead641b35c9678a96 Mon Sep 17 00:00:00 2001 From: Kurt Date: Sat, 1 Aug 2026 19:40:57 -0500 Subject: [PATCH] Handle baby->mother parent fetch Need to fix something with volbeat/nido for inheritance still. --- .../LearnSource/Sources/LearnSource2GS.cs | 7 ++- .../Moves/Breeding/ChainBreedLegality.cs | 55 ++++++++++++++----- .../Legality/ChainBreedLegalityTests.cs | 2 + 3 files changed, 46 insertions(+), 18 deletions(-) diff --git a/PKHeX.Core/Legality/LearnSource/Sources/LearnSource2GS.cs b/PKHeX.Core/Legality/LearnSource/Sources/LearnSource2GS.cs index b2a4cc728..0327224c4 100644 --- a/PKHeX.Core/Legality/LearnSource/Sources/LearnSource2GS.cs +++ b/PKHeX.Core/Legality/LearnSource/Sources/LearnSource2GS.cs @@ -51,13 +51,14 @@ public ReadOnlySpan GetEggMoves(ushort species, byte form) } // Present and not in Crystal: - // 001 (Bulbasaur) += Charm // 016 (Pidgey) += SteelWing - // 043 (Oddish) += Charm // 046 (Paras) += SweetScent // 083 (Farfetchd) += SteelWing - // 120 (Staryu) += AuroraBeam, Barrier, Supersonic // 142 (Aerodactyl) += SteelWing + // Inaccessible (no father in same egg group): + // 001 (Bulbasaur) += Charm + // 043 (Oddish) += Charm + // 120 (Staryu) += AuroraBeam, Barrier, Supersonic // 143 (Snorlax) += Charm // 238 (Smoochum) += LovelyKiss diff --git a/PKHeX.Core/Legality/Moves/Breeding/ChainBreedLegality.cs b/PKHeX.Core/Legality/Moves/Breeding/ChainBreedLegality.cs index bfc157861..df6e9442d 100644 --- a/PKHeX.Core/Legality/Moves/Breeding/ChainBreedLegality.cs +++ b/PKHeX.Core/Legality/Moves/Breeding/ChainBreedLegality.cs @@ -46,6 +46,7 @@ public static bool TryValidate(ushort species, byte form, GameVersion version, R // For male-only split breed species (Volbeat/Nidoran-M) in Gen 2-5, we need special validation: // All EGG moves must come from a single father. // Level-up moves don't need this restriction (can breed with Ditto). + // No cases of chain breeding combinations, so we can just check if a single father can pass all egg moves. var isMaleSplit = IsMaleOnlySplitBreed(species); if (isMaleSplit) { @@ -239,18 +240,7 @@ private static bool CanSingleFatherPassAllMoves(ushort motherSpecies, byte mothe continue; // Check if this father can learn ALL the moves - bool canLearnAll = true; - foreach (var move in moves) - { - if (move == 0) - break; - - // Father must be able to learn this move as an egg move or level-up move - if (CanFatherLearnMoveForEgg(fatherSpecies, fatherForm, move, learn)) - continue; - canLearnAll = false; - break; - } + var canLearnAll = CanFatherLearnAll(moves, fatherSpecies, fatherForm, learn); if (!canLearnAll) continue; @@ -262,6 +252,20 @@ private static bool CanSingleFatherPassAllMoves(ushort motherSpecies, byte mothe return false; // No single father can pass all moves } + private static bool CanFatherLearnAll(ReadOnlySpan moves, ushort fatherSpecies, byte fatherForm, ILearnSource learn) + { + foreach (var move in moves) + { + if (move == 0) + break; + // Father must be able to learn this move as an egg move or level-up move + if (CanFatherLearnMoveForEgg(fatherSpecies, fatherForm, move, learn)) + continue; + return false; + } + return true; + } + private static bool CanMotherAndFatherPassAllMoves(ushort motherSpecies, byte motherForm, GameVersion version, ReadOnlySpan moves, out ChainBreedSummary summary) { // For male-only split breed species in Gen 6-7: @@ -423,8 +427,7 @@ private static bool TryValidateBaseCounts(ushort eggSpecies, byte eggForm, GameV var suffix = moves.Slice(baseCount, inheritedCount); var suffixFlags = flags.Slice(baseCount, inheritedCount); - for (int i = 0; i < inheritedCount; i++) - inheritedMoves[i] = suffix[i]; + suffix.CopyTo(inheritedMoves); if (TryResolveInheritedSources(eggSpecies, eggForm, version, inheritedMoves[..inheritedCount], suffixFlags, 0, visited, depth + 1, out summary)) return true; @@ -463,6 +466,8 @@ private static bool TryResolveFather(ushort eggSpecies, byte eggForm, GameVersio return false; var mother = table[eggSpecies, eggForm]; + if (mother.EggGroup1 == (int)EggGroup.Undiscovered && TryGetEvolvedMother(eggSpecies, eggForm, version, out var newMother)) + mother = table[newMother.Species, newMother.Form]; // If the egg species can't breed (baby Pokemon like Tyrogue), check if its evolutions can act as fathers if (mother.Genderless || mother.OnlyMale || mother.EggGroup1 == (int)EggGroup.Undiscovered) @@ -496,9 +501,28 @@ private static bool TryResolveFather(ushort eggSpecies, byte eggForm, GameVersio return false; } + private static bool TryGetEvolvedMother(ushort eggSpecies, byte eggForm, GameVersion version, out (ushort Species, byte Form) newMother) + { + var tree = EvolutionTree.GetEvolutionTree(version.Context); + var evos = tree.Forward.GetEvolutions(eggSpecies, eggForm); + var pt = GameData.GetPersonal(version); + + foreach (var (evoSpecies, evoForm) in evos) + { + var pi = pt[evoSpecies, evoForm]; + if (pi.EggGroup1 == (int)EggGroup.Undiscovered) + continue; + + newMother = (evoSpecies, evoForm); + return true; + + } + newMother = default; + return false; + } + private static bool TryResolveFatherViaEvolution(ushort eggSpecies, byte eggForm, GameVersion version, ReadOnlySpan moves, Span visited, int depth, out ChainBreedSummary summary) { - summary = default; var tree = EvolutionTree.GetEvolutionTree(version.Context); var evos = tree.Forward.GetEvolutions(eggSpecies, eggForm); @@ -511,6 +535,7 @@ private static bool TryResolveFatherViaEvolution(ushort eggSpecies, byte eggForm return true; } + summary = default; return false; } diff --git a/Tests/PKHeX.Core.Tests/Legality/ChainBreedLegalityTests.cs b/Tests/PKHeX.Core.Tests/Legality/ChainBreedLegalityTests.cs index 8b09ec826..5eba6da34 100644 --- a/Tests/PKHeX.Core.Tests/Legality/ChainBreedLegalityTests.cs +++ b/Tests/PKHeX.Core.Tests/Legality/ChainBreedLegalityTests.cs @@ -32,6 +32,7 @@ public void DetectsInvalidChains(GameVersion version, Species species, params Mo [InlineData(HGSS, Mankey, Encore, Meditate, SmellingSalts)] [InlineData(GS, Chansey, DoubleEdge)] // via Jigglypuff (Level 39) [InlineData(Pt, Shellder, RapidSpin, IcicleSpear)] + [InlineData(R, Volbeat, HelpingHand)] // level up, breed with Illumise public void DetectsValidChains(GameVersion version, Species species, params Move[] movelist) => ValidateSimple(version, species, 0, movelist); @@ -60,6 +61,7 @@ private static void ValidateSimple(GameVersion version, Species species, byte fo [Theory] [InlineData(HGSS, Mankey, 0, Smeargle, Encore, Meditate, SmellingSalts)] + [InlineData(E, Pichu, 0, Smeargle, Reversal, Encore, Wish, Present)] // via Pikachu mother public void DetectsValidChainSmeargle(GameVersion version, Species species, byte form, Species father, params Move[] movelist) { var moves = GetMoves(movelist);