From 41693b0142e17ad44513100cf372dd078e641c60 Mon Sep 17 00:00:00 2001 From: Kurt Date: Thu, 6 Jul 2023 19:41:27 -0700 Subject: [PATCH] Misc fixes --- .../HeldItemLumpImage.cs | 0 .../EncounterSlot/GO/EncounterSlot8GO.cs | 2 +- .../ByGeneration/EncounterGenerator8GO.cs | 3 ++ .../Encounters/Verifiers/EvolutionVerifier.cs | 4 +- .../EvolutionGroup/EvolutionGroupHOME.cs | 13 +++++- .../EvolutionGroup/EvolutionUtil.cs | 10 ----- PKHeX.Core/Legality/Learnset/Learnset.cs | 2 +- .../Legality/Moves/Breeding/BreedInfo.cs | 4 +- PKHeX.Core/Legality/RNG/Methods/Tera9RNG.cs | 28 ++++++++++++ .../Legality/Restrictions/GBRestrictions.cs | 2 +- PKHeX.Core/Legality/Tables/FormInfo.cs | 10 ++--- .../Verifiers/FormArgumentVerifier.cs | 8 +++- .../Verifiers/LegendsArceusVerifier.cs | 5 ++- PKHeX.Core/Legality/Verifiers/MiscVerifier.cs | 8 ++-- PKHeX.Core/PKM/HOME/PKH.cs | 4 ++ .../PKM/Util/Conversion/EntityConverter.cs | 8 +++- .../PKHeX.Core.Tests/Legality/LegalityData.cs | 43 ++++++------------- 17 files changed, 94 insertions(+), 60 deletions(-) rename PKHeX.Core/{Legality/Restrictions => Items}/HeldItemLumpImage.cs (100%) diff --git a/PKHeX.Core/Legality/Restrictions/HeldItemLumpImage.cs b/PKHeX.Core/Items/HeldItemLumpImage.cs similarity index 100% rename from PKHeX.Core/Legality/Restrictions/HeldItemLumpImage.cs rename to PKHeX.Core/Items/HeldItemLumpImage.cs diff --git a/PKHeX.Core/Legality/Encounters/EncounterSlot/GO/EncounterSlot8GO.cs b/PKHeX.Core/Legality/Encounters/EncounterSlot/GO/EncounterSlot8GO.cs index b383986dc..e010ebf93 100644 --- a/PKHeX.Core/Legality/Encounters/EncounterSlot/GO/EncounterSlot8GO.cs +++ b/PKHeX.Core/Legality/Encounters/EncounterSlot/GO/EncounterSlot8GO.cs @@ -39,7 +39,7 @@ public bool IsBallValid(Ball ball, ushort currentSpecies) protected override PKM GetBlank() => OriginFormat switch { - PogoImportFormat.PK7 => new PK8(), + PogoImportFormat.PK7 => new PK9(), PogoImportFormat.PB7 => new PB7(), PogoImportFormat.PK8 => new PK8(), PogoImportFormat.PA8 => new PA8(), diff --git a/PKHeX.Core/Legality/Encounters/Generator/ByGeneration/EncounterGenerator8GO.cs b/PKHeX.Core/Legality/Encounters/Generator/ByGeneration/EncounterGenerator8GO.cs index e6478849f..3b34a7206 100644 --- a/PKHeX.Core/Legality/Encounters/Generator/ByGeneration/EncounterGenerator8GO.cs +++ b/PKHeX.Core/Legality/Encounters/Generator/ByGeneration/EncounterGenerator8GO.cs @@ -57,6 +57,9 @@ public IEnumerable GetEncounters(PKM pk, EvoCriteria[] chain, Le if (area.Species != evo.Species) continue; + if (area.Form != evo.Form && !FormInfo.IsFormChangeable(area.Species, area.Form, evo.Form, EntityContext.Gen8, pk.Context)) + continue; + var slots = area.GetMatchingSlots(pk, evo); foreach (var z in slots) { diff --git a/PKHeX.Core/Legality/Encounters/Verifiers/EvolutionVerifier.cs b/PKHeX.Core/Legality/Encounters/Verifiers/EvolutionVerifier.cs index 603a96052..a93a89045 100644 --- a/PKHeX.Core/Legality/Encounters/Verifiers/EvolutionVerifier.cs +++ b/PKHeX.Core/Legality/Encounters/Verifiers/EvolutionVerifier.cs @@ -44,12 +44,12 @@ private static bool IsValidEvolution(PKM pk, EvolutionHistory history, IEncounte return true; // never evolved var current = history.Get(pk.Context); - if (!EvolutionUtil.Contains(current, curSpecies)) + if (!EvolutionHistory.HasVisited(current, curSpecies)) return false; // Can't exist as current species // Double check that our encounter was able to exist as the encounter species. var original = history.Get(enc.Context); - if (!EvolutionUtil.Contains(original, encSpecies)) + if (!EvolutionHistory.HasVisited(original, encSpecies)) return false; // Bigender->Fixed (non-Genderless) destination species, accounting for PID-Gender relationship diff --git a/PKHeX.Core/Legality/Evolutions/EvolutionGroup/EvolutionGroupHOME.cs b/PKHeX.Core/Legality/Evolutions/EvolutionGroup/EvolutionGroupHOME.cs index d5469ed50..5164808f0 100644 --- a/PKHeX.Core/Legality/Evolutions/EvolutionGroup/EvolutionGroupHOME.cs +++ b/PKHeX.Core/Legality/Evolutions/EvolutionGroup/EvolutionGroupHOME.cs @@ -254,5 +254,16 @@ public bool TryDevolve(ISpeciesForm head, PKM pk, byte currentMaxLevel, byte lev => Tree.Reverse.TryDevolve(head, pk, currentMaxLevel, levelMin, skipChecks, out result); public bool TryEvolve(ISpeciesForm head, ISpeciesForm next, PKM pk, byte currentMaxLevel, byte levelMin, bool skipChecks, out EvoCriteria result) - => Tree.Forward.TryEvolve(head, next, pk, currentMaxLevel, levelMin, skipChecks, out result); + { + var b = Tree.Forward.TryEvolve(head, next, pk, currentMaxLevel, levelMin, skipChecks, out result); + return b && !IsEvolutionBanned(head); + } + + // Unreleased Item + private static bool IsEvolutionBanned(in ISpeciesForm head) => head.Species switch + { + (int)Species.Slowpoke => head.Form != 1, + (int)Species.Slowbro => head.Form != 2, + _ => false, + }; } diff --git a/PKHeX.Core/Legality/Evolutions/EvolutionGroup/EvolutionUtil.cs b/PKHeX.Core/Legality/Evolutions/EvolutionGroup/EvolutionUtil.cs index dddcb2e1a..0ebeda606 100644 --- a/PKHeX.Core/Legality/Evolutions/EvolutionGroup/EvolutionUtil.cs +++ b/PKHeX.Core/Legality/Evolutions/EvolutionGroup/EvolutionUtil.cs @@ -83,16 +83,6 @@ public static int IndexOf(Span result, ushort species) return -1; } - public static bool Contains(ReadOnlySpan result, ushort species) - { - foreach (ref readonly var z in result) - { - if (z.Species == species) - return true; - } - return false; - } - /// /// Revises the to account for a new maximum . /// diff --git a/PKHeX.Core/Legality/Learnset/Learnset.cs b/PKHeX.Core/Legality/Learnset/Learnset.cs index 1f79c243e..06a049104 100644 --- a/PKHeX.Core/Legality/Learnset/Learnset.cs +++ b/PKHeX.Core/Legality/Learnset/Learnset.cs @@ -238,7 +238,7 @@ public int GetLevelLearnMove(ushort move) return Levels[index]; } - public ReadOnlySpan GetBaseEggMoves(int level) + public ReadOnlySpan GetBaseEggMoves(byte level) { // Count moves <= level var count = 0; diff --git a/PKHeX.Core/Legality/Moves/Breeding/BreedInfo.cs b/PKHeX.Core/Legality/Moves/Breeding/BreedInfo.cs index fbc1479a1..5c6744c95 100644 --- a/PKHeX.Core/Legality/Moves/Breeding/BreedInfo.cs +++ b/PKHeX.Core/Legality/Moves/Breeding/BreedInfo.cs @@ -21,9 +21,9 @@ namespace PKHeX.Core; public readonly ReadOnlySpan Moves; /// Level the egg originated at. - public readonly int Level; + public readonly byte Level; - public BreedInfo(Span actual, Span possible, Learnset learnset, ReadOnlySpan moves, int level) + public BreedInfo(Span actual, Span possible, Learnset learnset, ReadOnlySpan moves, byte level) { Actual = actual; Possible = possible; diff --git a/PKHeX.Core/Legality/RNG/Methods/Tera9RNG.cs b/PKHeX.Core/Legality/RNG/Methods/Tera9RNG.cs index b263de173..50c38bbd5 100644 --- a/PKHeX.Core/Legality/RNG/Methods/Tera9RNG.cs +++ b/PKHeX.Core/Legality/RNG/Methods/Tera9RNG.cs @@ -85,6 +85,34 @@ public static bool IsMatchTeraTypePersonalAnyForm(in ushort species, in byte ori return false; } + private static bool IsMatchTeraTypeImport(PersonalInfo9SV pi, in byte original) + { + var import = TeraTypeUtil.GetTeraTypeImport(pi.Type1, pi.Type2); + return (MoveType)original == import; + } + + public static bool IsMatchTeraTypePersonalImport(in ushort species, in byte form, in byte original) + { + var pi = PersonalTable.SV[species, form]; + return IsMatchTeraTypeImport(pi, original); + } + + public static bool IsMatchTeraTypePersonalAnyFormImport(in ushort species, in byte original) + { + var pt = PersonalTable.SV; + var pi = pt.GetFormEntry(species, 0); + if (pi.IsPresentInGame && IsMatchTeraTypeImport(pi, original)) + return true; + var fc = pi.FormCount; + for (byte form = 1; form < fc; form++) + { + pi = pt.GetFormEntry(species, form); + if (pi.IsPresentInGame && IsMatchTeraTypeImport(pi, original)) + return true; + } + return false; + } + public static byte GetTeraTypeFromPersonal(in ushort species, in byte form, in ulong pivot) { var pi = PersonalTable.SV[species, form]; diff --git a/PKHeX.Core/Legality/Restrictions/GBRestrictions.cs b/PKHeX.Core/Legality/Restrictions/GBRestrictions.cs index e45beca97..0bfd07e87 100644 --- a/PKHeX.Core/Legality/Restrictions/GBRestrictions.cs +++ b/PKHeX.Core/Legality/Restrictions/GBRestrictions.cs @@ -107,7 +107,7 @@ private static bool GetCatchRateMatchesPreEvolution(PK1 pk, byte catch_rate) return true; } - if (!EvolutionTree.Evolves1.Reverse.TryDevolve(head, pk, max, 2, false, out var next)) + if (!EvolutionGroup1.Instance.TryDevolve(head, pk, max, 2, false, out var next)) break; head = next; max = next.LevelMax; diff --git a/PKHeX.Core/Legality/Tables/FormInfo.cs b/PKHeX.Core/Legality/Tables/FormInfo.cs index 89249b515..d4a3e2094 100644 --- a/PKHeX.Core/Legality/Tables/FormInfo.cs +++ b/PKHeX.Core/Legality/Tables/FormInfo.cs @@ -110,12 +110,10 @@ public static bool IsFormChangeable(ushort species, byte oldForm, byte newForm, } if (species is (int)Deerling or (int)Sawsbuck) { - return origin switch - { - EntityContext.Gen5 => true, - EntityContext.Gen9 => true, - _ => false, // todo home sv - }; + if (origin == EntityContext.Gen5) + return true; // B/W + if (current.Generation() >= 8) + return true; // Via S/V } return false; } diff --git a/PKHeX.Core/Legality/Verifiers/FormArgumentVerifier.cs b/PKHeX.Core/Legality/Verifiers/FormArgumentVerifier.cs index 358e8c197..4dfddb3f2 100644 --- a/PKHeX.Core/Legality/Verifiers/FormArgumentVerifier.cs +++ b/PKHeX.Core/Legality/Verifiers/FormArgumentVerifier.cs @@ -35,7 +35,13 @@ private CheckResult VerifyFormArgument(LegalityAnalysis data, IFormArgument f) => GetValid(LFormArgumentValid), Furfrou when pk.Form != 0 => !IsFormArgumentDayCounterValid(f, 5, true) ? GetInvalid(LFormArgumentInvalid) : GetValid(LFormArgumentValid), - Hoopa when pk.Form == 1 => !IsFormArgumentDayCounterValid(f, 3) ? GetInvalid(LFormArgumentInvalid) : GetValid(LFormArgumentValid), + Hoopa when pk.Form == 1 => data.Info.EvoChainsAllGens switch + { + { HasVisitedGen9: true } when arg == 0 => GetValid(LFormArgumentValid), // Value not applied on form change, and reset when reverted. + { HasVisitedGen6: true } when IsFormArgumentDayCounterValid(f, 3) => GetValid(LFormArgumentValid), // 0-3 via OR/AS + { HasVisitedGen7: true } when IsFormArgumentDayCounterValid(f, 3) && f.FormArgumentRemain != 0 => GetValid(LFormArgumentValid), // 1-3 via Gen7 + _ => GetInvalid(LFormArgumentInvalid), + }, Yamask when pk.Form == 1 => arg switch { not 0 when pk.IsEgg => GetInvalid(LFormArgumentNotAllowed), diff --git a/PKHeX.Core/Legality/Verifiers/LegendsArceusVerifier.cs b/PKHeX.Core/Legality/Verifiers/LegendsArceusVerifier.cs index c47d789ea..58166d5b6 100644 --- a/PKHeX.Core/Legality/Verifiers/LegendsArceusVerifier.cs +++ b/PKHeX.Core/Legality/Verifiers/LegendsArceusVerifier.cs @@ -63,11 +63,14 @@ private static void CheckLearnset(LegalityAnalysis data, PA8 pa) if (moveCount == 4) return; + // Flag move slots that are empty. + if (pa.Tracker != 0 || !ParseSettings.IgnoreTransferIfNoTracker) + return; // Can delete moves in PA8 moveset via HOME. + // Get the bare minimum moveset. Span expect = stackalloc ushort[4]; var minMoveCount = LoadBareMinimumMoveset(data.EncounterMatch, data.Info.EvoChainsAllGens, pa, expect); - // Flag move slots that are empty. var moves = data.Info.Moves; for (int i = moveCount; i < minMoveCount; i++) { diff --git a/PKHeX.Core/Legality/Verifiers/MiscVerifier.cs b/PKHeX.Core/Legality/Verifiers/MiscVerifier.cs index 8f369408a..a0ced7478 100644 --- a/PKHeX.Core/Legality/Verifiers/MiscVerifier.cs +++ b/PKHeX.Core/Legality/Verifiers/MiscVerifier.cs @@ -192,20 +192,20 @@ private void VerifySVStats(LegalityAnalysis data, PK9 pk9) public static int GetTeraImportMatch(ReadOnlySpan evos, MoveType actual, IEncounterTemplate enc) { - // Sanitize out Form here for Arceus/Silvally -- rewrite via evotree later. - if (evos.Length == 0 || evos[0].Species is (int)Species.Arceus or (int)Species.Silvally) + // Sanitize out Form here for Arceus + if (evos.Length == 0 || evos[0].Species is (int)Species.Arceus) return actual == MoveType.Normal ? 0 : -1; for (int i = evos.Length - 1; i >= 0; i--) { var evo = evos[i]; if (FormInfo.IsFormChangeable(evo.Species, enc.Form, evo.Form, enc.Context, EntityContext.Gen9)) { - if (Tera9RNG.IsMatchTeraTypePersonalAnyForm(evo.Species, (byte)actual)) + if (Tera9RNG.IsMatchTeraTypePersonalAnyFormImport(evo.Species, (byte)actual)) return i; } else { - if (Tera9RNG.IsMatchTeraTypePersonal(evo.Species, evo.Form, (byte)actual)) + if (Tera9RNG.IsMatchTeraTypePersonalImport(evo.Species, evo.Form, (byte)actual)) return i; } } diff --git a/PKHeX.Core/PKM/HOME/PKH.cs b/PKHeX.Core/PKM/HOME/PKH.cs index 3c164c32e..70dcc6696 100644 --- a/PKHeX.Core/PKM/HOME/PKH.cs +++ b/PKHeX.Core/PKM/HOME/PKH.cs @@ -399,6 +399,10 @@ private void EnsureScaleSizeExists() { // Fix for PLA static encounter Alphas with 127 scale. Core.HeightScalar = Core.WeightScalar = 255; + if (DataPA8 is { Scale: not 255 } pa8) + pa8.Scale = 255; + if (DataPK9 is { Scale: not 255 } pk9) + pk9.Scale = 255; return; } if (GO_HOME || FirstScaleData is IScaledSize3) diff --git a/PKHeX.Core/PKM/Util/Conversion/EntityConverter.cs b/PKHeX.Core/PKM/Util/Conversion/EntityConverter.cs index fdea091b0..4083f8ff8 100644 --- a/PKHeX.Core/PKM/Util/Conversion/EntityConverter.cs +++ b/PKHeX.Core/PKM/Util/Conversion/EntityConverter.cs @@ -150,7 +150,13 @@ public static bool IsConvertibleToFormat(PKM pk, int format) // Every format can eventually feed into HOME. Don't bother checking current type. var type = PKH.GetType(destType); if (type is not HomeGameDataFormat.None) - return HOME.GetEntity(pk).ConvertToPKM(type); + { + var pkh = HOME.GetEntity(pk); + var converted = pkh.ConvertToPKM(type); + if (converted is null) + result = IncompatibleSpecies; + return converted; + } result = NoTransferRoute; return null; diff --git a/Tests/PKHeX.Core.Tests/Legality/LegalityData.cs b/Tests/PKHeX.Core.Tests/Legality/LegalityData.cs index 53ef7689d..55dc6544d 100644 --- a/Tests/PKHeX.Core.Tests/Legality/LegalityData.cs +++ b/Tests/PKHeX.Core.Tests/Legality/LegalityData.cs @@ -1,5 +1,3 @@ -using System.Linq; -using System.Reflection; using FluentAssertions; using Xunit; @@ -7,23 +5,24 @@ namespace PKHeX.Core.Tests.Legality; public class LegalityData { - [Fact] - public void EvolutionsOrdered() // feebas, see issue #2394 + [Theory] + [InlineData(Species.Feebas, 0)] // feebas, see issue #2394 + [InlineData(Species.Crabrawler, 0)] // SV Crabrawler added a second, UseItem evolution method. Need to be sure it's before the more restrictive level-up method. + public void EvolutionsOrdered(Species species, byte form) { int count = 0; - var trees = typeof(EvolutionTree) - .GetFields(BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic) - .Select(z => z.GetValue(typeof(EvolutionTree))) - .OfType(); - - foreach (var tree in trees) + for (var context = EntityContext.None + 1; context < EntityContext.MaxInvalid; context++) { - var feebas = tree.Forward.GetForward((int)Species.Feebas, 0).Span; - if (feebas.Length <= 1) + if (!context.IsValid()) continue; - var t1 = feebas[0].Method; - var t2 = feebas[1].Method; + var tree = EvolutionTree.GetEvolutionTree(context); + var possible = tree.Forward.GetForward((ushort)species, form).Span; + if (possible.Length <= 1) + continue; + + var t1 = possible[0].Method; + var t2 = possible[1].Method; t1.IsLevelUpRequired().Should().BeFalse(); t2.IsLevelUpRequired().Should().BeTrue(); @@ -31,20 +30,6 @@ public class LegalityData count++; } - count.Should().NotBe(0); - } - - [Fact] - public void EvolutionsOrderedSV() - { - // SV Crabrawler added a second, UseItem evolution method. Need to be sure it's before the more restrictive level-up method. - var tree = EvolutionTree.Evolves9; - var crab = tree.Forward.GetForward((int)Species.Crabrawler, 0).Span; - - var t1 = crab[0].Method; - var t2 = crab[1].Method; - - t1.IsLevelUpRequired().Should().BeFalse(); - t2.IsLevelUpRequired().Should().BeTrue(); + count.Should().BeGreaterThan(0); } }