diff --git a/PKHeX.Core/Legality/Restrictions/Memories/MemoryContext.cs b/PKHeX.Core/Legality/Restrictions/Memories/MemoryContext.cs index fd5c71d6a..e7d9c9710 100644 --- a/PKHeX.Core/Legality/Restrictions/Memories/MemoryContext.cs +++ b/PKHeX.Core/Legality/Restrictions/Memories/MemoryContext.cs @@ -21,7 +21,7 @@ public abstract class MemoryContext 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); + public abstract bool IsInvalidMiscMemory(byte memory, ushort variable, Species species, GameVersion version, int handler); public abstract bool CanHaveIntensity(byte memory, byte intensity); public abstract bool CanHaveFeeling(byte memory, byte feeling, ushort argument); diff --git a/PKHeX.Core/Legality/Restrictions/Memories/MemoryContext6.cs b/PKHeX.Core/Legality/Restrictions/Memories/MemoryContext6.cs index bfac88b47..7207fe108 100644 --- a/PKHeX.Core/Legality/Restrictions/Memories/MemoryContext6.cs +++ b/PKHeX.Core/Legality/Restrictions/Memories/MemoryContext6.cs @@ -91,7 +91,7 @@ public sealed partial class MemoryContext6 : MemoryContext return false; // todo } - public override bool IsInvalidMiscMemory(byte memory, ushort variable) + public override bool IsInvalidMiscMemory(byte memory, ushort variable, Species species, GameVersion version, int handler) { return false; // todo } diff --git a/PKHeX.Core/Legality/Restrictions/Memories/MemoryContext8.cs b/PKHeX.Core/Legality/Restrictions/Memories/MemoryContext8.cs index d3a245184..e98b84364 100644 --- a/PKHeX.Core/Legality/Restrictions/Memories/MemoryContext8.cs +++ b/PKHeX.Core/Legality/Restrictions/Memories/MemoryContext8.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.Linq; +using static PKHeX.Core.Species; namespace PKHeX.Core; @@ -68,16 +69,47 @@ public sealed partial class MemoryContext8 : MemoryContext return IsInvalidGenLoc8Other(memory, variable); } - public override bool IsInvalidMiscMemory(byte memory, ushort variable) + public override bool IsInvalidMiscMemory(byte memory, ushort variable, Species species, GameVersion version, int handler) { return memory switch { // {0} encountered {2} when it was with {1}. {4} that {3}. - 29 when variable is not (888 or 889 or 890 or 898) => true, // Zacian, Zamazenta, Eternatus, Calyrex + 29 when !IsValidMemory29((Species)variable, species, version, handler) => true, _ => false, }; } + private static bool IsValidMemory29(Species encountered, Species species, GameVersion version, int handler) + { + // {0} encountered {2} when it was with {1}. {4} that {3}. + // Restrictions for this memory are based on game progress and version. + // These Pokémon are allowed to meet themselves if caught to an empty party slot. + + // Only these 4 species can appear in this memory. + if (encountered is not (Zacian or Zamazenta or Eternatus or Calyrex)) + return false; + + // If this is HT memory, it's possible to meet them in another game, so story progress doesn't matter. + if (handler == 1) + return true; + + // OT Memory checks from here on. + // Zacian and Zamazenta being in an OT memory need to match the Pokemon's version. + if (version == GameVersion.SW && encountered == Zamazenta) + return false; + if (version == GameVersion.SH && encountered == Zacian) + return false; + + return species switch + { + // Zacian and Zamazenta can't meet Eternatus as OT memory. + Zacian or Zamazenta => encountered != Eternatus, + // Calyrex, Spectrier, Glastrier can't meet Eternatus, Zacian, Zamazenta as OT memory. + Calyrex or Spectrier or Glastrier => encountered is not (Eternatus or Zacian or Zamazenta), + _ => true, + }; + } + private static bool CanObtainMemorySWSH(byte memory) => memory <= MAX_MEMORY_ID_SWSH && !Memory_NotSWSH.Contains(memory); public override bool CanWinLotoID(int item) => item < byte.MaxValue && LotoPrizeSWSH.Contains((byte)item); @@ -131,7 +163,7 @@ public sealed partial class MemoryContext8 : MemoryContext return false; if (pk is IRibbonSetMark8 { RibbonMarkCurry: true }) return false; - if (pk.Species == (int)Species.Shedinja && pk is IRibbonSetAffixed { AffixedRibbon: (int)RibbonIndex.MarkCurry }) + if (pk.Species == (int)Shedinja && pk is IRibbonSetAffixed { AffixedRibbon: (int)RibbonIndex.MarkCurry }) return false; return true; } @@ -140,7 +172,7 @@ public sealed partial class MemoryContext8 : MemoryContext { if (enc is not EncounterSlot8) return false; - return pk is IRibbonSetMark8 { RibbonMarkCurry: true } || pk.Species == (int)Species.Shedinja; + return pk is IRibbonSetMark8 { RibbonMarkCurry: true } || pk.Species == (int)Shedinja; } private static bool IsInvalidGenLoc8Other(byte memory, ushort variable) diff --git a/PKHeX.Core/Legality/Verifiers/MemoryVerifier.cs b/PKHeX.Core/Legality/Verifiers/MemoryVerifier.cs index ec011c069..2c47ba396 100644 --- a/PKHeX.Core/Legality/Verifiers/MemoryVerifier.cs +++ b/PKHeX.Core/Legality/Verifiers/MemoryVerifier.cs @@ -144,7 +144,7 @@ public sealed class MemoryVerifier : Verifier if (mem.IsInvalidGeneralLocationMemoryValue(memory.MemoryID, memory.Variable, info.EncounterMatch, pk)) return GetInvalid(string.Format(LMemoryArgBadLocation, memory.Handler)); - if (mem.IsInvalidMiscMemory(memory.MemoryID, memory.Variable)) + if (mem.IsInvalidMiscMemory(memory.MemoryID, memory.Variable, (Species)pk.Species, pk.Version, handler)) return GetInvalid(string.Format(LMemoryArgBadID, memory.Handler)); switch (memory.MemoryID)