diff --git a/PKHeX.Core/Game/GameUtil.cs b/PKHeX.Core/Game/GameUtil.cs index 897707880..af6d55817 100644 --- a/PKHeX.Core/Game/GameUtil.cs +++ b/PKHeX.Core/Game/GameUtil.cs @@ -1,5 +1,7 @@ using System; +using System.Collections.Generic; using System.Linq; +using static PKHeX.Core.GameVersion; namespace PKHeX.Core { @@ -8,6 +10,17 @@ namespace PKHeX.Core /// public static class GameUtil { + /// + /// List of possible values a can have. + /// + public static readonly GameVersion[] GameVersions = ((GameVersion[])Enum.GetValues(typeof(GameVersion))).Where(z => z < RB && z > 0).Reverse().ToArray(); + + /// + /// Indicates if the value is a value used by the games or is an aggregate indicator. + /// + /// Game to check + public static bool IsValidSavedVersion(this GameVersion game) => 0 < game && game <= RB; + /// Determines the Version Grouping of an input Version ID /// Version of which to determine the group /// Version Group Identifier or Invalid if type cannot be determined. @@ -15,73 +28,56 @@ namespace PKHeX.Core { switch (Version) { - case GameVersion.CXD: - return GameVersion.CXD; + // Sidegame + case CXD: + return CXD; + case GO: + return GO; - case GameVersion.GO: - return GameVersion.GO; + // Gen1 + case RBY: case RD: case BU: case YW: case GN: + return RBY; - case GameVersion.RBY: - case GameVersion.RD: - case GameVersion.BU: - case GameVersion.YW: - case GameVersion.GN: - return GameVersion.RBY; + // Gen2 + case GS: case GD: case SV: case C: + return GSC; - case GameVersion.GS: - case GameVersion.GD: - case GameVersion.SV: - case GameVersion.C: - return GameVersion.GSC; + // Gen3 + case R: case S: + return RS; + case E: + return E; + case FR: case LG: + return FR; - case GameVersion.R: - case GameVersion.S: - return GameVersion.RS; + // Gen4 + case D: case P: + return DP; + case Pt: + return Pt; + case HG: case SS: + return HGSS; - case GameVersion.E: - return GameVersion.E; + // Gen5 + case B: case W: + return BW; + case B2: case W2: + return B2W2; - case GameVersion.FR: - case GameVersion.LG: - return GameVersion.FR; + // Gen6 + case X: case Y: + return XY; + case OR: case AS: + return ORAS; - case GameVersion.D: - case GameVersion.P: - return GameVersion.DP; - - case GameVersion.Pt: - return GameVersion.Pt; - - case GameVersion.HG: - case GameVersion.SS: - return GameVersion.HGSS; - - case GameVersion.B: - case GameVersion.W: - return GameVersion.BW; - - case GameVersion.B2: - case GameVersion.W2: - return GameVersion.B2W2; - - case GameVersion.X: - case GameVersion.Y: - return GameVersion.XY; - - case GameVersion.OR: - case GameVersion.AS: - return GameVersion.ORAS; - - case GameVersion.SN: - case GameVersion.MN: - return GameVersion.SM; - - case GameVersion.US: - case GameVersion.UM: - return GameVersion.USUM; + // Gen7 + case SN: case MN: + return SM; + case US: case UM: + return USUM; default: - return GameVersion.Invalid; + return Invalid; } } @@ -94,59 +90,127 @@ namespace PKHeX.Core { switch (generation) { - case 1: return GameVersion.RBY; - case 2: return GameVersion.C; - case 3: return GameVersion.E; - case 4: return GameVersion.SS; - case 5: return GameVersion.W2; - case 6: return GameVersion.AS; - case 7: return GameVersion.UM; + case 1: return RBY; + case 2: return C; + case 3: return E; + case 4: return SS; + case 5: return W2; + case 6: return AS; + case 7: return UM; default: - return GameVersion.Invalid; - } - } - public static int GetGeneration(GameVersion game) - { - game = GetMetLocationVersionGroup(game); // get group - switch (game) - { - default: return -1; - - case GameVersion.RBY: return 1; - case GameVersion.GSC: return 2; - - case GameVersion.CXD: - case GameVersion.RS: case GameVersion.E: - case GameVersion.FR: case GameVersion.LG: - return 3; - - case GameVersion.DP: case GameVersion.Pt: - case GameVersion.HGSS: - return 4; - - case GameVersion.BW: - case GameVersion.B2W2: - return 5; - - case GameVersion.XY: - case GameVersion.ORAS: - return 6; - - case GameVersion.SM: - case GameVersion.USUM: - return 7; + return Invalid; } } /// - /// List of possible values a can have. + /// Gets the Generation the belongs to. /// - public static readonly GameVersion[] GameVersions = ((GameVersion[])Enum.GetValues(typeof(GameVersion))).Where(z => z < GameVersion.RB && z > 0).Reverse().ToArray(); + /// Game to retrieve the generation for + /// Generation ID + public static int GetGeneration(this GameVersion game) + { + if (Gen1.Contains(game)) return 1; + if (Gen2.Contains(game)) return 2; + if (Gen3.Contains(game)) return 3; + if (Gen4.Contains(game)) return 4; + if (Gen5.Contains(game)) return 5; + if (Gen6.Contains(game)) return 6; + if (Gen7.Contains(game)) return 7; + return -1; + } + + + /// + /// Checks if the version (or subset versions) is equivalent to . + /// + /// Version (set) + /// Individual version + public static bool Contains(this GameVersion g1, GameVersion g2) + { + if (g1 == g2 || g1 == Any) + return true; + + switch (g1) + { + case RB: + return g2 == RD || g2 == BU || g2 == GN; + case RBY: + return RB.Contains(g2) || g2 == YW; + case Gen1: + return RBY.Contains(g2) || g2 == Stadium || g2 == EventsGBGen1 || g2 == VCEvents; + case Stadium: + case EventsGBGen1: + case VCEvents: + goto case RBY; + + case GS: return g2 == GD || g2 == SV; + case GSC: + return GS.Contains(g2) || g2 == C; + case Gen2: + return GSC.Contains(g2) || g2 == Stadium2 || g2 == EventsGBGen2; + case Stadium2: + case EventsGBGen2: + goto case GSC; + case GBCartEraOnly: + return g2 == Stadium || g2 == Stadium2 || g2 == EventsGBGen1 || g2 == EventsGBGen2; + + case RS: return g2 == R || g2 == S; + case RSE: + return RS.Contains(g2) || g2 == E; + case FRLG: return g2 == FR || g2 == LG; + case COLO: + case XD: return g2 == CXD; + case CXD: return g2 == COLO || g2 == XD; + case RSBOX: return RS.Contains(g2) || g2 == E || FRLG.Contains(g2); + case Gen3: + return RSE.Contains(g2) || FRLG.Contains(g2) || CXD.Contains(g2) || g2 == RSBOX; + + case DP: return g2 == D || g2 == P; + case HGSS: return g2 == HG || g2 == SS; + case DPPt: + return DP.Contains(g2) || g2 == Pt; + case BATREV: return DP.Contains(g2) || g2 == Pt || HGSS.Contains(g2); + case Gen4: + return DPPt.Contains(g2) || HGSS.Contains(g2) || g2 == BATREV; + + case BW: return g2 == B || g2 == W; + case B2W2: return g2 == B2 || g2 == W2; + case Gen5: + return BW.Contains(g2) || B2W2.Contains(g2); + + case XY: return g2 == X || g2 == Y; + case ORAS: return g2 == OR || g2 == AS; + case Gen6: + return XY.Contains(g2) || ORAS.Contains(g2); + + case SM: + return g2 == SN || g2 == MN; + case USUM: + return g2 == US || g2 == UM; + case Gen7: + return SM.Contains(g2) || USUM.Contains(g2); + + default: return false; + } + } /// /// List of possible values within the provided . /// /// Generation to look within public static GameVersion[] GetVersionsInGeneration(int generation) => GameVersions.Where(z => z.GetGeneration() == generation).ToArray(); + + /// + /// List of possible values within the provided criteria. + /// + /// Criteria for retrieving versions + /// Generation format minimum (necessary for the CXD/Gen4 swap etc) + public static IEnumerable GetVersionsWithinRange(IGameValueLimit obj, int generation = -1) + { + var vers = GameVersions.Where(z => z >= (GameVersion)obj.MinGameID && z <= (GameVersion)obj.MaxGameID); + if (generation == -1) + return vers; + return vers.Where(z => z.GetGeneration() <= generation); + } } } diff --git a/PKHeX.Core/Game/GameVersion.cs b/PKHeX.Core/Game/GameVersion.cs index 3fe64fba8..fab7b8ddd 100644 --- a/PKHeX.Core/Game/GameVersion.cs +++ b/PKHeX.Core/Game/GameVersion.cs @@ -40,88 +40,4 @@ EventsGBGen2, VCEvents } - - public static partial class Extensions - { - public static int GetGeneration(this GameVersion g) - { - if (GameVersion.Gen1.Contains(g)) return 1; - if (GameVersion.Gen2.Contains(g)) return 2; - if (GameVersion.Gen3.Contains(g)) return 3; - if (GameVersion.Gen4.Contains(g)) return 4; - if (GameVersion.Gen5.Contains(g)) return 5; - if (GameVersion.Gen6.Contains(g)) return 6; - if (GameVersion.Gen7.Contains(g)) return 7; - return -1; - } - public static bool Contains(this GameVersion g1, GameVersion g2) - { - if (g1 == g2 || g1 == GameVersion.Any) - return true; - - switch (g1) - { - case GameVersion.RB: - return g2 == GameVersion.RD || g2 == GameVersion.BU || g2 == GameVersion.GN; - case GameVersion.RBY: - return GameVersion.RB.Contains(g2) || g2 == GameVersion.YW; - case GameVersion.Gen1: - return GameVersion.RBY.Contains(g2) || g2 == GameVersion.Stadium || g2 == GameVersion.EventsGBGen1 || g2 == GameVersion.VCEvents; - case GameVersion.Stadium: - case GameVersion.EventsGBGen1: - case GameVersion.VCEvents: - goto case GameVersion.RBY; - - case GameVersion.GS: return g2 == GameVersion.GD || g2 == GameVersion.SV; - case GameVersion.GSC: - return GameVersion.GS.Contains(g2) || g2 == GameVersion.C; - case GameVersion.Gen2: - return GameVersion.GSC.Contains(g2) || g2 == GameVersion.Stadium2 || g2 == GameVersion.EventsGBGen2; - case GameVersion.Stadium2: - case GameVersion.EventsGBGen2: - goto case GameVersion.GSC; - case GameVersion.GBCartEraOnly: - return g2 == GameVersion.Stadium || g2 == GameVersion.Stadium2 || g2 == GameVersion.EventsGBGen1 || g2 == GameVersion.EventsGBGen2; - - case GameVersion.RS: return g2 == GameVersion.R || g2 == GameVersion.S; - case GameVersion.RSE: - return GameVersion.RS.Contains(g2) || g2 == GameVersion.E; - case GameVersion.FRLG: return g2 == GameVersion.FR || g2 == GameVersion.LG; - case GameVersion.COLO: - case GameVersion.XD: return g2 == GameVersion.CXD; - case GameVersion.CXD: return g2 == GameVersion.COLO || g2 == GameVersion.XD; - case GameVersion.RSBOX: return GameVersion.RS.Contains(g2) || g2 == GameVersion.E || GameVersion.FRLG.Contains(g2); - case GameVersion.Gen3: - return GameVersion.RSE.Contains(g2) || GameVersion.FRLG.Contains(g2) || GameVersion.CXD.Contains(g2) || g2 == GameVersion.RSBOX; - - case GameVersion.DP: return g2 == GameVersion.D || g2 == GameVersion.P; - case GameVersion.HGSS: return g2 == GameVersion.HG || g2 == GameVersion.SS; - case GameVersion.DPPt: - return GameVersion.DP.Contains(g2) || g2 == GameVersion.Pt; - case GameVersion.BATREV: return GameVersion.DP.Contains(g2) || g2 == GameVersion.Pt || GameVersion.HGSS.Contains(g2); - case GameVersion.Gen4: - return GameVersion.DPPt.Contains(g2) || GameVersion.HGSS.Contains(g2) || g2 == GameVersion.BATREV; - - case GameVersion.BW: return g2 == GameVersion.B || g2 == GameVersion.W; - case GameVersion.B2W2: return g2 == GameVersion.B2 || g2 == GameVersion.W2; - case GameVersion.Gen5: - return GameVersion.BW.Contains(g2) || GameVersion.B2W2.Contains(g2); - - case GameVersion.XY: return g2 == GameVersion.X || g2 == GameVersion.Y; - case GameVersion.ORAS: return g2 == GameVersion.OR || g2 == GameVersion.AS; - case GameVersion.Gen6: - return GameVersion.XY.Contains(g2) || GameVersion.ORAS.Contains(g2); - - case GameVersion.SM: - return g2 == GameVersion.SN || g2 == GameVersion.MN; - case GameVersion.USUM: - return g2 == GameVersion.US || g2 == GameVersion.UM; - case GameVersion.Gen7: - return GameVersion.SM.Contains(g2) || GameVersion.USUM.Contains(g2); - - default: return false; - } - } - public static bool IsValid(this GameVersion g) => 0 < g && g <= GameVersion.RB; - } } diff --git a/PKHeX.Core/Legality/Encounters/Generator/EncounterMovesetGenerator.cs b/PKHeX.Core/Legality/Encounters/Generator/EncounterMovesetGenerator.cs index 94c9a1e62..93ac4c0d3 100644 --- a/PKHeX.Core/Legality/Encounters/Generator/EncounterMovesetGenerator.cs +++ b/PKHeX.Core/Legality/Encounters/Generator/EncounterMovesetGenerator.cs @@ -10,8 +10,6 @@ namespace PKHeX.Core /// public static class EncounterMovesetGenerator { - private static readonly GameVersion[] Versions = GameUtil.GameVersions; - /// /// Gets possible objects that allow all moves requested to be learned. /// @@ -24,7 +22,7 @@ namespace PKHeX.Core { pk.TID = info.TID; var m = moves ?? pk.Moves; - var vers = versions?.Length >= 1 ? versions : Versions.Where(z => z <= (GameVersion) pk.MaxGameID); + var vers = versions?.Length >= 1 ? versions : GameUtil.GetVersionsWithinRange(pk, pk.Format); foreach (var ver in vers) { var encs = GenerateVersionEncounters(pk, m, ver); @@ -77,7 +75,7 @@ namespace PKHeX.Core public static IEnumerable GenerateEncounters(PKM pk, int[] moves = null, params GameVersion[] versions) { var m = moves ?? pk.Moves; - var vers = versions?.Length >= 1 ? versions : Versions.Where(z => z <= (GameVersion)pk.MaxGameID); + var vers = versions?.Length >= 1 ? versions : GameUtil.GetVersionsWithinRange(pk, pk.Format); return vers.SelectMany(ver => GenerateVersionEncounters(pk, m, ver)); } @@ -89,8 +87,7 @@ namespace PKHeX.Core /// A consumable list of possible encounters. public static IEnumerable GenerateEncounters(PKM pk, int[] moves = null) { - var vers = Versions.Where(z => z <= (GameVersion)pk.MaxGameID).ToArray(); - return GenerateEncounters(pk, moves ?? pk.Moves, vers); + return GenerateEncounters(pk, moves ?? pk.Moves, null); } /// diff --git a/PKHeX.Core/Legality/Tables3.cs b/PKHeX.Core/Legality/Tables3.cs index 9b32482df..e7b42cf43 100644 --- a/PKHeX.Core/Legality/Tables3.cs +++ b/PKHeX.Core/Legality/Tables3.cs @@ -13,7 +13,7 @@ namespace PKHeX.Core internal const int MaxItemID_3_XD = 593; internal const int MaxAbilityID_3 = 77; internal const int MaxBallID_3 = 0xC; - internal const int MaxGameID_3 = 5; // LG + internal const int MaxGameID_3 = 15; // CXD /// /// Generation 3 -> Generation 4 Transfer Location (Pal Park) /// diff --git a/PKHeX.Core/PKM/PKM.cs b/PKHeX.Core/PKM/PKM.cs index 0f463f40b..8cc2cf097 100644 --- a/PKHeX.Core/PKM/PKM.cs +++ b/PKHeX.Core/PKM/PKM.cs @@ -6,7 +6,7 @@ namespace PKHeX.Core /// /// Object representing a 's data and derived properties. /// - public abstract class PKM : ITrainerID + public abstract class PKM : ITrainerID, IGameValueLimit { public static readonly string[] Extensions = PKX.GetPKMExtensions(); public abstract int SIZE_PARTY { get; } @@ -266,6 +266,7 @@ namespace PKHeX.Core public abstract int MaxAbilityID { get; } public abstract int MaxBallID { get; } public abstract int MaxGameID { get; } + public virtual int MinGameID => 0; public abstract int MaxIV { get; } public abstract int MaxEV { get; } public abstract int OTLength { get; } diff --git a/PKHeX.Core/PKM/Shared/IGameValueLimit.cs b/PKHeX.Core/PKM/Shared/IGameValueLimit.cs new file mode 100644 index 000000000..09576d625 --- /dev/null +++ b/PKHeX.Core/PKM/Shared/IGameValueLimit.cs @@ -0,0 +1,17 @@ +namespace PKHeX.Core +{ + public interface IGameValueLimit + { + int MaxMoveID { get; } + int MaxSpeciesID { get; } + int MaxItemID { get; } + int MaxAbilityID { get; } + int MaxBallID { get; } + int MaxGameID { get; } + int MinGameID { get; } + int MaxIV { get; } + int MaxEV { get; } + int OTLength { get; } + int NickLength { get; } + } +} diff --git a/PKHeX.Core/PKM/Util/PKMSorting.cs b/PKHeX.Core/PKM/Util/PKMSorting.cs index 14ae0de97..d475086b1 100644 --- a/PKHeX.Core/PKM/Util/PKMSorting.cs +++ b/PKHeX.Core/PKM/Util/PKMSorting.cs @@ -108,7 +108,7 @@ namespace PKHeX.Core public static IEnumerable OrderByOwnership(this IEnumerable list, ITrainerInfo trainer) { return list.InitialSortBy() - .ThenByDescending(p => trainer.IsOriginalHandler(p, ((GameVersion)trainer.Game).IsValid())) // true first + .ThenByDescending(p => trainer.IsOriginalHandler(p, ((GameVersion)trainer.Game).IsValidSavedVersion())) // true first .ThenByDescending(p => string.Equals(p.OT_Name, trainer.OT, StringComparison.CurrentCultureIgnoreCase)) .OrderByTrainer() .ThenBy(p => p.Species) diff --git a/PKHeX.Core/PKM/Util/StringConverter.cs b/PKHeX.Core/PKM/Util/StringConverter.cs index 6435e2818..88a47a361 100644 --- a/PKHeX.Core/PKM/Util/StringConverter.cs +++ b/PKHeX.Core/PKM/Util/StringConverter.cs @@ -125,7 +125,7 @@ namespace PKHeX.Core public static string GetG1ConvertedString(byte[] strdata, bool jp) { var table = jp ? jp_table : us_table; - return Util.TrimFromZero(new string(strdata.TakeWhile(b => b != 0).Select(b => (char)table[b]).ToArray())); + return string.Concat(strdata.TakeWhile(b => b != 0).Select(b => (char)table[b]).TakeWhile(b => b != 0)); } /// diff --git a/PKHeX.Core/Saves/SaveFile.cs b/PKHeX.Core/Saves/SaveFile.cs index 0c6009984..09620c6c6 100644 --- a/PKHeX.Core/Saves/SaveFile.cs +++ b/PKHeX.Core/Saves/SaveFile.cs @@ -8,7 +8,7 @@ namespace PKHeX.Core /// /// Base Class for Save Files /// - public abstract class SaveFile : ITrainerInfo + public abstract class SaveFile : ITrainerInfo, IGameValueLimit { public static bool SetUpdateDex { protected get; set; } = true; public static bool SetUpdatePKM { protected get; set; } = true; @@ -91,6 +91,7 @@ namespace PKHeX.Core public abstract int MaxItemID { get; } public abstract int MaxBallID { get; } public abstract int MaxGameID { get; } + public virtual int MinGameID => 0; // Flags public bool HasWondercards => WondercardData > -1; diff --git a/PKHeX.WinForms/Controls/PKM Editor/PKMEditor.cs b/PKHeX.WinForms/Controls/PKM Editor/PKMEditor.cs index 25caff668..3a5fa1ec5 100644 --- a/PKHeX.WinForms/Controls/PKM Editor/PKMEditor.cs +++ b/PKHeX.WinForms/Controls/PKM Editor/PKMEditor.cs @@ -1675,7 +1675,8 @@ namespace PKHeX.WinForms.Controls CB_Ball.DataSource = new BindingSource(GameInfo.BallDataSource.Where(b => b.Value <= SAV.MaxBallID).ToList(), null); CB_Species.DataSource = new BindingSource(GameInfo.SpeciesDataSource.Where(s => s.Value <= SAV.MaxSpeciesID).ToList(), null); DEV_Ability.DataSource = new BindingSource(GameInfo.AbilityDataSource.Where(a => a.Value <= SAV.MaxAbilityID).ToList(), null); - CB_GameOrigin.DataSource = new BindingSource(GameInfo.VersionDataSource.Where(g => g.Value <= SAV.MaxGameID || SAV.Generation >= 3 && g.Value == 15).ToList(), null); + var gamelist = GameUtil.GetVersionsWithinRange(SAV, SAV.Generation).ToList(); + CB_GameOrigin.DataSource = new BindingSource(GameInfo.VersionDataSource.Where(g => gamelist.Contains((GameVersion)g.Value)).ToList(), null); // Set the Move ComboBoxes too.. GameInfo.Strings.MoveDataSource = (HaX ? GameInfo.HaXMoveDataSource : GameInfo.LegalMoveDataSource).Where(m => m.Value <= SAV.MaxMoveID).ToList(); // Filter Z-Moves if appropriate