diff --git a/PKHeX.Core/Legality/Core.cs b/PKHeX.Core/Legality/Core.cs index cd151b069..3d204ef07 100644 --- a/PKHeX.Core/Legality/Core.cs +++ b/PKHeX.Core/Legality/Core.cs @@ -2195,5 +2195,31 @@ public static int[] GetEncounterMoves(PKM pk, int level, GameVersion version) var index = table.GetFormeIndex(pk.Species, pk.AltForm); return learn[index].GetEncounterMoves(level); } + + public static LanguageID GetSafeLanguage(int generation, LanguageID prefer, GameVersion game = GameVersion.Any) + { + switch (generation) + { + case 1: + case 2: + if (Languages_GB.Contains((int)prefer) && (prefer != LanguageID.Korean || game == GameVersion.C)) + return prefer; + return LanguageID.English; + case 3: + if (Languages_3.Contains((int) prefer)) + return prefer; + return LanguageID.English; + case 4: + case 5: + case 6: + if (Languages_46.Contains((int)prefer)) + return prefer; + return LanguageID.English; + default: + if (Languages_7.Contains((int)prefer)) + return prefer; + return LanguageID.English; + } + } } } diff --git a/PKHeX.Core/Legality/Encounters/Data/EncounterUtil.cs b/PKHeX.Core/Legality/Encounters/Data/EncounterUtil.cs index 17d086276..41201189b 100644 --- a/PKHeX.Core/Legality/Encounters/Data/EncounterUtil.cs +++ b/PKHeX.Core/Legality/Encounters/Data/EncounterUtil.cs @@ -261,5 +261,11 @@ internal static void MarkEncounterTradeStrings(EncounterTrade[] table, string[][ } string[] getNames(int i, IEnumerable names) => names?.Select(z => z?.Length > i ? z[i] : null).ToArray(); } + + internal static void MarkEncounterGame(IEnumerable table, GameVersion version) + { + foreach (var t in table.Where(z => z.Version == GameVersion.Any)) + t.Version = version; + } } } diff --git a/PKHeX.Core/Legality/Encounters/Data/Encounters6.cs b/PKHeX.Core/Legality/Encounters/Data/Encounters6.cs index 9452973af..bf30dbd12 100644 --- a/PKHeX.Core/Legality/Encounters/Data/Encounters6.cs +++ b/PKHeX.Core/Legality/Encounters/Data/Encounters6.cs @@ -373,18 +373,18 @@ private static void MarkG6AOSlots(ref EncounterArea[] Areas) internal static readonly EncounterLink[] LinkGifts6 = { - new EncounterLink { Species = 154, Level = 50, Ability = 4, XY = true, ORAS = true }, // Meganium - new EncounterLink { Species = 157, Level = 50, Ability = 4, XY = true, ORAS = true }, // Typhlosion - new EncounterLink { Species = 160, Level = 50, Ability = 4, XY = true, ORAS = true, Moves = new [] {8} }, // Feraligatr with Ice Punch (not relearn) + new EncounterLink { Species = 154, Level = 50, Ability = 4, }, // Meganium + new EncounterLink { Species = 157, Level = 50, Ability = 4, }, // Typhlosion + new EncounterLink { Species = 160, Level = 50, Ability = 4, Moves = new [] {8} }, // Feraligatr with Ice Punch (not relearn) - new EncounterLink { Species = 251, Level = 10, Ability = 1, RelearnMoves = new[] {610, 0, 0, 0}, Ball = 11, XY = true }, // Celebi + new EncounterLink { Species = 251, Level = 10, Ability = 1, RelearnMoves = new[] {610, 0, 0, 0}, Ball = 11, Version = GameVersion.XY }, // Celebi - new EncounterLink { Species = 377, Level = 50, Ability = 4, RelearnMoves = new[] {153, 8, 444, 359}, XY = true, ORAS = true }, // Regirock - new EncounterLink { Species = 378, Level = 50, Ability = 4, RelearnMoves = new[] {85, 133, 58, 258}, XY = true, ORAS = true }, // Regice - new EncounterLink { Species = 379, Level = 50, Ability = 4, RelearnMoves = new[] {442, 157, 356, 334}, XY = true, ORAS = true }, // Registeel + new EncounterLink { Species = 377, Level = 50, Ability = 4, RelearnMoves = new[] {153, 8, 444, 359}, }, // Regirock + new EncounterLink { Species = 378, Level = 50, Ability = 4, RelearnMoves = new[] {85, 133, 58, 258}, }, // Regice + new EncounterLink { Species = 379, Level = 50, Ability = 4, RelearnMoves = new[] {442, 157, 356, 334}, }, // Registeel - new EncounterLink { Species = 208, Level = 40, Ability = 1, RibbonClassic = false, ORAS = true, OT = false }, // Steelix - new EncounterLink { Species = 362, Level = 40, Ability = 1, RibbonClassic = false, ORAS = true, OT = false }, // Glalie + new EncounterLink { Species = 208, Level = 40, Ability = 1, RibbonClassic = false, Version = GameVersion.ORAS, OT = false }, // Steelix + new EncounterLink { Species = 362, Level = 40, Ability = 1, RibbonClassic = false, Version = GameVersion.ORAS, OT = false }, // Glalie }; #endregion } diff --git a/PKHeX.Core/Legality/Encounters/EncounterLink.cs b/PKHeX.Core/Legality/Encounters/EncounterLink.cs index 560b66758..46752bace 100644 --- a/PKHeX.Core/Legality/Encounters/EncounterLink.cs +++ b/PKHeX.Core/Legality/Encounters/EncounterLink.cs @@ -5,7 +5,7 @@ namespace PKHeX.Core /// /// Pokémon Link Encounter Data /// - public class EncounterLink : IEncounterable, IRibbonSetEvent4, IMoveset, ILocation + public class EncounterLink : IEncounterable, IRibbonSetEvent4, IMoveset, ILocation, IVersion { public int Species { get; set; } public int Level { get; set; } @@ -19,9 +19,7 @@ public class EncounterLink : IEncounterable, IRibbonSetEvent4, IMoveset, ILocati public bool EggEncounter => false; public int EggLocation { get => 0; set { } } - - public bool XY { get; set; } - public bool ORAS { get; set; } + public GameVersion Version { get; set; } = GameVersion.Gen6; public int[] Moves { get; set; } = new int[0]; @@ -42,15 +40,15 @@ public class EncounterLink : IEncounterable, IRibbonSetEvent4, IMoveset, ILocati public PKM ConvertToPKM(ITrainerInfo SAV) { const int gen = 6; - int version = GetCompatibleVersion(SAV.Game); - int lang = SAV.Language > (int) LanguageID.ChineseT ? (int) LanguageID.English : SAV.Language; + var version = this.GetCompatibleVersion((GameVersion)SAV.Game); + int lang = (int)Legal.GetSafeLanguage(6, (LanguageID)SAV.Language); var pk = new PK6 { EncryptionConstant = Util.Rand32(), Species = Species, Language = lang, CurrentLevel = Level, - Version = version, + Version = (int)version, PID = Util.Rand32(), Nickname = PKX.GetSpeciesNameGeneration(Species, lang, gen), Ball = Ball, @@ -78,19 +76,5 @@ public PKM ConvertToPKM(ITrainerInfo SAV) return pk; } - - private int GetCompatibleVersion(int savGame) - { - if (XY) - { - if (savGame == (int)GameVersion.X || savGame == (int)GameVersion.Y) - return savGame; - return (int) GameVersion.X + Util.Rand.Next(2); - } - // AO - if (savGame == (int)GameVersion.OR || savGame == (int)GameVersion.AS) - return savGame; - return (int)GameVersion.AS + Util.Rand.Next(2); - } } } diff --git a/PKHeX.Core/Legality/Encounters/EncounterSlot.cs b/PKHeX.Core/Legality/Encounters/EncounterSlot.cs index fdfab7025..ca7de8d18 100644 --- a/PKHeX.Core/Legality/Encounters/EncounterSlot.cs +++ b/PKHeX.Core/Legality/Encounters/EncounterSlot.cs @@ -19,7 +19,7 @@ public class EncounterSlotPermissions /// /// Wild Encounter Slot data /// - public class EncounterSlot : IEncounterable, IGeneration, ILocation + public class EncounterSlot : IEncounterable, IGeneration, ILocation, IVersion { public int Species { get; set; } public int Form { get; set; } @@ -31,8 +31,9 @@ public class EncounterSlot : IEncounterable, IGeneration, ILocation public int Generation { get; set; } = -1; internal EncounterSlotPermissions _perm; public EncounterSlotPermissions Permissions => _perm ?? (_perm = new EncounterSlotPermissions()); + public GameVersion Version { get; set; } - internal EncounterArea Area { get; set; } + internal EncounterArea Area { private get; set; } public int Location { get => Area.Location; set { } } public bool EggEncounter => false; public int EggLocation { get => 0; set { } } diff --git a/PKHeX.Core/Legality/Encounters/EncounterSlot1.cs b/PKHeX.Core/Legality/Encounters/EncounterSlot1.cs index d1fe5ecfd..2bcac5590 100644 --- a/PKHeX.Core/Legality/Encounters/EncounterSlot1.cs +++ b/PKHeX.Core/Legality/Encounters/EncounterSlot1.cs @@ -11,6 +11,5 @@ internal class EncounterSlot1 : EncounterSlot { public int Rate; internal EncounterTime Time = EncounterTime.Any; - public GameVersion Version = GameVersion.Any; } } \ No newline at end of file diff --git a/PKHeX.Core/Legality/Encounters/EncounterStatic.cs b/PKHeX.Core/Legality/Encounters/EncounterStatic.cs index dec9a4190..1d31333c9 100644 --- a/PKHeX.Core/Legality/Encounters/EncounterStatic.cs +++ b/PKHeX.Core/Legality/Encounters/EncounterStatic.cs @@ -6,7 +6,7 @@ /// /// Static Encounters are fixed position encounters with properties that are not subject to Wild Encounter conditions. /// - public class EncounterStatic : IEncounterable, IMoveset, IGeneration, ILocation, IContestStats + public class EncounterStatic : IEncounterable, IMoveset, IGeneration, ILocation, IContestStats, IVersion { public int Species { get; set; } public int[] Moves { get; set; } @@ -25,7 +25,7 @@ public class EncounterStatic : IEncounterable, IMoveset, IGeneration, ILocation, public Nature Nature { get; set; } = Nature.Random; public bool Gift { get; set; } public int Ball { get; set; } = 4; // Only checked when is Gift - public GameVersion Version = GameVersion.Any; + public GameVersion Version { get; set; } = GameVersion.Any; public int[] IVs { get; set; } public int FlawlessIVCount { get; internal set; } public bool IV3 { set => FlawlessIVCount = value ? 3 : 0; } diff --git a/PKHeX.Core/Legality/Encounters/EncounterTrade.cs b/PKHeX.Core/Legality/Encounters/EncounterTrade.cs index 410e3f56f..52364daae 100644 --- a/PKHeX.Core/Legality/Encounters/EncounterTrade.cs +++ b/PKHeX.Core/Legality/Encounters/EncounterTrade.cs @@ -6,7 +6,7 @@ /// /// Trade data is fixed level in all cases except for the first few generations of games. /// - public class EncounterTrade : IEncounterable, IMoveset, IGeneration, ILocation, IContestStats + public class EncounterTrade : IEncounterable, IMoveset, IGeneration, ILocation, IContestStats, IVersion { public int Species { get; set; } public int[] Moves { get; set; } diff --git a/PKHeX.Core/Legality/Encounters/Verifiers/EncounterVerifier.cs b/PKHeX.Core/Legality/Encounters/Verifiers/EncounterVerifier.cs index 1c48f884d..c0c75562d 100644 --- a/PKHeX.Core/Legality/Encounters/Verifiers/EncounterVerifier.cs +++ b/PKHeX.Core/Legality/Encounters/Verifiers/EncounterVerifier.cs @@ -332,9 +332,9 @@ private static CheckResult VerifyEncounterLink(PKM pkm, EncounterLink enc) if (enc == null) return new CheckResult(Severity.Invalid, V43, CheckIdentifier.Encounter); - if (pkm.XY && !enc.XY) + if (pkm.XY && !enc.CanBeReceivedBy(GameVersion.XY)) return new CheckResult(Severity.Invalid, V44, CheckIdentifier.Encounter); - if (pkm.AO && !enc.ORAS) + if (pkm.AO && !enc.CanBeReceivedBy(GameVersion.ORAS)) return new CheckResult(Severity.Invalid, V45, CheckIdentifier.Encounter); if (pkm.IsShiny) diff --git a/PKHeX.Core/Legality/Structures/IVersion.cs b/PKHeX.Core/Legality/Structures/IVersion.cs new file mode 100644 index 000000000..03bf1c4a4 --- /dev/null +++ b/PKHeX.Core/Legality/Structures/IVersion.cs @@ -0,0 +1,29 @@ +namespace PKHeX.Core +{ + public interface IVersion + { + GameVersion Version { get; set; } + } + + public static partial class Extensions + { + public static bool CanBeReceivedBy(this IVersion ver, GameVersion game) => ver.Version.Contains(game); + public static GameVersion GetCompatibleVersion(this IVersion ver, GameVersion prefer) + { + if (ver.CanBeReceivedBy(prefer) || ver.Version <= GameVersion.Unknown) + return prefer; + return ver.GetVersion(); + } + + private static GameVersion GetVersion(this IVersion ver) + { + const int max = (int) GameVersion.RB; + while (true) // this isn't optimal, but is low maintenance + { + var game = (GameVersion)Util.Rand.Next(1, max); + if (ver.CanBeReceivedBy(game)) + return game; + } + } + } +}