mirror of
https://github.com/kwsch/PKHeX.git
synced 2026-04-27 11:07:08 -05:00
Misc edge case tests
Gen9a Antishiny edge case Evolve-move traversal tweaks; eager checks and more
This commit is contained in:
parent
812f8e847e
commit
18f95269c0
|
|
@ -321,13 +321,15 @@ private static uint GetAdaptedPID(ref Xoroshiro128Plus rand, PKM pk, in Generate
|
||||||
else // Never
|
else // Never
|
||||||
{
|
{
|
||||||
if (ShinyUtil.GetIsShiny6(fakeTID, pid)) // battled
|
if (ShinyUtil.GetIsShiny6(fakeTID, pid)) // battled
|
||||||
pid ^= 0x1000_0000;
|
pid = AntiShiny(pid);
|
||||||
if (ShinyUtil.GetIsShiny6(pk.ID32, pid)) // captured
|
if (ShinyUtil.GetIsShiny6(pk.ID32, pid)) // captured
|
||||||
pid ^= 0x1000_0000;
|
pid = AntiShiny(pid);
|
||||||
}
|
}
|
||||||
return pid;
|
return pid;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static uint AntiShiny(uint pid) => pid ^ 0x1000_0000;
|
||||||
|
|
||||||
private static bool IsMatchUnknownPreFillIVs(PKM pk, in GenerateParam9a enc, Xoroshiro128Plus rand)
|
private static bool IsMatchUnknownPreFillIVs(PKM pk, in GenerateParam9a enc, Xoroshiro128Plus rand)
|
||||||
{
|
{
|
||||||
int k = enc.FlawlessIVs;
|
int k = enc.FlawlessIVs;
|
||||||
|
|
|
||||||
|
|
@ -81,6 +81,12 @@ private static bool TryGetSeedConsecutive(in GenerateParam9a param, PKM pk, uint
|
||||||
private static bool TryGetSeedSkip(in GenerateParam9a param, PKM pk, uint ec, uint pid, out ulong seed)
|
private static bool TryGetSeedSkip(in GenerateParam9a param, PKM pk, uint ec, uint pid, out ulong seed)
|
||||||
{
|
{
|
||||||
var solver = new XoroMachineSkip(ec, pid);
|
var solver = new XoroMachineSkip(ec, pid);
|
||||||
|
if (TryGetSeed(param, pk, solver, out seed))
|
||||||
|
return true;
|
||||||
|
|
||||||
|
// Try again assuming the FakeTrainer XORed the resulting PID to be anti-shiny (terrible luck for the player).
|
||||||
|
pid = LumioseRNG.AntiShiny(pid);
|
||||||
|
solver = new XoroMachineSkip(ec, pid);
|
||||||
return TryGetSeed(param, pk, solver, out seed);
|
return TryGetSeed(param, pk, solver, out seed);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -13,10 +13,10 @@ public sealed class LearnGroup7 : ILearnGroup
|
||||||
|
|
||||||
public ILearnGroup? GetPrevious(PKM pk, EvolutionHistory history, IEncounterTemplate enc, LearnOption option) => enc.Generation switch
|
public ILearnGroup? GetPrevious(PKM pk, EvolutionHistory history, IEncounterTemplate enc, LearnOption option) => enc.Generation switch
|
||||||
{
|
{
|
||||||
Generation => null,
|
1 => LearnGroup1.Instance,
|
||||||
1 => history.HasVisitedGen1 ? LearnGroup1.Instance : null,
|
2 => LearnGroup2.Instance,
|
||||||
<= 2 => history.HasVisitedGen2 ? LearnGroup2.Instance : null,
|
(3 or 4 or 5 or 6) => LearnGroup6.Instance,
|
||||||
_ => history.HasVisitedGen6 ? LearnGroup6.Instance : null,
|
_ => null,
|
||||||
};
|
};
|
||||||
|
|
||||||
public bool HasVisited(PKM pk, EvolutionHistory history) => history.HasVisitedGen7;
|
public bool HasVisited(PKM pk, EvolutionHistory history) => history.HasVisitedGen7;
|
||||||
|
|
|
||||||
|
|
@ -54,7 +54,7 @@ public sealed class LearnGroup8 : ILearnGroup
|
||||||
|
|
||||||
var home = LearnGroupHOME.Instance;
|
var home = LearnGroupHOME.Instance;
|
||||||
if (option != LearnOption.HOME && home.HasVisited(pk, history))
|
if (option != LearnOption.HOME && home.HasVisited(pk, history))
|
||||||
return home.Check(result, current, pk, history, enc, types);
|
return home.Check(result, current, pk, history, enc, types, option);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -27,7 +27,7 @@ public sealed class LearnGroup8a : ILearnGroup
|
||||||
|
|
||||||
var home = LearnGroupHOME.Instance;
|
var home = LearnGroupHOME.Instance;
|
||||||
if (option != LearnOption.HOME && home.HasVisited(pk, history))
|
if (option != LearnOption.HOME && home.HasVisited(pk, history))
|
||||||
return home.Check(result, current, pk, history, enc, types);
|
return home.Check(result, current, pk, history, enc, types, option);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -33,7 +33,7 @@ public sealed class LearnGroup8b : ILearnGroup
|
||||||
|
|
||||||
var home = LearnGroupHOME.Instance;
|
var home = LearnGroupHOME.Instance;
|
||||||
if (option != LearnOption.HOME && home.HasVisited(pk, history))
|
if (option != LearnOption.HOME && home.HasVisited(pk, history))
|
||||||
return home.Check(result, current, pk, history, enc, types);
|
return home.Check(result, current, pk, history, enc, types, option);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -35,7 +35,7 @@ public sealed class LearnGroup9 : ILearnGroup
|
||||||
|
|
||||||
var home = LearnGroupHOME.Instance;
|
var home = LearnGroupHOME.Instance;
|
||||||
if (option != LearnOption.HOME && home.HasVisited(pk, history))
|
if (option != LearnOption.HOME && home.HasVisited(pk, history))
|
||||||
return home.Check(result, current, pk, history, enc, types);
|
return home.Check(result, current, pk, history, enc, types, option);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -30,7 +30,7 @@ public sealed class LearnGroup9a : ILearnGroup
|
||||||
|
|
||||||
var home = LearnGroupHOME.Instance;
|
var home = LearnGroupHOME.Instance;
|
||||||
if (option != LearnOption.HOME && home.HasVisited(pk, history))
|
if (option != LearnOption.HOME && home.HasVisited(pk, history))
|
||||||
return home.Check(result, current, pk, history, enc, types);
|
return home.Check(result, current, pk, history, enc, types, option);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -12,13 +12,14 @@ namespace PKHeX.Core;
|
||||||
public sealed class LearnGroupHOME : ILearnGroup
|
public sealed class LearnGroupHOME : ILearnGroup
|
||||||
{
|
{
|
||||||
public static readonly LearnGroupHOME Instance = new();
|
public static readonly LearnGroupHOME Instance = new();
|
||||||
|
private const LearnOption Option = LearnOption.HOME;
|
||||||
public ushort MaxMoveID => 0;
|
public ushort MaxMoveID => 0;
|
||||||
|
|
||||||
public ILearnGroup? GetPrevious(PKM pk, EvolutionHistory history, IEncounterTemplate enc, LearnOption option) => null;
|
public ILearnGroup? GetPrevious(PKM pk, EvolutionHistory history, IEncounterTemplate enc, LearnOption option) => null;
|
||||||
public bool HasVisited(PKM pk, EvolutionHistory history) => pk is IHomeTrack { HasTracker: true } || !ParseSettings.IgnoreTransferIfNoTracker;
|
public bool HasVisited(PKM pk, EvolutionHistory history) => pk is IHomeTrack { HasTracker: true } || !ParseSettings.IgnoreTransferIfNoTracker;
|
||||||
|
|
||||||
public bool Check(Span<MoveResult> result, ReadOnlySpan<ushort> current, PKM pk, EvolutionHistory history,
|
public bool Check(Span<MoveResult> result, ReadOnlySpan<ushort> current, PKM pk, EvolutionHistory history,
|
||||||
IEncounterTemplate enc, MoveSourceType types = MoveSourceType.All, LearnOption option = LearnOption.HOME)
|
IEncounterTemplate enc, MoveSourceType types = MoveSourceType.All, LearnOption option = Option)
|
||||||
{
|
{
|
||||||
var context = pk.Context;
|
var context = pk.Context;
|
||||||
if (context == EntityContext.None)
|
if (context == EntityContext.None)
|
||||||
|
|
@ -29,36 +30,36 @@ public sealed class LearnGroupHOME : ILearnGroup
|
||||||
if (history.HasVisitedGen9 && pk is not PK9)
|
if (history.HasVisitedGen9 && pk is not PK9)
|
||||||
{
|
{
|
||||||
var instance = LearnGroup9.Instance;
|
var instance = LearnGroup9.Instance;
|
||||||
instance.Check(result, current, pk, history, enc, types, option);
|
instance.Check(result, current, pk, history, enc, types, Option);
|
||||||
if (CleanPurge(result, current, pk, types, local, evos))
|
if (CleanPurge(result, current, pk, types, local, evos, option))
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (history.HasVisitedZA && pk is not PA9)
|
if (history.HasVisitedZA && pk is not PA9)
|
||||||
{
|
{
|
||||||
var instance = LearnGroup9a.Instance;
|
var instance = LearnGroup9a.Instance;
|
||||||
instance.Check(result, current, pk, history, enc, types, option);
|
instance.Check(result, current, pk, history, enc, types, Option);
|
||||||
if (CleanPurge(result, current, pk, types, local, evos))
|
if (CleanPurge(result, current, pk, types, local, evos, option))
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (history.HasVisitedSWSH && pk is not PK8)
|
if (history.HasVisitedSWSH && pk is not PK8)
|
||||||
{
|
{
|
||||||
var instance = LearnGroup8.Instance;
|
var instance = LearnGroup8.Instance;
|
||||||
instance.Check(result, current, pk, history, enc, types, option);
|
instance.Check(result, current, pk, history, enc, types, Option);
|
||||||
if (CleanPurge(result, current, pk, types, local, evos))
|
if (CleanPurge(result, current, pk, types, local, evos, option))
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (history.HasVisitedPLA && pk is not PA8)
|
if (history.HasVisitedPLA && pk is not PA8)
|
||||||
{
|
{
|
||||||
var instance = LearnGroup8a.Instance;
|
var instance = LearnGroup8a.Instance;
|
||||||
instance.Check(result, current, pk, history, enc, types, option);
|
instance.Check(result, current, pk, history, enc, types, Option);
|
||||||
if (CleanPurge(result, current, pk, types, local, evos))
|
if (CleanPurge(result, current, pk, types, local, evos, option))
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (history.HasVisitedBDSP && pk is not PB8)
|
if (history.HasVisitedBDSP && pk is not PB8)
|
||||||
{
|
{
|
||||||
var instance = LearnGroup8b.Instance;
|
var instance = LearnGroup8b.Instance;
|
||||||
instance.Check(result, current, pk, history, enc, types, option);
|
instance.Check(result, current, pk, history, enc, types, Option);
|
||||||
if (CleanPurge(result, current, pk, types, local, evos))
|
if (CleanPurge(result, current, pk, types, local, evos, option))
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -67,14 +68,14 @@ public sealed class LearnGroupHOME : ILearnGroup
|
||||||
// SW/SH is the only game that can ever harbor external moves, and is the only game that uses Battle Version.
|
// SW/SH is the only game that can ever harbor external moves, and is the only game that uses Battle Version.
|
||||||
if (TryAddOriginalMoves(result, current, pk, enc))
|
if (TryAddOriginalMoves(result, current, pk, enc))
|
||||||
{
|
{
|
||||||
if (CleanPurge(result, current, pk, types, local, evos))
|
if (CleanPurge(result, current, pk, types, local, evos, option))
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// HOME is silly and allows form exclusive moves to be transferred without ever knowing the move.
|
// HOME is silly and allows form exclusive moves to be transferred without ever knowing the move.
|
||||||
if (TryAddExclusiveMoves(result, current, pk))
|
if (TryAddExclusiveMoves(result, current, pk))
|
||||||
{
|
{
|
||||||
if (CleanPurge(result, current, pk, types, local, evos))
|
if (CleanPurge(result, current, pk, types, local, evos, option))
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -82,8 +83,8 @@ public sealed class LearnGroupHOME : ILearnGroup
|
||||||
{
|
{
|
||||||
// PK8 w/ Battle Version can be ignored, as LGP/E has separate HOME data.
|
// PK8 w/ Battle Version can be ignored, as LGP/E has separate HOME data.
|
||||||
var instance = LearnGroup7b.Instance;
|
var instance = LearnGroup7b.Instance;
|
||||||
instance.Check(result, current, pk, history, enc, types, option);
|
instance.Check(result, current, pk, history, enc, types, Option);
|
||||||
if (CleanPurge(result, current, pk, types, local, evos))
|
if (CleanPurge(result, current, pk, types, local, evos, option))
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
else if (history.HasVisitedGen7)
|
else if (history.HasVisitedGen7)
|
||||||
|
|
@ -93,8 +94,8 @@ public sealed class LearnGroupHOME : ILearnGroup
|
||||||
ILearnGroup instance = LearnGroup7.Instance;
|
ILearnGroup instance = LearnGroup7.Instance;
|
||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
instance.Check(result, current, pk, history, enc, types, option);
|
instance.Check(result, current, pk, history, enc, types, Option);
|
||||||
if (CleanPurge(result, current, pk, types, local, evos))
|
if (CleanPurge(result, current, pk, types, local, evos, option))
|
||||||
return true;
|
return true;
|
||||||
var prev = instance.GetPrevious(pk, history, enc, option);
|
var prev = instance.GetPrevious(pk, history, enc, option);
|
||||||
if (prev is null)
|
if (prev is null)
|
||||||
|
|
@ -111,8 +112,11 @@ public sealed class LearnGroupHOME : ILearnGroup
|
||||||
/// Scan the results and remove any that are not valid for the game <see cref="local"/> game.
|
/// Scan the results and remove any that are not valid for the game <see cref="local"/> game.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns>True if all results are valid.</returns>
|
/// <returns>True if all results are valid.</returns>
|
||||||
private static bool CleanPurge(Span<MoveResult> result, ReadOnlySpan<ushort> current, PKM pk, MoveSourceType types, IHomeSource local, ReadOnlySpan<EvoCriteria> evos)
|
private static bool CleanPurge(Span<MoveResult> result, ReadOnlySpan<ushort> current, PKM pk, MoveSourceType types, IHomeSource local, ReadOnlySpan<EvoCriteria> evos, LearnOption option)
|
||||||
{
|
{
|
||||||
|
if (option == LearnOption.AtAnyTime)
|
||||||
|
return MoveResult.AllParsed(result);
|
||||||
|
|
||||||
// The logic used to update the results did not check if the move could be learned in the local game.
|
// The logic used to update the results did not check if the move could be learned in the local game.
|
||||||
// Double-check the results and remove any that are not valid for the local game.
|
// Double-check the results and remove any that are not valid for the local game.
|
||||||
// SW/SH will continue to iterate downwards to previous groups after HOME is checked, so we can exactly check via Environment.
|
// SW/SH will continue to iterate downwards to previous groups after HOME is checked, so we can exactly check via Environment.
|
||||||
|
|
|
||||||
|
|
@ -15,6 +15,9 @@ internal static class EvolutionRestrictions
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// List of species that evolve from a previous species having a move while leveling up
|
/// List of species that evolve from a previous species having a move while leveling up
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Using moves with a counter stored in form argument is explicitly checked via other logic. <see cref="IsFormArgEvolution"/>
|
||||||
|
/// </remarks>
|
||||||
private static ushort GetSpeciesEvolutionMove(ushort species) => species switch
|
private static ushort GetSpeciesEvolutionMove(ushort species) => species switch
|
||||||
{
|
{
|
||||||
(int)Sylveon => EEVEE,
|
(int)Sylveon => EEVEE,
|
||||||
|
|
@ -28,15 +31,22 @@ internal static class EvolutionRestrictions
|
||||||
(int)Tsareena => (int)Stomp,
|
(int)Tsareena => (int)Stomp,
|
||||||
(int)Naganadel => (int)DragonPulse,
|
(int)Naganadel => (int)DragonPulse,
|
||||||
(int)Grapploct => (int)Taunt,
|
(int)Grapploct => (int)Taunt,
|
||||||
|
|
||||||
|
// Form Argument evolutions sometimes with extra conditions; verify here because they aren't checked "completely" elsewhere (yet).
|
||||||
(int)Wyrdeer => (int)PsyshieldBash,
|
(int)Wyrdeer => (int)PsyshieldBash,
|
||||||
(int)Overqwil => (int)BarbBarrage,
|
(int)Overqwil => (int)BarbBarrage,
|
||||||
(int)Annihilape => (int)RageFist,
|
(int)Annihilape => (int)RageFist,
|
||||||
|
|
||||||
(int)Farigiraf => (int)TwinBeam,
|
(int)Farigiraf => (int)TwinBeam,
|
||||||
(int)Dudunsparce => (int)HyperDrill,
|
(int)Dudunsparce => (int)HyperDrill,
|
||||||
(int)Hydrapple => (int)DragonCheer,
|
(int)Hydrapple => (int)DragonCheer,
|
||||||
_ => NONE,
|
_ => NONE,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Checks if the evolution is the "rare" variant (less common).
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="encryptionConstant">Random value used to pivot between evolution results.</param>
|
||||||
public static bool IsEvolvedSpeciesFormRare(uint encryptionConstant) => encryptionConstant % 100 is 0;
|
public static bool IsEvolvedSpeciesFormRare(uint encryptionConstant) => encryptionConstant % 100 is 0;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
@ -50,6 +60,9 @@ internal static class EvolutionRestrictions
|
||||||
_ => throw new ArgumentOutOfRangeException(nameof(species), species, "Incorrect EC%100 species."),
|
_ => throw new ArgumentOutOfRangeException(nameof(species), species, "Incorrect EC%100 species."),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Checks if the evolution result matches what is expected for <see cref="IsEvolvedSpeciesFormRare"/>
|
||||||
|
/// </summary>
|
||||||
public static bool GetIsExpectedEvolveFormEC100(ushort species, byte form, bool rare) => species switch
|
public static bool GetIsExpectedEvolveFormEC100(ushort species, byte form, bool rare) => species switch
|
||||||
{
|
{
|
||||||
(ushort)Maushold => form == (byte)(rare ? 0 : 1),
|
(ushort)Maushold => form == (byte)(rare ? 0 : 1),
|
||||||
|
|
@ -76,6 +89,9 @@ public static bool IsFormArgEvolution(ushort species)
|
||||||
/// Checks if the <see cref="pk"/> is correctly evolved, assuming it had a known move requirement evolution in its evolution chain.
|
/// Checks if the <see cref="pk"/> is correctly evolved, assuming it had a known move requirement evolution in its evolution chain.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns>True if unnecessary to check or the evolution was valid.</returns>
|
/// <returns>True if unnecessary to check or the evolution was valid.</returns>
|
||||||
|
/// <remarks>
|
||||||
|
/// Performs some eager checks to skip doing a full evolution tree move check.
|
||||||
|
/// </remarks>
|
||||||
public static bool IsValidEvolutionWithMove(PKM pk, LegalInfo info)
|
public static bool IsValidEvolutionWithMove(PKM pk, LegalInfo info)
|
||||||
{
|
{
|
||||||
// Known-move evolutions were introduced in Gen4.
|
// Known-move evolutions were introduced in Gen4.
|
||||||
|
|
@ -88,6 +104,15 @@ public static bool IsValidEvolutionWithMove(PKM pk, LegalInfo info)
|
||||||
if (enc.Species == species)
|
if (enc.Species == species)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
|
// All move evolutions arrive at a maximally-evolved species chain.
|
||||||
|
// Except for Mr. Rime -- just manually devolve and let the rest of the logic check.
|
||||||
|
if (species is (ushort)MrRime)
|
||||||
|
{
|
||||||
|
species = (ushort)MrMime;
|
||||||
|
if (enc.Species == species)
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
// Exclude evolution paths that did not require a move w/level-up evolution
|
// Exclude evolution paths that did not require a move w/level-up evolution
|
||||||
var move = GetSpeciesEvolutionMove(species);
|
var move = GetSpeciesEvolutionMove(species);
|
||||||
if (move is NONE)
|
if (move is NONE)
|
||||||
|
|
@ -95,6 +120,10 @@ public static bool IsValidEvolutionWithMove(PKM pk, LegalInfo info)
|
||||||
if (!IsMoveSlotAvailable(info.Moves))
|
if (!IsMoveSlotAvailable(info.Moves))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
// Check if the move is in relearn moves (can know at any time)
|
||||||
|
if (pk.Format >= 6 && IsMoveInRelearnSource(pk, info, move))
|
||||||
|
return true;
|
||||||
|
|
||||||
// Check the entire chain to see if it could have learnt it at any point.
|
// Check the entire chain to see if it could have learnt it at any point.
|
||||||
var head = LearnGroupUtil.GetCurrentGroup(pk);
|
var head = LearnGroupUtil.GetCurrentGroup(pk);
|
||||||
var pruned = info.EvoChainsAllGens.PruneKeepPreEvolutions(species);
|
var pruned = info.EvoChainsAllGens.PruneKeepPreEvolutions(species);
|
||||||
|
|
@ -104,6 +133,54 @@ public static bool IsValidEvolutionWithMove(PKM pk, LegalInfo info)
|
||||||
return MemoryPermissions.GetCanKnowMove(enc, move, pruned, pk, head);
|
return MemoryPermissions.GetCanKnowMove(enc, move, pruned, pk, head);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static bool IsMoveInRelearnSource(PKM pk, LegalInfo info, ushort move)
|
||||||
|
{
|
||||||
|
if (move is not EEVEE)
|
||||||
|
return IsMoveInRelearn(pk, info, move);
|
||||||
|
return IsMoveInRelearn(pk, info, EeveeFairyMoves);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static bool IsMoveInRelearn(PKM pk, LegalInfo info, ReadOnlySpan<ushort> arr)
|
||||||
|
{
|
||||||
|
foreach (var move in arr)
|
||||||
|
{
|
||||||
|
if (IsMoveInRelearn(pk, info, move))
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static bool IsMoveInRelearn(PKM pk, LegalInfo info, ushort move)
|
||||||
|
{
|
||||||
|
if (pk.IsOriginalMovesetDeleted())
|
||||||
|
return WasMoveInRelearn(pk, info, move);
|
||||||
|
|
||||||
|
var first = pk.RelearnMove1;
|
||||||
|
if (first is 0) // eager check
|
||||||
|
return false;
|
||||||
|
if (pk.RelearnMove1 == move)
|
||||||
|
return true;
|
||||||
|
if (pk.RelearnMove2 == move)
|
||||||
|
return true;
|
||||||
|
if (pk.RelearnMove3 == move)
|
||||||
|
return true;
|
||||||
|
if (pk.RelearnMove4 == move)
|
||||||
|
return true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static bool WasMoveInRelearn(PKM pk, LegalInfo info, ushort move)
|
||||||
|
{
|
||||||
|
for (var i = 0; i < info.Moves.Length; i++)
|
||||||
|
{
|
||||||
|
if (pk.GetMove(i) != move)
|
||||||
|
continue;
|
||||||
|
var method = info.Moves[i].Info.Method;
|
||||||
|
return method is { IsEggSource: true } or { IsRelearn: true } or LearnMethod.Encounter;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
private static bool IsValidEvolutionWithMoveAny(IEncounterTemplate enc, ReadOnlySpan<ushort> any, EvolutionHistory history, PKM pk, ILearnGroup head)
|
private static bool IsValidEvolutionWithMoveAny(IEncounterTemplate enc, ReadOnlySpan<ushort> any, EvolutionHistory history, PKM pk, ILearnGroup head)
|
||||||
{
|
{
|
||||||
foreach (var move in any)
|
foreach (var move in any)
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user