diff --git a/.github/README-de.md b/.github/README-de.md index 0249567ac..4ca8214c8 100644 --- a/.github/README-de.md +++ b/.github/README-de.md @@ -28,9 +28,9 @@ PKHeX erwartet entschlüsselte Spielstände. Da diese konsolenspezifisch verschl ## Erstellen -PKHeX ist eine Windows Forms Anwendung, die das [.NET Framework v4.6](https://www.microsoft.com/de-de/download/details.aspx?id=48137) benötigt, mit experimenteller Unterstützung für [.NET 6.0](https://dotnet.microsoft.com/download/dotnet/6.0). +PKHeX ist eine Windows Forms Anwendung, die das [.NET 7.0](https://dotnet.microsoft.com/download/dotnet/7.0). -Die Anwendung kann mit jedem Kompiler erstellt werden, der C# 10 unterstützt. +Die Anwendung kann mit jedem Kompiler erstellt werden, der C# 11 unterstützt. ### Erstell Konfiguration @@ -47,7 +47,3 @@ PKHeXs Pokémon Legends: Arceus Sprites kommen vom [National Pokédex - Icon Dex ### IDE PKHeX kann mit IDEs wie [Visual Studio](https://visualstudio.microsoft.com/de/downloads/) durch das Öffnen der .sln oder .csproj Dateien geöffnet werden. - -### GNU/Linux - -Da GNU/Linux nicht das Hauptbetriebssystem der PKHeX Entwickler ist können Bugs auftreten. Manche kommen möglicherweise von GNU/Linux spezifischem Code in Mono/Wine und können deshalb nicht von jedem reproduziert werden kann. diff --git a/.github/README-es.md b/.github/README-es.md index 2692460ea..3c2737ccc 100644 --- a/.github/README-es.md +++ b/.github/README-es.md @@ -18,7 +18,7 @@ La interfaz gráfica puede ser traducida con archivos de texto externos para dar Pokémon Showdown asigna un código QR que puede ser importado/exportado para ayudar al compartir. -PKHeX espera archivos de guardado que no estén cifrados con las claves específicas de la consola. Use un gestor de archivos de guardado para importar y exportar información de la consola ([Checkpoint](https://github.com/FlagBrew/Checkpoint), save_manager, [JKSM](https://github.com/J-D-K/JKSM), o SaveDataFiler). +PKHeX espera archivos de guardado que no estén cifrados con las claves específicas de la consola. Use un gestor de archivos de guardado para importar y exportar información de la consola ([Checkpoint](https://github.com/FlagBrew/Checkpoint) o [JKSM](https://github.com/J-D-K/JKSM)). **No apoyamos ni toleramos las trampas a expensas de otros. No uses un Pokémon modificado significativamente en batalla o en intercambios con quienes no estén al tanto de que estás usando un Pokémon modificado.** @@ -28,9 +28,9 @@ PKHeX espera archivos de guardado que no estén cifrados con las claves específ ## Building -PKHeX es una aplicación de Windows Forms que requiere [.NET Framework v4.6](https://www.microsoft.com/es-es/download/details.aspx?id=48137), con soporte experimental para [.NET 6.0](https://dotnet.microsoft.com/download/dotnet/6.0). +PKHeX es una aplicación de Windows Forms que requiere [.NET 7.0](https://dotnet.microsoft.com/download/dotnet/7.0). -El archivo ejecutable puede ser construido con cualquier compilador que soporte C# 10. +El archivo ejecutable puede ser construido con cualquier compilador que soporte C# 11. ### Configuraciones del Build @@ -47,7 +47,3 @@ PKHeX's Pokémon Legends: Arceus sprite collection is taken from the [National P ### IDE PKHeX se puede abrir con un IDE como [Visual Studio](https://visualstudio.microsoft.com/es/downloads/), abriendo los archivos .sln o .csproj. - -### GNU/Linux - -GNU/Linux no es el sistema operativo principal de los desarrolladores de este proyecto, así que probablemente haya errores o bugs; de los cuales algunos pueden provenir de código no específico de GNU/Linux desde Mono o de Wine, con lo cual puede haber otros usuarios que no puedan reproducir ese error. diff --git a/.github/README-fr.md b/.github/README-fr.md index 8798c0290..9727687fd 100644 --- a/.github/README-fr.md +++ b/.github/README-fr.md @@ -17,7 +17,7 @@ Les données sont affichées dans une vue qui peut être modifiée et enregistr Les ensembles Pokémon Showdown et les QR codes peuvent être importés/exportés pour faciliter le partage. -PKHeX attend des fichiers de sauvegarde qui ne sont pas chiffrés avec des clés spécifiques à la console. Utilisez un gestionnaire de données enregistrées pour importer et exporter des données enregistrées à partir de la console ([Checkpoint](https://github.com/FlagBrew/Checkpoint), save_manager, [JKSM](https://github.com/J-D-K/JKSM) ou SaveDataFiler). +PKHeX attend des fichiers de sauvegarde qui ne sont pas chiffrés avec des clés spécifiques à la console. Utilisez un gestionnaire de données enregistrées pour importer et exporter des données enregistrées à partir de la console ([Checkpoint](https://github.com/FlagBrew/Checkpoint) ou [JKSM](https://github.com/J-D-K/JKSM)). **Nous ne soutenons ni ne tolérons la tricherie aux dépens des autres. N'utilisez pas de Pokémon piratés de manière significative au combat ou dans des échanges avec ceux qui ne savent pas que des Pokémon piratés sont en cours d'utilisation.** @@ -27,9 +27,9 @@ PKHeX attend des fichiers de sauvegarde qui ne sont pas chiffrés avec des clés ## Construction -PKHeX est une application Windows Forms qui nécessite [.NET Framework v4.6](https://www.microsoft.com/fr-fr/download/details.aspx?id=48137), avec une prise en charge expérimentale de [.NET 6.0.](https://dotnet.microsoft.com/download/dotnet/6.0) +PKHeX est une application Windows Forms qui nécessite [.NET 7.0.](https://dotnet.microsoft.com/download/dotnet/7.0) -L'exécutable peut être construit avec n'importe quel compilateur prenant en charge C# 10. +L'exécutable peut être construit avec n'importe quel compilateur prenant en charge C# 11. ### Construire les configurations @@ -46,7 +46,3 @@ PKHeX's Pokémon Legends: Arceus sprite collection is taken from the [National P ## IDE PKHeX peut être ouvert avec des IDE tels que [Visual Studio](https://visualstudio.microsoft.com/fr/downloads/) en ouvrant le fichier .sln ou .csproj. - -## GNU/Linux - -GNU/Linux n'est pas le système d'exploitation principal des développeurs de ce programme, il peut donc y avoir des bugues; certains peuvent provenir de code non spécifique à GNU/Linux de Mono/Wine, donc d'autres utilisateurs peuvent ne pas être en mesure de reproduire l'erreur que vous rencontrez. diff --git a/.github/README-it.md b/.github/README-it.md index a97dbd50c..97a5fd01c 100644 --- a/.github/README-it.md +++ b/.github/README-it.md @@ -18,7 +18,7 @@ L'interfaccia può essere tradotta con risorse/file di testo esterni, così che Set di Pokémon Showdown e QR Code possono essere importati/esportati per agevolare la condivisione di file. -PKHeX si aspetta file di salvataggio non criptati con le chiavi specifiche della console. È possibile usare un gestore di salvataggi per importare ed esportare dati di salvataggio dalla console ([Checkpoint](https://github.com/FlagBrew/Checkpoint), save_manager, [JKSM](https://github.com/J-D-K/JKSM), o SaveDataFiler). +PKHeX si aspetta file di salvataggio non criptati con le chiavi specifiche della console. È possibile usare un gestore di salvataggi per importare ed esportare dati di salvataggio dalla console ([Checkpoint](https://github.com/FlagBrew/Checkpoint) o [JKSM](https://github.com/J-D-K/JKSM)). **Non supportiamo e non perdoniamo l'utilizzo di cheat a scapito di altri giocatori. Non utilizzare Pokémon modificati significativamente in lotte o scambi con giocatori che non ne sono a conoscenza.** @@ -28,9 +28,9 @@ PKHeX si aspetta file di salvataggio non criptati con le chiavi specifiche della ## Building -PKHeX è un applicazione Windows Form e necessita [.NET Framework v4.6](https://www.microsoft.com/it-it/download/details.aspx?id=48137), con supporto sperimentale per [.NET 6.0](https://dotnet.microsoft.com/download/dotnet/6.0). +PKHeX è un applicazione Windows Form e necessita [.NET Framework 7.0](https://dotnet.microsoft.com/download/dotnet/7.0). -L'eseguibile può essere compilato con qualsiasi compiler che supporti C# 10. +L'eseguibile può essere compilato con qualsiasi compiler che supporti C# 11. ### Configurazioni di Build @@ -47,7 +47,3 @@ La collezione di sprite per Leggende Pokémon: Arceus è presa dal [National Pok ### IDE PKHeX può essere aperto con IDE come [Visual Studio](https://visualstudio.microsoft.com/it/downloads/) aprendo il file .sln o il file .csproj. - -### GNU/Linux - -GNU/Linux non è il Sistema Operativo principale dei developer di questo programma, quindi potrebbero esserci bug; alcuni potrebbero provenire da codice GNU/Linux non specifico da Mono/Wine, per cui alcuni utenti potrebbero non essere in grado di riprodurre l'errore riscontrato. diff --git a/.github/README-zh.md b/.github/README-zh.md index 2dc7dbb1c..7c4cd5b05 100644 --- a/.github/README-zh.md +++ b/.github/README-zh.md @@ -28,9 +28,9 @@ PKHeX 所读取存档文件必须是未经主机唯一密钥加密,因此请 ## 构建 -PKHeX 是 Windows 窗口应用程序,依赖于 [.NET Framework v4.6](https://www.microsoft.com/en-us/download/details.aspx?id=48137) 而运行,同时具有对 .[NET 6.0](https://www.microsoft.com/en-us/download/details.aspx?id=48137) 的实验性支持。 +PKHeX 是 Windows 窗口应用程序,依赖于 [.NET 7.0](https://dotnet.microsoft.com/download/dotnet/7.0)。 -可以使用任何支持 C# 10 的编译器生成可执行文件。 +可以使用任何支持 C# 11 的编译器生成可执行文件。 ### 构建配置 @@ -46,7 +46,3 @@ PKHeX 的“宝可梦传说:阿尔宙斯”精灵图片集来源于 [National ### IDE PKHeX 可以通过打开 .sln 或 .csproj 文件来使用 [Visual Studio](https://visualstudio.microsoft.com/downloads/) 等 IDE 打开。 - -### GNU/Linux - -GNU/Linux 非本程序开发人员主要操作系统,因此在 GNU/Linux 平台上运行本程序时可能存在 Bug; 部分 Bug 可能来自于 Mono/Wine 等非 GNU/Linux 特定源代码,因而其他使用者可能无法复现你所遇到的 Bug。 diff --git a/.github/README-zhHK.md b/.github/README-zhHK.md index 234410ff0..2b1a2177f 100644 --- a/.github/README-zhHK.md +++ b/.github/README-zhHK.md @@ -18,7 +18,7 @@ PKHeX 可匯入/匯出 配置資訊及 QR 碼以便進行共有分享。 -PKHeX 所讀取檔案須未經主機唯一密鑰加密,因而請使用儲存資料管理軟體(如 [Checkpoint](https://github.com/FlagBrew/Checkpoint), save_manager, [JKSM](https://github.com/J-D-K/JKSM), 抑或是 SaveDataFiler)以從主機中匯入匯出儲存資料 . +PKHeX 所讀取檔案須未經主機唯一密鑰加密,因而請使用儲存資料管理軟體(如 [Checkpoint](https://github.com/FlagBrew/Checkpoint), [JKSM](https://github.com/J-D-K/JKSM))以從主機中匯入匯出儲存資料 . **我們反對亦不會縱容透過作弊手段損害他人利益之行為。切勿將魔法寶可夢用於對戰,或連線交換至不知情之訓練家手中。** @@ -28,9 +28,9 @@ PKHeX 所讀取檔案須未經主機唯一密鑰加密,因而請使用儲存 ## 構建 -PKHeX 係 Windows 窗體應用程式,其須依賴於 [.NET Framework v4.6](https://www.microsoft.com/en-us/download/details.aspx?id=48137) 而運行,同時本程式亦實驗式地支援 [.NET 6.0](https://dotnet.microsoft.com/download/dotnet/6.0)。 +PKHeX 係 Windows 窗體應用程式,其須依賴於 [.NET Framework 7.0](https://dotnet.microsoft.com/download/dotnet/7.0)。 -程式可透過任意支援 C# 10 之編譯器構建。 +程式可透過任意支援 C# 11 之編譯器構建。 ### 構建配置 @@ -46,7 +46,3 @@ PKHeX 之「寶可夢傳説:阿爾宙斯」精靈圖示集合庫來源於 [Nat ### IDE PKHeX 可透過如 [Visual Studio](https://visualstudio.microsoft.com/downloads/) 等各類 IDE ,開啓 .sln 或 .csproj 檔案以打開。 - -### GNU/Linux - -GNU/Linux 非本程式開發者主要作業系統,因而於 GNU/Linux 平臺上運行本程式時可能存在 Bug; 部分 Bug 亦可能由 Mono/Wine 等非 GNU/Linux 特定源代碼所引入,因而其他使用者可能無法復現你所遇到之 Bug。 diff --git a/Directory.Build.props b/Directory.Build.props index 4daefe239..16ac74812 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -1,7 +1,7 @@ 22.12.18 - 10 + 11 enable en PKHeX diff --git a/PKHeX.Core/Editing/Applicators/BallApplicator.cs b/PKHeX.Core/Editing/Applicators/BallApplicator.cs index 0c4fe9c73..6795c87ca 100644 --- a/PKHeX.Core/Editing/Applicators/BallApplicator.cs +++ b/PKHeX.Core/Editing/Applicators/BallApplicator.cs @@ -114,7 +114,7 @@ public static class BallApplicator result[ctr++] = items[i]; return ctr; } - + private static readonly Ball[] BallList = (Ball[])Enum.GetValues(typeof(Ball)); private static int MaxBallSpanAlloc => BallList.Length; diff --git a/PKHeX.Core/Editing/Applicators/CatchRateApplicator.cs b/PKHeX.Core/Editing/Applicators/CatchRateApplicator.cs index 8f7351a81..c6c22bd0e 100644 --- a/PKHeX.Core/Editing/Applicators/CatchRateApplicator.cs +++ b/PKHeX.Core/Editing/Applicators/CatchRateApplicator.cs @@ -5,35 +5,49 @@ namespace PKHeX.Core; /// public static class CatchRateApplicator { - public static int GetSuggestedCatchRate(PK1 pk1, SaveFile sav) + /// + /// Gets the suggested for the entity. + /// + public static int GetSuggestedCatchRate(PK1 pk, SaveFile sav) { - var la = new LegalityAnalysis(pk1); - return GetSuggestedCatchRate(pk1, sav, la); + var la = new LegalityAnalysis(pk); + return GetSuggestedCatchRate(pk, sav, la); } - public static byte GetSuggestedCatchRate(PK1 pk1, SaveFile sav, LegalityAnalysis la) + /// + /// Gets the suggested for the entity. + /// + public static byte GetSuggestedCatchRate(PK1 pk, SaveFile sav, LegalityAnalysis la) { + // If it is already valid, just use the current value. if (la.Valid) - return pk1.Catch_Rate; + return pk.Catch_Rate; + // If it has ever visited generation 2, the Held Item can be removed prior to trade back. if (la.Info.Generation == 2) return 0; - var v = la.EncounterMatch; - switch (v) + // Return the encounter's original value. + var enc = la.EncounterMatch; + switch (enc) { case EncounterTrade1 c: return c.GetInitialCatchRate(); case EncounterStatic1E { Version: GameVersion.Stadium, Species: (int)Species.Psyduck}: - return pk1.Japanese ? (byte)167 : (byte)168; // Amnesia Psyduck has different catch rates depending on language + return pk.Japanese ? (byte)167 : (byte)168; // Amnesia Psyduck has different catch rates depending on language default: - { - if (sav.Version.Contains(v.Version) || v.Version.Contains(sav.Version)) - return (byte)sav.Personal[v.Species].CatchRate; - if (!GameVersion.RB.Contains(v.Version)) - return (byte)PersonalTable.Y[v.Species].CatchRate; - return (byte)PersonalTable.RB[v.Species].CatchRate; - } + var pt = GetPersonalTable(sav, enc); + var pi = pt[enc.Species]; + return (byte)pi.CatchRate; } } + + private static PersonalTable1 GetPersonalTable(SaveFile sav, IEncounterable v) + { + if (sav.Personal is PersonalTable1 pt && (sav.Version.Contains(v.Version) || v.Version.Contains(sav.Version))) + return pt; + if (!GameVersion.RB.Contains(v.Version)) + return PersonalTable.Y; + return PersonalTable.RB; + } } diff --git a/PKHeX.Core/Editing/Applicators/GenderApplicator.cs b/PKHeX.Core/Editing/Applicators/GenderApplicator.cs index 265e79fb4..4af0fa9cf 100644 --- a/PKHeX.Core/Editing/Applicators/GenderApplicator.cs +++ b/PKHeX.Core/Editing/Applicators/GenderApplicator.cs @@ -26,7 +26,7 @@ public static class GenderApplicator /// Desired value to set. public static void SetGender(this PKM pk, int gender) { - gender = Math.Min(2, Math.Max(0, gender)); + gender = Math.Clamp(gender, 0, 2); if (pk.Gender == gender) return; @@ -52,7 +52,7 @@ public static class GenderApplicator /// Most-legal value public static int GetSaneGender(this PKM pk) { - int gt = pk.PersonalInfo.Gender; + var gt = pk.PersonalInfo.Gender; switch (gt) { case PersonalInfo.RatioMagicGenderless: return 2; diff --git a/PKHeX.Core/Editing/Applicators/MoveSetApplicator.cs b/PKHeX.Core/Editing/Applicators/MoveSetApplicator.cs index a1229b532..b4c813f91 100644 --- a/PKHeX.Core/Editing/Applicators/MoveSetApplicator.cs +++ b/PKHeX.Core/Editing/Applicators/MoveSetApplicator.cs @@ -46,7 +46,7 @@ public static class MoveSetApplicator const int count = 4; if (m.Length > count) - return m.AsSpan(m.Length - count).ToArray(); + return m[^count..]; Array.Resize(ref m, count); return m; } diff --git a/PKHeX.Core/Editing/Applicators/MoveShopRecordApplicator.cs b/PKHeX.Core/Editing/Applicators/MoveShopRecordApplicator.cs index 2926db649..d67cb915f 100644 --- a/PKHeX.Core/Editing/Applicators/MoveShopRecordApplicator.cs +++ b/PKHeX.Core/Editing/Applicators/MoveShopRecordApplicator.cs @@ -7,23 +7,33 @@ namespace PKHeX.Core; /// public static class MoveShopRecordApplicator { + /// + /// Clears all the "purchased" and "mastered" move shop flags. + /// public static void ClearMoveShopFlags(this IMoveShop8 shop) { - var bits = shop.MoveShopPermitFlags; - for (int i = 0; i < bits.Length; i++) + var bits = shop.Permit; + for (int i = 0; i < bits.RecordCountUsed; i++) shop.SetPurchasedRecordFlag(i, false); if (shop is IMoveShop8Mastery m) m.ClearMoveShopFlagsMastered(); } + /// + /// Clears all the "mastered" move shop flags. + /// + /// public static void ClearMoveShopFlagsMastered(this IMoveShop8Mastery shop) { - var bits = shop.MoveShopPermitFlags; - for (int i = 0; i < bits.Length; i++) + var bits = shop.Permit; + for (int i = 0; i < bits.RecordCountUsed; i++) shop.SetMasteredRecordFlag(i, false); } + /// + /// Sets the required move shop flags for the requested entity. + /// public static void SetMoveShopFlags(this IMoveShop8Mastery shop, PKM pk) { Span moves = stackalloc ushort[4]; @@ -31,6 +41,9 @@ public static class MoveShopRecordApplicator shop.SetMoveShopFlags(moves, pk); } + /// + /// Sets the required move shop flags for the requested entity. + /// public static void SetMoveShopFlags(this IMoveShop8Mastery shop, ReadOnlySpan moves, PKM pk) { var index = PersonalTable.LA.GetFormIndex(pk.Species, pk.Form); @@ -41,6 +54,9 @@ public static class MoveShopRecordApplicator shop.SetMoveShopFlags(moves, learn, mastery, level); } + /// + /// Sets all possible move shop flags for the requested entity. + /// public static void SetMoveShopFlagsAll(this IMoveShop8Mastery shop, PKM pk) { var index = PersonalTable.LA.GetFormIndex(pk.Species, pk.Form); @@ -51,36 +67,45 @@ public static class MoveShopRecordApplicator shop.SetMoveShopFlagsAll(learn, mastery, level); } + /// + /// Sets all possible move shop flags for the requested entity. + /// public static void SetMoveShopFlagsAll(this IMoveShop8Mastery shop, Learnset learn, Learnset mastery, int level) { - var possible = shop.MoveShopPermitIndexes; - var permit = shop.MoveShopPermitFlags; - for (int index = 0; index < possible.Length; index++) + var permit = shop.Permit; + var possible = permit.RecordPermitIndexes; + for (int index = 0; index < permit.RecordCountUsed; index++) { - var move = possible[index]; - var allowed = permit[index]; + var allowed = permit.IsRecordPermitted(index); if (!allowed) continue; + var move = possible[index]; SetMasteredFlag(shop, learn, mastery, level, index, move); } } + /// + /// Sets all move shop flags for the currently known moves. + /// public static void SetMoveShopFlags(this IMoveShop8Mastery shop, ReadOnlySpan moves, Learnset learn, Learnset mastery, int level) { - var possible = shop.MoveShopPermitIndexes; - var permit = shop.MoveShopPermitFlags; + var permit = shop.Permit; + var possible = permit.RecordPermitIndexes; foreach (var move in moves) { var index = possible.IndexOf(move); if (index == -1) continue; - if (!permit[index]) + if (!permit.IsRecordPermitted(index)) continue; SetMasteredFlag(shop, learn, mastery, level, index, move); } } + /// + /// Sets the "mastered" move shop flag for the requested move. + /// public static void SetMasteredFlag(this IMoveShop8Mastery shop, Learnset learn, Learnset mastery, int level, int index, ushort move) { if (shop.GetMasteredRecordFlag(index)) @@ -97,16 +122,19 @@ public static class MoveShopRecordApplicator shop.SetMasteredRecordFlag(index, true); } + /// + /// Sets the "mastered" move shop flag for the encounter. + /// public static void SetEncounterMasteryFlags(this IMoveShop8Mastery shop, ReadOnlySpan moves, Learnset mastery, int level) { - var possible = shop.MoveShopPermitIndexes; - var permit = shop.MoveShopPermitFlags; + var permit = shop.Permit; + var possible = permit.RecordPermitIndexes; foreach (var move in moves) { var index = possible.IndexOf(move); if (index == -1) continue; - if (!permit[index]) + if (!permit.IsRecordPermitted(index)) continue; // If the Pokémon is caught with any move shop move in its learnset diff --git a/PKHeX.Core/Editing/Applicators/TechnicalRecordApplicator.cs b/PKHeX.Core/Editing/Applicators/TechnicalRecordApplicator.cs index d623bcaf8..61292fa03 100644 --- a/PKHeX.Core/Editing/Applicators/TechnicalRecordApplicator.cs +++ b/PKHeX.Core/Editing/Applicators/TechnicalRecordApplicator.cs @@ -23,7 +23,7 @@ public static class TechnicalRecordApplicator /// Clears the Technical Record flags for the . /// /// Pokémon to modify. - public static void ClearRecordFlags(this ITechRecord pk) => pk.SetRecordFlags(false, pk.RecordCountTotal); + public static void ClearRecordFlags(this ITechRecord pk) => pk.SetRecordFlags(false, pk.Permit.RecordCountTotal); /// /// Sets the Technical Record flags for the based on the current moves. @@ -32,17 +32,15 @@ public static class TechnicalRecordApplicator /// Moves to set flags for. If a move is not a Technical Record, it is skipped. public static void SetRecordFlags(this ITechRecord pk, ReadOnlySpan moves) { - var permit = pk.TechRecordPermitFlags; - var moveIDs = pk.TechRecordPermitIndexes; - if (permit.Length != moveIDs.Length) - return; + var permit = pk.Permit; + var moveIDs = permit.RecordPermitIndexes; foreach (var m in moves) { var index = moveIDs.IndexOf(m); if (index == -1) continue; - if (permit[index]) + if (permit.IsRecordPermitted(index)) pk.SetMoveRecordFlag(index); } } @@ -53,10 +51,10 @@ public static class TechnicalRecordApplicator /// Pokémon to modify. public static void SetRecordFlags(this ITechRecord pk) { - var permit = pk.TechRecordPermitFlags; - for (int i = 0; i < permit.Length; i++) + var permit = pk.Permit; + for (int i = 0; i < permit.RecordCountUsed; i++) { - if (permit[i]) + if (permit.IsRecordPermitted(i)) pk.SetMoveRecordFlag(i); } } diff --git a/PKHeX.Core/Editing/Bulk/BatchEditing.cs b/PKHeX.Core/Editing/Bulk/BatchEditing.cs index 8e6299000..40b5a60eb 100644 --- a/PKHeX.Core/Editing/Bulk/BatchEditing.cs +++ b/PKHeX.Core/Editing/Bulk/BatchEditing.cs @@ -57,10 +57,7 @@ public static class BatchEditing var dict = new Dictionary(expectedMax); var props = selector(type); foreach (var p in props) - { - if (!dict.ContainsKey(p.Name)) - dict.Add(p.Name, p); - } + dict.TryAdd(p.Name, p); return dict; } @@ -190,8 +187,12 @@ public static class BatchEditing foreach (var i in il.Where(i => !i.PropertyValue.All(char.IsDigit))) { string pv = i.PropertyValue; - if (pv.StartsWith(CONST_SPECIAL) && !pv.StartsWith(CONST_BYTES, StringComparison.Ordinal) && pv.Contains(',')) - i.SetRandRange(pv); + if (pv.StartsWith(CONST_SPECIAL) && !pv.StartsWith(CONST_BYTES, StringComparison.Ordinal)) + { + var str = pv.AsSpan(1); + if (StringInstruction.IsRandomRange(str)) + i.SetRandomRange(str); + } SetInstructionScreenedValue(i); } @@ -261,7 +262,7 @@ public static class BatchEditing { if (cmd.PropertyName is PROP_TYPENAME) { - if ((obj.GetType().Name == cmd.PropertyValue) != cmd.Evaluator) + if (!cmd.Comparer.IsCompareEquivalence(cmd.PropertyValue == obj.GetType().Name)) return false; continue; } @@ -270,7 +271,7 @@ public static class BatchEditing return false; try { - if (pi.IsValueEqual(obj, cmd.PropertyValue) == cmd.Evaluator) + if (cmd.Comparer.IsCompareOperator(pi.CompareTo(obj, cmd.PropertyValue))) continue; } // User provided inputs can mismatch the type's required value format, and fail to be compared. @@ -359,7 +360,7 @@ public static class BatchEditing if (cmd.PropertyValue.StartsWith(CONST_SUGGEST, StringComparison.OrdinalIgnoreCase)) return SetSuggestedPKMProperty(cmd.PropertyName, info, cmd.PropertyValue); - if (cmd.PropertyValue == CONST_RAND && cmd.PropertyName == nameof(PKM.Moves)) + if (cmd is { PropertyValue: CONST_RAND, PropertyName: nameof(PKM.Moves) }) return SetMoves(pk, info.Legality.GetMoveSet(true)); if (SetComplexProperty(pk, cmd)) @@ -375,7 +376,7 @@ public static class BatchEditing if (cmd.Random) val = cmd.RandomValue; else if (cmd.PropertyValue.StartsWith(CONST_POINTER) && props.TryGetValue(cmd.PropertyValue[1..], out var opi)) - val = opi.GetValue(pk); + val = opi.GetValue(pk) ?? throw new NullReferenceException(); else val = cmd.PropertyValue; @@ -426,7 +427,7 @@ public static class BatchEditing return false; if (!pi.CanRead) return false; - return pi.IsValueEqual(pk, cmd.PropertyValue) == cmd.Evaluator; + return cmd.Comparer.IsCompareOperator(pi.CompareTo(pk, cmd.PropertyValue)); } /// diff --git a/PKHeX.Core/Editing/Bulk/BatchEditor.cs b/PKHeX.Core/Editing/Bulk/BatchEditor.cs index be0453bba..3ad6dbd10 100644 --- a/PKHeX.Core/Editing/Bulk/BatchEditor.cs +++ b/PKHeX.Core/Editing/Bulk/BatchEditor.cs @@ -1,7 +1,6 @@ using System; using System.Collections.Generic; using System.Diagnostics; -using System.Linq; using static PKHeX.Core.MessageStrings; namespace PKHeX.Core; @@ -52,7 +51,7 @@ public sealed class BatchEditor /// /// Collection of modifications. /// Friendly (multi-line) string indicating the result of the batch edits. - public string GetEditorResults(ICollection sets) + public string GetEditorResults(IReadOnlyCollection sets) { if (sets.Count == 0) return MsgBEInstructionNone; @@ -65,10 +64,16 @@ public sealed class BatchEditor return result; } - public static BatchEditor Execute(IList lines, IEnumerable data) + /// + /// Executes the batch instruction on the input + /// + /// Batch instruction line(s) + /// Entities to modify + /// Editor object if follow up modifications are desired. + public static BatchEditor Execute(ReadOnlySpan lines, IEnumerable data) { var editor = new BatchEditor(); - var sets = StringInstructionSet.GetBatchSets(lines).ToArray(); + var sets = StringInstructionSet.GetBatchSets(lines); foreach (var pk in data) { foreach (var set in sets) diff --git a/PKHeX.Core/Editing/Bulk/BatchFilters.cs b/PKHeX.Core/Editing/Bulk/BatchFilters.cs index 66961f9e8..d3708c43a 100644 --- a/PKHeX.Core/Editing/Bulk/BatchFilters.cs +++ b/PKHeX.Core/Editing/Bulk/BatchFilters.cs @@ -11,18 +11,18 @@ public static class BatchFilters public static readonly List FilterMods = new() { new ComplexFilter(PROP_LEGAL, - (pk, cmd) => bool.TryParse(cmd.PropertyValue, out var b) && (b == new LegalityAnalysis(pk).Valid) == cmd.Evaluator, - (info, cmd) => bool.TryParse(cmd.PropertyValue, out var b) && (b == info.Legality.Valid) == cmd.Evaluator), + (pk, cmd) => bool.TryParse(cmd.PropertyValue, out var b) && cmd.Comparer.IsCompareEquivalence(b == new LegalityAnalysis(pk).Valid), + (info, cmd) => bool.TryParse(cmd.PropertyValue, out var b) && cmd.Comparer.IsCompareEquivalence(b == info.Legality.Valid)), new ComplexFilter(PROP_TYPENAME, - (pk, cmd) => (pk.GetType().Name == cmd.PropertyValue) == cmd.Evaluator, - (info, cmd) => (info.Entity.GetType().Name == cmd.PropertyValue) == cmd.Evaluator), + (pk, cmd) => cmd.Comparer.IsCompareEquivalence(pk.GetType().Name == cmd.PropertyValue), + (info, cmd) => cmd.Comparer.IsCompareEquivalence(info.Entity.GetType().Name == cmd.PropertyValue)), }; public static readonly List FilterMeta = new() { new MetaFilter(IdentifierContains, - (obj, cmd) => obj is SlotCache s && s.Identify().Contains(cmd.PropertyValue) == cmd.Evaluator), + (obj, cmd) => obj is SlotCache s && cmd.Comparer.IsCompareEquivalence(s.Identify().Contains(cmd.PropertyValue))), new MetaFilter(nameof(SlotInfoBox.Box), (obj, cmd) => obj is SlotCache { Source: SlotInfoBox b } && int.TryParse(cmd.PropertyValue, out var box) && b.Box + 1 == box), diff --git a/PKHeX.Core/Editing/Bulk/BatchMods.cs b/PKHeX.Core/Editing/Bulk/BatchMods.cs index 3e360ceed..e2d104058 100644 --- a/PKHeX.Core/Editing/Bulk/BatchMods.cs +++ b/PKHeX.Core/Editing/Bulk/BatchMods.cs @@ -19,6 +19,7 @@ public static class BatchMods new TypeSuggestion(nameof(Extensions.HyperTrainClear), p => p.HyperTrainClear()), new TypeSuggestion(nameof(Extensions.ClearGeoLocationData), p => p.ClearGeoLocationData()), new TypeSuggestion(nameof(AwakeningUtil.AwakeningClear), p => p.AwakeningClear()), + new TypeSuggestion(nameof(AwakeningUtil.AwakeningMinimum), p => p.AwakeningMinimum()), new TypeSuggestion(nameof(AwakeningUtil.AwakeningMax), p => p.AwakeningMax()), new TypeSuggestion(nameof(GanbaruExtensions.ClearGanbaruValues), p => p.ClearGanbaruValues()), new TypeSuggestion(nameof(GanbaruExtensions.SetSuggestedGanbaruValues), p => p.SetSuggestedGanbaruValues((PKM)p)), @@ -50,7 +51,7 @@ public static class BatchMods new ComplexSuggestion(PROP_MOVEMASTERY, (_, value, info) => BatchModifications.SetSuggestedMasteryData(info, value)), }; - private static DateTime ParseDate(string val) => DateTime.ParseExact(val, "yyyyMMdd", CultureInfo.InvariantCulture, DateTimeStyles.None); + private static DateOnly ParseDate(ReadOnlySpan val) => DateOnly.ParseExact(val, "yyyyMMdd", CultureInfo.InvariantCulture); public static readonly List ComplexMods = new() { @@ -71,6 +72,7 @@ public static class BatchMods new ComplexSet(nameof(PKM.PID), value => value == CONST_RAND, (pk, _) => pk.PID = Util.Rand32()), new ComplexSet(nameof(PKM.Gender), value => value == CONST_RAND, (pk, _) => pk.SetPIDGender(pk.Gender)), new ComplexSet(PROP_EVS, value => value == CONST_RAND, (pk, _) => SetRandomEVs(pk)), + new ComplexSet(nameof(ITeraType.TeraTypeOverride), value => value == CONST_RAND, (pk, _) => SetRandomTeraType(pk)), // Shiny new ComplexSet(nameof(PKM.PID), @@ -84,6 +86,12 @@ public static class BatchMods new ComplexSet(nameof(PKM.EncryptionConstant), value => value.StartsWith(CONST_RAND), (pk, cmd) => pk.EncryptionConstant = CommonEdits.GetComplicatedEC(pk, option: cmd.PropertyValue[^1])), }; + private static void SetRandomTeraType(PKM pk) + { + if (pk is ITeraType t) + t.TeraTypeOverride = (MoveType)Util.Rand.Next(0, TeraTypeUtil.MaxType + 1); + } + private static void SetRandomEVs(PKM pk) { Span evs = stackalloc int[6]; @@ -91,7 +99,7 @@ public static class BatchMods pk.SetEVs(evs); } - private static Shiny GetRequestedShinyState(string text) => text.Length == 0 ? Shiny.Random : GetRequestedShinyState(text[^1]); + private static Shiny GetRequestedShinyState(ReadOnlySpan text) => text.Length == 0 ? Shiny.Random : GetRequestedShinyState(text[^1]); private static Shiny GetRequestedShinyState(char last) => last switch { diff --git a/PKHeX.Core/Editing/Bulk/StringInstruction.cs b/PKHeX.Core/Editing/Bulk/StringInstruction.cs index 37dffe9cd..13944e3b0 100644 --- a/PKHeX.Core/Editing/Bulk/StringInstruction.cs +++ b/PKHeX.Core/Editing/Bulk/StringInstruction.cs @@ -1,6 +1,9 @@ -using System; +using System; using System.Collections.Generic; using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; +using System.Text; +using static PKHeX.Core.InstructionComparer; namespace PKHeX.Core; @@ -10,16 +13,17 @@ namespace PKHeX.Core; /// /// Can be a filter (skip), or a modification instruction (modify) /// -/// -/// +/// +/// /// public sealed class StringInstruction { + /// Property to modify. public string PropertyName { get; } + /// Value to set to the property. public string PropertyValue { get; private set; } - - /// True if ==, false if != - public bool Evaluator { get; private init; } + /// Filter Comparison Type + public InstructionComparer Comparer { get; private init; } public StringInstruction(string name, string value) { @@ -27,18 +31,23 @@ public sealed class StringInstruction PropertyValue = value; } - public void SetScreenedValue(string[] arr) + public void SetScreenedValue(ReadOnlySpan arr) { - int index = Array.IndexOf(arr, PropertyValue); - PropertyValue = index > -1 ? index.ToString() : PropertyValue; + int index = arr.IndexOf(PropertyValue); + PropertyValue = (uint)index >= arr.Length ? index.ToString() : PropertyValue; } - public static readonly IReadOnlyList Prefixes = new[] { Apply, Require, Exclude }; - private const char Exclude = '!'; - private const char Require = '='; + public static readonly IReadOnlyList Prefixes = new[] { Apply, FilterEqual, FilterNotEqual, FilterGreaterThan, FilterGreaterThanOrEqual, FilterLessThan, FilterLessThanOrEqual }; private const char Apply = '.'; private const char SplitRange = ','; + private const char FilterEqual = '='; + private const char FilterNotEqual = '!'; + private const char FilterGreaterThan = '>'; + private const char FilterLessThan = '<'; + private const char FilterGreaterThanOrEqual = '≥'; + private const char FilterLessThanOrEqual = '≤'; + /// /// Character which divides a property and a value. /// @@ -54,12 +63,30 @@ public sealed class StringInstruction public bool Random { get; private set; } public int RandomValue => Util.Rand.Next(RandomMinimum, RandomMaximum + 1); - public void SetRandRange(string pv) + /// + /// Checks if the input is a valid "random range" specification. + /// + public static bool IsRandomRange(ReadOnlySpan str) { - string str = pv[1..]; - var split = str.Split(SplitRange); - int.TryParse(split[0], out RandomMinimum); - int.TryParse(split[1], out RandomMaximum); + // Need at least one character on either side of the splitter char. + int index = str.IndexOf(SplitRange); + return index > 0 && index < str.Length - 1; + } + + /// + /// Sets a "random range" specification to the instruction. + /// + /// When the splitter is not present. + public void SetRandomRange(ReadOnlySpan str) + { + var index = str.IndexOf(SplitRange); + if (index <= 0) + throw new ArgumentException($"Invalid Random Range: {str.ToString()}", nameof(str)); + + var min = str[..index]; + var max = str[(index + 1)..]; + _ = int.TryParse(min, out RandomMinimum); + _ = int.TryParse(max, out RandomMaximum); if (RandomMinimum == RandomMaximum) { @@ -72,52 +99,217 @@ public sealed class StringInstruction } } - public static IEnumerable GetFilters(IEnumerable lines) + public static List GetFilters(ReadOnlySpan text) => GetFilters(text.EnumerateLines()); + + public static List GetFilters(ReadOnlySpan lines) { + var result = new List(lines.Length); foreach (var line in lines) { - if (line.Length is 0 || line[0] is not (Exclude or Require)) - continue; - - const int start = 1; - var splitIndex = line.IndexOf(SplitInstruction, start); - if (splitIndex == -1) - continue; - var noExtra = line.IndexOf(SplitInstruction, splitIndex + 1); - if (noExtra != -1) - continue; - - var name = line.AsSpan(start, splitIndex - start); - if (name.IsWhiteSpace()) - continue; - - bool eval = line[0] == Require; - var value = line[(splitIndex + 1)..]; - yield return new StringInstruction(name.ToString(), value) { Evaluator = eval }; + if (TryParseFilter(line, out var entry)) + result.Add(entry); } + return result; } - public static IEnumerable GetInstructions(IEnumerable lines) + public static List GetFilters(SpanLineEnumerator lines) { + var result = new List(); foreach (var line in lines) { - if (line.Length is 0 || line[0] is not Apply) - continue; - - const int start = 1; - var splitIndex = line.IndexOf(SplitInstruction, start); - if (splitIndex == -1) - continue; - var noExtra = line.IndexOf(SplitInstruction, splitIndex + 1); - if (noExtra != -1) - continue; - - var name = line.AsSpan(start, splitIndex - start); - if (name.IsWhiteSpace()) - continue; - - var value = line[(splitIndex + 1)..]; - yield return new StringInstruction(name.ToString(), value); + if (TryParseFilter(line, out var entry)) + result.Add(entry); } + return result; } + + public static List GetFilters(IReadOnlyList lines) + { + var result = new List(lines.Count); + foreach (var line in lines) + { + if (TryParseFilter(line, out var entry)) + result.Add(entry); + } + return result; + } + + public static List GetFilters(IEnumerable lines) + { + var result = new List(); + foreach (var line in lines) + { + if (TryParseFilter(line, out var entry)) + result.Add(entry); + } + return result; + } + + public static List GetInstructions(ReadOnlySpan text) => GetInstructions(text.EnumerateLines()); + + public static List GetInstructions(ReadOnlySpan lines) + { + var result = new List(lines.Length); + foreach (var line in lines) + { + if (TryParseInstruction(line, out var entry)) + result.Add(entry); + } + return result; + } + + public static List GetInstructions(SpanLineEnumerator lines) + { + var result = new List(); + foreach (var line in lines) + { + if (TryParseInstruction(line, out var entry)) + result.Add(entry); + } + return result; + } + + public static List GetInstructions(IReadOnlyList lines) + { + var result = new List(lines.Count); + foreach (var line in lines) + { + if (TryParseInstruction(line, out var entry)) + result.Add(entry); + } + return result; + } + + public static List GetInstructions(IEnumerable lines) + { + var result = new List(); + foreach (var line in lines) + { + if (TryParseInstruction(line, out var entry)) + result.Add(entry); + } + return result; + } + + public static bool TryParseFilter(ReadOnlySpan line, [NotNullWhen(true)] out StringInstruction? entry) + { + entry = null; + if (line.Length is 0) + return false; + var comparer = GetComparer(line[0]); + if (!comparer.IsSupportedComparer()) + return false; + return TryParseSplitTuple(line[1..], ref entry, comparer); + } + + public static bool TryParseInstruction(ReadOnlySpan line, [NotNullWhen(true)] out StringInstruction? entry) + { + entry = null; + if (line.Length is 0 || line[0] is not Apply) + return false; + return TryParseSplitTuple(line[1..], ref entry); + } + + public static bool TryParseSplitTuple(ReadOnlySpan tuple, [NotNullWhen(true)] ref StringInstruction? entry, InstructionComparer eval = default) + { + if (!TryParseSplitTuple(tuple, out var name, out var value)) + return false; + entry = new StringInstruction(name.ToString(), value.ToString()) { Comparer = eval }; + return true; + } + + public static bool TryParseSplitTuple(ReadOnlySpan tuple, out ReadOnlySpan name, out ReadOnlySpan value) + { + name = default; + value = default; + var splitIndex = tuple.IndexOf(SplitInstruction); + if (splitIndex <= 0) + return false; + + name = tuple[..splitIndex]; + if (name.IsWhiteSpace()) + return false; + + value = tuple[(splitIndex + 1)..]; + var noExtra = value.IndexOf(SplitInstruction); + if (noExtra != -1) + return false; + + return true; + } + + public static InstructionComparer GetComparer(char c) => c switch + { + FilterEqual => IsEqual, + FilterNotEqual => IsNotEqual, + FilterGreaterThan => IsGreaterThan, + FilterLessThan => IsLessThan, + FilterGreaterThanOrEqual => IsGreaterThanOrEqual, + FilterLessThanOrEqual => IsLessThanOrEqual, + _ => None, + }; +} + +/// +/// Value comparison type +/// +public enum InstructionComparer : byte +{ + None, + IsEqual, + IsNotEqual, + IsGreaterThan, + IsGreaterThanOrEqual, + IsLessThan, + IsLessThanOrEqual, +} + +public static class InstructionComparerExtensions +{ + /// + /// Indicates if the is supported by the logic. + /// + /// Type of comparison requested + /// True if supported, false if unsupported. + public static bool IsSupportedComparer(this InstructionComparer comparer) => comparer switch + { + IsEqual => true, + IsNotEqual => true, + IsGreaterThan => true, + IsGreaterThanOrEqual => true, + IsLessThan => true, + IsLessThanOrEqual => true, + _ => false, + }; + + /// + /// Checks if the compare operator is satisfied by a boolean comparison result. + /// + /// Type of comparison requested + /// Result from Equals comparison + /// True if satisfied + /// Only use this method if the comparison is boolean only. Use the otherwise. + public static bool IsCompareEquivalence(this InstructionComparer comparer, bool compareResult) => comparer switch + { + IsEqual => compareResult, + IsNotEqual => !compareResult, + _ => false, + }; + + /// + /// Checks if the compare operator is satisfied by the result. + /// + /// Type of comparison requested + /// Result from CompareTo + /// True if satisfied + public static bool IsCompareOperator(this InstructionComparer comparer, int compareResult) => comparer switch + { + IsEqual => compareResult is 0, + IsNotEqual => compareResult is not 0, + IsGreaterThan => compareResult > 0, + IsGreaterThanOrEqual => compareResult >= 0, + IsLessThan => compareResult < 0, + IsLessThanOrEqual => compareResult <= 0, + _ => false, + }; } diff --git a/PKHeX.Core/Editing/Bulk/StringInstructionSet.cs b/PKHeX.Core/Editing/Bulk/StringInstructionSet.cs index dc0a8063b..8fe55d367 100644 --- a/PKHeX.Core/Editing/Bulk/StringInstructionSet.cs +++ b/PKHeX.Core/Editing/Bulk/StringInstructionSet.cs @@ -1,6 +1,6 @@ -using System; +using System; using System.Collections.Generic; -using System.Linq; +using System.Text; namespace PKHeX.Core; @@ -13,6 +13,7 @@ public sealed class StringInstructionSet public readonly IReadOnlyList Instructions; private const string SetSeparator = ";"; + private const char SetSeparatorChar = ';'; public StringInstructionSet(IReadOnlyList filters, IReadOnlyList instructions) { @@ -20,19 +21,129 @@ public sealed class StringInstructionSet Instructions = instructions; } - public StringInstructionSet(ICollection set) + public StringInstructionSet(ReadOnlySpan text) { - Filters = StringInstruction.GetFilters(set).ToList(); - Instructions = StringInstruction.GetInstructions(set).ToList(); + var set = text.EnumerateLines(); + Filters = StringInstruction.GetFilters(set); + Instructions = StringInstruction.GetInstructions(set); } - public static IEnumerable GetBatchSets(IList lines) + public StringInstructionSet(SpanLineEnumerator set) + { + Filters = StringInstruction.GetFilters(set); + Instructions = StringInstruction.GetInstructions(set); + } + + public StringInstructionSet(ReadOnlySpan set) + { + Filters = StringInstruction.GetFilters(set); + Instructions = StringInstruction.GetInstructions(set); + } + + /// + /// Checks if the input is potentially formatted incorrectly. + /// + /// Normally, no blank lines should be present in the input. + /// True if a blank line is found in the input. + public static bool HasEmptyLine(ReadOnlySpan text) => HasEmptyLine(text.EnumerateLines()); + + /// + public static bool HasEmptyLine(SpanLineEnumerator lines) + { + foreach (var line in lines) + { + if (line.IsEmpty || line.IsWhiteSpace()) + return true; + } + return false; + } + + public static StringInstructionSet[] GetBatchSets(ReadOnlySpan lines) + { + int ctr = 0; + int start = 0; + while (start < lines.Length) + { + var slice = lines[start..]; + var count = GetInstructionSetLength(slice); + ctr++; + start += count + 1; + } + + var result = new StringInstructionSet[ctr]; + ctr = 0; + start = 0; + while (start < lines.Length) + { + var slice = lines[start..]; + var count = GetInstructionSetLength(slice); + var set = slice[..count]; + result[ctr++] = new StringInstructionSet(set); + start += count + 1; + } + return result; + } + + public static StringInstructionSet[] GetBatchSets(ReadOnlySpan text) + { + int ctr = 0; + int start = 0; + while (start < text.Length) + { + var slice = text[start..]; + var count = GetInstructionSetLength(slice); + ctr++; + start += count + 1; + } + + var result = new StringInstructionSet[ctr]; + ctr = 0; + start = 0; + while (start < text.Length) + { + var slice = text[start..]; + var count = GetInstructionSetLength(slice); + var set = slice[..count]; + result[ctr++] = new StringInstructionSet(set); + start += count + 1; + } + return result; + } + + /// + /// Scans through the to count the amount of characters to consume. + /// + /// Multi line string + /// Amount of characters comprising a set of instructions + public static int GetInstructionSetLength(ReadOnlySpan text) { int start = 0; - while (start < lines.Count) + while (start < text.Length) { - var list = lines.Skip(start).TakeWhile(_ => !lines[start++].StartsWith(SetSeparator, StringComparison.Ordinal)).ToList(); - yield return new StringInstructionSet(list); + var line = text[start..]; + if (line.Length != 0 && line[0] == SetSeparatorChar) + return start; + var next = line.IndexOf('\n'); + if (next == -1) + return text.Length; + start += next + 1; } + return start; + } + + /// + /// Scans through the to count the amount of valid lines to consume. + /// + /// Amount of lines comprising a set of instructions. + public static int GetInstructionSetLength(ReadOnlySpan lines) + { + int start = 0; + while (start < lines.Length) + { + var line = lines[start++]; + if (line.Length != 0 && line[0] == SetSeparatorChar) + return start; + } + return start; } } diff --git a/PKHeX.Core/Editing/Bulk/Suggestion/BatchModifications.cs b/PKHeX.Core/Editing/Bulk/Suggestion/BatchModifications.cs index a64bf453b..f19c3bd60 100644 --- a/PKHeX.Core/Editing/Bulk/Suggestion/BatchModifications.cs +++ b/PKHeX.Core/Editing/Bulk/Suggestion/BatchModifications.cs @@ -7,10 +7,10 @@ namespace PKHeX.Core; /// internal static class BatchModifications { - private static bool IsAll(string p) => p.EndsWith("All", StringComparison.OrdinalIgnoreCase); - private static bool IsNone(string p) => p.EndsWith("None", StringComparison.OrdinalIgnoreCase); + private static bool IsAll(ReadOnlySpan p) => p.EndsWith("All", StringComparison.OrdinalIgnoreCase); + private static bool IsNone(ReadOnlySpan p) => p.EndsWith("None", StringComparison.OrdinalIgnoreCase); - public static ModifyResult SetSuggestedRelearnData(BatchInfo info, string propValue) + public static ModifyResult SetSuggestedRelearnData(BatchInfo info, ReadOnlySpan propValue) { var pk = info.Entity; if (pk is ITechRecord t) @@ -32,7 +32,7 @@ internal static class BatchModifications return ModifyResult.Modified; } - public static ModifyResult SetSuggestedMasteryData(BatchInfo info, string propValue) + public static ModifyResult SetSuggestedMasteryData(BatchInfo info, ReadOnlySpan propValue) { var pk = info.Entity; if (pk is not IMoveShop8Mastery t) @@ -52,7 +52,7 @@ internal static class BatchModifications return ModifyResult.Modified; } - public static ModifyResult SetSuggestedRibbons(BatchInfo info, string value) + public static ModifyResult SetSuggestedRibbons(BatchInfo info, ReadOnlySpan value) { if (IsNone(value)) RibbonApplicator.RemoveAllValidRibbons(info.Legality); @@ -111,7 +111,7 @@ internal static class BatchModifications /// Pokémon to modify. /// Legality Information matched to. /// Option to apply with - public static ModifyResult SetContestStats(PKM pk, LegalityAnalysis la, string option) + public static ModifyResult SetContestStats(PKM pk, LegalityAnalysis la, ReadOnlySpan option) { if (option.Length != 0 && option[BatchEditing.CONST_SUGGEST.Length..] is not "0") pk.SetMaxContestStats(la.EncounterMatch, la.Info.EvoChainsAllGens); diff --git a/PKHeX.Core/Editing/CommonEdits.cs b/PKHeX.Core/Editing/CommonEdits.cs index 16d2c472d..bf9f207bc 100644 --- a/PKHeX.Core/Editing/CommonEdits.cs +++ b/PKHeX.Core/Editing/CommonEdits.cs @@ -142,7 +142,7 @@ public static class CommonEdits /// Desired value to set. public static void SetNature(this PKM pk, int nature) { - var value = Math.Min((int)Nature.Quirky, Math.Max((int)Nature.Hardy, nature)); + var value = Math.Clamp(nature, (int)Nature.Hardy, (int)Nature.Quirky); var format = pk.Format; if (format >= 8) pk.StatNature = value; @@ -192,7 +192,7 @@ public static class CommonEdits // IVs have no side effects such as hidden power type in gen 8 // therefore all specified IVs are deliberate and should not be Hyper Trained for pokemon met in gen 8 - if (!pk.Gen8) + if (pk.Generation < 8) pk.SetSuggestedHyperTrainingData(Set.IVs); if (ShowdownSetIVMarkings) @@ -313,7 +313,7 @@ public static class CommonEdits var sum = pk.EVTotal - pk.GetEV(index); int remaining = 510 - sum; - return Math.Min(Math.Max(remaining, 0), 252); + return Math.Clamp(remaining, 0, 252); } /// @@ -350,7 +350,7 @@ public static class CommonEdits var loc = EncounterSuggestion.GetSuggestedEggMetLocation(pk); if (loc >= 0) pk.Met_Location = loc; - pk.MetDate = DateTime.Today; + pk.MetDate = DateOnly.FromDateTime(DateTime.Today); if (pk.Gen6) pk.SetHatchMemory6(); } @@ -364,7 +364,7 @@ public static class CommonEdits public static void SetEggMetData(this PKM pk, GameVersion origin, GameVersion dest) { bool traded = origin != dest; - var today = pk.MetDate = DateTime.Today; + var today = pk.MetDate = DateOnly.FromDateTime(DateTime.Today); pk.Egg_Location = EncounterSuggestion.GetSuggestedEncounterEggLocationEgg(pk.Generation, origin, traded); pk.EggMetDate = today; } @@ -403,7 +403,7 @@ public static class CommonEdits /// Precomputed optional public static void SetDefaultNickname(this PKM pk, LegalityAnalysis la) { - if (la.Parsed && la.EncounterOriginal is EncounterTrade {HasNickname: true} t) + if (la is { Parsed: true, EncounterOriginal: EncounterTrade {HasNickname: true} t }) pk.SetNickname(t.GetNickname(pk.Language)); else pk.ClearNickname(); @@ -468,7 +468,7 @@ public static class CommonEdits '0' or '3' => 0u, _ when pk.Species is (int)Species.Dudunsparce && pk.Form == 1 => 0, // 3 Segment _ when pk.Species is (int)Species.Maushold && pk.Form == 0 => 0, // Family of 3 - _ => (uint)rng.Next(1, 100) + _ => (uint)rng.Next(1, 100), }; } else if (option is >= '0' and <= '5') diff --git a/PKHeX.Core/Editing/Database/TrainerDatabase.cs b/PKHeX.Core/Editing/Database/TrainerDatabase.cs index f871f4a76..50d3cdefc 100644 --- a/PKHeX.Core/Editing/Database/TrainerDatabase.cs +++ b/PKHeX.Core/Editing/Database/TrainerDatabase.cs @@ -131,7 +131,7 @@ public sealed class TrainerDatabase { var result = new SimpleTrainerInfo((GameVersion)pk.Version) { - TID = pk.TID, SID = pk.SID, OT = pk.OT_Name, Gender = pk.OT_Gender, + TID16 = pk.TID16, SID16 = pk.SID16, OT = pk.OT_Name, Gender = pk.OT_Gender, Language = pk.Language, Generation = pk.Generation, }; diff --git a/PKHeX.Core/Editing/HiddenPower.cs b/PKHeX.Core/Editing/HiddenPower.cs index 3c8eae67a..5abfcf645 100644 --- a/PKHeX.Core/Editing/HiddenPower.cs +++ b/PKHeX.Core/Editing/HiddenPower.cs @@ -196,7 +196,7 @@ public static class HiddenPower /// These are just precomputed for fast modification. /// Individual Values (H/A/B/S/C/D) /// - public static readonly byte[] DefaultLowBits = + public static ReadOnlySpan DefaultLowBits => new byte[] { 0b000011, // Fighting 0b001000, // Flying diff --git a/PKHeX.Core/Editing/PKM/EntitySummary.cs b/PKHeX.Core/Editing/PKM/EntitySummary.cs index 130d387e8..20359967c 100644 --- a/PKHeX.Core/Editing/PKM/EntitySummary.cs +++ b/PKHeX.Core/Editing/PKM/EntitySummary.cs @@ -6,7 +6,7 @@ namespace PKHeX.Core; /// /// Bindable summary object that can fetch strings that summarize a . /// -public class EntitySummary // do NOT seal, allow inheritance +public class EntitySummary : IFatefulEncounterReadOnly // do NOT seal, allow inheritance { private static readonly IReadOnlyList GenderSymbols = GameInfo.GenderSymbolASCII; @@ -76,14 +76,14 @@ public class EntitySummary // do NOT seal, allow inheritance public int MetLevel => pk.Met_Level; public int OT_Gender => pk.OT_Gender; - public bool FatefulFlag => pk.FatefulEncounter; + public bool FatefulEncounter => pk.FatefulEncounter; public bool IsEgg => pk.IsEgg; public bool IsNicknamed => pk.IsNicknamed; public bool IsShiny => pk.IsShiny; - public int TID => pk.DisplayTID; - public int SID => pk.DisplaySID; - public int TSV => pk.TSV; + public ushort TID16 => pk.TID16; + public ushort SID16 => pk.SID16; + public uint TSV => pk.TSV; public int Move1_PP => pk.Move1_PP; public int Move2_PP => pk.Move2_PP; public int Move3_PP => pk.Move3_PP; diff --git a/PKHeX.Core/Editing/PKM/EntityTemplates.cs b/PKHeX.Core/Editing/PKM/EntityTemplates.cs index a70135d42..e73b0f56c 100644 --- a/PKHeX.Core/Editing/PKM/EntityTemplates.cs +++ b/PKHeX.Core/Editing/PKM/EntityTemplates.cs @@ -17,7 +17,7 @@ public static class EntityTemplates pk.Move1 = (int)Move.Pound; pk.HealPP(); pk.Ball = 4; - pk.MetDate = DateTime.Today; + pk.MetDate = DateOnly.FromDateTime(DateTime.Today); if (tr.Game >= 0) pk.Version = tr.Game; @@ -30,8 +30,7 @@ public static class EntityTemplates pk.OT_Name = tr.OT; pk.OT_Gender = tr.Gender; - pk.TID = tr.TID; - pk.SID = tr.SID; + pk.ID32 = tr.ID32; if (tr is IRegionOrigin o && pk is IRegionOrigin gt) { gt.ConsoleRegion = o.ConsoleRegion; diff --git a/PKHeX.Core/Editing/PKM/QR/QRMessageUtil.cs b/PKHeX.Core/Editing/PKM/QR/QRMessageUtil.cs index 3392599c2..599d6fc3d 100644 --- a/PKHeX.Core/Editing/PKM/QR/QRMessageUtil.cs +++ b/PKHeX.Core/Editing/PKM/QR/QRMessageUtil.cs @@ -1,4 +1,5 @@ using System; +using System.Buffers; using System.Text; namespace PKHeX.Core; @@ -20,7 +21,7 @@ public static class QRMessageUtil /// QR Message /// Preferred to expect. /// Decoded object, null if invalid. - public static PKM? GetPKM(string message, EntityContext context) + public static PKM? GetPKM(ReadOnlySpan message, EntityContext context) { var data = DecodeMessagePKM(message); if (data == null) @@ -71,13 +72,13 @@ public static class QRMessageUtil return GetMessageBase64(data, server); } - public static string GetMessageBase64(byte[] data, string server) + public static string GetMessageBase64(ReadOnlySpan data, string server) { string payload = Convert.ToBase64String(data); return server + payload; } - private static byte[]? DecodeMessagePKM(string message) + private static byte[]? DecodeMessagePKM(ReadOnlySpan message) { if (message.Length < 32) // arbitrary length check; everything should be greater than this return null; @@ -89,27 +90,24 @@ public static class QRMessageUtil const int g7size = 0xE8; const int g7intro = 0x30; if (message.StartsWith("POKE", StringComparison.Ordinal) && message.Length > g7intro + g7size) // G7 data - return GetBytesFromMessage(message.AsSpan(g7intro), g7size); + return GetBytesFromMessage(message[g7intro..], g7size); return null; } - private static byte[]? DecodeMessageDataBase64(string url) + private static byte[]? DecodeMessageDataBase64(ReadOnlySpan url) { - if (url.Length == 0 || url[^1] == '#') - return null; + int payloadBegin = url.IndexOf('#'); + if (payloadBegin == -1) + return null; // bad URL, need the payload separator + if (payloadBegin == url.Length - 1) + return null; // no payload - try - { - int payloadBegin = url.IndexOf('#'); - if (payloadBegin < 0) // bad URL, need the payload separator - return null; - url = url[(payloadBegin + 1)..]; // Trim URL to right after # - return Convert.FromBase64String(url); - } - catch (FormatException) - { - return null; - } + url = url[(payloadBegin + 1)..]; // Trim URL to right after # + // Decode unicode string -- size might be pretty big (user input), so just rent instead of stackalloc + var tmp = ArrayPool.Shared.Rent(url.Length); + var result = Convert.TryFromBase64Chars(url, tmp, out int bytesWritten) ? tmp[..bytesWritten] : null; + ArrayPool.Shared.Return(tmp); + return result; } private static byte[] GetBytesFromMessage(ReadOnlySpan input, int count) diff --git a/PKHeX.Core/Editing/PKM/QR/QRPK7.cs b/PKHeX.Core/Editing/PKM/QR/QRPK7.cs index 9f81c085a..b091fe0bf 100644 --- a/PKHeX.Core/Editing/PKM/QR/QRPK7.cs +++ b/PKHeX.Core/Editing/PKM/QR/QRPK7.cs @@ -113,7 +113,7 @@ public sealed class QRPK7 : IEncounterInfo HT_Name = tr.OT, CurrentLevel = Level, Met_Level = Level, - MetDate = DateTime.Now, + MetDate = DateOnly.FromDateTime(DateTime.Today), }; RecentTrainerCache.SetConsoleRegionData3DS(pk, tr); diff --git a/PKHeX.Core/Editing/Program/StartupArguments.cs b/PKHeX.Core/Editing/Program/StartupArguments.cs index d29f290fa..6d3beac2b 100644 --- a/PKHeX.Core/Editing/Program/StartupArguments.cs +++ b/PKHeX.Core/Editing/Program/StartupArguments.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using System.IO; using System.Linq; @@ -103,7 +103,11 @@ public sealed class StartupArguments var tr = SaveUtil.GetSafeTrainerName(current, lang); var sav = SaveUtil.GetBlankSAV(version, tr, lang); if (sav.Version == GameVersion.Invalid) // will fail to load - sav = SaveUtil.GetBlankSAV((GameVersion)GameInfo.VersionDataSource.Max(z => z.Value), tr, lang); + { + var max = GameInfo.VersionDataSource.MaxBy(z => z.Value) ?? throw new Exception(); + var ver = (GameVersion)max.Value; + sav = SaveUtil.GetBlankSAV(ver, tr, lang); + } return sav; } diff --git a/PKHeX.Core/Editing/Saves/BoxManip/BoxManipDefaults.cs b/PKHeX.Core/Editing/Saves/BoxManip/BoxManipDefaults.cs index 2f98809c7..9e43eb9a0 100644 --- a/PKHeX.Core/Editing/Saves/BoxManip/BoxManipDefaults.cs +++ b/PKHeX.Core/Editing/Saves/BoxManip/BoxManipDefaults.cs @@ -36,11 +36,13 @@ public static class BoxManipDefaults new BoxManipSort(SortTraining, list => list.OrderByCustom(pk => (pk.MaxEV * 6) - pk.EVTotal)), new BoxManipSortComplex(SortOwner, (list, sav) => list.OrderByOwnership(sav)), new BoxManipSort(SortType, list => list.OrderByCustom(pk => pk.PersonalInfo.Type1, pk => pk.PersonalInfo.Type2)), - new BoxManipSort(SortTypeTera, list => list.OrderByCustom(pk => ((ITeraTypeReadOnly)pk).TeraType, pk => pk is ITeraTypeReadOnly)), + new BoxManipSort(SortTypeTera, list => list.OrderByCustom(pk => ((ITeraType)pk).GetTeraType()), s => s.BlankPKM is ITeraType), new BoxManipSort(SortVersion, list => list.OrderByCustom(pk => pk.Generation, pk => pk.Version, pk => pk.Met_Location), s => s.Generation >= 3), new BoxManipSort(SortBST, list => list.OrderByCustom(pk => pk.PersonalInfo.GetBaseStatTotal())), new BoxManipSort(SortCP, list => list.OrderByCustom(pk => pk is PB7 pb7 ? pb7.Stat_CP : 0), s => s is SAV7b), new BoxManipSort(SortScale, list => list.OrderByCustom(pk => pk is IScaledSize3 s3 ? s3.Scale : -1), s => s.BlankPKM is IScaledSize3), + new BoxManipSort(SortRibbons, list => list.OrderByCustom(pk => pk is IRibbonSetRibbons s ? int.MaxValue - s.RibbonCount : 0), s => s.BlankPKM is IRibbonSetRibbons), + new BoxManipSort(SortMarks, list => list.OrderByCustom(pk => pk is IRibbonSetMarks s ? int.MaxValue - s.MarkCount : 0), s => s.BlankPKM is IRibbonSetMarks), new BoxManipSort(SortLegal, list => list.OrderByCustom(pk => !new LegalityAnalysis(pk).Valid)), new BoxManipSort(SortEncounterType, list => list.OrderByCustom(pk => new LegalityAnalysis(pk).Info.EncounterMatch.LongName)), }; diff --git a/PKHeX.Core/Editing/Saves/BoxManip/BoxManipType.cs b/PKHeX.Core/Editing/Saves/BoxManip/BoxManipType.cs index 88944d01f..6a731611c 100644 --- a/PKHeX.Core/Editing/Saves/BoxManip/BoxManipType.cs +++ b/PKHeX.Core/Editing/Saves/BoxManip/BoxManipType.cs @@ -35,6 +35,8 @@ public enum BoxManipType SortBST, SortCP, SortScale, + SortRibbons, + SortMarks, SortLegal, SortEncounterType, diff --git a/PKHeX.Core/Editing/Saves/Editors/EventOld/EventLabelCollection.cs b/PKHeX.Core/Editing/Saves/Editors/EventOld/EventLabelCollection.cs index c3f221119..0e0ccab07 100644 --- a/PKHeX.Core/Editing/Saves/Editors/EventOld/EventLabelCollection.cs +++ b/PKHeX.Core/Editing/Saves/Editors/EventOld/EventLabelCollection.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; namespace PKHeX.Core; @@ -12,267 +11,7 @@ public sealed class EventLabelCollection { var f = GameLanguage.GetStrings(game, GameInfo.CurrentLanguage, "flags"); var c = GameLanguage.GetStrings(game, GameInfo.CurrentLanguage, "const"); - Flag = GetFlags(f, maxFlag); - Work = GetValues(c, maxValue); + Flag = EventLabelParsing.GetFlags(f, maxFlag); + Work = EventLabelParsing.GetWork(c, maxValue); } - - private static List GetFlags(IReadOnlyCollection strings, int maxValue) - { - var result = new List(strings.Count); - var processed = new HashSet(); - foreach (var s in strings) - { - var split = s.Split('\t'); - if (split.Length != 3) - continue; - - var index = TryParseHexDec(split[0]); - if (index >= maxValue) - throw new ArgumentOutOfRangeException(nameof(index), index, "Value too high."); - - if (processed.Contains(index)) - throw new ArgumentOutOfRangeException(nameof(index), index, "Already have an entry for this!"); - - var type = GetEventType(split[1]); - var desc = split[2]; - - var item = new NamedEventValue(desc, index, type); - result.Add(item); - processed.Add(index); - } - - return result; - } - - private static readonly NamedEventConst Custom = new("Custom", NamedEventConst.CustomMagicValue); - private static readonly NamedEventConst[] Empty = {Custom}; - - private static IReadOnlyList GetValues(IReadOnlyCollection strings, int maxValue) - { - var result = new List(strings.Count); - var processed = new HashSet(); - foreach (var s in strings) - { - var split = s.Split('\t'); - if (split.Length is not (3 or 4)) - continue; - - var index = TryParseHexDecConst(split[0]); - if (index >= maxValue) - throw new ArgumentOutOfRangeException(nameof(index), index, "Value too high."); - - if (processed.Contains(index)) - throw new ArgumentOutOfRangeException(nameof(index), index, "Already have an entry for this!"); - - var type = GetEventType(split[1]); - var desc = split[2]; - var predefined = split.Length is 3 ? Empty : GetPredefinedArray(split[3]); - var item = new NamedEventWork(desc, index, type, predefined); - result.Add(item); - processed.Add(index); - } - - return result; - } - - private static IReadOnlyList GetPredefinedArray(string combined) - { - var result = new List {Custom}; - var split = combined.Split(','); - foreach (var entry in split) - { - var subsplit = entry.Split(':'); - var name = subsplit[1]; - var value = Convert.ToUInt16(subsplit[0], 10); - result.Add(new NamedEventConst(name, value)); - } - return result; - } - - private static int TryParseHexDec(string flag) - { - if (!flag.StartsWith("0x", StringComparison.Ordinal)) - return Convert.ToInt16(flag, 10); - flag = flag[2..]; - return Convert.ToInt16(flag, 16); - } - - private static int TryParseHexDecConst(string c) - { - if (!c.StartsWith("0x40", StringComparison.Ordinal)) - return Convert.ToInt16(c, 10); - c = c[4..]; - return Convert.ToInt16(c, 16); - } - - private static NamedEventType GetEventType(string s) => s.Length == 0 ? 0 : GetEventType(s[0]); - - private static NamedEventType GetEventType(char c) => c switch - { - 'h' => NamedEventType.HiddenItem, - 'm' => NamedEventType.Misc, - 'f' => NamedEventType.FlyToggle, - 't' => NamedEventType.TrainerToggle, - 's' => NamedEventType.StoryProgress, - - 'a' => NamedEventType.Achievement, - '+' => NamedEventType.Statistic, - '*' => NamedEventType.UsefulFeature, - 'e' => NamedEventType.EncounterEvent, - 'g' => NamedEventType.GiftAvailable, - 'r' => NamedEventType.Rebattle, - _ => NamedEventType.None, - }; -} - -public sealed class EventLabelCollectionSystem -{ - public readonly IReadOnlyList Work; - public readonly IReadOnlyList Flag; - public readonly IReadOnlyList System; - - public EventLabelCollectionSystem(string game, int maxFlag = int.MaxValue, int maxSystem = int.MaxValue, int maxValue = int.MaxValue) - { - var f = GameLanguage.GetStrings(game, GameInfo.CurrentLanguage, "flag"); - var s = GameLanguage.GetStrings(game, GameInfo.CurrentLanguage, "system"); - var c = GameLanguage.GetStrings(game, GameInfo.CurrentLanguage, "work"); - Flag = GetFlags(f, maxFlag); - System = GetFlags(s, maxSystem); - Work = GetValues(c, maxValue); - } - - private static List GetFlags(IReadOnlyCollection strings, int maxValue) - { - var result = new List(strings.Count); - var processed = new HashSet(); - foreach (var s in strings) - { - var split = s.Split('\t'); - if (split.Length != 3) - continue; - - var index = TryParseHexDec(split[0]); - if (index >= maxValue) - throw new ArgumentOutOfRangeException(nameof(index), index, "Value too high."); - - if (processed.Contains(index)) - throw new ArgumentOutOfRangeException(nameof(index), index, "Already have an entry for this!"); - - var type = GetEventType(split[1]); - var desc = split[2]; - - var item = new NamedEventValue(desc, index, type); - result.Add(item); - processed.Add(index); - } - - return result; - } - - private static readonly NamedEventConst Custom = new("Custom", NamedEventConst.CustomMagicValue); - private static readonly NamedEventConst[] Empty = { Custom }; - - private static IReadOnlyList GetValues(IReadOnlyCollection strings, int maxValue) - { - var result = new List(strings.Count); - var processed = new HashSet(); - foreach (var s in strings) - { - var split = s.Split('\t'); - if (split.Length is not (3 or 4)) - continue; - - var index = TryParseHexDecConst(split[0]); - if (index >= maxValue) - throw new ArgumentOutOfRangeException(nameof(index), index, "Value too high."); - - if (processed.Contains(index)) - throw new ArgumentOutOfRangeException(nameof(index), index, "Already have an entry for this!"); - - var type = GetEventType(split[1]); - var desc = split[2]; - var predefined = split.Length is 3 ? Empty : GetPredefinedArray(split[3]); - var item = new NamedEventWork(desc, index, type, predefined); - result.Add(item); - processed.Add(index); - } - - return result; - } - - private static IReadOnlyList GetPredefinedArray(string combined) - { - var result = new List { Custom }; - var split = combined.Split(','); - foreach (var entry in split) - { - var subsplit = entry.Split(':'); - var name = subsplit[1]; - var value = Convert.ToUInt16(subsplit[0], 10); - result.Add(new NamedEventConst(name, value)); - } - return result; - } - - private static int TryParseHexDec(string flag) - { - if (!flag.StartsWith("0x", StringComparison.Ordinal)) - return Convert.ToInt16(flag, 10); - flag = flag[2..]; - return Convert.ToInt16(flag, 16); - } - - private static int TryParseHexDecConst(string c) - { - if (!c.StartsWith("0x40", StringComparison.Ordinal)) - return Convert.ToInt16(c, 10); - c = c[4..]; - return Convert.ToInt16(c, 16); - } - - private static NamedEventType GetEventType(string s) => s.Length == 0 ? 0 : GetEventType(s[0]); - - private static NamedEventType GetEventType(char c) => c switch - { - 'h' => NamedEventType.HiddenItem, - 'm' => NamedEventType.Misc, - 'f' => NamedEventType.FlyToggle, - 't' => NamedEventType.TrainerToggle, - 's' => NamedEventType.StoryProgress, - - 'a' => NamedEventType.Achievement, - '+' => NamedEventType.Statistic, - '*' => NamedEventType.UsefulFeature, - 'e' => NamedEventType.EncounterEvent, - 'g' => NamedEventType.GiftAvailable, - 'r' => NamedEventType.Rebattle, - _ => NamedEventType.None, - }; -} - -public enum NamedEventType -{ - None, - HiddenItem, - TrainerToggle, - StoryProgress, - FlyToggle, - Misc, - Statistic, - - Achievement, - UsefulFeature, - EncounterEvent, - GiftAvailable, - Rebattle = 100, -} - -public record NamedEventValue(string Name, int Index, NamedEventType Type); - -public sealed record NamedEventWork(string Name, int Index, NamedEventType Type, IReadOnlyList PredefinedValues) : NamedEventValue(Name, Index, Type); - -public sealed record NamedEventConst(string Name, ushort Value) -{ - public bool IsCustom => Value == CustomMagicValue; - public const ushort CustomMagicValue = ushort.MaxValue; } diff --git a/PKHeX.Core/Editing/Saves/Editors/EventOld/EventLabelCollectionSystem.cs b/PKHeX.Core/Editing/Saves/Editors/EventOld/EventLabelCollectionSystem.cs new file mode 100644 index 000000000..b3f206052 --- /dev/null +++ b/PKHeX.Core/Editing/Saves/Editors/EventOld/EventLabelCollectionSystem.cs @@ -0,0 +1,20 @@ +using System.Collections.Generic; + +namespace PKHeX.Core; + +public sealed class EventLabelCollectionSystem +{ + public readonly IReadOnlyList Work; + public readonly IReadOnlyList Flag; + public readonly IReadOnlyList System; + + public EventLabelCollectionSystem(string game, int maxFlag = int.MaxValue, int maxSystem = int.MaxValue, int maxValue = int.MaxValue) + { + var f = GameLanguage.GetStrings(game, GameInfo.CurrentLanguage, "flag"); + var s = GameLanguage.GetStrings(game, GameInfo.CurrentLanguage, "system"); + var c = GameLanguage.GetStrings(game, GameInfo.CurrentLanguage, "work"); + Flag = EventLabelParsing.GetFlags(f, maxFlag); + System = EventLabelParsing.GetFlags(s, maxSystem); + Work = EventLabelParsing.GetWork(c, maxValue); + } +} diff --git a/PKHeX.Core/Editing/Saves/Editors/EventOld/EventLabelParsing.cs b/PKHeX.Core/Editing/Saves/Editors/EventOld/EventLabelParsing.cs new file mode 100644 index 000000000..0c9df61b4 --- /dev/null +++ b/PKHeX.Core/Editing/Saves/Editors/EventOld/EventLabelParsing.cs @@ -0,0 +1,155 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Globalization; + +namespace PKHeX.Core; + +/// +/// Logic for parsing labeled scripted event schemas into labeled tags. +/// +public static class EventLabelParsing +{ + private const char Split = '\t'; + + private static readonly NamedEventConst Custom = new("Custom", NamedEventConst.CustomMagicValue); + private static readonly NamedEventConst[] Empty = { Custom }; + + public static List GetFlags(ReadOnlySpan strings, int maxValue = int.MaxValue) + { + var result = new List(strings.Length); + var processed = new HashSet(strings.Length); + foreach (var line in strings) + { + if (!TryParseValue(line, out var item)) + continue; + + SanityCheck(item, processed, maxValue); + result.Add(item); + } + return result; + } + + public static List GetWork(ReadOnlySpan strings, int maxValue = int.MaxValue) + { + var result = new List(strings.Length); + var processed = new HashSet(strings.Length); + foreach (var line in strings) + { + if (!TryParseWork(line, out var item)) + continue; + + SanityCheck(item, processed, maxValue); + result.Add(item); + } + return result; + } + + private static void SanityCheck(NamedEventValue item, ISet processed, int maxValue) + { + var index = item.Index; + if (index >= maxValue) + throw new ArgumentOutOfRangeException(nameof(index), index, "Value too high."); + if (processed.Contains(index)) + throw new ArgumentOutOfRangeException(nameof(index), index, "Already have an entry for this!"); + processed.Add(index); + } + + public static bool TryParseValue(ReadOnlySpan value, [NotNullWhen(true)] out NamedEventValue? result) + { + result = null; + var split = value.IndexOf(Split); + if (split < 0) + return false; + + var number = value[..split]; + var index = TryParseHexDec(number, "0x"); + + value = value[(split + 1)..]; + split = value.IndexOf(Split); + if (split < 0) + return false; + + var category = value[..split]; + var type = NamedEventTypeUtil.GetEventType(category); + + value = value[(split + 1)..]; + var desc = value.ToString(); + result = new NamedEventValue(desc, index, type); + return true; + } + + public static bool TryParseWork(ReadOnlySpan value, [NotNullWhen(true)] out NamedEventWork? item) + { + item = null; + var split = value.IndexOf(Split); + if (split < 0) + return false; + + var number = value[..split]; + var index = TryParseHexDec(number, "0x4"); + + value = value[(split + 1)..]; + split = value.IndexOf(Split); + if (split < 0) + return false; + + var category = value[..split]; + var type = NamedEventTypeUtil.GetEventType(category); + + value = value[(split + 1)..]; + var (desc, predefined) = GetDescPredefined(value); + item = new NamedEventWork(desc, index, type, predefined); + return true; + } + + private static (string Description, IReadOnlyList Named) GetDescPredefined(ReadOnlySpan remainder) + { + var split3 = remainder.IndexOf(Split); + if (split3 < 0) + return (remainder.ToString(), Empty); + + var values = remainder[(split3 + 1)..]; + var desc = remainder[..split3].ToString(); + var predefined = GetPredefinedArray(values); + return (desc, predefined); + } + + private static IReadOnlyList GetPredefinedArray(ReadOnlySpan combined) + { + var result = new List(Empty); + + // x:y tuples separated by , + while (true) + { + // grab the next tuple span + var next = combined.IndexOf(','); + var tuple = next < 0 ? combined : combined[..next]; + var split = tuple.IndexOf(':'); + if (split < 0) + break; + + // parse the tuple into the name and value object + var value = tuple[..split]; + var name = tuple[(split + 1)..]; + var val = TryParseHexDec(value, "0x"); + var item = new NamedEventConst(name.ToString(), (ushort)val); + result.Add(item); + + if (next < 0) + break; // no more tuples + + // advance the span to next potential tuple + combined = combined[(next + 1)..]; + } + return result; + } + + private static int TryParseHexDec(ReadOnlySpan text, ReadOnlySpan hexPrefix) + { + if (!text.StartsWith(hexPrefix)) + return int.TryParse(text, out var value) ? value : 0; + text = text[hexPrefix.Length..]; + return int.TryParse(text, NumberStyles.HexNumber, null, out var hex) ? hex : 0; + } +} diff --git a/PKHeX.Core/Editing/Saves/Editors/EventOld/NamedEventType.cs b/PKHeX.Core/Editing/Saves/Editors/EventOld/NamedEventType.cs new file mode 100644 index 000000000..4d8ee298c --- /dev/null +++ b/PKHeX.Core/Editing/Saves/Editors/EventOld/NamedEventType.cs @@ -0,0 +1,46 @@ +using System; +using static PKHeX.Core.NamedEventType; + +namespace PKHeX.Core; + +/// +/// Type of scripted event label +/// +public enum NamedEventType +{ + None, + HiddenItem, + TrainerToggle, + StoryProgress, + FlyToggle, + Misc, + Statistic, + + Achievement, + UsefulFeature, + EventEncounter, + GiftAvailable, + Rebattle = 100, +} + +public static class NamedEventTypeUtil +{ + public static NamedEventType GetEventType(ReadOnlySpan s) => s.Length == 0 ? None : GetEventType(s[0]); + + public static NamedEventType GetEventType(char c) => c switch + { + 'h' => HiddenItem, + 'm' => Misc, + 'f' => FlyToggle, + 't' => TrainerToggle, + 's' => StoryProgress, + + 'a' => Achievement, + '+' => Statistic, + '*' => UsefulFeature, + 'e' => EventEncounter, + 'g' => GiftAvailable, + 'r' => Rebattle, + _ => None, + }; +} diff --git a/PKHeX.Core/Editing/Saves/Editors/EventOld/NamedEventValue.cs b/PKHeX.Core/Editing/Saves/Editors/EventOld/NamedEventValue.cs new file mode 100644 index 000000000..d72230045 --- /dev/null +++ b/PKHeX.Core/Editing/Saves/Editors/EventOld/NamedEventValue.cs @@ -0,0 +1,3 @@ +namespace PKHeX.Core; + +public record NamedEventValue(string Name, int Index, NamedEventType Type); diff --git a/PKHeX.Core/Editing/Saves/Editors/EventOld/NamedEventWork.cs b/PKHeX.Core/Editing/Saves/Editors/EventOld/NamedEventWork.cs new file mode 100644 index 000000000..3954e44f4 --- /dev/null +++ b/PKHeX.Core/Editing/Saves/Editors/EventOld/NamedEventWork.cs @@ -0,0 +1,11 @@ +using System.Collections.Generic; + +namespace PKHeX.Core; + +public sealed record NamedEventWork(string Name, int Index, NamedEventType Type, IReadOnlyList PredefinedValues) : NamedEventValue(Name, Index, Type); + +public sealed record NamedEventConst(string Name, ushort Value) +{ + public bool IsCustom => Value == CustomMagicValue; + public const ushort CustomMagicValue = ushort.MaxValue; +} diff --git a/PKHeX.Core/Editing/Saves/Editors/EventUnlock/EventUnlocker8b.cs b/PKHeX.Core/Editing/Saves/Editors/EventUnlock/EventUnlocker8b.cs index 164d1e3d2..d4b41d39a 100644 --- a/PKHeX.Core/Editing/Saves/Editors/EventUnlock/EventUnlocker8b.cs +++ b/PKHeX.Core/Editing/Saves/Editors/EventUnlock/EventUnlocker8b.cs @@ -1,6 +1,6 @@ -namespace PKHeX.Core; +namespace PKHeX.Core; -public class EventUnlocker8b : EventUnlocker +public sealed class EventUnlocker8b : EventUnlocker { public EventUnlocker8b(SAV8BS sav) : base(sav) { } diff --git a/PKHeX.Core/Editing/Saves/Editors/EventWork/Diff/EventWorkDiffCompatibility.cs b/PKHeX.Core/Editing/Saves/Editors/EventWork/Diff/EventWorkDiffCompatibility.cs index c3d935206..1f5912106 100644 --- a/PKHeX.Core/Editing/Saves/Editors/EventWork/Diff/EventWorkDiffCompatibility.cs +++ b/PKHeX.Core/Editing/Saves/Editors/EventWork/Diff/EventWorkDiffCompatibility.cs @@ -5,6 +5,9 @@ using static PKHeX.Core.EventWorkDiffCompatibility; namespace PKHeX.Core; +/// +/// Indicates if the compared data is incompatible in any way. +/// public enum EventWorkDiffCompatibility { Valid, diff --git a/PKHeX.Core/Editing/Saves/Editors/FakeSaveFile.cs b/PKHeX.Core/Editing/Saves/Editors/FakeSaveFile.cs index e27d8213c..eac7ae1fc 100644 --- a/PKHeX.Core/Editing/Saves/Editors/FakeSaveFile.cs +++ b/PKHeX.Core/Editing/Saves/Editors/FakeSaveFile.cs @@ -7,19 +7,19 @@ public sealed class FakeSaveFile : SaveFile { public static readonly FakeSaveFile Default = new(); protected internal override string ShortSummary => "Fake Save File"; - protected override SaveFile CloneInternal() => this; + protected override FakeSaveFile CloneInternal() => this; public override string Extension => string.Empty; public override bool ChecksumsValid => true; public override string ChecksumInfo => string.Empty; public override int Generation => 3; public override string GetString(ReadOnlySpan data) => string.Empty; public override int SetString(Span destBuffer, ReadOnlySpan value, int maxLength, StringConverterOption option) => 0; - public override IPersonalTable Personal => PersonalTable.RS; + public override PersonalTable3 Personal => PersonalTable.RS; public override int MaxEV => 0; public override IReadOnlyList HeldItems => Legal.HeldItems_RS; public override int GetBoxOffset(int box) => -1; public override string GetBoxName(int box) => $"Box {box:00}"; - public override void SetBoxName(int box, string value) { } + public override void SetBoxName(int box, ReadOnlySpan value) { } public override int MaxStringLengthOT => 5; public override int MaxStringLengthNickname => 5; public override ushort MaxMoveID => 5; @@ -33,9 +33,9 @@ public sealed class FakeSaveFile : SaveFile protected override void SetChecksums() { } public override Type PKMType => typeof(PK3); - protected override PKM GetPKM(byte[] data) => BlankPKM; + protected override PK3 GetPKM(byte[] data) => BlankPKM; protected override byte[] DecryptPKM(byte[] data) => data; - public override PKM BlankPKM => new PK3(); + public override PK3 BlankPKM => new(); public override EntityContext Context => EntityContext.Gen3; protected override int SIZE_STORED => 0; protected override int SIZE_PARTY => 0; diff --git a/PKHeX.Core/Editing/Saves/Management/SavePreview.cs b/PKHeX.Core/Editing/Saves/Management/SavePreview.cs index ca05b61c1..d3dd7e639 100644 --- a/PKHeX.Core/Editing/Saves/Management/SavePreview.cs +++ b/PKHeX.Core/Editing/Saves/Management/SavePreview.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using System.IO; @@ -38,8 +38,8 @@ public sealed class SavePreview public string Played => Save.PlayTimeString.PadLeft(9, '0'); public string FileTime => File.GetLastWriteTimeUtc(FilePath).ToString("yyyy.MM.dd:hh:mm:ss"); - public string TID => Save.Generation >= 7 ? Save.TrainerID7.ToString("000000") : Save.TID.ToString("00000"); - public string SID => Save.Generation >= 7 ? Save.TrainerSID7.ToString("0000") : Save.SID.ToString("00000"); + public string TID => Save.GetDisplayTID().ToString(Save.TrainerIDDisplayFormat.GetTrainerIDFormatStringTID()); + public string SID => Save.GetDisplaySID().ToString(Save.TrainerIDDisplayFormat.GetTrainerIDFormatStringSID()); // ReSharper disable once MemberCanBePrivate.Local // ReSharper disable once UnusedAutoPropertyAccessor.Local diff --git a/PKHeX.Core/Editing/Saves/Slots/Info/SlotCache.cs b/PKHeX.Core/Editing/Saves/Slots/Info/SlotCache.cs index 0030b7031..777c35ad4 100644 --- a/PKHeX.Core/Editing/Saves/Slots/Info/SlotCache.cs +++ b/PKHeX.Core/Editing/Saves/Slots/Info/SlotCache.cs @@ -64,7 +64,7 @@ public sealed class SlotCache : IComparable return string.CompareOrdinal(Identify(), other.Identify()); } - public override bool Equals(object obj) + public override bool Equals(object? obj) { if (ReferenceEquals(this, obj)) return true; diff --git a/PKHeX.Core/Editing/Saves/Slots/SlotTouchType.cs b/PKHeX.Core/Editing/Saves/Slots/SlotTouchType.cs index d2263213e..9c81671d5 100644 --- a/PKHeX.Core/Editing/Saves/Slots/SlotTouchType.cs +++ b/PKHeX.Core/Editing/Saves/Slots/SlotTouchType.cs @@ -23,5 +23,8 @@ public enum SlotTouchType public static class SlotTouchTypeUtil { + /// + /// Indicates if the happens after a write operation and the underlying data has been changed. + /// public static bool IsContentChange(this SlotTouchType t) => t > SlotTouchType.Get; } diff --git a/PKHeX.Core/Editing/Saves/Slots/SlotViewInfo.cs b/PKHeX.Core/Editing/Saves/Slots/SlotViewInfo.cs index b0dac7521..b2002c64e 100644 --- a/PKHeX.Core/Editing/Saves/Slots/SlotViewInfo.cs +++ b/PKHeX.Core/Editing/Saves/Slots/SlotViewInfo.cs @@ -32,7 +32,7 @@ public sealed class SlotViewInfo : IEquatable return other.Slot.GetType() == Slot.GetType(); } - public override bool Equals(object obj) => ReferenceEquals(this, obj) || (obj is SlotViewInfo other && Equals(other)); + public override bool Equals(object? obj) => ReferenceEquals(this, obj) || (obj is SlotViewInfo other && Equals(other)); public override int GetHashCode() => (Slot.GetHashCode() * 397) ^ View.GetHashCode(); - bool IEquatable.Equals(T other) => other != null && Equals(other); + bool IEquatable.Equals(T? other) => other != null && Equals(other); } diff --git a/PKHeX.Core/Editing/Showdown/ShowdownParsing.cs b/PKHeX.Core/Editing/Showdown/ShowdownParsing.cs index 337693927..8d94981f0 100644 --- a/PKHeX.Core/Editing/Showdown/ShowdownParsing.cs +++ b/PKHeX.Core/Editing/Showdown/ShowdownParsing.cs @@ -85,11 +85,9 @@ public static class ShowdownParsing (int)Necrozma when form is "Dusk" => $"{form}-Mane", (int)Necrozma when form is "Dawn" => $"{form}-Wings", (int)Polteageist or (int)Sinistea => form == "Antique" ? form : string.Empty, - (int)Tauros when form is "Paldea (Fire)" => "Paldea-Fire", - (int)Tauros when form is "Paldea (Water)" => "Paldea-Water", (int)Maushold when form is "Family of Four" => "Four", - (int)Furfrou or (int)Greninja or (int)Rockruff or (int)Tatsugiri or (int)Koraidon or (int)Miraidon => string.Empty, + (int)Furfrou or (int)Greninja or (int)Rockruff or (int)Koraidon or (int)Miraidon => string.Empty, _ => Legal.Totem_USUM.Contains(species) && form == "Large" ? Legal.Totem_Alolan.Contains(species) && species != (int)Mimikyu ? "Alola-Totem" : "Totem" @@ -121,8 +119,6 @@ public static class ShowdownParsing (int)Zygarde when ability == 211 => $"{(string.IsNullOrWhiteSpace(form) ? "50%" : "10%")}-C", (int)Greninja when ability == 210 => "Ash", // Battle Bond (int)Rockruff when ability == 020 => "Dusk", // Rockruff-1 - (int)Tauros when form == "Paldea-Fire" => "Paldea (Fire)", - (int)Tauros when form == "Paldea-Water" => "Paldea (Water)", (int)Maushold when form == "Four" => "Family of Four", (int)Urshifu or (int)Pikachu or (int)Alcremie => form.Replace('-', ' '), // Strike and Cosplay @@ -156,6 +152,63 @@ public static class ShowdownParsing yield return new ShowdownSet(setLines); } + /// + public static IEnumerable GetShowdownSets(ReadOnlyMemory text) + { + int start = 0; + do + { + var span = text.Span; + var slice = span[start..]; + var set = GetShowdownSet(slice, out int length); + if (set.Species == 0) + break; + yield return set; + start += length; + } + while (start < text.Length); + } + + /// + public static IEnumerable GetShowdownSets(string text) => GetShowdownSets(text.AsMemory()); + + private static int GetLength(ReadOnlySpan text) + { + // Find the end of the Showdown Set lines. + // The end is implied when: + // - we see a completely whitespace or empty line, or + // - we witness four 'move' definition lines. + int length = 0; + int moveCount = 4; + + while (true) + { + var newline = text.IndexOf('\n'); + if (newline == -1) + return length + text.Length; + + var slice = text[..newline]; + var used = newline + 1; + length += used; + + if (slice.IsEmpty || slice.IsWhiteSpace()) + return length; + if (slice.TrimStart()[0] is '-' or '–' && --moveCount == 0) + return length; + text = text[used..]; + } + } + + public static ShowdownSet GetShowdownSet(ReadOnlySpan text, out int length) + { + length = GetLength(text); + var slice = text[..length]; + var set = new ShowdownSet(slice); + while (length < text.Length && text[length] is '\r' or '\n' or ' ') + length++; + return set; + } + /// /// Converts the data into an importable set format for Pokémon Showdown. /// diff --git a/PKHeX.Core/Editing/Showdown/ShowdownSet.cs b/PKHeX.Core/Editing/Showdown/ShowdownSet.cs index f4b44ba48..58355c57c 100644 --- a/PKHeX.Core/Editing/Showdown/ShowdownSet.cs +++ b/PKHeX.Core/Editing/Showdown/ShowdownSet.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Text; using static PKHeX.Core.Species; namespace PKHeX.Core; @@ -10,11 +11,9 @@ namespace PKHeX.Core; public sealed class ShowdownSet : IBattleTemplate { private static readonly string[] StatNames = { "HP", "Atk", "Def", "Spe", "SpA", "SpD" }; - private static readonly string[] Splitters = {"\r\n", "\n"}; - private static readonly string[] StatSplitters = { " / ", " " }; private const string LineSplit = ": "; private const string ItemSplit = " @ "; - private static readonly char[] ParenJunk = { '(', ')', '[', ']' }; + private const string ParenJunk = "()[]"; private const int MAX_SPECIES = (int)MAX_COUNT - 1; internal const string DefaultLanguage = GameLanguage.DefaultLanguage; private static readonly GameStrings DefaultStrings = GameInfo.GetStrings(DefaultLanguage); @@ -86,7 +85,7 @@ public sealed class ShowdownSet : IBattleTemplate /// /// Any lines that failed to be parsed. /// - public readonly List InvalidLines = new(); + public readonly List InvalidLines = new(0); private GameStrings Strings { get; set; } = DefaultStrings; @@ -94,7 +93,7 @@ public sealed class ShowdownSet : IBattleTemplate /// Loads a new from the input string. /// /// Single-line string which will be split before loading. - public ShowdownSet(string input) : this(input.Split(Splitters, 0)) { } + public ShowdownSet(ReadOnlySpan input) => LoadLines(input.EnumerateLines()); /// /// Loads a new from the input string. @@ -102,10 +101,20 @@ public sealed class ShowdownSet : IBattleTemplate /// Enumerable list of lines. public ShowdownSet(IEnumerable lines) => LoadLines(lines); + private void LoadLines(SpanLineEnumerator lines) + { + ParseLines(lines); + SanitizeResult(); + } + private void LoadLines(IEnumerable lines) { ParseLines(lines); + SanitizeResult(); + } + private void SanitizeResult() + { FormName = ShowdownParsing.SetShowdownFormName(Species, FormName, Ability); Form = ShowdownParsing.GetFormFromString(FormName, Strings, Species, Context); @@ -114,23 +123,6 @@ public sealed class ShowdownSet : IBattleTemplate ReviseGenderedForms(); } - private static IEnumerable GetSanitizedLines(IEnumerable lines) - { - foreach (var line in lines) - { - var trim = line.Trim(); - if (trim.Length <= 2) - continue; - - // Sanitize apostrophes & dashes - if (trim.IndexOf('\'') != -1) - trim = trim.Replace('\'', '’'); - if (trim.IndexOf('–') != -1) - trim = trim.Replace('–', '-'); - yield return trim; - } - } - private void ReviseGenderedForms() { if (Gender == 1) // Recognized with (F) @@ -147,58 +139,92 @@ public sealed class ShowdownSet : IBattleTemplate private const int MaxMoveCount = 4; - private void ParseLines(IEnumerable lines) + private void ParseLines(SpanLineEnumerator lines) { - lines = GetSanitizedLines(lines); - using var e = lines.GetEnumerator(); - if (!e.MoveNext()) - return; - - ParseFirstLine(e.Current!); int movectr = 0; - while (e.MoveNext()) + bool first = true; + foreach (var line in lines) { - var line = e.Current!; - if (line.Length < 3) - continue; - - if (line[0] == '-') + ReadOnlySpan trim = line.Trim(); + if (trim.Length is <= 2 or >= 40) { - string moveString = ParseLineMove(line); - int move = StringUtil.FindIndexIgnoreCase(Strings.movelist, moveString); - if (move < 0) - InvalidLines.Add($"Unknown Move: {moveString}"); - else if (Array.IndexOf(Moves, (ushort)move) != -1) - InvalidLines.Add($"Duplicate Move: {moveString}"); - else - Moves[movectr++] = (ushort)move; - - if (movectr == MaxMoveCount) - return; // End of moves, end of set data + InvalidLines.Add(line.ToString()); continue; } - if (movectr != 0) - break; - - bool valid; - var split = line.IndexOf(LineSplit, StringComparison.Ordinal); - if (split == -1) + if (first) { - valid = ParseSingle(line); // Nature + ParseFirstLine(trim); + first = false; + continue; } - else - { - var left = line[..split].Trim(); - var right = line[(split + LineSplit.Length)..].Trim(); - valid = ParseEntry(left, right); - } - if (!valid) - InvalidLines.Add(line); + if (ParseLine(trim, ref movectr)) + return; // End of moves, end of set data } } - private bool ParseSingle(string identifier) + private void ParseLines(IEnumerable lines) + { + int movectr = 0; + bool first = true; + foreach (var line in lines) + { + ReadOnlySpan trim = line.Trim(); + if (trim.Length is <= 2 or >= 40) + { + InvalidLines.Add(line); + continue; + } + + if (first) + { + ParseFirstLine(trim); + first = false; + continue; + } + if (ParseLine(trim, ref movectr)) + return; // End of moves, end of set data + } + } + + private bool ParseLine(ReadOnlySpan line, ref int movectr) + { + if (line[0] is '-' or '–') + { + var moveString = ParseLineMove(line); + int move = StringUtil.FindIndexIgnoreCase(Strings.movelist, moveString); + if (move < 0) + InvalidLines.Add($"Unknown Move: {moveString}"); + else if (Array.IndexOf(Moves, (ushort)move) != -1) + InvalidLines.Add($"Duplicate Move: {moveString}"); + else + Moves[movectr++] = (ushort)move; + + return movectr == MaxMoveCount; + } + + if (movectr != 0) + return true; + + bool valid; + var split = line.IndexOf(LineSplit, StringComparison.Ordinal); + if (split == -1) + { + valid = ParseSingle(line); // Nature + } + else + { + var left = line[..split].Trim(); + var right = line[(split + LineSplit.Length)..].Trim(); + valid = ParseEntry(left, right); + } + + if (!valid) + InvalidLines.Add(line.ToString()); + return false; + } + + private bool ParseSingle(ReadOnlySpan identifier) { if (!identifier.EndsWith("Nature", StringComparison.OrdinalIgnoreCase)) return false; @@ -209,7 +235,7 @@ public sealed class ShowdownSet : IBattleTemplate return (Nature = StringUtil.FindIndexIgnoreCase(Strings.natures, naturestr)) >= 0; } - private bool ParseEntry(string identifier, string value) => identifier switch + private bool ParseEntry(ReadOnlySpan identifier, ReadOnlySpan value) => identifier switch { "Ability" => (Ability = StringUtil.FindIndexIgnoreCase(Strings.abilitylist, value)) >= 0, "Nature" => (Nature = StringUtil.FindIndexIgnoreCase(Strings.natures , value)) >= 0, @@ -224,7 +250,7 @@ public sealed class ShowdownSet : IBattleTemplate _ => false, }; - private bool ParseLevel(string value) + private bool ParseLevel(ReadOnlySpan value) { if (!int.TryParse(value.Trim(), out var val)) return false; @@ -234,7 +260,7 @@ public sealed class ShowdownSet : IBattleTemplate return true; } - private bool ParseFriendship(string value) + private bool ParseFriendship(ReadOnlySpan value) { if (!int.TryParse(value.Trim(), out var val)) return false; @@ -244,7 +270,7 @@ public sealed class ShowdownSet : IBattleTemplate return true; } - private bool ParseDynamax(string value) + private bool ParseDynamax(ReadOnlySpan value) { Context = EntityContext.Gen8; var val = Util.ToInt32(value); @@ -253,7 +279,7 @@ public sealed class ShowdownSet : IBattleTemplate return (DynamaxLevel = (byte)val) is (>= 0 and <= 10); } - private bool ParseTeraType(string value) + private bool ParseTeraType(ReadOnlySpan value) { Context = EntityContext.Gen9; var types = Strings.types; @@ -478,7 +504,7 @@ public sealed class ShowdownSet : IBattleTemplate FormName = ShowdownParsing.GetStringFromForm(Form = pk.Form, Strings, Species, Context); } - private void ParseFirstLine(string first) + private void ParseFirstLine(ReadOnlySpan first) { int itemSplit = first.IndexOf(ItemSplit, StringComparison.Ordinal); if (itemSplit != -1) @@ -495,20 +521,20 @@ public sealed class ShowdownSet : IBattleTemplate } } - private void ParseItemName(string itemName) + private void ParseItemName(ReadOnlySpan itemName) { - if (TrySetItem(Context)) + if (TrySetItem(Context, itemName)) return; - if (TrySetItem(EntityContext.Gen3)) + if (TrySetItem(EntityContext.Gen3, itemName)) return; - if (TrySetItem(EntityContext.Gen2)) + if (TrySetItem(EntityContext.Gen2, itemName)) return; InvalidLines.Add($"Unknown Item: {itemName}"); - bool TrySetItem(EntityContext context) + bool TrySetItem(EntityContext context, ReadOnlySpan span) { var items = Strings.GetItemStrings(context); - int item = StringUtil.FindIndexIgnoreCase(items, itemName); + int item = StringUtil.FindIndexIgnoreCase(items, span); if (item < 0) return false; HeldItem = item; @@ -517,7 +543,7 @@ public sealed class ShowdownSet : IBattleTemplate } } - private void ParseFirstLineNoItem(string line) + private void ParseFirstLineNoItem(ReadOnlySpan line) { // Gender Detection if (line.EndsWith("(M)", StringComparison.Ordinal)) @@ -540,7 +566,7 @@ public sealed class ShowdownSet : IBattleTemplate private const string Gmax = "-Gmax"; - private bool ParseSpeciesForm(string speciesLine) + private bool ParseSpeciesForm(ReadOnlySpan speciesLine) { speciesLine = speciesLine.Trim(); if (speciesLine.Length == 0) @@ -569,7 +595,7 @@ public sealed class ShowdownSet : IBattleTemplate if (speciesIndex > 0) { Species = (ushort)speciesIndex; - FormName = speciesLine[(end + 1)..]; + FormName = speciesLine[(end + 1)..].ToString(); return true; } @@ -580,12 +606,12 @@ public sealed class ShowdownSet : IBattleTemplate if (!speciesLine.StartsWith(sn.Replace("♂", "-M").Replace("♀", "-F"), StringComparison.Ordinal)) continue; Species = e; - FormName = speciesLine[sn.Length..]; + FormName = speciesLine[sn.Length..].ToString(); return true; } // Version Megas - end = speciesLine.LastIndexOf('-', Math.Max(0, end - 1)); + end = speciesLine[Math.Max(0, end - 1)..].LastIndexOf('-'); if (end < 0) return false; @@ -593,21 +619,22 @@ public sealed class ShowdownSet : IBattleTemplate if (speciesIndex > 0) { Species = (ushort)speciesIndex; - FormName = speciesLine[(end + 1)..]; + FormName = speciesLine[(end + 1)..].ToString(); return true; } return false; } - private void ParseSpeciesNickname(string line) + private void ParseSpeciesNickname(ReadOnlySpan line) { int index = line.LastIndexOf('('); - string species, nickname; + Span species = stackalloc char[line.Length]; + Span nickname = stackalloc char[line.Length]; if (index > 1) // parenthesis value after: Nickname (Species), correct. { - nickname = line[..index].Trim(); - species = line[index..].Trim(); - species = RemoveAll(species, ParenJunk); // Trim out excess data + line[..index].Trim().CopyTo(nickname); + line[index..].Trim().CopyTo(species); + RemoveAll(ref species, ParenJunk); // Trim out excess data } else // parenthesis value before: (Species) Nickname, incorrect { @@ -616,29 +643,31 @@ public sealed class ShowdownSet : IBattleTemplate var tmp = line[start..end]; if (end < line.Length - 2) { - nickname = line[(end + 2)..]; - species = tmp; + line[(end + 2)..].CopyTo(nickname); + tmp.CopyTo(species); } else // (Species), or garbage { - species = tmp; - nickname = string.Empty; + tmp.CopyTo(species); + nickname = Span.Empty; } } + species = species.TrimEnd('\0'); + nickname = nickname.TrimEnd('\0'); if (ParseSpeciesForm(species)) - Nickname = nickname; + Nickname = nickname.ToString(); else if (ParseSpeciesForm(nickname)) - Nickname = species; + Nickname = species.ToString(); } - private string ParseLineMove(string line) + private ReadOnlySpan ParseLineMove(ReadOnlySpan line) { var startSearch = line[1] == ' ' ? 2 : 1; var option = line.IndexOf('/'); line = option != -1 ? line[startSearch..option] : line[startSearch..]; - string moveString = line.Trim(); + var moveString = line.Trim(); var hiddenPowerName = Strings.Move[(int)Move.HiddenPower]; if (!moveString.StartsWith(hiddenPowerName, StringComparison.OrdinalIgnoreCase)) @@ -648,8 +677,9 @@ public sealed class ShowdownSet : IBattleTemplate return hiddenPowerName; // Defined Hidden Power - string type = moveString[13..]; - type = RemoveAll(type, ParenJunk); // Trim out excess data + Span type = stackalloc char[moveString.Length - hiddenPowerName.Length]; + moveString[hiddenPowerName.Length..].CopyTo(type); + RemoveAll(ref type, ParenJunk); // Trim out excess data int hpVal = StringUtil.FindIndexIgnoreCase(Strings.types, type) - 1; // Get HP Type HiddenPowerType = hpVal; @@ -669,57 +699,84 @@ public sealed class ShowdownSet : IBattleTemplate return hiddenPowerName; } - private bool ParseLineEVs(string line) + private bool ParseLineEVs(ReadOnlySpan line) { - var list = line.Split(StatSplitters, StringSplitOptions.None); - if ((list.Length & 1) == 1) - InvalidLines.Add("Unknown EV input."); - for (int i = 0; i < list.Length / 2; i++) + int start = 0; + while (true) { - int pos = i * 2; - var statName = list[pos + 1]; - int index = StringUtil.FindIndexIgnoreCase(StatNames, statName); - if (index < 0 || !ushort.TryParse(list[pos + 0], out var value)) - { - InvalidLines.Add($"Unknown EV stat: {list[pos]}"); - continue; - } - EVs[index] = value; + var chunk = line[start..]; + var separator = chunk.IndexOf('/'); + var len = separator == -1 ? chunk.Length : separator; + var tuple = chunk[..len].Trim(); + if (!AbsorbValue(tuple)) + InvalidLines.Add($"Invalid EV tuple: {tuple}"); + if (separator == -1) + break; // no more stats + start += separator + 1; } return true; + + bool AbsorbValue(ReadOnlySpan text) + { + var space = text.IndexOf(' '); + if (space == -1) + return false; + var stat = text[(space + 1)..].Trim(); + var statIndex = StringUtil.FindIndexIgnoreCase(StatNames, stat); + if (statIndex == -1) + return false; + var value = text[..space].Trim(); + if (!ushort.TryParse(value, out var statValue)) + return false; + EVs[statIndex] = statValue; + return true; + } } - private bool ParseLineIVs(string line) + private bool ParseLineIVs(ReadOnlySpan line) { - var list = line.Split(StatSplitters, StringSplitOptions.None); - if ((list.Length & 1) == 1) - InvalidLines.Add("Unknown IV input."); - for (int i = 0; i < list.Length / 2; i++) + int start = 0; + while (true) { - int pos = i * 2; - var statName = list[pos + 1]; - int index = StringUtil.FindIndexIgnoreCase(StatNames, statName); - if (index < 0 || !byte.TryParse(list[pos + 0], out var value)) - { - InvalidLines.Add($"Unknown IV stat: {list[pos]}"); - continue; - } - IVs[index] = value; + var chunk = line[start..]; + var separator = chunk.IndexOf('/'); + var len = separator == -1 ? chunk.Length : separator; + var tuple = chunk[..len].Trim(); + if (!AbsorbValue(tuple)) + InvalidLines.Add($"Invalid IV tuple: {tuple}"); + if (separator == -1) + break; // no more stats + start += separator + 1; } return true; + + bool AbsorbValue(ReadOnlySpan text) + { + var space = text.IndexOf(' '); + if (space == -1) + return false; + var stat = text[(space + 1)..].Trim(); + var statIndex = StringUtil.FindIndexIgnoreCase(StatNames, stat); + if (statIndex == -1) + return false; + var value = text[..space].Trim(); + if (!byte.TryParse(value, out var statValue)) + return false; + IVs[statIndex] = statValue; + return true; + } } - private static string RemoveAll(string original, ReadOnlySpan remove) + private static void RemoveAll(ref Span buffer, ReadOnlySpan remove) { - Span result = stackalloc char[original.Length]; int ctr = 0; - foreach (var c in original) + for (var i = 0; i < buffer.Length; i++) { - if (remove.IndexOf(c) == -1) - result[ctr++] = c; + char c = buffer[i]; + if (!remove.Contains(c)) + buffer[ctr++] = c; } - if (ctr == original.Length) - return original; - return new string(result[..ctr].ToArray()); + if (ctr != buffer.Length) + buffer = buffer[..ctr]; } } diff --git a/PKHeX.Core/Editing/SpriteBuilderTweak.cs b/PKHeX.Core/Editing/SpriteBuilderTweak.cs index 32a2ef3cf..0646ef593 100644 --- a/PKHeX.Core/Editing/SpriteBuilderTweak.cs +++ b/PKHeX.Core/Editing/SpriteBuilderTweak.cs @@ -11,8 +11,3 @@ public enum SpriteBuilderTweak None = 0, BoxBackgroundRed = 1, } - -public static class SpriteBuilderTweakExtensions -{ - public static bool HasFlagFast(this SpriteBuilderTweak value, SpriteBuilderTweak flag) => (value & flag) != 0; -} diff --git a/PKHeX.Core/Game/Enums/GameVersion.cs b/PKHeX.Core/Game/Enums/GameVersion.cs index b1429d6a7..68c286749 100644 --- a/PKHeX.Core/Game/Enums/GameVersion.cs +++ b/PKHeX.Core/Game/Enums/GameVersion.cs @@ -160,7 +160,7 @@ public enum GameVersion : byte BU = 37, /// - /// Pokémon Yellow [JP] (3DS Virtual Console) + /// Pokémon Yellow (3DS Virtual Console) /// YW = 38, #endregion diff --git a/PKHeX.Core/Game/Enums/Species.cs b/PKHeX.Core/Game/Enums/Species.cs index 2c5299ca8..9340cca8f 100644 --- a/PKHeX.Core/Game/Enums/Species.cs +++ b/PKHeX.Core/Game/Enums/Species.cs @@ -922,99 +922,99 @@ public enum Species : ushort Quaquaval, Lechonk, Oinkologne, - Dudunsparce, Tarountula, Spidops, Nymble, Lokix, - Rellor, - Rabsca, - Greavard, - Houndstone, - Flittle, - Espathra, - Farigiraf, - Wiglett, - Wugtrio, - Dondozo, - Veluza, - Finizen, - Palafin, - Smoliv, - Dolliv, - Arboliva, - Capsakid, - Scovillain, - Tadbulb, - Bellibolt, - Varoom, - Revavroom, - Orthworm, - Tandemaus, - Maushold, - Cetoddle, - Cetitan, - Frigibax, - Arctibax, - Baxcalibur, - Tatsugiri, - Cyclizar, Pawmi, Pawmo, Pawmot, - Wattrel, - Kilowattrel, - Bombirdier, + Tandemaus, + Maushold, + Fidough, + Dachsbun, + Smoliv, + Dolliv, + Arboliva, Squawkabilly, - Flamigo, - Klawf, Nacli, Naclstack, Garganacl, - Glimmet, - Glimmora, - Shroodle, - Grafaiai, - Fidough, - Dachsbun, - Maschiff, - Mabosstiff, - Bramblin, - Brambleghast, - Gimmighoul, - Gholdengo, - GreatTusk, - BruteBonnet, - _980, - SandyShocks, - ScreamTail, - FlutterMane, - SlitherWing, - RoaringMoon, - IronTreads, - _987, - IronMoth, - IronHands, - IronJugulis, - IronThorns, - IronBundle, - IronValiant, - TingLu, - ChienPao, - WoChien, - ChiYu, - Koraidon, - Miraidon, - Tinkatink, - Tinkatuff, - Tinkaton, Charcadet, Armarouge, Ceruledge, + Tadbulb, + Bellibolt, + Wattrel, + Kilowattrel, + Maschiff, + Mabosstiff, + Shroodle, + Grafaiai, + Bramblin, + Brambleghast, Toedscool, Toedscruel, - Kingambit, - Clodsire, + Klawf, + Capsakid, + Scovillain, + Rellor, + Rabsca, + Flittle, + Espathra, + Tinkatink, + Tinkatuff, + Tinkaton, + Wiglett, + Wugtrio, + Bombirdier, + Finizen, + Palafin, + Varoom, + Revavroom, + Cyclizar, + Orthworm, + Glimmet, + Glimmora, + Greavard, + Houndstone, + Flamigo, + Cetoddle, + Cetitan, + Veluza, + Dondozo, + Tatsugiri, Annihilape, + Clodsire, + Farigiraf, + Dudunsparce, + Kingambit, + GreatTusk, + ScreamTail, + BruteBonnet, + FlutterMane, + SlitherWing, + SandyShocks, + IronTreads, + IronBundle, + IronHands, + IronJugulis, + IronMoth, + IronThorns, + Frigibax, + Arctibax, + Baxcalibur, + Gimmighoul, + Gholdengo, + WoChien, + ChienPao, + TingLu, + ChiYu, + RoaringMoon, + IronValiant, + Koraidon, + Miraidon, + _980, + _987, MAX_COUNT, } diff --git a/PKHeX.Core/Game/GameStrings/GameDataSource.cs b/PKHeX.Core/Game/GameStrings/GameDataSource.cs index 5fa736866..85aec16dc 100644 --- a/PKHeX.Core/Game/GameStrings/GameDataSource.cs +++ b/PKHeX.Core/Game/GameStrings/GameDataSource.cs @@ -77,6 +77,32 @@ public sealed class GameDataSource public readonly IReadOnlyList HaXMoveDataSource; public readonly IReadOnlyList GroundTileDataSource; + private static ReadOnlySpan OrderedVersionArray => new byte[] + { + 50, 51, // 9 sv + 47, // 8 legends arceus + 48, 49, // 8 bdsp + 44, 45, // 8 swsh + 42, 43, // 7 gg + 30, 31, // 7 sm + 32, 33, // 7 usum + 24, 25, // 6 xy + 27, 26, // 6 oras + 21, 20, // 5 bw + 23, 22, // 5 b2w2 + 10, 11, 12, // 4 dppt + 07, 08, // 4 hgss + 02, 01, 03, // 3 rse + 04, 05, // 3 frlg + 15, // 3 cxd + + 39, 40, 41, // 7vc2 + 35, 36, 37, 38, // 7vc1 + 34, // 7go + + 00, + }; + private static IReadOnlyList GetBalls(string[] itemList) { // ignores Poke/Great/Ultra @@ -88,33 +114,7 @@ public sealed class GameDataSource private static ComboItem[] GetVersionList(GameStrings s) { var list = s.gamelist; - ReadOnlySpan games = stackalloc byte[] - { - 50, 51, // 9 sv - 47, // 8 legends arceus - 48, 49, // 8 bdsp - 44, 45, // 8 swsh - 42, 43, // 7 gg - 30, 31, // 7 sm - 32, 33, // 7 usum - 24, 25, // 6 xy - 27, 26, // 6 oras - 21, 20, // 5 bw - 23, 22, // 5 b2w2 - 10, 11, 12, // 4 dppt - 07, 08, // 4 hgss - 02, 01, 03, // 3 rse - 04, 05, // 3 frlg - 15, // 3 cxd - - 39, 40, 41, // 7vc2 - 35, 36, 37, 38, // 7vc1 - 34, // 7go - - 00, - }; - - return Util.GetUnsortedCBList(list, games); + return Util.GetUnsortedCBList(list, OrderedVersionArray); } public List GetItemDataSource(GameVersion game, EntityContext context, IReadOnlyList allowed, bool HaX = false) diff --git a/PKHeX.Core/Game/GameStrings/GameStrings.cs b/PKHeX.Core/Game/GameStrings/GameStrings.cs index 4f615e06a..24833ff86 100644 --- a/PKHeX.Core/Game/GameStrings/GameStrings.cs +++ b/PKHeX.Core/Game/GameStrings/GameStrings.cs @@ -158,11 +158,10 @@ public sealed class GameStrings : IBasicStrings private string[] GetG3CXD(string[] arr, string fileName) { // Concatenate the Gen3 Item list with the CXD item array; CXD items starting at index 500. - // Empty slots between the two lists are marked as unused. var item500 = Get(fileName); var result = new string[500 + item500.Length]; for (int i = arr.Length; i < result.Length; i++) - result[i] = $"UNUSED {i}"; + result[i] = string.Empty; arr.CopyTo(result, 0); item500.CopyTo(result, 500); return result; @@ -170,7 +169,7 @@ public sealed class GameStrings : IBasicStrings private static void SanitizeMetStringsCXD(string[] cxd) { - // Less than 10% of location values are unique. + // Less than 10% of location values are unique. // Just mark them with the ID if they aren't empty. for (int i = 0; i < 227; i++) { @@ -479,7 +478,7 @@ public sealed class GameStrings : IBasicStrings set.Met4[i] += " (-)"; } - private void SanitizeMetGen7b(LocationSet6 set) + private static void SanitizeMetGen7b(LocationSet6 set) { for (int i = 48; i < 55; i++) // distinguish Event year duplicates set.Met4[i] += " (-)"; diff --git a/PKHeX.Core/Game/GameStrings/GeoLocation.cs b/PKHeX.Core/Game/GameStrings/GeoLocation.cs index 715f54b7b..9d76d668d 100644 --- a/PKHeX.Core/Game/GameStrings/GeoLocation.cs +++ b/PKHeX.Core/Game/GameStrings/GeoLocation.cs @@ -1,4 +1,4 @@ -using System; +using System; namespace PKHeX.Core; @@ -25,7 +25,7 @@ public static class GeoLocation return UnpackList(input); } - private static string[]?[] GetRegionList(int country) + private static string[]?[] GetRegionList(byte country) { var input = Util.GetStringList($"sr_{country:000}"); return UnpackList(input); @@ -51,7 +51,7 @@ public static class GeoLocation return entries; } - private static string GetCountryName(int country, int l) + private static string GetCountryName(byte country, int l) { if (l < 0) return INVALID; @@ -63,7 +63,7 @@ public static class GeoLocation return INVALID; } - private static string GetRegionName(int country, int region, int l) + private static string GetRegionName(byte country, byte region, int l) { if (l < 0) return INVALID; @@ -93,7 +93,7 @@ public static class GeoLocation /// Language ID /// Country ID /// Country ID string - public static string GetCountryName(string language, int country) => GetCountryName(country, GetLanguageIndex(language)); + public static string GetCountryName(string language, byte country) => GetCountryName(country, GetLanguageIndex(language)); /// /// Gets the Region string for a specified country ID. @@ -102,7 +102,7 @@ public static class GeoLocation /// Country ID /// Region ID /// Region ID string - public static string GetRegionName(string language, int country, int region) => GetRegionName(country, region, GetLanguageIndex(language)); + public static string GetRegionName(string language, byte country, byte region) => GetRegionName(country, region, GetLanguageIndex(language)); /// /// Gets the Country string for a given Country ID @@ -110,7 +110,7 @@ public static class GeoLocation /// Language ID /// Country ID /// Country ID string - public static string GetCountryName(LanguageID language, int country) => GetCountryName(country, GetLanguageIndex(language)); + public static string GetCountryName(LanguageID language, byte country) => GetCountryName(country, GetLanguageIndex(language)); /// /// Gets the Region string for a specified country ID. @@ -119,7 +119,7 @@ public static class GeoLocation /// Country ID /// Region ID /// Region ID string - public static string GetRegionName(LanguageID language, int country, int region) => GetRegionName(country, region, GetLanguageIndex(language)); + public static string GetRegionName(LanguageID language, byte country, byte region) => GetRegionName(country, region, GetLanguageIndex(language)); /// /// Gets Country and Region strings for corresponding IDs and language. @@ -128,7 +128,7 @@ public static class GeoLocation /// Region ID /// Language ID /// Tuple containing country and region - public static (string Country, string Region) GetCountryRegionText(int country, int region, string language) + public static (string Country, string Region) GetCountryRegionText(byte country, byte region, string language) { // Get Language we're fetching for int lang = Array.IndexOf(lang_geo, language); diff --git a/PKHeX.Core/Game/GameStrings/MetDataSource.cs b/PKHeX.Core/Game/GameStrings/MetDataSource.cs index a5fd3bd23..68742b8b3 100644 --- a/PKHeX.Core/Game/GameStrings/MetDataSource.cs +++ b/PKHeX.Core/Game/GameStrings/MetDataSource.cs @@ -184,7 +184,7 @@ public sealed class MetDataSource private static List CreateGen8b(GameStrings s) { - // Manually add invalid (-1) location from SWSH as ID 65535 + // Manually add invalid (-1) location from SW/SH as ID 65535 var locations = new List { new(s.Gen8.Met0[0], Locations.Default8bNone) }; Util.AddCBWithOffset(locations, s.Gen8b.Met6, 60000, Locations.Daycare5); Util.AddCBWithOffset(locations, s.Gen8b.Met3, 30000, Locations.LinkTrade6); diff --git a/PKHeX.Core/Game/Locations/Locations4.cs b/PKHeX.Core/Game/Locations/Locations4.cs index 163540679..afd77116b 100644 --- a/PKHeX.Core/Game/Locations/Locations4.cs +++ b/PKHeX.Core/Game/Locations/Locations4.cs @@ -1,8 +1,10 @@ +using System; + namespace PKHeX.Core; internal static class Locations4 { - internal static readonly byte[] Met0 = + internal static ReadOnlySpan Met0 => new byte[] { 000, 001, 002, 003, 004, 005, 006, 007, 008, 009, 010, 011, 012, 013, 014, 015, 016, 017, 018, 019, diff --git a/PKHeX.Core/Game/Locations/Locations5.cs b/PKHeX.Core/Game/Locations/Locations5.cs index 9a392f89d..0c68abf9e 100644 --- a/PKHeX.Core/Game/Locations/Locations5.cs +++ b/PKHeX.Core/Game/Locations/Locations5.cs @@ -1,8 +1,10 @@ +using System; + namespace PKHeX.Core; internal static class Locations5 { - internal static readonly byte[] Met0 = + internal static ReadOnlySpan Met0 => new byte[] { 001, 002, 004, 005, 006, 007, 008, 009, 010, 011, 012, 013, 014, 015, 016, 017, 018, 019, diff --git a/PKHeX.Core/Game/Locations/Locations7.cs b/PKHeX.Core/Game/Locations/Locations7.cs index b338c7608..c97cc6684 100644 --- a/PKHeX.Core/Game/Locations/Locations7.cs +++ b/PKHeX.Core/Game/Locations/Locations7.cs @@ -1,8 +1,10 @@ +using System; + namespace PKHeX.Core; internal static class Locations7 { - internal static readonly byte[] Met0 = + internal static ReadOnlySpan Met0 => new byte[] { 002, 004, 006, 008, 010, 012, 014, 016, 018, diff --git a/PKHeX.Core/Game/Locations/Locations7b.cs b/PKHeX.Core/Game/Locations/Locations7b.cs index b2a0c078c..657dfb0d6 100644 --- a/PKHeX.Core/Game/Locations/Locations7b.cs +++ b/PKHeX.Core/Game/Locations/Locations7b.cs @@ -1,8 +1,10 @@ +using System; + namespace PKHeX.Core; internal static class Locations7b { - internal static readonly byte[] Met0 = + internal static ReadOnlySpan Met0 => new byte[] { 002, 003, 004, 005, 006, 007, 008, 009, 010, 011, 012, 013, 014, 015, 016, 017, 018, 019, diff --git a/PKHeX.Core/Game/Locations/Locations8.cs b/PKHeX.Core/Game/Locations/Locations8.cs index cde781681..2c9c94ab6 100644 --- a/PKHeX.Core/Game/Locations/Locations8.cs +++ b/PKHeX.Core/Game/Locations/Locations8.cs @@ -1,8 +1,10 @@ +using System; + namespace PKHeX.Core; internal static class Locations8 { - internal static readonly byte[] Met0 = + internal static ReadOnlySpan Met0 => new byte[] { 002, 004, 006, 008, 012, 014, 016, 018, diff --git a/PKHeX.Core/Game/Locations/Locations8a.cs b/PKHeX.Core/Game/Locations/Locations8a.cs index 21c20e41f..71a7164f5 100644 --- a/PKHeX.Core/Game/Locations/Locations8a.cs +++ b/PKHeX.Core/Game/Locations/Locations8a.cs @@ -1,8 +1,10 @@ +using System; + namespace PKHeX.Core; internal static class Locations8a { - internal static readonly byte[] Met0 = + internal static ReadOnlySpan Met0 => new byte[] { 000, 002, 004, 006, 007, 008, 009, 010, 011, 012, 013, 014, 015, 016, 017, 018, 019, diff --git a/PKHeX.Core/Game/Locations/Locations9.cs b/PKHeX.Core/Game/Locations/Locations9.cs index 1daafef28..324224dff 100644 --- a/PKHeX.Core/Game/Locations/Locations9.cs +++ b/PKHeX.Core/Game/Locations/Locations9.cs @@ -1,8 +1,10 @@ +using System; + namespace PKHeX.Core; internal static class Locations9 { - internal static readonly byte[] Met0 = + internal static ReadOnlySpan Met0 => new byte[] { 002, 004, 006, 008, 010, 012, 014, 016, 018, diff --git a/PKHeX.Core/Legality/Areas/EncounterArea.cs b/PKHeX.Core/Legality/Areas/EncounterArea.cs index c6f26acca..4d0ec459e 100644 --- a/PKHeX.Core/Legality/Areas/EncounterArea.cs +++ b/PKHeX.Core/Legality/Areas/EncounterArea.cs @@ -28,5 +28,4 @@ public abstract record EncounterArea(GameVersion Version) : IVersion public virtual bool IsMatchLocation(int location) => Location == location; public bool HasSpecies(ushort species) => Raw.Any(z => z.Species == species); - public IEnumerable GetSpecies(EvoCriteria[] chain) => Raw.Where(z => chain.Any(c => z.Species == c.Species)); } diff --git a/PKHeX.Core/Legality/Areas/EncounterArea1.cs b/PKHeX.Core/Legality/Areas/EncounterArea1.cs index 9b4166b18..6bf725e1d 100644 --- a/PKHeX.Core/Legality/Areas/EncounterArea1.cs +++ b/PKHeX.Core/Legality/Areas/EncounterArea1.cs @@ -12,7 +12,7 @@ public sealed record EncounterArea1 : EncounterArea public readonly int Rate; public readonly EncounterSlot1[] Slots; - protected override IReadOnlyList Raw => Slots; + protected override IReadOnlyList Raw => Slots; public static EncounterArea1[] GetAreas(BinLinkerAccessor input, GameVersion game) { @@ -45,7 +45,7 @@ public sealed record EncounterArea1 : EncounterArea Slots = slots; } - public override IEnumerable GetMatchingSlots(PKM pk, EvoCriteria[] chain) + public override IEnumerable GetMatchingSlots(PKM pk, EvoCriteria[] chain) { (bool useCatchRate, byte rate) = pk is PK1 pk1 ? (true, pk1.Catch_Rate) : (false, (byte)0); foreach (var slot in Slots) diff --git a/PKHeX.Core/Legality/Areas/EncounterArea2.cs b/PKHeX.Core/Legality/Areas/EncounterArea2.cs index 0ce557fbc..54389267e 100644 --- a/PKHeX.Core/Legality/Areas/EncounterArea2.cs +++ b/PKHeX.Core/Legality/Areas/EncounterArea2.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; namespace PKHeX.Core; @@ -9,16 +9,16 @@ namespace PKHeX.Core; /// public sealed record EncounterArea2 : EncounterArea { - private static readonly byte[] BCC_SlotRates = { 20, 20, 10, 10, 05, 05, 10, 10, 05, 05 }; - private static readonly byte[] RatesGrass = { 30, 30, 20, 10, 5, 4, 1 }; - private static readonly byte[] RatesSurf = { 60, 30, 10 }; + private static ReadOnlySpan BCC_SlotRates => new byte[] { 20, 20, 10, 10, 05, 05, 10, 10, 05, 05 }; + private static ReadOnlySpan RatesGrass => new byte[] { 30, 30, 20, 10, 5, 4, 1 }; + private static ReadOnlySpan RatesSurf => new byte[] { 60, 30, 10 }; internal readonly EncounterTime Time; public readonly byte Rate; - public readonly IReadOnlyList Rates; + public readonly byte[]? Rates; public readonly EncounterSlot2[] Slots; - protected override IReadOnlyList Raw => Slots; + protected override IReadOnlyList Raw => Slots; public static EncounterArea2[] GetAreas(BinLinkerAccessor input, GameVersion game) { @@ -47,12 +47,7 @@ public sealed record EncounterArea2 : EncounterArea { const int size = 4; int count = next.Length / size; - Rates = type switch - { - SlotType.BugContest => BCC_SlotRates, - SlotType.Grass => RatesGrass, - _ => RatesSurf, - }; + Rates = null; // fetch as needed. Slots = ReadSlots(next, count); } } @@ -73,13 +68,13 @@ public sealed record EncounterArea2 : EncounterArea return slots; } - public override IEnumerable GetMatchingSlots(PKM pk, EvoCriteria[] chain) + public override IEnumerable GetMatchingSlots(PKM pk, EvoCriteria[] chain) { if (pk is not ICaughtData2 {CaughtData: not 0} pk2) return GetSlotsFuzzy(chain); if (pk2.Met_Location != Location) - return Array.Empty(); + return Array.Empty(); return GetSlotsSpecificLevelTime(chain, pk2.Met_TimeOfDay, pk2.Met_Level); } diff --git a/PKHeX.Core/Legality/Areas/EncounterArea3.cs b/PKHeX.Core/Legality/Areas/EncounterArea3.cs index 43940c27f..5ca3baab8 100644 --- a/PKHeX.Core/Legality/Areas/EncounterArea3.cs +++ b/PKHeX.Core/Legality/Areas/EncounterArea3.cs @@ -13,7 +13,7 @@ public sealed record EncounterArea3 : EncounterArea public readonly int Rate; public readonly EncounterSlot3[] Slots; - protected override IReadOnlyList Raw => Slots; + protected override IReadOnlyList Raw => Slots; public static EncounterArea3[] GetAreas(BinLinkerAccessor input, GameVersion game) { @@ -112,12 +112,12 @@ public sealed record EncounterArea3 : EncounterArea return new EncounterSlot3Swarm(this, species, min, max, slotNum, moves); } - public override IEnumerable GetMatchingSlots(PKM pk, EvoCriteria[] chain) + public override IEnumerable GetMatchingSlots(PKM pk, EvoCriteria[] chain) { if (pk.Format != 3) // Met Location and Met Level are changed on PK3->PK4 return GetSlotsFuzzy(chain); if (pk.Met_Location != Location) - return Array.Empty(); + return Array.Empty(); return GetSlotsMatching(chain, pk.Met_Level); } diff --git a/PKHeX.Core/Legality/Areas/EncounterArea3XD.cs b/PKHeX.Core/Legality/Areas/EncounterArea3XD.cs index 65c2768be..e0b8f7058 100644 --- a/PKHeX.Core/Legality/Areas/EncounterArea3XD.cs +++ b/PKHeX.Core/Legality/Areas/EncounterArea3XD.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; namespace PKHeX.Core; @@ -11,7 +11,7 @@ public sealed record EncounterArea3XD : EncounterArea { public readonly EncounterSlot3PokeSpot[] Slots; - protected override IReadOnlyList Raw => Slots; + protected override IReadOnlyList Raw => Slots; public EncounterArea3XD(int loc, ushort s0, byte l0, ushort s1, byte l1, ushort s2, byte l2) : base(GameVersion.XD) { @@ -25,7 +25,7 @@ public sealed record EncounterArea3XD : EncounterArea }; } - public override IEnumerable GetMatchingSlots(PKM pk, EvoCriteria[] chain) + public override IEnumerable GetMatchingSlots(PKM pk, EvoCriteria[] chain) { if (pk.Format != 3) // Met Location and Met Level are changed on PK3->PK4 return GetSlotsFuzzy(chain); diff --git a/PKHeX.Core/Legality/Areas/EncounterArea4.cs b/PKHeX.Core/Legality/Areas/EncounterArea4.cs index b07560616..3465ec5d3 100644 --- a/PKHeX.Core/Legality/Areas/EncounterArea4.cs +++ b/PKHeX.Core/Legality/Areas/EncounterArea4.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using static System.Buffers.Binary.BinaryPrimitives; @@ -14,7 +14,7 @@ public sealed record EncounterArea4 : EncounterArea public readonly GroundTileAllowed GroundTile; public readonly EncounterSlot4[] Slots; - protected override IReadOnlyList Raw => Slots; + protected override IReadOnlyList Raw => Slots; public static EncounterArea4[] GetAreas(BinLinkerAccessor input, GameVersion game) { @@ -64,7 +64,7 @@ public sealed record EncounterArea4 : EncounterArea return new EncounterSlot4(this, species, form, min, max, slotNum, mpi, mpc, sti, stc); } - public override IEnumerable GetMatchingSlots(PKM pk, EvoCriteria[] chain) + public override IEnumerable GetMatchingSlots(PKM pk, EvoCriteria[] chain) { if (pk.Format != 4) // Met Location and Met Level are changed on PK4->PK5 return GetSlotsFuzzy(chain); @@ -103,21 +103,21 @@ public sealed record EncounterArea4 : EncounterArea private static bool IsInaccessibleHoneySlotLocation(EncounterSlot4 slot, PKM pk) { // A/B/C tables, only Munchlax is a 'C' encounter, and A/B are accessible from any tree. - // C table encounters are only available from 4 trees, which are determined by TID/SID of the save file. + // C table encounters are only available from 4 trees, which are determined by TID16/SID16 of the save file. if (slot.Species is not (int)Species.Munchlax) return false; // We didn't encode the honey tree index to the encounter slot resource. // Check if any of the slot's location doesn't match any of the groupC trees' area location ID. var location = pk.Met_Location; - var trees = SAV4Sinnoh.CalculateMunchlaxTrees(pk.TID, pk.SID); + var trees = SAV4Sinnoh.CalculateMunchlaxTrees(pk.TID16, pk.SID16); return LocationID_HoneyTree[trees.Tree1] != location && LocationID_HoneyTree[trees.Tree2] != location && LocationID_HoneyTree[trees.Tree3] != location && LocationID_HoneyTree[trees.Tree4] != location; } - private static readonly byte[] LocationID_HoneyTree = + private static ReadOnlySpan LocationID_HoneyTree => new byte[] { 20, // 00 Route 205 Floaroma 20, // 01 Route 205 Eterna diff --git a/PKHeX.Core/Legality/Areas/EncounterArea5.cs b/PKHeX.Core/Legality/Areas/EncounterArea5.cs index 91c172936..bd6e9b227 100644 --- a/PKHeX.Core/Legality/Areas/EncounterArea5.cs +++ b/PKHeX.Core/Legality/Areas/EncounterArea5.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using static System.Buffers.Binary.BinaryPrimitives; @@ -12,7 +12,7 @@ public sealed record EncounterArea5 : EncounterArea { public readonly EncounterSlot5[] Slots; - protected override IReadOnlyList Raw => Slots; + protected override IReadOnlyList Raw => Slots; public static EncounterArea5[] GetAreas(BinLinkerAccessor input, GameVersion game) { @@ -55,7 +55,7 @@ public sealed record EncounterArea5 : EncounterArea return new EncounterSlot5(this, species, form, min, max); } - public override IEnumerable GetMatchingSlots(PKM pk, EvoCriteria[] chain) + public override IEnumerable GetMatchingSlots(PKM pk, EvoCriteria[] chain) { foreach (var slot in Slots) { diff --git a/PKHeX.Core/Legality/Areas/EncounterArea6AO.cs b/PKHeX.Core/Legality/Areas/EncounterArea6AO.cs index 4345b6a10..58074b04f 100644 --- a/PKHeX.Core/Legality/Areas/EncounterArea6AO.cs +++ b/PKHeX.Core/Legality/Areas/EncounterArea6AO.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using static System.Buffers.Binary.BinaryPrimitives; @@ -12,7 +12,7 @@ public sealed record EncounterArea6AO : EncounterArea { public readonly EncounterSlot6AO[] Slots; - protected override IReadOnlyList Raw => Slots; + protected override IReadOnlyList Raw => Slots; public static EncounterArea6AO[] GetAreas(BinLinkerAccessor input, GameVersion game) { @@ -59,7 +59,7 @@ public sealed record EncounterArea6AO : EncounterArea private const int FluteBoostMax = 4; // Black Flute increases levels. private const int DexNavBoost = 30; // Maximum DexNav chain - public override IEnumerable GetMatchingSlots(PKM pk, EvoCriteria[] chain) + public override IEnumerable GetMatchingSlots(PKM pk, EvoCriteria[] chain) { foreach (var slot in Slots) { diff --git a/PKHeX.Core/Legality/Areas/EncounterArea6XY.cs b/PKHeX.Core/Legality/Areas/EncounterArea6XY.cs index f8271bfb8..2ac7fac3b 100644 --- a/PKHeX.Core/Legality/Areas/EncounterArea6XY.cs +++ b/PKHeX.Core/Legality/Areas/EncounterArea6XY.cs @@ -12,7 +12,7 @@ public sealed record EncounterArea6XY : EncounterArea { public readonly EncounterSlot6XY[] Slots; - protected override IReadOnlyList Raw => Slots; + protected override IReadOnlyList Raw => Slots; public static EncounterArea6XY[] GetAreas(BinLinkerAccessor input, GameVersion game, EncounterArea6XY safari) { @@ -104,7 +104,7 @@ public sealed record EncounterArea6XY : EncounterArea return slots; } - public override IEnumerable GetMatchingSlots(PKM pk, EvoCriteria[] chain) + public override IEnumerable GetMatchingSlots(PKM pk, EvoCriteria[] chain) { foreach (var slot in Slots) { @@ -116,7 +116,7 @@ public sealed record EncounterArea6XY : EncounterArea if (!slot.IsLevelWithinRange(pk.Met_Level)) break; - if (slot.Form != evo.Form && !slot.IsRandomUnspecificForm && slot.Species is not ((int)Species.Burmy or (int)Species.Furfrou)) + if (slot.Form != evo.Form && slot is { IsRandomUnspecificForm: false, Species: not ((int)Species.Burmy or (int)Species.Furfrou) }) { // Only slot that can be form-mismatched via Pressure is Flabébé if (slot.Species != (int)Species.Flabébé) diff --git a/PKHeX.Core/Legality/Areas/EncounterArea7.cs b/PKHeX.Core/Legality/Areas/EncounterArea7.cs index 731c4ed90..d29660315 100644 --- a/PKHeX.Core/Legality/Areas/EncounterArea7.cs +++ b/PKHeX.Core/Legality/Areas/EncounterArea7.cs @@ -12,7 +12,7 @@ public sealed record EncounterArea7 : EncounterArea { public readonly EncounterSlot7[] Slots; - protected override IReadOnlyList Raw => Slots; + protected override IReadOnlyList Raw => Slots; public static EncounterArea7[] GetAreas(BinLinkerAccessor input, GameVersion game) { @@ -55,7 +55,7 @@ public sealed record EncounterArea7 : EncounterArea return new EncounterSlot7(this, species, form, min, max); } - public override IEnumerable GetMatchingSlots(PKM pk, EvoCriteria[] chain) + public override IEnumerable GetMatchingSlots(PKM pk, EvoCriteria[] chain) { foreach (var slot in Slots) { diff --git a/PKHeX.Core/Legality/Areas/EncounterArea7b.cs b/PKHeX.Core/Legality/Areas/EncounterArea7b.cs index 742e3377d..ea672455a 100644 --- a/PKHeX.Core/Legality/Areas/EncounterArea7b.cs +++ b/PKHeX.Core/Legality/Areas/EncounterArea7b.cs @@ -12,7 +12,7 @@ public sealed record EncounterArea7b : EncounterArea { public readonly EncounterSlot7b[] Slots; - protected override IReadOnlyList Raw => Slots; + protected override IReadOnlyList Raw => Slots; public static EncounterArea7b[] GetAreas(BinLinkerAccessor input, GameVersion game) { @@ -54,7 +54,7 @@ public sealed record EncounterArea7b : EncounterArea private const int CatchComboBonus = 1; - public override IEnumerable GetMatchingSlots(PKM pk, EvoCriteria[] chain) + public override IEnumerable GetMatchingSlots(PKM pk, EvoCriteria[] chain) { foreach (var slot in Slots) { diff --git a/PKHeX.Core/Legality/Areas/EncounterArea7g.cs b/PKHeX.Core/Legality/Areas/EncounterArea7g.cs index e46266a58..09c72c6ad 100644 --- a/PKHeX.Core/Legality/Areas/EncounterArea7g.cs +++ b/PKHeX.Core/Legality/Areas/EncounterArea7g.cs @@ -17,7 +17,7 @@ public sealed record EncounterArea7g : EncounterArea, ISpeciesForm public byte Form { get; } public readonly EncounterSlot7GO[] Slots; - protected override IReadOnlyList Raw => Slots; + protected override IReadOnlyList Raw => Slots; private EncounterArea7g(ushort species, byte form, EncounterSlot7GO[] slots) : base(GameVersion.GO) { @@ -68,17 +68,22 @@ public sealed record EncounterArea7g : EncounterArea, ISpeciesForm return new EncounterSlot7GO(area, species, form, start, end, shiny, gender, type); } - public override IEnumerable GetMatchingSlots(PKM pk, EvoCriteria[] chain) + public override IEnumerable GetMatchingSlots(PKM pk, EvoCriteria[] chain) { // Find the first chain that has slots defined. // Since it is possible to evolve before transferring, we only need the highest evolution species possible. // PoGoEncTool has already extrapolated the evolutions to separate encounters! var sf = Array.Find(chain, z => z.Species == Species && z.Form == Form); if (sf == default) - yield break; + return Array.Empty(); + return GetMatchingSlots(pk, sf); + } + + public IEnumerable GetMatchingSlots(PKM pk, EvoCriteria evo) + { var stamp = EncounterSlotGO.GetTimeStamp(pk.Met_Year + 2000, pk.Met_Month, pk.Met_Day); - var met = Math.Max(sf.LevelMin, pk.Met_Level); + var met = Math.Max(evo.LevelMin, pk.Met_Level); EncounterSlot7GO? deferredIV = null; foreach (var slot in Slots) diff --git a/PKHeX.Core/Legality/Areas/EncounterArea8.cs b/PKHeX.Core/Legality/Areas/EncounterArea8.cs index 2bfb3ad21..166806b5e 100644 --- a/PKHeX.Core/Legality/Areas/EncounterArea8.cs +++ b/PKHeX.Core/Legality/Areas/EncounterArea8.cs @@ -14,7 +14,7 @@ public sealed record EncounterArea8 : EncounterArea { public readonly EncounterSlot8[] Slots; - protected override IReadOnlyList Raw => Slots; + protected override IReadOnlyList Raw => Slots; /// /// Slots from this area can cross over to another area, resulting in a different met location. /// @@ -39,7 +39,7 @@ public sealed record EncounterArea8 : EncounterArea return Array.IndexOf(others, (byte)location) != -1; } - public override IEnumerable GetMatchingSlots(PKM pk, EvoCriteria[] chain) + public override IEnumerable GetMatchingSlots(PKM pk, EvoCriteria[] chain) { var metLocation = pk.Met_Location; // wild area gets boosted up to level 60 post-game @@ -109,6 +109,9 @@ public sealed record EncounterArea8 : EncounterArea return true; } + /// + /// Post-game boosts all levels to a minimum of 60. + /// public const int BoostLevel = 60; public static bool IsWildArea(int location) => IsWildArea8(location) || IsWildArea8Armor(location) || IsWildArea8Crown(location); diff --git a/PKHeX.Core/Legality/Areas/EncounterArea8a.cs b/PKHeX.Core/Legality/Areas/EncounterArea8a.cs index 00b4c1ac3..3801a1bf3 100644 --- a/PKHeX.Core/Legality/Areas/EncounterArea8a.cs +++ b/PKHeX.Core/Legality/Areas/EncounterArea8a.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using static System.Buffers.Binary.BinaryPrimitives; @@ -13,14 +13,14 @@ public sealed record EncounterArea8a : EncounterArea public readonly EncounterSlot8a[] Slots; private readonly byte[] Locations; - protected override IReadOnlyList Raw => Slots; + protected override IReadOnlyList Raw => Slots; public override bool IsMatchLocation(int location) { return Array.IndexOf(Locations, (byte)location) != -1; } - public override IEnumerable GetMatchingSlots(PKM pk, EvoCriteria[] chain) => GetMatches(chain, pk.Met_Level); + public override IEnumerable GetMatchingSlots(PKM pk, EvoCriteria[] chain) => GetMatches(chain, pk.Met_Level); private IEnumerable GetMatches(EvoCriteria[] chain, int metLevel) { diff --git a/PKHeX.Core/Legality/Areas/EncounterArea8b.cs b/PKHeX.Core/Legality/Areas/EncounterArea8b.cs index b2fd141fa..b952bcf19 100644 --- a/PKHeX.Core/Legality/Areas/EncounterArea8b.cs +++ b/PKHeX.Core/Legality/Areas/EncounterArea8b.cs @@ -12,7 +12,7 @@ public sealed record EncounterArea8b : EncounterArea { public readonly EncounterSlot8b[] Slots; - protected override IReadOnlyList Raw => Slots; + protected override IReadOnlyList Raw => Slots; public static EncounterArea8b[] GetAreas(BinLinkerAccessor input, GameVersion game) { @@ -81,7 +81,7 @@ public sealed record EncounterArea8b : EncounterArea return false; } - public override IEnumerable GetMatchingSlots(PKM pk, EvoCriteria[] chain) + public override IEnumerable GetMatchingSlots(PKM pk, EvoCriteria[] chain) { foreach (var slot in Slots) { @@ -107,14 +107,14 @@ public sealed record EncounterArea8b : EncounterArea private static bool IsInaccessibleHoneySlotLocation(EncounterSlot8b slot, PKM pk) { // A/B/C tables, only Munchlax is a 'C' encounter, and A/B are accessible from any tree. - // C table encounters are only available from 4 trees, which are determined by TID/SID of the save file. + // C table encounters are only available from 4 trees, which are determined by TID16/SID16 of the save file. if (slot.Species is not (int)Species.Munchlax) return false; // We didn't encode the honey tree index to the encounter slot resource. // Check if any of the slot's location doesn't match any of the groupC trees' area location ID. var location = pk.Met_Location; - var trees = SAV4Sinnoh.CalculateMunchlaxTrees(pk.TID, pk.SID); + var trees = SAV4Sinnoh.CalculateMunchlaxTrees(pk.TID16, pk.SID16); return LocationID_HoneyTree[trees.Tree1] != location && LocationID_HoneyTree[trees.Tree2] != location && LocationID_HoneyTree[trees.Tree3] != location diff --git a/PKHeX.Core/Legality/Areas/EncounterArea8g.cs b/PKHeX.Core/Legality/Areas/EncounterArea8g.cs index 261ca1b51..b23a833b0 100644 --- a/PKHeX.Core/Legality/Areas/EncounterArea8g.cs +++ b/PKHeX.Core/Legality/Areas/EncounterArea8g.cs @@ -17,7 +17,7 @@ public sealed record EncounterArea8g : EncounterArea, ISpeciesForm public byte Form { get; } public readonly EncounterSlot8GO[] Slots; - protected override IReadOnlyList Raw => Slots; + protected override IReadOnlyList Raw => Slots; private EncounterArea8g(ushort species, byte form, EncounterSlot8GO[] slots) : base(GameVersion.GO) { @@ -68,21 +68,23 @@ public sealed record EncounterArea8g : EncounterArea, ISpeciesForm return new EncounterSlot8GO(area, species, form, start, end, shiny, gender, type, format); } - public override IEnumerable GetMatchingSlots(PKM pk, EvoCriteria[] chain) + public override IEnumerable GetMatchingSlots(PKM pk, EvoCriteria[] chain) { - if (pk.TSV == 0) // HOME doesn't assign TSV=0 to accounts. - yield break; - // Find the first chain that has slots defined. // Since it is possible to evolve before transferring, we only need the highest evolution species possible. // PoGoEncTool has already extrapolated the evolutions to separate encounters! var sf = FindCriteriaToIterate(pk, chain); if (sf == default) - yield break; + return Array.Empty(); + return GetMatchingSlots(pk, sf); + } + + public IEnumerable GetMatchingSlots(PKM pk, EvoCriteria evo) + { var species = pk.Species; var ball = (Ball)pk.Ball; - var met = Math.Max(sf.LevelMin, pk.Met_Level); + var met = Math.Max(evo.LevelMin, pk.Met_Level); EncounterSlot8GO? deferredIV = null; foreach (var slot in Slots) diff --git a/PKHeX.Core/Legality/Areas/EncounterArea9.cs b/PKHeX.Core/Legality/Areas/EncounterArea9.cs index bb1afded3..2742add6e 100644 --- a/PKHeX.Core/Legality/Areas/EncounterArea9.cs +++ b/PKHeX.Core/Legality/Areas/EncounterArea9.cs @@ -6,15 +6,15 @@ namespace PKHeX.Core; /// /// -/// encounter area +/// encounter area /// public sealed record EncounterArea9 : EncounterArea { public readonly EncounterSlot9[] Slots; - public ushort CrossFrom { get; init; } + public ushort CrossFrom { get; } - protected override IReadOnlyList Raw => Slots; + protected override IReadOnlyList Raw => Slots; public static EncounterArea9[] GetAreas(BinLinkerAccessor input, GameVersion game) { @@ -51,7 +51,7 @@ public sealed record EncounterArea9 : EncounterArea return result; } - public override IEnumerable GetMatchingSlots(PKM pk, EvoCriteria[] chain) + public override IEnumerable GetMatchingSlots(PKM pk, EvoCriteria[] chain) { var lvl = pk.Met_Level; foreach (var slot in Slots) diff --git a/PKHeX.Core/Legality/BinLinkerAccessor.cs b/PKHeX.Core/Legality/BinLinkerAccessor.cs index b98f7fde8..398e91892 100644 --- a/PKHeX.Core/Legality/BinLinkerAccessor.cs +++ b/PKHeX.Core/Legality/BinLinkerAccessor.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Diagnostics; using static System.Buffers.Binary.BinaryPrimitives; @@ -42,11 +42,14 @@ public readonly ref struct BinLinkerAccessor /// Expected identifier (debug verification only) public static BinLinkerAccessor Get(ReadOnlySpan data, string identifier) { - var result = new BinLinkerAccessor(data); -#if DEBUG + SanityCheckIdentifier(data, identifier); + return new BinLinkerAccessor(data); + } + + [Conditional("DEBUG")] + private static void SanityCheckIdentifier(ReadOnlySpan data, string identifier) + { Debug.Assert(data.Length > 4); Debug.Assert(identifier[0] == data[0] && identifier[1] == data[1]); -#endif - return result; } } diff --git a/PKHeX.Core/Legality/Breeding.cs b/PKHeX.Core/Legality/Breeding.cs index 3e3df64d1..36ad4990c 100644 --- a/PKHeX.Core/Legality/Breeding.cs +++ b/PKHeX.Core/Legality/Breeding.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using static PKHeX.Core.GameVersion; using static PKHeX.Core.Species; @@ -54,7 +53,7 @@ public static class Breeding if (Legal.FixedGenderFromBiGender.Contains(species)) // Nincada -> Shedinja loses gender causing 'false', edge case return true; var pi = PKX.Personal[species]; - if (!pi.Genderless && !pi.OnlyMale) + if (pi is { Genderless: false, OnlyMale: false }) return true; if (MixedGenderBreeding.Contains(species)) return true; @@ -64,7 +63,7 @@ public static class Breeding private static readonly HashSet SplitBreed_3 = new() { // Incense - (int)Marill, (int)Azumarill, + (int)Marill, (int)Wobbuffet, }; @@ -74,21 +73,21 @@ public static class Breeding private static readonly HashSet SplitBreed = new(SplitBreed_3) { // Incense - (int)Chansey, (int)Blissey, - (int)MrMime, (int)MrRime, + (int)Chansey, + (int)MrMime, (int)Snorlax, (int)Sudowoodo, (int)Mantine, - (int)Roselia, (int)Roserade, + (int)Roselia, (int)Chimecho, }; - internal static ICollection GetSplitBreedGeneration(int generation) => generation switch + internal static IReadOnlySet? GetSplitBreedGeneration(int generation) => generation switch { 3 => SplitBreed_3, 4 or 5 or 6 or 7 or 8 => SplitBreed, // Gen9 does not have split-breed egg generation. - _ => Array.Empty(), + _ => null, }; /// @@ -99,7 +98,7 @@ public static class Breeding public static bool CanHatchAsEgg(ushort species) => !NoHatchFromEgg.Contains(species); /// - /// Checks if the - can exist as a hatched egg in the requested . + /// Checks if the - can exist as a hatched egg in the requested . /// /// Chained with the other 2 overloads for incremental checks with different parameters. /// Current species @@ -120,7 +119,7 @@ public static class Breeding } /// - /// Some species can have forms that cannot exist as egg (event/special forms). Same idea as + /// Some species can have forms that cannot exist as egg (event/special forms). Same idea as /// /// True if can be bred. private static bool IsBreedableForm(ushort species, byte form) => species switch @@ -132,25 +131,6 @@ public static class Breeding _ => true, }; - /// - /// Checks if the - can exist as a hatched egg in the requested . - /// - /// Chained with the other 2 overloads for incremental checks with different parameters. - /// Current species - /// Current form - /// Game of origin - public static bool CanHatchAsEgg(ushort species, byte form, GameVersion game) - { - // If form cannot change, then it must be able to originate in the game. - var pt = GameData.GetPersonal(game); - if (pt.IsPresentInGame(species, form)) - return true; - - // Only way it can not exist is if it can change form. - // The only species that can do this is D/P Rotom, being changed in a future game. - return species is (int)Rotom && form <= 5 && game is D or P; - } - /// /// Species that cannot hatch from an egg. /// diff --git a/PKHeX.Core/Legality/BulkAnalysis.cs b/PKHeX.Core/Legality/BulkAnalysis.cs index c13e040b6..589fff0a9 100644 --- a/PKHeX.Core/Legality/BulkAnalysis.cs +++ b/PKHeX.Core/Legality/BulkAnalysis.cs @@ -99,7 +99,7 @@ public sealed class BulkAnalysis { var tracker = home.Tracker; if (Trackers.TryGetValue(tracker, out var clone)) - AddLine(cs, clone!, "Clone detected (Duplicate Tracker).", Encounter); + AddLine(cs, clone, "Clone detected (Duplicate Tracker).", Encounter); else Trackers.Add(tracker, cs); } @@ -118,7 +118,7 @@ public sealed class BulkAnalysis } CloneFlags[i] = true; - AddLine(ps!, cs, "Clone detected (Details).", Encounter); + AddLine(ps, cs, "Clone detected (Details).", Encounter); } } @@ -135,7 +135,7 @@ public sealed class BulkAnalysis foreach (var dupe in dupes) { - var tidGroup = dupe.GroupBy(z => z.Slot.Entity.TID | (z.Slot.Entity.SID << 16)) + var tidGroup = dupe.GroupBy(z => z.Slot.Entity.TID16 | (z.Slot.Entity.SID16 << 16)) .Select(z => z.ToList()) .Where(z => z.Count >= 2).ToList(); if (tidGroup.Count == 0) @@ -160,7 +160,7 @@ public sealed class BulkAnalysis var id = cp.Entity.EncryptionConstant; var cr = new CombinedReference(cp, ca); - if (!dict.TryGetValue(id, out var pa) || pa is null) + if (!dict.TryGetValue(id, out var pa)) { dict.Add(id, cr); continue; @@ -182,7 +182,7 @@ public sealed class BulkAnalysis var id = g345 ? cp.Entity.EncryptionConstant : cp.Entity.PID; var cr = new CombinedReference(cp, ca); - if (!dict.TryGetValue(id, out var pr) || pr is null) + if (!dict.TryGetValue(id, out var pr)) { dict.Add(id, cr); continue; @@ -203,8 +203,6 @@ public sealed class BulkAnalysis var withOT = tr.IsFromTrainer(pk); var flag = pk.CurrentHandler; var expect = withOT ? 0 : 1; - if (pk.Version == 0) - expect = 0; if (flag != expect) AddLine(cs, LegalityCheckStrings.LTransferCurrentHandlerInvalid, CheckIdentifier.Trainer); @@ -222,17 +220,16 @@ public sealed class BulkAnalysis private void CheckIDReuse() { - var dict = new Dictionary(); + var dict = new Dictionary(); for (int i = 0; i < AllData.Count; i++) { if (CloneFlags[i]) continue; // already flagged var cs = AllData[i]; var ca = AllAnalysis[i]; - var id = cs.Entity.TID + (cs.Entity.SID << 16); - Debug.Assert(cs.Entity.TID <= ushort.MaxValue); + var id = cs.Entity.ID32; - if (!dict.TryGetValue(id, out var pr) || pr is null) + if (!dict.TryGetValue(id, out var pr)) { var r = new CombinedReference(cs, ca); dict.Add(id, r); @@ -241,7 +238,7 @@ public sealed class BulkAnalysis var pa = pr.Analysis; // ignore GB era collisions - // a 16bit TID can reasonably occur for multiple trainers, and versions + // a 16bit TID16 can reasonably occur for multiple trainers, and versions if (ca.Info.Generation <= 2 && pa.Info.Generation <= 2) continue; @@ -334,19 +331,19 @@ public sealed class BulkAnalysis var pp = ps.Entity; var cp = cs.Entity; - // 32bit ID-SID should only occur for one generation - // Trainer-ID-SID should only occur for one version + // 32bit ID-SID16 should only occur for one generation + // Trainer-ID-SID16 should only occur for one version if (IsSharedVersion(pp, pa, cp, ca)) { - AddLine(ps, cs, "TID sharing across versions detected.", ident); + AddLine(ps, cs, "TID16 sharing across versions detected.", ident); return true; } - // ID-SID should only occur for one Trainer name + // ID-SID16 should only occur for one Trainer name if (pp.OT_Name != cp.OT_Name) { var severity = ca.Info.Generation == 4 ? Severity.Fishy : Severity.Invalid; - AddLine(ps, cs, "TID sharing across different trainer names detected.", ident, severity); + AddLine(ps, cs, "TID16 sharing across different trainer names detected.", ident, severity); } return false; @@ -362,7 +359,7 @@ public sealed class BulkAnalysis return false; // Gen3/4 traded eggs do not have an Egg Location, and do not update the Version upon hatch. - // These eggs can obtain another trainer's TID/SID/OT and be valid with a different version ID. + // These eggs can obtain another trainer's TID16/SID16/OT and be valid with a different version ID. if (pa.EncounterMatch.EggEncounter && IsTradedEggVersionNoUpdate(pp, pa)) return false; // version doesn't update on trade if (ca.EncounterMatch.EggEncounter && IsTradedEggVersionNoUpdate(cp, ca)) diff --git a/PKHeX.Core/Legality/Core.cs b/PKHeX.Core/Legality/Core.cs index 798f08e9c..ed8aac562 100644 --- a/PKHeX.Core/Legality/Core.cs +++ b/PKHeX.Core/Legality/Core.cs @@ -63,15 +63,6 @@ public static partial class Legal internal static readonly ushort[][] ReminderSV = EggMoves9.GetArray(Get(Util.GetBinaryResource("reminder_sv.pkl"), "sv")); internal static readonly Learnset[] LevelUpSV = LearnsetReader.GetArray(Get(Util.GetBinaryResource("lvlmove_sv.pkl"), "sv")); - internal static int GetMaxSpeciesOrigin(PKM pk) - { - if (pk.Format == 1) - return MaxSpeciesID_1; - if (pk.Format == 2 || pk.VC) - return MaxSpeciesID_2; - return GetMaxSpeciesOrigin(pk.Generation); - } - internal static int GetMaxSpeciesOrigin(int generation) => generation switch { 1 => MaxSpeciesID_1, @@ -110,7 +101,7 @@ public static partial class Legal PA8 pa8 => !pa8.LA, PB8 pb8 => !pb8.BDSP, PK8 pk8 => pk8.IsSideTransfer || pk8.BattleVersion != 0, - PK9 pk9 => !(pk9.SV || (pk9.IsEgg && pk9.Version == 0)), + PK9 pk9 => !(pk9.SV || pk9 is { IsEgg: true, Version: 0 }), _ => false, }; @@ -149,7 +140,7 @@ public static partial class Legal _ => generation >= 6 ? 12 : 10, }; - public static bool GetIsFixedIVSequenceValidSkipRand(ReadOnlySpan IVs, PKM pk, int max = 31) + public static bool GetIsFixedIVSequenceValidSkipRand(ReadOnlySpan IVs, PKM pk, uint max = 31) { for (int i = 0; i < 6; i++) { @@ -183,11 +174,4 @@ public static partial class Legal if (IVs.SPD != pk.IV_SPD) return false; return true; } - - public static bool IsMetAsEgg(PKM pk) => pk switch - { - PA8 or PK8 => pk.Egg_Location is not 0 || (pk.BDSP && pk.Egg_Day is not 0), - PB8 pb8 => pb8.Egg_Location is not Locations.Default8bNone, - _ => pk.Egg_Location is not 0, - }; } diff --git a/PKHeX.Core/Legality/Encounters/Data/EncounterEvent.cs b/PKHeX.Core/Legality/Encounters/Data/EncounterEvent.cs index 4968fa0a9..58db1c776 100644 --- a/PKHeX.Core/Legality/Encounters/Data/EncounterEvent.cs +++ b/PKHeX.Core/Legality/Encounters/Data/EncounterEvent.cs @@ -120,7 +120,7 @@ public static class EncounterEvent // rather than use Linq to build an array, just do it the quick way directly. var result = new T[arr.Count]; - ((HashSet)arr).CopyTo(result, 0); + ((IReadOnlySet)arr).CopyTo(result); return result; } @@ -166,7 +166,7 @@ public static class EncounterEvent MGDB_G8B, MGDB_G9, }.SelectMany(z => z); - regular = regular.Where(mg => !mg.IsItem && mg.IsEntity && mg.Species > 0); + regular = regular.Where(mg => mg is { IsItem: false, IsEntity: true, Species: > 0 }); var result = MGDB_G3.Concat(regular); if (sorted) result = result.OrderBy(mg => mg.Species); diff --git a/PKHeX.Core/Legality/Encounters/Data/Encounters9.cs b/PKHeX.Core/Legality/Encounters/Data/Encounters9.cs index 969417de5..e359e2cb9 100644 --- a/PKHeX.Core/Legality/Encounters/Data/Encounters9.cs +++ b/PKHeX.Core/Legality/Encounters/Data/Encounters9.cs @@ -24,10 +24,6 @@ internal static class Encounters9 new(SV) { Gift = true, Species = 909, Shiny = Never, Level = 05, Location = 080, Ability = OnlyFirst, Size = 128 }, // Fuecoco new(SV) { Gift = true, Species = 912, Shiny = Never, Level = 05, Location = 080, Ability = OnlyFirst, Size = 128 }, // Quaxly - // Box Legendary (Ride Form) - new(SL) { Gift = true, Species = 998, Shiny = Never, Level = 68, Location = 070, Ability = OnlyFirst, Size = 128, Nature = Nature.Quirky, TeraType = GemType.Dragon, IVs = new(31,31,28,31,31,28), Moves = new(053,878,203,851) }, // Koraidon - new(VL) { Gift = true, Species = 999, Shiny = Never, Level = 68, Location = 070, Ability = OnlyFirst, Size = 128, Nature = Nature.Quirky, TeraType = GemType.Dragon, IVs = new(31,31,28,31,31,28), Moves = new(408,879,203,851) }, // Miraidon - // Galarian Meowth from Salvatore (Specific Met Location depending on game, inside Academy's Staff Quarters) new(SL) { Gift = true, Species = 052, Shiny = Never, Level = 05, Location = 130, Form = 2, FlawlessIVCount = 3 }, // Meowth-2 new(VL) { Gift = true, Species = 052, Shiny = Never, Level = 05, Location = 131, Form = 2, FlawlessIVCount = 3 }, // Meowth-2 @@ -36,47 +32,51 @@ internal static class Encounters9 new (SV) { Gift = true, Species = 734, Level = 02, Location = 064 }, // Yungoos level 2, no Marks in Inlet Grotto. Only Poké Ball available in early game. // Box Legendary (Battle Form) - new(SL) { Species = 998, Shiny = Never, Level = 72, Location = 124, Size = 128, Ability = OnlyFirst, Nature = Nature.Adamant, TeraType = GemType.Fighting, IVs = new(25,31,25,31,31,25), Moves = new(416,339,878,053) }, // Koraidon - new(VL) { Species = 999, Shiny = Never, Level = 72, Location = 124, Size = 128, Ability = OnlyFirst, Nature = Nature.Modest, TeraType = GemType.Electric, IVs = new(25,31,25,31,31,25), Moves = new(063,268,879,408) }, // Miraidon + new(SL) { Species = 1007, Shiny = Never, Level = 72, Location = 124, Size = 128, Ability = OnlyFirst, Nature = Nature.Adamant, TeraType = GemType.Fighting, IVs = new(25,31,25,31,31,25), Moves = new(416,339,878,053) }, // Koraidon + new(VL) { Species = 1008, Shiny = Never, Level = 72, Location = 124, Size = 128, Ability = OnlyFirst, Nature = Nature.Modest, TeraType = GemType.Electric, IVs = new(25,31,25,31,31,25), Moves = new(063,268,879,408) }, // Miraidon + + // Box Legendary (Ride Form) + new(SL) { Gift = true, Species = 1007, Shiny = Never, Level = 68, Location = 070, Ability = OnlyFirst, Size = 128, Nature = Nature.Quirky, TeraType = GemType.Dragon, IVs = new(31,31,28,31,31,28), Moves = new(053,878,203,851) }, // Koraidon + new(VL) { Gift = true, Species = 1008, Shiny = Never, Level = 68, Location = 070, Ability = OnlyFirst, Size = 128, Nature = Nature.Quirky, TeraType = GemType.Dragon, IVs = new(31,31,28,31,31,28), Moves = new(408,879,203,851) }, // Miraidon // Treasures of Ruin - new(SV) { Species = 994, Shiny = Never, Level = 60, Location = 109, Size = 128, FlawlessIVCount = 3 }, // Ting-Lu - new(SV) { Species = 995, Shiny = Never, Level = 60, Location = 022, Size = 128, FlawlessIVCount = 3 }, // Chien-Pao - new(SV) { Species = 996, Shiny = Never, Level = 60, Location = 006, Size = 128, FlawlessIVCount = 3 }, // Wo-Chien - new(SV) { Species = 997, Shiny = Never, Level = 60, Location = 048, Size = 128, FlawlessIVCount = 3 }, // Chi-Yu + new(SV) { Species = 1001, Shiny = Never, Level = 60, Location = 006, Size = 128, FlawlessIVCount = 3 }, // Wo-Chien + new(SV) { Species = 1002, Shiny = Never, Level = 60, Location = 022, Size = 128, FlawlessIVCount = 3 }, // Chien-Pao + new(SV) { Species = 1003, Shiny = Never, Level = 60, Location = 109, Size = 128, FlawlessIVCount = 3 }, // Ting-Lu + new(SV) { Species = 1004, Shiny = Never, Level = 60, Location = 048, Size = 128, FlawlessIVCount = 3 }, // Chi-Yu // Former Titans - new(SV) { Species = 962, Shiny = Never, Level = 16, Location = 020, Size = 255, Ability = OnlyFirst, Gender = 1, Nature = Nature.Gentle, IVs = new(30,30,30,30,30,30), Moves = new(011,249,335,317), IsTitan = true }, // Klawf - new(SV) { Species = 959, Shiny = Never, Level = 20, Location = 022, Size = 255, Ability = OnlyHidden, Gender = 1, Nature = Nature.Jolly, IVs = new(30,30,30,30,30,30), Moves = new(088,017,365,259), IsTitan = true }, // Bombirdier - new(SV) { Species = 944, Shiny = Never, Level = 29, Location = 032, Size = 255, Ability = OnlyFirst, Gender = 0, Nature = Nature.Quirky, IVs = new(30,30,30,30,30,30), Moves = new(231,029,035,201), IsTitan = true }, // Orthworm - new(SL) { Species = 978, Shiny = Never, Level = 45, Location = 024, Size = 255, Ability = OnlyFirst, Nature = Nature.Naughty, IVs = new(30,30,30,30,30,30), Moves = new(229,280,282,707), IsTitan = true }, // Great Tusk - new(VL) { Species = 986, Shiny = Never, Level = 45, Location = 024, Size = 255, Ability = OnlyFirst, Nature = Nature.Naughty, IVs = new(30,30,30,30,30,30), Moves = new(229,442,282,707), IsTitan = true }, // Iron Treads - new(SV) { Species = 952, Shiny = Never, Level = 57, Location = 040, Size = 255, Ability = OnlyFirst, Gender = 0, Nature = Nature.Quiet, IVs = new(30,30,30,30,30,30), Moves = new(330,196,269,406), IsTitan = true }, // Tatsugiri + new(SV) { Species = 950, Shiny = Never, Level = 16, Location = 020, Size = 255, Ability = OnlyFirst, Gender = 1, Nature = Nature.Gentle, IVs = new(30,30,30,30,30,30), Moves = new(011,249,335,317), IsTitan = true }, // Klawf + new(SV) { Species = 962, Shiny = Never, Level = 20, Location = 022, Size = 255, Ability = OnlyHidden, Gender = 1, Nature = Nature.Jolly, IVs = new(30,30,30,30,30,30), Moves = new(088,017,365,259), IsTitan = true }, // Bombirdier + new(SV) { Species = 968, Shiny = Never, Level = 29, Location = 032, Size = 255, Ability = OnlyFirst, Gender = 0, Nature = Nature.Quirky, IVs = new(30,30,30,30,30,30), Moves = new(231,029,035,201), IsTitan = true }, // Orthworm + new(SL) { Species = 984, Shiny = Never, Level = 45, Location = 024, Size = 255, Ability = OnlyFirst, Nature = Nature.Naughty, IVs = new(30,30,30,30,30,30), Moves = new(229,280,282,707), IsTitan = true }, // Great Tusk + new(VL) { Species = 990, Shiny = Never, Level = 45, Location = 024, Size = 255, Ability = OnlyFirst, Nature = Nature.Naughty, IVs = new(30,30,30,30,30,30), Moves = new(229,442,282,707), IsTitan = true }, // Iron Treads + new(SV) { Species = 978, Shiny = Never, Level = 57, Location = 040, Size = 255, Ability = OnlyFirst, Gender = 0, Nature = Nature.Quiet, IVs = new(30,30,30,30,30,30), Moves = new(330,196,269,406), IsTitan = true }, // Tatsugiri // Dummy Tatsugiri - new(SV) { Species = 952, Shiny = Never, Level = 45, Location = 040, Size = 128, }, // Tatsugiri - new(SV) { Species = 952, Shiny = Never, Level = 45, Location = 040, Size = 128, Form = 1 }, // Tatsugiri-1 - new(SV) { Species = 952, Shiny = Never, Level = 45, Location = 040, Size = 128, Form = 2 }, // Tatsugiri-2 + new(SV) { Species = 978, Shiny = Never, Level = 45, Location = 040, Size = 128 }, // Tatsugiri + new(SV) { Species = 978, Shiny = Never, Level = 45, Location = 040, Size = 128, Form = 1 }, // Tatsugiri-1 + new(SV) { Species = 978, Shiny = Never, Level = 45, Location = 040, Size = 128, Form = 2 }, // Tatsugiri-2 #region Chest Form Gimmighoul // Gimmighoul has 13 separate static encounter entries, all differing by Level. These can be placed in numerous parts of the map, so for now, manually define them all here. - new(SV) { Species = 976, Shiny = Never, Level = 05, Location = 006 }, // Gimmighoul - South Province (Area One) - new(SV) { Species = 976, Shiny = Never, Level = 10, Location = 012 }, // Gimmighoul - South Province (Area Two) - new(SV) { Species = 976, Shiny = Never, Level = 10, Location = 020 }, // Gimmighoul - South Province (Area Three) - new(SV) { Species = 976, Shiny = Never, Level = 15, Location = 014 }, // Gimmighoul - South Province (Area Four) - new(SV) { Species = 976, Shiny = Never, Level = 15, Location = 018 }, // Gimmighoul - South Province (Area Five) - new(SV) { Species = 976, Shiny = Never, Level = 15, Location = 022 }, // Gimmighoul - West Province (Area One) - new(SV) { Species = 976, Shiny = Never, Level = 15, Location = 034 }, // Gimmighoul - East Province (Area One) - new(SV) { Species = 976, Shiny = Never, Level = 20, Location = 024 }, // Gimmighoul - Asado Desert - new(SV) { Species = 976, Shiny = Never, Level = 25, Location = 032 }, // Gimmighoul - East Province (Area Three) - new(SV) { Species = 976, Shiny = Never, Level = 25, Location = 058 }, // Gimmighoul - West Paldean Sea - new(SV) { Species = 976, Shiny = Never, Level = 35, Location = 038 }, // Gimmighoul - Glaseado Mountain - new(SV) { Species = 976, Shiny = Never, Level = 40, Location = 016 }, // Gimmighoul - South Province (Area Six) - new(SV) { Species = 976, Shiny = Never, Level = 50, Location = 026 }, // Gimmighoul - West Province (Area Two) - new(SV) { Species = 976, Shiny = Never, Level = 50, Location = 040 }, // Gimmighoul - Casseroya Lake - new(SV) { Species = 976, Shiny = Never, Level = 50, Location = 046 }, // Gimmighoul - North Province (Area One) - new(SV) { Species = 976, Shiny = Never, Level = 50, Location = 048 }, // Gimmighoul - North Province (Area Two) - new(SV) { Species = 976, Shiny = Never, Level = 50, Location = 109 }, // Gimmighoul - Socarrat Trail + new(SV) { Species = 999, Shiny = Never, Level = 05, Location = 006 }, // Gimmighoul - South Province (Area One) + new(SV) { Species = 999, Shiny = Never, Level = 10, Location = 012 }, // Gimmighoul - South Province (Area Two) + new(SV) { Species = 999, Shiny = Never, Level = 10, Location = 020 }, // Gimmighoul - South Province (Area Three) + new(SV) { Species = 999, Shiny = Never, Level = 15, Location = 014 }, // Gimmighoul - South Province (Area Four) + new(SV) { Species = 999, Shiny = Never, Level = 15, Location = 018 }, // Gimmighoul - South Province (Area Five) + new(SV) { Species = 999, Shiny = Never, Level = 15, Location = 022 }, // Gimmighoul - West Province (Area One) + new(SV) { Species = 999, Shiny = Never, Level = 15, Location = 034 }, // Gimmighoul - East Province (Area One) + new(SV) { Species = 999, Shiny = Never, Level = 20, Location = 024 }, // Gimmighoul - Asado Desert + new(SV) { Species = 999, Shiny = Never, Level = 25, Location = 032 }, // Gimmighoul - East Province (Area Three) + new(SV) { Species = 999, Shiny = Never, Level = 25, Location = 058 }, // Gimmighoul - West Paldean Sea + new(SV) { Species = 999, Shiny = Never, Level = 35, Location = 038 }, // Gimmighoul - Glaseado Mountain + new(SV) { Species = 999, Shiny = Never, Level = 40, Location = 016 }, // Gimmighoul - South Province (Area Six) + new(SV) { Species = 999, Shiny = Never, Level = 50, Location = 026 }, // Gimmighoul - West Province (Area Two) + new(SV) { Species = 999, Shiny = Never, Level = 50, Location = 040 }, // Gimmighoul - Casseroya Lake + new(SV) { Species = 999, Shiny = Never, Level = 50, Location = 046 }, // Gimmighoul - North Province (Area One) + new(SV) { Species = 999, Shiny = Never, Level = 50, Location = 048 }, // Gimmighoul - North Province (Area Two) + new(SV) { Species = 999, Shiny = Never, Level = 50, Location = 109 }, // Gimmighoul - Socarrat Trail #endregion }; @@ -85,8 +85,8 @@ internal static class Encounters9 internal static readonly EncounterTrade9[] TradeGift_SV = { - new(SV, 872,10) { TID7 = 050724, IVs = new(31,18,13,20,28,26), OTGender = 0, Gender = 1, Nature = Nature.Bashful, }, // Snom - new(SV, 194,18) { Ability = OnlySecond, TID7 = 033081, IVs = new(27,18,25,13,16,31), OTGender = 1, Gender = 0, Nature = Nature.Relaxed, }, // Wooper + new(SV, 872,10) { TID7 = 050724, IVs = new(31,18,13,20,28,26), OTGender = 0, Gender = 1, Nature = Nature.Bashful }, // Snom + new(SV, 194,18) { Ability = OnlySecond, TID7 = 033081, IVs = new(27,18,25,13,16,31), OTGender = 1, Gender = 0, Nature = Nature.Relaxed }, // Wooper new(SV, 093,25) { Ability = OnlyFirst, TID7 = 016519, IVs = new(14,20,25,31,28,16), OTGender = 1, Gender = 1, Nature = Nature.Lonely, EvolveOnTrade = true }, // Haunter }; diff --git a/PKHeX.Core/Legality/Encounters/Data/Gen12/Encounters1.cs b/PKHeX.Core/Legality/Encounters/Data/Gen12/Encounters1.cs index 94f6edcc0..e0d798592 100644 --- a/PKHeX.Core/Legality/Encounters/Data/Gen12/Encounters1.cs +++ b/PKHeX.Core/Legality/Encounters/Data/Gen12/Encounters1.cs @@ -128,33 +128,33 @@ internal static class Encounters1 internal static readonly EncounterStatic1E[] StaticEventsVC = { // Event Mew - new(151, 5, RBY) { IVs = Flawless15, TID = 22796, OT_Name = "GF", Language = International }, - new(151, 5, RBY) { IVs = Flawless15, TID = 22796, OT_Name = "ゲーフリ" }, + new(151, 5, RBY) { IVs = Flawless15, TID16 = 22796, OT_Name = "GF", Language = International }, + new(151, 5, RBY) { IVs = Flawless15, TID16 = 22796, OT_Name = "ゲーフリ" }, }; internal static readonly EncounterStatic1E[] StaticEventsGB = { // Stadium 1 (International) - new(001, 05, Stadium) {Moves = new(033, 045), TID = 2000, OT_Names = StadiumOT_Int, Language = International}, // Bulbasaur - new(004, 05, Stadium) {Moves = new(010, 043), TID = 2000, OT_Names = StadiumOT_Int, Language = International}, // Charmander - new(007, 05, Stadium) {Moves = new(033, 045), TID = 2000, OT_Names = StadiumOT_Int, Language = International}, // Squirtle - new(106, 20, Stadium) {Moves = new(024, 096), TID = 2000, OT_Names = StadiumOT_Int, Language = International}, // Hitmonlee - new(107, 20, Stadium) {Moves = new(004, 097), TID = 2000, OT_Names = StadiumOT_Int, Language = International}, // Hitmonchan - new(133, 25, Stadium) {Moves = new(033, 039), TID = 2000, OT_Names = StadiumOT_Int, Language = International}, // Eevee - new(138, 20, Stadium) {Moves = new(055, 110), TID = 2000, OT_Names = StadiumOT_Int, Language = International}, // Omanyte - new(140, 20, Stadium) {Moves = new(010, 106), TID = 2000, OT_Names = StadiumOT_Int, Language = International}, // Kabuto - new(054, 15, Stadium) {Moves = new(133, 010), TID = 2000, OT_Names = StadiumOT_Int, Language = International}, // Psyduck (Amnesia) + new(001, 05, Stadium) {Moves = new(033, 045), TID16 = 2000, OT_Names = StadiumOT_Int, Language = International}, // Bulbasaur + new(004, 05, Stadium) {Moves = new(010, 043), TID16 = 2000, OT_Names = StadiumOT_Int, Language = International}, // Charmander + new(007, 05, Stadium) {Moves = new(033, 045), TID16 = 2000, OT_Names = StadiumOT_Int, Language = International}, // Squirtle + new(106, 20, Stadium) {Moves = new(024, 096), TID16 = 2000, OT_Names = StadiumOT_Int, Language = International}, // Hitmonlee + new(107, 20, Stadium) {Moves = new(004, 097), TID16 = 2000, OT_Names = StadiumOT_Int, Language = International}, // Hitmonchan + new(133, 25, Stadium) {Moves = new(033, 039), TID16 = 2000, OT_Names = StadiumOT_Int, Language = International}, // Eevee + new(138, 20, Stadium) {Moves = new(055, 110), TID16 = 2000, OT_Names = StadiumOT_Int, Language = International}, // Omanyte + new(140, 20, Stadium) {Moves = new(010, 106), TID16 = 2000, OT_Names = StadiumOT_Int, Language = International}, // Kabuto + new(054, 15, Stadium) {Moves = new(133, 010), TID16 = 2000, OT_Names = StadiumOT_Int, Language = International}, // Psyduck (Amnesia) // Stadium 2 (Japan) - new(001, 05, Stadium) {Moves = new(033, 045), TID = 1999, OT_Name = StadiumOT_JPN}, // Bulbasaur - new(004, 05, Stadium) {Moves = new(010, 043), TID = 1999, OT_Name = StadiumOT_JPN}, // Charmander - new(007, 05, Stadium) {Moves = new(033, 045), TID = 1999, OT_Name = StadiumOT_JPN}, // Squirtle - new(106, 20, Stadium) {Moves = new(024, 096), TID = 1999, OT_Name = StadiumOT_JPN}, // Hitmonlee - new(107, 20, Stadium) {Moves = new(004, 097), TID = 1999, OT_Name = StadiumOT_JPN}, // Hitmonchan - new(133, 25, Stadium) {Moves = new(033, 039), TID = 1999, OT_Name = StadiumOT_JPN}, // Eevee - new(138, 20, Stadium) {Moves = new(055, 110), TID = 1999, OT_Name = StadiumOT_JPN}, // Omanyte - new(140, 20, Stadium) {Moves = new(010, 106), TID = 1999, OT_Name = StadiumOT_JPN}, // Kabuto - new(054, 15, Stadium) {Moves = new(133, 010), TID = 1999, OT_Name = StadiumOT_JPN}, // Psyduck (Amnesia) + new(001, 05, Stadium) {Moves = new(033, 045), TID16 = 1999, OT_Name = StadiumOT_JPN}, // Bulbasaur + new(004, 05, Stadium) {Moves = new(010, 043), TID16 = 1999, OT_Name = StadiumOT_JPN}, // Charmander + new(007, 05, Stadium) {Moves = new(033, 045), TID16 = 1999, OT_Name = StadiumOT_JPN}, // Squirtle + new(106, 20, Stadium) {Moves = new(024, 096), TID16 = 1999, OT_Name = StadiumOT_JPN}, // Hitmonlee + new(107, 20, Stadium) {Moves = new(004, 097), TID16 = 1999, OT_Name = StadiumOT_JPN}, // Hitmonchan + new(133, 25, Stadium) {Moves = new(033, 039), TID16 = 1999, OT_Name = StadiumOT_JPN}, // Eevee + new(138, 20, Stadium) {Moves = new(055, 110), TID16 = 1999, OT_Name = StadiumOT_JPN}, // Omanyte + new(140, 20, Stadium) {Moves = new(010, 106), TID16 = 1999, OT_Name = StadiumOT_JPN}, // Kabuto + new(054, 15, Stadium) {Moves = new(133, 010), TID16 = 1999, OT_Name = StadiumOT_JPN}, // Psyduck (Amnesia) new(151, 5, RB) {IVs = Yoshira, OT_Names = YoshiOT, Language = International }, // Yoshira Mew Events new(151, 5, RB) {IVs = Yoshira, OT_Names = TourOT, Language = International }, // Pokémon 2000 Stadium Tour Mew diff --git a/PKHeX.Core/Legality/Encounters/Data/Gen12/Encounters2.cs b/PKHeX.Core/Legality/Encounters/Data/Gen12/Encounters2.cs index e2f67354a..9c0fc5c51 100644 --- a/PKHeX.Core/Legality/Encounters/Data/Gen12/Encounters2.cs +++ b/PKHeX.Core/Legality/Encounters/Data/Gen12/Encounters2.cs @@ -139,14 +139,14 @@ internal static class Encounters2 internal static readonly EncounterStatic2E[] StaticEventsGB = { // Stadium 2 Baton Pass Farfetch'd - new(083, 05, C) {Moves = new(226, 14, 97, 163), Location = 127, TID = 2000, OT_Name = "スタジアム"}, - new(083, 05, C) {Moves = new(226, 14, 97, 163), Location = 127, TID = 2000, OT_Name = "Stadium", Language = International}, - new(083, 05, C) {Moves = new(226, 14, 97, 163), Location = 127, TID = 2001, OT_Names = new[]{"Stade", "Stadion", "Stadio", "Estadio"}, Language = International}, + new(083, 05, C) {Moves = new(226, 14, 97, 163), Location = 127, TID16 = 2000, OT_Name = "スタジアム"}, + new(083, 05, C) {Moves = new(226, 14, 97, 163), Location = 127, TID16 = 2000, OT_Name = "Stadium", Language = International}, + new(083, 05, C) {Moves = new(226, 14, 97, 163), Location = 127, TID16 = 2001, OT_Names = new[]{"Stade", "Stadion", "Stadio", "Estadio"}, Language = International}, // Stadium 2 Earthquake Gligar - new(207, 05, C) {Moves = new(89, 68, 17), Location = 127, TID = 2000, OT_Name = "スタジアム"}, - new(207, 05, C) {Moves = new(89, 68, 17), Location = 127, TID = 2000, OT_Name = "Stadium", Language = International}, - new(207, 05, C) {Moves = new(89, 68, 17), Location = 127, TID = 2001, OT_Names = new[]{"Stade", "Stadion", "Stadio", "Estadio"}, Language = International}, + new(207, 05, C) {Moves = new(89, 68, 17), Location = 127, TID16 = 2000, OT_Name = "スタジアム"}, + new(207, 05, C) {Moves = new(89, 68, 17), Location = 127, TID16 = 2000, OT_Name = "Stadium", Language = International}, + new(207, 05, C) {Moves = new(89, 68, 17), Location = 127, TID16 = 2001, OT_Names = new[]{"Stade", "Stadion", "Stadio", "Estadio"}, Language = International}, //New York Pokémon Center Events diff --git a/PKHeX.Core/Legality/Encounters/Data/Gen3/Encounters3ColoShadow.cs b/PKHeX.Core/Legality/Encounters/Data/Gen3/Encounters3ColoShadow.cs index cfbca0a15..f4d523fe4 100644 --- a/PKHeX.Core/Legality/Encounters/Data/Gen3/Encounters3ColoShadow.cs +++ b/PKHeX.Core/Legality/Encounters/Data/Gen3/Encounters3ColoShadow.cs @@ -1,4 +1,3 @@ -// ReSharper disable StringLiteralTypo namespace PKHeX.Core; /// @@ -78,1007 +77,4 @@ public static class Encounters3ColoShadow }); #endregion - - #region XD - - public static readonly TeamLock XRalts = new( - 280, // Ralts - new[] { - new NPCLock(064, 00, 0, 063), // Kadabra (M) (Hardy) - new NPCLock(180, 06, 1, 127), // Flaaffy (F) (Docile) - new NPCLock(288, 18, 0, 127), // Vigoroth (M) (Bashful) - }); - - public static readonly TeamLock XPoochyena = new( - 261, // Poochyena - new[] { - new NPCLock(041, 12, 1, 127), // Zubat (F) (Serious) - }); - - public static readonly TeamLock XLedyba = new( - 165, // Ledyba - new[] { - new NPCLock(276, 00, 1, 127), // Taillow (F) (Hardy) - }); - - public static readonly TeamLock XSphealCipherLab = new( - 363, // Spheal - "Cipher Lab", - new[] { - new NPCLock(116, 24, 0, 063), // Horsea (M) (Quirky) - new NPCLock(118, 12, 1, 127), // Goldeen (F) (Serious) - }); - - public static readonly TeamLock XSphealPhenacCityandPost = new( - 363, // Spheal - "Phenac City and Post", - new[] { - new NPCLock(116, 24, 0, 063), // Horsea (M) (Quirky) - new NPCLock(118, 12, 1, 127), // Goldeen (F) (Serious) - new NPCLock(374, 00, 2, 255), // Beldum (-) (Hardy) - }); - - public static readonly TeamLock XGulpin = new( - 316, // Gulpin - new[] { - new NPCLock(109, 12, 1, 127), // Koffing (F) (Serious) - new NPCLock(088, 06, 0, 127), // Grimer (M) (Docile) - }); - - public static readonly TeamLock XSeedotCipherLab = new( - 273, // Seedot - "Cipher Lab", - new[] { - new NPCLock(043, 06, 0, 127), // Oddish (M) (Docile) - new NPCLock(331, 24, 1, 127), // Cacnea (F) (Quirky) - new NPCLock(285, 18, 1, 127), // Shroomish (F) (Bashful) - new NPCLock(270, 00, 0, 127), // Lotad (M) (Hardy) - new NPCLock(204, 12, 0, 127), // Pineco (M) (Serious) - }); - - public static readonly TeamLock XSeedotPhenacCity = new( - 273, // Seedot - "Phenac City", - new[] { - new NPCLock(043, 06, 0, 127), // Oddish (M) (Docile) - new NPCLock(331, 24, 1, 127), // Cacnea (F) (Quirky) - new NPCLock(285, 00, 1, 127), // Shroomish (F) (Hardy) - new NPCLock(270, 00, 1, 127), // Lotad (F) (Hardy) - new NPCLock(204, 06, 0, 127), // Pineco (M) (Docile) - }); - - public static readonly TeamLock XSeedotPost = new( - 273, // Seedot - "Post", - new[] { - new NPCLock(045, 06, 0, 127), // Vileplume (M) (Docile) - new NPCLock(332, 24, 1, 127), // Cacturne (F) (Quirky) - new NPCLock(286, 00, 1, 127), // Breloom (F) (Hardy) - new NPCLock(271, 00, 0, 127), // Lombre (M) (Hardy) - new NPCLock(205, 12, 0, 127), // Forretress (M) (Serious) - }); - - public static readonly TeamLock XSpinarak = new( - 167, // Spinarak - new[] { - new NPCLock(220, 12, 1, 127), // Swinub (F) (Serious) - new NPCLock(353, 06, 0, 127), // Shuppet (M) (Docile) - }); - - public static readonly TeamLock XNumel = new( - 322, // Numel - new[] { - new NPCLock(280, 06, 0, 127), // Ralts (M) (Docile) - new NPCLock(100, 00, 2, 255), // Voltorb (-) (Hardy) - new NPCLock(371, 24, 1, 127), // Bagon (F) (Quirky) - }); - - public static readonly TeamLock XShroomish = new( - 285, // Shroomish - new[] { - new NPCLock(209, 24, 1, 191), // Snubbull (F) (Quirky) - new NPCLock(352, 00, 1, 127), // Kecleon (F) (Hardy) - }); - - public static readonly TeamLock XDelcatty = new( - 301, // Delcatty - new[] { - new NPCLock(370, 06, 1, 191), // Luvdisc (F) (Docile) - new NPCLock(267, 00, 0, 127), // Beautifly (M) (Hardy) - new NPCLock(315, 24, 0, 127), // Roselia (M) (Quirky) - }); - - public static readonly TeamLock XVoltorb = new( - 100, // Voltorb - new[] { - new NPCLock(271, 00, 0, 127), // Lombre (M) (Hardy) - new NPCLock(271, 18, 0, 127), // Lombre (M) (Bashful) - new NPCLock(271, 12, 1, 127), // Lombre (F) (Serious) - }); - - public static readonly TeamLock XMakuhita = new( - 296, // Makuhita - new[] { - new NPCLock(352, 06, 0, 127), // Kecleon (M) (Docile) - new NPCLock(283, 18, 1, 127), // Surskit (F) (Bashful) - }); - - public static readonly TeamLock XVulpix = new( - 037, // Vulpix - new[] { - new NPCLock(167, 00, 0, 127), // Spinarak (M) (Hardy) - new NPCLock(267, 06, 1, 127), // Beautifly (F) (Docile) - new NPCLock(269, 18, 0, 127), // Dustox (M) (Bashful) - }); - - public static readonly TeamLock XDuskull = new( - 355, // Duskull - new[] { - new NPCLock(215, 12, 0, 127), // Sneasel (M) (Serious) - new NPCLock(193, 18, 1, 127), // Yanma (F) (Bashful) - new NPCLock(200, 24, 0, 127), // Misdreavus (M) (Quirky) - }); - - public static readonly TeamLock XMawile = new( - 303, // Mawile - new[] { - new NPCLock(294, 06, 0, 127), // Loudred (M) (Docile) - new NPCLock(203, 18, 1, 127), // Girafarig (F) (Bashful) - }); - - public static readonly TeamLock XSnorunt = new( - 361, // Snorunt - new[] { - new NPCLock(336, 06, 1, 127), // Seviper (F) (Docile) - }); - - public static readonly TeamLock XPineco = new( - 204, // Pineco - new[] { - new NPCLock(198, 06, 0, 127), // Murkrow (M) (Docile) - }); - - public static readonly TeamLock XNatu = new( - 177, // Natu - new[] { - new NPCLock(281, 00, 0, 127), // Kirlia (M) (Hardy) - new NPCLock(264, 00, 1, 127), // Linoone (F) (Hardy) - }); - - public static readonly TeamLock XRoselia = new( - 315, // Roselia - new[] { - new NPCLock(223, 06, 0, 127), // Remoraid (M) (Docile) - new NPCLock(042, 18, 0, 127), // Golbat (M) (Bashful) - }); - - public static readonly TeamLock XMeowth = new( - 052, // Meowth - new[] { - new NPCLock(064, 06, 0, 063), // Kadabra (M) (Docile) - new NPCLock(215, 00, 1, 127), // Sneasel (F) (Hardy) - new NPCLock(200, 18, 1, 127), // Misdreavus (F) (Bashful) - }); - - public static readonly TeamLock XSwinub = new( - 220, // Swinub - new[] { - new NPCLock(324, 18, 1, 127), // Torkoal (F) (Bashful) - new NPCLock(274, 00, 0, 127), // Nuzleaf (M) (Hardy) - }); - - public static readonly TeamLock XSpearow = new( - 021, // Spearow - new[] { - new NPCLock(279, 18, 0, 127), // Pelipper (M) (Bashful) - new NPCLock(309, 06, 1, 127), // Electrike (F) (Docile) - }); - - public static readonly TeamLock XGrimer = new( - 088, // Grimer - new[] { - new NPCLock(358, 12, 0, 127), // Chimecho (M) (Serious) - new NPCLock(234, 18, 0, 127), // Stantler (M) (Bashful) - }); - - public static readonly TeamLock XSeel = new( - 086, // Seel - new[] { - new NPCLock(163, 06, 0, 127), // Hoothoot (M) (Docile) - new NPCLock(075, 18, 0, 127), // Graveler (M) (Bashful) - new NPCLock(316, 18, 1, 127), // Gulpin (F) (Bashful) - }); - - public static readonly TeamLock XLunatone = new( - 337, // Lunatone - new[] { - new NPCLock(171, 00, 1, 127), // Lanturn (F) (Hardy) - new NPCLock(195, 18, 0, 127), // Quagsire (M) (Bashful) - }); - - public static readonly TeamLock XNosepass = new( - 299, // Nosepass - new[] { - new NPCLock(271, 00, 0, 127), // Lombre (M) (Hardy) - new NPCLock(271, 18, 0, 127), // Lombre (M) (Bashful) - new NPCLock(271, 12, 1, 127), // Lombre (F) (Serious) - }); - - public static readonly TeamLock XParas = new( - 046, // Paras - new[] { - new NPCLock(336, 24, 0, 127), // Seviper (M) (Quirky) - new NPCLock(198, 06, 1, 127), // Murkrow (F) (Docile) - }); - - public static readonly TeamLock XGrowlithe = new( - 058, // Growlithe - new[] { - new NPCLock(336, 24, 0, 127), // Seviper (M) (Quirky) - new NPCLock(198, 06, 1, 127), // Murkrow (F) (Docile) - new NPCLock(046), // Shadow Paras - }); - - public static readonly TeamLock XGrowlitheParasSeen = new( - 058, // Growlithe - "Paras Seen", - new[] { - new NPCLock(336, 24, 0, 127), // Seviper (M) (Quirky) - new NPCLock(198, 06, 1, 127), // Murkrow (F) (Docile) - new NPCLock(046, true), // Shadow Paras (Seen) - }); - - public static readonly TeamLock XPidgeotto = new( - 017, // Pidgeotto - new[] { - new NPCLock(015), // Shadow Beedrill - new NPCLock(162, 12, 0, 127), // Furret (M) (Serious) - new NPCLock(176, 18, 0, 031), // Togetic (M) (Bashful) - }); - - public static readonly TeamLock XPidgeottoBeedrillSeen = new( - 017, // Pidgeotto - "Beedrill Seen", - new[] { - new NPCLock(015, true), // Shadow Beedrill (Seen) - new NPCLock(162, 12, 0, 127), // Furret (M) (Serious) - new NPCLock(176, 18, 0, 031), // Togetic (M) (Bashful) - }); - - public static readonly TeamLock XTangela = new( - 114, // Tangela - new[] { - new NPCLock(038, 12, 1, 191), // Ninetales (F) (Serious) - new NPCLock(189, 06, 0, 127), // Jumpluff (M) (Docile) - new NPCLock(184, 00, 1, 127), // Azumarill (F) (Hardy) - }); - - public static readonly TeamLock XButterfree = new( - 012, // Butterfree - new[] { - new NPCLock(038, 12, 1, 191), // Ninetales (F) (Serious) - new NPCLock(189, 06, 0, 127), // Jumpluff (M) (Docile) - new NPCLock(184, 00, 1, 127), // Azumarill (F) (Hardy) - new NPCLock(114), // Shadow Tangela - }); - - public static readonly TeamLock XButterfreeTangelaSeen = new( - 012, // Butterfree - "Tangela Seen", - new[] { - new NPCLock(038, 12, 1, 191), // Ninetales (F) (Serious) - new NPCLock(189, 06, 0, 127), // Jumpluff (M) (Docile) - new NPCLock(184, 00, 1, 127), // Azumarill (F) (Hardy) - new NPCLock(114, true), // Shadow Tangela (Seen) - }); - - public static readonly TeamLock XMagneton = new( - 082, // Magneton - new[] { - new NPCLock(292, 18, 2, 255), // Shedinja (-) (Bashful) - new NPCLock(202, 00, 0, 127), // Wobbuffet (M) (Hardy) - new NPCLock(329, 12, 1, 127), // Vibrava (F) (Serious) - }); - - public static readonly TeamLock XVenomoth = new( - 049, // Venomoth - new[] { - new NPCLock(055, 18, 1, 127), // Golduck (F) (Bashful) - new NPCLock(237, 24, 0, 000), // Hitmontop (M) (Quirky) - new NPCLock(297, 12, 0, 063), // Hariyama (M) (Serious) - }); - - public static readonly TeamLock XWeepinbell = new( - 070, // Weepinbell - new[] { - new NPCLock(055, 18, 1, 127), // Golduck (F) (Bashful) - new NPCLock(237, 24, 0, 000), // Hitmontop (M) (Quirky) - new NPCLock(297, 12, 0, 063), // Hariyama (M) (Serious) - new NPCLock(049), // Shadow Venomoth - }); - - public static readonly TeamLock XWeepinbellVenomothSeen = new( - 070, // Weepinbell - "Venomoth Seen", - new[] { - new NPCLock(055, 18, 1, 127), // Golduck (F) (Bashful) - new NPCLock(237, 24, 0, 000), // Hitmontop (M) (Quirky) - new NPCLock(297, 12, 0, 063), // Hariyama (M) (Serious) - new NPCLock(049, true), // Shadow Venomoth (Seen) - }); - - public static readonly TeamLock XArbok = new( - 024, // Arbok - new[] { - new NPCLock(367, 06, 0, 127), // Huntail (M) (Docile) - new NPCLock(332, 00, 1, 127), // Cacturne (F) (Hardy) - new NPCLock(110, 12, 1, 127), // Weezing (F) (Serious) - new NPCLock(217, 18, 1, 127), // Ursaring (F) (Bashful) - }); - - public static readonly TeamLock XPrimeape = new( - 057, // Primeape - new[] { - new NPCLock(305, 18, 1, 127), // Lairon (F) (Bashful) - new NPCLock(364, 12, 1, 127), // Sealeo (F) (Serious) - new NPCLock(199, 06, 1, 127), // Slowking (F) (Docile) - new NPCLock(217, 24, 0, 127), // Ursaring (M) (Quirky) - }); - - public static readonly TeamLock XHypno = new( - 097, // Hypno - new[] { - new NPCLock(305, 18, 1, 127), // Lairon (F) (Bashful) - new NPCLock(364, 12, 1, 127), // Sealeo (F) (Serious) - new NPCLock(199, 06, 1, 127), // Slowking (F) (Docile) - new NPCLock(217, 24, 0, 127), // Ursaring (M) (Quirky) - new NPCLock(057), // Shadow Primeape - }); - - public static readonly TeamLock XHypnoPrimeapeSeen = new( - 097, // Hypno - "Primeape Seen", - new[] { - new NPCLock(305, 18, 1, 127), // Lairon (F) (Bashful) - new NPCLock(364, 12, 1, 127), // Sealeo (F) (Serious) - new NPCLock(199, 06, 1, 127), // Slowking (F) (Docile) - new NPCLock(217, 24, 0, 127), // Ursaring (M) (Quirky) - new NPCLock(057, true), // Shadow Primeape (Seen) - }); - - public static readonly TeamLock XGolduck = new( - 055, // Golduck - new[] { - new NPCLock(342, 24, 0, 127), // Crawdaunt (M) (Quirky) - new NPCLock(279, 06, 1, 127), // Pelipper (F) (Docile) - new NPCLock(226, 18, 1, 127), // Mantine (F) (Bashful) - }); - - public static readonly TeamLock XSableye = new( - 302, // Sableye - new[] { - new NPCLock(342, 24, 0, 127), // Crawdaunt (M) (Quirky) - new NPCLock(279, 06, 1, 127), // Pelipper (F) (Docile) - new NPCLock(226, 18, 1, 127), // Mantine (F) (Bashful) - new NPCLock(055), // Shadow Golduck - }); - - public static readonly TeamLock XSableyeGolduckSeen = new( - 302, // Sableye - "Golduck Seen", - new[] { - new NPCLock(342, 24, 0, 127), // Crawdaunt (M) (Quirky) - new NPCLock(279, 06, 1, 127), // Pelipper (F) (Docile) - new NPCLock(226, 18, 1, 127), // Mantine (F) (Bashful) - new NPCLock(055, true), // Shadow Golduck (Seen) - }); - - public static readonly TeamLock XDodrio = new( - 085, // Dodrio - new[] { - new NPCLock(178, 18, 1, 127), // Xatu (F) (Bashful) - }); - - public static readonly TeamLock XRaticate = new( - 020, // Raticate - new[] { - new NPCLock(178, 18, 1, 127), // Xatu (F) (Bashful) - new NPCLock(085), // Shadow Dodrio - new NPCLock(340, 18, 0, 127), // Whiscash (M) (Bashful) - }); - - public static readonly TeamLock XRaticateDodrioSeen = new( - 020, // Raticate - "Dodrio Seen", - new[] { - new NPCLock(178, 18, 1, 127), // Xatu (F) (Bashful) - new NPCLock(085, true), // Shadow Dodrio (Seen) - new NPCLock(340, 18, 0, 127), // Whiscash (M) (Bashful) - }); - - public static readonly TeamLock XFarfetchd = new( - 083, // Farfetch’d - new[] { - new NPCLock(282, 12, 0, 127), // Gardevoir (M) (Serious) - new NPCLock(368, 00, 1, 127), // Gorebyss (F) (Hardy) - new NPCLock(315, 24, 0, 127), // Roselia (M) (Quirky) - }); - - public static readonly TeamLock XAltaria = new( - 334, // Altaria - new[] { - new NPCLock(282, 12, 0, 127), // Gardevoir (M) (Serious) - new NPCLock(368, 00, 1, 127), // Gorebyss (F) (Hardy) - new NPCLock(315, 24, 0, 127), // Roselia (M) (Quirky) - new NPCLock(083), // Shadow Farfetch’d - }); - - public static readonly TeamLock XAltariaFarfetchdSeen = new( - 334, // Altaria - "Farfetch'd Seen", - new[] { - new NPCLock(282, 12, 0, 127), // Gardevoir (M) (Serious) - new NPCLock(368, 00, 1, 127), // Gorebyss (F) (Hardy) - new NPCLock(315, 24, 0, 127), // Roselia (M) (Quirky) - new NPCLock(083, true), // Shadow Farfetch’d (Seen) - }); - - public static readonly TeamLock XKangaskhan = new( - 115, // Kangaskhan - new[] { - new NPCLock(101, 00, 2, 255), // Electrode (-) (Hardy) - new NPCLock(200, 18, 1, 127), // Misdreavus (F) (Bashful) - new NPCLock(344, 12, 2, 255), // Claydol (-) (Serious) - }); - - public static readonly TeamLock XBanette = new( - 354, // Banette - new[] { - new NPCLock(101, 00, 2, 255), // Electrode (-) (Hardy) - new NPCLock(200, 18, 1, 127), // Misdreavus (F) (Bashful) - new NPCLock(344, 12, 2, 255), // Claydol (-) (Serious) - new NPCLock(115), // Shadow Kangaskhan - }); - - public static readonly TeamLock XBanetteKangaskhanSeen = new( - 354, // Banette - "Kangaskhan Seen", - new[] { - new NPCLock(101, 00, 2, 255), // Electrode (-) (Hardy) - new NPCLock(200, 18, 1, 127), // Misdreavus (F) (Bashful) - new NPCLock(344, 12, 2, 255), // Claydol (-) (Serious) - new NPCLock(115, true), // Shadow Kangaskhan (Seen) - }); - - public static readonly TeamLock XMagmar = new( - 126, // Magmar - new[] { - new NPCLock(229, 18, 0, 127), // Houndoom (M) (Bashful) - new NPCLock(038, 18, 0, 191), // Ninetales (M) (Bashful) - new NPCLock(045, 00, 1, 127), // Vileplume (F) (Hardy) - }); - - public static readonly TeamLock XPinsir = new( - 127, // Pinsir - new[] { - new NPCLock(229, 18, 0, 127), // Houndoom (M) (Bashful) - new NPCLock(038, 18, 0, 191), // Ninetales (M) (Bashful) - new NPCLock(045, 00, 1, 127), // Vileplume (F) (Hardy) - new NPCLock(126), // Shadow Magmar - }); - - public static readonly TeamLock XPinsirMagmarSeen = new( - 127, // Pinsir - "Magmar Seen", - new[] { - new NPCLock(229, 18, 0, 127), // Houndoom (M) (Bashful) - new NPCLock(038, 18, 0, 191), // Ninetales (M) (Bashful) - new NPCLock(045, 00, 1, 127), // Vileplume (F) (Hardy) - new NPCLock(126, true), // Shadow Magmar (Seen) - }); - - public static readonly TeamLock XRapidash = new( - 078, // Rapidash - new[] { - new NPCLock(323, 24, 0, 127), // Camerupt (M) (Quirky) - new NPCLock(110, 06, 0, 127), // Weezing (M) (Docile) - new NPCLock(089, 12, 1, 127), // Muk (F) (Serious) - }); - - public static readonly TeamLock XMagcargo = new( - 219, // Magcargo - new[] { - new NPCLock(323, 24, 0, 127), // Camerupt (M) (Quirky) - new NPCLock(110, 06, 0, 127), // Weezing (M) (Docile) - new NPCLock(089, 12, 1, 127), // Muk (F) (Serious) - new NPCLock(078), // Shadow Rapidash - }); - - public static readonly TeamLock XMagcargoRapidashSeen = new( - 219, // Magcargo - "Rapidash Seen", - new[] { - new NPCLock(323, 24, 0, 127), // Camerupt (M) (Quirky) - new NPCLock(110, 06, 0, 127), // Weezing (M) (Docile) - new NPCLock(089, 12, 1, 127), // Muk (F) (Serious) - new NPCLock(078, true), // Shadow Rapidash (Seen) - }); - - public static readonly TeamLock XHitmonchan = new( - 107, // Hitmonchan - new[] { - new NPCLock(308, 24, 0, 127), // Medicham (M) (Quirky) - new NPCLock(076, 06, 1, 127), // Golem (F) (Docile) - new NPCLock(178, 18, 1, 127), // Xatu (F) (Bashful) - }); - - public static readonly TeamLock XHitmonlee = new( - 106, // Hitmonlee - new[] { - new NPCLock(326, 18, 0, 127), // Grumpig (M) (Bashful) - new NPCLock(227, 12, 1, 127), // Skarmory (F) (Serious) - new NPCLock(375, 06, 2, 255), // Metang (-) (Docile) - new NPCLock(297, 24, 1, 063), // Hariyama (F) (Quirky) - }); - - public static readonly TeamLock XLickitung = new( - 108, // Lickitung - new[] { - new NPCLock(171, 24, 0, 127), // Lanturn (M) (Quirky) - new NPCLock(082, 06, 2, 255), // Magneton (-) (Docile) - }); - - public static readonly TeamLock XScyther = new( - 123, // Scyther - new[] - { - new NPCLock(234, 06, 1, 127), // Stantler (F) (Docile) - new NPCLock(295, 24, 0, 127), // Exploud (M) (Quirky) - }); - - public static readonly TeamLock XChansey = new( - 113, // Chansey - new[] { - new NPCLock(234, 06, 1, 127), // Stantler (F) (Docile) - new NPCLock(295, 24, 0, 127), // Exploud (M) (Quirky) - new NPCLock(123), // Shadow Scyther - }); - - public static readonly TeamLock XChanseyScytherSeen = new( - 113, // Chansey - "Scyther Seen", - new[] { - new NPCLock(234, 06, 1, 127), // Stantler (F) (Docile) - new NPCLock(295, 24, 0, 127), // Exploud (M) (Quirky) - new NPCLock(123, true), // Shadow Scyther (Seen) - }); - - public static readonly TeamLock XSolrock = new( - 338, // Solrock - new[] { - new NPCLock(375, 24, 2, 255), // Metang (-) (Quirky) - new NPCLock(195, 06, 0, 127), // Quagsire (M) (Docile) - new NPCLock(212, 00, 1, 127), // Scizor (F) (Hardy) - }); - - public static readonly TeamLock XStarmie = new( - 121, // Starmie - new[] { - new NPCLock(375, 24, 2, 255), // Metang (-) (Quirky) - new NPCLock(195, 06, 0, 127), // Quagsire (M) (Docile) - new NPCLock(212, 00, 1, 127), // Scizor (F) (Hardy) - new NPCLock(338), // Shadow Solrock - new NPCLock(351, 18, 0, 127), // Castform (M) (Bashful) - }); - - public static readonly TeamLock XStarmieSolrockSeen = new( - 121, // Starmie - "Solrock Seen", - new[] { - new NPCLock(375, 24, 2, 255), // Metang (-) (Quirky) - new NPCLock(195, 06, 0, 127), // Quagsire (M) (Docile) - new NPCLock(212, 00, 1, 127), // Scizor (F) (Hardy) - new NPCLock(338, true), // Shadow Solrock (Seen) - new NPCLock(351, 18, 0, 127), // Castform (M) (Bashful) - }); - - public static readonly TeamLock XElectabuzz = new( - 125, // Electabuzz - new[] { - new NPCLock(277), // Shadow Swellow - new NPCLock(065, 24, 0, 063), // Alakazam (M) (Quirky) - new NPCLock(230, 6, 1, 127), // Kingdra (F) (Docile) - new NPCLock(214, 18, 1, 127), // Heracross (F) (Bashful) - }); - - public static readonly TeamLock XElectabuzzSwellowSeen = new( - 125, // Electabuzz - "Swellow Seen", - new[] { - new NPCLock(277, true), // Shadow Swellow (Seen) - new NPCLock(065, 24, 0, 063), // Alakazam (M) (Quirky) - new NPCLock(230, 6, 1, 127), // Kingdra (F) (Docile) - new NPCLock(214, 18, 1, 127), // Heracross (F) (Bashful) - }); - - public static readonly TeamLock XSnorlax = new( - 143, // Snorlax - new[] { - new NPCLock(277), // Shadow Swellow - new NPCLock(065, 24, 0, 063), // Alakazam (M) (Quirky) - new NPCLock(230, 6, 1, 127), // Kingdra (F) (Docile) - new NPCLock(214, 18, 1, 127), // Heracross (F) (Bashful) - new NPCLock(125), // Shadow Electabuzz - }); - - public static readonly TeamLock XSnorlaxSwellowSeen = new( - 143, // Snorlax - "Swellow Seen", - new[] { - new NPCLock(277, true), // Shadow Swellow (Seen) - new NPCLock(065, 24, 0, 063), // Alakazam (M) (Quirky) - new NPCLock(230, 6, 1, 127), // Kingdra (F) (Docile) - new NPCLock(214, 18, 1, 127), // Heracross (F) (Bashful) - new NPCLock(125), // Shadow Electabuzz - }); - - public static readonly TeamLock XSnorlaxSwellowElectabuzzSeen = new( - 143, // Snorlax - "Swellow & Electabuzz Seen", - new[] { - new NPCLock(277, true), // Shadow Swellow (Seen) - new NPCLock(065, 24, 0, 063), // Alakazam (M) (Quirky) - new NPCLock(230, 6, 1, 127), // Kingdra (F) (Docile) - new NPCLock(214, 18, 1, 127), // Heracross (F) (Bashful) - new NPCLock(125, true), // Shadow Electabuzz - }); - - public static readonly TeamLock XPoliwrath = new( - 062, // Poliwrath - new[] { - new NPCLock(199, 18, 0, 127), // Slowking (M) (Bashful) - new NPCLock(217, 18, 0, 127), // Ursaring (M) (Bashful) - new NPCLock(306, 24, 0, 127), // Aggron (M) (Quirky) - new NPCLock(365, 06, 1, 127), // Walrein (F) (Docile) - }); - - public static readonly TeamLock XMrMime = new( - 122, // Mr. Mime - new[] { - new NPCLock(199, 18, 0, 127), // Slowking (M) (Bashful) - new NPCLock(217, 18, 0, 127), // Ursaring (M) (Bashful) - new NPCLock(306, 24, 0, 127), // Aggron (M) (Quirky) - new NPCLock(365, 06, 1, 127), // Walrein (F) (Docile) - new NPCLock(062), // Shadow Poliwrath - }); - - public static readonly TeamLock XMrMimePoliwrathSeen = new( - 122, // Mr. Mime - "Poliwrath Seen", - new[] { - new NPCLock(199, 18, 0, 127), // Slowking (M) (Bashful) - new NPCLock(217, 18, 0, 127), // Ursaring (M) (Bashful) - new NPCLock(306, 24, 0, 127), // Aggron (M) (Quirky) - new NPCLock(365, 06, 1, 127), // Walrein (F) (Docile) - new NPCLock(062, true), // Shadow Poliwrath (Seen) - }); - - public static readonly TeamLock XDugtrio = new( - 051, // Dugtrio - new[] { - new NPCLock(362, 00, 0, 127), // Glalie (M) (Hardy) - new NPCLock(181, 18, 0, 127), // Ampharos (M) (Bashful) - new NPCLock(286, 06, 1, 127), // Breloom (F) (Docile) - new NPCLock(232, 12, 0, 127), // Donphan (M) (Serious) - }); - - public static readonly TeamLock XManectric = new( - 310, // Manectric - new[] { - new NPCLock(291, 06, 1, 127), // Ninjask (F) (Docile) - }); - - public static readonly TeamLock XSalamence = new( - 373, // Salamence - new[] { - new NPCLock(291, 06, 1, 127), // Ninjask (F) (Docile) - new NPCLock(310), // Shadow Manectric - }); - - public static readonly TeamLock XMarowak = new( - 105, // Marowak - new[] { - new NPCLock(291, 06, 1, 127), // Ninjask (F) (Docile) - new NPCLock(310), // Shadow Manectric - new NPCLock(373), // Shadow Salamence - new NPCLock(330, 24, 0, 127), // Flygon (M) (Quirky) - }); - - public static readonly TeamLock XLapras = new( - 131, // Lapras - new[] { - new NPCLock(291, 06, 1, 127), // Ninjask (F) (Docile) - new NPCLock(310), // Shadow Manectric - new NPCLock(373), // Shadow Salamence - new NPCLock(330, 24, 0, 127), // Flygon (M) (Quirky) - new NPCLock(105), // Shadow Marowak - }); - - public static readonly TeamLock XSalamenceManectricSeen = new( - 373, // Salamence - "Manectric Seen", - new[] { - new NPCLock(291, 06, 1, 127), // Ninjask (F) (Docile) - new NPCLock(310, true), // Shadow Manectric (Seen) - }); - - public static readonly TeamLock XMarowakManectricSeen = new( - 105, // Marowak - "Manectric Seen", - new[] { - new NPCLock(291, 06, 1, 127), // Ninjask (F) (Docile) - new NPCLock(310, true), // Shadow Manectric (Seen) - new NPCLock(373), // Shadow Salamence - new NPCLock(330, 24, 0, 127), // Flygon (M) (Quirky) - }); - - public static readonly TeamLock XMarowakManectricSalamenceSeen = new( - 105, // Marowak - "Manectric & Salamence Seen", - new[] { - new NPCLock(291, 06, 1, 127), // Ninjask (F) (Docile) - new NPCLock(310, true), // Shadow Manectric (Seen) - new NPCLock(373, true), // Shadow Salamence (Seen) - new NPCLock(330, 24, 0, 127), // Flygon (M) (Quirky) - }); - - public static readonly TeamLock XLaprasManectricSeen = new( - 131, // Lapras - "Manectric Seen", - new[] { - new NPCLock(291, 06, 1, 127), // Ninjask (F) (Docile) - new NPCLock(310, true), // Shadow Manectric (Seen) - new NPCLock(373), // Shadow Salamence - new NPCLock(330, 24, 0, 127), // Flygon (M) (Quirky) - new NPCLock(105), // Shadow Marowak - }); - - public static readonly TeamLock XLaprasManectricSalamenceSeen = new( - 131, // Lapras - "Manectric & Salamence Seen", - new[] { - new NPCLock(291, 06, 1, 127), // Ninjask (F) (Docile) - new NPCLock(310, true), // Shadow Manectric (Seen) - new NPCLock(373, true), // Shadow Salamence (Seen) - new NPCLock(330, 24, 0, 127), // Flygon (M) (Quirky) - new NPCLock(105), // Shadow Marowak - }); - - public static readonly TeamLock XLaprasManectricMarowakSeen = new( - 131, // Lapras - "Manectric & Marowak Seen", - new[] { - new NPCLock(291, 06, 1, 127), // Ninjask (F) (Docile) - new NPCLock(310, true), // Shadow Manectric (Seen) - new NPCLock(373), // Shadow Salamence - new NPCLock(330, 24, 0, 127), // Flygon (M) (Quirky) - new NPCLock(105, true), // Shadow Marowak (Seen) - }); - - public static readonly TeamLock XLaprasManectricSalamenceMarowakSeen = new( - 131, // Lapras - "Manectric & Salamence & Marowak Seen", - new[] { - new NPCLock(291, 06, 1, 127), // Ninjask (F) (Docile) - new NPCLock(310, true), // Shadow Manectric (Seen) - new NPCLock(373, true), // Shadow Salamence (Seen) - new NPCLock(330, 24, 0, 127), // Flygon (M) (Quirky) - new NPCLock(105, true), // Shadow Marowak (Seen) - }); - - public static readonly TeamLock XMoltres = new( - 146, // Moltres - new[] { - new NPCLock(112), // Shadow Rhydon - }); - - public static readonly TeamLock XExeggutor = new( - 103, // Exeggutor - new[] { - new NPCLock(112), // Shadow Rhydon - new NPCLock(146), // Shadow Moltres - }); - - public static readonly TeamLock XTauros = new( - 128, // Tauros - new[] { - new NPCLock(112), // Shadow Rhydon - new NPCLock(146), // Shadow Moltres - new NPCLock(103), // Shadow Exeggutor - }); - - public static readonly TeamLock XArticuno = new( - 144, // Articuno - new[] { - new NPCLock(112), // Shadow Rhydon - new NPCLock(146), // Shadow Moltres - new NPCLock(103), // Shadow Exeggutor - new NPCLock(128), // Shadow Tauros - }); - - public static readonly TeamLock XZapdos = new( - 145, // Zapdos - new[] { - new NPCLock(112), // Shadow Rhydon - new NPCLock(146), // Shadow Moltres - new NPCLock(103), // Shadow Exeggutor - new NPCLock(128), // Shadow Tauros - new NPCLock(144), // Shadow Articuno - }); - - public static readonly TeamLock XExeggutorRhydonMoltresSeen = new( - 103, // Exeggutor - "Rhydon & Moltres Seen", - new[] { - new NPCLock(112, true), // Shadow Rhydon (Seen) - new NPCLock(146, true), // Shadow Moltres (Seen) - }); - - public static readonly TeamLock XTaurosRhydonMoltresSeen = new( - 128, // Tauros - "Rhydon & Moltres Seen", - new[] { - new NPCLock(112, true), // Shadow Rhydon (Seen) - new NPCLock(146, true), // Shadow Moltres (Seen) - new NPCLock(103), // Shadow Exeggutor - }); - - public static readonly TeamLock XTaurosRhydonMoltresExeggutorSeen = new( - 128, // Tauros - "Rhydon & Moltres & Exeggutor Seen", - new[] { - new NPCLock(112, true), // Shadow Rhydon (Seen) - new NPCLock(146, true), // Shadow Moltres (Seen) - new NPCLock(103, true), // Shadow Exeggutor (Seen) - }); - - public static readonly TeamLock XArticunoRhydonMoltresSeen = new( - 144, // Articuno - "Rhydon & Moltres Seen", - new[] { - new NPCLock(112, true), // Shadow Rhydon (Seen) - new NPCLock(146, true), // Shadow Moltres (Seen) - new NPCLock(103), // Shadow Exeggutor - new NPCLock(128), // Shadow Tauros - }); - - public static readonly TeamLock XArticunoRhydonMoltresTaurosSeen = new( - 144, // Articuno - "Rhydon & Moltres & Tauros Seen", - new[] { - new NPCLock(112, true), // Shadow Rhydon (Seen) - new NPCLock(146, true), // Shadow Moltres (Seen) - new NPCLock(103), // Shadow Exeggutor - new NPCLock(128, true), // Shadow Tauros (Seen) - }); - - public static readonly TeamLock XArticunoRhydonMoltresExeggutorSeen = new( - 144, // Articuno - "Rhydon & Moltres & Exeggutor Seen", - new[] { - new NPCLock(112, true), // Shadow Rhydon (Seen) - new NPCLock(146, true), // Shadow Moltres (Seen) - new NPCLock(103, true), // Shadow Exeggutor (Seen) - new NPCLock(128), // Shadow Tauros - }); - - public static readonly TeamLock XArticunoRhydonMoltresExeggutorTaurosSeen = new( - 144, // Articuno - "Rhydon & Moltres & Exeggutor & Tauros Seen", - new[] { - new NPCLock(112, true), // Shadow Rhydon (Seen) - new NPCLock(146, true), // Shadow Moltres (Seen) - new NPCLock(103, true), // Shadow Exeggutor (Seen) - new NPCLock(128, true), // Shadow Tauros (Seen) - }); - - public static readonly TeamLock XZapdosRhydonMoltresSeen = new( - 145, // Zapdos - "Rhydon & Moltres Seen", - new[] { - new NPCLock(112, true), // Shadow Rhydon (Seen) - new NPCLock(146, true), // Shadow Moltres (Seen) - new NPCLock(103), // Shadow Exeggutor - new NPCLock(128), // Shadow Tauros - new NPCLock(144), // Shadow Articuno - }); - - public static readonly TeamLock XZapdosRhydonMoltresTaurosSeen = new( - 145, // Zapdos - "Rhydon & Moltres & Tauros Seen", - new[] { - new NPCLock(112, true), // Shadow Rhydon (Seen) - new NPCLock(146, true), // Shadow Moltres (Seen) - new NPCLock(103), // Shadow Exeggutor - new NPCLock(128, true), // Shadow Tauros (Seen) - new NPCLock(144), // Shadow Articuno - }); - - public static readonly TeamLock XZapdosRhydonMoltresArticunoSeen = new( - 145, // Zapdos - "Rhydon & Moltres & Articuno Seen", - new[] { - new NPCLock(112, true), // Shadow Rhydon (Seen) - new NPCLock(146, true), // Shadow Moltres (Seen) - new NPCLock(103), // Shadow Exeggutor - new NPCLock(128), // Shadow Tauros - new NPCLock(144, true), // Shadow Articuno (Seen) - }); - - public static readonly TeamLock XZapdosRhydonMoltresExeggutorSeen = new( - 145, // Zapdos - "Rhydon & Moltres & Exeggutor Seen", - new[] { - new NPCLock(112, true), // Shadow Rhydon (Seen) - new NPCLock(146, true), // Shadow Moltres (Seen) - new NPCLock(103, true), // Shadow Exeggutor (Seen) - new NPCLock(128), // Shadow Tauros - new NPCLock(144), // Shadow Articuno - }); - - public static readonly TeamLock XZapdosRhydonMoltresTaurosArticunoSeen = new( - 145, // Zapdos - "Rhydon & Moltres & Tauros & Articuno Seen", - new[] { - new NPCLock(112, true), // Shadow Rhydon (Seen) - new NPCLock(146, true), // Shadow Moltres (Seen) - new NPCLock(103), // Shadow Exeggutor - new NPCLock(128, true), // Shadow Tauros (Seen) - new NPCLock(144, true), // Shadow Articuno (Seen) - }); - - public static readonly TeamLock XZapdosRhydonMoltresExeggutorTaurosSeen = new( - 145, // Zapdos - "Rhydon & Moltres & Exeggutor & Tauros Seen", - new[] { - new NPCLock(112, true), // Shadow Rhydon (Seen) - new NPCLock(146, true), // Shadow Moltres (Seen) - new NPCLock(103, true), // Shadow Exeggutor (Seen) - new NPCLock(128, true), // Shadow Tauros (Seen) - new NPCLock(144), // Shadow Articuno - }); - - public static readonly TeamLock XZapdosRhydonMoltresExeggutorArticunoSeen = new( - 145, // Zapdos - "Rhydon & Moltres & Exeggutor & Articuno Seen", - new[] { - new NPCLock(112, true), // Shadow Rhydon (Seen) - new NPCLock(146, true), // Shadow Moltres (Seen) - new NPCLock(103, true), // Shadow Exeggutor (Seen) - new NPCLock(128), // Shadow Tauros - new NPCLock(144, true), // Shadow Articuno (Seen) - }); - - public static readonly TeamLock XZapdosRhydonMoltresExeggutorTaurosArticunoSeen = new( - 145, // Zapdos - "Rhydon & Moltres & Exeggutor & Tauros & Articuno Seen", - new[] { - new NPCLock(112, true), // Shadow Rhydon (Seen) - new NPCLock(146, true), // Shadow Moltres (Seen) - new NPCLock(103, true), // Shadow Exeggutor (Seen) - new NPCLock(128, true), // Shadow Tauros (Seen) - new NPCLock(144, true), // Shadow Articuno (Seen) - }); - - public static readonly TeamLock XDragonite = new( - 149, // Dragonite - new[] { - new NPCLock(272, 00, 0, 127), // Ludicolo (M) (Hardy) - new NPCLock(272, 18, 0, 127), // Ludicolo (M) (Bashful) - new NPCLock(272, 12, 1, 127), // Ludicolo (F) (Serious) - new NPCLock(272, 12, 1, 127), // Ludicolo (F) (Serious) - new NPCLock(272, 00, 0, 127), // Ludicolo (M) (Hardy) - }); - - #endregion } diff --git a/PKHeX.Core/Legality/Encounters/Data/Gen3/Encounters3FRLG.cs b/PKHeX.Core/Legality/Encounters/Data/Gen3/Encounters3FRLG.cs index 335115616..2b8970110 100644 --- a/PKHeX.Core/Legality/Encounters/Data/Gen3/Encounters3FRLG.cs +++ b/PKHeX.Core/Legality/Encounters/Data/Gen3/Encounters3FRLG.cs @@ -1,3 +1,4 @@ +using System; using static PKHeX.Core.EncounterUtil; using static PKHeX.Core.GameVersion; using static PKHeX.Core.AbilityPermission; @@ -69,34 +70,34 @@ internal static class Encounters3FRLG new(150, 70, FRLG) { Location = 141 }, // Mewtwo @ Cerulean Cave // Event - new(249, 70, FRLG) { Location = 174, Fateful = true }, // Lugia @ Navel Rock - new(250, 70, FRLG) { Location = 174, Fateful = true }, // Ho-Oh @ Navel Rock - new(386, 30, FR ) { Location = 187, Fateful = true, Form = 1 }, // Deoxys @ Birth Island - new(386, 30, LG) { Location = 187, Fateful = true, Form = 2 }, // Deoxys @ Birth Island + new(249, 70, FRLG) { Location = 174, FatefulEncounter = true }, // Lugia @ Navel Rock + new(250, 70, FRLG) { Location = 174, FatefulEncounter = true }, // Ho-Oh @ Navel Rock + new(386, 30, FR ) { Location = 187, FatefulEncounter = true, Form = 1 }, // Deoxys @ Birth Island + new(386, 30, LG) { Location = 187, FatefulEncounter = true, Form = 2 }, // Deoxys @ Birth Island }; private static readonly EncounterStatic3[] Encounter_FRLG = ArrayUtil.ConcatAll(Encounter_FRLG_Roam, Encounter_FRLG_Stationary); - private static readonly byte[] TradeContest_Cool = { 30, 05, 05, 05, 05, 10 }; - private static readonly byte[] TradeContest_Beauty = { 05, 30, 05, 05, 05, 10 }; - private static readonly byte[] TradeContest_Cute = { 05, 05, 30, 05, 05, 10 }; - private static readonly byte[] TradeContest_Clever = { 05, 05, 05, 30, 05, 10 }; - private static readonly byte[] TradeContest_Tough = { 05, 05, 05, 05, 30, 10 }; + private static ReadOnlySpan TradeContest_Cool => new byte[] { 30, 05, 05, 05, 05, 10 }; + private static ReadOnlySpan TradeContest_Beauty => new byte[] { 05, 30, 05, 05, 05, 10 }; + private static ReadOnlySpan TradeContest_Cute => new byte[] { 05, 05, 30, 05, 05, 10 }; + private static ReadOnlySpan TradeContest_Clever => new byte[] { 05, 05, 05, 30, 05, 10 }; + private static ReadOnlySpan TradeContest_Tough => new byte[] { 05, 05, 05, 05, 30, 10 }; internal static readonly EncounterTrade3[] TradeGift_FRLG = { - new(FRLG, 0x00009CAE, 122, 05) { Ability = OnlyFirst, TID = 01985, SID = 00000, OTGender = 0, Gender = 0, IVs = new(20,15,17,24,23,22), Contest = TradeContest_Clever }, // Abra (Level 5 Breeding) -> Mr. Mime - new(FR , 0x4C970B89, 029, 05) { Ability = OnlyFirst, TID = 63184, SID = 00000, OTGender = 1, Gender = 1, IVs = new(22,18,25,19,15,22), Contest = TradeContest_Tough }, // Nidoran♀ - new( LG, 0x4C970B9E, 032, 05) { Ability = OnlyFirst, TID = 63184, SID = 00000, OTGender = 1, Gender = 0, IVs = new(19,25,18,22,22,15), Contest = TradeContest_Cool }, // Nidoran♂ * - new(FR , 0x00EECA15, 030, 16) { Ability = OnlyFirst, TID = 13637, SID = 00000, OTGender = 0, Gender = 1, IVs = new(22,25,18,19,22,15), Contest = TradeContest_Cute }, // Nidorina * - new( LG, 0x00EECA19, 033, 16) { Ability = OnlyFirst, TID = 13637, SID = 00000, OTGender = 0, Gender = 0, IVs = new(19,18,25,22,15,22), Contest = TradeContest_Tough }, // Nidorino * - new(FR , 0x451308AB, 108, 25) { Ability = OnlyFirst, TID = 01239, SID = 00000, OTGender = 0, Gender = 0, IVs = new(24,19,21,15,23,21), Contest = TradeContest_Tough }, // Golduck (Level 25) -> Lickitung * - new( LG, 0x451308AB, 108, 25) { Ability = OnlyFirst, TID = 01239, SID = 00000, OTGender = 0, Gender = 0, IVs = new(24,19,21,15,23,21), Contest = TradeContest_Tough }, // Slowbro (Level 25) -> Lickitung * - new(FRLG, 0x498A2E1D, 124, 20) { Ability = OnlyFirst, TID = 36728, SID = 00000, OTGender = 0, Gender = 1, IVs = new(18,17,18,22,25,21), Contest = TradeContest_Beauty }, // Poliwhirl (Level 20) -> Jynx - new(FRLG, 0x151943D7, 083, 03) { Ability = OnlyFirst, TID = 08810, SID = 00000, OTGender = 0, Gender = 0, IVs = new(20,25,21,24,15,20), Contest = TradeContest_Cool }, // Spearow (Level 3 Capture) -> Farfetch'd - new(FRLG, 0x06341016, 101, 03) { Ability = OnlySecond, TID = 50298, SID = 00000, OTGender = 0, Gender = 2, IVs = new(19,16,18,25,25,19), Contest = TradeContest_Cool }, // Raichu (Level 3) -> Electrode - new(FRLG, 0x5C77ECFA, 114, 05) { Ability = OnlyFirst, TID = 60042, SID = 00000, OTGender = 1, Gender = 0, IVs = new(22,17,25,16,23,20), Contest = TradeContest_Cute }, // Venonat (Level 5 Breeding) -> Tangela - new(FRLG, 0x482CAC89, 086, 05) { Ability = OnlyFirst, TID = 09853, SID = 00000, OTGender = 0, Gender = 0, IVs = new(24,15,22,16,23,22), Contest = TradeContest_Tough }, // Ponyta (Level 5 Breeding) -> Seel * + new(FRLG, 0x00009CAE, 122, 05) { Ability = OnlyFirst, TID16 = 01985, SID16 = 00000, OTGender = 0, Gender = 0, IVs = new(20,15,17,24,23,22), Contest = TradeContest_Clever }, // Abra (Level 5 Breeding) -> Mr. Mime + new(FR , 0x4C970B89, 029, 05) { Ability = OnlyFirst, TID16 = 63184, SID16 = 00000, OTGender = 1, Gender = 1, IVs = new(22,18,25,19,15,22), Contest = TradeContest_Tough }, // Nidoran♀ + new( LG, 0x4C970B9E, 032, 05) { Ability = OnlyFirst, TID16 = 63184, SID16 = 00000, OTGender = 1, Gender = 0, IVs = new(19,25,18,22,22,15), Contest = TradeContest_Cool }, // Nidoran♂ * + new(FR , 0x00EECA15, 030, 16) { Ability = OnlyFirst, TID16 = 13637, SID16 = 00000, OTGender = 0, Gender = 1, IVs = new(22,25,18,19,22,15), Contest = TradeContest_Cute }, // Nidorina * + new( LG, 0x00EECA19, 033, 16) { Ability = OnlyFirst, TID16 = 13637, SID16 = 00000, OTGender = 0, Gender = 0, IVs = new(19,18,25,22,15,22), Contest = TradeContest_Tough }, // Nidorino * + new(FR , 0x451308AB, 108, 25) { Ability = OnlyFirst, TID16 = 01239, SID16 = 00000, OTGender = 0, Gender = 0, IVs = new(24,19,21,15,23,21), Contest = TradeContest_Tough }, // Golduck (Level 25) -> Lickitung * + new( LG, 0x451308AB, 108, 25) { Ability = OnlyFirst, TID16 = 01239, SID16 = 00000, OTGender = 0, Gender = 0, IVs = new(24,19,21,15,23,21), Contest = TradeContest_Tough }, // Slowbro (Level 25) -> Lickitung * + new(FRLG, 0x498A2E1D, 124, 20) { Ability = OnlyFirst, TID16 = 36728, SID16 = 00000, OTGender = 0, Gender = 1, IVs = new(18,17,18,22,25,21), Contest = TradeContest_Beauty }, // Poliwhirl (Level 20) -> Jynx + new(FRLG, 0x151943D7, 083, 03) { Ability = OnlyFirst, TID16 = 08810, SID16 = 00000, OTGender = 0, Gender = 0, IVs = new(20,25,21,24,15,20), Contest = TradeContest_Cool }, // Spearow (Level 3 Capture) -> Farfetch'd + new(FRLG, 0x06341016, 101, 03) { Ability = OnlySecond, TID16 = 50298, SID16 = 00000, OTGender = 0, Gender = 2, IVs = new(19,16,18,25,25,19), Contest = TradeContest_Cool }, // Raichu (Level 3) -> Electrode + new(FRLG, 0x5C77ECFA, 114, 05) { Ability = OnlyFirst, TID16 = 60042, SID16 = 00000, OTGender = 1, Gender = 0, IVs = new(22,17,25,16,23,20), Contest = TradeContest_Cute }, // Venonat (Level 5 Breeding) -> Tangela + new(FRLG, 0x482CAC89, 086, 05) { Ability = OnlyFirst, TID16 = 09853, SID16 = 00000, OTGender = 0, Gender = 0, IVs = new(24,15,22,16,23,22), Contest = TradeContest_Tough }, // Ponyta (Level 5 Breeding) -> Seel * // If Pokémon with * is evolved in a Generation IV or V game, its Ability will become its second Ability. }; diff --git a/PKHeX.Core/Legality/Encounters/Data/Gen3/Encounters3RSE.cs b/PKHeX.Core/Legality/Encounters/Data/Gen3/Encounters3RSE.cs index f4d0898f6..f251af42b 100644 --- a/PKHeX.Core/Legality/Encounters/Data/Gen3/Encounters3RSE.cs +++ b/PKHeX.Core/Legality/Encounters/Data/Gen3/Encounters3RSE.cs @@ -1,3 +1,4 @@ +using System; using static PKHeX.Core.EncounterUtil; using static PKHeX.Core.GameVersion; using static PKHeX.Core.AbilityPermission; @@ -58,9 +59,9 @@ internal static class Encounters3RSE new(378, 40, RSE) { Location = 081 }, // Regice @ Island Cave new(379, 40, RSE) { Location = 083 }, // Registeel @ Ancient Tomb new(380, 50, R ) { Location = 073 }, // Latias @ Southern Island - new(380, 50, E) { Location = 073, Fateful = true }, // Latias @ Southern Island + new(380, 50, E) { Location = 073, FatefulEncounter = true }, // Latias @ Southern Island new(381, 50, S ) { Location = 073 }, // Latios @ Southern Island - new(381, 50, E) { Location = 073, Fateful = true }, // Latios @ Southern Island + new(381, 50, E) { Location = 073, FatefulEncounter = true }, // Latios @ Southern Island new(382, 45, S ) { Location = 072 }, // Kyogre @ Cave of Origin new(382, 70, E) { Location = 203 }, // Kyogre @ Marine Cave new(383, 45, R ) { Location = 072 }, // Groudon @ Cave of Origin @@ -68,29 +69,29 @@ internal static class Encounters3RSE new(384, 70, RSE) { Location = 085 }, // Rayquaza @ Sky Pillar // Event - new(151, 30, E) { Location = 201, Fateful = true }, // Mew @ Faraway Island (Unreleased outside of Japan) - new(249, 70, E) { Location = 211, Fateful = true }, // Lugia @ Navel Rock - new(250, 70, E) { Location = 211, Fateful = true }, // Ho-Oh @ Navel Rock - new(386, 30, E) { Location = 200, Fateful = true, Form = 3 }, // Deoxys @ Birth Island + new(151, 30, E) { Location = 201, FatefulEncounter = true }, // Mew @ Faraway Island (Unreleased outside of Japan) + new(249, 70, E) { Location = 211, FatefulEncounter = true }, // Lugia @ Navel Rock + new(250, 70, E) { Location = 211, FatefulEncounter = true }, // Ho-Oh @ Navel Rock + new(386, 30, E) { Location = 200, FatefulEncounter = true, Form = 3 }, // Deoxys @ Birth Island }; private static readonly EncounterStatic3[] Encounter_RSE = ArrayUtil.ConcatAll(Encounter_RSE_Roam, Encounter_RSE_Regular); - private static readonly byte[] TradeContest_Cool = { 30, 05, 05, 05, 05, 10 }; - private static readonly byte[] TradeContest_Beauty = { 05, 30, 05, 05, 05, 10 }; - private static readonly byte[] TradeContest_Cute = { 05, 05, 30, 05, 05, 10 }; - private static readonly byte[] TradeContest_Clever = { 05, 05, 05, 30, 05, 10 }; - private static readonly byte[] TradeContest_Tough = { 05, 05, 05, 05, 30, 10 }; + private static ReadOnlySpan TradeContest_Cool => new byte[] { 30, 05, 05, 05, 05, 10 }; + private static ReadOnlySpan TradeContest_Beauty => new byte[] { 05, 30, 05, 05, 05, 10 }; + private static ReadOnlySpan TradeContest_Cute => new byte[] { 05, 05, 30, 05, 05, 10 }; + private static ReadOnlySpan TradeContest_Clever => new byte[] { 05, 05, 05, 30, 05, 10 }; + private static ReadOnlySpan TradeContest_Tough => new byte[] { 05, 05, 05, 05, 30, 10 }; internal static readonly EncounterTrade3[] TradeGift_RSE = { - new(RS, 0x00009C40, 296, 05) { Ability = OnlySecond, TID = 49562, SID = 00000, OTGender = 0, Gender = 0, IVs = new(5,5,4,4,4,4), Contest = TradeContest_Tough }, // Slakoth (Level 5 Breeding) -> Makuhita - new(RS, 0x498A2E17, 300, 03) { Ability = OnlyFirst, TID = 02259, SID = 00000, OTGender = 1, Gender = 1, IVs = new(5,4,4,5,4,4), Contest = TradeContest_Cute }, // Pikachu (Level 3 Viridian Forest) -> Skitty - new(RS, 0x4C970B7F, 222, 21) { Ability = OnlySecond, TID = 50183, SID = 00000, OTGender = 1, Gender = 1, IVs = new(4,4,5,4,4,5), Contest = TradeContest_Beauty }, // Bellossom (Level 21 Oddish -> Gloom -> Bellossom) -> Corsola - new(E , 0x00000084, 273, 04) { Ability = OnlySecond, TID = 38726, SID = 00000, OTGender = 0, Gender = 0, IVs = new(5,4,5,4,4,4), Contest = TradeContest_Cool }, // Ralts (Level 4 Route 102) -> Seedot - new(E , 0x0000006F, 311, 05) { Ability = OnlyFirst, TID = 08460, SID = 00001, OTGender = 0, Gender = 1, IVs = new(4,4,4,5,5,4), Contest = TradeContest_Cute }, // Volbeat (Level 5 Breeding) -> Plusle - new(E , 0x0000007F, 116, 05) { Ability = OnlyFirst, TID = 46285, SID = 00000, OTGender = 0, Gender = 0, IVs = new(5,4,4,4,5,4), Contest = TradeContest_Tough }, // Bagon (Level 5 Breeding) -> Horsea* - new(E , 0x0000008B, 052, 03) { Ability = OnlyFirst, TID = 25945, SID = 00001, OTGender = 1, Gender = 0, IVs = new(4,5,4,5,4,4), Contest = TradeContest_Clever }, // Skitty (Level 3 Trade)-> Meowth* + new(RS, 0x00009C40, 296, 05) { Ability = OnlySecond, TID16 = 49562, SID16 = 00000, OTGender = 0, Gender = 0, IVs = new(5,5,4,4,4,4), Contest = TradeContest_Tough }, // Slakoth (Level 5 Breeding) -> Makuhita + new(RS, 0x498A2E17, 300, 03) { Ability = OnlyFirst, TID16 = 02259, SID16 = 00000, OTGender = 1, Gender = 1, IVs = new(5,4,4,5,4,4), Contest = TradeContest_Cute }, // Pikachu (Level 3 Viridian Forest) -> Skitty + new(RS, 0x4C970B7F, 222, 21) { Ability = OnlySecond, TID16 = 50183, SID16 = 00000, OTGender = 1, Gender = 1, IVs = new(4,4,5,4,4,5), Contest = TradeContest_Beauty }, // Bellossom (Level 21 Oddish -> Gloom -> Bellossom) -> Corsola + new(E , 0x00000084, 273, 04) { Ability = OnlySecond, TID16 = 38726, SID16 = 00000, OTGender = 0, Gender = 0, IVs = new(5,4,5,4,4,4), Contest = TradeContest_Cool }, // Ralts (Level 4 Route 102) -> Seedot + new(E , 0x0000006F, 311, 05) { Ability = OnlyFirst, TID16 = 08460, SID16 = 00001, OTGender = 0, Gender = 1, IVs = new(4,4,4,5,5,4), Contest = TradeContest_Cute }, // Volbeat (Level 5 Breeding) -> Plusle + new(E , 0x0000007F, 116, 05) { Ability = OnlyFirst, TID16 = 46285, SID16 = 00000, OTGender = 0, Gender = 0, IVs = new(5,4,4,4,5,4), Contest = TradeContest_Tough }, // Bagon (Level 5 Breeding) -> Horsea* + new(E , 0x0000008B, 052, 03) { Ability = OnlyFirst, TID16 = 25945, SID16 = 00001, OTGender = 1, Gender = 0, IVs = new(4,5,4,5,4,4), Contest = TradeContest_Clever }, // Skitty (Level 3 Trade)-> Meowth* // If Pokémon with * is evolved in a Generation IV or V game, its Ability will become its second Ability. }; diff --git a/PKHeX.Core/Legality/Encounters/Data/Gen3/Encounters3XD.cs b/PKHeX.Core/Legality/Encounters/Data/Gen3/Encounters3XD.cs index 2a94c550d..d6e16d7ec 100644 --- a/PKHeX.Core/Legality/Encounters/Data/Gen3/Encounters3XD.cs +++ b/PKHeX.Core/Legality/Encounters/Data/Gen3/Encounters3XD.cs @@ -6,104 +6,104 @@ internal static class Encounters3XD { private static readonly EncounterStatic3[] Encounter_XDGift = { - new(133, 10, GameVersion.XD) { Fateful = true, Gift = true, Location = 000, Moves = new(044) }, // Eevee (Bite) - new(152, 05, GameVersion.XD) { Fateful = true, Gift = true, Location = 016, Moves = new(246,033,045,338) }, // Chikorita - new(155, 05, GameVersion.XD) { Fateful = true, Gift = true, Location = 016, Moves = new(179,033,043,307) }, // Cyndaquil - new(158, 05, GameVersion.XD) { Fateful = true, Gift = true, Location = 016, Moves = new(242,010,043,308) }, // Totodile + new(133, 10, GameVersion.XD) { FatefulEncounter = true, Gift = true, Location = 000, Moves = new(044) }, // Eevee (Bite) + new(152, 05, GameVersion.XD) { FatefulEncounter = true, Gift = true, Location = 016, Moves = new(246,033,045,338) }, // Chikorita + new(155, 05, GameVersion.XD) { FatefulEncounter = true, Gift = true, Location = 016, Moves = new(179,033,043,307) }, // Cyndaquil + new(158, 05, GameVersion.XD) { FatefulEncounter = true, Gift = true, Location = 016, Moves = new(242,010,043,308) }, // Totodile }; private static readonly EncounterStaticShadow[] Encounter_XD = { - new(GameVersion.XD, 01, 03000, First) { Fateful = true, Species = 216, Level = 11, Moves = new(216,287,122,232), Location = 143, Gift = true }, // Teddiursa: Cipher Peon Naps @ Pokémon HQ Lab -- treat as Gift as it can only be captured in a Poké Ball - new(GameVersion.XD, 02, 02000, Vulpix) { Fateful = true, Species = 037, Level = 18, Moves = new(257,204,052,091), Location = 109 }, // Vulpix: Cipher Peon Mesin @ ONBS Building - new(GameVersion.XD, 03, 01500, Spheal) { Fateful = true, Species = 363, Level = 17, Moves = new(062,204,055,189), Location = 011 }, // Spheal: Cipher Peon Blusix @ Cipher Lab - new(GameVersion.XD, 03, 01500, Spheal) { Fateful = true, Species = 363, Level = 17, Moves = new(062,204,055,189), Location = 100 }, // Spheal: Cipher Peon Blusix @ Phenac City - new(GameVersion.XD, 04, 01500, First) { Fateful = true, Species = 343, Level = 17, Moves = new(317,287,189,060), Location = 011 }, // Baltoy: Cipher Peon Browsix @ Cipher Lab - new(GameVersion.XD, 04, 01500, First) { Fateful = true, Species = 343, Level = 17, Moves = new(317,287,189,060), Location = 096 }, // Baltoy: Cipher Peon Browsix @ Phenac City - new(GameVersion.XD, 05, 01500, First) { Fateful = true, Species = 179, Level = 17, Moves = new(034,215,084,086), Location = 011 }, // Mareep: Cipher Peon Yellosix @ Cipher Lab - new(GameVersion.XD, 05, 01500, First) { Fateful = true, Species = 179, Level = 17, Moves = new(034,215,084,086), Location = 096 }, // Mareep: Cipher Peon Yellosix @ Phenac City - new(GameVersion.XD, 06, 01500, Gulpin) { Fateful = true, Species = 316, Level = 17, Moves = new(351,047,124,092), Location = 011 }, // Gulpin: Cipher Peon Purpsix @ Cipher Lab - new(GameVersion.XD, 06, 01500, Gulpin) { Fateful = true, Species = 316, Level = 17, Moves = new(351,047,124,092), Location = 100 }, // Gulpin: Cipher Peon Purpsix @ Phenac City - new(GameVersion.XD, 07, 01500, Seedot) { Fateful = true, Species = 273, Level = 17, Moves = new(202,287,331,290), Location = 011 }, // Seedot: Cipher Peon Greesix @ Cipher Lab - new(GameVersion.XD, 07, 01500, Seedot) { Fateful = true, Species = 273, Level = 17, Moves = new(202,287,331,290), Location = 100 }, // Seedot: Cipher Peon Greesix @ Phenac City - new(GameVersion.XD, 08, 01500, Spinarak) { Fateful = true, Species = 167, Level = 14, Moves = new(091,287,324,101), Location = 010 }, // Spinarak: Cipher Peon Nexir @ Cipher Lab - new(GameVersion.XD, 09, 01500, Numel) { Fateful = true, Species = 322, Level = 14, Moves = new(036,204,091,052), Location = 009 }, // Numel: Cipher Peon Solox @ Cipher Lab - new(GameVersion.XD, 10, 01700, First) { Fateful = true, Species = 318, Level = 15, Moves = new(352,287,184,044), Location = 008 }, // Carvanha: Cipher Peon Cabol @ Cipher Lab - new(GameVersion.XD, 11, 03000, Roselia) { Fateful = true, Species = 315, Level = 22, Moves = new(345,186,320,073), Location = 094 }, // Roselia: Cipher Peon Fasin @ Phenac City - new(GameVersion.XD, 12, 02500, Delcatty) { Fateful = true, Species = 301, Level = 18, Moves = new(290,186,213,351), Location = 008 }, // Delcatty: Cipher Admin Lovrina @ Cipher Lab - new(GameVersion.XD, 13, 04000, Nosepass) { Fateful = true, Species = 299, Level = 26, Moves = new(085,270,086,157), Location = 090 }, // Nosepass: Wanderer Miror B. @ Poké Spots - new(GameVersion.XD, 14, 01500, First) { Fateful = true, Species = 228, Level = 17, Moves = new(185,204,052,046), Location = 100 }, // Houndour: Cipher Peon Resix @ Phenac City - new(GameVersion.XD, 14, 01500, First) { Fateful = true, Species = 228, Level = 17, Moves = new(185,204,052,046), Location = 011 }, // Houndour: Cipher Peon Resix @ Cipher Lab - new(GameVersion.XD, 15, 02000, Makuhita) { Fateful = true, Species = 296, Level = 18, Moves = new(280,287,292,317), Location = 109 }, // Makuhita: Cipher Peon Torkin @ ONBS Building - new(GameVersion.XD, 16, 02200, Duskull) { Fateful = true, Species = 355, Level = 19, Moves = new(247,270,310,109), Location = 110 }, // Duskull: Cipher Peon Lobar @ ONBS Building - new(GameVersion.XD, 17, 02200, Ralts) { Fateful = true, Species = 280, Level = 20, Moves = new(351,047,115,093), Location = 119 }, // Ralts: Cipher Peon Feldas @ ONBS Building - new(GameVersion.XD, 18, 02500, Mawile) { Fateful = true, Species = 303, Level = 22, Moves = new(206,047,011,334), Location = 111 }, // Mawile: Cipher Cmdr Exol @ ONBS Building - new(GameVersion.XD, 19, 02500, Snorunt) { Fateful = true, Species = 361, Level = 20, Moves = new(352,047,044,196), Location = 097 }, // Snorunt: Cipher Peon Exinn @ Phenac City - new(GameVersion.XD, 20, 02500, Pineco) { Fateful = true, Species = 204, Level = 20, Moves = new(042,287,191,068), Location = 096 }, // Pineco: Cipher Peon Gonrap @ Phenac City - new(GameVersion.XD, 21, 02500, Swinub) { Fateful = true, Species = 220, Level = 22, Moves = new(246,204,054,341), Location = 100 }, // Swinub: Cipher Peon Greck @ Phenac City - new(GameVersion.XD, 22, 02500, Natu) { Fateful = true, Species = 177, Level = 22, Moves = new(248,226,101,332), Location = 094 }, // Natu: Cipher Peon Eloin @ Phenac City - new(GameVersion.XD, 23, 01800, Shroomish) { Fateful = true, Species = 285, Level = 15, Moves = new(206,287,072,078), Location = 008 }, // Shroomish: Cipher R&D Klots @ Cipher Lab - new(GameVersion.XD, 24, 03500, Meowth) { Fateful = true, Species = 052, Level = 22, Moves = new(163,047,006,044), Location = 094 }, // Meowth: Cipher Peon Fostin @ Phenac City - new(GameVersion.XD, 25, 04500, Spearow) { Fateful = true, Species = 021, Level = 22, Moves = new(206,226,043,332), Location = 107 }, // Spearow: Cipher Peon Ezin @ Phenac Stadium - new(GameVersion.XD, 26, 03000, Grimer) { Fateful = true, Species = 088, Level = 23, Moves = new(188,270,325,107), Location = 107 }, // Grimer: Cipher Peon Faltly @ Phenac Stadium - new(GameVersion.XD, 27, 03500, Seel) { Fateful = true, Species = 086, Level = 23, Moves = new(057,270,219,058), Location = 107 }, // Seel: Cipher Peon Egrog @ Phenac Stadium - new(GameVersion.XD, 28, 05000, Lunatone) { Fateful = true, Species = 337, Level = 25, Moves = new(094,226,240,317), Location = 107 }, // Lunatone: Cipher Admin Snattle @ Phenac Stadium - new(GameVersion.XD, 29, 02500, Voltorb) { Fateful = true, Species = 100, Level = 19, Moves = new(243,287,209,129), Location = 092 }, // Voltorb: Wanderer Miror B. @ Cave Poké Spot - new(GameVersion.XD, 30, 05000, First) { Fateful = true, Species = 335, Level = 28, Moves = new(280,287,068,306), Location = 071 }, // Zangoose: Thug Zook @ Cipher Key Lair - new(GameVersion.XD, 31, 04000, Growlithe) { Fateful = true, Species = 058, Level = 28, Moves = new(053,204,044,036), Location = 064 }, // Growlithe: Cipher Peon Humah @ Cipher Key Lair - new(GameVersion.XD, 32, 04000, Paras) { Fateful = true, Species = 046, Level = 28, Moves = new(147,287,163,206), Location = 064 }, // Paras: Cipher Peon Humah @ Cipher Key Lair - new(GameVersion.XD, 33, 04000, First) { Fateful = true, Species = 090, Level = 29, Moves = new(036,287,057,062), Location = 065 }, // Shellder: Cipher Peon Gorog @ Cipher Key Lair - new(GameVersion.XD, 34, 04500, First) { Fateful = true, Species = 015, Level = 30, Moves = new(188,226,041,014), Location = 066 }, // Beedrill: Cipher Peon Lok @ Cipher Key Lair - new(GameVersion.XD, 35, 04000, Pidgeotto) { Fateful = true, Species = 017, Level = 30, Moves = new(017,287,211,297), Location = 066 }, // Pidgeotto: Cipher Peon Lok @ Cipher Key Lair - new(GameVersion.XD, 36, 04000, Butterfree){ Fateful = true, Species = 012, Level = 30, Moves = new(094,234,079,332), Location = 067 }, // Butterfree: Cipher Peon Targ @ Cipher Key Lair - new(GameVersion.XD, 37, 04000, Tangela) { Fateful = true, Species = 114, Level = 30, Moves = new(076,234,241,275), Location = 067 }, // Tangela: Cipher Peon Targ @ Cipher Key Lair - new(GameVersion.XD, 38, 06000, Raticate) { Fateful = true, Species = 020, Level = 34, Moves = new(162,287,184,158), Location = 076 }, // Raticate: Chaser Furgy @ Citadark Isle - new(GameVersion.XD, 39, 04000, Venomoth) { Fateful = true, Species = 049, Level = 32, Moves = new(318,287,164,094), Location = 070 }, // Venomoth: Cipher Peon Angic @ Cipher Key Lair - new(GameVersion.XD, 40, 04000, Weepinbell){ Fateful = true, Species = 070, Level = 32, Moves = new(345,234,188,230), Location = 070 }, // Weepinbell: Cipher Peon Angic @ Cipher Key Lair - new(GameVersion.XD, 41, 05000, Arbok) { Fateful = true, Species = 024, Level = 33, Moves = new(188,287,137,044), Location = 070 }, // Arbok: Cipher Peon Smarton @ Cipher Key Lair - new(GameVersion.XD, 42, 06000, Primeape) { Fateful = true, Species = 057, Level = 34, Moves = new(238,270,116,179), Location = 069 }, // Primeape: Cipher Admin Gorigan @ Cipher Key Lair - new(GameVersion.XD, 43, 05500, Hypno) { Fateful = true, Species = 097, Level = 34, Moves = new(094,226,096,247), Location = 069 }, // Hypno: Cipher Admin Gorigan @ Cipher Key Lair - new(GameVersion.XD, 44, 06500, Golduck) { Fateful = true, Species = 055, Level = 33, Moves = new(127,204,244,280), Location = 088 }, // Golduck: Navigator Abson @ Citadark Isle - new(GameVersion.XD, 45, 07000, Sableye) { Fateful = true, Species = 302, Level = 33, Moves = new(247,270,185,105), Location = 088 }, // Sableye: Navigator Abson @ Citadark Isle - new(GameVersion.XD, 46, 04500, Magneton) { Fateful = true, Species = 082, Level = 30, Moves = new(038,287,240,087), Location = 067 }, // Magneton: Cipher Peon Snidle @ Cipher Key Lair - new(GameVersion.XD, 47, 08000, Dodrio) { Fateful = true, Species = 085, Level = 34, Moves = new(065,226,097,161), Location = 076 }, // Dodrio: Chaser Furgy @ Citadark Isle - new(GameVersion.XD, 48, 05500, Farfetchd) { Fateful = true, Species = 083, Level = 36, Moves = new(163,226,014,332), Location = 076 }, // Farfetch'd: Cipher Admin Lovrina @ Citadark Isle - new(GameVersion.XD, 49, 06500, Altaria) { Fateful = true, Species = 334, Level = 36, Moves = new(225,215,076,332), Location = 076 }, // Altaria: Cipher Admin Lovrina @ Citadark Isle - new(GameVersion.XD, 50, 06000, Kangaskhan){ Fateful = true, Species = 115, Level = 35, Moves = new(089,047,039,146), Location = 085 }, // Kangaskhan: Cipher Peon Litnar @ Citadark Isle - new(GameVersion.XD, 51, 07000, Banette) { Fateful = true, Species = 354, Level = 37, Moves = new(185,270,247,174), Location = 085 }, // Banette: Cipher Peon Litnar @ Citadark Isle - new(GameVersion.XD, 52, 07000, Magmar) { Fateful = true, Species = 126, Level = 36, Moves = new(126,266,238,009), Location = 077 }, // Magmar: Cipher Peon Grupel @ Citadark Isle - new(GameVersion.XD, 53, 07000, Pinsir) { Fateful = true, Species = 127, Level = 35, Moves = new(012,270,206,066), Location = 077 }, // Pinsir: Cipher Peon Grupel @ Citadark Isle - new(GameVersion.XD, 54, 05500, Magcargo) { Fateful = true, Species = 219, Level = 38, Moves = new(257,287,089,053), Location = 080 }, // Magcargo: Cipher Peon Kolest @ Citadark Isle - new(GameVersion.XD, 55, 06000, Rapidash) { Fateful = true, Species = 078, Level = 40, Moves = new(076,226,241,053), Location = 080 }, // Rapidash: Cipher Peon Kolest @ Citadark Isle - new(GameVersion.XD, 56, 06000, Hitmonchan){ Fateful = true, Species = 107, Level = 38, Moves = new(005,270,170,327), Location = 081 }, // Hitmonchan: Cipher Peon Karbon @ Citadark Isle - new(GameVersion.XD, 57, 07000, Hitmonlee) { Fateful = true, Species = 106, Level = 38, Moves = new(136,287,170,025), Location = 081 }, // Hitmonlee: Cipher Peon Petro @ Citadark Isle - new(GameVersion.XD, 58, 05000, Lickitung) { Fateful = true, Species = 108, Level = 38, Moves = new(038,270,111,205), Location = 084 }, // Lickitung: Cipher Peon Geftal @ Citadark Isle - new(GameVersion.XD, 59, 08000, Scyther) { Fateful = true, Species = 123, Level = 40, Moves = new(013,234,318,163), Location = 084 }, // Scyther: Cipher Peon Leden @ Citadark Isle - new(GameVersion.XD, 60, 04000, Chansey) { Fateful = true, Species = 113, Level = 39, Moves = new(085,186,135,285), Location = 084 }, // Chansey: Cipher Peon Leden @ Citadark Isle - new(GameVersion.XD, 60, 04000, Chansey) { Fateful = true, Species = 113, Level = 39, Moves = new(085,186,135,285), Location = 087 }, // Chansey: Cipher Peon Leden @ Citadark Isle - new(GameVersion.XD, 61, 07500, Solrock) { Fateful = true, Species = 338, Level = 41, Moves = new(094,226,241,322), Location = 087 }, // Solrock: Cipher Admin Snattle @ Citadark Isle - new(GameVersion.XD, 62, 07500, Starmie) { Fateful = true, Species = 121, Level = 41, Moves = new(127,287,058,105), Location = 087 }, // Starmie: Cipher Admin Snattle @ Citadark Isle - new(GameVersion.XD, 63, 07000, Electabuzz){ Fateful = true, Species = 125, Level = 43, Moves = new(238,266,086,085), Location = 087 }, // Electabuzz: Cipher Admin Ardos @ Citadark Isle - new(GameVersion.XD, 64, 07000, First) { Fateful = true, Species = 277, Level = 43, Moves = new(143,226,097,263), Location = 087 }, // Swellow: Cipher Admin Ardos @ Citadark Isle - new(GameVersion.XD, 65, 09000, Snorlax) { Fateful = true, Species = 143, Level = 43, Moves = new(090,287,174,034), Location = 087 }, // Snorlax: Cipher Admin Ardos @ Citadark Isle - new(GameVersion.XD, 66, 07500, Poliwrath) { Fateful = true, Species = 062, Level = 42, Moves = new(056,270,240,280), Location = 087 }, // Poliwrath: Cipher Admin Gorigan @ Citadark Isle - new(GameVersion.XD, 67, 06500, MrMime) { Fateful = true, Species = 122, Level = 42, Moves = new(094,266,227,009), Location = 087 }, // Mr. Mime: Cipher Admin Gorigan @ Citadark Isle - new(GameVersion.XD, 68, 05000, Dugtrio) { Fateful = true, Species = 051, Level = 40, Moves = new(089,204,201,161), Location = 075 }, // Dugtrio: Cipher Peon Kolax @ Citadark Isle - new(GameVersion.XD, 69, 07000, Manectric) { Fateful = true, Species = 310, Level = 44, Moves = new(087,287,240,044), Location = 073 }, // Manectric: Cipher Admin Eldes @ Citadark Isle - new(GameVersion.XD, 70, 09000, Salamence) { Fateful = true, Species = 373, Level = 50, Moves = new(337,287,349,332), Location = 073 }, // Salamence: Cipher Admin Eldes @ Citadark Isle - new(GameVersion.XD, 71, 06500, Marowak) { Fateful = true, Species = 105, Level = 44, Moves = new(089,047,014,157), Location = 073 }, // Marowak: Cipher Admin Eldes @ Citadark Isle - new(GameVersion.XD, 72, 06000, Lapras) { Fateful = true, Species = 131, Level = 44, Moves = new(056,215,240,059), Location = 073 }, // Lapras: Cipher Admin Eldes @ Citadark Isle - new(GameVersion.XD, 73, 12000, First) { Fateful = true, Species = 249, Level = 50, Moves = new(354,297,089,056), Location = 074 }, // Lugia: Grand Master Greevil @ Citadark Isle - new(GameVersion.XD, 74, 10000, Zapdos) { Fateful = true, Species = 145, Level = 50, Moves = new(326,226,319,085), Location = 074 }, // Zapdos: Grand Master Greevil @ Citadark Isle - new(GameVersion.XD, 75, 10000, Moltres) { Fateful = true, Species = 146, Level = 50, Moves = new(326,234,261,053), Location = 074 }, // Moltres: Grand Master Greevil @ Citadark Isle - new(GameVersion.XD, 76, 10000, Articuno) { Fateful = true, Species = 144, Level = 50, Moves = new(326,215,114,058), Location = 074 }, // Articuno: Grand Master Greevil @ Citadark Isle - new(GameVersion.XD, 77, 09000, Tauros) { Fateful = true, Species = 128, Level = 46, Moves = new(089,287,039,034), Location = 074 }, // Tauros: Grand Master Greevil @ Citadark Isle - new(GameVersion.XD, 78, 07000, First) { Fateful = true, Species = 112, Level = 46, Moves = new(224,270,184,089), Location = 074 }, // Rhydon: Grand Master Greevil @ Citadark Isle - new(GameVersion.XD, 79, 09000, Exeggutor) { Fateful = true, Species = 103, Level = 46, Moves = new(094,287,095,246), Location = 074 }, // Exeggutor: Grand Master Greevil @ Citadark Isle - new(GameVersion.XD, 80, 09000, Dragonite) { Fateful = true, Species = 149, Level = 55, Moves = new(063,215,349,089), Location = 162 }, // Dragonite: Wanderer Miror B. @ Gateon Port - new(GameVersion.XD, 81, 04500, First) { Fateful = true, Species = 175, Level = 25, Moves = new(266,161,246,270), Location = 164, Gift = true }, // Togepi: Pokémon Trainer Hordel @ Outskirt Stand - new(GameVersion.XD, 82, 02500, Poochyena) { Fateful = true, Species = 261, Level = 10, Moves = new(091,215,305,336), Location = 162 }, // Poochyena: Bodybuilder Kilen @ Gateon Port - new(GameVersion.XD, 83, 02500, Ledyba) { Fateful = true, Species = 165, Level = 10, Moves = new(060,287,332,048), Location = 153 }, // Ledyba: Casual Guy Cyle @ Gateon Port + new(GameVersion.XD, 01, 03000, First) { FatefulEncounter = true, Species = 216, Level = 11, Moves = new(216,287,122,232), Location = 143, Gift = true }, // Teddiursa: Cipher Peon Naps @ Pokémon HQ Lab -- treat as Gift as it can only be captured in a Poké Ball + new(GameVersion.XD, 02, 02000, Vulpix) { FatefulEncounter = true, Species = 037, Level = 18, Moves = new(257,204,052,091), Location = 109 }, // Vulpix: Cipher Peon Mesin @ ONBS Building + new(GameVersion.XD, 03, 01500, Spheal) { FatefulEncounter = true, Species = 363, Level = 17, Moves = new(062,204,055,189), Location = 011 }, // Spheal: Cipher Peon Blusix @ Cipher Lab + new(GameVersion.XD, 03, 01500, Spheal) { FatefulEncounter = true, Species = 363, Level = 17, Moves = new(062,204,055,189), Location = 100 }, // Spheal: Cipher Peon Blusix @ Phenac City + new(GameVersion.XD, 04, 01500, First) { FatefulEncounter = true, Species = 343, Level = 17, Moves = new(317,287,189,060), Location = 011 }, // Baltoy: Cipher Peon Browsix @ Cipher Lab + new(GameVersion.XD, 04, 01500, First) { FatefulEncounter = true, Species = 343, Level = 17, Moves = new(317,287,189,060), Location = 096 }, // Baltoy: Cipher Peon Browsix @ Phenac City + new(GameVersion.XD, 05, 01500, First) { FatefulEncounter = true, Species = 179, Level = 17, Moves = new(034,215,084,086), Location = 011 }, // Mareep: Cipher Peon Yellosix @ Cipher Lab + new(GameVersion.XD, 05, 01500, First) { FatefulEncounter = true, Species = 179, Level = 17, Moves = new(034,215,084,086), Location = 096 }, // Mareep: Cipher Peon Yellosix @ Phenac City + new(GameVersion.XD, 06, 01500, Gulpin) { FatefulEncounter = true, Species = 316, Level = 17, Moves = new(351,047,124,092), Location = 011 }, // Gulpin: Cipher Peon Purpsix @ Cipher Lab + new(GameVersion.XD, 06, 01500, Gulpin) { FatefulEncounter = true, Species = 316, Level = 17, Moves = new(351,047,124,092), Location = 100 }, // Gulpin: Cipher Peon Purpsix @ Phenac City + new(GameVersion.XD, 07, 01500, Seedot) { FatefulEncounter = true, Species = 273, Level = 17, Moves = new(202,287,331,290), Location = 011 }, // Seedot: Cipher Peon Greesix @ Cipher Lab + new(GameVersion.XD, 07, 01500, Seedot) { FatefulEncounter = true, Species = 273, Level = 17, Moves = new(202,287,331,290), Location = 100 }, // Seedot: Cipher Peon Greesix @ Phenac City + new(GameVersion.XD, 08, 01500, Spinarak) { FatefulEncounter = true, Species = 167, Level = 14, Moves = new(091,287,324,101), Location = 010 }, // Spinarak: Cipher Peon Nexir @ Cipher Lab + new(GameVersion.XD, 09, 01500, Numel) { FatefulEncounter = true, Species = 322, Level = 14, Moves = new(036,204,091,052), Location = 009 }, // Numel: Cipher Peon Solox @ Cipher Lab + new(GameVersion.XD, 10, 01700, First) { FatefulEncounter = true, Species = 318, Level = 15, Moves = new(352,287,184,044), Location = 008 }, // Carvanha: Cipher Peon Cabol @ Cipher Lab + new(GameVersion.XD, 11, 03000, Roselia) { FatefulEncounter = true, Species = 315, Level = 22, Moves = new(345,186,320,073), Location = 094 }, // Roselia: Cipher Peon Fasin @ Phenac City + new(GameVersion.XD, 12, 02500, Delcatty) { FatefulEncounter = true, Species = 301, Level = 18, Moves = new(290,186,213,351), Location = 008 }, // Delcatty: Cipher Admin Lovrina @ Cipher Lab + new(GameVersion.XD, 13, 04000, Nosepass) { FatefulEncounter = true, Species = 299, Level = 26, Moves = new(085,270,086,157), Location = 090 }, // Nosepass: Wanderer Miror B. @ Poké Spots + new(GameVersion.XD, 14, 01500, First) { FatefulEncounter = true, Species = 228, Level = 17, Moves = new(185,204,052,046), Location = 100 }, // Houndour: Cipher Peon Resix @ Phenac City + new(GameVersion.XD, 14, 01500, First) { FatefulEncounter = true, Species = 228, Level = 17, Moves = new(185,204,052,046), Location = 011 }, // Houndour: Cipher Peon Resix @ Cipher Lab + new(GameVersion.XD, 15, 02000, Makuhita) { FatefulEncounter = true, Species = 296, Level = 18, Moves = new(280,287,292,317), Location = 109 }, // Makuhita: Cipher Peon Torkin @ ONBS Building + new(GameVersion.XD, 16, 02200, Duskull) { FatefulEncounter = true, Species = 355, Level = 19, Moves = new(247,270,310,109), Location = 110 }, // Duskull: Cipher Peon Lobar @ ONBS Building + new(GameVersion.XD, 17, 02200, Ralts) { FatefulEncounter = true, Species = 280, Level = 20, Moves = new(351,047,115,093), Location = 119 }, // Ralts: Cipher Peon Feldas @ ONBS Building + new(GameVersion.XD, 18, 02500, Mawile) { FatefulEncounter = true, Species = 303, Level = 22, Moves = new(206,047,011,334), Location = 111 }, // Mawile: Cipher Cmdr Exol @ ONBS Building + new(GameVersion.XD, 19, 02500, Snorunt) { FatefulEncounter = true, Species = 361, Level = 20, Moves = new(352,047,044,196), Location = 097 }, // Snorunt: Cipher Peon Exinn @ Phenac City + new(GameVersion.XD, 20, 02500, Pineco) { FatefulEncounter = true, Species = 204, Level = 20, Moves = new(042,287,191,068), Location = 096 }, // Pineco: Cipher Peon Gonrap @ Phenac City + new(GameVersion.XD, 21, 02500, Swinub) { FatefulEncounter = true, Species = 220, Level = 22, Moves = new(246,204,054,341), Location = 100 }, // Swinub: Cipher Peon Greck @ Phenac City + new(GameVersion.XD, 22, 02500, Natu) { FatefulEncounter = true, Species = 177, Level = 22, Moves = new(248,226,101,332), Location = 094 }, // Natu: Cipher Peon Eloin @ Phenac City + new(GameVersion.XD, 23, 01800, Shroomish) { FatefulEncounter = true, Species = 285, Level = 15, Moves = new(206,287,072,078), Location = 008 }, // Shroomish: Cipher R&D Klots @ Cipher Lab + new(GameVersion.XD, 24, 03500, Meowth) { FatefulEncounter = true, Species = 052, Level = 22, Moves = new(163,047,006,044), Location = 094 }, // Meowth: Cipher Peon Fostin @ Phenac City + new(GameVersion.XD, 25, 04500, Spearow) { FatefulEncounter = true, Species = 021, Level = 22, Moves = new(206,226,043,332), Location = 107 }, // Spearow: Cipher Peon Ezin @ Phenac Stadium + new(GameVersion.XD, 26, 03000, Grimer) { FatefulEncounter = true, Species = 088, Level = 23, Moves = new(188,270,325,107), Location = 107 }, // Grimer: Cipher Peon Faltly @ Phenac Stadium + new(GameVersion.XD, 27, 03500, Seel) { FatefulEncounter = true, Species = 086, Level = 23, Moves = new(057,270,219,058), Location = 107 }, // Seel: Cipher Peon Egrog @ Phenac Stadium + new(GameVersion.XD, 28, 05000, Lunatone) { FatefulEncounter = true, Species = 337, Level = 25, Moves = new(094,226,240,317), Location = 107 }, // Lunatone: Cipher Admin Snattle @ Phenac Stadium + new(GameVersion.XD, 29, 02500, Voltorb) { FatefulEncounter = true, Species = 100, Level = 19, Moves = new(243,287,209,129), Location = 092 }, // Voltorb: Wanderer Miror B. @ Cave Poké Spot + new(GameVersion.XD, 30, 05000, First) { FatefulEncounter = true, Species = 335, Level = 28, Moves = new(280,287,068,306), Location = 071 }, // Zangoose: Thug Zook @ Cipher Key Lair + new(GameVersion.XD, 31, 04000, Growlithe) { FatefulEncounter = true, Species = 058, Level = 28, Moves = new(053,204,044,036), Location = 064 }, // Growlithe: Cipher Peon Humah @ Cipher Key Lair + new(GameVersion.XD, 32, 04000, Paras) { FatefulEncounter = true, Species = 046, Level = 28, Moves = new(147,287,163,206), Location = 064 }, // Paras: Cipher Peon Humah @ Cipher Key Lair + new(GameVersion.XD, 33, 04000, First) { FatefulEncounter = true, Species = 090, Level = 29, Moves = new(036,287,057,062), Location = 065 }, // Shellder: Cipher Peon Gorog @ Cipher Key Lair + new(GameVersion.XD, 34, 04500, First) { FatefulEncounter = true, Species = 015, Level = 30, Moves = new(188,226,041,014), Location = 066 }, // Beedrill: Cipher Peon Lok @ Cipher Key Lair + new(GameVersion.XD, 35, 04000, Pidgeotto) { FatefulEncounter = true, Species = 017, Level = 30, Moves = new(017,287,211,297), Location = 066 }, // Pidgeotto: Cipher Peon Lok @ Cipher Key Lair + new(GameVersion.XD, 36, 04000, Butterfree){ FatefulEncounter = true, Species = 012, Level = 30, Moves = new(094,234,079,332), Location = 067 }, // Butterfree: Cipher Peon Targ @ Cipher Key Lair + new(GameVersion.XD, 37, 04000, Tangela) { FatefulEncounter = true, Species = 114, Level = 30, Moves = new(076,234,241,275), Location = 067 }, // Tangela: Cipher Peon Targ @ Cipher Key Lair + new(GameVersion.XD, 38, 06000, Raticate) { FatefulEncounter = true, Species = 020, Level = 34, Moves = new(162,287,184,158), Location = 076 }, // Raticate: Chaser Furgy @ Citadark Isle + new(GameVersion.XD, 39, 04000, Venomoth) { FatefulEncounter = true, Species = 049, Level = 32, Moves = new(318,287,164,094), Location = 070 }, // Venomoth: Cipher Peon Angic @ Cipher Key Lair + new(GameVersion.XD, 40, 04000, Weepinbell){ FatefulEncounter = true, Species = 070, Level = 32, Moves = new(345,234,188,230), Location = 070 }, // Weepinbell: Cipher Peon Angic @ Cipher Key Lair + new(GameVersion.XD, 41, 05000, Arbok) { FatefulEncounter = true, Species = 024, Level = 33, Moves = new(188,287,137,044), Location = 070 }, // Arbok: Cipher Peon Smarton @ Cipher Key Lair + new(GameVersion.XD, 42, 06000, Primeape) { FatefulEncounter = true, Species = 057, Level = 34, Moves = new(238,270,116,179), Location = 069 }, // Primeape: Cipher Admin Gorigan @ Cipher Key Lair + new(GameVersion.XD, 43, 05500, Hypno) { FatefulEncounter = true, Species = 097, Level = 34, Moves = new(094,226,096,247), Location = 069 }, // Hypno: Cipher Admin Gorigan @ Cipher Key Lair + new(GameVersion.XD, 44, 06500, Golduck) { FatefulEncounter = true, Species = 055, Level = 33, Moves = new(127,204,244,280), Location = 088 }, // Golduck: Navigator Abson @ Citadark Isle + new(GameVersion.XD, 45, 07000, Sableye) { FatefulEncounter = true, Species = 302, Level = 33, Moves = new(247,270,185,105), Location = 088 }, // Sableye: Navigator Abson @ Citadark Isle + new(GameVersion.XD, 46, 04500, Magneton) { FatefulEncounter = true, Species = 082, Level = 30, Moves = new(038,287,240,087), Location = 067 }, // Magneton: Cipher Peon Snidle @ Cipher Key Lair + new(GameVersion.XD, 47, 08000, Dodrio) { FatefulEncounter = true, Species = 085, Level = 34, Moves = new(065,226,097,161), Location = 076 }, // Dodrio: Chaser Furgy @ Citadark Isle + new(GameVersion.XD, 48, 05500, Farfetchd) { FatefulEncounter = true, Species = 083, Level = 36, Moves = new(163,226,014,332), Location = 076 }, // Farfetch'd: Cipher Admin Lovrina @ Citadark Isle + new(GameVersion.XD, 49, 06500, Altaria) { FatefulEncounter = true, Species = 334, Level = 36, Moves = new(225,215,076,332), Location = 076 }, // Altaria: Cipher Admin Lovrina @ Citadark Isle + new(GameVersion.XD, 50, 06000, Kangaskhan){ FatefulEncounter = true, Species = 115, Level = 35, Moves = new(089,047,039,146), Location = 085 }, // Kangaskhan: Cipher Peon Litnar @ Citadark Isle + new(GameVersion.XD, 51, 07000, Banette) { FatefulEncounter = true, Species = 354, Level = 37, Moves = new(185,270,247,174), Location = 085 }, // Banette: Cipher Peon Litnar @ Citadark Isle + new(GameVersion.XD, 52, 07000, Magmar) { FatefulEncounter = true, Species = 126, Level = 36, Moves = new(126,266,238,009), Location = 077 }, // Magmar: Cipher Peon Grupel @ Citadark Isle + new(GameVersion.XD, 53, 07000, Pinsir) { FatefulEncounter = true, Species = 127, Level = 35, Moves = new(012,270,206,066), Location = 077 }, // Pinsir: Cipher Peon Grupel @ Citadark Isle + new(GameVersion.XD, 54, 05500, Magcargo) { FatefulEncounter = true, Species = 219, Level = 38, Moves = new(257,287,089,053), Location = 080 }, // Magcargo: Cipher Peon Kolest @ Citadark Isle + new(GameVersion.XD, 55, 06000, Rapidash) { FatefulEncounter = true, Species = 078, Level = 40, Moves = new(076,226,241,053), Location = 080 }, // Rapidash: Cipher Peon Kolest @ Citadark Isle + new(GameVersion.XD, 56, 06000, Hitmonchan){ FatefulEncounter = true, Species = 107, Level = 38, Moves = new(005,270,170,327), Location = 081 }, // Hitmonchan: Cipher Peon Karbon @ Citadark Isle + new(GameVersion.XD, 57, 07000, Hitmonlee) { FatefulEncounter = true, Species = 106, Level = 38, Moves = new(136,287,170,025), Location = 081 }, // Hitmonlee: Cipher Peon Petro @ Citadark Isle + new(GameVersion.XD, 58, 05000, Lickitung) { FatefulEncounter = true, Species = 108, Level = 38, Moves = new(038,270,111,205), Location = 084 }, // Lickitung: Cipher Peon Geftal @ Citadark Isle + new(GameVersion.XD, 59, 08000, Scyther) { FatefulEncounter = true, Species = 123, Level = 40, Moves = new(013,234,318,163), Location = 084 }, // Scyther: Cipher Peon Leden @ Citadark Isle + new(GameVersion.XD, 60, 04000, Chansey) { FatefulEncounter = true, Species = 113, Level = 39, Moves = new(085,186,135,285), Location = 084 }, // Chansey: Cipher Peon Leden @ Citadark Isle + new(GameVersion.XD, 60, 04000, Chansey) { FatefulEncounter = true, Species = 113, Level = 39, Moves = new(085,186,135,285), Location = 087 }, // Chansey: Cipher Peon Leden @ Citadark Isle + new(GameVersion.XD, 61, 07500, Solrock) { FatefulEncounter = true, Species = 338, Level = 41, Moves = new(094,226,241,322), Location = 087 }, // Solrock: Cipher Admin Snattle @ Citadark Isle + new(GameVersion.XD, 62, 07500, Starmie) { FatefulEncounter = true, Species = 121, Level = 41, Moves = new(127,287,058,105), Location = 087 }, // Starmie: Cipher Admin Snattle @ Citadark Isle + new(GameVersion.XD, 63, 07000, Electabuzz){ FatefulEncounter = true, Species = 125, Level = 43, Moves = new(238,266,086,085), Location = 087 }, // Electabuzz: Cipher Admin Ardos @ Citadark Isle + new(GameVersion.XD, 64, 07000, First) { FatefulEncounter = true, Species = 277, Level = 43, Moves = new(143,226,097,263), Location = 087 }, // Swellow: Cipher Admin Ardos @ Citadark Isle + new(GameVersion.XD, 65, 09000, Snorlax) { FatefulEncounter = true, Species = 143, Level = 43, Moves = new(090,287,174,034), Location = 087 }, // Snorlax: Cipher Admin Ardos @ Citadark Isle + new(GameVersion.XD, 66, 07500, Poliwrath) { FatefulEncounter = true, Species = 062, Level = 42, Moves = new(056,270,240,280), Location = 087 }, // Poliwrath: Cipher Admin Gorigan @ Citadark Isle + new(GameVersion.XD, 67, 06500, MrMime) { FatefulEncounter = true, Species = 122, Level = 42, Moves = new(094,266,227,009), Location = 087 }, // Mr. Mime: Cipher Admin Gorigan @ Citadark Isle + new(GameVersion.XD, 68, 05000, Dugtrio) { FatefulEncounter = true, Species = 051, Level = 40, Moves = new(089,204,201,161), Location = 075 }, // Dugtrio: Cipher Peon Kolax @ Citadark Isle + new(GameVersion.XD, 69, 07000, Manectric) { FatefulEncounter = true, Species = 310, Level = 44, Moves = new(087,287,240,044), Location = 073 }, // Manectric: Cipher Admin Eldes @ Citadark Isle + new(GameVersion.XD, 70, 09000, Salamence) { FatefulEncounter = true, Species = 373, Level = 50, Moves = new(337,287,349,332), Location = 073 }, // Salamence: Cipher Admin Eldes @ Citadark Isle + new(GameVersion.XD, 71, 06500, Marowak) { FatefulEncounter = true, Species = 105, Level = 44, Moves = new(089,047,014,157), Location = 073 }, // Marowak: Cipher Admin Eldes @ Citadark Isle + new(GameVersion.XD, 72, 06000, Lapras) { FatefulEncounter = true, Species = 131, Level = 44, Moves = new(056,215,240,059), Location = 073 }, // Lapras: Cipher Admin Eldes @ Citadark Isle + new(GameVersion.XD, 73, 12000, First) { FatefulEncounter = true, Species = 249, Level = 50, Moves = new(354,297,089,056), Location = 074 }, // Lugia: Grand Master Greevil @ Citadark Isle + new(GameVersion.XD, 74, 10000, Zapdos) { FatefulEncounter = true, Species = 145, Level = 50, Moves = new(326,226,319,085), Location = 074 }, // Zapdos: Grand Master Greevil @ Citadark Isle + new(GameVersion.XD, 75, 10000, Moltres) { FatefulEncounter = true, Species = 146, Level = 50, Moves = new(326,234,261,053), Location = 074 }, // Moltres: Grand Master Greevil @ Citadark Isle + new(GameVersion.XD, 76, 10000, Articuno) { FatefulEncounter = true, Species = 144, Level = 50, Moves = new(326,215,114,058), Location = 074 }, // Articuno: Grand Master Greevil @ Citadark Isle + new(GameVersion.XD, 77, 09000, Tauros) { FatefulEncounter = true, Species = 128, Level = 46, Moves = new(089,287,039,034), Location = 074 }, // Tauros: Grand Master Greevil @ Citadark Isle + new(GameVersion.XD, 78, 07000, First) { FatefulEncounter = true, Species = 112, Level = 46, Moves = new(224,270,184,089), Location = 074 }, // Rhydon: Grand Master Greevil @ Citadark Isle + new(GameVersion.XD, 79, 09000, Exeggutor) { FatefulEncounter = true, Species = 103, Level = 46, Moves = new(094,287,095,246), Location = 074 }, // Exeggutor: Grand Master Greevil @ Citadark Isle + new(GameVersion.XD, 80, 09000, Dragonite) { FatefulEncounter = true, Species = 149, Level = 55, Moves = new(063,215,349,089), Location = 162 }, // Dragonite: Wanderer Miror B. @ Gateon Port + new(GameVersion.XD, 81, 04500, First) { FatefulEncounter = true, Species = 175, Level = 25, Moves = new(266,161,246,270), Location = 164, Gift = true }, // Togepi: Pokémon Trainer Hordel @ Outskirt Stand + new(GameVersion.XD, 82, 02500, Poochyena) { FatefulEncounter = true, Species = 261, Level = 10, Moves = new(091,215,305,336), Location = 162 }, // Poochyena: Bodybuilder Kilen @ Gateon Port + new(GameVersion.XD, 83, 02500, Ledyba) { FatefulEncounter = true, Species = 165, Level = 10, Moves = new(060,287,332,048), Location = 153 }, // Ledyba: Casual Guy Cyle @ Gateon Port }; internal static readonly EncounterArea3XD[] SlotsXD = @@ -113,5 +113,6 @@ internal static class Encounters3XD new(92, 041, 21, 304, 21, 194, 21), // Cave (Zubat, Aron, Wooper) }; - internal static readonly EncounterStatic[] Encounter_CXD = ArrayUtil.ConcatAll(Encounters3Colo.Encounter_ColoGift, Encounters3Colo.Encounter_Colo, Encounter_XDGift, Encounter_XD); + internal static readonly EncounterStatic3[] Encounter_CXDGift = ArrayUtil.ConcatAll(Encounters3Colo.Encounter_ColoGift, Encounter_XDGift); + internal static readonly EncounterStaticShadow[] Encounter_CXDShadow = ArrayUtil.ConcatAll(Encounters3Colo.Encounter_Colo, Encounter_XD); } diff --git a/PKHeX.Core/Legality/Encounters/Data/Gen3/Encounters3XDShadow.cs b/PKHeX.Core/Legality/Encounters/Data/Gen3/Encounters3XDShadow.cs index 801970818..0c48ea9cf 100644 --- a/PKHeX.Core/Legality/Encounters/Data/Gen3/Encounters3XDShadow.cs +++ b/PKHeX.Core/Legality/Encounters/Data/Gen3/Encounters3XDShadow.cs @@ -1,4 +1,5 @@ -// ReSharper disable StringLiteralTypo +using static PKHeX.Core.NPCLockDetail; + namespace PKHeX.Core; /// @@ -28,7 +29,7 @@ public static class Encounters3XDShadow public static readonly TeamLock XSphealCipherLab = new( 363, // Spheal - "Cipher Lab", + CipherLab, new[] { new NPCLock(116, 24, 0, 063), // Horsea (M) (Quirky) new NPCLock(118, 12, 1, 127), // Goldeen (F) (Serious) @@ -36,7 +37,7 @@ public static class Encounters3XDShadow public static readonly TeamLock XSphealPhenacCityandPost = new( 363, // Spheal - "Phenac City and Post", + PhenacCityAndPost, new[] { new NPCLock(116, 24, 0, 063), // Horsea (M) (Quirky) new NPCLock(118, 12, 1, 127), // Goldeen (F) (Serious) @@ -52,7 +53,7 @@ public static class Encounters3XDShadow public static readonly TeamLock XSeedotCipherLab = new( 273, // Seedot - "Cipher Lab", + CipherLab, new[] { new NPCLock(043, 06, 0, 127), // Oddish (M) (Docile) new NPCLock(331, 24, 1, 127), // Cacnea (F) (Quirky) @@ -63,7 +64,7 @@ public static class Encounters3XDShadow public static readonly TeamLock XSeedotPhenacCity = new( 273, // Seedot - "Phenac City", + PhenacCity, new[] { new NPCLock(043, 06, 0, 127), // Oddish (M) (Docile) new NPCLock(331, 24, 1, 127), // Cacnea (F) (Quirky) @@ -74,7 +75,7 @@ public static class Encounters3XDShadow public static readonly TeamLock XSeedotPost = new( 273, // Seedot - "Post", + Post, new[] { new NPCLock(045, 06, 0, 127), // Vileplume (M) (Docile) new NPCLock(332, 24, 1, 127), // Cacturne (F) (Quirky) @@ -246,7 +247,7 @@ public static class Encounters3XDShadow public static readonly TeamLock XGrowlitheParasSeen = new( 058, // Growlithe - "Paras Seen", + SeenParas, new[] { new NPCLock(336, 24, 0, 127), // Seviper (M) (Quirky) new NPCLock(198, 06, 1, 127), // Murkrow (F) (Docile) @@ -263,7 +264,7 @@ public static class Encounters3XDShadow public static readonly TeamLock XPidgeottoBeedrillSeen = new( 017, // Pidgeotto - "Beedrill Seen", + SeenBeedrill, new[] { new NPCLock(015, true), // Shadow Beedrill (Seen) new NPCLock(162, 12, 0, 127), // Furret (M) (Serious) @@ -289,7 +290,7 @@ public static class Encounters3XDShadow public static readonly TeamLock XButterfreeTangelaSeen = new( 012, // Butterfree - "Tangela Seen", + SeenTangela, new[] { new NPCLock(038, 12, 1, 191), // Ninetales (F) (Serious) new NPCLock(189, 06, 0, 127), // Jumpluff (M) (Docile) @@ -324,7 +325,7 @@ public static class Encounters3XDShadow public static readonly TeamLock XWeepinbellVenomothSeen = new( 070, // Weepinbell - "Venomoth Seen", + SeenVenomoth, new[] { new NPCLock(055, 18, 1, 127), // Golduck (F) (Bashful) new NPCLock(237, 24, 0, 000), // Hitmontop (M) (Quirky) @@ -362,7 +363,7 @@ public static class Encounters3XDShadow public static readonly TeamLock XHypnoPrimeapeSeen = new( 097, // Hypno - "Primeape Seen", + SeenPrimeape, new[] { new NPCLock(305, 18, 1, 127), // Lairon (F) (Bashful) new NPCLock(364, 12, 1, 127), // Sealeo (F) (Serious) @@ -390,7 +391,7 @@ public static class Encounters3XDShadow public static readonly TeamLock XSableyeGolduckSeen = new( 302, // Sableye - "Golduck Seen", + SeenGolduck, new[] { new NPCLock(342, 24, 0, 127), // Crawdaunt (M) (Quirky) new NPCLock(279, 06, 1, 127), // Pelipper (F) (Docile) @@ -414,7 +415,7 @@ public static class Encounters3XDShadow public static readonly TeamLock XRaticateDodrioSeen = new( 020, // Raticate - "Dodrio Seen", + SeenDodrio, new[] { new NPCLock(178, 18, 1, 127), // Xatu (F) (Bashful) new NPCLock(085, true), // Shadow Dodrio (Seen) @@ -440,7 +441,7 @@ public static class Encounters3XDShadow public static readonly TeamLock XAltariaFarfetchdSeen = new( 334, // Altaria - "Farfetch'd Seen", + SeenFarfetchd, new[] { new NPCLock(282, 12, 0, 127), // Gardevoir (M) (Serious) new NPCLock(368, 00, 1, 127), // Gorebyss (F) (Hardy) @@ -467,7 +468,7 @@ public static class Encounters3XDShadow public static readonly TeamLock XBanetteKangaskhanSeen = new( 354, // Banette - "Kangaskhan Seen", + SeenKangaskhan, new[] { new NPCLock(101, 00, 2, 255), // Electrode (-) (Hardy) new NPCLock(200, 18, 1, 127), // Misdreavus (F) (Bashful) @@ -494,7 +495,7 @@ public static class Encounters3XDShadow public static readonly TeamLock XPinsirMagmarSeen = new( 127, // Pinsir - "Magmar Seen", + SeenMagmar, new[] { new NPCLock(229, 18, 0, 127), // Houndoom (M) (Bashful) new NPCLock(038, 18, 0, 191), // Ninetales (M) (Bashful) @@ -521,7 +522,7 @@ public static class Encounters3XDShadow public static readonly TeamLock XMagcargoRapidashSeen = new( 219, // Magcargo - "Rapidash Seen", + SeenRapidash, new[] { new NPCLock(323, 24, 0, 127), // Camerupt (M) (Quirky) new NPCLock(110, 06, 0, 127), // Weezing (M) (Docile) @@ -571,7 +572,7 @@ public static class Encounters3XDShadow public static readonly TeamLock XChanseyScytherSeen = new( 113, // Chansey - "Scyther Seen", + SeenScyther, new[] { new NPCLock(234, 06, 1, 127), // Stantler (F) (Docile) new NPCLock(295, 24, 0, 127), // Exploud (M) (Quirky) @@ -598,7 +599,7 @@ public static class Encounters3XDShadow public static readonly TeamLock XStarmieSolrockSeen = new( 121, // Starmie - "Solrock Seen", + SeenSolrock, new[] { new NPCLock(375, 24, 2, 255), // Metang (-) (Quirky) new NPCLock(195, 06, 0, 127), // Quagsire (M) (Docile) @@ -618,7 +619,7 @@ public static class Encounters3XDShadow public static readonly TeamLock XElectabuzzSwellowSeen = new( 125, // Electabuzz - "Swellow Seen", + SeenSwellow, new[] { new NPCLock(277, true), // Shadow Swellow (Seen) new NPCLock(065, 24, 0, 063), // Alakazam (M) (Quirky) @@ -638,7 +639,7 @@ public static class Encounters3XDShadow public static readonly TeamLock XSnorlaxSwellowSeen = new( 143, // Snorlax - "Swellow Seen", + SeenSwellow, new[] { new NPCLock(277, true), // Shadow Swellow (Seen) new NPCLock(065, 24, 0, 063), // Alakazam (M) (Quirky) @@ -649,7 +650,7 @@ public static class Encounters3XDShadow public static readonly TeamLock XSnorlaxSwellowElectabuzzSeen = new( 143, // Snorlax - "Swellow & Electabuzz Seen", + SeenSwellowElectabuzz, new[] { new NPCLock(277, true), // Shadow Swellow (Seen) new NPCLock(065, 24, 0, 063), // Alakazam (M) (Quirky) @@ -679,7 +680,7 @@ public static class Encounters3XDShadow public static readonly TeamLock XMrMimePoliwrathSeen = new( 122, // Mr. Mime - "Poliwrath Seen", + SeenPoliwrath, new[] { new NPCLock(199, 18, 0, 127), // Slowking (M) (Bashful) new NPCLock(217, 18, 0, 127), // Ursaring (M) (Bashful) @@ -731,7 +732,7 @@ public static class Encounters3XDShadow public static readonly TeamLock XSalamenceManectricSeen = new( 373, // Salamence - "Manectric Seen", + SeenManectric, new[] { new NPCLock(291, 06, 1, 127), // Ninjask (F) (Docile) new NPCLock(310, true), // Shadow Manectric (Seen) @@ -739,7 +740,7 @@ public static class Encounters3XDShadow public static readonly TeamLock XMarowakManectricSeen = new( 105, // Marowak - "Manectric Seen", + SeenManectric, new[] { new NPCLock(291, 06, 1, 127), // Ninjask (F) (Docile) new NPCLock(310, true), // Shadow Manectric (Seen) @@ -749,7 +750,7 @@ public static class Encounters3XDShadow public static readonly TeamLock XMarowakManectricSalamenceSeen = new( 105, // Marowak - "Manectric & Salamence Seen", + SeenManectricSalamence, new[] { new NPCLock(291, 06, 1, 127), // Ninjask (F) (Docile) new NPCLock(310, true), // Shadow Manectric (Seen) @@ -759,7 +760,7 @@ public static class Encounters3XDShadow public static readonly TeamLock XLaprasManectricSeen = new( 131, // Lapras - "Manectric Seen", + SeenManectric, new[] { new NPCLock(291, 06, 1, 127), // Ninjask (F) (Docile) new NPCLock(310, true), // Shadow Manectric (Seen) @@ -770,7 +771,7 @@ public static class Encounters3XDShadow public static readonly TeamLock XLaprasManectricSalamenceSeen = new( 131, // Lapras - "Manectric & Salamence Seen", + SeenManectricSalamence, new[] { new NPCLock(291, 06, 1, 127), // Ninjask (F) (Docile) new NPCLock(310, true), // Shadow Manectric (Seen) @@ -781,7 +782,7 @@ public static class Encounters3XDShadow public static readonly TeamLock XLaprasManectricMarowakSeen = new( 131, // Lapras - "Manectric & Marowak Seen", + SeenManectricMarowak, new[] { new NPCLock(291, 06, 1, 127), // Ninjask (F) (Docile) new NPCLock(310, true), // Shadow Manectric (Seen) @@ -792,7 +793,7 @@ public static class Encounters3XDShadow public static readonly TeamLock XLaprasManectricSalamenceMarowakSeen = new( 131, // Lapras - "Manectric & Salamence & Marowak Seen", + SeenManectricMarowakSalamence, new[] { new NPCLock(291, 06, 1, 127), // Ninjask (F) (Docile) new NPCLock(310, true), // Shadow Manectric (Seen) @@ -843,7 +844,7 @@ public static class Encounters3XDShadow public static readonly TeamLock XExeggutorRhydonMoltresSeen = new( 103, // Exeggutor - "Rhydon & Moltres Seen", + SeenRhydonMoltres, new[] { new NPCLock(112, true), // Shadow Rhydon (Seen) new NPCLock(146, true), // Shadow Moltres (Seen) @@ -851,7 +852,7 @@ public static class Encounters3XDShadow public static readonly TeamLock XTaurosRhydonMoltresSeen = new( 128, // Tauros - "Rhydon & Moltres Seen", + SeenRhydonMoltres, new[] { new NPCLock(112, true), // Shadow Rhydon (Seen) new NPCLock(146, true), // Shadow Moltres (Seen) @@ -860,7 +861,7 @@ public static class Encounters3XDShadow public static readonly TeamLock XTaurosRhydonMoltresExeggutorSeen = new( 128, // Tauros - "Rhydon & Moltres & Exeggutor Seen", + SeenRhydonMoltresExeggutor, new[] { new NPCLock(112, true), // Shadow Rhydon (Seen) new NPCLock(146, true), // Shadow Moltres (Seen) @@ -869,7 +870,7 @@ public static class Encounters3XDShadow public static readonly TeamLock XArticunoRhydonMoltresSeen = new( 144, // Articuno - "Rhydon & Moltres Seen", + SeenRhydonMoltres, new[] { new NPCLock(112, true), // Shadow Rhydon (Seen) new NPCLock(146, true), // Shadow Moltres (Seen) @@ -879,7 +880,7 @@ public static class Encounters3XDShadow public static readonly TeamLock XArticunoRhydonMoltresTaurosSeen = new( 144, // Articuno - "Rhydon & Moltres & Tauros Seen", + SeenRhydonMoltresTauros, new[] { new NPCLock(112, true), // Shadow Rhydon (Seen) new NPCLock(146, true), // Shadow Moltres (Seen) @@ -889,7 +890,7 @@ public static class Encounters3XDShadow public static readonly TeamLock XArticunoRhydonMoltresExeggutorSeen = new( 144, // Articuno - "Rhydon & Moltres & Exeggutor Seen", + SeenRhydonMoltresExeggutor, new[] { new NPCLock(112, true), // Shadow Rhydon (Seen) new NPCLock(146, true), // Shadow Moltres (Seen) @@ -899,7 +900,7 @@ public static class Encounters3XDShadow public static readonly TeamLock XArticunoRhydonMoltresExeggutorTaurosSeen = new( 144, // Articuno - "Rhydon & Moltres & Exeggutor & Tauros Seen", + SeenRhydonMoltresExeggutorTauros, new[] { new NPCLock(112, true), // Shadow Rhydon (Seen) new NPCLock(146, true), // Shadow Moltres (Seen) @@ -909,7 +910,7 @@ public static class Encounters3XDShadow public static readonly TeamLock XZapdosRhydonMoltresSeen = new( 145, // Zapdos - "Rhydon & Moltres Seen", + SeenRhydonMoltres, new[] { new NPCLock(112, true), // Shadow Rhydon (Seen) new NPCLock(146, true), // Shadow Moltres (Seen) @@ -920,7 +921,7 @@ public static class Encounters3XDShadow public static readonly TeamLock XZapdosRhydonMoltresTaurosSeen = new( 145, // Zapdos - "Rhydon & Moltres & Tauros Seen", + SeenRhydonMoltresTauros, new[] { new NPCLock(112, true), // Shadow Rhydon (Seen) new NPCLock(146, true), // Shadow Moltres (Seen) @@ -931,7 +932,7 @@ public static class Encounters3XDShadow public static readonly TeamLock XZapdosRhydonMoltresArticunoSeen = new( 145, // Zapdos - "Rhydon & Moltres & Articuno Seen", + SeenRhydonMoltresArticuno, new[] { new NPCLock(112, true), // Shadow Rhydon (Seen) new NPCLock(146, true), // Shadow Moltres (Seen) @@ -942,7 +943,7 @@ public static class Encounters3XDShadow public static readonly TeamLock XZapdosRhydonMoltresExeggutorSeen = new( 145, // Zapdos - "Rhydon & Moltres & Exeggutor Seen", + SeenRhydonMoltresExeggutor, new[] { new NPCLock(112, true), // Shadow Rhydon (Seen) new NPCLock(146, true), // Shadow Moltres (Seen) @@ -953,7 +954,7 @@ public static class Encounters3XDShadow public static readonly TeamLock XZapdosRhydonMoltresTaurosArticunoSeen = new( 145, // Zapdos - "Rhydon & Moltres & Tauros & Articuno Seen", + SeenRhydonMoltresTaurosArticuno, new[] { new NPCLock(112, true), // Shadow Rhydon (Seen) new NPCLock(146, true), // Shadow Moltres (Seen) @@ -964,7 +965,7 @@ public static class Encounters3XDShadow public static readonly TeamLock XZapdosRhydonMoltresExeggutorTaurosSeen = new( 145, // Zapdos - "Rhydon & Moltres & Exeggutor & Tauros Seen", + SeenRhydonMoltresExeggutorTauros, new[] { new NPCLock(112, true), // Shadow Rhydon (Seen) new NPCLock(146, true), // Shadow Moltres (Seen) @@ -975,7 +976,7 @@ public static class Encounters3XDShadow public static readonly TeamLock XZapdosRhydonMoltresExeggutorArticunoSeen = new( 145, // Zapdos - "Rhydon & Moltres & Exeggutor & Articuno Seen", + SeenRhydonMoltresExeggutorArticuno, new[] { new NPCLock(112, true), // Shadow Rhydon (Seen) new NPCLock(146, true), // Shadow Moltres (Seen) @@ -986,7 +987,7 @@ public static class Encounters3XDShadow public static readonly TeamLock XZapdosRhydonMoltresExeggutorTaurosArticunoSeen = new( 145, // Zapdos - "Rhydon & Moltres & Exeggutor & Tauros & Articuno Seen", + SeenRhydonMoltresExeggutorTaurosArticuno, new[] { new NPCLock(112, true), // Shadow Rhydon (Seen) new NPCLock(146, true), // Shadow Moltres (Seen) diff --git a/PKHeX.Core/Legality/Encounters/Data/Gen3/EncountersWC3.cs b/PKHeX.Core/Legality/Encounters/Data/Gen3/EncountersWC3.cs index 0990e8fc5..fd28cded1 100644 --- a/PKHeX.Core/Legality/Encounters/Data/Gen3/EncountersWC3.cs +++ b/PKHeX.Core/Legality/Encounters/Data/Gen3/EncountersWC3.cs @@ -14,223 +14,241 @@ internal static class EncountersWC3 { internal static readonly WC3[] Encounter_Event3_Special = { - new() { Species = 385, Level = 05, TID = 20043, OT_Gender = 0, Version = GameVersion.R, Method = PIDType.BACD_R, OT_Name = "WISHMKR", CardTitle = "Wishmaker Jirachi", Language = (int)LanguageID.English }, + new() { Species = 385, Level = 05, TID16 = 20043, OT_Gender = 0, Version = GameVersion.R, Method = PIDType.BACD_R, OT_Name = "WISHMKR", CardTitle = "Wishmaker Jirachi", Language = (int)LanguageID.English }, }; private static IEnumerable GetIngameCXDData() { var langs = new[]{LanguageID.Japanese, LanguageID.English, LanguageID.French, LanguageID.Italian, LanguageID.German, LanguageID.Spanish}; - string[] p = {string.Empty, "コロシアム", "COLOS", "COLOSSEUM", "ARENA", "COLOSSEUM", string.Empty, "CLAUDIO" }; - string[] c = {string.Empty, "アゲト", "AGATE", "SAMARAGD", "SOFO", "EMERITAE", string.Empty, "ÁGATA" }; string[] h = {string.Empty, "ダニー", "HORDEL", "VOLKER", "ODINO", "HORAZ", string.Empty, "HORDEL"}; string[] d = {string.Empty, "ギンザル", "DUKING", "DOKING", "RODRIGO", "GRAND", string.Empty, "GERMÁN"}; - string[] m = {string.Empty, "バトルやま", "MATTLE", "MT BATAILL", "MONTE LOTT", "DUELLBERG", string.Empty, "ERNESTO"}; // truncated on ck3->pk3 transfer string[] z = {string.Empty, "コンセント", "ZAPRONG", "ZAPRONG", "ZAPRONG", "ZAPRONG", string.Empty, "ZAPRONG"}; return langs.SelectMany(l => GetIngame((int)l)); IEnumerable GetIngame(int l) { var id = (LanguageID) l; + return new WC3[] + { + // Colosseum + new() { Species = 311, Level = 13, Language = l, Location = 254, ID32 = 37149, OT_Gender = 0, OT_Name = d[l], Version = GameVersion.COLO, CardTitle = $"Special Gift ({id})", Method = PIDType.CXD, Shiny = Shiny.Never, Moves = new(045, 086, 098, 270) }, // Plusle @ Ingame Trade + // XD + new(true) { Species = 239, Level = 20, Language = l, Location = 164, TID16 = 41400, OT_Gender = 0, OT_Name = h[l], Version = GameVersion.XD, CardTitle = $"Trade Togepi ({id})", Method = PIDType.CXD, Moves = new(008, 007, 009, 238), Nickname = z[l] }, // Elekid @ Snagem Hideout + new(true) { Species = 307, Level = 20, Language = l, Location = 116, TID16 = 37149, OT_Gender = 0, OT_Name = d[l], Version = GameVersion.XD, CardTitle = $"Trade Trapinch ({id})", Method = PIDType.CXD, Moves = new(223, 093, 247, 197) }, // Meditite @ Pyrite Town + new(true) { Species = 213, Level = 20, Language = l, Location = 116, TID16 = 37149, OT_Gender = 0, OT_Name = d[l], Version = GameVersion.XD, CardTitle = $"Trade Surskit ({id})", Method = PIDType.CXD, Moves = new(092, 164, 188, 227) }, // Shuckle @ Pyrite Town + new(true) { Species = 246, Level = 20, Language = l, Location = 116, TID16 = 37149, OT_Gender = 0, OT_Name = d[l], Version = GameVersion.XD, CardTitle = $"Trade Wooper ({id})", Method = PIDType.CXD, Moves = new(201, 349, 044, 200) }, // Larvitar @ Pyrite Town + }; + } + } + + private static IEnumerable GetIngameCXDDataMainline() + { + var langs = new[] { LanguageID.Japanese, LanguageID.English, LanguageID.French, LanguageID.Italian, LanguageID.German, LanguageID.Spanish }; + string[] p = { string.Empty, "コロシアム", "COLOS", "COLOSSEUM", "ARENA", "COLOSSEUM", string.Empty, "CLAUDIO" }; + string[] c = { string.Empty, "アゲト", "AGATE", "SAMARAGD", "SOFO", "EMERITAE", string.Empty, "ÁGATA" }; + string[] m = { string.Empty, "バトルやま", "MATTLE", "MT BATAILL", "MONTE LOTT", "DUELLBERG", string.Empty, "ERNESTO" }; // truncated on ck3->pk3 transfer + + return langs.SelectMany(l => GetIngame((int)l)); + IEnumerable GetIngame(int l) + { + var id = (LanguageID)l; var nd = id != LanguageID.Japanese; return new WC3[] { // Colosseum - new() { Species = 025, Level = 10, Language = l, Location = 255, TID = 31121, SID = 0, OT_Gender = 0, OT_Name = p[l], Version = GameVersion.R, CardTitle = $"Colosseum Pikachu ({id})",Method = PIDType.CXD, Shiny = Shiny.Never, NotDistributed = nd }, // Colosseum Pikachu bonus gift - new() { Species = 251, Level = 10, Language = l, Location = 255, TID = 31121, SID = 0, OT_Gender = 1, OT_Name = c[l], Version = GameVersion.R, CardTitle = $"Agate Celebi ({id})", Method = PIDType.CXD, Shiny = Shiny.Never, NotDistributed = nd }, // Ageto Celebi bonus gift - new() { Species = 311, Level = 13, Language = l, Location = 254, TID = 37149, SID = 0, OT_Gender = 0, OT_Name = d[l], Version = GameVersion.COLO, CardTitle = $"Special Gift ({id})", Method = PIDType.CXD, Shiny = Shiny.Never, Moves = new(045, 086, 098, 270) }, // Plusle @ Ingame Trade - new() { Species = 250, Level = 70, Language = l, Location = 255, TID = 10048, SID = 0, OT_Gender = 0, OT_Name = m[l], Version = GameVersion.S, CardTitle = $"Mt. Battle Ho-Oh ({id})", Method = PIDType.CXD, Shiny = Shiny.Never, Moves = new(105, 126, 241, 129) }, // Ho-oh @ Mt. Battle - // XD - new() { Species = 239, Level = 20, Language = l, Location = 164, TID = 41400, SID = -1, OT_Gender = 0, OT_Name = h[l], Version = GameVersion.XD, CardTitle = $"Trade Togepi ({id})", Method = PIDType.CXD, Moves = new(008, 007, 009, 238), Fateful = true, Nickname = z[l] }, // Elekid @ Snagem Hideout - new() { Species = 307, Level = 20, Language = l, Location = 116, TID = 37149, SID = -1, OT_Gender = 0, OT_Name = d[l], Version = GameVersion.XD, CardTitle = $"Trade Trapinch ({id})", Method = PIDType.CXD, Moves = new(223, 093, 247, 197), Fateful = true }, // Meditite @ Pyrite Town - new() { Species = 213, Level = 20, Language = l, Location = 116, TID = 37149, SID = -1, OT_Gender = 0, OT_Name = d[l], Version = GameVersion.XD, CardTitle = $"Trade Surskit ({id})", Method = PIDType.CXD, Moves = new(092, 164, 188, 227), Fateful = true }, // Shuckle @ Pyrite Town - new() { Species = 246, Level = 20, Language = l, Location = 116, TID = 37149, SID = -1, OT_Gender = 0, OT_Name = d[l], Version = GameVersion.XD, CardTitle = $"Trade Wooper ({id})", Method = PIDType.CXD, Moves = new(201, 349, 044, 200), Fateful = true }, // Larvitar @ Pyrite Town + new() { Species = 025, Level = 10, Language = l, Location = 255, ID32 = 31121, OT_Gender = 0, OT_Name = p[l], Version = GameVersion.R, CardTitle = $"Colosseum Pikachu ({id})",Method = PIDType.CXD, Shiny = Shiny.Never, NotDistributed = nd }, // Colosseum Pikachu bonus gift + new() { Species = 251, Level = 10, Language = l, Location = 255, ID32 = 31121, OT_Gender = 1, OT_Name = c[l], Version = GameVersion.R, CardTitle = $"Agate Celebi ({id})", Method = PIDType.CXD, Shiny = Shiny.Never, NotDistributed = nd }, // Ageto Celebi bonus gift + new() { Species = 250, Level = 70, Language = l, Location = 255, ID32 = 10048, OT_Gender = 0, OT_Name = m[l], Version = GameVersion.S, CardTitle = $"Mt. Battle Ho-Oh ({id})", Method = PIDType.CXD, Shiny = Shiny.Never, Moves = new(105, 126, 241, 129) }, // Ho-oh @ Mt. Battle }; } } - internal static readonly WC3[] Encounter_Event3 = Encounter_Event3_Special.Concat(GetIngameCXDData()).ToArray(); + internal static readonly WC3[] Encounter_WC3CXD = GetIngameCXDData().ToArray(); + internal static readonly WC3[] Encounter_WC3CXDMain = GetIngameCXDDataMainline().ToArray(); + + internal static readonly WC3[] Encounter_Event3 = ArrayUtil.ConcatAll(Encounter_Event3_Special, Encounter_WC3CXD, Encounter_WC3CXDMain); internal static readonly WC3[] Encounter_Event3_FRLG = { // PCJP - Egg Pokémon Present Eggs (March 21 to April 4, 2004) - new() { Species = 043, IsEgg = true, Fateful = true, Level = 05, TID = -1, SID = -1, Version = GameVersion.FRLG, Moves = new(071,073,000,000), Method = PIDType.Method_2 }, // Oddish with Leech Seed - new() { Species = 052, IsEgg = true, Fateful = true, Level = 05, TID = -1, SID = -1, Version = GameVersion.FRLG, Moves = new(010,045,080,000), Method = PIDType.Method_2 }, // Meowth with Petal Dance - new() { Species = 060, IsEgg = true, Fateful = true, Level = 05, TID = -1, SID = -1, Version = GameVersion.FRLG, Moves = new(145,186,000,000), Method = PIDType.Method_2 }, // Poliwag with Sweet Kiss - new() { Species = 069, IsEgg = true, Fateful = true, Level = 05, TID = -1, SID = -1, Version = GameVersion.FRLG, Moves = new(022,298,000,000), Method = PIDType.Method_2 }, // Bellsprout with Teeter Dance + new(true) { Species = 043, IsEgg = true, Level = 05, Version = GameVersion.FRLG, Moves = new(071,073,000,000), Method = PIDType.Method_2 }, // Oddish with Leech Seed + new(true) { Species = 052, IsEgg = true, Level = 05, Version = GameVersion.FRLG, Moves = new(010,045,080,000), Method = PIDType.Method_2 }, // Meowth with Petal Dance + new(true) { Species = 060, IsEgg = true, Level = 05, Version = GameVersion.FRLG, Moves = new(145,186,000,000), Method = PIDType.Method_2 }, // Poliwag with Sweet Kiss + new(true) { Species = 069, IsEgg = true, Level = 05, Version = GameVersion.FRLG, Moves = new(022,298,000,000), Method = PIDType.Method_2 }, // Bellsprout with Teeter Dance // PCNY - Wish Eggs (December 16, 2004, to January 2, 2005) - new() { Species = 083, IsEgg = true, Fateful = true, Level = 05, TID = -1, SID = -1, Version = GameVersion.FRLG, Moves = new(281,273,000,000), Method = PIDType.Method_2 }, // Farfetch'd with Wish & Yawn - new() { Species = 096, IsEgg = true, Fateful = true, Level = 05, TID = -1, SID = -1, Version = GameVersion.FRLG, Moves = new(187,273,000,000), Method = PIDType.Method_2 }, // Drowzee with Wish & Belly Drum - new() { Species = 102, IsEgg = true, Fateful = true, Level = 05, TID = -1, SID = -1, Version = GameVersion.FRLG, Moves = new(230,273,000,000), Method = PIDType.Method_2 }, // Exeggcute with Wish & Sweet Scent - new() { Species = 108, IsEgg = true, Fateful = true, Level = 05, TID = -1, SID = -1, Version = GameVersion.FRLG, Moves = new(215,273,000,000), Method = PIDType.Method_2 }, // Lickitung with Wish & Heal Bell - new() { Species = 113, IsEgg = true, Fateful = true, Level = 05, TID = -1, SID = -1, Version = GameVersion.FRLG, Moves = new(230,273,000,000), Method = PIDType.Method_2 }, // Chansey with Wish & Sweet Scent - new() { Species = 115, IsEgg = true, Fateful = true, Level = 05, TID = -1, SID = -1, Version = GameVersion.FRLG, Moves = new(281,273,000,000), Method = PIDType.Method_2 }, // Kangaskhan with Wish & Yawn + new(true) { Species = 083, IsEgg = true, Level = 05, Version = GameVersion.FRLG, Moves = new(281,273,000,000), Method = PIDType.Method_2 }, // Farfetch'd with Wish & Yawn + new(true) { Species = 096, IsEgg = true, Level = 05, Version = GameVersion.FRLG, Moves = new(187,273,000,000), Method = PIDType.Method_2 }, // Drowzee with Wish & Belly Drum + new(true) { Species = 102, IsEgg = true, Level = 05, Version = GameVersion.FRLG, Moves = new(230,273,000,000), Method = PIDType.Method_2 }, // Exeggcute with Wish & Sweet Scent + new(true) { Species = 108, IsEgg = true, Level = 05, Version = GameVersion.FRLG, Moves = new(215,273,000,000), Method = PIDType.Method_2 }, // Lickitung with Wish & Heal Bell + new(true) { Species = 113, IsEgg = true, Level = 05, Version = GameVersion.FRLG, Moves = new(230,273,000,000), Method = PIDType.Method_2 }, // Chansey with Wish & Sweet Scent + new(true) { Species = 115, IsEgg = true, Level = 05, Version = GameVersion.FRLG, Moves = new(281,273,000,000), Method = PIDType.Method_2 }, // Kangaskhan with Wish & Yawn // PokePark Eggs - Wondercard - new() { Species = 054, IsEgg = true, Fateful = true, Level = 05, TID = -1, SID = -1, Version = GameVersion.FRLG, Moves = new(346,010,039,300), Method = PIDType.Method_2 }, // Psyduck with Mud Sport - new() { Species = 172, IsEgg = true, Fateful = true, Level = 05, TID = -1, SID = -1, Version = GameVersion.FRLG, Moves = new(084,204,266,000), Method = PIDType.Method_2 }, // Pichu with Follow me - new() { Species = 174, IsEgg = true, Fateful = true, Level = 05, TID = -1, SID = -1, Version = GameVersion.FRLG, Moves = new(047,204,111,321), Method = PIDType.Method_2 }, // Igglybuff with Tickle - new() { Species = 222, IsEgg = true, Fateful = true, Level = 05, TID = -1, SID = -1, Version = GameVersion.FRLG, Moves = new(033,300,000,000), Method = PIDType.Method_2 }, // Corsola with Mud Sport - new() { Species = 276, IsEgg = true, Fateful = true, Level = 05, TID = -1, SID = -1, Version = GameVersion.FRLG, Moves = new(064,045,116,297), Method = PIDType.Method_2 }, // Taillow with Feather Dance - new() { Species = 283, IsEgg = true, Fateful = true, Level = 05, TID = -1, SID = -1, Version = GameVersion.FRLG, Moves = new(145,300,000,000), Method = PIDType.Method_2 }, // Surskit with Mud Sport - new() { Species = 293, IsEgg = true, Fateful = true, Level = 05, TID = -1, SID = -1, Version = GameVersion.FRLG, Moves = new(001,253,298,000), Method = PIDType.Method_2 }, // Whismur with Teeter Dance - new() { Species = 300, IsEgg = true, Fateful = true, Level = 05, TID = -1, SID = -1, Version = GameVersion.FRLG, Moves = new(045,033,039,205), Method = PIDType.Method_2 }, // Skitty with Rollout - new() { Species = 311, IsEgg = true, Fateful = true, Level = 05, TID = -1, SID = -1, Version = GameVersion.FRLG, Moves = new(045,086,346,000), Method = PIDType.Method_2 }, // Plusle with Water Sport - new() { Species = 312, IsEgg = true, Fateful = true, Level = 05, TID = -1, SID = -1, Version = GameVersion.FRLG, Moves = new(045,086,300,000), Method = PIDType.Method_2 }, // Minun with Mud Sport - new() { Species = 325, IsEgg = true, Fateful = true, Level = 05, TID = -1, SID = -1, Version = GameVersion.FRLG, Moves = new(150,253,000,000), Method = PIDType.Method_2 }, // Spoink with Uproar - new() { Species = 327, IsEgg = true, Fateful = true, Level = 05, TID = -1, SID = -1, Version = GameVersion.FRLG, Moves = new(033,253,047,000), Method = PIDType.Method_2 }, // Spinda with Sing - new() { Species = 331, IsEgg = true, Fateful = true, Level = 05, TID = -1, SID = -1, Version = GameVersion.FRLG, Moves = new(040,043,071,227), Method = PIDType.Method_2 }, // Cacnea with Encore - new() { Species = 341, IsEgg = true, Fateful = true, Level = 05, TID = -1, SID = -1, Version = GameVersion.FRLG, Moves = new(145,346,000,000), Method = PIDType.Method_2 }, // Corphish with Water Sport - new() { Species = 360, IsEgg = true, Fateful = true, Level = 05, TID = -1, SID = -1, Version = GameVersion.FRLG, Moves = new(150,204,227,321), Method = PIDType.Method_2 }, // Wynaut with Tickle + new(true) { Species = 054, IsEgg = true, Level = 05, Version = GameVersion.FRLG, Moves = new(346,010,039,300), Method = PIDType.Method_2 }, // Psyduck with Mud Sport + new(true) { Species = 172, IsEgg = true, Level = 05, Version = GameVersion.FRLG, Moves = new(084,204,266,000), Method = PIDType.Method_2 }, // Pichu with Follow me + new(true) { Species = 174, IsEgg = true, Level = 05, Version = GameVersion.FRLG, Moves = new(047,204,111,321), Method = PIDType.Method_2 }, // Igglybuff with Tickle + new(true) { Species = 222, IsEgg = true, Level = 05, Version = GameVersion.FRLG, Moves = new(033,300,000,000), Method = PIDType.Method_2 }, // Corsola with Mud Sport + new(true) { Species = 276, IsEgg = true, Level = 05, Version = GameVersion.FRLG, Moves = new(064,045,116,297), Method = PIDType.Method_2 }, // Taillow with Feather Dance + new(true) { Species = 283, IsEgg = true, Level = 05, Version = GameVersion.FRLG, Moves = new(145,300,000,000), Method = PIDType.Method_2 }, // Surskit with Mud Sport + new(true) { Species = 293, IsEgg = true, Level = 05, Version = GameVersion.FRLG, Moves = new(001,253,298,000), Method = PIDType.Method_2 }, // Whismur with Teeter Dance + new(true) { Species = 300, IsEgg = true, Level = 05, Version = GameVersion.FRLG, Moves = new(045,033,039,205), Method = PIDType.Method_2 }, // Skitty with Rollout + new(true) { Species = 311, IsEgg = true, Level = 05, Version = GameVersion.FRLG, Moves = new(045,086,346,000), Method = PIDType.Method_2 }, // Plusle with Water Sport + new(true) { Species = 312, IsEgg = true, Level = 05, Version = GameVersion.FRLG, Moves = new(045,086,300,000), Method = PIDType.Method_2 }, // Minun with Mud Sport + new(true) { Species = 325, IsEgg = true, Level = 05, Version = GameVersion.FRLG, Moves = new(150,253,000,000), Method = PIDType.Method_2 }, // Spoink with Uproar + new(true) { Species = 327, IsEgg = true, Level = 05, Version = GameVersion.FRLG, Moves = new(033,253,047,000), Method = PIDType.Method_2 }, // Spinda with Sing + new(true) { Species = 331, IsEgg = true, Level = 05, Version = GameVersion.FRLG, Moves = new(040,043,071,227), Method = PIDType.Method_2 }, // Cacnea with Encore + new(true) { Species = 341, IsEgg = true, Level = 05, Version = GameVersion.FRLG, Moves = new(145,346,000,000), Method = PIDType.Method_2 }, // Corphish with Water Sport + new(true) { Species = 360, IsEgg = true, Level = 05, Version = GameVersion.FRLG, Moves = new(150,204,227,321), Method = PIDType.Method_2 }, // Wynaut with Tickle }; internal static readonly WC3[] Encounter_Event3_RS = { // PCJP - Pokémon Center 5th Anniversary Eggs (April 25 to May 18, 2003) - new() { Species = 172, IsEgg = true, Level = 05, OT_Name = "オヤNAME", TID = -1, SID = -1, Version = GameVersion.R, Moves = new(084,204,298,000), Method = PIDType.BACD_R }, // Pichu with Teeter Dance - new() { Species = 172, IsEgg = true, Level = 05, OT_Name = "オヤNAME", TID = -1, SID = -1, Version = GameVersion.R, Moves = new(084,204,273,000), Method = PIDType.BACD_R }, // Pichu with Wish - new() { Species = 172, IsEgg = true, Level = 05, OT_Name = "オヤNAME", TID = -1, SID = -1, Version = GameVersion.R, Moves = new(084,204,298,000), Method = PIDType.BACD_R_S }, // Pichu with Teeter Dance - new() { Species = 172, IsEgg = true, Level = 05, OT_Name = "オヤNAME", TID = -1, SID = -1, Version = GameVersion.R, Moves = new(084,204,273,000), Method = PIDType.BACD_R_S }, // Pichu with Wish - new() { Species = 280, IsEgg = true, Level = 05, OT_Name = "オヤNAME", TID = -1, SID = -1, Version = GameVersion.R, Moves = new(045,204,000,000), Method = PIDType.BACD_R }, // Ralts with Charm - new() { Species = 280, IsEgg = true, Level = 05, OT_Name = "オヤNAME", TID = -1, SID = -1, Version = GameVersion.R, Moves = new(045,273,000,000), Method = PIDType.BACD_R }, // Ralts with Wish - new() { Species = 359, IsEgg = true, Level = 05, OT_Name = "オヤNAME", TID = -1, SID = -1, Version = GameVersion.R, Moves = new(010,043,180,000), Method = PIDType.BACD_R }, // Absol with Spite - new() { Species = 359, IsEgg = true, Level = 05, OT_Name = "オヤNAME", TID = -1, SID = -1, Version = GameVersion.R, Moves = new(010,043,273,000), Method = PIDType.BACD_R }, // Absol with Wish - new() { Species = 371, IsEgg = true, Level = 05, OT_Name = "オヤNAME", TID = -1, SID = -1, Version = GameVersion.R, Moves = new(099,044,334,000), Method = PIDType.BACD_R }, // Bagon with Iron Defense - new() { Species = 371, IsEgg = true, Level = 05, OT_Name = "オヤNAME", TID = -1, SID = -1, Version = GameVersion.R, Moves = new(099,044,273,000), Method = PIDType.BACD_R }, // Bagon with Wish + new() { Species = 172, IsEgg = true, Level = 05, OT_Name = "オヤNAME", Version = GameVersion.R, Moves = new(084,204,298,000), Method = PIDType.BACD_R }, // Pichu with Teeter Dance + new() { Species = 172, IsEgg = true, Level = 05, OT_Name = "オヤNAME", Version = GameVersion.R, Moves = new(084,204,273,000), Method = PIDType.BACD_R }, // Pichu with Wish + new() { Species = 172, IsEgg = true, Level = 05, OT_Name = "オヤNAME", Version = GameVersion.R, Moves = new(084,204,298,000), Method = PIDType.BACD_R_S }, // Pichu with Teeter Dance + new() { Species = 172, IsEgg = true, Level = 05, OT_Name = "オヤNAME", Version = GameVersion.R, Moves = new(084,204,273,000), Method = PIDType.BACD_R_S }, // Pichu with Wish + new() { Species = 280, IsEgg = true, Level = 05, OT_Name = "オヤNAME", Version = GameVersion.R, Moves = new(045,204,000,000), Method = PIDType.BACD_R }, // Ralts with Charm + new() { Species = 280, IsEgg = true, Level = 05, OT_Name = "オヤNAME", Version = GameVersion.R, Moves = new(045,273,000,000), Method = PIDType.BACD_R }, // Ralts with Wish + new() { Species = 359, IsEgg = true, Level = 05, OT_Name = "オヤNAME", Version = GameVersion.R, Moves = new(010,043,180,000), Method = PIDType.BACD_R }, // Absol with Spite + new() { Species = 359, IsEgg = true, Level = 05, OT_Name = "オヤNAME", Version = GameVersion.R, Moves = new(010,043,273,000), Method = PIDType.BACD_R }, // Absol with Wish + new() { Species = 371, IsEgg = true, Level = 05, OT_Name = "オヤNAME", Version = GameVersion.R, Moves = new(099,044,334,000), Method = PIDType.BACD_R }, // Bagon with Iron Defense + new() { Species = 371, IsEgg = true, Level = 05, OT_Name = "オヤNAME", Version = GameVersion.R, Moves = new(099,044,273,000), Method = PIDType.BACD_R }, // Bagon with Wish // Negai Boshi Jirachi - new() { Species = 385, Level = 05, TID = 30719, OT_Gender = 0, OT_Name = "ネガイボシ", Version = GameVersion.R, Method = PIDType.BACD_R, Language = (int)LanguageID.Japanese, Shiny = Shiny.Never }, - new() { Species = 385, Level = 05, TID = 30719, OT_Name = "ネガイボシ", Version = GameVersion.RS, Method = PIDType.BACD_U_AX, Language = (int)LanguageID.Japanese, Shiny = Shiny.Never }, + new() { Species = 385, Level = 05, ID32 = 30719, OT_Gender = 0, OT_Name = "ネガイボシ", Version = GameVersion.R, Method = PIDType.BACD_R, Language = (int)LanguageID.Japanese, Shiny = Shiny.Never }, + new() { Species = 385, Level = 05, ID32 = 30719, OT_Name = "ネガイボシ", Version = GameVersion.RS, Method = PIDType.BACD_U_AX, Language = (int)LanguageID.Japanese, Shiny = Shiny.Never }, // Berry Glitch Fix // PCJP - (December 29, 2003 to March 31, 2004) - new() { Species = 263, Level = 5, Version = GameVersion.S, Language = (int)LanguageID.Japanese, Method = PIDType.BACD_R_S, TID = 21121, OT_Name = "ルビー", OT_Gender = 1, Shiny = Shiny.Always }, - new() { Species = 263, Level = 5, Version = GameVersion.S, Language = (int)LanguageID.Japanese, Method = PIDType.BACD_R_S, TID = 21121, OT_Name = "サファイア", OT_Gender = 0, Shiny = Shiny.Always }, + new() { Species = 263, Level = 5, Version = GameVersion.S, Language = (int)LanguageID.Japanese, Method = PIDType.BACD_R_S, ID32 = 21121, OT_Name = "ルビー", OT_Gender = 1, Shiny = Shiny.Always }, + new() { Species = 263, Level = 5, Version = GameVersion.S, Language = (int)LanguageID.Japanese, Method = PIDType.BACD_R_S, ID32 = 21121, OT_Name = "サファイア", OT_Gender = 0, Shiny = Shiny.Always }, // EBGames/GameStop (March 1, 2004 to April 22, 2007), also via multi-game discs - new() { Species = 263, Level = 5, Version = GameVersion.S, Language = (int)LanguageID.English, Method = PIDType.BACD_R_S, TID = 30317, OT_Name = "RUBY", OT_Gender = 1 }, - new() { Species = 263, Level = 5, Version = GameVersion.S, Language = (int)LanguageID.English, Method = PIDType.BACD_R_S, TID = 30317, OT_Name = "SAPHIRE", OT_Gender = 0 }, + new() { Species = 263, Level = 5, Version = GameVersion.S, Language = (int)LanguageID.English, Method = PIDType.BACD_R_S, ID32 = 30317, OT_Name = "RUBY", OT_Gender = 1 }, + new() { Species = 263, Level = 5, Version = GameVersion.S, Language = (int)LanguageID.English, Method = PIDType.BACD_R_S, ID32 = 30317, OT_Name = "SAPHIRE", OT_Gender = 0 }, // Channel Jirachi - new() { Species = 385, Level = 5, Version = GameVersion.RS, Method = PIDType.Channel, TID = 40122, OT_Gender = 3,SID = -1, OT_Name = "CHANNEL", CardTitle = "Channel Jirachi", Met_Level = 0 }, + new() { Species = 385, Level = 5, Version = GameVersion.RS, Method = PIDType.Channel, TID16 = 40122, OT_Gender = 3, OT_Name = "CHANNEL", CardTitle = "Channel Jirachi", Met_Level = 0 }, // Aura Mew - new() { Species = 151, Level = 10, Version = GameVersion.R, Language = (int)LanguageID.English, Method = PIDType.BACD_R, TID = 20078, OT_Name = "Aura", Fateful = true, Shiny = Shiny.Never }, // Mew - new() { Species = 151, Level = 10, Version = GameVersion.R, Language = (int)LanguageID.French, Method = PIDType.BACD_R, TID = 20078, OT_Name = "Aura", Fateful = true, Shiny = Shiny.Never }, // Mew - new() { Species = 151, Level = 10, Version = GameVersion.R, Language = (int)LanguageID.Italian, Method = PIDType.BACD_R, TID = 20078, OT_Name = "Aura", Fateful = true, Shiny = Shiny.Never }, // Mew - new() { Species = 151, Level = 10, Version = GameVersion.R, Language = (int)LanguageID.German, Method = PIDType.BACD_R, TID = 20078, OT_Name = "Aura", Fateful = true, Shiny = Shiny.Never }, // Mew - new() { Species = 151, Level = 10, Version = GameVersion.R, Language = (int)LanguageID.Spanish, Method = PIDType.BACD_R, TID = 20078, OT_Name = "Aura", Fateful = true, Shiny = Shiny.Never }, // Mew + new(true) { Species = 151, Level = 10, Version = GameVersion.R, Language = (int)LanguageID.English, Method = PIDType.BACD_R, ID32 = 20078, OT_Name = "Aura", Shiny = Shiny.Never }, // Mew + new(true) { Species = 151, Level = 10, Version = GameVersion.R, Language = (int)LanguageID.French, Method = PIDType.BACD_R, ID32 = 20078, OT_Name = "Aura", Shiny = Shiny.Never }, // Mew + new(true) { Species = 151, Level = 10, Version = GameVersion.R, Language = (int)LanguageID.Italian, Method = PIDType.BACD_R, ID32 = 20078, OT_Name = "Aura", Shiny = Shiny.Never }, // Mew + new(true) { Species = 151, Level = 10, Version = GameVersion.R, Language = (int)LanguageID.German, Method = PIDType.BACD_R, ID32 = 20078, OT_Name = "Aura", Shiny = Shiny.Never }, // Mew + new(true) { Species = 151, Level = 10, Version = GameVersion.R, Language = (int)LanguageID.Spanish, Method = PIDType.BACD_R, ID32 = 20078, OT_Name = "Aura", Shiny = Shiny.Never }, // Mew // English Events - new() { Species = 006, Level = 70, Version = GameVersion.R, Moves = new(017,163,082,083), Language = (int)LanguageID.English, Method = PIDType.BACD_R, TID = 06227, OT_Name = "10ANNIV", Shiny = Shiny.Never }, // Charizard - new() { Species = 025, Level = 70, Version = GameVersion.R, Moves = new(085,097,087,113), Language = (int)LanguageID.English, Method = PIDType.BACD_R, TID = 06227, OT_Name = "10ANNIV", Shiny = Shiny.Never }, // Pikachu - new() { Species = 144, Level = 70, Version = GameVersion.R, Moves = new(097,170,058,115), Language = (int)LanguageID.English, Method = PIDType.BACD_R, TID = 06227, OT_Name = "10ANNIV", Shiny = Shiny.Never }, // Articuno - new() { Species = 243, Level = 70, Version = GameVersion.R, Moves = new(098,209,115,242), Language = (int)LanguageID.English, Method = PIDType.BACD_R, TID = 06227, OT_Name = "10ANNIV", Shiny = Shiny.Never }, // Raikou - new() { Species = 244, Level = 70, Version = GameVersion.R, Moves = new(083,023,053,207), Language = (int)LanguageID.English, Method = PIDType.BACD_R, TID = 06227, OT_Name = "10ANNIV", Shiny = Shiny.Never }, // Entei - new() { Species = 245, Level = 70, Version = GameVersion.R, Moves = new(016,062,054,243), Language = (int)LanguageID.English, Method = PIDType.BACD_R, TID = 06227, OT_Name = "10ANNIV", Shiny = Shiny.Never }, // Suicune - new() { Species = 249, Level = 70, Version = GameVersion.R, Moves = new(105,056,240,129), Language = (int)LanguageID.English, Method = PIDType.BACD_R, TID = 06227, OT_Name = "10ANNIV", Shiny = Shiny.Never }, // Lugia - new() { Species = 250, Level = 70, Version = GameVersion.R, Moves = new(105,126,241,129), Language = (int)LanguageID.English, Method = PIDType.BACD_R, TID = 06227, OT_Name = "10ANNIV", Shiny = Shiny.Never }, // Ho-Oh - new() { Species = 380, Level = 70, Version = GameVersion.R, Moves = new(296,094,105,204), Language = (int)LanguageID.English, Method = PIDType.BACD_R, TID = 06227, OT_Name = "10ANNIV", Shiny = Shiny.Never }, // Latias - new() { Species = 381, Level = 70, Version = GameVersion.R, Moves = new(295,094,105,349), Language = (int)LanguageID.English, Method = PIDType.BACD_R, TID = 06227, OT_Name = "10ANNIV", Shiny = Shiny.Never }, // Latios + new() { Species = 006, Level = 70, Version = GameVersion.R, Moves = new(017,163,082,083), Language = (int)LanguageID.English, Method = PIDType.BACD_R, ID32 = 06227, OT_Name = "10ANNIV", Shiny = Shiny.Never }, // Charizard + new() { Species = 025, Level = 70, Version = GameVersion.R, Moves = new(085,097,087,113), Language = (int)LanguageID.English, Method = PIDType.BACD_R, ID32 = 06227, OT_Name = "10ANNIV", Shiny = Shiny.Never }, // Pikachu + new() { Species = 144, Level = 70, Version = GameVersion.R, Moves = new(097,170,058,115), Language = (int)LanguageID.English, Method = PIDType.BACD_R, ID32 = 06227, OT_Name = "10ANNIV", Shiny = Shiny.Never }, // Articuno + new() { Species = 243, Level = 70, Version = GameVersion.R, Moves = new(098,209,115,242), Language = (int)LanguageID.English, Method = PIDType.BACD_R, ID32 = 06227, OT_Name = "10ANNIV", Shiny = Shiny.Never }, // Raikou + new() { Species = 244, Level = 70, Version = GameVersion.R, Moves = new(083,023,053,207), Language = (int)LanguageID.English, Method = PIDType.BACD_R, ID32 = 06227, OT_Name = "10ANNIV", Shiny = Shiny.Never }, // Entei + new() { Species = 245, Level = 70, Version = GameVersion.R, Moves = new(016,062,054,243), Language = (int)LanguageID.English, Method = PIDType.BACD_R, ID32 = 06227, OT_Name = "10ANNIV", Shiny = Shiny.Never }, // Suicune + new() { Species = 249, Level = 70, Version = GameVersion.R, Moves = new(105,056,240,129), Language = (int)LanguageID.English, Method = PIDType.BACD_R, ID32 = 06227, OT_Name = "10ANNIV", Shiny = Shiny.Never }, // Lugia + new() { Species = 250, Level = 70, Version = GameVersion.R, Moves = new(105,126,241,129), Language = (int)LanguageID.English, Method = PIDType.BACD_R, ID32 = 06227, OT_Name = "10ANNIV", Shiny = Shiny.Never }, // Ho-Oh + new() { Species = 380, Level = 70, Version = GameVersion.R, Moves = new(296,094,105,204), Language = (int)LanguageID.English, Method = PIDType.BACD_R, ID32 = 06227, OT_Name = "10ANNIV", Shiny = Shiny.Never }, // Latias + new() { Species = 381, Level = 70, Version = GameVersion.R, Moves = new(295,094,105,349), Language = (int)LanguageID.English, Method = PIDType.BACD_R, ID32 = 06227, OT_Name = "10ANNIV", Shiny = Shiny.Never }, // Latios // French - new() { Species = 006, Level = 70, Version = GameVersion.R, Moves = new(017,163,082,083), Language = (int)LanguageID.French, Method = PIDType.BACD_R, TID = 06227, OT_Name = "10ANNIV", Shiny = Shiny.Never }, // Charizard - new() { Species = 025, Level = 70, Version = GameVersion.R, Moves = new(085,097,087,113), Language = (int)LanguageID.French, Method = PIDType.BACD_R, TID = 06227, OT_Name = "10ANNIV", Shiny = Shiny.Never }, // Pikachu - new() { Species = 144, Level = 70, Version = GameVersion.R, Moves = new(097,170,058,115), Language = (int)LanguageID.French, Method = PIDType.BACD_R, TID = 06227, OT_Name = "10ANNIV", Shiny = Shiny.Never }, // Articuno - new() { Species = 243, Level = 70, Version = GameVersion.R, Moves = new(098,209,115,242), Language = (int)LanguageID.French, Method = PIDType.BACD_R, TID = 06227, OT_Name = "10ANNIV", Shiny = Shiny.Never }, // Raikou - new() { Species = 244, Level = 70, Version = GameVersion.R, Moves = new(083,023,053,207), Language = (int)LanguageID.French, Method = PIDType.BACD_R, TID = 06227, OT_Name = "10ANNIV", Shiny = Shiny.Never }, // Entei - new() { Species = 245, Level = 70, Version = GameVersion.R, Moves = new(016,062,054,243), Language = (int)LanguageID.French, Method = PIDType.BACD_R, TID = 06227, OT_Name = "10ANNIV", Shiny = Shiny.Never }, // Suicune - new() { Species = 249, Level = 70, Version = GameVersion.R, Moves = new(105,056,240,129), Language = (int)LanguageID.French, Method = PIDType.BACD_R, TID = 06227, OT_Name = "10ANNIV", Shiny = Shiny.Never }, // Lugia - new() { Species = 250, Level = 70, Version = GameVersion.R, Moves = new(105,126,241,129), Language = (int)LanguageID.French, Method = PIDType.BACD_R, TID = 06227, OT_Name = "10ANNIV", Shiny = Shiny.Never }, // Ho-Oh - new() { Species = 380, Level = 70, Version = GameVersion.R, Moves = new(296,094,105,204), Language = (int)LanguageID.French, Method = PIDType.BACD_R, TID = 06227, OT_Name = "10ANNIV", Shiny = Shiny.Never }, // Latias - new() { Species = 381, Level = 70, Version = GameVersion.R, Moves = new(295,094,105,349), Language = (int)LanguageID.French, Method = PIDType.BACD_R, TID = 06227, OT_Name = "10ANNIV", Shiny = Shiny.Never }, // Latios + new() { Species = 006, Level = 70, Version = GameVersion.R, Moves = new(017,163,082,083), Language = (int)LanguageID.French, Method = PIDType.BACD_R, ID32 = 06227, OT_Name = "10ANNIV", Shiny = Shiny.Never }, // Charizard + new() { Species = 025, Level = 70, Version = GameVersion.R, Moves = new(085,097,087,113), Language = (int)LanguageID.French, Method = PIDType.BACD_R, ID32 = 06227, OT_Name = "10ANNIV", Shiny = Shiny.Never }, // Pikachu + new() { Species = 144, Level = 70, Version = GameVersion.R, Moves = new(097,170,058,115), Language = (int)LanguageID.French, Method = PIDType.BACD_R, ID32 = 06227, OT_Name = "10ANNIV", Shiny = Shiny.Never }, // Articuno + new() { Species = 243, Level = 70, Version = GameVersion.R, Moves = new(098,209,115,242), Language = (int)LanguageID.French, Method = PIDType.BACD_R, ID32 = 06227, OT_Name = "10ANNIV", Shiny = Shiny.Never }, // Raikou + new() { Species = 244, Level = 70, Version = GameVersion.R, Moves = new(083,023,053,207), Language = (int)LanguageID.French, Method = PIDType.BACD_R, ID32 = 06227, OT_Name = "10ANNIV", Shiny = Shiny.Never }, // Entei + new() { Species = 245, Level = 70, Version = GameVersion.R, Moves = new(016,062,054,243), Language = (int)LanguageID.French, Method = PIDType.BACD_R, ID32 = 06227, OT_Name = "10ANNIV", Shiny = Shiny.Never }, // Suicune + new() { Species = 249, Level = 70, Version = GameVersion.R, Moves = new(105,056,240,129), Language = (int)LanguageID.French, Method = PIDType.BACD_R, ID32 = 06227, OT_Name = "10ANNIV", Shiny = Shiny.Never }, // Lugia + new() { Species = 250, Level = 70, Version = GameVersion.R, Moves = new(105,126,241,129), Language = (int)LanguageID.French, Method = PIDType.BACD_R, ID32 = 06227, OT_Name = "10ANNIV", Shiny = Shiny.Never }, // Ho-Oh + new() { Species = 380, Level = 70, Version = GameVersion.R, Moves = new(296,094,105,204), Language = (int)LanguageID.French, Method = PIDType.BACD_R, ID32 = 06227, OT_Name = "10ANNIV", Shiny = Shiny.Never }, // Latias + new() { Species = 381, Level = 70, Version = GameVersion.R, Moves = new(295,094,105,349), Language = (int)LanguageID.French, Method = PIDType.BACD_R, ID32 = 06227, OT_Name = "10ANNIV", Shiny = Shiny.Never }, // Latios // Italian - new() { Species = 006, Level = 70, Version = GameVersion.R, Moves = new(017,163,082,083), Language = (int)LanguageID.Italian, Method = PIDType.BACD_R, TID = 06227, OT_Name = "10ANNI", Shiny = Shiny.Never }, // Charizard - new() { Species = 025, Level = 70, Version = GameVersion.R, Moves = new(085,097,087,113), Language = (int)LanguageID.Italian, Method = PIDType.BACD_R, TID = 06227, OT_Name = "10ANNI", Shiny = Shiny.Never }, // Pikachu - new() { Species = 144, Level = 70, Version = GameVersion.R, Moves = new(097,170,058,115), Language = (int)LanguageID.Italian, Method = PIDType.BACD_R, TID = 06227, OT_Name = "10ANNI", Shiny = Shiny.Never }, // Articuno - new() { Species = 243, Level = 70, Version = GameVersion.R, Moves = new(098,209,115,242), Language = (int)LanguageID.Italian, Method = PIDType.BACD_R, TID = 06227, OT_Name = "10ANNI", Shiny = Shiny.Never }, // Raikou - new() { Species = 244, Level = 70, Version = GameVersion.R, Moves = new(083,023,053,207), Language = (int)LanguageID.Italian, Method = PIDType.BACD_R, TID = 06227, OT_Name = "10ANNI", Shiny = Shiny.Never }, // Entei - new() { Species = 245, Level = 70, Version = GameVersion.R, Moves = new(016,062,054,243), Language = (int)LanguageID.Italian, Method = PIDType.BACD_R, TID = 06227, OT_Name = "10ANNI", Shiny = Shiny.Never }, // Suicune - new() { Species = 249, Level = 70, Version = GameVersion.R, Moves = new(105,056,240,129), Language = (int)LanguageID.Italian, Method = PIDType.BACD_R, TID = 06227, OT_Name = "10ANNI", Shiny = Shiny.Never }, // Lugia - new() { Species = 250, Level = 70, Version = GameVersion.R, Moves = new(105,126,241,129), Language = (int)LanguageID.Italian, Method = PIDType.BACD_R, TID = 06227, OT_Name = "10ANNI", Shiny = Shiny.Never }, // Ho-Oh - new() { Species = 380, Level = 70, Version = GameVersion.R, Moves = new(296,094,105,204), Language = (int)LanguageID.Italian, Method = PIDType.BACD_R, TID = 06227, OT_Name = "10ANNI", Shiny = Shiny.Never }, // Latias - new() { Species = 381, Level = 70, Version = GameVersion.R, Moves = new(295,094,105,349), Language = (int)LanguageID.Italian, Method = PIDType.BACD_R, TID = 06227, OT_Name = "10ANNI", Shiny = Shiny.Never }, // Latios + new() { Species = 006, Level = 70, Version = GameVersion.R, Moves = new(017,163,082,083), Language = (int)LanguageID.Italian, Method = PIDType.BACD_R, ID32 = 06227, OT_Name = "10ANNI", Shiny = Shiny.Never }, // Charizard + new() { Species = 025, Level = 70, Version = GameVersion.R, Moves = new(085,097,087,113), Language = (int)LanguageID.Italian, Method = PIDType.BACD_R, ID32 = 06227, OT_Name = "10ANNI", Shiny = Shiny.Never }, // Pikachu + new() { Species = 144, Level = 70, Version = GameVersion.R, Moves = new(097,170,058,115), Language = (int)LanguageID.Italian, Method = PIDType.BACD_R, ID32 = 06227, OT_Name = "10ANNI", Shiny = Shiny.Never }, // Articuno + new() { Species = 243, Level = 70, Version = GameVersion.R, Moves = new(098,209,115,242), Language = (int)LanguageID.Italian, Method = PIDType.BACD_R, ID32 = 06227, OT_Name = "10ANNI", Shiny = Shiny.Never }, // Raikou + new() { Species = 244, Level = 70, Version = GameVersion.R, Moves = new(083,023,053,207), Language = (int)LanguageID.Italian, Method = PIDType.BACD_R, ID32 = 06227, OT_Name = "10ANNI", Shiny = Shiny.Never }, // Entei + new() { Species = 245, Level = 70, Version = GameVersion.R, Moves = new(016,062,054,243), Language = (int)LanguageID.Italian, Method = PIDType.BACD_R, ID32 = 06227, OT_Name = "10ANNI", Shiny = Shiny.Never }, // Suicune + new() { Species = 249, Level = 70, Version = GameVersion.R, Moves = new(105,056,240,129), Language = (int)LanguageID.Italian, Method = PIDType.BACD_R, ID32 = 06227, OT_Name = "10ANNI", Shiny = Shiny.Never }, // Lugia + new() { Species = 250, Level = 70, Version = GameVersion.R, Moves = new(105,126,241,129), Language = (int)LanguageID.Italian, Method = PIDType.BACD_R, ID32 = 06227, OT_Name = "10ANNI", Shiny = Shiny.Never }, // Ho-Oh + new() { Species = 380, Level = 70, Version = GameVersion.R, Moves = new(296,094,105,204), Language = (int)LanguageID.Italian, Method = PIDType.BACD_R, ID32 = 06227, OT_Name = "10ANNI", Shiny = Shiny.Never }, // Latias + new() { Species = 381, Level = 70, Version = GameVersion.R, Moves = new(295,094,105,349), Language = (int)LanguageID.Italian, Method = PIDType.BACD_R, ID32 = 06227, OT_Name = "10ANNI", Shiny = Shiny.Never }, // Latios // German - new() { Species = 006, Level = 70, Version = GameVersion.R, Moves = new(017,163,082,083), Language = (int)LanguageID.German, Method = PIDType.BACD_R, TID = 06227, OT_Name = "10JAHRE", Shiny = Shiny.Never }, // Charizard - new() { Species = 025, Level = 70, Version = GameVersion.R, Moves = new(085,097,087,113), Language = (int)LanguageID.German, Method = PIDType.BACD_R, TID = 06227, OT_Name = "10JAHRE", Shiny = Shiny.Never }, // Pikachu - new() { Species = 144, Level = 70, Version = GameVersion.R, Moves = new(097,170,058,115), Language = (int)LanguageID.German, Method = PIDType.BACD_R, TID = 06227, OT_Name = "10JAHRE", Shiny = Shiny.Never }, // Articuno - new() { Species = 243, Level = 70, Version = GameVersion.R, Moves = new(098,209,115,242), Language = (int)LanguageID.German, Method = PIDType.BACD_R, TID = 06227, OT_Name = "10JAHRE", Shiny = Shiny.Never }, // Raikou - new() { Species = 244, Level = 70, Version = GameVersion.R, Moves = new(083,023,053,207), Language = (int)LanguageID.German, Method = PIDType.BACD_R, TID = 06227, OT_Name = "10JAHRE", Shiny = Shiny.Never }, // Entei - new() { Species = 245, Level = 70, Version = GameVersion.R, Moves = new(016,062,054,243), Language = (int)LanguageID.German, Method = PIDType.BACD_R, TID = 06227, OT_Name = "10JAHRE", Shiny = Shiny.Never }, // Suicune - new() { Species = 249, Level = 70, Version = GameVersion.R, Moves = new(105,056,240,129), Language = (int)LanguageID.German, Method = PIDType.BACD_R, TID = 06227, OT_Name = "10JAHRE", Shiny = Shiny.Never }, // Lugia - new() { Species = 250, Level = 70, Version = GameVersion.R, Moves = new(105,126,241,129), Language = (int)LanguageID.German, Method = PIDType.BACD_R, TID = 06227, OT_Name = "10JAHRE", Shiny = Shiny.Never }, // Ho-Oh - new() { Species = 380, Level = 70, Version = GameVersion.R, Moves = new(296,094,105,204), Language = (int)LanguageID.German, Method = PIDType.BACD_R, TID = 06227, OT_Name = "10JAHRE", Shiny = Shiny.Never }, // Latias - new() { Species = 381, Level = 70, Version = GameVersion.R, Moves = new(295,094,105,349), Language = (int)LanguageID.German, Method = PIDType.BACD_R, TID = 06227, OT_Name = "10JAHRE", Shiny = Shiny.Never }, // Latios + new() { Species = 006, Level = 70, Version = GameVersion.R, Moves = new(017,163,082,083), Language = (int)LanguageID.German, Method = PIDType.BACD_R, ID32 = 06227, OT_Name = "10JAHRE", Shiny = Shiny.Never }, // Charizard + new() { Species = 025, Level = 70, Version = GameVersion.R, Moves = new(085,097,087,113), Language = (int)LanguageID.German, Method = PIDType.BACD_R, ID32 = 06227, OT_Name = "10JAHRE", Shiny = Shiny.Never }, // Pikachu + new() { Species = 144, Level = 70, Version = GameVersion.R, Moves = new(097,170,058,115), Language = (int)LanguageID.German, Method = PIDType.BACD_R, ID32 = 06227, OT_Name = "10JAHRE", Shiny = Shiny.Never }, // Articuno + new() { Species = 243, Level = 70, Version = GameVersion.R, Moves = new(098,209,115,242), Language = (int)LanguageID.German, Method = PIDType.BACD_R, ID32 = 06227, OT_Name = "10JAHRE", Shiny = Shiny.Never }, // Raikou + new() { Species = 244, Level = 70, Version = GameVersion.R, Moves = new(083,023,053,207), Language = (int)LanguageID.German, Method = PIDType.BACD_R, ID32 = 06227, OT_Name = "10JAHRE", Shiny = Shiny.Never }, // Entei + new() { Species = 245, Level = 70, Version = GameVersion.R, Moves = new(016,062,054,243), Language = (int)LanguageID.German, Method = PIDType.BACD_R, ID32 = 06227, OT_Name = "10JAHRE", Shiny = Shiny.Never }, // Suicune + new() { Species = 249, Level = 70, Version = GameVersion.R, Moves = new(105,056,240,129), Language = (int)LanguageID.German, Method = PIDType.BACD_R, ID32 = 06227, OT_Name = "10JAHRE", Shiny = Shiny.Never }, // Lugia + new() { Species = 250, Level = 70, Version = GameVersion.R, Moves = new(105,126,241,129), Language = (int)LanguageID.German, Method = PIDType.BACD_R, ID32 = 06227, OT_Name = "10JAHRE", Shiny = Shiny.Never }, // Ho-Oh + new() { Species = 380, Level = 70, Version = GameVersion.R, Moves = new(296,094,105,204), Language = (int)LanguageID.German, Method = PIDType.BACD_R, ID32 = 06227, OT_Name = "10JAHRE", Shiny = Shiny.Never }, // Latias + new() { Species = 381, Level = 70, Version = GameVersion.R, Moves = new(295,094,105,349), Language = (int)LanguageID.German, Method = PIDType.BACD_R, ID32 = 06227, OT_Name = "10JAHRE", Shiny = Shiny.Never }, // Latios // Spanish - new() { Species = 006, Level = 70, Version = GameVersion.R, Moves = new(017,163,082,083), Language = (int)LanguageID.Spanish, Method = PIDType.BACD_R, TID = 06227, OT_Name = "10ANIV", Shiny = Shiny.Never }, // Charizard - new() { Species = 025, Level = 70, Version = GameVersion.R, Moves = new(085,097,087,113), Language = (int)LanguageID.Spanish, Method = PIDType.BACD_R, TID = 06227, OT_Name = "10ANIV", Shiny = Shiny.Never }, // Pikachu - new() { Species = 144, Level = 70, Version = GameVersion.R, Moves = new(097,170,058,115), Language = (int)LanguageID.Spanish, Method = PIDType.BACD_R, TID = 06227, OT_Name = "10ANIV", Shiny = Shiny.Never }, // Articuno - new() { Species = 243, Level = 70, Version = GameVersion.R, Moves = new(098,209,115,242), Language = (int)LanguageID.Spanish, Method = PIDType.BACD_R, TID = 06227, OT_Name = "10ANIV", Shiny = Shiny.Never }, // Raikou - new() { Species = 244, Level = 70, Version = GameVersion.R, Moves = new(083,023,053,207), Language = (int)LanguageID.Spanish, Method = PIDType.BACD_R, TID = 06227, OT_Name = "10ANIV", Shiny = Shiny.Never }, // Entei - new() { Species = 245, Level = 70, Version = GameVersion.R, Moves = new(016,062,054,243), Language = (int)LanguageID.Spanish, Method = PIDType.BACD_R, TID = 06227, OT_Name = "10ANIV", Shiny = Shiny.Never }, // Suicune - new() { Species = 249, Level = 70, Version = GameVersion.R, Moves = new(105,056,240,129), Language = (int)LanguageID.Spanish, Method = PIDType.BACD_R, TID = 06227, OT_Name = "10ANIV", Shiny = Shiny.Never }, // Lugia - new() { Species = 250, Level = 70, Version = GameVersion.R, Moves = new(105,126,241,129), Language = (int)LanguageID.Spanish, Method = PIDType.BACD_R, TID = 06227, OT_Name = "10ANIV", Shiny = Shiny.Never }, // Ho-Oh - new() { Species = 380, Level = 70, Version = GameVersion.R, Moves = new(296,094,105,204), Language = (int)LanguageID.Spanish, Method = PIDType.BACD_R, TID = 06227, OT_Name = "10ANIV", Shiny = Shiny.Never }, // Latias - new() { Species = 381, Level = 70, Version = GameVersion.R, Moves = new(295,094,105,349), Language = (int)LanguageID.Spanish, Method = PIDType.BACD_R, TID = 06227, OT_Name = "10ANIV", Shiny = Shiny.Never }, // Latios + new() { Species = 006, Level = 70, Version = GameVersion.R, Moves = new(017,163,082,083), Language = (int)LanguageID.Spanish, Method = PIDType.BACD_R, ID32 = 06227, OT_Name = "10ANIV", Shiny = Shiny.Never }, // Charizard + new() { Species = 025, Level = 70, Version = GameVersion.R, Moves = new(085,097,087,113), Language = (int)LanguageID.Spanish, Method = PIDType.BACD_R, ID32 = 06227, OT_Name = "10ANIV", Shiny = Shiny.Never }, // Pikachu + new() { Species = 144, Level = 70, Version = GameVersion.R, Moves = new(097,170,058,115), Language = (int)LanguageID.Spanish, Method = PIDType.BACD_R, ID32 = 06227, OT_Name = "10ANIV", Shiny = Shiny.Never }, // Articuno + new() { Species = 243, Level = 70, Version = GameVersion.R, Moves = new(098,209,115,242), Language = (int)LanguageID.Spanish, Method = PIDType.BACD_R, ID32 = 06227, OT_Name = "10ANIV", Shiny = Shiny.Never }, // Raikou + new() { Species = 244, Level = 70, Version = GameVersion.R, Moves = new(083,023,053,207), Language = (int)LanguageID.Spanish, Method = PIDType.BACD_R, ID32 = 06227, OT_Name = "10ANIV", Shiny = Shiny.Never }, // Entei + new() { Species = 245, Level = 70, Version = GameVersion.R, Moves = new(016,062,054,243), Language = (int)LanguageID.Spanish, Method = PIDType.BACD_R, ID32 = 06227, OT_Name = "10ANIV", Shiny = Shiny.Never }, // Suicune + new() { Species = 249, Level = 70, Version = GameVersion.R, Moves = new(105,056,240,129), Language = (int)LanguageID.Spanish, Method = PIDType.BACD_R, ID32 = 06227, OT_Name = "10ANIV", Shiny = Shiny.Never }, // Lugia + new() { Species = 250, Level = 70, Version = GameVersion.R, Moves = new(105,126,241,129), Language = (int)LanguageID.Spanish, Method = PIDType.BACD_R, ID32 = 06227, OT_Name = "10ANIV", Shiny = Shiny.Never }, // Ho-Oh + new() { Species = 380, Level = 70, Version = GameVersion.R, Moves = new(296,094,105,204), Language = (int)LanguageID.Spanish, Method = PIDType.BACD_R, ID32 = 06227, OT_Name = "10ANIV", Shiny = Shiny.Never }, // Latias + new() { Species = 381, Level = 70, Version = GameVersion.R, Moves = new(295,094,105,349), Language = (int)LanguageID.Spanish, Method = PIDType.BACD_R, ID32 = 06227, OT_Name = "10ANIV", Shiny = Shiny.Never }, // Latios - new() { Species = 375, Level = 30, Version = GameVersion.R, Moves = new(036,093,232,287), Language = (int)LanguageID.English, Method = PIDType.BACD_R, TID = 02005, OT_Name = "ROCKS", OT_Gender = 0, RibbonNational = true, Shiny = Shiny.Never }, // Metang - new() { Species = 386, Level = 70, Version = GameVersion.R, Moves = new(322,105,354,063), Language = (int)LanguageID.English, Method = PIDType.BACD_R, TID = 28606, OT_Name = "DOEL", Fateful = true, Shiny = Shiny.Never }, // Deoxys - new() { Species = 386, Level = 70, Version = GameVersion.R, Moves = new(322,105,354,063), Language = (int)LanguageID.English, Method = PIDType.BACD_R, TID = 00010, OT_Name = "SPACE C", Fateful = true, Shiny = Shiny.Never }, // Deoxys - new() { Species = 151, Level = 10, Version = GameVersion.R, Language = (int)LanguageID.English, Method = PIDType.BACD_U, TID = 06930, OT_Name = "MYSTRY", Fateful = true, Shiny = Shiny.Never }, // Mew - new() { Species = 151, Level = 10, Version = GameVersion.R, Language = (int)LanguageID.English, Method = PIDType.BACD_R, TID = 06930, OT_Name = "MYSTRY", Fateful = true, Shiny = Shiny.Never }, // Mew + new() { Species = 375, Level = 30, Version = GameVersion.R, Moves = new(036,093,232,287), Language = (int)LanguageID.English, Method = PIDType.BACD_R, ID32 = 02005, OT_Name = "ROCKS", OT_Gender = 0, RibbonNational = true, Shiny = Shiny.Never }, // Metang + new(true) { Species = 386, Level = 70, Version = GameVersion.R, Moves = new(322,105,354,063), Language = (int)LanguageID.English, Method = PIDType.BACD_R, ID32 = 28606, OT_Name = "DOEL", Shiny = Shiny.Never }, // Deoxys + new(true) { Species = 386, Level = 70, Version = GameVersion.R, Moves = new(322,105,354,063), Language = (int)LanguageID.English, Method = PIDType.BACD_R, ID32 = 00010, OT_Name = "SPACE C", Shiny = Shiny.Never }, // Deoxys + new(true) { Species = 151, Level = 10, Version = GameVersion.R, Language = (int)LanguageID.English, Method = PIDType.BACD_U, ID32 = 06930, OT_Name = "MYSTRY", Shiny = Shiny.Never }, // Mew + new(true) { Species = 151, Level = 10, Version = GameVersion.R, Language = (int)LanguageID.English, Method = PIDType.BACD_R, ID32 = 06930, OT_Name = "MYSTRY", Shiny = Shiny.Never }, // Mew // Party of the Decade - new() { Species = 001, Level = 70, Version = GameVersion.R, Moves = new(230,074,076,235), Language = (int)LanguageID.English, Method = PIDType.BACD_R, TID = 06808, OT_Name = "10 ANIV", Shiny = Shiny.Never }, // Bulbasaur - new() { Species = 006, Level = 70, Version = GameVersion.R, Moves = new(017,163,082,083), Language = (int)LanguageID.English, Method = PIDType.BACD_R, TID = 06808, OT_Name = "10 ANIV", Shiny = Shiny.Never }, // Charizard - new() { Species = 009, Level = 70, Version = GameVersion.R, Moves = new(182,240,130,056), Language = (int)LanguageID.English, Method = PIDType.BACD_R, TID = 06808, OT_Name = "10 ANIV", Shiny = Shiny.Never }, // Blastoise - new() { Species = 025, Level = 70, Version = GameVersion.R, Moves = new(085,087,113,019), Language = (int)LanguageID.English, Method = PIDType.BACD_R, TID = 06808, OT_Name = "10 ANIV", HeldItem = 202, Shiny = Shiny.Never }, // Pikachu (Fly) - new() { Species = 065, Level = 70, Version = GameVersion.R, Moves = new(248,347,094,271), Language = (int)LanguageID.English, Method = PIDType.BACD_R, TID = 06808, OT_Name = "10 ANIV", Shiny = Shiny.Never }, // Alakazam - new() { Species = 144, Level = 70, Version = GameVersion.R, Moves = new(097,170,058,115), Language = (int)LanguageID.English, Method = PIDType.BACD_R, TID = 06808, OT_Name = "10 ANIV", Shiny = Shiny.Never }, // Articuno - new() { Species = 145, Level = 70, Version = GameVersion.R, Moves = new(097,197,065,268), Language = (int)LanguageID.English, Method = PIDType.BACD_R, TID = 06808, OT_Name = "10 ANIV", Shiny = Shiny.Never }, // Zapdos - new() { Species = 146, Level = 70, Version = GameVersion.R, Moves = new(097,203,053,219), Language = (int)LanguageID.English, Method = PIDType.BACD_R, TID = 06808, OT_Name = "10 ANIV", Shiny = Shiny.Never }, // Moltres - new() { Species = 149, Level = 70, Version = GameVersion.R, Moves = new(097,219,017,200), Language = (int)LanguageID.English, Method = PIDType.BACD_R, TID = 06808, OT_Name = "10 ANIV", Shiny = Shiny.Never }, // Dragonite - new() { Species = 157, Level = 70, Version = GameVersion.R, Moves = new(098,172,129,053), Language = (int)LanguageID.English, Method = PIDType.BACD_R, TID = 06808, OT_Name = "10 ANIV", Shiny = Shiny.Never }, // Typhlosion - new() { Species = 196, Level = 70, Version = GameVersion.R, Moves = new(060,244,094,234), Language = (int)LanguageID.English, Method = PIDType.BACD_R, TID = 06808, OT_Name = "10 ANIV", Shiny = Shiny.Never }, // Espeon - new() { Species = 197, Level = 70, Version = GameVersion.R, Moves = new(185,212,103,236), Language = (int)LanguageID.English, Method = PIDType.BACD_R, TID = 06808, OT_Name = "10 ANIV", Shiny = Shiny.Never }, // Umbreon - new() { Species = 243, Level = 70, Version = GameVersion.R, Moves = new(098,209,115,242), Language = (int)LanguageID.English, Method = PIDType.BACD_R, TID = 06808, OT_Name = "10 ANIV", Shiny = Shiny.Never }, // Raikou - new() { Species = 244, Level = 70, Version = GameVersion.R, Moves = new(083,023,053,207), Language = (int)LanguageID.English, Method = PIDType.BACD_R, TID = 06808, OT_Name = "10 ANIV", Shiny = Shiny.Never }, // Entei - new() { Species = 245, Level = 70, Version = GameVersion.R, Moves = new(016,062,054,243), Language = (int)LanguageID.English, Method = PIDType.BACD_R, TID = 06808, OT_Name = "10 ANIV", Shiny = Shiny.Never }, // Suicune - new() { Species = 248, Level = 70, Version = GameVersion.R, Moves = new(037,184,242,089), Language = (int)LanguageID.English, Method = PIDType.BACD_R, TID = 06808, OT_Name = "10 ANIV", Shiny = Shiny.Never }, // Tyranitar - new() { Species = 257, Level = 70, Version = GameVersion.R, Moves = new(299,163,119,327), Language = (int)LanguageID.English, Method = PIDType.BACD_R, TID = 06808, OT_Name = "10 ANIV", Shiny = Shiny.Never }, // Blaziken - new() { Species = 359, Level = 70, Version = GameVersion.R, Moves = new(104,163,248,195), Language = (int)LanguageID.English, Method = PIDType.BACD_R, TID = 06808, OT_Name = "10 ANIV", Shiny = Shiny.Never }, // Absol - new() { Species = 380, Level = 70, Version = GameVersion.R, Moves = new(296,094,105,204), Language = (int)LanguageID.English, Method = PIDType.BACD_R, TID = 06808, OT_Name = "10 ANIV", HeldItem = 191, Shiny = Shiny.Never }, // Latias - new() { Species = 381, Level = 70, Version = GameVersion.R, Moves = new(295,094,105,349), Language = (int)LanguageID.English, Method = PIDType.BACD_R, TID = 06808, OT_Name = "10 ANIV", HeldItem = 191, Shiny = Shiny.Never }, // Latios + new() { Species = 001, Level = 70, Version = GameVersion.R, Moves = new(230,074,076,235), Language = (int)LanguageID.English, Method = PIDType.BACD_R, ID32 = 06808, OT_Name = "10 ANIV", Shiny = Shiny.Never }, // Bulbasaur + new() { Species = 006, Level = 70, Version = GameVersion.R, Moves = new(017,163,082,083), Language = (int)LanguageID.English, Method = PIDType.BACD_R, ID32 = 06808, OT_Name = "10 ANIV", Shiny = Shiny.Never }, // Charizard + new() { Species = 009, Level = 70, Version = GameVersion.R, Moves = new(182,240,130,056), Language = (int)LanguageID.English, Method = PIDType.BACD_R, ID32 = 06808, OT_Name = "10 ANIV", Shiny = Shiny.Never }, // Blastoise + new() { Species = 025, Level = 70, Version = GameVersion.R, Moves = new(085,087,113,019), Language = (int)LanguageID.English, Method = PIDType.BACD_R, ID32 = 06808, OT_Name = "10 ANIV", HeldItem = 202, Shiny = Shiny.Never }, // Pikachu (Fly) + new() { Species = 065, Level = 70, Version = GameVersion.R, Moves = new(248,347,094,271), Language = (int)LanguageID.English, Method = PIDType.BACD_R, ID32 = 06808, OT_Name = "10 ANIV", Shiny = Shiny.Never }, // Alakazam + new() { Species = 144, Level = 70, Version = GameVersion.R, Moves = new(097,170,058,115), Language = (int)LanguageID.English, Method = PIDType.BACD_R, ID32 = 06808, OT_Name = "10 ANIV", Shiny = Shiny.Never }, // Articuno + new() { Species = 145, Level = 70, Version = GameVersion.R, Moves = new(097,197,065,268), Language = (int)LanguageID.English, Method = PIDType.BACD_R, ID32 = 06808, OT_Name = "10 ANIV", Shiny = Shiny.Never }, // Zapdos + new() { Species = 146, Level = 70, Version = GameVersion.R, Moves = new(097,203,053,219), Language = (int)LanguageID.English, Method = PIDType.BACD_R, ID32 = 06808, OT_Name = "10 ANIV", Shiny = Shiny.Never }, // Moltres + new() { Species = 149, Level = 70, Version = GameVersion.R, Moves = new(097,219,017,200), Language = (int)LanguageID.English, Method = PIDType.BACD_R, ID32 = 06808, OT_Name = "10 ANIV", Shiny = Shiny.Never }, // Dragonite + new() { Species = 157, Level = 70, Version = GameVersion.R, Moves = new(098,172,129,053), Language = (int)LanguageID.English, Method = PIDType.BACD_R, ID32 = 06808, OT_Name = "10 ANIV", Shiny = Shiny.Never }, // Typhlosion + new() { Species = 196, Level = 70, Version = GameVersion.R, Moves = new(060,244,094,234), Language = (int)LanguageID.English, Method = PIDType.BACD_R, ID32 = 06808, OT_Name = "10 ANIV", Shiny = Shiny.Never }, // Espeon + new() { Species = 197, Level = 70, Version = GameVersion.R, Moves = new(185,212,103,236), Language = (int)LanguageID.English, Method = PIDType.BACD_R, ID32 = 06808, OT_Name = "10 ANIV", Shiny = Shiny.Never }, // Umbreon + new() { Species = 243, Level = 70, Version = GameVersion.R, Moves = new(098,209,115,242), Language = (int)LanguageID.English, Method = PIDType.BACD_R, ID32 = 06808, OT_Name = "10 ANIV", Shiny = Shiny.Never }, // Raikou + new() { Species = 244, Level = 70, Version = GameVersion.R, Moves = new(083,023,053,207), Language = (int)LanguageID.English, Method = PIDType.BACD_R, ID32 = 06808, OT_Name = "10 ANIV", Shiny = Shiny.Never }, // Entei + new() { Species = 245, Level = 70, Version = GameVersion.R, Moves = new(016,062,054,243), Language = (int)LanguageID.English, Method = PIDType.BACD_R, ID32 = 06808, OT_Name = "10 ANIV", Shiny = Shiny.Never }, // Suicune + new() { Species = 248, Level = 70, Version = GameVersion.R, Moves = new(037,184,242,089), Language = (int)LanguageID.English, Method = PIDType.BACD_R, ID32 = 06808, OT_Name = "10 ANIV", Shiny = Shiny.Never }, // Tyranitar + new() { Species = 257, Level = 70, Version = GameVersion.R, Moves = new(299,163,119,327), Language = (int)LanguageID.English, Method = PIDType.BACD_R, ID32 = 06808, OT_Name = "10 ANIV", Shiny = Shiny.Never }, // Blaziken + new() { Species = 359, Level = 70, Version = GameVersion.R, Moves = new(104,163,248,195), Language = (int)LanguageID.English, Method = PIDType.BACD_R, ID32 = 06808, OT_Name = "10 ANIV", Shiny = Shiny.Never }, // Absol + new() { Species = 380, Level = 70, Version = GameVersion.R, Moves = new(296,094,105,204), Language = (int)LanguageID.English, Method = PIDType.BACD_R, ID32 = 06808, OT_Name = "10 ANIV", HeldItem = 191, Shiny = Shiny.Never }, // Latias + new() { Species = 381, Level = 70, Version = GameVersion.R, Moves = new(295,094,105,349), Language = (int)LanguageID.English, Method = PIDType.BACD_R, ID32 = 06808, OT_Name = "10 ANIV", HeldItem = 191, Shiny = Shiny.Never }, // Latios // Journey Across America - new() { Species = 001, Level = 70, Version = GameVersion.R, Moves = new(230,074,076,235), Language = (int)LanguageID.English, Method = PIDType.BACD_R, TID = 00010, OT_Name = "10 ANIV", Shiny = Shiny.Never }, // Bulbasaur - new() { Species = 006, Level = 70, Version = GameVersion.R, Moves = new(017,163,082,083), Language = (int)LanguageID.English, Method = PIDType.BACD_R, TID = 00010, OT_Name = "10 ANIV", Shiny = Shiny.Never }, // Charizard - new() { Species = 009, Level = 70, Version = GameVersion.R, Moves = new(182,240,130,056), Language = (int)LanguageID.English, Method = PIDType.BACD_R, TID = 00010, OT_Name = "10 ANIV", Shiny = Shiny.Never }, // Blastoise - new() { Species = 025, Level = 70, Version = GameVersion.R, Moves = new(085,097,087,113), Language = (int)LanguageID.English, Method = PIDType.BACD_R, TID = 00010, OT_Name = "10 ANIV", HeldItem = 202, Shiny = Shiny.Never }, // Pikachu (No Fly) - new() { Species = 065, Level = 70, Version = GameVersion.R, Moves = new(248,347,094,271), Language = (int)LanguageID.English, Method = PIDType.BACD_R, TID = 00010, OT_Name = "10 ANIV", Shiny = Shiny.Never }, // Alakazam - new() { Species = 144, Level = 70, Version = GameVersion.R, Moves = new(097,170,058,115), Language = (int)LanguageID.English, Method = PIDType.BACD_R, TID = 00010, OT_Name = "10 ANIV", Shiny = Shiny.Never }, // Articuno - new() { Species = 145, Level = 70, Version = GameVersion.R, Moves = new(097,197,065,268), Language = (int)LanguageID.English, Method = PIDType.BACD_R, TID = 00010, OT_Name = "10 ANIV", Shiny = Shiny.Never }, // Zapdos - new() { Species = 146, Level = 70, Version = GameVersion.R, Moves = new(097,203,053,219), Language = (int)LanguageID.English, Method = PIDType.BACD_R, TID = 00010, OT_Name = "10 ANIV", Shiny = Shiny.Never }, // Moltres - new() { Species = 149, Level = 70, Version = GameVersion.R, Moves = new(097,219,017,200), Language = (int)LanguageID.English, Method = PIDType.BACD_R, TID = 00010, OT_Name = "10 ANIV", Shiny = Shiny.Never }, // Dragonite - new() { Species = 157, Level = 70, Version = GameVersion.R, Moves = new(098,172,129,053), Language = (int)LanguageID.English, Method = PIDType.BACD_R, TID = 00010, OT_Name = "10 ANIV", Shiny = Shiny.Never }, // Typhlosion - new() { Species = 196, Level = 70, Version = GameVersion.R, Moves = new(060,244,094,234), Language = (int)LanguageID.English, Method = PIDType.BACD_R, TID = 00010, OT_Name = "10 ANIV", Shiny = Shiny.Never }, // Espeon - new() { Species = 197, Level = 70, Version = GameVersion.R, Moves = new(185,212,103,236), Language = (int)LanguageID.English, Method = PIDType.BACD_R, TID = 00010, OT_Name = "10 ANIV", Shiny = Shiny.Never }, // Umbreon - new() { Species = 243, Level = 70, Version = GameVersion.R, Moves = new(098,209,115,242), Language = (int)LanguageID.English, Method = PIDType.BACD_R, TID = 00010, OT_Name = "10 ANIV", Shiny = Shiny.Never }, // Raikou - new() { Species = 244, Level = 70, Version = GameVersion.R, Moves = new(083,023,053,207), Language = (int)LanguageID.English, Method = PIDType.BACD_R, TID = 00010, OT_Name = "10 ANIV", Shiny = Shiny.Never }, // Entei - new() { Species = 245, Level = 70, Version = GameVersion.R, Moves = new(016,062,054,243), Language = (int)LanguageID.English, Method = PIDType.BACD_R, TID = 00010, OT_Name = "10 ANIV", Shiny = Shiny.Never }, // Suicune - new() { Species = 248, Level = 70, Version = GameVersion.R, Moves = new(037,184,242,089), Language = (int)LanguageID.English, Method = PIDType.BACD_R, TID = 00010, OT_Name = "10 ANIV", Shiny = Shiny.Never }, // Tyranitar - new() { Species = 251, Level = 70, Version = GameVersion.R, Moves = new(246,248,226,195), Language = (int)LanguageID.English, Method = PIDType.BACD_R, TID = 00010, OT_Name = "10 ANIV", Shiny = Shiny.Never }, // Celebi - new() { Species = 257, Level = 70, Version = GameVersion.R, Moves = new(299,163,119,327), Language = (int)LanguageID.English, Method = PIDType.BACD_R, TID = 00010, OT_Name = "10 ANIV", Shiny = Shiny.Never }, // Blaziken - new() { Species = 359, Level = 70, Version = GameVersion.R, Moves = new(104,163,248,195), Language = (int)LanguageID.English, Method = PIDType.BACD_R, TID = 00010, OT_Name = "10 ANIV", Shiny = Shiny.Never }, // Absol - new() { Species = 380, Level = 70, Version = GameVersion.R, Moves = new(296,094,105,204), Language = (int)LanguageID.English, Method = PIDType.BACD_R, TID = 00010, OT_Name = "10 ANIV", HeldItem = 191, Shiny = Shiny.Never }, // Latias - new() { Species = 381, Level = 70, Version = GameVersion.R, Moves = new(295,094,105,349), Language = (int)LanguageID.English, Method = PIDType.BACD_R, TID = 00010, OT_Name = "10 ANIV", HeldItem = 191, Shiny = Shiny.Never }, // Latios + new() { Species = 001, Level = 70, Version = GameVersion.R, Moves = new(230,074,076,235), Language = (int)LanguageID.English, Method = PIDType.BACD_R, ID32 = 00010, OT_Name = "10 ANIV", Shiny = Shiny.Never }, // Bulbasaur + new() { Species = 006, Level = 70, Version = GameVersion.R, Moves = new(017,163,082,083), Language = (int)LanguageID.English, Method = PIDType.BACD_R, ID32 = 00010, OT_Name = "10 ANIV", Shiny = Shiny.Never }, // Charizard + new() { Species = 009, Level = 70, Version = GameVersion.R, Moves = new(182,240,130,056), Language = (int)LanguageID.English, Method = PIDType.BACD_R, ID32 = 00010, OT_Name = "10 ANIV", Shiny = Shiny.Never }, // Blastoise + new() { Species = 025, Level = 70, Version = GameVersion.R, Moves = new(085,097,087,113), Language = (int)LanguageID.English, Method = PIDType.BACD_R, ID32 = 00010, OT_Name = "10 ANIV", HeldItem = 202, Shiny = Shiny.Never }, // Pikachu (No Fly) + new() { Species = 065, Level = 70, Version = GameVersion.R, Moves = new(248,347,094,271), Language = (int)LanguageID.English, Method = PIDType.BACD_R, ID32 = 00010, OT_Name = "10 ANIV", Shiny = Shiny.Never }, // Alakazam + new() { Species = 144, Level = 70, Version = GameVersion.R, Moves = new(097,170,058,115), Language = (int)LanguageID.English, Method = PIDType.BACD_R, ID32 = 00010, OT_Name = "10 ANIV", Shiny = Shiny.Never }, // Articuno + new() { Species = 145, Level = 70, Version = GameVersion.R, Moves = new(097,197,065,268), Language = (int)LanguageID.English, Method = PIDType.BACD_R, ID32 = 00010, OT_Name = "10 ANIV", Shiny = Shiny.Never }, // Zapdos + new() { Species = 146, Level = 70, Version = GameVersion.R, Moves = new(097,203,053,219), Language = (int)LanguageID.English, Method = PIDType.BACD_R, ID32 = 00010, OT_Name = "10 ANIV", Shiny = Shiny.Never }, // Moltres + new() { Species = 149, Level = 70, Version = GameVersion.R, Moves = new(097,219,017,200), Language = (int)LanguageID.English, Method = PIDType.BACD_R, ID32 = 00010, OT_Name = "10 ANIV", Shiny = Shiny.Never }, // Dragonite + new() { Species = 157, Level = 70, Version = GameVersion.R, Moves = new(098,172,129,053), Language = (int)LanguageID.English, Method = PIDType.BACD_R, ID32 = 00010, OT_Name = "10 ANIV", Shiny = Shiny.Never }, // Typhlosion + new() { Species = 196, Level = 70, Version = GameVersion.R, Moves = new(060,244,094,234), Language = (int)LanguageID.English, Method = PIDType.BACD_R, ID32 = 00010, OT_Name = "10 ANIV", Shiny = Shiny.Never }, // Espeon + new() { Species = 197, Level = 70, Version = GameVersion.R, Moves = new(185,212,103,236), Language = (int)LanguageID.English, Method = PIDType.BACD_R, ID32 = 00010, OT_Name = "10 ANIV", Shiny = Shiny.Never }, // Umbreon + new() { Species = 243, Level = 70, Version = GameVersion.R, Moves = new(098,209,115,242), Language = (int)LanguageID.English, Method = PIDType.BACD_R, ID32 = 00010, OT_Name = "10 ANIV", Shiny = Shiny.Never }, // Raikou + new() { Species = 244, Level = 70, Version = GameVersion.R, Moves = new(083,023,053,207), Language = (int)LanguageID.English, Method = PIDType.BACD_R, ID32 = 00010, OT_Name = "10 ANIV", Shiny = Shiny.Never }, // Entei + new() { Species = 245, Level = 70, Version = GameVersion.R, Moves = new(016,062,054,243), Language = (int)LanguageID.English, Method = PIDType.BACD_R, ID32 = 00010, OT_Name = "10 ANIV", Shiny = Shiny.Never }, // Suicune + new() { Species = 248, Level = 70, Version = GameVersion.R, Moves = new(037,184,242,089), Language = (int)LanguageID.English, Method = PIDType.BACD_R, ID32 = 00010, OT_Name = "10 ANIV", Shiny = Shiny.Never }, // Tyranitar + new() { Species = 251, Level = 70, Version = GameVersion.R, Moves = new(246,248,226,195), Language = (int)LanguageID.English, Method = PIDType.BACD_R, ID32 = 00010, OT_Name = "10 ANIV", Shiny = Shiny.Never }, // Celebi + new() { Species = 257, Level = 70, Version = GameVersion.R, Moves = new(299,163,119,327), Language = (int)LanguageID.English, Method = PIDType.BACD_R, ID32 = 00010, OT_Name = "10 ANIV", Shiny = Shiny.Never }, // Blaziken + new() { Species = 359, Level = 70, Version = GameVersion.R, Moves = new(104,163,248,195), Language = (int)LanguageID.English, Method = PIDType.BACD_R, ID32 = 00010, OT_Name = "10 ANIV", Shiny = Shiny.Never }, // Absol + new() { Species = 380, Level = 70, Version = GameVersion.R, Moves = new(296,094,105,204), Language = (int)LanguageID.English, Method = PIDType.BACD_R, ID32 = 00010, OT_Name = "10 ANIV", HeldItem = 191, Shiny = Shiny.Never }, // Latias + new() { Species = 381, Level = 70, Version = GameVersion.R, Moves = new(295,094,105,349), Language = (int)LanguageID.English, Method = PIDType.BACD_R, ID32 = 00010, OT_Name = "10 ANIV", HeldItem = 191, Shiny = Shiny.Never }, // Latios }; internal static readonly WC3[] Encounter_Event3_Common = @@ -247,21 +265,21 @@ internal static class EncountersWC3 new() { Species = 172, IsEgg = true, Level = 05, Moves = new(084,204,057,000), Method = PIDType.BACD_U, OT_Gender = 1, OT_Name = "AZUSA", Version = GameVersion.FRLG }, // Pichu Egg with Surf // PokePark Eggs - DS Download Play - new() { Species = 054, IsEgg = true, Level = 05, Met_Level = 05, TID = 50318, OT_Gender = 0, OT_Name = "ポケパーク", Version = GameVersion.R, Moves = new(300), Method = PIDType.BACD_R }, // Psyduck with Mud Sport - new() { Species = 172, IsEgg = true, Level = 05, Met_Level = 05, TID = 50318, OT_Gender = 0, OT_Name = "ポケパーク", Version = GameVersion.R, Moves = new(266), Method = PIDType.BACD_R }, // Pichu with Follow Me - new() { Species = 174, IsEgg = true, Level = 05, Met_Level = 05, TID = 50318, OT_Gender = 0, OT_Name = "ポケパーク", Version = GameVersion.R, Moves = new(321), Method = PIDType.BACD_R }, // Igglybuff with Tickle - new() { Species = 222, IsEgg = true, Level = 05, Met_Level = 05, TID = 50318, OT_Gender = 0, OT_Name = "ポケパーク", Version = GameVersion.R, Moves = new(300), Method = PIDType.BACD_R }, // Corsola with Mud Sport - new() { Species = 276, IsEgg = true, Level = 05, Met_Level = 05, TID = 50318, OT_Gender = 0, OT_Name = "ポケパーク", Version = GameVersion.R, Moves = new(297), Method = PIDType.BACD_R }, // Taillow with Feather Dance - new() { Species = 283, IsEgg = true, Level = 05, Met_Level = 05, TID = 50318, OT_Gender = 0, OT_Name = "ポケパーク", Version = GameVersion.R, Moves = new(300), Method = PIDType.BACD_R }, // Surskit with Mud Sport - new() { Species = 293, IsEgg = true, Level = 05, Met_Level = 05, TID = 50318, OT_Gender = 0, OT_Name = "ポケパーク", Version = GameVersion.R, Moves = new(298), Method = PIDType.BACD_R }, // Whismur with Teeter Dance - new() { Species = 300, IsEgg = true, Level = 05, Met_Level = 05, TID = 50318, OT_Gender = 0, OT_Name = "ポケパーク", Version = GameVersion.R, Moves = new(205), Method = PIDType.BACD_R }, // Skitty with Rollout - new() { Species = 311, IsEgg = true, Level = 05, Met_Level = 05, TID = 50318, OT_Gender = 0, OT_Name = "ポケパーク", Version = GameVersion.R, Moves = new(346), Method = PIDType.BACD_R }, // Plusle with Water Sport - new() { Species = 312, IsEgg = true, Level = 05, Met_Level = 05, TID = 50318, OT_Gender = 0, OT_Name = "ポケパーク", Version = GameVersion.R, Moves = new(300), Method = PIDType.BACD_R }, // Minun with Mud Sport - new() { Species = 325, IsEgg = true, Level = 05, Met_Level = 05, TID = 50318, OT_Gender = 0, OT_Name = "ポケパーク", Version = GameVersion.R, Moves = new(253), Method = PIDType.BACD_R }, // Spoink with Uproar - new() { Species = 327, IsEgg = true, Level = 05, Met_Level = 05, TID = 50318, OT_Gender = 0, OT_Name = "ポケパーク", Version = GameVersion.R, Moves = new(047), Method = PIDType.BACD_R }, // Spinda with Sing - new() { Species = 331, IsEgg = true, Level = 05, Met_Level = 05, TID = 50318, OT_Gender = 0, OT_Name = "ポケパーク", Version = GameVersion.R, Moves = new(227), Method = PIDType.BACD_R }, // Cacnea with Encore - new() { Species = 341, IsEgg = true, Level = 05, Met_Level = 05, TID = 50318, OT_Gender = 0, OT_Name = "ポケパーク", Version = GameVersion.R, Moves = new(346), Method = PIDType.BACD_R }, // Corphish with Water Sport - new() { Species = 360, IsEgg = true, Level = 05, Met_Level = 05, TID = 50318, OT_Gender = 0, OT_Name = "ポケパーク", Version = GameVersion.R, Moves = new(321), Method = PIDType.BACD_R }, // Wynaut with Tickle + new() { Species = 054, IsEgg = true, Level = 05, Met_Level = 05, TID16 = 50318, OT_Gender = 0, OT_Name = "ポケパーク", Version = GameVersion.R, Moves = new(300), Method = PIDType.BACD_R }, // Psyduck with Mud Sport + new() { Species = 172, IsEgg = true, Level = 05, Met_Level = 05, TID16 = 50318, OT_Gender = 0, OT_Name = "ポケパーク", Version = GameVersion.R, Moves = new(266), Method = PIDType.BACD_R }, // Pichu with Follow Me + new() { Species = 174, IsEgg = true, Level = 05, Met_Level = 05, TID16 = 50318, OT_Gender = 0, OT_Name = "ポケパーク", Version = GameVersion.R, Moves = new(321), Method = PIDType.BACD_R }, // Igglybuff with Tickle + new() { Species = 222, IsEgg = true, Level = 05, Met_Level = 05, TID16 = 50318, OT_Gender = 0, OT_Name = "ポケパーク", Version = GameVersion.R, Moves = new(300), Method = PIDType.BACD_R }, // Corsola with Mud Sport + new() { Species = 276, IsEgg = true, Level = 05, Met_Level = 05, TID16 = 50318, OT_Gender = 0, OT_Name = "ポケパーク", Version = GameVersion.R, Moves = new(297), Method = PIDType.BACD_R }, // Taillow with Feather Dance + new() { Species = 283, IsEgg = true, Level = 05, Met_Level = 05, TID16 = 50318, OT_Gender = 0, OT_Name = "ポケパーク", Version = GameVersion.R, Moves = new(300), Method = PIDType.BACD_R }, // Surskit with Mud Sport + new() { Species = 293, IsEgg = true, Level = 05, Met_Level = 05, TID16 = 50318, OT_Gender = 0, OT_Name = "ポケパーク", Version = GameVersion.R, Moves = new(298), Method = PIDType.BACD_R }, // Whismur with Teeter Dance + new() { Species = 300, IsEgg = true, Level = 05, Met_Level = 05, TID16 = 50318, OT_Gender = 0, OT_Name = "ポケパーク", Version = GameVersion.R, Moves = new(205), Method = PIDType.BACD_R }, // Skitty with Rollout + new() { Species = 311, IsEgg = true, Level = 05, Met_Level = 05, TID16 = 50318, OT_Gender = 0, OT_Name = "ポケパーク", Version = GameVersion.R, Moves = new(346), Method = PIDType.BACD_R }, // Plusle with Water Sport + new() { Species = 312, IsEgg = true, Level = 05, Met_Level = 05, TID16 = 50318, OT_Gender = 0, OT_Name = "ポケパーク", Version = GameVersion.R, Moves = new(300), Method = PIDType.BACD_R }, // Minun with Mud Sport + new() { Species = 325, IsEgg = true, Level = 05, Met_Level = 05, TID16 = 50318, OT_Gender = 0, OT_Name = "ポケパーク", Version = GameVersion.R, Moves = new(253), Method = PIDType.BACD_R }, // Spoink with Uproar + new() { Species = 327, IsEgg = true, Level = 05, Met_Level = 05, TID16 = 50318, OT_Gender = 0, OT_Name = "ポケパーク", Version = GameVersion.R, Moves = new(047), Method = PIDType.BACD_R }, // Spinda with Sing + new() { Species = 331, IsEgg = true, Level = 05, Met_Level = 05, TID16 = 50318, OT_Gender = 0, OT_Name = "ポケパーク", Version = GameVersion.R, Moves = new(227), Method = PIDType.BACD_R }, // Cacnea with Encore + new() { Species = 341, IsEgg = true, Level = 05, Met_Level = 05, TID16 = 50318, OT_Gender = 0, OT_Name = "ポケパーク", Version = GameVersion.R, Moves = new(346), Method = PIDType.BACD_R }, // Corphish with Water Sport + new() { Species = 360, IsEgg = true, Level = 05, Met_Level = 05, TID16 = 50318, OT_Gender = 0, OT_Name = "ポケパーク", Version = GameVersion.R, Moves = new(321), Method = PIDType.BACD_R }, // Wynaut with Tickle }; internal static readonly WC3[] Encounter_WC3 = ArrayUtil.ConcatAll(Encounter_Event3, Encounter_Event3_RS, Encounter_Event3_FRLG, Encounter_Event3_Common); diff --git a/PKHeX.Core/Legality/Encounters/Data/Gen45/Encounters4DPPt.cs b/PKHeX.Core/Legality/Encounters/Data/Gen45/Encounters4DPPt.cs index 36df4a354..6d45a04f7 100644 --- a/PKHeX.Core/Legality/Encounters/Data/Gen45/Encounters4DPPt.cs +++ b/PKHeX.Core/Legality/Encounters/Data/Gen45/Encounters4DPPt.cs @@ -79,7 +79,7 @@ internal static class Encounters4DPPt // Event //new(DP) { Species = 491, Level = 40, Location = 079, GroundTile = Grass }, // Darkrai @ Newmoon Island (Unreleased in Diamond and Pearl) new(Pt) { Species = 491, Level = 50, Location = 079, GroundTile = Grass }, // Darkrai @ Newmoon Island - new(Pt) { Species = 492, Form = 0, Level = 30, Location = 063, Fateful = true }, // Shaymin @ Flower Paradise + new(Pt) { Species = 492, Form = 0, Level = 30, Location = 063, FatefulEncounter = true }, // Shaymin @ Flower Paradise //new(DP) { Species = 492, Form = 0, Level = 30, Location = 063, Fateful = false }, // Shaymin @ Flower Paradise (Unreleased in Diamond and Pearl) //new(DPPt) { Species = 493, Form = 0, Level = 80, Location = 086, GroundTile = Cave }, // Arceus @ Hall of Origin (Unreleased) @@ -95,36 +95,36 @@ internal static class Encounters4DPPt private static readonly EncounterTrade4[] RanchGifts = { - new EncounterTrade4RanchGift(323975838, 025, 18) { Moves = new(447,085,148,104), TID = 1000, SID = 19840, OTGender = 1, MetLocation = 0068, Gender = 0, Ability = OnlyFirst, CurrentLevel = 20 }, // Pikachu - new EncounterTrade4RanchGift(323977664, 037, 16) { Moves = new(412,109,053,219), TID = 1000, SID = 21150, OTGender = 1, MetLocation = 3000, Gender = 0, Ability = OnlyFirst, CurrentLevel = 30 }, // Vulpix - new EncounterTrade4RanchGift(323975579, 077, 13) { Moves = new(036,033,039,052), TID = 1000, SID = 01123, OTGender = 1, MetLocation = 3000, Gender = 0, Ability = OnlySecond, CurrentLevel = 16 }, // Ponyta - new EncounterTrade4RanchGift(323975564, 108, 34) { Moves = new(076,111,014,205), TID = 1000, SID = 03050, OTGender = 1, MetLocation = 0077, Gender = 0, Ability = OnlyFirst, CurrentLevel = 40 }, // Lickitung - new EncounterTrade4RanchGift(323977579, 114, 01) { Moves = new(437,438,079,246), TID = 1000, SID = 49497, OTGender = 1, MetLocation = 3000, Gender = 1, Ability = OnlySecond }, // Tangela - new EncounterTrade4RanchGift(323977675, 133, 16) { Moves = new(363,270,098,247), TID = 1000, SID = 47710, OTGender = 1, MetLocation = 0068, Gender = 0, Ability = OnlySecond, CurrentLevel = 30 }, // Eevee - new EncounterTrade4RanchGift(323977588, 142, 20) { Moves = new(363,089,444,332), TID = 1000, SID = 43066, OTGender = 1, MetLocation = 0094, Gender = 0, Ability = OnlyFirst, CurrentLevel = 50 }, // Aerodactyl - new EncounterTrade4RanchGift(232975554, 193, 22) { Moves = new(318,095,246,138), TID = 1000, SID = 42301, OTGender = 1, MetLocation = 0052, Gender = 0, Ability = OnlyFirst, CurrentLevel = 45, Ball = 5 }, // Yanma - new EncounterTrade4RanchGift(323975570, 241, 16) { Moves = new(208,215,360,359), TID = 1000, SID = 02707, OTGender = 1, MetLocation = 3000, Gender = 1, Ability = OnlyFirst, CurrentLevel = 48 }, // Miltank - new EncounterTrade4RanchGift(323975563, 285, 22) { Moves = new(402,147,206,078), TID = 1000, SID = 02788, OTGender = 1, MetLocation = 3000, Gender = 0, Ability = OnlySecond, CurrentLevel = 45, Ball = 5 }, // Shroomish - new EncounterTrade4RanchGift(323975559, 320, 30) { Moves = new(156,323,133,058), TID = 1000, SID = 27046, OTGender = 1, MetLocation = 0038, Gender = 0, Ability = OnlySecond, CurrentLevel = 45 }, // Wailmer - new EncounterTrade4RanchGift(323977657, 360, 01) { Moves = new(204,150,227,000), TID = 1000, SID = 01788, OTGender = 1, MetLocation = 0004, Gender = 0, Ability = OnlySecond, EggLocation = 2000 }, // Wynaut - new EncounterTrade4RanchGift(323975563, 397, 02) { Moves = new(355,017,283,018), TID = 1000, SID = 59298, OTGender = 1, MetLocation = 0016, Gender = 0, Ability = OnlySecond, CurrentLevel = 23 }, // Staravia - new EncounterTrade4RanchGift(323970584, 415, 05) { Moves = new(230,016,000,000), TID = 1000, SID = 54140, OTGender = 1, MetLocation = 0020, Gender = 1, Ability = OnlyFirst, CurrentLevel = 20 }, // Combee - new EncounterTrade4RanchGift(323977539, 417, 09) { Moves = new(447,045,351,098), TID = 1000, SID = 18830, OTGender = 1, MetLocation = 0020, Gender = 1, Ability = OnlySecond, CurrentLevel = 10 }, // Pachirisu - new EncounterTrade4RanchGift(323974107, 422, 20) { Moves = new(363,352,426,104), TID = 1000, SID = 39272, OTGender = 1, MetLocation = 0028, Gender = 0, Ability = OnlySecond, CurrentLevel = 25, Form = 1 }, // Shellos - new EncounterTrade4RanchGift(323977566, 427, 10) { Moves = new(204,193,409,098), TID = 1000, SID = 31045, OTGender = 1, MetLocation = 3000, Gender = 1, Ability = OnlyFirst, CurrentLevel = 16 }, // Buneary - new EncounterTrade4RanchGift(323975579, 453, 22) { Moves = new(310,207,426,389), TID = 1000, SID = 41342, OTGender = 1, MetLocation = 0052, Gender = 0, Ability = OnlySecond, CurrentLevel = 31, Ball = 5 }, // Croagunk - new EncounterTrade4RanchGift(323977566, 456, 15) { Moves = new(213,352,219,392), TID = 1000, SID = 48348, OTGender = 1, MetLocation = 0020, Gender = 1, Ability = OnlyFirst, CurrentLevel = 35 }, // Finneon - new EncounterTrade4RanchGift(323975582, 459, 32) { Moves = new(452,420,275,059), TID = 1000, SID = 23360, OTGender = 1, MetLocation = 0031, Gender = 0, Ability = OnlyFirst, CurrentLevel = 41 }, // Snover - new EncounterTrade4RanchSpecial(151, 50) { Moves = new(235,216,095,100), TID = 1000, SID = 59228, OTGender = 1, Ball = 0x10, Gender = 2 }, // Mew - new EncounterTrade4RanchSpecial(489, 01) { Moves = new(447,240,156,057), TID = 1000, SID = 09248, OTGender = 1, Ball = 0x10, Gender = 2, CurrentLevel = 50, EggLocation = 3000 }, // Phione + new EncounterTrade4RanchGift(323975838, 025, 18) { Moves = new(447,085,148,104), TID16 = 1000, SID16 = 19840, OTGender = 1, MetLocation = 0068, Gender = 0, Ability = OnlyFirst, CurrentLevel = 20 }, // Pikachu + new EncounterTrade4RanchGift(323977664, 037, 16) { Moves = new(412,109,053,219), TID16 = 1000, SID16 = 21150, OTGender = 1, MetLocation = 3000, Gender = 0, Ability = OnlyFirst, CurrentLevel = 30 }, // Vulpix + new EncounterTrade4RanchGift(323975579, 077, 13) { Moves = new(036,033,039,052), TID16 = 1000, SID16 = 01123, OTGender = 1, MetLocation = 3000, Gender = 0, Ability = OnlySecond, CurrentLevel = 16 }, // Ponyta + new EncounterTrade4RanchGift(323975564, 108, 34) { Moves = new(076,111,014,205), TID16 = 1000, SID16 = 03050, OTGender = 1, MetLocation = 0077, Gender = 0, Ability = OnlyFirst, CurrentLevel = 40 }, // Lickitung + new EncounterTrade4RanchGift(323977579, 114, 01) { Moves = new(437,438,079,246), TID16 = 1000, SID16 = 49497, OTGender = 1, MetLocation = 3000, Gender = 1, Ability = OnlySecond }, // Tangela + new EncounterTrade4RanchGift(323977675, 133, 16) { Moves = new(363,270,098,247), TID16 = 1000, SID16 = 47710, OTGender = 1, MetLocation = 0068, Gender = 0, Ability = OnlySecond, CurrentLevel = 30 }, // Eevee + new EncounterTrade4RanchGift(323977588, 142, 20) { Moves = new(363,089,444,332), TID16 = 1000, SID16 = 43066, OTGender = 1, MetLocation = 0094, Gender = 0, Ability = OnlyFirst, CurrentLevel = 50 }, // Aerodactyl + new EncounterTrade4RanchGift(232975554, 193, 22) { Moves = new(318,095,246,138), TID16 = 1000, SID16 = 42301, OTGender = 1, MetLocation = 0052, Gender = 0, Ability = OnlyFirst, CurrentLevel = 45, Ball = 5 }, // Yanma + new EncounterTrade4RanchGift(323975570, 241, 16) { Moves = new(208,215,360,359), TID16 = 1000, SID16 = 02707, OTGender = 1, MetLocation = 3000, Gender = 1, Ability = OnlyFirst, CurrentLevel = 48 }, // Miltank + new EncounterTrade4RanchGift(323975563, 285, 22) { Moves = new(402,147,206,078), TID16 = 1000, SID16 = 02788, OTGender = 1, MetLocation = 3000, Gender = 0, Ability = OnlySecond, CurrentLevel = 45, Ball = 5 }, // Shroomish + new EncounterTrade4RanchGift(323975559, 320, 30) { Moves = new(156,323,133,058), TID16 = 1000, SID16 = 27046, OTGender = 1, MetLocation = 0038, Gender = 0, Ability = OnlySecond, CurrentLevel = 45 }, // Wailmer + new EncounterTrade4RanchGift(323977657, 360, 01) { Moves = new(204,150,227,000), TID16 = 1000, SID16 = 01788, OTGender = 1, MetLocation = 0004, Gender = 0, Ability = OnlySecond, EggLocation = 2000 }, // Wynaut + new EncounterTrade4RanchGift(323975563, 397, 02) { Moves = new(355,017,283,018), TID16 = 1000, SID16 = 59298, OTGender = 1, MetLocation = 0016, Gender = 0, Ability = OnlySecond, CurrentLevel = 23 }, // Staravia + new EncounterTrade4RanchGift(323970584, 415, 05) { Moves = new(230,016,000,000), TID16 = 1000, SID16 = 54140, OTGender = 1, MetLocation = 0020, Gender = 1, Ability = OnlyFirst, CurrentLevel = 20 }, // Combee + new EncounterTrade4RanchGift(323977539, 417, 09) { Moves = new(447,045,351,098), TID16 = 1000, SID16 = 18830, OTGender = 1, MetLocation = 0020, Gender = 1, Ability = OnlySecond, CurrentLevel = 10 }, // Pachirisu + new EncounterTrade4RanchGift(323974107, 422, 20) { Moves = new(363,352,426,104), TID16 = 1000, SID16 = 39272, OTGender = 1, MetLocation = 0028, Gender = 0, Ability = OnlySecond, CurrentLevel = 25, Form = 1 }, // Shellos + new EncounterTrade4RanchGift(323977566, 427, 10) { Moves = new(204,193,409,098), TID16 = 1000, SID16 = 31045, OTGender = 1, MetLocation = 3000, Gender = 1, Ability = OnlyFirst, CurrentLevel = 16 }, // Buneary + new EncounterTrade4RanchGift(323975579, 453, 22) { Moves = new(310,207,426,389), TID16 = 1000, SID16 = 41342, OTGender = 1, MetLocation = 0052, Gender = 0, Ability = OnlySecond, CurrentLevel = 31, Ball = 5 }, // Croagunk + new EncounterTrade4RanchGift(323977566, 456, 15) { Moves = new(213,352,219,392), TID16 = 1000, SID16 = 48348, OTGender = 1, MetLocation = 0020, Gender = 1, Ability = OnlyFirst, CurrentLevel = 35 }, // Finneon + new EncounterTrade4RanchGift(323975582, 459, 32) { Moves = new(452,420,275,059), TID16 = 1000, SID16 = 23360, OTGender = 1, MetLocation = 0031, Gender = 0, Ability = OnlyFirst, CurrentLevel = 41 }, // Snover + new EncounterTrade4RanchSpecial(151, 50) { Moves = new(235,216,095,100), TID16 = 1000, SID16 = 59228, OTGender = 1, Ball = 0x10, Gender = 2 }, // Mew + new EncounterTrade4RanchSpecial(489, 01) { Moves = new(447,240,156,057), TID16 = 1000, SID16 = 09248, OTGender = 1, Ball = 0x10, Gender = 2, CurrentLevel = 50, EggLocation = 3000 }, // Phione }; private static readonly EncounterTrade4PID[] TradeGift_DPPtIngame = { - new(DPPt, 0x0000008E, 063, 01) { Ability = OnlyFirst, TID = 25643, SID = 00000, OTGender = 1, Gender = 0, IVs = new(15,15,15,20,25,25) }, // Machop -> Abra - new(DPPt, 0x00000867, 441, 01) { Ability = OnlySecond, TID = 44142, SID = 00000, OTGender = 0, Gender = 1, IVs = new(15,20,15,25,25,15), Contest = 20 }, // Buizel -> Chatot - new(DPPt, 0x00000088, 093, 35) { Ability = OnlyFirst, TID = 19248, SID = 00000, OTGender = 1, Gender = 0, IVs = new(20,25,15,25,15,15) }, // Medicham (35 from Route 217) -> Haunter - new(DPPt, 0x0000045C, 129, 01) { Ability = OnlyFirst, TID = 53277, SID = 00000, OTGender = 0, Gender = 1, IVs = new(15,25,15,20,25,15) }, // Finneon -> Magikarp + new(DPPt, 0x0000008E, 063, 01) { Ability = OnlyFirst, TID16 = 25643, SID16 = 00000, OTGender = 1, Gender = 0, IVs = new(15,15,15,20,25,25) }, // Machop -> Abra + new(DPPt, 0x00000867, 441, 01) { Ability = OnlySecond, TID16 = 44142, SID16 = 00000, OTGender = 0, Gender = 1, IVs = new(15,20,15,25,25,15), Contest = 20 }, // Buizel -> Chatot + new(DPPt, 0x00000088, 093, 35) { Ability = OnlyFirst, TID16 = 19248, SID16 = 00000, OTGender = 1, Gender = 0, IVs = new(20,25,15,25,15,15) }, // Medicham (35 from Route 217) -> Haunter + new(DPPt, 0x0000045C, 129, 01) { Ability = OnlyFirst, TID16 = 53277, SID16 = 00000, OTGender = 0, Gender = 1, IVs = new(15,25,15,20,25,15) }, // Finneon -> Magikarp }; internal static readonly EncounterTrade4[] TradeGift_DPPt = ArrayUtil.ConcatAll(TradeGift_DPPtIngame, RanchGifts); diff --git a/PKHeX.Core/Legality/Encounters/Data/Gen45/Encounters4HGSS.cs b/PKHeX.Core/Legality/Encounters/Data/Gen45/Encounters4HGSS.cs index dfdeada54..36266fa96 100644 --- a/PKHeX.Core/Legality/Encounters/Data/Gen45/Encounters4HGSS.cs +++ b/PKHeX.Core/Legality/Encounters/Data/Gen45/Encounters4HGSS.cs @@ -119,20 +119,20 @@ internal static class Encounters4HGSS #region Trade Tables internal static readonly EncounterTrade4PID[] TradeGift_HGSS = { - new(HGSS, 0x000025EF, 095, 01) { Ability = OnlySecond, TID = 48926, SID = 00000, OTGender = 0, Gender = 0, IVs = new(25,20,25,15,15,15) }, // Bellsprout -> Onix - new(HGSS, 0x00002310, 066, 01) { Ability = OnlyFirst, TID = 37460, SID = 00000, OTGender = 0, Gender = 1, IVs = new(15,25,20,20,15,15) }, // Drowzee -> Machop - new(HGSS, 0x000001DB, 100, 01) { Ability = OnlySecond, TID = 29189, SID = 00000, OTGender = 0, Gender = 2, IVs = new(15,20,15,25,25,15) }, // Krabby -> Voltorb - new(HGSS, 0x0001FC0A, 085, 15) { Ability = OnlyFirst, TID = 00283, SID = 00000, OTGender = 1, Gender = 1, IVs = new(20,20,20,15,15,15) }, // Dragonair (15 from DPPt) -> Dodrio - new(HGSS, 0x0000D136, 082, 19) { Ability = OnlyFirst, TID = 50082, SID = 00000, OTGender = 0, Gender = 2, IVs = new(15,20,15,20,20,20) }, // Dugtrio (19 from Diglett's Cave) -> Magneton - new(HGSS, 0x000034E4, 178, 16) { Ability = OnlyFirst, TID = 15616, SID = 00000, OTGender = 0, Gender = 0, IVs = new(15,20,15,20,20,20) }, // Haunter (16 from Old Chateau) -> Xatu - new(HGSS, 0x00485876, 025, 02) { Ability = OnlyFirst, TID = 33038, SID = 00000, OTGender = 0, Gender = 1, IVs = new(20,25,18,31,25,13) }, // Pikachu - new(HGSS, 0x0012B6D4, 374, 31) { Ability = OnlyFirst, TID = 23478, SID = 00000, OTGender = 0, Gender = 2, IVs = new(28,29,24,23,24,25) }, // Forretress -> Beldum - new(HGSS, 0x0012971C, 111, 01) { Ability = OnlyFirst, TID = 06845, SID = 00000, OTGender = 0, Gender = 1, IVs = new(22,31,13,00,22,09), Moves = new(422) }, // Bonsly -> Rhyhorn - new(HGSS, 0x00101596, 208, 01) { Ability = OnlyFirst, TID = 26491, SID = 00000, OTGender = 1, Gender = 0, IVs = new(08,30,28,06,18,20) }, // Any -> Steelix + new(HGSS, 0x000025EF, 095, 01) { Ability = OnlySecond, TID16 = 48926, SID16 = 00000, OTGender = 0, Gender = 0, IVs = new(25,20,25,15,15,15) }, // Bellsprout -> Onix + new(HGSS, 0x00002310, 066, 01) { Ability = OnlyFirst, TID16 = 37460, SID16 = 00000, OTGender = 0, Gender = 1, IVs = new(15,25,20,20,15,15) }, // Drowzee -> Machop + new(HGSS, 0x000001DB, 100, 01) { Ability = OnlySecond, TID16 = 29189, SID16 = 00000, OTGender = 0, Gender = 2, IVs = new(15,20,15,25,25,15) }, // Krabby -> Voltorb + new(HGSS, 0x0001FC0A, 085, 15) { Ability = OnlyFirst, TID16 = 00283, SID16 = 00000, OTGender = 1, Gender = 1, IVs = new(20,20,20,15,15,15) }, // Dragonair (15 from DPPt) -> Dodrio + new(HGSS, 0x0000D136, 082, 19) { Ability = OnlyFirst, TID16 = 50082, SID16 = 00000, OTGender = 0, Gender = 2, IVs = new(15,20,15,20,20,20) }, // Dugtrio (19 from Diglett's Cave) -> Magneton + new(HGSS, 0x000034E4, 178, 16) { Ability = OnlyFirst, TID16 = 15616, SID16 = 00000, OTGender = 0, Gender = 0, IVs = new(15,20,15,20,20,20) }, // Haunter (16 from Old Chateau) -> Xatu + new(HGSS, 0x00485876, 025, 02) { Ability = OnlyFirst, TID16 = 33038, SID16 = 00000, OTGender = 0, Gender = 1, IVs = new(20,25,18,31,25,13) }, // Pikachu + new(HGSS, 0x0012B6D4, 374, 31) { Ability = OnlyFirst, TID16 = 23478, SID16 = 00000, OTGender = 0, Gender = 2, IVs = new(28,29,24,23,24,25) }, // Forretress -> Beldum + new(HGSS, 0x0012971C, 111, 01) { Ability = OnlyFirst, TID16 = 06845, SID16 = 00000, OTGender = 0, Gender = 1, IVs = new(22,31,13,00,22,09), Moves = new(422) }, // Bonsly -> Rhyhorn + new(HGSS, 0x00101596, 208, 01) { Ability = OnlyFirst, TID16 = 26491, SID16 = 00000, OTGender = 1, Gender = 0, IVs = new(08,30,28,06,18,20) }, // Any -> Steelix //Gift - new(HGSS, 0x00006B5E, 021, 20) { Ability = OnlyFirst, TID = 01001, SID = 00000, OTGender = 0, Gender = 1, IVs = new(15,20,15,20,20,20), MetLocation = 183, Moves = new(043,031,228,332) },// Webster's Spearow - new(HGSS, 0x000214D7, 213, 20) { Ability = OnlySecond, TID = 04336, SID = 00001, OTGender = 0, Gender = 0, IVs = new(15,20,15,20,20,20), MetLocation = 130, Moves = new(132,117,227,219) },// Kirk's Shuckle + new(HGSS, 0x00006B5E, 021, 20) { Ability = OnlyFirst, TID16 = 01001, SID16 = 00000, OTGender = 0, Gender = 1, IVs = new(15,20,15,20,20,20), MetLocation = 183, Moves = new(043,031,228,332) },// Webster's Spearow + new(HGSS, 0x000214D7, 213, 20) { Ability = OnlySecond, TID16 = 04336, SID16 = 00001, OTGender = 0, Gender = 0, IVs = new(15,20,15,20,20,20), MetLocation = 130, Moves = new(132,117,227,219) },// Kirk's Shuckle }; private const string tradeHGSS = "tradehgss"; diff --git a/PKHeX.Core/Legality/Encounters/Data/Gen45/Encounters5B2W2.cs b/PKHeX.Core/Legality/Encounters/Data/Gen45/Encounters5B2W2.cs index 352e8884b..d92ea26d2 100644 --- a/PKHeX.Core/Legality/Encounters/Data/Gen45/Encounters5B2W2.cs +++ b/PKHeX.Core/Legality/Encounters/Data/Gen45/Encounters5B2W2.cs @@ -16,7 +16,7 @@ public static class Encounters5B2W2 static Encounters5B2W2() => MarkEncounterTradeStrings(TradeGift_B2W2_Regular, TradeB2W2); #region DreamWorld Encounter - public static readonly EncounterStatic5[] DreamWorld_B2W2 = DreamWorldEntry.GetArray(B2W2, new DreamWorldEntry[] + public static readonly EncounterStatic5[] DreamWorld_B2W2 = DreamWorldEntry.GetArray(B2W2, stackalloc DreamWorldEntry[] { // Pleasant Forest new(535, 10, 496, 414, 352), // Tympole @@ -173,13 +173,13 @@ public static class Encounters5B2W2 #region Trade Tables internal static readonly EncounterTrade5[] TradeGift_B2W2_Regular = { - new(B2 ) { Species = 548, Level = 20, Ability = OnlySecond, TID = 65217, SID = 00000, OTGender = 1, Gender = 1, IVs = new(20,20,20,20,31,20), Nature = Nature.Timid }, // Petilil - new( W2) { Species = 546, Level = 20, Ability = OnlyFirst, TID = 05720, SID = 00001, OTGender = 0, Gender = 0, IVs = new(20,20,20,20,31,20), Nature = Nature.Modest }, // Cottonee - new(B2W2) { Species = 526, Level = 35, Ability = OnlyFirst, TID = 11195, SID = 00000, OTGender = 0, Gender = 0, IVs = new(20,31,20,20,20,20), Nature = Nature.Adamant, IsNicknamed = false }, // Gigalith - new(B2W2) { Species = 465, Level = 45, Ability = OnlyFirst, TID = 27658, SID = 00001, OTGender = 0, Gender = 0, IVs = new(31,20,20,20,20,20), Nature = Nature.Hardy }, // Tangrowth - new(B2W2) { Species = 479, Level = 60, Ability = OnlyFirst, TID = 54673, SID = 00000, OTGender = 1, Gender = 2, IVs = new(20,20,20,20,20,31), Nature = Nature.Calm }, // Rotom - new(B2W2) { Species = 424, Level = 40, Ability = OnlySecond, TID = 17074, SID = 00001, OTGender = 1, Gender = 0, IVs = new(20,20,20,31,20,20), Nature = Nature.Jolly }, // Ambipom - new(B2W2) { Species = 065, Level = 40, Ability = OnlyFirst, TID = 17074, SID = 00001, OTGender = 1, Gender = 0, IVs = new(20,20,20,31,20,20), Nature = Nature.Timid }, // Alakazam + new(B2 ) { Species = 548, Level = 20, Ability = OnlySecond, TID16 = 65217, SID16 = 00000, OTGender = 1, Gender = 1, IVs = new(20,20,20,20,31,20), Nature = Nature.Timid }, // Petilil + new( W2) { Species = 546, Level = 20, Ability = OnlyFirst, TID16 = 05720, SID16 = 00001, OTGender = 0, Gender = 0, IVs = new(20,20,20,20,31,20), Nature = Nature.Modest }, // Cottonee + new(B2W2) { Species = 526, Level = 35, Ability = OnlyFirst, TID16 = 11195, SID16 = 00000, OTGender = 0, Gender = 0, IVs = new(20,31,20,20,20,20), Nature = Nature.Adamant, IsNicknamed = false }, // Gigalith + new(B2W2) { Species = 465, Level = 45, Ability = OnlyFirst, TID16 = 27658, SID16 = 00001, OTGender = 0, Gender = 0, IVs = new(31,20,20,20,20,20), Nature = Nature.Hardy }, // Tangrowth + new(B2W2) { Species = 479, Level = 60, Ability = OnlyFirst, TID16 = 54673, SID16 = 00000, OTGender = 1, Gender = 2, IVs = new(20,20,20,20,20,31), Nature = Nature.Calm }, // Rotom + new(B2W2) { Species = 424, Level = 40, Ability = OnlySecond, TID16 = 17074, SID16 = 00001, OTGender = 1, Gender = 0, IVs = new(20,20,20,31,20,20), Nature = Nature.Jolly }, // Ambipom + new(B2W2) { Species = 065, Level = 40, Ability = OnlyFirst, TID16 = 17074, SID16 = 00001, OTGender = 1, Gender = 0, IVs = new(20,20,20,31,20,20), Nature = Nature.Timid }, // Alakazam }; internal const int YancyTID = 10303; @@ -190,32 +190,32 @@ public static class Encounters5B2W2 private static readonly EncounterTrade5[] TradeGift_B2W2_YancyCurtis = { // Player is Male - new(B2W2) { Species = 052, Level = 50, Ability = OnlyHidden, TID = 10303, SID = 00000, OTGender = 1, TrainerNames = TradeOT_B2W2_F }, // Meowth - new(B2W2) { Species = 202, Level = 50, Ability = OnlyHidden, TID = 10303, SID = 00000, OTGender = 1, TrainerNames = TradeOT_B2W2_F }, // Wobbuffet - new(B2W2) { Species = 280, Level = 50, Ability = OnlyHidden, TID = 10303, SID = 00000, OTGender = 1, TrainerNames = TradeOT_B2W2_F }, // Ralts - new(B2W2) { Species = 410, Level = 50, Ability = OnlyHidden, TID = 10303, SID = 00000, OTGender = 1, TrainerNames = TradeOT_B2W2_F }, // Shieldon - new(B2W2) { Species = 111, Level = 50, Ability = OnlyHidden, TID = 10303, SID = 00000, OTGender = 1, TrainerNames = TradeOT_B2W2_F }, // Rhyhorn - new(B2W2) { Species = 422, Level = 50, Ability = OnlyHidden, TID = 10303, SID = 00000, OTGender = 1, TrainerNames = TradeOT_B2W2_F, Form = 0 }, // Shellos-West - new(B2W2) { Species = 303, Level = 50, Ability = OnlyHidden, TID = 10303, SID = 00000, OTGender = 1, TrainerNames = TradeOT_B2W2_F }, // Mawile - new(B2W2) { Species = 442, Level = 50, Ability = OnlyHidden, TID = 10303, SID = 00000, OTGender = 1, TrainerNames = TradeOT_B2W2_F }, // Spiritomb - new(B2W2) { Species = 143, Level = 50, Ability = OnlyHidden, TID = 10303, SID = 00000, OTGender = 1, TrainerNames = TradeOT_B2W2_F }, // Snorlax - new(B2W2) { Species = 216, Level = 50, Ability = OnlyHidden, TID = 10303, SID = 00000, OTGender = 1, TrainerNames = TradeOT_B2W2_F }, // Teddiursa - new(B2W2) { Species = 327, Level = 50, Ability = OnlyHidden, TID = 10303, SID = 00000, OTGender = 1, TrainerNames = TradeOT_B2W2_F }, // Spinda - new(B2W2) { Species = 175, Level = 50, Ability = OnlyHidden, TID = 10303, SID = 00000, OTGender = 1, TrainerNames = TradeOT_B2W2_F }, // Togepi + new(B2W2) { Species = 052, Level = 50, Ability = OnlyHidden, TID16 = 10303, SID16 = 00000, OTGender = 1, TrainerNames = TradeOT_B2W2_F }, // Meowth + new(B2W2) { Species = 202, Level = 50, Ability = OnlyHidden, TID16 = 10303, SID16 = 00000, OTGender = 1, TrainerNames = TradeOT_B2W2_F }, // Wobbuffet + new(B2W2) { Species = 280, Level = 50, Ability = OnlyHidden, TID16 = 10303, SID16 = 00000, OTGender = 1, TrainerNames = TradeOT_B2W2_F }, // Ralts + new(B2W2) { Species = 410, Level = 50, Ability = OnlyHidden, TID16 = 10303, SID16 = 00000, OTGender = 1, TrainerNames = TradeOT_B2W2_F }, // Shieldon + new(B2W2) { Species = 111, Level = 50, Ability = OnlyHidden, TID16 = 10303, SID16 = 00000, OTGender = 1, TrainerNames = TradeOT_B2W2_F }, // Rhyhorn + new(B2W2) { Species = 422, Level = 50, Ability = OnlyHidden, TID16 = 10303, SID16 = 00000, OTGender = 1, TrainerNames = TradeOT_B2W2_F, Form = 0 }, // Shellos-West + new(B2W2) { Species = 303, Level = 50, Ability = OnlyHidden, TID16 = 10303, SID16 = 00000, OTGender = 1, TrainerNames = TradeOT_B2W2_F }, // Mawile + new(B2W2) { Species = 442, Level = 50, Ability = OnlyHidden, TID16 = 10303, SID16 = 00000, OTGender = 1, TrainerNames = TradeOT_B2W2_F }, // Spiritomb + new(B2W2) { Species = 143, Level = 50, Ability = OnlyHidden, TID16 = 10303, SID16 = 00000, OTGender = 1, TrainerNames = TradeOT_B2W2_F }, // Snorlax + new(B2W2) { Species = 216, Level = 50, Ability = OnlyHidden, TID16 = 10303, SID16 = 00000, OTGender = 1, TrainerNames = TradeOT_B2W2_F }, // Teddiursa + new(B2W2) { Species = 327, Level = 50, Ability = OnlyHidden, TID16 = 10303, SID16 = 00000, OTGender = 1, TrainerNames = TradeOT_B2W2_F }, // Spinda + new(B2W2) { Species = 175, Level = 50, Ability = OnlyHidden, TID16 = 10303, SID16 = 00000, OTGender = 1, TrainerNames = TradeOT_B2W2_F }, // Togepi // Player is Female - new(B2W2) { Species = 056, Level = 50, Ability = OnlyHidden, TID = 54118, SID = 00000, OTGender = 0, TrainerNames = TradeOT_B2W2_M }, // Mankey - new(B2W2) { Species = 202, Level = 50, Ability = OnlyHidden, TID = 54118, SID = 00000, OTGender = 0, TrainerNames = TradeOT_B2W2_M }, // Wobbuffet - new(B2W2) { Species = 280, Level = 50, Ability = OnlyHidden, TID = 54118, SID = 00000, OTGender = 0, TrainerNames = TradeOT_B2W2_M }, // Ralts - new(B2W2) { Species = 408, Level = 50, Ability = OnlyHidden, TID = 54118, SID = 00000, OTGender = 0, TrainerNames = TradeOT_B2W2_M }, // Cranidos - new(B2W2) { Species = 111, Level = 50, Ability = OnlyHidden, TID = 54118, SID = 00000, OTGender = 0, TrainerNames = TradeOT_B2W2_M }, // Rhyhorn - new(B2W2) { Species = 422, Level = 50, Ability = OnlyHidden, TID = 54118, SID = 00000, OTGender = 0, TrainerNames = TradeOT_B2W2_M, Form = 1 }, // Shellos-East - new(B2W2) { Species = 302, Level = 50, Ability = OnlyHidden, TID = 54118, SID = 00000, OTGender = 0, TrainerNames = TradeOT_B2W2_M }, // Sableye - new(B2W2) { Species = 442, Level = 50, Ability = OnlyHidden, TID = 54118, SID = 00000, OTGender = 0, TrainerNames = TradeOT_B2W2_M }, // Spiritomb - new(B2W2) { Species = 143, Level = 50, Ability = OnlyHidden, TID = 54118, SID = 00000, OTGender = 0, TrainerNames = TradeOT_B2W2_M }, // Snorlax - new(B2W2) { Species = 231, Level = 50, Ability = OnlyHidden, TID = 54118, SID = 00000, OTGender = 0, TrainerNames = TradeOT_B2W2_M }, // Phanpy - new(B2W2) { Species = 327, Level = 50, Ability = OnlyHidden, TID = 54118, SID = 00000, OTGender = 0, TrainerNames = TradeOT_B2W2_M }, // Spinda - new(B2W2) { Species = 175, Level = 50, Ability = OnlyHidden, TID = 54118, SID = 00000, OTGender = 0, TrainerNames = TradeOT_B2W2_M }, // Togepi + new(B2W2) { Species = 056, Level = 50, Ability = OnlyHidden, TID16 = 54118, SID16 = 00000, OTGender = 0, TrainerNames = TradeOT_B2W2_M }, // Mankey + new(B2W2) { Species = 202, Level = 50, Ability = OnlyHidden, TID16 = 54118, SID16 = 00000, OTGender = 0, TrainerNames = TradeOT_B2W2_M }, // Wobbuffet + new(B2W2) { Species = 280, Level = 50, Ability = OnlyHidden, TID16 = 54118, SID16 = 00000, OTGender = 0, TrainerNames = TradeOT_B2W2_M }, // Ralts + new(B2W2) { Species = 408, Level = 50, Ability = OnlyHidden, TID16 = 54118, SID16 = 00000, OTGender = 0, TrainerNames = TradeOT_B2W2_M }, // Cranidos + new(B2W2) { Species = 111, Level = 50, Ability = OnlyHidden, TID16 = 54118, SID16 = 00000, OTGender = 0, TrainerNames = TradeOT_B2W2_M }, // Rhyhorn + new(B2W2) { Species = 422, Level = 50, Ability = OnlyHidden, TID16 = 54118, SID16 = 00000, OTGender = 0, TrainerNames = TradeOT_B2W2_M, Form = 1 }, // Shellos-East + new(B2W2) { Species = 302, Level = 50, Ability = OnlyHidden, TID16 = 54118, SID16 = 00000, OTGender = 0, TrainerNames = TradeOT_B2W2_M }, // Sableye + new(B2W2) { Species = 442, Level = 50, Ability = OnlyHidden, TID16 = 54118, SID16 = 00000, OTGender = 0, TrainerNames = TradeOT_B2W2_M }, // Spiritomb + new(B2W2) { Species = 143, Level = 50, Ability = OnlyHidden, TID16 = 54118, SID16 = 00000, OTGender = 0, TrainerNames = TradeOT_B2W2_M }, // Snorlax + new(B2W2) { Species = 231, Level = 50, Ability = OnlyHidden, TID16 = 54118, SID16 = 00000, OTGender = 0, TrainerNames = TradeOT_B2W2_M }, // Phanpy + new(B2W2) { Species = 327, Level = 50, Ability = OnlyHidden, TID16 = 54118, SID16 = 00000, OTGender = 0, TrainerNames = TradeOT_B2W2_M }, // Spinda + new(B2W2) { Species = 175, Level = 50, Ability = OnlyHidden, TID16 = 54118, SID16 = 00000, OTGender = 0, TrainerNames = TradeOT_B2W2_M }, // Togepi }; private const string tradeB2W2 = "tradeb2w2"; diff --git a/PKHeX.Core/Legality/Encounters/Data/Gen45/Encounters5BW.cs b/PKHeX.Core/Legality/Encounters/Data/Gen45/Encounters5BW.cs index d0bc13281..ec1edcf97 100644 --- a/PKHeX.Core/Legality/Encounters/Data/Gen45/Encounters5BW.cs +++ b/PKHeX.Core/Legality/Encounters/Data/Gen45/Encounters5BW.cs @@ -15,12 +15,9 @@ public static class Encounters5BW static Encounters5BW() => MarkEncounterTradeStrings(TradeGift_BW, TradeBW); - #region Dream Radar Tables - - #endregion #region DreamWorld Encounter - public static readonly EncounterStatic5[] DreamWorld_BW = DreamWorldEntry.GetArray(BW, new DreamWorldEntry[] + public static readonly EncounterStatic5[] DreamWorld_BW = DreamWorldEntry.GetArray(BW, stackalloc DreamWorldEntry[] { // Pleasant Forest new(029, 10, 010, 389, 162), // Nidoran♀ @@ -181,13 +178,13 @@ public static class Encounters5BW #region Trade Tables internal static readonly EncounterTrade5PID[] TradeGift_BW = { - new(B , 0x64000000) { Species = 548, Level = 15, Ability = OnlyFirst, TID = 39922, SID = 00000, OTGender = 1, Gender = 1, IVs = new(20,20,20,20,31,20), Nature = Nature.Modest }, // Petilil - new( W, 0x6400007E) { Species = 546, Level = 15, Ability = OnlyFirst, TID = 39922, SID = 00000, OTGender = 1, Gender = 1, IVs = new(20,20,20,20,31,20), Nature = Nature.Modest }, // Cottonee - new(B , 0x9400007F) { Species = 550, Level = 25, Ability = OnlyFirst, TID = 27646, SID = 00000, OTGender = 0, Gender = 0, IVs = new(20,31,20,20,20,20), Nature = Nature.Adamant, Form = 0 }, // Basculin-Red - new( W, 0x9400007F) { Species = 550, Level = 25, Ability = OnlyFirst, TID = 27646, SID = 00000, OTGender = 0, Gender = 0, IVs = new(20,31,20,20,20,20), Nature = Nature.Adamant, Form = 1 }, // Basculin-Blue - new(BW, 0xD400007F) { Species = 587, Level = 30, Ability = OnlyFirst, TID = 11195, SID = 00000, OTGender = 0, Gender = 0, IVs = new(20,20,31,20,20,20), Nature = Nature.Lax }, // Emolga - new(BW, 0x2A000000) { Species = 479, Level = 60, Ability = OnlyFirst, TID = 54673, SID = 00000, OTGender = 1, Gender = 2, IVs = new(20,20,20,20,20,31), Nature = Nature.Gentle }, // Rotom - new(BW, 0x6200001F) { Species = 446, Level = 60, Ability = OnlySecond, TID = 40217, SID = 00000, OTGender = 0, Gender = 0, IVs = new(31,20,20,20,20,20), Nature = Nature.Serious }, // Munchlax + new(B , 0x64000000) { Species = 548, Level = 15, Ability = OnlyFirst, TID16 = 39922, SID16 = 00000, OTGender = 1, Gender = 1, IVs = new(20,20,20,20,31,20), Nature = Nature.Modest }, // Petilil + new( W, 0x6400007E) { Species = 546, Level = 15, Ability = OnlyFirst, TID16 = 39922, SID16 = 00000, OTGender = 1, Gender = 1, IVs = new(20,20,20,20,31,20), Nature = Nature.Modest }, // Cottonee + new(B , 0x9400007F) { Species = 550, Level = 25, Ability = OnlyFirst, TID16 = 27646, SID16 = 00000, OTGender = 0, Gender = 0, IVs = new(20,31,20,20,20,20), Nature = Nature.Adamant, Form = 0 }, // Basculin-Red + new( W, 0x9400007F) { Species = 550, Level = 25, Ability = OnlyFirst, TID16 = 27646, SID16 = 00000, OTGender = 0, Gender = 0, IVs = new(20,31,20,20,20,20), Nature = Nature.Adamant, Form = 1 }, // Basculin-Blue + new(BW, 0xD400007F) { Species = 587, Level = 30, Ability = OnlyFirst, TID16 = 11195, SID16 = 00000, OTGender = 0, Gender = 0, IVs = new(20,20,31,20,20,20), Nature = Nature.Lax }, // Emolga + new(BW, 0x2A000000) { Species = 479, Level = 60, Ability = OnlyFirst, TID16 = 54673, SID16 = 00000, OTGender = 1, Gender = 2, IVs = new(20,20,20,20,20,31), Nature = Nature.Gentle }, // Rotom + new(BW, 0x6200001F) { Species = 446, Level = 60, Ability = OnlySecond, TID16 = 40217, SID16 = 00000, OTGender = 0, Gender = 0, IVs = new(31,20,20,20,20,20), Nature = Nature.Serious }, // Munchlax }; private const string tradeBW = "tradebw"; diff --git a/PKHeX.Core/Legality/Encounters/Data/Gen45/Encounters5DR.cs b/PKHeX.Core/Legality/Encounters/Data/Gen45/Encounters5DR.cs index 55242b3e3..3ac6382a1 100644 --- a/PKHeX.Core/Legality/Encounters/Data/Gen45/Encounters5DR.cs +++ b/PKHeX.Core/Legality/Encounters/Data/Gen45/Encounters5DR.cs @@ -43,7 +43,7 @@ public static class Encounters5DR #endregion #region DreamWorld Encounter - public static readonly EncounterStatic5[] DreamWorld_Common = DreamWorldEntry.GetArray(Gen5, new DreamWorldEntry[] + public static readonly EncounterStatic5[] DreamWorld_Common = DreamWorldEntry.GetArray(Gen5, stackalloc DreamWorldEntry[] { // Pleasant Forest new(019, 10, 098, 382, 231), // Rattata diff --git a/PKHeX.Core/Legality/Encounters/Data/Gen67/Encounters6AO.cs b/PKHeX.Core/Legality/Encounters/Data/Gen67/Encounters6AO.cs index 5ece2c629..9b75c92bf 100644 --- a/PKHeX.Core/Legality/Encounters/Data/Gen67/Encounters6AO.cs +++ b/PKHeX.Core/Legality/Encounters/Data/Gen67/Encounters6AO.cs @@ -91,7 +91,7 @@ internal static class Encounters6AO new( AS) { Species = 382, Level = 45, Location = 296, Shiny = Shiny.Never, FlawlessIVCount = 3 }, // Kyogre new(OR ) { Species = 383, Level = 45, Location = 296, Shiny = Shiny.Never, FlawlessIVCount = 3 }, // Groudon new(ORAS) { Species = 384, Level = 70, Location = 316, Shiny = Shiny.Never, FlawlessIVCount = 3 }, // Rayquaza - new(ORAS) { Species = 386, Level = 80, Location = 316, Shiny = Shiny.Never, FlawlessIVCount = 3, Fateful = true }, // Deoxys + new(ORAS) { Species = 386, Level = 80, Location = 316, Shiny = Shiny.Never, FlawlessIVCount = 3, FatefulEncounter = true }, // Deoxys // Hoopa Rings new( AS) { Species = 249, Level = 50, Location = 304, FlawlessIVCount = 3 }, // Lugia @@ -118,8 +118,8 @@ internal static class Encounters6AO new(ORAS) { Species = 646, Level = 50, Location = 342, FlawlessIVCount = 3 }, // Kyurem // Devon Scope Kecleon - //new EncounterStatic { Species = 352, Level = 30, Location = 240 }, // Kecleon @ Route 119 -- dexnav encounter slot collision; prefer EncounterSlot - //new EncounterStatic { Species = 352, Level = 30, Location = 242 }, // Kecleon @ Route 120 -- dexnav encounter slot collision; prefer EncounterSlot + //new(ORAS) { Species = 352, Level = 30, Location = 240 }, // Kecleon @ Route 119 -- dexnav encounter slot collision; prefer EncounterSlot + //new(ORAS) { Species = 352, Level = 30, Location = 242 }, // Kecleon @ Route 120 -- dexnav encounter slot collision; prefer EncounterSlot new(ORAS) { Species = 352, Level = 40, Location = 176, Gender = 1 }, // Kecleon @ Lavaridge new(ORAS) { Species = 352, Level = 45, Location = 196, Ability = OnlyHidden }, // Kecleon @ Mossdeep City @@ -156,9 +156,9 @@ internal static class Encounters6AO #region Trade Tables internal static readonly EncounterTrade6[] TradeGift_AO = { - new(ORAS, 01,3,05,040) { Species = 296, Level = 09, Ability = OnlySecond, TID = 30724, IVs = new(-1,31,-1,-1,-1,-1), Gender = 0, Nature = Nature.Brave }, // Makuhita - new(ORAS, 34,3,13,176) { Species = 300, Level = 30, Ability = OnlyFirst, TID = 03239, IVs = new(-1,-1,-1,31,-1,-1), Gender = 1, Nature = Nature.Naughty }, // Skitty - new(ORAS, 07,4,10,319) { Species = 222, Level = 50, Ability = OnlyHidden, TID = 00325, IVs = new(31,-1,-1,-1,-1,31), Gender = 1, Nature = Nature.Calm }, // Corsola + new(ORAS, 01,3,05,040) { Species = 296, Level = 09, Ability = OnlySecond, TID16 = 30724, IVs = new(-1,31,-1,-1,-1,-1), Gender = 0, Nature = Nature.Brave }, // Makuhita + new(ORAS, 34,3,13,176) { Species = 300, Level = 30, Ability = OnlyFirst, TID16 = 03239, IVs = new(-1,-1,-1,31,-1,-1), Gender = 1, Nature = Nature.Naughty }, // Skitty + new(ORAS, 07,4,10,319) { Species = 222, Level = 50, Ability = OnlyHidden, TID16 = 00325, IVs = new(31,-1,-1,-1,-1,31), Gender = 1, Nature = Nature.Calm }, // Corsola }; #endregion diff --git a/PKHeX.Core/Legality/Encounters/Data/Gen67/Encounters6XY.cs b/PKHeX.Core/Legality/Encounters/Data/Gen67/Encounters6XY.cs index f02d1a693..424130c63 100644 --- a/PKHeX.Core/Legality/Encounters/Data/Gen67/Encounters6XY.cs +++ b/PKHeX.Core/Legality/Encounters/Data/Gen67/Encounters6XY.cs @@ -83,17 +83,17 @@ internal static class Encounters6XY #region Trade Tables internal static readonly EncounterTrade6[] TradeGift_XY = { - new(XY, 01,3,23,049) { Species = 129, Level = 05, Ability = OnlyFirst, TID = 44285, IVs = new(-1,31,-1,-1,31,-1), Gender = 0, Nature = Nature.Adamant }, // Magikarp - new(XY, 10,3,00,000) { Species = 133, Level = 05, Ability = OnlyFirst, TID = 29294, Gender = 1, Nature = Nature.Docile }, // Eevee + new(XY, 01,3,23,049) { Species = 129, Level = 05, Ability = OnlyFirst, TID16 = 44285, IVs = new(-1,31,-1,-1,31,-1), Gender = 0, Nature = Nature.Adamant }, // Magikarp + new(XY, 10,3,00,000) { Species = 133, Level = 05, Ability = OnlyFirst, TID16 = 29294, Gender = 1, Nature = Nature.Docile }, // Eevee - new(XY, 15,4,13,017) { Species = 083, Level = 10, Ability = OnlyFirst, TID = 00185, IVs = new(-1,-1,-1,31,-1,-1), Gender = 0, Nature = Nature.Jolly }, // Farfetch'd - new(XY, 17,5,08,025) { Species = 208, Level = 20, Ability = OnlyFirst, TID = 19250, IVs = new(-1,-1,31,-1,-1,-1), Gender = 1, Nature = Nature.Impish }, // Steelix - new(XY, 18,7,20,709) { Species = 625, Level = 50, Ability = OnlyFirst, TID = 03447, IVs = new(-1,31,-1,-1,-1,-1), Gender = 0, Nature = Nature.Adamant }, // Bisharp + new(XY, 15,4,13,017) { Species = 083, Level = 10, Ability = OnlyFirst, TID16 = 00185, IVs = new(-1,-1,-1,31,-1,-1), Gender = 0, Nature = Nature.Jolly }, // Farfetch'd + new(XY, 17,5,08,025) { Species = 208, Level = 20, Ability = OnlyFirst, TID16 = 19250, IVs = new(-1,-1,31,-1,-1,-1), Gender = 1, Nature = Nature.Impish }, // Steelix + new(XY, 18,7,20,709) { Species = 625, Level = 50, Ability = OnlyFirst, TID16 = 03447, IVs = new(-1,31,-1,-1,-1,-1), Gender = 0, Nature = Nature.Adamant }, // Bisharp - new(XY, 02,3,11,005) { Species = 656, Level = 05, Ability = OnlyFirst, TID = 00037, IVs = new(20,20,20,31,20,20), Gender = 0, Nature = Nature.Jolly }, // Froakie - new(XY, 02,3,09,005) { Species = 650, Level = 05, Ability = OnlyFirst, TID = 00037, IVs = new(20,31,20,20,20,20), Gender = 0, Nature = Nature.Adamant }, // Chespin - new(XY, 02,3,18,005) { Species = 653, Level = 05, Ability = OnlyFirst, TID = 00037, IVs = new(20,20,20,20,31,20), Gender = 0, Nature = Nature.Modest }, // Fennekin - new(XY, 51,4,04,033) { Species = 280, Level = 05, Ability = OnlyFirst, TID = 37110, IVs = new(20,20,20,31,31,20), Gender = 1, Nature = Nature.Modest, IsNicknamed = false }, // Ralts + new(XY, 02,3,11,005) { Species = 656, Level = 05, Ability = OnlyFirst, TID16 = 00037, IVs = new(20,20,20,31,20,20), Gender = 0, Nature = Nature.Jolly }, // Froakie + new(XY, 02,3,09,005) { Species = 650, Level = 05, Ability = OnlyFirst, TID16 = 00037, IVs = new(20,31,20,20,20,20), Gender = 0, Nature = Nature.Adamant }, // Chespin + new(XY, 02,3,18,005) { Species = 653, Level = 05, Ability = OnlyFirst, TID16 = 00037, IVs = new(20,20,20,20,31,20), Gender = 0, Nature = Nature.Modest }, // Fennekin + new(XY, 51,4,04,033) { Species = 280, Level = 05, Ability = OnlyFirst, TID16 = 37110, IVs = new(20,20,20,31,31,20), Gender = 1, Nature = Nature.Modest, IsNicknamed = false }, // Ralts }; #endregion diff --git a/PKHeX.Core/Legality/Encounters/Data/Gen67/Encounters7SM.cs b/PKHeX.Core/Legality/Encounters/Data/Gen67/Encounters7SM.cs index ce7e4f436..31b38ae7d 100644 --- a/PKHeX.Core/Legality/Encounters/Data/Gen67/Encounters7SM.cs +++ b/PKHeX.Core/Legality/Encounters/Data/Gen67/Encounters7SM.cs @@ -51,7 +51,7 @@ internal static class Encounters7SM new(SM) // Magearna (Bottle Cap) 00 FF { Gift = true, Species = 801, Level = 50, Location = 40001, Shiny = Shiny.Never, FlawlessIVCount = 3, HeldItem = 795, Ability = OnlySecond, - Fateful = true, Relearn = new(705, 430, 381, 270), Ball = 0x10, // Cherish + FatefulEncounter = true, Relearn = new(705, 430, 381, 270), Ball = 0x10, // Cherish }, // Static Encounters - 1.bin @@ -120,13 +120,13 @@ internal static class Encounters7SM internal static readonly EncounterTrade7[] TradeGift_SM = // @ a\1\5\5 { // Trades - 4.bin - new(SM) { Species = 066, Form = 0, Level = 09, Ability = OnlySecond, TID = 00410, SID = 00000, IVs = new(-1,31,-1,-1,-1,-1), OTGender = 1, Gender = 0, Nature = Nature.Brave }, // Machop - new(SM) { Species = 761, Form = 0, Level = 16, Ability = OnlyFirst, TID = 20683, SID = 00009, IVs = new(-1,31,-1,-1,-1,-1), OTGender = 0, Gender = 1, Nature = Nature.Adamant }, // Bounsweet - new(SM) { Species = 061, Form = 0, Level = 22, Ability = OnlySecond, TID = 01092, SID = 00009, IVs = new(31,-1,-1,-1,-1,-1), OTGender = 1, Gender = 1, Nature = Nature.Naughty }, // Poliwhirl - new(SM) { Species = 440, Form = 0, Level = 27, Ability = OnlySecond, TID = 10913, SID = 00000, IVs = new(-1,-1,-1,-1,31,-1), OTGender = 1, Gender = 1, Nature = Nature.Calm }, // Happiny - new(SM) { Species = 075, Form = 1, Level = 32, Ability = OnlyFirst, TID = 20778, SID = 00009, IVs = new(-1,-1,31,-1,-1,-1), OTGender = 0, Gender = 0, Nature = Nature.Impish, EvolveOnTrade = true }, // Graveler-1 - new(SM) { Species = 762, Form = 0, Level = 43, Ability = OnlyFirst, TID = 20679, SID = 00009, IVs = new(-1,-1,-1,-1,-1,31), OTGender = 1, Gender = 1, Nature = Nature.Careful }, // Steenee - new(SM) { Species = 663, Form = 0, Level = 59, Ability = OnlyHidden, TID = 56734, SID = 00008, IVs = new(-1,-1,-1,31,-1,-1), OTGender = 0, Gender = 0, Nature = Nature.Jolly }, // Talonflame + new(SM) { Species = 066, Form = 0, Level = 09, Ability = OnlySecond, TID16 = 00410, SID16 = 00000, IVs = new(-1,31,-1,-1,-1,-1), OTGender = 1, Gender = 0, Nature = Nature.Brave }, // Machop + new(SM) { Species = 761, Form = 0, Level = 16, Ability = OnlyFirst, TID16 = 20683, SID16 = 00009, IVs = new(-1,31,-1,-1,-1,-1), OTGender = 0, Gender = 1, Nature = Nature.Adamant }, // Bounsweet + new(SM) { Species = 061, Form = 0, Level = 22, Ability = OnlySecond, TID16 = 01092, SID16 = 00009, IVs = new(31,-1,-1,-1,-1,-1), OTGender = 1, Gender = 1, Nature = Nature.Naughty }, // Poliwhirl + new(SM) { Species = 440, Form = 0, Level = 27, Ability = OnlySecond, TID16 = 10913, SID16 = 00000, IVs = new(-1,-1,-1,-1,31,-1), OTGender = 1, Gender = 1, Nature = Nature.Calm }, // Happiny + new(SM) { Species = 075, Form = 1, Level = 32, Ability = OnlyFirst, TID16 = 20778, SID16 = 00009, IVs = new(-1,-1,31,-1,-1,-1), OTGender = 0, Gender = 0, Nature = Nature.Impish, EvolveOnTrade = true }, // Graveler-1 + new(SM) { Species = 762, Form = 0, Level = 43, Ability = OnlyFirst, TID16 = 20679, SID16 = 00009, IVs = new(-1,-1,-1,-1,-1,31), OTGender = 1, Gender = 1, Nature = Nature.Careful }, // Steenee + new(SM) { Species = 663, Form = 0, Level = 59, Ability = OnlyHidden, TID16 = 56734, SID16 = 00008, IVs = new(-1,-1,-1,31,-1,-1), OTGender = 0, Gender = 0, Nature = Nature.Jolly }, // Talonflame }; private const string tradeSM = "tradesm"; diff --git a/PKHeX.Core/Legality/Encounters/Data/Gen67/Encounters7USUM.cs b/PKHeX.Core/Legality/Encounters/Data/Gen67/Encounters7USUM.cs index 5d1d92f5d..c34f59366 100644 --- a/PKHeX.Core/Legality/Encounters/Data/Gen67/Encounters7USUM.cs +++ b/PKHeX.Core/Legality/Encounters/Data/Gen67/Encounters7USUM.cs @@ -59,7 +59,7 @@ internal static class Encounters7USUM new(USUM) // Magearna (Bottle Cap) { Gift = true, Species = 801, Level = 50, Location = 40001, Shiny = Shiny.Never, FlawlessIVCount = 3, HeldItem = 795, Ability = OnlySecond, - Fateful = true, Relearn = new(705, 430, 381, 270), Ball = 0x10, // Cherish + FatefulEncounter = true, Relearn = new(705, 430, 381, 270), Ball = 0x10, // Cherish }, new(USUM) { Gift = true, Species = 718, Form = 0, Level = 50, Shiny = Shiny.Never, Location = 118, FlawlessIVCount = 3 }, // Zygarde (50%) @@ -76,7 +76,7 @@ internal static class Encounters7USUM new(USUM) { Species = 007, Level = 12, Location = 042, Relearn = new(453,110,055,033) }, // Squirtle @ Seaward Cave new(USUM) { Species = 095, Level = 14, Location = 034, Relearn = new(563,099,317,088) }, // Onix @ Ten Carat Hill new(USUM) { Species = 116, Level = 18, Location = 014, Relearn = new(352,239,055,043) }, // Horsea @ Kala'e Bay - new(USUM) { Species = 664, Level = 09, Location = 020, Relearn = new(476,081,078,033), Form = EncounterStatic.FormVivillon }, // Scatterbug @ Hau'oli City + new(USUM) { Species = 664, Level = 09, Location = 020, Relearn = new(476,081,078,033), Form = EncounterStatic7.FormVivillon }, // Scatterbug @ Hau'oli City new(USUM) { Species = 001, Level = 10, Location = 012, Relearn = new(580,022,045,033) }, // Bulbasaur @ Route 2 new(USUM) { Species = 607, Level = 09, Location = 038, Relearn = new(203,052,083,123) }, // Litwick @ Hau'oli Cemetery @@ -219,13 +219,13 @@ internal static class Encounters7USUM internal static readonly EncounterTrade7[] TradeGift_USUM = { // Trades - 4.bin - new(USUM) { Species = 701, Form = 0, Level = 08, Ability = OnlySecond, TID = 00410, SID = 00000, IVs = new(-1,31,-1,-1,-1,-1), OTGender = 1, Gender = 0, Nature = Nature.Brave }, // Hawlucha - new(USUM) { Species = 714, Form = 0, Level = 19, Ability = OnlyFirst, TID = 20683, SID = 00009, IVs = new(-1,-1,-1,-1,31,-1), OTGender = 0, Gender = 0, Nature = Nature.Modest }, // Noibat - new(USUM) { Species = 339, Form = 0, Level = 21, Ability = OnlySecond, TID = 01092, SID = 00009, IVs = new(31,-1,-1,-1,-1,-1), OTGender = 0, Gender = 1, Nature = Nature.Naughty }, // Barboach - new(USUM) { Species = 024, Form = 0, Level = 22, Ability = OnlyFirst, TID = 10913, SID = 00000, IVs = new(-1,-1,31,-1,-1,-1), OTGender = 1, Gender = 1, Nature = Nature.Impish }, // Arbok - new(USUM) { Species = 708, Form = 0, Level = 33, Ability = OnlyFirst, TID = 20778, SID = 00009, IVs = new(-1,-1,-1,-1,-1,31), OTGender = 0, Gender = 0, Nature = Nature.Calm, EvolveOnTrade = true }, // Phantump - new(USUM) { Species = 422, Form = 0, Level = 44, Ability = OnlySecond, TID = 20679, SID = 00009, IVs = new(-1,-1,31,-1,-1,-1), OTGender = 1, Gender = 1, Nature = Nature.Quiet }, // Shellos - new(USUM) { Species = 128, Form = 0, Level = 59, Ability = OnlyFirst, TID = 56734, SID = 00008, IVs = new(-1,-1,-1,31,-1,-1), OTGender = 0, Gender = 0, Nature = Nature.Jolly }, // Tauros + new(USUM) { Species = 701, Form = 0, Level = 08, Ability = OnlySecond, TID16 = 00410, SID16 = 00000, IVs = new(-1,31,-1,-1,-1,-1), OTGender = 1, Gender = 0, Nature = Nature.Brave }, // Hawlucha + new(USUM) { Species = 714, Form = 0, Level = 19, Ability = OnlyFirst, TID16 = 20683, SID16 = 00009, IVs = new(-1,-1,-1,-1,31,-1), OTGender = 0, Gender = 0, Nature = Nature.Modest }, // Noibat + new(USUM) { Species = 339, Form = 0, Level = 21, Ability = OnlySecond, TID16 = 01092, SID16 = 00009, IVs = new(31,-1,-1,-1,-1,-1), OTGender = 0, Gender = 1, Nature = Nature.Naughty }, // Barboach + new(USUM) { Species = 024, Form = 0, Level = 22, Ability = OnlyFirst, TID16 = 10913, SID16 = 00000, IVs = new(-1,-1,31,-1,-1,-1), OTGender = 1, Gender = 1, Nature = Nature.Impish }, // Arbok + new(USUM) { Species = 708, Form = 0, Level = 33, Ability = OnlyFirst, TID16 = 20778, SID16 = 00009, IVs = new(-1,-1,-1,-1,-1,31), OTGender = 0, Gender = 0, Nature = Nature.Calm, EvolveOnTrade = true }, // Phantump + new(USUM) { Species = 422, Form = 0, Level = 44, Ability = OnlySecond, TID16 = 20679, SID16 = 00009, IVs = new(-1,-1,31,-1,-1,-1), OTGender = 1, Gender = 1, Nature = Nature.Quiet }, // Shellos + new(USUM) { Species = 128, Form = 0, Level = 59, Ability = OnlyFirst, TID16 = 56734, SID16 = 00008, IVs = new(-1,-1,-1,31,-1,-1), OTGender = 0, Gender = 0, Nature = Nature.Jolly }, // Tauros }; private const string tradeUSUM = "tradeusum"; diff --git a/PKHeX.Core/Legality/Encounters/Data/Gen8/Encounters8.cs b/PKHeX.Core/Legality/Encounters/Data/Gen8/Encounters8.cs index 6d41c702d..3a793992a 100644 --- a/PKHeX.Core/Legality/Encounters/Data/Gen8/Encounters8.cs +++ b/PKHeX.Core/Legality/Encounters/Data/Gen8/Encounters8.cs @@ -580,7 +580,7 @@ internal static class Encounters8 new() { Species = 638, Level = 70, Location = 226, FlawlessIVCount = 3, Ability = OnlyFirst, Weather = No_Sun_Sand }, // Cobalion at the Frigid Sea new() { Species = 639, Level = 70, Location = 232, FlawlessIVCount = 3, Ability = OnlyFirst, Weather = Overcast }, // Terrakion in Lakeside Cavern new() { Species = 640, Level = 70, Location = 210, FlawlessIVCount = 3, Ability = OnlyFirst, Weather = All_CT }, // Virizion at Giant's Bed - new() { Species = 647, Level = 65, Location = 230, Moves = new(548,533,014,056), FlawlessIVCount = 3, Shiny = Never, Ability = OnlyFirst, Form = 01, Fateful = true, Weather = All_Ballimere }, // Keldeo-1 at Ballimere Lake + new() { Species = 647, Level = 65, Location = 230, Moves = new(548,533,014,056), FlawlessIVCount = 3, Shiny = Never, Ability = OnlyFirst, Form = 01, FatefulEncounter = true, Weather = All_Ballimere }, // Keldeo-1 at Ballimere Lake //new() { Species = 896, Level = 75, Location = -1, Moves = new(556,037,419,023}, FlawlessIVCount = 3, Shiny = Never, Ability = OnlyFirst }, // Glastrier //new() { Species = 897, Level = 75, Location = -1, Moves = new(247,037,506,024}, FlawlessIVCount = 3, Shiny = Never, Ability = OnlyFirst }, // Spectrier new() { Species = 898, Level = 80, Location = 220, Moves = new(202,094,473,505), FlawlessIVCount = 3, Shiny = Never, Ability = OnlyFirst, ScriptedNoMarks = true }, // Calyrex diff --git a/PKHeX.Core/Legality/Encounters/Data/Gen8/Encounters8a.cs b/PKHeX.Core/Legality/Encounters/Data/Gen8/Encounters8a.cs index 075fd0e90..f38a8a0f3 100644 --- a/PKHeX.Core/Legality/Encounters/Data/Gen8/Encounters8a.cs +++ b/PKHeX.Core/Legality/Encounters/Data/Gen8/Encounters8a.cs @@ -22,7 +22,7 @@ internal static class Encounters8a new(037,001,40,M,M) { Location = 088, Gift = true, Method = Fixed, Ball = (int)Ball.LAPoke }, // Vulpix-1 new(483,000,65,M,M) { Location = 109, FlawlessIVCount = 3, Gift = true, Method = Fixed, Ball = (int)Ball.LAOrigin }, // Dialga new(484,000,65,M,M) { Location = 109, FlawlessIVCount = 3, Gift = true, Method = Fixed, Ball = (int)Ball.LAOrigin }, // Palkia - new(493,000,75,M,M) { Location = 109, FlawlessIVCount = 3, Gift = true, Method = Fixed, Ball = (int)Ball.LAPoke, Fateful = true }, // Arceus + new(493,000,75,M,M) { Location = 109, FlawlessIVCount = 3, Gift = true, Method = Fixed, Ball = (int)Ball.LAPoke, FatefulEncounter = true }, // Arceus // Static Encounters - Scripted Table Slots new(480,000,70,M,M) { Location = 111, FlawlessIVCount = 3, Moves = new(129,326,832,095) }, // Uxie @@ -42,13 +42,13 @@ internal static class Encounters8a new(570,001,28 ) { Location = 027 }, // Zorua new(570,001,29 ) { Location = 027 }, // Zorua - new(489,000,33 ) { Location = 064, Fateful = true, Moves = new(145,352,151,428) }, // Phione - new(489,000,34 ) { Location = 064, Fateful = true, Moves = new(145,352,151,428) }, // Phione - new(489,000,35 ) { Location = 064, Fateful = true, Moves = new(145,352,151,428) }, // Phione - new(489,000,36 ) { Location = 064, Fateful = true, Moves = new(145,352,151,428) }, // Phione - new(490,000,50,M,M) { Location = 064, FlawlessIVCount = 3, Fateful = true, Moves = new(352,428,585,145) }, // Manaphy - new(491,000,70,M,M) { Location = 010, FlawlessIVCount = 3, Fateful = true, Moves = new(506,399,094,464) }, // Darkrai - new(492,000,70,M,M) { Location = 026, FlawlessIVCount = 3, Fateful = true, Moves = new(403,412,414,465) }, // Shaymin + new(489,000,33 ) { Location = 064, FatefulEncounter = true, Moves = new(145,352,151,428) }, // Phione + new(489,000,34 ) { Location = 064, FatefulEncounter = true, Moves = new(145,352,151,428) }, // Phione + new(489,000,35 ) { Location = 064, FatefulEncounter = true, Moves = new(145,352,151,428) }, // Phione + new(489,000,36 ) { Location = 064, FatefulEncounter = true, Moves = new(145,352,151,428) }, // Phione + new(490,000,50,M,M) { Location = 064, FlawlessIVCount = 3, FatefulEncounter = true, Moves = new(352,428,585,145) }, // Manaphy + new(491,000,70,M,M) { Location = 010, FlawlessIVCount = 3, FatefulEncounter = true, Moves = new(506,399,094,464) }, // Darkrai + new(492,000,70,M,M) { Location = 026, FlawlessIVCount = 3, FatefulEncounter = true, Moves = new(403,412,414,465) }, // Shaymin // Unown Notes new(201,000,25,U) { Location = 040, Method = Fixed }, // Unown A @@ -91,7 +91,7 @@ internal static class Encounters8a new(642,000,70,M,M) { Location = 059, FlawlessIVCount = 3, Moves = new(326,242,087,847) }, // Thundurus (Lunker’s Lair) new(642,000,70,M,M) { Location = 129, FlawlessIVCount = 3, Moves = new(326,242,087,847) }, // Thundurus (Sand’s Reach) new(488,000,70,M,M) { Location = 010, FlawlessIVCount = 3, Moves = new(427,094,585,849) }, // Cresselia (Coronet Highlands) - new(491,000,70,M,M) { Location = 074, FlawlessIVCount = 3, Fateful = true, Moves = new(506,399,094,464) }, // Darkrai (Lonely Spring) + new(491,000,70,M,M) { Location = 074, FlawlessIVCount = 3, FatefulEncounter = true, Moves = new(506,399,094,464) }, // Darkrai (Lonely Spring) // Static Encounters new(046,000,50,M,M) { Location = 019, Method = Fixed }, // paras01: Paras diff --git a/PKHeX.Core/Legality/Encounters/Data/Gen8/Encounters8b.cs b/PKHeX.Core/Legality/Encounters/Data/Gen8/Encounters8b.cs index 5eb2480fd..af3b67641 100644 --- a/PKHeX.Core/Legality/Encounters/Data/Gen8/Encounters8b.cs +++ b/PKHeX.Core/Legality/Encounters/Data/Gen8/Encounters8b.cs @@ -37,8 +37,8 @@ internal static class Encounters8b new(BDSP) { Gift = true, Species = 410, Level = 01, Location = 049, FlawlessIVCount = 3 }, // Shieldon // Game-specific gifts - new(BDSP) { Gift = true, Species = 151, Level = 01, Ability = OnlySecond, Location = 438, Shiny = Never, FlawlessIVCount = 3, Fateful = true }, // Mew - new(BDSP) { Gift = true, Species = 385, Level = 05, Ability = OnlySecond, Location = 438, Shiny = Never, FlawlessIVCount = 3, Fateful = true }, // Jirachi + new(BDSP) { Gift = true, Species = 151, Level = 01, Ability = OnlySecond, Location = 438, Shiny = Never, FlawlessIVCount = 3, FatefulEncounter = true }, // Mew + new(BDSP) { Gift = true, Species = 385, Level = 05, Ability = OnlySecond, Location = 438, Shiny = Never, FlawlessIVCount = 3, FatefulEncounter = true }, // Jirachi // Stationary new(BDSP) { Species = 425, Level = 22, Location = 197 }, // Drifloon @@ -59,10 +59,10 @@ internal static class Encounters8b new(BDSP) { Species = 487, Level = 70, Location = 266, FlawlessIVCount = 3 }, // Giratina // Mythical - new(BDSP) { Species = 491, Level = 50, Location = 333, FlawlessIVCount = 3, Fateful = true }, // Darkrai - new(BDSP) { Species = 492, Level = 30, Location = 285, FlawlessIVCount = 3, Fateful = true }, // Shaymin - new(BD ) { Species = 493, Level = 80, Location = 218, FlawlessIVCount = 3, Fateful = true }, // Arceus (Brilliant Diamond) - new( SP) { Species = 493, Level = 80, Location = 618, FlawlessIVCount = 3, Fateful = true }, // Arceus (Shining Pearl) + new(BDSP) { Species = 491, Level = 50, Location = 333, FlawlessIVCount = 3, FatefulEncounter = true }, // Darkrai + new(BDSP) { Species = 492, Level = 30, Location = 285, FlawlessIVCount = 3, FatefulEncounter = true }, // Shaymin + new(BD ) { Species = 493, Level = 80, Location = 218, FlawlessIVCount = 3, FatefulEncounter = true }, // Arceus (Brilliant Diamond) + new( SP) { Species = 493, Level = 80, Location = 618, FlawlessIVCount = 3, FatefulEncounter = true }, // Arceus (Shining Pearl) // Ramanas Park (Pure Space) new( SP) { Species = 144, Level = 70, Location = 506, FlawlessIVCount = 3, Ability = OnlyHidden }, // Articuno @@ -94,9 +94,9 @@ internal static class Encounters8b internal static readonly EncounterTrade8b[] TradeGift_BDSP = { - new(BDSP) { Species = 063, EncryptionConstant = 0x0000008E, PID = 0xFF50A8F5, Level = 09, Ability = OnlyFirst, Gender = 0, OTGender = 0, TID = 25643, IVs = new(28,10,09,31,11,03), Moves = new(100,000,000,000), HeightScalar = 029, WeightScalar = 202, Nature = Nature.Quiet }, // Abra - new(BDSP) { Species = 441, EncryptionConstant = 0x00000867, PID = 0x17DAAB19, Level = 15, Ability = OnlySecond, Gender = 1, OTGender = 0, TID = 44142, IVs = new(17,08,29,25,17,23), Moves = new(448,047,064,045), HeightScalar = 088, WeightScalar = 091, Nature = Nature.Lonely }, // Chatot - new(BDSP) { Species = 093, EncryptionConstant = 0x00000088, PID = 0xF60AB5BB, Level = 33, Ability = OnlyFirst, Gender = 0, OTGender = 0, TID = 19248, IVs = new(18,24,28,02,22,30), Moves = new(247,371,389,109), HeightScalar = 096, WeightScalar = 208, Nature = Nature.Hasty }, // Haunter - new(BDSP) { Species = 129, EncryptionConstant = 0x0000045C, PID = 0xFCE82F88, Level = 45, Ability = OnlyFirst, Gender = 1, OTGender = 0, TID = 53277, IVs = new(03,03,31,02,11,03), Moves = new(150,000,000,000), HeightScalar = 169, WeightScalar = 068, Nature = Nature.Mild }, // Magikarp + new(BDSP) { Species = 063, EncryptionConstant = 0x0000008E, PID = 0xFF50A8F5, Level = 09, Ability = OnlyFirst, Gender = 0, OTGender = 0, TID16 = 25643, IVs = new(28,10,09,31,11,03), Moves = new(100,000,000,000), HeightScalar = 029, WeightScalar = 202, Nature = Nature.Quiet }, // Abra + new(BDSP) { Species = 441, EncryptionConstant = 0x00000867, PID = 0x17DAAB19, Level = 15, Ability = OnlySecond, Gender = 1, OTGender = 0, TID16 = 44142, IVs = new(17,08,29,25,17,23), Moves = new(448,047,064,045), HeightScalar = 088, WeightScalar = 091, Nature = Nature.Lonely }, // Chatot + new(BDSP) { Species = 093, EncryptionConstant = 0x00000088, PID = 0xF60AB5BB, Level = 33, Ability = OnlyFirst, Gender = 0, OTGender = 0, TID16 = 19248, IVs = new(18,24,28,02,22,30), Moves = new(247,371,389,109), HeightScalar = 096, WeightScalar = 208, Nature = Nature.Hasty }, // Haunter + new(BDSP) { Species = 129, EncryptionConstant = 0x0000045C, PID = 0xFCE82F88, Level = 45, Ability = OnlyFirst, Gender = 1, OTGender = 0, TID16 = 53277, IVs = new(03,03,31,02,11,03), Moves = new(150,000,000,000), HeightScalar = 169, WeightScalar = 068, Nature = Nature.Mild }, // Magikarp }; } diff --git a/PKHeX.Core/Legality/Encounters/Data/Live/EncounterServerDate.cs b/PKHeX.Core/Legality/Encounters/Data/Live/EncounterServerDate.cs index a45c16694..87a6d31ba 100644 --- a/PKHeX.Core/Legality/Encounters/Data/Live/EncounterServerDate.cs +++ b/PKHeX.Core/Legality/Encounters/Data/Live/EncounterServerDate.cs @@ -9,10 +9,11 @@ namespace PKHeX.Core; /// public static class EncounterServerDate { - private static bool IsValidDate(DateTime obtained, DateTime start) => obtained >= start && obtained <= DateTime.UtcNow; - private static bool IsValidDate(DateTime obtained, DateTime start, DateTime end) => obtained >= start && obtained <= end; + private static bool IsValidDate(DateOnly obtained, DateOnly start) => obtained >= start && obtained <= DateOnly.FromDateTime(DateTime.UtcNow); - private static bool IsValidDate(DateTime obtained, (DateTime Start, DateTime? End) value) + private static bool IsValidDate(DateOnly obtained, DateOnly start, DateOnly end) => obtained >= start && obtained <= end; + + private static bool IsValidDate(DateOnly obtained, (DateOnly Start, DateOnly? End) value) { var (start, end) = value; if (end is not { } x) @@ -22,46 +23,48 @@ public static class EncounterServerDate private static EncounterServerDateCheck Result(bool result) => result ? Valid : Invalid; - public static EncounterServerDateCheck IsValidDate(this IEncounterServerDate enc, DateTime obtained) => enc switch + public static EncounterServerDateCheck IsValidDate(this IEncounterServerDate enc, DateOnly obtained) => enc switch { WC8 wc8 => Result(IsValidDateWC8(wc8.CardID, obtained)), WA8 wa8 => Result(IsValidDateWA8(wa8.CardID, obtained)), WB8 wb8 => Result(IsValidDateWB8(wb8.CardID, obtained)), + //WC9 wc9 => Result(IsValidDateWC9(wc9.CardID, obtained)), _ => throw new ArgumentOutOfRangeException(nameof(enc)), }; - public static bool IsValidDateWC8(int cardID, DateTime obtained) => WC8Gifts.TryGetValue(cardID, out var time) && IsValidDate(obtained, time); - public static bool IsValidDateWA8(int cardID, DateTime obtained) => WA8Gifts.TryGetValue(cardID, out var time) && IsValidDate(obtained, time); - public static bool IsValidDateWB8(int cardID, DateTime obtained) => WB8Gifts.TryGetValue(cardID, out var time) && IsValidDate(obtained, time); + public static bool IsValidDateWC8(int cardID, DateOnly obtained) => WC8Gifts.TryGetValue(cardID, out var time) && IsValidDate(obtained, time); + public static bool IsValidDateWA8(int cardID, DateOnly obtained) => WA8Gifts.TryGetValue(cardID, out var time) && IsValidDate(obtained, time); + public static bool IsValidDateWB8(int cardID, DateOnly obtained) => WB8Gifts.TryGetValue(cardID, out var time) && IsValidDate(obtained, time); + public static bool IsValidDateWC9(int cardID, DateOnly obtained) => WC9Gifts.TryGetValue(cardID, out var time) && IsValidDate(obtained, time); /// /// Minimum date the gift can be received. /// - public static readonly Dictionary WC8Gifts = new() + public static readonly Dictionary WC8Gifts = new() { - {9000, new DateTime(2020, 02, 12)}, // Bulbasaur - {9001, new DateTime(2020, 02, 12)}, // Charmander - {9002, new DateTime(2020, 02, 12)}, // Squirtle - {9003, new DateTime(2020, 02, 12)}, // Pikachu - {9004, new DateTime(2020, 02, 15)}, // Original Color Magearna - {9005, new DateTime(2020, 02, 12)}, // Eevee - {9006, new DateTime(2020, 02, 12)}, // Rotom - {9007, new DateTime(2020, 02, 12)}, // Pichu - {9008, new DateTime(2020, 06, 02)}, // Hidden Ability Grookey - {9009, new DateTime(2020, 06, 02)}, // Hidden Ability Scorbunny - {9010, new DateTime(2020, 06, 02)}, // Hidden Ability Sobble - {9011, new DateTime(2020, 06, 30)}, // Shiny Zeraora - {9012, new DateTime(2020, 11, 10)}, // Gigantamax Melmetal - {9013, new DateTime(2021, 06, 17)}, // Gigantamax Bulbasaur - {9014, new DateTime(2021, 06, 17)}, // Gigantamax Squirtle + {9000, new(2020, 02, 12)}, // Bulbasaur + {9001, new(2020, 02, 12)}, // Charmander + {9002, new(2020, 02, 12)}, // Squirtle + {9003, new(2020, 02, 12)}, // Pikachu + {9004, new(2020, 02, 15)}, // Original Color Magearna + {9005, new(2020, 02, 12)}, // Eevee + {9006, new(2020, 02, 12)}, // Rotom + {9007, new(2020, 02, 12)}, // Pichu + {9008, new(2020, 06, 02)}, // Hidden Ability Grookey + {9009, new(2020, 06, 02)}, // Hidden Ability Scorbunny + {9010, new(2020, 06, 02)}, // Hidden Ability Sobble + {9011, new(2020, 06, 30)}, // Shiny Zeraora + {9012, new(2020, 11, 10)}, // Gigantamax Melmetal + {9013, new(2021, 06, 17)}, // Gigantamax Bulbasaur + {9014, new(2021, 06, 17)}, // Gigantamax Squirtle }; - private static readonly DateTime? Never = null; + private static readonly DateOnly? Never = null; /// /// Minimum date the gift can be received. /// - public static readonly Dictionary WA8Gifts = new() + public static readonly Dictionary WA8Gifts = new() { {0138, (new(2022, 01, 27), new(2023, 02, 01))}, // Poké Center Happiny {0301, (new(2022, 02, 04), new(2023, 03, 01))}, // プロポチャ Piplup @@ -79,15 +82,16 @@ public static class EncounterServerDate /// /// Minimum date the gift can be received. /// - public static readonly Dictionary WB8Gifts = new() + public static readonly Dictionary WB8Gifts = new() { {9015, (new(2022, 05, 18), Never)}, // Hidden Ability Turtwig {9016, (new(2022, 05, 18), Never)}, // Hidden Ability Chimchar {9017, (new(2022, 05, 18), Never)}, // Hidden Ability Piplup }; + // ReSharper disable once CollectionNeverUpdated.Global /// /// Minimum date the gift can be received. /// - public static Dictionary WC9Gifts = new(0); + public static readonly Dictionary WC9Gifts = new(0); } diff --git a/PKHeX.Core/Legality/Encounters/EncounterSlot/EncounterSlot.cs b/PKHeX.Core/Legality/Encounters/EncounterSlot/EncounterSlot.cs index d65a93fe1..e95b59b80 100644 --- a/PKHeX.Core/Legality/Encounters/EncounterSlot/EncounterSlot.cs +++ b/PKHeX.Core/Legality/Encounters/EncounterSlot/EncounterSlot.cs @@ -7,7 +7,7 @@ namespace PKHeX.Core; /// Wild Encounter Slot data /// /// Wild encounter slots are found as random encounters in-game. -public abstract record EncounterSlot(EncounterArea Area, ushort Species, byte Form, byte LevelMin, byte LevelMax) : IEncounterable, IEncounterMatch +public abstract record EncounterSlot(EncounterArea Area, ushort Species, byte Form, byte LevelMin, byte LevelMax) : IEncounterable, IEncounterMatch, IEncounterFormRandom { public abstract int Generation { get; } public abstract EntityContext Context { get; } @@ -165,7 +165,7 @@ public abstract record EncounterSlot(EncounterArea Area, ushort Species, byte Fo pk.Met_Level = level; if (pk.Format >= 4) - pk.MetDate = DateTime.Today; + pk.MetDate = DateOnly.FromDateTime(DateTime.Today); } public bool IsRandomUnspecificForm => Form >= FormDynamic; diff --git a/PKHeX.Core/Legality/Encounters/EncounterSlot/EncounterSlot2.cs b/PKHeX.Core/Legality/Encounters/EncounterSlot/EncounterSlot2.cs index ca7eda260..3d44add85 100644 --- a/PKHeX.Core/Legality/Encounters/EncounterSlot/EncounterSlot2.cs +++ b/PKHeX.Core/Legality/Encounters/EncounterSlot/EncounterSlot2.cs @@ -15,6 +15,7 @@ public sealed record EncounterSlot2 : EncounterSlot, INumberedSlot public override EntityContext Context => EntityContext.Gen2; public byte SlotNumber { get; } public override Ball FixedBall => Ball.Poke; + public bool IsHeadbutt => SlotType == SlotType.Headbutt; public EncounterSlot2(EncounterArea2 area, byte species, byte min, byte max, byte slot) : base(area, species, species == 201 ? FormRandom : (byte)0, min, max) { @@ -27,10 +28,16 @@ public sealed record EncounterSlot2 : EncounterSlot, INumberedSlot var pk2 = (PK2)pk; - if (SlotType == SlotType.Headbutt) + if (IsHeadbutt) { - while (!IsTreeAvailable(pk2.TID)) - pk2.TID = Util.Rand.Next(ushort.MaxValue + 1); + var id = pk2.TID16; + if (!IsTreeAvailable(id)) + { + // Get a random TID that satisfies this slot. + do { id = (ushort)Util.Rand.Next(); } + while (!IsTreeAvailable(id)); + pk2.TID16 = id; + } } if (Version == GameVersion.C) @@ -60,7 +67,7 @@ public sealed record EncounterSlot2 : EncounterSlot, INumberedSlot { 92, 0x2BB_3FF }, // Route 27 }; - internal bool IsTreeAvailable(int trainerID) + public bool IsTreeAvailable(ushort trainerID) { if (!Trees.TryGetValue(Location, out var permissions)) return false; diff --git a/PKHeX.Core/Legality/Encounters/EncounterSlot/EncounterSlot3PokeSpot.cs b/PKHeX.Core/Legality/Encounters/EncounterSlot/EncounterSlot3PokeSpot.cs index f345f44bd..16128c193 100644 --- a/PKHeX.Core/Legality/Encounters/EncounterSlot/EncounterSlot3PokeSpot.cs +++ b/PKHeX.Core/Legality/Encounters/EncounterSlot/EncounterSlot3PokeSpot.cs @@ -4,10 +4,11 @@ namespace PKHeX.Core; /// Encounter Slot found in . /// /// -public sealed record EncounterSlot3PokeSpot : EncounterSlot, INumberedSlot +public sealed record EncounterSlot3PokeSpot : EncounterSlot, INumberedSlot, IFatefulEncounterReadOnly { public override int Generation => 3; public override EntityContext Context => EntityContext.Gen3; + public bool FatefulEncounter => true; public byte SlotNumber { get; } diff --git a/PKHeX.Core/Legality/Encounters/EncounterSlot/EncounterSlot8a.cs b/PKHeX.Core/Legality/Encounters/EncounterSlot/EncounterSlot8a.cs index 896031a48..b4bce7700 100644 --- a/PKHeX.Core/Legality/Encounters/EncounterSlot/EncounterSlot8a.cs +++ b/PKHeX.Core/Legality/Encounters/EncounterSlot/EncounterSlot8a.cs @@ -146,21 +146,22 @@ public sealed record EncounterSlot8a : EncounterSlot, IAlphaReadOnly, IMasteryIn return !hasAlphaMove ? EncounterMatchRating.Match : EncounterMatchRating.DeferredErrors; var pi = PersonalTable.LA.GetFormEntry(Species, Form); - var tutors = pi.SpecialTutors[0]; + // Alpha encounters grant one Alpha move from the MoveShop list, if any exists. if (alphaMove is 0) { - bool hasAnyTutor = Array.IndexOf(tutors, true) >= 0; - if (hasAnyTutor) + // None set, but if any are available, it's a mismatch. + if (pi.HasMoveShop) return EncounterMatchRating.Deferred; } else { - var idx = pa.MoveShopPermitIndexes; - var index = idx.IndexOf(idx); + var permit = pa.Permit; + var idx = permit.RecordPermitIndexes; + var index = idx.IndexOf(alphaMove); if (index == -1) return EncounterMatchRating.Deferred; - if (!tutors[index]) + if (!permit.IsRecordPermitted(index)) return EncounterMatchRating.Deferred; } return EncounterMatchRating.Match; @@ -218,7 +219,7 @@ public sealed record EncounterSlot8a : EncounterSlot, IAlphaReadOnly, IMasteryIn { var pt = PersonalTable.LA; var entry = pt.GetFormEntry(Species, Form); - return (byte)entry.Gender; + return entry.Gender; } // hardcoded 7 to assume max dex progress + shiny charm. diff --git a/PKHeX.Core/Legality/Encounters/EncounterSlot/GO/EncounterSlot7GO.cs b/PKHeX.Core/Legality/Encounters/EncounterSlot/GO/EncounterSlot7GO.cs index 5583a3728..e4d3b0528 100644 --- a/PKHeX.Core/Legality/Encounters/EncounterSlot/GO/EncounterSlot7GO.cs +++ b/PKHeX.Core/Legality/Encounters/EncounterSlot/GO/EncounterSlot7GO.cs @@ -17,7 +17,7 @@ public sealed record EncounterSlot7GO : EncounterSlotGO { } - protected override PKM GetBlank() => new PB7(); + protected override PB7 GetBlank() => new(); protected override void ApplyDetails(ITrainerInfo sav, EncounterCriteria criteria, PKM pk) { diff --git a/PKHeX.Core/Legality/Encounters/EncounterSlot/GO/EncounterSlot8GO.cs b/PKHeX.Core/Legality/Encounters/EncounterSlot/GO/EncounterSlot8GO.cs index 7c0e30c75..254581e82 100644 --- a/PKHeX.Core/Legality/Encounters/EncounterSlot/GO/EncounterSlot8GO.cs +++ b/PKHeX.Core/Legality/Encounters/EncounterSlot/GO/EncounterSlot8GO.cs @@ -69,11 +69,10 @@ public sealed record EncounterSlot8GO : EncounterSlotGO, IFixedOTFriendship public override EntityContext Context => OriginFormat switch { - PogoImportFormat.PK7 => + PogoImportFormat.PK7 or PogoImportFormat.PB7 => PersonalTable.BDSP.IsPresentInGame(Species, Form) ? EntityContext.Gen8b : PersonalTable.LA.IsPresentInGame(Species, Form) ? EntityContext.Gen8a : EntityContext.Gen8, // don't throw an exception, just give them a context. - PogoImportFormat.PB7 => EntityContext.Gen7b, PogoImportFormat.PK8 => EntityContext.Gen8, PogoImportFormat.PA8 => EntityContext.Gen8a, PogoImportFormat.PK9 => EntityContext.Gen9, diff --git a/PKHeX.Core/Legality/Encounters/EncounterSlot/GO/EncounterSlotGO.cs b/PKHeX.Core/Legality/Encounters/EncounterSlot/GO/EncounterSlotGO.cs index aaeb89281..3728c5cfa 100644 --- a/PKHeX.Core/Legality/Encounters/EncounterSlot/GO/EncounterSlotGO.cs +++ b/PKHeX.Core/Legality/Encounters/EncounterSlot/GO/EncounterSlotGO.cs @@ -48,18 +48,18 @@ public abstract record EncounterSlotGO : EncounterSlot, IPogoSlot private static string GetDateString(int time) => time == 0 ? "X" : $"{GetDate(time):yyyy.MM.dd}"; - private static DateTime GetDate(int time) + private static DateOnly GetDate(int time) { var d = time & 0xFF; var m = (time >> 8) & 0xFF; var y = time >> 16; - return new DateTime(y, m, d); + return new DateOnly(y, m, d); } public bool IsWithinStartEnd(int stamp) { if (EndDate == 0) - return StartDate <= stamp && GetDate(stamp) <= GetMaxDateTime(); + return StartDate <= stamp && GetDate(stamp) <= GetMaxDate(); if (StartDate == 0) return stamp <= EndDate; return StartDate <= stamp && stamp <= EndDate; @@ -70,15 +70,15 @@ public abstract record EncounterSlotGO : EncounterSlot, IPogoSlot /// public static int GetTimeStamp(int year, int month, int day) => (year << 16) | (month << 8) | day; - private static DateTime GetMaxDateTime() => DateTime.UtcNow.AddHours(12); // UTC+12 for Kiribati, no daylight savings + private static DateOnly GetMaxDate() => DateOnly.FromDateTime(DateTime.UtcNow.AddHours(12)); // UTC+12 for Kiribati, no daylight savings /// /// Gets a random date within the availability range. /// - public DateTime GetRandomValidDate() + public DateOnly GetRandomValidDate() { if (StartDate == 0) - return EndDate == 0 ? GetMaxDateTime() : GetDate(EndDate); + return EndDate == 0 ? GetMaxDate() : GetDate(EndDate); var start = GetDate(StartDate); if (EndDate == 0) @@ -138,7 +138,8 @@ public abstract record EncounterSlotGO : EncounterSlot, IPogoSlot { case Shiny.Random when !pk.IsShiny && criteria.Shiny.IsShiny(): case Shiny.Always when !pk.IsShiny: // Force Square - pk.PID = (uint)(((pk.TID ^ pk.SID ^ (pk.PID & 0xFFFF) ^ 0) << 16) | (pk.PID & 0xFFFF)); + var low = pk.PID & 0xFFFF; + pk.PID = ((low ^ pk.TID16 ^ pk.SID16 ^ 0) << 16) | low; break; case Shiny.Random when pk.IsShiny && !criteria.Shiny.IsShiny(): diff --git a/PKHeX.Core/Legality/Encounters/EncounterSlot/IMagnetStatic.cs b/PKHeX.Core/Legality/Encounters/EncounterSlot/IMagnetStatic.cs index 079acab36..c214219e1 100644 --- a/PKHeX.Core/Legality/Encounters/EncounterSlot/IMagnetStatic.cs +++ b/PKHeX.Core/Legality/Encounters/EncounterSlot/IMagnetStatic.cs @@ -1,4 +1,4 @@ -namespace PKHeX.Core; +namespace PKHeX.Core; /// /// Contains information about the RNG restrictions for the slot, and any mutated RNG values. @@ -19,14 +19,10 @@ public interface IMagnetStatic byte StaticCount { get; } /// Count of slots in the parent area that can be yielded by byte MagnetPullCount { get; } -} -public static class MagnetStaticExtensions -{ - private const byte NotMagnetStaticSlot = byte.MaxValue; - public static bool IsStaticSlot(this IMagnetStatic slot) => slot.StaticCount != 0 && slot.StaticIndex != NotMagnetStaticSlot; - public static bool IsMagnetSlot(this IMagnetStatic slot) => slot.MagnetPullCount != 0 && slot.MagnetPullIndex != NotMagnetStaticSlot; + bool IsStaticSlot => StaticCount != 0 && StaticIndex != byte.MaxValue; + bool IsMagnetSlot => MagnetPullCount != 0 && MagnetPullIndex != byte.MaxValue; - public static bool IsMatchStatic(this IMagnetStatic slot, int index, int count) => index == slot.StaticIndex && count == slot.StaticCount; - public static bool IsMatchMagnet(this IMagnetStatic slot, int index, int count) => index == slot.MagnetPullIndex && count == slot.MagnetPullCount; + bool IsMatchStatic(int index, int count) => index == StaticIndex && count == StaticCount; + bool IsMatchMagnet(int index, int count) => index == MagnetPullIndex && count == MagnetPullCount; } diff --git a/PKHeX.Core/Legality/Encounters/EncounterStatic/DreamWorldEntry.cs b/PKHeX.Core/Legality/Encounters/EncounterStatic/DreamWorldEntry.cs index ac7134e35..5b878f865 100644 --- a/PKHeX.Core/Legality/Encounters/EncounterStatic/DreamWorldEntry.cs +++ b/PKHeX.Core/Legality/Encounters/EncounterStatic/DreamWorldEntry.cs @@ -1,12 +1,11 @@ -using System.Collections.Generic; -using System.Linq; +using System; namespace PKHeX.Core; /// /// Intermediary Representation of Dream World Data /// -internal record DreamWorldEntry(ushort Species, byte Level, ushort Move1 = 0, ushort Move2 = 0, ushort Move3 = 0, byte Form = 0, sbyte Gender = -1) +public readonly record struct DreamWorldEntry(ushort Species, byte Level, ushort Move1 = 0, ushort Move2 = 0, ushort Move3 = 0, byte Form = 0, sbyte Gender = -1) { private int EntryCount => Move1 == 0 ? 1 : Move2 == 0 ? 1 : Move3 == 0 ? 2 : 3; @@ -49,10 +48,12 @@ internal record DreamWorldEntry(ushort Species, byte Level, ushort Move1 = 0, us Moves = new(move), }; - public static EncounterStatic5[] GetArray(GameVersion game, IReadOnlyList t) + public static EncounterStatic5[] GetArray(GameVersion game, ReadOnlySpan t) { // Split encounters with multiple permitted special moves -- a pk can only be obtained with 1 of the special moves! - var count = t.Sum(z => z.EntryCount); + int count = 0; + foreach (var e in t) + count += e.EntryCount; var result = new EncounterStatic5[count]; int ctr = 0; diff --git a/PKHeX.Core/Legality/Encounters/EncounterStatic/EncounterDist9.cs b/PKHeX.Core/Legality/Encounters/EncounterStatic/EncounterDist9.cs index aefa0d7e7..c73291a0b 100644 --- a/PKHeX.Core/Legality/Encounters/EncounterStatic/EncounterDist9.cs +++ b/PKHeX.Core/Legality/Encounters/EncounterStatic/EncounterDist9.cs @@ -60,7 +60,7 @@ public sealed record EncounterDist9 : EncounterStatic, ITeraRaid9 3 => RandRate3MinScarlet, _ => throw new ArgumentOutOfRangeException(nameof(stage)), }; - + public ushort GetRandRateMinViolet(int stage) => stage switch { 0 => RandRate0MinViolet, @@ -74,7 +74,7 @@ public sealed record EncounterDist9 : EncounterStatic, ITeraRaid9 private const int StageNone = -1; public bool CanBeEncountered(uint seed) => GetProgressMaximum(seed) != StageNone; - + public int ProgressStageMin { get @@ -238,7 +238,7 @@ public sealed record EncounterDist9 : EncounterStatic, ITeraRaid9 return true; var pi = PersonalTable.SV.GetFormEntry(Species, Form); - var param = new GenerateParam9((byte)pi.Gender, FlawlessIVCount, 1, 0, 0, 0, Ability, Shiny); + var param = new GenerateParam9(pi.Gender, FlawlessIVCount, 1, 0, 0, 0, Ability, Shiny); if (!Encounter9RNG.IsMatch(pk, param, seed)) return true; return base.IsMatchPartial(pk); @@ -258,7 +258,7 @@ public sealed record EncounterDist9 : EncounterStatic, ITeraRaid9 const byte rollCount = 1; const byte undefinedSize = 0; var pi = PersonalTable.SV.GetFormEntry(Species, Form); - var param = new GenerateParam9((byte)pi.Gender, FlawlessIVCount, rollCount, + var param = new GenerateParam9(pi.Gender, FlawlessIVCount, rollCount, undefinedSize, undefinedSize, undefinedSize, Ability, Shiny); diff --git a/PKHeX.Core/Legality/Encounters/EncounterStatic/EncounterMight9.cs b/PKHeX.Core/Legality/Encounters/EncounterStatic/EncounterMight9.cs index e168c458c..8d1504aba 100644 --- a/PKHeX.Core/Legality/Encounters/EncounterStatic/EncounterMight9.cs +++ b/PKHeX.Core/Legality/Encounters/EncounterStatic/EncounterMight9.cs @@ -284,6 +284,6 @@ public sealed record EncounterMight9 : EncounterStatic, ITeraRaid9 0 => PersonalInfo.RatioMagicMale, 1 => PersonalInfo.RatioMagicFemale, 2 => PersonalInfo.RatioMagicGenderless, - _ => (byte)PersonalTable.SV.GetFormEntry(Species, Form).Gender, + _ => PersonalTable.SV.GetFormEntry(Species, Form).Gender, }; } diff --git a/PKHeX.Core/Legality/Encounters/EncounterStatic/EncounterStatic.cs b/PKHeX.Core/Legality/Encounters/EncounterStatic/EncounterStatic.cs index 668f2b158..a30747c35 100644 --- a/PKHeX.Core/Legality/Encounters/EncounterStatic/EncounterStatic.cs +++ b/PKHeX.Core/Legality/Encounters/EncounterStatic/EncounterStatic.cs @@ -8,7 +8,7 @@ namespace PKHeX.Core; /// /// Static Encounters are fixed position encounters with properties that are not subject to Wild Encounter conditions. /// -public abstract record EncounterStatic(GameVersion Version) : IEncounterable, IMoveset, IEncounterMatch +public abstract record EncounterStatic(GameVersion Version) : IEncounterable, IMoveset, IEncounterMatch, IFatefulEncounterReadOnly { public ushort Species { get; init; } public byte Form { get; init; } @@ -26,7 +26,7 @@ public abstract record EncounterStatic(GameVersion Version) : IEncounterable, IM public ushort HeldItem { get; init; } public bool Gift { get; init; } - public bool Fateful { get; init; } + public bool FatefulEncounter { get; init; } public byte EggCycles { get; init; } public byte FlawlessIVCount { get; init; } @@ -46,11 +46,6 @@ public abstract record EncounterStatic(GameVersion Version) : IEncounterable, IM public string LongName => $"{_name} ({Version})"; public bool IsShiny => Shiny.IsShiny(); - public bool IsRandomUnspecificForm => Form >= FormDynamic; - private const int FormDynamic = FormVivillon; - internal const int FormVivillon = 30; - //protected const int FormRandom = 31; - protected virtual PKM GetBlank(ITrainerInfo tr) => EntityBlank.GetBlank(Generation, Version); public PKM ConvertToPKM(ITrainerInfo tr) => ConvertToPKM(tr, EncounterCriteria.Unrestricted); @@ -91,7 +86,7 @@ public abstract record EncounterStatic(GameVersion Version) : IEncounterable, IM SetPINGA(pk, criteria); SetEncounterMoves(pk, version, level); - if (Fateful) + if (FatefulEncounter) pk.FatefulEncounter = true; if (pk.Format < 6) @@ -139,10 +134,10 @@ public abstract record EncounterStatic(GameVersion Version) : IEncounterable, IM { bool traded = (int)Version == tr.Game; pk.Egg_Location = EncounterSuggestion.GetSuggestedEncounterEggLocationEgg(Generation, Version, traded); - pk.EggMetDate = today; + pk.EggMetDate = DateOnly.FromDateTime(today); } pk.Egg_Location = EggLocation; - pk.EggMetDate = today; + pk.EggMetDate = DateOnly.FromDateTime(today); } protected virtual void SetMetData(PKM pk, int level, DateTime today) @@ -153,7 +148,7 @@ public abstract record EncounterStatic(GameVersion Version) : IEncounterable, IM pk.Met_Location = Location; pk.Met_Level = level; if (pk.Format >= 4) - pk.MetDate = today; + pk.MetDate = DateOnly.FromDateTime(today); } protected virtual void SetEncounterMoves(PKM pk, GameVersion version, int level) @@ -276,8 +271,6 @@ public abstract record EncounterStatic(GameVersion Version) : IEncounterable, IM protected virtual bool IsMatchForm(PKM pk, EvoCriteria evo) { - if (IsRandomUnspecificForm) - return true; return Form == evo.Form || FormInfo.IsFormChangeable(Species, Form, pk.Form, Context, pk.Context); } @@ -332,8 +325,8 @@ public abstract record EncounterStatic(GameVersion Version) : IEncounterable, IM /// protected virtual bool IsMatchPartial(PKM pk) { - if (pk.Format >= 5 && pk.AbilityNumber == 4 && this.IsPartialMatchHidden(pk.Species, Species)) + if (pk is { Format: >= 5, AbilityNumber: 4 } && this.IsPartialMatchHidden(pk.Species, Species)) return true; - return pk.FatefulEncounter != Fateful; + return pk.FatefulEncounter != FatefulEncounter; } } diff --git a/PKHeX.Core/Legality/Encounters/EncounterStatic/EncounterStatic1E.cs b/PKHeX.Core/Legality/Encounters/EncounterStatic/EncounterStatic1E.cs index 9d46f88db..5c73ab0c1 100644 --- a/PKHeX.Core/Legality/Encounters/EncounterStatic/EncounterStatic1E.cs +++ b/PKHeX.Core/Legality/Encounters/EncounterStatic/EncounterStatic1E.cs @@ -18,7 +18,9 @@ public sealed record EncounterStatic1E : EncounterStatic1, IFixedGBLanguage public IReadOnlyList OT_Names { get; init; } = Array.Empty(); /// Trainer ID for the event. - public int TID { get; init; } = -1; + public ushort TID16 { get; init; } = UnspecifiedID; + + public const ushort UnspecifiedID = 0; public EncounterStatic1E(byte species, byte level, GameVersion game) : base(species, level, game) { @@ -36,7 +38,7 @@ public sealed record EncounterStatic1E : EncounterStatic1, IFixedGBLanguage if (!IsShinyValid(pk)) return false; - if (TID != -1 && pk.TID != TID) + if (TID16 != UnspecifiedID && pk.TID16 != TID16) return false; if (OT_Name.Length != 0) @@ -60,11 +62,11 @@ public sealed record EncounterStatic1E : EncounterStatic1, IFixedGBLanguage _ => true, }; - protected override PKM GetBlank(ITrainerInfo tr) => Language switch + protected override PK1 GetBlank(ITrainerInfo tr) => Language switch { - EncounterGBLanguage.Japanese => new PK1(true), - EncounterGBLanguage.International => new PK1(), - _ => new PK1(tr.Language == 1), + EncounterGBLanguage.Japanese => new(true), + EncounterGBLanguage.International => new(), + _ => new(tr.Language == 1), }; protected override void ApplyDetails(ITrainerInfo tr, EncounterCriteria criteria, PKM pk) @@ -81,8 +83,8 @@ public sealed record EncounterStatic1E : EncounterStatic1, IFixedGBLanguage pk1.Catch_Rate = Util.Rand.Next(2) == 0 ? (byte)167 : (byte)168; } - if (TID != -1) - pk.TID = TID; + if (TID16 != UnspecifiedID) + pk.TID16 = TID16; if (OT_Name.Length != 0) pk.OT_Name = OT_Name; diff --git a/PKHeX.Core/Legality/Encounters/EncounterStatic/EncounterStatic2E.cs b/PKHeX.Core/Legality/Encounters/EncounterStatic/EncounterStatic2E.cs index b50a4e240..ec3f97a11 100644 --- a/PKHeX.Core/Legality/Encounters/EncounterStatic/EncounterStatic2E.cs +++ b/PKHeX.Core/Legality/Encounters/EncounterStatic/EncounterStatic2E.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using System.Linq; @@ -17,10 +17,12 @@ public sealed record EncounterStatic2E : EncounterStatic2, IFixedGBLanguage public IReadOnlyList OT_Names { get; init; } = Array.Empty(); - /// Trainer ID for the event. - public int TID { get; init; } = -1; + private const ushort UnspecifiedID = 0; - public bool IsGift => TID != -1; + /// Trainer ID for the event. + public ushort TID16 { get; init; } = UnspecifiedID; + + public bool IsGift => TID16 != UnspecifiedID; public int CurrentLevel { get; init; } = -1; @@ -47,7 +49,7 @@ public sealed record EncounterStatic2E : EncounterStatic2, IFixedGBLanguage return true; // Check OT Details - if (TID != -1 && pk.TID != TID) + if (TID16 != UnspecifiedID && pk.TID16 != TID16) return false; if (OT_Name.Length != 0) @@ -73,11 +75,11 @@ public sealed record EncounterStatic2E : EncounterStatic2, IFixedGBLanguage protected override int GetMinimalLevel() => CurrentLevel == -1 ? base.GetMinimalLevel() : CurrentLevel; - protected override PKM GetBlank(ITrainerInfo tr) => Language switch + protected override PK2 GetBlank(ITrainerInfo tr) => Language switch { - EncounterGBLanguage.Japanese => new PK2(true), - EncounterGBLanguage.International => new PK2(), - _ => new PK2(tr.Language == 1), + EncounterGBLanguage.Japanese => new(true), + EncounterGBLanguage.International => new(), + _ => new(tr.Language == 1), }; protected override void ApplyDetails(ITrainerInfo tr, EncounterCriteria criteria, PKM pk) @@ -86,8 +88,8 @@ public sealed record EncounterStatic2E : EncounterStatic2, IFixedGBLanguage if (CurrentLevel != -1) // Restore met level pk.Met_Level = LevelMin; - if (TID != -1) - pk.TID = TID; + if (TID16 != UnspecifiedID) + pk.TID16 = TID16; if (IsGift) pk.OT_Gender = 0; diff --git a/PKHeX.Core/Legality/Encounters/EncounterStatic/EncounterStatic3.cs b/PKHeX.Core/Legality/Encounters/EncounterStatic/EncounterStatic3.cs index 375bafc13..243dbbaae 100644 --- a/PKHeX.Core/Legality/Encounters/EncounterStatic/EncounterStatic3.cs +++ b/PKHeX.Core/Legality/Encounters/EncounterStatic/EncounterStatic3.cs @@ -31,7 +31,7 @@ public sealed record EncounterStatic3 : EncounterStatic return Level <= evo.LevelMax; if (EggEncounter) - return pk.Met_Level == 0 && pk.CurrentLevel >= 5; // met level 0, origin level 5 + return pk is { Met_Level: 0, CurrentLevel: >= 5 }; // met level 0, origin level 5 return pk.Met_Level == Level; } diff --git a/PKHeX.Core/Legality/Encounters/EncounterStatic/EncounterStatic4.cs b/PKHeX.Core/Legality/Encounters/EncounterStatic/EncounterStatic4.cs index 7febd4c70..7997c3887 100644 --- a/PKHeX.Core/Legality/Encounters/EncounterStatic/EncounterStatic4.cs +++ b/PKHeX.Core/Legality/Encounters/EncounterStatic/EncounterStatic4.cs @@ -116,10 +116,10 @@ public sealed record EncounterStatic4(GameVersion Version) : EncounterStatic(Ver pk4.GroundTile = Roaming ? GroundTileType.Grass : GroundTile.GetIndex(); pk.Met_Location = Location; pk.Met_Level = level; - pk.MetDate = today; + pk.MetDate = DateOnly.FromDateTime(today); } - public static bool IsMatchRoamerLocation(uint permit, int location, int first) + public static bool IsMatchRoamerLocation(ulong permit, int location, int first) { var value = location - first; if ((uint)value >= 64) @@ -127,10 +127,18 @@ public sealed record EncounterStatic4(GameVersion Version) : EncounterStatic(Ver return (permit & (1u << value)) != 0; } + public static bool IsMatchRoamerLocation(uint permit, int location, int first) + { + var value = location - first; + if ((uint)value >= 32) + return false; + return (permit & (1u << value)) != 0; + } + // Merged all locations into a bitmask for quick computation. private const int FirstS = 16; - private const uint PermitGrassS = 0x8033FFFF; // 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 36, 37, 47, 49, - private const uint PermitWaterS = 0x803E3B9E; // 18, 19, 20, 23, 24, 25, 27, 28, 29, 33, 34, 35, 36, 37, 47, 49, + private const ulong PermitGrassS = 0x2_8033FFFF; // 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 36, 37, 47, 49, + private const ulong PermitWaterS = 0x2_803E3B9E; // 18, 19, 20, 23, 24, 25, 27, 28, 29, 33, 34, 35, 36, 37, 47, 49, private const int FirstJ = 177; private const uint PermitGrassJ = 0x0003E7FF; // 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 190, 191, 192, 193, 194, diff --git a/PKHeX.Core/Legality/Encounters/EncounterStatic/EncounterStatic5.cs b/PKHeX.Core/Legality/Encounters/EncounterStatic/EncounterStatic5.cs index db3dbac19..b3018e668 100644 --- a/PKHeX.Core/Legality/Encounters/EncounterStatic/EncounterStatic5.cs +++ b/PKHeX.Core/Legality/Encounters/EncounterStatic/EncounterStatic5.cs @@ -11,6 +11,8 @@ public record EncounterStatic5(GameVersion Version) : EncounterStatic(Version) public bool Roaming { get; init; } public bool IsWildCorrelationPID => !Roaming && Shiny == Shiny.Random && Species != (int)Core.Species.Crustle; + public bool EntreeForestDreamWorld => Location == 75; + protected sealed override bool IsMatchPartial(PKM pk) { // BW/2 Jellicent collision with wild surf slot, resolved by duplicating the encounter with any abil diff --git a/PKHeX.Core/Legality/Encounters/EncounterStatic/EncounterStatic5N.cs b/PKHeX.Core/Legality/Encounters/EncounterStatic/EncounterStatic5N.cs index cd5d12bdf..34c75dff6 100644 --- a/PKHeX.Core/Legality/Encounters/EncounterStatic/EncounterStatic5N.cs +++ b/PKHeX.Core/Legality/Encounters/EncounterStatic/EncounterStatic5N.cs @@ -47,8 +47,8 @@ internal sealed record EncounterStatic5N : EncounterStatic5 pk5.IV_HP = pk5.IV_ATK = pk5.IV_DEF = pk5.IV_SPA = pk5.IV_SPD = pk5.IV_SPE = 30; pk5.NSparkle = NSparkle; pk5.OT_Name = GetOT(lang); - pk5.TID = 00002; - pk5.SID = 00000; + pk5.TID16 = 00002; + pk5.SID16 = 00000; } public static string GetOT(int lang) => lang == (int)LanguageID.Japanese ? "N" : "N"; diff --git a/PKHeX.Core/Legality/Encounters/EncounterStatic/EncounterStatic7.cs b/PKHeX.Core/Legality/Encounters/EncounterStatic/EncounterStatic7.cs index 105fe4e03..882af64f3 100644 --- a/PKHeX.Core/Legality/Encounters/EncounterStatic/EncounterStatic7.cs +++ b/PKHeX.Core/Legality/Encounters/EncounterStatic/EncounterStatic7.cs @@ -4,7 +4,7 @@ namespace PKHeX.Core; /// Generation 7 Static Encounter /// /// -public sealed record EncounterStatic7(GameVersion Version) : EncounterStatic(Version), IRelearn +public sealed record EncounterStatic7(GameVersion Version) : EncounterStatic(Version), IRelearn, IEncounterFormRandom { public override int Generation => 7; public override EntityContext Context => EntityContext.Gen7; @@ -14,6 +14,11 @@ public sealed record EncounterStatic7(GameVersion Version) : EncounterStatic(Ver public bool IsTotemNoTransfer => Legal.Totem_NoTransfer.Contains(Species); public int GetTotemBaseForm() => FormInfo.GetTotemBaseForm(Species, Form); + public bool IsRandomUnspecificForm => Form >= FormDynamic; + private const int FormDynamic = FormVivillon; + internal const int FormVivillon = 30; + //protected const int FormRandom = 31; + protected override bool IsMatchLocation(PKM pk) { if (EggLocation == Locations.Daycare5 && !Relearn.HasMoves && pk.RelearnMove1 != 0) // Gift Eevee edge case @@ -40,6 +45,9 @@ public sealed record EncounterStatic7(GameVersion Version) : EncounterStatic(Ver protected override bool IsMatchForm(PKM pk, EvoCriteria evo) { + if (IsRandomUnspecificForm) + return true; + if (IsTotem) { var expectForm = pk.Format == 7 ? Form : FormInfo.GetTotemBaseForm(Species, Form); @@ -65,9 +73,9 @@ public sealed record EncounterStatic7(GameVersion Version) : EncounterStatic(Ver { Species = species, Gift = true, // Forces Poké Ball - Ability = Legal.TransferSpeciesDefaultAbilityGen1(species) ? AbilityPermission.OnlyFirst : AbilityPermission.OnlyHidden, // Hidden by default, else first + Ability = TransporterLogic.IsHiddenDisallowedVC1(species) ? AbilityPermission.OnlyFirst : AbilityPermission.OnlyHidden, // Hidden by default, else first Shiny = mew ? Shiny.Never : Shiny.Random, - Fateful = mew, + FatefulEncounter = mew, Location = Locations.Transfer1, Level = metLevel, FlawlessIVCount = mew ? (byte)5 : (byte)3, @@ -82,9 +90,9 @@ public sealed record EncounterStatic7(GameVersion Version) : EncounterStatic(Ver { Species = species, Gift = true, // Forces Poké Ball - Ability = Legal.TransferSpeciesDefaultAbilityGen2(species) ? AbilityPermission.OnlyFirst : AbilityPermission.OnlyHidden, // Hidden by default, else first + Ability = TransporterLogic.IsHiddenDisallowedVC2(species) ? AbilityPermission.OnlyFirst : AbilityPermission.OnlyHidden, // Hidden by default, else first Shiny = mew ? Shiny.Never : Shiny.Random, - Fateful = fateful, + FatefulEncounter = fateful, Location = Locations.Transfer2, Level = metLevel, FlawlessIVCount = fateful ? (byte)5 : (byte)3, diff --git a/PKHeX.Core/Legality/Encounters/EncounterStatic/EncounterStatic8N.cs b/PKHeX.Core/Legality/Encounters/EncounterStatic/EncounterStatic8N.cs index ae8f585b2..f89708ef5 100644 --- a/PKHeX.Core/Legality/Encounters/EncounterStatic/EncounterStatic8N.cs +++ b/PKHeX.Core/Legality/Encounters/EncounterStatic/EncounterStatic8N.cs @@ -9,8 +9,8 @@ namespace PKHeX.Core; /// public sealed record EncounterStatic8N : EncounterStatic8Nest { - private readonly uint MinRank; - private readonly uint MaxRank; + private readonly byte MinRank; + private readonly byte MaxRank; private readonly byte NestID; private byte[] NestLocations => Encounters8Nest.NestLocations[NestID]; @@ -19,7 +19,7 @@ public sealed record EncounterStatic8N : EncounterStatic8Nest public override byte LevelMin => LevelCaps[MinRank * 2]; public override byte LevelMax => LevelCaps[(MaxRank * 2) + 1]; - public EncounterStatic8N(byte nestID, uint minRank, uint maxRank, byte val, GameVersion game) : base(game) + public EncounterStatic8N(byte nestID, byte minRank, byte maxRank, byte val, GameVersion game) : base(game) { NestID = nestID; MinRank = minRank; @@ -37,7 +37,7 @@ public sealed record EncounterStatic8N : EncounterStatic8Nest CanGigantamax = data[5] != 0, }; - private static readonly byte[] LevelCaps = + private static ReadOnlySpan LevelCaps => new byte[] { 15, 20, // 0 25, 30, // 1 diff --git a/PKHeX.Core/Legality/Encounters/EncounterStatic/EncounterStatic8NC.cs b/PKHeX.Core/Legality/Encounters/EncounterStatic/EncounterStatic8NC.cs index dad4a1cee..429bb1ce9 100644 --- a/PKHeX.Core/Legality/Encounters/EncounterStatic/EncounterStatic8NC.cs +++ b/PKHeX.Core/Legality/Encounters/EncounterStatic/EncounterStatic8NC.cs @@ -1,4 +1,4 @@ -using static PKHeX.Core.Encounters8Nest; +using static PKHeX.Core.Encounters8Nest; namespace PKHeX.Core; @@ -25,7 +25,7 @@ public sealed record EncounterStatic8NC(GameVersion Version) : EncounterStatic8N return false; if (lvl is < 20 or > 55) return false; - if (pk.Met_Location == Watchtower && pk.IsShiny) + if (pk is { Met_Location: Watchtower, IsShiny: true }) return false; // host cannot downlevel and be shiny return lvl % 5 == 0; } diff --git a/PKHeX.Core/Legality/Encounters/EncounterStatic/EncounterStatic8Nest.cs b/PKHeX.Core/Legality/Encounters/EncounterStatic/EncounterStatic8Nest.cs index 858920c8f..28a214daf 100644 --- a/PKHeX.Core/Legality/Encounters/EncounterStatic/EncounterStatic8Nest.cs +++ b/PKHeX.Core/Legality/Encounters/EncounterStatic/EncounterStatic8Nest.cs @@ -34,7 +34,7 @@ public abstract record EncounterStatic8Nest(GameVersion Version) : EncounterS if (VerifyCorrelation != null && !VerifyCorrelation(pk, (T)this)) return false; - if (pk is IRibbonSetMark8 m8 && m8.HasMark()) + if (pk is IRibbonSetMark8 { HasMarkEncounter8: true }) return false; if (pk.Species == (int)Core.Species.Shedinja && pk is IRibbonSetAffixed { AffixedRibbon: >= (int)RibbonIndex.MarkLunchtime }) return false; diff --git a/PKHeX.Core/Legality/Encounters/EncounterStatic/EncounterStatic8a.cs b/PKHeX.Core/Legality/Encounters/EncounterStatic/EncounterStatic8a.cs index 393b4df37..00f6e3356 100644 --- a/PKHeX.Core/Legality/Encounters/EncounterStatic/EncounterStatic8a.cs +++ b/PKHeX.Core/Legality/Encounters/EncounterStatic/EncounterStatic8a.cs @@ -205,7 +205,7 @@ public sealed record EncounterStatic8a(GameVersion Version) : EncounterStatic(Ve { var pt = PersonalTable.LA; var entry = pt.GetFormEntry(Species, Form); - return (byte)entry.Gender; + return entry.Gender; } } diff --git a/PKHeX.Core/Legality/Encounters/EncounterStatic/EncounterStatic8b.cs b/PKHeX.Core/Legality/Encounters/EncounterStatic/EncounterStatic8b.cs index 967d06bd9..43a5d2aaf 100644 --- a/PKHeX.Core/Legality/Encounters/EncounterStatic/EncounterStatic8b.cs +++ b/PKHeX.Core/Legality/Encounters/EncounterStatic/EncounterStatic8b.cs @@ -101,7 +101,7 @@ public sealed record EncounterStatic8b : EncounterStatic, IStaticCorrelation8b { pk.Met_Level = level; pk.Met_Location = !Roaming ? Location : Roaming_MetLocation_BDSP[0]; - pk.MetDate = today; + pk.MetDate = DateOnly.FromDateTime(today); } // defined by mvpoke in encounter data diff --git a/PKHeX.Core/Legality/Encounters/EncounterStatic/EncounterStatic9.cs b/PKHeX.Core/Legality/Encounters/EncounterStatic/EncounterStatic9.cs index 3e8e313af..62421c2ac 100644 --- a/PKHeX.Core/Legality/Encounters/EncounterStatic/EncounterStatic9.cs +++ b/PKHeX.Core/Legality/Encounters/EncounterStatic/EncounterStatic9.cs @@ -71,7 +71,7 @@ public sealed record EncounterStatic9(GameVersion Version) : EncounterStatic(Ver const byte rollCount = 1; var pi = PersonalTable.SV.GetFormEntry(Species, Form); - var param = new GenerateParam9((byte)pi.Gender, FlawlessIVCount, rollCount, height, weight, scale, Ability, Shiny); + var param = new GenerateParam9(pi.Gender, FlawlessIVCount, rollCount, height, weight, scale, Ability, Shiny); ulong init = Util.Rand.Rand64(); var success = this.TryApply64(pk9, init, param, criteria, IVs.IsSpecified); diff --git a/PKHeX.Core/Legality/Encounters/EncounterStatic/EncounterTera9.cs b/PKHeX.Core/Legality/Encounters/EncounterStatic/EncounterTera9.cs index ac9d82332..9328ff5d0 100644 --- a/PKHeX.Core/Legality/Encounters/EncounterStatic/EncounterTera9.cs +++ b/PKHeX.Core/Legality/Encounters/EncounterStatic/EncounterTera9.cs @@ -132,7 +132,7 @@ public sealed record EncounterTera9 : EncounterStatic, ITeraRaid9 return true; var pi = PersonalTable.SV.GetFormEntry(Species, Form); - var param = new GenerateParam9((byte)pi.Gender, FlawlessIVCount, 1, 0, 0, 0, Ability, Shiny); + var param = new GenerateParam9(pi.Gender, FlawlessIVCount, 1, 0, 0, 0, Ability, Shiny); if (!Encounter9RNG.IsMatch(pk, param, seed)) return true; return base.IsMatchPartial(pk); @@ -152,7 +152,7 @@ public sealed record EncounterTera9 : EncounterStatic, ITeraRaid9 const byte rollCount = 1; const byte undefinedSize = 0; var pi = PersonalTable.SV.GetFormEntry(Species, Form); - var param = new GenerateParam9((byte)pi.Gender, FlawlessIVCount, rollCount, + var param = new GenerateParam9(pi.Gender, FlawlessIVCount, rollCount, undefinedSize, undefinedSize, undefinedSize, Ability, Shiny); diff --git a/PKHeX.Core/Legality/Encounters/EncounterStatic/ITeraRaid9.cs b/PKHeX.Core/Legality/Encounters/EncounterStatic/ITeraRaid9.cs new file mode 100644 index 000000000..e4fa64ac1 --- /dev/null +++ b/PKHeX.Core/Legality/Encounters/EncounterStatic/ITeraRaid9.cs @@ -0,0 +1,32 @@ +namespace PKHeX.Core; + +/// +/// Properties shared for all Tera Crystal raids. +/// +public interface ITeraRaid9 : IGemType +{ + /// + /// Is a BCAT raid. + /// + bool IsDistribution { get; } + + /// + /// BCAT distribution index. + /// + byte Index { get; } + + /// + /// Star count difficulty. + /// + byte Stars { get; } + + /// + /// Raw random chance value the encounter will be chosen. + /// + byte RandRate { get; } + + /// + /// Checks if the provided will pick this object by random choice. + /// + bool CanBeEncountered(uint seed); +} diff --git a/PKHeX.Core/Legality/Encounters/EncounterTrade/EncounterTrade.cs b/PKHeX.Core/Legality/Encounters/EncounterTrade/EncounterTrade.cs index e8c8fef31..b0613a7e5 100644 --- a/PKHeX.Core/Legality/Encounters/EncounterTrade/EncounterTrade.cs +++ b/PKHeX.Core/Legality/Encounters/EncounterTrade/EncounterTrade.cs @@ -34,8 +34,8 @@ public abstract record EncounterTrade(GameVersion Version) : IEncounterable, IMo public int EggLocation { get; init; } - public ushort TID { get; init; } - public ushort SID { get; init; } + public ushort TID16 { get; init; } + public ushort SID16 { get; init; } public Moveset Moves { get; init; } public IndividualValueSet IVs { get; init; } @@ -47,8 +47,8 @@ public abstract record EncounterTrade(GameVersion Version) : IEncounterable, IMo { init { - TID = (ushort) value; - SID = (ushort)(value >> 16); + TID16 = (ushort) value; + SID16 = (ushort)(value >> 16); } } @@ -97,8 +97,8 @@ public abstract record EncounterTrade(GameVersion Version) : IEncounterable, IMo pk.CurrentLevel = level; pk.Version = (int) version; - pk.TID = TID; - pk.SID = SID; + pk.TID16 = TID16; + pk.SID16 = SID16; pk.Ball = Ball; pk.OT_Friendship = pk.PersonalInfo.BaseFriendship; @@ -175,14 +175,14 @@ public abstract record EncounterTrade(GameVersion Version) : IEncounterable, IMo private void SetEggMetData(PKM pk, DateTime time) { pk.Egg_Location = EggLocation; - pk.EggMetDate = time; + pk.EggMetDate = DateOnly.FromDateTime(time); } private static void SetMetData(PKM pk, int level, int location, DateTime time) { pk.Met_Level = level; pk.Met_Location = location; - pk.MetDate = time; + pk.MetDate = DateOnly.FromDateTime(time); } public virtual bool IsMatchExact(PKM pk, EvoCriteria evo) @@ -195,9 +195,9 @@ public abstract record EncounterTrade(GameVersion Version) : IEncounterable, IMo if (!IsMatchNatureGenderShiny(pk)) return false; - if (TID != pk.TID) + if (TID16 != pk.TID16) return false; - if (SID != pk.SID) + if (SID16 != pk.SID16) return false; if (!IsMatchLevel(pk, evo)) diff --git a/PKHeX.Core/Legality/Encounters/EncounterTrade/EncounterTrade2.cs b/PKHeX.Core/Legality/Encounters/EncounterTrade/EncounterTrade2.cs index 02df84376..02faa80eb 100644 --- a/PKHeX.Core/Legality/Encounters/EncounterTrade/EncounterTrade2.cs +++ b/PKHeX.Core/Legality/Encounters/EncounterTrade/EncounterTrade2.cs @@ -14,14 +14,14 @@ public sealed record EncounterTrade2 : EncounterTradeGB public EncounterTrade2(ushort species, byte level, ushort tid) : base(species, level, GameVersion.GSC) { - TID = tid; + TID16 = tid; } public override bool IsMatchExact(PKM pk, EvoCriteria evo) { if (Level > pk.CurrentLevel) // minimum required level return false; - if (TID != pk.TID) + if (TID16 != pk.TID16) return false; if (pk.Format <= 2) @@ -30,7 +30,7 @@ public sealed record EncounterTrade2 : EncounterTradeGB return false; if (IVs.IsSpecified && !Legal.GetIsFixedIVSequenceValidNoRand(IVs, pk)) return false; - if (pk.Format == 2 && pk.Met_Location is not (0 or 126)) + if (pk is { Format: 2, Met_Location: not (0 or 126) }) return false; } diff --git a/PKHeX.Core/Legality/Encounters/EncounterTrade/EncounterTrade3.cs b/PKHeX.Core/Legality/Encounters/EncounterTrade/EncounterTrade3.cs index 43373d1d7..5c0fef1ac 100644 --- a/PKHeX.Core/Legality/Encounters/EncounterTrade/EncounterTrade3.cs +++ b/PKHeX.Core/Legality/Encounters/EncounterTrade/EncounterTrade3.cs @@ -1,4 +1,4 @@ -using System.Collections.Generic; +using System; namespace PKHeX.Core; @@ -26,7 +26,7 @@ public sealed record EncounterTrade3 : EncounterTrade, IContestStatsReadOnly public byte CNT_Tough { get; private init; } public byte CNT_Sheen { get; private init; } - public IReadOnlyList Contest + public ReadOnlySpan Contest { init { @@ -63,7 +63,7 @@ public sealed record EncounterTrade3 : EncounterTrade, IContestStatsReadOnly var pk3 = (PK3) pk; // Italian LG Jynx untranslated from English name - if (Species == (int)Core.Species.Jynx && pk3.Version == (int)GameVersion.LG && pk3.Language == (int)LanguageID.Italian) + if (Species == (int)Core.Species.Jynx && pk3 is { Version: (int)GameVersion.LG, Language: (int)LanguageID.Italian }) { pk3.OT_Name = GetOT((int)LanguageID.English); pk3.SetNickname(GetNickname((int)LanguageID.English)); diff --git a/PKHeX.Core/Legality/Encounters/EncounterTrade/EncounterTrade4.cs b/PKHeX.Core/Legality/Encounters/EncounterTrade/EncounterTrade4.cs index 68c84a609..33da7acae 100644 --- a/PKHeX.Core/Legality/Encounters/EncounterTrade/EncounterTrade4.cs +++ b/PKHeX.Core/Legality/Encounters/EncounterTrade/EncounterTrade4.cs @@ -147,9 +147,10 @@ public sealed record EncounterTrade4RanchGift : EncounterTrade4 /// Generation 4 Trade Encounter with a fixed location and version, as well as special details. /// /// -public sealed record EncounterTrade4RanchSpecial : EncounterTrade4 +public sealed record EncounterTrade4RanchSpecial : EncounterTrade4, IFatefulEncounterReadOnly { public override int Location => 3000; + public bool FatefulEncounter => true; public EncounterTrade4RanchSpecial(ushort species, byte level) : base(GameVersion.D) { diff --git a/PKHeX.Core/Legality/Encounters/EncounterTrade/EncounterTrade5.cs b/PKHeX.Core/Legality/Encounters/EncounterTrade/EncounterTrade5.cs index 56090da72..818e951d4 100644 --- a/PKHeX.Core/Legality/Encounters/EncounterTrade/EncounterTrade5.cs +++ b/PKHeX.Core/Legality/Encounters/EncounterTrade/EncounterTrade5.cs @@ -56,6 +56,6 @@ public sealed record EncounterTrade5PID(GameVersion Version, uint PID) : Encount public static bool IsValidMissingLanguage(PKM pk) { - return pk.Format == 5 && pk.BW; + return pk is { Context: EntityContext.Gen5, BW: true }; } } diff --git a/PKHeX.Core/Legality/Encounters/Generator/AbilityPermission.cs b/PKHeX.Core/Legality/Encounters/Generator/AbilityPermission.cs index a2a5139a0..06f0f0bac 100644 --- a/PKHeX.Core/Legality/Encounters/Generator/AbilityPermission.cs +++ b/PKHeX.Core/Legality/Encounters/Generator/AbilityPermission.cs @@ -1,4 +1,5 @@ -using System; +using System; +using static PKHeX.Core.AbilityPermission; namespace PKHeX.Core; @@ -15,9 +16,9 @@ public static class AbilityPermissionExtensions { public static int GetSingleValue(this AbilityPermission value) => value switch { - AbilityPermission.OnlyFirst => 0, - AbilityPermission.OnlySecond => 1, - AbilityPermission.OnlyHidden => 2, + OnlyFirst => 0, + OnlySecond => 1, + OnlyHidden => 2, _ => throw new ArgumentOutOfRangeException(nameof(value)), }; @@ -25,17 +26,17 @@ public static class AbilityPermissionExtensions { switch (value) { - case AbilityPermission.OnlyFirst: index = 0; return true; - case AbilityPermission.OnlySecond: index = 1; return true; - case AbilityPermission.OnlyHidden: index = 2; return true; + case OnlyFirst: index = 0; return true; + case OnlySecond: index = 1; return true; + case OnlyHidden: index = 2; return true; default: index = 0; return false; } } public static bool CanBeHidden(this AbilityPermission value) => value switch { - AbilityPermission.Any12H => true, - AbilityPermission.OnlyHidden => true, + Any12H => true, + OnlyHidden => true, _ => false, }; } diff --git a/PKHeX.Core/Legality/Encounters/Generator/ByGeneration/EncounterGenerator1.cs b/PKHeX.Core/Legality/Encounters/Generator/ByGeneration/EncounterGenerator1.cs new file mode 100644 index 000000000..cfe655b13 --- /dev/null +++ b/PKHeX.Core/Legality/Encounters/Generator/ByGeneration/EncounterGenerator1.cs @@ -0,0 +1,208 @@ +using System; +using System.Collections.Generic; + +using static PKHeX.Core.EncounterStateUtil; +using static PKHeX.Core.EncounterTypeGroup; +using static PKHeX.Core.EncounterMatchRating; + +namespace PKHeX.Core; + +public sealed class EncounterGenerator1 : IEncounterGenerator +{ + public static readonly EncounterGenerator1 Instance = new(); + + public IEnumerable GetPossible(PKM pk, EvoCriteria[] chain, GameVersion game, EncounterTypeGroup groups) + { + if (groups.HasFlag(Mystery)) + { + var table = GetGifts(); + foreach (var enc in GetPossibleGifts(chain, table)) + yield return enc; + } + if (groups.HasFlag(Trade)) + { + var table = GetTrade(game); + foreach (var enc in GetPossibleTrades(chain, table)) + yield return enc; + } + if (groups.HasFlag(Static)) + { + var table = GetStatic(game); + foreach (var enc in GetPossibleStatic(chain, table)) + yield return enc; + } + if (groups.HasFlag(Slot)) + { + var areas = GetAreas(game, pk.Japanese); + foreach (var area in GetPossibleSlots(chain, areas)) + yield return area; + } + } + + private static IEnumerable GetPossibleGifts(EvoCriteria[] chain, EncounterStatic1E[] table) + { + foreach (var enc in table) + { + foreach (var evo in chain) + { + if (evo.Species != enc.Species) + continue; + yield return enc; + break; + } + } + } + + private static IEnumerable GetPossibleTrades(EvoCriteria[] chain, EncounterTrade1[] table) + { + foreach (var enc in table) + { + foreach (var evo in chain) + { + if (evo.Species != enc.Species) + continue; + yield return enc; + break; + } + } + } + + private static IEnumerable GetPossibleStatic(EvoCriteria[] chain, EncounterStatic1[] table) + { + foreach (var enc in table) + { + foreach (var evo in chain) + { + if (evo.Species != enc.Species) + continue; + yield return enc; + break; + } + } + } + + private static IEnumerable GetPossibleSlots(EvoCriteria[] chain, EncounterArea1[] areas) + { + foreach (var area in areas) + { + foreach (var slot in area.Slots) + { + foreach (var evo in chain) + { + if (evo.Species != slot.Species) + continue; + yield return slot; + break; + } + } + } + } + + public IEnumerable GetEncounters(PKM pk, EvoCriteria[] chain, LegalInfo info) + { + throw new ArgumentException("Generator does not support direct calls to this method."); + } + + public IEnumerable GetEncounters(PKM pk, GameVersion game) + { + // Since encounter matching is super weak due to limited stored data in the structure + // Calculate all 3 at the same time and pick the best result (by species). + // Favor special event move gifts as Static Encounters when applicable + var chain = EncounterOrigin.GetOriginChain12(pk, game); + return GetEncounters(pk, chain, game); + } + + private IEnumerable GetEncounters(PKM pk, EvoCriteria[] chain, GameVersion game) + { + IEncounterable? deferred = null; + + foreach (var enc in GetTrade(game)) + { + if (!(enc.Version.Contains(game) || game.Contains(enc.Version))) + continue; + + foreach (var evo in chain) + { + if (evo.Species != enc.Species) + continue; + if (!enc.IsMatchExact(pk, evo)) + break; + + var match = enc.GetMatchRating(pk); + if (match != Match) + deferred = enc; + else + yield return enc; + break; + } + } + foreach (var enc in GetStatic(game)) + { + if (!(enc.Version.Contains(game) || game.Contains(enc.Version))) + continue; + + foreach (var evo in chain) + { + if (evo.Species != enc.Species) + continue; + if (enc.IsMatchExact(pk, evo)) + yield return enc; + break; + } + } + if (CanBeWildEncounter(pk)) + { + foreach (var area in GetAreas(game, pk.Japanese)) + { + var slots = area.GetMatchingSlots(pk, chain); + foreach (var slot in slots) + yield return slot; + } + } + foreach (var enc in GetGifts()) + { + if (!(enc.Version.Contains(game) || game.Contains(enc.Version))) + continue; + + foreach (var evo in chain) + { + if (evo.Species != enc.Species) + continue; + if (enc.IsMatchExact(pk, evo)) + yield return enc; + break; + } + } + + if (deferred != null) + yield return deferred; + } + + private static EncounterStatic1E[] GetGifts() + { + if (!ParseSettings.AllowGBCartEra) + return Encounters1.StaticEventsVC; + return Encounters1.StaticEventsGB; + } + + private static EncounterArea1[] GetAreas(GameVersion game, bool japanese) => game switch + { + GameVersion.RD => Encounters1.SlotsRD, + GameVersion.GN => Encounters1.SlotsGN, + GameVersion.BU => japanese ? Encounters1.SlotsBU : Array.Empty(), + GameVersion.YW => Encounters1.SlotsYW, + + _ when japanese => Encounters1.SlotsRGBY, + _ => Encounters1.SlotsRBY, + }; + + private static EncounterStatic1[] GetStatic(GameVersion game) => game switch + { + _ => Encounters1.StaticRBY, + }; + + private static EncounterTrade1[] GetTrade(GameVersion game) => game switch + { + _ => Encounters1.TradeGift_RBY, + }; +} diff --git a/PKHeX.Core/Legality/Encounters/Generator/ByGeneration/EncounterGenerator12.cs b/PKHeX.Core/Legality/Encounters/Generator/ByGeneration/EncounterGenerator12.cs deleted file mode 100644 index ff44de7d7..000000000 --- a/PKHeX.Core/Legality/Encounters/Generator/ByGeneration/EncounterGenerator12.cs +++ /dev/null @@ -1,174 +0,0 @@ -using System.Collections.Generic; - -using static PKHeX.Core.EncounterTradeGenerator; -using static PKHeX.Core.EncounterStaticGenerator; -using static PKHeX.Core.EncounterSlotGenerator; -using static PKHeX.Core.EncounterEggGenerator2; -using static PKHeX.Core.EncounterMatchRating; - -namespace PKHeX.Core; - -/// -/// This class is essentially a sub-class of specialized for Gen1 & Gen2 encounters. -/// -internal static class EncounterGenerator12 -{ - internal static IEnumerable GetEncounters12(PKM pk, LegalInfo info) - { - foreach (var z in GenerateFilteredEncounters12(pk)) - { - info.StoreMetadata(z.Generation); - yield return z; - } - } - - private static IEnumerable GenerateRawEncounters12(PKM pk, GameVersion game) - { - // Since encounter matching is super weak due to limited stored data in the structure - // Calculate all 3 at the same time and pick the best result (by species). - // Favor special event move gifts as Static Encounters when applicable - var chain = EncounterOrigin.GetOriginChain12(pk, game); - - IEncounterable? deferred = null; - foreach (var t in GetValidEncounterTradesVC(pk, chain, game)) - { - // Gen2 trades are strictly matched (OT/Nick), while Gen1 trades allow for deferral (shrug). - if (t is EncounterTrade1 t1 && t1.GetMatchRating(pk) != Match) - { - deferred ??= t; - continue; - } - yield return t; - } - foreach (var s in GetValidStaticEncounter(pk, chain, game)) - { - yield return s; - } - foreach (var e in GetValidWildEncounters12(pk, chain, game)) - { - yield return e; - } - if (game != GameVersion.RBY) - { - foreach (var e in GenerateEggs(pk, chain)) - yield return e; - } - - foreach (var s in GenerateGBEvents(pk, chain, game)) - { - yield return s; - } - - if (deferred != null) - yield return deferred; - } - - private static IEnumerable GenerateGBEvents(PKM pk, EvoCriteria[] chain, GameVersion game) - { - if (pk.Korean) // only GS; no events - yield break; - - foreach (var e in GetValidGBGifts(pk, chain, game)) - { - foreach (var evo in chain) - { - if (e.IsMatchExact(pk, evo)) - yield return e; - } - } - } - - private static IEnumerable GenerateFilteredEncounters12(PKM pk) - { - // If the current data indicates that it must have originated from Crystal, only yield encounter data from Crystal. - bool crystal = (pk is ICaughtData2 {CaughtData: not 0}) || (pk.Format >= 7 && pk.OT_Gender == 1); - if (crystal) - return GenerateRawEncounters12(pk, GameVersion.C); - - var visited = GBRestrictions.GetTradebackStatusInitial(pk); - switch (visited) - { - case PotentialGBOrigin.Gen1Only: - return GenerateRawEncounters12(pk, GameVersion.RBY); - case PotentialGBOrigin.Gen2Only: - return GenerateRawEncounters12(pk, GameVersion.GSC); - default: - if (pk.Korean) - return GenerateFilteredEncounters12BothKorean(pk); - return GenerateFilteredEncounters12Both(pk); - } - } - - private static IEnumerable GenerateFilteredEncounters12BothKorean(PKM pk) - { - // Korean origin PK1/PK2 can only originate from GS, but since we're nice we'll defer & yield matches from other games. - // Yield GS first, then Crystal, then RBY. Anything other than GS will be flagged by later checks. - - var deferred = new List(); - var get2 = GenerateRawEncounters12(pk, GameVersion.GSC); - foreach (var enc in get2) - { - if (enc.Version == GameVersion.C) - deferred.Add(enc); - else - yield return enc; - } - - foreach (var enc in deferred) - yield return enc; - - var get1 = GenerateRawEncounters12(pk, GameVersion.RBY); - foreach (var enc in get1) - yield return enc; - } - - private static IEnumerable GenerateFilteredEncounters12Both(PKM pk) - { - // Iterate over both games, consuming from one list at a time until the other list has higher priority encounters - // Buffer the encounters so that we can consume each iterator separately - var get1 = GenerateRawEncounters12(pk, GameVersion.RBY); - var get2 = GenerateRawEncounters12(pk, GameVersion.GSC); - using var g1i = new PeekEnumerator(get1); - using var g2i = new PeekEnumerator(get2); - while (g2i.PeekIsNext() || g1i.PeekIsNext()) - { - var iter = PickPreferredIterator(pk, g1i, g2i); - yield return iter.Current; - iter.MoveNext(); - } - } - - private static PeekEnumerator PickPreferredIterator(PKM pk, PeekEnumerator g1i, PeekEnumerator g2i) - { - if (!g1i.PeekIsNext()) - return g2i; - if (!g2i.PeekIsNext()) - return g1i; - var p1 = GetGBEncounterPriority(pk, g1i.Current); - var p2 = GetGBEncounterPriority(pk, g2i.Current); - return p1 > p2 ? g1i : g2i; - } - - private static GBEncounterPriority GetGBEncounterPriority(PKM pk, IEncounterTemplate enc) => enc switch - { - EncounterTrade1 t1 when t1.GetMatchRating(pk) != Match => GBEncounterPriority.Least, - EncounterTrade1 => GBEncounterPriority.TradeEncounterG1, - EncounterTrade2 => GBEncounterPriority.TradeEncounterG2, - EncounterSlot1 or EncounterSlot2 => GBEncounterPriority.WildEncounter, - EncounterEgg => GBEncounterPriority.EggEncounter, - _ => GBEncounterPriority.StaticEncounter, - }; - - /// - /// Generation 1/2 Encounter Data type, which serves as a 'best match' priority rating when returning from a list. - /// - private enum GBEncounterPriority - { - Least, - EggEncounter, - WildEncounter, - StaticEncounter, - TradeEncounterG1, - TradeEncounterG2, - } -} diff --git a/PKHeX.Core/Legality/Encounters/Generator/ByGeneration/EncounterGenerator2.cs b/PKHeX.Core/Legality/Encounters/Generator/ByGeneration/EncounterGenerator2.cs new file mode 100644 index 000000000..fb5e5c7ea --- /dev/null +++ b/PKHeX.Core/Legality/Encounters/Generator/ByGeneration/EncounterGenerator2.cs @@ -0,0 +1,300 @@ +using System; +using System.Collections.Generic; + +using static PKHeX.Core.EncounterStateUtil; +using static PKHeX.Core.EncounterTypeGroup; +using static PKHeX.Core.EncounterMatchRating; + +namespace PKHeX.Core; + +public sealed class EncounterGenerator2 : IEncounterGenerator +{ + public static readonly EncounterGenerator2 Instance = new(); + + public IEnumerable GetPossible(PKM pk, EvoCriteria[] chain, GameVersion game, EncounterTypeGroup groups) + { + bool korean = pk.Korean; + if (groups.HasFlag(Mystery)) + { + var table = GetGifts(korean); + foreach (var enc in GetPossibleGifts(chain, table)) + yield return enc; + } + if (groups.HasFlag(Trade)) + { + var table = GetTrade(game); + foreach (var enc in GetPossibleTrades(chain, table)) + yield return enc; + } + if (groups.HasFlag(Egg)) + { + var eggs = GetEggs(pk, chain); + foreach (var egg in eggs) + yield return egg; + } + if (groups.HasFlag(Static)) + { + var table = GetStatic(game, korean); + foreach (var enc in GetPossibleStatic(chain, table)) + yield return enc; + } + if (groups.HasFlag(Slot)) + { + var areas = GetAreas(game, korean); + foreach (var enc in GetPossibleSlots(chain, areas, pk)) + yield return enc; + } + } + + private static IEnumerable GetPossibleGifts(EvoCriteria[] chain, EncounterStatic2E[] table) + { + foreach (var enc in table) + { + foreach (var evo in chain) + { + if (evo.Species != enc.Species) + continue; + yield return enc; + break; + } + } + } + + private static IEnumerable GetPossibleTrades(EvoCriteria[] chain, EncounterTrade2[] table) + { + foreach (var enc in table) + { + foreach (var evo in chain) + { + if (evo.Species != enc.Species) + continue; + yield return enc; + break; + } + } + } + + private static IEnumerable GetPossibleStatic(EvoCriteria[] chain, EncounterStatic2[] table) + { + foreach (var enc in table) + { + foreach (var evo in chain) + { + if (evo.Species != enc.Species) + continue; + yield return enc; + break; + } + } + } + + private static IEnumerable GetPossibleSlots(EvoCriteria[] chain, EncounterArea2[] areas, ITrainerID16 pk) + { + foreach (var area in areas) + { + foreach (var slot in area.Slots) + { + foreach (var evo in chain) + { + if (evo.Species != slot.Species) + continue; + + if (slot.IsHeadbutt && !slot.IsTreeAvailable(pk.TID16)) + break; + yield return slot; + break; + } + } + } + } + + public IEnumerable GetEncounters(PKM pk, EvoCriteria[] chain, LegalInfo info) + { + throw new ArgumentException("Generator does not support direct calls to this method."); + } + + public IEnumerable GetEncounters(PKM pk, GameVersion game) + { + var chain = EncounterOrigin.GetOriginChain12(pk, game); + return GetEncounters(pk, chain, game); + } + + private IEnumerable GetEncounters(PKM pk, EvoCriteria[] chain, GameVersion game) + { + // Since encounter matching is super weak due to limited stored data in the structure + // Calculate all 3 at the same time and pick the best result (by species). + // Favor special event move gifts as Static Encounters when applicable + IEncounterable? deferred = null; + + bool korean = pk.Korean; + foreach (var enc in GetTrade(game)) + { + if (!(enc.Version.Contains(game) || game.Contains(enc.Version))) + continue; + + foreach (var evo in chain) + { + if (evo.Species != enc.Species) + continue; + if (!enc.IsMatchExact(pk, evo)) + break; + + var match = enc.GetMatchRating(pk); + if (match != Match) + deferred = enc; + else + yield return enc; + break; + } + } + foreach (var enc in GetStatic(game, korean)) + { + if (!(enc.Version.Contains(game) || game.Contains(enc.Version))) + continue; + + foreach (var evo in chain) + { + if (evo.Species != enc.Species) + continue; + if (enc.IsMatchExact(pk, evo)) + yield return enc; + break; + } + } + if (CanBeWildEncounter(pk)) + { + foreach (var area in GetAreas(game, korean)) + { + var slots = area.GetMatchingSlots(pk, chain); + foreach (var slot in slots) + yield return slot; + } + } + if (GetCanBeEgg(pk)) + { + foreach (var e in GetEggs(pk, chain)) + yield return e; + } + foreach (var enc in GetGifts(korean)) + { + if (!(enc.Version.Contains(game) || game.Contains(enc.Version))) + continue; + + foreach (var evo in chain) + { + if (evo.Species != enc.Species) + continue; + if (enc.IsMatchExact(pk, evo)) + yield return enc; + break; + } + } + + if (deferred != null) + yield return deferred; + } + + private static EncounterStatic2E[] GetGifts(bool korean) + { + if (korean) + return Array.Empty(); + if (!ParseSettings.AllowGBCartEra) + return Encounters2.StaticEventsVC; + return Encounters2.StaticEventsGB; + } + + private static EncounterArea2[] GetAreas(GameVersion game, bool korean) => game switch + { + GameVersion.GD => Encounters2.SlotsGD, + GameVersion.SI => Encounters2.SlotsSV, + GameVersion.C => !korean ? Encounters2.SlotsC : Array.Empty(), + GameVersion.GS => Encounters2.SlotsGS, + GameVersion.GSC => !korean ? Encounters2.SlotsGSC : Encounters2.SlotsGS, + _ => throw new ArgumentOutOfRangeException(nameof(game), game, null), + }; + + private static EncounterStatic2[] GetStatic(GameVersion game, bool korean) => game switch + { + GameVersion.GD => Encounters2.StaticGS, + GameVersion.SI => Encounters2.StaticGS, + GameVersion.C => !korean ? Encounters2.StaticC : Array.Empty(), + GameVersion.GS => Encounters2.StaticGS, + GameVersion.GSC => !korean ? Encounters2.StaticGSC : Encounters2.StaticGS, + _ => throw new ArgumentOutOfRangeException(nameof(game), game, null), + }; + + private static EncounterTrade2[] GetTrade(GameVersion game) => game switch + { + _ => Encounters2.TradeGift_GSC, + }; + + private const int Generation = 2; + private const EntityContext Context = EntityContext.Gen2; + private const byte EggLevel = 5; + + private static IEnumerable GetEggs(PKM pk, EvoCriteria[] chain) + { + var devolved = chain[^1]; + // Ensure most devolved species is the same as the egg species. + var (species, form) = GetBaby(devolved); + if (species != devolved.Species) + yield break; // no split-breed. + + // Sanity Check 1 + if (!Breeding.CanHatchAsEgg(species)) + yield break; + // Sanity Check 3 + if (!PersonalTable.C.IsPresentInGame(species, form)) + yield break; + + // Gen2 was before split-breed species existed; try to ensure that the egg we try and match to can actually originate in the game. + // Species must be < 251 + // Form must be 0 (Unown cannot breed). + if (form != 0) + yield break; // Forms don't exist in Gen2, besides Unown (which can't breed). Nothing can form-change. + + // Depending on the game it was hatched (GS vs C), met data will be present. + // Since met data can't be used to infer which game it was created on, we yield both if possible. + var egg = CreateEggEncounter(species, 0, GameVersion.GS); + yield return egg; + if (ParseSettings.AllowGen2Crystal(pk)) + yield return egg with { Version = GameVersion.C }; + } + + private static EncounterEgg CreateEggEncounter(ushort species, byte form, GameVersion version) + { + if (FormInfo.IsBattleOnlyForm(species, form, Generation)) + form = FormInfo.GetOutOfBattleForm(species, form, Generation); + return new EncounterEgg(species, form, EggLevel, Generation, version, Context); + } + + private static (ushort Species, byte Form) GetBaby(EvoCriteria lowest) + { + return EvolutionTree.Evolves2.GetBaseSpeciesForm(lowest.Species, lowest.Form); + } + + private static bool GetCanBeEgg(PKM pk) + { + if (pk.Format == 1 && !ParseSettings.AllowGen1Tradeback) + return false; + + if (pk.CurrentLevel < EggLevel) + return false; + + var format = pk.Format; + if (pk.IsEgg) + return format == 2; + + var metLevel = pk.Met_Level; + if (format > 2) + return metLevel >= EggLevel; + + // 2->1->2 clears met info + return metLevel switch + { + 0 => pk.Met_Location == 0, + 1 => true, // Met location of 0 is valid -- second floor of every Pokémon Center + _ => false, + }; + } +} diff --git a/PKHeX.Core/Legality/Encounters/Generator/ByGeneration/EncounterGenerator3.cs b/PKHeX.Core/Legality/Encounters/Generator/ByGeneration/EncounterGenerator3.cs index 9494e5d01..dcdd6cb0e 100644 --- a/PKHeX.Core/Legality/Encounters/Generator/ByGeneration/EncounterGenerator3.cs +++ b/PKHeX.Core/Legality/Encounters/Generator/ByGeneration/EncounterGenerator3.cs @@ -2,149 +2,189 @@ using System; using System.Collections.Generic; using System.Linq; -using static PKHeX.Core.MysteryGiftGenerator; -using static PKHeX.Core.EncounterTradeGenerator; -using static PKHeX.Core.EncounterSlotGenerator; -using static PKHeX.Core.EncounterStaticGenerator; -using static PKHeX.Core.EncounterEggGenerator; +using static PKHeX.Core.EncounterStateUtil; +using static PKHeX.Core.EncounterTypeGroup; using static PKHeX.Core.EncounterMatchRating; namespace PKHeX.Core; -public static class EncounterGenerator3 +public sealed class EncounterGenerator3 : IEncounterGenerator { - public static IEnumerable GetEncounters(PKM pk, LegalInfo info) - { - if (pk.Version == (int) GameVersion.CXD) - return GetEncounters3CXD(pk, info); - return GetEncounters3(pk, info); - } + public static readonly EncounterGenerator3 Instance = new(); - private static IEnumerable GetEncounters3(PKM pk, LegalInfo info) + public IEnumerable GetPossible(PKM _, EvoCriteria[] chain, GameVersion game, EncounterTypeGroup groups) { - info.PIDIV = MethodFinder.Analyze(pk); - IEncounterable? Partial = null; - - foreach (var z in GenerateRawEncounters3(pk, info)) + if (groups.HasFlag(Mystery)) { - if (info.PIDIV.Type.IsCompatible3(z, pk)) - yield return z; - else - Partial ??= z; + var table = EncountersWC3.Encounter_WC3; + foreach (var enc in GetPossibleGifts(chain, table, game)) + yield return enc; } - if (Partial == null) - yield break; - info.PIDIVMatches = false; - yield return Partial; + if (groups.HasFlag(Trade)) + { + var table = GetTrades(game); + foreach (var enc in GetPossibleTrades(chain, table, game)) + yield return enc; + } + if (groups.HasFlag(Egg)) + { + var eggs = GetEggs(chain, game); + foreach (var egg in eggs) + yield return egg; + } + if (groups.HasFlag(Slot)) + { + var areas = GetAreas(game); + foreach (var enc in GetPossibleAreas(chain, areas)) + yield return enc; + } + if (groups.HasFlag(Static)) + { + var table = GetStatic(game); + foreach (var enc in GetPossibleStatic(chain, table)) + yield return enc; + } } - private static IEnumerable GetEncounters3CXD(PKM pk, LegalInfo info) + private static IEnumerable GetPossibleGifts(EvoCriteria[] chain, WC3[] table, GameVersion game) { - info.PIDIV = MethodFinder.Analyze(pk); - IEncounterable? Partial = null; - foreach (var z in GenerateRawEncounters3CXD(pk)) + foreach (var enc in table) { - if (z is EncounterSlot3PokeSpot w) + if (!enc.Version.Contains(game)) + continue; + if (enc.NotDistributed) + continue; + + foreach (var evo in chain) { - var pidiv = MethodFinder.GetPokeSpotSeedFirst(pk, w.SlotNumber); - if (pidiv.Type == PIDType.PokeSpot) - info.PIDIV = pidiv; - } - else if (z is EncounterStaticShadow s) - { - bool valid = GetIsShadowLockValid(pk, info, s); - if (!valid) - { - Partial ??= s; + if (evo.Species != enc.Species) continue; + yield return enc; + break; + } + } + } + + private static IEnumerable GetPossibleTrades(EvoCriteria[] chain, EncounterTrade3[] table, + GameVersion game) + { + foreach (var enc in table) + { + if (!enc.Version.Contains(game)) + continue; + + foreach (var evo in chain) + { + if (evo.Species != enc.Species) + continue; + yield return enc; + break; + } + } + } + + private static IEnumerable GetPossibleAreas(EvoCriteria[] chain, EncounterArea3[] areas) + { + foreach (var area in areas) + { + foreach (var slot in area.Slots) + { + foreach (var evo in chain) + { + if (evo.Species != slot.Species) + continue; + yield return slot; + break; } } + } + } + private static IEnumerable GetPossibleStatic(EvoCriteria[] chain, EncounterStatic3[] table) + { + foreach (var enc in table) + { + foreach (var evo in chain) + { + if (evo.Species != enc.Species) + continue; + yield return enc; + break; + } + } + } + + public IEnumerable GetEncounters(PKM pk, LegalInfo info) + { + var chain = EncounterOrigin.GetOriginChain(pk); + return GetEncounters(pk, chain, info); + } + + public IEnumerable GetEncounters(PKM pk, EvoCriteria[] chain, LegalInfo info) + { + info.PIDIV = MethodFinder.Analyze(pk); + IEncounterable? partial = null; + + foreach (var z in GetEncountersInner(pk, chain, info)) + { if (info.PIDIV.Type.IsCompatible3(z, pk)) yield return z; else - Partial ??= z; + partial ??= z; } - if (Partial == null) + if (partial == null) yield break; info.PIDIVMatches = false; - yield return Partial; + yield return partial; } - private static IEnumerable GenerateRawEncounters3CXD(PKM pk) + private static IEnumerable GetEncountersInner(PKM pk, EvoCriteria[] chain, LegalInfo info) { - var chain = EncounterOrigin.GetOriginChain(pk); - var game = (GameVersion)pk.Version; + // Mystery Gifts - foreach (var z in GetValidGifts(pk, chain, game)) + foreach (var z in EncountersWC3.Encounter_WC3) { - // Don't bother deferring matches. - var match = z.GetMatchRating(pk); - if (match != PartialMatch) - yield return z; - } - - // Trades - foreach (var z in GetValidEncounterTrades(pk, chain, game)) - { - // Don't bother deferring matches. - var match = z.GetMatchRating(pk); - if (match != PartialMatch) - yield return z; - } - - IEncounterable? partial = null; - - // Static Encounter - foreach (var z in GetValidStaticEncounter(pk, chain, game)) - { - var match = z.GetMatchRating(pk); - if (match == PartialMatch) - partial ??= z; - else - yield return z; - } - - // Encounter Slots - foreach (var z in GetValidWildEncounters(pk, chain, game)) - { - var match = z.GetMatchRating(pk); - if (match == PartialMatch) - { - partial ??= z; + if (!z.Version.Contains(game)) continue; + + foreach (var evo in chain) + { + if (evo.Species != z.Species) + continue; + if (!z.IsMatchExact(pk, evo)) + break; + + // Don't bother deferring matches. + var match = z.GetMatchRating(pk); + if (match != PartialMatch) + yield return z; + break; } - yield return z; - } - - if (partial is not null) - yield return partial; - } - - private static IEnumerable GenerateRawEncounters3(PKM pk, LegalInfo info) - { - var chain = EncounterOrigin.GetOriginChain(pk); - var game = (GameVersion)pk.Version; - - // Mystery Gifts - foreach (var z in GetValidGifts(pk, chain, game)) - { - // Don't bother deferring matches. - var match = z.GetMatchRating(pk); - if (match != PartialMatch) - yield return z; } // Trades - foreach (var z in GetValidEncounterTrades(pk, chain, game)) + var trades = GetTrades(game); + foreach (var z in trades) { - // Don't bother deferring matches. - var match = z.GetMatchRating(pk); - if (match != PartialMatch) - yield return z; + if (!z.Version.Contains(game)) + continue; + + foreach (var evo in chain) + { + if (evo.Species != z.Species) + continue; + if (!z.IsMatchExact(pk, evo)) + break; + + // Don't bother deferring matches. + var match = z.GetMatchRating(pk); + if (match != PartialMatch) + yield return z; + break; + } } IEncounterable? deferred = null; @@ -152,93 +192,204 @@ public static class EncounterGenerator3 // Static Encounter // Defer everything if Safari Ball - bool safari = pk.Ball == 0x05; // never static encounters + bool safari = pk.Ball == (byte)Ball.Safari; // never static encounters if (!safari) { - foreach (var z in GetValidStaticEncounter(pk, chain, game)) + var table = GetStatic(game); + foreach (var z in table) { - var match = z.GetMatchRating(pk); - if (match == PartialMatch) - partial ??= z; - else - yield return z; + if (!z.Version.Contains(game)) + continue; + + foreach (var evo in chain) + { + if (evo.Species != z.Species) + continue; + if (!z.IsMatchExact(pk, evo)) + break; + + var match = z.GetMatchRating(pk); + if (match == PartialMatch) + partial ??= z; + else + yield return z; + break; + } } } // Encounter Slots - var slots = FrameFinder.GetFrames(info.PIDIV, pk).ToList(); - foreach (var z in GetValidWildEncounters(pk, chain, game)) + List? wildFrames = null; + if (CanBeWildEncounter(pk)) { - var match = z.GetMatchRating(pk); - if (match == PartialMatch) + wildFrames = AnalyzeFrames(pk, info); + var areas = GetAreas(game); + foreach (var area in areas) { - partial ??= z; - continue; + var all = area.GetMatchingSlots(pk, chain); + foreach (var z in all) + { + var match = z.GetMatchRating(pk); + if (match == PartialMatch) + { + partial ??= z; + continue; + } + + var frame = wildFrames.Find(s => s.IsSlotCompatibile(z, pk)); + if (frame == null) + { + deferred ??= z; + continue; + } + yield return z; + } } - var frame = slots.Find(s => s.IsSlotCompatibile((EncounterSlot3)z, pk)); - if (frame == null) - { - deferred ??= z; - continue; - } + info.FrameMatches = false; + if (deferred is EncounterSlot3 x) + yield return x; + } + + // Due to the lack of Egg Met Location, eggs can be confused with Slots. Yield them now. + var eggs = GetEggs(chain, game); + foreach (var z in eggs) yield return z; - } - - info.FrameMatches = false; - if (deferred is EncounterSlot3 x) - yield return x; - - if (pk.Version != (int)GameVersion.CXD) // no eggs in C/XD - { - foreach (var z in GenerateEggs(pk, 3)) - yield return z; - } if (partial is EncounterSlot3 y) { - var frame = slots.Find(s => s.IsSlotCompatibile(y, pk)); + wildFrames ??= AnalyzeFrames(pk, info); + var frame = wildFrames.Find(s => s.IsSlotCompatibile(y, pk)); info.FrameMatches = frame != null; yield return y; } - // do static encounters if they were deferred to end, spit out any possible encounters for invalid pk + // Do static encounters if they were deferred to end, spit out any possible encounters for invalid pk if (!safari) yield break; partial = null; - foreach (var z in GetValidStaticEncounter(pk, chain, game)) + var encStatic = GetStatic(game); + foreach (var z in encStatic) { - var match = z.GetMatchRating(pk); - if (match == PartialMatch) - partial ??= z; - else - yield return z; + if (!z.Version.Contains(game)) + continue; + + foreach (var evo in chain) + { + if (evo.Species != z.Species) + continue; + if (!z.IsMatchExact(pk, evo)) + break; + + var match = z.GetMatchRating(pk); + if (match == PartialMatch) + partial ??= z; + else + yield return z; + break; + } } if (partial is not null) yield return partial; } - private static bool GetIsShadowLockValid(PKM pk, LegalInfo info, EncounterStaticShadow s) + private static List AnalyzeFrames(PKM pk, LegalInfo info) { - if (!s.EReader) - return LockFinder.IsAllShadowLockValid(s, info.PIDIV, pk); + return FrameFinder.GetFrames(info.PIDIV, pk).ToList(); + } - // E-Reader have fixed IVs, and aren't recognized as CXD (no PID-IV correlation). - Span seeds = stackalloc uint[4]; - var count = XDRNG.GetSeeds(seeds, pk.EncryptionConstant); - var xdc = seeds[..count]; - foreach (var seed in xdc) + private static EncounterStatic3[] GetStatic(GameVersion gameSource) => gameSource switch + { + GameVersion.R => Encounters3RSE.StaticR, + GameVersion.S => Encounters3RSE.StaticS, + GameVersion.E => Encounters3RSE.StaticE, + GameVersion.FR => Encounters3FRLG.StaticFR, + GameVersion.LG => Encounters3FRLG.StaticLG, + _ => throw new ArgumentOutOfRangeException(nameof(gameSource), gameSource, null), + }; + + private static EncounterArea3[] GetAreas(GameVersion gameSource) => gameSource switch + { + GameVersion.R => Encounters3RSE.SlotsR, + GameVersion.S => Encounters3RSE.SlotsS, + GameVersion.E => Encounters3RSE.SlotsE, + GameVersion.FR => Encounters3FRLG.SlotsFR, + GameVersion.LG => Encounters3FRLG.SlotsLG, + _ => throw new ArgumentOutOfRangeException(nameof(gameSource), gameSource, null), + }; + + private static EncounterTrade3[] GetTrades(GameVersion gameSource) => gameSource switch + { + GameVersion.R => Encounters3RSE.TradeGift_RSE, + GameVersion.S => Encounters3RSE.TradeGift_RSE, + GameVersion.E => Encounters3RSE.TradeGift_RSE, + GameVersion.FR => Encounters3FRLG.TradeGift_FRLG, + GameVersion.LG => Encounters3FRLG.TradeGift_FRLG, + _ => throw new ArgumentOutOfRangeException(nameof(gameSource), gameSource, null), + }; + + private const int Generation = 3; + private const EntityContext Context = EntityContext.Gen3; + private const byte EggLevel = 5; + + private static IEnumerable GetEggs(EvoCriteria[] chain, GameVersion version) + { + var devolved = chain[^1]; + + // Ensure most devolved species is the same as the egg species. + var (species, form) = GetBaby(devolved); + if (species != devolved.Species && !IsValidBabySpecies(devolved.Species)) + yield break; // no split-breed. + + // Sanity Check 1 + if (!Breeding.CanHatchAsEgg(species)) + yield break; + // Sanity Check 2 + if (!Breeding.CanHatchAsEgg(species, form, Context)) + yield break; + // Sanity Check 3 + if (!PersonalTable.E.IsPresentInGame(species, form)) + yield break; + + yield return CreateEggEncounter(species, form, version); + // Version is not updated when hatching an Egg in Gen3. Version is a clear indicator of the game it originated on. + + // Check for split-breed + if (species == devolved.Species) { - var pidiv = new PIDIV(PIDType.CXD, XDRNG.Next4(seed)); - if (!LockFinder.IsAllShadowLockValid(s, pidiv, pk)) - continue; - info.PIDIV = pidiv; - return true; + if (chain.Length < 2) + yield break; // no split-breed + devolved = chain[^2]; } + var splitSet = Breeding.GetSplitBreedGeneration(Generation); + if (splitSet is null) + yield break; // Shouldn't happen. + if (!splitSet.Contains(devolved.Species)) + yield break; - return false; + species = devolved.Species; + form = devolved.Form; + yield return CreateEggEncounter(species, form, version); + } + + private static bool IsValidBabySpecies(ushort species) + { + var split = Breeding.GetSplitBreedGeneration(Generation); + return split is not null && split.Contains(species); + } + + private static EncounterEgg CreateEggEncounter(ushort species, byte form, GameVersion version) + { + if (FormInfo.IsBattleOnlyForm(species, form, Generation) || species is (int)Species.Castform) + form = FormInfo.GetOutOfBattleForm(species, form, Generation); + return new EncounterEgg(species, form, EggLevel, Generation, version, Context); + } + + private static (ushort Species, byte Form) GetBaby(EvoCriteria lowest) + { + return EvolutionTree.Evolves3.GetBaseSpeciesForm(lowest.Species, lowest.Form); } } diff --git a/PKHeX.Core/Legality/Encounters/Generator/ByGeneration/EncounterGenerator3GC.cs b/PKHeX.Core/Legality/Encounters/Generator/ByGeneration/EncounterGenerator3GC.cs new file mode 100644 index 000000000..d19e7cda1 --- /dev/null +++ b/PKHeX.Core/Legality/Encounters/Generator/ByGeneration/EncounterGenerator3GC.cs @@ -0,0 +1,202 @@ +using System; +using System.Collections.Generic; + +using static PKHeX.Core.EncounterStateUtil; +using static PKHeX.Core.EncounterTypeGroup; +using static PKHeX.Core.EncounterMatchRating; + +namespace PKHeX.Core; + +public sealed class EncounterGenerator3GC : IEncounterGenerator +{ + public static readonly EncounterGenerator3GC Instance = new(); + + public IEnumerable GetPossible(PKM pk, EvoCriteria[] chain, GameVersion game, EncounterTypeGroup groups) + { + if (groups.HasFlag(Mystery)) + { + var table = EncountersWC3.Encounter_WC3CXD; + foreach (var enc in GetPossible(chain, table)) + yield return enc; + } + if (groups.HasFlag(Slot)) + { + var areas = Encounters3XD.SlotsXD; + foreach (var enc in GetPossibleSlots(chain, areas)) + yield return enc; + } + if (groups.HasFlag(Static)) + { + foreach (var enc in GetPossible(chain, Encounters3XD.Encounter_CXDShadow)) + yield return enc; + foreach (var enc in GetPossible(chain, Encounters3XD.Encounter_CXDGift)) + yield return enc; + } + } + + private static IEnumerable GetPossibleSlots(EvoCriteria[] chain, EncounterArea3XD[] areas) + { + foreach (var area in areas) + { + foreach (var slot in area.Slots) + { + foreach (var evo in chain) + { + if (evo.Species != slot.Species) + continue; + yield return slot; + break; + } + } + } + } + + private static IEnumerable GetPossible(EvoCriteria[] chain, T[] table) where T : class, IEncounterable + { + foreach (var enc in table) + { + foreach (var evo in chain) + { + if (evo.Species != enc.Species) + continue; + yield return enc; + break; + } + } + } + + public IEnumerable GetEncounters(PKM pk, LegalInfo info) + { + var chain = EncounterOrigin.GetOriginChain(pk); + return GetEncounters(pk, chain, info); + } + + public IEnumerable GetEncounters(PKM pk, EvoCriteria[] chain, LegalInfo info) + { + IEncounterable? partial = null; + info.PIDIV = MethodFinder.Analyze(pk); + foreach (var z in IterateInner(pk, chain)) + { + if (z is EncounterSlot3PokeSpot w) + { + var pidiv = MethodFinder.GetPokeSpotSeedFirst(pk, w.SlotNumber); + if (pidiv.Type == PIDType.PokeSpot) + info.PIDIV = pidiv; + } + else if (z is EncounterStaticShadow s) + { + bool valid = GetIsShadowLockValid(pk, info, s); + if (!valid) + { + partial ??= s; + continue; + } + } + + if (info.PIDIV.Type.IsCompatible3(z, pk)) + yield return z; + else + partial ??= z; + } + + if (partial == null) + yield break; + + info.PIDIVMatches = false; + yield return partial; + } + + private static IEnumerable IterateInner(PKM pk, EvoCriteria[] chain) + { + IEncounterable? partial = null; + foreach (var enc in EncountersWC3.Encounter_WC3CXD) + { + foreach (var evo in chain) + { + if (evo.Species != enc.Species) + continue; + if (!enc.IsMatchExact(pk, evo)) + break; + + // Don't bother deferring matches. + var match = enc.GetMatchRating(pk); + if (match != PartialMatch) + yield return enc; + break; + } + } + foreach (var enc in Encounters3XD.Encounter_CXDShadow) + { + foreach (var evo in chain) + { + if (evo.Species != enc.Species) + continue; + if (!enc.IsMatchExact(pk, evo)) + break; + + var match = enc.GetMatchRating(pk); + if (match == PartialMatch) + partial ??= enc; + else + yield return enc; + break; + } + } + foreach (var enc in Encounters3XD.Encounter_CXDGift) + { + foreach (var evo in chain) + { + if (evo.Species != enc.Species) + continue; + if (!enc.IsMatchExact(pk, evo)) + break; + + var match = enc.GetMatchRating(pk); + if (match == PartialMatch) + partial ??= enc; + else + yield return enc; + break; + } + } + if (CanBeWildEncounter(pk)) + { + foreach (var area in Encounters3XD.SlotsXD) + { + var slots = area.GetMatchingSlots(pk, chain); + foreach (var slot in slots) + { + var match = slot.GetMatchRating(pk); + if (match == PartialMatch) + partial ??= slot; + else + yield return slot; + } + } + } + + if (partial != null) + yield return partial; + } + + private static bool GetIsShadowLockValid(PKM pk, LegalInfo info, EncounterStaticShadow s) + { + if (!s.EReader) + return LockFinder.IsAllShadowLockValid(s, info.PIDIV, pk); + + // E-Reader have fixed IVs, and aren't recognized as CXD (no PID-IV correlation). + Span seeds = stackalloc uint[XDRNG.MaxCountSeedsPID]; + var count = XDRNG.GetSeeds(seeds, pk.EncryptionConstant); + var xdc = seeds[..count]; + foreach (var seed in xdc) + { + var pidiv = new PIDIV(PIDType.CXD, XDRNG.Next4(seed)); + if (!LockFinder.IsAllShadowLockValid(s, pidiv, pk)) + continue; + info.PIDIV = pidiv; + return true; + } + + return false; + } +} diff --git a/PKHeX.Core/Legality/Encounters/Generator/ByGeneration/EncounterGenerator4.cs b/PKHeX.Core/Legality/Encounters/Generator/ByGeneration/EncounterGenerator4.cs index 501fe6564..1ee18730e 100644 --- a/PKHeX.Core/Legality/Encounters/Generator/ByGeneration/EncounterGenerator4.cs +++ b/PKHeX.Core/Legality/Encounters/Generator/ByGeneration/EncounterGenerator4.cs @@ -1,24 +1,129 @@ -using System.Collections.Generic; +using System; +using System.Collections.Generic; using System.Linq; -using static PKHeX.Core.MysteryGiftGenerator; -using static PKHeX.Core.EncounterTradeGenerator; -using static PKHeX.Core.EncounterSlotGenerator; -using static PKHeX.Core.EncounterStaticGenerator; -using static PKHeX.Core.EncounterEggGenerator; +using static PKHeX.Core.EncounterStateUtil; +using static PKHeX.Core.EncounterTypeGroup; using static PKHeX.Core.EncounterMatchRating; namespace PKHeX.Core; -internal static class EncounterGenerator4 +public sealed class EncounterGenerator4 : IEncounterGenerator { - public static IEnumerable GetEncounters(PKM pk, LegalInfo info) + public static readonly EncounterGenerator4 Instance = new(); + + // Utility + private static readonly PGT RangerManaphy = new() { Data = { [0] = 7, [8] = 1 } }; + + public IEnumerable GetEncounters(PKM pk, LegalInfo info) + { + var chain = EncounterOrigin.GetOriginChain(pk); + return GetEncounters(pk, chain, info); + } + + public IEnumerable GetPossible(PKM _, EvoCriteria[] chain, GameVersion game, EncounterTypeGroup groups) + { + if (groups.HasFlag(Mystery)) + { + if (chain[^1].Species == (int)Species.Manaphy) + yield return RangerManaphy; + + var table = EncounterEvent.MGDB_G4; + foreach (var enc in GetPossibleGifts(chain, table)) + yield return enc; + } + if (groups.HasFlag(Egg)) + { + var eggs = GetEggs(chain, game); + foreach (var enc in eggs) + yield return enc; + } + if (groups.HasFlag(Static)) + { + var table = GetStatic(game); + foreach (var enc in GetPossibleStatic(chain, table)) + yield return enc; + } + if (groups.HasFlag(Slot)) + { + var areas = GetAreas(game); + foreach (var enc in GetPossibleSlots(chain, areas)) + yield return enc; + } + if (groups.HasFlag(Trade)) + { + var table = GetTrades(game); + foreach (var enc in GetPossibleTrades(chain, table)) + yield return enc; + } + } + + private static IEnumerable GetPossibleGifts(EvoCriteria[] chain, IReadOnlyList table) + { + foreach (var enc in table) + { + foreach (var evo in chain) + { + if (evo.Species != enc.Species) + continue; + yield return enc; + break; + } + } + } + + private static IEnumerable GetPossibleStatic(EvoCriteria[] chain, EncounterStatic[] table) + { + foreach (var enc in table) + { + foreach (var evo in chain) + { + if (evo.Species != enc.Species) + continue; + yield return enc; + break; + } + } + } + + private static IEnumerable GetPossibleSlots(EvoCriteria[] chain, EncounterArea4[] areas) + { + foreach (var area in areas) + { + foreach (var slot in area.Slots) + { + foreach (var evo in chain) + { + if (evo.Species != slot.Species) + continue; + yield return slot; + break; + } + } + } + } + + private static IEnumerable GetPossibleTrades(EvoCriteria[] chain, EncounterTrade[] table) + { + foreach (var enc in table) + { + foreach (var evo in chain) + { + if (evo.Species != enc.Species) + continue; + yield return enc; + break; + } + } + } + + public IEnumerable GetEncounters(PKM pk, EvoCriteria[] chain, LegalInfo info) { info.PIDIV = MethodFinder.Analyze(pk); var deferredPIDIV = new List(); var deferredEType = new List(); - foreach (var z in GenerateRawEncounters4(pk, info)) + foreach (var z in GetEncountersInner(pk, chain, info)) { if (!info.PIDIV.Type.IsCompatible4(z, pk)) deferredPIDIV.Add(z); @@ -39,24 +144,54 @@ internal static class EncounterGenerator4 yield return z; } - private static IEnumerable GenerateRawEncounters4(PKM pk, LegalInfo info) + private static IEnumerable GetEncountersInner(PKM pk, EvoCriteria[] chain, LegalInfo info) { - var chain = EncounterOrigin.GetOriginChain(pk); var game = (GameVersion)pk.Version; if (pk.FatefulEncounter) { - int ctr = 0; - foreach (var z in GetValidGifts(pk, chain, game)) - { yield return z; ++ctr; } - if (ctr != 0) yield break; + if (PGT.IsRangerManaphy(pk)) + { + yield return RangerManaphy; + yield break; + } + + bool yielded = false; + foreach (var mg in EncounterEvent.MGDB_G4) + { + foreach (var evo in chain) + { + if (evo.Species != mg.Species) + continue; + if (mg.IsMatchExact(pk, evo)) + { + yield return mg; + yielded = true; + } + break; + } + } + if (yielded) + yield break; } if (Locations.IsEggLocationBred4(pk.Egg_Location, game)) { - foreach (var z in GenerateEggs(pk, 4)) - yield return z; + var eggs = GetEggs(chain, game); + foreach (var egg in eggs) + yield return egg; + } + + var encTrade = GetTrades(game); + foreach (var enc in encTrade) + { + foreach (var evo in chain) + { + if (evo.Species != enc.Species) + continue; + if (enc.IsMatchExact(pk, evo)) + yield return enc; + break; + } } - foreach (var z in GetValidEncounterTrades(pk, chain, game)) - yield return z; IEncounterable? deferred = null; IEncounterable? partial = null; @@ -64,68 +199,192 @@ internal static class EncounterGenerator4 bool safariSport = pk.Ball is (int)Ball.Sport or (int)Ball.Safari; // never static encounters if (!safariSport) { - foreach (var z in GetValidStaticEncounter(pk, chain, game)) + var encStatic = GetStatic(game); + foreach (var enc in encStatic) { - var match = z.GetMatchRating(pk); - if (match == PartialMatch) - partial ??= z; - else - yield return z; + foreach (var evo in chain) + { + if (evo.Species != enc.Species) + continue; + if (!enc.IsMatchExact(pk, evo)) + break; + + var match = enc.GetMatchRating(pk); + if (match == PartialMatch) + partial ??= enc; + else + yield return enc; + break; + } } } - var slots = FrameFinder.GetFrames(info.PIDIV, pk).ToList(); - foreach (var slot in GetValidWildEncounters(pk, chain, game)) + if (CanBeWildEncounter(pk)) { - var z = (EncounterSlot4)slot; - var match = z.GetMatchRating(pk); - if (match == PartialMatch) + var wildFrames = AnalyzeFrames(pk, info); + var areas = GetAreas(game); + foreach (var area in areas) { - partial ??= z; - continue; + var slots = area.GetMatchingSlots(pk, chain); + foreach (var slot in slots) + { + var match = slot.GetMatchRating(pk); + if (match == PartialMatch) + { + partial ??= slot; + continue; + } + + // Can use Radar to force the encounter slot to stay consistent across encounters. + if (slot.CanUseRadar) + { + yield return slot; + continue; + } + + var frame = wildFrames.Find(s => s.IsSlotCompatibile(slot, pk)); + if (frame == null) + { + deferred ??= slot; + continue; + } + yield return slot; + } } - // Can use Radar to force the encounter slot to stay consistent across encounters. - if (z.CanUseRadar) + info.FrameMatches = false; + if (deferred is EncounterSlot4 x) + yield return x; + + if (partial is EncounterSlot4 y) { - yield return slot; - continue; + var frame = wildFrames.Find(s => s.IsSlotCompatibile(y, pk)); + info.FrameMatches = frame != null; + yield return y; } - - var frame = slots.Find(s => s.IsSlotCompatibile(z, pk)); - if (frame == null) - { - deferred ??= z; - continue; - } - yield return z; - } - - info.FrameMatches = false; - if (deferred is EncounterSlot4 x) - yield return x; - - if (partial is EncounterSlot4 y) - { - var frame = slots.Find(s => s.IsSlotCompatibile(y, pk)); - info.FrameMatches = frame != null; - yield return y; } // do static encounters if they were deferred to end, spit out any possible encounters for invalid pk if (!safariSport) yield break; - foreach (var z in GetValidStaticEncounter(pk, chain, game)) + var encStatic2 = GetStatic(game); + foreach (var enc in encStatic2) { - var match = z.GetMatchRating(pk); - if (match == PartialMatch) - partial ??= z; - else - yield return z; + foreach (var evo in chain) + { + if (evo.Species != enc.Species) + continue; + if (!enc.IsMatchExact(pk, evo)) + break; + + var match = enc.GetMatchRating(pk); + if (match == PartialMatch) + partial ??= enc; + else + yield return enc; + break; + } } if (partial is not null) yield return partial; } + + private static List AnalyzeFrames(PKM pk, LegalInfo info) + { + return FrameFinder.GetFrames(info.PIDIV, pk).ToList(); + } + + private static EncounterStatic[] GetStatic(GameVersion gameSource) => gameSource switch + { + GameVersion.D => Encounters4DPPt.StaticD, + GameVersion.P => Encounters4DPPt.StaticP, + GameVersion.Pt => Encounters4DPPt.StaticPt, + GameVersion.HG => Encounters4HGSS.StaticHG, + GameVersion.SS => Encounters4HGSS.StaticSS, + _ => throw new ArgumentOutOfRangeException(nameof(gameSource), gameSource, null), + }; + + private static EncounterArea4[] GetAreas(GameVersion gameSource) => gameSource switch + { + GameVersion.D => Encounters4DPPt.SlotsD, + GameVersion.P => Encounters4DPPt.SlotsP, + GameVersion.Pt => Encounters4DPPt.SlotsPt, + GameVersion.HG => Encounters4HGSS.SlotsHG, + GameVersion.SS => Encounters4HGSS.SlotsSS, + _ => throw new ArgumentOutOfRangeException(nameof(gameSource), gameSource, null), + }; + + private static EncounterTrade[] GetTrades(GameVersion gameSource) => gameSource switch + { + GameVersion.D => Encounters4DPPt.TradeGift_DPPt, + GameVersion.P => Encounters4DPPt.TradeGift_DPPt, + GameVersion.Pt => Encounters4DPPt.TradeGift_DPPt, + GameVersion.HG => Encounters4HGSS.TradeGift_HGSS, + GameVersion.SS => Encounters4HGSS.TradeGift_HGSS, + _ => throw new ArgumentOutOfRangeException(nameof(gameSource), gameSource, null), + }; + + private const int Generation = 4; + private const EntityContext Context = EntityContext.Gen4; + private const byte EggLevel = 1; + + private static IEnumerable GetEggs(EvoCriteria[] chain, GameVersion version) + { + var devolved = chain[^1]; + + // Ensure most devolved species is the same as the egg species. + var (species, form) = GetBaby(devolved); + if (species != devolved.Species && !IsValidBabySpecies(devolved.Species)) + yield break; // not a split-breed. + + // Sanity Check 1 + if (!Breeding.CanHatchAsEgg(species)) + yield break; + // Sanity Check 2 + if (!Breeding.CanHatchAsEgg(species, form, Context)) + yield break; + // Sanity Check 3 + if (!PersonalTable.HGSS.IsPresentInGame(species, form)) + yield break; + + yield return CreateEggEncounter(species, form, version); + // Version is not updated when hatching an Egg in Gen4. Version is a clear indicator of the game it originated on. + + // Check for split-breed + if (species == devolved.Species) + { + if (chain.Length < 2) + yield break; // no split-breed + devolved = chain[^2]; + } + var splitSet = Breeding.GetSplitBreedGeneration(Generation); + if (splitSet is null) + yield break; // Shouldn't happen. + if (!splitSet.Contains(devolved.Species)) + yield break; + + species = devolved.Species; + form = devolved.Form; + yield return CreateEggEncounter(species, form, version); + } + + private static bool IsValidBabySpecies(ushort species) + { + var split = Breeding.GetSplitBreedGeneration(Generation); + return split is not null && split.Contains(species); + } + + private static EncounterEgg CreateEggEncounter(ushort species, byte form, GameVersion version) + { + if (FormInfo.IsBattleOnlyForm(species, form, Generation) || species is (int)Species.Rotom or (int)Species.Castform) + form = FormInfo.GetOutOfBattleForm(species, form, Generation); + return new EncounterEgg(species, form, EggLevel, Generation, version, Context); + } + + private static (ushort Species, byte Form) GetBaby(EvoCriteria lowest) + { + return EvolutionTree.Evolves4.GetBaseSpeciesForm(lowest.Species, lowest.Form); + } } diff --git a/PKHeX.Core/Legality/Encounters/Generator/ByGeneration/EncounterGenerator5.cs b/PKHeX.Core/Legality/Encounters/Generator/ByGeneration/EncounterGenerator5.cs index 514f0d7a4..56e2ab9f7 100644 --- a/PKHeX.Core/Legality/Encounters/Generator/ByGeneration/EncounterGenerator5.cs +++ b/PKHeX.Core/Legality/Encounters/Generator/ByGeneration/EncounterGenerator5.cs @@ -1,79 +1,322 @@ -using System.Collections.Generic; +using System; +using System.Collections.Generic; -using static PKHeX.Core.MysteryGiftGenerator; -using static PKHeX.Core.EncounterTradeGenerator; -using static PKHeX.Core.EncounterSlotGenerator; -using static PKHeX.Core.EncounterStaticGenerator; -using static PKHeX.Core.EncounterEggGenerator; +using static PKHeX.Core.EncounterStateUtil; +using static PKHeX.Core.EncounterTypeGroup; using static PKHeX.Core.EncounterMatchRating; namespace PKHeX.Core; -internal static class EncounterGenerator5 +public sealed class EncounterGenerator5 : IEncounterGenerator { - public static IEnumerable GetEncounters(PKM pk) - { - int ctr = 0; + public static readonly EncounterGenerator5 Instance = new(); + public IEnumerable GetEncounters(PKM pk, LegalInfo info) + { var chain = EncounterOrigin.GetOriginChain(pk); + return GetEncounters(pk, chain, info); + } + + public IEnumerable GetPossible(PKM _, EvoCriteria[] chain, GameVersion game, EncounterTypeGroup groups) + { + if (groups.HasFlag(Mystery)) + { + var table = EncounterEvent.MGDB_G5; + foreach (var enc in GetPossibleGifts(chain, table)) + yield return enc; + } + if (groups.HasFlag(Egg)) + { + var eggs = GetEggs(chain, game); + foreach (var enc in eggs) + yield return enc; + } + if (groups.HasFlag(Static)) + { + var table = GetStatic(game); + foreach (var enc in GetPossibleStatic(chain, table)) + yield return enc; + } + if (groups.HasFlag(Slot)) + { + var areas = GetAreas(game); + foreach (var enc in GetPossibleSlots(chain, areas)) + yield return enc; + } + if (groups.HasFlag(Trade)) + { + var table = GetTrades(game); + foreach (var enc in GetPossibleTrades(chain, table, game)) + yield return enc; + } + } + + private static IEnumerable GetPossibleGifts(EvoCriteria[] chain, IReadOnlyList table) + { + foreach (var enc in table) + { + foreach (var evo in chain) + { + if (evo.Species != enc.Species) + continue; + yield return enc; + break; + } + } + } + + private static IEnumerable GetPossibleStatic(EvoCriteria[] chain, EncounterStatic5[] table) + { + foreach (var enc in table) + { + foreach (var evo in chain) + { + if (evo.Species != enc.Species) + continue; + yield return enc; + break; + } + } + } + + private static IEnumerable GetPossibleSlots(EvoCriteria[] chain, EncounterArea5[] areas) + { + foreach (var area in areas) + { + foreach (var slot in area.Slots) + { + foreach (var evo in chain) + { + if (evo.Species != slot.Species) + continue; + yield return slot; + break; + } + } + } + } + + private static IEnumerable GetPossibleTrades(EvoCriteria[] chain, EncounterTrade[] table, GameVersion game) + { + foreach (var enc in table) + { + if (enc.Version < GameVersion.BW && enc.Version != game) + continue; + foreach (var evo in chain) + { + if (evo.Species != enc.Species) + continue; + yield return enc; + break; + } + } + } + + public IEnumerable GetEncounters(PKM pk, EvoCriteria[] chain, LegalInfo info) + { var game = (GameVersion)pk.Version; + bool yielded = false; if (pk.FatefulEncounter) { - foreach (var z in GetValidGifts(pk, chain, game)) - { yield return z; ++ctr; } - if (ctr != 0) yield break; + foreach (var mg in EncounterEvent.MGDB_G5) + { + foreach (var evo in chain) + { + if (evo.Species != mg.Species) + continue; + + if (mg.IsMatchExact(pk, evo)) + { + yield return mg; + yielded = true; + } + break; + } + } + if (yielded) + yield break; } if (Locations.IsEggLocationBred5(pk.Egg_Location)) { - foreach (var z in GenerateEggs(pk, 5)) - { yield return z; ++ctr; } - if (ctr == 0) yield break; + var eggs = GetEggs(chain, game); + foreach (var egg in eggs) + { + yield return egg; + yielded = true; + } + + if (yielded) + yield break; } IEncounterable? deferred = null; IEncounterable? partial = null; - foreach (var z in GetValidStaticEncounter(pk, chain, game)) + var encStatic = GetStatic(game); + foreach (var enc in encStatic) { - var match = z.GetMatchRating(pk); - switch (match) + foreach (var evo in chain) { - case Match: yield return z; ++ctr; break; - case Deferred: deferred ??= z; break; - case PartialMatch: partial ??= z; break; + if (evo.Species != enc.Species) + continue; + + if (!enc.IsMatchExact(pk, evo)) + break; + + var match = enc.GetMatchRating(pk); + switch (match) + { + case Match: yield return enc; yielded = true; break; + case Deferred: deferred ??= enc; break; + case PartialMatch: partial ??= enc; break; + } + break; } } - if (ctr != 0) yield break; + if (yielded) + yield break; - foreach (var z in GetValidWildEncounters(pk, chain, game)) + if (CanBeWildEncounter(pk)) { - var match = z.GetMatchRating(pk); - switch (match) + var location = pk.Met_Location; + var areas = GetAreas(game); + foreach (var area in areas) { - case Match: yield return z; ++ctr; break; - case Deferred: deferred ??= z; break; - case PartialMatch: partial ??= z; break; - } - } - if (ctr != 0) yield break; + if (!area.IsMatchLocation(location)) + continue; - foreach (var z in GetValidEncounterTrades(pk, chain, game)) - { - var match = z.GetMatchRating(pk); - switch (match) - { - case Match: yield return z; /*++ctr*/ break; - case Deferred: deferred ??= z; break; - case PartialMatch: partial ??= z; break; + var slots = area.GetMatchingSlots(pk, chain); + foreach (var enc in slots) + { + var match = enc.GetMatchRating(pk); + switch (match) + { + case Match: yield return enc; yielded = true; break; + case Deferred: deferred ??= enc; break; + case PartialMatch: partial ??= enc; break; + } + break; + } } + if (yielded) + yield break; } + var trades = GetTrades(game); + foreach (var trade in trades) + { + foreach (var evo in chain) + { + if (evo.Species != trade.Species) + continue; + if (!trade.IsMatchExact(pk, evo)) + break; + + var match = trade.GetMatchRating(pk); + switch (match) + { + case Match: yield return trade; break; + case Deferred: deferred ??= trade; break; + case PartialMatch: partial ??= trade; break; + } + break; + } + } if (deferred != null) yield return deferred; - if (partial != null) yield return partial; } + + private static EncounterStatic5[] GetStatic(GameVersion gameSource) => gameSource switch + { + GameVersion.B => Encounters5BW.StaticB, + GameVersion.W => Encounters5BW.StaticW, + GameVersion.B2 => Encounters5B2W2.StaticB2, + GameVersion.W2 => Encounters5B2W2.StaticW2, + _ => throw new ArgumentOutOfRangeException(nameof(gameSource), gameSource, null), + }; + + private static EncounterArea5[] GetAreas(GameVersion gameSource) => gameSource switch + { + GameVersion.B => Encounters5BW.SlotsB, + GameVersion.W => Encounters5BW.SlotsW, + GameVersion.B2 => Encounters5B2W2.SlotsB2, + GameVersion.W2 => Encounters5B2W2.SlotsW2, + _ => throw new ArgumentOutOfRangeException(nameof(gameSource), gameSource, null), + }; + + private static EncounterTrade[] GetTrades(GameVersion gameSource) => gameSource switch + { + GameVersion.B => Encounters5BW.TradeGift_BW, + GameVersion.W => Encounters5BW.TradeGift_BW, + GameVersion.B2 => Encounters5B2W2.TradeGift_B2W2, + GameVersion.W2 => Encounters5B2W2.TradeGift_B2W2, + _ => throw new ArgumentOutOfRangeException(nameof(gameSource), gameSource, null), + }; + + private const int Generation = 5; + private const EntityContext Context = EntityContext.Gen5; + private const byte EggLevel = 1; + + private static IEnumerable GetEggs(EvoCriteria[] chain, GameVersion version) + { + var devolved = chain[^1]; + + // Ensure most devolved species is the same as the egg species. + var (species, form) = GetBaby(devolved); + if (species != devolved.Species && !IsValidBabySpecies(devolved.Species)) + yield break; // not a split-breed. + + // Sanity Check 1 + if (!Breeding.CanHatchAsEgg(species)) + yield break; + // Sanity Check 2 + if (!Breeding.CanHatchAsEgg(species, form, Context)) + yield break; + // Sanity Check 3 + if (!PersonalTable.B2W2.IsPresentInGame(species, form)) + yield break; + + yield return CreateEggEncounter(species, form, version); + // Both B/W and B2/W2 have the same egg move sets, so there is no point generating other-game pair encounters for traded eggs. + // When hatched, the entity's Version is updated to the OT's. + + // Check for split-breed + if (species == devolved.Species) + { + if (chain.Length < 2) + yield break; // no split-breed + devolved = chain[^2]; + } + var splitSet = Breeding.GetSplitBreedGeneration(Generation); + if (splitSet is null) + yield break; // Shouldn't happen. + if (!splitSet.Contains(devolved.Species)) + yield break; + + species = devolved.Species; + form = devolved.Form; + yield return CreateEggEncounter(species, form, version); + } + + private static bool IsValidBabySpecies(ushort species) + { + var split = Breeding.GetSplitBreedGeneration(Generation); + return split is not null && split.Contains(species); + } + + private static EncounterEgg CreateEggEncounter(ushort species, byte form, GameVersion version) + { + if (FormInfo.IsBattleOnlyForm(species, form, Generation) || species is (int)Species.Rotom or (int)Species.Castform) + form = FormInfo.GetOutOfBattleForm(species, form, Generation); + return new EncounterEgg(species, form, EggLevel, Generation, version, Context); + } + + private static (ushort Species, byte Form) GetBaby(EvoCriteria lowest) + { + return EvolutionTree.Evolves5.GetBaseSpeciesForm(lowest.Species, lowest.Form); + } } diff --git a/PKHeX.Core/Legality/Encounters/Generator/ByGeneration/EncounterGenerator6.cs b/PKHeX.Core/Legality/Encounters/Generator/ByGeneration/EncounterGenerator6.cs index 5e1aab7f4..a004b24e4 100644 --- a/PKHeX.Core/Legality/Encounters/Generator/ByGeneration/EncounterGenerator6.cs +++ b/PKHeX.Core/Legality/Encounters/Generator/ByGeneration/EncounterGenerator6.cs @@ -1,98 +1,387 @@ -using System.Collections.Generic; +using System; +using System.Collections.Generic; -using static PKHeX.Core.MysteryGiftGenerator; -using static PKHeX.Core.EncounterTradeGenerator; -using static PKHeX.Core.EncounterSlotGenerator; -using static PKHeX.Core.EncounterStaticGenerator; -using static PKHeX.Core.EncounterEggGenerator; +using static PKHeX.Core.EncounterStateUtil; +using static PKHeX.Core.EncounterTypeGroup; using static PKHeX.Core.EncounterMatchRating; namespace PKHeX.Core; -internal static class EncounterGenerator6 +public sealed class EncounterGenerator6 : IEncounterGenerator { - public static IEnumerable GetEncounters(PKM pk) - { - int ctr = 0; + public static readonly EncounterGenerator6 Instance = new(); + public IEnumerable GetPossible(PKM pk, EvoCriteria[] chain, GameVersion game, EncounterTypeGroup groups) + { + if (groups.HasFlag(Mystery)) + { + var table = EncounterEvent.MGDB_G6; + foreach (var enc in GetPossibleGifts(chain, table)) + yield return enc; + } + if (groups.HasFlag(Egg)) + { + var eggs = GetEggs(pk, chain, game); + foreach (var enc in eggs) + yield return enc; + } + if (groups.HasFlag(Static)) + { + var table = GetStatic(game); + foreach (var enc in GetPossibleStatic(chain, table)) + yield return enc; + } + if (groups.HasFlag(Slot)) + { + if (game is GameVersion.X or GameVersion.Y) + { + var areas = game == GameVersion.X ? Encounters6XY.SlotsX : Encounters6XY.SlotsY; + foreach (var enc in GetPossibleSlots(chain, areas)) + yield return enc; + } + else if (game is GameVersion.AS or GameVersion.OR) + { + var areas = game == GameVersion.AS ? Encounters6AO.SlotsA : Encounters6AO.SlotsO; + foreach (var enc in GetPossibleSlots(chain, areas)) + yield return enc; + } + } + if (groups.HasFlag(Trade)) + { + var table = GetTrades(game); + foreach (var enc in GetPossibleTrades(chain, table)) + yield return enc; + } + } + + private static IEnumerable GetPossibleGifts(EvoCriteria[] chain, IReadOnlyList table) + { + foreach (var enc in table) + { + foreach (var evo in chain) + { + if (evo.Species != enc.Species) + continue; + yield return enc; + break; + } + } + } + + private static IEnumerable GetPossibleStatic(EvoCriteria[] chain, EncounterStatic6[] table) + { + foreach (var enc in table) + { + foreach (var evo in chain) + { + if (evo.Species != enc.Species) + continue; + yield return enc; + break; + } + } + } + + private static IEnumerable GetPossibleSlots(EvoCriteria[] chain, EncounterArea6XY[] areas) + { + foreach (var area in areas) + { + foreach (var slot in area.Slots) + { + foreach (var evo in chain) + { + if (evo.Species != slot.Species) + continue; + yield return slot; + break; + } + } + } + } + + private static IEnumerable GetPossibleSlots(EvoCriteria[] chain, EncounterArea6AO[] areas) + { + foreach (var area in areas) + { + foreach (var slot in area.Slots) + { + foreach (var evo in chain) + { + if (evo.Species != slot.Species) + continue; + yield return slot; + break; + } + } + } + } + + private static IEnumerable GetPossibleTrades(EvoCriteria[] chain, EncounterTrade6[] table) + { + foreach (var enc in table) + { + foreach (var evo in chain) + { + if (evo.Species != enc.Species) + continue; + yield return enc; + break; + } + } + } + + public IEnumerable GetEncounters(PKM pk, LegalInfo info) + { var chain = EncounterOrigin.GetOriginChain(pk); + return GetEncounters(pk, chain, info); + } + + public IEnumerable GetEncounters(PKM pk, EvoCriteria[] chain, LegalInfo info) + { var game = (GameVersion)pk.Version; IEncounterable? deferred = null; IEncounterable? partial = null; + bool yielded = false; if (pk.FatefulEncounter || pk.Met_Location == Locations.LinkGift6) { - foreach (var z in GetValidGifts(pk, chain, game)) + foreach (var mg in EncounterEvent.MGDB_G6) { - var match = z.GetMatchRating(pk); - switch (match) + foreach (var evo in chain) { - case Match: yield return z; break; - case Deferred: deferred ??= z; break; - case PartialMatch: partial ??= z; break; - } - ++ctr; - } + if (mg.Species != evo.Species) + continue; + if (!mg.IsMatchExact(pk, evo)) + break; - if (ctr != 0) + var match = mg.GetMatchRating(pk); + if (match == Match) + { + yield return mg; + yielded = true; + } + else if (match == Deferred) + { + deferred ??= mg; + } + else if (match == PartialMatch) + { + partial ??= mg; + } + break; + } + } + if (!yielded) { if (deferred != null) + { yield return deferred; - + yielded = true; + } if (partial != null) + { yield return partial; - - yield break; + yielded = true; + } } + if (yielded) + yield break; } if (Locations.IsEggLocationBred6(pk.Egg_Location)) { - foreach (var z in GenerateEggs(pk, 6)) - { yield return z; ++ctr; } - if (ctr == 0) yield break; + var eggs = GetEggs(pk, chain, game); + foreach (var egg in eggs) + { + yield return egg; + yielded = true; + } + if (yielded) + yield break; } - foreach (var z in GetValidStaticEncounter(pk, chain, game)) + var encStatic = GetStatic(game); + foreach (var enc in encStatic) { - var match = z.GetMatchRating(pk); - switch (match) + foreach (var evo in chain) { - case Match: yield return z; ++ctr; break; - case Deferred: deferred ??= z; break; - case PartialMatch: partial ??= z; break; - } - } - if (ctr != 0) yield break; + if (evo.Species != enc.Species) + continue; + if (!enc.IsMatchExact(pk, evo)) + break; - foreach (var z in GetValidWildEncounters(pk, chain, game)) - { - var match = z.GetMatchRating(pk); - switch (match) - { - case Match: yield return z; ++ctr; break; - case Deferred: deferred ??= z; break; - case PartialMatch: partial ??= z; break; + var match = enc.GetMatchRating(pk); + switch (match) + { + case Match: yield return enc; yielded = true; break; + case Deferred: deferred ??= enc; break; + case PartialMatch: partial ??= enc; break; + } + break; } } - if (ctr != 0) yield break; + if (yielded) + yield break; - foreach (var z in GetValidEncounterTrades(pk, chain, game)) + if (CanBeWildEncounter(pk)) { - var match = z.GetMatchRating(pk); - switch (match) + var location = pk.Met_Location; + var areas = GetAreas(game); + foreach (var area in areas) { - case Match: yield return z; /*++ctr*/ break; - case Deferred: deferred ??= z; break; - case PartialMatch: partial ??= z; break; + if (!area.IsMatchLocation(location)) + continue; + + var slots = area.GetMatchingSlots(pk, chain); + foreach (var slot in slots) + { + var match = slot.GetMatchRating(pk); + switch (match) + { + case Match: yield return slot; yielded = true; break; + case Deferred: deferred ??= slot; break; + case PartialMatch: partial ??= slot; break; + } + } + } + if (yielded) + yield break; + } + + var trades = GetTrades(game); + foreach (var enc in trades) + { + foreach (var evo in chain) + { + if (evo.Species != enc.Species) + continue; + if (!enc.IsMatchExact(pk, evo)) + break; + + var match = enc.GetMatchRating(pk); + switch (match) + { + case Match: yield return enc; yielded = true; break; + case Deferred: deferred ??= enc; break; + case PartialMatch: partial ??= enc; break; + } + break; } } + if (yielded) + yield break; if (deferred != null) yield return deferred; - if (partial != null) yield return partial; } + + private static EncounterStatic6[] GetStatic(GameVersion gameSource) => gameSource switch + { + GameVersion.X => Encounters6XY.StaticX, + GameVersion.Y => Encounters6XY.StaticY, + GameVersion.AS => Encounters6AO.StaticA, + GameVersion.OR => Encounters6AO.StaticO, + _ => throw new ArgumentOutOfRangeException(nameof(gameSource), gameSource, null), + }; + + private static EncounterArea[] GetAreas(GameVersion gameSource) => gameSource switch + { + GameVersion.X => Encounters6XY.SlotsX, + GameVersion.Y => Encounters6XY.SlotsY, + GameVersion.AS => Encounters6AO.SlotsA, + GameVersion.OR => Encounters6AO.SlotsO, + _ => throw new ArgumentOutOfRangeException(nameof(gameSource), gameSource, null), + }; + + private static EncounterTrade6[] GetTrades(GameVersion gameSource) => gameSource switch + { + GameVersion.X => Encounters6XY.TradeGift_XY, + GameVersion.Y => Encounters6XY.TradeGift_XY, + GameVersion.AS => Encounters6AO.TradeGift_AO, + GameVersion.OR => Encounters6AO.TradeGift_AO, + _ => throw new ArgumentOutOfRangeException(nameof(gameSource), gameSource, null), + }; + + private const int Generation = 6; + private const EntityContext Context = EntityContext.Gen6; + private const byte EggLevel = 1; + + private static IEnumerable GetEggs(PKM pk, EvoCriteria[] chain, GameVersion version) + { + var devolved = chain[^1]; + + // Ensure most devolved species is the same as the egg species. + var (species, form) = GetBaby(devolved); + if (species != devolved.Species && !IsValidBabySpecies(devolved.Species)) + yield break; // not a split-breed. + + // Sanity Check 1 + if (!Breeding.CanHatchAsEgg(species)) + yield break; + // Sanity Check 2 + if (!Breeding.CanHatchAsEgg(species, form, Context)) + yield break; + // Sanity Check 3 + if (!PersonalTable.AO.IsPresentInGame(species, form)) + yield break; + + var egg = CreateEggEncounter(species, form, version); + yield return egg; + if (pk.IsEgg) + yield break; + bool otherVersion = pk is { Egg_Location: Locations.LinkTrade6 }; + if (otherVersion) + yield return egg with { Version = GetOtherGamePair(version) }; + + // Check for split-breed + if (species == devolved.Species) + { + if (chain.Length < 2) + yield break; // no split-breed + devolved = chain[^2]; + } + var splitSet = Breeding.GetSplitBreedGeneration(Generation); + if (splitSet is null) + yield break; // Shouldn't happen. + if (!splitSet.Contains(devolved.Species)) + yield break; + + species = devolved.Species; + form = devolved.Form; + egg = CreateEggEncounter(species, form, version); + yield return egg; + if (otherVersion) + yield return egg with { Version = GetOtherGamePair(version) }; + } + + private static bool IsValidBabySpecies(ushort species) + { + var split = Breeding.GetSplitBreedGeneration(Generation); + return split is not null && split.Contains(species); + } + + private static GameVersion GetOtherGamePair(GameVersion version) + { + // 24 -> 26 ( X -> AS) + // 25 -> 27 ( Y -> OR) + // 26 -> 24 (AS -> X) + // 27 -> 25 (OR -> Y) + // ReSharper disable once BitwiseOperatorOnEnumWithoutFlags + return version ^ (GameVersion)2; + } + + private static EncounterEgg CreateEggEncounter(ushort species, byte form, GameVersion version) + { + if (FormInfo.IsBattleOnlyForm(species, form, Generation) || species is (int)Species.Rotom or (int)Species.Castform) + form = FormInfo.GetOutOfBattleForm(species, form, Generation); + return new EncounterEgg(species, form, EggLevel, Generation, version, Context); + } + + private static (ushort Species, byte Form) GetBaby(EvoCriteria lowest) + { + return EvolutionTree.Evolves6.GetBaseSpeciesForm(lowest.Species, lowest.Form); + } } diff --git a/PKHeX.Core/Legality/Encounters/Generator/ByGeneration/EncounterGenerator7.cs b/PKHeX.Core/Legality/Encounters/Generator/ByGeneration/EncounterGenerator7.cs index 5be864a5a..72a208af3 100644 --- a/PKHeX.Core/Legality/Encounters/Generator/ByGeneration/EncounterGenerator7.cs +++ b/PKHeX.Core/Legality/Encounters/Generator/ByGeneration/EncounterGenerator7.cs @@ -1,171 +1,363 @@ -using System.Collections.Generic; +using System; +using System.Collections.Generic; -using static PKHeX.Core.MysteryGiftGenerator; -using static PKHeX.Core.EncounterTradeGenerator; -using static PKHeX.Core.EncounterSlotGenerator; -using static PKHeX.Core.EncounterStaticGenerator; -using static PKHeX.Core.EncounterEggGenerator; +using static PKHeX.Core.EncounterStateUtil; +using static PKHeX.Core.EncounterTypeGroup; using static PKHeX.Core.EncounterMatchRating; namespace PKHeX.Core; -internal static class EncounterGenerator7 +public sealed class EncounterGenerator7 : IEncounterGenerator { - public static IEnumerable GetEncounters(PKM pk) + public static readonly EncounterGenerator7 Instance = new(); + + public IEnumerable GetPossible(PKM pk, EvoCriteria[] chain, GameVersion game, EncounterTypeGroup groups) { - var chain = EncounterOrigin.GetOriginChain(pk); - return pk.Version switch + if (groups.HasFlag(Mystery)) { - (int)GameVersion.GO => GetEncountersGO(pk, chain), - > (int)GameVersion.GO => GetEncountersGG(pk, chain), - _ => GetEncountersMainline(pk, chain), - }; + var table = EncounterEvent.MGDB_G7; + foreach (var enc in GetPossibleGifts(chain, table)) + yield return enc; + } + if (groups.HasFlag(Egg)) + { + var eggs = GetEggs(pk, chain, game); + foreach (var enc in eggs) + yield return enc; + } + if (groups.HasFlag(Static)) + { + var table = GetStatic(game); + foreach (var enc in GetPossibleStatic(chain, table)) + yield return enc; + } + if (groups.HasFlag(Slot)) + { + var areas = GetAreas(game); + foreach (var enc in GetPossibleSlots(chain, areas)) + yield return enc; + } + if (groups.HasFlag(Trade)) + { + var table = GetTrades(game); + foreach (var enc in GetPossibleTrades(chain, table)) + yield return enc; + } } - internal static IEnumerable GetEncountersGO(PKM pk, EvoCriteria[] chain) + private static IEnumerable GetPossibleGifts(EvoCriteria[] chain, IReadOnlyList table) { - IEncounterable? deferred = null; - IEncounterable? partial = null; - - int ctr = 0; - foreach (var z in GetValidWildEncounters(pk, chain, GameVersion.GO)) + foreach (var enc in table) { - var match = z.GetMatchRating(pk); - switch (match) + foreach (var evo in chain) { - case Match: yield return z; ++ctr; break; - case Deferred: deferred ??= z; break; - case PartialMatch: partial ??= z; break; + if (evo.Species != enc.Species) + continue; + yield return enc; + break; } } - if (ctr != 0) yield break; - - if (deferred != null) - yield return deferred; - - if (partial != null) - yield return partial; } - private static IEnumerable GetEncountersGG(PKM pk, EvoCriteria[] chain) + private static IEnumerable GetPossibleStatic(EvoCriteria[] chain, EncounterStatic7[] table) + { + foreach (var enc in table) + { + foreach (var evo in chain) + { + if (evo.Species != enc.Species) + continue; + yield return enc; + break; + } + } + } + + private static IEnumerable GetPossibleSlots(EvoCriteria[] chain, EncounterArea7[] areas) + { + foreach (var area in areas) + { + foreach (var slot in area.Slots) + { + foreach (var evo in chain) + { + if (evo.Species != slot.Species) + continue; + yield return slot; + break; + } + } + } + } + + private static IEnumerable GetPossibleTrades(EvoCriteria[] chain, EncounterTrade7[] table) + { + foreach (var enc in table) + { + foreach (var evo in chain) + { + if (evo.Species != enc.Species) + continue; + yield return enc; + break; + } + } + } + + public IEnumerable GetEncounters(PKM pk, EvoCriteria[] chain, LegalInfo info) { - int ctr = 0; var game = (GameVersion)pk.Version; + bool yielded = false; if (pk.FatefulEncounter) { - foreach (var z in GetValidGifts(pk, chain, game)) - { yield return z; ++ctr; } - if (ctr != 0) yield break; - } - - IEncounterable? deferred = null; - IEncounterable? partial = null; - - foreach (var z in GetValidStaticEncounter(pk, chain, game)) - { - var match = z.GetMatchRating(pk); - switch (match) + foreach (var mg in EncounterEvent.MGDB_G7) { - case Match: yield return z; ++ctr; break; - case Deferred: deferred ??= z; break; - case PartialMatch: partial ??= z; break; + foreach (var evo in chain) + { + if (mg.Species != evo.Species) + continue; + + if (mg.IsMatchExact(pk, evo)) + { + yield return mg; + yielded = true; + } + break; + } } - } - if (ctr != 0) yield break; - - foreach (var z in GetValidWildEncounters(pk, chain, game)) - { - var match = z.GetMatchRating(pk); - switch (match) - { - case Match: yield return z; ++ctr; break; - case Deferred: deferred ??= z; break; - case PartialMatch: partial ??= z; break; - } - } - if (ctr != 0) yield break; - - foreach (var z in GetValidEncounterTrades(pk, chain, game)) - { - var match = z.GetMatchRating(pk); - switch (match) - { - case Match: yield return z; /*++ctr*/ break; - case Deferred: deferred ??= z; break; - case PartialMatch: partial ??= z; break; - } - } - - if (deferred != null) - yield return deferred; - - if (partial != null) - yield return partial; - } - - private static IEnumerable GetEncountersMainline(PKM pk, EvoCriteria[] chain) - { - int ctr = 0; - var game = (GameVersion)pk.Version; - - if (pk.FatefulEncounter) - { - foreach (var z in GetValidGifts(pk, chain, game)) - { yield return z; ++ctr; } - if (ctr != 0) yield break; + if (yielded) + yield break; } if (Locations.IsEggLocationBred6(pk.Egg_Location)) { - foreach (var z in GenerateEggs(pk, 7)) - { yield return z; ++ctr; } - if (ctr == 0) yield break; + var eggs = GetEggs(pk, chain, game); + foreach (var egg in eggs) + yield return egg; + if (chain[^1].Species != (int)Species.Eevee) // Static encounter clash (gift egg) + yield break; } IEncounterable? deferred = null; IEncounterable? partial = null; - foreach (var z in GetValidStaticEncounter(pk, chain, game)) + var table = GetStatic(game); + foreach (var z in table) { - var match = z.GetMatchRating(pk); - switch (match) + foreach (var evo in chain) { - case Match: yield return z; ++ctr; break; - case Deferred: deferred ??= z; break; - case PartialMatch: partial ??= z; break; + if (z.Species != evo.Species) + continue; + if (!z.IsMatchExact(pk, evo)) + continue; + + var match = z.GetMatchRating(pk); + switch (match) + { + case Match: yield return z; yielded = true; break; + case Deferred: deferred ??= z; break; + case PartialMatch: partial ??= z; break; + } } } - if (ctr != 0) yield break; + if (yielded) + yield break; - foreach (var z in GetValidWildEncounters(pk, chain, game)) + if (CanBeWildEncounter(pk)) { - var match = z.GetMatchRating(pk); - switch (match) + var location = pk.Met_Location; + var areas = GetAreas(game); + foreach (var area in areas) { - case Match: yield return z; ++ctr; break; - case Deferred: deferred ??= z; break; - case PartialMatch: partial ??= z; break; + if (!area.IsMatchLocation(location)) + continue; + + var slots = area.GetMatchingSlots(pk, chain); + foreach (var slot in slots) + { + var match = slot.GetMatchRating(pk); + switch (match) + { + case Match: yield return slot; yielded = true; break; + case Deferred: deferred ??= slot; break; + case PartialMatch: partial ??= slot; break; + } + } } + if (yielded) + yield break; } - if (ctr != 0) yield break; - foreach (var z in GetValidEncounterTrades(pk, chain, game)) + var trades = GetTrades(game); + foreach (var trade in trades) { - var match = z.GetMatchRating(pk); - switch (match) + foreach (var evo in chain) { - case Match: yield return z; break; - case Deferred: deferred ??= z; break; - case PartialMatch: partial ??= z; break; + if (trade.Species != evo.Species) + continue; + if (!trade.IsMatchExact(pk, evo)) + continue; + + var match = trade.GetMatchRating(pk); + switch (match) + { + case Match: yield return trade; break; + case Deferred: deferred ??= trade; break; + case PartialMatch: partial ??= trade; break; + } } - //++ctr; } if (deferred != null) yield return deferred; - - if (partial != null) + else if (partial != null) yield return partial; } + + private static EncounterStatic7[] GetStatic(GameVersion game) => game switch + { + GameVersion.SN => Encounters7SM.StaticSN, + GameVersion.MN => Encounters7SM.StaticMN, + GameVersion.US => Encounters7USUM.StaticUS, + GameVersion.UM => Encounters7USUM.StaticUM, + _ => throw new ArgumentOutOfRangeException(nameof(game), game, null), + }; + + private static EncounterArea7[] GetAreas(GameVersion game) => game switch + { + GameVersion.SN => Encounters7SM.SlotsSN, + GameVersion.MN => Encounters7SM.SlotsMN, + GameVersion.US => Encounters7USUM.SlotsUS, + GameVersion.UM => Encounters7USUM.SlotsUM, + _ => throw new ArgumentOutOfRangeException(nameof(game), game, null), + }; + + private static EncounterTrade7[] GetTrades(GameVersion game) => game switch + { + GameVersion.SN => Encounters7SM.TradeGift_SM, + GameVersion.MN => Encounters7SM.TradeGift_SM, + GameVersion.US => Encounters7USUM.TradeGift_USUM, + GameVersion.UM => Encounters7USUM.TradeGift_USUM, + _ => throw new ArgumentOutOfRangeException(nameof(game), game, null), + }; + + internal static EncounterStatic7 GetVCStaticTransferEncounter(PKM pk, ushort encSpecies, ReadOnlySpan chain) + { + // Obtain the lowest evolution species with matching OT friendship. Not all species chains have the same base friendship. + var met = (byte)pk.Met_Level; + if (pk.VC1) + { + // Only yield a VC1 template if it could originate in VC1. + // Catch anything that can only exist in VC2 (Entei) even if it was "transferred" from VC1. + var species = GetVCSpecies(chain, pk, Legal.MaxSpeciesID_1); + var vc1Species = species > Legal.MaxSpeciesID_1 ? encSpecies : species; + if (vc1Species <= Legal.MaxSpeciesID_1) + return EncounterStatic7.GetVC1(vc1Species, met); + } + // fall through else + { + var species = GetVCSpecies(chain, pk, Legal.MaxSpeciesID_2); + return EncounterStatic7.GetVC2(species > Legal.MaxSpeciesID_2 ? encSpecies : species, met); + } + } + + /// + /// Get the most devolved species that matches the . + /// + private static ushort GetVCSpecies(ReadOnlySpan chain, PKM pk, ushort maxSpecies) + { + for (var i = chain.Length - 1; i >= 0; i--) + { + var evo = chain[i]; + if (evo.Species > maxSpecies) + continue; + if (evo.Form != 0) + continue; + if (PersonalTable.SM.GetFormEntry(evo.Species, evo.Form).BaseFriendship != pk.OT_Friendship) + continue; + return evo.Species; + } + return pk.Species; + } + + private const int Generation = 7; + private const EntityContext Context = EntityContext.Gen7; + private const byte EggLevel = 1; + + private static IEnumerable GetEggs(PKM pk, EvoCriteria[] chain, GameVersion version) + { + var devolved = chain[^1]; + + // Ensure most devolved species is the same as the egg species. + var (species, form) = GetBaby(devolved); + if (species != devolved.Species && !IsValidBabySpecies(devolved.Species)) + yield break; // not a split-breed. + + // Sanity Check 1 + if (!Breeding.CanHatchAsEgg(species)) + yield break; + // Sanity Check 2 + if (!Breeding.CanHatchAsEgg(species, form, Context)) + yield break; + // Sanity Check 3 + if (!PersonalTable.USUM.IsPresentInGame(species, form)) + yield break; + + var egg = CreateEggEncounter(species, form, version); + yield return egg; + if (pk.IsEgg) + yield break; + bool otherVersion = pk is { Egg_Location: Locations.LinkTrade6 }; + if (otherVersion) + yield return egg with { Version = GetOtherGamePair(version) }; + + // Check for split-breed + if (species == devolved.Species) + { + if (chain.Length < 2) + yield break; // no split-breed + devolved = chain[^2]; + } + var splitSet = Breeding.GetSplitBreedGeneration(Generation); + if (splitSet is null) + yield break; // Shouldn't happen. + if (!splitSet.Contains(devolved.Species)) + yield break; + + species = devolved.Species; + form = devolved.Form; + egg = CreateEggEncounter(species, form, version); + yield return egg; + if (otherVersion) + yield return egg with { Version = GetOtherGamePair(version) }; + } + + private static bool IsValidBabySpecies(ushort species) + { + var split = Breeding.GetSplitBreedGeneration(Generation); + return split is not null && split.Contains(species); + } + + private static GameVersion GetOtherGamePair(GameVersion version) + { + // 30 -> 32 (SN -> US) + // 31 -> 33 (MN -> UM) + // 32 -> 30 (US -> SN) + // 33 -> 31 (UM -> MN) + // ReSharper disable once BitwiseOperatorOnEnumWithoutFlags + return version ^ (GameVersion)0b111110; + } + + private static EncounterEgg CreateEggEncounter(ushort species, byte form, GameVersion version) + { + if (FormInfo.IsBattleOnlyForm(species, form, Generation) || species is (int)Species.Rotom or (int)Species.Castform) + form = FormInfo.GetOutOfBattleForm(species, form, Generation); + return new EncounterEgg(species, form, EggLevel, Generation, version, Context); + } + + private static (ushort Species, byte Form) GetBaby(EvoCriteria lowest) + { + return EvolutionTree.Evolves7.GetBaseSpeciesForm(lowest.Species, lowest.Form); + } } diff --git a/PKHeX.Core/Legality/Encounters/Generator/ByGeneration/EncounterGenerator7GG.cs b/PKHeX.Core/Legality/Encounters/Generator/ByGeneration/EncounterGenerator7GG.cs new file mode 100644 index 000000000..101a2d2e3 --- /dev/null +++ b/PKHeX.Core/Legality/Encounters/Generator/ByGeneration/EncounterGenerator7GG.cs @@ -0,0 +1,216 @@ +using System.Collections.Generic; + +using static PKHeX.Core.EncounterStateUtil; +using static PKHeX.Core.EncounterTypeGroup; +using static PKHeX.Core.EncounterMatchRating; + +namespace PKHeX.Core; + +/// +/// Encounter Generator for & +/// +public sealed class EncounterGenerator7GG : IEncounterGenerator +{ + public static readonly EncounterGenerator7GG Instance = new(); + + public IEnumerable GetPossible(PKM _, EvoCriteria[] chain, GameVersion game, EncounterTypeGroup groups) + { + if (groups.HasFlag(Mystery)) + { + var table = EncounterEvent.MGDB_G7GG; + foreach (var enc in GetPossibleMystery(chain, table)) + yield return enc; + } + if (groups.HasFlag(Static)) + { + var table = game == GameVersion.GP ? Encounters7GG.StaticGP : Encounters7GG.StaticGE; + foreach (var enc in GetPossibleStatic(chain, table)) + yield return enc; + } + if (groups.HasFlag(Slot)) + { + var table = game == GameVersion.GP ? Encounters7GG.SlotsGP : Encounters7GG.SlotsGE; + foreach (var enc in GetPossibleSlot(chain, table)) + yield return enc; + } + if (groups.HasFlag(Trade)) + { + var table = Encounters7GG.TradeGift_GG; + foreach (var enc in GetPossibleTrade(chain, table)) + yield return enc; + } + } + + private static IEnumerable GetPossibleMystery(EvoCriteria[] chain, IReadOnlyList table) + { + foreach (var enc in table) + { + foreach (var evo in chain) + { + if (evo.Species != enc.Species) + continue; + yield return enc; + break; + } + } + } + + private static IEnumerable GetPossibleStatic(EvoCriteria[] chain, EncounterStatic7b[] table) + { + foreach (var enc in table) + { + foreach (var evo in chain) + { + if (evo.Species != enc.Species) + continue; + yield return enc; + break; + } + } + } + + private static IEnumerable GetPossibleSlot(EvoCriteria[] chain, EncounterArea7b[] areas) + { + foreach (var area in areas) + { + foreach (var slot in area.Slots) + { + foreach (var evo in chain) + { + if (evo.Species != slot.Species) + continue; + yield return slot; + break; + } + } + } + } + + private static IEnumerable GetPossibleTrade(EvoCriteria[] chain, EncounterTrade7b[] table) + { + foreach (var enc in table) + { + foreach (var evo in chain) + { + if (enc.Species != evo.Species) + continue; + yield return enc; + break; + } + } + } + + public IEnumerable GetEncounters(PKM pk, EvoCriteria[] chain, LegalInfo info) + { + bool yielded = false; + if (pk.FatefulEncounter) + { + foreach (var z in EncounterEvent.MGDB_G7GG) + { + foreach (var evo in chain) + { + if (evo.Species != z.Species) + continue; + + if (z.IsMatchExact(pk, evo)) + { + yield return z; + yielded = true; + } + break; + } + } + if (yielded) + yield break; + } + + var game = (GameVersion)pk.Version; + IEncounterable? deferred = null; + IEncounterable? partial = null; + + var encStatic = game == GameVersion.GP ? Encounters7GG.StaticGP : Encounters7GG.StaticGE; + foreach (var z in encStatic) + { + foreach (var evo in chain) + { + if (evo.Species != z.Species) + continue; + if (!z.IsMatchExact(pk, evo)) + break; + + var match = z.GetMatchRating(pk); + switch (match) + { + case Match: yield return z; yielded = true; break; + case Deferred: deferred ??= z; break; + case PartialMatch: partial ??= z; break; + } + break; + } + } + if (yielded) + yield break; + + if (CanBeWildEncounter(pk)) + { + var location = pk.Met_Location; + var areas = game == GameVersion.GP ? Encounters7GG.SlotsGP : Encounters7GG.SlotsGE; + foreach (var area in areas) + { + if (!area.IsMatchLocation(location)) + continue; + + foreach (var slot in area.Slots) + { + foreach (var evo in chain) + { + if (evo.Species != slot.Species) + continue; + + if (!slot.IsMatchExact(pk, evo)) + break; + + var match = slot.GetMatchRating(pk); + switch (match) + { + case Match: yield return slot; yielded = true; break; + case Deferred: deferred ??= slot; break; + case PartialMatch: partial ??= slot; break; + } + break; + } + } + } + if (yielded) + yield break; + } + + foreach (var z in Encounters7GG.TradeGift_GG) + { + if (z.Version != GameVersion.GG && z.Version != game) + continue; + + foreach (var evo in chain) + { + if (evo.Species != z.Species) + continue; + if (!z.IsMatchExact(pk, evo)) + break; + + var match = z.GetMatchRating(pk); + switch (match) + { + case Match: yield return z; break; + case Deferred: deferred ??= z; break; + case PartialMatch: partial ??= z; break; + } + break; + } + } + + if (deferred != null) + yield return deferred; + else if (partial != null) + yield return partial; + } +} diff --git a/PKHeX.Core/Legality/Encounters/Generator/ByGeneration/EncounterGenerator7GO.cs b/PKHeX.Core/Legality/Encounters/Generator/ByGeneration/EncounterGenerator7GO.cs new file mode 100644 index 000000000..30919aaaf --- /dev/null +++ b/PKHeX.Core/Legality/Encounters/Generator/ByGeneration/EncounterGenerator7GO.cs @@ -0,0 +1,77 @@ +using System.Collections.Generic; + +using static PKHeX.Core.EncounterStateUtil; +using static PKHeX.Core.EncounterTypeGroup; +using static PKHeX.Core.EncounterMatchRating; + +namespace PKHeX.Core; + +public sealed class EncounterGenerator7GO : IEncounterGenerator +{ + public static readonly EncounterGenerator7GO Instance = new(); + + public IEnumerable GetPossible(PKM pk, EvoCriteria[] chain, GameVersion game, EncounterTypeGroup groups) + { + if (groups.HasFlag(Slot)) + { + var areas = EncountersGO.SlotsGO_GG; + foreach (var enc in GetPossibleSlots(chain, areas)) + yield return enc; + } + } + + private static IEnumerable GetPossibleSlots(EvoCriteria[] chain, EncounterArea7g[] areas) + { + foreach (var area in areas) + { + foreach (var evo in chain) + { + if (area.Species != evo.Species) + continue; + + foreach (var slot in area.Slots) + yield return slot; + break; + } + } + } + + public IEnumerable GetEncounters(PKM pk, EvoCriteria[] chain, LegalInfo info) + { + if (!CanBeWildEncounter(pk)) + yield break; + + IEncounterable? deferred = null; + IEncounterable? partial = null; + + bool yielded = false; + foreach (var area in EncountersGO.SlotsGO_GG) + { + foreach (var evo in chain) + { + if (area.Species != evo.Species) + continue; + + var slots = area.GetMatchingSlots(pk, evo); + foreach (var z in slots) + { + var match = z.GetMatchRating(pk); + switch (match) + { + case Match: yield return z; yielded = true; break; + case Deferred: deferred ??= z; break; + case PartialMatch: partial ??= z; break; + } + } + break; + } + } + if (yielded) + yield break; + + if (deferred != null) + yield return deferred; + else if (partial != null) + yield return partial; + } +} diff --git a/PKHeX.Core/Legality/Encounters/Generator/ByGeneration/EncounterGenerator8.cs b/PKHeX.Core/Legality/Encounters/Generator/ByGeneration/EncounterGenerator8.cs index ae7719d6a..fb58de6ab 100644 --- a/PKHeX.Core/Legality/Encounters/Generator/ByGeneration/EncounterGenerator8.cs +++ b/PKHeX.Core/Legality/Encounters/Generator/ByGeneration/EncounterGenerator8.cs @@ -1,58 +1,228 @@ -using System.Collections.Generic; +using System.Collections.Generic; -using static PKHeX.Core.MysteryGiftGenerator; -using static PKHeX.Core.EncounterTradeGenerator; -using static PKHeX.Core.EncounterSlotGenerator; -using static PKHeX.Core.EncounterStaticGenerator; -using static PKHeX.Core.EncounterEggGenerator; +using static PKHeX.Core.EncounterStateUtil; +using static PKHeX.Core.EncounterTypeGroup; using static PKHeX.Core.EncounterMatchRating; namespace PKHeX.Core; -internal static class EncounterGenerator8 +public sealed class EncounterGenerator8 : IEncounterGenerator { - public static IEnumerable GetEncounters(PKM pk) + public static readonly EncounterGenerator8 Instance = new(); + + public IEnumerable GetPossible(PKM _, EvoCriteria[] chain, GameVersion game, EncounterTypeGroup groups) { - var chain = EncounterOrigin.GetOriginChain(pk); - return pk.Version switch + if (groups.HasFlag(Mystery)) { - (int)GameVersion.GO => EncounterGenerator7.GetEncountersGO(pk, chain), - (int)GameVersion.PLA => EncounterGenerator8a.GetEncounters(pk, chain), - (int)GameVersion.BD or (int)GameVersion.SP => EncounterGenerator8b.GetEncounters(pk, chain), - (int)GameVersion.SW when pk.Met_Location == Locations.HOME_SWLA => EncounterGenerator8a.GetEncounters(pk, chain), - (int)GameVersion.SW when pk.Met_Location == Locations.HOME_SWBD => EncounterGenerator8b.GetEncountersFuzzy(pk, chain, GameVersion.BD), - (int)GameVersion.SH when pk.Met_Location == Locations.HOME_SHSP => EncounterGenerator8b.GetEncountersFuzzy(pk, chain, GameVersion.SP), - _ => GetEncountersMainline(pk, chain), - }; + var table = EncounterEvent.MGDB_G8; + foreach (var enc in GetPossibleGifts(chain, table)) + yield return enc; + } + if (groups.HasFlag(Egg)) + { + var eggs = GetEggs(chain, game); + foreach (var enc in eggs) + yield return enc; + } + if (groups.HasFlag(Static)) + { + var table = game == GameVersion.SW ? Encounters8.StaticSW : Encounters8.StaticSH; + foreach (var enc in GetPossibleStatic(chain, table)) + yield return enc; + } + if (groups.HasFlag(Slot)) + { + var areas = game == GameVersion.SW ? Encounters8.SlotsSW : Encounters8.SlotsSH; + foreach (var enc in GetPossibleSlots(chain, areas)) + yield return enc; + } + if (groups.HasFlag(Trade)) + { + var table = Encounters8.TradeGift_SWSH; + foreach (var enc in GetPossibleTrades(chain, game, table)) + yield return enc; + } } - private static IEnumerable GetEncountersMainline(PKM pk, EvoCriteria[] chain) + private static IEnumerable GetPossibleGifts(EvoCriteria[] chain, IReadOnlyList table) { - int ctr = 0; - var game = (GameVersion)pk.Version; + foreach (var enc in table) + { + foreach (var evo in chain) + { + if (evo.Species != enc.Species) + continue; + yield return enc; + break; + } + } + } + private static IEnumerable GetPossibleStatic(EvoCriteria[] chain, EncounterStatic[] table) + { + foreach (var enc in table) + { + foreach (var evo in chain) + { + if (evo.Species != enc.Species) + continue; + yield return enc; + break; + } + } + } + + private static IEnumerable GetPossibleSlots(EvoCriteria[] chain, EncounterArea8[] areas) + { + foreach (var area in areas) + { + foreach (var slot in area.Slots) + { + foreach (var evo in chain) + { + if (evo.Species != slot.Species) + continue; + yield return slot; + break; + } + } + } + } + + private static IEnumerable GetPossibleTrades(EvoCriteria[] chain, GameVersion game, EncounterTrade8[] table) + { + foreach (var enc in table) + { + if (enc.Version != GameVersion.SWSH && game != enc.Version) + continue; + + foreach (var evo in chain) + { + if (evo.Species != enc.Species) + continue; + yield return enc; + break; + } + } + } + + public IEnumerable GetEncounters(PKM pk, EvoCriteria[] chain, LegalInfo info) + { if (pk.FatefulEncounter) { - foreach (var z in GetValidGifts(pk, chain, game)) - { yield return z; ++ctr; } - if (ctr != 0) yield break; + bool yielded = false; + foreach (var z in EncounterEvent.MGDB_G8) + { + foreach (var evo in chain) + { + if (evo.Species != z.Species) + continue; + if (!z.IsMatchExact(pk, evo)) + break; + + yield return z; + yielded = true; + break; + } + } + if (yielded) + yield break; } + var game = (GameVersion)pk.Version; if (Locations.IsEggLocationBred6(pk.Egg_Location)) { - foreach (var z in GenerateEggs(pk, 8)) - { yield return z; ++ctr; } - if (ctr == 0) yield break; + bool yielded = false; + var eggs = GetEggs(chain, game); + foreach (var egg in eggs) + { yield return egg; yielded = true; } + if (yielded) yield break; + } + + // Trades + if (pk.Met_Location == Locations.LinkTrade6NPC) + { + foreach (var enc in GetEncountersTrade(pk, chain, game)) + yield return enc; + yield break; } IEncounterable? cache = null; EncounterMatchRating rating = MaxNotMatch; - // Trades - if (pk.Met_Location == Locations.LinkTrade6NPC) + // Static Encounters can collide with wild encounters (close match); don't break if a Static Encounter is yielded. + var encStatic = game == GameVersion.SW ? Encounters8.StaticSW : Encounters8.StaticSH; + foreach (var enc in encStatic) { - foreach (var z in GetValidEncounterTrades(pk, chain, game)) + foreach (var evo in chain) { + if (evo.Species != enc.Species) + continue; + if (!enc.IsMatchExact(pk, evo)) + break; + + var match = enc.GetMatchRating(pk); + if (match == Match) + { + yield return enc; + } + else if (match < rating) + { + cache = enc; + rating = match; + } + break; + } + } + + // Wild Encounters + if (CanBeWildEncounter(pk)) + { + var location = pk.Met_Location; + var areas = game == GameVersion.SW ? Encounters8.SlotsSW : Encounters8.SlotsSH; + foreach (var area in areas) + { + if (!area.IsMatchLocation(location)) + continue; + + var slots = area.GetMatchingSlots(pk, chain); + foreach (var slot in slots) + { + var match = slot.GetMatchRating(pk); + if (match == Match) + { + yield return slot; + } + else if (match < rating) + { + cache = slot; + rating = match; + } + break; + } + } + } + + if (cache != null) + yield return cache; + } + + private static IEnumerable GetEncountersTrade(PKM pk, EvoCriteria[] chain, GameVersion game) + { + EncounterMatchRating rating = MaxNotMatch; + IEncounterable? cache = null; + foreach (var z in Encounters8.TradeGift_SWSH) + { + if (z.Version != GameVersion.SWSH && z.Version != game) + continue; + + foreach (var evo in chain) + { + if (evo.Species != z.Species) + continue; + if (!z.IsMatchExact(pk, evo)) + break; + var match = z.GetMatchRating(pk); if (match == Match) { @@ -63,44 +233,70 @@ internal static class EncounterGenerator8 cache = z; rating = match; } - } - - if (cache != null) - yield return cache; - yield break; - } - - // Static Encounters can collide with wild encounters (close match); don't break if a Static Encounter is yielded. - var encs = GetValidStaticEncounter(pk, chain, game); - foreach (var z in encs) - { - var match = z.GetMatchRating(pk); - if (match == Match) - { - yield return z; - } - else if (match < rating) - { - cache = z; - rating = match; - } - } - - foreach (var z in GetValidWildEncounters(pk, chain, game)) - { - var match = z.GetMatchRating(pk); - if (match == Match) - { - yield return z; - } - else if (match < rating) - { - cache = z; - rating = match; + break; } } if (cache != null) yield return cache; } + + private const int Generation = 8; + private const EntityContext Context = EntityContext.Gen8; + private const byte EggLevel = 1; + + private static IEnumerable GetEggs(EvoCriteria[] chain, GameVersion version) + { + var devolved = chain[^1]; + + // Ensure most devolved species is the same as the egg species. + var (species, form) = GetBaby(devolved); + if (species != devolved.Species && !IsValidBabySpecies(devolved.Species)) + yield break; // not a split-breed. + + // Sanity Check 1 + if (!Breeding.CanHatchAsEgg(species)) + yield break; + // Sanity Check 2 + if (!Breeding.CanHatchAsEgg(species, form, Context)) + yield break; + // Sanity Check 3 + if (!PersonalTable.SWSH.IsPresentInGame(species, form)) + yield break; + + yield return CreateEggEncounter(species, form, version); + + // Check for split-breed + if (species == devolved.Species) + { + if (chain.Length < 2) + yield break; // no split-breed + devolved = chain[^2]; + } + var splitSet = Breeding.GetSplitBreedGeneration(Generation); + if (splitSet is null) + yield break; // Shouldn't happen. + if (!splitSet.Contains(devolved.Species)) + yield break; + + yield return CreateEggEncounter(devolved.Species, devolved.Form, version); + } + + private static bool IsValidBabySpecies(ushort species) + { + var split = Breeding.GetSplitBreedGeneration(Generation); + return split is not null && split.Contains(species); + } + + private static EncounterEgg CreateEggEncounter(ushort species, byte form, GameVersion version) + { + if (FormInfo.IsBattleOnlyForm(species, form, Generation) || species is (int)Species.Rotom or (int)Species.Castform) + form = FormInfo.GetOutOfBattleForm(species, form, Generation); + return new EncounterEgg(species, form, EggLevel, Generation, version, Context); + } + + private static (ushort Species, byte Form) GetBaby(EvoCriteria lowest) + { + return EvolutionTree.Evolves8.GetBaseSpeciesForm(lowest.Species, lowest.Form); + } } diff --git a/PKHeX.Core/Legality/Encounters/Generator/ByGeneration/EncounterGenerator8GO.cs b/PKHeX.Core/Legality/Encounters/Generator/ByGeneration/EncounterGenerator8GO.cs new file mode 100644 index 000000000..30f358173 --- /dev/null +++ b/PKHeX.Core/Legality/Encounters/Generator/ByGeneration/EncounterGenerator8GO.cs @@ -0,0 +1,79 @@ +using System.Collections.Generic; + +using static PKHeX.Core.EncounterStateUtil; +using static PKHeX.Core.EncounterTypeGroup; +using static PKHeX.Core.EncounterMatchRating; + +namespace PKHeX.Core; + +public sealed class EncounterGenerator8GO : IEncounterGenerator +{ + public static readonly EncounterGenerator8GO Instance = new(); + + public IEnumerable GetPossible(PKM pk, EvoCriteria[] chain, GameVersion game, EncounterTypeGroup groups) + { + if (groups.HasFlag(Slot)) + { + var table = EncountersGO.SlotsGO; + foreach (var enc in GetPossibleSlots(chain, table)) + yield return enc; + } + } + + private static IEnumerable GetPossibleSlots(EvoCriteria[] chain, EncounterArea8g[] table) + { + foreach (var area in table) + { + foreach (var evo in chain) + { + if (area.Species != evo.Species) + continue; + + foreach (var slot in area.Slots) + yield return slot; + break; + } + } + } + + public IEnumerable GetEncounters(PKM pk, EvoCriteria[] chain, LegalInfo info) + { + if (pk.TSV == 0) // HOME doesn't assign TSV=0 to accounts. + yield break; + if (!CanBeWildEncounter(pk)) + yield break; + + IEncounterable? deferred = null; + IEncounterable? partial = null; + + bool yielded = false; + foreach (var area in EncountersGO.SlotsGO) + { + foreach (var evo in chain) + { + if (area.Species != evo.Species) + continue; + + var slots = area.GetMatchingSlots(pk, evo); + foreach (var z in slots) + { + var match = z.GetMatchRating(pk); + switch (match) + { + case Match: yield return z; yielded = true; break; + case Deferred: deferred ??= z; break; + case PartialMatch: partial ??= z; break; + } + } + break; + } + } + if (yielded) + yield break; + + if (deferred != null) + yield return deferred; + else if (partial != null) + yield return partial; + } +} diff --git a/PKHeX.Core/Legality/Encounters/Generator/ByGeneration/EncounterGenerator8a.cs b/PKHeX.Core/Legality/Encounters/Generator/ByGeneration/EncounterGenerator8a.cs index 94c974eac..fd1356a63 100644 --- a/PKHeX.Core/Legality/Encounters/Generator/ByGeneration/EncounterGenerator8a.cs +++ b/PKHeX.Core/Legality/Encounters/Generator/ByGeneration/EncounterGenerator8a.cs @@ -1,59 +1,165 @@ using System.Collections.Generic; -using static PKHeX.Core.MysteryGiftGenerator; -using static PKHeX.Core.EncounterSlotGenerator; -using static PKHeX.Core.EncounterStaticGenerator; +using static PKHeX.Core.EncounterStateUtil; +using static PKHeX.Core.EncounterTypeGroup; using static PKHeX.Core.EncounterMatchRating; namespace PKHeX.Core; -internal static class EncounterGenerator8a +public sealed class EncounterGenerator8a : IEncounterGenerator { - public static IEnumerable GetEncounters(PKM pk, EvoCriteria[] chain) + public static readonly EncounterGenerator8a Instance = new(); + + public IEnumerable GetPossible(PKM pk, EvoCriteria[] chain, GameVersion game, EncounterTypeGroup groups) + { + if (groups.HasFlag(Mystery)) + { + var table = EncounterEvent.MGDB_G8A; + foreach (var enc in GetPossibleGifts(chain, table)) + yield return enc; + } + if (groups.HasFlag(Static)) + { + var table = Encounters8a.StaticLA; + foreach (var enc in GetPossibleStatic(chain, table)) + yield return enc; + } + + if (groups.HasFlag(Slot)) + { + var areas = Encounters8a.SlotsLA; + foreach (var enc in GetPossibleSlots(chain, areas)) + yield return enc; + } + } + + private static IEnumerable GetPossibleGifts(EvoCriteria[] chain, IReadOnlyList table) + { + foreach (var e in table) + { + foreach (var evo in chain) + { + if (evo.Species != e.Species) + continue; + yield return e; + break; + } + } + } + + private static IEnumerable GetPossibleStatic(EvoCriteria[] chain, EncounterStatic8a[] table) + { + foreach (var e in table) + { + foreach (var evo in chain) + { + if (evo.Species != e.Species) + continue; + yield return e; + break; + } + } + } + + private static IEnumerable GetPossibleSlots(EvoCriteria[] chain, EncounterArea8a[] areas) + { + foreach (var area in areas) + { + foreach (var slot in area.Slots) + { + foreach (var evo in chain) + { + if (evo.Species != slot.Species) + continue; + yield return slot; + break; + } + } + } + } + + public IEnumerable GetEncounters(PKM pk, EvoCriteria[] chain, LegalInfo info) { if (pk is PK8 { SWSH: false }) yield break; if (pk.IsEgg) yield break; - int ctr = 0; + // Mystery Gifts + // All gifts are Fateful Encounter, but some Static Encounters are as well. if (pk.FatefulEncounter) { - foreach (var z in GetValidGifts(pk, chain, GameVersion.PLA)) - { yield return z; ++ctr; } - if (ctr != 0) yield break; + // If we yield any Mystery Gifts, we don't need to yield any other encounters. + bool yielded = false; + foreach (var mg in EncounterEvent.MGDB_G8A) + { + foreach (var evo in chain) + { + if (evo.Species != mg.Species) + continue; + + if (mg.IsMatchExact(pk, evo)) + { + yield return mg; + yielded = true; + } + break; + } + } + if (yielded) + yield break; } IEncounterable? cache = null; EncounterMatchRating rating = MaxNotMatch; // Static Encounters can collide with wild encounters (close match); don't break if a Static Encounter is yielded. - var encs = GetValidStaticEncounter(pk, chain, GameVersion.PLA); - foreach (var z in encs) + foreach (var e in Encounters8a.StaticLA) { - var match = z.GetMatchRating(pk); - if (match == Match) + foreach (var evo in chain) { - yield return z; - } - else if (match < rating) - { - cache = z; - rating = match; + if (evo.Species != e.Species) + continue; + if (!e.IsMatchExact(pk, evo)) + continue; + + var match = e.GetMatchRating(pk); + if (match == Match) + { + yield return e; + } + else if (match < rating) + { + cache = e; + rating = match; + } } } - foreach (var z in GetValidWildEncounters(pk, chain, GameVersion.PLA)) + // Encounter Slots + if (CanBeWildEncounter(pk)) { - var match = z.GetMatchRating(pk); - if (match == Match) + bool hasOriginalLocation = pk is not (PK8 or PB8 { Met_Location: Locations.HOME_SWLA }); + var location = pk.Met_Location; + foreach (var area in Encounters8a.SlotsLA) { - yield return z; - } - else if (match < rating) - { - cache = z; - rating = match; + if (hasOriginalLocation && !area.IsMatchLocation(location)) + continue; + + var slots = area.GetMatchingSlots(pk, chain); + foreach (var z in slots) + { + var match = z.GetMatchRating(pk); + if (match == Match) + { + yield return z; + } + else if (match < rating) + { + cache = z; + rating = match; + } + } } } diff --git a/PKHeX.Core/Legality/Encounters/Generator/ByGeneration/EncounterGenerator8b.cs b/PKHeX.Core/Legality/Encounters/Generator/ByGeneration/EncounterGenerator8b.cs index a18e9c9eb..6620d2732 100644 --- a/PKHeX.Core/Legality/Encounters/Generator/ByGeneration/EncounterGenerator8b.cs +++ b/PKHeX.Core/Legality/Encounters/Generator/ByGeneration/EncounterGenerator8b.cs @@ -1,89 +1,209 @@ using System.Collections.Generic; -using static PKHeX.Core.MysteryGiftGenerator; -using static PKHeX.Core.EncounterTradeGenerator; -using static PKHeX.Core.EncounterSlotGenerator; -using static PKHeX.Core.EncounterStaticGenerator; -using static PKHeX.Core.EncounterEggGenerator; +using static PKHeX.Core.EncounterStateUtil; +using static PKHeX.Core.EncounterTypeGroup; using static PKHeX.Core.EncounterMatchRating; namespace PKHeX.Core; -internal static class EncounterGenerator8b +public sealed class EncounterGenerator8b : IEncounterGenerator { - public static IEnumerable GetEncounters(PKM pk, EvoCriteria[] chain) + public static readonly EncounterGenerator8b Instance = new(); + + public IEnumerable GetPossible(PKM _, EvoCriteria[] chain, GameVersion game, EncounterTypeGroup groups) + { + if (groups.HasFlag(Mystery)) + { + var table = EncounterEvent.MGDB_G8B; + foreach (var enc in GetPossibleGifts(chain, table)) + yield return enc; + } + if (groups.HasFlag(Egg)) + { + var eggs = GetEggs(chain, game); + foreach (var enc in eggs) + yield return enc; + } + if (groups.HasFlag(Static)) + { + var table = game == GameVersion.BD ? Encounters8b.StaticBD : Encounters8b.StaticSP; + foreach (var enc in GetPossibleStatic(chain, table)) + yield return enc; + } + if (groups.HasFlag(Slot)) + { + var areas = game == GameVersion.BD ? Encounters8b.SlotsBD : Encounters8b.SlotsSP; + foreach (var enc in GetPossibleSlots(chain, areas)) + yield return enc; + } + if (groups.HasFlag(Trade)) + { + foreach (var enc in GetPossibleTrades(chain, game)) + yield return enc; + } + } + + private static IEnumerable GetPossibleGifts(EvoCriteria[] chain, IReadOnlyList table) + { + foreach (var enc in table) + { + foreach (var evo in chain) + { + if (evo.Species != enc.Species) + continue; + yield return enc; + break; + } + } + } + + private static IEnumerable GetPossibleStatic(EvoCriteria[] chain, EncounterStatic8b[] table) + { + foreach (var enc in table) + { + foreach (var evo in chain) + { + if (evo.Species != enc.Species) + continue; + yield return enc; + break; + } + } + } + + private static IEnumerable GetPossibleSlots(EvoCriteria[] chain, EncounterArea8b[] areas) + { + foreach (var area in areas) + { + foreach (var slot in area.Slots) + { + foreach (var evo in chain) + { + if (evo.Species != slot.Species) + continue; + yield return slot; + break; + } + } + } + } + + private static IEnumerable GetPossibleTrades(EvoCriteria[] chain, GameVersion game) + { + var table = Encounters8b.TradeGift_BDSP; + foreach (var enc in table) + { + if (enc.Version != GameVersion.BDSP && enc.Version != game) + continue; + foreach (var evo in chain) + { + if (evo.Species != enc.Species) + continue; + yield return enc; + break; + } + } + } + + public IEnumerable GetEncounters(PKM pk, EvoCriteria[] chain, LegalInfo info) { if (pk is PK8) yield break; - int ctr = 0; + + bool yielded = false; var game = (GameVersion)pk.Version; if (pk.FatefulEncounter) { - foreach (var z in GetValidGifts(pk, chain, game)) - { yield return z; ++ctr; } - if (ctr != 0) yield break; + foreach (var enc in EncounterEvent.MGDB_G8B) + { + foreach (var evo in chain) + { + if (evo.Species != enc.Species) + continue; + if (!enc.IsMatchExact(pk, evo)) + break; + yield return enc; + yielded = true; + break; + } + } + if (yielded) + yield break; } if (Locations.IsEggLocationBred8b(pk.Egg_Location)) { - foreach (var z in GenerateEggs(pk, 8)) - { yield return z; ++ctr; } - if (ctr == 0) yield break; + var egg = GetEggs(chain, game); + foreach (var enc in egg) + { + yield return enc; + yielded = true; + } + if (yielded) + yield break; } IEncounterable? cache = null; EncounterMatchRating rating = MaxNotMatch; // Trades - if (!pk.IsEgg && pk.Met_Location == Locations.LinkTrade6NPC) + if (pk is { IsEgg: false, Met_Location: Locations.LinkTrade6NPC }) { - foreach (var z in GetValidEncounterTrades(pk, chain, game)) - { - var match = z.GetMatchRating(pk); - if (match == Match) - { - yield return z; - } - else if (match < rating) - { - cache = z; - rating = match; - } - } - - if (cache != null) - yield return cache; + foreach (var enc in GetEncountersTrade(pk, chain, game)) + yield return enc; yield break; } // Static Encounters can collide with wild encounters (close match); don't break if a Static Encounter is yielded. - var encs = GetValidStaticEncounter(pk, chain, game); - foreach (var z in encs) + var encStatic = game == GameVersion.BD ? Encounters8b.StaticBD : Encounters8b.StaticSP; + foreach (var enc in encStatic) { - var match = z.GetMatchRating(pk); - if (match == Match) + foreach (var evo in chain) { - yield return z; - } - else if (match < rating) - { - cache = z; - rating = match; + if (evo.Species != enc.Species) + continue; + if (!enc.IsMatchExact(pk, evo)) + break; + + var match = enc.GetMatchRating(pk); + if (match == Match) + { + yield return enc; + } + else if (match < rating) + { + cache = enc; + rating = match; + } + break; } } - foreach (var z in GetValidWildEncounters(pk, chain, game)) + if (CanBeWildEncounter(pk)) { - var match = z.GetMatchRating(pk); - if (match == Match) + bool hasOriginalLocation = pk is not PK8; + var location = pk.Met_Location; + var encWild = game == GameVersion.BD ? Encounters8b.SlotsBD : Encounters8b.SlotsSP; + foreach (var area in encWild) { - yield return z; - } - else if (match < rating) - { - cache = z; - rating = match; + if (hasOriginalLocation && !area.IsMatchLocation(location)) + continue; + + var slots = area.GetMatchingSlots(pk, chain); + foreach (var slot in slots) + { + var match = slot.GetMatchRating(pk); + if (match == Match) + { + yield return slot; + } + else if (match < rating) + { + cache = slot; + rating = match; + } + } } } @@ -91,18 +211,67 @@ internal static class EncounterGenerator8b yield return cache; } - public static IEnumerable GetEncountersFuzzy(PKM pk, EvoCriteria[] chain, GameVersion game) + private static IEnumerable GetEncountersTrade(PKM pk, EvoCriteria[] chain, GameVersion game) { - int ctr = 0; - - if (pk.FatefulEncounter) + bool yielded = false; + EncounterMatchRating rating = MaxNotMatch; + IEncounterable? cache = null; + foreach (var enc in Encounters8b.TradeGift_BDSP) { - foreach (var z in GetValidGifts(pk, chain, game)) - { yield return z; ++ctr; } - if (ctr != 0) yield break; + if (enc.Version != GameVersion.BDSP && enc.Version != game) + continue; + foreach (var evo in chain) + { + if (evo.Species != enc.Species) + continue; + if (!enc.IsMatchExact(pk, evo)) + break; + + var match = enc.GetMatchRating(pk); + if (match == Match) + { + yield return enc; + yielded = true; + } + else if (match < rating) + { + cache = enc; + rating = match; + } + + break; + } } - var wasEgg = pk.Egg_Location switch + if (yielded) + yield break; + if (cache != null) + yield return cache; + } + + public IEnumerable GetEncountersSWSH(PKM pk, EvoCriteria[] chain, GameVersion game) + { + bool yielded = false; + if (pk.FatefulEncounter) + { + foreach (var enc in EncounterEvent.MGDB_G8B) + { + foreach (var evo in chain) + { + if (evo.Species != enc.Species) + continue; + if (!enc.IsMatchExact(pk, evo)) + break; + yield return enc; + yielded = true; + break; + } + } + if (yielded) + yield break; + } + + bool wasEgg = pk.Egg_Location switch { Locations.HOME_SWSHBDSPEgg => true, // Regular hatch location (not link trade) Locations.HOME_SWBD => pk.Met_Location == Locations.HOME_SWBD, // Link Trade transferred over must match Met Location @@ -111,9 +280,14 @@ internal static class EncounterGenerator8b }; if (wasEgg && pk.Met_Level == 1) { - foreach (var z in GenerateEggs(pk, 8)) - { yield return z; ++ctr; } - if (ctr == 0) yield break; + var egg = GetEggs(chain, game); + foreach (var enc in egg) + { + yield return enc; + yielded = true; + } + if (yielded) + yield break; } IEncounterable? cache = null; @@ -122,60 +296,141 @@ internal static class EncounterGenerator8b // Trades if (!pk.IsEgg) { - foreach (var z in GetValidEncounterTrades(pk, chain, game)) + foreach (var enc in Encounters8b.TradeGift_BDSP) { - var match = z.GetMatchRating(pk); - if (match == Match) + if (enc.Version != GameVersion.BDSP && enc.Version != game) + continue; + foreach (var evo in chain) { - yield return z; - } - else if (match < rating) - { - cache = z; - rating = match; + if (evo.Species != enc.Species) + continue; + if (!enc.IsMatchExact(pk, evo)) + break; + + var match = enc.GetMatchRating(pk); + if (match == Match) + { + yield return enc; + } + else if (match < rating) + { + cache = enc; + rating = match; + } + break; } } - - if (cache != null) - yield return cache; } // Static Encounters can collide with wild encounters (close match); don't break if a Static Encounter is yielded. - var encs = GetValidStaticEncounter(pk, chain, game); - foreach (var z in encs) + var encStatic = game == GameVersion.BD ? Encounters8b.StaticBD : Encounters8b.StaticSP; + foreach (var enc in encStatic) { - var match = z.GetMatchRating(pk); - if (match == Match) + foreach (var evo in chain) { - yield return z; - } - else if (match < rating) - { - cache = z; - rating = match; + if (evo.Species != enc.Species) + continue; + if (!enc.IsMatchExact(pk, evo)) + break; + + var match = enc.GetMatchRating(pk); + if (match == Match) + { + yield return enc; + } + else if (match < rating) + { + cache = enc; + rating = match; + } + break; } } // Only yield if Safari and Marsh encounters match. bool safari = pk is PK8 { Ball: (int)Ball.Safari }; - foreach (var z in GetValidWildEncounters(pk, chain, game)) + var encWild = game == GameVersion.BD ? Encounters8b.SlotsBD : Encounters8b.SlotsSP; + foreach (var area in encWild) { - var marsh = Locations.IsSafariZoneLocation8b(z.Location); - var match = z.GetMatchRating(pk); - if (safari != marsh) - match = DeferredErrors; - if (match == Match) + var slots = area.GetMatchingSlots(pk, chain); + foreach (var slot in slots) { - yield return z; - } - else if (match < rating) - { - cache = z; - rating = match; + var match = slot.GetMatchRating(pk); + var marsh = Locations.IsSafariZoneLocation8b(area.Location); + if (safari != marsh) + match = DeferredErrors; + if (match == Match) + { + yield return slot; + } + else if (match < rating) + { + cache = slot; + rating = match; + } } } if (cache != null) yield return cache; } + + private const int Generation = 8; + private const EntityContext Context = EntityContext.Gen8b; + private const byte EggLevel = 1; + + private static IEnumerable GetEggs(EvoCriteria[] chain, GameVersion version) + { + var devolved = chain[^1]; + + // Ensure most devolved species is the same as the egg species. + var (species, form) = GetBaby(devolved); + if (species != devolved.Species && !IsValidBabySpecies(devolved.Species)) + yield break; // not a split-breed. + + // Sanity Check 1 + if (!Breeding.CanHatchAsEgg(species)) + yield break; + // Sanity Check 2 + if (!Breeding.CanHatchAsEgg(species, form, Context)) + yield break; + // Sanity Check 3 + if (!PersonalTable.BDSP.IsPresentInGame(species, form)) + yield break; + + yield return CreateEggEncounter(species, form, version); + + // Check for split-breed + if (species == devolved.Species) + { + if (chain.Length < 2) + yield break; // no split-breed + devolved = chain[^2]; + } + var splitSet = Breeding.GetSplitBreedGeneration(Generation); + if (splitSet is null) + yield break; // Shouldn't happen. + if (!splitSet.Contains(devolved.Species)) + yield break; + + yield return CreateEggEncounter(devolved.Species, devolved.Form, version); + } + + private static bool IsValidBabySpecies(ushort species) + { + var split = Breeding.GetSplitBreedGeneration(Generation); + return split is not null && split.Contains(species); + } + + private static EncounterEgg CreateEggEncounter(ushort species, byte form, GameVersion version) + { + if (FormInfo.IsBattleOnlyForm(species, form, Generation) || species is (int)Species.Rotom or (int)Species.Castform) + form = FormInfo.GetOutOfBattleForm(species, form, Generation); + return new EncounterEgg(species, form, EggLevel, Generation, version, Context); + } + + private static (ushort Species, byte Form) GetBaby(EvoCriteria lowest) + { + return EvolutionTree.Evolves8b.GetBaseSpeciesForm(lowest.Species, lowest.Form); + } } diff --git a/PKHeX.Core/Legality/Encounters/Generator/ByGeneration/EncounterGenerator9.cs b/PKHeX.Core/Legality/Encounters/Generator/ByGeneration/EncounterGenerator9.cs index eeed05fcc..7608b91b8 100644 --- a/PKHeX.Core/Legality/Encounters/Generator/ByGeneration/EncounterGenerator9.cs +++ b/PKHeX.Core/Legality/Encounters/Generator/ByGeneration/EncounterGenerator9.cs @@ -1,40 +1,155 @@ using System.Collections.Generic; -using static PKHeX.Core.MysteryGiftGenerator; -using static PKHeX.Core.EncounterTradeGenerator; -using static PKHeX.Core.EncounterSlotGenerator; -using static PKHeX.Core.EncounterStaticGenerator; -using static PKHeX.Core.EncounterEggGenerator; +using static PKHeX.Core.EncounterStateUtil; +using static PKHeX.Core.EncounterTypeGroup; using static PKHeX.Core.EncounterMatchRating; namespace PKHeX.Core; -internal static class EncounterGenerator9 +public sealed class EncounterGenerator9 : IEncounterGenerator { - public static IEnumerable GetEncounters(PKM pk) + public static readonly EncounterGenerator9 Instance = new(); + + public IEnumerable GetEncounters(PKM pk, LegalInfo info) { var chain = EncounterOrigin.GetOriginChain(pk); - return GetEncounters(pk, chain); + return GetEncounters(pk, chain, info); } - private static IEnumerable GetEncounters(PKM pk, EvoCriteria[] chain) + public IEnumerable GetPossible(PKM pk, EvoCriteria[] chain, GameVersion game, EncounterTypeGroup groups) { - int ctr = 0; - var game = (GameVersion)pk.Version; + if (groups.HasFlag(Mystery)) + { + var table = EncounterEvent.MGDB_G9; + foreach (var enc in GetPossibleEvents(chain, table)) + yield return enc; + } + if (groups.HasFlag(Egg)) + { + var eggs = GetEggs(pk, chain, game); + foreach (var enc in eggs) + yield return enc; + } + if (groups.HasFlag(Static)) + { + var table = game == GameVersion.SL ? Encounters9.StaticSL : Encounters9.StaticVL; + foreach (var enc in GetPossibleStatic(chain, table)) + yield return enc; + } + if (groups.HasFlag(Slot)) + { + var areas = Encounters9.Slots; + foreach (var enc in GetPossibleSlots(chain, areas)) + yield return enc; + } + if (groups.HasFlag(Trade)) + { + var table = Encounters9.TradeGift_SV; + foreach (var enc in GetPossibleTrade(chain, table, game)) + yield return enc; + } + } + private static IEnumerable GetPossibleEvents(EvoCriteria[] chain, IReadOnlyList table) + { + foreach (var enc in table) + { + foreach (var evo in chain) + { + if (evo.Species != enc.Species) + continue; + yield return enc; + break; + } + } + } + + private static IEnumerable GetPossibleStatic(EvoCriteria[] chain, EncounterStatic[] table) + { + foreach (var enc in table) + { + foreach (var evo in chain) + { + if (evo.Species != enc.Species) + continue; + yield return enc; + break; + } + } + } + + private static IEnumerable GetPossibleSlots(EvoCriteria[] chain, EncounterArea9[] areas) + { + foreach (var area in areas) + { + foreach (var slot in area.Slots) + { + foreach (var evo in chain) + { + if (evo.Species != slot.Species) + continue; + yield return slot; + break; + } + } + } + } + + private static IEnumerable GetPossibleTrade(EvoCriteria[] chain, EncounterTrade9[] table, GameVersion game) + { + foreach (var enc in table) + { + if (enc.Version != GameVersion.SV && enc.Version != game) + continue; + + foreach (var evo in chain) + { + if (evo.Species != enc.Species) + continue; + yield return enc; + break; + } + } + } + + public IEnumerable GetEncounters(PKM pk, EvoCriteria[] chain, LegalInfo info) + { if (pk.FatefulEncounter) { - foreach (var z in GetValidGifts(pk, chain, game)) - { yield return z; ++ctr; } - if (ctr != 0) yield break; + bool yielded = false; + foreach (var mg in EncounterEvent.MGDB_G9) + { + foreach (var evo in chain) + { + if (evo.Species != mg.Species) + continue; + + if (mg.IsMatchExact(pk, evo)) + { + yield return mg; + yielded = true; + } + break; + } + } + if (yielded) + yield break; } + var game = (GameVersion)pk.Version; + // While an unhatched picnic egg, the Version remains 0. - if (Locations.IsEggLocationBred9(pk.Egg_Location) && !(pk.IsEgg && pk.Version != 0)) + if (Locations.IsEggLocationBred9(pk.Egg_Location) && !(pk.IsEgg && game != 0)) { - foreach (var z in GenerateEggs(pk, 9)) - { yield return z; ++ctr; } - if (ctr == 0) yield break; + bool yielded = false; + var eggs = GetEggs(pk, chain, game); + foreach (var egg in eggs) + { + yield return egg; + yielded = true; + } + if (yielded) + yield break; } IEncounterable? cache = null; @@ -43,20 +158,30 @@ internal static class EncounterGenerator9 // Trades if (pk.Met_Location == Locations.LinkTrade6NPC) { - foreach (var z in GetValidEncounterTrades(pk, chain, game)) + foreach (var z in Encounters9.TradeGift_SV) { - var match = z.GetMatchRating(pk); - if (match == Match) + foreach (var evo in chain) { - yield return z; - } - else if (match < rating) - { - cache = z; - rating = match; + if (z.Version != GameVersion.SV && z.Version != game) + continue; + if (evo.Species != z.Species) + continue; + if (!z.IsMatchExact(pk, evo)) + break; + + var match = z.GetMatchRating(pk); + if (match == Match) + { + yield return z; + } + else if (match < rating) + { + cache = z; + rating = match; + } + break; } } - if (cache != null) yield return cache; yield break; @@ -64,39 +189,101 @@ internal static class EncounterGenerator9 if (pk is not IRibbonIndex r || !r.HasEncounterMark()) { - var encs = GetValidStaticEncounter(pk, chain, game); - foreach (var z in encs) + var encStatic = game == GameVersion.SL ? Encounters9.StaticSL : Encounters9.StaticVL; + foreach (var z in encStatic) { - var match = z.GetMatchRating(pk); - if (match == Match) + foreach (var evo in chain) { - yield return z; - } - else if (match < rating) - { - cache = z; - rating = match; + if (evo.Species != z.Species) + continue; + if (!z.IsMatchExact(pk, evo)) + break; + + var match = z.GetMatchRating(pk); + if (match == Match) + { + yield return z; + } + else if (match < rating) + { + cache = z; + rating = match; + } + break; } } } // Wild encounters are more permissive than static encounters. // Can have encounter marks, can have varied scales/shiny states. - foreach (var z in GetValidWildEncounters(pk, chain, game)) + if (CanBeWildEncounter(pk)) { - var match = z.GetMatchRating(pk); - if (match == Match) + var location = pk.Met_Location; + var areas = Encounters9.Slots; + foreach (var area in areas) { - yield return z; - } - else if (match < rating) - { - cache = z; - rating = match; + if (!area.IsMatchLocation(location)) + continue; + + var slots = area.GetMatchingSlots(pk, chain); + foreach (var slot in slots) + { + var match = slot.GetMatchRating(pk); + if (match == Match) + { + yield return slot; + } + else if (match < rating) + { + cache = slot; + rating = match; + } + } } } if (cache != null) yield return cache; } + + private const int Generation = 9; + private const EntityContext Context = EntityContext.Gen9; + private const byte EggLevel = 1; + + private static IEnumerable GetEggs(PKM pk, EvoCriteria[] chain, GameVersion version) + { + var devolved = chain[^1]; + if (version == 0 && pk.IsEgg) + version = GameVersion.SL; + + // Ensure most devolved species is the same as the egg species. + // No split-breed to consider. + var (species, form) = GetBaby(devolved); + if (species != devolved.Species) + yield break; // no split-breed. + + // Sanity Check 1 + if (!Breeding.CanHatchAsEgg(species)) + yield break; + // Sanity Check 2 + if (!Breeding.CanHatchAsEgg(species, form, Context)) + yield break; + // Sanity Check 3 + if (!PersonalTable.SV.IsPresentInGame(species, form)) + yield break; + + yield return CreateEggEncounter(species, form, version); + } + + private static EncounterEgg CreateEggEncounter(ushort species, byte form, GameVersion version) + { + if (FormInfo.IsBattleOnlyForm(species, form, Generation) || species is (int)Species.Rotom or (int)Species.Castform) + form = FormInfo.GetOutOfBattleForm(species, form, Generation); + return new EncounterEgg(species, form, EggLevel, Generation, version, Context); + } + + private static (ushort Species, byte Form) GetBaby(EvoCriteria lowest) + { + return EvolutionTree.Evolves9.GetBaseSpeciesForm(lowest.Species, lowest.Form); + } } diff --git a/PKHeX.Core/Legality/Encounters/Generator/ByGeneration/EncounterStateUtil.cs b/PKHeX.Core/Legality/Encounters/Generator/ByGeneration/EncounterStateUtil.cs new file mode 100644 index 000000000..4de5f0e83 --- /dev/null +++ b/PKHeX.Core/Legality/Encounters/Generator/ByGeneration/EncounterStateUtil.cs @@ -0,0 +1,20 @@ +namespace PKHeX.Core; + +public static class EncounterStateUtil +{ + public static bool CanBeWildEncounter(PKM pk) + { + if (pk.IsEgg) + return false; + if (IsMetAsEgg(pk)) + return false; + return true; + } + + public static bool IsMetAsEgg(PKM pk) => pk switch + { + PA8 or PK8 => pk.Egg_Location is not 0 || pk is { BDSP: true, Egg_Day: not 0 }, + PB8 pb8 => pb8.Egg_Location is not Locations.Default8bNone, + _ => pk.Egg_Location is not 0, + }; +} diff --git a/PKHeX.Core/Legality/Encounters/Generator/ByGeneration/Lump/EncounterGenerator12.cs b/PKHeX.Core/Legality/Encounters/Generator/ByGeneration/Lump/EncounterGenerator12.cs new file mode 100644 index 000000000..663e660f7 --- /dev/null +++ b/PKHeX.Core/Legality/Encounters/Generator/ByGeneration/Lump/EncounterGenerator12.cs @@ -0,0 +1,125 @@ +using System.Collections.Generic; +using static PKHeX.Core.EncounterMatchRating; + +namespace PKHeX.Core; + +/// +/// Dual-generator implementation to yield from multiple sets of games at the same time. +/// +public sealed class EncounterGenerator12 : IEncounterGenerator +{ + public static readonly EncounterGenerator12 Instance = new(); + + public IEnumerable GetEncounters(PKM pk, LegalInfo info) + { + foreach (var z in GetEncounters(pk)) + { + info.StoreMetadata(z.Generation); + yield return z; + } + } + + private static IEnumerable GetEncounters(PKM pk) + { + // If the current data indicates that it must have originated from Crystal, only yield encounter data from Crystal. + bool crystal = pk is ICaughtData2 { CaughtData: not 0 } or { Format: >= 7, OT_Gender: 1 }; + if (crystal) + return EncounterGenerator2.Instance.GetEncounters(pk, GameVersion.C); + + var visited = GBRestrictions.GetTradebackStatusInitial(pk); + return visited switch + { + PotentialGBOrigin.Gen1Only => EncounterGenerator1.Instance.GetEncounters(pk, GameVersion.RBY), + PotentialGBOrigin.Gen2Only => EncounterGenerator2.Instance.GetEncounters(pk, GameVersion.GSC), + _ when pk.Korean => GenerateFilteredEncounters12BothKorean(pk), + _ => GenerateFilteredEncounters12Both(pk), + }; + } + + private static IEnumerable GenerateFilteredEncounters12BothKorean(PKM pk) + { + // Korean origin PK1/PK2 can only originate from GS, but since we're nice we'll defer & yield matches from other games. + // Yield GS first, then Crystal, then RBY. Anything other than GS will be flagged by later checks. + + var deferred = new List(); + var get2 = EncounterGenerator2.Instance.GetEncounters(pk, GameVersion.GSC); + foreach (var enc in get2) + { + if (enc.Version == GameVersion.C) + deferred.Add(enc); + else + yield return enc; + } + + foreach (var enc in deferred) + yield return enc; + + var get1 = EncounterGenerator1.Instance.GetEncounters(pk, GameVersion.RBY); + foreach (var enc in get1) + yield return enc; + } + + private static IEnumerable GenerateFilteredEncounters12Both(PKM pk) + { + // Iterate over both games, consuming from one list at a time until the other list has higher priority encounters + // Buffer the encounters so that we can consume each iterator separately + var get1 = EncounterGenerator1.Instance.GetEncounters(pk, GameVersion.RBY); + var get2 = EncounterGenerator2.Instance.GetEncounters(pk, GameVersion.GSC); + using var g1i = new PeekEnumerator(get1); + using var g2i = new PeekEnumerator(get2); + while (g2i.PeekIsNext() || g1i.PeekIsNext()) + { + var iter = PickPreferredIterator(pk, g1i, g2i); + yield return iter.Current; + iter.MoveNext(); + } + } + + private static PeekEnumerator PickPreferredIterator(PKM pk, PeekEnumerator g1i, PeekEnumerator g2i) + { + if (!g1i.PeekIsNext()) + return g2i; + if (!g2i.PeekIsNext()) + return g1i; + var p1 = GetGBEncounterPriority(pk, g1i.Current); + var p2 = GetGBEncounterPriority(pk, g2i.Current); + return p1 > p2 ? g1i : g2i; + } + + private static GBEncounterPriority GetGBEncounterPriority(PKM pk, IEncounterTemplate enc) => enc switch + { + EncounterTrade1 t1 when t1.GetMatchRating(pk) != Match => GBEncounterPriority.Least, + EncounterTrade1 => GBEncounterPriority.TradeEncounterG1, + EncounterTrade2 => GBEncounterPriority.TradeEncounterG2, + EncounterSlot1 or EncounterSlot2 => GBEncounterPriority.WildEncounter, + EncounterEgg => GBEncounterPriority.EggEncounter, + _ => GBEncounterPriority.StaticEncounter, + }; + + /// + /// Generation 1/2 Encounter Data type, which serves as a 'best match' priority rating when returning from a list. + /// + private enum GBEncounterPriority + { + Least, + EggEncounter, + WildEncounter, + StaticEncounter, + TradeEncounterG1, + TradeEncounterG2, + } + + public IEnumerable GetEncounters(PKM pk, EvoCriteria[] chain, LegalInfo info) + { + // Don't call this method. + return GetEncounters(pk, info); + } + + public IEnumerable GetPossible(PKM pk, EvoCriteria[] chain, GameVersion game, EncounterTypeGroup groups) + { + // Don't call this method. + if (game.GetGeneration() == 1) + return EncounterGenerator1.Instance.GetPossible(pk, chain, game, groups); + return EncounterGenerator2.Instance.GetPossible(pk, chain, game, groups); + } +} diff --git a/PKHeX.Core/Legality/Encounters/Generator/ByGeneration/Lump/EncounterGenerator7X.cs b/PKHeX.Core/Legality/Encounters/Generator/ByGeneration/Lump/EncounterGenerator7X.cs new file mode 100644 index 000000000..495ab13e2 --- /dev/null +++ b/PKHeX.Core/Legality/Encounters/Generator/ByGeneration/Lump/EncounterGenerator7X.cs @@ -0,0 +1,28 @@ +using System.Collections.Generic; + +namespace PKHeX.Core; + +public sealed class EncounterGenerator7X : IEncounterGenerator +{ + public static readonly EncounterGenerator7X Instance = new(); + + public IEnumerable GetPossible(PKM pk, EvoCriteria[] chain, GameVersion game, EncounterTypeGroup groups) => pk.Version switch + { + (int)GameVersion.GO => EncounterGenerator7GO.Instance.GetPossible(pk, chain, game, groups), + > (int)GameVersion.GO => EncounterGenerator7GG.Instance.GetPossible(pk, chain, game, groups), + _ => EncounterGenerator7.Instance.GetPossible(pk, chain, game, groups), + }; + + public IEnumerable GetEncounters(PKM pk, LegalInfo info) + { + var chain = EncounterOrigin.GetOriginChain(pk); + return GetEncounters(pk, chain, info); + } + + public IEnumerable GetEncounters(PKM pk, EvoCriteria[] chain, LegalInfo info) => pk.Version switch + { + (int)GameVersion.GO => EncounterGenerator7GO.Instance.GetEncounters(pk, chain, info), + > (int)GameVersion.GO => EncounterGenerator7GG.Instance.GetEncounters(pk, chain, info), + _ => EncounterGenerator7.Instance.GetEncounters(pk, chain, info), + }; +} diff --git a/PKHeX.Core/Legality/Encounters/Generator/ByGeneration/Lump/EncounterGenerator8X.cs b/PKHeX.Core/Legality/Encounters/Generator/ByGeneration/Lump/EncounterGenerator8X.cs new file mode 100644 index 000000000..b0d0f7a8c --- /dev/null +++ b/PKHeX.Core/Legality/Encounters/Generator/ByGeneration/Lump/EncounterGenerator8X.cs @@ -0,0 +1,35 @@ +using System.Collections.Generic; +using static PKHeX.Core.GameVersion; +using static PKHeX.Core.Locations; + +namespace PKHeX.Core; + +public sealed class EncounterGenerator8X : IEncounterGenerator +{ + public static readonly EncounterGenerator8X Instance = new(); + + public IEnumerable GetPossible(PKM pk, EvoCriteria[] chain, GameVersion game, EncounterTypeGroup groups) => game switch + { + GO => EncounterGenerator8GO.Instance.GetPossible(pk, chain, game, groups), + PLA => EncounterGenerator8a.Instance.GetPossible(pk, chain, game, groups), + BD or SP => EncounterGenerator8b.Instance.GetPossible(pk, chain, game, groups), + _ => EncounterGenerator8.Instance.GetPossible(pk, chain, game, groups), + }; + + public IEnumerable GetEncounters(PKM pk, LegalInfo info) + { + var chain = EncounterOrigin.GetOriginChain(pk); + return GetEncounters(pk, chain, info); + } + + public IEnumerable GetEncounters(PKM pk, EvoCriteria[] chain, LegalInfo info) => (GameVersion)pk.Version switch + { + GO => EncounterGenerator8GO.Instance.GetEncounters(pk, chain, info), + PLA => EncounterGenerator8a.Instance.GetEncounters(pk, chain, info), + BD or SP => EncounterGenerator8b.Instance.GetEncounters(pk, chain, info), + SW when pk.Met_Location == HOME_SWLA => EncounterGenerator8a.Instance.GetEncounters(pk, chain, info), + SW when pk.Met_Location == HOME_SWBD => EncounterGenerator8b.Instance.GetEncountersSWSH(pk, chain, BD), + SH when pk.Met_Location == HOME_SHSP => EncounterGenerator8b.Instance.GetEncountersSWSH(pk, chain, SP), + _ => EncounterGenerator8.Instance.GetEncounters(pk, chain, info), + }; +} diff --git a/PKHeX.Core/Legality/Encounters/Generator/ByGeneration/Lump/EncounterGeneratorDummy.cs b/PKHeX.Core/Legality/Encounters/Generator/ByGeneration/Lump/EncounterGeneratorDummy.cs new file mode 100644 index 000000000..67370c73a --- /dev/null +++ b/PKHeX.Core/Legality/Encounters/Generator/ByGeneration/Lump/EncounterGeneratorDummy.cs @@ -0,0 +1,24 @@ +using System; +using System.Collections.Generic; + +namespace PKHeX.Core; + +internal sealed class EncounterGeneratorDummy : IEncounterGenerator +{ + public static readonly EncounterGeneratorDummy Instance = new(); + + public IEnumerable GetPossible(PKM pk, EvoCriteria[] chain, GameVersion game, EncounterTypeGroup groups) + { + return Array.Empty(); + } + + public IEnumerable GetEncounters(PKM pk, EvoCriteria[] chain, LegalInfo info) + { + return Array.Empty(); + } + + public IEnumerable GetEncounters(PKM _, LegalInfo __) + { + return Array.Empty(); + } +} diff --git a/PKHeX.Core/Legality/Encounters/Generator/ByGeneration/Lump/EncounterGeneratorGO.cs b/PKHeX.Core/Legality/Encounters/Generator/ByGeneration/Lump/EncounterGeneratorGO.cs new file mode 100644 index 000000000..415a05726 --- /dev/null +++ b/PKHeX.Core/Legality/Encounters/Generator/ByGeneration/Lump/EncounterGeneratorGO.cs @@ -0,0 +1,30 @@ +using System; +using System.Collections.Generic; + +namespace PKHeX.Core; + +public sealed class EncounterGeneratorGO : IEncounterGenerator +{ + public static readonly EncounterGeneratorGO Instance = new(); + + public IEnumerable GetEncounters(PKM pk, EvoCriteria[] chain, LegalInfo info) + { + var loc = pk.Met_Location; + if (loc == Locations.GO7) + return EncounterGenerator7GO.Instance.GetEncounters(pk, chain, info); + if (loc == Locations.GO8) + return EncounterGenerator8GO.Instance.GetEncounters(pk, chain, info); + return Array.Empty(); + } + + public IEnumerable GetPossible(PKM pk, EvoCriteria[] chain, GameVersion game, EncounterTypeGroup groups) + { + var lgpe = EncounterGenerator7GO.Instance.GetPossible(pk, chain, game, groups); + foreach (var enc in lgpe) + yield return enc; + + var home = EncounterGenerator8GO.Instance.GetPossible(pk, chain, game, groups); + foreach (var enc in home) + yield return enc; + } +} diff --git a/PKHeX.Core/Legality/Encounters/Generator/ByGeneration/Lump/IEncounterGenerator.cs b/PKHeX.Core/Legality/Encounters/Generator/ByGeneration/Lump/IEncounterGenerator.cs new file mode 100644 index 000000000..f5765ba3b --- /dev/null +++ b/PKHeX.Core/Legality/Encounters/Generator/ByGeneration/Lump/IEncounterGenerator.cs @@ -0,0 +1,10 @@ +using System.Collections.Generic; + +namespace PKHeX.Core; + +public interface IEncounterGenerator +{ + IEnumerable GetEncounters(PKM pk, EvoCriteria[] chain, LegalInfo info); + + IEnumerable GetPossible(PKM pk, EvoCriteria[] chain, GameVersion game, EncounterTypeGroup groups); +} diff --git a/PKHeX.Core/Legality/Encounters/Generator/EncounterFinder.cs b/PKHeX.Core/Legality/Encounters/Generator/EncounterFinder.cs index 20f6aeaf8..79663e956 100644 --- a/PKHeX.Core/Legality/Encounters/Generator/EncounterFinder.cs +++ b/PKHeX.Core/Legality/Encounters/Generator/EncounterFinder.cs @@ -66,7 +66,7 @@ public static class EncounterFinder break; } - if (!info.FrameMatches && info.EncounterMatch is EncounterSlot {Version: not GameVersion.CXD}) // if false, all valid RNG frame matches have already been consumed + if (info is { FrameMatches: false, EncounterMatch: EncounterSlot }) // if false, all valid RNG frame matches have already been consumed info.Parse.Add(new CheckResult(ParseSettings.RNGFrameNotFound, LEncConditionBadRNGFrame, CheckIdentifier.PID)); // todo for further confirmation if (!info.PIDIVMatches) // if false, all valid PIDIV matches have already been consumed info.Parse.Add(new CheckResult(Severity.Invalid, LPIDTypeMismatch, CheckIdentifier.PID)); @@ -183,7 +183,7 @@ public static class EncounterFinder { // Event Egg, indistinguishable from normal eggs after hatch // can't tell after transfer - 3 => pk.Format == 3 && pk.IsEgg && Locations.IsEventLocation3(pk.Met_Location), + 3 => pk is { Context: EntityContext.Gen3, IsEgg: true } && Locations.IsEventLocation3(pk.Met_Location), // Manaphy was the only generation 4 released event egg _ => pk.FatefulEncounter && pk.Egg_Day != 0, diff --git a/PKHeX.Core/Legality/Encounters/Generator/EncounterGenerator.cs b/PKHeX.Core/Legality/Encounters/Generator/EncounterGenerator.cs index 2ea8433ba..deaa31fed 100644 --- a/PKHeX.Core/Legality/Encounters/Generator/EncounterGenerator.cs +++ b/PKHeX.Core/Legality/Encounters/Generator/EncounterGenerator.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; namespace PKHeX.Core; @@ -20,15 +19,46 @@ public static class EncounterGenerator /// public static IEnumerable GetEncounters(PKM pk, LegalInfo info) => info.Generation switch { - 1 => EncounterGenerator12.GetEncounters12(pk, info), - 2 => EncounterGenerator12.GetEncounters12(pk, info), - 3 => EncounterGenerator3.GetEncounters(pk, info), - 4 => EncounterGenerator4.GetEncounters(pk, info), - 5 => EncounterGenerator5.GetEncounters(pk), - 6 => EncounterGenerator6.GetEncounters(pk), - 7 => EncounterGenerator7.GetEncounters(pk), - 8 => EncounterGenerator8.GetEncounters(pk), - 9 => EncounterGenerator9.GetEncounters(pk), - _ => Array.Empty(), + 1 => EncounterGenerator12.Instance.GetEncounters(pk, info), + 2 => EncounterGenerator12.Instance.GetEncounters(pk, info), + 3 => pk.Version == (int)GameVersion.CXD + ? EncounterGenerator3GC.Instance.GetEncounters(pk, info) + : EncounterGenerator3.Instance.GetEncounters(pk, info), + 4 => EncounterGenerator4.Instance.GetEncounters(pk, info), + 5 => EncounterGenerator5.Instance.GetEncounters(pk, info), + 6 => EncounterGenerator6.Instance.GetEncounters(pk, info), + 7 => EncounterGenerator7X.Instance.GetEncounters(pk, info), + 8 => EncounterGenerator8X.Instance.GetEncounters(pk, info), + 9 => EncounterGenerator9.Instance.GetEncounters(pk, info), + _ => EncounterGeneratorDummy.Instance.GetEncounters(pk, info), + }; + + public static IEncounterGenerator GetGenerator(GameVersion version) => GetGeneration(version, version.GetGeneration()); + + public static IEncounterGenerator GetGeneration(GameVersion version, int generation) => generation switch + { + 1 => EncounterGenerator1.Instance, + 2 => EncounterGenerator2.Instance, + 3 => version == GameVersion.CXD + ? EncounterGenerator3GC.Instance + : EncounterGenerator3.Instance, + 4 => EncounterGenerator4.Instance, + 5 => EncounterGenerator5.Instance, + 6 => EncounterGenerator6.Instance, + 7 => version switch + { + GameVersion.GP or GameVersion.GE => EncounterGenerator7GG.Instance, + GameVersion.GO => EncounterGeneratorGO.Instance, + _ => EncounterGenerator7.Instance, + }, + 8 => version switch + { + GameVersion.GO => EncounterGeneratorGO.Instance, + GameVersion.PLA => EncounterGenerator8a.Instance, + GameVersion.BD or GameVersion.SP => EncounterGenerator8b.Instance, + _ => EncounterGenerator8.Instance, + }, + 9 => EncounterGenerator9.Instance, + _ => EncounterGeneratorDummy.Instance, }; } diff --git a/PKHeX.Core/Legality/Encounters/Generator/Moveset/EncounterMovesetGenerator.cs b/PKHeX.Core/Legality/Encounters/Generator/Moveset/EncounterMovesetGenerator.cs index ac2b80fea..cb46f8e97 100644 --- a/PKHeX.Core/Legality/Encounters/Generator/Moveset/EncounterMovesetGenerator.cs +++ b/PKHeX.Core/Legality/Encounters/Generator/Moveset/EncounterMovesetGenerator.cs @@ -4,6 +4,7 @@ using System.Buffers; using System.Collections.Generic; using System.Linq; using System.Runtime.CompilerServices; +using static PKHeX.Core.EncounterTypeGroup; namespace PKHeX.Core; @@ -16,12 +17,12 @@ public static class EncounterMovesetGenerator /// Order in which objects are yielded from the generator. /// // ReSharper disable once AutoPropertyCanBeMadeGetOnly.Global - public static IReadOnlyCollection PriorityList { get; set; } = PriorityList = (EncounterOrder[])Enum.GetValues(typeof(EncounterOrder)); + public static IReadOnlyCollection PriorityList { get; set; } = PriorityList = (EncounterTypeGroup[])Enum.GetValues(typeof(EncounterTypeGroup)); /// /// Resets the to the default values. /// - public static void ResetFilters() => PriorityList = (EncounterOrder[])Enum.GetValues(typeof(EncounterOrder)); + public static void ResetFilters() => PriorityList = (EncounterTypeGroup[])Enum.GetValues(typeof(EncounterTypeGroup)); /// /// Gets possible objects that allow all moves requested to be learned. @@ -34,7 +35,10 @@ public static class EncounterMovesetGenerator /// When updating, update the sister method. public static IEnumerable GeneratePKMs(PKM pk, ITrainerInfo info, ushort[] moves, params GameVersion[] versions) { - pk.TID = info.TID; + if (!IsSane(pk, moves)) + yield break; + + pk.TID16 = info.TID16; // Necessary for Gen2 Headbutt encounters. var vers = versions.Length >= 1 ? versions : GameUtil.GetVersionsWithinRange(pk, pk.Format); foreach (var ver in vers) { @@ -63,7 +67,10 @@ public static class EncounterMovesetGenerator /// When updating, update the sister method. public static IEnumerable GenerateEncounters(PKM pk, ITrainerInfo info, ushort[] moves, params GameVersion[] versions) { - pk.TID = info.TID; + if (!IsSane(pk, moves)) + yield break; + + pk.TID16 = info.TID16; // Necessary for Gen2 Headbutt encounters. var vers = versions.Length >= 1 ? versions : GameUtil.GetVersionsWithinRange(pk, pk.Format); foreach (var ver in vers) { @@ -108,6 +115,9 @@ public static class EncounterMovesetGenerator /// A consumable list of possible encounters. public static IEnumerable GenerateEncounters(PKM pk, ushort[] moves, params GameVersion[] versions) { + if (!IsSane(pk, moves)) + yield break; + if (versions.Length > 0) { foreach (var enc in GenerateEncounters(pk, moves, (IReadOnlyList)versions)) @@ -132,6 +142,9 @@ public static class EncounterMovesetGenerator /// A consumable list of possible encounters. public static IEnumerable GenerateEncounters(PKM pk, ushort[] moves, IReadOnlyList vers) { + if (!IsSane(pk, moves)) + yield break; + foreach (var ver in vers) { foreach (var enc in GenerateVersionEncounters(pk, moves, ver)) @@ -146,24 +159,33 @@ public static class EncounterMovesetGenerator /// Moves that the resulting must be able to learn. /// Specific version to iterate for. /// A consumable list of possible encounters. - public static IEnumerable GenerateVersionEncounters(PKM pk, ushort[] moves, GameVersion version) + private static IEnumerable GenerateVersionEncounters(PKM pk, ReadOnlySpan moves, GameVersion version) { - if (pk.Species == 0 || pk.Species > pk.MaxSpeciesID) // can enter this method after failing to set a species ID that cannot exist in the format - return Array.Empty(); - if (AnyMoveOutOfRange(moves, pk.MaxMoveID)) - return Array.Empty(); - if (pk.Species is (int)Species.Smeargle && !IsPlausibleSmeargleMoveset(pk, moves)) - return Array.Empty(); - pk.Version = (int)version; + var context = pk.Context; if (context is EntityContext.Gen2 && version is GameVersion.RD or GameVersion.GN or GameVersion.BU or GameVersion.YW) context = EntityContext.Gen1; // try excluding baby pokemon from our evolution chain, for move learning purposes. var et = EvolutionTree.GetEvolutionTree(context); var chain = et.GetValidPreEvolutions(pk, levelMax: 100, skipChecks: true); - ushort[] needs = GetNeededMoves(pk, moves); - return PriorityList.SelectMany(type => GetPossibleOfType(pk, needs, version, type, chain)); + var needs = GetNeededMoves(pk, moves, version); + var generator = EncounterGenerator.GetGenerator(version); + + return PriorityList.SelectMany(type => GetPossibleOfType(pk, needs, version, type, chain, generator)); + } + + private static bool IsSane(PKM pk, ReadOnlySpan moves) + { + var species = pk.Species; + if ((uint)(species - 1) >= pk.MaxSpeciesID) // can enter this method after failing to set a species ID that cannot exist in the format + return false; + if (AnyMoveOutOfRange(moves, pk.MaxMoveID)) + return false; + if (species is (int)Species.Smeargle && !IsPlausibleSmeargleMoveset(pk.Context, moves)) + return false; + + return true; } private static bool AnyMoveOutOfRange(ReadOnlySpan moves, ushort max) @@ -176,26 +198,25 @@ public static class EncounterMovesetGenerator return false; } - private static bool IsPlausibleSmeargleMoveset(PKM pk, ReadOnlySpan moves) + private static bool IsPlausibleSmeargleMoveset(EntityContext context, ReadOnlySpan moves) { foreach (var move in moves) { - if (!MoveInfo.IsValidSketch(move, pk.Context)) + if (!MoveInfo.IsSketchValid(move, context)) return false; } return true; } - private static ushort[] GetNeededMoves(PKM pk, ReadOnlySpan moves) + private static ushort[] GetNeededMoves(PKM pk, ReadOnlySpan moves, GameVersion ver) { if (pk.Species == (int)Species.Smeargle) return Array.Empty(); // Roughly determine the generation the PKM is originating from - var ver = pk.Version; int origin = pk.Generation; if (origin < 0) - origin = ((GameVersion)ver).GetGeneration(); + origin = ver.GetGeneration(); // Temporarily replace the Version for VC1 transfers, so that they can have VC2 moves if needed. bool vcBump = origin == 1 && pk.Format >= 7; @@ -224,25 +245,23 @@ public static class EncounterMovesetGenerator ArrayPool.Shared.Return(rent); if (vcBump) - pk.Version = ver; + pk.Version = (int)ver; if (ctr == 0) return Array.Empty(); return result[..ctr].ToArray(); } - private static IEnumerable GetPossibleOfType(PKM pk, ushort[] needs, GameVersion version, EncounterOrder type, EvoCriteria[] chain) + private static IEnumerable GetPossibleOfType(PKM pk, ushort[] needs, GameVersion version, EncounterTypeGroup type, EvoCriteria[] chain, IEncounterGenerator generator) + => type switch { - return type switch - { - EncounterOrder.Egg => GetEggs(pk, needs, chain, version), - EncounterOrder.Mystery => GetGifts(pk, needs, chain, version), - EncounterOrder.Static => GetStatic(pk, needs, chain, version), - EncounterOrder.Trade => GetTrades(pk, needs, chain, version), - EncounterOrder.Slot => GetSlots(pk, needs, chain, version), - _ => throw new ArgumentOutOfRangeException(nameof(type), type, null), - }; - } + Egg => GetEggs(pk, needs, chain, version, generator), + Mystery => GetGifts(pk, needs, chain, version, generator), + Static => GetStatic(pk, needs, chain, version, generator), + Trade => GetTrades(pk, needs, chain, version, generator), + Slot => GetSlots(pk, needs, chain, version, generator), + _ => throw new ArgumentOutOfRangeException(nameof(type), type, null), + }; /// /// Gets possible encounters that allow all moves requested to be learned. @@ -251,15 +270,14 @@ public static class EncounterMovesetGenerator /// Moves which cannot be taught by the player. /// Origin possible evolution chain /// Specific version to iterate for. Necessary for retrieving possible Egg Moves. + /// /// A consumable list of possible encounters. - private static IEnumerable GetEggs(PKM pk, ushort[] needs, EvoCriteria[] chain, GameVersion version) + private static IEnumerable GetEggs(PKM pk, ushort[] needs, EvoCriteria[] chain, GameVersion version, IEncounterGenerator generator) { if (!Breeding.CanGameGenerateEggs(version)) yield break; // no eggs from these games - int gen = version.GetGeneration(); - var eggs = gen == 2 - ? EncounterEggGenerator2.GenerateEggs(pk, chain, all: true) - : EncounterEggGenerator.GenerateEggs(pk, chain, gen, all: true); + + var eggs = generator.GetPossible(pk, chain, version, Egg); foreach (var egg in eggs) { if (needs.Length == 0) @@ -271,14 +289,10 @@ public static class EncounterMovesetGenerator var eggMoves = MoveEgg.GetEggMoves(egg.Species, egg.Form, egg.Version, egg.Generation); int flags = Moveset.BitOverlap(eggMoves, needs); var vt = Array.IndexOf(needs, (ushort)Move.VoltTackle); - if (vt != -1 && egg.CanHaveVoltTackle) + if (vt != -1 && egg is EncounterEgg { CanHaveVoltTackle: true }) flags |= 1 << vt; - - if (egg.Generation <= 2) - { - var tmp = MoveLevelUp.GetEncounterMoves(egg.Species, 0, egg.Level, egg.Version); - flags |= Moveset.BitOverlap(tmp, needs); - } + else if (egg.Generation <= 2) + flags |= GetMoveMaskGen2(needs, egg); if (flags == (1 << needs.Length) - 1) yield return egg; @@ -292,26 +306,28 @@ public static class EncounterMovesetGenerator /// Moves which cannot be taught by the player. /// Origin possible evolution chain /// Specific version to iterate for. + /// Generator /// A consumable list of possible encounters. - private static IEnumerable GetGifts(PKM pk, ushort[] needs, EvoCriteria[] chain, GameVersion version) + private static IEnumerable GetGifts(PKM pk, ushort[] needs, EvoCriteria[] chain, GameVersion version, IEncounterGenerator generator) { var context = pk.Context; - var gifts = MysteryGiftGenerator.GetPossible(pk, chain, version); - foreach (var gift in gifts) + var gifts = generator.GetPossible(pk, chain, version, Mystery); + foreach (var g in gifts) { - if (gift is WC3 {NotDistributed: true}) - continue; - if (!IsSane(chain, gift, context)) + if (!IsSane(chain, g, context)) continue; if (needs.Length == 0) { - yield return gift; + yield return g; continue; } - - var flags = gift.Moves.BitOverlap(needs) | gift.Relearn.BitOverlap(needs); + var flags = 0; + if (g is IMoveset m) + flags = m.Moves.BitOverlap(needs); + if (g is IRelearn r) + flags |= r.Relearn.BitOverlap(needs); if (flags == (1 << needs.Length) - 1) - yield return gift; + yield return g; } } @@ -322,11 +338,12 @@ public static class EncounterMovesetGenerator /// Moves which cannot be taught by the player. /// Origin possible evolution chain /// Specific version to iterate for. + /// /// A consumable list of possible encounters. - private static IEnumerable GetStatic(PKM pk, ushort[] needs, EvoCriteria[] chain, GameVersion version) + private static IEnumerable GetStatic(PKM pk, ushort[] needs, EvoCriteria[] chain, GameVersion version, IEncounterGenerator generator) { var context = pk.Context; - var encounters = EncounterStaticGenerator.GetPossible(pk, chain, version); + var encounters = generator.GetPossible(pk, chain, version, Static); foreach (var enc in encounters) { if (!IsSane(chain, enc, context)) @@ -338,33 +355,7 @@ public static class EncounterMovesetGenerator } // Some rare encounters have special moves hidden in the Relearn section (Gen7 Wormhole Ho-Oh). Include relearn moves - var flags = enc.Moves.BitOverlap(needs); - if (enc is IRelearn { Relearn: { HasMoves: true } r }) - flags |= r.BitOverlap(needs); - - if (enc.Generation <= 2) - { - var tmp = MoveLevelUp.GetEncounterMoves(enc.Species, 0, enc.Level, enc.Version); - flags |= Moveset.BitOverlap(tmp, needs); - } - - if (flags == (1 << needs.Length) - 1) - yield return enc; - } - - int gen = version.GetGeneration(); - if ((uint)gen >= 3) - yield break; - - var gifts = EncounterStaticGenerator.GetPossibleGBGifts(chain, version); - foreach (var enc in gifts) - { - if (needs.Length == 0) - { - yield return enc; - continue; - } - var flags = enc.Moves.BitOverlap(needs); + var flags = GetMoveMaskConsiderGen2(needs, enc); if (flags == (1 << needs.Length) - 1) yield return enc; } @@ -377,11 +368,12 @@ public static class EncounterMovesetGenerator /// Moves which cannot be taught by the player. /// Origin possible evolution chain /// Specific version to iterate for. + /// /// A consumable list of possible encounters. - private static IEnumerable GetTrades(PKM pk, ushort[] needs, EvoCriteria[] chain, GameVersion version) + private static IEnumerable GetTrades(PKM pk, ushort[] needs, EvoCriteria[] chain, GameVersion version, IEncounterGenerator generator) { var context = pk.Context; - var trades = EncounterTradeGenerator.GetPossible(pk, chain, version); + var trades = generator.GetPossible(pk, chain, version, Trade); foreach (var trade in trades) { if (!IsSane(chain, trade, context)) @@ -392,16 +384,7 @@ public static class EncounterMovesetGenerator continue; } - var flags = trade.Moves.BitOverlap(needs); - if (trade is IRelearn { Relearn: { HasMoves: true } r }) - flags |= r.BitOverlap(needs); - - if (trade.Generation <= 2) - { - var tmp = MoveLevelUp.GetEncounterMoves(trade.Species, 0, trade.Level, trade.Version); - flags |= Moveset.BitOverlap(tmp, needs); - } - + var flags = GetMoveMaskConsiderGen2(needs, trade); if (flags == (1 << needs.Length) - 1) yield return trade; } @@ -414,29 +397,17 @@ public static class EncounterMovesetGenerator /// Moves which cannot be taught by the player. /// Origin possible evolution chain /// Origin version + /// /// A consumable list of possible encounters. - private static IEnumerable GetSlots(PKM pk, ushort[] needs, EvoCriteria[] chain, GameVersion version) + private static IEnumerable GetSlots(PKM pk, ushort[] needs, EvoCriteria[] chain, GameVersion version, IEncounterGenerator generator) { var context = pk.Context; - var slots = EncounterSlotGenerator.GetPossible(pk, chain, version); + var slots = generator.GetPossible(pk, chain, version, Slot); foreach (var slot in slots) { if (!IsSane(chain, slot, context)) continue; - - if (needs.Length == 0) - { - yield return slot; - continue; - } - - if (slot is IMoveset m && m.Moves.ContainsAll(needs)) - yield return slot; - else if (needs.Length == 1 && slot is EncounterSlot6AO {CanDexNav: true} dn && dn.CanBeDexNavMove(needs[0])) - yield return slot; - else if (needs.Length == 1 && slot is EncounterSlot8b {IsUnderground: true} ug && ug.CanBeUndergroundMove(needs[0])) - yield return slot; - else if (slot.Generation <= 2 && HasAllMoves(needs, MoveLevelUp.GetEncounterMoves(slot.Species, 0, slot.LevelMin, slot.Version))) + if (needs.Length == 0 || HasAllNeededMovesSlot(needs, slot)) yield return slot; } } @@ -452,7 +423,7 @@ public static class EncounterMovesetGenerator return true; if (FormInfo.IsFormChangeable(enc.Species, enc.Form, evo.Form, enc.Context, current)) return true; - if (enc is EncounterSlot {IsRandomUnspecificForm: true} or EncounterStatic {IsRandomUnspecificForm: true}) + if (enc is IEncounterFormRandom { IsRandomUnspecificForm: true }) return true; if (enc is EncounterStatic7 {IsTotem: true} && evo.Form == 0 && current.Generation() > 7) // totems get form wiped return true; @@ -461,17 +432,41 @@ public static class EncounterMovesetGenerator return false; } - private static bool HasAllMoves(ReadOnlySpan needs, IEnumerable extra) + private static int GetMoveMaskConsiderGen2(ReadOnlySpan needs, IEncounterTemplate enc) { - // Flag each present index; having all moves will have all bitflags. - int flags = 0; - foreach (var move in extra) - { - var index = needs.IndexOf(move); - if (index == -1) - continue; - flags |= 1 << index; - } + var flags = 0; + if (enc is IMoveset m) + flags = m.Moves.BitOverlap(needs); + if (enc is IRelearn { Relearn: { HasMoves: true } r }) + flags |= r.BitOverlap(needs); + if (enc.Generation <= 2) + flags |= GetMoveMaskGen2(needs, enc); + return flags; + } + + private static int GetMoveMaskGen2(ReadOnlySpan needs, IEncounterTemplate enc) + { + Span moves = stackalloc ushort[4]; + MoveLevelUp.GetEncounterMoves(moves, enc.Species, 0, enc.LevelMin, enc.Version); + return Moveset.BitOverlap(moves, needs); + } + + private static bool HasAllNeededMovesSlot(ReadOnlySpan needs, IEncounterTemplate slot) + { + if (slot is IMoveset m) + return m.Moves.ContainsAll(needs); + if (needs.Length == 1 && slot is EncounterSlot6AO dn) + return dn.CanDexNav && dn.CanBeDexNavMove(needs[0]); + if (needs.Length == 1 && slot is EncounterSlot8b ug) + return ug.IsUnderground && ug.CanBeUndergroundMove(needs[0]); + if (slot.Generation <= 2) + return HasAllNeededMovesEncounter2(needs, slot); + return false; + } + + private static bool HasAllNeededMovesEncounter2(ReadOnlySpan needs, IEncounterTemplate enc) + { + int flags = GetMoveMaskGen2(needs, enc); return flags == (1 << needs.Length) - 1; } } diff --git a/PKHeX.Core/Legality/Encounters/Generator/Moveset/EncounterOrder.cs b/PKHeX.Core/Legality/Encounters/Generator/Moveset/EncounterTypeGroup.cs similarity index 74% rename from PKHeX.Core/Legality/Encounters/Generator/Moveset/EncounterOrder.cs rename to PKHeX.Core/Legality/Encounters/Generator/Moveset/EncounterTypeGroup.cs index 4941bd6dc..4594e9156 100644 --- a/PKHeX.Core/Legality/Encounters/Generator/Moveset/EncounterOrder.cs +++ b/PKHeX.Core/Legality/Encounters/Generator/Moveset/EncounterTypeGroup.cs @@ -1,18 +1,21 @@ +using System; + namespace PKHeX.Core; /// /// Enumeration for indicating the various "base type" category of encounter templates. /// -public enum EncounterOrder +[Flags] +public enum EncounterTypeGroup { /// Bred egg from the Daycare/etc. - Egg, + Egg = 1 << 0, /// Mystery Gift data from external distributions. - Mystery, + Mystery = 1 << 1, /// Static encounter / gift in-game. - Static, + Static = 1 << 2, /// Trade encounter from an in-game NPC. - Trade, + Trade = 1 << 3, /// Wild encounter - Slot, + Slot = 1 << 4, } diff --git a/PKHeX.Core/Legality/Encounters/Generator/Specific/EncounterEggGenerator.cs b/PKHeX.Core/Legality/Encounters/Generator/Specific/EncounterEggGenerator.cs deleted file mode 100644 index da844cd41..000000000 --- a/PKHeX.Core/Legality/Encounters/Generator/Specific/EncounterEggGenerator.cs +++ /dev/null @@ -1,104 +0,0 @@ -using System.Collections.Generic; - -using static PKHeX.Core.Legal; - -namespace PKHeX.Core; - -public static class EncounterEggGenerator -{ - public static IEnumerable GenerateEggs(PKM pk, int generation, bool all = false) - { - var table = EvolutionTree.GetEvolutionTree(pk.Context); - int maxSpeciesOrigin = GetMaxSpeciesOrigin(generation); - var evos = table.GetValidPreEvolutions(pk, levelMax: 100, maxSpeciesOrigin: maxSpeciesOrigin, skipChecks: true); - return GenerateEggs(pk, evos, generation, all); - } - - public static IEnumerable GenerateEggs(PKM pk, EvoCriteria[] chain, int generation, bool all = false) - { - System.Diagnostics.Debug.Assert(generation >= 3); // if generating Gen2 eggs, use the other generator. - var currentSpecies = pk.Species; - if (!Breeding.CanHatchAsEgg(currentSpecies)) - yield break; - - // version is a true indicator for all generation 3-5 origins - var ver = (GameVersion)pk.Version; - if (!Breeding.CanGameGenerateEggs(ver)) - { - if (ver == 0 && pk is PK9) - ver = GameVersion.SL; - else - yield break; - } - - var context = ver.GetContext(); - var currentForm = pk.Form; - if (!Breeding.CanHatchAsEgg(currentSpecies, currentForm, context)) - yield break; // can't originate from eggs - - var lvl = EggStateLegality.GetEggLevel(generation); - int max = GetMaxSpeciesOrigin(generation); - - var (species, form) = GetBaseSpecies(chain, 0); - if (species != 0 && species <= max) - { - // NOTE: THE SPLIT-BREED SECTION OF CODE SHOULD BE EXACTLY THE SAME AS THE BELOW SECTION - if (FormInfo.IsBattleOnlyForm(species, form, generation) || species is (int)Species.Rotom or (int)Species.Castform) - form = FormInfo.GetOutOfBattleForm(species, form, generation); - if (Breeding.CanHatchAsEgg(species, form, ver)) - { - yield return new EncounterEgg(species, form, lvl, generation, ver, context); - if (generation > 5 && (pk.WasTradedEgg || all) && HasOtherGamePair(ver)) - yield return new EncounterEgg(species, form, lvl, generation, GetOtherTradePair(ver), context); - } - } - - if (!Breeding.GetSplitBreedGeneration(generation).Contains(currentSpecies)) - yield break; // no other possible species - - var otherSplit = species; - (species, form) = GetBaseSpecies(chain, 1); - if ((uint)species == otherSplit) - yield break; - - if (species <= max) - { - // NOTE: THIS SECTION OF CODE SHOULD BE EXACTLY THE SAME AS THE ABOVE SECTION - if (FormInfo.IsBattleOnlyForm(species, form, generation)) - form = FormInfo.GetOutOfBattleForm(species, form, generation); - if (Breeding.CanHatchAsEgg(species, form, ver)) - { - yield return new EncounterEgg(species, form, lvl, generation, ver, context); - if (generation > 5 && (pk.WasTradedEgg || all) && HasOtherGamePair(ver)) - yield return new EncounterEgg(species, form, lvl, generation, GetOtherTradePair(ver), context); - } - } - } - - // Gen6+ update the origin game when hatched. Quick manip for X.Y<->A.O | S.M<->US.UM, ie X->A - private static GameVersion GetOtherTradePair(GameVersion ver) => ver switch - { - <= GameVersion.OR => (GameVersion) ((int) ver ^ 2), // gen6 - <= GameVersion.MN => ver + 2, // gen7 - _ => ver - 2, - }; - - private static bool HasOtherGamePair(GameVersion ver) - { - return ver < GameVersion.GP; // lgpe and sw/sh don't have a sister pair - } - - private static (ushort Species, byte Form) GetBaseSpecies(EvoCriteria[] evolutions, int skipOption) - { - ushort species = evolutions[0].Species; - if (species == (int)Species.Shedinja) // Shedinja - return ((int)Species.Nincada, 0); // Nincada - - // skip n from end, return empty if invalid index - int index = evolutions.Length - 1 - skipOption; - if ((uint)index >= evolutions.Length) - return default; - var evo = evolutions[index]; - return (evo.Species, evo.Form); - } -} diff --git a/PKHeX.Core/Legality/Encounters/Generator/Specific/EncounterEggGenerator2.cs b/PKHeX.Core/Legality/Encounters/Generator/Specific/EncounterEggGenerator2.cs deleted file mode 100644 index ea86d6af5..000000000 --- a/PKHeX.Core/Legality/Encounters/Generator/Specific/EncounterEggGenerator2.cs +++ /dev/null @@ -1,85 +0,0 @@ -using System.Collections.Generic; - -namespace PKHeX.Core; - -/// -/// Specialized Egg Generator for Gen2 -/// -internal static class EncounterEggGenerator2 -{ - public static IEnumerable GenerateEggs(PKM pk, bool all = false) - { - var table = EvolutionTree.Evolves2; - const int maxSpeciesOrigin = Legal.MaxSpeciesID_2; - var evos = table.GetValidPreEvolutions(pk, levelMax: 100, maxSpeciesOrigin: maxSpeciesOrigin, skipChecks: true); - return GenerateEggs(pk, evos, all); - } - - public static IEnumerable GenerateEggs(PKM pk, EvoCriteria[] chain, bool all = false) - { - if (!Breeding.CanHatchAsEgg(chain[0].Species)) - yield break; - - var canBeEgg = all || GetCanBeEgg(pk); - if (!canBeEgg) - yield break; - - // Gen2 was before split-breed species existed; try to ensure that the egg we try and match to can actually originate in the game. - // Species must be < 251 - // Form must be 0 (Unown cannot breed). - var baseID = chain[^1]; - if ((baseID.Species >= Legal.MaxSpeciesID_2 || baseID.Form != 0) && chain.Length != 1) - baseID = chain[^2]; - if (baseID.Form != 0) - yield break; // Forms don't exist in Gen2, besides Unown (which can't breed). Nothing can form-change. - - var species = baseID.Species; - if (species > Legal.MaxSpeciesID_2) - yield break; - - // Depending on the game it was hatched (GS vs C), met data will be present. - // Since met data can't be used to infer which game it was created on, we yield both if possible. - if (ParseSettings.AllowGen2Crystal(pk)) - yield return new EncounterEgg(species, 0, 5, 2, GameVersion.C, EntityContext.Gen2); - yield return new EncounterEgg(species, 0, 5, 2, GameVersion.GS, EntityContext.Gen2); - } - - private static bool GetCanBeEgg(PKM pk) - { - if (pk.Format == 1 && !ParseSettings.AllowGen1Tradeback) - return false; - if (!GetCanBeEgg2(pk)) - return false; - if (!IsEvolutionValid(pk)) - return false; - - return true; - } - - private static bool GetCanBeEgg2(PKM pk) - { - if (pk.CurrentLevel < 5) - return false; - - var format = pk.Format; - if (pk.IsEgg) - return format == 2; - if (format > 2) - return pk.Met_Level >= 5; - - // 2->1->2 clears met info - return pk.Met_Level switch - { - 0 => pk.Met_Location == 0, - 1 => true, // Met location of 0 is valid -- second floor of every Pokémon Center - _ => false, - }; - } - - private static bool IsEvolutionValid(PKM pk) - { - var curr = EvolutionChain.GetValidPreEvolutions(pk, minLevel: 5); - var poss = EvolutionChain.GetValidPreEvolutions(pk, maxLevel: 100, minLevel: 5, skipChecks: true); - return curr.Length >= poss.Length; - } -} diff --git a/PKHeX.Core/Legality/Encounters/Generator/Specific/EncounterSlotGenerator.cs b/PKHeX.Core/Legality/Encounters/Generator/Specific/EncounterSlotGenerator.cs deleted file mode 100644 index 398ad6993..000000000 --- a/PKHeX.Core/Legality/Encounters/Generator/Specific/EncounterSlotGenerator.cs +++ /dev/null @@ -1,193 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; - -using static PKHeX.Core.Legal; -using static PKHeX.Core.Encounters1; -using static PKHeX.Core.Encounters2; -using static PKHeX.Core.Encounters3RSE; -using static PKHeX.Core.Encounters3FRLG; -using static PKHeX.Core.Encounters3XD; -using static PKHeX.Core.Encounters4DPPt; -using static PKHeX.Core.Encounters4HGSS; -using static PKHeX.Core.Encounters5BW; -using static PKHeX.Core.Encounters5B2W2; -using static PKHeX.Core.Encounters6XY; -using static PKHeX.Core.Encounters6AO; -using static PKHeX.Core.Encounters7SM; -using static PKHeX.Core.Encounters7USUM; -using static PKHeX.Core.Encounters7GG; -using static PKHeX.Core.Encounters8; -using static PKHeX.Core.Encounters8a; -using static PKHeX.Core.Encounters8b; -using static PKHeX.Core.Encounters9; -using static PKHeX.Core.EncountersGO; - -using static PKHeX.Core.GameVersion; - -namespace PKHeX.Core; - -public static class EncounterSlotGenerator -{ - public static IEnumerable GetPossible(PKM pk, EvoCriteria[] chain, GameVersion gameSource) - { - var possibleAreas = GetAreasByGame(pk, gameSource); - foreach (var area in possibleAreas) - { - foreach (var result in area.GetSpecies(chain)) - yield return result; - } - } - - private static IEnumerable GetAreasByGame(PKM pk, GameVersion gameSource) => gameSource switch - { - RD => SlotsRD, - GN => SlotsGN, - BU => SlotsBU, - YW => SlotsYW, - - GD => SlotsGD, - SI => SlotsSV, - C => SlotsC, - - _ => GetEncounterTable(pk, gameSource), - }; - - private static IEnumerable GetRawEncounterSlots(PKM pk, EvoCriteria[] chain, GameVersion gameSource) - { - if (pk.IsEgg) - yield break; - if (IsMetAsEgg(pk)) - yield break; - - var possibleAreas = GetEncounterAreas(pk, gameSource); - foreach (var area in possibleAreas) - { - var slots = area.GetMatchingSlots(pk, chain); - foreach (var s in slots) - yield return s; - } - } - - public static IEnumerable GetValidWildEncounters12(PKM pk, EvoCriteria[] chain, GameVersion gameSource) - { - return GetRawEncounterSlots(pk, chain, gameSource); - } - - public static IEnumerable GetValidWildEncounters(PKM pk, EvoCriteria[] chain, GameVersion gameSource) - { - return GetRawEncounterSlots(pk, chain, gameSource); - } - - private static IEnumerable GetEncounterAreas(PKM pk, GameVersion gameSource) - { - var slots = GetEncounterTable(pk, gameSource); - bool noMet = !pk.HasOriginalMetLocation || (pk.Format == 2 && gameSource != C); - if (noMet) - return slots; - return GetIsMatchLocation(pk, slots); - } - - private static IEnumerable GetIsMatchLocation(PKM pk, IEnumerable areas) - { - var metLocation = pk.Met_Location; - foreach (var area in areas) - { - if (area.IsMatchLocation(metLocation)) - yield return area; - } - } - - internal static EncounterSlot? GetCaptureLocation(PKM pk, EvoCriteria[] chain) - { - var possible = GetPossible(pk, chain, (GameVersion)pk.Version); - return EncounterUtil.GetMinByLevel(chain, possible); - } - - private static IEnumerable GetEncounterTable(PKM pk, GameVersion game) => game switch - { - RBY or RD or BU or GN or YW => pk.Japanese ? SlotsRGBY : SlotsRBY, - - GSC or GD or SI or C => GetEncounterTableGSC(pk), - - R => SlotsR, - S => SlotsS, - E => SlotsE, - FR => SlotsFR, - LG => SlotsLG, - CXD => SlotsXD, - - D => SlotsD, - P => SlotsP, - Pt => SlotsPt, - HG => SlotsHG, - SS => SlotsSS, - - B => SlotsB, - W => SlotsW, - B2 => SlotsB2, - W2 => SlotsW2, - - X => SlotsX, - Y => SlotsY, - AS => SlotsA, - OR => SlotsO, - - SN => SlotsSN, - MN => SlotsMN, - US => SlotsUS, - UM => SlotsUM, - GP => SlotsGP, - GE => SlotsGE, - - GO => GetEncounterTableGO(pk), - SW => SlotsSW, - SH => SlotsSH, - BD => SlotsBD, - SP => SlotsSP, - PLA => SlotsLA, - - SL or VL => Slots, - - _ => Array.Empty(), - }; - - private static EncounterArea[] GetEncounterTableGSC(PKM pk) - { - if (!ParseSettings.AllowGen2Crystal(pk)) - return SlotsGS; - - // Gen 2 met location is lost outside gen 2 games - if (pk.Format != 2) - return SlotsGSC; - - // Format 2 with met location, encounter should be from Crystal - if (pk.HasOriginalMetLocation) - return SlotsC; - - // Format 2 without met location but pokemon could not be tradeback to gen 1, - // encounter should be from gold or silver - if (pk.Species > MaxSpeciesID_1 && !EvolutionLegality.FutureEvolutionsGen1.Contains(pk.Species)) - return SlotsGS; - - // Encounter could be any gen 2 game, it can have empty met location for have a g/s origin - // or it can be a Crystal pokemon that lost met location after being tradeback to gen 1 games - return SlotsGSC; - } - - private static IEnumerable GetEncounterTableGO(PKM pk) - { - if (pk.Format < 8) - return SlotsGO_GG; - - // If we know the met location, return the specific area list. - // If we're just getting all encounters (lack of met location is kinda bad...), just return everything. - var met = pk.Met_Location; - return met switch - { - Locations.GO8 => SlotsGO, - Locations.GO7 => SlotsGO_GG, - _ => SlotsGO_GG.Concat(SlotsGO), - }; - } -} diff --git a/PKHeX.Core/Legality/Encounters/Generator/Specific/EncounterStaticGenerator.cs b/PKHeX.Core/Legality/Encounters/Generator/Specific/EncounterStaticGenerator.cs deleted file mode 100644 index b8f6eeb34..000000000 --- a/PKHeX.Core/Legality/Encounters/Generator/Specific/EncounterStaticGenerator.cs +++ /dev/null @@ -1,205 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; - -using static PKHeX.Core.Legal; -using static PKHeX.Core.Encounters1; -using static PKHeX.Core.Encounters2; -using static PKHeX.Core.Encounters3RSE; -using static PKHeX.Core.Encounters3FRLG; -using static PKHeX.Core.Encounters3XD; -using static PKHeX.Core.Encounters4DPPt; -using static PKHeX.Core.Encounters4HGSS; -using static PKHeX.Core.Encounters5BW; -using static PKHeX.Core.Encounters5B2W2; -using static PKHeX.Core.Encounters6XY; -using static PKHeX.Core.Encounters6AO; -using static PKHeX.Core.Encounters7SM; -using static PKHeX.Core.Encounters7USUM; -using static PKHeX.Core.Encounters7GG; -using static PKHeX.Core.Encounters8; -using static PKHeX.Core.Encounters8a; -using static PKHeX.Core.Encounters8b; -using static PKHeX.Core.Encounters9; - -using static PKHeX.Core.GameVersion; - -namespace PKHeX.Core; - -public static class EncounterStaticGenerator -{ - public static IEnumerable GetPossible(PKM pk, EvoCriteria[] chain, GameVersion gameSource) - { - var table = gameSource switch - { - RD or GN or BU or YW => StaticRBY.Where(z => z.Version.Contains(gameSource)), - GD or SI => StaticGS.Where(z => z.Version.Contains(gameSource)), - C => StaticC, - _ => GetEncounterStaticTable(pk, gameSource), - }; - return table.Where(e => chain.Any(d => d.Species == e.Species)); - } - - public static IEnumerable GetPossibleGBGifts(EvoCriteria[] chain, GameVersion gameSource) - { - static IEnumerable GetEvents(GameVersion g) - { - if (g.GetGeneration() == 1) - return !ParseSettings.AllowGBCartEra ? Encounters1.StaticEventsVC : Encounters1.StaticEventsGB; - - return !ParseSettings.AllowGBCartEra ? Encounters2.StaticEventsVC : Encounters2.StaticEventsGB; - } - - var table = GetEvents(gameSource); - return table.Where(e => chain.Any(d => d.Species == e.Species)); - } - - public static IEnumerable GetValidStaticEncounter(PKM pk, EvoCriteria[] chain, GameVersion gameSource) - { - var table = GetEncounterStaticTable(pk, gameSource); - return GetMatchingStaticEncounters(pk, table, chain); - } - - public static IEnumerable GetValidGBGifts(PKM pk, EvoCriteria[] chain, GameVersion gameSource) - { - var poss = GetPossibleGBGifts(chain, gameSource: gameSource); - foreach (EncounterStatic e in poss) - { - foreach (var evo in chain) - { - if (evo.Species != e.Species) - continue; - if (!e.IsMatchExact(pk, evo)) - continue; - - yield return e; - } - } - } - - private static IEnumerable GetMatchingStaticEncounters(PKM pk, IEnumerable poss, EvoCriteria[] chain) - { - // check for petty rejection scenarios that will be flagged by other legality checks - foreach (var e in poss) - { - foreach (var evo in chain) - { - if (evo.Species != e.Species) - continue; - if (!e.IsMatchExact(pk, evo)) - continue; - - yield return e; - } - } - } - - internal static EncounterStatic7 GetVCStaticTransferEncounter(PKM pk, IEncounterTemplate enc, ReadOnlySpan chain) - { - // Obtain the lowest evolution species with matching OT friendship. Not all species chains have the same base friendship. - var met = (byte)pk.Met_Level; - if (pk.VC1) - { - // Only yield a VC1 template if it could originate in VC1. - // Catch anything that can only exist in VC2 (Entei) even if it was "transferred" from VC1. - var species = GetVCSpecies(chain, pk, MaxSpeciesID_1); - var vc1Species = species > MaxSpeciesID_1 ? enc.Species : species; - if (vc1Species <= MaxSpeciesID_1) - return EncounterStatic7.GetVC1(vc1Species, met); - } - // fall through else - { - var species = GetVCSpecies(chain, pk, MaxSpeciesID_2); - return EncounterStatic7.GetVC2(species > MaxSpeciesID_2 ? enc.Species : species, met); - } - } - - private static ushort GetVCSpecies(ReadOnlySpan chain, PKM pk, int max) - { - ushort species = pk.Species; - foreach (var z in chain) - { - if (z.Species > max) - continue; - if (z.Form != 0) - continue; - if (PersonalTable.SM.GetFormEntry(z.Species, z.Form).BaseFriendship != pk.OT_Friendship) - continue; - species = z.Species; - } - return species; - } - - internal static EncounterStatic? GetStaticLocation(PKM pk, EvoCriteria[] chain) => pk.Generation switch - { - 1 => EncounterStatic7.GetVC1(MaxSpeciesID_1, (byte)pk.Met_Level), - 2 => EncounterStatic7.GetVC2(MaxSpeciesID_2, (byte)pk.Met_Level), - _ => GetStaticMinByLevel(pk, chain), - }; - - private static EncounterStatic? GetStaticMinByLevel(PKM pk, EvoCriteria[] chain) - { - var possible = GetPossible(pk, chain, (GameVersion)pk.Version); - return EncounterUtil.GetMinByLevel(chain, possible); - } - - // Generation Specific Fetching - private static IEnumerable GetEncounterStaticTable(PKM pk, GameVersion game) => game switch - { - RBY or RD or BU or GN or YW => StaticRBY, - - GSC or GD or SI or C => GetEncounterStaticTableGSC(pk), - - R => StaticR, - S => StaticS, - E => StaticE, - FR => StaticFR, - LG => StaticLG, - CXD => Encounter_CXD, - - D => StaticD, - P => StaticP, - Pt => StaticPt, - HG => StaticHG, - SS => StaticSS, - - B => StaticB, - W => StaticW, - B2 => StaticB2, - W2 => StaticW2, - - X => StaticX, - Y => StaticY, - AS => StaticA, - OR => StaticO, - - SN => StaticSN, - MN => StaticMN, - US => StaticUS, - UM => StaticUM, - GP => StaticGP, - GE => StaticGE, - - SW => StaticSW, - SH => StaticSH, - BD => StaticBD, - SP => StaticSP, - PLA => StaticLA, - - SL => StaticSL, - VL => StaticVL, - _ => Array.Empty(), - }; - - private static IEnumerable GetEncounterStaticTableGSC(PKM pk) - { - if (!ParseSettings.AllowGen2Crystal(pk)) - return StaticGS; - if (pk.Format != 2) - return StaticGSC; - - if (pk.HasOriginalMetLocation) - return StaticC; - return StaticGSC; - } -} diff --git a/PKHeX.Core/Legality/Encounters/Generator/Specific/EncounterTradeGenerator.cs b/PKHeX.Core/Legality/Encounters/Generator/Specific/EncounterTradeGenerator.cs deleted file mode 100644 index 4e1c646f0..000000000 --- a/PKHeX.Core/Legality/Encounters/Generator/Specific/EncounterTradeGenerator.cs +++ /dev/null @@ -1,119 +0,0 @@ -using System; -using System.Collections.Generic; -using static PKHeX.Core.GameVersion; - -namespace PKHeX.Core; - -public static class EncounterTradeGenerator -{ - public static IEnumerable GetPossible(PKM pk, EvoCriteria[] chain, GameVersion gameSource) - { - if (pk.Format <= 2 || pk.VC) - return GetPossibleVC(chain, gameSource); - return GetPossible(chain, gameSource); - } - - private static IEnumerable GetPossibleVC(EvoCriteria[] chain, GameVersion game) - { - var table = GetTableVC(game); - foreach (var enc in table) - { - foreach (var evo in chain) - { - if (evo.Species != enc.Species) - continue; - if (evo.Form != 0) - break; - yield return enc; - break; - } - } - } - - private static IEnumerable GetPossible(EvoCriteria[] chain, GameVersion game) - { - var table = GetTable(game); - foreach (var enc in table) - { - foreach (var evo in chain) - { - if (evo.Species != enc.Species) - continue; - yield return enc; - break; - } - } - } - - public static IEnumerable GetValidEncounterTradesVC(PKM pk, EvoCriteria[] chain, GameVersion game) - { - var table = GetTableVC(game); - foreach (var p in table) - { - foreach (var evo in chain) - { - if (evo.Species != p.Species || evo.Form != 0) - continue; - if (p.IsMatchExact(pk, evo)) - yield return p; - break; - } - } - } - - public static IEnumerable GetValidEncounterTrades(PKM pk, EvoCriteria[] chain, GameVersion game) - { - // Pre-filter for some language scenarios - int lang = pk.Language; - if (lang == (int)LanguageID.UNUSED_6) // invalid language - return Array.Empty(); - if (lang == (int)LanguageID.Hacked && !EncounterTrade5PID.IsValidMissingLanguage(pk)) // Japanese trades in BW have no language ID - return Array.Empty(); - - var table = GetTable(game); - return GetValidEncounterTrades(pk, chain, table); - } - - private static IEnumerable GetValidEncounterTrades(PKM pk, EvoCriteria[] chain, EncounterTrade[] poss) - { - foreach (var p in poss) - { - foreach (var evo in chain) - { - if (evo.Species != p.Species) - continue; - if (p.IsMatchExact(pk, evo)) - yield return p; - break; - } - } - } - - private static IEnumerable GetTableVC(GameVersion game) - { - if (RBY.Contains(game)) - return Encounters1.TradeGift_RBY; - if (GSC.Contains(game)) - return Encounters2.TradeGift_GSC; - return Array.Empty(); - } - - private static EncounterTrade[] GetTable(GameVersion game) => game switch - { - R or S or E => Encounters3RSE.TradeGift_RSE, - FR or LG => Encounters3FRLG.TradeGift_FRLG, - D or P or Pt => Encounters4DPPt.TradeGift_DPPt, - HG or SS => Encounters4HGSS.TradeGift_HGSS, - B or W => Encounters5BW.TradeGift_BW, - B2 or W2 => Encounters5B2W2.TradeGift_B2W2, - X or Y => Encounters6XY.TradeGift_XY, - AS or OR => Encounters6AO.TradeGift_AO, - SN or MN => Encounters7SM.TradeGift_SM, - US or UM => Encounters7USUM.TradeGift_USUM, - GP or GE => Encounters7GG.TradeGift_GG, - SW or SH => Encounters8.TradeGift_SWSH, - BD or SP => Encounters8b.TradeGift_BDSP, - SL or VL => Encounters9.TradeGift_SV, - _ => Array.Empty(), - }; -} diff --git a/PKHeX.Core/Legality/Encounters/Generator/Specific/MysteryGiftGenerator.cs b/PKHeX.Core/Legality/Encounters/Generator/Specific/MysteryGiftGenerator.cs deleted file mode 100644 index 76f766b75..000000000 --- a/PKHeX.Core/Legality/Encounters/Generator/Specific/MysteryGiftGenerator.cs +++ /dev/null @@ -1,86 +0,0 @@ -using System; -using System.Collections.Generic; -using static PKHeX.Core.EncounterEvent; - -namespace PKHeX.Core; - -public static class MysteryGiftGenerator -{ - public static IEnumerable GetPossible(PKM pk, EvoCriteria[] chain, GameVersion game) - { - // Ranger Manaphy is a PGT and is not in the PCD[] for gen4. Check manually. - int gen = pk.Generation; - if (gen == 4 && pk.Species == (int) Species.Manaphy) - yield return RangerManaphy; - - var table = GetTable(gen, game); - foreach (var enc in table) - { - foreach (var evo in chain) - { - if (evo.Species != enc.Species) - continue; - yield return enc; - break; - } - } - } - - public static IEnumerable GetValidGifts(PKM pk, EvoCriteria[] chain, GameVersion game) - { - int gen = pk.Generation; - if (pk.IsEgg && pk.Format != gen) // transferred - return Array.Empty(); - - if (gen == 4) // check for Manaphy gift - return GetMatchingPCD(pk, MGDB_G4, chain); - var table = GetTable(gen, game); - return GetMatchingGifts(pk, table, chain); - } - - private static IReadOnlyCollection GetTable(int generation, GameVersion game) => generation switch - { - 3 => MGDB_G3, - 4 => MGDB_G4, - 5 => MGDB_G5, - 6 => MGDB_G6, - 7 => game is GameVersion.GP or GameVersion.GE ? MGDB_G7GG : MGDB_G7, - 8 => game switch - { - GameVersion.BD or GameVersion.SP => MGDB_G8B, - GameVersion.PLA => MGDB_G8A, - _ => MGDB_G8, - }, - 9 => MGDB_G9, - _ => Array.Empty(), - }; - - private static IEnumerable GetMatchingPCD(PKM pk, IReadOnlyCollection table, EvoCriteria[] chain) - { - if (PGT.IsRangerManaphy(pk)) - { - yield return RangerManaphy; - yield break; - } - - foreach (var g in GetMatchingGifts(pk, table, chain)) - yield return g; - } - - private static IEnumerable GetMatchingGifts(PKM pk, IReadOnlyCollection table, EvoCriteria[] chain) - { - foreach (var mg in table) - { - foreach (var evo in chain) - { - if (evo.Species != mg.Species) - continue; - if (mg.IsMatchExact(pk, evo)) - yield return mg; - } - } - } - - // Utility - private static readonly PGT RangerManaphy = new() {Data = {[0] = 7, [8] = 1}}; -} diff --git a/PKHeX.Core/Legality/Encounters/IEncounterFormRandom.cs b/PKHeX.Core/Legality/Encounters/IEncounterFormRandom.cs new file mode 100644 index 000000000..f7095800d --- /dev/null +++ b/PKHeX.Core/Legality/Encounters/IEncounterFormRandom.cs @@ -0,0 +1,9 @@ +namespace PKHeX.Core; + +/// +/// Interface for an that can be one of many forms. +/// +public interface IEncounterFormRandom +{ + bool IsRandomUnspecificForm { get; } +} diff --git a/PKHeX.Core/Legality/Encounters/Information/EncounterSuggestion.cs b/PKHeX.Core/Legality/Encounters/Information/EncounterSuggestion.cs index 7b3012828..ccb0f7f4b 100644 --- a/PKHeX.Core/Legality/Encounters/Information/EncounterSuggestion.cs +++ b/PKHeX.Core/Legality/Encounters/Information/EncounterSuggestion.cs @@ -1,5 +1,4 @@ using System; - using static PKHeX.Core.GameVersion; namespace PKHeX.Core; @@ -20,8 +19,11 @@ public static class EncounterSuggestion return GetSuggestedEncounterEgg(pk, loc); var chain = EvolutionChain.GetValidPreEvolutions(pk, maxLevel: 100, skipChecks: true); - var w = EncounterSlotGenerator.GetCaptureLocation(pk, chain); - var s = EncounterStaticGenerator.GetStaticLocation(pk, chain); + var ver = (GameVersion)pk.Version; + var generator = EncounterGenerator.GetGenerator(ver); + var w = EncounterUtil.GetMinByLevel(chain, generator.GetPossible(pk, chain, ver, EncounterTypeGroup.Slot)); + var s = EncounterUtil.GetMinByLevel(chain, generator.GetPossible(pk, chain, ver, EncounterTypeGroup.Static)); + if (w is null) return s is null ? null : GetSuggestedEncounter(pk, s, loc); if (s is null) @@ -42,7 +44,7 @@ public static class EncounterSuggestion public static int GetSuggestedEncounterEggMetLevel(PKM pk) { - if (!pk.IsNative && pk.Generation < 5) + if (pk is { IsNative: false, Generation: < 5 }) return pk.CurrentLevel; // be generous with transfer conditions if (pk.Format < 5) // and native return pk.Format == 2 && pk.Met_Location != 0 ? 1 : 0; diff --git a/PKHeX.Core/Legality/Encounters/Verifiers/EncounterVerifier.cs b/PKHeX.Core/Legality/Encounters/Verifiers/EncounterVerifier.cs index 1be30aef9..9b43661ee 100644 --- a/PKHeX.Core/Legality/Encounters/Verifiers/EncounterVerifier.cs +++ b/PKHeX.Core/Legality/Encounters/Verifiers/EncounterVerifier.cs @@ -64,9 +64,9 @@ public static class EncounterVerifier return new CheckResult(Severity.Valid, LEncCondition, CheckIdentifier.Encounter); } - private static CheckResult VerifyWildEncounterCrystalHeadbutt(ITrainerID tr, EncounterSlot2 s2) + private static CheckResult VerifyWildEncounterCrystalHeadbutt(ITrainerID32 tr, EncounterSlot2 s2) { - return s2.IsTreeAvailable(tr.TID) + return s2.IsTreeAvailable(tr.TID16) ? new CheckResult(Severity.Valid, LG2TreeID, CheckIdentifier.Encounter) : new CheckResult(Severity.Invalid, LG2InvalidTileTreeNotFound, CheckIdentifier.Encounter); } @@ -168,6 +168,17 @@ public static class EncounterVerifier private static CheckResult VerifyEncounterEgg5(PKM pk) { + // Two game-specific locations we need to double check for. + // White / White2 cannot access Black Gate (112) + // Black / Black2 cannot access White Gate (113) + var met = pk.Met_Location; + var delta = (uint)(met - 112); + if (delta <= 1) + { + var ver = pk.Version & 1; // W*=0, B*=1 + if (ver == delta) + return new CheckResult(Severity.Invalid, LEggLocationInvalid, CheckIdentifier.Encounter); + } return VerifyEncounterEggLevelLoc(pk, 1, pk.B2W2 ? Legal.ValidMet_B2W2 : Legal.ValidMet_BW); } @@ -224,7 +235,7 @@ public static class EncounterVerifier return new CheckResult(Severity.Invalid, LEggLocationInvalid, CheckIdentifier.Encounter); } - private static CheckResult VerifyEncounterEggLevelLoc(PKM pk, int eggLevel, ICollection MetLocations) + private static CheckResult VerifyEncounterEggLevelLoc(PKM pk, int eggLevel, IReadOnlySet MetLocations) { return VerifyEncounterEggLevelLoc(pk, eggLevel, (location, _) => MetLocations.Contains(location)); } diff --git a/PKHeX.Core/Legality/Encounters/Verifiers/MysteryGiftRestriction.cs b/PKHeX.Core/Legality/Encounters/Verifiers/MysteryGiftRestriction.cs index d4e8673b8..58d09ba57 100644 --- a/PKHeX.Core/Legality/Encounters/Verifiers/MysteryGiftRestriction.cs +++ b/PKHeX.Core/Legality/Encounters/Verifiers/MysteryGiftRestriction.cs @@ -34,11 +34,6 @@ public enum MysteryGiftRestriction public static class MysteryGiftRestrictionExtensions { - public static bool HasFlagFast(this MysteryGiftRestriction value, MysteryGiftRestriction flag) - { - return (value & flag) != 0; - } - /// /// Checks the flags to pick out a language that can receive the gift. /// @@ -48,7 +43,7 @@ public static class MysteryGiftRestrictionExtensions { for (int i = (int)LanguageID.Japanese; i <= (int)LanguageID.Korean; i++) { - if (value.HasFlagFast((MysteryGiftRestriction)(1 << i))) + if (value.HasFlag((MysteryGiftRestriction)(1 << i))) return i; } return -1; @@ -58,7 +53,7 @@ public static class MysteryGiftRestrictionExtensions { for (int i = (int)Region3DSIndex.Japan; i <= (int)Region3DSIndex.Taiwan; i++) { - if (value.HasFlagFast((MysteryGiftRestriction)((int)MysteryGiftRestriction.RegionBase << i))) + if (value.HasFlag((MysteryGiftRestriction)((int)MysteryGiftRestriction.RegionBase << i))) return i; } return -1; diff --git a/PKHeX.Core/Legality/Encounters/Verifiers/MysteryGiftVerifier.cs b/PKHeX.Core/Legality/Encounters/Verifiers/MysteryGiftVerifier.cs index 8e60c9a0e..528993cec 100644 --- a/PKHeX.Core/Legality/Encounters/Verifiers/MysteryGiftVerifier.cs +++ b/PKHeX.Core/Legality/Encounters/Verifiers/MysteryGiftVerifier.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using static PKHeX.Core.LegalityCheckStrings; using static System.Buffers.Binary.BinaryPrimitives; @@ -45,13 +45,13 @@ public static class MysteryGiftVerifier return new CheckResult(Severity.Invalid, LEncGiftVersionNotDistributed, CheckIdentifier.GameOrigin); var lang = value & MysteryGiftRestriction.LangRestrict; - if (lang != 0 && !lang.HasFlagFast((MysteryGiftRestriction) (1 << pk.Language))) + if (lang != 0 && !lang.HasFlag((MysteryGiftRestriction) (1 << pk.Language))) return new CheckResult(Severity.Invalid, string.Format(LOTLanguage, lang.GetSuggestedLanguage(), pk.Language), CheckIdentifier.GameOrigin); if (pk is IRegionOrigin tr) { var region = value & MysteryGiftRestriction.RegionRestrict; - if (region != 0 && !region.HasFlagFast((MysteryGiftRestriction)((int)MysteryGiftRestriction.RegionBase << tr.ConsoleRegion))) + if (region != 0 && !region.HasFlag((MysteryGiftRestriction)((int)MysteryGiftRestriction.RegionBase << tr.ConsoleRegion))) return new CheckResult(Severity.Invalid, LGeoHardwareRange, CheckIdentifier.GameOrigin); } @@ -72,7 +72,7 @@ public static class MysteryGiftVerifier bool restricted = TryGetRestriction(g, out var val); if (!restricted) return false; // no data - if (!val.HasFlagFast(MysteryGiftRestriction.OTReplacedOnTrade)) + if (!val.HasFlag(MysteryGiftRestriction.OTReplacedOnTrade)) return false; return CurrentOTMatchesReplaced(g.Generation, pk.OT_Name); } @@ -85,7 +85,7 @@ public static class MysteryGiftVerifier }; } - private static bool CurrentOTMatchesReplaced(int format, string pkOtName) + private static bool CurrentOTMatchesReplaced(int format, ReadOnlySpan pkOtName) { if (format <= 4 && IsMatchName(pkOtName, 4)) return true; @@ -98,7 +98,7 @@ public static class MysteryGiftVerifier return false; } - private static bool IsMatchName(string pkOtName, int generation) + private static bool IsMatchName(ReadOnlySpan pkOtName, int generation) { return generation switch { diff --git a/PKHeX.Core/Legality/Enums/CheckIdentifier.cs b/PKHeX.Core/Legality/Enums/CheckIdentifier.cs index 8ae979402..2ab32dfd9 100644 --- a/PKHeX.Core/Legality/Enums/CheckIdentifier.cs +++ b/PKHeX.Core/Legality/Enums/CheckIdentifier.cs @@ -54,7 +54,7 @@ public enum CheckIdentifier : byte Nickname, /// - /// The pertains to the , , or . + /// The pertains to the , , or . /// Trainer, diff --git a/PKHeX.Core/Legality/Enums/GroundTileAllowed.cs b/PKHeX.Core/Legality/Enums/GroundTileAllowed.cs index 877acefaa..eafbc6fee 100644 --- a/PKHeX.Core/Legality/Enums/GroundTileAllowed.cs +++ b/PKHeX.Core/Legality/Enums/GroundTileAllowed.cs @@ -1,4 +1,4 @@ -using System; +using System; namespace PKHeX.Core; @@ -53,15 +53,5 @@ public static class GroundTileAllowedExtensions /// /// Tile bit-permission value /// Bit index - public static GroundTileType GetIndex(this GroundTileAllowed g) - { - int val = (int) g; - for (byte i = 0; i < 8 * sizeof(GroundTileAllowed); i++) - { - val >>= 1; - if (val == 0) - return (GroundTileType)i; - } - return 0; - } + public static GroundTileType GetIndex(this GroundTileAllowed g) => (GroundTileType)System.Numerics.BitOperations.Log2((uint)g); } diff --git a/PKHeX.Core/Legality/Evolutions/EvoCriteria.cs b/PKHeX.Core/Legality/Evolutions/EvoCriteria.cs index 643c74d1e..36602f2f3 100644 --- a/PKHeX.Core/Legality/Evolutions/EvoCriteria.cs +++ b/PKHeX.Core/Legality/Evolutions/EvoCriteria.cs @@ -5,7 +5,7 @@ namespace PKHeX.Core; /// public readonly record struct EvoCriteria : ISpeciesForm { - public ushort Species { get; init; } + public required ushort Species { get; init; } public byte Form { get; init; } public byte LevelUpRequired { get; init; } diff --git a/PKHeX.Core/Legality/Evolutions/EvolutionChain.cs b/PKHeX.Core/Legality/Evolutions/EvolutionChain.cs index e1368ff76..48e1ce17f 100644 --- a/PKHeX.Core/Legality/Evolutions/EvolutionChain.cs +++ b/PKHeX.Core/Legality/Evolutions/EvolutionChain.cs @@ -46,7 +46,7 @@ internal static class EvolutionChain if (maxLevel < 0) maxLevel = pk.CurrentLevel; - if (maxspeciesorigin == -1 && ParseSettings.AllowGen1Tradeback && pk.Format <= 2 && pk.Generation == 1) + if (maxspeciesorigin == -1 && ParseSettings.AllowGen1Tradeback && pk is { Format: <= 2, Generation: 1 }) maxspeciesorigin = MaxSpeciesID_2; var context = pk.Context; diff --git a/PKHeX.Core/Legality/Evolutions/EvolutionHistory.cs b/PKHeX.Core/Legality/Evolutions/EvolutionHistory.cs index 0885d1fad..6fad85b55 100644 --- a/PKHeX.Core/Legality/Evolutions/EvolutionHistory.cs +++ b/PKHeX.Core/Legality/Evolutions/EvolutionHistory.cs @@ -5,10 +5,9 @@ namespace PKHeX.Core; /// /// Stores the possible evolution bounds for a parsed entity with respect to its origins and game traversal. /// -public class EvolutionHistory +public sealed class EvolutionHistory { private static readonly EvoCriteria[] NONE = Array.Empty(); - public static readonly EvolutionHistory Empty = new(); public EvoCriteria[] Gen1 = NONE; public EvoCriteria[] Gen2 = NONE; diff --git a/PKHeX.Core/Legality/Evolutions/EvolutionSets/EvolutionSet3.cs b/PKHeX.Core/Legality/Evolutions/EvolutionSets/EvolutionSet3.cs index 2981cd822..aa1cc1586 100644 --- a/PKHeX.Core/Legality/Evolutions/EvolutionSets/EvolutionSet3.cs +++ b/PKHeX.Core/Legality/Evolutions/EvolutionSets/EvolutionSet3.cs @@ -13,7 +13,7 @@ public static class EvolutionSet3 { var method = data[0]; var arg = ReadUInt16LittleEndian(data[2..]); - var species = SpeciesConverter.GetG4Species(ReadUInt16LittleEndian(data[4..])); + var species = SpeciesConverter.GetNational3(ReadUInt16LittleEndian(data[4..])); //2 bytes padding switch (method) @@ -51,7 +51,7 @@ public static class EvolutionSet3 evos[0] = Array.Empty(); for (ushort i = 1; i <= Legal.MaxSpeciesIndex_3; i++) { - int g4species = SpeciesConverter.GetG4Species(i); + int g4species = SpeciesConverter.GetNational3(i); if (g4species == 0) continue; diff --git a/PKHeX.Core/Legality/Evolutions/EvolutionTree.cs b/PKHeX.Core/Legality/Evolutions/EvolutionTree.cs index 6e59137cb..0f18d3ec8 100644 --- a/PKHeX.Core/Legality/Evolutions/EvolutionTree.cs +++ b/PKHeX.Core/Legality/Evolutions/EvolutionTree.cs @@ -156,20 +156,22 @@ public sealed class EvolutionTree private void FixEvoTreeSM() { // Sun/Moon lack Ultra's Kantonian evolution methods. - BanEvo((int)Species.Raichu, 0, pk => pk.IsUntraded && pk.SM); - BanEvo((int)Species.Marowak, 0, pk => pk.IsUntraded && pk.SM); - BanEvo((int)Species.Exeggutor, 0, pk => pk.IsUntraded && pk.SM); + static bool BanOnlySM(PKM pk) => pk is { IsUntraded: true, SM: true }; + BanEvo((int)Species.Raichu, 0, BanOnlySM); + BanEvo((int)Species.Marowak, 0, BanOnlySM); + BanEvo((int)Species.Exeggutor, 0, BanOnlySM); } private void FixEvoTreeSS() { // Gigantamax Pikachu, Meowth-0, and Eevee are prevented from evolving. // Raichu cannot be evolved to the Alolan variant at this time. - BanEvo((int)Species.Raichu, 0, pk => pk is IGigantamax {CanGigantamax: true}); + static bool BanGmax(PKM pk) => pk is IGigantamax { CanGigantamax: true }; + BanEvo((int)Species.Raichu, 0, BanGmax); BanEvo((int)Species.Raichu, 1, pk => (pk is IGigantamax {CanGigantamax: true}) || pk.Version is (int)GO or >= (int)GP); - BanEvo((int)Species.Persian, 0, pk => pk is IGigantamax {CanGigantamax: true}); - BanEvo((int)Species.Persian, 1, pk => pk is IGigantamax {CanGigantamax: true}); - BanEvo((int)Species.Perrserker, 0, pk => pk is IGigantamax {CanGigantamax: true}); + BanEvo((int)Species.Persian, 0, BanGmax); + BanEvo((int)Species.Persian, 1, BanGmax); + BanEvo((int)Species.Perrserker, 0, BanGmax); BanEvo((int)Species.Exeggutor, 1, pk => pk.Version is (int)GO or >= (int)GP); BanEvo((int)Species.Marowak, 1, pk => pk.Version is (int)GO or >= (int)GP); @@ -177,7 +179,7 @@ public sealed class EvolutionTree BanEvo((int)Species.MrMime, 0, pk => pk.Version >= (int)SW); foreach (var s in GetEvolutions((int)Species.Eevee, 0)) // Eeveelutions - BanEvo(s.Species, s.Form, pk => pk is IGigantamax {CanGigantamax: true}); + BanEvo(s.Species, s.Form, BanGmax); } private void FixEvoTreeBS() @@ -215,6 +217,15 @@ public sealed class EvolutionTree return GetExplicitLineage(species, form, pk, levelMin, levelMax, maxSpeciesOrigin, skipChecks, stopSpecies); } + private static int GetMaxSpeciesOrigin(PKM pk) + { + if (pk.Format == 1) + return MaxSpeciesID_1; + if (pk.Format == 2 || pk.VC) + return MaxSpeciesID_2; + return Legal.GetMaxSpeciesOrigin(pk.Generation); + } + public bool IsSpeciesDerivedFrom(ushort species, byte form, int otherSpecies, int otherForm, bool ignoreForm = true) { var evos = GetEvolutionsAndPreEvolutions(species, form); diff --git a/PKHeX.Core/Legality/Evolutions/Reversal/EvolutionReverseLookup.cs b/PKHeX.Core/Legality/Evolutions/Reversal/EvolutionReverseLookup.cs index 5a663d609..541733d06 100644 --- a/PKHeX.Core/Legality/Evolutions/Reversal/EvolutionReverseLookup.cs +++ b/PKHeX.Core/Legality/Evolutions/Reversal/EvolutionReverseLookup.cs @@ -6,7 +6,7 @@ namespace PKHeX.Core; /// /// Object storing a reversal path for evolution nodes. /// -public class EvolutionReverseLookup : IEvolutionLookup +public sealed class EvolutionReverseLookup : IEvolutionLookup { private readonly EvolutionNode[] Nodes; private readonly int MaxSpecies; diff --git a/PKHeX.Core/Legality/Formatting/LegalityCheckStrings.cs b/PKHeX.Core/Legality/Formatting/LegalityCheckStrings.cs index 388ca2579..158fa3c5b 100644 --- a/PKHeX.Core/Legality/Formatting/LegalityCheckStrings.cs +++ b/PKHeX.Core/Legality/Formatting/LegalityCheckStrings.cs @@ -1,10 +1,13 @@ // ReSharper disable AutoPropertyCanBeMadeGetOnly.Global +using System.Diagnostics.CodeAnalysis; + namespace PKHeX.Core; /// /// Legality Check Message Strings to indicate why certain values are flagged. /// +[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicProperties)] public static class LegalityCheckStrings { // Message String Name format: L/F[Category][Summary] @@ -249,7 +252,7 @@ public static class LegalityCheckStrings public static string LG3EReader { get; set; } = "Non Japanese Shadow E-reader Pokémon. Unreleased encounter."; public static string LG3OTGender { get; set; } = "OT from Colosseum/XD cannot be female."; public static string LG4InvalidTileR45Surf { get; set; } = "Johto Route 45 surfing encounter. Unreachable Water tiles."; - public static string LG5ID_N { get; set; } = "The Name/TID/SID of N is incorrect."; + public static string LG5ID_N { get; set; } = "The Name/TID16/SID16 of N is incorrect."; public static string LG5IVAll30 { get; set; } = "All IVs of N's Pokémon should be 30."; public static string LG5OTGenderN { get; set; } = "N's Pokémon must have a male OT gender."; public static string LG5PIDShinyGrotto { get; set; } = "Hidden Grotto captures cannot be shiny."; @@ -416,12 +419,12 @@ public static class LegalityCheckStrings public static string LOTShort { get; set; } = "OT Name too short."; public static string LOTSuspicious { get; set; } = "Suspicious Original Trainer details."; - public static string LOT_IDEqual { get; set; } = "TID and SID are equal."; - public static string LOT_IDs0 { get; set; } = "TID and SID are 0."; - public static string LOT_SID0 { get; set; } = "SID is zero."; - public static string LOT_SID0Invalid { get; set; } = "SID should be 0."; - public static string LOT_TID0 { get; set; } = "TID is zero."; - public static string LOT_IDInvalid { get; set; } = "TID and SID combination is not possible."; + public static string LOT_IDEqual { get; set; } = "TID16 and SID16 are equal."; + public static string LOT_IDs0 { get; set; } = "TID16 and SID16 are 0."; + public static string LOT_SID0 { get; set; } = "SID16 is zero."; + public static string LOT_SID0Invalid { get; set; } = "SID16 should be 0."; + public static string LOT_TID0 { get; set; } = "TID16 is zero."; + public static string LOT_IDInvalid { get; set; } = "TID16 and SID16 combination is not possible."; public static string LPIDEncryptWurmple { get; set; } = "Wurmple evolution Encryption Constant mismatch."; public static string LPIDEncryptZero { get; set; } = "Encryption Constant is not set."; diff --git a/PKHeX.Core/Legality/LearnSource/Group/LearnGroup1.cs b/PKHeX.Core/Legality/LearnSource/Group/LearnGroup1.cs index a24acf4c0..8700a2b5d 100644 --- a/PKHeX.Core/Legality/LearnSource/Group/LearnGroup1.cs +++ b/PKHeX.Core/Legality/LearnSource/Group/LearnGroup1.cs @@ -23,7 +23,7 @@ public sealed class LearnGroup1 : ILearnGroup public bool Check(Span result, ReadOnlySpan current, PKM pk, EvolutionHistory history, IEncounterTemplate enc, MoveSourceType types = MoveSourceType.All, LearnOption option = LearnOption.Current) { - if (enc.Generation == Generation && types.HasFlagFast(MoveSourceType.Encounter)) + if (enc.Generation == Generation && types.HasFlag(MoveSourceType.Encounter)) CheckEncounterMoves(result, current, enc, pk); var evos = history.Gen1; @@ -176,7 +176,7 @@ public sealed class LearnGroup1 : ILearnGroup for (int i = result.Length - 1; i >= 0; i--) { ref var entry = ref result[i]; - if (entry.Valid && entry.Generation > 2) + if (entry is { Valid: true, Generation: > 2 }) continue; var move = current[i]; @@ -217,7 +217,7 @@ public sealed class LearnGroup1 : ILearnGroup public void GetAllMoves(Span result, PKM pk, EvolutionHistory history, IEncounterTemplate enc, MoveSourceType types = MoveSourceType.All, LearnOption option = LearnOption.Current) { - if (types.HasFlagFast(MoveSourceType.Encounter) && enc.Generation == Generation) + if (types.HasFlag(MoveSourceType.Encounter) && enc.Generation == Generation) FlagEncounterMoves(enc, result); foreach (var evo in history.Gen1) diff --git a/PKHeX.Core/Legality/LearnSource/Group/LearnGroup2.cs b/PKHeX.Core/Legality/LearnSource/Group/LearnGroup2.cs index d2e01a8ff..39865addb 100644 --- a/PKHeX.Core/Legality/LearnSource/Group/LearnGroup2.cs +++ b/PKHeX.Core/Legality/LearnSource/Group/LearnGroup2.cs @@ -22,7 +22,7 @@ public sealed class LearnGroup2 : ILearnGroup public bool Check(Span result, ReadOnlySpan current, PKM pk, EvolutionHistory history, IEncounterTemplate enc, MoveSourceType types = MoveSourceType.All, LearnOption option = LearnOption.Current) { - if (enc.Generation == Generation && types.HasFlagFast(MoveSourceType.Encounter)) + if (enc.Generation == Generation && types.HasFlag(MoveSourceType.Encounter)) CheckEncounterMoves(result, current, enc); var evos = history.Gen2; @@ -103,7 +103,7 @@ public sealed class LearnGroup2 : ILearnGroup for (int i = result.Length - 1; i >= 0; i--) { ref var entry = ref result[i]; - if (entry.Valid && entry.Generation > 2) + if (entry is { Valid: true, Generation: > 2 }) continue; var move = current[i]; @@ -148,7 +148,7 @@ public sealed class LearnGroup2 : ILearnGroup public void GetAllMoves(Span result, PKM pk, EvolutionHistory history, IEncounterTemplate enc, MoveSourceType types = MoveSourceType.All, LearnOption option = LearnOption.Current) { - if (types.HasFlagFast(MoveSourceType.Encounter) && enc.Generation == Generation) + if (types.HasFlag(MoveSourceType.Encounter) && enc.Generation == Generation) FlagEncounterMoves(enc, result); foreach (var evo in history.Gen2) diff --git a/PKHeX.Core/Legality/LearnSource/Group/LearnGroup3.cs b/PKHeX.Core/Legality/LearnSource/Group/LearnGroup3.cs index 501e988da..9fb9594e6 100644 --- a/PKHeX.Core/Legality/LearnSource/Group/LearnGroup3.cs +++ b/PKHeX.Core/Legality/LearnSource/Group/LearnGroup3.cs @@ -20,10 +20,10 @@ public sealed class LearnGroup3 : ILearnGroup for (var i = 0; i < evos.Length; i++) Check(result, current, pk, evos[i], i, types); - if (types.HasFlagFast(MoveSourceType.Encounter) && enc is EncounterEgg { Generation: Generation } egg) + if (types.HasFlag(MoveSourceType.Encounter) && enc is EncounterEgg { Generation: Generation } egg) CheckEncounterMoves(result, current, egg); - if (types.HasFlagFast(MoveSourceType.LevelUp) && enc.Species is (int)Species.Nincada && evos.Length == 2 && evos[0].Species == (int)Species.Shedinja) + if (types.HasFlag(MoveSourceType.LevelUp) && enc.Species is (int)Species.Nincada && evos is [{ Species: (int)Species.Shedinja }, _]) CheckNincadaMoves(result, current, evos[^1]); return MoveResult.AllParsed(result); @@ -161,14 +161,14 @@ public sealed class LearnGroup3 : ILearnGroup public void GetAllMoves(Span result, PKM pk, EvolutionHistory history, IEncounterTemplate enc, MoveSourceType types = MoveSourceType.All, LearnOption option = LearnOption.Current) { - if (types.HasFlagFast(MoveSourceType.Encounter) && enc.Generation == Generation) + if (types.HasFlag(MoveSourceType.Encounter) && enc.Generation == Generation) FlagEncounterMoves(enc, result); var evos = history.Gen3; foreach (var evo in evos) GetAllMoves(result, pk, evo, types); - if (evos.Length == 2 && evos[0].Species == (int)Species.Shedinja) + if (evos is [{ Species: (int)Species.Shedinja }, _]) { var shedinja = LearnSource3E.Instance; var moves = shedinja.GetLearnset((int)Species.Ninjask, 0); diff --git a/PKHeX.Core/Legality/LearnSource/Group/LearnGroup4.cs b/PKHeX.Core/Legality/LearnSource/Group/LearnGroup4.cs index 7488375eb..2257130fc 100644 --- a/PKHeX.Core/Legality/LearnSource/Group/LearnGroup4.cs +++ b/PKHeX.Core/Legality/LearnSource/Group/LearnGroup4.cs @@ -20,10 +20,10 @@ public sealed class LearnGroup4 : ILearnGroup for (var i = 0; i < evos.Length; i++) Check(result, current, pk, evos[i], i); - if (types.HasFlagFast(MoveSourceType.Encounter) && enc is EncounterEgg { Generation: Generation } egg) + if (types.HasFlag(MoveSourceType.Encounter) && enc is EncounterEgg { Generation: Generation } egg) CheckEncounterMoves(result, current, egg); - if (types.HasFlagFast(MoveSourceType.LevelUp) && enc.Species is (int)Species.Nincada && evos.Length == 2 && evos[0].Species == (int)Species.Shedinja) + if (types.HasFlag(MoveSourceType.LevelUp) && enc.Species is (int)Species.Nincada && evos is [{ Species: (int)Species.Shedinja }, _]) CheckNincadaMoves(result, current, evos[^1]); return MoveResult.AllParsed(result); @@ -159,14 +159,14 @@ public sealed class LearnGroup4 : ILearnGroup public void GetAllMoves(Span result, PKM pk, EvolutionHistory history, IEncounterTemplate enc, MoveSourceType types = MoveSourceType.All, LearnOption option = LearnOption.Current) { - if (types.HasFlagFast(MoveSourceType.Encounter) && enc.Generation == Generation) + if (types.HasFlag(MoveSourceType.Encounter) && enc.Generation == Generation) FlagEncounterMoves(enc, result); var evos = history.Gen4; foreach (var evo in evos) GetAllMoves(result, pk, evo, types); - if (evos.Length == 2 && evos[0].Species == (int)Species.Shedinja) + if (evos is [{ Species: (int)Species.Shedinja }, _]) { var shedinja = LearnSource4Pt.Instance; var moves = shedinja.GetLearnset((int)Species.Ninjask, 0); diff --git a/PKHeX.Core/Legality/LearnSource/Group/LearnGroup5.cs b/PKHeX.Core/Legality/LearnSource/Group/LearnGroup5.cs index caf109c37..48774d68e 100644 --- a/PKHeX.Core/Legality/LearnSource/Group/LearnGroup5.cs +++ b/PKHeX.Core/Legality/LearnSource/Group/LearnGroup5.cs @@ -20,7 +20,7 @@ public sealed class LearnGroup5 : ILearnGroup for (var i = 0; i < evos.Length; i++) Check(result, current, pk, evos[i], i, types, option); - if (types.HasFlagFast(MoveSourceType.Encounter) && enc is EncounterEgg { Generation: Generation } egg) + if (types.HasFlag(MoveSourceType.Encounter) && enc is EncounterEgg { Generation: Generation } egg) CheckEncounterMoves(result, current, egg); return MoveResult.AllParsed(result); @@ -113,7 +113,7 @@ public sealed class LearnGroup5 : ILearnGroup public void GetAllMoves(Span result, PKM pk, EvolutionHistory history, IEncounterTemplate enc, MoveSourceType types = MoveSourceType.All, LearnOption option = LearnOption.Current) { - if (types.HasFlagFast(MoveSourceType.Encounter) && enc.Generation == Generation) + if (types.HasFlag(MoveSourceType.Encounter) && enc.Generation == Generation) FlagEncounterMoves(enc, result); foreach (var evo in history.Gen5) diff --git a/PKHeX.Core/Legality/LearnSource/Group/LearnGroup6.cs b/PKHeX.Core/Legality/LearnSource/Group/LearnGroup6.cs index d69c7b449..7866a9be8 100644 --- a/PKHeX.Core/Legality/LearnSource/Group/LearnGroup6.cs +++ b/PKHeX.Core/Legality/LearnSource/Group/LearnGroup6.cs @@ -21,7 +21,7 @@ public sealed class LearnGroup6 : ILearnGroup for (var i = 0; i < evos.Length; i++) Check(result, current, pk, evos[i], i, types, option, mode); - if (option is not LearnOption.Current && types.HasFlagFast(MoveSourceType.Encounter) && enc is EncounterEgg { Generation: Generation } egg) + if (option is not LearnOption.Current && types.HasFlag(MoveSourceType.Encounter) && enc is EncounterEgg { Generation: Generation } egg) CheckEncounterMoves(result, current, egg); return MoveResult.AllParsed(result); @@ -101,9 +101,9 @@ public sealed class LearnGroup6 : ILearnGroup if (mode == CheckMode.Both) CheckBoth(result, current, pk, evo, stage, types, option); else if (mode == CheckMode.AO) - CheckSingle(result, current, pk, evo, stage, LearnSource6AO.Instance, types, option); + CheckSingle, PersonalInfo6AO>(result, current, pk, evo, stage, LearnSource6AO.Instance, types, option); else - CheckSingle(result, current, pk, evo, stage, LearnSource6XY.Instance, types, option); + CheckSingle, PersonalInfo6XY>(result, current, pk, evo, stage, LearnSource6XY.Instance, types, option); } private static void CheckBoth(Span result, ReadOnlySpan current, PKM pk, EvoCriteria evo, int stage, MoveSourceType types, LearnOption option) @@ -114,12 +114,17 @@ public sealed class LearnGroup6 : ILearnGroup return; // should never happen. var xy = LearnSource6XY.Instance; + xy.TryGetPersonal(species, evo.Form, out var xy_pi); + for (int i = result.Length - 1; i >= 0; i--) { if (result[i].Valid) continue; // Level Up moves are different for each game, but others (TM/Tutor) are same. + if (xy_pi is null) + continue; + var move = current[i]; var chk = ao.GetCanLearn(pk, ao_pi, evo, move, types, option); if (chk != default) @@ -127,13 +132,16 @@ public sealed class LearnGroup6 : ILearnGroup result[i] = new(chk, (byte)stage, Generation); continue; } - chk = xy.GetCanLearn(pk, ao_pi, evo, move, types & MoveSourceType.LevelUp, option); + + chk = xy.GetCanLearn(pk, xy_pi, evo, move, types & MoveSourceType.LevelUp, option); if (chk != default) result[i] = new(chk, (byte)stage, Generation); } } - private static void CheckSingle(Span result, ReadOnlySpan current, PKM pk, EvoCriteria evo, int stage, T game, MoveSourceType types, LearnOption option) where T : ILearnSource + private static void CheckSingle(Span result, ReadOnlySpan current, PKM pk, EvoCriteria evo, int stage, TSource game, MoveSourceType types, LearnOption option) + where TSource : ILearnSource + where TPersonal : PersonalInfo { var species = evo.Species; if (!game.TryGetPersonal(species, evo.Form, out var pi)) @@ -153,7 +161,7 @@ public sealed class LearnGroup6 : ILearnGroup public void GetAllMoves(Span result, PKM pk, EvolutionHistory history, IEncounterTemplate enc, MoveSourceType types = MoveSourceType.All, LearnOption option = LearnOption.Current) { - if (types.HasFlagFast(MoveSourceType.Encounter) && enc.Generation == Generation) + if (types.HasFlag(MoveSourceType.Encounter) && enc.Generation == Generation) FlagEncounterMoves(enc, result); var mode = GetCheckMode(enc, pk); diff --git a/PKHeX.Core/Legality/LearnSource/Group/LearnGroup7.cs b/PKHeX.Core/Legality/LearnSource/Group/LearnGroup7.cs index 02bb34431..13450baec 100644 --- a/PKHeX.Core/Legality/LearnSource/Group/LearnGroup7.cs +++ b/PKHeX.Core/Legality/LearnSource/Group/LearnGroup7.cs @@ -28,7 +28,7 @@ public sealed class LearnGroup7 : ILearnGroup for (var i = 0; i < evos.Length; i++) Check(result, current, pk, evos[i], i, types, option, mode); - if (option is not LearnOption.Current && types.HasFlagFast(MoveSourceType.Encounter) && enc is EncounterEgg { Generation: Generation } egg) + if (option is not LearnOption.Current && types.HasFlag(MoveSourceType.Encounter) && enc is EncounterEgg { Generation: Generation } egg) CheckEncounterMoves(result, current, egg); return MoveResult.AllParsed(result); @@ -144,7 +144,7 @@ public sealed class LearnGroup7 : ILearnGroup } } - private static void CheckSingle(Span result, ReadOnlySpan current, PKM pk, EvoCriteria evo, int stage, T game, MoveSourceType types, LearnOption option) where T : ILearnSource + private static void CheckSingle(Span result, ReadOnlySpan current, PKM pk, EvoCriteria evo, int stage, ILearnSource game, MoveSourceType types, LearnOption option) { var species = evo.Species; if (!game.TryGetPersonal(species, evo.Form, out var pi)) @@ -164,7 +164,7 @@ public sealed class LearnGroup7 : ILearnGroup public void GetAllMoves(Span result, PKM pk, EvolutionHistory history, IEncounterTemplate enc, MoveSourceType types = MoveSourceType.All, LearnOption option = LearnOption.Current) { - if (types.HasFlagFast(MoveSourceType.Encounter) && enc.Generation == Generation) + if (types.HasFlag(MoveSourceType.Encounter) && enc.Generation == Generation) FlagEncounterMoves(enc, result); var mode = GetCheckMode(pk); diff --git a/PKHeX.Core/Legality/LearnSource/Group/LearnGroup7b.cs b/PKHeX.Core/Legality/LearnSource/Group/LearnGroup7b.cs index 02716164e..26d1c7b08 100644 --- a/PKHeX.Core/Legality/LearnSource/Group/LearnGroup7b.cs +++ b/PKHeX.Core/Legality/LearnSource/Group/LearnGroup7b.cs @@ -43,7 +43,7 @@ public sealed class LearnGroup7b : ILearnGroup public void GetAllMoves(Span result, PKM pk, EvolutionHistory history, IEncounterTemplate enc, MoveSourceType types = MoveSourceType.All, LearnOption option = LearnOption.Current) { - if (types.HasFlagFast(MoveSourceType.Encounter) && enc.Generation == Generation) + if (types.HasFlag(MoveSourceType.Encounter) && enc.Generation == Generation) FlagEncounterMoves(enc, result); foreach (var evo in history.Gen7b) diff --git a/PKHeX.Core/Legality/LearnSource/Group/LearnGroup8.cs b/PKHeX.Core/Legality/LearnSource/Group/LearnGroup8.cs index b828dd97d..a1de72a51 100644 --- a/PKHeX.Core/Legality/LearnSource/Group/LearnGroup8.cs +++ b/PKHeX.Core/Legality/LearnSource/Group/LearnGroup8.cs @@ -45,7 +45,7 @@ public sealed class LearnGroup8 : ILearnGroup CheckSharedMoves(result, current, evos[0]); - if (option is not LearnOption.Current && types.HasFlagFast(MoveSourceType.Encounter) && pk.IsOriginalMovesetDeleted() && enc is EncounterEgg { Generation: Generation } egg) + if (option is not LearnOption.Current && types.HasFlag(MoveSourceType.Encounter) && pk.IsOriginalMovesetDeleted() && enc is EncounterEgg { Generation: Generation } egg) CheckEncounterMoves(result, current, egg); return MoveResult.AllParsed(result); @@ -130,7 +130,7 @@ public sealed class LearnGroup8 : ILearnGroup public void GetAllMoves(Span result, PKM pk, EvolutionHistory history, IEncounterTemplate enc, MoveSourceType types = MoveSourceType.All, LearnOption option = LearnOption.Current) { var evos = history.Gen8; - if (types.HasFlagFast(MoveSourceType.Encounter) && enc.Context == Context) + if (types.HasFlag(MoveSourceType.Encounter) && enc.Context == Context) { FlagEncounterMoves(enc, result); if (enc is EncounterStatic8N r && r.IsDownLeveled(pk)) diff --git a/PKHeX.Core/Legality/LearnSource/Group/LearnGroup8a.cs b/PKHeX.Core/Legality/LearnSource/Group/LearnGroup8a.cs index b5ddf3040..1ec7231ef 100644 --- a/PKHeX.Core/Legality/LearnSource/Group/LearnGroup8a.cs +++ b/PKHeX.Core/Legality/LearnSource/Group/LearnGroup8a.cs @@ -44,7 +44,7 @@ public sealed class LearnGroup8a : ILearnGroup public void GetAllMoves(Span result, PKM pk, EvolutionHistory history, IEncounterTemplate enc, MoveSourceType types = MoveSourceType.All, LearnOption option = LearnOption.Current) { - if (types.HasFlagFast(MoveSourceType.Encounter) && enc.Context == Context) + if (types.HasFlag(MoveSourceType.Encounter) && enc.Context == Context) FlagEncounterMoves(enc, result); foreach (var evo in history.Gen8a) diff --git a/PKHeX.Core/Legality/LearnSource/Group/LearnGroup8b.cs b/PKHeX.Core/Legality/LearnSource/Group/LearnGroup8b.cs index 31a5a4caf..ba3212b86 100644 --- a/PKHeX.Core/Legality/LearnSource/Group/LearnGroup8b.cs +++ b/PKHeX.Core/Legality/LearnSource/Group/LearnGroup8b.cs @@ -85,7 +85,7 @@ public sealed class LearnGroup8b : ILearnGroup public void GetAllMoves(Span result, PKM pk, EvolutionHistory history, IEncounterTemplate enc, MoveSourceType types = MoveSourceType.All, LearnOption option = LearnOption.Current) { - if (types.HasFlagFast(MoveSourceType.Encounter) && enc.Context == Context) + if (types.HasFlag(MoveSourceType.Encounter) && enc.Context == Context) FlagEncounterMoves(enc, result); foreach (var evo in history.Gen8b) diff --git a/PKHeX.Core/Legality/LearnSource/Group/LearnGroup9.cs b/PKHeX.Core/Legality/LearnSource/Group/LearnGroup9.cs index 6624d2339..9a83644af 100644 --- a/PKHeX.Core/Legality/LearnSource/Group/LearnGroup9.cs +++ b/PKHeX.Core/Legality/LearnSource/Group/LearnGroup9.cs @@ -30,7 +30,7 @@ public sealed class LearnGroup9 : ILearnGroup CheckSharedMoves(result, current, evos[0]); - if (option is not LearnOption.Current && types.HasFlagFast(MoveSourceType.Encounter) && pk.IsOriginalMovesetDeleted() && enc is EncounterEgg { Generation: Generation } egg) + if (option is not LearnOption.Current && types.HasFlag(MoveSourceType.Encounter) && pk.IsOriginalMovesetDeleted() && enc is EncounterEgg { Generation: Generation } egg) CheckEncounterMoves(result, current, egg); return MoveResult.AllParsed(result); @@ -115,7 +115,7 @@ public sealed class LearnGroup9 : ILearnGroup public void GetAllMoves(Span result, PKM pk, EvolutionHistory history, IEncounterTemplate enc, MoveSourceType types = MoveSourceType.All, LearnOption option = LearnOption.Current) { var evos = history.Gen9; - if (types.HasFlagFast(MoveSourceType.Encounter) && enc.Context == Context) + if (types.HasFlag(MoveSourceType.Encounter) && enc.Context == Context) FlagEncounterMoves(enc, result); foreach (var evo in evos) diff --git a/PKHeX.Core/Legality/LearnSource/Sources/LearnSource1RB.cs b/PKHeX.Core/Legality/LearnSource/Sources/LearnSource1RB.cs index cebf01147..945e8ad16 100644 --- a/PKHeX.Core/Legality/LearnSource/Sources/LearnSource1RB.cs +++ b/PKHeX.Core/Legality/LearnSource/Sources/LearnSource1RB.cs @@ -9,35 +9,41 @@ namespace PKHeX.Core; /// /// Exposes information about how moves are learned in . /// -public sealed class LearnSource1RB : ILearnSource +public sealed class LearnSource1RB : ILearnSource { public static readonly LearnSource1RB Instance = new(); private static readonly PersonalTable1 Personal = PersonalTable.RB; private static readonly Learnset[] Learnsets = Legal.LevelUpRB; private const LearnEnvironment Game = RB; + private const int MaxSpecies = Legal.MaxSpeciesID_1; public Learnset GetLearnset(ushort species, byte form) => Learnsets[species]; - public bool TryGetPersonal(ushort species, byte form, [NotNullWhen(true)] out PersonalInfo? pi) + public bool TryGetPersonal(ushort species, byte form, [NotNullWhen(true)] out PersonalInfo1? pi) { - pi = null; - if (form is not 0 || species > Legal.MaxSpeciesID_1) + if (form is not 0 || species > MaxSpecies) + { + pi = null; return false; + } pi = Personal[species]; return true; } - public MoveLearnInfo GetCanLearn(PKM pk, PersonalInfo pi, EvoCriteria evo, ushort move, MoveSourceType types = MoveSourceType.All, LearnOption option = LearnOption.Current) + public MoveLearnInfo GetCanLearn(PKM pk, PersonalInfo1 pi, EvoCriteria evo, ushort move, MoveSourceType types = MoveSourceType.All, LearnOption option = LearnOption.Current) { - if (types.HasFlagFast(MoveSourceType.Machine) && GetIsTM(pi, move)) + if (move > Legal.MaxMoveID_1) // byte + return default; + + if (types.HasFlag(MoveSourceType.Machine) && GetIsTM(pi, (byte)move)) return new(TMHM, Game); - if (types.HasFlagFast(MoveSourceType.SpecialTutor) && GetIsTutor(evo.Species, move)) + if (types.HasFlag(MoveSourceType.SpecialTutor) && GetIsTutor(evo.Species, (byte)move)) return new (Tutor, Game); - if (types.HasFlagFast(MoveSourceType.LevelUp)) + if (types.HasFlag(MoveSourceType.LevelUp)) { - var learn = GetLearnset(evo.Species, evo.Form); + var learn = Learnsets[evo.Species]; var level = learn.GetLevelLearnMove(move); if (level != -1 && evo.LevelMin <= level && level <= evo.LevelMax) return new(LevelUp, Game, (byte)level); @@ -46,7 +52,7 @@ public sealed class LearnSource1RB : ILearnSource return default; } - private static bool GetIsTutor(ushort species, ushort move) + private static bool GetIsTutor(ushort species, byte move) { // No special tutors besides Stadium, which is GB-era only. if (!ParseSettings.AllowGBCartEra) @@ -58,12 +64,12 @@ public sealed class LearnSource1RB : ILearnSource return species is (int)Species.Pikachu or (int)Species.Raichu; } - private static bool GetIsTM(PersonalInfo info, ushort move) + private static bool GetIsTM(PersonalInfo1 info, byte move) { - var index = Array.IndexOf(TMHM_RBY, move); + var index = TMHM_RBY.IndexOf(move); if (index == -1) return false; - return info.TMHM[index]; + return info.GetIsLearnTM(index); } public void GetAllMoves(Span result, PKM pk, EvoCriteria evo, MoveSourceType types = MoveSourceType.All) @@ -71,9 +77,9 @@ public sealed class LearnSource1RB : ILearnSource if (!TryGetPersonal(evo.Species, evo.Form, out var pi)) return; - if (types.HasFlagFast(MoveSourceType.LevelUp)) + if (types.HasFlag(MoveSourceType.LevelUp)) { - var learn = GetLearnset(evo.Species, evo.Form); + var learn = Learnsets[evo.Species]; var min = ParseSettings.AllowGen1Tradeback && ParseSettings.AllowGen2MoveReminder(pk) ? 1 : evo.LevelMin; (bool hasMoves, int start, int end) = learn.GetMoveRange(evo.LevelMax, min); if (hasMoves) @@ -84,18 +90,10 @@ public sealed class LearnSource1RB : ILearnSource } } - if (types.HasFlagFast(MoveSourceType.Machine)) - { - var flags = pi.TMHM; - var moves = TMHM_RBY; - for (int i = 0; i < moves.Length; i++) - { - if (flags[i]) - result[moves[i]] = true; - } - } + if (types.HasFlag(MoveSourceType.Machine)) + pi.SetAllLearnTM(result, TMHM_RBY); - if (types.HasFlagFast(MoveSourceType.SpecialTutor)) + if (types.HasFlag(MoveSourceType.SpecialTutor)) { if (GetIsTutor(evo.Species, (int)Move.Surf)) result[(int)Move.Surf] = true; @@ -108,10 +106,9 @@ public sealed class LearnSource1RB : ILearnSource if (!TryGetPersonal(species, 0, out var personal)) return; - var pi = (PersonalInfo1)personal; var learn = Learnsets[species]; - pi.GetMoves(init); - var start = (4 - init.Count((ushort)0)) & 3; + personal.GetMoves(init); + var start = (4 - init.Count(0)) & 3; learn.SetEncounterMoves(enc.LevelMin, init, start); } } diff --git a/PKHeX.Core/Legality/LearnSource/Sources/LearnSource1YW.cs b/PKHeX.Core/Legality/LearnSource/Sources/LearnSource1YW.cs index 7e68dd846..a6b196dce 100644 --- a/PKHeX.Core/Legality/LearnSource/Sources/LearnSource1YW.cs +++ b/PKHeX.Core/Legality/LearnSource/Sources/LearnSource1YW.cs @@ -9,35 +9,41 @@ namespace PKHeX.Core; /// /// Exposes information about how moves are learned in . /// -public sealed class LearnSource1YW : ILearnSource +public sealed class LearnSource1YW : ILearnSource { public static readonly LearnSource1YW Instance = new(); private static readonly PersonalTable1 Personal = PersonalTable.Y; private static readonly Learnset[] Learnsets = Legal.LevelUpY; private const LearnEnvironment Game = YW; + private const int MaxSpecies = Legal.MaxSpeciesID_1; public Learnset GetLearnset(ushort species, byte form) => Learnsets[species]; - public bool TryGetPersonal(ushort species, byte form, [NotNullWhen(true)] out PersonalInfo? pi) + public bool TryGetPersonal(ushort species, byte form, [NotNullWhen(true)] out PersonalInfo1? pi) { - pi = null; - if (form is not 0 || species > Legal.MaxSpeciesID_1) + if (form is not 0 || species > MaxSpecies) + { + pi = null; return false; + } pi = Personal[species]; return true; } - public MoveLearnInfo GetCanLearn(PKM pk, PersonalInfo pi, EvoCriteria evo, ushort move, MoveSourceType types = MoveSourceType.All, LearnOption option = LearnOption.Current) + public MoveLearnInfo GetCanLearn(PKM pk, PersonalInfo1 pi, EvoCriteria evo, ushort move, MoveSourceType types = MoveSourceType.All, LearnOption option = LearnOption.Current) { - if (types.HasFlagFast(MoveSourceType.Machine) && GetIsTM(pi, move)) + if (move > Legal.MaxMoveID_1) // byte + return default; + + if (types.HasFlag(MoveSourceType.Machine) && GetIsTM(pi, (byte)move)) return new(TMHM, Game); - if (types.HasFlagFast(MoveSourceType.SpecialTutor) && GetIsTutor(evo.Species, move)) + if (types.HasFlag(MoveSourceType.SpecialTutor) && GetIsTutor(evo.Species, (byte)move)) return new(Tutor, Game); - if (types.HasFlagFast(MoveSourceType.LevelUp)) + if (types.HasFlag(MoveSourceType.LevelUp)) { - var learn = GetLearnset(evo.Species, evo.Form); + var learn = Learnsets[evo.Species]; var level = learn.GetLevelLearnMove(move); if (level != -1 && evo.LevelMin <= level && level <= evo.LevelMax) return new(LevelUp, Game, (byte)level); @@ -46,7 +52,7 @@ public sealed class LearnSource1YW : ILearnSource return default; } - private static bool GetIsTutor(ushort species, ushort move) + private static bool GetIsTutor(ushort species, byte move) { // No special tutors besides Stadium, which is GB-era only. if (!ParseSettings.AllowGBCartEra) @@ -58,12 +64,12 @@ public sealed class LearnSource1YW : ILearnSource return species is (int)Species.Pikachu or (int)Species.Raichu; } - private static bool GetIsTM(PersonalInfo info, ushort move) + private static bool GetIsTM(PersonalInfo1 info, byte move) { - var index = Array.IndexOf(TMHM_RBY, move); + var index = TMHM_RBY.IndexOf(move); if (index == -1) return false; - return info.TMHM[index]; + return info.GetIsLearnTM(index); } public void GetAllMoves(Span result, PKM pk, EvoCriteria evo, MoveSourceType types = MoveSourceType.All) @@ -71,7 +77,7 @@ public sealed class LearnSource1YW : ILearnSource if (!TryGetPersonal(evo.Species, evo.Form, out var pi)) return; - if (types.HasFlagFast(MoveSourceType.LevelUp)) + if (types.HasFlag(MoveSourceType.LevelUp)) { var learn = GetLearnset(evo.Species, evo.Form); var min = ParseSettings.AllowGen1Tradeback && ParseSettings.AllowGen2MoveReminder(pk) ? 1 : evo.LevelMin; @@ -84,18 +90,10 @@ public sealed class LearnSource1YW : ILearnSource } } - if (types.HasFlagFast(MoveSourceType.Machine)) - { - var flags = pi.TMHM; - var moves = TMHM_RBY; - for (int i = 0; i < moves.Length; i++) - { - if (flags[i]) - result[moves[i]] = true; - } - } + if (types.HasFlag(MoveSourceType.Machine)) + pi.SetAllLearnTM(result, TMHM_RBY); - if (types.HasFlagFast(MoveSourceType.SpecialTutor)) + if (types.HasFlag(MoveSourceType.SpecialTutor)) { if (GetIsTutor(evo.Species, (int)Move.Surf)) result[(int)Move.Surf] = true; @@ -108,9 +106,8 @@ public sealed class LearnSource1YW : ILearnSource if (!TryGetPersonal(species, 0, out var personal)) return; - var pi = (PersonalInfo1)personal; var learn = Learnsets[species]; - pi.GetMoves(init); + personal.GetMoves(init); var start = (4 - init.Count((ushort)0)) & 3; learn.SetEncounterMoves(enc.LevelMin, init, start); } diff --git a/PKHeX.Core/Legality/LearnSource/Sources/LearnSource2C.cs b/PKHeX.Core/Legality/LearnSource/Sources/LearnSource2C.cs index 058acdee6..187b63262 100644 --- a/PKHeX.Core/Legality/LearnSource/Sources/LearnSource2C.cs +++ b/PKHeX.Core/Legality/LearnSource/Sources/LearnSource2C.cs @@ -9,7 +9,7 @@ namespace PKHeX.Core; /// /// Exposes information about how moves are learned in . /// -public sealed class LearnSource2C : ILearnSource, IEggSource +public sealed class LearnSource2C : ILearnSource, IEggSource { public static readonly LearnSource2C Instance = new(); private static readonly PersonalTable2 Personal = PersonalTable.C; @@ -17,15 +17,16 @@ public sealed class LearnSource2C : ILearnSource, IEggSource private static readonly Learnset[] Learnsets = Legal.LevelUpC; private const int MaxSpecies = Legal.MaxSpeciesID_2; private const LearnEnvironment Game = C; - private const int CountTMHM = 57; public Learnset GetLearnset(ushort species, byte form) => Learnsets[species]; - public bool TryGetPersonal(ushort species, byte form, [NotNullWhen(true)] out PersonalInfo? pi) + public bool TryGetPersonal(ushort species, byte form, [NotNullWhen(true)] out PersonalInfo2? pi) { - pi = null; - if (species > Legal.MaxSpeciesID_2) + if (form is not 0 || species > MaxSpecies) + { + pi = null; return false; + } pi = Personal[species]; return true; } @@ -45,15 +46,18 @@ public sealed class LearnSource2C : ILearnSource, IEggSource return EggMoves[species].Moves; } - public MoveLearnInfo GetCanLearn(PKM pk, PersonalInfo pi, EvoCriteria evo, ushort move, MoveSourceType types = MoveSourceType.All, LearnOption option = LearnOption.Current) + public MoveLearnInfo GetCanLearn(PKM pk, PersonalInfo2 pi, EvoCriteria evo, ushort move, MoveSourceType types = MoveSourceType.All, LearnOption option = LearnOption.Current) { - if (types.HasFlagFast(MoveSourceType.Machine) && GetIsTM(pi, move)) + if (move > Legal.MaxMoveID_2) // byte + return default; + + if (types.HasFlag(MoveSourceType.Machine) && GetIsTM(pi, (byte)move)) return new(TMHM, Game); - if (types.HasFlagFast(MoveSourceType.SpecialTutor) && GetIsSpecialTutor(pk, evo.Species, move)) + if (types.HasFlag(MoveSourceType.SpecialTutor) && GetIsSpecialTutor(pk, evo.Species, (byte)move)) return new(Tutor, Game); - if (types.HasFlagFast(MoveSourceType.LevelUp)) + if (types.HasFlag(MoveSourceType.LevelUp)) { var learn = GetLearnset(evo.Species, evo.Form); var level = learn.GetLevelLearnMove(move); @@ -64,23 +68,23 @@ public sealed class LearnSource2C : ILearnSource, IEggSource return default; } - private static bool GetIsSpecialTutor(PKM pk, ushort species, ushort move) + private static bool GetIsSpecialTutor(PKM pk, ushort species, byte move) { if (!ParseSettings.AllowGen2Crystal(pk)) return false; - var tutor = Array.IndexOf(Tutors_GSC, move); + var tutor = Tutors_GSC.IndexOf(move); if (tutor == -1) return false; var info = PersonalTable.C[species]; - return info.TMHM[CountTMHM + tutor]; + return info.GetIsLearnTutorType(tutor); } - private static bool GetIsTM(PersonalInfo info, ushort move) + private static bool GetIsTM(PersonalInfo2 info, byte move) { - var index = Array.IndexOf(TMHM_GSC, move); + var index = TMHM_GSC.IndexOf(move); if (index == -1) return false; - return info.TMHM[index]; + return info.GetIsLearnTM(index); } public void GetAllMoves(Span result, PKM pk, EvoCriteria evo, MoveSourceType types = MoveSourceType.All) @@ -89,7 +93,7 @@ public sealed class LearnSource2C : ILearnSource, IEggSource return; bool removeVC = pk.Format == 1 || pk.VC1; - if (types.HasFlagFast(MoveSourceType.LevelUp)) + if (types.HasFlag(MoveSourceType.LevelUp)) { var learn = GetLearnset(evo.Species, evo.Form); var min = ParseSettings.AllowGen2MoveReminder(pk) ? 1 : evo.LevelMin; @@ -106,30 +110,11 @@ public sealed class LearnSource2C : ILearnSource, IEggSource } } - if (types.HasFlagFast(MoveSourceType.Machine)) - { - var flags = pi.TMHM; - var moves = TMHM_GSC; - for (int i = 0; i < moves.Length; i++) - { - if (flags[i]) - { - var move = moves[i]; - if (!removeVC || move <= Legal.MaxMoveID_1) - result[move] = true; - } - } - } + if (types.HasFlag(MoveSourceType.Machine)) + pi.SetAllLearnTM(result, TMHM_GSC); - if (types.HasFlagFast(MoveSourceType.SpecialTutor)) - { - var flags = pi.TMHM; - for (int i = CountTMHM; i < flags.Length; i++) - { - if (flags[i]) - result[Tutors_GSC[i - CountTMHM]] = true; - } - } + if (types.HasFlag(MoveSourceType.SpecialTutor)) + pi.SetAllLearnTutorType(result, Tutors_GSC); } public static void GetEncounterMoves(IEncounterTemplate enc, Span init) diff --git a/PKHeX.Core/Legality/LearnSource/Sources/LearnSource2GS.cs b/PKHeX.Core/Legality/LearnSource/Sources/LearnSource2GS.cs index f5f19502a..ddb634d2f 100644 --- a/PKHeX.Core/Legality/LearnSource/Sources/LearnSource2GS.cs +++ b/PKHeX.Core/Legality/LearnSource/Sources/LearnSource2GS.cs @@ -9,7 +9,7 @@ namespace PKHeX.Core; /// /// Exposes information about how moves are learned in . /// -public sealed class LearnSource2GS : ILearnSource, IEggSource +public sealed class LearnSource2GS : ILearnSource, IEggSource { public static readonly LearnSource2GS Instance = new(); private static readonly PersonalTable2 Personal = PersonalTable.GS; @@ -20,11 +20,13 @@ public sealed class LearnSource2GS : ILearnSource, IEggSource public Learnset GetLearnset(ushort species, byte form) => Learnsets[species]; - public bool TryGetPersonal(ushort species, byte form, [NotNullWhen(true)] out PersonalInfo? pi) + public bool TryGetPersonal(ushort species, byte form, [NotNullWhen(true)] out PersonalInfo2? pi) { - pi = null; - if (species > MaxSpecies) + if (form is not 0 || species > MaxSpecies) + { + pi = null; return false; + } pi = Personal[species]; return true; } @@ -39,19 +41,22 @@ public sealed class LearnSource2GS : ILearnSource, IEggSource public ReadOnlySpan GetEggMoves(ushort species, byte form) { - if ((uint)species > MaxSpecies) + if (species > MaxSpecies) return ReadOnlySpan.Empty; return EggMoves[species].Moves; } - public MoveLearnInfo GetCanLearn(PKM pk, PersonalInfo pi, EvoCriteria evo, ushort move, MoveSourceType types = MoveSourceType.All, LearnOption option = LearnOption.Current) + public MoveLearnInfo GetCanLearn(PKM pk, PersonalInfo2 pi, EvoCriteria evo, ushort move, MoveSourceType types = MoveSourceType.All, LearnOption option = LearnOption.Current) { - if (types.HasFlagFast(MoveSourceType.Machine) && GetIsTM(pi, move)) + if (move > Legal.MaxMoveID_2) // byte + return default; + + if (types.HasFlag(MoveSourceType.Machine) && GetIsTM(pi, (byte)move)) return new(TMHM, Game); - if (types.HasFlagFast(MoveSourceType.LevelUp)) + if (types.HasFlag(MoveSourceType.LevelUp)) { - var learn = GetLearnset(evo.Species, evo.Form); + var learn = Learnsets[evo.Species]; var level = learn.GetLevelLearnMove(move); if (level != -1 && evo.LevelMin <= level && level <= evo.LevelMax) return new(LevelUp, Game, (byte)level); @@ -60,12 +65,12 @@ public sealed class LearnSource2GS : ILearnSource, IEggSource return default; } - private static bool GetIsTM(PersonalInfo info, ushort move) + private static bool GetIsTM(PersonalInfo2 info, byte move) { - var index = Array.IndexOf(TMHM_GSC, move); + var index = TMHM_GSC.IndexOf(move); if (index == -1) return false; - return info.TMHM[index]; + return info.GetIsLearnTM(index); } public void GetAllMoves(Span result, PKM pk, EvoCriteria evo, MoveSourceType types = MoveSourceType.All) @@ -74,9 +79,9 @@ public sealed class LearnSource2GS : ILearnSource, IEggSource return; bool removeVC = pk.Format == 1 || pk.VC1; - if (types.HasFlagFast(MoveSourceType.LevelUp)) + if (types.HasFlag(MoveSourceType.LevelUp)) { - var learn = GetLearnset(evo.Species, evo.Form); + var learn = Learnsets[evo.Species]; var min = ParseSettings.AllowGen2MoveReminder(pk) ? 1 : evo.LevelMin; (bool hasMoves, int start, int end) = learn.GetMoveRange(evo.LevelMax, min); if (hasMoves) @@ -91,20 +96,8 @@ public sealed class LearnSource2GS : ILearnSource, IEggSource } } - if (types.HasFlagFast(MoveSourceType.Machine)) - { - var flags = pi.TMHM; - var moves = TMHM_GSC; - for (int i = 0; i < moves.Length; i++) - { - if (flags[i]) - { - var move = moves[i]; - if (!removeVC || move <= Legal.MaxMoveID_1) - result[move] = true; - } - } - } + if (types.HasFlag(MoveSourceType.Machine)) + pi.SetAllLearnTM(result, TMHM_GSC); } public static void GetEncounterMoves(IEncounterTemplate enc, Span init) diff --git a/PKHeX.Core/Legality/LearnSource/Sources/LearnSource3E.cs b/PKHeX.Core/Legality/LearnSource/Sources/LearnSource3E.cs index 3f1a3f6b9..d2bdb7ef2 100644 --- a/PKHeX.Core/Legality/LearnSource/Sources/LearnSource3E.cs +++ b/PKHeX.Core/Legality/LearnSource/Sources/LearnSource3E.cs @@ -9,7 +9,7 @@ namespace PKHeX.Core; /// /// Exposes information about how moves are learned in . /// -public sealed class LearnSource3E : ILearnSource, IEggSource +public sealed class LearnSource3E : ILearnSource, IEggSource { public static readonly LearnSource3E Instance = new(); private static readonly PersonalTable3 Personal = PersonalTable.E; @@ -21,9 +21,9 @@ public sealed class LearnSource3E : ILearnSource, IEggSource private const int CountTM = 50; public Learnset GetLearnset(ushort species, byte form) => Learnsets[species]; - internal PersonalInfo this[ushort species] => Personal[species]; + internal PersonalInfo3 this[ushort species] => Personal[species]; - public bool TryGetPersonal(ushort species, byte form, [NotNullWhen(true)] out PersonalInfo? pi) + public bool TryGetPersonal(ushort species, byte form, [NotNullWhen(true)] out PersonalInfo3? pi) { pi = null; if (species > MaxSpecies) @@ -47,9 +47,9 @@ public sealed class LearnSource3E : ILearnSource, IEggSource return EggMoves[species].Moves; } - public MoveLearnInfo GetCanLearn(PKM pk, PersonalInfo pi, EvoCriteria evo, ushort move, MoveSourceType types = MoveSourceType.All, LearnOption option = LearnOption.Current) + public MoveLearnInfo GetCanLearn(PKM pk, PersonalInfo3 pi, EvoCriteria evo, ushort move, MoveSourceType types = MoveSourceType.All, LearnOption option = LearnOption.Current) { - if (types.HasFlagFast(MoveSourceType.LevelUp)) + if (types.HasFlag(MoveSourceType.LevelUp)) { var learn = GetLearnset(evo.Species, evo.Form); var level = learn.GetLevelLearnMove(move); @@ -57,7 +57,7 @@ public sealed class LearnSource3E : ILearnSource, IEggSource return new(LevelUp, Game, (byte)level); } - if (types.HasFlagFast(MoveSourceType.Machine)) + if (types.HasFlag(MoveSourceType.Machine)) { if (GetIsTM(pi, move)) return new(TMHM, Game); @@ -65,7 +65,7 @@ public sealed class LearnSource3E : ILearnSource, IEggSource return new(TMHM, Game); } - if (types.HasFlagFast(MoveSourceType.SpecialTutor) && GetIsSpecialTutor(evo.Species, move)) + if (types.HasFlag(MoveSourceType.SpecialTutor) && GetIsSpecialTutor(evo.Species, move)) return new(Tutor, Game); return default; @@ -80,7 +80,7 @@ public sealed class LearnSource3E : ILearnSource, IEggSource return info.TypeTutors[index]; } - private static bool GetIsTM(PersonalInfo info, ushort move) + private static bool GetIsTM(PersonalInfo3 info, ushort move) { var index = Array.IndexOf(TM_3, move); if (index == -1) @@ -88,7 +88,7 @@ public sealed class LearnSource3E : ILearnSource, IEggSource return info.TMHM[index]; } - private static bool GetIsHM(PersonalInfo info, ushort move) + private static bool GetIsHM(PersonalInfo3 info, ushort move) { var index = Array.IndexOf(HM_3, move); if (index == -1) @@ -101,7 +101,7 @@ public sealed class LearnSource3E : ILearnSource, IEggSource if (!TryGetPersonal(evo.Species, evo.Form, out var pi)) return; - if (types.HasFlagFast(MoveSourceType.LevelUp)) + if (types.HasFlag(MoveSourceType.LevelUp)) { var learn = GetLearnset(evo.Species, evo.Form); (bool hasMoves, int start, int end) = learn.GetMoveRange(evo.LevelMax); @@ -113,7 +113,7 @@ public sealed class LearnSource3E : ILearnSource, IEggSource } } - if (types.HasFlagFast(MoveSourceType.Machine)) + if (types.HasFlag(MoveSourceType.Machine)) { var flags = pi.TMHM; var moves = TM_3; @@ -134,7 +134,7 @@ public sealed class LearnSource3E : ILearnSource, IEggSource } } - if (types.HasFlagFast(MoveSourceType.SpecialTutor)) + if (types.HasFlag(MoveSourceType.SpecialTutor)) { var flags = pi.TypeTutors; var moves = Tutor_E; diff --git a/PKHeX.Core/Legality/LearnSource/Sources/LearnSource3FR.cs b/PKHeX.Core/Legality/LearnSource/Sources/LearnSource3FR.cs index 2806dc271..2feed166a 100644 --- a/PKHeX.Core/Legality/LearnSource/Sources/LearnSource3FR.cs +++ b/PKHeX.Core/Legality/LearnSource/Sources/LearnSource3FR.cs @@ -9,7 +9,7 @@ namespace PKHeX.Core; /// /// Exposes information about how moves are learned in . /// -public sealed class LearnSource3FR : ILearnSource, IEggSource +public sealed class LearnSource3FR : ILearnSource, IEggSource { public static readonly LearnSource3FR Instance = new(); private static readonly PersonalTable3 Personal = PersonalTable.FR; @@ -21,9 +21,9 @@ public sealed class LearnSource3FR : ILearnSource, IEggSource private const int CountTM = 50; public Learnset GetLearnset(ushort species, byte form) => Learnsets[species]; - internal PersonalInfo this[ushort species] => Personal[species]; + internal PersonalInfo3 this[ushort species] => Personal[species]; - public bool TryGetPersonal(ushort species, byte form, [NotNullWhen(true)] out PersonalInfo? pi) + public bool TryGetPersonal(ushort species, byte form, [NotNullWhen(true)] out PersonalInfo3? pi) { pi = null; if (species > MaxSpecies) @@ -47,9 +47,9 @@ public sealed class LearnSource3FR : ILearnSource, IEggSource return EggMoves[species].Moves; } - public MoveLearnInfo GetCanLearn(PKM pk, PersonalInfo pi, EvoCriteria evo, ushort move, MoveSourceType types = MoveSourceType.All, LearnOption option = LearnOption.Current) + public MoveLearnInfo GetCanLearn(PKM pk, PersonalInfo3 pi, EvoCriteria evo, ushort move, MoveSourceType types = MoveSourceType.All, LearnOption option = LearnOption.Current) { - if (types.HasFlagFast(MoveSourceType.LevelUp)) + if (types.HasFlag(MoveSourceType.LevelUp)) { var learn = GetLearnset(evo.Species, evo.Form); var level = learn.GetLevelLearnMove(move); @@ -57,7 +57,7 @@ public sealed class LearnSource3FR : ILearnSource, IEggSource return new(LevelUp, Game, (byte)level); } - if (types.HasFlagFast(MoveSourceType.Machine)) + if (types.HasFlag(MoveSourceType.Machine)) { if (GetIsTM(pi, move)) return new(TMHM, Game); @@ -65,7 +65,7 @@ public sealed class LearnSource3FR : ILearnSource, IEggSource return new(TMHM, Game); } - if (types.HasFlagFast(MoveSourceType.SpecialTutor) && GetIsTutor(evo.Species, move)) + if (types.HasFlag(MoveSourceType.SpecialTutor) && GetIsTutor(evo.Species, move)) return new(Tutor, Game); return default; @@ -79,7 +79,7 @@ public sealed class LearnSource3FR : ILearnSource, IEggSource _ => false, }; - private static bool GetIsTM(PersonalInfo info, ushort move) + private static bool GetIsTM(PersonalInfo3 info, ushort move) { var index = Array.IndexOf(TM_3, move); if (index == -1) @@ -87,7 +87,7 @@ public sealed class LearnSource3FR : ILearnSource, IEggSource return info.TMHM[index]; } - private static bool GetIsHM(PersonalInfo info, ushort move) + private static bool GetIsHM(PersonalInfo3 info, ushort move) { var index = Array.IndexOf(HM_3, move); if (index == -1) @@ -100,7 +100,7 @@ public sealed class LearnSource3FR : ILearnSource, IEggSource if (!TryGetPersonal(evo.Species, evo.Form, out var pi)) return; - if (types.HasFlagFast(MoveSourceType.LevelUp)) + if (types.HasFlag(MoveSourceType.LevelUp)) { var learn = GetLearnset(evo.Species, evo.Form); (bool hasMoves, int start, int end) = learn.GetMoveRange(evo.LevelMax); @@ -112,7 +112,7 @@ public sealed class LearnSource3FR : ILearnSource, IEggSource } } - if (types.HasFlagFast(MoveSourceType.Machine)) + if (types.HasFlag(MoveSourceType.Machine)) { var flags = pi.TMHM; var moves = TM_3; @@ -133,7 +133,7 @@ public sealed class LearnSource3FR : ILearnSource, IEggSource } } - if (types.HasFlagFast(MoveSourceType.SpecialTutor)) + if (types.HasFlag(MoveSourceType.SpecialTutor)) { if (evo.Species == (int)Species.Charizard) result[(int)Move.BlastBurn] = true; diff --git a/PKHeX.Core/Legality/LearnSource/Sources/LearnSource3LG.cs b/PKHeX.Core/Legality/LearnSource/Sources/LearnSource3LG.cs index 9e7b4ee46..959ba40dd 100644 --- a/PKHeX.Core/Legality/LearnSource/Sources/LearnSource3LG.cs +++ b/PKHeX.Core/Legality/LearnSource/Sources/LearnSource3LG.cs @@ -9,7 +9,7 @@ namespace PKHeX.Core; /// /// Exposes information about how moves are learned in . /// -public sealed class LearnSource3LG : ILearnSource, IEggSource +public sealed class LearnSource3LG : ILearnSource, IEggSource { public static readonly LearnSource3LG Instance = new(); private static readonly PersonalTable3 Personal = PersonalTable.LG; @@ -21,9 +21,9 @@ public sealed class LearnSource3LG : ILearnSource, IEggSource private const int CountTM = 50; public Learnset GetLearnset(ushort species, byte form) => Learnsets[species]; - internal PersonalInfo this[ushort species] => Personal[species]; + internal PersonalInfo3 this[ushort species] => Personal[species]; - public bool TryGetPersonal(ushort species, byte form, [NotNullWhen(true)] out PersonalInfo? pi) + public bool TryGetPersonal(ushort species, byte form, [NotNullWhen(true)] out PersonalInfo3? pi) { pi = null; if (species > MaxSpecies) @@ -47,9 +47,9 @@ public sealed class LearnSource3LG : ILearnSource, IEggSource return EggMoves[species].Moves; } - public MoveLearnInfo GetCanLearn(PKM pk, PersonalInfo pi, EvoCriteria evo, ushort move, MoveSourceType types = MoveSourceType.All, LearnOption option = LearnOption.Current) + public MoveLearnInfo GetCanLearn(PKM pk, PersonalInfo3 pi, EvoCriteria evo, ushort move, MoveSourceType types = MoveSourceType.All, LearnOption option = LearnOption.Current) { - if (types.HasFlagFast(MoveSourceType.LevelUp)) + if (types.HasFlag(MoveSourceType.LevelUp)) { var learn = GetLearnset(evo.Species, evo.Form); var level = learn.GetLevelLearnMove(move); @@ -57,7 +57,7 @@ public sealed class LearnSource3LG : ILearnSource, IEggSource return new(LevelUp, Game, (byte)level); } - if (types.HasFlagFast(MoveSourceType.Machine)) + if (types.HasFlag(MoveSourceType.Machine)) { if (GetIsTM(pi, move)) return new(TMHM, Game); @@ -65,7 +65,7 @@ public sealed class LearnSource3LG : ILearnSource, IEggSource return new(TMHM, Game); } - if (types.HasFlagFast(MoveSourceType.SpecialTutor) && GetIsTutor(evo.Species, move)) + if (types.HasFlag(MoveSourceType.SpecialTutor) && GetIsTutor(evo.Species, move)) return new(Tutor, Game); return default; @@ -79,7 +79,7 @@ public sealed class LearnSource3LG : ILearnSource, IEggSource _ => false, }; - private static bool GetIsTM(PersonalInfo info, ushort move) + private static bool GetIsTM(PersonalInfo3 info, ushort move) { var index = Array.IndexOf(TM_3, move); if (index == -1) @@ -87,7 +87,7 @@ public sealed class LearnSource3LG : ILearnSource, IEggSource return info.TMHM[index]; } - private static bool GetIsHM(PersonalInfo info, ushort move) + private static bool GetIsHM(PersonalInfo3 info, ushort move) { var index = Array.IndexOf(HM_3, move); if (index == -1) @@ -100,7 +100,7 @@ public sealed class LearnSource3LG : ILearnSource, IEggSource if (!TryGetPersonal(evo.Species, evo.Form, out var pi)) return; - if (types.HasFlagFast(MoveSourceType.LevelUp)) + if (types.HasFlag(MoveSourceType.LevelUp)) { var learn = GetLearnset(evo.Species, evo.Form); (bool hasMoves, int start, int end) = learn.GetMoveRange(evo.LevelMax); @@ -112,7 +112,7 @@ public sealed class LearnSource3LG : ILearnSource, IEggSource } } - if (types.HasFlagFast(MoveSourceType.Machine)) + if (types.HasFlag(MoveSourceType.Machine)) { var flags = pi.TMHM; var moves = TM_3; @@ -133,7 +133,7 @@ public sealed class LearnSource3LG : ILearnSource, IEggSource } } - if (types.HasFlagFast(MoveSourceType.SpecialTutor)) + if (types.HasFlag(MoveSourceType.SpecialTutor)) { if (evo.Species == (int)Species.Charizard) result[(int)Move.BlastBurn] = true; diff --git a/PKHeX.Core/Legality/LearnSource/Sources/LearnSource3RS.cs b/PKHeX.Core/Legality/LearnSource/Sources/LearnSource3RS.cs index d787d1875..8eaefb978 100644 --- a/PKHeX.Core/Legality/LearnSource/Sources/LearnSource3RS.cs +++ b/PKHeX.Core/Legality/LearnSource/Sources/LearnSource3RS.cs @@ -9,7 +9,7 @@ namespace PKHeX.Core; /// /// Exposes information about how moves are learned in . /// -public sealed class LearnSource3RS : ILearnSource, IEggSource +public sealed class LearnSource3RS : ILearnSource, IEggSource { public static readonly LearnSource3RS Instance = new(); private static readonly PersonalTable3 Personal = PersonalTable.RS; @@ -22,7 +22,7 @@ public sealed class LearnSource3RS : ILearnSource, IEggSource public Learnset GetLearnset(ushort species, byte form) => Learnsets[species]; - public bool TryGetPersonal(ushort species, byte form, [NotNullWhen(true)] out PersonalInfo? pi) + public bool TryGetPersonal(ushort species, byte form, [NotNullWhen(true)] out PersonalInfo3? pi) { pi = null; if (species > MaxSpecies) @@ -46,9 +46,9 @@ public sealed class LearnSource3RS : ILearnSource, IEggSource return EggMoves[species].Moves; } - public MoveLearnInfo GetCanLearn(PKM pk, PersonalInfo pi, EvoCriteria evo, ushort move, MoveSourceType types = MoveSourceType.All, LearnOption option = LearnOption.Current) + public MoveLearnInfo GetCanLearn(PKM pk, PersonalInfo3 pi, EvoCriteria evo, ushort move, MoveSourceType types = MoveSourceType.All, LearnOption option = LearnOption.Current) { - if (types.HasFlagFast(MoveSourceType.LevelUp)) + if (types.HasFlag(MoveSourceType.LevelUp)) { var learn = GetLearnset(evo.Species, evo.Form); var level = learn.GetLevelLearnMove(move); @@ -56,7 +56,7 @@ public sealed class LearnSource3RS : ILearnSource, IEggSource return new(LevelUp, Game, (byte)level); } - if (types.HasFlagFast(MoveSourceType.Machine)) + if (types.HasFlag(MoveSourceType.Machine)) { if (GetIsTM(pi, move)) return new(TMHM, Game); @@ -64,7 +64,7 @@ public sealed class LearnSource3RS : ILearnSource, IEggSource return new(TMHM, Game); } - if (types.HasFlagFast(MoveSourceType.SpecialTutor) && GetIsTutor(evo.Species, move)) + if (types.HasFlag(MoveSourceType.SpecialTutor) && GetIsTutor(evo.Species, move)) return new(Tutor, Game); return default; @@ -85,7 +85,7 @@ public sealed class LearnSource3RS : ILearnSource, IEggSource }; } - private static bool GetIsTM(PersonalInfo info, ushort move) + private static bool GetIsTM(PersonalInfo3 info, ushort move) { var index = Array.IndexOf(TM_3, move); if (index == -1) @@ -93,7 +93,7 @@ public sealed class LearnSource3RS : ILearnSource, IEggSource return info.TMHM[index]; } - private static bool GetIsHM(PersonalInfo info, ushort move) + private static bool GetIsHM(PersonalInfo3 info, ushort move) { var index = Array.IndexOf(HM_3, move); if (index == -1) @@ -106,7 +106,7 @@ public sealed class LearnSource3RS : ILearnSource, IEggSource if (!TryGetPersonal(evo.Species, evo.Form, out var pi)) return; - if (types.HasFlagFast(MoveSourceType.LevelUp)) + if (types.HasFlag(MoveSourceType.LevelUp)) { var learn = GetLearnset(evo.Species, evo.Form); (bool hasMoves, int start, int end) = learn.GetMoveRange(evo.LevelMax); @@ -118,7 +118,7 @@ public sealed class LearnSource3RS : ILearnSource, IEggSource } } - if (types.HasFlagFast(MoveSourceType.Machine)) + if (types.HasFlag(MoveSourceType.Machine)) { var flags = pi.TMHM; var moves = TM_3; @@ -139,7 +139,7 @@ public sealed class LearnSource3RS : ILearnSource, IEggSource } } - if (types.HasFlagFast(MoveSourceType.SpecialTutor)) + if (types.HasFlag(MoveSourceType.SpecialTutor)) { if (evo.Species == (int)Species.Mew) { diff --git a/PKHeX.Core/Legality/LearnSource/Sources/LearnSource4DP.cs b/PKHeX.Core/Legality/LearnSource/Sources/LearnSource4DP.cs index 227449e5a..daa6c6d7b 100644 --- a/PKHeX.Core/Legality/LearnSource/Sources/LearnSource4DP.cs +++ b/PKHeX.Core/Legality/LearnSource/Sources/LearnSource4DP.cs @@ -9,7 +9,7 @@ namespace PKHeX.Core; /// /// Exposes information about how moves are learned in . /// -public sealed class LearnSource4DP : ILearnSource, IEggSource +public sealed class LearnSource4DP : ILearnSource, IEggSource { public static readonly LearnSource4DP Instance = new(); private static readonly PersonalTable4 Personal = PersonalTable.DP; @@ -22,7 +22,7 @@ public sealed class LearnSource4DP : ILearnSource, IEggSource public Learnset GetLearnset(ushort species, byte form) => Learnsets[Personal.GetFormIndex(species, form)]; - public bool TryGetPersonal(ushort species, byte form, [NotNullWhen(true)] out PersonalInfo? pi) + public bool TryGetPersonal(ushort species, byte form, [NotNullWhen(true)] out PersonalInfo4? pi) { pi = null; if (species > MaxSpecies) @@ -46,9 +46,9 @@ public sealed class LearnSource4DP : ILearnSource, IEggSource return EggMoves[species].Moves; } - public MoveLearnInfo GetCanLearn(PKM pk, PersonalInfo pi, EvoCriteria evo, ushort move, MoveSourceType types = MoveSourceType.All, LearnOption option = LearnOption.Current) + public MoveLearnInfo GetCanLearn(PKM pk, PersonalInfo4 pi, EvoCriteria evo, ushort move, MoveSourceType types = MoveSourceType.All, LearnOption option = LearnOption.Current) { - if (types.HasFlagFast(MoveSourceType.LevelUp)) + if (types.HasFlag(MoveSourceType.LevelUp)) { var learn = GetLearnset(evo.Species, evo.Form); var level = learn.GetLevelLearnMove(move); @@ -56,7 +56,7 @@ public sealed class LearnSource4DP : ILearnSource, IEggSource return new(LevelUp, Game, (byte)level); } - if (types.HasFlagFast(MoveSourceType.Machine)) + if (types.HasFlag(MoveSourceType.Machine)) { if (GetIsTM(pi, move)) return new(TMHM, Game); @@ -64,10 +64,10 @@ public sealed class LearnSource4DP : ILearnSource, IEggSource return new(TMHM, Game); } - if (types.HasFlagFast(MoveSourceType.TypeTutor) && GetIsTypeTutor(evo.Species, move)) + if (types.HasFlag(MoveSourceType.TypeTutor) && GetIsTypeTutor(evo.Species, move)) return new(Tutor, Game); - if (types.HasFlagFast(MoveSourceType.SpecialTutor) && GetIsSpecialTutor(pi, move)) + if (types.HasFlag(MoveSourceType.SpecialTutor) && GetIsSpecialTutor(pi, move)) return new(Tutor, Game); return default; @@ -82,7 +82,7 @@ public sealed class LearnSource4DP : ILearnSource, IEggSource return list.IndexOf(species) != -1; } - private static bool GetIsSpecialTutor(PersonalInfo pi, ushort move) + private static bool GetIsSpecialTutor(PersonalInfo4 pi, ushort move) { var index = Array.IndexOf(Tutors_4, move); if (index == -1) @@ -90,20 +90,16 @@ public sealed class LearnSource4DP : ILearnSource, IEggSource return pi.TypeTutors[index]; } - private static bool GetIsTM(PersonalInfo info, ushort move) + private static bool GetIsTM(PersonalInfo4 info, ushort move) { var index = Array.IndexOf(TM_4, move); - if (index == -1) - return false; - return info.TMHM[index]; + return info.GetIsLearnTM(index); } - private static bool GetIsHM(PersonalInfo info, ushort move) + private static bool GetIsHM(PersonalInfo4 info, ushort move) { var index = Array.IndexOf(HM_DPPt, move); - if (index == -1) - return false; - return info.TMHM[CountTM + index]; + return info.GetIsLearnTM(CountTM + index); } public void GetAllMoves(Span result, PKM pk, EvoCriteria evo, MoveSourceType types = MoveSourceType.All) @@ -111,7 +107,7 @@ public sealed class LearnSource4DP : ILearnSource, IEggSource if (!TryGetPersonal(evo.Species, evo.Form, out var pi)) return; - if (types.HasFlagFast(MoveSourceType.LevelUp)) + if (types.HasFlag(MoveSourceType.LevelUp)) { var learn = GetLearnset(evo.Species, evo.Form); (bool hasMoves, int start, int end) = learn.GetMoveRange(evo.LevelMax); @@ -123,42 +119,17 @@ public sealed class LearnSource4DP : ILearnSource, IEggSource } } - if (types.HasFlagFast(MoveSourceType.Machine)) + if (types.HasFlag(MoveSourceType.Machine)) { - var flags = pi.TMHM; - var moves = TM_4; - for (int i = 0; i < moves.Length; i++) - { - if (flags[i]) - result[moves[i]] = true; - } + pi.SetAllLearnTM(result, TM_4); if (pk.Format == Generation) - { - moves = HM_DPPt; - for (int i = 0; i < moves.Length; i++) - { - if (flags[CountTM + i]) - result[moves[i]] = true; - } - } - else - { - // Permit Defog to leak through if transferred to Gen5+ (via HG/SS) - if (flags[CountTM + 4]) - result[(int)Move.Defog] = true; - } + pi.SetAllLearnHM(result, HM_DPPt); + else if (pi.GetIsLearnHM(4)) // Permit Defog to leak through if transferred to Gen5+ (via HG/SS) + result[(int)Move.Defog] = true; } - if (types.HasFlagFast(MoveSourceType.SpecialTutor)) - { - var flags = pi.TypeTutors; - var moves = Tutors_4; - for (int i = 0; i < moves.Length; i++) - { - if (flags[i]) - result[moves[i]] = true; - } - } + if (types.HasFlag(MoveSourceType.SpecialTutor)) + pi.SetAllLearnTutorType(result, Tutors_4); } } diff --git a/PKHeX.Core/Legality/LearnSource/Sources/LearnSource4HGSS.cs b/PKHeX.Core/Legality/LearnSource/Sources/LearnSource4HGSS.cs index e6d04f868..faa2626dd 100644 --- a/PKHeX.Core/Legality/LearnSource/Sources/LearnSource4HGSS.cs +++ b/PKHeX.Core/Legality/LearnSource/Sources/LearnSource4HGSS.cs @@ -9,7 +9,7 @@ namespace PKHeX.Core; /// /// Exposes information about how moves are learned in . /// -public sealed class LearnSource4HGSS : ILearnSource, IEggSource +public sealed class LearnSource4HGSS : ILearnSource, IEggSource { public static readonly LearnSource4HGSS Instance = new(); private static readonly PersonalTable4 Personal = PersonalTable.HGSS; @@ -22,7 +22,7 @@ public sealed class LearnSource4HGSS : ILearnSource, IEggSource public Learnset GetLearnset(ushort species, byte form) => Learnsets[Personal.GetFormIndex(species, form)]; - public bool TryGetPersonal(ushort species, byte form, [NotNullWhen(true)] out PersonalInfo? pi) + public bool TryGetPersonal(ushort species, byte form, [NotNullWhen(true)] out PersonalInfo4? pi) { pi = null; if (species > MaxSpecies) @@ -46,9 +46,9 @@ public sealed class LearnSource4HGSS : ILearnSource, IEggSource return EggMoves[species].Moves; } - public MoveLearnInfo GetCanLearn(PKM pk, PersonalInfo pi, EvoCriteria evo, ushort move, MoveSourceType types = MoveSourceType.All, LearnOption option = LearnOption.Current) + public MoveLearnInfo GetCanLearn(PKM pk, PersonalInfo4 pi, EvoCriteria evo, ushort move, MoveSourceType types = MoveSourceType.All, LearnOption option = LearnOption.Current) { - if (types.HasFlagFast(MoveSourceType.LevelUp)) + if (types.HasFlag(MoveSourceType.LevelUp)) { var learn = GetLearnset(evo.Species, evo.Form); var level = learn.GetLevelLearnMove(move); @@ -56,7 +56,7 @@ public sealed class LearnSource4HGSS : ILearnSource, IEggSource return new(LevelUp, Game, (byte)level); } - if (types.HasFlagFast(MoveSourceType.Machine)) + if (types.HasFlag(MoveSourceType.Machine)) { if (GetIsTM(pi, move)) return new(TMHM, Game); @@ -64,13 +64,13 @@ public sealed class LearnSource4HGSS : ILearnSource, IEggSource return new(TMHM, Game); } - if (types.HasFlagFast(MoveSourceType.TypeTutor) && GetIsTypeTutor(evo.Species, move)) + if (types.HasFlag(MoveSourceType.TypeTutor) && GetIsTypeTutor(evo.Species, move)) return new(Tutor, Game); - if (types.HasFlagFast(MoveSourceType.SpecialTutor) && GetIsSpecialTutor(pi, move)) + if (types.HasFlag(MoveSourceType.SpecialTutor) && GetIsSpecialTutor(pi, move)) return new(Tutor, Game); - if (types.HasFlagFast(MoveSourceType.EnhancedTutor) && GetIsEnhancedTutor(evo, pk, move, option)) + if (types.HasFlag(MoveSourceType.EnhancedTutor) && GetIsEnhancedTutor(evo, pk, move, option)) return new(Tutor, Game); return default; @@ -95,7 +95,7 @@ public sealed class LearnSource4HGSS : ILearnSource, IEggSource return Array.IndexOf(list, species) != -1; } - private static bool GetIsSpecialTutor(PersonalInfo pi, ushort move) + private static bool GetIsSpecialTutor(PersonalInfo4 pi, ushort move) { var index = Array.IndexOf(Tutors_4, move); if (index == -1) @@ -103,20 +103,16 @@ public sealed class LearnSource4HGSS : ILearnSource, IEggSource return pi.TypeTutors[index]; } - private static bool GetIsTM(PersonalInfo info, ushort move) + private static bool GetIsTM(PersonalInfo4 info, ushort move) { var index = Array.IndexOf(TM_4, move); - if (index == -1) - return false; - return info.TMHM[index]; + return info.GetIsLearnTM(index); } - private static bool GetIsHM(PersonalInfo info, ushort move) + private static bool GetIsHM(PersonalInfo4 info, ushort move) { var index = Array.IndexOf(HM_HGSS, move); - if (index == -1) - return false; - return info.TMHM[CountTM + index]; + return info.GetIsLearnHM(index); } public void GetAllMoves(Span result, PKM pk, EvoCriteria evo, MoveSourceType types = MoveSourceType.All) @@ -124,7 +120,7 @@ public sealed class LearnSource4HGSS : ILearnSource, IEggSource if (!TryGetPersonal(evo.Species, evo.Form, out var pi)) return; - if (types.HasFlagFast(MoveSourceType.LevelUp)) + if (types.HasFlag(MoveSourceType.LevelUp)) { var learn = GetLearnset(evo.Species, evo.Form); (bool hasMoves, int start, int end) = learn.GetMoveRange(evo.LevelMax); @@ -136,34 +132,17 @@ public sealed class LearnSource4HGSS : ILearnSource, IEggSource } } - if (types.HasFlagFast(MoveSourceType.Machine)) + if (types.HasFlag(MoveSourceType.Machine)) { - var flags = pi.TMHM; - var moves = TM_4; - for (int i = 0; i < moves.Length; i++) - { - if (flags[i]) - result[moves[i]] = true; - } + pi.SetAllLearnTM(result, TM_4); if (pk.Format == Generation) - { - moves = HM_HGSS; - for (int i = 0; i < moves.Length; i++) - { - if (flags[CountTM + i]) - result[moves[i]] = true; - } - } - else - { - // Permit Whirlpool to leak through if transferred to Gen5+ (via D/P/Pt) - if (flags[CountTM + 4]) - result[(int)Move.Whirlpool] = true; - } + pi.SetAllLearnHM(result, HM_HGSS); + else if (pi.GetIsLearnHM(4)) // Permit Whirlpool to leak through if transferred to Gen5+ (via D/P/Pt) + result[(int)Move.Whirlpool] = true; } - if (types.HasFlagFast(MoveSourceType.TypeTutor)) + if (types.HasFlag(MoveSourceType.TypeTutor)) { // Elemental Beams var species = SpecialTutors_Compatibility_4; @@ -175,19 +154,11 @@ public sealed class LearnSource4HGSS : ILearnSource, IEggSource result[moves[i]] = true; } } + + if (types.HasFlag(MoveSourceType.SpecialTutor)) + pi.SetAllLearnTutorType(result, Tutors_4); - if (types.HasFlagFast(MoveSourceType.SpecialTutor)) - { - var flags = pi.TypeTutors; - var moves = Tutors_4; - for (int i = 0; i < moves.Length; i++) - { - if (flags[i]) - result[moves[i]] = true; - } - } - - if (types.HasFlagFast(MoveSourceType.EnhancedTutor)) + if (types.HasFlag(MoveSourceType.EnhancedTutor)) { if (evo.Species is (int)Species.Rotom && evo.Form is not 0) result[MoveTutor.GetRotomFormMove(evo.Form)] = true; diff --git a/PKHeX.Core/Legality/LearnSource/Sources/LearnSource4Pt.cs b/PKHeX.Core/Legality/LearnSource/Sources/LearnSource4Pt.cs index f8e45c478..422db8bcc 100644 --- a/PKHeX.Core/Legality/LearnSource/Sources/LearnSource4Pt.cs +++ b/PKHeX.Core/Legality/LearnSource/Sources/LearnSource4Pt.cs @@ -9,7 +9,7 @@ namespace PKHeX.Core; /// /// Exposes information about how moves are learned in . /// -public sealed class LearnSource4Pt : ILearnSource, IEggSource +public sealed class LearnSource4Pt : ILearnSource, IEggSource { public static readonly LearnSource4Pt Instance = new(); private static readonly PersonalTable4 Personal = PersonalTable.Pt; @@ -22,7 +22,7 @@ public sealed class LearnSource4Pt : ILearnSource, IEggSource public Learnset GetLearnset(ushort species, byte form) => Learnsets[Personal.GetFormIndex(species, form)]; - public bool TryGetPersonal(ushort species, byte form, [NotNullWhen(true)] out PersonalInfo? pi) + public bool TryGetPersonal(ushort species, byte form, [NotNullWhen(true)] out PersonalInfo4? pi) { pi = null; if (species > MaxSpecies) @@ -46,9 +46,9 @@ public sealed class LearnSource4Pt : ILearnSource, IEggSource return EggMoves[species].Moves; } - public MoveLearnInfo GetCanLearn(PKM pk, PersonalInfo pi, EvoCriteria evo, ushort move, MoveSourceType types = MoveSourceType.All, LearnOption option = LearnOption.Current) + public MoveLearnInfo GetCanLearn(PKM pk, PersonalInfo4 pi, EvoCriteria evo, ushort move, MoveSourceType types = MoveSourceType.All, LearnOption option = LearnOption.Current) { - if (types.HasFlagFast(MoveSourceType.LevelUp)) + if (types.HasFlag(MoveSourceType.LevelUp)) { var learn = GetLearnset(evo.Species, evo.Form); var level = learn.GetLevelLearnMove(move); @@ -56,7 +56,7 @@ public sealed class LearnSource4Pt : ILearnSource, IEggSource return new(LevelUp, Game, (byte)level); } - if (types.HasFlagFast(MoveSourceType.Machine)) + if (types.HasFlag(MoveSourceType.Machine)) { if (GetIsTM(pi, move)) return new(TMHM, Game); @@ -64,13 +64,13 @@ public sealed class LearnSource4Pt : ILearnSource, IEggSource return new(TMHM, Game); } - if (types.HasFlagFast(MoveSourceType.TypeTutor) && GetIsTypeTutor(evo.Species, move)) + if (types.HasFlag(MoveSourceType.TypeTutor) && GetIsTypeTutor(evo.Species, move)) return new(Tutor, Game); - if (types.HasFlagFast(MoveSourceType.SpecialTutor) && GetIsSpecialTutor(pi, move)) + if (types.HasFlag(MoveSourceType.SpecialTutor) && GetIsSpecialTutor(pi, move)) return new(Tutor, Game); - if (types.HasFlagFast(MoveSourceType.EnhancedTutor) && GetIsEnhancedTutor(evo, pk, move, option)) + if (types.HasFlag(MoveSourceType.EnhancedTutor) && GetIsEnhancedTutor(evo, pk, move, option)) return new(Tutor, Game); return default; @@ -95,7 +95,7 @@ public sealed class LearnSource4Pt : ILearnSource, IEggSource return Array.IndexOf(list, species) != -1; } - private static bool GetIsSpecialTutor(PersonalInfo pi, ushort move) + private static bool GetIsSpecialTutor(PersonalInfo4 pi, ushort move) { var index = Array.IndexOf(Tutors_4, move); if (index == -1) @@ -103,20 +103,16 @@ public sealed class LearnSource4Pt : ILearnSource, IEggSource return pi.TypeTutors[index]; } - private static bool GetIsTM(PersonalInfo info, ushort move) + private static bool GetIsTM(PersonalInfo4 info, ushort move) { var index = Array.IndexOf(TM_4, move); - if (index == -1) - return false; - return info.TMHM[index]; + return info.GetIsLearnTM(index); } - private static bool GetIsHM(PersonalInfo info, ushort move) + private static bool GetIsHM(PersonalInfo4 info, ushort move) { var index = Array.IndexOf(HM_DPPt, move); - if (index == -1) - return false; - return info.TMHM[CountTM + index]; + return info.GetIsLearnHM(index); } public void GetAllMoves(Span result, PKM pk, EvoCriteria evo, MoveSourceType types = MoveSourceType.All) @@ -124,7 +120,7 @@ public sealed class LearnSource4Pt : ILearnSource, IEggSource if (!TryGetPersonal(evo.Species, evo.Form, out var pi)) return; - if (types.HasFlagFast(MoveSourceType.LevelUp)) + if (types.HasFlag(MoveSourceType.LevelUp)) { var learn = GetLearnset(evo.Species, evo.Form); (bool hasMoves, int start, int end) = learn.GetMoveRange(evo.LevelMax); @@ -136,34 +132,17 @@ public sealed class LearnSource4Pt : ILearnSource, IEggSource } } - if (types.HasFlagFast(MoveSourceType.Machine)) + if (types.HasFlag(MoveSourceType.Machine)) { - var flags = pi.TMHM; - var moves = TM_4; - for (int i = 0; i < moves.Length; i++) - { - if (flags[i]) - result[moves[i]] = true; - } + pi.SetAllLearnTM(result, TM_4); if (pk.Format == Generation) - { - moves = HM_DPPt; - for (int i = 0; i < moves.Length; i++) - { - if (flags[CountTM + i]) - result[moves[i]] = true; - } - } - else - { - // Permit Defog to leak through if transferred to Gen5+ (via HG/SS) - if (flags[CountTM + 4]) - result[(int)Move.Defog] = true; - } + pi.SetAllLearnHM(result, HM_DPPt); + else if (pi.GetIsLearnHM(4)) // Permit Defog to leak through if transferred to Gen5+ (via HG/SS) + result[(int)Move.Defog] = true; } - if (types.HasFlagFast(MoveSourceType.SpecialTutor)) + if (types.HasFlag(MoveSourceType.SpecialTutor)) { var flags = pi.TypeTutors; var moves = Tutors_4; @@ -174,7 +153,7 @@ public sealed class LearnSource4Pt : ILearnSource, IEggSource } } - if (types.HasFlagFast(MoveSourceType.EnhancedTutor)) + if (types.HasFlag(MoveSourceType.EnhancedTutor)) { if (evo.Species is (int)Species.Rotom && evo.Form is not 0) result[MoveTutor.GetRotomFormMove(evo.Form)] = true; diff --git a/PKHeX.Core/Legality/LearnSource/Sources/LearnSource5B2W2.cs b/PKHeX.Core/Legality/LearnSource/Sources/LearnSource5B2W2.cs index 91900ac98..d68bd7cab 100644 --- a/PKHeX.Core/Legality/LearnSource/Sources/LearnSource5B2W2.cs +++ b/PKHeX.Core/Legality/LearnSource/Sources/LearnSource5B2W2.cs @@ -9,7 +9,7 @@ namespace PKHeX.Core; /// /// Exposes information about how moves are learned in . /// -public sealed class LearnSource5B2W2 : ILearnSource, IEggSource +public sealed class LearnSource5B2W2 : ILearnSource, IEggSource { public static readonly LearnSource5B2W2 Instance = new(); private static readonly PersonalTable5B2W2 Personal = PersonalTable.B2W2; @@ -20,7 +20,7 @@ public sealed class LearnSource5B2W2 : ILearnSource, IEggSource public Learnset GetLearnset(ushort species, byte form) => Learnsets[Personal.GetFormIndex(species, form)]; - public bool TryGetPersonal(ushort species, byte form, [NotNullWhen(true)] out PersonalInfo? pi) + public bool TryGetPersonal(ushort species, byte form, [NotNullWhen(true)] out PersonalInfo5B2W2? pi) { pi = null; if (species > MaxSpecies) @@ -44,9 +44,9 @@ public sealed class LearnSource5B2W2 : ILearnSource, IEggSource return EggMoves[species].Moves; } - public MoveLearnInfo GetCanLearn(PKM pk, PersonalInfo pi, EvoCriteria evo, ushort move, MoveSourceType types = MoveSourceType.All, LearnOption option = LearnOption.Current) + public MoveLearnInfo GetCanLearn(PKM pk, PersonalInfo5B2W2 pi, EvoCriteria evo, ushort move, MoveSourceType types = MoveSourceType.All, LearnOption option = LearnOption.Current) { - if (types.HasFlagFast(MoveSourceType.LevelUp)) + if (types.HasFlag(MoveSourceType.LevelUp)) { var learn = GetLearnset(evo.Species, evo.Form); var level = learn.GetLevelLearnMove(move); @@ -54,36 +54,21 @@ public sealed class LearnSource5B2W2 : ILearnSource, IEggSource return new(LevelUp, Game, (byte)level); } - if (types.HasFlagFast(MoveSourceType.Machine) && GetIsTM(pi, move)) + if (types.HasFlag(MoveSourceType.Machine) && GetIsTM(pi, move)) return new(TMHM, Game); - if (types.HasFlagFast(MoveSourceType.TypeTutor) && GetIsTypeTutor(pi, move)) + if (types.HasFlag(MoveSourceType.TypeTutor) && GetIsTypeTutor(pi, move)) return new(Tutor, Game); - if (types.HasFlagFast(MoveSourceType.SpecialTutor) && GetIsSpecialTutor(pi, move)) + if (types.HasFlag(MoveSourceType.SpecialTutor) && pi.GetIsTutorSpecial(move)) return new(Tutor, Game); - if (types.HasFlagFast(MoveSourceType.EnhancedTutor) && GetIsEnhancedTutor(evo, pk, move, option)) + if (types.HasFlag(MoveSourceType.EnhancedTutor) && GetIsEnhancedTutor(evo, pk, move, option)) return new(Tutor, Game); return default; } - private static bool GetIsSpecialTutor(PersonalInfo pi, ushort move) - { - var tutors = Tutors_B2W2; - for (int i = 0; i < tutors.Length; i++) - { - var tutor = Array.IndexOf(tutors[i], move); - if (tutor == -1) - continue; - if (pi.SpecialTutors[i][tutor]) - return true; - break; - } - return false; - } - private static bool GetIsEnhancedTutor(EvoCriteria evo, ISpeciesForm current, ushort move, LearnOption option) => evo.Species switch { (int)Species.Keldeo => move is (int)Move.SecretSword, @@ -100,20 +85,20 @@ public sealed class LearnSource5B2W2 : ILearnSource, IEggSource _ => false, }; - private static bool GetIsTypeTutor(PersonalInfo pi, ushort move) + private static bool GetIsTypeTutor(PersonalInfo5B2W2 pi, ushort move) { var index = Array.IndexOf(TypeTutor567, move); if (index == -1) return false; - return pi.TypeTutors[index]; + return pi.GetIsLearnTutorType(index); } - private static bool GetIsTM(PersonalInfo info, ushort move) + private static bool GetIsTM(PersonalInfo5B2W2 info, ushort move) { var index = Array.IndexOf(TMHM_BW, move); if (index == -1) return false; - return info.TMHM[index]; + return info.GetIsLearnTM(index); } public void GetAllMoves(Span result, PKM pk, EvoCriteria evo, MoveSourceType types = MoveSourceType.All) @@ -121,7 +106,7 @@ public sealed class LearnSource5B2W2 : ILearnSource, IEggSource if (!TryGetPersonal(evo.Species, evo.Form, out var pi)) return; - if (types.HasFlagFast(MoveSourceType.LevelUp)) + if (types.HasFlag(MoveSourceType.LevelUp)) { var learn = GetLearnset(evo.Species, evo.Form); (bool hasMoves, int start, int end) = learn.GetMoveRange(evo.LevelMax); @@ -133,45 +118,14 @@ public sealed class LearnSource5B2W2 : ILearnSource, IEggSource } } - if (types.HasFlagFast(MoveSourceType.Machine)) - { - var flags = pi.TMHM; - var moves = TMHM_BW; - for (int i = 0; i < moves.Length; i++) - { - if (flags[i]) - result[moves[i]] = true; - } - } + if (types.HasFlag(MoveSourceType.Machine)) + pi.SetAllLearnTM(result, TMHM_BW); + if (types.HasFlag(MoveSourceType.TypeTutor)) + pi.SetAllLearnTutorType(result, TypeTutor567); + if (types.HasFlag(MoveSourceType.SpecialTutor)) + pi.SetAllLearnTutorSpecial(result); - if (types.HasFlagFast(MoveSourceType.TypeTutor)) - { - var flags = pi.TypeTutors; - var moves = TypeTutor567; - for (int i = 0; i < moves.Length; i++) - { - if (flags[i]) - result[moves[i]] = true; - } - } - - if (types.HasFlagFast(MoveSourceType.SpecialTutor)) - { - // B2W2 Tutors - var tutors = Tutors_B2W2; - for (int i = 0; i < tutors.Length; i++) - { - var flags = pi.SpecialTutors[i]; - var moves = tutors[i]; - for (int m = 0; m < moves.Length; m++) - { - if (flags[m]) - result[moves[m]] = true; - } - } - } - - if (types.HasFlagFast(MoveSourceType.EnhancedTutor)) + if (types.HasFlag(MoveSourceType.EnhancedTutor)) { var species = evo.Species; if (species is (int)Species.Rotom && evo.Form is not 0) @@ -182,12 +136,4 @@ public sealed class LearnSource5B2W2 : ILearnSource, IEggSource result[(int)Move.RelicSong] = true; } } - - internal static readonly ushort[][] Tutors_B2W2 = - { - new ushort[] { 450, 343, 162, 530, 324, 442, 402, 529, 340, 067, 441, 253, 009, 007, 008 }, // Driftveil City - new ushort[] { 277, 335, 414, 492, 356, 393, 334, 387, 276, 527, 196, 401, 399, 428, 406, 304, 231 }, // Lentimas Town - new ushort[] { 020, 173, 282, 235, 257, 272, 215, 366, 143, 220, 202, 409, 355 }, // Humilau City - new ushort[] { 380, 388, 180, 495, 270, 271, 478, 472, 283, 200, 278, 289, 446, 214, 285 }, // Nacrene City - }; } diff --git a/PKHeX.Core/Legality/LearnSource/Sources/LearnSource5BW.cs b/PKHeX.Core/Legality/LearnSource/Sources/LearnSource5BW.cs index 7d995e8f6..4ca9785e0 100644 --- a/PKHeX.Core/Legality/LearnSource/Sources/LearnSource5BW.cs +++ b/PKHeX.Core/Legality/LearnSource/Sources/LearnSource5BW.cs @@ -9,7 +9,7 @@ namespace PKHeX.Core; /// /// Exposes information about how moves are learned in . /// -public sealed class LearnSource5BW : ILearnSource, IEggSource +public sealed class LearnSource5BW : ILearnSource, IEggSource { public static readonly LearnSource5BW Instance = new(); private static readonly PersonalTable5BW Personal = PersonalTable.BW; @@ -20,7 +20,7 @@ public sealed class LearnSource5BW : ILearnSource, IEggSource public Learnset GetLearnset(ushort species, byte form) => Learnsets[Personal.GetFormIndex(species, form)]; - public bool TryGetPersonal(ushort species, byte form, [NotNullWhen(true)] out PersonalInfo? pi) + public bool TryGetPersonal(ushort species, byte form, [NotNullWhen(true)] out PersonalInfo5BW? pi) { pi = null; if (!Personal.IsPresentInGame(species, form)) @@ -44,9 +44,9 @@ public sealed class LearnSource5BW : ILearnSource, IEggSource return EggMoves[species].Moves; } - public MoveLearnInfo GetCanLearn(PKM pk, PersonalInfo pi, EvoCriteria evo, ushort move, MoveSourceType types = MoveSourceType.All, LearnOption option = LearnOption.Current) + public MoveLearnInfo GetCanLearn(PKM pk, PersonalInfo5BW pi, EvoCriteria evo, ushort move, MoveSourceType types = MoveSourceType.All, LearnOption option = LearnOption.Current) { - if (types.HasFlagFast(MoveSourceType.LevelUp)) + if (types.HasFlag(MoveSourceType.LevelUp)) { var learn = GetLearnset(evo.Species, evo.Form); var level = learn.GetLevelLearnMove(move); @@ -54,13 +54,13 @@ public sealed class LearnSource5BW : ILearnSource, IEggSource return new(LevelUp, Game, (byte)level); } - if (types.HasFlagFast(MoveSourceType.Machine) && GetIsTM(pi, move)) + if (types.HasFlag(MoveSourceType.Machine) && GetIsTM(pi, move)) return new(TMHM, Game); - if (types.HasFlagFast(MoveSourceType.TypeTutor) && GetIsTypeTutor(pi, move)) + if (types.HasFlag(MoveSourceType.TypeTutor) && GetIsTypeTutor(pi, move)) return new(Tutor, Game); - if (types.HasFlagFast(MoveSourceType.EnhancedTutor) && GetIsEnhancedTutor(evo, pk, move, option)) + if (types.HasFlag(MoveSourceType.EnhancedTutor) && GetIsEnhancedTutor(evo, pk, move, option)) return new(Tutor, Game); return default; @@ -82,20 +82,20 @@ public sealed class LearnSource5BW : ILearnSource, IEggSource _ => false, }; - private static bool GetIsTypeTutor(PersonalInfo pi, ushort move) + private static bool GetIsTypeTutor(PersonalInfo5BW pi, ushort move) { var index = Array.IndexOf(TypeTutor567, move); if (index == -1) return false; - return pi.TypeTutors[index]; + return pi.GetIsLearnTutorType(index); } - private static bool GetIsTM(PersonalInfo info, ushort move) + private static bool GetIsTM(PersonalInfo5BW info, ushort move) { var index = Array.IndexOf(TMHM_BW, move); if (index == -1) return false; - return info.TMHM[index] && index != 94; // TM95 not available in this game + return info.GetIsLearnTM(index) && index != 94; // TM95 not available in this game } public void GetAllMoves(Span result, PKM pk, EvoCriteria evo, MoveSourceType types = MoveSourceType.All) @@ -103,7 +103,7 @@ public sealed class LearnSource5BW : ILearnSource, IEggSource if (!TryGetPersonal(evo.Species, evo.Form, out var pi)) return; - if (types.HasFlagFast(MoveSourceType.LevelUp)) + if (types.HasFlag(MoveSourceType.LevelUp)) { var learn = GetLearnset(evo.Species, evo.Form); (bool hasMoves, int start, int end) = learn.GetMoveRange(evo.LevelMax); @@ -115,36 +115,22 @@ public sealed class LearnSource5BW : ILearnSource, IEggSource } } - if (types.HasFlagFast(MoveSourceType.Machine)) + if (types.HasFlag(MoveSourceType.Machine)) { - var flags = pi.TMHM; - var moves = TMHM_BW; - for (int i = 95; i < moves.Length; i++) - { - if (flags[i]) - result[moves[i]] = true; - } // TM95 is unavailable (Snarl - Lock Capsule) - for (int i = 0; i < 94; i++) - { - if (flags[i]) - result[moves[i]] = true; - } + // Cache the current value to clear it if so. + var tm95 = result[(int)Move.Snarl]; + pi.SetAllLearnTM(result, TMHM_BW); + if (!tm95) + result[(int)Move.Snarl] = tm95; } - if (types.HasFlagFast(MoveSourceType.TypeTutor)) + if (types.HasFlag(MoveSourceType.TypeTutor)) { - // Beams - var flags = pi.TypeTutors; - var moves = TypeTutor567; - for (int i = 0; i < moves.Length; i++) - { - if (flags[i]) - result[moves[i]] = true; - } + pi.SetAllLearnTutorType(result, TypeTutor567); } - if (types.HasFlagFast(MoveSourceType.EnhancedTutor)) + if (types.HasFlag(MoveSourceType.EnhancedTutor)) { var species = evo.Species; if (species is (int)Species.Rotom && evo.Form is not 0) diff --git a/PKHeX.Core/Legality/LearnSource/Sources/LearnSource6AO.cs b/PKHeX.Core/Legality/LearnSource/Sources/LearnSource6AO.cs index 6626fd628..c716aac25 100644 --- a/PKHeX.Core/Legality/LearnSource/Sources/LearnSource6AO.cs +++ b/PKHeX.Core/Legality/LearnSource/Sources/LearnSource6AO.cs @@ -8,7 +8,7 @@ namespace PKHeX.Core; /// /// Exposes information about how moves are learned in . /// -public sealed class LearnSource6AO : ILearnSource, IEggSource +public sealed class LearnSource6AO : ILearnSource, IEggSource { public static readonly LearnSource6AO Instance = new(); private static readonly PersonalTable6AO Personal = PersonalTable.AO; @@ -19,10 +19,10 @@ public sealed class LearnSource6AO : ILearnSource, IEggSource public Learnset GetLearnset(ushort species, byte form) => Learnsets[Personal.GetFormIndex(species, form)]; - public bool TryGetPersonal(ushort species, byte form, [NotNullWhen(true)] out PersonalInfo? pi) + public bool TryGetPersonal(ushort species, byte form, [NotNullWhen(true)] out PersonalInfo6AO? pi) { pi = null; - if ((uint)species > MaxSpecies) + if (species > MaxSpecies) return false; pi = Personal[species, form]; return true; @@ -43,9 +43,9 @@ public sealed class LearnSource6AO : ILearnSource, IEggSource return EggMoves[species].Moves; } - public MoveLearnInfo GetCanLearn(PKM pk, PersonalInfo pi, EvoCriteria evo, ushort move, MoveSourceType types = MoveSourceType.All, LearnOption option = LearnOption.Current) + public MoveLearnInfo GetCanLearn(PKM pk, PersonalInfo6AO pi, EvoCriteria evo, ushort move, MoveSourceType types = MoveSourceType.All, LearnOption option = LearnOption.Current) { - if (types.HasFlagFast(MoveSourceType.LevelUp)) + if (types.HasFlag(MoveSourceType.LevelUp)) { var learn = GetLearnset(evo.Species, evo.Form); var level = learn.GetLevelLearnMove(move); @@ -53,16 +53,16 @@ public sealed class LearnSource6AO : ILearnSource, IEggSource return new(LevelUp, Game, (byte)level); } - if (types.HasFlagFast(MoveSourceType.Machine) && GetIsTM(pi, move)) + if (types.HasFlag(MoveSourceType.Machine) && GetIsTM(pi, move)) return new(TMHM, Game); - if (types.HasFlagFast(MoveSourceType.TypeTutor) && GetIsTypeTutor(pi, move)) + if (types.HasFlag(MoveSourceType.TypeTutor) && pi.GetIsLearnTutorType(Array.IndexOf(LearnSource5.TypeTutor567, move))) return new(Tutor, Game); - if (types.HasFlagFast(MoveSourceType.SpecialTutor) && GetIsSpecialTutor(pi, move)) + if (types.HasFlag(MoveSourceType.SpecialTutor) && pi.GetIsTutorSpecial(move)) return new(Tutor, Game); - if (types.HasFlagFast(MoveSourceType.EnhancedTutor) && GetIsEnhancedTutor(evo, pk, move, option)) + if (types.HasFlag(MoveSourceType.EnhancedTutor) && GetIsEnhancedTutor(evo, pk, move, option)) return new(Tutor, Game); return default; @@ -84,44 +84,10 @@ public sealed class LearnSource6AO : ILearnSource, IEggSource _ => false, }; - private static bool GetIsTypeTutor(PersonalInfo pi, ushort move) - { - var tutors = Tutors_AO; - for (int i = 0; i < tutors.Length; i++) - { - var tutor = Array.IndexOf(tutors[i], move); - if (tutor == -1) - continue; - if (pi.SpecialTutors[i][tutor]) - return true; - break; - } - - var index = Array.IndexOf(LearnSource5.TypeTutor567, move); - if (index == -1) - return false; - return pi.TypeTutors[index]; - } - - private static bool GetIsSpecialTutor(PersonalInfo pi, ushort move) - { - var tutors = Tutors_AO; - for (int i = 0; i < tutors.Length; i++) - { - var index = Array.IndexOf(tutors[i], move); - if (index == -1) - continue; - return pi.SpecialTutors[i][index]; - } - return false; - } - - private static bool GetIsTM(PersonalInfo info, ushort move) + private static bool GetIsTM(PersonalInfo6AO info, ushort move) { var index = Array.IndexOf(TMHM_AO, move); - if (index == -1) - return false; - return info.TMHM[index]; + return info.GetIsLearnTM(index); } public void GetAllMoves(Span result, PKM pk, EvoCriteria evo, MoveSourceType types = MoveSourceType.All) @@ -129,7 +95,7 @@ public sealed class LearnSource6AO : ILearnSource, IEggSource if (!TryGetPersonal(evo.Species, evo.Form, out var pi)) return; - if (types.HasFlagFast(MoveSourceType.LevelUp)) + if (types.HasFlag(MoveSourceType.LevelUp)) { var learn = GetLearnset(evo.Species, evo.Form); (bool hasMoves, int start, int end) = learn.GetMoveRange(evo.LevelMax); @@ -141,46 +107,14 @@ public sealed class LearnSource6AO : ILearnSource, IEggSource } } - if (types.HasFlagFast(MoveSourceType.Machine)) - { - var flags = pi.TMHM; - var moves = TMHM_AO; - for (int i = 0; i < moves.Length; i++) - { - if (flags[i]) - result[moves[i]] = true; - } - } + if (types.HasFlag(MoveSourceType.Machine)) + pi.SetAllLearnTM(result, TMHM_AO); + if (types.HasFlag(MoveSourceType.TypeTutor)) + pi.SetAllLearnTutorType(result, LearnSource5.TypeTutor567); + if (types.HasFlag(MoveSourceType.SpecialTutor)) + pi.SetAllLearnTutorSpecial(result); - if (types.HasFlagFast(MoveSourceType.TypeTutor)) - { - // Beams - var flags = pi.TypeTutors; - var moves = LearnSource5.TypeTutor567; - for (int i = 0; i < moves.Length; i++) - { - if (flags[i]) - result[moves[i]] = true; - } - } - - if (types.HasFlagFast(MoveSourceType.SpecialTutor)) - { - // OR/AS Tutors - var tutors = Tutors_AO; - for (int i = 0; i < tutors.Length; i++) - { - var flags = pi.SpecialTutors[i]; - var moves = tutors[i]; - for (int m = 0; m < moves.Length; m++) - { - if (flags[m]) - result[moves[m]] = true; - } - } - } - - if (types.HasFlagFast(MoveSourceType.EnhancedTutor)) + if (types.HasFlag(MoveSourceType.EnhancedTutor)) { var species = evo.Species; if (species is (int)Species.Rotom && evo.Form is not 0) @@ -207,12 +141,4 @@ public sealed class LearnSource6AO : ILearnSource, IEggSource 15, 19, 57, 70, 127, 249, 291, }; - - private static readonly ushort[][] Tutors_AO = - { - new ushort[] {450, 343, 162, 530, 324, 442, 402, 529, 340, 067, 441, 253, 009, 007, 008}, - new ushort[] {277, 335, 414, 492, 356, 393, 334, 387, 276, 527, 196, 401, 399, 428, 406, 304, 231}, - new ushort[] {020, 173, 282, 235, 257, 272, 215, 366, 143, 220, 202, 409, 355, 264, 351, 352}, - new ushort[] {380, 388, 180, 495, 270, 271, 478, 472, 283, 200, 278, 289, 446, 214, 285}, - }; } diff --git a/PKHeX.Core/Legality/LearnSource/Sources/LearnSource6XY.cs b/PKHeX.Core/Legality/LearnSource/Sources/LearnSource6XY.cs index 66d49b888..f0d1e1af0 100644 --- a/PKHeX.Core/Legality/LearnSource/Sources/LearnSource6XY.cs +++ b/PKHeX.Core/Legality/LearnSource/Sources/LearnSource6XY.cs @@ -8,7 +8,7 @@ namespace PKHeX.Core; /// /// Exposes information about how moves are learned in . /// -public sealed class LearnSource6XY : ILearnSource, IEggSource +public sealed class LearnSource6XY : ILearnSource, IEggSource { public static readonly LearnSource6XY Instance = new(); private static readonly PersonalTable6XY Personal = PersonalTable.XY; @@ -19,7 +19,7 @@ public sealed class LearnSource6XY : ILearnSource, IEggSource public Learnset GetLearnset(ushort species, byte form) => Learnsets[Personal.GetFormIndex(species, form)]; - public bool TryGetPersonal(ushort species, byte form, [NotNullWhen(true)] out PersonalInfo? pi) + public bool TryGetPersonal(ushort species, byte form, [NotNullWhen(true)] out PersonalInfo6XY? pi) { pi = null; if (species > MaxSpecies) @@ -43,9 +43,9 @@ public sealed class LearnSource6XY : ILearnSource, IEggSource return EggMoves[species].Moves; } - public MoveLearnInfo GetCanLearn(PKM pk, PersonalInfo pi, EvoCriteria evo, ushort move, MoveSourceType types = MoveSourceType.All, LearnOption option = LearnOption.Current) + public MoveLearnInfo GetCanLearn(PKM pk, PersonalInfo6XY pi, EvoCriteria evo, ushort move, MoveSourceType types = MoveSourceType.All, LearnOption option = LearnOption.Current) { - if (types.HasFlagFast(MoveSourceType.LevelUp)) + if (types.HasFlag(MoveSourceType.LevelUp)) { var learn = GetLearnset(evo.Species, evo.Form); var level = learn.GetLevelLearnMove(move); @@ -53,13 +53,13 @@ public sealed class LearnSource6XY : ILearnSource, IEggSource return new(LevelUp, Game, (byte)level); } - if (types.HasFlagFast(MoveSourceType.Machine) && GetIsTM(pi, move)) + if (types.HasFlag(MoveSourceType.Machine) && pi.GetIsLearnTM(Array.IndexOf(TMHM_XY, move))) return new(TMHM, Game); - if (types.HasFlagFast(MoveSourceType.TypeTutor) && GetIsTypeTutor(pi, move)) + if (types.HasFlag(MoveSourceType.TypeTutor) && pi.GetIsLearnTutorType(Array.IndexOf(LearnSource5.TypeTutor567, move))) return new(Tutor, Game); - if (types.HasFlagFast(MoveSourceType.EnhancedTutor) && GetIsEnhancedTutor(evo, pk, move, option)) + if (types.HasFlag(MoveSourceType.EnhancedTutor) && GetIsEnhancedTutor(evo, pk, move, option)) return new(Tutor, Game); return default; @@ -81,28 +81,12 @@ public sealed class LearnSource6XY : ILearnSource, IEggSource _ => false, }; - private static bool GetIsTypeTutor(PersonalInfo pi, ushort move) - { - var index = Array.IndexOf(LearnSource5.TypeTutor567, move); - if (index == -1) - return false; - return pi.TypeTutors[index]; - } - - private static bool GetIsTM(PersonalInfo info, ushort move) - { - var index = Array.IndexOf(TMHM_XY, move); - if (index == -1) - return false; - return info.TMHM[index]; - } - public void GetAllMoves(Span result, PKM pk, EvoCriteria evo, MoveSourceType types = MoveSourceType.All) { if (!TryGetPersonal(evo.Species, evo.Form, out var pi)) return; - if (types.HasFlagFast(MoveSourceType.LevelUp)) + if (types.HasFlag(MoveSourceType.LevelUp)) { var learn = GetLearnset(evo.Species, evo.Form); (bool hasMoves, int start, int end) = learn.GetMoveRange(evo.LevelMax); @@ -114,30 +98,13 @@ public sealed class LearnSource6XY : ILearnSource, IEggSource } } - if (types.HasFlagFast(MoveSourceType.Machine)) - { - var flags = pi.TMHM; - var moves = TMHM_XY; - for (int i = 0; i < moves.Length; i++) - { - if (flags[i]) - result[moves[i]] = true; - } - } + if (types.HasFlag(MoveSourceType.Machine)) + pi.SetAllLearnTM(result, TMHM_XY); - if (types.HasFlagFast(MoveSourceType.TypeTutor)) - { - // Beams - var flags = pi.TypeTutors; - var moves = LearnSource5.TypeTutor567; - for (int i = 0; i < moves.Length; i++) - { - if (flags[i]) - result[moves[i]] = true; - } - } + if (types.HasFlag(MoveSourceType.TypeTutor)) + pi.SetAllLearnTutorType(result, LearnSource5.TypeTutor567); - if (types.HasFlagFast(MoveSourceType.EnhancedTutor)) + if (types.HasFlag(MoveSourceType.EnhancedTutor)) { var species = evo.Species; if (species is (int)Species.Rotom && evo.Form is not 0) diff --git a/PKHeX.Core/Legality/LearnSource/Sources/LearnSource7GG.cs b/PKHeX.Core/Legality/LearnSource/Sources/LearnSource7GG.cs index 8d7e08bbf..079dbc82a 100644 --- a/PKHeX.Core/Legality/LearnSource/Sources/LearnSource7GG.cs +++ b/PKHeX.Core/Legality/LearnSource/Sources/LearnSource7GG.cs @@ -8,7 +8,7 @@ namespace PKHeX.Core; /// /// Exposes information about how moves are learned in . /// -public sealed class LearnSource7GG : ILearnSource +public sealed class LearnSource7GG : ILearnSource { public static readonly LearnSource7GG Instance = new(); private static readonly PersonalTable7GG Personal = PersonalTable.GG; @@ -19,18 +19,18 @@ public sealed class LearnSource7GG : ILearnSource public Learnset GetLearnset(ushort species, byte form) => Learnsets[Personal.GetFormIndex(species, form)]; - public bool TryGetPersonal(ushort species, byte form, [NotNullWhen(true)] out PersonalInfo? pi) + public bool TryGetPersonal(ushort species, byte form, [NotNullWhen(true)] out PersonalInfo7GG? pi) { pi = null; - if ((uint)species > MaxSpecies) + if (species > MaxSpecies) return false; pi = Personal[species, form]; return true; } - public MoveLearnInfo GetCanLearn(PKM pk, PersonalInfo pi, EvoCriteria evo, ushort move, MoveSourceType types = MoveSourceType.All, LearnOption option = LearnOption.Current) + public MoveLearnInfo GetCanLearn(PKM pk, PersonalInfo7GG pi, EvoCriteria evo, ushort move, MoveSourceType types = MoveSourceType.All, LearnOption option = LearnOption.Current) { - if (types.HasFlagFast(MoveSourceType.LevelUp)) + if (types.HasFlag(MoveSourceType.LevelUp)) { var learn = GetLearnset(evo.Species, evo.Form); var level = learn.GetLevelLearnMove(move); @@ -38,10 +38,10 @@ public sealed class LearnSource7GG : ILearnSource return new(LevelUp, Game, (byte)level); } - if (types.HasFlagFast(MoveSourceType.Machine) && GetIsTM(pi, move)) + if (types.HasFlag(MoveSourceType.Machine) && pi.GetIsLearnTM(Array.IndexOf(TMHM_GG, move))) return new(TMHM, Game); - if (types.HasFlagFast(MoveSourceType.EnhancedTutor) && GetIsEnhancedTutor(evo.Species, evo.Form, move)) + if (types.HasFlag(MoveSourceType.EnhancedTutor) && GetIsEnhancedTutor(evo.Species, evo.Form, move)) return new(Tutor, Game); return default; @@ -56,20 +56,12 @@ public sealed class LearnSource7GG : ILearnSource return false; } - private static bool GetIsTM(PersonalInfo info, ushort move) - { - var index = Array.IndexOf(TMHM_GG, move); - if (index == -1) - return false; - return info.TMHM[index]; - } - public void GetAllMoves(Span result, PKM pk, EvoCriteria evo, MoveSourceType types = MoveSourceType.All) { if (!TryGetPersonal(evo.Species, evo.Form, out var pi)) return; - if (types.HasFlagFast(MoveSourceType.LevelUp)) + if (types.HasFlag(MoveSourceType.LevelUp)) { var learn = GetLearnset(evo.Species, evo.Form); (bool hasMoves, int start, int end) = learn.GetMoveRange(ReminderBonus); @@ -81,25 +73,17 @@ public sealed class LearnSource7GG : ILearnSource } } - if (types.HasFlagFast(MoveSourceType.Machine)) - { - var flags = pi.TMHM; - var moves = TMHM_GG; - for (int i = 0; i < moves.Length; i++) - { - if (flags[i]) - result[moves[i]] = true; - } - } + if (types.HasFlag(MoveSourceType.Machine)) + pi.SetAllLearnTM(result, TMHM_GG); - if (types.HasFlagFast(MoveSourceType.SpecialTutor)) + if (types.HasFlag(MoveSourceType.SpecialTutor)) { - if (evo.Species == (int)Species.Pikachu && evo.Form == 8) // Partner + if (evo is { Species: (int)Species.Pikachu, Form: 8 }) // Partner { foreach (var move in Tutor_StarterPikachu) result[move] = true; } - else if (evo.Species == (int)Species.Eevee && evo.Form == 1) // Partner + else if (evo is { Species: (int)Species.Eevee, Form: 1 }) // Partner { foreach (var move in Tutor_StarterEevee) result[move] = true; diff --git a/PKHeX.Core/Legality/LearnSource/Sources/LearnSource7SM.cs b/PKHeX.Core/Legality/LearnSource/Sources/LearnSource7SM.cs index 1e6a3a3b3..2edccf19e 100644 --- a/PKHeX.Core/Legality/LearnSource/Sources/LearnSource7SM.cs +++ b/PKHeX.Core/Legality/LearnSource/Sources/LearnSource7SM.cs @@ -9,7 +9,7 @@ namespace PKHeX.Core; /// /// Exposes information about how moves are learned in . /// -public sealed class LearnSource7SM : ILearnSource, IEggSource +public sealed class LearnSource7SM : ILearnSource, IEggSource { public static readonly LearnSource7SM Instance = new(); private static readonly PersonalTable7 Personal = PersonalTable.SM; @@ -21,7 +21,7 @@ public sealed class LearnSource7SM : ILearnSource, IEggSource public Learnset GetLearnset(ushort species, byte form) => Learnsets[Personal.GetFormIndex(species, form)]; - public bool TryGetPersonal(ushort species, byte form, [NotNullWhen(true)] out PersonalInfo? pi) + public bool TryGetPersonal(ushort species, byte form, [NotNullWhen(true)] out PersonalInfo7? pi) { pi = null; if (species > MaxSpecies) @@ -42,12 +42,12 @@ public sealed class LearnSource7SM : ILearnSource, IEggSource { if (species > MaxSpecies) return ReadOnlySpan.Empty; - return MoveEgg.GetFormEggMoves(species, form, EggMoves).AsSpan(); + return MoveEgg.GetFormEggMoves(species, form, EggMoves); } - public MoveLearnInfo GetCanLearn(PKM pk, PersonalInfo pi, EvoCriteria evo, ushort move, MoveSourceType types = MoveSourceType.All, LearnOption option = LearnOption.Current) + public MoveLearnInfo GetCanLearn(PKM pk, PersonalInfo7 pi, EvoCriteria evo, ushort move, MoveSourceType types = MoveSourceType.All, LearnOption option = LearnOption.Current) { - if (types.HasFlagFast(MoveSourceType.LevelUp)) + if (types.HasFlag(MoveSourceType.LevelUp)) { var learn = GetLearnset(evo.Species, evo.Form); var level = learn.GetLevelLearnMove(move); @@ -55,13 +55,13 @@ public sealed class LearnSource7SM : ILearnSource, IEggSource return new(LevelUp, Game, 1); } - if (types.HasFlagFast(MoveSourceType.Machine) && GetIsTM(pi, move)) + if (types.HasFlag(MoveSourceType.Machine) && pi.GetIsLearnTM(Array.IndexOf(TMHM_SM, move))) return new(TMHM, Game); - if (types.HasFlagFast(MoveSourceType.TypeTutor) && GetIsTypeTutor(pi, move)) + if (types.HasFlag(MoveSourceType.TypeTutor) && pi.GetIsLearnTutorType(Array.IndexOf(LearnSource5.TypeTutor567, move))) return new(Tutor, Game); - if (types.HasFlagFast(MoveSourceType.EnhancedTutor) && GetIsEnhancedTutor(evo, pk, move, option)) + if (types.HasFlag(MoveSourceType.EnhancedTutor) && GetIsEnhancedTutor(evo, pk, move, option)) return new(Tutor, Game); return default; @@ -91,28 +91,12 @@ public sealed class LearnSource7SM : ILearnSource, IEggSource _ => false, }; - private static bool GetIsTypeTutor(PersonalInfo pi, ushort move) - { - var index = Array.IndexOf(LearnSource5.TypeTutor567, move); - if (index == -1) - return false; - return pi.TypeTutors[index]; - } - - private static bool GetIsTM(PersonalInfo info, ushort move) - { - var index = Array.IndexOf(TMHM_SM, move); - if (index == -1) - return false; - return info.TMHM[index]; - } - public void GetAllMoves(Span result, PKM pk, EvoCriteria evo, MoveSourceType types = MoveSourceType.All) { if (!TryGetPersonal(evo.Species, evo.Form, out var pi)) return; - if (types.HasFlagFast(MoveSourceType.LevelUp)) + if (types.HasFlag(MoveSourceType.LevelUp)) { var learn = GetLearnset(evo.Species, evo.Form); (bool hasMoves, int start, int end) = learn.GetMoveRange(ReminderBonus); @@ -124,30 +108,13 @@ public sealed class LearnSource7SM : ILearnSource, IEggSource } } - if (types.HasFlagFast(MoveSourceType.Machine)) - { - var flags = pi.TMHM; - var moves = TMHM_SM; - for (int i = 0; i < moves.Length; i++) - { - if (flags[i]) - result[moves[i]] = true; - } - } + if (types.HasFlag(MoveSourceType.Machine)) + pi.SetAllLearnTM(result, TMHM_SM); - if (types.HasFlagFast(MoveSourceType.TypeTutor)) - { - // Beams - var flags = pi.TypeTutors; - var moves = LearnSource5.TypeTutor567; - for (int i = 0; i < moves.Length; i++) - { - if (flags[i]) - result[moves[i]] = true; - } - } + if (types.HasFlag(MoveSourceType.TypeTutor)) + pi.SetAllLearnTutorType(result, LearnSource5.TypeTutor567); - if (types.HasFlagFast(MoveSourceType.EnhancedTutor)) + if (types.HasFlag(MoveSourceType.EnhancedTutor)) { var species = evo.Species; if (species is (int)Species.Zygarde) diff --git a/PKHeX.Core/Legality/LearnSource/Sources/LearnSource7USUM.cs b/PKHeX.Core/Legality/LearnSource/Sources/LearnSource7USUM.cs index 8e3ef5ecf..a5945e639 100644 --- a/PKHeX.Core/Legality/LearnSource/Sources/LearnSource7USUM.cs +++ b/PKHeX.Core/Legality/LearnSource/Sources/LearnSource7USUM.cs @@ -9,7 +9,7 @@ namespace PKHeX.Core; /// /// Exposes information about how moves are learned in . /// -public sealed class LearnSource7USUM : ILearnSource, IEggSource +public sealed class LearnSource7USUM : ILearnSource, IEggSource { public static readonly LearnSource7USUM Instance = new(); private static readonly PersonalTable7 Personal = PersonalTable.USUM; @@ -21,7 +21,7 @@ public sealed class LearnSource7USUM : ILearnSource, IEggSource public Learnset GetLearnset(ushort species, byte form) => Learnsets[Personal.GetFormIndex(species, form)]; - public bool TryGetPersonal(ushort species, byte form, [NotNullWhen(true)] out PersonalInfo? pi) + public bool TryGetPersonal(ushort species, byte form, [NotNullWhen(true)] out PersonalInfo7? pi) { pi = null; if (species > MaxSpecies) @@ -42,12 +42,12 @@ public sealed class LearnSource7USUM : ILearnSource, IEggSource { if (species > MaxSpecies) return ReadOnlySpan.Empty; - return MoveEgg.GetFormEggMoves(species, form, EggMoves).AsSpan(); + return MoveEgg.GetFormEggMoves(species, form, EggMoves); } - public MoveLearnInfo GetCanLearn(PKM pk, PersonalInfo pi, EvoCriteria evo, ushort move, MoveSourceType types = MoveSourceType.All, LearnOption option = LearnOption.Current) + public MoveLearnInfo GetCanLearn(PKM pk, PersonalInfo7 pi, EvoCriteria evo, ushort move, MoveSourceType types = MoveSourceType.All, LearnOption option = LearnOption.Current) { - if (types.HasFlagFast(MoveSourceType.LevelUp)) + if (types.HasFlag(MoveSourceType.LevelUp)) { var learn = GetLearnset(evo.Species, evo.Form); var level = learn.GetLevelLearnMove(move); @@ -55,16 +55,16 @@ public sealed class LearnSource7USUM : ILearnSource, IEggSource return new(LevelUp, Game, 1); } - if (types.HasFlagFast(MoveSourceType.Machine) && GetIsTM(pi, move)) + if (types.HasFlag(MoveSourceType.Machine) && pi.GetIsLearnTM(Array.IndexOf(TMHM_SM, move))) return new(TMHM, Game); - if (types.HasFlagFast(MoveSourceType.TypeTutor) && GetIsTypeTutor(pi, move)) + if (types.HasFlag(MoveSourceType.TypeTutor) && pi.GetIsLearnTutorType(Array.IndexOf(LearnSource5.TypeTutor567, move))) return new(Tutor, Game); - if (types.HasFlagFast(MoveSourceType.SpecialTutor) && GetIsSpecialTutor(pi, move)) + if (types.HasFlag(MoveSourceType.SpecialTutor) && pi.GetIsLearnTutorSpecial(move)) return new(Tutor, Game); - if (types.HasFlagFast(MoveSourceType.EnhancedTutor) && GetIsEnhancedTutor(evo, pk, move, option)) + if (types.HasFlag(MoveSourceType.EnhancedTutor) && GetIsEnhancedTutor(evo, pk, move, option)) return new(Tutor, Game); return default; @@ -94,38 +94,12 @@ public sealed class LearnSource7USUM : ILearnSource, IEggSource _ => false, }; - private static bool GetIsTypeTutor(PersonalInfo pi, ushort move) - { - var index = Array.IndexOf(LearnSource5.TypeTutor567, move); - if (index == -1) - return false; - return pi.TypeTutors[index]; - } - - private static bool GetIsSpecialTutor(PersonalInfo pi, ushort move) - { - // US/UM Tutors - var tutors = Tutors_USUM; - var tutor = Array.IndexOf(tutors, move); - if (tutor == -1) - return false; - return pi.SpecialTutors[0][tutor]; - } - - private static bool GetIsTM(PersonalInfo info, ushort move) - { - var index = Array.IndexOf(TMHM_SM, move); - if (index == -1) - return false; - return info.TMHM[index]; - } - public void GetAllMoves(Span result, PKM pk, EvoCriteria evo, MoveSourceType types = MoveSourceType.All) { if (!TryGetPersonal(evo.Species, evo.Form, out var pi)) return; - if (types.HasFlagFast(MoveSourceType.LevelUp)) + if (types.HasFlag(MoveSourceType.LevelUp)) { var learn = GetLearnset(evo.Species, evo.Form); (bool hasMoves, int start, int end) = learn.GetMoveRange(ReminderBonus); @@ -137,42 +111,16 @@ public sealed class LearnSource7USUM : ILearnSource, IEggSource } } - if (types.HasFlagFast(MoveSourceType.Machine)) - { - var flags = pi.TMHM; - var moves = TMHM_SM; - for (int i = 0; i < moves.Length; i++) - { - if (flags[i]) - result[moves[i]] = true; - } - } + if (types.HasFlag(MoveSourceType.Machine)) + pi.SetAllLearnTM(result, TMHM_SM); - if (types.HasFlagFast(MoveSourceType.TypeTutor)) - { - // Beams - var flags = pi.TypeTutors; - var moves = LearnSource5.TypeTutor567; - for (int i = 0; i < moves.Length; i++) - { - if (flags[i]) - result[moves[i]] = true; - } - } + if (types.HasFlag(MoveSourceType.TypeTutor)) + pi.SetAllLearnTutorType(result, LearnSource5.TypeTutor567); - if (types.HasFlagFast(MoveSourceType.SpecialTutor)) - { - // US/UM Tutors - var flags = pi.SpecialTutors[0]; - var moves = Tutors_USUM; - for (int i = 0; i < flags.Length; i++) - { - if (flags[i]) - result[moves[i]] = true; - } - } + if (types.HasFlag(MoveSourceType.SpecialTutor)) + pi.SetAllLearnTutorSpecial(result); - if (types.HasFlagFast(MoveSourceType.EnhancedTutor)) + if (types.HasFlag(MoveSourceType.EnhancedTutor)) { var species = evo.Species; if (species is (int)Species.Zygarde) @@ -199,14 +147,4 @@ public sealed class LearnSource7USUM : ILearnSource, IEggSource result[(int)Move.MoongeistBeam] = true; } } - - private static readonly ushort[] Tutors_USUM = - { - 450, 343, 162, 530, 324, 442, 402, 529, 340, 067, 441, 253, 009, 007, 008, - 277, 335, 414, 492, 356, 393, 334, 387, 276, 527, 196, 401, 428, 406, 304, 231, - 020, 173, 282, 235, 257, 272, 215, 366, 143, 220, 202, 409, 264, 351, 352, - 380, 388, 180, 495, 270, 271, 478, 472, 283, 200, 278, 289, 446, 285, - - 477, 502, 432, 710, 707, 675, 673, - }; } diff --git a/PKHeX.Core/Legality/LearnSource/Sources/LearnSource8BDSP.cs b/PKHeX.Core/Legality/LearnSource/Sources/LearnSource8BDSP.cs index 1765e15c1..721e88cce 100644 --- a/PKHeX.Core/Legality/LearnSource/Sources/LearnSource8BDSP.cs +++ b/PKHeX.Core/Legality/LearnSource/Sources/LearnSource8BDSP.cs @@ -8,7 +8,7 @@ namespace PKHeX.Core; /// /// Exposes information about how moves are learned in . /// -public sealed class LearnSource8BDSP : ILearnSource, IEggSource +public sealed class LearnSource8BDSP : ILearnSource, IEggSource { public static readonly LearnSource8BDSP Instance = new(); private static readonly PersonalTable8BDSP Personal = PersonalTable.BDSP; @@ -19,7 +19,7 @@ public sealed class LearnSource8BDSP : ILearnSource, IEggSource public Learnset GetLearnset(ushort species, byte form) => Learnsets[Personal.GetFormIndex(species, form)]; - public bool TryGetPersonal(ushort species, byte form, [NotNullWhen(true)] out PersonalInfo? pi) + public bool TryGetPersonal(ushort species, byte form, [NotNullWhen(true)] out PersonalInfo8BDSP? pi) { pi = null; if (species > MaxSpecies) @@ -47,9 +47,9 @@ public sealed class LearnSource8BDSP : ILearnSource, IEggSource return arr[species].Moves; } - public MoveLearnInfo GetCanLearn(PKM pk, PersonalInfo pi, EvoCriteria evo, ushort move, MoveSourceType types = MoveSourceType.All, LearnOption option = LearnOption.Current) + public MoveLearnInfo GetCanLearn(PKM pk, PersonalInfo8BDSP pi, EvoCriteria evo, ushort move, MoveSourceType types = MoveSourceType.All, LearnOption option = LearnOption.Current) { - if (types.HasFlagFast(MoveSourceType.LevelUp)) + if (types.HasFlag(MoveSourceType.LevelUp)) { var learn = GetLearnset(evo.Species, evo.Form); var level = learn.GetLevelLearnMove(move); @@ -57,16 +57,16 @@ public sealed class LearnSource8BDSP : ILearnSource, IEggSource return new(LevelUp, Game, (byte)level); } - if (types.HasFlagFast(MoveSourceType.SharedEggMove) && GetIsSharedEggMove(pi, move)) + if (types.HasFlag(MoveSourceType.SharedEggMove) && GetIsSharedEggMove(pi, move)) return new(Shared, Game); - if (types.HasFlagFast(MoveSourceType.Machine) && GetIsTM(pi, move)) + if (types.HasFlag(MoveSourceType.Machine) && pi.GetIsLearnTM(Array.IndexOf(TMHM_BDSP, move))) return new(TMHM, Game); - if (types.HasFlagFast(MoveSourceType.TypeTutor) && GetIsTypeTutor(pi, move)) + if (types.HasFlag(MoveSourceType.TypeTutor) && pi.GetIsLearnTutorType(Array.IndexOf(TypeTutor8b, move))) return new(Tutor, Game); - if (types.HasFlagFast(MoveSourceType.EnhancedTutor) && GetIsEnhancedTutor(evo, pk, move, option)) + if (types.HasFlag(MoveSourceType.EnhancedTutor) && GetIsEnhancedTutor(evo, pk, move, option)) return new(Tutor, Game); return default; @@ -82,36 +82,19 @@ public sealed class LearnSource8BDSP : ILearnSource, IEggSource _ => false, }; - private bool GetIsSharedEggMove(PersonalInfo pi, ushort move) + private bool GetIsSharedEggMove(PersonalInfo8BDSP pi, ushort move) { - var entry = (PersonalInfo8BDSP)pi; - var baseSpecies = entry.HatchSpecies; - var baseForm = entry.HatchFormIndex; + var baseSpecies = pi.HatchSpecies; + var baseForm = pi.HatchFormIndex; return GetEggMoves(baseSpecies, baseForm).IndexOf(move) != -1; } - private static bool GetIsTypeTutor(PersonalInfo pi, ushort move) - { - var index = Array.IndexOf(TypeTutor8b, move); - if (index == -1) - return false; - return pi.TypeTutors[index]; - } - - private static bool GetIsTM(PersonalInfo info, ushort move) - { - var index = Array.IndexOf(TMHM_BDSP, move); - if (index == -1) - return false; - return info.TMHM[index]; - } - public void GetAllMoves(Span result, PKM pk, EvoCriteria evo, MoveSourceType types = MoveSourceType.All) { if (!TryGetPersonal(evo.Species, evo.Form, out var pi)) return; - if (types.HasFlagFast(MoveSourceType.LevelUp)) + if (types.HasFlag(MoveSourceType.LevelUp)) { var learn = GetLearnset(evo.Species, evo.Form); (bool hasMoves, int start, int end) = learn.GetMoveRange(evo.LevelMax); @@ -123,39 +106,22 @@ public sealed class LearnSource8BDSP : ILearnSource, IEggSource } } - if (types.HasFlagFast(MoveSourceType.SharedEggMove)) + if (types.HasFlag(MoveSourceType.SharedEggMove)) { - var entry = (PersonalInfo8BDSP)pi; - var baseSpecies = entry.HatchSpecies; - var baseForm = entry.HatchFormIndex; + var baseSpecies = pi.HatchSpecies; + var baseForm = pi.HatchFormIndex; var egg = GetEggMoves(baseSpecies, baseForm); foreach (var move in egg) result[move] = true; } - if (types.HasFlagFast(MoveSourceType.Machine)) - { - var flags = pi.TMHM; - var moves = TMHM_BDSP; - for (int i = 0; i < moves.Length; i++) - { - if (flags[i]) - result[moves[i]] = true; - } - } + if (types.HasFlag(MoveSourceType.Machine)) + pi.SetAllLearnTM(result, TMHM_BDSP); - if (types.HasFlagFast(MoveSourceType.TypeTutor)) - { - var flags = pi.TypeTutors; - var moves = TypeTutor8b; - for (int i = 0; i < moves.Length; i++) - { - if (flags[i]) - result[moves[i]] = true; - } - } + if (types.HasFlag(MoveSourceType.TypeTutor)) + pi.SetAllLearnTutorType(result, TypeTutor8b); - if (types.HasFlagFast(MoveSourceType.EnhancedTutor)) + if (types.HasFlag(MoveSourceType.EnhancedTutor)) { var species = evo.Species; if (species is (int)Species.Rotom && evo.Form is not 0) diff --git a/PKHeX.Core/Legality/LearnSource/Sources/LearnSource8PLA.cs b/PKHeX.Core/Legality/LearnSource/Sources/LearnSource8PLA.cs index adc54a2f8..cfb46294a 100644 --- a/PKHeX.Core/Legality/LearnSource/Sources/LearnSource8PLA.cs +++ b/PKHeX.Core/Legality/LearnSource/Sources/LearnSource8PLA.cs @@ -8,7 +8,7 @@ namespace PKHeX.Core; /// /// Exposes information about how moves are learned in . /// -public sealed class LearnSource8LA : ILearnSource +public sealed class LearnSource8LA : ILearnSource { public static readonly LearnSource8LA Instance = new(); private static readonly PersonalTable8LA Personal = PersonalTable.LA; @@ -18,18 +18,18 @@ public sealed class LearnSource8LA : ILearnSource public Learnset GetLearnset(ushort species, byte form) => Learnsets[Personal.GetFormIndex(species, form)]; - public bool TryGetPersonal(ushort species, byte form, [NotNullWhen(true)] out PersonalInfo? pi) + public bool TryGetPersonal(ushort species, byte form, [NotNullWhen(true)] out PersonalInfo8LA? pi) { pi = null; - if ((uint)species > MaxSpecies) + if (species > MaxSpecies) return false; pi = Personal[species, form]; return true; } - public MoveLearnInfo GetCanLearn(PKM pk, PersonalInfo pi, EvoCriteria evo, ushort move, MoveSourceType types = MoveSourceType.All, LearnOption option = LearnOption.Current) + public MoveLearnInfo GetCanLearn(PKM pk, PersonalInfo8LA pi, EvoCriteria evo, ushort move, MoveSourceType types = MoveSourceType.All, LearnOption option = LearnOption.Current) { - if (types.HasFlagFast(MoveSourceType.LevelUp)) + if (types.HasFlag(MoveSourceType.LevelUp)) { var learn = GetLearnset(evo.Species, evo.Form); var level = learn.GetLevelLearnMove(move); @@ -37,10 +37,10 @@ public sealed class LearnSource8LA : ILearnSource return new(LevelUp, Game, (byte)level); } - if (types.HasFlagFast(MoveSourceType.Machine) && GetIsMoveShop(pi, move)) + if (types.HasFlag(MoveSourceType.Machine) && pi.GetIsLearnMoveShop(move)) return new(TMHM, Game); - if (types.HasFlagFast(MoveSourceType.EnhancedTutor) && GetIsEnhancedTutor(evo, pk, move, option)) + if (types.HasFlag(MoveSourceType.EnhancedTutor) && GetIsEnhancedTutor(evo, pk, move, option)) return new(Tutor, Game); return default; @@ -56,20 +56,12 @@ public sealed class LearnSource8LA : ILearnSource _ => false, }; - private static bool GetIsMoveShop(PersonalInfo pi, ushort move) - { - var index = Legal.MoveShop8_LA.AsSpan().IndexOf(move); - if (index == -1) - return false; - return pi.SpecialTutors[0][index]; - } - public void GetAllMoves(Span result, PKM pk, EvoCriteria evo, MoveSourceType types = MoveSourceType.All) { if (!TryGetPersonal(evo.Species, evo.Form, out var pi)) return; - if (types.HasFlagFast(MoveSourceType.LevelUp)) + if (types.HasFlag(MoveSourceType.LevelUp)) { var learn = GetLearnset(evo.Species, evo.Form); (bool hasMoves, int start, int end) = learn.GetMoveRange(evo.LevelMax); @@ -81,18 +73,10 @@ public sealed class LearnSource8LA : ILearnSource } } - if (types.HasFlagFast(MoveSourceType.Machine)) - { - var flags = pi.SpecialTutors[0]; - var moves = Legal.MoveShop8_LA; - for (int i = 0; i < moves.Length; i++) - { - if (flags[i]) - result[moves[i]] = true; - } - } + if (types.HasFlag(MoveSourceType.Machine)) + pi.SetAllLearnMoveShop(result); - if (types.HasFlagFast(MoveSourceType.EnhancedTutor)) + if (types.HasFlag(MoveSourceType.EnhancedTutor)) { var species = evo.Species; if (species is (int)Species.Rotom && evo.Form is not 0) diff --git a/PKHeX.Core/Legality/LearnSource/Sources/LearnSource8SWSH.cs b/PKHeX.Core/Legality/LearnSource/Sources/LearnSource8SWSH.cs index 072e38c58..7cc59f8b6 100644 --- a/PKHeX.Core/Legality/LearnSource/Sources/LearnSource8SWSH.cs +++ b/PKHeX.Core/Legality/LearnSource/Sources/LearnSource8SWSH.cs @@ -8,7 +8,7 @@ namespace PKHeX.Core; /// /// Exposes information about how moves are learned in . /// -public sealed class LearnSource8SWSH : ILearnSource, IEggSource +public sealed class LearnSource8SWSH : ILearnSource, IEggSource { public static readonly LearnSource8SWSH Instance = new(); private static readonly PersonalTable8SWSH Personal = PersonalTable.SWSH; @@ -19,7 +19,7 @@ public sealed class LearnSource8SWSH : ILearnSource, IEggSource public Learnset GetLearnset(ushort species, byte form) => Learnsets[Personal.GetFormIndex(species, form)]; - public bool TryGetPersonal(ushort species, byte form, [NotNullWhen(true)] out PersonalInfo? pi) + public bool TryGetPersonal(ushort species, byte form, [NotNullWhen(true)] out PersonalInfo8SWSH? pi) { pi = null; if (species > MaxSpecies) @@ -40,12 +40,12 @@ public sealed class LearnSource8SWSH : ILearnSource, IEggSource { if (species > MaxSpecies) return ReadOnlySpan.Empty; - return MoveEgg.GetFormEggMoves(species, form, EggMoves).AsSpan(); + return MoveEgg.GetFormEggMoves(species, form, EggMoves); } - public MoveLearnInfo GetCanLearn(PKM pk, PersonalInfo pi, EvoCriteria evo, ushort move, MoveSourceType types = MoveSourceType.All, LearnOption option = LearnOption.Current) + public MoveLearnInfo GetCanLearn(PKM pk, PersonalInfo8SWSH pi, EvoCriteria evo, ushort move, MoveSourceType types = MoveSourceType.All, LearnOption option = LearnOption.Current) { - if (types.HasFlagFast(MoveSourceType.LevelUp)) + if (types.HasFlag(MoveSourceType.LevelUp)) { var learn = GetLearnset(evo.Species, evo.Form); var level = learn.GetLevelLearnMove(move); @@ -53,35 +53,27 @@ public sealed class LearnSource8SWSH : ILearnSource, IEggSource return new(LevelUp, Game, (byte)level); } - if (types.HasFlagFast(MoveSourceType.SharedEggMove) && GetIsSharedEggMove(pi, move)) + if (types.HasFlag(MoveSourceType.SharedEggMove) && GetIsSharedEggMove(pi, move)) return new(Shared, Game); - if (types.HasFlagFast(MoveSourceType.Machine) && GetIsTM(pi, move)) + if (types.HasFlag(MoveSourceType.Machine) && pi.GetIsLearnTM(move)) return new(TMHM, Game); - if (types.HasFlagFast(MoveSourceType.TechnicalRecord) && GetIsTR(pi, pk, evo, move, option)) + if (types.HasFlag(MoveSourceType.TechnicalRecord) && GetIsTR(pi, pk, evo, move, option)) return new(TMHM, Game); - if (types.HasFlagFast(MoveSourceType.TypeTutor) && GetIsTypeTutor(pi, move)) + if (types.HasFlag(MoveSourceType.TypeTutor) && pi.GetIsLearnTutorType(move)) return new(Tutor, Game); - if (types.HasFlagFast(MoveSourceType.SpecialTutor) && GetIsSpecialTutor(pi, move)) + if (types.HasFlag(MoveSourceType.SpecialTutor) && pi.GetIsLearnTutorSpecial(move)) return new(Tutor, Game); - if (types.HasFlagFast(MoveSourceType.EnhancedTutor) && GetIsEnhancedTutor(evo, pk, move, option)) + if (types.HasFlag(MoveSourceType.EnhancedTutor) && GetIsEnhancedTutor(evo, pk, move, option)) return new(Tutor, Game); return default; } - private static bool GetIsSpecialTutor(PersonalInfo pi, ushort move) - { - var tutor = Array.IndexOf(Tutors_SWSH, move); - if (tutor == -1) - return false; - return pi.SpecialTutors[0][tutor]; - } - private static bool GetIsEnhancedTutor(EvoCriteria evo, ISpeciesForm current, ushort move, LearnOption option) => evo.Species switch { (int)Species.Necrozma => move switch @@ -102,39 +94,22 @@ public sealed class LearnSource8SWSH : ILearnSource, IEggSource _ => false, }; - private bool GetIsSharedEggMove(PersonalInfo pi, ushort move) + private bool GetIsSharedEggMove(PersonalInfo8SWSH pi, ushort move) { - var entry = (PersonalInfo8SWSH)pi; - var baseSpecies = entry.HatchSpecies; - var baseForm = entry.HatchFormIndexEverstone; + var baseSpecies = pi.HatchSpecies; + var baseForm = pi.HatchFormIndexEverstone; return GetEggMoves(baseSpecies, baseForm).IndexOf(move) != -1; } - private static bool GetIsTypeTutor(PersonalInfo pi, ushort move) - { - var index = Array.IndexOf(TypeTutor8, move); - if (index == -1) - return false; - return pi.TypeTutors[index]; - } - - private static bool GetIsTM(PersonalInfo info, ushort move) - { - var index = TM_SWSH.AsSpan().IndexOf(move); - if (index == -1) - return false; - return info.TMHM[index]; - } - - private static bool GetIsTR(PersonalInfo info, PKM pk, EvoCriteria evo, ushort move, LearnOption option) + private static bool GetIsTR(PersonalInfo8SWSH info, PKM pk, EvoCriteria evo, ushort move, LearnOption option) { if (pk is not ITechRecord tr) return false; - var index = TR_SWSH.AsSpan().IndexOf(move); + var index = info.RecordPermitIndexes.IndexOf(move); if (index == -1) return false; - if (!info.TMHM[PersonalInfo8SWSH.CountTM + index]) + if (!info.GetIsLearnTR(index)) return false; if (tr.GetMoveRecordFlag(index)) @@ -142,7 +117,7 @@ public sealed class LearnSource8SWSH : ILearnSource, IEggSource if (option != LearnOption.Current && !pk.SWSH && pk.IsOriginalMovesetDeleted()) return true; - if (index == 12 && evo.Species == (int)Species.Calyrex && evo.Form == 0) // TR12 + if (index == 12 && evo is { Species: (int)Species.Calyrex, Form: 0 }) // TR12 return true; // Agility Calyrex without TR glitch. return false; @@ -153,7 +128,7 @@ public sealed class LearnSource8SWSH : ILearnSource, IEggSource if (!TryGetPersonal(evo.Species, evo.Form, out var pi)) return; - if (types.HasFlagFast(MoveSourceType.LevelUp)) + if (types.HasFlag(MoveSourceType.LevelUp)) { var learn = GetLearnset(evo.Species, evo.Form); (bool hasMoves, int start, int end) = learn.GetMoveRange(evo.LevelMax); @@ -165,66 +140,30 @@ public sealed class LearnSource8SWSH : ILearnSource, IEggSource } } - if (types.HasFlagFast(MoveSourceType.SharedEggMove)) + if (types.HasFlag(MoveSourceType.SharedEggMove)) { - var entry = (PersonalInfo8SWSH)pi; - var baseSpecies = entry.HatchSpecies; - var baseForm = entry.HatchFormIndexEverstone; + var baseSpecies = pi.HatchSpecies; + var baseForm = pi.HatchFormIndexEverstone; var egg = GetEggMoves(baseSpecies, baseForm); foreach (var move in egg) result[move] = true; } - if (types.HasFlagFast(MoveSourceType.Machine)) + if (types.HasFlag(MoveSourceType.Machine)) { - var flags = pi.TMHM; - var moves = TM_SWSH; - for (int i = 0; i < PersonalInfo8SWSH.CountTM; i++) - { - if (flags[i]) - result[moves[i]] = true; - } - - if (pk is ITechRecord) - { - var trFlags = flags.AsSpan(PersonalInfo8SWSH.CountTM); - var trMoves = TR_SWSH.AsSpan(); - for (int index = 0; index < trFlags.Length; index++) - { - var move = trMoves[index]; - if (trFlags[index]) - result[move] = true; - else if (index == 12 && evo.Species == (int)Species.Calyrex && evo.Form == 0) // TR12 - result[move] = true; // Agility Calyrex without TR glitch. - } - } + pi.SetAllLearnTM(result); + pi.SetAllLearnTR(result); + if (evo is { Species: (int)Species.Calyrex, Form: 0 }) + result[(int)Move.Agility] = true; // Agility Calyrex without TR glitch. } - if (types.HasFlagFast(MoveSourceType.TypeTutor)) - { - // Beams - var flags = pi.TypeTutors; - var moves = TypeTutor8; - for (int i = 0; i < moves.Length; i++) - { - if (flags[i]) - result[moves[i]] = true; - } - } + if (types.HasFlag(MoveSourceType.TypeTutor)) + pi.SetAllLearnTutorType(result); - if (types.HasFlagFast(MoveSourceType.SpecialTutor)) - { - // SW/SH Tutors - var flags = pi.SpecialTutors[0]; - var moves = Tutors_SWSH; - for (int i = 0; i < flags.Length; i++) - { - if (flags[i]) - result[moves[i]] = true; - } - } + if (types.HasFlag(MoveSourceType.SpecialTutor)) + pi.SetAllLearnTutorSpecial(result); - if (types.HasFlagFast(MoveSourceType.EnhancedTutor)) + if (types.HasFlag(MoveSourceType.EnhancedTutor)) { var species = evo.Species; if (species is (int)Species.Rotom && pk.Form is not 0) @@ -235,53 +174,4 @@ public sealed class LearnSource8SWSH : ILearnSource, IEggSource result[(int)Move.MoongeistBeam] = true; } } - - public static readonly ushort[] TM_SWSH = - { - 005, 025, 006, 007, 008, 009, 019, 042, 063, 416, - 345, 076, 669, 083, 086, 091, 103, 113, 115, 219, - 120, 156, 157, 168, 173, 182, 184, 196, 202, 204, - 211, 213, 201, 240, 241, 258, 250, 251, 261, 263, - 129, 270, 279, 280, 286, 291, 311, 313, 317, 328, - 331, 333, 340, 341, 350, 362, 369, 371, 372, 374, - 384, 385, 683, 409, 419, 421, 422, 423, 424, 427, - 433, 472, 478, 440, 474, 490, 496, 506, 512, 514, - 521, 523, 527, 534, 541, 555, 566, 577, 580, 581, - 604, 678, 595, 598, 206, 403, 684, 693, 707, 784, - }; - - internal static readonly ushort[] TR_SWSH = - { - 014, 034, 053, 056, 057, 058, 059, 067, 085, 087, - 089, 094, 097, 116, 118, 126, 127, 133, 141, 161, - 164, 179, 188, 191, 200, 473, 203, 214, 224, 226, - 227, 231, 242, 247, 248, 253, 257, 269, 271, 276, - 285, 299, 304, 315, 322, 330, 334, 337, 339, 347, - 348, 349, 360, 370, 390, 394, 396, 398, 399, 402, - 404, 405, 406, 408, 411, 412, 413, 414, 417, 428, - 430, 437, 438, 441, 442, 444, 446, 447, 482, 484, - 486, 492, 500, 502, 503, 526, 528, 529, 535, 542, - 583, 599, 605, 663, 667, 675, 676, 706, 710, 776, - }; - - internal static readonly ushort[] TypeTutor8 = - { - (int)Move.GrassPledge, - (int)Move.FirePledge, - (int)Move.WaterPledge, - (int)Move.FrenzyPlant, - (int)Move.BlastBurn, - (int)Move.HydroCannon, - (int)Move.DracoMeteor, - (int)Move.SteelBeam, - }; - - internal static readonly ushort[] Tutors_SWSH = - { - 805, 807, 812, 804, - 803, 813, 811, 810, - 815, 814, 797, 806, - 800, 809, 799, 808, - 798, 802, - }; } diff --git a/PKHeX.Core/Legality/LearnSource/Sources/LearnSource9SV.cs b/PKHeX.Core/Legality/LearnSource/Sources/LearnSource9SV.cs index 1097825bc..c6ca3d862 100644 --- a/PKHeX.Core/Legality/LearnSource/Sources/LearnSource9SV.cs +++ b/PKHeX.Core/Legality/LearnSource/Sources/LearnSource9SV.cs @@ -8,7 +8,7 @@ namespace PKHeX.Core; /// /// Exposes information about how moves are learned in . /// -public sealed class LearnSource9SV : ILearnSource, IEggSource, IReminderSource +public sealed class LearnSource9SV : ILearnSource, IEggSource, IReminderSource { public static readonly LearnSource9SV Instance = new(); private static readonly PersonalTable9SV Personal = PersonalTable.SV; @@ -20,7 +20,7 @@ public sealed class LearnSource9SV : ILearnSource, IEggSource, IReminderSource public Learnset GetLearnset(ushort species, byte form) => Learnsets[Personal.GetFormIndex(species, form)]; - public bool TryGetPersonal(ushort species, byte form, [NotNullWhen(true)] out PersonalInfo? pi) + public bool TryGetPersonal(ushort species, byte form, [NotNullWhen(true)] out PersonalInfo9SV? pi) { pi = null; if (species > MaxSpecies) @@ -43,7 +43,7 @@ public sealed class LearnSource9SV : ILearnSource, IEggSource, IReminderSource var index = Personal.GetFormIndex(species, form); if (index >= EggMoves.Length) return ReadOnlySpan.Empty; - return EggMoves[index].AsSpan(); + return EggMoves[index]; } public bool GetIsReminderMove(ushort species, byte form, ushort move) @@ -60,12 +60,12 @@ public sealed class LearnSource9SV : ILearnSource, IEggSource, IReminderSource var index = Personal.GetFormIndex(species, form); if (index >= Reminder.Length) return ReadOnlySpan.Empty; - return Reminder[index].AsSpan(); + return Reminder[index]; } - public MoveLearnInfo GetCanLearn(PKM pk, PersonalInfo pi, EvoCriteria evo, ushort move, MoveSourceType types = MoveSourceType.All, LearnOption option = LearnOption.Current) + public MoveLearnInfo GetCanLearn(PKM pk, PersonalInfo9SV pi, EvoCriteria evo, ushort move, MoveSourceType types = MoveSourceType.All, LearnOption option = LearnOption.Current) { - if (types.HasFlagFast(MoveSourceType.LevelUp)) + if (types.HasFlag(MoveSourceType.LevelUp)) { var learn = GetLearnset(evo.Species, evo.Form); var level = learn.GetLevelLearnMove(move); @@ -73,27 +73,27 @@ public sealed class LearnSource9SV : ILearnSource, IEggSource, IReminderSource return new(LevelUp, Game, (byte)level); } - if (types.HasFlagFast(MoveSourceType.SharedEggMove) && GetIsEggMove(evo.Species, evo.Form, move)) + if (types.HasFlag(MoveSourceType.SharedEggMove) && GetIsSharedEggMove(pi, move)) return new(Shared, Game); - if (types.HasFlagFast(MoveSourceType.Machine) && GetIsTM(pi, pk, move, option)) + if (types.HasFlag(MoveSourceType.Machine) && GetIsTM(pi, pk, move, option)) return new(TMHM, Game); - if (types.HasFlagFast(MoveSourceType.SpecialTutor) && GetIsReminderMove(evo.Species, evo.Form, move)) + if (types.HasFlag(MoveSourceType.SpecialTutor) && GetIsReminderMove(evo.Species, evo.Form, move)) return new(Tutor, Game); - if (types.HasFlagFast(MoveSourceType.EnhancedTutor) && GetIsEnhancedTutor(evo, pk, move)) + if (types.HasFlag(MoveSourceType.EnhancedTutor) && GetIsEnhancedTutor(evo, pk, move)) return new(Tutor, Game); return default; } - private static bool GetIsTM(PersonalInfo info, PKM pk, ushort move, LearnOption option) + private static bool GetIsTM(PersonalInfo9SV info, PKM pk, ushort move, LearnOption option) { - var index = TM_SV.AsSpan().IndexOf(move); + int index = info.RecordPermitIndexes.IndexOf(move); if (index == -1) return false; - if (!info.TMHM[index]) + if (!info.GetIsLearnTM(index)) return false; if (pk is not ITechRecord tr) return true; @@ -118,12 +118,19 @@ public sealed class LearnSource9SV : ILearnSource, IEggSource, IReminderSource _ => false, }; + private bool GetIsSharedEggMove(PersonalInfo9SV pi, ushort move) + { + var baseSpecies = pi.HatchSpecies; + var baseForm = pi.HatchFormIndexEverstone; + return GetEggMoves(baseSpecies, baseForm).IndexOf(move) != -1; + } + public void GetAllMoves(Span result, PKM pk, EvoCriteria evo, MoveSourceType types = MoveSourceType.All) { if (!TryGetPersonal(evo.Species, evo.Form, out var pi)) return; - if (types.HasFlagFast(MoveSourceType.LevelUp)) + if (types.HasFlag(MoveSourceType.LevelUp)) { var learn = GetLearnset(evo.Species, evo.Form); (bool hasMoves, int start, int end) = learn.GetMoveRange(evo.LevelMax); @@ -135,61 +142,30 @@ public sealed class LearnSource9SV : ILearnSource, IEggSource, IReminderSource } } - if (types.HasFlagFast(MoveSourceType.SharedEggMove)) + if (types.HasFlag(MoveSourceType.SharedEggMove)) { - var entry = (PersonalInfo9SV)pi; - var baseSpecies = entry.HatchSpecies; - var baseForm = entry.HatchFormIndexEverstone; + var baseSpecies = pi.HatchSpecies; + var baseForm = pi.HatchFormIndexEverstone; var egg = GetEggMoves(baseSpecies, baseForm); foreach (var move in egg) result[move] = true; } - if (types.HasFlagFast(MoveSourceType.Machine)) - { - var flags = pi.TMHM; - var moves = TM_SV; - for (int i = 0; i < moves.Length; i++) - { - if (flags[i]) - result[moves[i]] = true; - } - } + if (types.HasFlag(MoveSourceType.Machine)) + pi.SetAllLearnTM(result); - if (types.HasFlagFast(MoveSourceType.SpecialTutor)) + if (types.HasFlag(MoveSourceType.SpecialTutor)) { var reminder = GetReminderMoves(evo.Species, evo.Form); foreach (var move in reminder) result[move] = true; } - if (types.HasFlagFast(MoveSourceType.EnhancedTutor)) + if (types.HasFlag(MoveSourceType.EnhancedTutor)) { var species = evo.Species; if (species is (int)Species.Rotom && pk.Form is not 0) result[MoveTutor.GetRotomFormMove(evo.Form)] = true; } } - - public static readonly ushort[] TM_SV = - { - 005, 036, 204, 313, 097, 189, 184, 182, 424, 422, - 423, 352, 067, 491, 512, 522, 060, 109, 168, 574, - 885, 884, 886, 451, 083, 263, 342, 332, 523, 506, - 555, 232, 129, 345, 196, 341, 317, 577, 488, 490, - 314, 500, 101, 374, 525, 474, 419, 203, 521, 241, - 240, 201, 883, 684, 473, 091, 331, 206, 280, 428, - 369, 421, 492, 706, 339, 403, 034, 007, 009, 008, - 214, 402, 486, 409, 115, 113, 350, 127, 337, 605, - 118, 447, 086, 398, 707, 156, 157, 269, 014, 776, - 191, 390, 286, 430, 399, 141, 598, 019, 285, 442, - 349, 408, 441, 164, 334, 404, 529, 261, 242, 271, - 710, 202, 396, 366, 247, 406, 446, 304, 257, 412, - 094, 484, 227, 057, 861, 053, 085, 583, 133, 347, - 270, 676, 226, 414, 179, 058, 604, 580, 678, 581, - 417, 126, 056, 059, 519, 518, 520, 528, 188, 089, - 444, 566, 416, 307, 308, 338, 200, 315, 411, 437, - 542, 433, 405, 063, 413, 394, 087, 370, 076, 434, - 796, 851, - }; } diff --git a/PKHeX.Core/Legality/LearnSource/Sources/Shared/ILearnSource.cs b/PKHeX.Core/Legality/LearnSource/Sources/Shared/ILearnSource.cs index 4960dc96d..49a0e82a2 100644 --- a/PKHeX.Core/Legality/LearnSource/Sources/Shared/ILearnSource.cs +++ b/PKHeX.Core/Legality/LearnSource/Sources/Shared/ILearnSource.cs @@ -8,18 +8,6 @@ namespace PKHeX.Core; /// public interface ILearnSource { - /// - /// Checks if the can learn the requested while existing as . - /// - /// Entity reference - /// Entity game stats - /// Details about the state of the entity - /// Move ID to check - /// Types of move sources to iterate - /// Option to check if it can be currently known, or previously known. - /// Details about how the move can be learned. Will be equivalent to default if cannot learn. - public MoveLearnInfo GetCanLearn(PKM pk, PersonalInfo pi, EvoCriteria evo, ushort move, MoveSourceType types = MoveSourceType.All, LearnOption option = LearnOption.Current); - /// /// Yields an iterable list of all potential moves that an can learn from this . /// @@ -35,13 +23,31 @@ public interface ILearnSource /// Entity species /// Entity form public Learnset GetLearnset(ushort species, byte form); +} + +/// +/// Exposes information about how moves are learned in game based on the game's . +/// +public interface ILearnSource : ILearnSource where T : PersonalInfo +{ + /// + /// Checks if the can learn the requested while existing as . + /// + /// Entity reference + /// Entity game stats + /// Details about the state of the entity + /// Move ID to check + /// Types of move sources to iterate + /// Option to check if it can be currently known, or previously known. + /// Details about how the move can be learned. Will be equivalent to default if cannot learn. + public MoveLearnInfo GetCanLearn(PKM pk, T pi, EvoCriteria evo, ushort move, MoveSourceType types = MoveSourceType.All, LearnOption option = LearnOption.Current); /// - /// Gets the for the given and . + /// Gets the for the given and . /// /// Entity species /// Entity form /// Result value - /// True if the reference is a valid entity reference. - public bool TryGetPersonal(ushort species, byte form, [NotNullWhen(true)] out PersonalInfo? pi); + /// True if the reference is a valid entity reference. + public bool TryGetPersonal(ushort species, byte form, [NotNullWhen(true)] out T? pi); } diff --git a/PKHeX.Core/Legality/LearnSource/Sources/Shared/LearnSource1.cs b/PKHeX.Core/Legality/LearnSource/Sources/Shared/LearnSource1.cs index a8e3e296c..34800a98d 100644 --- a/PKHeX.Core/Legality/LearnSource/Sources/Shared/LearnSource1.cs +++ b/PKHeX.Core/Legality/LearnSource/Sources/Shared/LearnSource1.cs @@ -1,8 +1,10 @@ +using System; + namespace PKHeX.Core; internal static class LearnSource1 { - internal static readonly ushort[] TMHM_RBY = + internal static ReadOnlySpan TMHM_RBY => new byte[] { 005, 013, 014, 018, 025, 092, 032, 034, 036, 038, 061, 055, 058, 059, 063, 006, 066, 068, 069, 099, diff --git a/PKHeX.Core/Legality/LearnSource/Sources/Shared/LearnSource2.cs b/PKHeX.Core/Legality/LearnSource/Sources/Shared/LearnSource2.cs index 35fe0eefd..63a38e9a9 100644 --- a/PKHeX.Core/Legality/LearnSource/Sources/Shared/LearnSource2.cs +++ b/PKHeX.Core/Legality/LearnSource/Sources/Shared/LearnSource2.cs @@ -1,8 +1,10 @@ +using System; + namespace PKHeX.Core; internal static class LearnSource2 { - internal static readonly ushort[] TMHM_GSC = + internal static ReadOnlySpan TMHM_GSC => new byte[] { 223, 029, 174, 205, 046, 092, 192, 249, 244, 237, 241, 230, 173, 059, 063, 196, 182, 240, 202, 203, @@ -13,5 +15,5 @@ internal static class LearnSource2 015, 019, 057, 070, 148, 250, 127, }; - internal static readonly ushort[] Tutors_GSC = { (int)Move.Flamethrower, (int)Move.Thunderbolt, (int)Move.IceBeam }; + internal static ReadOnlySpan Tutors_GSC => new byte[] { (int)Move.Flamethrower, (int)Move.Thunderbolt, (int)Move.IceBeam }; } diff --git a/PKHeX.Core/Legality/LearnSource/Sources/Shared/LearnSource4.cs b/PKHeX.Core/Legality/LearnSource/Sources/Shared/LearnSource4.cs index 242ef51cf..d8ba9b110 100644 --- a/PKHeX.Core/Legality/LearnSource/Sources/Shared/LearnSource4.cs +++ b/PKHeX.Core/Legality/LearnSource/Sources/Shared/LearnSource4.cs @@ -32,12 +32,9 @@ internal static class LearnSource4 internal static readonly ushort[] Tutors_4 = { - 291, 189, 210, 196, 205, 009, 007, 276, - 008, 442, 401, 466, 380, 173, 180, 314, - 270, 283, 200, 246, 235, 324, 428, 410, - 414, 441, 239, 402, 334, 393, 387, 340, - 271, 257, 282, 389, 129, 253, 162, 220, - 081, 366, 356, 388, 277, 272, 215, 067, + 291, 189, 210, 196, 205, 009, 007, 276, 008, 442, 401, 466, 380, 173, 180, 314, + 270, 283, 200, 246, 235, 324, 428, 410, 414, 441, 239, 402, 334, 393, 387, 340, + 271, 257, 282, 389, 129, 253, 162, 220, 081, 366, 356, 388, 277, 272, 215, 067, 143, 335, 450, 029, }; diff --git a/PKHeX.Core/Legality/LearnSource/Verify/LearnPossible.cs b/PKHeX.Core/Legality/LearnSource/Verify/LearnPossible.cs index 7e8a5e626..0cb816bfe 100644 --- a/PKHeX.Core/Legality/LearnSource/Verify/LearnPossible.cs +++ b/PKHeX.Core/Legality/LearnSource/Verify/LearnPossible.cs @@ -17,7 +17,7 @@ public static class LearnPossible /// Move types to give public static void Get(PKM pk, IEncounterTemplate enc, EvolutionHistory history, Span result, MoveSourceType types = MoveSourceType.All) { - if (types.HasFlagFast(MoveSourceType.Encounter)) + if (types.HasFlag(MoveSourceType.Encounter)) FlagEncounterMoves(pk, enc, result); IterateAndFlag(result, pk, enc, history, types); } diff --git a/PKHeX.Core/Legality/LearnSource/Verify/LearnVerifierHistory.cs b/PKHeX.Core/Legality/LearnSource/Verify/LearnVerifierHistory.cs index ef9cf9be5..4303e3ae7 100644 --- a/PKHeX.Core/Legality/LearnSource/Verify/LearnVerifierHistory.cs +++ b/PKHeX.Core/Legality/LearnSource/Verify/LearnVerifierHistory.cs @@ -25,7 +25,7 @@ internal static class LearnVerifierHistory public static void MarkAndIterate(Span result, ReadOnlySpan current, IEncounterTemplate enc, PKM pk, EvolutionHistory history, ILearnGroup game, MoveSourceType types = MoveSourceType.All, LearnOption option = LearnOption.Current) { - if (!pk.IsOriginalMovesetDeleted() && types.HasFlagFast(MoveSourceType.Encounter)) + if (!pk.IsOriginalMovesetDeleted() && types.HasFlag(MoveSourceType.Encounter)) { // Knock off relearn moves if available. if (pk.Format >= 6) @@ -125,7 +125,7 @@ internal static class LearnVerifierHistory var move = current[i]; if (move == 0) result[i] = MoveResult.Empty; - else if (MoveInfo.IsValidSketch(move, pk.Context)) + else if (MoveInfo.IsSketchValid(move, pk.Context)) result[i] = MoveResult.Sketch; else result[i] = MoveResult.Unobtainable(); diff --git a/PKHeX.Core/Legality/Learnset/EggMoves.cs b/PKHeX.Core/Legality/Learnset/EggMoves.cs index 4feb0216a..6b784e339 100644 --- a/PKHeX.Core/Legality/Learnset/EggMoves.cs +++ b/PKHeX.Core/Legality/Learnset/EggMoves.cs @@ -20,7 +20,12 @@ public sealed class EggMoves2 : EggMoves { private EggMoves2(ushort[] moves) : base(moves) { } - public static EggMoves2[] GetArray(ReadOnlySpan data, int count) + /// + /// Gets the Egg Moves from the Generation 2 encoded format. + /// + /// Encoded data + /// Max Species ID + public static EggMoves2[] GetArray(ReadOnlySpan data, ushort count) { var entries = new EggMoves2[count + 1]; var empty = entries[0] = new EggMoves2(Array.Empty()); @@ -30,7 +35,7 @@ public sealed class EggMoves2 : EggMoves { int start = ReadInt16LittleEndian(data[((i - 1) * 2)..]) - baseOffset; var slice = data[start..]; - int moveCount = slice.IndexOf((byte)0xFF); + int moveCount = slice.IndexOf(0xFF); if (moveCount == 0) { entries[i] = empty; @@ -87,9 +92,9 @@ public sealed class EggMoves7 : EggMoves /// /// Points to the index where form data is, within the parent Egg Move object array. /// - public readonly int FormTableIndex; + public readonly ushort FormTableIndex; - private EggMoves7(ushort[] moves, int formIndex = 0) : base(moves) => FormTableIndex = formIndex; + private EggMoves7(ushort[] moves, ushort formIndex = 0) : base(moves) => FormTableIndex = formIndex; public static EggMoves7[] GetArray(BinLinkerAccessor entries) { @@ -99,7 +104,7 @@ public sealed class EggMoves7 : EggMoves { var data = entries[i]; int count = ReadInt16LittleEndian(data[2..]); - int formIndex = ReadInt16LittleEndian(data); + var formIndex = ReadUInt16LittleEndian(data); if (count == 0) { // Might need to keep track of the Form Index for unavailable forms pointing to valid forms. diff --git a/PKHeX.Core/Legality/Learnset/LearnsetReader.cs b/PKHeX.Core/Legality/Learnset/LearnsetReader.cs index 0404d93f9..a4290de22 100644 --- a/PKHeX.Core/Legality/Learnset/LearnsetReader.cs +++ b/PKHeX.Core/Legality/Learnset/LearnsetReader.cs @@ -15,7 +15,7 @@ public static class LearnsetReader /// /// Raw ROM data containing the contiguous moves /// Highest species ID for the input game. - public static Learnset[] GetArray(ReadOnlySpan input, int maxSpecies) + public static Learnset[] GetArray(ReadOnlySpan input, ushort maxSpecies) { int offset = 0; var result = new Learnset[maxSpecies + 1]; diff --git a/PKHeX.Core/Legality/LegalityAnalysis.cs b/PKHeX.Core/Legality/LegalityAnalysis.cs index 52afb7d88..f8ad084a7 100644 --- a/PKHeX.Core/Legality/LegalityAnalysis.cs +++ b/PKHeX.Core/Legality/LegalityAnalysis.cs @@ -26,11 +26,6 @@ public sealed class LegalityAnalysis /// public IReadOnlyList Results => Parse; - /// - /// Only use this when trying to mutate the legality. Not for use when checking legality. - /// - public void ResetParse() => Parse.Clear(); - /// /// Matched encounter data for the . /// @@ -160,14 +155,7 @@ public sealed class LegalityAnalysis if (Entity.Format <= 2) // prior to storing GameVersion return ParsePK1; - int gen = Entity.Generation; - if (gen <= 0) - { - if (Entity is PK9 { IsUnhatchedEgg: true }) - gen = 9; - else - gen = Entity.Format; - } + var gen = GetParseFormat(); return gen switch { 3 => ParsePK3, @@ -186,6 +174,16 @@ public sealed class LegalityAnalysis }; } + private int GetParseFormat() + { + int gen = Entity.Generation; + if (gen > 0) + return gen; + if (Entity is PK9 { IsUnhatchedEgg: true }) + return 9; + return Entity.Format; + } + private void ParsePK1() { Nickname.Verify(this); @@ -279,7 +277,7 @@ public sealed class LegalityAnalysis var enc = (Info.EncounterOriginalGB = EncounterMatch); if (enc is EncounterInvalid) return; - var vc = EncounterStaticGenerator.GetVCStaticTransferEncounter(Entity, enc, Info.EvoChainsAllGens.Gen7); + var vc = EncounterGenerator7.GetVCStaticTransferEncounter(Entity, enc.Species, Info.EvoChainsAllGens.Gen7); Info.EncounterMatch = vc; Transfer.VerifyVCEncounter(Entity, enc, vc, this); diff --git a/PKHeX.Core/Legality/MoveList.cs b/PKHeX.Core/Legality/MoveList.cs index 0c9a73d70..74ccb4ae1 100644 --- a/PKHeX.Core/Legality/MoveList.cs +++ b/PKHeX.Core/Legality/MoveList.cs @@ -9,38 +9,35 @@ namespace PKHeX.Core; /// internal static class MoveList { - internal static void GetCurrentMoves(PKM pk, ushort species, byte form, GameVersion gameSource, int lvl, Span moves) + internal static void GetCurrentMoves(PKM pk, ushort species, byte form, GameVersion gameSource, int lvl, Span moves) => _ = gameSource switch { - _ = gameSource switch - { - GSC or GS => Get(moves, LevelUpGS, species, lvl, pk.Format), - C => Get(moves, LevelUpC, species, lvl, pk.Format), + GSC or GS => Get(moves, LevelUpGS, species, lvl, pk.Format), + C => Get(moves, LevelUpC, species, lvl, pk.Format), - R or S or RS => Get(moves, LevelUpRS, species, lvl), - E => Get(moves, LevelUpE, species, lvl), - FR or LG or FRLG => Get(moves, LevelUpFR, species, lvl), + R or S or RS => Get(moves, LevelUpRS, species, lvl), + E => Get(moves, LevelUpE, species, lvl), + FR or LG or FRLG => Get(moves, LevelUpFR, species, lvl), - D or P or DP => Get(moves, LevelUpDP, species, lvl), - Pt => Get(moves, LevelUpPt, species, lvl), - HG or SS or HGSS => Get(moves, LevelUpHGSS, species, lvl), + D or P or DP => Get(moves, LevelUpDP, species, lvl), + Pt => Get(moves, LevelUpPt, species, lvl), + HG or SS or HGSS => Get(moves, LevelUpHGSS, species, lvl), - B or W or BW => Get(moves, LevelUpBW, species, lvl), - B2 or W2 or B2W2 => Get(moves, LevelUpB2W2, species, lvl), + B or W or BW => Get(moves, LevelUpBW, species, lvl), + B2 or W2 or B2W2 => Get(moves, LevelUpB2W2, species, lvl), - X or Y or XY => Get(moves, LevelUpXY, species, lvl), - AS or OR or ORAS => Get(moves, LevelUpAO, species, lvl), + X or Y or XY => Get(moves, LevelUpXY, species, lvl), + AS or OR or ORAS => Get(moves, LevelUpAO, species, lvl), - SN or MN or SM => Get(moves, LevelUpSM, PersonalTable.SM, species, form, lvl), - US or UM or USUM => Get(moves, LevelUpUSUM, PersonalTable.USUM, species, form, lvl), - SW or SH or SWSH => Get(moves, LevelUpSWSH, PersonalTable.SWSH, species, form, lvl), - BD or SP or BDSP => Get(moves, LevelUpBDSP, PersonalTable.BDSP, species, form, lvl), - PLA => Get(moves, LevelUpLA, PersonalTable.LA, species, form, lvl), + SN or MN or SM => Get(moves, LevelUpSM, PersonalTable.SM, species, form, lvl), + US or UM or USUM => Get(moves, LevelUpUSUM, PersonalTable.USUM, species, form, lvl), + SW or SH or SWSH => Get(moves, LevelUpSWSH, PersonalTable.SWSH, species, form, lvl), + BD or SP or BDSP => Get(moves, LevelUpBDSP, PersonalTable.BDSP, species, form, lvl), + PLA => Get(moves, LevelUpLA, PersonalTable.LA, species, form, lvl), - SL or VL or SV => Get(moves, LevelUpSV, PersonalTable.SV, species, form, lvl), + SL or VL or SV => Get(moves, LevelUpSV, PersonalTable.SV, species, form, lvl), - _ => moves, - }; - } + _ => moves, + }; private static Span Get(Span moves, Learnset[] source, ushort species, int lvl) { @@ -50,7 +47,7 @@ internal static class MoveList return moves; } - private static Span Get(Span moves, Learnset[] source, IPersonalTable pt, ushort species, byte form, int lvl) + private static Span Get(Span moves, Learnset[] source, T pt, ushort species, byte form, int lvl) where T : IPersonalTable { if (!pt.IsPresentInGame(species, form)) return moves; @@ -62,7 +59,7 @@ internal static class MoveList private static Span Get(Span moves, Learnset[] source, ushort species, int lvl, int format) { - if ((uint)species > MaxSpeciesID_2) + if (species > MaxSpeciesID_2) return moves; source[species].SetLevelUpMoves(1, lvl, moves); diff --git a/PKHeX.Core/Legality/MoveListSuggest.cs b/PKHeX.Core/Legality/MoveListSuggest.cs index 4bb33d32a..b432ef8a9 100644 --- a/PKHeX.Core/Legality/MoveListSuggest.cs +++ b/PKHeX.Core/Legality/MoveListSuggest.cs @@ -11,7 +11,7 @@ public static class MoveListSuggest { private static ushort[] GetSuggestedMoves(PKM pk, EvolutionHistory evoChains, MoveSourceType types, IEncounterTemplate enc) { - if (pk.IsEgg && pk.Format <= 5) // pre relearn + if (pk is { IsEgg: true, Format: <= 5 }) // pre relearn { var moves = new ushort[4]; MoveList.GetCurrentMoves(pk, pk.Species, 0, (GameVersion)pk.Version, pk.CurrentLevel, moves); @@ -26,12 +26,16 @@ public static class MoveListSuggest { var lvl = pk.Format >= 7 ? pk.Met_Level : pk.CurrentLevel; var ver = enc.Version; - return MoveLevelUp.GetEncounterMoves(enc.Species, 0, lvl, ver); + var result = new ushort[4]; + MoveLevelUp.GetEncounterMoves(result, enc.Species, 0, lvl, ver); + return result; } if (pk.Species == enc.Species) { - return MoveLevelUp.GetEncounterMoves(pk.Species, pk.Form, pk.CurrentLevel, (GameVersion)pk.Version); + var result = new ushort[4]; + MoveLevelUp.GetEncounterMoves(result, pk.Species, pk.Form, pk.CurrentLevel, (GameVersion)pk.Version); + return result; } return GetValidMoves(pk, enc, evoChains, types); @@ -68,7 +72,7 @@ public static class MoveListSuggest if (!analysis.Parsed) return new ushort[4]; var pk = analysis.Entity; - if (pk.IsEgg && pk.Format >= 6) + if (pk is { IsEgg: true, Format: >= 6 }) return pk.RelearnMoves; if (pk.IsEgg) @@ -136,7 +140,7 @@ public static class MoveListSuggest // Split-breed species like Budew & Roselia may be legal for one, and not the other. // If we're not a split-breed or are already legal, return. var split = Breeding.GetSplitBreedGeneration(generation); - if (!split.Contains(enc.Species)) + if (split?.Contains(enc.Species) != true) return result; var tmp = pk.Clone(); @@ -147,7 +151,10 @@ public static class MoveListSuggest return result; // Try again with the other split-breed species if possible. - var other = EncounterEggGenerator.GenerateEggs(tmp, generation); + var generator = EncounterGenerator.GetGenerator(enc.Version); + var tree = EvolutionTree.GetEvolutionTree(enc.Context); + var chain = tree.GetValidPreEvolutions(pk, 100, skipChecks: true); + var other = generator.GetPossible(pk, chain, enc.Version, EncounterTypeGroup.Egg); foreach (var incense in other) { if (incense.Species != enc.Species) diff --git a/PKHeX.Core/Legality/MoveSourceType.cs b/PKHeX.Core/Legality/MoveSourceType.cs index 80d4f80e5..6d2e393dc 100644 --- a/PKHeX.Core/Legality/MoveSourceType.cs +++ b/PKHeX.Core/Legality/MoveSourceType.cs @@ -26,6 +26,5 @@ public enum MoveSourceType public static class MoveSourceTypeExtensions { - public static bool HasFlagFast(this MoveSourceType value, MoveSourceType flag) => (value & flag) != 0; public static MoveSourceType ClearNonEggSources(this MoveSourceType value) => value & MoveSourceType.Encounter; } diff --git a/PKHeX.Core/Legality/Moves/Breeding/MoveBreed2.cs b/PKHeX.Core/Legality/Moves/Breeding/MoveBreed2.cs index 660fb3b3d..b65eb3d42 100644 --- a/PKHeX.Core/Legality/Moves/Breeding/MoveBreed2.cs +++ b/PKHeX.Core/Legality/Moves/Breeding/MoveBreed2.cs @@ -154,12 +154,13 @@ public static class MoveBreed2 var possible = value.Possible; var learn = value.Learnset; var baseEgg = value.Learnset.GetBaseEggMoves(value.Level); - var tm = info.TMHM; var moves = value.Moves; for (int i = 0; i < count; i++) { var move = moves[i]; + if (move > Legal.MaxMoveID_2) // byte + continue; if (baseEgg.IndexOf(move) != -1) possible[i] |= 1 << (int)Base; @@ -170,18 +171,12 @@ public static class MoveBreed2 if (eggMoves.Contains(move)) possible[i] |= 1 << (int)FatherEgg; - var tmIndex = Array.IndexOf(TMHM_GSC, move, 0, 50); - if (tmIndex != -1 && tm[tmIndex]) - possible[i] |= 1 << (int)FatherTM; - - var hmIndex = Array.IndexOf(TMHM_GSC, move, 50); - if (hmIndex != -1 && tm[hmIndex + 50]) + if (info.GetIsLearnTM(TMHM_GSC.IndexOf((byte)move))) possible[i] |= 1 << (int)FatherTM; if (version is GameVersion.C) { - var tutorIndex = Array.IndexOf(Tutors_GSC, move); - if (tutorIndex != -1 && tm[57 + tutorIndex]) + if (info.GetIsLearnTutorType(Tutors_GSC.IndexOf((byte)move))) possible[i] |= 1 << (int)Tutor; } } diff --git a/PKHeX.Core/Legality/Moves/Breeding/MoveBreed4.cs b/PKHeX.Core/Legality/Moves/Breeding/MoveBreed4.cs index 763d973ad..4bc020697 100644 --- a/PKHeX.Core/Legality/Moves/Breeding/MoveBreed4.cs +++ b/PKHeX.Core/Legality/Moves/Breeding/MoveBreed4.cs @@ -25,8 +25,13 @@ public static class MoveBreed4 count = moves.Length; var learn = GameData.GetLearnsets(version); - var table = GameData.GetPersonal(version); var learnset = learn[species]; + var table = version switch + { + HG or SS => PersonalTable.HGSS, + D or P => PersonalTable.DP, + _ => PersonalTable.Pt, + }; var pi = table[species]; var egg = (version is HG or SS ? Legal.EggMovesHGSS : Legal.EggMovesDPPt)[species].Moves; @@ -141,12 +146,11 @@ public static class MoveBreed4 return true; } - private static void MarkMovesForOrigin(in BreedInfo value, ReadOnlySpan eggMoves, int count, bool inheritLevelUp, PersonalInfo info, GameVersion gameVersion) + private static void MarkMovesForOrigin(in BreedInfo value, ReadOnlySpan eggMoves, int count, bool inheritLevelUp, PersonalInfo4 info, GameVersion gameVersion) { var possible = value.Possible; var learn = value.Learnset; var baseEgg = value.Learnset.GetBaseEggMoves(value.Level); - var tm = info.TMHM; var tmlist = TM_4.AsSpan(0, 92); var hmlist = (gameVersion is HG or SS ? HM_HGSS : HM_DPPt).AsSpan(); @@ -165,11 +169,11 @@ public static class MoveBreed4 possible[i] |= 1 << (int)FatherEgg; var tmIndex = tmlist.IndexOf(move); - if (tmIndex != -1 && tm[tmIndex]) + if (tmIndex != -1 && info.GetIsLearnTM(tmIndex)) possible[i] |= 1 << (int)FatherTM; var hmIndex = hmlist.IndexOf(move); - if (hmIndex != -1 && tm[hmIndex + 92]) + if (hmIndex != -1 && info.GetIsLearnHM(hmIndex)) possible[i] |= 1 << (int)FatherTM; } } diff --git a/PKHeX.Core/Legality/Moves/Breeding/MoveBreed5.cs b/PKHeX.Core/Legality/Moves/Breeding/MoveBreed5.cs index ae0ec0aea..ee7c508ba 100644 --- a/PKHeX.Core/Legality/Moves/Breeding/MoveBreed5.cs +++ b/PKHeX.Core/Legality/Moves/Breeding/MoveBreed5.cs @@ -23,9 +23,12 @@ public static class MoveBreed5 count = moves.Length; var learn = GameData.GetLearnsets(version); - var table = GameData.GetPersonal(version); var learnset = learn[species]; - var pi = table[species]; + IPersonalInfoTM pi = version switch + { + GameVersion.B or GameVersion.W => PersonalTable.BW[species], + _ => PersonalTable.B2W2[species], + }; var egg = Legal.EggMovesBW[species].Moves; var actual = MemoryMarshal.Cast(origins); @@ -139,12 +142,11 @@ public static class MoveBreed5 return true; } - private static void MarkMovesForOrigin(in BreedInfo value, ReadOnlySpan eggMoves, int count, bool inheritLevelUp, PersonalInfo info) + private static void MarkMovesForOrigin(in BreedInfo value, ReadOnlySpan eggMoves, int count, bool inheritLevelUp, IPersonalInfoTM info) { var possible = value.Possible; var learn = value.Learnset; var baseEgg = value.Learnset.GetBaseEggMoves(value.Level); - var tm = info.TMHM; var tmlist = LearnSource5.TMHM_BW.AsSpan(0, 95); // actually 96, but TM96 is unavailable (Snarl - Lock Capsule) var moves = value.Moves; @@ -162,7 +164,7 @@ public static class MoveBreed5 possible[i] |= 1 << (int)FatherEgg; var tmIndex = tmlist.IndexOf(move); - if (tmIndex != -1 && tm[tmIndex]) + if (tmIndex != -1 && info.GetIsLearnTM(tmIndex)) possible[i] |= 1 << (int)FatherTM; } } diff --git a/PKHeX.Core/Legality/Moves/MoveLevelUp.cs b/PKHeX.Core/Legality/Moves/MoveLevelUp.cs index 15e7ce267..a4bcc1e7a 100644 --- a/PKHeX.Core/Legality/Moves/MoveLevelUp.cs +++ b/PKHeX.Core/Legality/Moves/MoveLevelUp.cs @@ -21,7 +21,7 @@ public static class MoveLevelUp // The initial moves are seeded from Personal rather than learn. table[index].GetMoves(result); - int start = Math.Max(0, result.IndexOf((ushort)0)); + int start = Math.Max(0, result.IndexOf(0)); learn[index].SetEncounterMoves(level, result, start); } @@ -40,11 +40,4 @@ public static class MoveLevelUp learn[index].SetEncounterMoves(level, result); } } - - public static ushort[] GetEncounterMoves(ushort species, byte form, int level, GameVersion version) - { - var result = new ushort[4]; - GetEncounterMoves(result, species, form, level, version); - return result; - } } diff --git a/PKHeX.Core/Legality/RNG/Algorithms/XorShift128.cs b/PKHeX.Core/Legality/RNG/Algorithms/XorShift128.cs index 87aef60c9..63b23d468 100644 --- a/PKHeX.Core/Legality/RNG/Algorithms/XorShift128.cs +++ b/PKHeX.Core/Legality/RNG/Algorithms/XorShift128.cs @@ -1,3 +1,4 @@ +using System; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; @@ -19,6 +20,7 @@ public ref struct XorShift128 // not really readonly! just prevents future updates from touching this. [FieldOffset(0x0)] private readonly ulong s0; [FieldOffset(0x8)] private readonly ulong s1; + [FieldOffset(0x0)] public readonly UInt128 State; /// /// Uses the to advance the seed for each 32-bit input. @@ -47,9 +49,11 @@ public ref struct XorShift128 this.w = w; } + public XorShift128(UInt128 state) => State = state; + public (uint x, uint y, uint z, uint w) GetState32() => (x, y, z, w); public (ulong s0, ulong s1) GetState64() => (s0, s1); - public string FullState => $"{s1:X16}{s0:X16}"; + public string FullState => $"{State:X32}"; /// /// Gets the next random . diff --git a/PKHeX.Core/Legality/RNG/Algorithms/Xoroshiro128Plus.cs b/PKHeX.Core/Legality/RNG/Algorithms/Xoroshiro128Plus.cs index 017474375..8b836343a 100644 --- a/PKHeX.Core/Legality/RNG/Algorithms/Xoroshiro128Plus.cs +++ b/PKHeX.Core/Legality/RNG/Algorithms/Xoroshiro128Plus.cs @@ -1,4 +1,6 @@ -using System.Runtime.CompilerServices; +using System; +using System.Numerics; +using System.Runtime.CompilerServices; namespace PKHeX.Core; @@ -11,15 +13,12 @@ public ref struct Xoroshiro128Plus public const ulong XOROSHIRO_CONST0= 0x0F4B17A579F18960; public const ulong XOROSHIRO_CONST = 0x82A2B175229D6A5B; - private ulong s0, s1; + private ulong s0; + private ulong s1; public Xoroshiro128Plus(ulong s0 = XOROSHIRO_CONST0, ulong s1 = XOROSHIRO_CONST) => (this.s0, this.s1) = (s0, s1); - public (ulong s0, ulong s1) GetState() => (s0, s1); - public string FullState => $"{s1:X16}{s0:X16}"; - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private static ulong RotateLeft(ulong x, int k) => (x << k) | (x >> -k); + public UInt128 FullState() => new(s1, s0); /// /// Gets the next random . @@ -33,8 +32,8 @@ public ref struct Xoroshiro128Plus _s1 ^= _s0; // Final calculations and store back to fields - s0 = RotateLeft(_s0, 24) ^ _s1 ^ (_s1 << 16); - s1 = RotateLeft(_s1, 37); + s0 = BitOperations.RotateLeft(_s0, 24) ^ _s1 ^ (_s1 << 16); + s1 = BitOperations.RotateLeft(_s1, 37); return result; } @@ -47,9 +46,9 @@ public ref struct Xoroshiro128Plus { var _s0 = s0; var _s1 = s1; - _s1 = RotateLeft(_s1, 27); + _s1 = BitOperations.RotateLeft(_s1, 27); _s0 = _s0 ^ _s1 ^ (_s1 << 16); - _s0 = RotateLeft(_s0, 40); + _s0 = BitOperations.RotateLeft(_s0, 40); _s1 ^= _s0; ulong result = _s0 + _s1; @@ -59,35 +58,27 @@ public ref struct Xoroshiro128Plus } /// - /// Gets a random value that is less than + /// Gets a random value that is less than /// - /// Maximum value (exclusive). Generates a bitmask for the loop. + /// Maximum value (exclusive). Generates a bitmask for the loop. /// Random value - public ulong NextInt(ulong MOD = 0xFFFFFFFF) + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public ulong NextInt(ulong max = uint.MaxValue) { - ulong mask = GetBitmask(MOD); - ulong res; - do + ulong mask = GetBitmask(max); + while (true) { - res = Next() & mask; - } while (res >= MOD); - return res; + var result = Next() & mask; + if (result < max) + return result; + } } /// - /// Next Power of Two + /// Gets the inclusive range bitmask for the specified value. /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - private static ulong GetBitmask(ulong x) - { - x--; // comment out to always take the next biggest power of two, even if x is already a power of two - x |= x >> 1; - x |= x >> 2; - x |= x >> 4; - x |= x >> 8; - x |= x >> 16; - return x; - } + private static ulong GetBitmask(ulong exclusiveMax) => (1UL << (64 - BitOperations.LeadingZeroCount(--exclusiveMax))) - 1; /// /// Gets a random float value. diff --git a/PKHeX.Core/Legality/RNG/Algorithms/Xoroshiro128Plus8b.cs b/PKHeX.Core/Legality/RNG/Algorithms/Xoroshiro128Plus8b.cs index 2b343ec7c..d1b41bea8 100644 --- a/PKHeX.Core/Legality/RNG/Algorithms/Xoroshiro128Plus8b.cs +++ b/PKHeX.Core/Legality/RNG/Algorithms/Xoroshiro128Plus8b.cs @@ -1,4 +1,6 @@ -using System.Runtime.CompilerServices; +using System; +using System.Numerics; +using System.Runtime.CompilerServices; namespace PKHeX.Core; @@ -10,7 +12,12 @@ namespace PKHeX.Core; /// Used by the Brilliant Diamond & Shining Pearl games; differs in how values are yielded by Next calls. public ref struct Xoroshiro128Plus8b { - private ulong s0, s1; + private ulong s0; + private ulong s1; + + public Xoroshiro128Plus8b(ulong s0, ulong s1) => (this.s0, this.s1) = (s0, s1); + public (ulong s0, ulong s1) GetState() => (s0, s1); + public UInt128 FullState() => new(s1, s0); public Xoroshiro128Plus8b(ulong seed) { @@ -25,21 +32,6 @@ public ref struct Xoroshiro128Plus8b return seed ^ (seed >> 31); } - public Xoroshiro128Plus8b(ulong s0, ulong s1) - { - this.s0 = s0; - this.s1 = s1; - } - - public (ulong s0, ulong s1) GetState() => (s0, s1); - public string FullState => $"{s1:X16}{s0:X16}"; - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private static ulong RotateLeft(ulong x, int k) - { - return (x << k) | (x >> (64 - k)); - } - /// /// Gets the next random . /// @@ -52,8 +44,8 @@ public ref struct Xoroshiro128Plus8b _s1 ^= _s0; // Final calculations and store back to fields - s0 = RotateLeft(_s0, 24) ^ _s1 ^ (_s1 << 16); - s1 = RotateLeft(_s1, 37); + s0 = BitOperations.RotateLeft(_s0, 24) ^ _s1 ^ (_s1 << 16); + s1 = BitOperations.RotateLeft(_s1, 37); return result; } @@ -66,9 +58,9 @@ public ref struct Xoroshiro128Plus8b { var _s0 = s0; var _s1 = s1; - _s1 = RotateLeft(_s1, 27); + _s1 = BitOperations.RotateLeft(_s1, 27); _s0 = _s0 ^ _s1 ^ (_s1 << 16); - _s0 = RotateLeft(_s0, 40); + _s0 = BitOperations.RotateLeft(_s0, 40); _s1 ^= _s0; ulong result = _s0 + _s1; diff --git a/PKHeX.Core/Legality/RNG/Frame/Frame.cs b/PKHeX.Core/Legality/RNG/Frame/Frame.cs index 8e7f3f133..55e5ffdc0 100644 --- a/PKHeX.Core/Legality/RNG/Frame/Frame.cs +++ b/PKHeX.Core/Legality/RNG/Frame/Frame.cs @@ -87,7 +87,7 @@ public sealed class Frame /// /// Slot Data /// Slot number for this frame & lead value. - private int GetSlot(T slot) where T : EncounterSlot, IMagnetStatic, INumberedSlot, ISlotRNGType + private int GetSlot(T slot) where T : IMagnetStatic, INumberedSlot, ISlotRNGType { // Static and Magnet Pull do a slot search rather than slot mapping 0-99. return Lead != LeadRequired.StaticMagnet diff --git a/PKHeX.Core/Legality/RNG/Frame/FrameFinder.cs b/PKHeX.Core/Legality/RNG/Frame/FrameFinder.cs index ec14092fa..9073087cf 100644 --- a/PKHeX.Core/Legality/RNG/Frame/FrameFinder.cs +++ b/PKHeX.Core/Legality/RNG/Frame/FrameFinder.cs @@ -32,7 +32,7 @@ public static class FrameFinder // gather possible nature determination seeds until a same-nature PID breaks the unrolling private static IEnumerable GetSeeds(PIDIV pidiv, FrameGenerator info, PKM pk) { - if (pk.Species == (int)Species.Unown && pk.FRLG) // Gen3 FRLG Unown: reversed await case + if (pk is { Species: (int)Species.Unown, FRLG: true }) // Gen3 FRLG Unown: reversed await case return SeedInfo.GetSeedsUntilUnownForm(pidiv, info, pk.Form); if (pidiv.Type == PIDType.CuteCharm && info.FrameType != FrameType.MethodH) // Gen4: ambiguous seed due to gender-buffered PID return SeedInfo.GetSeedsUntilNature4Cute(pk); diff --git a/PKHeX.Core/Legality/RNG/Frame/SlotRange.cs b/PKHeX.Core/Legality/RNG/Frame/SlotRange.cs index 3a8d88e43..b3d6d4f0c 100644 --- a/PKHeX.Core/Legality/RNG/Frame/SlotRange.cs +++ b/PKHeX.Core/Legality/RNG/Frame/SlotRange.cs @@ -135,15 +135,15 @@ public static class SlotRange /// Slot Data /// Rand16 value for the call /// Slot number from the slot data if the slot is selected on this frame, else an invalid slot value. - internal static int GetSlotStaticMagnet(T slot, uint esv) where T : EncounterSlot, IMagnetStatic, INumberedSlot + internal static int GetSlotStaticMagnet(T slot, uint esv) where T : IMagnetStatic, INumberedSlot { - if (slot.IsStaticSlot()) + if (slot.IsStaticSlot) { var index = esv % slot.StaticCount; if (index == slot.StaticIndex) return slot.SlotNumber; } - if (slot.IsMagnetSlot()) + if (slot.IsMagnetSlot) { var index = esv % slot.MagnetPullCount; if (index == slot.MagnetPullIndex) diff --git a/PKHeX.Core/Legality/RNG/Locks/LockFinder.cs b/PKHeX.Core/Legality/RNG/Locks/LockFinder.cs index ecc611289..ea80408f9 100644 --- a/PKHeX.Core/Legality/RNG/Locks/LockFinder.cs +++ b/PKHeX.Core/Legality/RNG/Locks/LockFinder.cs @@ -22,7 +22,7 @@ public static class LockFinder if (teams.Length == 0) return true; - var tsv = s.Version == GameVersion.XD ? (pk.TID ^ pk.SID) >> 3 : -1; // no xd shiny shadow mons + var tsv = s.Version == GameVersion.XD ? (uint)(pk.TID16 ^ pk.SID16) >> 3 : uint.MaxValue; // no xd shiny shadow mons return IsAllShadowLockValid(pv, teams, tsv); } @@ -32,7 +32,7 @@ public static class LockFinder /// RNG result PID and IV seed state /// Possible team data setups the NPC trainer has that need to generate before the shadow. /// Trainer shiny value that is disallowed in XD - public static bool IsAllShadowLockValid(PIDIV pv, IEnumerable teams, int tsv = -1) + public static bool IsAllShadowLockValid(PIDIV pv, IEnumerable teams, uint tsv = uint.MaxValue) { foreach (var t in teams) { @@ -47,15 +47,15 @@ public static class LockFinder /// Checks if the XD starter Eevee can be obtained with the trainer's IDs. /// /// Seed that generated the PID and IV - /// Trainer ID - /// Trainer Secret ID + /// Trainer ID + /// Trainer Secret ID /// True if the starter ID correlation is correct - public static bool IsXDStarterValid(uint seed, int TID, int SID) + public static bool IsXDStarterValid(uint seed, uint TID16, uint SID16) { - // pidiv reversed 2x yields SID, 3x yields TID. shift by 7 if another PKM is generated prior + // pidiv reversed 2x yields SID16, 3x yields TID16. shift by 7 if another PKM is generated prior var SIDf = XDRNG.Prev2(seed); var TIDf = XDRNG.Prev(SIDf); - return SIDf >> 16 == SID && TIDf >> 16 == TID; + return SIDf >> 16 == SID16 && TIDf >> 16 == TID16; } /// @@ -63,22 +63,22 @@ public static class LockFinder /// /// Species of the starter, to indicate Espeon vs Umbreon /// Seed the PID/IV is generated with - /// Trainer ID of the trainer - /// Secret ID of the trainer + /// Trainer ID of the trainer + /// Secret ID of the trainer /// PID of the entity /// First 3 IVs combined /// Last 3 IVs combined - public static bool IsColoStarterValid(ushort species, ref uint seed, int TID, int SID, uint pkPID, uint IV1, uint IV2) + public static bool IsColoStarterValid(ushort species, ref uint seed, ushort TID16, ushort SID16, uint pkPID, uint IV1, uint IV2) { // reverse the seed the bare minimum uint SIDf = species == (int)Species.Espeon ? XDRNG.Prev9(seed) : XDRNG.Prev2(seed); - // reverse until we find the TID/SID, then run the generation forward to see if it matches our inputs. + // reverse until we find the TID16/SID16, then run the generation forward to see if it matches our inputs. int ctr = 0; uint temp; - while ((temp = XDRNG.Prev(SIDf)) >> 16 != TID || SIDf >> 16 != SID) + while ((temp = XDRNG.Prev(SIDf)) >> 16 != TID16 || SIDf >> 16 != SID16) { SIDf = temp; if (ctr > 32) // arbitrary @@ -89,9 +89,9 @@ public static class LockFinder var next = XDRNG.Next(SIDf); // generate Umbreon - var PIDIV = GenerateValidColoStarterPID(ref next, TID, SID); + var PIDIV = GenerateValidColoStarterPID(ref next, TID16, SID16); if (species == (int)Species.Espeon) // need Espeon, which is immediately next - PIDIV = GenerateValidColoStarterPID(ref next, TID, SID); + PIDIV = GenerateValidColoStarterPID(ref next, TID16, SID16); if (!PIDIV.Equals(pkPID, IV1, IV2)) return false; @@ -104,7 +104,7 @@ public static class LockFinder public bool Equals(uint pid, uint iv1, uint iv2) => PID == pid && IV1 == iv1 && IV2 == iv2; } - private static PIDIVGroup GenerateValidColoStarterPID(ref uint uSeed, int TID, int SID) + private static PIDIVGroup GenerateValidColoStarterPID(ref uint uSeed, ushort TID16, ushort SID16) { uSeed = XDRNG.Next2(uSeed); // skip fakePID var IV1 = (uSeed >> 16) & 0x7FFF; @@ -112,16 +112,16 @@ public static class LockFinder var IV2 = (uSeed >> 16) & 0x7FFF; uSeed = XDRNG.Next(uSeed); uSeed = XDRNG.Next(uSeed); // skip ability call - var PID = GenerateStarterPID(ref uSeed, TID, SID); + var PID = GenerateStarterPID(ref uSeed, TID16, SID16); uSeed = XDRNG.Next2(uSeed); // PID calls consumed return new PIDIVGroup(PID, IV1, IV2); } - private static bool IsShiny(int TID, int SID, uint PID) => (TID ^ SID ^ (PID >> 16) ^ (PID & 0xFFFF)) < 8; + private static bool IsShiny(ushort TID16, ushort SID16, uint PID) => ((PID >> 16) ^ TID16 ^ SID16 ^ (PID & 0xFFFF)) < 8; - private static uint GenerateStarterPID(ref uint uSeed, int TID, int SID) + private static uint GenerateStarterPID(ref uint uSeed, ushort TID16, ushort SID16) { uint PID; const byte ratio = 0x1F; // 12.5% F (can't be female) @@ -129,7 +129,7 @@ public static class LockFinder { var next = XDRNG.Next(uSeed); PID = (uSeed & 0xFFFF0000) | (next >> 16); - if ((PID & 0xFF) >= ratio && !IsShiny(TID, SID, PID)) + if ((PID & 0xFF) >= ratio && !IsShiny(TID16, SID16, PID)) break; uSeed = XDRNG.Next(next); } diff --git a/PKHeX.Core/Legality/RNG/Locks/NPCLock.cs b/PKHeX.Core/Legality/RNG/Locks/NPCLock.cs index 1a6f4a56c..eb1e4b827 100644 --- a/PKHeX.Core/Legality/RNG/Locks/NPCLock.cs +++ b/PKHeX.Core/Legality/RNG/Locks/NPCLock.cs @@ -5,11 +5,11 @@ namespace PKHeX.Core; /// public readonly record struct NPCLock { - private readonly int Species; private readonly byte Nature; private readonly byte Gender; private readonly byte Ratio; private readonly byte State; + private readonly ushort Species; public int FramesConsumed => Seen ? 5 : 7; public bool Seen => State > 1; @@ -17,22 +17,18 @@ public readonly record struct NPCLock public (byte Nature, byte Gender) GetLock => (Nature, Gender); // Not-Shadow - public NPCLock(short s, byte n, byte g, byte r) + public NPCLock(ushort s, byte n, byte g, byte r) { Species = s; Nature = n; Gender = g; Ratio = r; - State = 0; } // Shadow - public NPCLock(short s, bool seen = false) + public NPCLock(ushort s, bool seen = false) { Species = s; - Nature = 0; - Gender = 0; - Ratio = 0; State = seen ? (byte)2 : (byte)1; } diff --git a/PKHeX.Core/Legality/RNG/Locks/TeamLock.cs b/PKHeX.Core/Legality/RNG/Locks/TeamLock.cs index 65ac7a892..254f0e865 100644 --- a/PKHeX.Core/Legality/RNG/Locks/TeamLock.cs +++ b/PKHeX.Core/Legality/RNG/Locks/TeamLock.cs @@ -12,15 +12,15 @@ public sealed class TeamLock /// /// For trainers that have different teams, this indicates what conditions (when/where) the trainer must be battled. /// - public readonly string Comment; + public readonly NPCLockDetail Comment; /// /// Species of shadow Pokémon that is generated after the . /// - public readonly int Species; + public readonly ushort Species; - public TeamLock(ushort species, NPCLock[] locks) : this(species, string.Empty, locks) { } + public TeamLock(ushort species, NPCLock[] locks) : this(species, 0, locks) { } - public TeamLock(ushort species, string comment, NPCLock[] locks) + public TeamLock(ushort species, NPCLockDetail comment, NPCLock[] locks) { Species = species; Locks = locks; @@ -29,8 +29,45 @@ public sealed class TeamLock public override string ToString() { - if (Comment.Length == 0) + if (Comment == 0) return $"{(Species)Species} [{Locks.Length}]"; return $"{(Species)Species} [{Locks.Length}] - {Comment}"; } } + +public enum NPCLockDetail : byte +{ + CipherLab, + Post, + PhenacCity, + PhenacCityAndPost, + + SeenParas, + SeenBeedrill, + SeenTangela, + SeenVenomoth, + SeenPrimeape, + SeenGolduck, + SeenDodrio, + SeenFarfetchd, + SeenKangaskhan, + SeenMagmar, + SeenRapidash, + SeenScyther, + SeenSolrock, + SeenSwellow, + SeenSwellowElectabuzz, + SeenPoliwrath, + SeenManectric, + SeenManectricSalamence, + SeenManectricMarowak, + SeenManectricMarowakSalamence, + SeenRhydonMoltres, + SeenRhydonMoltresExeggutor, + SeenRhydonMoltresTauros, + SeenRhydonMoltresArticuno, + SeenRhydonMoltresTaurosArticuno, + SeenRhydonMoltresExeggutorTauros, + SeenRhydonMoltresExeggutorArticuno, + SeenRhydonMoltresExeggutorTaurosArticuno, +} diff --git a/PKHeX.Core/Legality/RNG/Locks/TeamLockResult.cs b/PKHeX.Core/Legality/RNG/Locks/TeamLockResult.cs index 841616504..1f05ccb22 100644 --- a/PKHeX.Core/Legality/RNG/Locks/TeamLockResult.cs +++ b/PKHeX.Core/Legality/RNG/Locks/TeamLockResult.cs @@ -43,22 +43,22 @@ public sealed class TeamLockResult /// If this value is >= 0, the CPU Trainer Shiny Value must be equal to this value as a skipped over a matching interrupt frame. /// If this value is , the CPU Trainer Shiny Value can be anything (except matching any of the result members. /// - private int RCSV = NOT_FORCED; + private uint RCSV = NOT_FORCED; /// /// Player Trainer Shiny Value /// /// Only used by encounters, which disallow shiny shadow members for both player & CPU TSVs. - private readonly int TSV; + private readonly uint TSV; private readonly Stack Locks; private readonly FrameCache Cache; // only save a list of valid nodes we've visited to save memory while we recursively search for a full team. private readonly Stack Team; - private const int NOT_FORCED = -1; + private const uint NOT_FORCED = uint.MaxValue; - internal TeamLockResult(TeamLock teamSpec, uint originSeed, int tsv) + internal TeamLockResult(TeamLock teamSpec, uint originSeed, uint tsv) { Locks = new Stack((Specifications = teamSpec).Locks); Team = new Stack(Locks.Count); @@ -145,7 +145,7 @@ public sealed class TeamLockResult if (sv == RCSV) { // No CPU shiny value forced yet. Lets try to skip this lock by requiring the eventual OT to get this shiny. - RCSV = (int) sv; + RCSV = sv; forcedOT = true; continue; // don't break } @@ -208,7 +208,7 @@ public sealed class TeamLockResult } else // No CPU shiny value forced yet. Lets try to skip this lock by requiring the eventual OT to get this shiny. { - RCSV = (int)sv; + RCSV = sv; forcedOT = true; // don't break } @@ -229,9 +229,9 @@ public sealed class TeamLockResult /// True if the are valid. private bool VerifyNPC(int ctr) { - var TID = Cache[ctr + 1]; - var SID = Cache[ctr]; - var CPUSV = (TID ^ SID) >> 3; + var TID16 = Cache[ctr + 1]; + var SID16 = Cache[ctr]; + var CPUSV = (TID16 ^ SID16) >> 3; if (RCSV != NOT_FORCED && RCSV != CPUSV) return false; // required CPU Trainer's shiny value did not match the required value. diff --git a/PKHeX.Core/Legality/RNG/MethodFinder.cs b/PKHeX.Core/Legality/RNG/MethodFinder.cs index 3c57bc441..faa06d058 100644 --- a/PKHeX.Core/Legality/RNG/MethodFinder.cs +++ b/PKHeX.Core/Legality/RNG/MethodFinder.cs @@ -263,7 +263,7 @@ public static class MethodFinder } // check for anti-shiny against player TSV - var tsv = (uint)(pk.TID ^ pk.SID) >> 3; + var tsv = (uint)(pk.TID16 ^ pk.SID16) >> 3; var psv = (top ^ bot) >> 3; if (psv == tsv) // already shiny, wouldn't be anti-shiny continue; @@ -302,7 +302,7 @@ public static class MethodFinder return GetNonMatch(out pidiv); var undo = (top >> 16) ^ 0x8000; - if ((undo > 7 ? 0 : 1) != ((bot >> 16) ^ pk.SID ^ 40122)) + if ((undo > 7 ? 0 : 1) != ((bot >> 16) ^ pk.SID16 ^ 40122)) top = (undo << 16); var count = XDRNG.GetSeeds(seeds, top, bot); @@ -323,7 +323,7 @@ public static class MethodFinder if (!XDRNG.GetSequentialIVsUInt32(E, IVs)) continue; - if (seed >> 16 != pk.SID) + if (seed >> 16 != pk.SID16) continue; pidiv = new PIDIV(Channel, XDRNG.Prev(seed)); @@ -359,7 +359,7 @@ public static class MethodFinder if (low <= 0xFF) { var av = (pid >> 16) & 1; - var genPID = PIDGenerator.GetMG5ShinyPID(low, av, pk.TID, pk.SID); + var genPID = PIDGenerator.GetMG5ShinyPID(low, av, pk.TID16, pk.SID16); if (genPID == pid) { pidiv = PIDIV.G5MGShiny; @@ -375,7 +375,7 @@ public static class MethodFinder return GetNonMatch(out pidiv); (var species, int genderValue) = GetCuteCharmGenderSpecies(pk, pid, pk.Species); - static int getRatio(ushort species) + static byte getRatio(ushort species) { return species <= Legal.MaxSpeciesID_4 ? PersonalTable.HGSS[species].Gender @@ -442,7 +442,7 @@ public static class MethodFinder if ((lower >> 16 & 7) != (pid & 7)) continue; - var upid = (((pid & 0xFFFF) ^ pk.TID ^ pk.SID) & 0xFFF8) | ((upper >> 16) & 0x7); + var upid = (((pid & 0xFFFF) ^ pk.TID16 ^ pk.SID16) & 0xFFF8) | ((upper >> 16) & 0x7); if (upid != pid >> 16) continue; @@ -470,7 +470,7 @@ public static class MethodFinder var PID = (A & 0xFFFF0000) | low; if (PID != pid) { - uint idxor = (uint)(pk.TID ^ pk.SID); + uint idxor = (uint)(pk.TID16 ^ pk.SID16); bool isShiny = (idxor ^ PID >> 16 ^ (PID & 0xFFFF)) < 8; if (!isShiny) { @@ -522,7 +522,7 @@ public static class MethodFinder return GetNonMatch(out pidiv); var gender = pk.Gender; - uint pid = PIDGenerator.GetPokeWalkerPID(pk.TID, pk.SID, nature, gender, pk.PersonalInfo.Gender); + uint pid = PIDGenerator.GetPokeWalkerPID(pk.TID16, pk.SID16, nature, gender, pk.PersonalInfo.Gender); if (pid != oldpid) { @@ -541,12 +541,12 @@ public static class MethodFinder if (species is not ((int)Species.Marill or (int)Species.Azumarill)) return false; - const int AzurillGenderRatio = 0xBF; + const byte AzurillGenderRatio = 0xBF; var gender = EntityGender.GetFromPIDAndRatio(pk.PID, AzurillGenderRatio); if (gender != 1) return false; - var pid = PIDGenerator.GetPokeWalkerPID(pk.TID, pk.SID, nature, 1, AzurillGenderRatio); + var pid = PIDGenerator.GetPokeWalkerPID(pk.TID16, pk.SID16, nature, 1, AzurillGenderRatio); return pid == oldpid; } @@ -569,7 +569,7 @@ public static class MethodFinder foreach (var seed in xdc) { uint origin = seed; - if (!LockFinder.IsColoStarterValid(pk.Species, ref origin, pk.TID, pk.SID, pk.PID, iv1, iv2)) + if (!LockFinder.IsColoStarterValid(pk.Species, ref origin, pk.TID16, pk.SID16, pk.PID, iv1, iv2)) continue; pidiv = new PIDIV(CXD_ColoStarter, origin); @@ -593,7 +593,7 @@ public static class MethodFinder /// /// Checks if the PID is a match. /// - /// ^ + /// ^ /// Full actual PID /// Low portion of PID (B) /// First RNG call @@ -607,7 +607,7 @@ public static class MethodFinder // 1-PIDH // 2-PIDL (ends up unused) // 3-FORCEBITS - // PID = PIDH << 16 | (SID ^ TID ^ PIDH) + // PID = PIDH << 16 | (SID16 ^ TID16 ^ PIDH) var X = LCRNG.Prev(A); // unroll once as there's 3 calls instead of 2 uint PID = (X & 0xFFFF0000) | (idxor ^ X >> 16); @@ -624,7 +624,7 @@ public static class MethodFinder /// /// Checks if the PID is a match. /// - /// ^ + /// ^ /// Full actual PID /// Low portion of PID (B) /// First RNG call @@ -705,7 +705,7 @@ public static class MethodFinder val |= IVs[i+start] << (5*i); return val; } - + public static bool IsPokeSpotActivation(int slot, uint seed, out uint s) { s = seed; @@ -778,7 +778,7 @@ public static class MethodFinder // only 8 bits are stored instead of 32 -- 5 bits HP, 3 bits for ATK. // return pk.IV32 <= 0xFF; - return pk.IV_DEF == 0 && pk.IV_SPE == 0 && pk.IV_SPA == 0 && pk.IV_SPD == 0 && pk.IV_ATK <= 7; + return pk is { IV_DEF: 0, IV_SPE: 0, IV_SPA: 0, IV_SPD: 0, IV_ATK: <= 7 }; } public static bool IsCompatible4(this PIDType val, IEncounterTemplate encounter, PKM pk) => encounter switch @@ -795,7 +795,7 @@ public static class MethodFinder EncounterSlot4 w => val switch { // Chain shiny with Poké Radar is only possible in DPPt, in grass. Safari Zone does not allow using the Poké Radar - ChainShiny => pk.IsShiny && !pk.HGSS && (w.GroundTile & GroundTileAllowed.Grass) != 0 && !Locations.IsSafariZoneLocation4(w.Location), + ChainShiny => pk is { IsShiny: true, HGSS: false } && (w.GroundTile & GroundTileAllowed.Grass) != 0 && !Locations.IsSafariZoneLocation4(w.Location), CuteCharm => IsCuteCharm4Valid(encounter, pk), _ => val is Method_1, }, @@ -823,7 +823,9 @@ public static class MethodFinder bool IsAntiShinyARNG() { var shinyPID = ARNG.Prev(pk.PID); - return (pk.TID ^ pk.SID ^ (shinyPID & 0xFFFF) ^ (shinyPID >> 16)) < 8; // shiny proc + var tmp = pk.ID32 ^ shinyPID; + var xor = (ushort)(tmp ^ (tmp >> 16)); + return xor < 8; // shiny proc } } diff --git a/PKHeX.Core/Legality/RNG/Methods/Encounter9RNG.cs b/PKHeX.Core/Legality/RNG/Methods/Encounter9RNG.cs index 4ed37c491..951fac98f 100644 --- a/PKHeX.Core/Legality/RNG/Methods/Encounter9RNG.cs +++ b/PKHeX.Core/Legality/RNG/Methods/Encounter9RNG.cs @@ -246,18 +246,16 @@ public static class Encounter9RNG { var tid = (ushort)fakeTID; var sid = (ushort)(fakeTID >> 16); - if (!GetIsShiny(tid, sid, pid)) // battled + if (!GetIsShiny(fakeTID, pid)) // battled pid = GetShinyPID(tid, sid, pid, 0); - if (!GetIsShiny(pk.TID, pk.SID, pid)) // captured - pid = GetShinyPID(pk.TID, pk.SID, pid, GetShinyXor(pid, fakeTID) == 0 ? 0 : 1); + if (!GetIsShiny(pk.ID32, pid)) // captured + pid = GetShinyPID(pk.TID16, pk.SID16, pid, GetShinyXor(pid, fakeTID) == 0 ? 0u : 1u); } else // Never { - var tid = (ushort)fakeTID; - var sid = (ushort)(fakeTID >> 16); - if (GetIsShiny(tid, sid, pid)) // battled + if (GetIsShiny(fakeTID, pid)) // battled pid ^= 0x1000_0000; - if (GetIsShiny(pk.TID, pk.SID, pid)) // captured + if (GetIsShiny(pk.ID32, pid)) // captured pid ^= 0x1000_0000; } return pid; @@ -279,43 +277,30 @@ public static class Encounter9RNG { if (isShiny) { - if (!GetIsShiny(pk.TID, pk.SID, pid)) - pid = GetShinyPID(pk.TID, pk.SID, pid, (int)xor); + if (!GetIsShiny(pk.ID32, pid)) + pid = GetShinyPID(pk.TID16, pk.SID16, pid, xor); } else { - if (GetIsShiny(pk.TID, pk.SID, pid)) + if (GetIsShiny(pk.ID32, pid)) pid ^= 0x1000_0000; } } - private static uint GetShinyPID(in int tid, in int sid, in uint pid, in int type) + private static uint GetShinyPID(in ushort tid, in ushort sid, in uint pid, in uint type) { - return (uint)(((tid ^ sid ^ (pid & 0xFFFF) ^ type) << 16) | (pid & 0xFFFF)); + var low = pid & 0xFFFF; + return ((type ^ tid ^ sid ^ low) << 16) | low; } - private static bool GetIsShiny(in int tid, in int sid, in uint pid) + private static bool GetIsShiny(in uint id32, in uint pid) { - return GetShinyXor(tid, sid, pid) < 16; + return GetShinyXor(id32, pid) < 16; } - private static uint GetShinyXor(in int tid, in int sid, in uint pid) + private static uint GetShinyXor(in uint pid, in uint id32) { - return GetShinyXor(pid, (uint)((sid << 16) | tid)); - } - - private static uint GetShinyXor(in uint pid, in uint oid) - { - var xor = pid ^ oid; + var xor = pid ^ id32; return (xor ^ (xor >> 16)) & 0xFFFF; } } - -public interface ITeraRaid9 : IGemType -{ - bool IsDistribution { get; } - byte Index { get; } - byte Stars { get; } - byte RandRate { get; } - bool CanBeEncountered(uint seed); -} diff --git a/PKHeX.Core/Legality/RNG/Methods/Overworld8RNG.cs b/PKHeX.Core/Legality/RNG/Methods/Overworld8RNG.cs index 63c9005da..c3498879a 100644 --- a/PKHeX.Core/Legality/RNG/Methods/Overworld8RNG.cs +++ b/PKHeX.Core/Legality/RNG/Methods/Overworld8RNG.cs @@ -37,7 +37,7 @@ public static class Overworld8RNG // PID var pid = (uint) xoro.NextInt(uint.MaxValue); - var xor = GetShinyXor(pk.TID, pk.SID, pid); + var xor = GetShinyXor(pk.ID32, pid); var type = GetRareType(xor); if (shiny == Shiny.Never) { @@ -136,15 +136,15 @@ public static class Overworld8RNG // Check forced shiny if (pk.IsShiny) { - if (GetIsShiny(pk.TID, pk.SID, pid)) + if (GetIsShiny(pk.ID32, pid)) return false; - pid = GetShinyPID(pk.TID, pk.SID, pid, 0); + pid = GetShinyPID(pk.TID16, pk.SID16, pid, 0); return pid == pk.PID; } // Check forced non-shiny - if (!GetIsShiny(pk.TID, pk.SID, pid)) + if (!GetIsShiny(pk.ID32, pid)) return false; pid ^= 0x1000_0000; @@ -199,24 +199,12 @@ public static class Overworld8RNG return NoMatchIVs; } - private static uint GetShinyPID(int tid, int sid, uint pid, int type) - { - return (uint)(((tid ^ sid ^ (pid & 0xFFFF) ^ type) << 16) | (pid & 0xFFFF)); - } + private static bool GetIsShiny(uint id32, uint pid) => GetShinyXor(pid, id32) < 16; + private static uint GetShinyPID(ushort tid, ushort sid, uint pid, uint type) => (((pid & 0xFFFF) ^ tid ^ sid ^ type) << 16) | (pid & 0xFFFF); - private static bool GetIsShiny(int tid, int sid, uint pid) + private static uint GetShinyXor(uint pid, uint id32) { - return GetShinyXor(pid, (uint)((sid << 16) | tid)) < 16; - } - - private static uint GetShinyXor(int tid, int sid, uint pid) - { - return GetShinyXor(pid, (uint)((sid << 16) | tid)); - } - - private static uint GetShinyXor(uint pid, uint oid) - { - var xor = pid ^ oid; + var xor = pid ^ id32; return (xor ^ (xor >> 16)) & 0xFFFF; } diff --git a/PKHeX.Core/Legality/RNG/Methods/Overworld8aRNG.cs b/PKHeX.Core/Legality/RNG/Methods/Overworld8aRNG.cs index 6d7a648a7..2feb05b12 100644 --- a/PKHeX.Core/Legality/RNG/Methods/Overworld8aRNG.cs +++ b/PKHeX.Core/Legality/RNG/Methods/Overworld8aRNG.cs @@ -8,24 +8,12 @@ namespace PKHeX.Core; /// public static class Overworld8aRNG { - private static uint GetShinyPID(int tid, int sid, uint pid, int type) - { - return (uint)(((tid ^ sid ^ (pid & 0xFFFF) ^ type) << 16) | (pid & 0xFFFF)); - } + private static uint GetShinyPID(ushort tid, ushort sid, uint pid, uint type) => (((pid & 0xFFFF) ^ tid ^ sid ^ type) << 16) | (pid & 0xFFFF); + private static bool GetIsShiny(uint id32, uint pid) => GetShinyXor(id32, pid) < 16; - private static bool GetIsShiny(int tid, int sid, uint pid) + private static uint GetShinyXor(uint pid, uint id32) { - return GetShinyXor(tid, sid, pid) < 16; - } - - private static uint GetShinyXor(int tid, int sid, uint pid) - { - return GetShinyXor(pid, (uint)((sid << 16) | tid)); - } - - private static uint GetShinyXor(uint pid, uint oid) - { - var xor = pid ^ oid; + var xor = pid ^ id32; return (xor ^ (xor >> 16)) & 0xFFFF; } @@ -94,9 +82,7 @@ public static class Overworld8aRNG var index = GetRandomAlphaMoveIndex(seed, count); var alphaIndex = pi.GetMoveShopIndex(index); - var alphaMove = Legal.MoveShop8_LA[alphaIndex]; - - pa8.AlphaMove = alphaMove; + pa8.AlphaMove = PersonalInfo8LA.GetMoveShopMove(alphaIndex); } private static int GetRandomAlphaMoveIndex(ulong alphaSeed, int count) @@ -134,7 +120,7 @@ public static class Overworld8aRNG ForceShinyState(pk, isShiny, ref pid); - var xor = GetShinyXor(pk.TID, pk.SID, pid); + var xor = GetShinyXor(pk.ID32, pid); var type = GetRareType(xor); if (para.Shiny == Shiny.Never) { @@ -325,12 +311,12 @@ public static class Overworld8aRNG { if (isShiny) { - if (!GetIsShiny(pk.TID, pk.SID, pid)) - pid = GetShinyPID(pk.TID, pk.SID, pid, 0); + if (!GetIsShiny(pk.ID32, pid)) + pid = GetShinyPID(pk.TID16, pk.SID16, pid, 0); } else { - if (GetIsShiny(pk.TID, pk.SID, pid)) + if (GetIsShiny(pk.ID32, pid)) pid ^= 0x1000_0000; } } diff --git a/PKHeX.Core/Legality/RNG/Methods/Roaming8bRNG.cs b/PKHeX.Core/Legality/RNG/Methods/Roaming8bRNG.cs index 8023a1435..5cc6d0cc1 100644 --- a/PKHeX.Core/Legality/RNG/Methods/Roaming8bRNG.cs +++ b/PKHeX.Core/Legality/RNG/Methods/Roaming8bRNG.cs @@ -43,7 +43,7 @@ public static class Roaming8bRNG var fakeTID = xoro.NextUInt(); // fakeTID var pid = xoro.NextUInt(); pid = GetRevisedPID(fakeTID, pid, pk); - var xor = GetShinyXor(pk.TID, pk.SID, pid); + var xor = GetShinyXor(pk.ID32, pid); var type = GetRareType(xor); if (shiny == Shiny.Never) { @@ -234,10 +234,10 @@ public static class Roaming8bRNG return s.HeightScalar == height && s.WeightScalar == weight; } - private static uint GetRevisedPID(uint fakeTID, uint pid, ITrainerID tr) + private static uint GetRevisedPID(uint fakeTID, uint pid, ITrainerID32 tr) { var xor = GetShinyXor(pid, fakeTID); - var newXor = GetShinyXor(pid, (uint)(tr.TID | (tr.SID << 16))); + var newXor = GetShinyXor(pid, tr.ID32); var fakeRare = GetRareType(xor); var newRare = GetRareType(newXor); @@ -246,9 +246,10 @@ public static class Roaming8bRNG return pid; var isShiny = xor < 16; - if (isShiny) - return (((uint)(tr.TID ^ tr.SID) ^ (pid & 0xFFFF) ^ (xor == 0 ? 0u : 1u)) << 16) | (pid & 0xFFFF); // force same shiny star type - return pid ^ 0x1000_0000; + if (!isShiny) + return pid ^ 0x1000_0000; + var low = pid & 0xFFFF; + return (((xor == 0 ? 0u : 1u) ^ tr.TID16 ^ tr.SID16 ^ low) << 16) | low; // force same shiny star type } private static Shiny GetRareType(uint xor) => xor switch @@ -258,14 +259,9 @@ public static class Roaming8bRNG _ => Shiny.Never, }; - private static uint GetShinyXor(int tid, int sid, uint pid) + private static uint GetShinyXor(uint pid, uint id32) { - return GetShinyXor(pid, (uint)((sid << 16) | tid)); - } - - private static uint GetShinyXor(uint pid, uint oid) - { - var xor = pid ^ oid; + var xor = pid ^ id32; return (xor ^ (xor >> 16)) & 0xFFFF; } } diff --git a/PKHeX.Core/Legality/RNG/Methods/ToxtricityUtil.cs b/PKHeX.Core/Legality/RNG/Methods/ToxtricityUtil.cs index 29a33e09a..c777614cd 100644 --- a/PKHeX.Core/Legality/RNG/Methods/ToxtricityUtil.cs +++ b/PKHeX.Core/Legality/RNG/Methods/ToxtricityUtil.cs @@ -1,13 +1,15 @@ +using System; + namespace PKHeX.Core; public static class ToxtricityUtil { - private static readonly byte[] Nature0 = { 3, 4, 2, 8, 9, 19, 22, 11, 13, 14, 0, 6, 24 }; - private static readonly byte[] Nature1 = { 1, 5, 7, 10, 12, 15, 16, 17, 18, 20, 21, 23 }; + private static ReadOnlySpan Nature0 => new byte[] { 3, 4, 2, 8, 9, 19, 22, 11, 13, 14, 0, 6, 24 }; + private static ReadOnlySpan Nature1 => new byte[] { 1, 5, 7, 10, 12, 15, 16, 17, 18, 20, 21, 23 }; public static byte GetRandomNature(ref Xoroshiro128Plus rand, byte form) { var table = form == 0 ? Nature0 : Nature1; - return table[rand.NextInt((uint)table.Length)]; + return table[(int)rand.NextInt((uint)table.Length)]; } } diff --git a/PKHeX.Core/Legality/RNG/Methods/Wild8bRNG.cs b/PKHeX.Core/Legality/RNG/Methods/Wild8bRNG.cs index 536e10990..3690c2a03 100644 --- a/PKHeX.Core/Legality/RNG/Methods/Wild8bRNG.cs +++ b/PKHeX.Core/Legality/RNG/Methods/Wild8bRNG.cs @@ -48,7 +48,7 @@ public static class Wild8bRNG var fakeTID = xors.NextUInt(); // fakeTID var pid = xors.NextUInt(); pid = GetRevisedPID(fakeTID, pid, pk); - var xor = GetShinyXor(pk.TID, pk.SID, pid); + var xor = GetShinyXor(pk.ID32, pid); var type = GetRareType(xor); if (shiny == Shiny.Never) { @@ -142,10 +142,10 @@ public static class Wild8bRNG return true; } - private static uint GetRevisedPID(uint fakeTID, uint pid, ITrainerID tr) + private static uint GetRevisedPID(uint fakeTID, uint pid, ITrainerID32 tr) { var xor = GetShinyXor(pid, fakeTID); - var newXor = GetShinyXor(pid, (uint)(tr.TID | (tr.SID << 16))); + var newXor = GetShinyXor(pid, tr.ID32); var fakeRare = GetRareType(xor); var newRare = GetRareType(newXor); @@ -155,8 +155,9 @@ public static class Wild8bRNG var isShiny = xor < 16; if (isShiny) - return (((uint)(tr.TID ^ tr.SID) ^ (pid & 0xFFFF) ^ (xor == 0 ? 0u : 1u)) << 16) | (pid & 0xFFFF); // force same shiny star type - return pid ^ 0x1000_0000; + return pid ^ 0x1000_0000; + var low = pid & 0xFFFF; + return (((xor == 0 ? 0u : 1u) ^ tr.TID16 ^ tr.SID16 ^ low) << 16) | low; // force same shiny star type } private static Shiny GetRareType(uint xor) => xor switch @@ -166,14 +167,9 @@ public static class Wild8bRNG _ => Shiny.Never, }; - private static uint GetShinyXor(int tid, int sid, uint pid) + private static uint GetShinyXor(uint pid, uint id32) { - return GetShinyXor(pid, (uint)((sid << 16) | tid)); - } - - private static uint GetShinyXor(uint pid, uint oid) - { - var xor = pid ^ oid; + var xor = pid ^ id32; return (xor ^ (xor >> 16)) & 0xFFFF; } } diff --git a/PKHeX.Core/Legality/RNG/PIDGenerator.cs b/PKHeX.Core/Legality/RNG/PIDGenerator.cs index 0652bb842..3f69582d5 100644 --- a/PKHeX.Core/Legality/RNG/PIDGenerator.cs +++ b/PKHeX.Core/Legality/RNG/PIDGenerator.cs @@ -54,7 +54,7 @@ public static class PIDGenerator if (shiny) { - uint PID = (X & 0xFFFF0000) | ((uint)pk.SID ^ (uint)pk.TID ^ (X >> 16)); + uint PID = (X & 0xFFFF0000) | ((X >> 16) ^ pk.TID16 ^ pk.SID16); PID &= 0xFFFFFFF8; PID |= (B >> 16) & 0x7; // lowest 3 bits @@ -63,7 +63,7 @@ public static class PIDGenerator else if (type is PIDType.BACD_R_AX or PIDType.BACD_U_AX) { uint low = B >> 16; - pk.PID = ((A & 0xFFFF0000) ^ (((uint)pk.TID ^ (uint)pk.SID ^ low) << 16)) | low; + pk.PID = ((A & 0xFFFF0000) ^ ((low ^ pk.TID16 ^ pk.SID16) << 16)) | low; } else { @@ -84,13 +84,13 @@ public static class PIDGenerator switch (pk.Species) { case (int)Species.Umbreon or (int)Species.Eevee: // Colo Umbreon, XD Eevee - pk.TID = (int)((seed = XDRNG.Next(seed)) >> 16); - pk.SID = (int)((seed = XDRNG.Next(seed)) >> 16); + pk.TID16 = (ushort)((seed = XDRNG.Next(seed)) >> 16); + pk.SID16 = (ushort)((seed = XDRNG.Next(seed)) >> 16); seed = XDRNG.Next2(seed); // PID calls consumed break; case (int)Species.Espeon: // Colo Espeon - pk.TID = (int)((seed = XDRNG.Next(seed)) >> 16); - pk.SID = (int)((seed = XDRNG.Next(seed)) >> 16); + pk.TID16 = (ushort)((seed = XDRNG.Next(seed)) >> 16); + pk.SID16 = (ushort)((seed = XDRNG.Next(seed)) >> 16); seed = XDRNG.Next9(seed); // PID calls consumed, skip over Umbreon break; } @@ -116,21 +116,20 @@ public static class PIDGenerator private static void SetValuesFromSeedChannel(PKM pk, uint seed) { - var O = XDRNG.Next(seed); // SID + var O = XDRNG.Next(seed); // SID16 var A = XDRNG.Next(O); // PID var B = XDRNG.Next(A); // PID var C = XDRNG.Next(B); // Held Item var D = XDRNG.Next(C); // Version var E = XDRNG.Next(D); // OT Gender - const int TID = 40122; - var SID = (int)(O >> 16); + const ushort TID16 = 40122; + pk.ID32 = (O & 0xFFFF0000) | TID16; + var SID16 = O >> 16; var pid1 = A >> 16; var pid2 = B >> 16; - pk.TID = TID; - pk.SID = SID; var pid = (pid1 << 16) | pid2; - if ((pid2 > 7 ? 0 : 1) != (pid1 ^ SID ^ TID)) + if ((pid2 > 7 ? 0 : 1) != (pid1 ^ SID16 ^ TID16)) pid ^= 0x80000000; pk.PID = pid; pk.HeldItem = (int)(C >> 31) + 169; // 0-Ganlon, 1-Salac @@ -179,7 +178,7 @@ public static class PIDGenerator return SetValuesFromSeedMG5Shiny; case PIDType.Pokewalker: - return (pk, seed) => pk.PID = GetPokeWalkerPID(pk.TID, pk.SID, seed%24, pk.Gender, pk.PersonalInfo.Gender); + return (pk, seed) => pk.PID = GetPokeWalkerPID(pk.TID16, pk.SID16, seed%24, pk.Gender, pk.PersonalInfo.Gender); // others: unimplemented case PIDType.CuteCharm: @@ -204,7 +203,7 @@ public static class PIDGenerator for (int i = 0; i < 13; i++) lower |= (Next() & 1) << (3 + i); - upper = ((uint)(lower ^ pk.TID ^ pk.SID) & 0xFFF8) | (upper & 0x7); + upper = ((lower ^ pk.TID16 ^ pk.SID16) & 0xFFF8) | (upper & 0x7); pk.PID = (upper << 16) | lower; Span IVs = stackalloc int[6]; MethodFinder.GetIVsInt32(IVs, Next(), Next()); @@ -232,19 +231,19 @@ public static class PIDGenerator } } - public static uint GetMG5ShinyPID(uint gval, uint av, int TID, int SID) + public static uint GetMG5ShinyPID(uint gval, uint av, ushort TID16, ushort SID16) { - uint PID = (uint)(((TID ^ SID ^ gval) << 16) | gval); + uint PID = ((gval ^ TID16 ^ SID16) << 16) | gval; if ((PID & 0x10000) != av << 16) PID ^= 0x10000; return PID; } - public static uint GetPokeWalkerPID(int TID, int SID, uint nature, int gender, int gr) + public static uint GetPokeWalkerPID(ushort TID16, ushort SID16, uint nature, int gender, byte gr) { if (nature >= 24) nature = 0; - uint pid = (uint)(((TID ^ SID) >> 8) ^ 0xFF) << 24; // the most significant byte of the PID is chosen so the Pokémon can never be shiny. + uint pid = ((((uint)TID16 ^ SID16) >> 8) ^ 0xFF) << 24; // the most significant byte of the PID is chosen so the Pokémon can never be shiny. // Ensure nature is set to required nature without affecting shininess pid += nature - (pid % 25); @@ -261,13 +260,13 @@ public static class PIDGenerator if (gender == 0) // Male { - pid += (uint)((((gr - (pid & 0xFF)) / 25) + 1) * 25); + pid += (((gr - (pid & 0xFF)) / 25) + 1) * 25; if ((nature & 1) != (pid & 1)) pid += 25; } else { - pid -= (uint)(((((pid & 0xFF) - gr) / 25) + 1) * 25); + pid -= ((((pid & 0xFF) - gr) / 25) + 1) * 25; if ((nature & 1) != (pid & 1)) pid -= 25; } @@ -278,7 +277,7 @@ public static class PIDGenerator { var gv = seed >> 24; var av = seed & 1; // arbitrary choice - pk.PID = GetMG5ShinyPID(gv, av, pk.TID, pk.SID); + pk.PID = GetMG5ShinyPID(gv, av, pk.TID16, pk.SID16); SetRandomIVs(pk); } @@ -310,7 +309,7 @@ public static class PIDGenerator pk.Gender = gender; do { - pk.PID = GetPokeWalkerPID(pk.TID, pk.SID, (uint) nature, gender, pk.PersonalInfo.Gender); + pk.PID = GetPokeWalkerPID(pk.TID16, pk.SID16, (uint) nature, gender, pk.PersonalInfo.Gender); } while (!pk.IsGenderValid()); pk.RefreshAbility((int) (pk.PID & 1)); @@ -365,7 +364,7 @@ public static class PIDGenerator return specific; if (pk.Version == 15) return PIDType.CXD; - if (pk.Gen3 && pk.Species == (int)Species.Unown) + if (pk is { Species: (int)Species.Unown, Gen3: true }) { return Util.Rand.Next(3) switch { @@ -380,7 +379,7 @@ public static class PIDGenerator private static void SetRandomWildPID5(PKM pk, int nature, int ability, int gender, PIDType specific = PIDType.None) { - var tidbit = (pk.TID ^ pk.SID) & 1; + var tidbit = (pk.TID16 ^ pk.SID16) & 1; pk.RefreshAbility(ability); pk.Gender = gender; pk.Nature = nature; diff --git a/PKHeX.Core/Legality/RNG/PIDType.cs b/PKHeX.Core/Legality/RNG/PIDType.cs index 66b04a11d..b207fae47 100644 --- a/PKHeX.Core/Legality/RNG/PIDType.cs +++ b/PKHeX.Core/Legality/RNG/PIDType.cs @@ -124,9 +124,9 @@ public enum PIDType CXDAnti, /// - /// Generation 3 PID+IV which is created immediately after the TID and SID RNG calls. + /// Generation 3 PID+IV which is created immediately after the TID16 and SID16 RNG calls. /// - /// . The second starter is created after the first starter, with the same TID and SID. + /// . The second starter is created after the first starter, with the same TID16 and SID16. CXD_ColoStarter, /// @@ -158,14 +158,14 @@ public enum PIDType /// /// Generation 5 Mystery Gift Shiny /// - /// Formulaic based on TID, SID, and Gender bytes. + /// Formulaic based on TID16, SID16, and Gender bytes. /// Unrelated to IVs G5MGShiny, /// /// Generation 4 Pokewalker PID, never Shiny. /// - /// Formulaic based on TID, SID, and Gender bytes. + /// Formulaic based on TID16, SID16, and Gender bytes. /// Unrelated to IVs Pokewalker, @@ -187,5 +187,11 @@ public enum PIDType /// Formulaic based on EC value = 32bit-seed. Roaming8b, + /// + /// Generation 9 Tera Raid PID + /// + /// Formulaic based on PID & EC values from a 32bit-seed. + Tera9, + #endregion } diff --git a/PKHeX.Core/Legality/RNG/RaidRNG.cs b/PKHeX.Core/Legality/RNG/RaidRNG.cs index 4973cbfc8..f9f32279b 100644 --- a/PKHeX.Core/Legality/RNG/RaidRNG.cs +++ b/PKHeX.Core/Legality/RNG/RaidRNG.cs @@ -168,12 +168,12 @@ public static class RaidRNG { if (isShiny) { - if (!GetIsShiny(pk.TID, pk.SID, pid)) - pid = GetShinyPID(pk.TID, pk.SID, pid, 0); + if (!GetIsShiny(pk.ID32, pid)) + pid = GetShinyPID(pk.TID16, pk.SID16, pid, 0); } else { - if (GetIsShiny(pk.TID, pk.SID, pid)) + if (GetIsShiny(pk.ID32, pid)) pid ^= 0x1000_0000; } } @@ -200,12 +200,12 @@ public static class RaidRNG if (isShiny) { - if (!GetIsShiny(pk.TID, pk.SID, pid)) - pid = GetShinyPID(pk.TID, pk.SID, pid, 0); + if (!GetIsShiny(pk.ID32, pid)) + pid = GetShinyPID(pk.TID16, pk.SID16, pid, 0); } else { - if (GetIsShiny(pk.TID, pk.SID, pid)) + if (GetIsShiny(pk.ID32, pid)) pid ^= 0x1000_0000; } @@ -268,19 +268,16 @@ public static class RaidRNG return true; } - private static uint GetShinyPID(int tid, int sid, uint pid, int type) + private static uint GetShinyPID(ushort tid, ushort sid, uint pid, uint type) { - return (uint) (((tid ^ sid ^ (pid & 0xFFFF) ^ type) << 16) | (pid & 0xFFFF)); + return (type ^ tid ^ sid ^ (pid & 0xFFFF)) << 16 | (pid & 0xFFFF); } - private static bool GetIsShiny(int tid, int sid, uint pid) - { - return GetShinyXor(pid, (uint) ((sid << 16) | tid)) < 16; - } + private static bool GetIsShiny(uint id32, uint pid) => GetShinyXor(pid, id32) < 16; - private static uint GetShinyXor(uint pid, uint oid) + private static uint GetShinyXor(uint pid, uint id32) { - var xor = pid ^ oid; + var xor = pid ^ id32; return (xor ^ (xor >> 16)) & 0xFFFF; } } diff --git a/PKHeX.Core/Legality/Restrictions/EvolutionRestrictions.cs b/PKHeX.Core/Legality/Restrictions/EvolutionRestrictions.cs index fcb91331c..6e81eaa68 100644 --- a/PKHeX.Core/Legality/Restrictions/EvolutionRestrictions.cs +++ b/PKHeX.Core/Legality/Restrictions/EvolutionRestrictions.cs @@ -76,26 +76,28 @@ internal static class EvolutionRestrictions /// Minimum current level for a given species to have learned the evolve-move and be successfully evolved. /// /// Having a value of 0 means the move can't be learned. - private static readonly byte[][] MinLevelEvolutionWithMove = + private static ReadOnlySpan MinLevelEvolutionWithMove => new byte[] { - new byte[] { 00, 00, 00, 00, 00, 29, 09, 02, 02, 02 }, // Sylveon (Eevee with Fairy Move) - new byte[] { 00, 00, 00, 00, 18, 15, 15, 02, 32, 00 }, // Mr. Mime (Mime Jr with Mimic) - new byte[] { 00, 00, 00, 00, 17, 17, 15, 02, 16, 16 }, // Sudowoodo (Bonsly with Mimic) - new byte[] { 00, 00, 00, 00, 32, 32, 32, 02, 32, 00 }, // Ambipom (Aipom with Double Hit) - new byte[] { 00, 00, 02, 00, 02, 33, 33, 02, 06, 00 }, // Lickilicky (Lickitung with Rollout) - new byte[] { 00, 00, 00, 00, 02, 36, 38, 02, 24, 00 }, // Tangrowth (Tangela with Ancient Power) - new byte[] { 00, 00, 00, 00, 02, 33, 33, 02, 33, 00 }, // Yanmega (Yanma with Ancient Power) - new byte[] { 00, 00, 00, 00, 02, 02, 02, 02, 02, 00 }, // Mamoswine (Piloswine with Ancient Power) - new byte[] { 00, 00, 00, 00, 00, 00, 00, 02, 28, 28 }, // Tsareena (Steenee with Stomp) - new byte[] { 00, 00, 00, 00, 00, 00, 00, 00, 35, 00 }, // Grapploct (Clobbopus with Taunt) - new byte[] { 00, 00, 00, 00, 00, 00, 00, 00, 00, 00 }, // Wyrdeer (Stantler with AGILE Psyshield Bash) - new byte[] { 00, 00, 00, 00, 00, 00, 00, 00, 00, 00 }, // Overqwil (Qwilfish-1 with STRONG Barb Barrage) - new byte[] { 00, 00, 00, 00, 00, 00, 00, 00, 00, 35 }, // Annihilape (Primeape with Rage Fist) - new byte[] { 00, 00, 00, 00, 00, 00, 00, 00, 00, 32 }, // Farigiraf (Girafarig with Twin Beam) - new byte[] { 00, 00, 00, 00, 00, 00, 00, 00, 00, 32 }, // Dudunsparce (Dunsparce with Hyper Drill) + 00, 00, 00, 00, 00, 29, 09, 02, 02, 02, // Sylveon (Eevee with Fairy Move) + 00, 00, 00, 00, 18, 15, 15, 02, 32, 00, // Mr. Mime (Mime Jr with Mimic) + 00, 00, 00, 00, 17, 17, 15, 02, 16, 16, // Sudowoodo (Bonsly with Mimic) + 00, 00, 00, 00, 32, 32, 32, 02, 32, 00, // Ambipom (Aipom with Double Hit) + 00, 00, 02, 00, 02, 33, 33, 02, 06, 00, // Lickilicky (Lickitung with Rollout) + 00, 00, 00, 00, 02, 36, 38, 02, 24, 00, // Tangrowth (Tangela with Ancient Power) + 00, 00, 00, 00, 02, 33, 33, 02, 33, 00, // Yanmega (Yanma with Ancient Power) + 00, 00, 00, 00, 02, 02, 02, 02, 02, 00, // Mamoswine (Piloswine with Ancient Power) + 00, 00, 00, 00, 00, 00, 00, 02, 28, 28, // Tsareena (Steenee with Stomp) + 00, 00, 00, 00, 00, 00, 00, 00, 35, 00, // Grapploct (Clobbopus with Taunt) + 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, // Wyrdeer (Stantler with AGILE Psyshield Bash) + 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, // Overqwil (Qwilfish-1 with STRONG Barb Barrage) + 00, 00, 00, 00, 00, 00, 00, 00, 00, 35, // Annihilape (Primeape with Rage Fist) + 00, 00, 00, 00, 00, 00, 00, 00, 00, 32, // Farigiraf (Girafarig with Twin Beam) + 00, 00, 00, 00, 00, 00, 00, 00, 00, 32, // Dudunsparce (Dunsparce with Hyper Drill) }; - private static readonly byte[] MinLevelEvolutionWithMove_8LA = + private const int MinLevelEvoWidth = 10; + + private static ReadOnlySpan MinLevelEvolutionWithMove_8LA => new byte[] { 00, // Sylveon (Eevee with Fairy Move) 25, // Mr. Mime (Mime Jr with Mimic) @@ -111,23 +113,23 @@ internal static class EvolutionRestrictions 25, // Overqwil (Qwilfish-1 with STRONG Barb Barrage) }; - private static readonly bool[][] CanEggHatchWithEvolveMove = + private static ReadOnlySpan CanEggHatchWithEvolveMove => new byte[] { - new [] { false, false, true, true, true, true, true, true, true, true }, // Sylveon (Eevee with Fairy Move) - new [] { false, false, false, false, true, true, true, true, true, false }, // Mr. Mime (Mime Jr with Mimic) - new [] { false, false, false, false, true, true, true, true, true, true }, // Sudowoodo (Bonsly with Mimic) - new [] { false, false, false, false, true, true, true, true, true, false }, // Ambipom (Aipom with Double Hit) - new [] { false, false, true, false, true, true, true, true, true, false }, // Lickilicky (Lickitung with Rollout) - new [] { false, false, false, false, true, true, true, true, true, false }, // Tangrowth (Tangela with Ancient Power) - new [] { false, false, false, false, true, true, true, true, true, false }, // Yanmega (Yanma with Ancient Power) - new [] { false, false, true, true, true, true, true, true, true, false }, // Mamoswine (Piloswine with Ancient Power) - new [] { false, false, false, false, false, false, false, false, false, false }, // Tsareena (Steenee with Stomp) - new [] { false, false, false, false, false, false, false, false, true, false }, // Grapploct (Clobbopus with Taunt) - new [] { false, false, false, false, false, false, false, false, false, false }, // Wyrdeer (Stantler with AGILE Psyshield Bash) - new [] { false, false, false, false, false, false, false, false, false, false }, // Overqwil (Qwilfish-1 with STRONG Barb Barrage) - new [] { false, false, false, false, false, false, false, false, false, false }, // Annihilape (Primeape with Rage Fist) - new [] { false, false, false, false, false, false, false, false, false, true }, // Farigiraf (Girafarig with Twin Beam) - new [] { false, false, false, false, false, false, false, false, false, true }, // Dudunsparce (Dunsparce with Hyper Drill) + 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, // Sylveon (Eevee with Fairy Move) + 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, // Mr. Mime (Mime Jr with Mimic) + 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, // Sudowoodo (Bonsly with Mimic) + 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, // Ambipom (Aipom with Double Hit) + 0, 0, 1, 0, 1, 1, 1, 1, 1, 0, // Lickilicky (Lickitung with Rollout) + 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, // Tangrowth (Tangela with Ancient Power) + 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, // Yanmega (Yanma with Ancient Power) + 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, // Mamoswine (Piloswine with Ancient Power) + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // Tsareena (Steenee with Stomp) + 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, // Grapploct (Clobbopus with Taunt) + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // Wyrdeer (Stantler with AGILE Psyshield Bash) + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // Overqwil (Qwilfish-1 with STRONG Barb Barrage) + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // Annihilape (Primeape with Rage Fist) + 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, // Farigiraf (Girafarig with Twin Beam) + 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, // Dudunsparce (Dunsparce with Hyper Drill) }; /// @@ -163,7 +165,8 @@ internal static class EvolutionRestrictions var index = entry.ReferenceIndex; if (enc is EncounterEgg) { - if (CanEggHatchWithEvolveMove[index][gen]) + var slice = CanEggHatchWithEvolveMove.Slice(index * MinLevelEvoWidth, MinLevelEvoWidth); + if (slice[gen] != 0) // true { var result = move == 0 ? IsMoveInherited(pk, info, FairyMoves) : IsMoveInherited(pk, info, move); if (result) @@ -207,7 +210,7 @@ internal static class EvolutionRestrictions private static int GetLevelLearnMove(PKM pk, int gen, int index) { // Get the minimum level in any generation when the pokemon could learn the evolve move - var levels = MinLevelEvolutionWithMove[index]; + var levels = MinLevelEvolutionWithMove.Slice(index * MinLevelEvoWidth, MinLevelEvoWidth); var lvl = 101; var end = pk.Format; for (int g = gen; g <= end; g++) diff --git a/PKHeX.Core/Legality/Restrictions/GBRestrictions.cs b/PKHeX.Core/Legality/Restrictions/GBRestrictions.cs index 11f1a08dd..bf43f100b 100644 --- a/PKHeX.Core/Legality/Restrictions/GBRestrictions.cs +++ b/PKHeX.Core/Legality/Restrictions/GBRestrictions.cs @@ -29,7 +29,7 @@ internal static class GBRestrictions /// Checks if the type matches any of the type IDs extracted from the Personal Table used for R/G/B/Y games. /// /// Valid values: 0, 1, 2, 3, 4, 5, 7, 8, 20, 21, 22, 23, 24, 25, 26 - internal static bool TypeIDExists(int type) => (uint)type < 32 && (0b111111100000000000110111111 & (1 << type)) != 0; + internal static bool TypeIDExists(byte type) => type < 32 && (0b111111100000000000110111111 & (1 << type)) != 0; /// /// Species that have a catch rate value that is different from their pre-evolutions, and cannot be obtained directly. @@ -55,13 +55,7 @@ internal static class GBRestrictions (int)Dragonite, }; - internal static readonly HashSet Trade_Evolution1 = new() - { - (int)Kadabra, - (int)Machoke, - (int)Graveler, - (int)Haunter, - }; + internal static bool IsTradeEvolution1(ushort species) => species is (int)Kadabra or (int)Machoke or (int)Graveler or (int)Haunter; public static bool RateMatchesEncounter(ushort species, GameVersion version, byte rate) { @@ -230,16 +224,41 @@ public enum PotentialGBOrigin Gen2Only, } +/// +/// Indicates if the entity has been transferred between Generation 1-2 games via the Time Capsule. +/// public enum TimeCapsuleEvaluation { + /// + /// Transferring via Time Capsule cannot be inferred. + /// Indeterminate, + + /// + /// Indicates that the entity was transferred from Generation 2 to Generation 1. + /// Transferred21, + + /// + /// Indicates that the entity was transferred from Generation 1 to Generation 2, but the catch rate is not a valid tradeback item. + /// Transferred12, + + /// + /// Was not transferred via the Time Capsule. + /// NotTransferred, + + /// + /// Has a catch rate that does not match a held item or the original catch rate value for any progenitor species. + /// BadCatchRate, } public static class TimeCapsuleEvlautationExtensions { + /// + /// Indicates if the definitely transferred via Time Capsule. + /// public static bool WasTimeCapsuleTransferred(this TimeCapsuleEvaluation eval) => eval is not (TimeCapsuleEvaluation.Indeterminate or TimeCapsuleEvaluation.NotTransferred or TimeCapsuleEvaluation.BadCatchRate); } diff --git a/PKHeX.Core/Legality/Restrictions/Locale3DS.cs b/PKHeX.Core/Legality/Restrictions/Locale3DS.cs index e8837ce95..854882fff 100644 --- a/PKHeX.Core/Legality/Restrictions/Locale3DS.cs +++ b/PKHeX.Core/Legality/Restrictions/Locale3DS.cs @@ -1,4 +1,4 @@ -using static PKHeX.Core.LanguageID; +using static PKHeX.Core.LanguageID; namespace PKHeX.Core; @@ -14,7 +14,7 @@ public static class Locale3DS /// Console region. /// Country of nationality /// Country is within Console Region - public static bool IsConsoleRegionCountryValid(int consoleRegion, int country) => consoleRegion switch + public static bool IsConsoleRegionCountryValid(byte consoleRegion, byte country) => consoleRegion switch { 0 => country is 1, // Japan 1 => country is (>= 8 and <= 52) or 153 or 156 or 168 or 174 or 186, // Americas @@ -34,7 +34,7 @@ public static class Locale3DS /// Console region. /// Language of region /// Language is available within Console Region - public static bool IsRegionLockedLanguageValidVC(int consoleRegion, int language) => consoleRegion switch + public static bool IsRegionLockedLanguageValidVC(byte consoleRegion, int language) => consoleRegion switch { 0 or 6 => language == 1, // Japan & Taiwan 1 => language is (int)English or (int)Spanish or (int)French, // Americas @@ -52,7 +52,7 @@ public static class Locale3DS /// Console region. /// Language of region /// Language is available within Console Region - public static bool IsRegionLockedLanguageValid(int consoleRegion, int language) => consoleRegion switch + public static bool IsRegionLockedLanguageValid(byte consoleRegion, int language) => consoleRegion switch { 0 => language is (int)Japanese, // Japan & Taiwan 1 => language is (int)English or (int)Spanish or (int)French, // Americas diff --git a/PKHeX.Core/Legality/Restrictions/Memories/Memories.cs b/PKHeX.Core/Legality/Restrictions/Memories/Memories.cs index 5eb720fae..77fbaa6a9 100644 --- a/PKHeX.Core/Legality/Restrictions/Memories/Memories.cs +++ b/PKHeX.Core/Legality/Restrictions/Memories/Memories.cs @@ -1,3 +1,4 @@ +using System; using System.Collections.Generic; namespace PKHeX.Core; @@ -7,7 +8,7 @@ namespace PKHeX.Core; /// public static class Memories { - private static readonly byte[] ArgTypes = + private static ReadOnlySpan ArgTypes => new byte[] { 0, 1, 1, 1, 1, 5, 2, 3, 0, 3, 0, 0, 4, 3, 3, 5, 4, 3, 3, 1, diff --git a/PKHeX.Core/Legality/Restrictions/Memories/MemoryContext6.cs b/PKHeX.Core/Legality/Restrictions/Memories/MemoryContext6.cs index 8ea22d920..75ea94b7c 100644 --- a/PKHeX.Core/Legality/Restrictions/Memories/MemoryContext6.cs +++ b/PKHeX.Core/Legality/Restrictions/Memories/MemoryContext6.cs @@ -1,3 +1,4 @@ +using System; using System.Collections.Generic; using System.Linq; @@ -10,7 +11,7 @@ public sealed partial class MemoryContext6 : MemoryContext public static readonly MemoryContext6 Instance = new(); private MemoryContext6() { } - private static ICollection GetPokeCenterLocations(GameVersion game) + private static ReadOnlySpan GetPokeCenterLocations(GameVersion game) { return GameVersion.XY.Contains(game) ? LocationsWithPokeCenter_XY : LocationsWithPokeCenter_AO; } diff --git a/PKHeX.Core/Legality/Restrictions/Memories/MemoryContext6Data.cs b/PKHeX.Core/Legality/Restrictions/Memories/MemoryContext6Data.cs index 1c2539e98..abe6a063c 100644 --- a/PKHeX.Core/Legality/Restrictions/Memories/MemoryContext6Data.cs +++ b/PKHeX.Core/Legality/Restrictions/Memories/MemoryContext6Data.cs @@ -1,3 +1,4 @@ +using System; using System.Collections.Generic; namespace PKHeX.Core; @@ -5,7 +6,7 @@ namespace PKHeX.Core; // data tables stored separately! public partial class MemoryContext6 { - private static readonly byte[] Memory_NotXY = + private static ReadOnlySpan Memory_NotXY => new byte[] { 65, // {0} was with {1} when (he/she) built a Secret Base. {4} that {3}. 66, // {0} participated in a contest with {1} and impressed many people. {4} that {3}. @@ -14,7 +15,7 @@ public partial class MemoryContext6 69, // {1} asked {0} to dive. Down it went, deep into the ocean, to explore the bottom of the sea. {4} that {3}. }; - private static readonly byte[] Memory_NotAO = + private static ReadOnlySpan Memory_NotAO => new byte[] { 11, // {0} went clothes shopping with {1}. {4} that {3}. 43, // {0} was impressed by the speed of the train it took with {1}. {4} that {3}. @@ -24,7 +25,7 @@ public partial class MemoryContext6 62, // {0} saw itself in a mirror in a mirror cave that it went to with {1}. {4} that {3}. }; - internal static readonly byte[] MoveSpecificMemoryHM = // Ordered by HM index for bitflag checks. + internal static ReadOnlySpan MoveSpecificMemoryHM => new byte[] // Ordered by HM index for bitflag checks. { 36, // {0} proudly used Cut at {1}’s instruction in... {2}. {4} that {3}. 24, // {0} flew, carrying {1} on its back, to {2}. {4} that {3}. @@ -38,7 +39,7 @@ public partial class MemoryContext6 /// /// Kalos locations with a Pokémon Center /// - private static readonly byte[] LocationsWithPokeCenter_XY = + private static ReadOnlySpan LocationsWithPokeCenter_XY => new byte[] { // Kalos locations with a PKMN CENTER 018, // Santalune City @@ -46,7 +47,7 @@ public partial class MemoryContext6 030, // Camphrier Town 040, // Cyllage City 044, // Ambrette Town - 052, // Geosenge Towny + 052, // Geosenge Town 058, // Shalour City 064, // Coumarine City 070, // Laverre City @@ -60,7 +61,7 @@ public partial class MemoryContext6 /// /// Hoenn locations with a Pokémon Center /// - private static readonly byte[] LocationsWithPokeCenter_AO = + private static ReadOnlySpan LocationsWithPokeCenter_AO => new byte[] { // Hoenn locations with a PKMN CENTER 172, // Oldale Town @@ -81,7 +82,7 @@ public partial class MemoryContext6 202, // Pokémon League (OR/AS) }; - private static readonly byte[] MemoryMinIntensity = + private static ReadOnlySpan MemoryMinIntensity => new byte[] { 0, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, @@ -92,7 +93,7 @@ public partial class MemoryContext6 3, 3, 3, 3, 3, 2, 3, 4, 4, 2, }; - private static readonly byte[] MemoryRandChance = + private static ReadOnlySpan MemoryRandChance => new byte[] { 000, 100, 100, 100, 100, 005, 005, 005, 005, 005, 005, 005, 005, 005, 010, 020, 010, 001, 050, 030, diff --git a/PKHeX.Core/Legality/Restrictions/Memories/MemoryContext8.cs b/PKHeX.Core/Legality/Restrictions/Memories/MemoryContext8.cs index 9d0948f73..233daa825 100644 --- a/PKHeX.Core/Legality/Restrictions/Memories/MemoryContext8.cs +++ b/PKHeX.Core/Legality/Restrictions/Memories/MemoryContext8.cs @@ -1,3 +1,4 @@ +using System; using System.Collections.Generic; using System.Linq; @@ -56,7 +57,7 @@ public sealed partial class MemoryContext8 : MemoryContext private static bool CanObtainMemorySWSH(byte memory) => memory <= MAX_MEMORY_ID_SWSH && !Memory_NotSWSH.Contains(memory); - public override bool CanWinLotoID(int item) => LotoPrizeSWSH.Contains((ushort)item); + public override bool CanWinLotoID(int item) => item < byte.MaxValue && LotoPrizeSWSH.Contains((byte)item); public override bool CanBuyItem(int item, GameVersion version) => item switch { @@ -94,7 +95,7 @@ public sealed partial class MemoryContext8 : MemoryContext private static bool IsWildEncounterMeet(PKM pk, IEncounterTemplate enc) { - if (enc is EncounterTrade or EncounterStatic { Gift: true } or WC8 { IsHOMEGift: false }) + if (enc is EncounterTrade8 or EncounterStatic8 { Gift: true } or WC8 { IsHOMEGift: false }) return true; if (IsCurryEncounter(pk, enc)) return true; @@ -103,7 +104,7 @@ public sealed partial class MemoryContext8 : MemoryContext private static bool IsWildEncounter(PKM pk, IEncounterTemplate enc) { - if (enc is not (EncounterSlot or EncounterStatic { Gift: false })) + if (enc is not (EncounterSlot8 or EncounterStatic { Gift: false } or EncounterStatic8N or EncounterStatic8ND or EncounterStatic8NC or EncounterStatic8U)) return false; if (pk is IRibbonSetMark8 { RibbonMarkCurry: true }) return false; diff --git a/PKHeX.Core/Legality/Restrictions/Memories/MemoryContext8Data.cs b/PKHeX.Core/Legality/Restrictions/Memories/MemoryContext8Data.cs index 49619e109..1374706c6 100644 --- a/PKHeX.Core/Legality/Restrictions/Memories/MemoryContext8Data.cs +++ b/PKHeX.Core/Legality/Restrictions/Memories/MemoryContext8Data.cs @@ -1,10 +1,11 @@ +using System; using System.Collections.Generic; namespace PKHeX.Core; public partial class MemoryContext8 { - private static readonly byte[] Memory_NotSWSH = + private static ReadOnlySpan Memory_NotSWSH => new byte[] { 10, // {0} got treats from {1}. {4} that {3}. 17, // {0} battled at {1}’s side and beat {2}. {4} that {3}. @@ -69,7 +70,7 @@ public partial class MemoryContext8 1260, 1261, 1262, 1263, }; - private static readonly ushort[] LotoPrizeSWSH = + private static ReadOnlySpan LotoPrizeSWSH => new byte[] { 0001, 0033, 0050, 0051, 0053, }; @@ -253,7 +254,7 @@ public partial class MemoryContext8 71, 72, 73, 74, 75, 76, 77, 78, 79, }; - private static readonly byte[] MemoryMinIntensity = + private static ReadOnlySpan MemoryMinIntensity => new byte[] { 0, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, @@ -267,23 +268,23 @@ public partial class MemoryContext8 }; #if FALSE - // [0,99]+1 >= CHANCE -> abort - // this silly +1 causes: - // 100% memories to fail 1% of the time - // 1% memories to fail 100% of the time (!!!) - // swsh v1.3 sub_71013B0C40 - private static readonly byte[] MemoryRandChance = - { - 000, 100, 100, 100, 100, 005, 005, 005, 005, 005, - 005, 005, 005, 005, 010, 020, 010, 001, 050, 030, - 005, 005, 020, 005, 005, 005, 001, 050, 100, 050, - 050, 002, 002, 005, 005, 005, 005, 005, 005, 002, - 020, 020, 005, 010, 001, 001, 050, 030, 020, 020, - 010, 010, 001, 010, 001, 050, 030, 030, 030, 002, - 050, 020, 020, 020, 020, 010, 010, 050, 020, 005, // same as Gen6 - 005, 010, 010, 020, 020, 010, 100, 010, 005, 010, - 010, 010, 010, 010, 010, 010, 010, 001, 001, 001, - }; + // [0,99]+1 >= CHANCE -> abort + // this silly +1 causes: + // 100% memories to fail 1% of the time + // 1% memories to fail 100% of the time (!!!) + // SW/SH v1.3 sub_71013B0C40 + private static ReadOnlySpan MemoryRandChance => new byte[] + { + 000, 100, 100, 100, 100, 005, 005, 005, 005, 005, + 005, 005, 005, 005, 010, 020, 010, 001, 050, 030, + 005, 005, 020, 005, 005, 005, 001, 050, 100, 050, + 050, 002, 002, 005, 005, 005, 005, 005, 005, 002, + 020, 020, 005, 010, 001, 001, 050, 030, 020, 020, + 010, 010, 001, 010, 001, 050, 030, 030, 030, 002, + 050, 020, 020, 020, 020, 010, 010, 050, 020, 005, // same as Gen6 + 005, 010, 010, 020, 020, 010, 100, 010, 005, 010, + 010, 010, 010, 010, 010, 010, 010, 001, 001, 001, + }; #endif /// diff --git a/PKHeX.Core/Legality/Restrictions/Memories/MemoryPermissions.cs b/PKHeX.Core/Legality/Restrictions/Memories/MemoryPermissions.cs index 72ac54010..e4e56af16 100644 --- a/PKHeX.Core/Legality/Restrictions/Memories/MemoryPermissions.cs +++ b/PKHeX.Core/Legality/Restrictions/Memories/MemoryPermissions.cs @@ -152,7 +152,7 @@ public static class MemoryPermissions private static bool GetCanKnowMove(PKM pk, ushort move, EntityContext context, EvolutionHistory history, IEncounterTemplate enc) { if (pk.Species == (int)Smeargle) - return MoveInfo.IsValidSketch(move, context); + return MoveInfo.IsSketchValid(move, context); ILearnGroup game; if (context == EntityContext.Gen6) diff --git a/PKHeX.Core/Legality/Restrictions/Vivillon3DS.cs b/PKHeX.Core/Legality/Restrictions/Vivillon3DS.cs index 5c5dffb30..2aa03ef19 100644 --- a/PKHeX.Core/Legality/Restrictions/Vivillon3DS.cs +++ b/PKHeX.Core/Legality/Restrictions/Vivillon3DS.cs @@ -8,7 +8,7 @@ namespace PKHeX.Core; /// public static class Vivillon3DS { - public const int MaxWildFormID = 17; // 0-17 valid form indexes + public const byte MaxWildFormID = 17; // 0-17 valid form indexes private sealed class CountryTable { @@ -61,7 +61,7 @@ public static class Vivillon3DS /*17 Jungle */ Region3DSFlags.Americas | Region3DSFlags.Europe, }; - private static Region3DSFlags GetConsoleRegionFlag(int consoleRegion) => (Region3DSFlags)(1 << consoleRegion); + private static Region3DSFlags GetConsoleRegionFlag(byte consoleRegion) => (Region3DSFlags)(1 << consoleRegion); /// /// List of valid countries for each Vivillon form. @@ -209,9 +209,9 @@ public static class Vivillon3DS /// /// Compares the Vivillon pattern against its console region to determine if the pattern is legal. /// - public static bool IsPatternValid(byte form, int consoleRegion) + public static bool IsPatternValid(byte form, byte consoleRegion) { - if ((uint)form > MaxWildFormID) + if (form > MaxWildFormID) return false; var permit = GetConsoleRegionFlag(consoleRegion); return VivillonRegionTable[form].HasFlag(permit); @@ -226,7 +226,7 @@ public static class Vivillon3DS /// True if valid public static bool IsPatternNative(byte form, byte country, byte region) { - if ((uint)form > MaxWildFormID) + if (form > MaxWildFormID) return false; if (!VivillonCountryTable[form].Contains(country)) return false; // Country mismatch @@ -273,7 +273,7 @@ public static class Vivillon3DS /// /// Not to be confused with . [Flags] - private enum Region3DSFlags : ushort + private enum Region3DSFlags : byte { None, Japan = 1, diff --git a/PKHeX.Core/Legality/Restrictions/WordFilter.cs b/PKHeX.Core/Legality/Restrictions/WordFilter.cs index 4b60471cc..898ae7d00 100644 --- a/PKHeX.Core/Legality/Restrictions/WordFilter.cs +++ b/PKHeX.Core/Legality/Restrictions/WordFilter.cs @@ -1,4 +1,6 @@ -using System.Collections.Generic; +using System; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; using System.Text.RegularExpressions; namespace PKHeX.Core; @@ -25,12 +27,30 @@ public static class WordFilter return result; } + /// + /// Checks to see if a phrase contains filtered content. + /// + /// Phrase to check for + /// Matching regex that filters the phrase. + /// Boolean result if the message is filtered or not. + public static bool TryMatch(ReadOnlySpan message, [NotNullWhen(true)] out string? regMatch) + { + foreach (var regex in Regexes) + { + foreach (var _ in regex.EnumerateMatches(message)) + { + regMatch = regex.ToString(); + return true; + } + } + regMatch = null; + return false; + } + /// /// Due to some messages repeating (Trainer names), keep a list of repeated values for faster lookup. /// - private static readonly Dictionary Lookup = new(INIT_COUNT); - - private const string NoMatch = ""; + private static readonly Dictionary Lookup = new(INIT_COUNT); /// /// Checks to see if a phrase contains filtered content. @@ -38,32 +58,31 @@ public static class WordFilter /// Phrase to check for /// Matching regex that filters the phrase. /// Boolean result if the message is filtered or not. - public static bool IsFiltered(string message, out string regMatch) + public static bool IsFiltered(string message, [NotNullWhen(true)] out string? regMatch) { if (string.IsNullOrWhiteSpace(message) || message.Length <= 1) { - regMatch = NoMatch; + regMatch = null; return false; } - var msg = message.ToLowerInvariant(); // Check dictionary lock (dictLock) { - if (Lookup.TryGetValue(msg, out regMatch)) - return !ReferenceEquals(regMatch, NoMatch); + if (Lookup.TryGetValue(message, out regMatch)) + return regMatch != null; } - // not in dictionary, check patterns - foreach (var regex in Regexes) - { - if (!regex.IsMatch(msg)) - continue; + // Make the string lowercase invariant + Span lowercase = stackalloc char[message.Length]; + for (int i = 0; i < lowercase.Length; i++) + lowercase[i] = char.ToLowerInvariant(message[i]); - // match found, cache result - regMatch = regex.ToString(); // fetches from regex field + // not in dictionary, check patterns + if (TryMatch(lowercase, out regMatch)) + { lock (dictLock) - Lookup[msg] = regMatch; + Lookup[message] = regMatch; return true; } @@ -72,7 +91,7 @@ public static class WordFilter { if ((Lookup.Count & ~MAX_COUNT) != 0) Lookup.Clear(); // reset - Lookup[msg] = regMatch = NoMatch; + Lookup[message] = regMatch = null; } return false; } diff --git a/PKHeX.Core/Legality/Structures/IMasteryInitialMoveShop8.cs b/PKHeX.Core/Legality/Structures/IMasteryInitialMoveShop8.cs index 38e0d5bd8..ae5cc92bf 100644 --- a/PKHeX.Core/Legality/Structures/IMasteryInitialMoveShop8.cs +++ b/PKHeX.Core/Legality/Structures/IMasteryInitialMoveShop8.cs @@ -10,18 +10,14 @@ public interface IMasteryInitialMoveShop8 (Learnset Learn, Learnset Mastery) GetLevelUpInfo(); void LoadInitialMoveset(PA8 pa8, Span moves, Learnset learn, int level); bool IsForcedMasteryCorrect(PKM pk); -} - -public static class MasteryInitialMoveShop8Extensions -{ - public static void SetInitialMastery(this IMasteryInitialMoveShop8 enc, PKM pk) + void SetInitialMastery(PKM pk) { if (pk is PA8 pa8) { Span moves = stackalloc ushort[4]; var level = pa8.Met_Level; - var (learn, mastery) = enc.GetLevelUpInfo(); - enc.LoadInitialMoveset(pa8, moves, learn, level); + var (learn, mastery) = GetLevelUpInfo(); + LoadInitialMoveset(pa8, moves, learn, level); pa8.SetEncounterMasteryFlags(moves, mastery, level); } } diff --git a/PKHeX.Core/Legality/Structures/ITrainerInfo.cs b/PKHeX.Core/Legality/Structures/ITrainerInfo.cs index d8ed51b98..4126af1dc 100644 --- a/PKHeX.Core/Legality/Structures/ITrainerInfo.cs +++ b/PKHeX.Core/Legality/Structures/ITrainerInfo.cs @@ -3,7 +3,7 @@ namespace PKHeX.Core; /// /// Minimal Trainer Information necessary for generating a . /// -public interface ITrainerInfo : ITrainerID +public interface ITrainerInfo : ITrainerID32 { string OT { get; } int Gender { get; } @@ -19,8 +19,8 @@ public static class TrainerInfoExtensions public static void ApplyTo(this ITrainerInfo info, PKM pk) { pk.OT_Name = info.OT; - pk.TID = info.TID; - pk.SID = pk.Format < 3 || pk.VC ? 0 : info.SID; + pk.TID16 = info.TID16; + pk.SID16 = pk.Format < 3 || pk.VC ? (ushort)0 : info.SID16; pk.OT_Gender = info.Gender; pk.Language = info.Language; pk.Version = info.Game; @@ -59,27 +59,64 @@ public static class TrainerInfoExtensions public static bool IsFromTrainer(this ITrainerInfo tr, PKM pk) { + if (pk.IsEgg) + return tr.IsFromTrainerEgg(pk); + if (tr.Game == (int)GameVersion.Any) return true; - if (tr.TID != pk.TID) - return false; - if (tr.OT != pk.OT_Name) - return false; - if (pk.Format <= 2) - return false; - - if (tr.SID != pk.SID) - return false; - if (pk.Format == 3) - return false; - - if (tr.Gender != pk.OT_Gender) + if (!IsFromTrainerNoVersion(tr, pk)) return false; return IsMatchVersion(tr, pk); } + public static bool IsFromTrainerNoVersion(ITrainerInfo tr, PKM pk) + { + if (tr.ID32 != pk.ID32) + return false; + if (tr.OT != pk.OT_Name) + return false; + + if (pk.Format == 3) + return true; // Generation 3 does not check ot gender nor pokemon version + + if (tr.Gender != pk.OT_Gender) + { + if (pk.Format == 2) + return pk is ICaughtData2 { CaughtData: 0 }; + return false; + } + return true; + } + + /// + /// Only call this if it is still an egg. + /// + public static bool IsFromTrainerEgg(this ITrainerInfo tr, PKM pk) + { + System.Diagnostics.Debug.Assert(pk.IsEgg); + + if (tr.Context != pk.Context) + return false; + if (tr.ID32 != pk.ID32) + return false; + if (tr.Gender != pk.OT_Gender) + return false; + + if (tr.Game != pk.Version) + { + // PK9 does not store version for Picnic eggs. + if (pk is PK9 { Version: 0 }) { } + else { return false; } + } + + if (tr.OT != pk.OT_Name) + return false; + + return true; + } + private static bool IsMatchVersion(ITrainerInfo tr, PKM pk) { if (tr.Game == pk.Version) diff --git a/PKHeX.Core/Legality/Structures/Moveset.cs b/PKHeX.Core/Legality/Structures/Moveset.cs index 72a9d03b6..5964a95ba 100644 --- a/PKHeX.Core/Legality/Structures/Moveset.cs +++ b/PKHeX.Core/Legality/Structures/Moveset.cs @@ -74,7 +74,7 @@ public readonly record struct Moveset(ushort Move1, ushort Move2 = 0, ushort Mov return flags; } - public static int BitOverlap(Span moves, Span span) + public static int BitOverlap(ReadOnlySpan moves, ReadOnlySpan span) { // Flag each present index; having all moves will have all bitflags. int flags = 0; diff --git a/PKHeX.Core/Legality/Structures/SimpleTrainerInfo.cs b/PKHeX.Core/Legality/Structures/SimpleTrainerInfo.cs index 3a494bf1e..f3341ec8a 100644 --- a/PKHeX.Core/Legality/Structures/SimpleTrainerInfo.cs +++ b/PKHeX.Core/Legality/Structures/SimpleTrainerInfo.cs @@ -6,10 +6,12 @@ namespace PKHeX.Core; public sealed record SimpleTrainerInfo : ITrainerInfo, IRegionOrigin { public string OT { get; set; } = "PKHeX"; - public int TID { get; set; } = 12345; - public int SID { get; set; } = 54321; + public ushort TID16 { get; set; } = 12345; + public ushort SID16 { get; set; } = 54321; public int Gender { get; set; } public int Language { get; set; } = (int)LanguageID.English; + public uint ID32 { get => (uint)(TID16 | (SID16 << 16)); set => (TID16, SID16) = ((ushort)value, (ushort)(value >> 16)); } + public TrainerIDFormat TrainerIDDisplayFormat => this.GetTrainerIDFormat(); // IRegionOrigin for generation 6/7 public byte ConsoleRegion { get; set; } = 1; // North America @@ -35,8 +37,8 @@ public sealed record SimpleTrainerInfo : ITrainerInfo, IRegionOrigin public SimpleTrainerInfo(ITrainerInfo other) : this((GameVersion)other.Game) { OT = other.OT; - TID = other.TID; - SID = other.SID; + TID16 = other.TID16; + SID16 = other.SID16; Gender = other.Gender; Language = other.Language; Generation = other.Generation; diff --git a/PKHeX.Core/Legality/Tables/Tables.cs b/PKHeX.Core/Legality/Tables/Tables.cs index e54a34aae..ac837822c 100644 --- a/PKHeX.Core/Legality/Tables/Tables.cs +++ b/PKHeX.Core/Legality/Tables/Tables.cs @@ -41,17 +41,17 @@ public static partial class Legal /// /// Species classified as "Legend" by the game code. /// + /// Previous games may have included Mythicals in this species list, but that list should be considered separately. public static readonly HashSet Legends = new() { - (int)Mewtwo, (int)Mew, - (int)Lugia, (int)HoOh, (int)Celebi, - (int)Kyogre, (int)Groudon, (int)Rayquaza, (int)Jirachi, (int)Deoxys, - (int)Dialga, (int)Palkia, (int)Giratina, (int)Phione, (int)Manaphy, (int)Darkrai, (int)Shaymin, (int)Arceus, - (int)Victini, (int)Reshiram, (int)Zekrom, (int)Kyurem, (int)Keldeo, (int)Meloetta, (int)Genesect, - (int)Xerneas, (int)Yveltal, (int)Zygarde, (int)Diancie, (int)Hoopa, (int)Volcanion, - (int)Cosmog, (int)Cosmoem, (int)Solgaleo, (int)Lunala, (int)Necrozma, (int)Magearna, (int)Marshadow, (int)Zeraora, - (int)Meltan, (int)Melmetal, - (int)Zacian, (int)Zamazenta, (int)Eternatus, (int)Zarude, (int)Calyrex, + (int)Mewtwo, + (int)Lugia, (int)HoOh, + (int)Kyogre, (int)Groudon, (int)Rayquaza, + (int)Dialga, (int)Palkia, (int)Giratina, + (int)Reshiram, (int)Zekrom, (int)Kyurem, + (int)Xerneas, (int)Yveltal, (int)Zygarde, + (int)Cosmog, (int)Cosmoem, (int)Solgaleo, (int)Lunala, (int)Necrozma, + (int)Zacian, (int)Zamazenta, (int)Eternatus, (int)Calyrex, (int)Koraidon, (int)Miraidon, }; @@ -66,12 +66,22 @@ public static partial class Legal (int)Uxie, (int)Mesprit, (int)Azelf, (int)Heatran, (int)Regigigas, (int)Cresselia, (int)Cobalion, (int)Terrakion, (int)Virizion, (int)Tornadus, (int)Thundurus, (int)Landorus, (int)TypeNull, (int)Silvally, (int)TapuKoko, (int)TapuLele, (int)TapuBulu, (int)TapuFini, - (int)Nihilego, (int)Buzzwole, (int)Pheromosa, (int)Xurkitree, (int)Celesteela, (int)Kartana, (int)Guzzlord, - (int)Poipole, (int)Naganadel, (int)Stakataka, (int)Blacephalon, (int)Kubfu, (int)Urshifu, (int)Regieleki, (int)Regidrago, (int)Glastrier, (int)Spectrier, (int)Enamorus, (int)TingLu, (int)ChienPao, (int)WoChien, (int)ChiYu, }; + /// + /// Checks if the is an Ultra Beast Pokémon. + /// + public static bool IsUltraBeast(ushort species) => species is + (int)Nihilego or (int)Buzzwole or (int)Pheromosa or (int)Xurkitree or (int)Celesteela or (int)Kartana or (int)Guzzlord or + (int)Poipole or (int)Naganadel or (int)Stakataka or (int)Blacephalon; + + /// + /// Checks if the is a Paradox Pokémon. + /// + public static bool IsParadox(ushort species) => species is (>= (int)GreatTusk and <= (int)IronThorns) or (int)RoaringMoon or (int)IronValiant; + /// /// Species that evolve from a Bi-Gendered species into a Single-Gender. /// diff --git a/PKHeX.Core/Legality/Tables/Tables1.cs b/PKHeX.Core/Legality/Tables/Tables1.cs index 925fee920..a3090a6db 100644 --- a/PKHeX.Core/Legality/Tables/Tables1.cs +++ b/PKHeX.Core/Legality/Tables/Tables1.cs @@ -1,5 +1,3 @@ -using static PKHeX.Core.Species; - namespace PKHeX.Core; public static partial class Legal @@ -25,12 +23,4 @@ public static partial class Legal 224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239, 240,241,242,243,244,245,246,247,248,249,250, }; - - internal static bool TransferSpeciesDefaultAbilityGen1(ushort species) - { - System.Diagnostics.Debug.Assert((uint)species <= MaxSpeciesID_1); - return species is (int)Gastly or (int)Haunter or (int)Gengar - or (int)Koffing or (int)Weezing - or (int)Mew; - } } diff --git a/PKHeX.Core/Legality/Tables/Tables2.cs b/PKHeX.Core/Legality/Tables/Tables2.cs index 2503c3e78..ae9d4182d 100644 --- a/PKHeX.Core/Legality/Tables/Tables2.cs +++ b/PKHeX.Core/Legality/Tables/Tables2.cs @@ -1,5 +1,3 @@ -using static PKHeX.Core.Species; - namespace PKHeX.Core; public static partial class Legal @@ -30,13 +28,4 @@ public static partial class Legal internal static readonly ushort[] HeldItems_GSC = ArrayUtil.ConcatAll(Pouch_Items_GSC, Pouch_Ball_GSC, Pouch_TMHM_GSC); internal static readonly bool[] ReleasedHeldItems_2 = GetPermitList(MaxItemID_2, HeldItems_GSC); - - internal static bool TransferSpeciesDefaultAbilityGen2(ushort species) - { - System.Diagnostics.Debug.Assert((uint)species <= MaxSpeciesID_2); - return species is (int)Gastly or (int)Haunter or (int)Gengar - or (int)Koffing or (int)Weezing - or (int)Misdreavus or (int)Unown - or (int)Mew or (int)Celebi; - } } diff --git a/PKHeX.Core/Legality/Tables/Tables5.cs b/PKHeX.Core/Legality/Tables/Tables5.cs index 11ad36a03..375ff450f 100644 --- a/PKHeX.Core/Legality/Tables/Tables5.cs +++ b/PKHeX.Core/Legality/Tables/Tables5.cs @@ -77,18 +77,19 @@ public static partial class Legal internal static readonly HashSet ValidMet_B2W2 = new() { - 004, 005, 006, 007, 008, 009, + 004, 005, 006, 007, 008, 009, 010, 011, 012, 013, 014, 015, 016, 017, 018, 019, 020, 021, 022, 024, 025, 026, 027, 028, 029, // 023 Route 10 030, 031, 032, 033, 034, 035, 036, 037, 038, 039, 041, 042, 043, 044, 045, 046, 047, 048, 049, // 040->134 Victory Road 050, 051, 052, 053, 054, 055, 056, 057, 058, // 059 Challenger's cave 060, 061, 062, 063, 064, 065, 066, 067, 068, 069, - 070, 071, 072, 073, 074, 075, 076, 077, 078, 079, + 070, 071, 072, 074, 075, 076, 077, 078, 079, // 073 Trial Chamber 080, 081, 082, 083, 084, 085, 086, 087, 088, 089, 090, 091, 092, 093, 094, 095, 096, 097, 098, 099, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, - 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, + 110, 111, 112, 113, 114, 115, 116, + 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 139, // 138 --- 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, diff --git a/PKHeX.Core/Legality/Tables/Tables6.cs b/PKHeX.Core/Legality/Tables/Tables6.cs index fb0bfcc9f..afe6ccb0c 100644 --- a/PKHeX.Core/Legality/Tables/Tables6.cs +++ b/PKHeX.Core/Legality/Tables/Tables6.cs @@ -146,9 +146,6 @@ public static partial class Legal internal static readonly ushort[] HeldItem_AO = ArrayUtil.ConcatAll(Pouch_Items_AO, Pouch_Medicine_AO, Pouch_Berry_XY); #endregion - #region TMHM - - #endregion internal static readonly HashSet ValidMet_XY = new() { diff --git a/PKHeX.Core/Legality/Tables/Tables8a.cs b/PKHeX.Core/Legality/Tables/Tables8a.cs index 6a017a5be..b9f608744 100644 --- a/PKHeX.Core/Legality/Tables/Tables8a.cs +++ b/PKHeX.Core/Legality/Tables/Tables8a.cs @@ -68,73 +68,4 @@ public static partial class Legal 1805, 1806, 1807, 1828, }; - - #region Moves - - internal static readonly ushort[] MoveShop8_LA = - { - (int)Move.FalseSwipe, - (int)Move.FireFang, - (int)Move.ThunderFang, - (int)Move.IceFang, - (int)Move.IceBall, - (int)Move.RockSmash, - (int)Move.Spikes, - (int)Move.Bulldoze, - (int)Move.AerialAce, - (int)Move.StealthRock, - (int)Move.Swift, - (int)Move.TriAttack, - (int)Move.MagicalLeaf, - (int)Move.OminousWind, - (int)Move.PowerShift, - (int)Move.FocusEnergy, - (int)Move.BulkUp, - (int)Move.CalmMind, - (int)Move.Rest, - (int)Move.BabyDollEyes, - (int)Move.FirePunch, - (int)Move.ThunderPunch, - (int)Move.IcePunch, - (int)Move.DrainPunch, - (int)Move.PoisonJab, - (int)Move.PsychoCut, - (int)Move.ZenHeadbutt, - (int)Move.LeechLife, - (int)Move.XScissor, - (int)Move.RockSlide, - (int)Move.ShadowClaw, - (int)Move.IronHead, - (int)Move.IronTail, - (int)Move.MysticalFire, - (int)Move.WaterPulse, - (int)Move.ChargeBeam, - (int)Move.EnergyBall, - (int)Move.IcyWind, - (int)Move.SludgeBomb, - (int)Move.EarthPower, - (int)Move.ShadowBall, - (int)Move.Snarl, - (int)Move.FlashCannon, - (int)Move.DazzlingGleam, - (int)Move.GigaImpact, - (int)Move.AquaTail, - (int)Move.WildCharge, - (int)Move.HighHorsepower, - (int)Move.Megahorn, - (int)Move.StoneEdge, - (int)Move.Outrage, - (int)Move.PlayRough, - (int)Move.HyperBeam, - (int)Move.Flamethrower, - (int)Move.Thunderbolt, - (int)Move.IceBeam, - (int)Move.Psychic, - (int)Move.DarkPulse, - (int)Move.DracoMeteor, - (int)Move.SteelBeam, - (int)Move.VoltTackle, - }; - - #endregion } diff --git a/PKHeX.Core/Legality/Tables/Tables9.cs b/PKHeX.Core/Legality/Tables/Tables9.cs index 1a6ee5944..e9f14a6ab 100644 --- a/PKHeX.Core/Legality/Tables/Tables9.cs +++ b/PKHeX.Core/Legality/Tables/Tables9.cs @@ -4,7 +4,7 @@ namespace PKHeX.Core; public static partial class Legal { - internal const int MaxSpeciesID_9 = (int)Species.Annihilape; + internal const int MaxSpeciesID_9 = (int)Species.Miraidon; internal const int MaxMoveID_9 = (int)Move.MagicalTorque; internal const int MaxItemID_9 = 2400; // Yellow Dish internal const int MaxAbilityID_9 = (int)Ability.MyceliumMight; diff --git a/PKHeX.Core/Legality/Verifiers/AwakenedValueVerifier.cs b/PKHeX.Core/Legality/Verifiers/AwakenedValueVerifier.cs index e9acd7971..f6f02228c 100644 --- a/PKHeX.Core/Legality/Verifiers/AwakenedValueVerifier.cs +++ b/PKHeX.Core/Legality/Verifiers/AwakenedValueVerifier.cs @@ -19,7 +19,7 @@ public sealed class AwakenedValueVerifier : Verifier data.AddLine(GetInvalid(LegalityCheckStrings.LAwakenedCap)); Span required = stackalloc byte[6]; - AwakeningUtil.GetExpectedMinimumAVs(required, pb7); + AwakeningUtil.SetExpectedMinimumAVs(required, pb7); Span current = stackalloc byte[6]; AwakeningUtil.AwakeningGetVisual(pb7, current); diff --git a/PKHeX.Core/Legality/Verifiers/Ball/BallVerifier.cs b/PKHeX.Core/Legality/Verifiers/Ball/BallVerifier.cs index 09c8133a2..8f2440c92 100644 --- a/PKHeX.Core/Legality/Verifiers/Ball/BallVerifier.cs +++ b/PKHeX.Core/Legality/Verifiers/Ball/BallVerifier.cs @@ -59,14 +59,14 @@ public sealed class BallVerifier : Verifier // Only a Gen3 origin Shedinja can copy the wild ball. // Evolution chains will indicate if it could have existed as Shedinja in Gen3. // The special move verifier has a similar check! - if (pk.HGSS && pk.Ball == (int)Sport) // Can evolve in DP to retain the HG/SS ball (separate byte) -- not able to be captured in any other ball + if (pk is { HGSS: true, Ball: (int)Sport }) // Can evolve in DP to retain the HG/SS ball (separate byte) -- not able to be captured in any other ball return VerifyBallEquals(data, (int)Sport); if (Info.Generation != 3 || Info.EvoChainsAllGens.Gen3.Length != 2) // not evolved in Gen3 Nincada->Shedinja return VerifyBallEquals(data, (int)Poke); // Poké ball Only } // Capturing with Heavy Ball is impossible in Sun/Moon for specific species. - if (pk.Ball == (int)Heavy && pk.SM && enc is not EncounterEgg && BallBreedLegality.AlolanCaptureNoHeavyBall.Contains(enc.Species)) + if (pk is { Ball: (int)Heavy, SM: true } && enc is not EncounterEgg && BallBreedLegality.AlolanCaptureNoHeavyBall.Contains(enc.Species)) return GetInvalid(LBallHeavy); // Heavy Ball, can inherit if from egg (US/UM fixed catch rate calc) return enc switch @@ -79,16 +79,16 @@ public sealed class BallVerifier : Verifier }; } - private CheckResult VerifyBallMysteryGift(LegalityAnalysis data, MysteryGift g) + private CheckResult VerifyBallMysteryGift(LegalityAnalysis data, MysteryGift gift) { - if (g.Generation == 4 && g.Species == (int)Species.Manaphy && g.Ball == 0) // there is no ball data in Manaphy PGT Mystery Gift from Gen4 + if (gift is { Generation: 4, Species: (int)Species.Manaphy, Ball: 0 }) // there is no ball data in Manaphy PGT Mystery Gift from Gen4 return VerifyBallEquals(data, (int)Poke); // Pokeball - return VerifyBallEquals(data, g.Ball); + return VerifyBallEquals(data, gift.Ball); } private CheckResult VerifyBallStatic(LegalityAnalysis data, EncounterStatic s) { - if (s.Location == 75 && s.Generation == 5) // Entree Forest (Dream World) + if (s is EncounterStatic5 { EntreeForestDreamWorld: true }) return VerifyBallEquals(data, BallUseLegality.DreamWorldBalls); return VerifyBallEquals(data, BallUseLegality.GetWildBalls(data.Info.Generation, s.Version)); } diff --git a/PKHeX.Core/Legality/Verifiers/CXDVerifier.cs b/PKHeX.Core/Legality/Verifiers/CXDVerifier.cs index ea62a7ca3..bb29badfd 100644 --- a/PKHeX.Core/Legality/Verifiers/CXDVerifier.cs +++ b/PKHeX.Core/Legality/Verifiers/CXDVerifier.cs @@ -14,9 +14,6 @@ public sealed class CXDVerifier : Verifier var pk = data.Entity; if (data.EncounterMatch is EncounterStatic3 s3) VerifyCXDStarterCorrelation(data, s3); - else if (pk.Egg_Location != 0 && pk is not PB8 {Egg_Location: Locations.Default8bNone}) // can't obtain eggs in CXD - data.AddLine(GetInvalid(LEncInvalid, CheckIdentifier.Encounter)); // invalid encounter - if (pk.OT_Gender == 1) data.AddLine(GetInvalid(LG3OTGender, CheckIdentifier.Trainer)); } @@ -43,8 +40,8 @@ public sealed class CXDVerifier : Verifier } else { - valid = LockFinder.IsXDStarterValid(seed, pk.TID, pk.SID); - if (valid) // unroll seed to origin that generated TID/SID->pkm + valid = LockFinder.IsXDStarterValid(seed, pk.TID16, pk.SID16); + if (valid) // unroll seed to origin that generated TID16/SID16->pkm data.Info.PIDIV = new PIDIV(PIDType.CXD, XDRNG.Prev4(seed)); } } diff --git a/PKHeX.Core/Legality/Verifiers/ConsoleRegionVerifier.cs b/PKHeX.Core/Legality/Verifiers/ConsoleRegionVerifier.cs index b73a83789..db464fe57 100644 --- a/PKHeX.Core/Legality/Verifiers/ConsoleRegionVerifier.cs +++ b/PKHeX.Core/Legality/Verifiers/ConsoleRegionVerifier.cs @@ -1,4 +1,4 @@ -using static PKHeX.Core.LegalityCheckStrings; +using static PKHeX.Core.LegalityCheckStrings; namespace PKHeX.Core; @@ -19,14 +19,14 @@ public sealed class ConsoleRegionVerifier : Verifier private CheckResult VerifyConsoleRegion(IRegionOrigin pk) { - int consoleRegion = pk.ConsoleRegion; + var consoleRegion = pk.ConsoleRegion; if (consoleRegion >= 7) return GetInvalid(LGeoHardwareRange); return Verify3DSDataPresent(pk, consoleRegion); } - private CheckResult Verify3DSDataPresent(IRegionOrigin pk, int consoleRegion) + private CheckResult Verify3DSDataPresent(IRegionOrigin pk, byte consoleRegion) { if (!Locale3DS.IsConsoleRegionCountryValid(consoleRegion, pk.Country)) return GetInvalid(LGeoHardwareInvalid); diff --git a/PKHeX.Core/Legality/Verifiers/ContestStatVerifier.cs b/PKHeX.Core/Legality/Verifiers/ContestStatVerifier.cs index 7a9615123..3ca4d44e0 100644 --- a/PKHeX.Core/Legality/Verifiers/ContestStatVerifier.cs +++ b/PKHeX.Core/Legality/Verifiers/ContestStatVerifier.cs @@ -22,8 +22,8 @@ public sealed class ContestStatVerifier : Verifier return; // Check the correlation of Stats & Sheen! - // In generations 3,4 and BDSP, blocks/poffins have a feel(sheen) equal to sheen=sum(stats)/5, with +/- 10% for a favored stat. - // In generation 6 (ORAS), they don't award any sheen, so any value is legal. + // In generations 3,4 and BD/SP, blocks/poffins have a feel(sheen) equal to sheen=sum(stats)/5, with +/- 10% for a favored stat. + // In generation 6 (OR/AS), they don't award any sheen, so any value is legal. var correlation = GetContestStatRestriction(pk, data.Info.Generation, data.Info.EvoChainsAllGens); if (correlation == None) diff --git a/PKHeX.Core/Legality/Verifiers/FormVerifier.cs b/PKHeX.Core/Legality/Verifiers/FormVerifier.cs index 1dace185c..c9307b8e5 100644 --- a/PKHeX.Core/Legality/Verifiers/FormVerifier.cs +++ b/PKHeX.Core/Legality/Verifiers/FormVerifier.cs @@ -71,10 +71,10 @@ public sealed class FormVerifier : Verifier case Dialga or Palkia or Giratina or Arceus when form > 0 && pk is PA8: // can change forms with key items break; - case Dialga when pk.Format >= 9 && form == 1 ^ pk.HeldItem == 1777: // Origin Forme Dialga with Adamant Crystal - case Palkia when pk.Format >= 9 && form == 1 ^ pk.HeldItem == 1778: // Origin Forme Palkia with Lustrous Globe - case Giratina when pk.Format >= 9 && form == 1 ^ pk.HeldItem == 1779: // Origin Forme Giratina with Griseous Core - case Giratina when pk.Format <= 8 && form == 1 ^ pk.HeldItem == 0112: // Origin Forme Giratina with Griseous Orb + case Dialga when pk.Format >= 9 && ((form == 1) != (pk.HeldItem == 1777)): // Origin Forme Dialga with Adamant Crystal + case Palkia when pk.Format >= 9 && ((form == 1) != (pk.HeldItem == 1778)): // Origin Forme Palkia with Lustrous Globe + case Giratina when pk.Format >= 9 && ((form == 1) != (pk.HeldItem == 1779)): // Origin Forme Giratina with Griseous Core + case Giratina when pk.Format <= 8 && ((form == 1) != (pk.HeldItem == 0112)): // Origin Forme Giratina with Griseous Orb return GetInvalid(LFormItemInvalid); case Arceus: @@ -261,7 +261,7 @@ public sealed class FormVerifier : Verifier return (Species)pk.Species switch { // Transfer Edge Cases -- Bank wipes the form but keeps old FormArgument value. - Furfrou when pk.Format == 7 && pk.Form == 0 && + Furfrou when pk is { Context: EntityContext.Gen7, Form: 0 } && ((enc.Generation == 6 && f.FormArgument <= byte.MaxValue) || IsFormArgumentDayCounterValid(f, 5, true)) => GetValid(LFormArgumentValid), @@ -337,7 +337,7 @@ public sealed class FormVerifier : Verifier _ => VerifyFormArgumentNone(pk, f), }; } - + private static bool HasVisitedPLA(LegalityAnalysis data, Species species) { var evos = data.Info.EvoChainsAllGens; @@ -376,7 +376,7 @@ public sealed class FormVerifier : Verifier { if (f.FormArgument != 0) { - if (pk.Species == (int)Furfrou && pk.Form == 0 && (f.FormArgument & ~0xFF_00_00u) == 0) + if (pk is { Species: (int)Furfrou, Form: 0 } && (f.FormArgument & ~0xFF_00_00u) == 0) return GetValid(LFormArgumentValid); return GetInvalid(LFormArgumentNotAllowed); } @@ -385,7 +385,7 @@ public sealed class FormVerifier : Verifier if (f.FormArgument != 0) { - if (pk.Species == (int)Furfrou && pk.Form == 0 && (f.FormArgument & ~0xFFu) == 0) + if (pk is { Species: (int)Furfrou, Form: 0 } && (f.FormArgument & ~0xFFu) == 0) return GetValid(LFormArgumentValid); return GetInvalid(LFormArgumentNotAllowed); } diff --git a/PKHeX.Core/Legality/Verifiers/GenderVerifier.cs b/PKHeX.Core/Legality/Verifiers/GenderVerifier.cs index 628422b5f..cd7b62f4f 100644 --- a/PKHeX.Core/Legality/Verifiers/GenderVerifier.cs +++ b/PKHeX.Core/Legality/Verifiers/GenderVerifier.cs @@ -16,7 +16,7 @@ public sealed class GenderVerifier : Verifier if (pi.Genderless != (pk.Gender == 2)) { // DP/HGSS shedinja glitch -- only generation 4 spawns - bool ignore = pk.Format == 4 && pk.Species == (int)Species.Shedinja && pk.Met_Level != pk.CurrentLevel; + bool ignore = pk is { Format: 4, Species: (int)Species.Shedinja } && pk.Met_Level != pk.CurrentLevel; if (!ignore) data.AddLine(GetInvalid(LGenderInvalidNone)); return; diff --git a/PKHeX.Core/Legality/Verifiers/HistoryVerifier.cs b/PKHeX.Core/Legality/Verifiers/HistoryVerifier.cs index c7d102042..2a9b7df7c 100644 --- a/PKHeX.Core/Legality/Verifiers/HistoryVerifier.cs +++ b/PKHeX.Core/Legality/Verifiers/HistoryVerifier.cs @@ -165,7 +165,7 @@ public sealed class HistoryVerifier : Verifier { if (origin == 6) { - if (pk.IsUntraded && pk.XY) + if (pk is { IsUntraded: true, XY: true }) { if (a.OT_Affection != 0) data.AddLine(GetInvalid(LMemoryStatAffectionOT0)); @@ -246,8 +246,8 @@ public sealed class HistoryVerifier : Verifier { EncounterTrade => false, EncounterSlot8GO => false, - WC6 wc6 when wc6.OT_Name.Length > 0 => false, - WC7 wc7 when wc7.OT_Name.Length > 0 && wc7.TID != 18075 => false, // Ash Pikachu QR Gift doesn't set Current Handler + WC6 { OT_Name.Length: > 0 } => false, + WC7 { OT_Name.Length: > 0, TID16: not 18075 } => false, // Ash Pikachu QR Gift doesn't set Current Handler WC8 wc8 when wc8.GetHasOT(pk.Language) => false, WB8 wb8 when wb8.GetHasOT(pk.Language) => false, WA8 wa8 when wa8.GetHasOT(pk.Language) => false, diff --git a/PKHeX.Core/Legality/Verifiers/IndividualValueVerifier.cs b/PKHeX.Core/Legality/Verifiers/IndividualValueVerifier.cs index 5a5ce27ab..b47550459 100644 --- a/PKHeX.Core/Legality/Verifiers/IndividualValueVerifier.cs +++ b/PKHeX.Core/Legality/Verifiers/IndividualValueVerifier.cs @@ -89,8 +89,7 @@ public sealed class IndividualValueVerifier : Verifier var pk = data.Entity; if (pk.GO) VerifyIVsGoTransfer(data); - - if (data.EncounterMatch is EncounterSlot8a s) + else if (data.EncounterMatch is EncounterSlot8a s) VerifyIVsFlawless(data, s.FlawlessIVCount); } diff --git a/PKHeX.Core/Legality/Verifiers/LanguageVerifier.cs b/PKHeX.Core/Legality/Verifiers/LanguageVerifier.cs index 22ab3b170..28ed1e79a 100644 --- a/PKHeX.Core/Legality/Verifiers/LanguageVerifier.cs +++ b/PKHeX.Core/Legality/Verifiers/LanguageVerifier.cs @@ -41,7 +41,7 @@ public sealed class LanguageVerifier : Verifier data.AddLine(GetInvalid(string.Format(LOTLanguage, $"!={(LanguageID)currentLanguage}", (LanguageID)currentLanguage))); // Japanese VC is language locked; cannot obtain Japanese-Blue version as other languages. - if (pk.Version == (int)GameVersion.BU && !pk.Japanese) + if (pk is { Version: (int)GameVersion.BU, Japanese: false }) data.AddLine(GetInvalid(string.Format(LOTLanguage, nameof(LanguageID.Japanese), (LanguageID)currentLanguage))); } } diff --git a/PKHeX.Core/Legality/Verifiers/LegendsArceusVerifier.cs b/PKHeX.Core/Legality/Verifiers/LegendsArceusVerifier.cs index c30b1ac2f..d712e8907 100644 --- a/PKHeX.Core/Legality/Verifiers/LegendsArceusVerifier.cs +++ b/PKHeX.Core/Legality/Verifiers/LegendsArceusVerifier.cs @@ -131,7 +131,7 @@ public sealed class LegendsArceusVerifier : Verifier private static void LoadPurchasedMoves(IMoveShop8 pa, Span result) { int ctr = 0; - var purchased = pa.MoveShopPermitIndexes; + var purchased = pa.Permit.RecordPermitIndexes; for (int i = 0; i < purchased.Length; i++) { if (pa.GetPurchasedRecordFlag(i)) @@ -141,7 +141,8 @@ public sealed class LegendsArceusVerifier : Verifier private static int AddMasteredMissing(PA8 pa, Span current, int ctr, Learnset baseLearn, Learnset currentLearn, int level) { - for (int i = 0; i < pa.MoveShopPermitIndexes.Length; i++) + var purchased = pa.Permit.RecordPermitIndexes; + for (int i = 0; i < purchased.Length; i++) { // Buying the move tutor grants access, but does not learn the move. // Mastering requires the move to be present in the movepool. @@ -153,7 +154,7 @@ public sealed class LegendsArceusVerifier : Verifier continue; // Check if we can swap it into the moveset after it evolves. - var move = pa.MoveShopPermitIndexes[i]; + var move = purchased[i]; var baseLevel = baseLearn.GetMoveLevel(move); var mustKnow = baseLevel is not -1 && baseLevel <= pa.Met_Level; if (!mustKnow && currentLearn.GetMoveLevel(move) != level) @@ -180,28 +181,27 @@ public sealed class LegendsArceusVerifier : Verifier private void CheckMastery(LegalityAnalysis data, PA8 pa) { - var bits = pa.MoveShopPermitFlags; - var moves = pa.MoveShopPermitIndexes; + var permit = pa.Permit; var alphaMove = pa.AlphaMove; if (alphaMove is not 0) - VerifyAlphaMove(data, pa, alphaMove, moves, bits); + VerifyAlphaMove(data, pa, alphaMove, permit); else VerifyAlphaMoveZero(data); - for (int i = 0; i < bits.Length; i++) - VerifyTutorMoveIndex(data, pa, i, bits, moves); + for (int i = 0; i < permit.RecordCountUsed; i++) + VerifyTutorMoveIndex(data, pa, i, permit); } - private void VerifyTutorMoveIndex(LegalityAnalysis data, PA8 pa, int i, ReadOnlySpan bits, ReadOnlySpan moves) + private void VerifyTutorMoveIndex(LegalityAnalysis data, PA8 pa, int i, IPermitRecord permit) { bool isPurchased = pa.GetPurchasedRecordFlag(i); if (isPurchased) { // Check if the move can be purchased. - if (bits[i]) + if (permit.IsRecordPermitted(i)) return; // If it has been legally purchased, then any mastery state is legal. - data.AddLine(GetInvalid(string.Format(LMoveShopPurchaseInvalid_0, ParseSettings.MoveStrings[moves[i]]))); + data.AddLine(GetInvalid(string.Format(LMoveShopPurchaseInvalid_0, ParseSettings.MoveStrings[permit.RecordPermitIndexes[i]]))); return; } @@ -210,14 +210,16 @@ public sealed class LegendsArceusVerifier : Verifier return; // All good. // Check if the move can be purchased; using a Mastery Seed checks the permission. - if (pa.AlphaMove == moves[i]) + var moves = permit.RecordPermitIndexes; + var move = moves[i]; + if (pa.AlphaMove == move) return; // Previously checked. - if (data.EncounterMatch is (IMoveset m and IMasteryInitialMoveShop8) && m.Moves.Contains(moves[i])) + if (data.EncounterMatch is (IMoveset m and IMasteryInitialMoveShop8) && m.Moves.Contains(move)) return; // Previously checked. - if (!bits[i]) - data.AddLine(GetInvalid(string.Format(LMoveShopMasterInvalid_0, ParseSettings.MoveStrings[moves[i]]))); + if (!permit.IsRecordPermitted(i)) + data.AddLine(GetInvalid(string.Format(LMoveShopMasterInvalid_0, ParseSettings.MoveStrings[move]))); else if (!CanLearnMoveByLevelUp(data, pa, i, moves)) - data.AddLine(GetInvalid(string.Format(LMoveShopMasterNotLearned_0, ParseSettings.MoveStrings[moves[i]]))); + data.AddLine(GetInvalid(string.Format(LMoveShopMasterNotLearned_0, ParseSettings.MoveStrings[move]))); } private static bool CanLearnMoveByLevelUp(LegalityAnalysis data, PA8 pa, int i, ReadOnlySpan moves) @@ -239,21 +241,21 @@ public sealed class LegendsArceusVerifier : Verifier return pa.CurrentLevel >= level; } - private void VerifyAlphaMove(LegalityAnalysis data, PA8 pa, ushort alphaMove, ReadOnlySpan moves, ReadOnlySpan bits) + private void VerifyAlphaMove(LegalityAnalysis data, PA8 pa, ushort alphaMove, IPermitRecord permit) { if (!pa.IsAlpha || data.EncounterMatch is EncounterSlot8a { Type: SlotType.Landmark }) { data.AddLine(GetInvalid(LMoveShopAlphaMoveShouldBeZero)); return; } - if (!CanMasterMoveFromMoveShop(alphaMove, moves, bits)) + if (!CanMasterMoveFromMoveShop(alphaMove, permit)) { data.AddLine(GetInvalid(LMoveShopAlphaMoveShouldBeOther)); return; } // An Alpha Move must be marked as mastered. - var masteredIndex = moves.IndexOf(alphaMove); + var masteredIndex = permit.RecordPermitIndexes.IndexOf(alphaMove); // Index is already >= 0, implicitly via the above call not returning false. if (!pa.GetMasteredRecordFlag(masteredIndex)) data.AddLine(GetInvalid(LMoveShopAlphaMoveShouldBeMastered)); @@ -269,18 +271,17 @@ public sealed class LegendsArceusVerifier : Verifier return; // okay var pi = PersonalTable.LA.GetFormEntry(enc.Species, enc.Form); - var tutors = pi.SpecialTutors[0]; - bool hasAnyTutor = Array.IndexOf(tutors, true) >= 0; - if (hasAnyTutor) // must have had a tutor flag + if (!pi.HasMoveShop) // must have had a tutor flag data.AddLine(GetInvalid(LMoveShopAlphaMoveShouldBeOther)); } - private static bool CanMasterMoveFromMoveShop(ushort move, ReadOnlySpan moves, ReadOnlySpan bits) + private static bool CanMasterMoveFromMoveShop(ushort move, IPermitRecord permit) { + var moves = permit.RecordPermitIndexes; var index = moves.IndexOf(move); if (index == -1) return false; // not in the list - if (!bits[index]) + if (!permit.IsRecordPermitted(index)) return false; // not a possible move return true; } diff --git a/PKHeX.Core/Legality/Verifiers/LevelVerifier.cs b/PKHeX.Core/Legality/Verifiers/LevelVerifier.cs index 1aa500978..e51c75adb 100644 --- a/PKHeX.Core/Legality/Verifiers/LevelVerifier.cs +++ b/PKHeX.Core/Legality/Verifiers/LevelVerifier.cs @@ -111,7 +111,9 @@ public sealed class LevelVerifier : Verifier var species = pk.Species; // This check is only applicable if it's a trade evolution that has not been evolved. - if (!GBRestrictions.Trade_Evolution1.Contains((byte)enc.Species) || enc.Species != species) + if (enc.Species != species) + return false; + if (!GBRestrictions.IsTradeEvolution1(enc.Species)) return false; // Context check is only applicable to gen1/2; transferring to Gen2 is a trade. diff --git a/PKHeX.Core/Legality/Verifiers/MarkVerifier.cs b/PKHeX.Core/Legality/Verifiers/MarkVerifier.cs index cb9294b6d..1bfa02356 100644 --- a/PKHeX.Core/Legality/Verifiers/MarkVerifier.cs +++ b/PKHeX.Core/Legality/Verifiers/MarkVerifier.cs @@ -101,7 +101,7 @@ public sealed class MarkVerifier : Verifier // Try re-verifying to see if it could have had the Ribbon/Mark. var enc = data.EncounterOriginal; - if (affix.IsEncounterMark()) + if (affix.IsEncounterMark8()) { if (!MarkRules.IsEncounterMarkValid(affix, pk, enc)) data.AddLine(GetInvalid(string.Format(LRibbonMarkingAffixedF_0, GetRibbonNameSafe(affix)))); diff --git a/PKHeX.Core/Legality/Verifiers/MemoryVerifier.cs b/PKHeX.Core/Legality/Verifiers/MemoryVerifier.cs index 6c80b9ced..404c5fe95 100644 --- a/PKHeX.Core/Legality/Verifiers/MemoryVerifier.cs +++ b/PKHeX.Core/Legality/Verifiers/MemoryVerifier.cs @@ -40,7 +40,7 @@ public sealed class MemoryVerifier : Verifier var memory = MemoryVariableSet.Read((ITrainerMemories)pk, handler); // Actionable HM moves - int hmIndex = Array.IndexOf(MemoryContext6.MoveSpecificMemoryHM, memory.MemoryID); + int hmIndex = MemoryContext6.MoveSpecificMemoryHM.IndexOf(memory.MemoryID); if (hmIndex != -1) { if (context != Gen6) // Gen8 has no HMs, so this memory can never exist. @@ -51,7 +51,7 @@ public sealed class MemoryVerifier : Verifier // All AO hidden machine permissions are super-sets of Gen 3-5 games. // Don't need to check the move history -- a learned HM in a prior game can still be learned in Gen6. var evos = info.EvoChainsAllGens.Gen6; - var exists = Array.Exists(evos, z => PersonalTable.AO.GetFormEntry(z.Species, 0).TMHM[100 + hmIndex]); + var exists = Array.Exists(evos, z => PersonalTable.AO.GetFormEntry(z.Species, 0).GetIsLearnHM(hmIndex)); if (!exists) return GetInvalid(string.Format(LMemoryArgBadMove, memory.Handler)); } @@ -70,7 +70,7 @@ public sealed class MemoryVerifier : Verifier return GetInvalid(string.Format(LMemoryArgBadLocation, memory.Handler)); // {0} saw {2} carrying {1} on its back. {4} that {3}. - case 21 when context != Gen6 || !PersonalTable.AO.GetFormEntry(memory.Variable, 0).TMHM[101]: // Fly + case 21 when context != Gen6 || !PersonalTable.AO.GetFormEntry(memory.Variable, 0).GetIsLearnHM(2): // Fly return GetInvalid(string.Format(LMemoryArgBadMove, memory.Handler)); // {0} used {2} at {1}’s instruction, but it had no effect. {4} that {3}. @@ -230,7 +230,7 @@ public sealed class MemoryVerifier : Verifier switch (memory) { // No Memory - case 0: // SWSH trades don't set HT memories immediately, which is hilarious. + case 0: // SW/SH trades don't set HT memories immediately, which is hilarious. data.AddLine(Get(LMemoryMissingOT, context == Gen8 ? Severity.Fishy : Severity.Invalid)); VerifyOTMemoryIs(data, 0, 0, 0, 0); return; @@ -320,7 +320,7 @@ public sealed class MemoryVerifier : Verifier switch (memory) { // No Memory - case 0: // SWSH memory application has an off-by-one error: [0,99] + 1 <= chance --> don't apply + case 0: // SW/SH memory application has an off-by-one error: [0,99] + 1 <= chance --> don't apply var severity = memoryGen switch { Gen8 when pk is not PK8 && !pk.SWSH => Severity.Valid, diff --git a/PKHeX.Core/Legality/Verifiers/Misc/ContestStatInfo.cs b/PKHeX.Core/Legality/Verifiers/Misc/ContestStatInfo.cs index 4e59d9ed6..0293b6821 100644 --- a/PKHeX.Core/Legality/Verifiers/Misc/ContestStatInfo.cs +++ b/PKHeX.Core/Legality/Verifiers/Misc/ContestStatInfo.cs @@ -59,8 +59,8 @@ public static class ContestStatInfo 3 => pk.Format < 6 ? CorrelateSheen : Mixed, 4 => pk.Format < 6 ? CorrelateSheen : Mixed, - 5 => pk.Format < 6 ? None : !h.HasVisitedBDSP ? NoSheen : Mixed, // ORAS Contests - 6 => !pk.AO && pk.IsUntraded ? None : !h.HasVisitedBDSP ? NoSheen : Mixed, + 5 => pk.Format < 6 ? None : !h.HasVisitedBDSP ? NoSheen : Mixed, // ORAS Contests + 6 => pk is { AO: false, IsUntraded: true } ? None : !h.HasVisitedBDSP ? NoSheen : Mixed, _ => h.HasVisitedBDSP ? CorrelateSheen : None, // BDSP Contests }; @@ -109,7 +109,7 @@ public static class ContestStatInfo avg = Math.Min(rawAvg, avg); // be generous avg = (BestSheenStat8b * avg) / MaxContestStat; - return Math.Min(BestSheenStat8b, Math.Max(LowestFeelPoffin8b, avg)); + return Math.Clamp(avg, LowestFeelPoffin8b, BestSheenStat8b); } public static int CalculateMinimumSheen3(IContestStatsReadOnly s, int nature, IContestStatsReadOnly initial) @@ -125,7 +125,7 @@ public static class ContestStatInfo avg = Math.Min(rawAvg, avg); // be generous avg = (BestSheenStat3 * avg) / MaxContestStat; - return Math.Min(BestSheenStat3, Math.Max(LowestFeelBlock3, avg)); + return Math.Clamp(avg, LowestFeelBlock3, BestSheenStat3); } public static int CalculateMinimumSheen4(IContestStatsReadOnly s, int nature, IContestStatsReadOnly initial) @@ -140,7 +140,7 @@ public static class ContestStatInfo var avg = Math.Max(1, nature % 6 == 0 ? rawAvg : GetAverageFeel(s, nature, initial)); avg = Math.Min(rawAvg, avg); // be generous - return Math.Min(MaxContestStat, Math.Max(LowestFeelPoffin4, avg)); + return Math.Clamp(avg, LowestFeelPoffin4, MaxContestStat); } private static int CalculateMaximumSheen3(IContestStatsReadOnly s, int nature, IContestStatsReadOnly initial) @@ -162,7 +162,7 @@ public static class ContestStatInfo // Prefer the bad-black-block correlation if more than 3 stats have gains >= 2. var permit = has3 ? (sum * 83 / 6) : (sum * 19 / 9); - return Math.Min(MaxContestStat, Math.Max(LowestFeelBlock3, permit)); + return Math.Clamp(permit, LowestFeelBlock3, MaxContestStat); } private static int GetAverageFeel(IContestStatsReadOnly s, int nature, IContestStatsReadOnly initial) @@ -173,7 +173,7 @@ public static class ContestStatInfo private static int GetGainedSum(IContestStatsReadOnly s, int nature, IContestStatsReadOnly initial) { - ReadOnlySpan span = NatureAmpTable.AsSpan(5 * nature, 5); + var span = NatureAmpTable.Slice(5 * nature, 5); int sum = 0; sum += GetAmpedStat(span, 0, s.CNT_Cool - initial.CNT_Cool); sum += GetAmpedStat(span, 1, s.CNT_Beauty - initial.CNT_Beauty); @@ -223,7 +223,7 @@ public static class ContestStatInfo public byte CNT_Sheen => 0; } - private static readonly sbyte[] NatureAmpTable = + private static ReadOnlySpan NatureAmpTable => new sbyte[] { // Spicy, Dry, Sweet, Bitter, Sour 0, 0, 0, 0, 0, // Hardy diff --git a/PKHeX.Core/Legality/Verifiers/MiscVerifier.cs b/PKHeX.Core/Legality/Verifiers/MiscVerifier.cs index ad346b990..ae7853025 100644 --- a/PKHeX.Core/Legality/Verifiers/MiscVerifier.cs +++ b/PKHeX.Core/Legality/Verifiers/MiscVerifier.cs @@ -6,7 +6,7 @@ using static PKHeX.Core.CheckIdentifier; namespace PKHeX.Core; /// -/// Verifies miscellaneous data including and minor values. +/// Verifies miscellaneous data including and minor values. /// public sealed class MiscVerifier : Verifier { @@ -74,12 +74,12 @@ public sealed class MiscVerifier : Verifier var enc = data.EncounterMatch; if (enc is IEncounterServerDate { IsDateRestricted: true } serverGift) { - var date = new DateTime(pk.Met_Year + 2000, pk.Met_Month, pk.Met_Day); + var date = new DateOnly(pk.Met_Year + 2000, pk.Met_Month, pk.Met_Day); // HOME Gifts for Sinnoh/Hisui starters were forced JPN until May 20, 2022 (UTC). if (enc is WB8 { CardID: 9015 or 9016 or 9017 } or WA8 { CardID: 9018 or 9019 or 9020 }) { - if (date < new DateTime(2022, 5, 20) && pk.Language != (int)LanguageID.Japanese) + if (date < new DateOnly(2022, 5, 20) && pk.Language != (int)LanguageID.Japanese) data.AddLine(GetInvalid(LDateOutsideDistributionWindow)); } @@ -142,7 +142,7 @@ public sealed class MiscVerifier : Verifier data.AddLine(GetInvalid(LStatBattleVersionInvalid)); var enc = data.EncounterOriginal; - if (CheckHeightWeightOdds(enc) && pk9.HeightScalar == 0 && pk9.WeightScalar == 0 && ParseSettings.ZeroHeightWeight != Severity.Valid) + if (CheckHeightWeightOdds(enc) && pk9 is { HeightScalar: 0, WeightScalar: 0 } && ParseSettings.ZeroHeightWeight != Severity.Valid) data.AddLine(Get(LStatInvalidHeightWeight, ParseSettings.ZeroHeightWeight, Encounter)); if (enc is EncounterEgg g && UnreleasedSV.Contains(g.Species | g.Form << 11)) @@ -159,6 +159,12 @@ public sealed class MiscVerifier : Verifier if (pk9.IsEgg && pk9.TeraTypeOverride != (MoveType)TeraTypeUtil.OverrideNone) data.AddLine(GetInvalid(LTeraTypeIncorrect)); + if (enc is ITeraRaid9) + { + var seed = Tera9RNG.GetOriginalSeed(pk9); + data.Info.PIDIV = new PIDIV(PIDType.Tera9, seed); + } + VerifyTechRecordSV(data, pk9); } @@ -331,7 +337,7 @@ public sealed class MiscVerifier : Verifier var enc = data.EncounterMatch; switch (enc) { - case WC3 {Fateful: true} w: + case WC3 {FatefulEncounter: true} w: if (w.IsEgg) { // Eggs hatched in RS clear the obedience flag! @@ -354,9 +360,7 @@ public sealed class MiscVerifier : Verifier VerifyReceivability(data, g); VerifyFatefulMysteryGift(data, g); return; - case EncounterStatic {Fateful: true}: // ingame fateful - case EncounterSlot3PokeSpot: // ingame pokespot - case EncounterTrade4RanchSpecial: // ranch varied PID + case IFatefulEncounterReadOnly {FatefulEncounter: true}: // ingame fateful VerifyFatefulIngameActive(data); return; } @@ -466,20 +470,13 @@ public sealed class MiscVerifier : Verifier data.AddLine(GetInvalid(LPIDTypeMismatch, PID)); } - bool shouldHave = GetFatefulState(g); + bool shouldHave = g.FatefulEncounter; var result = pk.FatefulEncounter == shouldHave ? GetValid(LFatefulMystery, Fateful) : GetInvalid(LFatefulMysteryMissing, Fateful); data.AddLine(result); } - private static bool GetFatefulState(MysteryGift g) - { - if (g is WC6 {IsLinkGift: true}) - return false; // Pokémon Link fake-gifts do not have Fateful - return true; - } - private static void VerifyReceivability(LegalityAnalysis data, MysteryGift g) { var pk = data.Entity; @@ -641,7 +638,7 @@ public sealed class MiscVerifier : Verifier data.AddLine(GetInvalid(LStatDynamaxInvalid)); } - if (CheckHeightWeightOdds(data.EncounterMatch) && pk8.HeightScalar == 0 && pk8.WeightScalar == 0 && ParseSettings.ZeroHeightWeight != Severity.Valid) + if (CheckHeightWeightOdds(data.EncounterMatch) && pk8 is { HeightScalar: 0, WeightScalar: 0 } && ParseSettings.ZeroHeightWeight != Severity.Valid) data.AddLine(Get(LStatInvalidHeightWeight, ParseSettings.ZeroHeightWeight, Encounter)); VerifyTechRecordSWSH(data, pk8); @@ -675,7 +672,7 @@ public sealed class MiscVerifier : Verifier if (pa8.GetMoveRecordFlagAny() && !pa8.IsEgg) // already checked for eggs data.AddLine(GetInvalid(LEggRelearnFlags)); - if (CheckHeightWeightOdds(data.EncounterMatch) && pa8.HeightScalar == 0 && pa8.WeightScalar == 0 && ParseSettings.ZeroHeightWeight != Severity.Valid) + if (CheckHeightWeightOdds(data.EncounterMatch) && pa8 is { HeightScalar: 0, WeightScalar: 0 } && ParseSettings.ZeroHeightWeight != Severity.Valid) data.AddLine(Get(LStatInvalidHeightWeight, ParseSettings.ZeroHeightWeight, Encounter)); VerifyTechRecordSWSH(data, pa8); @@ -715,7 +712,7 @@ public sealed class MiscVerifier : Verifier if (pb8.GetMoveRecordFlagAny() && !pb8.IsEgg) // already checked for eggs data.AddLine(GetInvalid(LEggRelearnFlags)); - if (CheckHeightWeightOdds(data.EncounterMatch) && pb8.HeightScalar == 0 && pb8.WeightScalar == 0 && ParseSettings.ZeroHeightWeight != Severity.Valid) + if (CheckHeightWeightOdds(data.EncounterMatch) && pb8 is { HeightScalar: 0, WeightScalar: 0 } && ParseSettings.ZeroHeightWeight != Severity.Valid) data.AddLine(Get(LStatInvalidHeightWeight, ParseSettings.ZeroHeightWeight, Encounter)); VerifyTechRecordSWSH(data, pb8); @@ -742,11 +739,12 @@ public sealed class MiscVerifier : Verifier private void VerifyTechRecordSWSH(LegalityAnalysis data, T pk) where T : PKM, ITechRecord { - static string GetMoveName(int index) => ParseSettings.MoveStrings[LearnSource8SWSH.TR_SWSH[index]]; + string GetMoveName(int index) => ParseSettings.MoveStrings[pk.Permit.RecordPermitIndexes[index]]; var evos = data.Info.EvoChainsAllGens.Gen8; if (evos.Length == 0) { - for (int i = 0; i < PersonalInfo8SWSH.CountTR; i++) + var count = pk.Permit.RecordCountUsed; + for (int i = 0; i < count; i++) { if (!pk.GetMoveRecordFlag(i)) continue; @@ -757,11 +755,12 @@ public sealed class MiscVerifier : Verifier { static PersonalInfo8SWSH GetPersonal(EvoCriteria evo) => PersonalTable.SWSH.GetFormEntry(evo.Species, evo.Form); PersonalInfo8SWSH? pi = null; - for (int i = 0; i < PersonalInfo8SWSH.CountTR; i++) + var count = pk.Permit.RecordCountUsed; + for (int i = 0; i < count; i++) { if (!pk.GetMoveRecordFlag(i)) continue; - if ((pi ??= GetPersonal(evos[0])).TMHM[i + PersonalInfo8SWSH.CountTM]) + if ((pi ??= GetPersonal(evos[0])).GetIsLearnTR(i)) continue; // Calyrex-0 can have TR flags for Calyrex-1/2 after it has force unlearned them. @@ -783,16 +782,17 @@ public sealed class MiscVerifier : Verifier private static bool CanLearnTR(ushort species, byte form, int tr) { var pi = PersonalTable.SWSH.GetFormEntry(species, form); - return pi.TMHM[tr + PersonalInfo8SWSH.CountTM]; + return pi.GetIsLearnTR(tr); } private void VerifyTechRecordSV(LegalityAnalysis data, PK9 pk) { - static string GetMoveName(int index) => ParseSettings.MoveStrings[LearnSource9SV.TM_SV[index]]; + string GetMoveName(int index) => ParseSettings.MoveStrings[pk.Permit.RecordPermitIndexes[index]]; var evos = data.Info.EvoChainsAllGens.Gen9; if (evos.Length == 0) { - for (int i = 0; i < PersonalInfo9SV.CountTM; i++) + int count = pk.Permit.RecordCountUsed; + for (int i = 0; i < count; i++) { if (!pk.GetMoveRecordFlag(i)) continue; @@ -803,11 +803,12 @@ public sealed class MiscVerifier : Verifier { static PersonalInfo9SV GetPersonal(EvoCriteria evo) => PersonalTable.SV.GetFormEntry(evo.Species, evo.Form); PersonalInfo9SV? pi = null; - for (int i = 0; i < PersonalInfo9SV.CountTM; i++) + int count = pk.Permit.RecordCountUsed; + for (int i = 0; i < count; i++) { if (!pk.GetMoveRecordFlag(i)) continue; - if ((pi ??= GetPersonal(evos[0])).TMHM[i]) + if ((pi ??= GetPersonal(evos[0])).GetIsLearnTM(i)) continue; // Zoroark-0 cannot learn Encore via TM, but the pre-evolution Zorua-0 can via TM. @@ -815,7 +816,7 @@ public sealed class MiscVerifier : Verifier bool preEvoHas = false; for (int p = 1; p < evos.Length; p++) { - if (!GetPersonal(evos[p]).TMHM[i]) + if (!GetPersonal(evos[p]).GetIsLearnTM(i)) continue; preEvoHas = true; break; diff --git a/PKHeX.Core/Legality/Verifiers/NHarmoniaVerifier.cs b/PKHeX.Core/Legality/Verifiers/NHarmoniaVerifier.cs index a5c108ea8..f3b8c38d6 100644 --- a/PKHeX.Core/Legality/Verifiers/NHarmoniaVerifier.cs +++ b/PKHeX.Core/Legality/Verifiers/NHarmoniaVerifier.cs @@ -38,12 +38,12 @@ public sealed class NHarmoniaVerifier : Verifier private static bool VerifyNsPKMIVsValid(PKM pk) { // All are 30. - return pk.IV_HP == 30 && pk.IV_ATK == 30 && pk.IV_DEF == 30 && pk.IV_SPA == 30 && pk.IV_SPD == 30 && pk.IV_SPE == 30; + return pk is { IV_HP: 30, IV_ATK: 30, IV_DEF: 30, IV_SPA: 30, IV_SPD: 30, IV_SPE: 30 }; } private static bool VerifyNsPKMOTValid(PKM pk) { - if (pk.TID != 00002 || pk.SID != 00000) + if (pk.TID16 != 00002 || pk.SID16 != 00000) return false; var ot = pk.OT_Name; if (ot.Length != 1) diff --git a/PKHeX.Core/Legality/Verifiers/NicknameVerifier.cs b/PKHeX.Core/Legality/Verifiers/NicknameVerifier.cs index 4dcbf1aac..9f5d4fe20 100644 --- a/PKHeX.Core/Legality/Verifiers/NicknameVerifier.cs +++ b/PKHeX.Core/Legality/Verifiers/NicknameVerifier.cs @@ -38,10 +38,10 @@ public sealed class NicknameVerifier : Verifier return; } - if (pk.Format <= 7 && pk.IsNicknamed) // can nickname afterwards + if (pk is { Format: <= 7, IsNicknamed: true }) // can nickname afterwards { if (pk.VC) - VerifyG1NicknameWithinBounds(data, nickname.AsSpan()); + VerifyG1NicknameWithinBounds(data, nickname); else if (enc is MysteryGift {IsEgg: false}) data.AddLine(Get(LEncGiftNicknamed, ParseSettings.NicknamedMysteryGift)); } @@ -65,18 +65,18 @@ public sealed class NicknameVerifier : Verifier // Non-nicknamed strings have already been checked. if (ParseSettings.CheckWordFilter && pk.IsNicknamed) { - if (WordFilter.IsFiltered(nickname, out string bad)) - data.AddLine(GetInvalid($"Word Filter: {bad}")); + if (WordFilter.IsFiltered(nickname, out var badPattern)) + data.AddLine(GetInvalid($"Word Filter: {badPattern}")); if (TrainerNameVerifier.ContainsTooManyNumbers(nickname, data.Info.Generation)) data.AddLine(GetInvalid("Word Filter: Too many numbers.")); } } - private void VerifyFixedNicknameEncounter(LegalityAnalysis data, ILangNicknamedTemplate n, IEncounterTemplate enc, PKM pk, string nickname) + private void VerifyFixedNicknameEncounter(LegalityAnalysis data, ILangNicknamedTemplate n, IEncounterTemplate enc, PKM pk, ReadOnlySpan nickname) { - var nick = n.GetNickname(pk.Language); + var encounterNickname = n.GetNickname(pk.Language); - if (string.IsNullOrWhiteSpace(nick)) + if (string.IsNullOrWhiteSpace(encounterNickname)) { if (n is WC8 {IsHOMEGift: true}) { @@ -107,7 +107,7 @@ public sealed class NicknameVerifier : Verifier { // Check if it had a nickname at all var orig = SpeciesName.GetSpeciesNameGeneration(enc.Species, pk.Language, enc.Generation); - if (orig == nick) + if (orig == encounterNickname) { // Didn't have a nickname. Ensure that the language matches the current nickname string. if (!SpeciesName.IsNicknamed(pk.Species, nickname, pk.Language, pk.Format)) @@ -120,11 +120,12 @@ public sealed class NicknameVerifier : Verifier } // Encounter has a nickname, and PKM should have it. - var severity = nick != nickname || !pk.IsNicknamed ? Severity.Invalid : Severity.Valid; + bool matches = nickname.SequenceEqual(encounterNickname); + var severity = !matches || !pk.IsNicknamed ? Severity.Invalid : Severity.Valid; data.AddLine(Get(LEncGiftNicknamed, severity)); } - private void VerifyHomeGiftNickname(LegalityAnalysis data, IEncounterTemplate enc, ILangNick pk, string nickname) + private void VerifyHomeGiftNickname(LegalityAnalysis data, IEncounterTemplate enc, ILangNick pk, ReadOnlySpan nickname) { // can nickname on redemption if (!pk.IsNicknamed) @@ -139,7 +140,7 @@ public sealed class NicknameVerifier : Verifier // Ensure the nickname does not match species name var orig = SpeciesName.GetSpeciesNameGeneration(enc.Species, pk.Language, enc.Generation); - if (nickname == orig) + if (nickname.SequenceEqual(orig)) data.AddLine(GetInvalid(LNickMatchLanguageFlag)); } @@ -147,7 +148,7 @@ public sealed class NicknameVerifier : Verifier { if (pk.IsNicknamed) { - if (data.Info.Generation >= 8) + if (data.Info.Generation >= 8 && CanNicknameForeign8Plus(data, pk)) { // Can only nickname if it matches your language. // Setting the nickname to the same as the species name does not set the Nickname flag (equals unmodified, no flag) @@ -165,7 +166,7 @@ public sealed class NicknameVerifier : Verifier data.AddLine(Get(msg, ParseSettings.NicknamedAnotherSpecies)); return true; } - if (pk.Format <= 7 && StringConverter.HasEastAsianScriptCharacters(nickname.AsSpan()) && pk is not PB7) // East Asian Scripts + if (pk.Format <= 7 && StringConverter.HasEastAsianScriptCharacters(nickname) && pk is not PB7) // East Asian Scripts { data.AddLine(GetInvalid(LNickInvalidChar)); return true; @@ -179,7 +180,17 @@ public sealed class NicknameVerifier : Verifier } data.AddLine(GetValid(LNickMatchNoOthers)); } - else if (pk.Format < 3) + else + { + VerifyUnNicknamed(data, pk, nickname); + } + + return false; + } + + private void VerifyUnNicknamed(LegalityAnalysis data, PKM pk, ReadOnlySpan nickname) + { + if (pk.Format < 3) { // pk1/pk2 IsNicknamed getter checks for match, logic should only reach here if matches. data.AddLine(GetValid(LNickMatchLanguage)); @@ -191,6 +202,14 @@ public sealed class NicknameVerifier : Verifier var result = valid ? GetValid(LNickMatchLanguage) : GetInvalid(LNickMatchLanguageFail); data.AddLine(result); } + } + + private static bool CanNicknameForeign8Plus(LegalityAnalysis data, PKM pk) + { + if (data.Info.EvoChainsAllGens.HasVisitedSWSH) + return true; + if (pk.Format >= 9) + return !pk.FatefulEncounter; return false; } @@ -214,12 +233,13 @@ public sealed class NicknameVerifier : Verifier return Math.Max(length, future); } - private static bool IsNicknameValid(PKM pk, IEncounterTemplate enc, string nickname) + private static bool IsNicknameValid(PKM pk, IEncounterTemplate enc, ReadOnlySpan nickname) { ushort species = pk.Species; int format = pk.Format; int language = pk.Language; - if (SpeciesName.GetSpeciesNameGeneration(species, language, format) == nickname) + var expect = SpeciesName.GetSpeciesNameGeneration(species, language, format); + if (nickname.SequenceEqual(expect)) return true; // Can't have another language name if it hasn't evolved or wasn't a language-traded egg. @@ -244,7 +264,8 @@ public sealed class NicknameVerifier : Verifier { if (canHaveAnyLanguage) return !SpeciesName.IsNicknamedAnyLanguage(species, nickname, 4); - return SpeciesName.GetSpeciesNameGeneration(species, language, 4) == nickname; + expect = SpeciesName.GetSpeciesNameGeneration(species, language, 4); + return nickname.SequenceEqual(expect); } return false; @@ -259,10 +280,10 @@ public sealed class NicknameVerifier : Verifier if (pk.IsNicknamed != flagState) data.AddLine(GetInvalid(flagState ? LNickFlagEggYes : LNickFlagEggNo, CheckIdentifier.Egg)); - var nick = pk.Nickname; - if (pk.Format == 2 && !SpeciesName.IsNicknamedAnyLanguage(0, nick, 2)) + ReadOnlySpan nickname = pk.Nickname; + if (pk.Format == 2 && !SpeciesName.IsNicknamedAnyLanguage(0, nickname, 2)) data.AddLine(GetValid(LNickMatchLanguageEgg, CheckIdentifier.Egg)); - else if (nick != SpeciesName.GetEggName(pk.Language, Info.Generation)) + else if (!nickname.SequenceEqual(SpeciesName.GetEggName(pk.Language, Info.Generation))) data.AddLine(GetInvalid(LNickMatchLanguageEggFail, CheckIdentifier.Egg)); else data.AddLine(GetValid(LNickMatchLanguageEgg, CheckIdentifier.Egg)); @@ -329,7 +350,7 @@ public sealed class NicknameVerifier : Verifier private static void VerifyTrade4(LegalityAnalysis data, EncounterTrade t) { var pk = data.Entity; - if (pk.TID == 1000) + if (pk.TID16 == 1000) { VerifyTradeOTOnly(data, t); return; @@ -359,8 +380,14 @@ public sealed class NicknameVerifier : Verifier } // Since two locales (JPN/ENG) can have the same LanguageID, check which we should be validating with. - if (lang == 1 && pk.OT_Name != t.GetOT(1)) // not Japanese - lang = 2; // verify strings with English locale instead. + if (lang == 1) + { + ReadOnlySpan ot = pk.OT_Name; + var expect = t.GetOT(1); + var match = ot.SequenceEqual(expect); + if (!match) + lang = 2; // verify strings with English locale instead. + } } break; } @@ -374,7 +401,7 @@ public sealed class NicknameVerifier : Verifier if (t.Species == (int)Species.Magikarp) { // Japanese - if (pk.Language == (int)Japanese && pk.OT_Name is "Diamond." or "Pearl.") + if (pk is { Language: (int)Japanese, OT_Name: "Diamond." or "Pearl." }) { // Traded between players, the original OT is replaced with the above OT (version dependent) as the original OT is >6 chars in length. VerifyTradeNickname(data, t, t.Nicknames[(int)German], pk); @@ -419,14 +446,15 @@ public sealed class NicknameVerifier : Verifier data.AddLine(GetInvalid(string.Format(LTransferOriginFInvalid0_1, L_XKorean, L_XKoreanNon), CheckIdentifier.Language)); } - private static int DetectTradeLanguage(string OT, EncounterTrade t, int currentLanguageID) + private static int DetectTradeLanguage(ReadOnlySpan OT, EncounterTrade t, int currentLanguageID) { var names = t.TrainerNames; for (int lang = 1; lang < names.Count; lang++) { - if (names[lang] != OT) - continue; - return lang; + var expect = names[lang]; + var match = OT.SequenceEqual(expect); + if (match) + return lang; } return currentLanguageID; } @@ -482,7 +510,7 @@ public sealed class NicknameVerifier : Verifier } else // B2W2 { - if (t.TID is Encounters5B2W2.YancyTID or Encounters5B2W2.CurtisTID) + if (t.TID16 is Encounters5B2W2.YancyTID or Encounters5B2W2.CurtisTID) VerifyTradeOTOnly(data, t); else VerifyTrade(data, t, lang); @@ -518,17 +546,19 @@ public sealed class NicknameVerifier : Verifier VerifyTradeOTNick(data, t, nick, ot); } - private static void VerifyTradeOTNick(LegalityAnalysis data, EncounterTrade t, string nick, string OT) + private static void VerifyTradeOTNick(LegalityAnalysis data, EncounterTrade t, ReadOnlySpan nick, ReadOnlySpan encounterOT) { var pk = data.Entity; // trades that are not nicknamed (but are present in a table with others being named) VerifyTradeNickname(data, t, nick, pk); - if (OT != pk.OT_Name) + var currentOT = pk.OT_Name; + var match = encounterOT.SequenceEqual(currentOT); + if (!match) data.AddLine(GetInvalid(LEncTradeChangedOT, CheckIdentifier.Trainer)); } - private static void VerifyTradeNickname(LegalityAnalysis data, EncounterTrade t, string expectedNickname, PKM pk) + private static void VerifyTradeNickname(LegalityAnalysis data, EncounterTrade t, ReadOnlySpan expectedNickname, PKM pk) { var result = IsNicknameMatch(expectedNickname, pk, t) ? GetValid(LEncTradeUnchanged, CheckIdentifier.Nickname) @@ -536,13 +566,16 @@ public sealed class NicknameVerifier : Verifier data.AddLine(result); } - private static bool IsNicknameMatch(string nick, ILangNick pk, EncounterTrade enc) + private static bool IsNicknameMatch(ReadOnlySpan nick, ILangNick pk, EncounterTrade enc) { if (nick == "Quacklin’" && pk.Nickname == "Quacklin'") return true; if (enc.IsNicknamed != pk.IsNicknamed) return false; - if (nick != pk.Nickname) // if not match, must not be a nicknamed trade && not currently named + + var currentNick = pk.Nickname; + var match = nick.SequenceEqual(currentNick); + if (!match) // if not match, must not be a nicknamed trade && not currently named return !enc.IsNicknamed && !pk.IsNicknamed; return true; } diff --git a/PKHeX.Core/Legality/Verifiers/PIDVerifier.cs b/PKHeX.Core/Legality/Verifiers/PIDVerifier.cs index 9b0429cbb..b61c78268 100644 --- a/PKHeX.Core/Legality/Verifiers/PIDVerifier.cs +++ b/PKHeX.Core/Legality/Verifiers/PIDVerifier.cs @@ -90,7 +90,7 @@ public sealed class PIDVerifier : Verifier { var pk = data.Entity; var pid = pk.EncryptionConstant; - var result = (pid & 1) ^ (pid >> 31) ^ (pk.TID & 1) ^ (pk.SID & 1); + var result = (pid & 1) ^ (pid >> 31) ^ (pk.TID16 & 1) ^ (pk.SID16 & 1); if (result != 0) data.AddLine(GetInvalid(LPIDTypeMismatch)); } @@ -126,7 +126,7 @@ public sealed class PIDVerifier : Verifier { (int)Species.Tandemaus => ((ushort)Species.Maushold, rare ? 0 : 1), (int)Species.Dunsparce => ((ushort)Species.Dudunsparce, rare ? 1 : 0), - _ => throw new ArgumentOutOfRangeException(nameof(enc.Species)), + _ => throw new ArgumentOutOfRangeException(nameof(enc.Species), "Incorrect EC%100 species."), }; var str = GameInfo.Strings; var forms = FormConverter.GetFormList(species, str.Types, str.forms, GameInfo.GenderSymbolASCII, EntityContext.Gen9); @@ -171,7 +171,7 @@ public sealed class PIDVerifier : Verifier // Check for Gen3-5 => Gen6 edge case being incorrectly applied here. if ((pk.PID ^ 0x80000000) == pk.EncryptionConstant) { - int xor = pk.TSV ^ pk.PSV; + var xor = pk.ShinyXor; if (xor >> 3 == 1) // 8 <= x <= 15 data.AddLine(Get(LTransferPIDECXor, Severity.Fishy, CheckIdentifier.EC)); } @@ -192,10 +192,9 @@ public sealed class PIDVerifier : Verifier return false; } - uint pid = pk.PID; - uint LID = pid & 0xFFFF; - uint HID = pid >> 16; - uint XOR = (uint)(pk.TID ^ LID ^ pk.SID ^ HID); + var pid = pk.PID; + var tmp = pid ^ pk.ID32; + var XOR = (ushort)(tmp ^ (tmp >> 16)); // Ensure we don't have a shiny. if (XOR >> 3 == 1) // Illegal, fix. (not 16=8) @@ -228,7 +227,9 @@ public sealed class PIDVerifier : Verifier private static bool GetExpectedTransferPID(PKM pk, out uint expect) { var ec = pk.EncryptionConstant; // should be original PID - bool xorPID = ((pk.TID ^ pk.SID ^ (int) (ec & 0xFFFF) ^ (int) (ec >> 16)) & ~0x7) == 8; + var tmp = ec ^ pk.ID32; + var xor = tmp ^ (tmp >> 16); + bool xorPID = (xor & 0xFFF8u) == 8; expect = (xorPID ? (ec ^ 0x80000000) : ec); return xorPID; } diff --git a/PKHeX.Core/Legality/Verifiers/Ribbons/RibbonResult.cs b/PKHeX.Core/Legality/Verifiers/Ribbons/RibbonResult.cs index e745e63bc..76d20329e 100644 --- a/PKHeX.Core/Legality/Verifiers/Ribbons/RibbonResult.cs +++ b/PKHeX.Core/Legality/Verifiers/Ribbons/RibbonResult.cs @@ -35,7 +35,7 @@ public readonly record struct RibbonResult Mainline => ((RibbonIndex)Value).GetPropertyName(), Index3 => ((RibbonIndex3)Value).GetPropertyName(), Index4 => ((RibbonIndex4)Value).GetPropertyName(), - _ => throw new ArgumentOutOfRangeException(), + _ => throw new ArgumentException($"Invalid type: {Type}"), }; /// @@ -48,7 +48,7 @@ public readonly record struct RibbonResult case Mainline: ((RibbonIndex)Value).Fix(args, IsMissing); break; case Index3: ((RibbonIndex3)Value).Fix(args, IsMissing); break; case Index4: ((RibbonIndex4)Value).Fix(args, IsMissing); break; - default: throw new ArgumentOutOfRangeException(); + default: throw new ArgumentException($"Invalid type: {Type}"); } } } diff --git a/PKHeX.Core/Legality/Verifiers/Ribbons/RibbonResultList.cs b/PKHeX.Core/Legality/Verifiers/Ribbons/RibbonResultList.cs index 5c557bd5d..5528dd99f 100644 --- a/PKHeX.Core/Legality/Verifiers/Ribbons/RibbonResultList.cs +++ b/PKHeX.Core/Legality/Verifiers/Ribbons/RibbonResultList.cs @@ -14,11 +14,7 @@ public ref struct RibbonResultList /// public int Count { get; private set; } - public RibbonResultList(Span span) - { - Span = span; - Count = 0; - } + public RibbonResultList(Span span) => Span = span; private void Add(RibbonResult item) => Span[Count++] = item; diff --git a/PKHeX.Core/Legality/Verifiers/Ribbons/RibbonRules.cs b/PKHeX.Core/Legality/Verifiers/Ribbons/RibbonRules.cs index d108f6544..7b3dd5005 100644 --- a/PKHeX.Core/Legality/Verifiers/Ribbons/RibbonRules.cs +++ b/PKHeX.Core/Legality/Verifiers/Ribbons/RibbonRules.cs @@ -28,7 +28,7 @@ public static class RibbonRules public static bool IsRibbonValidEffort(PKM pk, EvolutionHistory evos, int gen) => gen switch { 5 when pk.Format == 5 => false, // Not available in BW/B2W2 - 8 when !evos.HasVisitedSWSH && !evos.HasVisitedBDSP => false, // not available in PLA + 8 when evos is { HasVisitedSWSH: false, HasVisitedBDSP: false } => false, // not available in PLA _ => true, }; @@ -38,7 +38,7 @@ public static class RibbonRules public static bool IsRibbonValidBestFriends(PKM pk, EvolutionHistory evos, int gen) => gen switch { < 7 when pk is { IsUntraded: true } and IAffection { OT_Affection: < 255 } => false, // Gen6/7 uses affection. Can't lower it on OT! - 8 when !evos.HasVisitedSWSH && !evos.HasVisitedBDSP => false, // Gen8+ replaced with Max Friendship. + 8 when evos is { HasVisitedSWSH: false, HasVisitedBDSP: false } => false, // Gen8+ replaced with Max Friendship. _ => true, }; @@ -101,7 +101,7 @@ public static class RibbonRules { // Ranked is still ongoing, but the use of Mythicals was restricted to Series 13 only. var met = pk.MetDate; - if (Legal.Mythicals.Contains(pk.Species) && met > new DateTime(2022, 11, 1)) + if (Legal.Mythicals.Contains(pk.Species) && met > new DateOnly(2022, 11, 1)) return false; } @@ -113,11 +113,13 @@ public static class RibbonRules private static bool IsRibbonValidMasterRankSV(ISpeciesForm pk) { var species = pk.Species; + if (Legal.Mythicals.Contains(species)) + return false; if (Legal.Legends.Contains(species)) return false; if (Legal.SubLegends.Contains(species)) return false; - if (species is >= (int)Species.GreatTusk and <= (int)Species.IronValiant) + if (Legal.IsParadox(species)) return false; var pt = PersonalTable.SV; @@ -210,7 +212,7 @@ public static class RibbonRules var species = evo.Species; if (species >= arr.Length) continue; - if (!arr[species]) + if (arr[species]) return true; } return false; @@ -218,7 +220,7 @@ public static class RibbonRules // Derived from ROM data: true for all Footprint types besides 5 (5 = no feet). // If true, requires gaining 30 levels to obtain ribbon. If false, can obtain ribbon at any level. - private static readonly bool[] HasFootprintBDSP = + private static ReadOnlySpan HasFootprintBDSP => new[] { true, true, true, true, true, true, true, true, true, true, true, false, true, true, false, true, true, true, true, true, @@ -232,9 +234,9 @@ public static class RibbonRules true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, - false, false, true, true, true, true, true, true, true, true, + false, false, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, false, true, true, - false, true, true, true, true, true, true, true, true, true, + false, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, false, true, @@ -249,7 +251,7 @@ public static class RibbonRules true, true, true, true, true, true, false, true, false, true, true, true, true, false, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, - false, true, true, true, true, true, true, true, true, false, + false, true, true, true, true, true, true, true, true, false, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, @@ -372,15 +374,15 @@ public static class RibbonRules if (!evos.HasVisitedGen4) return false; var head = evos.Gen4[0]; - return IsAllowedBattleFrontier(head.Species, head.Form, 4); + return IsAllowedBattleFrontier(head.Species, head.Form, EntityContext.Gen4); } /// /// Checks if the input species-form could have participated in a specific Battle Frontier trial. /// - public static bool IsAllowedBattleFrontier(ushort species, byte form, int generation) + public static bool IsAllowedBattleFrontier(ushort species, byte form, EntityContext context) { - if (generation == 4 && species == (int)Species.Pichu && form == 1) // spiky + if (context == EntityContext.Gen4 && species == (int)Species.Pichu && form == 1) // spiky return false; return IsAllowedBattleFrontier(species); } diff --git a/PKHeX.Core/Legality/Verifiers/Ribbons/RibbonStrings.cs b/PKHeX.Core/Legality/Verifiers/Ribbons/RibbonStrings.cs index 31cc14b86..34882888d 100644 --- a/PKHeX.Core/Legality/Verifiers/Ribbons/RibbonStrings.cs +++ b/PKHeX.Core/Legality/Verifiers/Ribbons/RibbonStrings.cs @@ -1,4 +1,4 @@ -using System.Collections.Generic; +using System.Collections.Generic; namespace PKHeX.Core; @@ -37,7 +37,7 @@ public static class RibbonStrings { // Throw an exception with the requested property name as the message, rather than an ambiguous "key not present" message. // We should ALWAYS have the key present as the input arguments are not user-defined, rather, they are from PKM property names. - if (!RibbonNames.TryGetValue(propertyName, out string value)) + if (!RibbonNames.TryGetValue(propertyName, out var value)) throw new KeyNotFoundException(propertyName); return value; } diff --git a/PKHeX.Core/Legality/Verifiers/Ribbons/RibbonVerifierCommon4.cs b/PKHeX.Core/Legality/Verifiers/Ribbons/RibbonVerifierCommon4.cs index 3df2ae77c..d92e35198 100644 --- a/PKHeX.Core/Legality/Verifiers/Ribbons/RibbonVerifierCommon4.cs +++ b/PKHeX.Core/Legality/Verifiers/Ribbons/RibbonVerifierCommon4.cs @@ -19,7 +19,7 @@ public static class RibbonVerifierCommon4 bool gen4 = evos.HasVisitedGen4; bool gen6 = evos.HasVisitedGen6; bool bdsp = evos.HasVisitedBDSP; - bool oras6 = gen6 && !(pk.IsUntraded && pk.XY); + bool oras6 = gen6 && pk is not { IsUntraded: true, XY: true }; bool sinnoh4 = gen4 && args.Encounter is not EncounterStatic4 { Species: (int)Species.Pichu, Form: 1 }; bool sinnohChamp = sinnoh4 || bdsp; // no gen4 hg/ss bool cosmetic = sinnoh4 || oras6 || bdsp; // no gen4 hg/ss diff --git a/PKHeX.Core/Legality/Verifiers/Ribbons/RibbonVerifierCommon6.cs b/PKHeX.Core/Legality/Verifiers/Ribbons/RibbonVerifierCommon6.cs index 403c466a2..38eddfd43 100644 --- a/PKHeX.Core/Legality/Verifiers/Ribbons/RibbonVerifierCommon6.cs +++ b/PKHeX.Core/Legality/Verifiers/Ribbons/RibbonVerifierCommon6.cs @@ -16,8 +16,8 @@ public static class RibbonVerifierCommon6 bool gen6 = evos.HasVisitedGen6; bool bdsp = evos.HasVisitedBDSP; - bool kalos6 = gen6 && !(pk.IsUntraded && pk.AO) && args.Encounter is not EncounterStatic6 { Species: (int)Species.Pikachu, Form: not 0 }; - bool oras6 = gen6 && !(pk.IsUntraded && pk.XY); + bool kalos6 = gen6 && pk is not { IsUntraded: true, AO: true } && args.Encounter is not EncounterStatic6 { Species: (int)Species.Pikachu, Form: not 0 }; + bool oras6 = gen6 && pk is not { IsUntraded: true, XY: true }; bool contest = oras6 || bdsp; bool k = r.RibbonChampionKalos; diff --git a/PKHeX.Core/Legality/Verifiers/Ribbons/RibbonVerifierCommon8.cs b/PKHeX.Core/Legality/Verifiers/Ribbons/RibbonVerifierCommon8.cs index 65e576758..3e40f924b 100644 --- a/PKHeX.Core/Legality/Verifiers/Ribbons/RibbonVerifierCommon8.cs +++ b/PKHeX.Core/Legality/Verifiers/Ribbons/RibbonVerifierCommon8.cs @@ -26,7 +26,6 @@ public static class RibbonVerifierCommon8 { list.Add(MasterRank); } - else { // If it can exist in SW/SH, it can have the ribbon. diff --git a/PKHeX.Core/Legality/Verifiers/Ribbons/RibbonVerifierCommon9.cs b/PKHeX.Core/Legality/Verifiers/Ribbons/RibbonVerifierCommon9.cs index 520bba29e..6a9b5a9b8 100644 --- a/PKHeX.Core/Legality/Verifiers/Ribbons/RibbonVerifierCommon9.cs +++ b/PKHeX.Core/Legality/Verifiers/Ribbons/RibbonVerifierCommon9.cs @@ -9,7 +9,6 @@ public static class RibbonVerifierCommon9 { public static void Parse(this IRibbonSetCommon9 r, RibbonVerifierArguments args, ref RibbonResultList list) { - var evos = args.History; if (r.RibbonChampionPaldea && !args.History.HasVisitedGen9) list.Add(ChampionPaldea); if (r.RibbonOnceInALifetime) // Flag it. diff --git a/PKHeX.Core/Legality/Verifiers/Ribbons/RibbonVerifierUnique4.cs b/PKHeX.Core/Legality/Verifiers/Ribbons/RibbonVerifierUnique4.cs index 8efc9cbe3..5885e8c0b 100644 --- a/PKHeX.Core/Legality/Verifiers/Ribbons/RibbonVerifierUnique4.cs +++ b/PKHeX.Core/Legality/Verifiers/Ribbons/RibbonVerifierUnique4.cs @@ -37,12 +37,12 @@ public static class RibbonVerifierUnique4 if (Hyper) top = true; else if (top) - list.Add((RibbonIndex3)((byte)index + 2)); + list.Add(index + 2); if (Super) top = true; else if (top) - list.Add((RibbonIndex3)((byte)index + 1)); + list.Add(index + 1); if (top && !Initial) list.Add(index); @@ -62,12 +62,12 @@ public static class RibbonVerifierUnique4 if (Ultra) top = true; else if (top) - list.Add((RibbonIndex4)((byte)index + 2)); + list.Add(index + 2); if (Great) top = true; else if (top) - list.Add((RibbonIndex4)((byte)index + 1)); + list.Add(index + 1); if (top && !Initial) list.Add(index); @@ -100,11 +100,11 @@ public static class RibbonVerifierUnique4 static void CheckSet(bool Master, bool Hyper, bool Super, bool Initial, ref RibbonResultList list, RibbonIndex3 index) { if (Master) - list.Add((RibbonIndex3)((byte)index + 3)); + list.Add(index + 3); if (Hyper) - list.Add((RibbonIndex3)((byte)index + 2)); + list.Add(index + 2); if (Super) - list.Add((RibbonIndex3)((byte)index + 1)); + list.Add(index + 1); if (Initial) list.Add(index); } @@ -120,11 +120,11 @@ public static class RibbonVerifierUnique4 static void CheckSet(bool Master, bool Ultra, bool Great, bool Initial, ref RibbonResultList list, RibbonIndex4 index) { if (Master) - list.Add((RibbonIndex4)((byte)index + 3)); + list.Add(index + 3); if (Ultra) - list.Add((RibbonIndex4)((byte)index + 2)); + list.Add(index + 2); if (Great) - list.Add((RibbonIndex4)((byte)index + 1)); + list.Add(index + 1); if (Initial) list.Add(index); } diff --git a/PKHeX.Core/Legality/Verifiers/TrainerIDVerifier.cs b/PKHeX.Core/Legality/Verifiers/TrainerIDVerifier.cs index 935356cb1..fe5220746 100644 --- a/PKHeX.Core/Legality/Verifiers/TrainerIDVerifier.cs +++ b/PKHeX.Core/Legality/Verifiers/TrainerIDVerifier.cs @@ -17,54 +17,47 @@ public sealed class TrainerIDVerifier : Verifier if (pk.BDSP) { - if (pk.TID == 0 && pk.SID == 0) // Game loops to ensure a nonzero full-ID - { - data.AddLine(GetInvalid(LOT_IDInvalid)); - return; - } - if (pk.TID == 0xFFFF && pk.SID == 0x7FFF) // int.MaxValue cannot be yielded by Unity's Random.Range[min, max) + // Game loops to ensure a nonzero full-ID + // int.MaxValue cannot be yielded by Unity's Random.Range[min, max) + var id32 = pk.ID32; + if (id32 is 0 or int.MaxValue) { data.AddLine(GetInvalid(LOT_IDInvalid)); return; } } - else if (pk.VC && pk.SID != 0) + else if (pk.VC && pk.SID16 != 0) { data.AddLine(GetInvalid(LOT_SID0Invalid)); return; } - if (pk.TID == 0 && pk.SID == 0) + if (pk is { ID32: 0 }) { data.AddLine(Get(LOT_IDs0, Severity.Fishy)); } - else if (pk.TID == pk.SID) + else if (pk.TID16 == pk.SID16) { data.AddLine(Get(LOT_IDEqual, Severity.Fishy)); } - else if (pk.TID == 0) + else if (pk.TID16 == 0) { data.AddLine(Get(LOT_TID0, Severity.Fishy)); } - else if (pk.SID == 0) + else if (pk.SID16 == 0) { data.AddLine(Get(LOT_SID0, Severity.Fishy)); } - else if (IsOTIDSuspicious(pk.TID, pk.SID)) + else if (IsOTIDSuspicious(pk.TID16, pk.SID16)) { data.AddLine(Get(LOTSuspicious, Severity.Fishy)); } } - public static bool IsOTIDSuspicious(int tid16, int sid16) + public static bool IsOTIDSuspicious(ushort tid16, ushort sid16) => (tid16, sid16) switch { - if (tid16 == 12345 && sid16 == 54321) - return true; - - // 1234_123456 (SID7_TID7) - if (tid16 == 15040 && sid16 == 18831) - return true; - - return false; - } + (12345, 54321) => true, + (15040, 18831) => true, // 1234_123456 (SID7_TID7) + _ => false, + }; } diff --git a/PKHeX.Core/Legality/Verifiers/TrainerNameVerifier.cs b/PKHeX.Core/Legality/Verifiers/TrainerNameVerifier.cs index e37732461..226d4a1c1 100644 --- a/PKHeX.Core/Legality/Verifiers/TrainerNameVerifier.cs +++ b/PKHeX.Core/Legality/Verifiers/TrainerNameVerifier.cs @@ -1,4 +1,4 @@ -using System; +using System; using static PKHeX.Core.LegalityCheckStrings; namespace PKHeX.Core; @@ -44,13 +44,13 @@ public sealed class TrainerNameVerifier : Verifier if (ParseSettings.CheckWordFilter) { - if (WordFilter.IsFiltered(ot, out string bad)) - data.AddLine(GetInvalid($"Wordfilter: {bad}")); + if (WordFilter.IsFiltered(ot, out var badPattern)) + data.AddLine(GetInvalid($"Wordfilter: {badPattern}")); if (ContainsTooManyNumbers(ot, data.Info.Generation)) data.AddLine(GetInvalid("Wordfilter: Too many numbers.")); - if (WordFilter.IsFiltered(pk.HT_Name, out bad)) - data.AddLine(GetInvalid($"Wordfilter: {bad}")); + if (WordFilter.IsFiltered(pk.HT_Name, out badPattern)) + data.AddLine(GetInvalid($"Wordfilter: {badPattern}")); } } @@ -93,7 +93,7 @@ public sealed class TrainerNameVerifier : Verifier if (tr.Length == 0) { - if (pk is SK2 {TID: 0, IsRental: true}) + if (pk is SK2 {TID16: 0, IsRental: true}) { data.AddLine(Get(LOTShort, Severity.Fishy)); } @@ -104,11 +104,11 @@ public sealed class TrainerNameVerifier : Verifier } } - VerifyG1OTWithinBounds(data, tr.AsSpan()); + VerifyG1OTWithinBounds(data, tr); if (pk.OT_Gender == 1) { - if (pk is ICaughtData2 {CaughtData:0} || (pk.Format > 2 && pk.VC1) || data is {EncounterOriginal: {Generation:1} or EncounterStatic2E {IsGift:true}}) + if (pk is ICaughtData2 {CaughtData:0} or { Format: > 2, VC1: true } || data is {EncounterOriginal: {Generation:1} or EncounterStatic2E {IsGift:true}}) data.AddLine(GetInvalid(LG1OTGender)); } } diff --git a/PKHeX.Core/Legality/Verifiers/TransferVerifier.cs b/PKHeX.Core/Legality/Verifiers/TransferVerifier.cs index 7839728a6..89dbf871a 100644 --- a/PKHeX.Core/Legality/Verifiers/TransferVerifier.cs +++ b/PKHeX.Core/Legality/Verifiers/TransferVerifier.cs @@ -220,7 +220,9 @@ public sealed class TransferVerifier : Verifier if (pk.Gender == 1) // female { - if (pk.PersonalInfo.Gender == 31 && pk.IsShiny) // impossible gender-shiny + var enc = data.EncounterOriginal; + var pi = PersonalTable.USUM[enc.Species]; + if (pi.Gender == 31 && pk.IsShiny) // impossible gender-shiny data.AddLine(GetInvalid(LEncStaticPIDShiny, CheckIdentifier.PID)); } else if (pk.Species == (int)Species.Unown) diff --git a/PKHeX.Core/Moves/MoveInfo.cs b/PKHeX.Core/Moves/MoveInfo.cs index 0732f988c..add396aab 100644 --- a/PKHeX.Core/Moves/MoveInfo.cs +++ b/PKHeX.Core/Moves/MoveInfo.cs @@ -48,13 +48,13 @@ public static class MoveInfo /// /// Gets a collection that can be used to check if a move cannot be used in battle. /// - public static ICollection GetDummiedMovesHashSet(EntityContext context) => context switch + public static IReadOnlySet? GetDummiedMovesHashSet(EntityContext context) => context switch { Gen8 => MoveInfo8.DummiedMoves_SWSH, Gen8a => MoveInfo8a.DummiedMoves_LA, Gen8b => MoveInfo8b.DummiedMoves_BDSP, Gen9 => MoveInfo9.DummiedMoves_SV, - _ => Array.Empty(), + _ => null, }; /// @@ -80,28 +80,13 @@ public static class MoveInfo /// Assumes the move ID is within [0,max]. public static bool IsMoveKnowable(ushort move) => !IsMoveZ(move) && !IsMoveDynamax(move); - /// - /// Checks if the move can be sketched in any game. - /// - public static bool IsMoveSketch(ushort move) => move switch - { - // Can't Sketch - (int)Struggle => false, - (int)Chatter => false, - - // Unreleased - (int)LightofRuin => false, - - _ => IsMoveKnowable(move), - }; - /// /// Checks if the is unable to be used in battle. /// public static bool IsDummiedMove(PKM pk, ushort move) { var hashSet = GetDummiedMovesHashSet(pk.Context); - return hashSet.Contains(move); + return hashSet?.Contains(move) ?? false; } /// @@ -110,7 +95,7 @@ public static class MoveInfo public static bool IsDummiedMoveAny(PKM pk) { var hs = GetDummiedMovesHashSet(pk.Context); - if (hs.Count == 0) + if (hs is null) return false; for (int i = 0; i < 4; i++) @@ -128,23 +113,44 @@ public static class MoveInfo /// Move ID /// Generation to check /// True if can be sketched, false if not available. - public static bool IsValidSketch(ushort move, EntityContext context) + public static bool IsSketchValid(ushort move, EntityContext context) { - if (!IsMoveSketch(move)) + if (move > GetMaxMoveID(context)) return false; - if (context is Gen6 && move is ((int)ThousandArrows or (int)ThousandWaves)) + if (!IsSketchPossible(move)) return false; - if (context is Gen8b) // can't Sketch unusable moves in BDSP, no Sketch in PLA - { - if (MoveInfo8b.DummiedMoves_BDSP.Contains(move)) - return false; - if (move > Legal.MaxMoveID_8) - return false; - } - - return move <= GetMaxMoveID(context); + if (!IsSketchPossible(move, context)) + return false; + return true; } + /// + /// Checks if the move can be sketched in any game. + /// + private static bool IsSketchPossible(ushort move) => move switch + { + // Can't Sketch + (int)Struggle => false, + (int)Chatter => false, + + // Unreleased + (int)LightofRuin => false, + + _ => IsMoveKnowable(move), + }; + + /// + /// Checks if the move can be sketched in a specific game context. Pre-check with . + /// + /// + /// + private static bool IsSketchPossible(ushort move, EntityContext context) => context switch + { + Gen6 when move is (int)ThousandArrows or (int)ThousandWaves => false, + Gen8b when MoveInfo8b.DummiedMoves_BDSP.Contains(move) => false, + _ => true, + }; + private static int GetMaxMoveID(EntityContext context) => context switch { Gen1 => Legal.MaxMoveID_1, diff --git a/PKHeX.Core/Moves/MoveInfo1.cs b/PKHeX.Core/Moves/MoveInfo1.cs index f4cc09735..80dd59e73 100644 --- a/PKHeX.Core/Moves/MoveInfo1.cs +++ b/PKHeX.Core/Moves/MoveInfo1.cs @@ -1,3 +1,5 @@ +using System; + namespace PKHeX.Core; /// @@ -5,12 +7,16 @@ namespace PKHeX.Core; /// internal static class MoveInfo1 { - public static readonly byte[] MovePP_RBY = + public static ReadOnlySpan MovePP_RBY => new byte[] { - 0, - 35, 25, 10, 15, 20, 20, 15, 15, 15, 35, 30, 05, 10, 30, 30, 35, 35, 20, 15, 20, 20, 10, 20, 30, 05, 25, 15, 15, 15, 25, 20, 05, 35, 15, 20, 20, 20, 15, 30, 35, 20, 20, 30, 25, 40, 20, 15, 20, 20, 20, - 30, 25, 15, 30, 25, 05, 15, 10, 05, 20, 20, 20, 05, 35, 20, 25, 20, 20, 20, 15, 20, 10, 10, 40, 25, 10, 35, 30, 15, 20, 40, 10, 15, 30, 15, 20, 10, 15, 10, 05, 10, 10, 25, 10, 20, 40, 30, 30, 20, 20, - 15, 10, 40, 15, 20, 30, 20, 20, 10, 40, 40, 30, 30, 30, 20, 30, 10, 10, 20, 05, 10, 30, 20, 20, 20, 05, 15, 10, 20, 15, 15, 35, 20, 15, 10, 20, 30, 15, 40, 20, 15, 10, 05, 10, 30, 10, 15, 20, 15, 40, - 40, 10, 05, 15, 10, 10, 10, 15, 30, 30, 10, 10, 20, 10, 10, + 00, 35, 25, 10, 15, 20, 20, 15, 15, 15, 35, 30, 05, 10, 30, 30, 35, 35, 20, 15, + 20, 20, 10, 20, 30, 05, 25, 15, 15, 15, 25, 20, 05, 35, 15, 20, 20, 20, 15, 30, + 35, 20, 20, 30, 25, 40, 20, 15, 20, 20, 20, 30, 25, 15, 30, 25, 05, 15, 10, 05, + 20, 20, 20, 05, 35, 20, 25, 20, 20, 20, 15, 20, 10, 10, 40, 25, 10, 35, 30, 15, + 20, 40, 10, 15, 30, 15, 20, 10, 15, 10, 05, 10, 10, 25, 10, 20, 40, 30, 30, 20, + 20, 15, 10, 40, 15, 20, 30, 20, 20, 10, 40, 40, 30, 30, 30, 20, 30, 10, 10, 20, + 05, 10, 30, 20, 20, 20, 05, 15, 10, 20, 15, 15, 35, 20, 15, 10, 20, 30, 15, 40, + 20, 15, 10, 05, 10, 30, 10, 15, 20, 15, 40, 40, 10, 05, 15, 10, 10, 10, 15, 30, + 30, 10, 10, 20, 10, 10, }; } diff --git a/PKHeX.Core/Moves/MoveInfo2.cs b/PKHeX.Core/Moves/MoveInfo2.cs index 7e36cd841..354740457 100644 --- a/PKHeX.Core/Moves/MoveInfo2.cs +++ b/PKHeX.Core/Moves/MoveInfo2.cs @@ -1,3 +1,5 @@ +using System; + namespace PKHeX.Core; /// @@ -5,14 +7,20 @@ namespace PKHeX.Core; /// internal static class MoveInfo2 { - public static readonly byte[] MovePP_GSC = + public static ReadOnlySpan MovePP_GSC => new byte[] { - 00, - 35, 25, 10, 15, 20, 20, 15, 15, 15, 35, 30, 05, 10, 30, 30, 35, 35, 20, 15, 20, 20, 10, 20, 30, 05, 25, 15, 15, 15, 25, 20, 05, 35, 15, 20, 20, 20, 15, 30, 35, 20, 20, 30, 25, 40, 20, 15, 20, 20, 20, - 30, 25, 15, 30, 25, 05, 15, 10, 05, 20, 20, 20, 05, 35, 20, 25, 20, 20, 20, 15, 20, 10, 10, 40, 25, 10, 35, 30, 15, 20, 40, 10, 15, 30, 15, 20, 10, 15, 10, 05, 10, 10, 25, 10, 20, 40, 30, 30, 20, 20, - 15, 10, 40, 15, 20, 30, 20, 20, 10, 40, 40, 30, 30, 30, 20, 30, 10, 10, 20, 05, 10, 30, 20, 20, 20, 05, 15, 10, 20, 15, 15, 35, 20, 15, 10, 20, 30, 15, 40, 20, 15, 10, 05, 10, 30, 10, 15, 20, 15, 40, - 40, 10, 05, 15, 10, 10, 10, 15, 30, 30, 10, 10, 20, 10, 01, 01, 10, 10, 10, 05, 15, 25, 15, 10, 15, 30, 05, 40, 15, 10, 25, 10, 30, 10, 20, 10, 10, 10, 10, 10, 20, 05, 40, 05, 05, 15, 05, 10, 05, 15, - 10, 05, 10, 20, 20, 40, 15, 10, 20, 20, 25, 05, 15, 10, 05, 20, 15, 20, 25, 20, 05, 30, 05, 10, 20, 40, 05, 20, 40, 20, 15, 35, 10, 05, 05, 05, 15, 05, 20, 05, 05, 15, 20, 10, 05, 05, 15, 15, 15, 15, - 10, + 00, 35, 25, 10, 15, 20, 20, 15, 15, 15, 35, 30, 05, 10, 30, 30, 35, 35, 20, 15, + 20, 20, 10, 20, 30, 05, 25, 15, 15, 15, 25, 20, 05, 35, 15, 20, 20, 20, 15, 30, + 35, 20, 20, 30, 25, 40, 20, 15, 20, 20, 20, 30, 25, 15, 30, 25, 05, 15, 10, 05, + 20, 20, 20, 05, 35, 20, 25, 20, 20, 20, 15, 20, 10, 10, 40, 25, 10, 35, 30, 15, + 20, 40, 10, 15, 30, 15, 20, 10, 15, 10, 05, 10, 10, 25, 10, 20, 40, 30, 30, 20, + 20, 15, 10, 40, 15, 20, 30, 20, 20, 10, 40, 40, 30, 30, 30, 20, 30, 10, 10, 20, + 05, 10, 30, 20, 20, 20, 05, 15, 10, 20, 15, 15, 35, 20, 15, 10, 20, 30, 15, 40, + 20, 15, 10, 05, 10, 30, 10, 15, 20, 15, 40, 40, 10, 05, 15, 10, 10, 10, 15, 30, + 30, 10, 10, 20, 10, 01, 01, 10, 10, 10, 05, 15, 25, 15, 10, 15, 30, 05, 40, 15, + 10, 25, 10, 30, 10, 20, 10, 10, 10, 10, 10, 20, 05, 40, 05, 05, 15, 05, 10, 05, + 15, 10, 05, 10, 20, 20, 40, 15, 10, 20, 20, 25, 05, 15, 10, 05, 20, 15, 20, 25, + 20, 05, 30, 05, 10, 20, 40, 05, 20, 40, 20, 15, 35, 10, 05, 05, 05, 15, 05, 20, + 05, 05, 15, 20, 10, 05, 05, 15, 15, 15, 15, 10, }; } diff --git a/PKHeX.Core/Moves/MoveInfo3.cs b/PKHeX.Core/Moves/MoveInfo3.cs index 4e9dbbd00..3a9122951 100644 --- a/PKHeX.Core/Moves/MoveInfo3.cs +++ b/PKHeX.Core/Moves/MoveInfo3.cs @@ -1,3 +1,5 @@ +using System; + namespace PKHeX.Core; /// @@ -5,16 +7,25 @@ namespace PKHeX.Core; /// internal static class MoveInfo3 { - public static readonly byte[] MovePP_RS = + public static ReadOnlySpan MovePP_RS => new byte[] { - 00, - 35, 25, 10, 15, 20, 20, 15, 15, 15, 35, 30, 05, 10, 30, 30, 35, 35, 20, 15, 20, 20, 10, 20, 30, 05, 25, 15, 15, 15, 25, 20, 05, 35, 15, 20, 20, 20, 15, 30, 35, 20, 20, 30, 25, 40, 20, 15, 20, 20, 20, - 30, 25, 15, 30, 25, 05, 15, 10, 05, 20, 20, 20, 05, 35, 20, 25, 20, 20, 20, 15, 20, 10, 10, 40, 25, 10, 35, 30, 15, 20, 40, 10, 15, 30, 15, 20, 10, 15, 10, 05, 10, 10, 25, 10, 20, 40, 30, 30, 20, 20, - 15, 10, 40, 15, 20, 30, 20, 20, 10, 40, 40, 30, 30, 30, 20, 30, 10, 10, 20, 05, 10, 30, 20, 20, 20, 05, 15, 10, 20, 15, 15, 35, 20, 15, 10, 20, 30, 15, 40, 20, 15, 10, 05, 10, 30, 10, 15, 20, 15, 40, - 40, 10, 05, 15, 10, 10, 10, 15, 30, 30, 10, 10, 20, 10, 01, 01, 10, 10, 10, 05, 15, 25, 15, 10, 15, 30, 05, 40, 15, 10, 25, 10, 30, 10, 20, 10, 10, 10, 10, 10, 20, 05, 40, 05, 05, 15, 05, 10, 05, 15, - 10, 05, 10, 20, 20, 40, 15, 10, 20, 20, 25, 05, 15, 10, 05, 20, 15, 20, 25, 20, 05, 30, 05, 10, 20, 40, 05, 20, 40, 20, 15, 35, 10, 05, 05, 05, 15, 05, 20, 05, 05, 15, 20, 10, 05, 05, 15, 15, 15, 15, - 10, 10, 10, 10, 10, 10, 10, 10, 15, 15, 15, 10, 20, 20, 10, 20, 20, 20, 20, 20, 10, 10, 10, 20, 20, 05, 15, 10, 10, 15, 10, 20, 05, 05, 10, 10, 20, 05, 10, 20, 10, 20, 20, 20, 05, 05, 15, 20, 10, 15, - 20, 15, 10, 10, 15, 10, 05, 05, 10, 15, 10, 05, 20, 25, 05, 40, 10, 05, 40, 15, 20, 20, 05, 15, 20, 30, 15, 15, 05, 10, 30, 20, 30, 15, 05, 40, 15, 05, 20, 05, 15, 25, 40, 15, 20, 15, 20, 15, 20, 10, - 20, 20, 05, 05, + 00, 35, 25, 10, 15, 20, 20, 15, 15, 15, 35, 30, 05, 10, 30, 30, 35, 35, 20, 15, + 20, 20, 10, 20, 30, 05, 25, 15, 15, 15, 25, 20, 05, 35, 15, 20, 20, 20, 15, 30, + 35, 20, 20, 30, 25, 40, 20, 15, 20, 20, 20, 30, 25, 15, 30, 25, 05, 15, 10, 05, + 20, 20, 20, 05, 35, 20, 25, 20, 20, 20, 15, 20, 10, 10, 40, 25, 10, 35, 30, 15, + 20, 40, 10, 15, 30, 15, 20, 10, 15, 10, 05, 10, 10, 25, 10, 20, 40, 30, 30, 20, + 20, 15, 10, 40, 15, 20, 30, 20, 20, 10, 40, 40, 30, 30, 30, 20, 30, 10, 10, 20, + 05, 10, 30, 20, 20, 20, 05, 15, 10, 20, 15, 15, 35, 20, 15, 10, 20, 30, 15, 40, + 20, 15, 10, 05, 10, 30, 10, 15, 20, 15, 40, 40, 10, 05, 15, 10, 10, 10, 15, 30, + 30, 10, 10, 20, 10, 01, 01, 10, 10, 10, 05, 15, 25, 15, 10, 15, 30, 05, 40, 15, + 10, 25, 10, 30, 10, 20, 10, 10, 10, 10, 10, 20, 05, 40, 05, 05, 15, 05, 10, 05, + 15, 10, 05, 10, 20, 20, 40, 15, 10, 20, 20, 25, 05, 15, 10, 05, 20, 15, 20, 25, + 20, 05, 30, 05, 10, 20, 40, 05, 20, 40, 20, 15, 35, 10, 05, 05, 05, 15, 05, 20, + 05, 05, 15, 20, 10, 05, 05, 15, 15, 15, 15, 10, 10, 10, 10, 10, 10, 10, 10, 15, + 15, 15, 10, 20, 20, 10, 20, 20, 20, 20, 20, 10, 10, 10, 20, 20, 05, 15, 10, 10, + 15, 10, 20, 05, 05, 10, 10, 20, 05, 10, 20, 10, 20, 20, 20, 05, 05, 15, 20, 10, + 15, 20, 15, 10, 10, 15, 10, 05, 05, 10, 15, 10, 05, 20, 25, 05, 40, 10, 05, 40, + 15, 20, 20, 05, 15, 20, 30, 15, 15, 05, 10, 30, 20, 30, 15, 05, 40, 15, 05, 20, + 05, 15, 25, 40, 15, 20, 15, 20, 15, 20, 10, 20, 20, 05, 05, }; } diff --git a/PKHeX.Core/Moves/MoveInfo4.cs b/PKHeX.Core/Moves/MoveInfo4.cs index c719745b3..896865844 100644 --- a/PKHeX.Core/Moves/MoveInfo4.cs +++ b/PKHeX.Core/Moves/MoveInfo4.cs @@ -1,3 +1,5 @@ +using System; + namespace PKHeX.Core; /// @@ -5,18 +7,31 @@ namespace PKHeX.Core; /// internal static class MoveInfo4 { - public static readonly byte[] MovePP_DP = + public static ReadOnlySpan MovePP_DP => new byte[] { - 00, - 35, 25, 10, 15, 20, 20, 15, 15, 15, 35, 30, 05, 10, 30, 30, 35, 35, 20, 15, 20, 20, 15, 20, 30, 05, 25, 15, 15, 15, 25, 20, 05, 35, 15, 20, 20, 20, 15, 30, 35, 20, 20, 30, 25, 40, 20, 15, 20, 20, 20, - 30, 25, 15, 30, 25, 05, 15, 10, 05, 20, 20, 20, 05, 35, 20, 25, 20, 20, 20, 15, 25, 15, 10, 40, 25, 10, 35, 30, 15, 20, 40, 10, 15, 30, 15, 20, 10, 15, 10, 05, 10, 10, 25, 10, 20, 40, 30, 30, 20, 20, - 15, 10, 40, 15, 10, 30, 20, 20, 10, 40, 40, 30, 30, 30, 20, 30, 10, 10, 20, 05, 10, 30, 20, 20, 20, 05, 15, 10, 20, 15, 15, 35, 20, 15, 10, 20, 30, 15, 40, 20, 15, 10, 05, 10, 30, 10, 15, 20, 15, 40, - 40, 10, 05, 15, 10, 10, 10, 15, 30, 30, 10, 10, 20, 10, 01, 01, 10, 10, 10, 05, 15, 25, 15, 10, 15, 30, 05, 40, 15, 10, 25, 10, 30, 10, 20, 10, 10, 10, 10, 10, 20, 05, 40, 05, 05, 15, 05, 10, 05, 15, - 10, 10, 10, 20, 20, 40, 15, 10, 20, 20, 25, 05, 15, 10, 05, 20, 15, 20, 25, 20, 05, 30, 05, 10, 20, 40, 05, 20, 40, 20, 15, 35, 10, 05, 05, 05, 15, 05, 20, 05, 05, 15, 20, 10, 05, 05, 15, 15, 15, 15, - 10, 10, 10, 20, 10, 10, 10, 10, 15, 15, 15, 10, 20, 20, 10, 20, 20, 20, 20, 20, 10, 10, 10, 20, 20, 05, 15, 10, 10, 15, 10, 20, 05, 05, 10, 10, 20, 05, 10, 20, 10, 20, 20, 20, 05, 05, 15, 20, 10, 15, - 20, 15, 10, 10, 15, 10, 05, 05, 10, 15, 10, 05, 20, 25, 05, 40, 10, 05, 40, 15, 20, 20, 05, 15, 20, 30, 15, 15, 05, 10, 30, 20, 30, 15, 05, 40, 15, 05, 20, 05, 15, 25, 40, 15, 20, 15, 20, 15, 20, 10, - 20, 20, 05, 05, 10, 05, 40, 10, 10, 05, 10, 10, 15, 10, 20, 30, 30, 10, 20, 05, 10, 10, 15, 10, 10, 05, 15, 05, 10, 10, 30, 20, 20, 10, 10, 05, 05, 10, 05, 20, 10, 20, 10, 15, 10, 20, 20, 20, 15, 15, - 10, 15, 20, 15, 10, 10, 10, 20, 05, 30, 05, 10, 15, 10, 10, 05, 20, 30, 10, 30, 15, 15, 15, 15, 30, 10, 20, 15, 10, 10, 20, 15, 05, 05, 15, 15, 05, 10, 05, 20, 05, 15, 20, 05, 20, 20, 20, 20, 10, 20, - 10, 15, 20, 15, 10, 10, 05, 10, 05, 05, 10, 05, 05, 10, 05, 05, 05, + 00, 35, 25, 10, 15, 20, 20, 15, 15, 15, 35, 30, 05, 10, 30, 30, 35, 35, 20, 15, + 20, 20, 15, 20, 30, 05, 25, 15, 15, 15, 25, 20, 05, 35, 15, 20, 20, 20, 15, 30, + 35, 20, 20, 30, 25, 40, 20, 15, 20, 20, 20, 30, 25, 15, 30, 25, 05, 15, 10, 05, + 20, 20, 20, 05, 35, 20, 25, 20, 20, 20, 15, 25, 15, 10, 40, 25, 10, 35, 30, 15, + 20, 40, 10, 15, 30, 15, 20, 10, 15, 10, 05, 10, 10, 25, 10, 20, 40, 30, 30, 20, + 20, 15, 10, 40, 15, 10, 30, 20, 20, 10, 40, 40, 30, 30, 30, 20, 30, 10, 10, 20, + 05, 10, 30, 20, 20, 20, 05, 15, 10, 20, 15, 15, 35, 20, 15, 10, 20, 30, 15, 40, + 20, 15, 10, 05, 10, 30, 10, 15, 20, 15, 40, 40, 10, 05, 15, 10, 10, 10, 15, 30, + 30, 10, 10, 20, 10, 01, 01, 10, 10, 10, 05, 15, 25, 15, 10, 15, 30, 05, 40, 15, + 10, 25, 10, 30, 10, 20, 10, 10, 10, 10, 10, 20, 05, 40, 05, 05, 15, 05, 10, 05, + 15, 10, 10, 10, 20, 20, 40, 15, 10, 20, 20, 25, 05, 15, 10, 05, 20, 15, 20, 25, + 20, 05, 30, 05, 10, 20, 40, 05, 20, 40, 20, 15, 35, 10, 05, 05, 05, 15, 05, 20, + 05, 05, 15, 20, 10, 05, 05, 15, 15, 15, 15, 10, 10, 10, 20, 10, 10, 10, 10, 15, + 15, 15, 10, 20, 20, 10, 20, 20, 20, 20, 20, 10, 10, 10, 20, 20, 05, 15, 10, 10, + 15, 10, 20, 05, 05, 10, 10, 20, 05, 10, 20, 10, 20, 20, 20, 05, 05, 15, 20, 10, + 15, 20, 15, 10, 10, 15, 10, 05, 05, 10, 15, 10, 05, 20, 25, 05, 40, 10, 05, 40, + 15, 20, 20, 05, 15, 20, 30, 15, 15, 05, 10, 30, 20, 30, 15, 05, 40, 15, 05, 20, + 05, 15, 25, 40, 15, 20, 15, 20, 15, 20, 10, 20, 20, 05, 05, 10, 05, 40, 10, 10, + 05, 10, 10, 15, 10, 20, 30, 30, 10, 20, 05, 10, 10, 15, 10, 10, 05, 15, 05, 10, + 10, 30, 20, 20, 10, 10, 05, 05, 10, 05, 20, 10, 20, 10, 15, 10, 20, 20, 20, 15, + 15, 10, 15, 20, 15, 10, 10, 10, 20, 05, 30, 05, 10, 15, 10, 10, 05, 20, 30, 10, + 30, 15, 15, 15, 15, 30, 10, 20, 15, 10, 10, 20, 15, 05, 05, 15, 15, 05, 10, 05, + 20, 05, 15, 20, 05, 20, 20, 20, 20, 10, 20, 10, 15, 20, 15, 10, 10, 05, 10, 05, + 05, 10, 05, 05, 10, 05, 05, 05, }; } diff --git a/PKHeX.Core/Moves/MoveInfo5.cs b/PKHeX.Core/Moves/MoveInfo5.cs index 3a139f996..806bc72fd 100644 --- a/PKHeX.Core/Moves/MoveInfo5.cs +++ b/PKHeX.Core/Moves/MoveInfo5.cs @@ -1,3 +1,5 @@ +using System; + namespace PKHeX.Core; /// @@ -5,20 +7,35 @@ namespace PKHeX.Core; /// internal static class MoveInfo5 { - public static readonly byte[] MovePP_BW = + public static ReadOnlySpan MovePP_BW => new byte[] { - 00, - 35, 25, 10, 15, 20, 20, 15, 15, 15, 35, 30, 05, 10, 30, 30, 35, 35, 20, 15, 20, 20, 15, 20, 30, 05, 10, 15, 15, 15, 25, 20, 05, 35, 15, 20, 20, 10, 15, 30, 35, 20, 20, 30, 25, 40, 20, 15, 20, 20, 20, - 30, 25, 15, 30, 25, 05, 15, 10, 05, 20, 20, 20, 05, 35, 20, 25, 20, 20, 20, 15, 25, 15, 10, 40, 25, 10, 35, 30, 15, 10, 40, 10, 15, 30, 15, 20, 10, 15, 10, 05, 10, 10, 25, 10, 20, 40, 30, 30, 20, 20, - 15, 10, 40, 15, 10, 30, 20, 20, 10, 40, 40, 30, 30, 30, 20, 30, 10, 10, 20, 05, 10, 30, 20, 20, 20, 05, 15, 15, 20, 15, 15, 35, 20, 15, 10, 10, 30, 15, 40, 20, 15, 10, 05, 10, 30, 10, 15, 20, 15, 40, - 40, 10, 05, 15, 10, 10, 10, 15, 30, 30, 10, 10, 20, 10, 01, 01, 10, 10, 10, 05, 15, 25, 15, 10, 15, 30, 05, 40, 15, 10, 25, 10, 30, 10, 20, 10, 10, 10, 10, 10, 20, 05, 40, 05, 05, 15, 05, 10, 05, 10, - 10, 10, 10, 20, 20, 40, 15, 10, 20, 20, 25, 05, 15, 10, 05, 20, 15, 20, 25, 20, 05, 30, 05, 10, 20, 40, 05, 20, 40, 20, 15, 35, 10, 05, 05, 05, 15, 05, 20, 05, 05, 15, 20, 10, 05, 05, 15, 10, 15, 15, - 10, 10, 10, 20, 10, 10, 10, 10, 15, 15, 15, 10, 20, 20, 10, 20, 20, 20, 20, 20, 10, 10, 10, 20, 20, 05, 15, 10, 10, 15, 10, 20, 05, 05, 10, 10, 20, 05, 10, 20, 10, 20, 20, 20, 05, 05, 15, 20, 10, 15, - 20, 15, 10, 10, 15, 10, 05, 05, 10, 15, 10, 05, 20, 25, 05, 40, 10, 05, 40, 15, 20, 20, 05, 15, 20, 30, 15, 15, 05, 10, 30, 20, 30, 15, 05, 40, 15, 05, 20, 05, 15, 25, 40, 15, 20, 15, 20, 15, 20, 10, - 20, 20, 05, 05, 10, 05, 40, 10, 10, 05, 10, 10, 15, 10, 20, 30, 30, 10, 20, 05, 10, 10, 15, 10, 10, 05, 15, 05, 10, 10, 30, 20, 20, 10, 10, 05, 05, 10, 05, 20, 10, 20, 10, 15, 10, 20, 20, 20, 15, 15, - 10, 15, 20, 15, 10, 10, 10, 20, 10, 30, 05, 10, 15, 10, 10, 05, 20, 30, 10, 30, 15, 15, 15, 15, 30, 10, 20, 15, 10, 10, 20, 15, 05, 05, 15, 15, 05, 10, 05, 20, 05, 15, 20, 05, 20, 20, 20, 20, 10, 20, - 10, 15, 20, 15, 10, 10, 05, 10, 05, 05, 10, 05, 05, 10, 05, 05, 05, 15, 10, 10, 10, 10, 10, 10, 15, 20, 15, 10, 15, 10, 15, 10, 20, 10, 15, 10, 20, 20, 20, 20, 20, 15, 15, 15, 15, 15, 15, 20, 15, 10, - 15, 15, 15, 15, 10, 10, 10, 10, 10, 15, 15, 15, 15, 05, 05, 15, 05, 10, 10, 10, 20, 20, 20, 10, 10, 30, 15, 15, 10, 15, 25, 10, 20, 10, 10, 10, 20, 10, 10, 10, 10, 10, 15, 15, 05, 05, 10, 10, 10, 05, - 05, 10, 05, 05, 15, 10, 05, 05, 05, + 00, 35, 25, 10, 15, 20, 20, 15, 15, 15, 35, 30, 05, 10, 30, 30, 35, 35, 20, 15, + 20, 20, 15, 20, 30, 05, 10, 15, 15, 15, 25, 20, 05, 35, 15, 20, 20, 10, 15, 30, + 35, 20, 20, 30, 25, 40, 20, 15, 20, 20, 20, 30, 25, 15, 30, 25, 05, 15, 10, 05, + 20, 20, 20, 05, 35, 20, 25, 20, 20, 20, 15, 25, 15, 10, 40, 25, 10, 35, 30, 15, + 10, 40, 10, 15, 30, 15, 20, 10, 15, 10, 05, 10, 10, 25, 10, 20, 40, 30, 30, 20, + 20, 15, 10, 40, 15, 10, 30, 20, 20, 10, 40, 40, 30, 30, 30, 20, 30, 10, 10, 20, + 05, 10, 30, 20, 20, 20, 05, 15, 15, 20, 15, 15, 35, 20, 15, 10, 10, 30, 15, 40, + 20, 15, 10, 05, 10, 30, 10, 15, 20, 15, 40, 40, 10, 05, 15, 10, 10, 10, 15, 30, + 30, 10, 10, 20, 10, 01, 01, 10, 10, 10, 05, 15, 25, 15, 10, 15, 30, 05, 40, 15, + 10, 25, 10, 30, 10, 20, 10, 10, 10, 10, 10, 20, 05, 40, 05, 05, 15, 05, 10, 05, + 10, 10, 10, 10, 20, 20, 40, 15, 10, 20, 20, 25, 05, 15, 10, 05, 20, 15, 20, 25, + 20, 05, 30, 05, 10, 20, 40, 05, 20, 40, 20, 15, 35, 10, 05, 05, 05, 15, 05, 20, + 05, 05, 15, 20, 10, 05, 05, 15, 10, 15, 15, 10, 10, 10, 20, 10, 10, 10, 10, 15, + 15, 15, 10, 20, 20, 10, 20, 20, 20, 20, 20, 10, 10, 10, 20, 20, 05, 15, 10, 10, + 15, 10, 20, 05, 05, 10, 10, 20, 05, 10, 20, 10, 20, 20, 20, 05, 05, 15, 20, 10, + 15, 20, 15, 10, 10, 15, 10, 05, 05, 10, 15, 10, 05, 20, 25, 05, 40, 10, 05, 40, + 15, 20, 20, 05, 15, 20, 30, 15, 15, 05, 10, 30, 20, 30, 15, 05, 40, 15, 05, 20, + 05, 15, 25, 40, 15, 20, 15, 20, 15, 20, 10, 20, 20, 05, 05, 10, 05, 40, 10, 10, + 05, 10, 10, 15, 10, 20, 30, 30, 10, 20, 05, 10, 10, 15, 10, 10, 05, 15, 05, 10, + 10, 30, 20, 20, 10, 10, 05, 05, 10, 05, 20, 10, 20, 10, 15, 10, 20, 20, 20, 15, + 15, 10, 15, 20, 15, 10, 10, 10, 20, 10, 30, 05, 10, 15, 10, 10, 05, 20, 30, 10, + 30, 15, 15, 15, 15, 30, 10, 20, 15, 10, 10, 20, 15, 05, 05, 15, 15, 05, 10, 05, + 20, 05, 15, 20, 05, 20, 20, 20, 20, 10, 20, 10, 15, 20, 15, 10, 10, 05, 10, 05, + 05, 10, 05, 05, 10, 05, 05, 05, 15, 10, 10, 10, 10, 10, 10, 15, 20, 15, 10, 15, + 10, 15, 10, 20, 10, 15, 10, 20, 20, 20, 20, 20, 15, 15, 15, 15, 15, 15, 20, 15, + 10, 15, 15, 15, 15, 10, 10, 10, 10, 10, 15, 15, 15, 15, 05, 05, 15, 05, 10, 10, + 10, 20, 20, 20, 10, 10, 30, 15, 15, 10, 15, 25, 10, 20, 10, 10, 10, 20, 10, 10, + 10, 10, 10, 15, 15, 05, 05, 10, 10, 10, 05, 05, 10, 05, 05, 15, 10, 05, 05, 05, }; } diff --git a/PKHeX.Core/Moves/MoveInfo6.cs b/PKHeX.Core/Moves/MoveInfo6.cs index 4cf31c852..bf136caed 100644 --- a/PKHeX.Core/Moves/MoveInfo6.cs +++ b/PKHeX.Core/Moves/MoveInfo6.cs @@ -1,3 +1,5 @@ +using System; + namespace PKHeX.Core; /// @@ -5,21 +7,39 @@ namespace PKHeX.Core; /// internal static class MoveInfo6 { - public static readonly byte[] MovePP = + public static ReadOnlySpan MovePP => new byte[] { - 00, - 35, 25, 10, 15, 20, 20, 15, 15, 15, 35, 30, 05, 10, 20, 30, 35, 35, 20, 15, 20, 20, 25, 20, 30, 05, 10, 15, 15, 15, 25, 20, 05, 35, 15, 20, 20, 10, 15, 30, 35, 20, 20, 30, 25, 40, 20, 15, 20, 20, 20, - 30, 25, 15, 30, 25, 05, 15, 10, 05, 20, 20, 20, 05, 35, 20, 25, 20, 20, 20, 15, 25, 15, 10, 20, 25, 10, 35, 30, 15, 10, 40, 10, 15, 30, 15, 20, 10, 15, 10, 05, 10, 10, 25, 10, 20, 40, 30, 30, 20, 20, - 15, 10, 40, 15, 10, 30, 10, 20, 10, 40, 40, 20, 30, 30, 20, 30, 10, 10, 20, 05, 10, 30, 20, 20, 20, 05, 15, 15, 20, 10, 15, 35, 20, 15, 10, 10, 30, 15, 40, 20, 15, 10, 05, 10, 30, 10, 15, 20, 15, 40, - 20, 10, 05, 15, 10, 10, 10, 15, 30, 30, 10, 10, 20, 10, 01, 01, 10, 25, 10, 05, 15, 25, 15, 10, 15, 30, 05, 40, 15, 10, 25, 10, 30, 10, 20, 10, 10, 10, 10, 10, 20, 05, 40, 05, 05, 15, 05, 10, 05, 10, - 10, 10, 10, 20, 20, 40, 15, 10, 20, 20, 25, 05, 15, 10, 05, 20, 15, 20, 25, 20, 05, 30, 05, 10, 20, 40, 05, 20, 40, 20, 15, 35, 10, 05, 05, 05, 15, 05, 20, 05, 05, 15, 20, 10, 05, 05, 15, 10, 15, 15, - 10, 10, 10, 20, 10, 10, 10, 10, 15, 15, 15, 10, 20, 20, 10, 20, 20, 20, 20, 20, 10, 10, 10, 20, 20, 05, 15, 10, 10, 15, 10, 20, 05, 05, 10, 10, 20, 05, 10, 20, 10, 20, 20, 20, 05, 05, 15, 20, 10, 15, - 20, 15, 10, 10, 15, 10, 05, 05, 10, 15, 10, 05, 20, 25, 05, 40, 15, 05, 40, 15, 20, 20, 05, 15, 20, 20, 15, 15, 05, 10, 30, 20, 30, 15, 05, 40, 15, 05, 20, 05, 15, 25, 25, 15, 20, 15, 20, 15, 20, 10, - 20, 20, 05, 05, 10, 05, 40, 10, 10, 05, 10, 10, 15, 10, 20, 15, 30, 10, 20, 05, 10, 10, 15, 10, 10, 05, 15, 05, 10, 10, 30, 20, 20, 10, 10, 05, 05, 10, 05, 20, 10, 20, 10, 15, 10, 20, 20, 20, 15, 15, - 10, 15, 15, 15, 10, 10, 10, 20, 10, 30, 05, 10, 15, 10, 10, 05, 20, 30, 10, 30, 15, 15, 15, 15, 30, 10, 20, 15, 10, 10, 20, 15, 05, 05, 15, 15, 05, 10, 05, 20, 05, 15, 20, 05, 20, 20, 20, 20, 10, 20, - 10, 15, 20, 15, 10, 10, 05, 10, 05, 05, 10, 05, 05, 10, 05, 05, 05, 15, 10, 10, 10, 10, 10, 10, 15, 20, 15, 10, 15, 10, 15, 10, 20, 10, 10, 10, 20, 20, 20, 20, 20, 15, 15, 15, 15, 15, 15, 20, 15, 10, - 15, 15, 15, 15, 10, 10, 10, 10, 10, 15, 15, 15, 15, 05, 05, 15, 05, 10, 10, 10, 20, 20, 20, 10, 10, 30, 15, 15, 10, 15, 25, 10, 15, 10, 10, 10, 20, 10, 10, 10, 10, 10, 15, 15, 05, 05, 10, 10, 10, 05, - 05, 10, 05, 05, 15, 10, 05, 05, 05, 10, 10, 10, 10, 20, 25, 10, 20, 30, 25, 20, 20, 15, 20, 15, 20, 20, 10, 10, 10, 10, 10, 20, 10, 30, 15, 10, 10, 10, 20, 20, 05, 05, 05, 20, 10, 10, 20, 15, 20, 20, - 10, 20, 30, 10, 10, 40, 40, 30, 20, 40, 20, 20, 10, 10, 10, 10, 05, 10, 10, 05, 05, + 00, 35, 25, 10, 15, 20, 20, 15, 15, 15, 35, 30, 05, 10, 20, 30, 35, 35, 20, 15, + 20, 20, 25, 20, 30, 05, 10, 15, 15, 15, 25, 20, 05, 35, 15, 20, 20, 10, 15, 30, + 35, 20, 20, 30, 25, 40, 20, 15, 20, 20, 20, 30, 25, 15, 30, 25, 05, 15, 10, 05, + 20, 20, 20, 05, 35, 20, 25, 20, 20, 20, 15, 25, 15, 10, 20, 25, 10, 35, 30, 15, + 10, 40, 10, 15, 30, 15, 20, 10, 15, 10, 05, 10, 10, 25, 10, 20, 40, 30, 30, 20, + 20, 15, 10, 40, 15, 10, 30, 10, 20, 10, 40, 40, 20, 30, 30, 20, 30, 10, 10, 20, + 05, 10, 30, 20, 20, 20, 05, 15, 15, 20, 10, 15, 35, 20, 15, 10, 10, 30, 15, 40, + 20, 15, 10, 05, 10, 30, 10, 15, 20, 15, 40, 20, 10, 05, 15, 10, 10, 10, 15, 30, + 30, 10, 10, 20, 10, 01, 01, 10, 25, 10, 05, 15, 25, 15, 10, 15, 30, 05, 40, 15, + 10, 25, 10, 30, 10, 20, 10, 10, 10, 10, 10, 20, 05, 40, 05, 05, 15, 05, 10, 05, + 10, 10, 10, 10, 20, 20, 40, 15, 10, 20, 20, 25, 05, 15, 10, 05, 20, 15, 20, 25, + 20, 05, 30, 05, 10, 20, 40, 05, 20, 40, 20, 15, 35, 10, 05, 05, 05, 15, 05, 20, + 05, 05, 15, 20, 10, 05, 05, 15, 10, 15, 15, 10, 10, 10, 20, 10, 10, 10, 10, 15, + 15, 15, 10, 20, 20, 10, 20, 20, 20, 20, 20, 10, 10, 10, 20, 20, 05, 15, 10, 10, + 15, 10, 20, 05, 05, 10, 10, 20, 05, 10, 20, 10, 20, 20, 20, 05, 05, 15, 20, 10, + 15, 20, 15, 10, 10, 15, 10, 05, 05, 10, 15, 10, 05, 20, 25, 05, 40, 15, 05, 40, + 15, 20, 20, 05, 15, 20, 20, 15, 15, 05, 10, 30, 20, 30, 15, 05, 40, 15, 05, 20, + 05, 15, 25, 25, 15, 20, 15, 20, 15, 20, 10, 20, 20, 05, 05, 10, 05, 40, 10, 10, + 05, 10, 10, 15, 10, 20, 15, 30, 10, 20, 05, 10, 10, 15, 10, 10, 05, 15, 05, 10, + 10, 30, 20, 20, 10, 10, 05, 05, 10, 05, 20, 10, 20, 10, 15, 10, 20, 20, 20, 15, + 15, 10, 15, 15, 15, 10, 10, 10, 20, 10, 30, 05, 10, 15, 10, 10, 05, 20, 30, 10, + 30, 15, 15, 15, 15, 30, 10, 20, 15, 10, 10, 20, 15, 05, 05, 15, 15, 05, 10, 05, + 20, 05, 15, 20, 05, 20, 20, 20, 20, 10, 20, 10, 15, 20, 15, 10, 10, 05, 10, 05, + 05, 10, 05, 05, 10, 05, 05, 05, 15, 10, 10, 10, 10, 10, 10, 15, 20, 15, 10, 15, + 10, 15, 10, 20, 10, 10, 10, 20, 20, 20, 20, 20, 15, 15, 15, 15, 15, 15, 20, 15, + 10, 15, 15, 15, 15, 10, 10, 10, 10, 10, 15, 15, 15, 15, 05, 05, 15, 05, 10, 10, + 10, 20, 20, 20, 10, 10, 30, 15, 15, 10, 15, 25, 10, 15, 10, 10, 10, 20, 10, 10, + 10, 10, 10, 15, 15, 05, 05, 10, 10, 10, 05, 05, 10, 05, 05, 15, 10, 05, 05, 05, + 10, 10, 10, 10, 20, 25, 10, 20, 30, 25, 20, 20, 15, 20, 15, 20, 20, 10, 10, 10, + 10, 10, 20, 10, 30, 15, 10, 10, 10, 20, 20, 05, 05, 05, 20, 10, 10, 20, 15, 20, + 20, 10, 20, 30, 10, 10, 40, 40, 30, 20, 40, 20, 20, 10, 10, 10, 10, 05, 10, 10, + 05, 05, }; } diff --git a/PKHeX.Core/Moves/MoveInfo7.cs b/PKHeX.Core/Moves/MoveInfo7.cs index f024e0db7..9743d6ac8 100644 --- a/PKHeX.Core/Moves/MoveInfo7.cs +++ b/PKHeX.Core/Moves/MoveInfo7.cs @@ -1,3 +1,5 @@ +using System; + namespace PKHeX.Core; /// @@ -5,23 +7,44 @@ namespace PKHeX.Core; /// internal static class MoveInfo7 { - public static readonly byte[] MovePP_SM = + public static ReadOnlySpan MovePP_SM => new byte[] { - 00, - 35, 25, 10, 15, 20, 20, 15, 15, 15, 35, 30, 05, 10, 20, 30, 35, 35, 20, 15, 20, 20, 25, 20, 30, 05, 10, 15, 15, 15, 25, 20, 05, 35, 15, 20, 20, 10, 15, 30, 35, 20, 20, 30, 25, 40, 20, 15, 20, 20, 20, - 30, 25, 15, 30, 25, 05, 15, 10, 05, 20, 20, 20, 05, 35, 20, 20, 20, 20, 20, 15, 25, 15, 10, 20, 25, 10, 35, 30, 15, 10, 40, 10, 15, 30, 15, 20, 10, 15, 10, 05, 10, 10, 25, 10, 20, 40, 30, 30, 20, 20, - 15, 10, 40, 15, 10, 30, 10, 20, 10, 40, 40, 20, 30, 30, 20, 30, 10, 10, 20, 05, 10, 30, 20, 20, 20, 05, 15, 15, 20, 10, 15, 35, 20, 15, 10, 10, 30, 15, 40, 20, 10, 10, 05, 10, 30, 10, 15, 20, 15, 40, - 20, 10, 05, 15, 10, 10, 10, 15, 30, 30, 10, 10, 20, 10, 01, 01, 10, 25, 10, 05, 15, 25, 15, 10, 15, 30, 05, 40, 15, 10, 25, 10, 30, 10, 20, 10, 10, 10, 10, 10, 20, 05, 40, 05, 05, 15, 05, 10, 05, 10, - 10, 10, 10, 20, 20, 40, 15, 10, 20, 20, 25, 05, 15, 10, 05, 20, 15, 20, 25, 20, 05, 30, 05, 10, 20, 40, 05, 20, 40, 20, 15, 35, 10, 05, 05, 05, 15, 05, 20, 05, 05, 15, 20, 10, 05, 05, 15, 10, 15, 15, - 10, 10, 10, 20, 10, 10, 10, 10, 15, 15, 15, 10, 20, 20, 10, 20, 20, 20, 20, 20, 10, 10, 10, 20, 20, 05, 15, 10, 10, 15, 10, 20, 05, 05, 10, 10, 20, 05, 10, 20, 10, 20, 20, 20, 05, 05, 15, 20, 10, 15, - 20, 15, 10, 10, 15, 10, 05, 05, 10, 15, 10, 05, 20, 25, 05, 40, 15, 05, 40, 15, 20, 20, 05, 15, 20, 20, 15, 15, 05, 10, 30, 20, 30, 15, 05, 40, 15, 05, 20, 05, 15, 25, 25, 15, 20, 15, 20, 15, 20, 10, - 20, 20, 05, 05, 10, 05, 40, 10, 10, 05, 10, 10, 15, 10, 20, 15, 30, 10, 20, 05, 10, 10, 15, 10, 10, 05, 15, 05, 10, 10, 30, 20, 20, 10, 10, 05, 05, 10, 05, 20, 10, 20, 10, 15, 10, 20, 20, 20, 15, 15, - 10, 15, 15, 15, 10, 10, 10, 20, 10, 30, 05, 10, 15, 10, 10, 05, 20, 30, 10, 30, 15, 15, 15, 15, 30, 10, 20, 15, 10, 10, 20, 15, 05, 05, 15, 15, 05, 10, 05, 20, 05, 15, 20, 05, 20, 20, 20, 20, 10, 20, - 10, 15, 20, 15, 10, 10, 05, 10, 05, 05, 10, 05, 05, 10, 05, 05, 05, 15, 10, 10, 10, 10, 10, 10, 15, 20, 15, 10, 15, 10, 15, 10, 20, 10, 10, 10, 20, 20, 20, 20, 20, 15, 15, 15, 15, 15, 15, 20, 15, 10, - 15, 15, 15, 15, 10, 10, 10, 10, 10, 15, 15, 15, 15, 05, 05, 15, 05, 10, 10, 10, 20, 20, 20, 10, 10, 30, 15, 15, 10, 15, 25, 10, 15, 10, 10, 10, 20, 10, 10, 10, 10, 10, 15, 15, 05, 05, 10, 10, 10, 05, - 05, 10, 05, 05, 15, 10, 05, 05, 05, 10, 10, 10, 10, 20, 25, 10, 20, 30, 25, 20, 20, 15, 20, 15, 20, 20, 10, 10, 10, 10, 10, 20, 10, 30, 15, 10, 10, 10, 20, 20, 05, 05, 05, 20, 10, 10, 20, 15, 20, 20, - 10, 20, 30, 10, 10, 40, 40, 30, 20, 40, 20, 20, 10, 10, 10, 10, 05, 10, 10, 05, 05, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, - 01, 01, 01, 01, 01, 01, 01, 01, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 40, 15, 20, 30, 20, 15, 15, 20, 10, 15, 15, 10, 05, 10, 10, 20, 15, 10, 15, 15, 15, 05, 15, 20, 20, 01, 01, 01, 01, 01, 01, - 01, 01, 01, 05, 05, 10, 10, 10, 20, 10, 10, 10, 05, 05, 20, 10, 10, 10, 01, 05, 15, 05, 01, 01, 01, 01, 01, 01, + 00, 35, 25, 10, 15, 20, 20, 15, 15, 15, 35, 30, 05, 10, 20, 30, 35, 35, 20, 15, + 20, 20, 25, 20, 30, 05, 10, 15, 15, 15, 25, 20, 05, 35, 15, 20, 20, 10, 15, 30, + 35, 20, 20, 30, 25, 40, 20, 15, 20, 20, 20, 30, 25, 15, 30, 25, 05, 15, 10, 05, + 20, 20, 20, 05, 35, 20, 20, 20, 20, 20, 15, 25, 15, 10, 20, 25, 10, 35, 30, 15, + 10, 40, 10, 15, 30, 15, 20, 10, 15, 10, 05, 10, 10, 25, 10, 20, 40, 30, 30, 20, + 20, 15, 10, 40, 15, 10, 30, 10, 20, 10, 40, 40, 20, 30, 30, 20, 30, 10, 10, 20, + 05, 10, 30, 20, 20, 20, 05, 15, 15, 20, 10, 15, 35, 20, 15, 10, 10, 30, 15, 40, + 20, 10, 10, 05, 10, 30, 10, 15, 20, 15, 40, 20, 10, 05, 15, 10, 10, 10, 15, 30, + 30, 10, 10, 20, 10, 01, 01, 10, 25, 10, 05, 15, 25, 15, 10, 15, 30, 05, 40, 15, + 10, 25, 10, 30, 10, 20, 10, 10, 10, 10, 10, 20, 05, 40, 05, 05, 15, 05, 10, 05, + 10, 10, 10, 10, 20, 20, 40, 15, 10, 20, 20, 25, 05, 15, 10, 05, 20, 15, 20, 25, + 20, 05, 30, 05, 10, 20, 40, 05, 20, 40, 20, 15, 35, 10, 05, 05, 05, 15, 05, 20, + 05, 05, 15, 20, 10, 05, 05, 15, 10, 15, 15, 10, 10, 10, 20, 10, 10, 10, 10, 15, + 15, 15, 10, 20, 20, 10, 20, 20, 20, 20, 20, 10, 10, 10, 20, 20, 05, 15, 10, 10, + 15, 10, 20, 05, 05, 10, 10, 20, 05, 10, 20, 10, 20, 20, 20, 05, 05, 15, 20, 10, + 15, 20, 15, 10, 10, 15, 10, 05, 05, 10, 15, 10, 05, 20, 25, 05, 40, 15, 05, 40, + 15, 20, 20, 05, 15, 20, 20, 15, 15, 05, 10, 30, 20, 30, 15, 05, 40, 15, 05, 20, + 05, 15, 25, 25, 15, 20, 15, 20, 15, 20, 10, 20, 20, 05, 05, 10, 05, 40, 10, 10, + 05, 10, 10, 15, 10, 20, 15, 30, 10, 20, 05, 10, 10, 15, 10, 10, 05, 15, 05, 10, + 10, 30, 20, 20, 10, 10, 05, 05, 10, 05, 20, 10, 20, 10, 15, 10, 20, 20, 20, 15, + 15, 10, 15, 15, 15, 10, 10, 10, 20, 10, 30, 05, 10, 15, 10, 10, 05, 20, 30, 10, + 30, 15, 15, 15, 15, 30, 10, 20, 15, 10, 10, 20, 15, 05, 05, 15, 15, 05, 10, 05, + 20, 05, 15, 20, 05, 20, 20, 20, 20, 10, 20, 10, 15, 20, 15, 10, 10, 05, 10, 05, + 05, 10, 05, 05, 10, 05, 05, 05, 15, 10, 10, 10, 10, 10, 10, 15, 20, 15, 10, 15, + 10, 15, 10, 20, 10, 10, 10, 20, 20, 20, 20, 20, 15, 15, 15, 15, 15, 15, 20, 15, + 10, 15, 15, 15, 15, 10, 10, 10, 10, 10, 15, 15, 15, 15, 05, 05, 15, 05, 10, 10, + 10, 20, 20, 20, 10, 10, 30, 15, 15, 10, 15, 25, 10, 15, 10, 10, 10, 20, 10, 10, + 10, 10, 10, 15, 15, 05, 05, 10, 10, 10, 05, 05, 10, 05, 05, 15, 10, 05, 05, 05, + 10, 10, 10, 10, 20, 25, 10, 20, 30, 25, 20, 20, 15, 20, 15, 20, 20, 10, 10, 10, + 10, 10, 20, 10, 30, 15, 10, 10, 10, 20, 20, 05, 05, 05, 20, 10, 10, 20, 15, 20, + 20, 10, 20, 30, 10, 10, 40, 40, 30, 20, 40, 20, 20, 10, 10, 10, 10, 05, 10, 10, + 05, 05, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, + 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 40, 15, 20, 30, 20, 15, 15, 20, 10, 15, + 15, 10, 05, 10, 10, 20, 15, 10, 15, 15, 15, 05, 15, 20, 20, 01, 01, 01, 01, 01, + 01, 01, 01, 01, 05, 05, 10, 10, 10, 20, 10, 10, 10, 05, 05, 20, 10, 10, 10, 01, + 05, 15, 05, 01, 01, 01, 01, 01, 01, }; } diff --git a/PKHeX.Core/Moves/MoveInfo7b.cs b/PKHeX.Core/Moves/MoveInfo7b.cs index 464d86ee8..aa495f35c 100644 --- a/PKHeX.Core/Moves/MoveInfo7b.cs +++ b/PKHeX.Core/Moves/MoveInfo7b.cs @@ -1,3 +1,5 @@ +using System; + namespace PKHeX.Core; /// @@ -5,26 +7,48 @@ namespace PKHeX.Core; /// internal static class MoveInfo7b { - public static readonly byte[] MovePP_GG = + public static ReadOnlySpan MovePP_GG => new byte[] { // Absorb: 25 -> 15 (damage buffed from 20->40) // Mega Drain: 15 -> 10 (damage buffed from 40->75) - 00, - 35, 25, 10, 15, 20, 20, 15, 15, 15, 35, 30, 05, 10, 20, 30, 35, 35, 20, 15, 20, 20, 25, 20, 30, 05, 10, 15, 15, 15, 25, 20, 05, 35, 15, 20, 20, 10, 15, 30, 35, 20, 20, 30, 25, 40, 20, 15, 20, 20, 20, - 30, 25, 15, 30, 25, 05, 15, 10, 05, 20, 20, 20, 05, 35, 20, 20, 20, 20, 20, 15, 15, 10, 10, 20, 25, 10, 35, 30, 15, 10, 40, 10, 15, 30, 15, 20, 10, 15, 10, 05, 10, 10, 25, 10, 20, 40, 30, 30, 20, 20, - 15, 10, 40, 15, 10, 30, 10, 20, 10, 40, 40, 20, 30, 30, 20, 30, 10, 10, 20, 05, 10, 30, 20, 20, 20, 05, 15, 15, 20, 10, 15, 35, 20, 15, 10, 10, 30, 15, 40, 20, 10, 10, 05, 10, 30, 10, 15, 20, 15, 40, - 20, 10, 05, 15, 10, 10, 10, 15, 30, 30, 10, 10, 20, 10, 01, 01, 10, 25, 10, 05, 15, 25, 15, 10, 15, 30, 05, 40, 15, 10, 25, 10, 30, 10, 20, 10, 10, 10, 10, 10, 20, 05, 40, 05, 05, 15, 05, 10, 05, 10, - 10, 10, 10, 20, 20, 40, 15, 10, 20, 20, 25, 05, 15, 10, 05, 20, 15, 20, 25, 20, 05, 30, 05, 10, 20, 40, 05, 20, 40, 20, 15, 35, 10, 05, 05, 05, 15, 05, 20, 05, 05, 15, 20, 10, 05, 05, 15, 10, 15, 15, - 10, 10, 10, 20, 10, 10, 10, 10, 15, 15, 15, 10, 20, 20, 10, 20, 20, 20, 20, 20, 10, 10, 10, 20, 20, 05, 15, 10, 10, 15, 10, 20, 05, 05, 10, 10, 20, 05, 10, 20, 10, 20, 20, 20, 05, 05, 15, 20, 10, 15, - 20, 15, 10, 10, 15, 10, 05, 05, 10, 15, 10, 05, 20, 25, 05, 40, 15, 05, 40, 15, 20, 20, 05, 15, 20, 20, 15, 15, 05, 10, 30, 20, 30, 15, 05, 40, 15, 05, 20, 05, 15, 25, 25, 15, 20, 15, 20, 15, 20, 10, - 20, 20, 05, 05, 10, 05, 40, 10, 10, 05, 10, 10, 15, 10, 20, 15, 30, 10, 20, 05, 10, 10, 15, 10, 10, 05, 15, 05, 10, 10, 30, 20, 20, 10, 10, 05, 05, 10, 05, 20, 10, 20, 10, 15, 10, 20, 20, 20, 15, 15, - 10, 15, 15, 15, 10, 10, 10, 20, 10, 30, 05, 10, 15, 10, 10, 05, 20, 30, 10, 30, 15, 15, 15, 15, 30, 10, 20, 15, 10, 10, 20, 15, 05, 05, 15, 15, 05, 10, 05, 20, 05, 15, 20, 05, 20, 20, 20, 20, 10, 20, - 10, 15, 20, 15, 10, 10, 05, 10, 05, 05, 10, 05, 05, 10, 05, 05, 05, 15, 10, 10, 10, 10, 10, 10, 15, 20, 15, 10, 15, 10, 15, 10, 20, 10, 10, 10, 20, 20, 20, 20, 20, 15, 15, 15, 15, 15, 15, 20, 15, 10, - 15, 15, 15, 15, 10, 10, 10, 10, 10, 15, 15, 15, 15, 05, 05, 15, 05, 10, 10, 10, 20, 20, 20, 10, 10, 30, 15, 15, 10, 15, 25, 10, 15, 10, 10, 10, 20, 10, 10, 10, 10, 10, 15, 15, 05, 05, 10, 10, 10, 05, - 05, 10, 05, 05, 15, 10, 05, 05, 05, 10, 10, 10, 10, 20, 25, 10, 20, 30, 25, 20, 20, 15, 20, 15, 20, 20, 10, 10, 10, 10, 10, 20, 10, 30, 15, 10, 10, 10, 20, 20, 05, 05, 05, 20, 10, 10, 20, 15, 20, 20, - 10, 20, 30, 10, 10, 40, 40, 30, 20, 40, 20, 20, 10, 10, 10, 10, 05, 10, 10, 05, 05, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, - 01, 01, 01, 01, 01, 01, 01, 01, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 40, 15, 20, 30, 20, 15, 15, 20, 10, 15, 15, 10, 05, 10, 10, 20, 15, 10, 15, 15, 15, 05, 15, 20, 20, 01, 01, 01, 01, 01, 01, - 01, 01, 01, 05, 05, 10, 10, 10, 20, 10, 10, 10, 05, 05, 20, 10, 10, 10, 01, 05, 15, 05, 01, 01, 01, 01, 01, 01, 15, 15, 15, 20, 15, 15, 15, 15, 15, 15, 15, 15, 20, 05, + 00, 35, 25, 10, 15, 20, 20, 15, 15, 15, 35, 30, 05, 10, 20, 30, 35, 35, 20, 15, + 20, 20, 25, 20, 30, 05, 10, 15, 15, 15, 25, 20, 05, 35, 15, 20, 20, 10, 15, 30, + 35, 20, 20, 30, 25, 40, 20, 15, 20, 20, 20, 30, 25, 15, 30, 25, 05, 15, 10, 05, + 20, 20, 20, 05, 35, 20, 20, 20, 20, 20, 15, 15, 10, 10, 20, 25, 10, 35, 30, 15, + 10, 40, 10, 15, 30, 15, 20, 10, 15, 10, 05, 10, 10, 25, 10, 20, 40, 30, 30, 20, + 20, 15, 10, 40, 15, 10, 30, 10, 20, 10, 40, 40, 20, 30, 30, 20, 30, 10, 10, 20, + 05, 10, 30, 20, 20, 20, 05, 15, 15, 20, 10, 15, 35, 20, 15, 10, 10, 30, 15, 40, + 20, 10, 10, 05, 10, 30, 10, 15, 20, 15, 40, 20, 10, 05, 15, 10, 10, 10, 15, 30, + 30, 10, 10, 20, 10, 01, 01, 10, 25, 10, 05, 15, 25, 15, 10, 15, 30, 05, 40, 15, + 10, 25, 10, 30, 10, 20, 10, 10, 10, 10, 10, 20, 05, 40, 05, 05, 15, 05, 10, 05, + 10, 10, 10, 10, 20, 20, 40, 15, 10, 20, 20, 25, 05, 15, 10, 05, 20, 15, 20, 25, + 20, 05, 30, 05, 10, 20, 40, 05, 20, 40, 20, 15, 35, 10, 05, 05, 05, 15, 05, 20, + 05, 05, 15, 20, 10, 05, 05, 15, 10, 15, 15, 10, 10, 10, 20, 10, 10, 10, 10, 15, + 15, 15, 10, 20, 20, 10, 20, 20, 20, 20, 20, 10, 10, 10, 20, 20, 05, 15, 10, 10, + 15, 10, 20, 05, 05, 10, 10, 20, 05, 10, 20, 10, 20, 20, 20, 05, 05, 15, 20, 10, + 15, 20, 15, 10, 10, 15, 10, 05, 05, 10, 15, 10, 05, 20, 25, 05, 40, 15, 05, 40, + 15, 20, 20, 05, 15, 20, 20, 15, 15, 05, 10, 30, 20, 30, 15, 05, 40, 15, 05, 20, + 05, 15, 25, 25, 15, 20, 15, 20, 15, 20, 10, 20, 20, 05, 05, 10, 05, 40, 10, 10, + 05, 10, 10, 15, 10, 20, 15, 30, 10, 20, 05, 10, 10, 15, 10, 10, 05, 15, 05, 10, + 10, 30, 20, 20, 10, 10, 05, 05, 10, 05, 20, 10, 20, 10, 15, 10, 20, 20, 20, 15, + 15, 10, 15, 15, 15, 10, 10, 10, 20, 10, 30, 05, 10, 15, 10, 10, 05, 20, 30, 10, + 30, 15, 15, 15, 15, 30, 10, 20, 15, 10, 10, 20, 15, 05, 05, 15, 15, 05, 10, 05, + 20, 05, 15, 20, 05, 20, 20, 20, 20, 10, 20, 10, 15, 20, 15, 10, 10, 05, 10, 05, + 05, 10, 05, 05, 10, 05, 05, 05, 15, 10, 10, 10, 10, 10, 10, 15, 20, 15, 10, 15, + 10, 15, 10, 20, 10, 10, 10, 20, 20, 20, 20, 20, 15, 15, 15, 15, 15, 15, 20, 15, + 10, 15, 15, 15, 15, 10, 10, 10, 10, 10, 15, 15, 15, 15, 05, 05, 15, 05, 10, 10, + 10, 20, 20, 20, 10, 10, 30, 15, 15, 10, 15, 25, 10, 15, 10, 10, 10, 20, 10, 10, + 10, 10, 10, 15, 15, 05, 05, 10, 10, 10, 05, 05, 10, 05, 05, 15, 10, 05, 05, 05, + 10, 10, 10, 10, 20, 25, 10, 20, 30, 25, 20, 20, 15, 20, 15, 20, 20, 10, 10, 10, + 10, 10, 20, 10, 30, 15, 10, 10, 10, 20, 20, 05, 05, 05, 20, 10, 10, 20, 15, 20, + 20, 10, 20, 30, 10, 10, 40, 40, 30, 20, 40, 20, 20, 10, 10, 10, 10, 05, 10, 10, + 05, 05, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, + 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 40, 15, 20, 30, 20, 15, 15, 20, 10, 15, + 15, 10, 05, 10, 10, 20, 15, 10, 15, 15, 15, 05, 15, 20, 20, 01, 01, 01, 01, 01, + 01, 01, 01, 01, 05, 05, 10, 10, 10, 20, 10, 10, 10, 05, 05, 20, 10, 10, 10, 01, + 05, 15, 05, 01, 01, 01, 01, 01, 01, 15, 15, 15, 20, 15, 15, 15, 15, 15, 15, 15, + 15, 20, 05, }; } diff --git a/PKHeX.Core/Moves/MoveInfo8.cs b/PKHeX.Core/Moves/MoveInfo8.cs index 75ebe938e..155ff54d9 100644 --- a/PKHeX.Core/Moves/MoveInfo8.cs +++ b/PKHeX.Core/Moves/MoveInfo8.cs @@ -1,3 +1,4 @@ +using System; using System.Collections.Generic; namespace PKHeX.Core; @@ -7,28 +8,51 @@ namespace PKHeX.Core; /// internal static class MoveInfo8 { - public static readonly byte[] MovePP_SWSH = + public static ReadOnlySpan MovePP_SWSH => new byte[] { - 00, - 35, 25, 10, 15, 20, 20, 15, 15, 15, 35, 30, 05, 10, 20, 30, 35, 35, 20, 15, 20, 20, 25, 20, 30, 05, 10, 15, 15, 15, 25, 20, 05, 35, 15, 20, 20, 10, 15, 30, 35, 20, 20, 30, 25, 40, 20, 15, 20, 20, 20, - 30, 25, 15, 30, 25, 05, 15, 10, 05, 20, 20, 20, 05, 35, 20, 20, 20, 20, 20, 15, 25, 15, 10, 20, 25, 10, 35, 30, 15, 10, 40, 10, 15, 30, 15, 20, 10, 15, 10, 05, 10, 10, 25, 10, 20, 40, 30, 30, 20, 20, - 15, 10, 40, 15, 10, 30, 10, 20, 10, 40, 40, 20, 30, 30, 20, 30, 10, 10, 20, 05, 10, 30, 20, 20, 20, 05, 15, 15, 20, 10, 15, 35, 20, 15, 10, 10, 30, 15, 40, 20, 10, 10, 05, 10, 30, 10, 15, 20, 15, 40, - 20, 10, 05, 15, 10, 10, 10, 15, 30, 30, 10, 10, 20, 10, 01, 01, 10, 25, 10, 05, 15, 25, 15, 10, 15, 30, 05, 40, 15, 10, 25, 10, 30, 10, 20, 10, 10, 10, 10, 10, 20, 05, 40, 05, 05, 15, 05, 10, 05, 10, - 10, 10, 10, 20, 20, 40, 15, 10, 20, 20, 25, 05, 15, 10, 05, 20, 15, 20, 25, 20, 05, 30, 05, 10, 20, 40, 05, 20, 40, 20, 15, 35, 10, 05, 05, 05, 15, 05, 20, 05, 05, 15, 20, 10, 05, 05, 15, 10, 15, 15, - 10, 10, 10, 20, 10, 10, 10, 10, 15, 15, 15, 10, 20, 20, 10, 20, 20, 20, 20, 20, 10, 10, 10, 20, 20, 05, 15, 10, 10, 15, 10, 20, 05, 05, 10, 10, 20, 05, 10, 20, 10, 20, 20, 20, 05, 05, 15, 20, 10, 15, - 20, 15, 10, 10, 15, 10, 05, 05, 10, 15, 10, 05, 20, 25, 05, 40, 15, 05, 40, 15, 20, 20, 05, 15, 20, 20, 15, 15, 05, 10, 30, 20, 30, 15, 05, 40, 15, 05, 20, 05, 15, 25, 25, 15, 20, 15, 20, 15, 20, 10, - 20, 20, 05, 05, 10, 05, 40, 10, 10, 05, 10, 10, 15, 10, 20, 15, 30, 10, 20, 05, 10, 10, 15, 10, 10, 05, 15, 05, 10, 10, 30, 20, 20, 10, 10, 05, 05, 10, 05, 20, 10, 20, 10, 15, 10, 20, 20, 20, 15, 15, - 10, 15, 15, 15, 10, 10, 10, 20, 10, 30, 05, 10, 15, 10, 10, 05, 20, 30, 10, 30, 15, 15, 15, 15, 30, 10, 20, 15, 10, 10, 20, 15, 05, 05, 15, 15, 05, 10, 05, 20, 05, 15, 20, 05, 20, 20, 20, 20, 10, 20, - 10, 15, 20, 15, 10, 10, 05, 10, 05, 05, 10, 05, 05, 10, 05, 05, 05, 15, 10, 10, 10, 10, 10, 10, 15, 20, 15, 10, 15, 10, 15, 10, 20, 10, 10, 10, 20, 20, 20, 20, 20, 15, 15, 15, 15, 15, 15, 20, 15, 10, - 15, 15, 15, 15, 10, 10, 10, 10, 10, 15, 15, 15, 15, 05, 05, 15, 05, 10, 10, 10, 20, 20, 20, 10, 10, 30, 15, 15, 10, 15, 25, 10, 15, 10, 10, 10, 20, 10, 10, 10, 10, 10, 15, 15, 05, 05, 10, 10, 10, 05, - 05, 10, 05, 05, 15, 10, 05, 05, 05, 10, 10, 10, 10, 20, 25, 10, 20, 30, 25, 20, 20, 15, 20, 15, 20, 20, 10, 10, 10, 10, 10, 20, 10, 30, 15, 10, 10, 10, 20, 20, 05, 05, 05, 20, 10, 10, 20, 15, 20, 20, - 10, 20, 30, 10, 10, 40, 40, 30, 20, 40, 20, 20, 10, 10, 10, 10, 05, 10, 10, 05, 05, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, - 01, 01, 01, 01, 01, 01, 01, 01, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 40, 15, 20, 30, 20, 15, 15, 20, 10, 15, 15, 10, 05, 10, 10, 20, 15, 10, 15, 15, 15, 05, 15, 20, 20, 01, 01, 01, 01, 01, 01, - 01, 01, 01, 05, 05, 10, 10, 10, 20, 10, 10, 10, 05, 05, 20, 10, 10, 10, 01, 05, 15, 05, 01, 01, 01, 01, 01, 01, 10, 15, 15, 20, 20, 20, 20, 15, 15, 10, 10, 05, 20, 05, 10, 05, 15, 10, 10, 05, 15, 20, - 10, 10, 15, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 05, 10, 15, 10, 15, 05, 05, 05, 10, 15, 40, 10, 10, 10, 15, 10, 10, 10, 10, 05, 05, 05, 10, 05, 20, 10, - 10, 05, 20, 20, 10, 10, 05, 05, 05, 40, 10, 20, 10, 10, 10, 10, 05, 05, 15, 05, 10, 10, 10, 05, 05, 05, + 00, 35, 25, 10, 15, 20, 20, 15, 15, 15, 35, 30, 05, 10, 20, 30, 35, 35, 20, 15, + 20, 20, 25, 20, 30, 05, 10, 15, 15, 15, 25, 20, 05, 35, 15, 20, 20, 10, 15, 30, + 35, 20, 20, 30, 25, 40, 20, 15, 20, 20, 20, 30, 25, 15, 30, 25, 05, 15, 10, 05, + 20, 20, 20, 05, 35, 20, 20, 20, 20, 20, 15, 25, 15, 10, 20, 25, 10, 35, 30, 15, + 10, 40, 10, 15, 30, 15, 20, 10, 15, 10, 05, 10, 10, 25, 10, 20, 40, 30, 30, 20, + 20, 15, 10, 40, 15, 10, 30, 10, 20, 10, 40, 40, 20, 30, 30, 20, 30, 10, 10, 20, + 05, 10, 30, 20, 20, 20, 05, 15, 15, 20, 10, 15, 35, 20, 15, 10, 10, 30, 15, 40, + 20, 10, 10, 05, 10, 30, 10, 15, 20, 15, 40, 20, 10, 05, 15, 10, 10, 10, 15, 30, + 30, 10, 10, 20, 10, 01, 01, 10, 25, 10, 05, 15, 25, 15, 10, 15, 30, 05, 40, 15, + 10, 25, 10, 30, 10, 20, 10, 10, 10, 10, 10, 20, 05, 40, 05, 05, 15, 05, 10, 05, + 10, 10, 10, 10, 20, 20, 40, 15, 10, 20, 20, 25, 05, 15, 10, 05, 20, 15, 20, 25, + 20, 05, 30, 05, 10, 20, 40, 05, 20, 40, 20, 15, 35, 10, 05, 05, 05, 15, 05, 20, + 05, 05, 15, 20, 10, 05, 05, 15, 10, 15, 15, 10, 10, 10, 20, 10, 10, 10, 10, 15, + 15, 15, 10, 20, 20, 10, 20, 20, 20, 20, 20, 10, 10, 10, 20, 20, 05, 15, 10, 10, + 15, 10, 20, 05, 05, 10, 10, 20, 05, 10, 20, 10, 20, 20, 20, 05, 05, 15, 20, 10, + 15, 20, 15, 10, 10, 15, 10, 05, 05, 10, 15, 10, 05, 20, 25, 05, 40, 15, 05, 40, + 15, 20, 20, 05, 15, 20, 20, 15, 15, 05, 10, 30, 20, 30, 15, 05, 40, 15, 05, 20, + 05, 15, 25, 25, 15, 20, 15, 20, 15, 20, 10, 20, 20, 05, 05, 10, 05, 40, 10, 10, + 05, 10, 10, 15, 10, 20, 15, 30, 10, 20, 05, 10, 10, 15, 10, 10, 05, 15, 05, 10, + 10, 30, 20, 20, 10, 10, 05, 05, 10, 05, 20, 10, 20, 10, 15, 10, 20, 20, 20, 15, + 15, 10, 15, 15, 15, 10, 10, 10, 20, 10, 30, 05, 10, 15, 10, 10, 05, 20, 30, 10, + 30, 15, 15, 15, 15, 30, 10, 20, 15, 10, 10, 20, 15, 05, 05, 15, 15, 05, 10, 05, + 20, 05, 15, 20, 05, 20, 20, 20, 20, 10, 20, 10, 15, 20, 15, 10, 10, 05, 10, 05, + 05, 10, 05, 05, 10, 05, 05, 05, 15, 10, 10, 10, 10, 10, 10, 15, 20, 15, 10, 15, + 10, 15, 10, 20, 10, 10, 10, 20, 20, 20, 20, 20, 15, 15, 15, 15, 15, 15, 20, 15, + 10, 15, 15, 15, 15, 10, 10, 10, 10, 10, 15, 15, 15, 15, 05, 05, 15, 05, 10, 10, + 10, 20, 20, 20, 10, 10, 30, 15, 15, 10, 15, 25, 10, 15, 10, 10, 10, 20, 10, 10, + 10, 10, 10, 15, 15, 05, 05, 10, 10, 10, 05, 05, 10, 05, 05, 15, 10, 05, 05, 05, + 10, 10, 10, 10, 20, 25, 10, 20, 30, 25, 20, 20, 15, 20, 15, 20, 20, 10, 10, 10, + 10, 10, 20, 10, 30, 15, 10, 10, 10, 20, 20, 05, 05, 05, 20, 10, 10, 20, 15, 20, + 20, 10, 20, 30, 10, 10, 40, 40, 30, 20, 40, 20, 20, 10, 10, 10, 10, 05, 10, 10, + 05, 05, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, + 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 40, 15, 20, 30, 20, 15, 15, 20, 10, 15, + 15, 10, 05, 10, 10, 20, 15, 10, 15, 15, 15, 05, 15, 20, 20, 01, 01, 01, 01, 01, + 01, 01, 01, 01, 05, 05, 10, 10, 10, 20, 10, 10, 10, 05, 05, 20, 10, 10, 10, 01, + 05, 15, 05, 01, 01, 01, 01, 01, 01, 10, 15, 15, 20, 20, 20, 20, 15, 15, 10, 10, + 05, 20, 05, 10, 05, 15, 10, 10, 05, 15, 20, 10, 10, 15, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 05, 10, 15, 10, 15, + 05, 05, 05, 10, 15, 40, 10, 10, 10, 15, 10, 10, 10, 10, 05, 05, 05, 10, 05, 20, + 10, 10, 05, 20, 20, 10, 10, 05, 05, 05, 40, 10, 20, 10, 10, 10, 10, 05, 05, 15, + 05, 10, 10, 10, 05, 05, 05, }; - /// /// Moves that are kill /// diff --git a/PKHeX.Core/Moves/MoveInfo8a.cs b/PKHeX.Core/Moves/MoveInfo8a.cs index 8ae570161..ff95be6c5 100644 --- a/PKHeX.Core/Moves/MoveInfo8a.cs +++ b/PKHeX.Core/Moves/MoveInfo8a.cs @@ -1,3 +1,4 @@ +using System; using System.Collections.Generic; namespace PKHeX.Core; @@ -7,26 +8,51 @@ namespace PKHeX.Core; /// internal static class MoveInfo8a { - public static readonly byte[] MovePP_LA = + public static ReadOnlySpan MovePP_LA => new byte[] { - 00, - 35, 25, 10, 15, 20, 20, 10, 10, 10, 35, 30, 05, 10, 20, 30, 25, 35, 20, 15, 20, 20, 25, 20, 30, 05, 10, 15, 15, 15, 25, 20, 05, 30, 15, 20, 20, 10, 05, 30, 20, 20, 20, 30, 20, 40, 20, 15, 20, 20, 20, - 30, 25, 10, 30, 25, 05, 15, 10, 05, 20, 20, 20, 05, 35, 20, 20, 20, 20, 20, 15, 20, 15, 10, 20, 25, 10, 20, 20, 20, 10, 40, 10, 15, 25, 10, 20, 05, 15, 10, 05, 10, 10, 20, 10, 20, 40, 30, 20, 20, 20, - 15, 10, 40, 15, 10, 30, 10, 20, 10, 40, 40, 20, 30, 30, 20, 20, 10, 10, 20, 05, 10, 30, 20, 20, 20, 05, 15, 15, 20, 10, 15, 35, 20, 15, 10, 10, 30, 15, 20, 20, 10, 10, 05, 10, 25, 10, 10, 20, 15, 40, - 20, 10, 05, 15, 10, 10, 10, 15, 30, 30, 10, 10, 15, 10, 01, 01, 10, 25, 10, 05, 15, 20, 15, 10, 15, 30, 05, 40, 15, 10, 25, 10, 20, 10, 20, 10, 10, 10, 20, 15, 20, 05, 40, 05, 05, 20, 05, 10, 05, 10, - 10, 10, 10, 20, 20, 30, 15, 10, 20, 20, 25, 05, 15, 10, 05, 20, 15, 20, 25, 20, 05, 30, 05, 05, 20, 40, 05, 20, 40, 20, 05, 35, 10, 05, 05, 05, 15, 05, 25, 05, 05, 10, 20, 10, 05, 15, 10, 10, 20, 15, - 10, 10, 10, 20, 10, 10, 10, 10, 15, 15, 15, 10, 20, 20, 10, 20, 20, 20, 20, 20, 10, 10, 10, 20, 20, 05, 15, 10, 10, 15, 10, 20, 05, 05, 10, 10, 20, 05, 10, 20, 10, 20, 20, 20, 05, 05, 15, 20, 10, 15, - 20, 15, 10, 10, 15, 10, 05, 05, 10, 25, 10, 05, 20, 15, 05, 40, 15, 15, 40, 15, 20, 20, 05, 15, 20, 15, 15, 15, 05, 10, 30, 20, 30, 20, 05, 40, 10, 05, 10, 05, 15, 25, 25, 05, 20, 15, 10, 10, 20, 10, - 20, 20, 05, 05, 10, 05, 40, 10, 10, 05, 10, 10, 15, 10, 20, 15, 30, 10, 20, 05, 10, 10, 15, 10, 10, 05, 15, 05, 10, 10, 30, 20, 20, 10, 10, 05, 05, 10, 05, 20, 10, 20, 10, 05, 10, 10, 20, 10, 10, 15, - 10, 15, 10, 10, 10, 10, 10, 10, 10, 30, 05, 10, 05, 10, 10, 05, 20, 20, 10, 20, 15, 15, 15, 15, 20, 15, 15, 10, 10, 10, 20, 15, 05, 05, 15, 15, 05, 10, 05, 15, 05, 10, 20, 05, 20, 20, 20, 20, 05, 20, - 15, 05, 20, 15, 10, 10, 05, 10, 05, 05, 10, 05, 05, 10, 05, 15, 05, 15, 10, 10, 10, 10, 10, 15, 15, 20, 15, 10, 15, 10, 15, 10, 20, 10, 10, 10, 20, 20, 20, 20, 20, 15, 15, 15, 15, 15, 15, 20, 15, 10, - 15, 15, 15, 15, 10, 15, 10, 10, 10, 15, 15, 15, 15, 05, 05, 15, 05, 10, 10, 10, 20, 20, 20, 10, 10, 30, 15, 10, 10, 15, 25, 10, 15, 10, 10, 10, 20, 10, 10, 10, 10, 05, 15, 15, 05, 05, 10, 10, 10, 05, - 05, 10, 05, 05, 15, 10, 05, 05, 05, 10, 10, 10, 10, 20, 25, 10, 20, 30, 25, 20, 20, 15, 20, 15, 20, 20, 15, 10, 10, 10, 10, 20, 10, 25, 10, 10, 10, 10, 20, 20, 05, 05, 05, 20, 10, 10, 20, 15, 20, 20, - 10, 20, 30, 10, 10, 40, 40, 20, 20, 40, 20, 20, 10, 10, 10, 10, 05, 10, 10, 05, 05, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, - 01, 01, 01, 01, 01, 01, 01, 01, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 25, 15, 20, 30, 20, 15, 15, 20, 10, 15, 15, 10, 05, 10, 10, 20, 15, 10, 15, 15, 15, 05, 15, 20, 20, 01, 01, 01, 01, 01, 01, - 01, 01, 01, 05, 05, 10, 10, 10, 20, 10, 10, 10, 05, 05, 20, 10, 10, 10, 01, 05, 15, 05, 01, 01, 01, 01, 01, 01, 10, 15, 15, 20, 20, 20, 20, 15, 15, 10, 10, 05, 20, 05, 10, 05, 15, 10, 10, 05, 15, 20, - 10, 10, 15, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 05, 10, 15, 10, 15, 05, 05, 05, 10, 15, 40, 10, 10, 10, 15, 10, 10, 10, 10, 05, 05, 05, 10, 05, 20, 10, - 10, 05, 20, 20, 10, 10, 05, 05, 05, 40, 10, 20, 10, 10, 10, 10, 05, 05, 15, 05, 10, 10, 10, 05, 05, 35, 15, 10, 10, 15, 05, 10, 10, 10, 05, 05, 10, 05, 15, 10, 15, 10, 15, 15, 15, 05, 05, 05, 10, 10, + 00, 35, 25, 10, 15, 20, 20, 10, 10, 10, 35, 30, 05, 10, 20, 30, 25, 35, 20, 15, + 20, 20, 25, 20, 30, 05, 10, 15, 15, 15, 25, 20, 05, 30, 15, 20, 20, 10, 05, 30, + 20, 20, 20, 30, 20, 40, 20, 15, 20, 20, 20, 30, 25, 10, 30, 25, 05, 15, 10, 05, + 20, 20, 20, 05, 35, 20, 20, 20, 20, 20, 15, 20, 15, 10, 20, 25, 10, 20, 20, 20, + 10, 40, 10, 15, 25, 10, 20, 05, 15, 10, 05, 10, 10, 20, 10, 20, 40, 30, 20, 20, + 20, 15, 10, 40, 15, 10, 30, 10, 20, 10, 40, 40, 20, 30, 30, 20, 20, 10, 10, 20, + 05, 10, 30, 20, 20, 20, 05, 15, 15, 20, 10, 15, 35, 20, 15, 10, 10, 30, 15, 20, + 20, 10, 10, 05, 10, 25, 10, 10, 20, 15, 40, 20, 10, 05, 15, 10, 10, 10, 15, 30, + 30, 10, 10, 15, 10, 01, 01, 10, 25, 10, 05, 15, 20, 15, 10, 15, 30, 05, 40, 15, + 10, 25, 10, 20, 10, 20, 10, 10, 10, 20, 15, 20, 05, 40, 05, 05, 20, 05, 10, 05, + 10, 10, 10, 10, 20, 20, 30, 15, 10, 20, 20, 25, 05, 15, 10, 05, 20, 15, 20, 25, + 20, 05, 30, 05, 05, 20, 40, 05, 20, 40, 20, 05, 35, 10, 05, 05, 05, 15, 05, 25, + 05, 05, 10, 20, 10, 05, 15, 10, 10, 20, 15, 10, 10, 10, 20, 10, 10, 10, 10, 15, + 15, 15, 10, 20, 20, 10, 20, 20, 20, 20, 20, 10, 10, 10, 20, 20, 05, 15, 10, 10, + 15, 10, 20, 05, 05, 10, 10, 20, 05, 10, 20, 10, 20, 20, 20, 05, 05, 15, 20, 10, + 15, 20, 15, 10, 10, 15, 10, 05, 05, 10, 25, 10, 05, 20, 15, 05, 40, 15, 15, 40, + 15, 20, 20, 05, 15, 20, 15, 15, 15, 05, 10, 30, 20, 30, 20, 05, 40, 10, 05, 10, + 05, 15, 25, 25, 05, 20, 15, 10, 10, 20, 10, 20, 20, 05, 05, 10, 05, 40, 10, 10, + 05, 10, 10, 15, 10, 20, 15, 30, 10, 20, 05, 10, 10, 15, 10, 10, 05, 15, 05, 10, + 10, 30, 20, 20, 10, 10, 05, 05, 10, 05, 20, 10, 20, 10, 05, 10, 10, 20, 10, 10, + 15, 10, 15, 10, 10, 10, 10, 10, 10, 10, 30, 05, 10, 05, 10, 10, 05, 20, 20, 10, + 20, 15, 15, 15, 15, 20, 15, 15, 10, 10, 10, 20, 15, 05, 05, 15, 15, 05, 10, 05, + 15, 05, 10, 20, 05, 20, 20, 20, 20, 05, 20, 15, 05, 20, 15, 10, 10, 05, 10, 05, + 05, 10, 05, 05, 10, 05, 15, 05, 15, 10, 10, 10, 10, 10, 15, 15, 20, 15, 10, 15, + 10, 15, 10, 20, 10, 10, 10, 20, 20, 20, 20, 20, 15, 15, 15, 15, 15, 15, 20, 15, + 10, 15, 15, 15, 15, 10, 15, 10, 10, 10, 15, 15, 15, 15, 05, 05, 15, 05, 10, 10, + 10, 20, 20, 20, 10, 10, 30, 15, 10, 10, 15, 25, 10, 15, 10, 10, 10, 20, 10, 10, + 10, 10, 05, 15, 15, 05, 05, 10, 10, 10, 05, 05, 10, 05, 05, 15, 10, 05, 05, 05, + 10, 10, 10, 10, 20, 25, 10, 20, 30, 25, 20, 20, 15, 20, 15, 20, 20, 15, 10, 10, + 10, 10, 20, 10, 25, 10, 10, 10, 10, 20, 20, 05, 05, 05, 20, 10, 10, 20, 15, 20, + 20, 10, 20, 30, 10, 10, 40, 40, 20, 20, 40, 20, 20, 10, 10, 10, 10, 05, 10, 10, + 05, 05, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, + 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 25, 15, 20, 30, 20, 15, 15, 20, 10, 15, + 15, 10, 05, 10, 10, 20, 15, 10, 15, 15, 15, 05, 15, 20, 20, 01, 01, 01, 01, 01, + 01, 01, 01, 01, 05, 05, 10, 10, 10, 20, 10, 10, 10, 05, 05, 20, 10, 10, 10, 01, + 05, 15, 05, 01, 01, 01, 01, 01, 01, 10, 15, 15, 20, 20, 20, 20, 15, 15, 10, 10, + 05, 20, 05, 10, 05, 15, 10, 10, 05, 15, 20, 10, 10, 15, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 05, 10, 15, 10, 15, + 05, 05, 05, 10, 15, 40, 10, 10, 10, 15, 10, 10, 10, 10, 05, 05, 05, 10, 05, 20, + 10, 10, 05, 20, 20, 10, 10, 05, 05, 05, 40, 10, 20, 10, 10, 10, 10, 05, 05, 15, + 05, 10, 10, 10, 05, 05, 35, 15, 10, 10, 15, 05, 10, 10, 10, 05, 05, 10, 05, 15, + 10, 15, 10, 15, 15, 15, 05, 05, 05, 10, 10, }; /// diff --git a/PKHeX.Core/Moves/MoveInfo9.cs b/PKHeX.Core/Moves/MoveInfo9.cs index 957d1add9..15c860ab9 100644 --- a/PKHeX.Core/Moves/MoveInfo9.cs +++ b/PKHeX.Core/Moves/MoveInfo9.cs @@ -1,3 +1,4 @@ +using System; using System.Collections.Generic; namespace PKHeX.Core; @@ -7,27 +8,54 @@ namespace PKHeX.Core; /// internal static class MoveInfo9 { - public static readonly byte[] MovePP_SV = + public static ReadOnlySpan MovePP_SV => new byte[] { - 00, - 35, 25, 10, 15, 20, 20, 15, 15, 15, 35, 30, 05, 10, 20, 30, 35, 35, 20, 15, 20, 20, 25, 20, 30, 05, 10, 15, 15, 15, 25, 20, 05, 35, 15, 20, 20, 10, 15, 30, 35, 20, 20, 30, 25, 40, 20, 15, 20, 20, 20, - 30, 25, 15, 30, 25, 05, 15, 10, 05, 20, 20, 20, 05, 35, 20, 20, 20, 20, 20, 15, 25, 15, 10, 20, 25, 10, 35, 30, 15, 10, 40, 10, 15, 30, 15, 20, 10, 15, 10, 05, 10, 10, 25, 10, 20, 40, 30, 30, 20, 20, - 15, 10, 40, 15, 05, 30, 10, 20, 10, 40, 40, 20, 30, 30, 20, 30, 10, 10, 20, 05, 10, 30, 20, 20, 20, 05, 15, 15, 20, 10, 15, 35, 20, 15, 05, 10, 30, 15, 40, 20, 10, 10, 05, 10, 30, 10, 15, 20, 15, 40, - 20, 10, 05, 15, 10, 05, 10, 15, 30, 30, 10, 10, 20, 10, 01, 01, 10, 25, 10, 05, 15, 25, 15, 10, 15, 30, 05, 40, 15, 10, 25, 10, 30, 10, 20, 10, 10, 10, 10, 10, 20, 05, 40, 05, 05, 15, 05, 10, 05, 10, - 10, 10, 10, 20, 20, 40, 15, 05, 20, 20, 25, 05, 15, 10, 05, 20, 15, 20, 25, 20, 05, 30, 05, 10, 20, 40, 05, 20, 40, 20, 15, 35, 10, 05, 05, 05, 15, 05, 20, 05, 05, 15, 20, 10, 05, 05, 15, 10, 15, 15, - 10, 10, 10, 20, 10, 10, 10, 10, 15, 15, 15, 10, 20, 20, 10, 20, 20, 20, 20, 20, 10, 10, 10, 20, 20, 05, 15, 10, 10, 15, 10, 20, 05, 05, 10, 10, 20, 05, 10, 20, 10, 20, 20, 20, 05, 05, 15, 20, 10, 15, - 20, 15, 05, 10, 15, 10, 05, 05, 10, 15, 10, 05, 20, 25, 05, 40, 15, 05, 40, 15, 20, 20, 05, 15, 20, 20, 15, 15, 05, 10, 30, 20, 30, 15, 05, 40, 15, 05, 20, 05, 15, 25, 25, 15, 20, 15, 20, 15, 20, 10, - 20, 20, 05, 05, 05, 05, 40, 10, 10, 05, 10, 10, 15, 10, 20, 15, 30, 10, 20, 05, 10, 10, 15, 10, 10, 05, 15, 05, 10, 10, 30, 20, 20, 10, 10, 05, 05, 10, 05, 20, 10, 20, 10, 15, 10, 20, 20, 20, 15, 15, - 10, 15, 15, 15, 10, 10, 10, 20, 10, 30, 05, 10, 15, 10, 10, 05, 20, 30, 10, 30, 15, 15, 15, 15, 30, 10, 20, 15, 10, 10, 20, 15, 05, 05, 15, 15, 05, 10, 05, 20, 05, 15, 20, 05, 20, 20, 20, 20, 10, 20, - 10, 15, 20, 15, 10, 10, 05, 10, 05, 05, 10, 05, 05, 10, 05, 05, 05, 15, 10, 10, 10, 10, 10, 10, 15, 20, 15, 10, 15, 10, 15, 10, 20, 10, 10, 10, 20, 20, 20, 20, 20, 15, 15, 15, 15, 15, 15, 20, 15, 10, - 15, 15, 15, 15, 10, 10, 10, 10, 10, 15, 15, 15, 15, 05, 05, 15, 05, 10, 10, 10, 20, 20, 20, 10, 10, 30, 15, 15, 10, 15, 25, 10, 15, 10, 10, 10, 20, 10, 10, 10, 10, 10, 15, 15, 05, 05, 10, 10, 10, 05, - 05, 10, 05, 05, 15, 10, 05, 05, 05, 10, 10, 10, 10, 20, 25, 10, 20, 30, 25, 20, 20, 15, 20, 15, 20, 20, 10, 10, 10, 10, 10, 20, 10, 30, 15, 10, 10, 10, 20, 20, 05, 05, 05, 20, 10, 10, 20, 15, 20, 20, - 10, 20, 30, 10, 10, 40, 40, 30, 20, 40, 20, 20, 10, 10, 10, 10, 05, 10, 10, 05, 05, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, - 01, 01, 01, 01, 01, 01, 01, 01, 05, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 40, 15, 20, 30, 20, 15, 15, 20, 10, 15, 15, 10, 05, 10, 10, 20, 15, 10, 15, 15, 15, 05, 15, 20, 20, 01, 01, 01, 01, 01, 01, - 01, 01, 01, 05, 05, 10, 10, 10, 20, 10, 10, 10, 05, 05, 20, 10, 10, 10, 01, 05, 15, 05, 01, 01, 01, 01, 01, 01, 10, 15, 15, 20, 20, 20, 20, 15, 15, 10, 10, 05, 20, 05, 10, 05, 15, 10, 10, 05, 15, 20, - 10, 10, 15, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 05, 10, 15, 10, 15, 05, 05, 05, 10, 15, 40, 10, 10, 10, 15, 10, 10, 10, 10, 05, 05, 05, 10, 05, 20, 10, - 10, 05, 20, 20, 10, 10, 05, 05, 05, 40, 10, 20, 10, 10, 10, 10, 05, 05, 15, 05, 10, 10, 10, 05, 05, 05, 15, 10, 10, 15, 05, 10, 10, 10, 05, 10, 10, 05, 10, 10, 10, 10, 10, 15, 15, 10, 10, 10, 05, 15, - 10, 10, 10, 10, 10, 10, 15, 15, 05, 10, 15, 05, 01, 15, 10, 15, 10, 10, 10, 10, 10, 10, 10, 05, 35, 35, 10, 05, 05, 10, 10, 10, 10, 20, 20, 20, 05, 10, 10, 05, 10, 05, 05, 10, 20, 10, 10, 10, 10, 10, + 00, 35, 25, 10, 15, 20, 20, 15, 15, 15, 35, 30, 05, 10, 20, 30, 35, 35, 20, 15, + 20, 20, 25, 20, 30, 05, 10, 15, 15, 15, 25, 20, 05, 35, 15, 20, 20, 10, 15, 30, + 35, 20, 20, 30, 25, 40, 20, 15, 20, 20, 20, 30, 25, 15, 30, 25, 05, 15, 10, 05, + 20, 20, 20, 05, 35, 20, 20, 20, 20, 20, 15, 25, 15, 10, 20, 25, 10, 35, 30, 15, + 10, 40, 10, 15, 30, 15, 20, 10, 15, 10, 05, 10, 10, 25, 10, 20, 40, 30, 30, 20, + 20, 15, 10, 40, 15, 05, 30, 10, 20, 10, 40, 40, 20, 30, 30, 20, 30, 10, 10, 20, + 05, 10, 30, 20, 20, 20, 05, 15, 15, 20, 10, 15, 35, 20, 15, 05, 10, 30, 15, 40, + 20, 10, 10, 05, 10, 30, 10, 15, 20, 15, 40, 20, 10, 05, 15, 10, 05, 10, 15, 30, + 30, 10, 10, 20, 10, 01, 01, 10, 25, 10, 05, 15, 25, 15, 10, 15, 30, 05, 40, 15, + 10, 25, 10, 30, 10, 20, 10, 10, 10, 10, 10, 20, 05, 40, 05, 05, 15, 05, 10, 05, + 10, 10, 10, 10, 20, 20, 40, 15, 05, 20, 20, 25, 05, 15, 10, 05, 20, 15, 20, 25, + 20, 05, 30, 05, 10, 20, 40, 05, 20, 40, 20, 15, 35, 10, 05, 05, 05, 15, 05, 20, + 05, 05, 15, 20, 10, 05, 05, 15, 10, 15, 15, 10, 10, 10, 20, 10, 10, 10, 10, 15, + 15, 15, 10, 20, 20, 10, 20, 20, 20, 20, 20, 10, 10, 10, 20, 20, 05, 15, 10, 10, + 15, 10, 20, 05, 05, 10, 10, 20, 05, 10, 20, 10, 20, 20, 20, 05, 05, 15, 20, 10, + 15, 20, 15, 05, 10, 15, 10, 05, 05, 10, 15, 10, 05, 20, 25, 05, 40, 15, 05, 40, + 15, 20, 20, 05, 15, 20, 20, 15, 15, 05, 10, 30, 20, 30, 15, 05, 40, 15, 05, 20, + 05, 15, 25, 25, 15, 20, 15, 20, 15, 20, 10, 20, 20, 05, 05, 05, 05, 40, 10, 10, + 05, 10, 10, 15, 10, 20, 15, 30, 10, 20, 05, 10, 10, 15, 10, 10, 05, 15, 05, 10, + 10, 30, 20, 20, 10, 10, 05, 05, 10, 05, 20, 10, 20, 10, 15, 10, 20, 20, 20, 15, + 15, 10, 15, 15, 15, 10, 10, 10, 20, 10, 30, 05, 10, 15, 10, 10, 05, 20, 30, 10, + 30, 15, 15, 15, 15, 30, 10, 20, 15, 10, 10, 20, 15, 05, 05, 15, 15, 05, 10, 05, + 20, 05, 15, 20, 05, 20, 20, 20, 20, 10, 20, 10, 15, 20, 15, 10, 10, 05, 10, 05, + 05, 10, 05, 05, 10, 05, 05, 05, 15, 10, 10, 10, 10, 10, 10, 15, 20, 15, 10, 15, + 10, 15, 10, 20, 10, 10, 10, 20, 20, 20, 20, 20, 15, 15, 15, 15, 15, 15, 20, 15, + 10, 15, 15, 15, 15, 10, 10, 10, 10, 10, 15, 15, 15, 15, 05, 05, 15, 05, 10, 10, + 10, 20, 20, 20, 10, 10, 30, 15, 15, 10, 15, 25, 10, 15, 10, 10, 10, 20, 10, 10, + 10, 10, 10, 15, 15, 05, 05, 10, 10, 10, 05, 05, 10, 05, 05, 15, 10, 05, 05, 05, + 10, 10, 10, 10, 20, 25, 10, 20, 30, 25, 20, 20, 15, 20, 15, 20, 20, 10, 10, 10, + 10, 10, 20, 10, 30, 15, 10, 10, 10, 20, 20, 05, 05, 05, 20, 10, 10, 20, 15, 20, + 20, 10, 20, 30, 10, 10, 40, 40, 30, 20, 40, 20, 20, 10, 10, 10, 10, 05, 10, 10, + 05, 05, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, + 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 05, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 40, 15, 20, 30, 20, 15, 15, 20, 10, 15, + 15, 10, 05, 10, 10, 20, 15, 10, 15, 15, 15, 05, 15, 20, 20, 01, 01, 01, 01, 01, + 01, 01, 01, 01, 05, 05, 10, 10, 10, 20, 10, 10, 10, 05, 05, 20, 10, 10, 10, 01, + 05, 15, 05, 01, 01, 01, 01, 01, 01, 10, 15, 15, 20, 20, 20, 20, 15, 15, 10, 10, + 05, 20, 05, 10, 05, 15, 10, 10, 05, 15, 20, 10, 10, 15, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 05, 10, 15, 10, 15, + 05, 05, 05, 10, 15, 40, 10, 10, 10, 15, 10, 10, 10, 10, 05, 05, 05, 10, 05, 20, + 10, 10, 05, 20, 20, 10, 10, 05, 05, 05, 40, 10, 20, 10, 10, 10, 10, 05, 05, 15, + 05, 10, 10, 10, 05, 05, 05, 15, 10, 10, 15, 05, 10, 10, 10, 05, 10, 10, 05, 10, + 10, 10, 10, 10, 15, 15, 10, 10, 10, 05, 15, 10, 10, 10, 10, 10, 10, 15, 15, 05, + 10, 15, 05, 01, 15, 10, 15, 10, 10, 10, 10, 10, 10, 10, 05, 35, 35, 10, 05, 05, + 10, 10, 10, 10, 20, 20, 20, 05, 10, 10, 05, 10, 05, 05, 10, 20, 10, 10, 10, 10, + 10, }; /// diff --git a/PKHeX.Core/MysteryGifts/DataMysteryGift.cs b/PKHeX.Core/MysteryGifts/DataMysteryGift.cs index ba9832e5f..a91ffe936 100644 --- a/PKHeX.Core/MysteryGifts/DataMysteryGift.cs +++ b/PKHeX.Core/MysteryGifts/DataMysteryGift.cs @@ -1,4 +1,4 @@ -using System; +using System; namespace PKHeX.Core; @@ -36,5 +36,5 @@ public abstract class DataMysteryGift : MysteryGift return result; } - public override bool Empty => new ReadOnlySpan(Data).IsRangeEmpty(); + public override bool Empty => Data.AsSpan().IndexOfAnyExcept(0) == -1; } diff --git a/PKHeX.Core/MysteryGifts/MysteryGift.cs b/PKHeX.Core/MysteryGifts/MysteryGift.cs index b4115cfaf..f4c8a74db 100644 --- a/PKHeX.Core/MysteryGifts/MysteryGift.cs +++ b/PKHeX.Core/MysteryGifts/MysteryGift.cs @@ -7,7 +7,7 @@ namespace PKHeX.Core; /// /// Mystery Gift Template File /// -public abstract class MysteryGift : IEncounterable, IMoveset, IRelearn +public abstract class MysteryGift : IEncounterable, IMoveset, IRelearn, ITrainerID32, IFatefulEncounterReadOnly { /// /// Determines whether or not the given length of bytes is valid for a mystery gift. @@ -25,7 +25,7 @@ public abstract class MysteryGift : IEncounterable, IMoveset, IRelearn /// Extension of the file from which the was retrieved. /// An instance of representing the given data, or null if or is invalid. /// This overload differs from by checking the / combo for validity. If either is invalid, a null reference is returned. - public static DataMysteryGift? GetMysteryGift(byte[] data, string ext) => data.Length switch + public static DataMysteryGift? GetMysteryGift(byte[] data, ReadOnlySpan ext) => data.Length switch { PGT.Size when ext == ".pgt" => new PGT(data), PCD.Size when ext is ".pcd" or ".wc4" => new PCD(data), @@ -73,6 +73,7 @@ public abstract class MysteryGift : IEncounterable, IMoveset, IRelearn public string FileName => $"{CardHeader}.{Extension}"; public abstract int Generation { get; } public abstract EntityContext Context { get; } + public abstract bool FatefulEncounter { get; } public PKM ConvertToPKM(ITrainerInfo tr) => ConvertToPKM(tr, EncounterCriteria.Unrestricted); public abstract PKM ConvertToPKM(ITrainerInfo tr, EncounterCriteria criteria); @@ -151,8 +152,9 @@ public abstract class MysteryGift : IEncounterable, IMoveset, IRelearn public virtual int AbilityType { get => -1; set { } } public abstract int Gender { get; set; } public abstract byte Form { get; set; } - public abstract int TID { get; set; } - public abstract int SID { get; set; } + public abstract uint ID32 { get; set; } + public abstract ushort TID16 { get; set; } + public abstract ushort SID16 { get; set; } public abstract string OT_Name { get; set; } public abstract int Location { get; set; } @@ -171,8 +173,11 @@ public abstract class MysteryGift : IEncounterable, IMoveset, IRelearn public Ball FixedBall => (Ball)Ball; - public int TrainerID7 => (int)((uint)(TID | (SID << 16)) % 1000000); - public int TrainerSID7 => (int)((uint)(TID | (SID << 16)) / 1000000); + public TrainerIDFormat TrainerIDDisplayFormat => this.GetTrainerIDFormat(); + public uint TrainerTID7 { get => this.GetTrainerTID7(); set => this.SetTrainerTID7(value); } + public uint TrainerSID7 { get => this.GetTrainerSID7(); set => this.SetTrainerSID7(value); } + public uint DisplayTID { get => this.GetDisplayTID(); set => this.SetDisplayTID(value); } + public uint DisplaySID { get => this.GetDisplaySID(); set => this.SetDisplaySID(value); } /// /// Checks if the has the in its current move list. diff --git a/PKHeX.Core/MysteryGifts/MysteryUtil.cs b/PKHeX.Core/MysteryGifts/MysteryUtil.cs index da275b74f..0501f1637 100644 --- a/PKHeX.Core/MysteryGifts/MysteryUtil.cs +++ b/PKHeX.Core/MysteryGifts/MysteryUtil.cs @@ -102,7 +102,7 @@ public static class MysteryUtil private static void AddLinesPKM(MysteryGift gift, IBasicStrings strings, ICollection result) { - var id = gift.Generation < 7 ? $"{gift.TID:D5}/{gift.SID:D5}" : $"[{gift.TrainerSID7:D4}]{gift.TrainerID7:D6}"; + var id = gift.Generation < 7 ? $"{gift.TID16:D5}/{gift.SID16:D5}" : $"[{gift.TrainerSID7:D4}]{gift.TrainerTID7:D6}"; var first = $"{strings.Species[gift.Species]} @ {strings.Item[gift.HeldItem >= 0 ? gift.HeldItem : 0]} --- " @@ -139,7 +139,7 @@ public static class MysteryUtil return false; } - if (g is WC6 && g.CardID == 2048 && g.ItemID == 726) // Eon Ticket (OR/AS) + if (g is WC6 { CardID: 2048, ItemID: 726 }) // Eon Ticket (OR/AS) { if (sav is not SAV6AO) { diff --git a/PKHeX.Core/MysteryGifts/PCD.cs b/PKHeX.Core/MysteryGifts/PCD.cs index 5fbaceb54..15c11b13a 100644 --- a/PKHeX.Core/MysteryGifts/PCD.cs +++ b/PKHeX.Core/MysteryGifts/PCD.cs @@ -17,6 +17,8 @@ public sealed class PCD : DataMysteryGift, IRibbonSetEvent3, IRibbonSetEvent4 public const int Size = 0x358; // 856 public override int Generation => 4; public override EntityContext Context => EntityContext.Gen4; + public override bool FatefulEncounter => Gift.PK.FatefulEncounter; + public override GameVersion Version { get=> Gift.Version; set => Gift.Version = value; } public override byte Level { @@ -73,7 +75,7 @@ public sealed class PCD : DataMysteryGift, IRibbonSetEvent3, IRibbonSetEvent4 public override string CardTitle { get => StringConverter4.GetString(CardTitleSpan); - set => StringConverter4.SetString(CardTitleSpan, value.AsSpan(), TitleLength / 2, StringConverterOption.ClearFF); + set => StringConverter4.SetString(CardTitleSpan, value, TitleLength / 2, StringConverterOption.ClearFF); } public ushort CardCompatibility => ReadUInt16LittleEndian(Data.AsSpan(0x14C)); // rest of bytes we don't really care about @@ -86,8 +88,9 @@ public sealed class PCD : DataMysteryGift, IRibbonSetEvent3, IRibbonSetEvent4 public override bool IsEgg { get => Gift.IsEgg; set => Gift.IsEgg = value; } public override int Gender { get => Gift.Gender; set => Gift.Gender = value; } public override byte Form { get => Gift.Form; set => Gift.Form = value; } - public override int TID { get => Gift.TID; set => Gift.TID = value; } - public override int SID { get => Gift.SID; set => Gift.SID = value; } + public override uint ID32 { get => Gift.ID32; set => Gift.ID32 = value; } + public override ushort TID16 { get => Gift.TID16; set => Gift.TID16 = value; } + public override ushort SID16 { get => Gift.SID16; set => Gift.SID16 = value; } public override string OT_Name { get => Gift.OT_Name; set => Gift.OT_Name = value; } public override AbilityPermission Ability => Gift.Ability; public override bool HasFixedIVs => Gift.HasFixedIVs; @@ -119,7 +122,7 @@ public sealed class PCD : DataMysteryGift, IRibbonSetEvent3, IRibbonSetEvent4 return true; } - public override PKM ConvertToPKM(ITrainerInfo tr, EncounterCriteria criteria) + public override PK4 ConvertToPKM(ITrainerInfo tr, EncounterCriteria criteria) { return Gift.ConvertToPKM(tr, criteria); } @@ -131,8 +134,8 @@ public sealed class PCD : DataMysteryGift, IRibbonSetEvent3, IRibbonSetEvent4 var wc = Gift.PK; if (!wc.IsEgg) { - if (wc.TID != pk.TID) return false; - if (wc.SID != pk.SID) return false; + if (wc.TID16 != pk.TID16) return false; + if (wc.SID16 != pk.SID16) return false; if (wc.OT_Name != pk.OT_Name) return false; if (wc.OT_Gender != pk.OT_Gender) return false; if (wc.Language != 0 && wc.Language != pk.Language) return false; @@ -156,7 +159,7 @@ public sealed class PCD : DataMysteryGift, IRibbonSetEvent3, IRibbonSetEvent4 return false; if (wc.CurrentLevel != pk.Met_Level) return false; - if (pk.IsEgg && !pk.IsNative) + if (pk is { IsEgg: true, IsNative: false }) return false; } diff --git a/PKHeX.Core/MysteryGifts/PGF.cs b/PKHeX.Core/MysteryGifts/PGF.cs index 06a49de69..51818147c 100644 --- a/PKHeX.Core/MysteryGifts/PGF.cs +++ b/PKHeX.Core/MysteryGifts/PGF.cs @@ -11,12 +11,14 @@ public sealed class PGF : DataMysteryGift, IRibbonSetEvent3, IRibbonSetEvent4, I public const int Size = 0xCC; public override int Generation => 5; public override EntityContext Context => EntityContext.Gen5; + public override bool FatefulEncounter => true; public PGF() : this(new byte[Size]) { } public PGF(byte[] data) : base(data) { } - public override int TID { get => ReadUInt16LittleEndian(Data.AsSpan(0x00)); set => WriteUInt16LittleEndian(Data.AsSpan(0x00), (ushort)value); } - public override int SID { get => ReadUInt16LittleEndian(Data.AsSpan(0x02)); set => WriteUInt16LittleEndian(Data.AsSpan(0x02), (ushort)value); } + public override uint ID32 { get => ReadUInt32LittleEndian(Data.AsSpan(0x00)); set => WriteUInt32LittleEndian(Data.AsSpan(0x00), value); } + public override ushort TID16 { get => ReadUInt16LittleEndian(Data.AsSpan(0x00)); set => WriteUInt16LittleEndian(Data.AsSpan(0x00), value); } + public override ushort SID16 { get => ReadUInt16LittleEndian(Data.AsSpan(0x02)); set => WriteUInt16LittleEndian(Data.AsSpan(0x02), value); } public int OriginGame { get => Data[0x04]; set => Data[0x04] = (byte)value; } // Unused 0x05 0x06, 0x07 public uint PID { get => ReadUInt32LittleEndian(Data.AsSpan(0x08)); set => WriteUInt32LittleEndian(Data.AsSpan(0x08), value); } @@ -53,7 +55,7 @@ public sealed class PGF : DataMysteryGift, IRibbonSetEvent3, IRibbonSetEvent4, I public string Nickname { get => StringConverter5.GetString(Data.AsSpan(0x1E, 11 * 2)); - set => StringConverter5.SetString(Data.AsSpan(0x1E, 11 * 2), value.AsSpan(), 11, StringConverterOption.ClearFF); + set => StringConverter5.SetString(Data.AsSpan(0x1E, 11 * 2), value, 11, StringConverterOption.ClearFF); } public int Nature { get => (sbyte)Data[0x34]; set => Data[0x34] = (byte)value; } @@ -79,7 +81,7 @@ public sealed class PGF : DataMysteryGift, IRibbonSetEvent3, IRibbonSetEvent4, I public override string OT_Name { get => StringConverter5.GetString(Data.AsSpan(0x4A, 8 * 2)); - set => StringConverter5.SetString(Data.AsSpan(0x4A, 8 * 2), value.AsSpan(), 8, StringConverterOption.ClearFF); + set => StringConverter5.SetString(Data.AsSpan(0x4A, 8 * 2), value, 8, StringConverterOption.ClearFF); } public int OTGender { get => Data[0x5A]; set => Data[0x5A] = (byte)value; } @@ -89,7 +91,7 @@ public sealed class PGF : DataMysteryGift, IRibbonSetEvent3, IRibbonSetEvent4, I public override string CardTitle { get => StringConverter5.GetString(Data.AsSpan(0x60, 37 * 2)); - set => StringConverter5.SetString(Data.AsSpan(0x60, 37 * 2), value.AsSpan(), 36, StringConverterOption.ClearZero); + set => StringConverter5.SetString(Data.AsSpan(0x60, 37 * 2), value, 36, StringConverterOption.ClearZero); } // Card Attributes @@ -102,7 +104,7 @@ public sealed class PGF : DataMysteryGift, IRibbonSetEvent3, IRibbonSetEvent4, I /// /// Gets or sets the date of the card. /// - public DateTime? Date + public DateOnly? Date { get { @@ -110,7 +112,7 @@ public sealed class PGF : DataMysteryGift, IRibbonSetEvent3, IRibbonSetEvent4, I if (!DateUtil.IsDateValid(Year, Month, Day)) return null; - return new DateTime(Year, Month, Day); + return new DateOnly(Year, Month, Day); } set { @@ -175,7 +177,7 @@ public sealed class PGF : DataMysteryGift, IRibbonSetEvent3, IRibbonSetEvent4, I public override bool IsItem { get => CardType == 2; set { if (value) CardType = 2; } } public bool IsPower { get => CardType == 3; set { if (value) CardType = 3; } } - public override PKM ConvertToPKM(ITrainerInfo tr, EncounterCriteria criteria) + public override PK5 ConvertToPKM(ITrainerInfo tr, EncounterCriteria criteria) { if (!IsEntity) throw new ArgumentException(nameof(IsEntity)); @@ -190,7 +192,7 @@ public sealed class PGF : DataMysteryGift, IRibbonSetEvent3, IRibbonSetEvent4, I Year = (byte)dt.Year; } - int currentLevel = Level > 0 ? Level : rnd.Next(1, 101); + int currentLevel = Level > 0 ? Level : 1 + rnd.Next(100); var pi = PersonalTable.B2W2.GetFormEntry(Species, Form); PK5 pk = new() { @@ -252,15 +254,15 @@ public sealed class PGF : DataMysteryGift, IRibbonSetEvent3, IRibbonSetEvent4, I if (IsEgg) // User's { - pk.TID = tr.TID; - pk.SID = tr.SID; + pk.TID16 = tr.TID16; + pk.SID16 = tr.SID16; pk.OT_Name = tr.OT; pk.OT_Gender = tr.Gender; } else // Hardcoded { - pk.TID = TID; - pk.SID = SID; + pk.TID16 = TID16; + pk.SID16 = SID16; pk.OT_Name = OT_Name; pk.OT_Gender = (OTGender == 3 ? tr.Gender : OTGender) & 1; // some events have variable gender based on receiving SaveFile } @@ -287,7 +289,7 @@ public sealed class PGF : DataMysteryGift, IRibbonSetEvent3, IRibbonSetEvent4, I pk.IsNicknamed = true; } - private void SetPINGA(PKM pk, EncounterCriteria criteria) + private void SetPINGA(PK5 pk, EncounterCriteria criteria) { var pi = PersonalTable.B2W2.GetFormEntry(Species, Form); pk.Nature = (int)criteria.GetNature((Nature)Nature); @@ -314,7 +316,7 @@ public sealed class PGF : DataMysteryGift, IRibbonSetEvent3, IRibbonSetEvent4, I _ => AbilityPermission.Any12H, }; - private void SetPID(PKM pk, int av) + private void SetPID(PK5 pk, int av) { if (PID != 0) { @@ -330,8 +332,8 @@ public sealed class PGF : DataMysteryGift, IRibbonSetEvent3, IRibbonSetEvent4, I if (PIDType == 2) // Always { - uint gb = pk.PID & 0xFF; - pk.PID = PIDGenerator.GetMG5ShinyPID(gb, (uint)av, pk.TID, pk.SID); + var gb = (byte)pk.PID; + pk.PID = PIDGenerator.GetMG5ShinyPID(gb, (uint)av, pk.TID16, pk.SID16); } else if (PIDType != 1) // Force Not Shiny { @@ -352,7 +354,7 @@ public sealed class PGF : DataMysteryGift, IRibbonSetEvent3, IRibbonSetEvent4, I _ => Shiny.Random, // 1 }; - private void SetIVs(PKM pk) + private void SetIVs(PK5 pk) { Span finalIVs = stackalloc int[6]; GetIVs(finalIVs); @@ -366,8 +368,8 @@ public sealed class PGF : DataMysteryGift, IRibbonSetEvent3, IRibbonSetEvent4, I { if (!IsEgg) { - if (SID != pk.SID) return false; - if (TID != pk.TID) return false; + if (SID16 != pk.SID16) return false; + if (TID16 != pk.TID16) return false; if (OT_Name != pk.OT_Name) return false; if (OTGender < 3 && OTGender != pk.OT_Gender) return false; if (PID != 0 && pk.PID != PID) return false; @@ -391,7 +393,7 @@ public sealed class PGF : DataMysteryGift, IRibbonSetEvent3, IRibbonSetEvent4, I return false; // can't be traded away for un-shiny } - if (pk.IsEgg && !pk.IsNative) + if (pk is { IsEgg: true, IsNative: false }) return false; } diff --git a/PKHeX.Core/MysteryGifts/PGT.cs b/PKHeX.Core/MysteryGifts/PGT.cs index ea274757a..8bbd1431a 100644 --- a/PKHeX.Core/MysteryGifts/PGT.cs +++ b/PKHeX.Core/MysteryGifts/PGT.cs @@ -11,6 +11,8 @@ public sealed class PGT : DataMysteryGift, IRibbonSetEvent3, IRibbonSetEvent4 public const int Size = 0x104; // 260 public override int Generation => 4; public override EntityContext Context => EntityContext.Gen4; + public override bool FatefulEncounter => IsManaphyEgg || PK.FatefulEncounter; + public override GameVersion Version { get => (GameVersion)PK.Version; set => PK.Version = (int)value; } public override byte Level { @@ -116,8 +118,9 @@ public sealed class PGT : DataMysteryGift, IRibbonSetEvent3, IRibbonSetEvent4 public override bool IsShiny => PK.IsShiny; public override int Gender { get => PK.Gender; set => PK.Gender = value; } public override byte Form { get => PK.Form; set => PK.Form = value; } - public override int TID { get => (ushort)PK.TID; set => PK.TID = value; } - public override int SID { get => (ushort)PK.SID; set => PK.SID = value; } + public override uint ID32 { get => PK.ID32; set => PK.ID32= value; } + public override ushort TID16 { get => PK.TID16; set => PK.TID16 = value; } + public override ushort SID16 { get => PK.SID16; set => PK.SID16 = value; } public override string OT_Name { get => PK.OT_Name; set => PK.OT_Name = value; } public override int Location { get => PK.Met_Location; set => PK.Met_Location = value; } public override int EggLocation { get => PK.Egg_Location; set => PK.Egg_Location = value; } @@ -128,7 +131,7 @@ public sealed class PGT : DataMysteryGift, IRibbonSetEvent3, IRibbonSetEvent4 PK.GetIVs(value); } - public override PKM ConvertToPKM(ITrainerInfo tr, EncounterCriteria criteria) + public override PK4 ConvertToPKM(ITrainerInfo tr, EncounterCriteria criteria) { if (!IsEntity) throw new ArgumentException(nameof(IsEntity)); @@ -138,8 +141,8 @@ public sealed class PGT : DataMysteryGift, IRibbonSetEvent3, IRibbonSetEvent4 if (!IsHatched && Detail == 0) { pk4.OT_Name = tr.OT; - pk4.TID = tr.TID; - pk4.SID = tr.SID; + pk4.TID16 = tr.TID16; + pk4.SID16 = tr.SID16; pk4.OT_Gender = tr.Gender; pk4.Language = tr.Language; } @@ -163,7 +166,7 @@ public sealed class PGT : DataMysteryGift, IRibbonSetEvent3, IRibbonSetEvent4 { pk4.Met_Location = pk4.Egg_Location + 3000; pk4.Egg_Location = 0; - pk4.MetDate = DateTime.Now; + pk4.MetDate = DateOnly.FromDateTime(DateTime.Now); pk4.IsEgg = false; } else @@ -237,7 +240,7 @@ public sealed class PGT : DataMysteryGift, IRibbonSetEvent3, IRibbonSetEvent4 { pk4.IsEgg = false; // Met Location & Date is modified when transferred to pk5; don't worry about it. - pk4.EggMetDate = DateTime.Now; + pk4.EggMetDate = DateOnly.FromDateTime(DateTime.Now); } private void SetUnhatchedEggDetails(PK4 pk4) @@ -245,7 +248,7 @@ public sealed class PGT : DataMysteryGift, IRibbonSetEvent3, IRibbonSetEvent4 pk4.IsEgg = true; pk4.IsNicknamed = false; pk4.Nickname = SpeciesName.GetEggName(pk4.Language, Generation); - pk4.EggMetDate = DateTime.Now; + pk4.EggMetDate = DateOnly.FromDateTime(DateTime.Now); } private static uint GeneratePID(uint seed, PK4 pk4) diff --git a/PKHeX.Core/MysteryGifts/PL6.cs b/PKHeX.Core/MysteryGifts/PL6.cs index f423f8066..88f1d0ddb 100644 --- a/PKHeX.Core/MysteryGifts/PL6.cs +++ b/PKHeX.Core/MysteryGifts/PL6.cs @@ -34,7 +34,7 @@ public sealed class PL6 /// /// Name of data source /// - public string Origin { get => StringConverter6.GetString(Data.AsSpan(0x01, 110)); set => StringConverter6.SetString(Data.AsSpan(0x01, 110), value.AsSpan(), 54, StringConverterOption.ClearZero); } + public string Origin { get => StringConverter6.GetString(Data.AsSpan(0x01, 110)); set => StringConverter6.SetString(Data.AsSpan(0x01, 110), value, 54, StringConverterOption.ClearZero); } // Pokemon transfer flags? public uint Flags_1 { get => ReadUInt32LittleEndian(Data.AsSpan(0x099)); set => WriteUInt32LittleEndian(Data.AsSpan(0x099), value); } @@ -86,8 +86,8 @@ public sealed class PL6_PKM : IRibbonSetEvent3, IRibbonSetEvent4, IEncounterInfo public PL6_PKM() : this(new byte[Size]) { } public PL6_PKM(byte[] data) => Data = data; - public int TID { get => ReadUInt16LittleEndian(Data.AsSpan(0x00)); set => WriteUInt16LittleEndian(Data.AsSpan(0x00), (ushort)value); } - public int SID { get => ReadUInt16LittleEndian(Data.AsSpan(0x02)); set => WriteUInt16LittleEndian(Data.AsSpan(0x02), (ushort)value); } + public int TID16 { get => ReadUInt16LittleEndian(Data.AsSpan(0x00)); set => WriteUInt16LittleEndian(Data.AsSpan(0x00), (ushort)value); } + public int SID16 { get => ReadUInt16LittleEndian(Data.AsSpan(0x02)); set => WriteUInt16LittleEndian(Data.AsSpan(0x02), (ushort)value); } public int OriginGame { get => Data[0x04]; set => Data[0x04] = (byte)value; } public uint EncryptionConstant { get => ReadUInt32LittleEndian(Data.AsSpan(0x08)); set => WriteUInt32LittleEndian(Data.AsSpan(0x08), value); } public int Ball { get => Data[0xE]; set => Data[0xE] = (byte)value; } @@ -103,7 +103,7 @@ public sealed class PL6_PKM : IRibbonSetEvent3, IRibbonSetEvent4, IEncounterInfo public string Nickname { get => StringConverter6.GetString(Data.AsSpan(0x1E, 0x1A)); - set => StringConverter6.SetString(Data.AsSpan(0x1E, 0x1A), value.AsSpan(), 12, StringConverterOption.ClearZero); + set => StringConverter6.SetString(Data.AsSpan(0x1E, 0x1A), value, 12, StringConverterOption.ClearZero); } public int Nature { get => Data[0x38]; set => Data[0x38] = (byte)value; } @@ -133,7 +133,7 @@ public sealed class PL6_PKM : IRibbonSetEvent3, IRibbonSetEvent4, IEncounterInfo public string OT { get => StringConverter6.GetString(Data.AsSpan(0x4E, 0x1A)); - set => StringConverter6.SetString(Data.AsSpan(0x4E, 0x1A), value.AsSpan(), 12, StringConverterOption.ClearZero); + set => StringConverter6.SetString(Data.AsSpan(0x4E, 0x1A), value, 12, StringConverterOption.ClearZero); } public int Level { get => Data[0x68]; set => Data[0x68] = (byte)value; } diff --git a/PKHeX.Core/MysteryGifts/WA8.cs b/PKHeX.Core/MysteryGifts/WA8.cs index 76f3a91b0..8a6d7bfee 100644 --- a/PKHeX.Core/MysteryGifts/WA8.cs +++ b/PKHeX.Core/MysteryGifts/WA8.cs @@ -15,6 +15,7 @@ public sealed class WA8 : DataMysteryGift, ILangNick, INature, IGigantamax, IDyn public override int Generation => 8; public override EntityContext Context => EntityContext.Gen8a; + public override bool FatefulEncounter => true; public enum GiftType : byte { @@ -95,27 +96,32 @@ public sealed class WA8 : DataMysteryGift, ILangNick, INature, IGigantamax, IDyn _ => throw new ArgumentOutOfRangeException(), }; - private int GetShinyXor() + private uint GetShinyXor() { // Player owned anti-shiny fixed PID - if (TID == 0 && SID == 0) - return int.MaxValue; + if (ID32 == 0) + return uint.MaxValue; - var pid = PID; - var psv = (int)((pid >> 16) ^ (pid & 0xFFFF)); - var tsv = TID ^ SID; - return psv ^ tsv; + var xor = PID ^ ID32; + return (xor >> 16) ^ (xor & 0xFFFF); } - public override int TID + public override uint ID32 + { + get => ReadUInt32LittleEndian(Data.AsSpan(0x18)); + set => WriteUInt32LittleEndian(Data.AsSpan(0x18), value); + } + + public override ushort TID16 { get => ReadUInt16LittleEndian(Data.AsSpan(0x18)); - set => WriteUInt16LittleEndian(Data.AsSpan(0x18), (ushort)value); + set => WriteUInt16LittleEndian(Data.AsSpan(0x18), value); } - public override int SID { + public override ushort SID16 + { get => ReadUInt16LittleEndian(Data.AsSpan(0x1A)); - set => WriteUInt16LittleEndian(Data.AsSpan(0x1A), (ushort)value); + set => WriteUInt16LittleEndian(Data.AsSpan(0x1A), value); } public int OriginGame @@ -190,17 +196,21 @@ public sealed class WA8 : DataMysteryGift, ILangNick, INature, IGigantamax, IDyn private const int RibbonBytesCount = 0x20; private const int RibbonByteNone = 0xFF; // signed -1 - public bool HasMark() + private ReadOnlySpan RibbonSpan => Data.AsSpan(RibbonBytesOffset, RibbonBytesCount); + + public bool HasMarkEncounter8 { - for (int i = 0; i < RibbonBytesCount; i++) + get { - var value = Data[RibbonBytesOffset + i]; - if (value == RibbonByteNone) - return false; - if ((RibbonIndex)value is >= MarkLunchtime and <= MarkSlump) - return true; + foreach (var value in RibbonSpan) + { + if (value == RibbonByteNone) + return false; // end + if (((RibbonIndex)value).IsEncounterMark8()) + return true; + } + return false; } - return false; } public byte GetRibbonAtIndex(int byteIndex) @@ -368,11 +378,13 @@ public sealed class WA8 : DataMysteryGift, ILangNick, INature, IGigantamax, IDyn public bool IsNicknamed => false; public int Language => 2; - public string GetNickname(int language) => StringConverter8.GetString(Data.AsSpan(GetNicknameOffset(language), 0x1A)); - public void SetNickname(int language, string value) => StringConverter8.SetString(Data.AsSpan(GetNicknameOffset(language), 0x1A), value.AsSpan(), 12, StringConverterOption.ClearZero); + private Span GetNicknameSpan(int language) => Data.AsSpan(GetNicknameOffset(language), 0x1A); + public string GetNickname(int language) => StringConverter8.GetString(GetNicknameSpan(language)); + public void SetNickname(int language, ReadOnlySpan value) => StringConverter8.SetString(GetNicknameSpan(language), value, 12, StringConverterOption.ClearZero); - public string GetOT(int language) => StringConverter8.GetString(Data.AsSpan(GetOTOffset(language), 0x1A)); - public void SetOT(int language, string value) => StringConverter8.SetString(Data.AsSpan(GetOTOffset(language), 0x1A), value.AsSpan(), 12, StringConverterOption.ClearZero); + private Span GetOTSpan(int language) => Data.AsSpan(GetOTOffset(language), 0x1A); + public string GetOT(int language) => StringConverter8.GetString(GetOTSpan(language)); + public void SetOT(int language, ReadOnlySpan value) => StringConverter8.SetString(GetOTSpan(language), value, 12, StringConverterOption.ClearZero); private static int GetNicknameOffset(int language) { @@ -398,7 +410,7 @@ public sealed class WA8 : DataMysteryGift, ILangNick, INature, IGigantamax, IDyn public bool IsAlpha { get => false; set { } } - public override PKM ConvertToPKM(ITrainerInfo tr, EncounterCriteria criteria) + public override PA8 ConvertToPKM(ITrainerInfo tr, EncounterCriteria criteria) { if (!IsEntity) throw new ArgumentException(nameof(IsEntity)); @@ -412,8 +424,8 @@ public sealed class WA8 : DataMysteryGift, ILangNick, INature, IGigantamax, IDyn var pk = new PA8 { EncryptionConstant = EncryptionConstant != 0 ? EncryptionConstant : Util.Rand32(), - TID = TID, - SID = SID, + TID16 = TID16, + SID16 = SID16, Species = Species, Form = Form, CurrentLevel = currentLevel, @@ -475,11 +487,11 @@ public sealed class WA8 : DataMysteryGift, ILangNick, INature, IGigantamax, IDyn if (OTGender >= 2) { - pk.TID = tr.TID; - pk.SID = tr.SID; + pk.TID16 = tr.TID16; + pk.SID16 = tr.SID16; } - pk.MetDate = IsDateRestricted && EncounterServerDate.WA8Gifts.TryGetValue(CardID, out var dt) ? dt.Start : DateTime.Now; + pk.MetDate = IsDateRestricted && EncounterServerDate.WA8Gifts.TryGetValue(CardID, out var dt) ? dt.Start : DateOnly.FromDateTime(DateTime.Now); // HOME Gifts for Sinnoh/Hisui starters were forced JPN until May 20, 2022 (UTC). if (CardID is 9018 or 9019 or 9020) @@ -517,7 +529,7 @@ public sealed class WA8 : DataMysteryGift, ILangNick, INature, IGigantamax, IDyn private void SetEggMetData(PKM pk) { pk.IsEgg = true; - pk.EggMetDate = DateTime.Now; + pk.EggMetDate = DateOnly.FromDateTime(DateTime.Now); pk.Nickname = SpeciesName.GetEggName(pk.Language, Generation); pk.IsNicknamed = true; } @@ -550,20 +562,20 @@ public sealed class WA8 : DataMysteryGift, ILangNick, INature, IGigantamax, IDyn _ => AbilityPermission.Any12H, }; - private uint GetPID(ITrainerID tr, ShinyType8 type) => type switch + private uint GetPID(ITrainerID32 tr, ShinyType8 type) => type switch { ShinyType8.Never => GetAntishiny(tr), // Random, Never Shiny ShinyType8.Random => Util.Rand32(), // Random, Any - ShinyType8.AlwaysStar => (uint)(((tr.TID ^ tr.SID ^ (PID & 0xFFFF) ^ 1) << 16) | (PID & 0xFFFF)), // Fixed, Force Star - ShinyType8.AlwaysSquare => (uint)(((tr.TID ^ tr.SID ^ (PID & 0xFFFF) ^ 0) << 16) | (PID & 0xFFFF)), // Fixed, Force Square + ShinyType8.AlwaysStar => (1u ^ (PID & 0xFFFF) ^ tr.TID16 ^ tr.SID16) << 16 | (PID & 0xFFFF), // Fixed, Force Star + ShinyType8.AlwaysSquare => (0u ^ (PID & 0xFFFF) ^ tr.TID16 ^ tr.SID16) << 16 | (PID & 0xFFFF), // Fixed, Force Square ShinyType8.FixedValue => GetFixedPID(tr), _ => throw new ArgumentOutOfRangeException(nameof(type)), }; - private uint GetFixedPID(ITrainerID tr) + private uint GetFixedPID(ITrainerID32 tr) { var pid = PID; - if (pid != 0 && !(TID == 0 && SID == 0)) + if (pid != 0 && ID32 != 0) return pid; if (!tr.IsShiny(pid, 8)) @@ -573,13 +585,9 @@ public sealed class WA8 : DataMysteryGift, ILangNick, INature, IGigantamax, IDyn return pid; } - private static uint GetAntishinyFixedHOME(ITrainerID tr) - { - var fid = (uint)(tr.SID << 16) | (uint)tr.TID; - return fid ^ 0x10u; - } + private static uint GetAntishinyFixedHOME(ITrainerID32 tr) => tr.ID32 ^ 0x10u; - private static uint GetAntishiny(ITrainerID tr) + private static uint GetAntishiny(ITrainerID32 tr) { var pid = Util.Rand32(); if (tr.IsShiny(pid, 8)) @@ -626,8 +634,8 @@ public sealed class WA8 : DataMysteryGift, ILangNick, INature, IGigantamax, IDyn { if (OTGender < 2) { - if (SID != pk.SID) return false; - if (TID != pk.TID) return false; + if (SID16 != pk.SID16) return false; + if (TID16 != pk.TID16) return false; if (OTGender != pk.OT_Gender) return false; } @@ -659,7 +667,7 @@ public sealed class WA8 : DataMysteryGift, ILangNick, INature, IGigantamax, IDyn { if (pk.Egg_Location != Locations.LinkTrade6) return false; - if (PIDType == ShinyType8.Random && pk.IsShiny && pk.ShinyXor > 1) + if (PIDType == ShinyType8.Random && pk is { IsShiny: true, ShinyXor: > 1 }) return false; // shiny traded egg will always have xor0/1. } if (!Shiny.IsValid(pk)) @@ -667,7 +675,7 @@ public sealed class WA8 : DataMysteryGift, ILangNick, INature, IGigantamax, IDyn return false; // can't be traded away for unshiny } - if (pk.IsEgg && !pk.IsNative) + if (pk is { IsEgg: true, IsNative: false }) return false; } else @@ -696,7 +704,7 @@ public sealed class WA8 : DataMysteryGift, ILangNick, INature, IGigantamax, IDyn if (expectedBall < poke) // Not even Cherish balls are safe! They get set to the proto-Poké ball. expectedBall = poke; if (pk is PK8) - expectedBall = (int)Core.Ball.Poke; // Transferred to SWSH -> Regular Poké ball + expectedBall = (int)Core.Ball.Poke; // Transferred to SW/SH -> Regular Poké ball if (expectedBall != pk.Ball) return false; diff --git a/PKHeX.Core/MysteryGifts/WB7.cs b/PKHeX.Core/MysteryGifts/WB7.cs index 27eeb44ee..68ad7c36b 100644 --- a/PKHeX.Core/MysteryGifts/WB7.cs +++ b/PKHeX.Core/MysteryGifts/WB7.cs @@ -11,6 +11,7 @@ public sealed class WB7 : DataMysteryGift, ILangNick, IAwakened, INature, ILangN public const int Size = 0x108; public const int SizeFull = 0x310; private const int CardStart = SizeFull - Size; + public override bool FatefulEncounter => true; public override int Generation => 7; public override EntityContext Context => EntityContext.Gen7b; @@ -44,7 +45,7 @@ public sealed class WB7 : DataMysteryGift, ILangNick, IAwakened, INature, ILangN { // Max len 36 char, followed by null terminator get => StringConverter8.GetString(Data.AsSpan(CardStart + 2, 0x4A)); - set => StringConverter8.SetString(Data.AsSpan(CardStart + 2, 0x4A), value.AsSpan(), 36, StringConverterOption.ClearZero); + set => StringConverter8.SetString(Data.AsSpan(CardStart + 2, 0x4A), value, 36, StringConverterOption.ClearZero); } private uint RawDate @@ -76,7 +77,7 @@ public sealed class WB7 : DataMysteryGift, ILangNick, IAwakened, INature, ILangN /// /// Gets or sets the date of the card. /// - public DateTime? Date + public DateOnly? Date { get { @@ -84,7 +85,7 @@ public sealed class WB7 : DataMysteryGift, ILangNick, IAwakened, INature, ILangN if (!DateUtil.IsDateValid(Year, Month, Day)) return null; - return new DateTime((int)Year, (int)Month, (int)Day); + return new DateOnly((int)Year, (int)Month, (int)Day); } set { @@ -144,15 +145,21 @@ public sealed class WB7 : DataMysteryGift, ILangNick, IAwakened, INature, ILangN _ => throw new ArgumentOutOfRangeException(), }; - public override int TID + public override uint ID32 { - get => ReadUInt16LittleEndian(Data.AsSpan(CardStart + 0x68)); - set => WriteUInt16LittleEndian(Data.AsSpan(CardStart + 0x68), (ushort)value); + get => ReadUInt32LittleEndian(Data.AsSpan(CardStart + 0x68)); + set => WriteUInt32LittleEndian(Data.AsSpan(CardStart + 0x68), value); } - public override int SID { + public override ushort TID16 + { + get => ReadUInt16LittleEndian(Data.AsSpan(CardStart + 0x68)); + set => WriteUInt16LittleEndian(Data.AsSpan(CardStart + 0x68), value); + } + + public override ushort SID16 { get => ReadUInt16LittleEndian(Data.AsSpan(CardStart + 0x6A)); - set => WriteUInt16LittleEndian(Data.AsSpan(CardStart + 0x6A), (ushort)value); + set => WriteUInt16LittleEndian(Data.AsSpan(CardStart + 0x6A), value); } public int OriginGame @@ -321,11 +328,13 @@ public sealed class WB7 : DataMysteryGift, ILangNick, IAwakened, INature, ILangN public bool GetHasOT(int language) => ReadUInt16LittleEndian(Data.AsSpan(GetOTOffset(language))) != 0; - public string GetNickname(int language) => StringConverter8.GetString(Data.AsSpan(GetNicknameOffset(language), 0x1A)); - public void SetNickname(int language, string value) => StringConverter8.SetString(Data.AsSpan(GetNicknameOffset(language), 0x1A), value.AsSpan(), 12, StringConverterOption.ClearZero); + private Span GetNicknameSpan(int language) => Data.AsSpan(GetNicknameOffset(language), 0x1A); + public string GetNickname(int language) => StringConverter8.GetString(GetNicknameSpan(language)); + public void SetNickname(int language, ReadOnlySpan value) => StringConverter8.SetString(GetNicknameSpan(language), value, 12, StringConverterOption.ClearZero); - public string GetOT(int language) => StringConverter8.GetString(Data.AsSpan(GetOTOffset(language), 0x1A)); - public void SetOT(int language, string value) => StringConverter8.SetString(Data.AsSpan(GetOTOffset(language), 0x1A), value.AsSpan(), 12, StringConverterOption.ClearZero); + private Span GetOTSpan(int language) => Data.AsSpan(GetOTOffset(language), 0x1A); + public string GetOT(int language) => StringConverter8.GetString(GetOTSpan(language)); + public void SetOT(int language, ReadOnlySpan value) => StringConverter8.SetString(GetOTSpan(language), value, 12, StringConverterOption.ClearZero); private static int GetNicknameOffset(int language) { @@ -339,14 +348,14 @@ public sealed class WB7 : DataMysteryGift, ILangNick, IAwakened, INature, ILangN return 0xEE + (index * 0x1A); } - public override PKM ConvertToPKM(ITrainerInfo tr, EncounterCriteria criteria) + public override PB7 ConvertToPKM(ITrainerInfo tr, EncounterCriteria criteria) { if (!IsEntity) throw new ArgumentException(nameof(IsEntity)); var rnd = Util.Rand; - int currentLevel = Level > 0 ? Level : rnd.Next(1, 101); + int currentLevel = Level > 0 ? Level : (1 + rnd.Next(100)); int metLevel = MetLevel > 0 ? MetLevel : currentLevel; var pi = PersonalTable.GG.GetFormEntry(Species, Form); @@ -358,8 +367,8 @@ public sealed class WB7 : DataMysteryGift, ILangNick, IAwakened, INature, ILangN { Species = Species, HeldItem = HeldItem, - TID = TID, - SID = SID, + TID16 = TID16, + SID16 = SID16, Met_Level = metLevel, Form = Form, EncryptionConstant = EncryptionConstant != 0 ? EncryptionConstant : Util.Rand32(), @@ -410,11 +419,11 @@ public sealed class WB7 : DataMysteryGift, ILangNick, IAwakened, INature, ILangN if (OTGender == 3) { - pk.TID = tr.TID; - pk.SID = tr.SID; + pk.TID16 = tr.TID16; + pk.SID16 = tr.SID16; } - pk.MetDate = Date ?? DateTime.Now; + pk.MetDate = Date ?? DateOnly.FromDateTime(DateTime.Now); pk.IsNicknamed = GetIsNicknamed(redeemLanguage); pk.Nickname = pk.IsNicknamed ? GetNickname(redeemLanguage) : SpeciesName.GetSpeciesNameGeneration(Species, pk.Language, Generation); @@ -478,8 +487,8 @@ public sealed class WB7 : DataMysteryGift, ILangNick, IAwakened, INature, ILangN pk.PID = Util.Rand32(); break; case ShinyType6.Always: // Random Shiny - pk.PID = Util.Rand32(); - pk.PID = (uint)(((pk.TID ^ pk.SID ^ (pk.PID & 0xFFFF)) << 16) | (pk.PID & 0xFFFF)); + var low = Util.Rand32() & 0xFFFF; + pk.PID = ((low ^ pk.TID16 ^ pk.SID16) << 16) | low; break; case ShinyType6.Never: // Random Nonshiny pk.PID = Util.Rand32(); @@ -545,8 +554,8 @@ public sealed class WB7 : DataMysteryGift, ILangNick, IAwakened, INature, ILangN { if (OTGender != 3) { - if (SID != pk.SID) return false; - if (TID != pk.TID) return false; + if (SID16 != pk.SID16) return false; + if (TID16 != pk.TID16) return false; if (OTGender != pk.OT_Gender) return false; } var OT = GetOT(pk.Language); @@ -574,7 +583,7 @@ public sealed class WB7 : DataMysteryGift, ILangNick, IAwakened, INature, ILangN return false; // can't be traded away for unshiny } - if (pk.IsEgg && !pk.IsNative) + if (pk is { IsEgg: true, IsNative: false }) return false; } else diff --git a/PKHeX.Core/MysteryGifts/WB8.cs b/PKHeX.Core/MysteryGifts/WB8.cs index a4e87cbcb..02f0110d1 100644 --- a/PKHeX.Core/MysteryGifts/WB8.cs +++ b/PKHeX.Core/MysteryGifts/WB8.cs @@ -15,6 +15,7 @@ public sealed class WB8 : DataMysteryGift, ILangNick, INature, IRibbonIndex, ICo public override int Generation => 8; public override EntityContext Context => EntityContext.Gen8b; + public override bool FatefulEncounter => true; public bool IsDateRestricted => IsHOMEGift; public bool IsEquivalentFixedECPID => EncryptionConstant != 0 && PIDType == ShinyType8.FixedValue && PID == EncryptionConstant; @@ -105,27 +106,32 @@ public sealed class WB8 : DataMysteryGift, ILangNick, INature, IRibbonIndex, ICo _ => throw new ArgumentOutOfRangeException(), }; - private int GetShinyXor() + private uint GetShinyXor() { // Player owned anti-shiny fixed PID - if (TID == 0 && SID == 0) - return int.MaxValue; + if (ID32 == 0) + return uint.MaxValue; - var pid = PID; - var psv = (int)((pid >> 16) ^ (pid & 0xFFFF)); - var tsv = (TID ^ SID); - return psv ^ tsv; + var xor = PID ^ ID32; + return (xor >> 16) ^ (xor & 0xFFFF); } - public override int TID + public override uint ID32 + { + get => ReadUInt32LittleEndian(Data.AsSpan(CardStart + 0x20)); + set => WriteUInt32LittleEndian(Data.AsSpan(CardStart + 0x20), value); + } + + public override ushort TID16 { get => ReadUInt16LittleEndian(Data.AsSpan(CardStart + 0x20)); - set => WriteUInt16LittleEndian(Data.AsSpan(CardStart + 0x20), (ushort)value); + set => WriteUInt16LittleEndian(Data.AsSpan(CardStart + 0x20), value); } - public override int SID { + public override ushort SID16 + { get => ReadUInt16LittleEndian(Data.AsSpan(CardStart + 0x22)); - set => WriteUInt16LittleEndian(Data.AsSpan(CardStart + 0x22), (ushort)value); + set => WriteUInt16LittleEndian(Data.AsSpan(CardStart + 0x22), value); } public int OriginGame @@ -190,17 +196,21 @@ public sealed class WB8 : DataMysteryGift, ILangNick, INature, IRibbonIndex, ICo private const int RibbonBytesCount = 0x20; private const int RibbonByteNone = 0xFF; // signed -1 - public bool HasMark() + private ReadOnlySpan RibbonSpan => Data.AsSpan(RibbonBytesOffset, RibbonBytesCount); + + public bool HasMarkEncounter8 { - for (int i = 0; i < RibbonBytesCount; i++) + get { - var value = Data[RibbonBytesOffset + i]; - if (value == RibbonByteNone) - return false; - if ((RibbonIndex)value is >= MarkLunchtime and <= MarkSlump) - return true; + foreach (var value in RibbonSpan) + { + if (value == RibbonByteNone) + return false; // end + if (((RibbonIndex)value).IsEncounterMark8()) + return true; + } + return false; } - return false; } public byte GetRibbonAtIndex(int byteIndex) @@ -360,11 +370,13 @@ public sealed class WB8 : DataMysteryGift, ILangNick, INature, IRibbonIndex, ICo public bool IsNicknamed => false; public int Language => 2; - public string GetNickname(int language) => StringConverter8.GetString(Data.AsSpan(GetNicknameOffset(language), 0x1A)); - public void SetNickname(int language, string value) => StringConverter8.SetString(Data.AsSpan(GetNicknameOffset(language), 0x1A), value.AsSpan(), 12, StringConverterOption.ClearZero); + private Span GetNicknameSpan(int language) => Data.AsSpan(GetNicknameOffset(language), 0x1A); + public string GetNickname(int language) => StringConverter8.GetString(GetNicknameSpan(language)); + public void SetNickname(int language, ReadOnlySpan value) => StringConverter8.SetString(GetNicknameSpan(language), value, 12, StringConverterOption.ClearZero); - public string GetOT(int language) => StringConverter8.GetString(Data.AsSpan(GetOTOffset(language), 0x1A)); - public void SetOT(int language, string value) => StringConverter8.SetString(Data.AsSpan(GetOTOffset(language), 0x1A), value.AsSpan(), 12, StringConverterOption.ClearZero); + private Span GetOTSpan(int language) => Data.AsSpan(GetOTOffset(language), 0x1A); + public string GetOT(int language) => StringConverter8.GetString(GetOTSpan(language)); + public void SetOT(int language, ReadOnlySpan value) => StringConverter8.SetString(GetOTSpan(language), value, 12, StringConverterOption.ClearZero); private static int GetNicknameOffset(int language) { @@ -388,7 +400,7 @@ public sealed class WB8 : DataMysteryGift, ILangNick, INature, IRibbonIndex, ICo set { } } - public override PKM ConvertToPKM(ITrainerInfo tr, EncounterCriteria criteria) + public override PB8 ConvertToPKM(ITrainerInfo tr, EncounterCriteria criteria) { if (!IsEntity) throw new ArgumentException(nameof(IsEntity)); @@ -402,8 +414,8 @@ public sealed class WB8 : DataMysteryGift, ILangNick, INature, IRibbonIndex, ICo var pk = new PB8 { EncryptionConstant = EncryptionConstant != 0 ? EncryptionConstant : Util.Rand32(), - TID = TID, - SID = SID, + TID16 = TID16, + SID16 = SID16, Species = Species, Form = Form, CurrentLevel = currentLevel, @@ -470,13 +482,13 @@ public sealed class WB8 : DataMysteryGift, ILangNick, INature, IRibbonIndex, ICo while (!CanBeReceivedByVersion(pk.Version, pk)); } - if (pk.TID == 0 && pk.SID == 0) + if (pk is { TID16: 0, SID16: 0 }) { - pk.TID = tr.TID; - pk.SID = tr.SID; + pk.TID16 = tr.TID16; + pk.SID16 = tr.SID16; } - pk.MetDate = IsDateRestricted && EncounterServerDate.WB8Gifts.TryGetValue(CardID, out var dt) ? dt.Start : DateTime.Now; + pk.MetDate = IsDateRestricted && EncounterServerDate.WB8Gifts.TryGetValue(CardID, out var dt) ? dt.Start : DateOnly.FromDateTime(DateTime.Now); // HOME Gifts for Sinnoh/Hisui starters were forced JPN until May 20, 2022 (UTC). if (CardID is 9015 or 9016 or 9017) pk.Met_Day = 20; @@ -510,7 +522,7 @@ public sealed class WB8 : DataMysteryGift, ILangNick, INature, IRibbonIndex, ICo private void SetEggMetData(PKM pk) { pk.IsEgg = true; - pk.EggMetDate = DateTime.Now; + pk.EggMetDate = DateOnly.FromDateTime(DateTime.Now); pk.Nickname = SpeciesName.GetEggName(pk.Language, Generation); pk.IsNicknamed = false; } @@ -543,20 +555,20 @@ public sealed class WB8 : DataMysteryGift, ILangNick, INature, IRibbonIndex, ICo _ => AbilityPermission.Any12H, }; - private uint GetPID(ITrainerID tr, ShinyType8 type) => type switch + private uint GetPID(ITrainerID32 tr, ShinyType8 type) => type switch { ShinyType8.Never => GetAntishiny(tr), // Random, Never Shiny ShinyType8.Random => Util.Rand32(), // Random, Any - ShinyType8.AlwaysStar => (uint)(((tr.TID ^ tr.SID ^ (PID & 0xFFFF) ^ 1) << 16) | (PID & 0xFFFF)), // Fixed, Force Star - ShinyType8.AlwaysSquare => (uint)(((tr.TID ^ tr.SID ^ (PID & 0xFFFF) ^ 0) << 16) | (PID & 0xFFFF)), // Fixed, Force Square + ShinyType8.AlwaysStar => (1u ^ (PID & 0xFFFF) ^ tr.TID16 ^ tr.SID16) << 16 | (PID & 0xFFFF), // Fixed, Force Star + ShinyType8.AlwaysSquare => (0u ^ (PID & 0xFFFF) ^ tr.TID16 ^ tr.SID16) << 16 | (PID & 0xFFFF), // Fixed, Force Square ShinyType8.FixedValue => GetFixedPID(tr), _ => throw new ArgumentOutOfRangeException(nameof(type)), }; - private uint GetFixedPID(ITrainerID tr) + private uint GetFixedPID(ITrainerID32 tr) { var pid = PID; - if (pid != 0 && !(TID == 0 && SID == 0)) + if (pid != 0 && ID32 != 0) return pid; if (!tr.IsShiny(pid, 8)) @@ -566,13 +578,9 @@ public sealed class WB8 : DataMysteryGift, ILangNick, INature, IRibbonIndex, ICo return pid; } - private static uint GetAntishinyFixedHOME(ITrainerID tr) - { - var fid = ((uint)(tr.SID << 16) | (uint)tr.TID); - return fid ^ 0x10u; - } + private static uint GetAntishinyFixedHOME(ITrainerID32 tr) => tr.ID32 ^ 0x10u; - private static uint GetAntishiny(ITrainerID tr) + private static uint GetAntishiny(ITrainerID32 tr) { var pid = Util.Rand32(); if (tr.IsShiny(pid, 8)) @@ -619,8 +627,8 @@ public sealed class WB8 : DataMysteryGift, ILangNick, INature, IRibbonIndex, ICo { if (OTGender < 2) { - if (SID != pk.SID) return false; - if (TID != pk.TID) return false; + if (SID16 != pk.SID16) return false; + if (TID16 != pk.TID16) return false; if (OTGender != pk.OT_Gender) return false; } @@ -653,7 +661,7 @@ public sealed class WB8 : DataMysteryGift, ILangNick, INature, IRibbonIndex, ICo { if (pk.Egg_Location != Locations.LinkTrade6NPC) return false; - if (PIDType == ShinyType8.Random && pk.IsShiny && pk.ShinyXor > 1) + if (PIDType == ShinyType8.Random && pk is { IsShiny: true, ShinyXor: > 1 }) return false; // shiny traded egg will always have xor0/1. } if (!Shiny.IsValid(pk)) @@ -661,7 +669,7 @@ public sealed class WB8 : DataMysteryGift, ILangNick, INature, IRibbonIndex, ICo return false; // can't be traded away for unshiny } - if (pk.IsEgg && !pk.IsNative) + if (pk is { IsEgg: true, IsNative: false }) return false; } else diff --git a/PKHeX.Core/MysteryGifts/WC3.cs b/PKHeX.Core/MysteryGifts/WC3.cs index 872644093..b7f81e934 100644 --- a/PKHeX.Core/MysteryGifts/WC3.cs +++ b/PKHeX.Core/MysteryGifts/WC3.cs @@ -13,15 +13,20 @@ public sealed class WC3 : MysteryGift, IRibbonSetEvent3, ILangNicknamedTemplate { public override MysteryGift Clone() => (WC3)MemberwiseClone(); + public WC3(bool fateful = false) => FatefulEncounter = fateful; + /// /// Matched Type /// - public PIDType Method; + public PIDType Method { get; init; } + + private const ushort UnspecifiedID = ushort.MaxValue; public override string OT_Name { get; set; } = string.Empty; public int OT_Gender { get; init; } = 3; - public override int TID { get; set; } - public override int SID { get; set; } + public override uint ID32 { get => (uint)(SID16 << 16 | TID16); set => (SID16, TID16) = ((ushort)(value >> 16), (ushort)value); } + public override ushort TID16 { get; set; } = UnspecifiedID; + public override ushort SID16 { get; set; } = UnspecifiedID; public override int Location { get; set; } = 255; public override int EggLocation { get => 0; set {} } public override GameVersion Version { get; set; } @@ -31,7 +36,7 @@ public sealed class WC3 : MysteryGift, IRibbonSetEvent3, ILangNicknamedTemplate public override Moveset Moves { get; set; } public bool NotDistributed { get; init; } public override Shiny Shiny { get; init; } - public bool Fateful { get; init; } // Obedience Flag + public override bool FatefulEncounter { get; } // Obedience Flag // Mystery Gift Properties public override int Generation => 3; @@ -47,7 +52,7 @@ public sealed class WC3 : MysteryGift, IRibbonSetEvent3, ILangNicknamedTemplate public bool RibbonChampionRegional { get; set; } public bool RibbonChampionNational { get; set; } - public string? Nickname { get; set; } + public string? Nickname { get; init; } // Description public override string CardTitle { get; set; } = "Generation 3 Event"; @@ -74,7 +79,7 @@ public sealed class WC3 : MysteryGift, IRibbonSetEvent3, ILangNicknamedTemplate public override AbilityPermission Ability => AbilityPermission.Any12; - public override PKM ConvertToPKM(ITrainerInfo tr, EncounterCriteria criteria) + public override PK3 ConvertToPKM(ITrainerInfo tr, EncounterCriteria criteria) { PK3 pk = new() { @@ -91,7 +96,7 @@ public sealed class WC3 : MysteryGift, IRibbonSetEvent3, ILangNicknamedTemplate RibbonChampionRegional = RibbonChampionRegional, RibbonChampionNational = RibbonChampionNational, - FatefulEncounter = Fateful, + FatefulEncounter = FatefulEncounter, Version = GetVersion(tr), }; pk.EXP = Experience.GetEXP(Level, pk.PersonalInfo.EXPGrowth); @@ -105,8 +110,8 @@ public sealed class WC3 : MysteryGift, IRibbonSetEvent3, ILangNicknamedTemplate else { pk.OT_Gender = OT_Gender != 3 ? OT_Gender & 1 : tr.Gender; - pk.TID = TID; - pk.SID = SID; + pk.TID16 = TID16; + pk.SID16 = SID16; pk.Language = (int)GetSafeLanguage((LanguageID)tr.Language); pk.OT_Name = !string.IsNullOrWhiteSpace(OT_Name) ? OT_Name : tr.OT; @@ -141,8 +146,8 @@ public sealed class WC3 : MysteryGift, IRibbonSetEvent3, ILangNicknamedTemplate } pk.OT_Gender = sav.Gender; - pk.TID = sav.TID; - pk.SID = sav.SID; + pk.TID16 = sav.TID16; + pk.SID16 = sav.SID16; pk.Met_Location = pk.FRLG ? 146 /* Four Island */ : 32; // Route 117 pk.FatefulEncounter &= pk.FRLG; // clear flag for RSE pk.Met_Level = 0; // hatched @@ -172,7 +177,7 @@ public sealed class WC3 : MysteryGift, IRibbonSetEvent3, ILangNicknamedTemplate private void SetPINGA(PK3 pk, EncounterCriteria _) { var seed = Util.Rand32(); - seed = TID == 06930 ? MystryMew.GetSeed(seed, Method) : GetSaneSeed(seed); + seed = TID16 == 06930 ? MystryMew.GetSeed(seed, Method) : GetSaneSeed(seed); PIDGenerator.SetValuesFromSeed(pk, Method, seed); } @@ -222,8 +227,8 @@ public sealed class WC3 : MysteryGift, IRibbonSetEvent3, ILangNicknamedTemplate bool hatchedEgg = IsEgg && !pk.IsEgg; if (!hatchedEgg) { - if (SID != -1 && SID != pk.SID) return false; - if (TID != -1 && TID != pk.TID) return false; + if (SID16 != UnspecifiedID && SID16 != pk.SID16) return false; + if (TID16 != UnspecifiedID && TID16 != pk.TID16) return false; if (OT_Gender < 3 && OT_Gender != pk.OT_Gender) return false; var wcOT = OT_Name; if (!string.IsNullOrEmpty(wcOT)) @@ -245,7 +250,7 @@ public sealed class WC3 : MysteryGift, IRibbonSetEvent3, ILangNicknamedTemplate if (Language != -1 && Language != pk.Language) return false; if (Ball != pk.Ball) return false; - if (Fateful != pk.FatefulEncounter) + if (FatefulEncounter != pk.FatefulEncounter) { // XD Gifts only at level 20 get flagged after transfer if (Version == GameVersion.XD != (pk is XK3)) @@ -271,7 +276,7 @@ public sealed class WC3 : MysteryGift, IRibbonSetEvent3, ILangNicknamedTemplate return true; } - private static bool GetIsValidOTMattleHoOh(string wc, string ot, bool ck3) + private static bool GetIsValidOTMattleHoOh(ReadOnlySpan wc, ReadOnlySpan ot, bool ck3) { if (ck3) // match original if still ck3, otherwise must be truncated 7char return wc == ot; diff --git a/PKHeX.Core/MysteryGifts/WC6.cs b/PKHeX.Core/MysteryGifts/WC6.cs index 7953efd61..81796bccc 100644 --- a/PKHeX.Core/MysteryGifts/WC6.cs +++ b/PKHeX.Core/MysteryGifts/WC6.cs @@ -12,6 +12,7 @@ public sealed class WC6 : DataMysteryGift, IRibbonSetEvent3, IRibbonSetEvent4, I public const uint EonTicketConst = 0x225D73C2; public override int Generation => 6; public override EntityContext Context => EntityContext.Gen6; + public override bool FatefulEncounter => !IsLinkGift; // Link gifts do not set fateful encounter; public WC6() : this(new byte[Size]) { } public WC6(byte[] data) : base(data) { } @@ -41,7 +42,7 @@ public sealed class WC6 : DataMysteryGift, IRibbonSetEvent3, IRibbonSetEvent4, I { // Max len 36 char, followed by null terminator get => StringConverter6.GetString(Data.AsSpan(2, 0x4A)); - set => StringConverter6.SetString(Data.AsSpan(2, 0x4A), value.AsSpan(), 36, StringConverterOption.ClearZero); + set => StringConverter6.SetString(Data.AsSpan(2, 0x4A), value, 36, StringConverterOption.ClearZero); } internal uint RawDate @@ -73,7 +74,7 @@ public sealed class WC6 : DataMysteryGift, IRibbonSetEvent3, IRibbonSetEvent4, I /// /// Gets or sets the date of the card. /// - public DateTime? Date + public DateOnly? Date { get { @@ -81,7 +82,7 @@ public sealed class WC6 : DataMysteryGift, IRibbonSetEvent3, IRibbonSetEvent4, I if (!DateUtil.IsDateValid(Year, Month, Day)) return null; - return new DateTime((int)Year, (int)Month, (int)Day); + return new DateOnly((int)Year, (int)Month, (int)Day); } set { @@ -138,20 +139,19 @@ public sealed class WC6 : DataMysteryGift, IRibbonSetEvent3, IRibbonSetEvent4, I _ => throw new ArgumentOutOfRangeException(), }; - private int GetShinyXor() + private uint GetShinyXor() { // Player owned anti-shiny fixed PID - if (TID == 0 && SID == 0) - return int.MaxValue; + if (ID32 == 0) + return uint.MaxValue; - var pid = PID; - var psv = (int)((pid >> 16) ^ (pid & 0xFFFF)); - var tsv = TID ^ SID; - return psv ^ tsv; + var xor = PID ^ ID32; + return (xor >> 16) ^ (xor & 0xFFFF); } - public override int TID { get => ReadUInt16LittleEndian(Data.AsSpan(0x68)); set => WriteUInt16LittleEndian(Data.AsSpan(0x68), (ushort)value); } - public override int SID { get => ReadUInt16LittleEndian(Data.AsSpan(0x6A)); set => WriteUInt16LittleEndian(Data.AsSpan(0x6A), (ushort)value); } + public override uint ID32 { get => ReadUInt32LittleEndian(Data.AsSpan(0x68)); set => WriteUInt32LittleEndian(Data.AsSpan(0x68), value); } + public override ushort TID16 { get => ReadUInt16LittleEndian(Data.AsSpan(0x68)); set => WriteUInt16LittleEndian(Data.AsSpan(0x68), value); } + public override ushort SID16 { get => ReadUInt16LittleEndian(Data.AsSpan(0x6A)); set => WriteUInt16LittleEndian(Data.AsSpan(0x6A), value); } public int OriginGame { get => Data[0x6C]; set => Data[0x6C] = (byte)value; } public uint EncryptionConstant { get => ReadUInt32LittleEndian(Data.AsSpan(0x70)); set => WriteUInt32LittleEndian(Data.AsSpan(0x70), value); } public override int Ball { get => Data[0x76]; set => Data[0x76] = (byte)value; } @@ -169,7 +169,7 @@ public sealed class WC6 : DataMysteryGift, IRibbonSetEvent3, IRibbonSetEvent4, I public string Nickname { get => StringConverter6.GetString(Data.AsSpan(0x86, 0x1A)); - set => StringConverter6.SetString(Data.AsSpan(0x86, 0x1A), value.AsSpan(), 12, StringConverterOption.ClearZero); + set => StringConverter6.SetString(Data.AsSpan(0x86, 0x1A), value, 12, StringConverterOption.ClearZero); } public int Nature { get => (sbyte)Data[0xA0]; set => Data[0xA0] = (byte)value; } @@ -198,7 +198,7 @@ public sealed class WC6 : DataMysteryGift, IRibbonSetEvent3, IRibbonSetEvent4, I public override string OT_Name { get => StringConverter6.GetString(Data.AsSpan(0xB6, 0x1A)); - set => StringConverter6.SetString(Data.AsSpan(0xB6, 0x1A), value.AsSpan(), 12, StringConverterOption.ClearZero); + set => StringConverter6.SetString(Data.AsSpan(0xB6, 0x1A), value, 12, StringConverterOption.ClearZero); } public override byte Level { get => Data[0xD0]; set => Data[0xD0] = value; } @@ -293,21 +293,21 @@ public sealed class WC6 : DataMysteryGift, IRibbonSetEvent3, IRibbonSetEvent4, I public bool IsLinkGift => MetLocation == Locations.LinkGift6; - public override PKM ConvertToPKM(ITrainerInfo tr, EncounterCriteria criteria) + public override PK6 ConvertToPKM(ITrainerInfo tr, EncounterCriteria criteria) { if (!IsEntity) throw new ArgumentException(nameof(IsEntity)); var rnd = Util.Rand; - int currentLevel = Level > 0 ? Level : rnd.Next(1, 101); + int currentLevel = Level > 0 ? Level : (1 + rnd.Next(100)); var pi = PersonalTable.AO.GetFormEntry(Species, Form); PK6 pk = new() { Species = Species, HeldItem = HeldItem, - TID = TID, - SID = SID, + TID16 = TID16, + SID16 = SID16, Met_Level = currentLevel, Form = Form, EncryptionConstant = EncryptionConstant != 0 ? EncryptionConstant : Util.Rand32(), @@ -358,7 +358,7 @@ public sealed class WC6 : DataMysteryGift, IRibbonSetEvent3, IRibbonSetEvent4, I OT_Memory = OT_Memory, OT_TextVar = OT_TextVar, OT_Feeling = OT_Feeling, - FatefulEncounter = !IsLinkGift, // Link gifts do not set fateful encounter + FatefulEncounter = FatefulEncounter, EV_HP = EV_HP, EV_ATK = EV_ATK, @@ -381,7 +381,7 @@ public sealed class WC6 : DataMysteryGift, IRibbonSetEvent3, IRibbonSetEvent4, I pk.SetMaximumPPCurrent(); - pk.MetDate = Date ?? DateTime.Now; + pk.MetDate = Date ?? DateOnly.FromDateTime(DateTime.Now); if ((tr.Generation > Generation && OriginGame == 0) || !CanBeReceivedByVersion(pk.Version)) { @@ -468,8 +468,8 @@ public sealed class WC6 : DataMysteryGift, IRibbonSetEvent3, IRibbonSetEvent4, I pk.PID = Util.Rand32(); break; case ShinyType6.Always: // Random Shiny - pk.PID = Util.Rand32(); - pk.PID = (uint)(((pk.TID ^ pk.SID ^ (pk.PID & 0xFFFF)) << 16) | (pk.PID & 0xFFFF)); + var low = Util.Rand32() & 0xFFFF; + pk.PID = (low ^ pk.TID16 ^ pk.SID16) << 16 | low; break; case ShinyType6.Never: // Random Nonshiny pk.PID = Util.Rand32(); @@ -527,8 +527,8 @@ public sealed class WC6 : DataMysteryGift, IRibbonSetEvent3, IRibbonSetEvent4, I // Skip ID check if ORASDEMO Simulated wc6 if (CardID != 0) { - if (SID != pk.SID) return false; - if (TID != pk.TID) return false; + if (SID16 != pk.SID16) return false; + if (TID16 != pk.TID16) return false; } if (OTGender != pk.OT_Gender) return false; } @@ -554,7 +554,7 @@ public sealed class WC6 : DataMysteryGift, IRibbonSetEvent3, IRibbonSetEvent4, I return false; // can't be traded away for unshiny } - if (pk.IsEgg && !pk.IsNative) + if (pk is { IsEgg: true, IsNative: false }) return false; } else diff --git a/PKHeX.Core/MysteryGifts/WC7.cs b/PKHeX.Core/MysteryGifts/WC7.cs index 10c70e33f..13610a8e7 100644 --- a/PKHeX.Core/MysteryGifts/WC7.cs +++ b/PKHeX.Core/MysteryGifts/WC7.cs @@ -11,6 +11,7 @@ public sealed class WC7 : DataMysteryGift, IRibbonSetEvent3, IRibbonSetEvent4, I public const int Size = 0x108; public override int Generation => 7; public override EntityContext Context => EntityContext.Gen7; + public override bool FatefulEncounter => true; public WC7() : this(new byte[Size]) { } public WC7(byte[] data) : base(data) { } @@ -40,7 +41,7 @@ public sealed class WC7 : DataMysteryGift, IRibbonSetEvent3, IRibbonSetEvent4, I { // Max len 36 char, followed by null terminator get => StringConverter7.GetString(Data.AsSpan(2, 0x4A)); - set => StringConverter7.SetString(Data.AsSpan(2, 0x4A), value.AsSpan(), 36, Language, StringConverterOption.ClearZero); + set => StringConverter7.SetString(Data.AsSpan(2, 0x4A), value, 36, Language, StringConverterOption.ClearZero); } internal uint RawDate @@ -72,7 +73,7 @@ public sealed class WC7 : DataMysteryGift, IRibbonSetEvent3, IRibbonSetEvent4, I /// /// Gets or sets the date of the card. /// - public DateTime? Date + public DateOnly? Date { get { @@ -80,7 +81,7 @@ public sealed class WC7 : DataMysteryGift, IRibbonSetEvent3, IRibbonSetEvent4, I if (!DateUtil.IsDateValid(Year, Month, Day)) return null; - return new DateTime((int)Year, (int)Month, (int)Day); + return new DateOnly((int)Year, (int)Month, (int)Day); } set { @@ -153,27 +154,32 @@ public sealed class WC7 : DataMysteryGift, IRibbonSetEvent3, IRibbonSetEvent4, I _ => throw new ArgumentOutOfRangeException(), }; - private int GetShinyXor() + private uint GetShinyXor() { // Player owned anti-shiny fixed PID - if (TID == 0 && SID == 0) - return int.MaxValue; + if (ID32 == 0) + return uint.MaxValue; - var pid = PID; - var psv = (int)((pid >> 16) ^ (pid & 0xFFFF)); - var tsv = (TID ^ SID); - return psv ^ tsv; + var xor = PID ^ ID32; + return (xor >> 16) ^ (xor & 0xFFFF); } - public override int TID + public override uint ID32 + { + get => ReadUInt32LittleEndian(Data.AsSpan(0x68)); + set => WriteUInt32LittleEndian(Data.AsSpan(0x68), value); + } + + public override ushort TID16 { get => ReadUInt16LittleEndian(Data.AsSpan(0x68)); - set => WriteUInt16LittleEndian(Data.AsSpan(0x68), (ushort)value); + set => WriteUInt16LittleEndian(Data.AsSpan(0x68), value); } - public override int SID { + public override ushort SID16 + { get => ReadUInt16LittleEndian(Data.AsSpan(0x6A)); - set => WriteUInt16LittleEndian(Data.AsSpan(0x6A), (ushort)value); + set => WriteUInt16LittleEndian(Data.AsSpan(0x6A), value); } public int OriginGame @@ -209,7 +215,7 @@ public sealed class WC7 : DataMysteryGift, IRibbonSetEvent3, IRibbonSetEvent4, I public string Nickname { get => StringConverter7.GetString(Data.AsSpan(0x86, 0x1A)); - set => StringConverter7.SetString(Data.AsSpan(0x86, 0x1A), value.AsSpan(), 12, Language, StringConverterOption.ClearZero); + set => StringConverter7.SetString(Data.AsSpan(0x86, 0x1A), value, 12, Language, StringConverterOption.ClearZero); } public int Nature { get => (sbyte)Data[0xA0]; set => Data[0xA0] = (byte)value; } @@ -239,7 +245,7 @@ public sealed class WC7 : DataMysteryGift, IRibbonSetEvent3, IRibbonSetEvent4, I public override string OT_Name { get => StringConverter7.GetString(Data.AsSpan(0xB6, 0x1A)); - set => StringConverter7.SetString(Data.AsSpan(0xB6, 0x1A), value.AsSpan(), 12, Language, StringConverterOption.ClearZero); + set => StringConverter7.SetString(Data.AsSpan(0xB6, 0x1A), value, 12, Language, StringConverterOption.ClearZero); } public override byte Level { get => Data[0xD0]; set => Data[0xD0] = value; } @@ -345,14 +351,14 @@ public sealed class WC7 : DataMysteryGift, IRibbonSetEvent3, IRibbonSetEvent4, I } } - public override PKM ConvertToPKM(ITrainerInfo tr, EncounterCriteria criteria) + public override PK7 ConvertToPKM(ITrainerInfo tr, EncounterCriteria criteria) { if (!IsEntity) throw new ArgumentException(nameof(IsEntity)); var rnd = Util.Rand; - int currentLevel = Level > 0 ? Level : rnd.Next(1, 101); + int currentLevel = Level > 0 ? Level : (1 + rnd.Next(100)); int metLevel = MetLevel > 0 ? MetLevel : currentLevel; var version = OriginGame != 0 ? OriginGame : (int)this.GetCompatibleVersion((GameVersion)tr.Game); var language = Language != 0 ? Language : (int)Core.Language.GetSafeLanguage(Generation, (LanguageID)tr.Language, (GameVersion)version); @@ -362,8 +368,8 @@ public sealed class WC7 : DataMysteryGift, IRibbonSetEvent3, IRibbonSetEvent4, I { Species = Species, HeldItem = HeldItem, - TID = TID, - SID = SID, + TID16 = TID16, + SID16 = SID16, Met_Level = metLevel, Form = Form, EncryptionConstant = EncryptionConstant != 0 ? EncryptionConstant : Util.Rand32(), @@ -446,11 +452,11 @@ public sealed class WC7 : DataMysteryGift, IRibbonSetEvent3, IRibbonSetEvent4, I if (OTGender == 3) { - pk.TID = tr.TID; - pk.SID = tr.SID; + pk.TID16 = tr.TID16; + pk.SID16 = tr.SID16; } - pk.MetDate = Date ?? DateTime.Now; + pk.MetDate = Date ?? DateOnly.FromDateTime(DateTime.Now); pk.IsNicknamed = IsNicknamed; pk.Nickname = IsNicknamed ? Nickname : SpeciesName.GetSpeciesNameGeneration(Species, pk.Language, Generation); @@ -511,8 +517,8 @@ public sealed class WC7 : DataMysteryGift, IRibbonSetEvent3, IRibbonSetEvent4, I pk.PID = Util.Rand32(); break; case ShinyType6.Always: // Random Shiny - pk.PID = Util.Rand32(); - pk.PID = (uint)(((pk.TID ^ pk.SID ^ (pk.PID & 0xFFFF)) << 16) | (pk.PID & 0xFFFF)); + var low = Util.Rand32() & 0xFFFF; + pk.PID = ((low ^ pk.TID16 ^ pk.SID16) << 16) | low; break; case ShinyType6.Never: // Random Nonshiny pk.PID = Util.Rand32(); @@ -551,7 +557,7 @@ public sealed class WC7 : DataMysteryGift, IRibbonSetEvent3, IRibbonSetEvent4, I public bool IsAshGreninjaWC7(PKM pk) { - return CardID == 2046 && ((pk.SID << 16) | pk.TID) == 0x79F57B49; + return CardID == 2046 && ((pk.SID16 << 16) | pk.TID16) == 0x79F57B49; } public override bool IsMatchExact(PKM pk, EvoCriteria evo) @@ -560,8 +566,8 @@ public sealed class WC7 : DataMysteryGift, IRibbonSetEvent3, IRibbonSetEvent4, I { if (OTGender != 3) { - if (SID != pk.SID) return false; - if (TID != pk.TID) return false; + if (SID16 != pk.SID16) return false; + if (TID16 != pk.TID16) return false; if (OTGender != pk.OT_Gender) return false; } if (!string.IsNullOrEmpty(OT_Name) && OT_Name != pk.OT_Name) return false; @@ -585,7 +591,7 @@ public sealed class WC7 : DataMysteryGift, IRibbonSetEvent3, IRibbonSetEvent4, I return false; // can't be traded away for un-shiny } - if (pk.IsEgg && !pk.IsNative) + if (pk is { IsEgg: true, IsNative: false }) return false; } else diff --git a/PKHeX.Core/MysteryGifts/WC8.cs b/PKHeX.Core/MysteryGifts/WC8.cs index 290d938f3..27d4c72d1 100644 --- a/PKHeX.Core/MysteryGifts/WC8.cs +++ b/PKHeX.Core/MysteryGifts/WC8.cs @@ -15,6 +15,7 @@ public sealed class WC8 : DataMysteryGift, ILangNick, INature, IGigantamax, IDyn public override int Generation => 8; public override EntityContext Context => EntityContext.Gen8; + public override bool FatefulEncounter => true; public enum GiftType : byte { @@ -90,7 +91,7 @@ public sealed class WC8 : DataMysteryGift, ILangNick, INature, IGigantamax, IDyn public override Shiny Shiny => PIDType switch { - ShinyType8.FixedValue => FixedShinyType(DateTime.UtcNow), + ShinyType8.FixedValue => FixedShinyType(DateOnly.FromDateTime(DateTime.UtcNow)), ShinyType8.Random => Shiny.Random, ShinyType8.Never => Shiny.Never, ShinyType8.AlwaysStar => Shiny.AlwaysStar, @@ -98,34 +99,39 @@ public sealed class WC8 : DataMysteryGift, ILangNick, INature, IGigantamax, IDyn _ => throw new ArgumentOutOfRangeException(), }; - private Shiny FixedShinyType(DateTime date) => IsHOMEGift && IsHOMEShinyPossible(date) ? Shiny.Random : GetShinyXor() switch + private Shiny FixedShinyType(DateOnly date) => IsHOMEGift && IsHOMEShinyPossible(date) ? Shiny.Random : GetShinyXor() switch { 0 => Shiny.AlwaysSquare, <= 15 => Shiny.AlwaysStar, _ => Shiny.Never, }; - private int GetShinyXor() + private uint GetShinyXor() { // Player owned anti-shiny fixed PID - if (TID == 0 && SID == 0) - return int.MaxValue; + if (ID32 == 0) + return uint.MaxValue; - var pid = PID; - var psv = (int)((pid >> 16) ^ (pid & 0xFFFF)); - var tsv = (TID ^ SID); - return psv ^ tsv; + var xor = PID ^ ID32; + return (xor >> 16) ^ (xor & 0xFFFF); } - public override int TID + public override uint ID32 + { + get => ReadUInt32LittleEndian(Data.AsSpan(CardStart + 0x20)); + set => WriteUInt32LittleEndian(Data.AsSpan(CardStart + 0x20), value); + } + + public override ushort TID16 { get => ReadUInt16LittleEndian(Data.AsSpan(CardStart + 0x20)); - set => WriteUInt16LittleEndian(Data.AsSpan(CardStart + 0x20), (ushort)value); + set => WriteUInt16LittleEndian(Data.AsSpan(CardStart + 0x20), value); } - public override int SID { + public override ushort SID16 + { get => ReadUInt16LittleEndian(Data.AsSpan(CardStart + 0x22)); - set => WriteUInt16LittleEndian(Data.AsSpan(CardStart + 0x22), (ushort)value); + set => WriteUInt16LittleEndian(Data.AsSpan(CardStart + 0x22), value); } public int OriginGame @@ -190,17 +196,21 @@ public sealed class WC8 : DataMysteryGift, ILangNick, INature, IGigantamax, IDyn private const int RibbonBytesCount = 0x20; private const int RibbonByteNone = 0xFF; // signed -1 - public bool HasMark() + public bool HasMarkEncounter8 { - for (int i = 0; i < RibbonBytesCount; i++) + get { - var value = Data[RibbonBytesOffset + i]; - if (value == RibbonByteNone) - return false; - if ((RibbonIndex)value is >= MarkLunchtime and <= MarkSlump) - return true; + for (int i = 0; i < RibbonBytesCount; i++) + { + var value = Data[RibbonBytesOffset + i]; + if (value == RibbonByteNone) + return false; + if ((RibbonIndex)value is >= MarkLunchtime and <= MarkSlump) + return true; + } + + return false; } - return false; } public byte GetRibbonAtIndex(int byteIndex) @@ -358,11 +368,13 @@ public sealed class WC8 : DataMysteryGift, ILangNick, INature, IGigantamax, IDyn public bool IsNicknamed => false; public int Language => 2; - public string GetNickname(int language) => StringConverter8.GetString(Data.AsSpan(GetNicknameOffset(language), 0x1A)); - public void SetNickname(int language, string value) => StringConverter8.SetString(Data.AsSpan(GetNicknameOffset(language), 0x1A), value.AsSpan(), 12, StringConverterOption.ClearZero); + private Span GetNicknameSpan(int language) => Data.AsSpan(GetNicknameOffset(language), 0x1A); + public string GetNickname(int language) => StringConverter8.GetString(GetNicknameSpan(language)); + public void SetNickname(int language, ReadOnlySpan value) => StringConverter8.SetString(GetNicknameSpan(language), value, 12, StringConverterOption.ClearZero); - public string GetOT(int language) => StringConverter8.GetString(Data.AsSpan(GetOTOffset(language), 0x1A)); - public void SetOT(int language, string value) => StringConverter8.SetString(Data.AsSpan(GetOTOffset(language), 0x1A), value.AsSpan(), 12, StringConverterOption.ClearZero); + private Span GetOTSpan(int language) => Data.AsSpan(GetOTOffset(language), 0x1A); + public string GetOT(int language) => StringConverter8.GetString(GetOTSpan(language)); + public void SetOT(int language, ReadOnlySpan value) => StringConverter8.SetString(GetOTSpan(language), value, 12, StringConverterOption.ClearZero); private static int GetNicknameOffset(int language) { @@ -386,7 +398,7 @@ public sealed class WC8 : DataMysteryGift, ILangNick, INature, IGigantamax, IDyn set { } } - public override PKM ConvertToPKM(ITrainerInfo tr, EncounterCriteria criteria) + public override PK8 ConvertToPKM(ITrainerInfo tr, EncounterCriteria criteria) { if (!IsEntity) throw new ArgumentException(nameof(IsEntity)); @@ -401,8 +413,8 @@ public sealed class WC8 : DataMysteryGift, ILangNick, INature, IGigantamax, IDyn var pk = new PK8 { EncryptionConstant = EncryptionConstant != 0 || IsHOMEGift ? EncryptionConstant : Util.Rand32(), - TID = TID, - SID = SID, + TID16 = TID16, + SID16 = SID16, Species = Species, Form = Form, CurrentLevel = currentLevel, @@ -462,16 +474,14 @@ public sealed class WC8 : DataMysteryGift, ILangNick, INature, IGigantamax, IDyn if (OTGender >= 2) { - pk.TID = tr.TID; - pk.SID = tr.SID; + pk.TID16 = tr.TID16; + pk.SID16 = tr.SID16; if (IsHOMEGift) { - pk.TrainerSID7 = 0; + pk.ID32 %= 1_000_000; while (pk.TSV == 0) - { - pk.TrainerID7 = Util.Rand.Next(16, 999_999 + 1); - } + pk.ID32 = (uint)Util.Rand.Next(16, 999_999 + 1); } } @@ -479,7 +489,7 @@ public sealed class WC8 : DataMysteryGift, ILangNick, INature, IGigantamax, IDyn if (pk.Species == (int)Core.Species.Meowstic) pk.Form = (byte)(pk.Gender & 1); - pk.MetDate = IsDateRestricted && EncounterServerDate.WC8Gifts.TryGetValue(CardID, out var dt) ? dt : DateTime.Now; + pk.MetDate = IsDateRestricted && EncounterServerDate.WC8Gifts.TryGetValue(CardID, out var dt) ? dt : DateOnly.FromDateTime(DateTime.Now); var nickname_language = GetLanguage(language); pk.Language = nickname_language != 0 ? nickname_language : tr.Language; @@ -513,7 +523,7 @@ public sealed class WC8 : DataMysteryGift, ILangNick, INature, IGigantamax, IDyn private void SetEggMetData(PKM pk) { pk.IsEgg = true; - pk.EggMetDate = DateTime.Now; + pk.EggMetDate = DateOnly.FromDateTime(DateTime.Now); pk.Nickname = SpeciesName.GetEggName(pk.Language, Generation); pk.IsNicknamed = true; } @@ -526,7 +536,7 @@ public sealed class WC8 : DataMysteryGift, ILangNick, INature, IGigantamax, IDyn pk.Gender = criteria.GetGender(Gender, pi); var av = GetAbilityIndex(criteria); pk.RefreshAbility(av); - SetPID(pk, pk.MetDate ?? DateTime.UtcNow); + SetPID(pk, pk.MetDate ?? DateOnly.FromDateTime(DateTime.UtcNow)); SetIVs(pk); } @@ -546,20 +556,20 @@ public sealed class WC8 : DataMysteryGift, ILangNick, INature, IGigantamax, IDyn _ => AbilityPermission.Any12H, }; - private uint GetPID(ITrainerID tr, ShinyType8 type, DateTime date) => type switch + private uint GetPID(ITrainerID32 tr, ShinyType8 type, DateOnly date) => type switch { ShinyType8.Never => GetAntishiny(tr), // Random, Never Shiny ShinyType8.Random => Util.Rand32(), // Random, Any - ShinyType8.AlwaysStar => (uint) (((tr.TID ^ tr.SID ^ (PID & 0xFFFF) ^ 1) << 16) | (PID & 0xFFFF)), // Fixed, Force Star - ShinyType8.AlwaysSquare => (uint) (((tr.TID ^ tr.SID ^ (PID & 0xFFFF) ^ 0) << 16) | (PID & 0xFFFF)), // Fixed, Force Square + ShinyType8.AlwaysStar => (1u ^ (PID & 0xFFFF) ^ tr.TID16 ^ tr.SID16) << 16 | (PID & 0xFFFF), // Fixed, Force Star + ShinyType8.AlwaysSquare => (0u ^ (PID & 0xFFFF) ^ tr.TID16 ^ tr.SID16) << 16 | (PID & 0xFFFF), // Fixed, Force Square ShinyType8.FixedValue => GetFixedPID(tr, date), _ => throw new ArgumentOutOfRangeException(nameof(type)), }; - private uint GetFixedPID(ITrainerID tr, DateTime date) + private uint GetFixedPID(ITrainerID32 tr, DateOnly date) { var pid = PID; - if (pid != 0 && !(TID == 0 && SID == 0)) + if (pid != 0 && ID32 != 0) return pid; if (!tr.IsShiny(pid, 8)) @@ -569,13 +579,9 @@ public sealed class WC8 : DataMysteryGift, ILangNick, INature, IGigantamax, IDyn return pid; } - private static uint GetAntishinyFixedHOME(ITrainerID tr) - { - var fid = (uint)(tr.SID << 16) | (uint)tr.TID; - return fid ^ 0x10u; - } + private static uint GetAntishinyFixedHOME(ITrainerID32 tr) => tr.ID32 ^ 0x10u; - private static uint GetAntishiny(ITrainerID tr) + private static uint GetAntishiny(ITrainerID32 tr) { var pid = Util.Rand32(); if (tr.IsShiny(pid, 8)) @@ -583,7 +589,7 @@ public sealed class WC8 : DataMysteryGift, ILangNick, INature, IGigantamax, IDyn return pid; } - private void SetPID(PKM pk, DateTime date) + private void SetPID(PKM pk, DateOnly date) { pk.PID = GetPID(pk, PIDType, date); } @@ -622,8 +628,8 @@ public sealed class WC8 : DataMysteryGift, ILangNick, INature, IGigantamax, IDyn { if (OTGender < 2) { - if (SID != pk.SID) return false; - if (TID != pk.TID) return false; + if (SID16 != pk.SID16) return false; + if (TID16 != pk.TID16) return false; if (OTGender != pk.OT_Gender) return false; } @@ -654,7 +660,7 @@ public sealed class WC8 : DataMysteryGift, ILangNick, INature, IGigantamax, IDyn } else // Never or Random (HOME ID specific) { - if (pk.IsShiny && !IsHOMEShinyPossible(pk.MetDate ?? DateTime.UtcNow)) + if (pk.IsShiny && !IsHOMEShinyPossible(pk.MetDate ?? DateOnly.FromDateTime(DateTime.UtcNow))) return false; } } @@ -665,14 +671,14 @@ public sealed class WC8 : DataMysteryGift, ILangNick, INature, IGigantamax, IDyn var shinyType = Shiny; if (PIDType == ShinyType8.FixedValue) - shinyType = FixedShinyType(pk.MetDate ?? DateTime.UtcNow); + shinyType = FixedShinyType(pk.MetDate ?? DateOnly.FromDateTime(DateTime.UtcNow)); if (IsEgg) { if (EggLocation != pk.Egg_Location) // traded { if (pk.Egg_Location != Locations.LinkTrade6) return false; - if (PIDType == ShinyType8.Random && pk.IsShiny && pk.ShinyXor > 1) + if (PIDType == ShinyType8.Random && pk is { IsShiny: true, ShinyXor: > 1 }) return false; // shiny traded egg will always have xor0/1. } if (!shinyType.IsValid(pk)) @@ -680,7 +686,7 @@ public sealed class WC8 : DataMysteryGift, ILangNick, INature, IGigantamax, IDyn return false; // can't be traded away for unshiny } - if (pk.IsEgg && !pk.IsNative) + if (pk is { IsEgg: true, IsNative: false }) return false; } else @@ -720,13 +726,13 @@ public sealed class WC8 : DataMysteryGift, ILangNick, INature, IGigantamax, IDyn var type = PIDType; if (type is ShinyType8.Never or ShinyType8.Random) return true; - return pk.PID == GetPID(pk, type, pk.MetDate ?? DateTime.UtcNow); + return pk.PID == GetPID(pk, type, pk.MetDate ?? DateOnly.FromDateTime(DateTime.UtcNow)); } - private bool IsHOMEShinyPossible(DateTime date) + private bool IsHOMEShinyPossible(DateOnly date) { - // no defined TID/SID and having a fixed PID can cause the player's TID/SID to match the PID's shiny calc. - return TID == 0 && SID == 0 && PID != 0 && (CardID < 9015 && date < new DateTime(2022, 5, 18)); + // no defined TID16/SID16 and having a fixed PID can cause the player's TID16/SID16 to match the PID's shiny calc. + return ID32 == 0 && PID != 0 && (CardID < 9015 && date < new DateOnly(2022, 5, 18)); } public bool IsDateRestricted => IsHOMEGift; diff --git a/PKHeX.Core/MysteryGifts/WC9.cs b/PKHeX.Core/MysteryGifts/WC9.cs index aadf10f8b..2b80bb4c9 100644 --- a/PKHeX.Core/MysteryGifts/WC9.cs +++ b/PKHeX.Core/MysteryGifts/WC9.cs @@ -15,6 +15,7 @@ public sealed class WC9 : DataMysteryGift, ILangNick, INature, ITeraType, IRibbo public override int Generation => 9; public override EntityContext Context => EntityContext.Gen9; + public override bool FatefulEncounter => true; public enum GiftType : byte { @@ -105,30 +106,34 @@ public sealed class WC9 : DataMysteryGift, ILangNick, INature, ITeraType, IRibbo _ => Shiny.Never, }; - private int GetShinyXor() + private uint GetShinyXor() { // Player owned anti-shiny fixed PID - if (TID == 0 && SID == 0) - return int.MaxValue; + if (ID32 == 0) + return uint.MaxValue; - var pid = PID; - var psv = (int)((pid >> 16) ^ (pid & 0xFFFF)); - var tsv = (TID ^ SID); - return psv ^ tsv; + var xor = PID ^ ID32; + return (xor >> 16) ^ (xor & 0xFFFF); } // When applying the TID32, the game sets the DisplayTID7 directly, then sets pk9.DisplaySID7 as (wc9.DisplaySID7 - wc9.CardID) // Since we expose the 16bit (pk9) component values here, just adjust them accordingly with an inlined calc. - public override int TID + public override uint ID32 { - get => (ushort)((ReadUInt32LittleEndian(Data.AsSpan(CardStart + 0x18)) - (1000000 * CardID)) & 0xFFFF); - set => WriteUInt32LittleEndian(Data.AsSpan(CardStart + 0x18), (uint)((SID << 16) | value) + (uint)(1000000 * CardID)); + get => ReadUInt32LittleEndian(Data.AsSpan(CardStart + 0x18)) - (1000000u * (uint)CardID); + set => WriteUInt32LittleEndian(Data.AsSpan(CardStart + 0x18), value + (1000000u * (uint)CardID)); } - public override int SID + public override ushort TID16 { - get => (ushort)((ReadUInt32LittleEndian(Data.AsSpan(CardStart + 0x18)) - (1000000 * CardID)) >> 16 & 0xFFFF); - set => WriteUInt32LittleEndian(Data.AsSpan(CardStart + 0x18), (uint)((value << 16) | TID) + (uint)(1000000 * CardID)); + get => (ushort)(ID32 & 0xFFFF); + set => ID32 = ((uint)SID16 << 16) | value; + } + + public override ushort SID16 + { + get => (ushort)(ID32 >> 16); + set => ID32 = ((uint)value << 16) | TID16; } public int OriginGame @@ -196,17 +201,36 @@ public sealed class WC9 : DataMysteryGift, ILangNick, INature, ITeraType, IRibbo private const int RibbonBytesCount = 0x20; private const int RibbonByteNone = 0xFF; // signed -1 - public bool HasMark() + private ReadOnlySpan RibbonSpan => Data.AsSpan(RibbonBytesOffset, RibbonBytesCount); + + public bool HasMarkEncounter8 { - for (int i = 0; i < RibbonBytesCount; i++) + get { - var value = Data[RibbonBytesOffset + i]; - if (value == RibbonByteNone) - return false; - if ((RibbonIndex)value is >= MarkLunchtime and <= MarkSlump) - return true; + foreach (var value in RibbonSpan) + { + if (value == RibbonByteNone) + return false; // end + if (((RibbonIndex)value).IsEncounterMark8()) + return true; + } + return false; + } + } + + public bool HasMarkEncounter9 + { + get + { + foreach (var value in RibbonSpan) + { + if (value == RibbonByteNone) + return false; // end + if (((RibbonIndex)value).IsEncounterMark9()) + return true; + } + return false; } - return false; } public byte GetRibbonAtIndex(int byteIndex) @@ -364,11 +388,13 @@ public sealed class WC9 : DataMysteryGift, ILangNick, INature, ITeraType, IRibbo public bool IsNicknamed => false; public int Language => 2; - public string GetNickname(int language) => StringConverter8.GetString(Data.AsSpan(GetNicknameOffset(language), 0x1A)); - public void SetNickname(int language, string value) => StringConverter8.SetString(Data.AsSpan(GetNicknameOffset(language), 0x1A), value.AsSpan(), 12, StringConverterOption.ClearZero); + private Span GetNicknameSpan(int language) => Data.AsSpan(GetNicknameOffset(language), 0x1A); + public string GetNickname(int language) => StringConverter8.GetString(GetNicknameSpan(language)); + public void SetNickname(int language, ReadOnlySpan value) => StringConverter8.SetString(GetNicknameSpan(language), value, 12, StringConverterOption.ClearZero); - public string GetOT(int language) => StringConverter8.GetString(Data.AsSpan(GetOTOffset(language), 0x1A)); - public void SetOT(int language, string value) => StringConverter8.SetString(Data.AsSpan(GetOTOffset(language), 0x1A), value.AsSpan(), 12, StringConverterOption.ClearZero); + private Span GetOTSpan(int language) => Data.AsSpan(GetOTOffset(language), 0x1A); + public string GetOT(int language) => StringConverter8.GetString(GetOTSpan(language)); + public void SetOT(int language, ReadOnlySpan value) => StringConverter8.SetString(GetOTSpan(language), value, 12, StringConverterOption.ClearZero); private static int GetNicknameOffset(int language) { @@ -392,7 +418,7 @@ public sealed class WC9 : DataMysteryGift, ILangNick, INature, ITeraType, IRibbo set { } } - public override PKM ConvertToPKM(ITrainerInfo tr, EncounterCriteria criteria) + public override PK9 ConvertToPKM(ITrainerInfo tr, EncounterCriteria criteria) { if (!IsEntity) throw new ArgumentException(nameof(IsEntity)); @@ -407,8 +433,8 @@ public sealed class WC9 : DataMysteryGift, ILangNick, INature, ITeraType, IRibbo var pk = new PK9 { EncryptionConstant = EncryptionConstant != 0 || IsHOMEGift ? EncryptionConstant : Util.Rand32(), - TID = TID, - SID = SID, + TID16 = TID16, + SID16 = SID16, Species = Species, Form = Form, CurrentLevel = currentLevel, @@ -468,20 +494,18 @@ public sealed class WC9 : DataMysteryGift, ILangNick, INature, ITeraType, IRibbo if (OTGender >= 2) { - pk.TID = tr.TID; - pk.SID = tr.SID; + pk.TID16 = tr.TID16; + pk.SID16 = tr.SID16; if (IsHOMEGift) { - pk.TrainerSID7 = 0; + pk.ID32 %= 1_000_000; while (pk.TSV == 0) - { - pk.TrainerID7 = Util.Rand.Next(16, 999_999 + 1); - } + pk.ID32 = (uint)Util.Rand.Next(16, 999_999 + 1); } } - pk.MetDate = IsDateRestricted && EncounterServerDate.WC9Gifts.TryGetValue(CardID, out var dt) ? dt.Start : DateTime.Now; + pk.MetDate = IsDateRestricted && EncounterServerDate.WC9Gifts.TryGetValue(CardID, out var dt) ? dt.Start : DateOnly.FromDateTime(DateTime.Now); var nickname_language = GetLanguage(language); pk.Language = nickname_language != 0 ? nickname_language : tr.Language; @@ -517,7 +541,7 @@ public sealed class WC9 : DataMysteryGift, ILangNick, INature, ITeraType, IRibbo private void SetEggMetData(PKM pk) { pk.IsEgg = true; - pk.EggMetDate = DateTime.Now; + pk.EggMetDate = DateOnly.FromDateTime(DateTime.Now); pk.Nickname = SpeciesName.GetEggName(pk.Language, Generation); pk.IsNicknamed = true; } @@ -530,7 +554,7 @@ public sealed class WC9 : DataMysteryGift, ILangNick, INature, ITeraType, IRibbo pk.Gender = criteria.GetGender(Gender, pi); var av = GetAbilityIndex(criteria); pk.RefreshAbility(av); - SetPID(pk, pk.MetDate ?? DateTime.UtcNow); + SetPID(pk, pk.MetDate ?? DateOnly.FromDateTime(DateTime.UtcNow)); SetIVs(pk); } @@ -550,20 +574,20 @@ public sealed class WC9 : DataMysteryGift, ILangNick, INature, ITeraType, IRibbo _ => AbilityPermission.Any12H, }; - private uint GetPID(ITrainerID tr, ShinyType8 type) => type switch + private uint GetPID(ITrainerID32 tr, ShinyType8 type) => type switch { ShinyType8.Never => GetAntishiny(tr), // Random, Never Shiny ShinyType8.Random => Util.Rand32(), // Random, Any - ShinyType8.AlwaysStar => (uint) (((tr.TID ^ tr.SID ^ (PID & 0xFFFF) ^ 1) << 16) | (PID & 0xFFFF)), // Fixed, Force Star - ShinyType8.AlwaysSquare => (uint) (((tr.TID ^ tr.SID ^ (PID & 0xFFFF) ^ 0) << 16) | (PID & 0xFFFF)), // Fixed, Force Square + ShinyType8.AlwaysStar => (1u ^ (PID & 0xFFFF) ^ tr.TID16 ^ tr.SID16) << 16 | (PID & 0xFFFF), // Fixed, Force Star + ShinyType8.AlwaysSquare => (0u ^ (PID & 0xFFFF) ^ tr.TID16 ^ tr.SID16) << 16 | (PID & 0xFFFF), // Fixed, Force Square ShinyType8.FixedValue => GetFixedPID(tr), _ => throw new ArgumentOutOfRangeException(nameof(type)), }; - private uint GetFixedPID(ITrainerID tr) + private uint GetFixedPID(ITrainerID32 tr) { var pid = PID; - if (pid != 0 && !(TID == 0 && SID == 0)) + if (pid != 0 && ID32 != 0) return pid; if (!tr.IsShiny(pid, 9)) @@ -573,13 +597,9 @@ public sealed class WC9 : DataMysteryGift, ILangNick, INature, ITeraType, IRibbo return pid; } - private static uint GetAntishinyFixedHOME(ITrainerID tr) - { - var fid = (uint)(tr.SID << 16) | (uint)tr.TID; - return fid ^ 0x10u; - } + private static uint GetAntishinyFixedHOME(ITrainerID32 tr) => tr.ID32 ^ 0x10u; - private static uint GetAntishiny(ITrainerID tr) + private static uint GetAntishiny(ITrainerID32 tr) { var pid = Util.Rand32(); if (tr.IsShiny(pid, 9)) @@ -587,7 +607,7 @@ public sealed class WC9 : DataMysteryGift, ILangNick, INature, ITeraType, IRibbo return pid; } - private void SetPID(PKM pk, DateTime date) + private void SetPID(PKM pk, DateOnly date) { pk.PID = GetPID(pk, PIDType); } @@ -626,8 +646,8 @@ public sealed class WC9 : DataMysteryGift, ILangNick, INature, ITeraType, IRibbo { if (OTGender < 2) { - if (SID != pk.SID) return false; - if (TID != pk.TID) return false; + if (SID16 != pk.SID16) return false; + if (TID16 != pk.TID16) return false; if (OTGender != pk.OT_Gender) return false; } @@ -679,7 +699,7 @@ public sealed class WC9 : DataMysteryGift, ILangNick, INature, ITeraType, IRibbo { if (pk.Egg_Location != Locations.LinkTrade6) return false; - if (PIDType == ShinyType8.Random && pk.IsShiny && pk.ShinyXor > 1) + if (PIDType == ShinyType8.Random && pk is { IsShiny: true, ShinyXor: > 1 }) return false; // shiny traded egg will always have xor0/1. } if (!shinyType.IsValid(pk)) @@ -687,7 +707,7 @@ public sealed class WC9 : DataMysteryGift, ILangNick, INature, ITeraType, IRibbo return false; // can't be traded away for unshiny } - if (pk.IsEgg && !pk.IsNative) + if (pk is { IsEgg: true, IsNative: false }) return false; } else diff --git a/PKHeX.Core/MysteryGifts/WR7.cs b/PKHeX.Core/MysteryGifts/WR7.cs index 33796957a..09ac3ced3 100644 --- a/PKHeX.Core/MysteryGifts/WR7.cs +++ b/PKHeX.Core/MysteryGifts/WR7.cs @@ -15,6 +15,7 @@ public sealed class WR7 : DataMysteryGift public const int Size = 0x140; public override int Generation => 7; public override EntityContext Context => EntityContext.Gen7; + public override bool FatefulEncounter => true; public override GameVersion Version { get => GameVersion.GG; set { } } @@ -23,13 +24,13 @@ public sealed class WR7 : DataMysteryGift public override AbilityPermission Ability => AbilityPermission.Any12H; // undefined - public uint Epoch + public long Epoch { - get => ReadUInt32LittleEndian(Data.AsSpan(0x00)); - set => WriteUInt32LittleEndian(Data.AsSpan(0x00), value); + get => ReadInt64LittleEndian(Data.AsSpan(0x00)); + set => WriteInt64LittleEndian(Data.AsSpan(0x00), value); } - public DateTime Date => new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc).AddSeconds(Epoch); + public DateOnly Date => new DateOnly(1970, 1, 1).AddDays((int)(Epoch / 86400)); public override int CardID { @@ -86,13 +87,14 @@ public sealed class WR7 : DataMysteryGift public override int Gender { get; set; } public override byte Form { get; set; } - public override int TID { get; set; } - public override int SID { get; set; } + public override uint ID32 { get; set; } + public override ushort TID16 { get; set; } + public override ushort SID16 { get; set; } public override string OT_Name { get => StringConverter8.GetString(Data.AsSpan(0x120, 0x1A)); - set => StringConverter8.SetString(Data.AsSpan(0x120, 0x1A), value.AsSpan(), 12, StringConverterOption.ClearZero); + set => StringConverter8.SetString(Data.AsSpan(0x120, 0x1A), value, 12, StringConverterOption.ClearZero); } public LanguageID LanguageReceived @@ -133,7 +135,7 @@ public sealed class WR7 : DataMysteryGift } } - public override PKM ConvertToPKM(ITrainerInfo tr, EncounterCriteria criteria) + public override PB7 ConvertToPKM(ITrainerInfo tr, EncounterCriteria criteria) { // this method shouldn't really be called, use the WB7 data not the WR7 data. if (!IsEntity) diff --git a/PKHeX.Core/PKHeX.Core.csproj b/PKHeX.Core/PKHeX.Core.csproj index ff4e669c7..adb4d8a21 100644 --- a/PKHeX.Core/PKHeX.Core.csproj +++ b/PKHeX.Core/PKHeX.Core.csproj @@ -1,7 +1,7 @@ - netstandard2.0;net46 + net7.0 Pokémon C# Class Library PKHeX.Core @@ -27,11 +27,6 @@ true - - - - - diff --git a/PKHeX.Core/PKM/BK4.cs b/PKHeX.Core/PKM/BK4.cs index 0f4d20e49..ce605b5dc 100644 --- a/PKHeX.Core/PKM/BK4.cs +++ b/PKHeX.Core/PKM/BK4.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Numerics; using static System.Buffers.Binary.BinaryPrimitives; namespace PKHeX.Core; @@ -21,7 +22,7 @@ public sealed class BK4 : G4PKM public override int SIZE_PARTY => PokeCrypto.SIZE_4STORED; public override int SIZE_STORED => PokeCrypto.SIZE_4STORED; public override EntityContext Context => EntityContext.Gen4; - public override PersonalInfo PersonalInfo => PersonalTable.HGSS[Species]; + public override PersonalInfo4 PersonalInfo => PersonalTable.HGSS[Species]; public override byte[] DecryptedBoxData => EncryptedBoxData; @@ -43,7 +44,7 @@ public sealed class BK4 : G4PKM public BK4() : this(new byte[PokeCrypto.SIZE_4STORED]) { } - public override PKM Clone() => new BK4((byte[])Data.Clone()); + public override BK4 Clone() => new((byte[])Data.Clone()); // Structure public override uint PID { get => ReadUInt32BigEndian(Data.AsSpan(0x00)); set => WriteUInt32BigEndian(Data.AsSpan(0x00), value); } @@ -53,8 +54,9 @@ public sealed class BK4 : G4PKM #region Block A public override ushort Species { get => ReadUInt16BigEndian(Data.AsSpan(0x08)); set => WriteUInt16BigEndian(Data.AsSpan(0x08), value); } public override int HeldItem { get => ReadUInt16BigEndian(Data.AsSpan(0x0A)); set => WriteUInt16BigEndian(Data.AsSpan(0x0A), (ushort)value); } - public override int SID { get => ReadUInt16BigEndian(Data.AsSpan(0x0C)); set => WriteUInt16BigEndian(Data.AsSpan(0x0C), (ushort)value); } - public override int TID { get => ReadUInt16BigEndian(Data.AsSpan(0x0E)); set => WriteUInt16BigEndian(Data.AsSpan(0x0E), (ushort)value); } + public override uint ID32 { get => ReadUInt32BigEndian(Data.AsSpan(0x0C)); set => WriteUInt32BigEndian(Data.AsSpan(0x0C), value); } + public override ushort SID16 { get => ReadUInt16BigEndian(Data.AsSpan(0x0C)); set => WriteUInt16BigEndian(Data.AsSpan(0x0C), value); } + public override ushort TID16 { get => ReadUInt16BigEndian(Data.AsSpan(0x0E)); set => WriteUInt16BigEndian(Data.AsSpan(0x0E), value); } public override uint EXP { @@ -115,6 +117,10 @@ public sealed class BK4 : G4PKM public override bool RIB3_5 { get => (RIB3 & (1 << 5)) == 1 << 5; set => RIB3 = (byte)((RIB3 & ~(1 << 5)) | (value ? 1 << 5 : 0)); } // Unused public override bool RIB3_6 { get => (RIB3 & (1 << 6)) == 1 << 6; set => RIB3 = (byte)((RIB3 & ~(1 << 6)) | (value ? 1 << 6 : 0)); } // Unused public override bool RIB3_7 { get => (RIB3 & (1 << 7)) == 1 << 7; set => RIB3 = (byte)((RIB3 & ~(1 << 7)) | (value ? 1 << 7 : 0)); } // Unused + + public override int RibbonCount => BitOperations.PopCount(ReadUInt32LittleEndian(Data.AsSpan(0x30)) & 0b00001111_11111111__11111111_11111111) + + BitOperations.PopCount(ReadUInt32LittleEndian(Data.AsSpan(0x3C))) + + BitOperations.PopCount(ReadUInt32LittleEndian(Data.AsSpan(0x60)) & 0b00000000_00001111__11111111_11111111); #endregion #region Block B @@ -197,7 +203,7 @@ public sealed class BK4 : G4PKM #endregion #region Block C - public override string Nickname { get => StringConverter4GC.GetString(Nickname_Trash); set => StringConverter4GC.SetString(Nickname_Trash, value.AsSpan(), 10, StringConverterOption.None); } + public override string Nickname { get => StringConverter4GC.GetString(Nickname_Trash); set => StringConverter4GC.SetString(Nickname_Trash, value, 10, StringConverterOption.None); } // 0x5E unused public override int Version { get => Data[0x5F]; set => Data[0x5F] = (byte)value; } private byte RIB8 { get => Data[0x60]; set => Data[0x60] = value; } // Sinnoh 3 @@ -240,7 +246,7 @@ public sealed class BK4 : G4PKM #endregion #region Block D - public override string OT_Name { get => StringConverter4GC.GetString(OT_Trash); set => StringConverter4GC.SetString(OT_Trash, value.AsSpan(), 7, StringConverterOption.None); } + public override string OT_Name { get => StringConverter4GC.GetString(OT_Trash); set => StringConverter4GC.SetString(OT_Trash, value, 7, StringConverterOption.None); } public override int Egg_Year { get => Data[0x78]; set => Data[0x78] = (byte)value; } public override int Egg_Month { get => Data[0x79]; set => Data[0x79] = (byte)value; } public override int Egg_Day { get => Data[0x7A]; set => Data[0x7A] = (byte)value; } @@ -284,7 +290,7 @@ public sealed class BK4 : G4PKM // Methods protected override ushort CalculateChecksum() { - ReadOnlySpan arr = Data.AsSpan(); + ReadOnlySpan arr = Data; ushort chk = 0; for (int i = 8; i < PokeCrypto.SIZE_4STORED; i += 2) chk += ReadUInt16BigEndian(arr[i..]); diff --git a/PKHeX.Core/PKM/CK3.cs b/PKHeX.Core/PKM/CK3.cs index 294da16eb..6ef155764 100644 --- a/PKHeX.Core/PKM/CK3.cs +++ b/PKHeX.Core/PKM/CK3.cs @@ -23,10 +23,10 @@ public sealed class CK3 : G3PKM, IShadowCapture public override int SIZE_PARTY => PokeCrypto.SIZE_3CSTORED; public override int SIZE_STORED => PokeCrypto.SIZE_3CSTORED; public override EntityContext Context => EntityContext.Gen3; - public override PersonalInfo PersonalInfo => PersonalTable.RS[Species]; + public override PersonalInfo3 PersonalInfo => PersonalTable.RS[Species]; public CK3(byte[] data) : base(data) { } public CK3() : this(new byte[PokeCrypto.SIZE_3CSTORED]) { } - public override PKM Clone() => new CK3((byte[])Data.Clone()); + public override CK3 Clone() => new((byte[])Data.Clone()); // Trash Bytes public override Span OT_Trash => Data.AsSpan(0x18, 22); @@ -34,8 +34,8 @@ public sealed class CK3 : G3PKM, IShadowCapture public Span NicknameCopy_Trash => Data.AsSpan(0x44, 22); // Future Attributes - public override ushort SpeciesID3 { get => ReadUInt16BigEndian(Data.AsSpan(0x00)); set => WriteUInt16BigEndian(Data.AsSpan(0x00), value); } // raw access - public override ushort Species { get => SpeciesConverter.GetG4Species(SpeciesID3); set => SpeciesID3 = SpeciesConverter.GetG3Species(value); } + public override ushort SpeciesInternal { get => ReadUInt16BigEndian(Data.AsSpan(0x00)); set => WriteUInt16BigEndian(Data.AsSpan(0x00), value); } // raw access + public override ushort Species { get => SpeciesConverter.GetNational3(SpeciesInternal); set => SpeciesInternal = SpeciesConverter.GetInternal3(value); } // 02-04 unused public override uint PID { get => ReadUInt32BigEndian(Data.AsSpan(0x04)); set => WriteUInt32BigEndian(Data.AsSpan(0x04), value); } public override int Version { get => GetGBAVersionID(Data[0x08]); set => Data[0x08] = GetGCVersionID(value); } @@ -46,11 +46,12 @@ public sealed class CK3 : G3PKM, IShadowCapture public override int Met_Level { get => Data[0x0E]; set => Data[0x0E] = (byte)value; } public override int Ball { get => Data[0x0F]; set => Data[0x0F] = (byte)value; } public override int OT_Gender { get => Data[0x10]; set => Data[0x10] = (byte)value; } - public override int SID { get => ReadUInt16BigEndian(Data.AsSpan(0x14)); set => WriteUInt16BigEndian(Data.AsSpan(0x14), (ushort)value); } - public override int TID { get => ReadUInt16BigEndian(Data.AsSpan(0x16)); set => WriteUInt16BigEndian(Data.AsSpan(0x16), (ushort)value); } - public override string OT_Name { get => StringConverter3GC.GetString(OT_Trash); set => StringConverter3GC.SetString(OT_Trash, value.AsSpan(), 10, StringConverterOption.None); } - public override string Nickname { get => StringConverter3GC.GetString(Nickname_Trash); set { StringConverter3GC.SetString(Nickname_Trash, value.AsSpan(), 10, StringConverterOption.None); NicknameCopy = value; } } - public string NicknameCopy { get => StringConverter3GC.GetString(NicknameCopy_Trash); set => StringConverter3GC.SetString(NicknameCopy_Trash, value.AsSpan(), 10, StringConverterOption.None); } + public override uint ID32 { get => ReadUInt32BigEndian(Data.AsSpan(0x14)); set => WriteUInt32BigEndian(Data.AsSpan(0x14), value); } + public override ushort SID16 { get => ReadUInt16BigEndian(Data.AsSpan(0x14)); set => WriteUInt16BigEndian(Data.AsSpan(0x14), value); } + public override ushort TID16 { get => ReadUInt16BigEndian(Data.AsSpan(0x16)); set => WriteUInt16BigEndian(Data.AsSpan(0x16), value); } + public override string OT_Name { get => StringConverter3GC.GetString(OT_Trash); set => StringConverter3GC.SetString(OT_Trash, value, 10, StringConverterOption.None); } + public override string Nickname { get => StringConverter3GC.GetString(Nickname_Trash); set { StringConverter3GC.SetString(Nickname_Trash, value, 10, StringConverterOption.None); NicknameCopy = value; } } + public string NicknameCopy { get => StringConverter3GC.GetString(NicknameCopy_Trash); set => StringConverter3GC.SetString(NicknameCopy_Trash, value, 10, StringConverterOption.None); } public override uint EXP { get => ReadUInt32BigEndian(Data.AsSpan(0x5C)); set => WriteUInt32BigEndian(Data.AsSpan(0x5C), value); } public override int Stat_Level { get => Data[0x60]; set => Data[0x60] = (byte)value; } @@ -170,6 +171,7 @@ public sealed class CK3 : G3PKM, IShadowCapture public override bool Unused3 { get => ((Data[0xC9] >> 2) & 1) == 1; set => Data[0xC9] = (byte)((Data[0xC9] & ~4) | (value ? 4 : 0)); } public override bool Unused4 { get => ((Data[0xC9] >> 3) & 1) == 1; set => Data[0xC9] = (byte)((Data[0xC9] & ~8) | (value ? 8 : 0)); } public override bool FatefulEncounter { get => ((Data[0xC9] >> 4) & 1) == 1; set => Data[0xC9] = (byte)((Data[0xC9] &~16) | (value ?16 : 0)); } + public override int RibbonCount => Data.AsSpan(0xBD, 12).Count(1) + RibbonCountG3Cool + RibbonCountG3Beauty + RibbonCountG3Cute + RibbonCountG3Smart + RibbonCountG3Tough; public override int PKRS_Strain { get => Data[0xCA] & 0xF; set => Data[0xCA] = (byte)(value & 0xF); } public override bool IsEgg { get => Data[0xCB] == 1; set => Data[0xCB] = value ? (byte)1 : (byte)0; } @@ -192,7 +194,7 @@ public sealed class CK3 : G3PKM, IShadowCapture public PK3 ConvertToPK3() { var pk = ConvertTo(); - pk.FlagHasSpecies = pk.SpeciesID3 != 0; // Update Flag + pk.FlagHasSpecies = pk.SpeciesInternal != 0; // Update Flag pk.RefreshChecksum(); return pk; } diff --git a/PKHeX.Core/PKM/Enums/GroundTileType.cs b/PKHeX.Core/PKM/Enums/GroundTileType.cs index 10949daf5..03374efd4 100644 --- a/PKHeX.Core/PKM/Enums/GroundTileType.cs +++ b/PKHeX.Core/PKM/Enums/GroundTileType.cs @@ -1,3 +1,4 @@ +using System; using static PKHeX.Core.GroundTileType; namespace PKHeX.Core; @@ -8,6 +9,7 @@ namespace PKHeX.Core; /// /// Used in Generation 4 games, this value is set depending on what type of overworld tile the player is standing on when the is obtained. /// +#pragma warning disable CA1069, RCS1234 // Enums values should not be duplicated public enum GroundTileType : byte { None = 00, // No animation for the tile @@ -46,7 +48,7 @@ public static class GroundTileTypeExtensions { public static bool IsObtainable(this GroundTileType type) => ((0b_1_10000000_00010110_10110111 >> (int) type) & 1) == 1; - public static readonly byte[] ValidTileTypes = + public static ReadOnlySpan ValidTileTypes => new[] { (byte)None, (byte)Sand, (byte)Grass, (byte)Rock, (byte)Cave, (byte)Water, (byte)Building, (byte)Marsh, (byte)Max_DP, (byte)Distortion, (byte)Max_Pt, }; diff --git a/PKHeX.Core/PKM/HOME/GameDataCore.cs b/PKHeX.Core/PKM/HOME/GameDataCore.cs index 709f8b094..91150755d 100644 --- a/PKHeX.Core/PKM/HOME/GameDataCore.cs +++ b/PKHeX.Core/PKM/HOME/GameDataCore.cs @@ -1,4 +1,5 @@ using System; +using System.Numerics; using static System.Buffers.Binary.BinaryPrimitives; namespace PKHeX.Core; @@ -6,7 +7,7 @@ namespace PKHeX.Core; /// /// Core game data storage, format 1. /// -public sealed class GameDataCore : IHomeTrack, ISpeciesForm, ITrainerID, INature, IContestStats, IScaledSize, ITrainerMemories, IHandlerLanguage, IBattleVersion, IHyperTrain, IFormArgument, IFavorite, +public sealed class GameDataCore : IHomeTrack, ISpeciesForm, ITrainerID, INature, IFatefulEncounter, IContestStats, IScaledSize, ITrainerMemories, IHandlerLanguage, IBattleVersion, IHyperTrain, IFormArgument, IFavorite, IRibbonSetEvent3, IRibbonSetEvent4, IRibbonSetCommon3, IRibbonSetCommon4, IRibbonSetCommon6, IRibbonSetMemory6, IRibbonSetCommon7, IRibbonSetCommon8, IRibbonSetMark8, IRibbonSetCommon9, IRibbonSetMark9 @@ -28,8 +29,9 @@ public sealed class GameDataCore : IHomeTrack, ISpeciesForm, ITrainerID, INature public uint EncryptionConstant { get => ReadUInt32LittleEndian(Data.AsSpan(Offset + 0x08)); set => WriteUInt32LittleEndian(Data.AsSpan(Offset + 0x08), value); } public bool IsBadEgg { get => Data[Offset + 0x0C] != 0; set => Data[Offset + 0x0C] = (byte)(value ? 1 : 0); } public ushort Species { get => ReadUInt16LittleEndian(Data.AsSpan(Offset + 0x0D)); set => WriteUInt16LittleEndian(Data.AsSpan(Offset + 0x0D), value); } - public int TID { get => ReadUInt16LittleEndian(Data.AsSpan(Offset + 0x0F)); set => WriteUInt16LittleEndian(Data.AsSpan(Offset + 0x0F), (ushort)value); } - public int SID { get => ReadUInt16LittleEndian(Data.AsSpan(Offset + 0x11)); set => WriteUInt16LittleEndian(Data.AsSpan(Offset + 0x11), (ushort)value); } + public uint ID32 { get => ReadUInt32LittleEndian(Data.AsSpan(Offset + 0x0F)); set => WriteUInt32LittleEndian(Data.AsSpan(Offset + 0x0F), value); } + public ushort TID16 { get => ReadUInt16LittleEndian(Data.AsSpan(Offset + 0x0F)); set => WriteUInt16LittleEndian(Data.AsSpan(Offset + 0x0F), value); } + public ushort SID16 { get => ReadUInt16LittleEndian(Data.AsSpan(Offset + 0x11)); set => WriteUInt16LittleEndian(Data.AsSpan(Offset + 0x11), value); } public uint EXP { get => ReadUInt32LittleEndian(Data.AsSpan(Offset + 0x13)); set => WriteUInt32LittleEndian(Data.AsSpan(Offset + 0x13), value); } public int Ability { get => ReadUInt16LittleEndian(Data.AsSpan(Offset + 0x17)); set => WriteUInt16LittleEndian(Data.AsSpan(Offset + 0x17), (ushort)value); } public int AbilityNumber { get => Data[Offset + 0x19] & 7; set => Data[Offset + 0x19] = (byte)((Data[Offset + 0x19] & ~7) | (value & 7)); } @@ -135,6 +137,7 @@ public sealed class GameDataCore : IHomeTrack, ISpeciesForm, ITrainerID, INature public byte RibbonCountMemoryContest { get => Data[0x3C]; set => HasContestMemoryRibbon = (Data[0x3C] = value) != 0; } public byte RibbonCountMemoryBattle { get => Data[0x3D]; set => HasBattleMemoryRibbon = (Data[0x3D] = value) != 0; } + // !!! no padding, unlike PKM formats! // 0x3E Ribbon 3 public bool RibbonMarkMisty { get => GetFlag(0x3E, 0); set => SetFlag(0x3E, 0, value); } @@ -209,15 +212,16 @@ public sealed class GameDataCore : IHomeTrack, ISpeciesForm, ITrainerID, INature public bool RIB47_6 { get => GetFlag(0x45, 6); set => SetFlag(0x45, 6, value); } public bool RIB47_7 { get => GetFlag(0x45, 7); set => SetFlag(0x45, 7, value); } - public bool HasMark() - { - var d = Data.AsSpan(); - if ((ReadUInt16LittleEndian(d[0x3A..]) & 0xFFE0) != 0) - return true; - if (ReadUInt32LittleEndian(d[0x3E..]) != 0) - return true; - return (d[0x42] & 3) != 0; - } + public int RibbonCount => BitOperations.PopCount(ReadUInt64LittleEndian(Data.AsSpan(Offset + 0x34)) & 0b00000000_00011111__11111111_11111111__11111111_11111111__11111111_11111111) + + BitOperations.PopCount(ReadUInt64LittleEndian(Data.AsSpan(Offset + 0x3E)) & 0b00000000_00000000__00000100_00011100__00000000_00000000__00000000_00000000); + public int MarkCount => BitOperations.PopCount(ReadUInt64LittleEndian(Data.AsSpan(Offset + 0x34)) & 0b11111111_11100000__00000000_00000000__00000000_00000000__00000000_00000000) + + BitOperations.PopCount(ReadUInt64LittleEndian(Data.AsSpan(Offset + 0x3E)) & 0b00000000_00000000__00111011_11100011__11111111_11111111__11111111_11111111); + public int RibbonMarkCount => BitOperations.PopCount(ReadUInt64LittleEndian(Data.AsSpan(Offset + 0x34)) & 0b11111111_11111111__11111111_11111111__11111111_11111111__11111111_11111111) + + BitOperations.PopCount(ReadUInt64LittleEndian(Data.AsSpan(Offset + 0x3E)) & 0b00000000_00000000__00111111_11111111__11111111_11111111__11111111_11111111); + + public bool HasMarkEncounter8 => BitOperations.PopCount(ReadUInt64LittleEndian(Data.AsSpan(Offset + 0x34)) & 0b11111111_11100000__00000000_00000000__00000000_00000000__00000000_00000000) + + BitOperations.PopCount(ReadUInt64LittleEndian(Data.AsSpan(Offset + 0x3E)) & 0b00000000_00000000__00000000_00000011__11111111_11111111__11111111_11111111) != 0; + public bool HasMarkEncounter9 => (Data[Offset + 0x43] & 0b00111000) != 0; public byte HeightScalar { get => Data[Offset + 0x46]; set => Data[Offset + 0x46] = value; } public byte WeightScalar { get => Data[Offset + 0x47]; set => Data[Offset + 0x47] = value; } @@ -227,7 +231,7 @@ public sealed class GameDataCore : IHomeTrack, ISpeciesForm, ITrainerID, INature public string Nickname { get => StringConverter8.GetString(Nickname_Trash); - set => StringConverter8.SetString(Nickname_Trash, value.AsSpan(), 12, StringConverterOption.None); + set => StringConverter8.SetString(Nickname_Trash, value, 12, StringConverterOption.None); } public int Stat_HPCurrent { get => ReadUInt16LittleEndian(Data.AsSpan(Offset + 0x62)); set => WriteUInt16LittleEndian(Data.AsSpan(Offset + 0x62), (ushort)value); } @@ -244,7 +248,7 @@ public sealed class GameDataCore : IHomeTrack, ISpeciesForm, ITrainerID, INature public string HT_Name { get => StringConverter8.GetString(HT_Trash); - set => StringConverter8.SetString(HT_Trash, value.AsSpan(), 12, StringConverterOption.None); + set => StringConverter8.SetString(HT_Trash, value, 12, StringConverterOption.None); } public int HT_Gender { get => Data[Offset + 0x8A]; set => Data[Offset + 0x8A] = (byte)value; } public byte HT_Language { get => Data[Offset + 0x8B]; set => Data[Offset + 0x8B] = value; } @@ -267,7 +271,7 @@ public sealed class GameDataCore : IHomeTrack, ISpeciesForm, ITrainerID, INature public string OT_Name { get => StringConverter8.GetString(OT_Trash); - set => StringConverter8.SetString(OT_Trash, value.AsSpan(), 12, StringConverterOption.None); + set => StringConverter8.SetString(OT_Trash, value, 12, StringConverterOption.None); } public int OT_Friendship { get => Data[Offset + 0xB7]; set => Data[Offset + 0xB7] = (byte)value; } public byte OT_Intensity { get => Data[Offset + 0xB8]; set => Data[Offset + 0xB8] = value; } @@ -294,6 +298,8 @@ public sealed class GameDataCore : IHomeTrack, ISpeciesForm, ITrainerID, INature public int MarkingCount => 6; + public TrainerIDFormat TrainerIDDisplayFormat => ((GameVersion)Version).GetGeneration() >= 7 ? TrainerIDFormat.SixDigit : TrainerIDFormat.SixteenBit; + public int GetMarking(int index) { if ((uint)index >= MarkingCount) @@ -316,8 +322,8 @@ public sealed class GameDataCore : IHomeTrack, ISpeciesForm, ITrainerID, INature pk.Species = Species; pk.Form = Form; pk.Gender = Gender; - pk.TID = TID; - pk.SID = SID; + pk.TID16 = TID16; + pk.SID16 = SID16; pk.EXP = EXP; pk.Ability = Ability; pk.AbilityNumber = AbilityNumber; diff --git a/PKHeX.Core/PKM/HOME/HomeCrypto.cs b/PKHeX.Core/PKM/HOME/HomeCrypto.cs index bb0aee75a..209dbba6a 100644 --- a/PKHeX.Core/PKM/HOME/HomeCrypto.cs +++ b/PKHeX.Core/PKM/HOME/HomeCrypto.cs @@ -100,6 +100,9 @@ public static class HomeCrypto } } + /// + /// Converts the input data into their encrypted state. + /// public static byte[] Encrypt(ReadOnlySpan pk) { var result = Crypt1(pk, false); @@ -113,8 +116,15 @@ public static class HomeCrypto WriteUInt32LittleEndian(dest[0xA..0xE], chk); } + /// + /// Calculates the checksum of format 1 data. + /// public static uint GetChecksum1(ReadOnlySpan encrypted) => GetCHK(encrypted[SIZE_1HEADER..]); + /// + /// Checks if the format 1 data is encrypted. + /// + /// True if encrypted. public static bool GetIsEncrypted1(ReadOnlySpan data) { if (ReadUInt16LittleEndian(data[SIZE_1HEADER..]) != SIZE_1CORE) diff --git a/PKHeX.Core/PKM/HOME/PKH.cs b/PKHeX.Core/PKM/HOME/PKH.cs index f79802b9a..718a20010 100644 --- a/PKHeX.Core/PKM/HOME/PKH.cs +++ b/PKHeX.Core/PKM/HOME/PKH.cs @@ -6,7 +6,7 @@ using static PKHeX.Core.Locations; namespace PKHeX.Core; /// Pokémon HOME format. -public class PKH : PKM, IHandlerLanguage, IFormArgument, IHomeTrack, IBattleVersion, ITrainerMemories, IRibbonSetAffixed, IContestStats, IScaledSize +public sealed class PKH : PKM, IHandlerLanguage, IFormArgument, IHomeTrack, IBattleVersion, ITrainerMemories, IRibbonSetAffixed, IContestStats, IScaledSize, IRibbonSetRibbons, IRibbonSetMarks { public readonly GameDataCore _coreData; public GameDataPB7? DataPB7 { get; private set; } @@ -68,8 +68,9 @@ public class PKH : PKM, IHandlerLanguage, IFormArgument, IHomeTrack, IBattleVers public override uint EncryptionConstant { get => _coreData.EncryptionConstant; set => _coreData.EncryptionConstant = value; } public bool IsBadEgg { get => _coreData.IsBadEgg; set => _coreData.IsBadEgg = value; } public override ushort Species { get => _coreData.Species; set => _coreData.Species = value; } - public override int TID { get => _coreData.TID; set => _coreData.TID = value; } - public override int SID { get => _coreData.SID; set => _coreData.SID = value; } + public override uint ID32 { get => _coreData.ID32; set => _coreData.ID32 = value; } + public override ushort TID16 { get => _coreData.TID16; set => _coreData.TID16 = value; } + public override ushort SID16 { get => _coreData.SID16; set => _coreData.SID16 = value; } public override uint EXP { get => _coreData.EXP; set => _coreData.EXP = value; } public override int Ability { get => _coreData.Ability; set => _coreData.Ability = value; } public override int AbilityNumber { get => _coreData.AbilityNumber; set => _coreData.AbilityNumber = value; } @@ -151,6 +152,9 @@ public class PKH : PKM, IHandlerLanguage, IFormArgument, IHomeTrack, IBattleVers public override string HT_Name { get => _coreData.HT_Name; set => _coreData.HT_Name = value; } public override int MarkingCount => _coreData.MarkingCount; + public int RibbonCount => _coreData.RibbonCount; + public int MarkCount => _coreData.MarkCount; + public int RibbonMarkCount => _coreData.RibbonMarkCount; public override int GetMarking(int index) => _coreData.GetMarking(index); public override void SetMarking(int index, int value) => _coreData.SetMarking(index, value); @@ -160,8 +164,8 @@ public class PKH : PKM, IHandlerLanguage, IFormArgument, IHomeTrack, IBattleVers public override int CurrentFriendship { get => CurrentHandler == 0 ? OT_Friendship : HT_Friendship; set { if (CurrentHandler == 0) OT_Friendship = value; else HT_Friendship = value; } } - public override int PSV => (int)(((PID >> 16) ^ (PID & 0xFFFF)) >> 4); - public override int TSV => (TID ^ SID) >> 4; + public override uint PSV => ((PID >> 16) ^ (PID & 0xFFFF)) >> 4; + public override uint TSV => (uint)(TID16 ^ SID16) >> 4; public override int Characteristic { @@ -283,7 +287,7 @@ public class PKH : PKM, IHandlerLanguage, IFormArgument, IHomeTrack, IBattleVers } } - public override PKM Clone() => new PKH((byte[])Data.Clone()) + public override PKH Clone() => new((byte[])Data.Clone()) { DataPK8 = DataPK8?.Clone(), DataPA8 = DataPA8?.Clone(), diff --git a/PKHeX.Core/PKM/Interfaces/IAwakened.cs b/PKHeX.Core/PKM/Interfaces/IAwakened.cs index 04715f063..2b226d0cb 100644 --- a/PKHeX.Core/PKM/Interfaces/IAwakened.cs +++ b/PKHeX.Core/PKM/Interfaces/IAwakened.cs @@ -43,6 +43,20 @@ public static class AwakeningUtil /// Value to set all to public static void AwakeningSetAllTo(this IAwakened pk, byte value) => pk.AV_HP = pk.AV_ATK = pk.AV_DEF = pk.AV_SPE = pk.AV_SPA = pk.AV_SPD = value; + /// + /// Sets all values to the bare minimum legal value. + /// + /// Data to set values for + public static void AwakeningMinimum(this IAwakened pk) + { + if (pk is not PB7 pb7) + return; + + Span result = stackalloc byte[6]; + SetExpectedMinimumAVs(result, pb7); + AwakeningSetVisual(pb7, result); + } + /// /// Sets all values to the specified value. /// @@ -55,23 +69,23 @@ public static class AwakeningUtil return; Span result = stackalloc byte[6]; - GetExpectedMinimumAVs(result, pb7); + SetExpectedMinimumAVs(result, pb7); var rnd = Util.Rand; - for (int i = 0; i < 6; i++) + foreach (ref var av in result) { - var realMin = Math.Max(min, result[i]); - var realMax = Math.Min(result[i], max); - result[i] = (byte)rnd.Next(realMin, realMax + 1); + var realMin = Math.Max(min, av); + var realMax = Math.Max(av, max); + av = (byte)rnd.Next(realMin, realMax + 1); } AwakeningSetVisual(pb7, result); } /// - /// Sets the awakening values according to their displayed order. + /// Gets the awakening values according to their displayed order. /// /// Data to set values for - /// + /// Value storage result public static void AwakeningGetVisual(IAwakened pk, Span value) { value[0] = pk.AV_HP; @@ -86,7 +100,7 @@ public static class AwakeningUtil /// Sets the awakening values according to their displayed order. /// /// Data to set values for - /// + /// Value storage to set from public static void AwakeningSetVisual(IAwakened pk, ReadOnlySpan value) { pk.AV_HP = value[0]; @@ -174,7 +188,7 @@ public static class AwakeningUtil public static void SetSuggestedAwakenedValues(this IAwakened a, PKM pk) { Span result = stackalloc byte[6]; - GetExpectedMinimumAVs(result, (PB7)a); + SetExpectedMinimumAVs(result, (PB7)a); a.AV_HP = Legal.AwakeningMax; a.AV_ATK = pk.IV_ATK == 0 ? result[1] : Legal.AwakeningMax; a.AV_DEF = Legal.AwakeningMax; @@ -210,14 +224,14 @@ public static class AwakeningUtil /// /// Stat results /// Entity to check - public static void GetExpectedMinimumAVs(Span result, PB7 pk) + public static void SetExpectedMinimumAVs(Span result, PB7 pk) { // GO Park transfers start with 2 AVs for all stats. // Every other encounter is either all 0, or can legally start at 0 (trades). if (pk.Version == (int)GameVersion.GO) - result.Fill(2); + result.Fill(GP1.InitialAV); - // Leveling up in-game applies 1 AV to a "random" index. + // Leveling up in-game adds 1 AV to a "random" index. var start = pk.Met_Level; var end = pk.CurrentLevel; if (start == end) diff --git a/PKHeX.Core/PKM/Interfaces/IBattleVersion.cs b/PKHeX.Core/PKM/Interfaces/IBattleVersion.cs index cb2b24aa9..16219cfc9 100644 --- a/PKHeX.Core/PKM/Interfaces/IBattleVersion.cs +++ b/PKHeX.Core/PKM/Interfaces/IBattleVersion.cs @@ -15,10 +15,13 @@ public interface IBattleVersion public static class BattleVersionExtensions { + /// + /// Checks if the applied Battle Version value is valid based on visitation. + /// public static bool IsBattleVersionValid(this T pk, EvolutionHistory h) where T : PKM, IBattleVersion => pk.BattleVersion switch { 0 => true, - (int)GameVersion.SW or (int)GameVersion.SH => !(pk.SWSH || pk.BDSP || pk.LA) && h.HasVisitedSWSH, + (int)GameVersion.SW or (int)GameVersion.SH => h.HasVisitedSWSH && !(pk.SWSH || pk.BDSP || pk.LA), _ => false, }; @@ -38,9 +41,12 @@ public static class BattleVersionExtensions MoveLevelUp.GetEncounterMoves(moves, pk, pk.CurrentLevel, version); pk.SetMoves(moves); pk.FixMoves(); - v.BattleVersion = (byte) version; + v.BattleVersion = (byte)version; } + /// + /// Gets the minimum Generation ID that it was last reset in. + /// public static int GetMinGeneration(this IBattleVersion v) { var ver = v.BattleVersion; diff --git a/PKHeX.Core/PKM/Interfaces/IFatefulEncounter.cs b/PKHeX.Core/PKM/Interfaces/IFatefulEncounter.cs new file mode 100644 index 000000000..526c44dd0 --- /dev/null +++ b/PKHeX.Core/PKM/Interfaces/IFatefulEncounter.cs @@ -0,0 +1,23 @@ +namespace PKHeX.Core; + +/// +/// Is tagged as a "Fateful Encounter". +/// +public interface IFatefulEncounter : IFatefulEncounterReadOnly +{ + /// + /// Is tagged as a "Fateful Encounter". + /// + new bool FatefulEncounter { get; set; } +} + +/// +/// Is tagged as a "Fateful Encounter". +/// +public interface IFatefulEncounterReadOnly +{ + /// + /// Is tagged as a "Fateful Encounter". + /// + bool FatefulEncounter { get; } +} diff --git a/PKHeX.Core/PKM/Interfaces/IFormArgument.cs b/PKHeX.Core/PKM/Interfaces/IFormArgument.cs index ce4d0ad50..0c7fc3d89 100644 --- a/PKHeX.Core/PKM/Interfaces/IFormArgument.cs +++ b/PKHeX.Core/PKM/Interfaces/IFormArgument.cs @@ -102,6 +102,12 @@ public static class FormArgumentUtil f.FormArgumentMaximum = Math.Max(f.FormArgumentMaximum, elapsed); } + /// + /// Gets the maximum value the can be. + /// + /// Entity Species + /// Entity Form + /// Generation to check with. public static uint GetFormArgumentMax(ushort species, byte form, int generation) { if (generation <= 5) @@ -127,6 +133,11 @@ public static class FormArgumentUtil }; } + /// + /// Gets the minimum value the value can be to satisfy an evolution requirement. + /// + /// Current state species + /// Initial species public static uint GetFormArgumentMinEvolution(ushort currentSpecies, ushort originalSpecies) => originalSpecies switch { (int)Yamask when currentSpecies == (int)Runerigus => 49u, @@ -139,6 +150,9 @@ public static class FormArgumentUtil _ => 0u, }; + /// + /// Checks if the value is stored as a days-elapsed / days-remaining pair. + /// public static bool IsFormArgumentTypeDatePair(ushort species, byte form) => species switch { (int)Furfrou when form != 0 => true, diff --git a/PKHeX.Core/PKM/Interfaces/IGanbaru.cs b/PKHeX.Core/PKM/Interfaces/IGanbaru.cs index f17d70292..62fc9e6ce 100644 --- a/PKHeX.Core/PKM/Interfaces/IGanbaru.cs +++ b/PKHeX.Core/PKM/Interfaces/IGanbaru.cs @@ -22,7 +22,7 @@ public static class GanbaruExtensions /// public const byte TrueMax = 10; - private static readonly byte[] GanbaruMultiplier = { 0, 2, 3, 4, 7, 8, 9, 14, 15, 16, 25 }; + private static ReadOnlySpan GanbaruMultiplier => new byte[] { 0, 2, 3, 4, 7, 8, 9, 14, 15, 16, 25 }; /// /// Gets the max possible value that can be legally stored for the specific stat . diff --git a/PKHeX.Core/PKM/Interfaces/IGeoTrack.cs b/PKHeX.Core/PKM/Interfaces/IGeoTrack.cs index 2638999c4..1e37042b1 100644 --- a/PKHeX.Core/PKM/Interfaces/IGeoTrack.cs +++ b/PKHeX.Core/PKM/Interfaces/IGeoTrack.cs @@ -1,4 +1,4 @@ -namespace PKHeX.Core; +namespace PKHeX.Core; /// /// Tracks Geolocation history of a @@ -19,12 +19,21 @@ public interface IGeoTrack : IRegionOrigin public static partial class Extensions { + /// + /// Clears all Geolocation history. + /// public static void ClearGeoLocationData(this IGeoTrack g) { g.Geo1_Country = g.Geo2_Country = g.Geo3_Country = g.Geo4_Country = g.Geo5_Country = 0; g.Geo1_Region = g.Geo2_Region = g.Geo3_Region = g.Geo4_Region = g.Geo5_Region = 0; } + /// + /// Inserts a new Geolocation tuple to the values. + /// + /// Object tracking the geolocation history + /// Newly arrived country + /// Newly arrived region public static void TradeGeoLocation(this IGeoTrack g, byte GeoCountry, byte GeoRegion) { // Trickle existing values up one slot @@ -86,32 +95,38 @@ public static partial class Extensions } } + /// + /// Checks if all Geolocation tuples are valid. + /// + /// + /// public static bool GetIsValid(this IGeoTrack g) => g.GetValidity() == GeoValid.Valid; + /// + /// Checks if all Geolocation tuples are valid. + /// internal static GeoValid GetValidity(this IGeoTrack g) { bool end = false; GeoValid result; - if ((result = update(g.Geo1_Country, g.Geo1_Region)) != GeoValid.Valid) + if ((result = UpdateCheck(g.Geo1_Country, g.Geo1_Region, ref end)) != GeoValid.Valid) return result; - if ((result = update(g.Geo2_Country, g.Geo2_Region)) != GeoValid.Valid) + if ((result = UpdateCheck(g.Geo2_Country, g.Geo2_Region, ref end)) != GeoValid.Valid) return result; - if ((result = update(g.Geo3_Country, g.Geo3_Region)) != GeoValid.Valid) + if ((result = UpdateCheck(g.Geo3_Country, g.Geo3_Region, ref end)) != GeoValid.Valid) return result; - if ((result = update(g.Geo4_Country, g.Geo4_Region)) != GeoValid.Valid) + if ((result = UpdateCheck(g.Geo4_Country, g.Geo4_Region, ref end)) != GeoValid.Valid) return result; - if ((result = update(g.Geo5_Country, g.Geo5_Region)) != GeoValid.Valid) + if ((result = UpdateCheck(g.Geo5_Country, g.Geo5_Region, ref end)) != GeoValid.Valid) return result; return result; - GeoValid update(int c, int r) + static GeoValid UpdateCheck(byte country, byte region, ref bool end) { - if (end && c != 0) - return GeoValid.CountryAfterPreviousEmpty; - if (c != 0) - return GeoValid.Valid; - if (r != 0) // c == 0 + if (country != 0) + return end ? GeoValid.CountryAfterPreviousEmpty : GeoValid.Valid; + if (region != 0) // c == 0 return GeoValid.RegionWithoutCountry; end = true; return GeoValid.Valid; @@ -119,9 +134,21 @@ public static partial class Extensions } } +/// +/// Geolocation Country-Region tuple validity tagging. +/// internal enum GeoValid { + /// Tuple is valid. Valid, + + /// + /// Lower-index country is empty, but higher has data (invalid). + /// CountryAfterPreviousEmpty, + + /// + /// Zero-value country (None) with a non-zero Region (invalid). + /// RegionWithoutCountry, } diff --git a/PKHeX.Core/PKM/Interfaces/IHyperTrain.cs b/PKHeX.Core/PKM/Interfaces/IHyperTrain.cs index d7596a054..9fc3a23ac 100644 --- a/PKHeX.Core/PKM/Interfaces/IHyperTrain.cs +++ b/PKHeX.Core/PKM/Interfaces/IHyperTrain.cs @@ -65,29 +65,56 @@ public static partial class Extensions { if (pk is not IHyperTrain t) return; - if (!pk.IsHyperTrainingAvailable(h)) - { - t.HyperTrainFlags = 0; - return; - } + if (!pk.IsHyperTrainingAvailable(h)) + t.HyperTrainFlags = 0; + else + t.SetSuggestedHyperTrainingData(pk, IVs); + } + + /// + public static void SetSuggestedHyperTrainingData(this PKM pk, EntityContext c, ReadOnlySpan IVs) + { + if (pk is not IHyperTrain t) + return; + + if (!c.IsHyperTrainingAvailable(pk.CurrentLevel)) + t.HyperTrainFlags = 0; + else + t.SetSuggestedHyperTrainingData(pk, IVs); + } + + private static void SetSuggestedHyperTrainingData(this IHyperTrain t, PKM pk, ReadOnlySpan IVs) + { t.HT_HP = IVs[0] != 31; t.HT_ATK = IVs[1] != 31 && IVs[1] > 2; t.HT_DEF = IVs[2] != 31; t.HT_SPA = IVs[4] != 31; t.HT_SPD = IVs[5] != 31; - - // sometimes unusual speed IVs are desirable for competitive reasons - // if nothing else was HT'd and the IV isn't too high, it was probably intentional - t.HT_SPE = IVs[3] != 31 && IVs[3] > 2 && - (IVs[3] > 17 || t.HT_HP || t.HT_ATK || t.HT_DEF || t.HT_SPA || t.HT_SPD); + t.HT_SPE = IsSpeedHyperTrainSuggested(t, IVs); if (pk is ICombatPower pb) pb.ResetCP(); } + private static bool IsSpeedHyperTrainSuggested(IHyperTrain t, ReadOnlySpan IVs) + { + // sometimes unusual speed IVs are desirable for competitive reasons + var speed = IVs[3]; + if (speed is 31 or <= 2) + return false; + + // if IV isn't too high and nothing else was HT'd, it was probably intentional to stay low. + if (speed > 17) + return true; + return t.HT_HP || t.HT_ATK || t.HT_DEF || t.HT_SPA || t.HT_SPD; + } + /// - public static void SetSuggestedHyperTrainingData(this PKM pk, ReadOnlySpan IVs) => pk.SetSuggestedHyperTrainingData(EvolutionHistory.Empty, IVs); + public static void SetSuggestedHyperTrainingData(this PKM pk, ReadOnlySpan IVs) + { + pk.SetSuggestedHyperTrainingData(pk.Context, IVs); + } /// public static void SetSuggestedHyperTrainingData(this PKM pk) @@ -98,7 +125,7 @@ public static partial class Extensions } /// - /// Indicates if Hyper Training is available for toggling. + /// Indicates if Hyper Training is available to be set. /// /// Entity to train /// History of evolutions present as @@ -110,8 +137,23 @@ public static partial class Extensions _ => true, }; + /// + public static bool IsHyperTrainingAvailable(this EntityContext c, int currentLevel) + { + var min = GetHyperTrainMinLevel(c); + return currentLevel <= min; + } + + /// + public static int GetHyperTrainMinLevel(this EntityContext c) => c switch + { + EntityContext.Gen7 or EntityContext.Gen8 or EntityContext.Gen8b => 100, + EntityContext.Gen9 => 50, + _ => 101, + }; + /// - /// Indicates if Hyper Training is available for toggling. + /// Gets the minimum level required for Hyper Training an IV. /// /// Entity to train /// History of evolutions present as diff --git a/PKHeX.Core/PKM/Interfaces/IMoveShop8.cs b/PKHeX.Core/PKM/Interfaces/IMoveShop8.cs index 07bd82adb..3c00b881c 100644 --- a/PKHeX.Core/PKM/Interfaces/IMoveShop8.cs +++ b/PKHeX.Core/PKM/Interfaces/IMoveShop8.cs @@ -7,15 +7,7 @@ namespace PKHeX.Core; /// public interface IMoveShop8 { - /// - /// Individual accessed indexes indicate if they can be learned. - /// - ReadOnlySpan MoveShopPermitFlags { get; } - - /// - /// Individual accessed move IDs that are provided by the Move Shop. - /// - ReadOnlySpan MoveShopPermitIndexes { get; } + IPermitRecord Permit { get; } /// /// Indicates if the move shop offering at the requested index has been purchased. @@ -71,11 +63,11 @@ public static class MoveShop8MasteryExtensions { public static bool IsValidPurchasedEncounter(this IMoveShop8 shop, Learnset learn, int level, ushort alpha, bool allowPurchasedAlpha) { - var permit = shop.MoveShopPermitIndexes; - var current = shop.MoveShopPermitFlags; - for (int i = 0; i < current.Length; i++) + var permit = shop.Permit.RecordPermitIndexes; + var current = shop.Permit; + for (int i = 0; i < current.RecordCountUsed; i++) { - if (!current[i]) + if (!current.IsRecordPermitted(i)) continue; if (!shop.GetPurchasedRecordFlag(i)) @@ -96,28 +88,29 @@ public static class MoveShop8MasteryExtensions return true; } - public static bool IsValidMasteredEncounter(this IMoveShop8Mastery shop, Span moves, Learnset learn, Learnset mastery, int level, ushort alpha, bool allowPurchasedAlpha) + public static bool IsValidMasteredEncounter(this IMoveShop8Mastery shop, Span moves, Learnset learn, Learnset mastery, int metLevel, ushort alphaMove, bool allowPurchasedAlpha) { foreach (var move in moves) { if (move == 0) continue; - var index = shop.MoveShopPermitIndexes.IndexOf(move); + var index = shop.Permit.RecordPermitIndexes.IndexOf(move); if (index == -1) continue; // manually mastered for encounter, not a tutor - bool p = shop.GetPurchasedRecordFlag(index); - bool m = shop.GetMasteredRecordFlag(index); + bool purchased = shop.GetPurchasedRecordFlag(index); + bool mastered = shop.GetMasteredRecordFlag(index); var masteryLevel = mastery.GetMoveLevel(move); - if (masteryLevel > level && move != alpha) // no master flag set + if (masteryLevel > metLevel && move != alphaMove) // no master flag set { - if (!p && m) - { - // Check for seed of mastery usage - if (learn.GetMoveLevel(move) > level) - return false; - } + if (!mastered) + continue; + if (purchased) + continue; + // Check for seed of mastery usage + if (learn.GetMoveLevel(move) > metLevel) + return false; } else { @@ -125,9 +118,9 @@ public static class MoveShop8MasteryExtensions // After the patch, the Alpha Move is considered purchased (even without the flag). // Players won't be able to waste money after the patch :) // For legality, allow the Alpha Move to be flagged as Purchased if it was a pre-patch capture. - if (p && (move != alpha || !allowPurchasedAlpha)) + if (!mastered) return false; - if (!m) + if (purchased && (move != alphaMove || !allowPurchasedAlpha)) return false; } } diff --git a/PKHeX.Core/PKM/Interfaces/ITechRecord.cs b/PKHeX.Core/PKM/Interfaces/ITechRecord.cs index e3ef7002a..7cd694148 100644 --- a/PKHeX.Core/PKM/Interfaces/ITechRecord.cs +++ b/PKHeX.Core/PKM/Interfaces/ITechRecord.cs @@ -8,24 +8,9 @@ namespace PKHeX.Core; public interface ITechRecord { /// - /// Individual accessed indexes indicate if they can be learned. + /// Rules for permitting the given record. /// - ReadOnlySpan TechRecordPermitFlags { get; } - - /// - /// Individual accessed move IDs that a given TR teaches. - /// - ReadOnlySpan TechRecordPermitIndexes { get; } - - /// - /// Maximum count of record flags that are available. - /// - int RecordCountTotal { get; } - - /// - /// Maximum count of record flags that are used. - /// - int RecordCountUsed { get; } + public IPermitRecord Permit { get; } /// /// Indicates if the TR has been previously used on this entity to learn the move. @@ -46,3 +31,26 @@ public interface ITechRecord /// bool GetMoveRecordFlagAny(); } + +public interface IPermitRecord +{ + /// + /// Individual accessed indexes indicate if they can be learned. + /// + bool IsRecordPermitted(int index); + + /// + /// Individual accessed move IDs that a given record remembers. + /// + ReadOnlySpan RecordPermitIndexes { get; } + + /// + /// Maximum count of record flags that are available. + /// + int RecordCountTotal { get; } + + /// + /// Maximum count of record flags that are used. + /// + int RecordCountUsed { get; } +} diff --git a/PKHeX.Core/PKM/Interfaces/ITrainerID.cs b/PKHeX.Core/PKM/Interfaces/ITrainerID.cs index 8548ca08c..055a893eb 100644 --- a/PKHeX.Core/PKM/Interfaces/ITrainerID.cs +++ b/PKHeX.Core/PKM/Interfaces/ITrainerID.cs @@ -1,38 +1,81 @@ +using static PKHeX.Core.TrainerIDFormat; + namespace PKHeX.Core; /// -/// Object has Trainer ownership +/// Object has Trainer ownership with a way to show the Trainer ID. /// public interface ITrainerID { - int TID { get; set; } - int SID { get; set; } + /// + /// Format the stored Trainer ID is shown to the player. + /// + TrainerIDFormat TrainerIDDisplayFormat { get; } } -public static partial class Extensions +public enum TrainerIDFormat { - public static int GetTrainerIDFormat(this ITrainerID tr) - { - if (tr is PKM pk) - { - if (pk.Version is 0) - return pk.Format; + /// + /// Don't use me. + /// + None, - var format = pk.Generation; - if (format < 3 && pk.Format >= 7) // VC or bad gen - return 4; // use TID/SID 16bit style - if (format <= 0) - return 4; // use TID/SID 16bit style - return format; - } - if (tr is SaveFile s) - return s.Generation; - return -1; - } + /// + /// 16-bit Trainer ID + /// + /// Generations 1-2 only. Secret ID did not exist. + SixteenBitSingle, - public static bool IsShiny(this ITrainerID tr, uint pid, int gen = 7) - { - var xor = tr.SID ^ tr.TID ^ (pid >> 16) ^ (pid & 0xFFFF); - return xor < (gen >= 7 ? 16 : 8); - } + /// + /// 16-bit Trainer ID, 16-bit Secret ID + /// + /// Generations 3-6, and Generation 1-2 transferred 7+. + SixteenBit, + + /// + /// 32-bit Trainer ID, showing the lowest 6 digits. + /// + /// Generation 7 origin onward. + SixDigit, +} + +public static class TrainerIDExtensions +{ + /// + /// Detects the correct to use for the input . + /// + public static TrainerIDFormat GetTrainerIDFormat(this ITrainerID tr) => tr switch + { + PKM { Format: <= 2 } => SixteenBitSingle, + PKM { Version: 0 } pk => pk.Format >= 7 ? SixDigit : SixteenBit, + IGeneration sv => sv.Generation >= 7 ? SixDigit : SixteenBit, + _ => SixteenBit, + }; + + /// String format specifier for TID. + public const string TID7 = "D6"; + /// String format specifier for SID. + public const string SID7 = "D4"; + /// String format specifier for TID. + public const string TID16 = "D5"; + /// String format specifier for SID. + public const string SID16 = "D5"; + + /// + /// Gets the string format specifier to use for the requested format TID. + /// + public static string GetTrainerIDFormatStringTID(this TrainerIDFormat format) => format switch + { + SixDigit => TID7, + _ => TID16, + }; + + /// + /// Gets the string format specifier to use for the requested format SID. + /// + public static string GetTrainerIDFormatStringSID(this TrainerIDFormat format) => format switch + { + SixDigit => SID7, + _ => SID16, + }; } diff --git a/PKHeX.Core/PKM/Interfaces/ITrainerID32.cs b/PKHeX.Core/PKM/Interfaces/ITrainerID32.cs new file mode 100644 index 000000000..c653cff52 --- /dev/null +++ b/PKHeX.Core/PKM/Interfaces/ITrainerID32.cs @@ -0,0 +1,85 @@ +using static PKHeX.Core.TrainerIDFormat; + +namespace PKHeX.Core; + +/// +/// Object stores a numerical trainer ID. +/// +public interface ITrainerID32 : ITrainerID16 +{ + uint ID32 { get; set; } + ushort SID16 { get; set; } +} + +public interface ITrainerID16 : ITrainerID +{ + ushort TID16 { get; set; } +} + +public static class ITrainerID32Extensions +{ + /// + /// Checks if the is shiny when owned by the . + /// + /// Possessing trainer + /// + /// Generation of origin. + /// True if shiny, false if not. + public static bool IsShiny(this ITrainerID32 tr, uint pid, int gen = 7) + { + var xor = GetShinyXor(tr, pid); + var threshold = (gen >= 7 ? 16 : 8); + return xor < threshold; + } + + /// + /// Calculates the and xor. + /// + public static uint GetShinyXor(this ITrainerID32 tr, uint pid) => (pid >> 16) ^ (pid & 0xFFFF) ^ tr.SID16 ^ tr.TID16; + + public static uint GetTrainerTID7(this ITrainerID32 tr) => tr.ID32 % 1000000; + public static uint GetTrainerSID7(this ITrainerID32 tr) => tr.ID32 / 1000000; + public static uint SetTrainerTID7(this ITrainerID32 tr, uint value) => tr.ID32 = ((tr.ID32 / 1000000) * 1000000) + value; + public static uint SetTrainerSID7(this ITrainerID32 tr, uint value) => tr.ID32 = (value * 1000000) + (tr.ID32 % 1000000); + public static uint SetTrainerID16(this ITrainerID32 tr, ushort tid16, ushort sid16) => tr.ID32 = ((uint)sid16 << 16) | tid16; + public static uint SetTrainerID7(this ITrainerID32 tr, uint sid7, uint tid7) => tr.ID32 = (sid7 * 1000000) + tid7; + + public static uint GetDisplayTID(this ITrainerID32 tr) => tr.TrainerIDDisplayFormat switch + { + SixDigit => GetTrainerTID7(tr), + _ => tr.TID16, + }; + + public static uint GetDisplaySID(this ITrainerID32 tr) => tr.TrainerIDDisplayFormat switch + { + SixDigit => GetTrainerSID7(tr), + _ => tr.SID16, + }; + + public static void SetDisplayTID(this ITrainerID32 tr, uint value) + { + switch (tr.TrainerIDDisplayFormat) + { + case SixDigit: tr.SetTrainerTID7(value); break; + default: tr.TID16 = (ushort)value; break; + } + } + + public static void SetDisplaySID(this ITrainerID32 tr, uint value) + { + switch (tr.TrainerIDDisplayFormat) + { + case SixDigit: tr.SetTrainerSID7(value); break; + default: tr.SID16 = (ushort)value; break; + } + } + + public static void SetDisplayID(this ITrainerID32 tr, uint tid, uint sid) + { + switch (tr.TrainerIDDisplayFormat) + { + case SixDigit: tr.SetTrainerID7(sid, tid); break; + default: tr.SetTrainerID16((ushort)tid, (ushort)sid); break; + } + } +} diff --git a/PKHeX.Core/PKM/Interfaces/Templates/IContestStatsReadOnly.cs b/PKHeX.Core/PKM/Interfaces/Templates/IContestStatsReadOnly.cs index f7bd47f33..e7cf5b3c1 100644 --- a/PKHeX.Core/PKM/Interfaces/Templates/IContestStatsReadOnly.cs +++ b/PKHeX.Core/PKM/Interfaces/Templates/IContestStatsReadOnly.cs @@ -101,8 +101,8 @@ public static partial class Extensions /// Entity to check /// True if any equals public static bool IsAnyContestStatMax(this IContestStatsReadOnly s) => CONTEST_MAX == s.CNT_Cool - || CONTEST_MAX == s.CNT_Beauty - || CONTEST_MAX == s.CNT_Cute - || CONTEST_MAX == s.CNT_Smart - || CONTEST_MAX == s.CNT_Tough; + || CONTEST_MAX == s.CNT_Beauty + || CONTEST_MAX == s.CNT_Cute + || CONTEST_MAX == s.CNT_Smart + || CONTEST_MAX == s.CNT_Tough; } diff --git a/PKHeX.Core/PKM/PA8.cs b/PKHeX.Core/PKM/PA8.cs index 5f11a5e0c..7c597f6ff 100644 --- a/PKHeX.Core/PKM/PA8.cs +++ b/PKHeX.Core/PKM/PA8.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Numerics; using System.Runtime.CompilerServices; using static System.Buffers.Binary.BinaryPrimitives; @@ -7,8 +8,8 @@ namespace PKHeX.Core; /// Generation 8 format. public sealed class PA8 : PKM, ISanityChecksum, IMoveReset, - IRibbonSetEvent3, IRibbonSetEvent4, IRibbonSetCommon3, IRibbonSetCommon4, IRibbonSetCommon6, IRibbonSetMemory6, IRibbonSetCommon7, IRibbonSetCommon8, IRibbonSetMark8, IRibbonSetAffixed, IGanbaru, IAlpha, INoble, ITechRecord, ISociability, IMoveShop8Mastery, - IContestStats, IHyperTrain, IScaledSizeValue, IScaledSize3, IGigantamax, IFavorite, IDynamaxLevel, IRibbonIndex, IHandlerLanguage, IFormArgument, IHomeTrack, IBattleVersion, ITrainerMemories + IGanbaru, IAlpha, INoble, ITechRecord, ISociability, IMoveShop8Mastery, IContestStats, IHyperTrain, IScaledSizeValue, IScaledSize3, IGigantamax, IFavorite, IDynamaxLevel, IHandlerLanguage, IFormArgument, IHomeTrack, IBattleVersion, ITrainerMemories, + IRibbonIndex, IRibbonSetAffixed, IRibbonSetRibbons, IRibbonSetEvent3, IRibbonSetEvent4, IRibbonSetCommon3, IRibbonSetCommon4, IRibbonSetCommon6, IRibbonSetMemory6, IRibbonSetCommon7, IRibbonSetCommon8, IRibbonSetMarks, IRibbonSetMark8 { private static readonly ushort[] Unused = { @@ -29,7 +30,8 @@ public sealed class PA8 : PKM, ISanityChecksum, IMoveReset, }; public override IReadOnlyList ExtraBytes => Unused; - public override PersonalInfo PersonalInfo => PersonalTable.LA.GetFormEntry(Species, Form); + public override PersonalInfo8LA PersonalInfo => PersonalTable.LA.GetFormEntry(Species, Form); + public IPermitRecord Permit => PersonalInfo; public override EntityContext Context => EntityContext.Gen8a; public override bool IsNative => LA; @@ -39,7 +41,7 @@ public sealed class PA8 : PKM, ISanityChecksum, IMoveReset, public override int SIZE_PARTY => PokeCrypto.SIZE_8APARTY; public override int SIZE_STORED => PokeCrypto.SIZE_8ASTORED; public override bool ChecksumValid => CalculateChecksum() == Checksum; - public override PKM Clone() => new PA8((byte[])Data.Clone()); + public override PA8 Clone() => new((byte[])Data.Clone()); private static byte[] DecryptParty(byte[] data) { @@ -57,12 +59,6 @@ public sealed class PA8 : PKM, ISanityChecksum, IMoveReset, } // Simple Generated Attributes - public ReadOnlySpan TechRecordPermitFlags => Span.Empty; - public ReadOnlySpan TechRecordPermitIndexes => LearnSource8SWSH.TR_SWSH.AsSpan(); - public ReadOnlySpan MoveShopPermitFlags => PersonalInfo.SpecialTutors[0]; - public ReadOnlySpan MoveShopPermitIndexes => Legal.MoveShop8_LA; - public int RecordCountTotal => 112; - public int RecordCountUsed => 0; public override int CurrentFriendship { @@ -84,8 +80,8 @@ public sealed class PA8 : PKM, ISanityChecksum, IMoveReset, public override int MaxStringLengthOT => 12; public override int MaxStringLengthNickname => 12; - public override int PSV => (int)(((PID >> 16) ^ (PID & 0xFFFF)) >> 4); - public override int TSV => (TID ^ SID) >> 4; + public override uint PSV => ((PID >> 16) ^ (PID & 0xFFFF)) >> 4; + public override uint TSV => (uint)(TID16 ^ SID16) >> 4; public override bool IsUntraded => Data[0xB8] == 0 && Data[0xB8 + 1] == 0 && Format == Generation; // immediately terminated HT_Name data (\0) // Complex Generated Attributes @@ -146,8 +142,9 @@ public sealed class PA8 : PKM, ISanityChecksum, IMoveReset, #region Block A public override ushort Species { get => ReadUInt16LittleEndian(Data.AsSpan(0x08)); set => WriteUInt16LittleEndian(Data.AsSpan(0x08), value); } public override int HeldItem { get => ReadUInt16LittleEndian(Data.AsSpan(0x0A)); set => WriteUInt16LittleEndian(Data.AsSpan(0x0A), (ushort)value); } - public override int TID { get => ReadUInt16LittleEndian(Data.AsSpan(0x0C)); set => WriteUInt16LittleEndian(Data.AsSpan(0x0C), (ushort)value); } - public override int SID { get => ReadUInt16LittleEndian(Data.AsSpan(0x0E)); set => WriteUInt16LittleEndian(Data.AsSpan(0x0E), (ushort)value); } + public override uint ID32 { get => ReadUInt32LittleEndian(Data.AsSpan(0x0C)); set => WriteUInt32LittleEndian(Data.AsSpan(0x0C), value); } + public override ushort TID16 { get => ReadUInt16LittleEndian(Data.AsSpan(0x0C)); set => WriteUInt16LittleEndian(Data.AsSpan(0x0C), value); } + public override ushort SID16 { get => ReadUInt16LittleEndian(Data.AsSpan(0x0E)); set => WriteUInt16LittleEndian(Data.AsSpan(0x0E), value); } public override uint EXP { get => ReadUInt32LittleEndian(Data.AsSpan(0x10)); set => WriteUInt32LittleEndian(Data.AsSpan(0x10), value); } public override int Ability { get => ReadUInt16LittleEndian(Data.AsSpan(0x14)); set => WriteUInt16LittleEndian(Data.AsSpan(0x14), (ushort)value); } public override int AbilityNumber { get => Data[0x16] & 7; set => Data[0x16] = (byte)((Data[0x16] & ~7) | (value & 7)); } @@ -337,15 +334,14 @@ public sealed class PA8 : PKM, ISanityChecksum, IMoveReset, public bool RIB47_6 { get => FlagUtil.GetFlag(Data, 0x47, 6); set => FlagUtil.SetFlag(Data, 0x47, 6, value); } public bool RIB47_7 { get => FlagUtil.GetFlag(Data, 0x47, 7); set => FlagUtil.SetFlag(Data, 0x47, 7, value); } - public bool HasMark() - { - var d = Data.AsSpan(); - if ((ReadUInt16LittleEndian(d[0x3A..]) & 0xFFE0) != 0) - return true; - if (ReadUInt32LittleEndian(d[0x40..]) != 0) - return true; - return (d[0x44] & 3) != 0; - } + public int RibbonCount => BitOperations.PopCount(ReadUInt64LittleEndian(Data.AsSpan(0x34)) & 0b00000000_00011111__11111111_11111111__11111111_11111111__11111111_11111111) + + BitOperations.PopCount(ReadUInt64LittleEndian(Data.AsSpan(0x40)) & 0b00000000_00000000__00000000_00001100__00000000_00000000__00000000_00000000); + public int MarkCount => BitOperations.PopCount(ReadUInt64LittleEndian(Data.AsSpan(0x34)) & 0b11111111_11100000__00000000_00000000__00000000_00000000__00000000_00000000) + + BitOperations.PopCount(ReadUInt64LittleEndian(Data.AsSpan(0x40)) & 0b00000000_00000000__00000000_00000011__11111111_11111111__11111111_11111111); + public int RibbonMarkCount => BitOperations.PopCount(ReadUInt64LittleEndian(Data.AsSpan(0x34)) & 0b11111111_11111111__11111111_11111111__11111111_11111111__11111111_11111111) + + BitOperations.PopCount(ReadUInt64LittleEndian(Data.AsSpan(0x40)) & 0b00000000_00000000__00000000_00001111__11111111_11111111__11111111_11111111); + + public bool HasMarkEncounter8 => MarkCount != 0; public uint Sociability { get => ReadUInt32LittleEndian(Data.AsSpan(0x48)); set => WriteUInt32LittleEndian(Data.AsSpan(0x48), value); } @@ -371,7 +367,7 @@ public sealed class PA8 : PKM, ISanityChecksum, IMoveReset, public override string Nickname { get => StringConverter8.GetString(Nickname_Trash); - set => StringConverter8.SetString(Nickname_Trash, value.AsSpan(), 12, StringConverterOption.None); + set => StringConverter8.SetString(Nickname_Trash, value, 12, StringConverterOption.None); } // 2 bytes for \0, automatically handled above @@ -420,7 +416,7 @@ public sealed class PA8 : PKM, ISanityChecksum, IMoveReset, public override string HT_Name { get => StringConverter8.GetString(HT_Trash); - set => StringConverter8.SetString(HT_Trash, value.AsSpan(), 12, StringConverterOption.None); + set => StringConverter8.SetString(HT_Trash, value, 12, StringConverterOption.None); } public override int HT_Gender { get => Data[0xD2]; set => Data[0xD2] = (byte)value; } @@ -440,8 +436,8 @@ public sealed class PA8 : PKM, ISanityChecksum, IMoveReset, public override byte Enjoyment { get => Data[0xED]; set => Data[0xED] = value; } public override int Version { get => Data[0xEE]; set => Data[0xEE] = (byte)value; } public byte BattleVersion { get => Data[0xEF]; set => Data[0xEF] = value; } - // public override int Region { get => Data[0xF0]; set => Data[0xF0] = (byte)value; } - // public override int ConsoleRegion { get => Data[0xF1]; set => Data[0xF1] = (byte)value; } + // public override byte Region { get => Data[0xF0]; set => Data[0xF0] = (byte)value; } + // public override byte ConsoleRegion { get => Data[0xF1]; set => Data[0xF1] = (byte)value; } public override int Language { get => Data[0xF2]; set => Data[0xF2] = (byte)value; } public int UnkF3 { get => Data[0xF3]; set => Data[0xF3] = (byte)value; } public uint FormArgument { get => ReadUInt32LittleEndian(Data.AsSpan(0xF4)); set => WriteUInt32LittleEndian(Data.AsSpan(0xF4), value); } @@ -455,7 +451,7 @@ public sealed class PA8 : PKM, ISanityChecksum, IMoveReset, public override string OT_Name { get => StringConverter8.GetString(OT_Trash); - set => StringConverter8.SetString(OT_Trash, value.AsSpan(), 12, StringConverterOption.None); + set => StringConverter8.SetString(OT_Trash, value, 12, StringConverterOption.None); } public override int OT_Friendship { get => Data[0x12A]; set => Data[0x12A] = (byte)value; } @@ -612,7 +608,7 @@ public sealed class PA8 : PKM, ISanityChecksum, IMoveReset, return NatureAmpTable[(5 * nature) + index]; } - private static readonly sbyte[] NatureAmpTable = + private static ReadOnlySpan NatureAmpTable => new sbyte[] { 0, 0, 0, 0, 0, // Hardy 1,-1, 0, 0, 0, // Lonely @@ -713,7 +709,7 @@ public sealed class PA8 : PKM, ISanityChecksum, IMoveReset, private bool TradeOT(ITrainerInfo tr) { // Check to see if the OT matches the SAV's OT info. - if (!(tr.TID == TID && tr.SID == SID && tr.Gender == OT_Gender && tr.OT == OT_Name)) + if (!(tr.ID32 == ID32 && tr.Gender == OT_Gender && tr.OT == OT_Name)) return false; CurrentHandler = 0; @@ -750,7 +746,7 @@ public sealed class PA8 : PKM, ISanityChecksum, IMoveReset, public void ResetWeight() => WeightAbsolute = CalcWeightAbsolute; [MethodImpl(MethodImplOptions.NoOptimization | MethodImplOptions.NoInlining)] - private static float GetHeightRatio(int heightScalar) + private static float GetHeightRatio(byte heightScalar) { // +/- 20% (down from +/- 40% in LGP/E) float result = heightScalar / 255f; // 0x437F0000 @@ -760,7 +756,7 @@ public sealed class PA8 : PKM, ISanityChecksum, IMoveReset, } [MethodImpl(MethodImplOptions.NoOptimization | MethodImplOptions.NoInlining)] - private static float GetWeightRatio(int weightScalar) + private static float GetWeightRatio(byte weightScalar) { // +/- 20% float result = weightScalar / 255f; // 0x437F0000 @@ -770,14 +766,14 @@ public sealed class PA8 : PKM, ISanityChecksum, IMoveReset, } [MethodImpl(MethodImplOptions.NoOptimization | MethodImplOptions.NoInlining)] - public static float GetHeightAbsolute(IPersonalMisc p, int heightScalar) + public static float GetHeightAbsolute(IPersonalMisc p, byte heightScalar) { float HeightRatio = GetHeightRatio(heightScalar); return HeightRatio * p.Height; } [MethodImpl(MethodImplOptions.NoOptimization | MethodImplOptions.NoInlining)] - public static float GetWeightAbsolute(IPersonalMisc p, int heightScalar, int weightScalar) + public static float GetWeightAbsolute(IPersonalMisc p, byte heightScalar, byte weightScalar) { float HeightRatio = GetHeightRatio(heightScalar); float WeightRatio = GetWeightRatio(weightScalar); @@ -825,11 +821,12 @@ public sealed class PA8 : PKM, ISanityChecksum, IMoveReset, public void SetMasteryFlagMove(ushort move) { - var moves = MoveShopPermitIndexes; + var permit = Permit; + var moves = permit.RecordPermitIndexes; int flagIndex = moves.IndexOf(move); if (flagIndex == -1) return; - if (MoveShopPermitFlags[flagIndex]) + if (permit.IsRecordPermitted(flagIndex)) SetMasteredRecordFlag(flagIndex, true); } @@ -861,8 +858,8 @@ public sealed class PA8 : PKM, ISanityChecksum, IMoveReset, Nature = Nature, StatNature = StatNature, - TID = TID, - SID = SID, + TID16 = TID16, + SID16 = SID16, EXP = EXP, Ability = Ability, AbilityNumber = AbilityNumber, diff --git a/PKHeX.Core/PKM/PB7.cs b/PKHeX.Core/PKM/PB7.cs index ec71bb474..d72f57216 100644 --- a/PKHeX.Core/PKM/PB7.cs +++ b/PKHeX.Core/PKM/PB7.cs @@ -27,7 +27,7 @@ public sealed class PB7 : G6PKM, IHyperTrain, IAwakened, IScaledSizeValue, IComb public override int SIZE_STORED => SIZE; private const int SIZE = 260; public override EntityContext Context => EntityContext.Gen7b; - public override PersonalInfo PersonalInfo => PersonalTable.GG.GetFormEntry(Species, Form); + public override PersonalInfo7GG PersonalInfo => PersonalTable.GG.GetFormEntry(Species, Form); public PB7() : base(SIZE) { } public PB7(byte[] data) : base(DecryptParty(data)) { } @@ -40,7 +40,7 @@ public sealed class PB7 : G6PKM, IHyperTrain, IAwakened, IScaledSizeValue, IComb return data; } - public override PKM Clone() => new PB7((byte[])Data.Clone()); + public override PB7 Clone() => new((byte[])Data.Clone()); // Structure #region Block A @@ -74,16 +74,22 @@ public sealed class PB7 : G6PKM, IHyperTrain, IAwakened, IScaledSizeValue, IComb set => WriteUInt16LittleEndian(Data.AsSpan(0x0A), (ushort)value); } - public override int TID + public override uint ID32 { - get => ReadUInt16LittleEndian(Data.AsSpan(0x0C)); - set => WriteUInt16LittleEndian(Data.AsSpan(0x0C), (ushort)value); + get => ReadUInt32LittleEndian(Data.AsSpan(0x0C)); + set => WriteUInt32LittleEndian(Data.AsSpan(0x0C), value); } - public override int SID + public override ushort TID16 + { + get => ReadUInt16LittleEndian(Data.AsSpan(0x0C)); + set => WriteUInt16LittleEndian(Data.AsSpan(0x0C), value); + } + + public override ushort SID16 { get => ReadUInt16LittleEndian(Data.AsSpan(0x0E)); - set => WriteUInt16LittleEndian(Data.AsSpan(0x0E), (ushort)value); + set => WriteUInt16LittleEndian(Data.AsSpan(0x0E), value); } public override uint EXP @@ -138,7 +144,7 @@ public sealed class PB7 : G6PKM, IHyperTrain, IAwakened, IScaledSizeValue, IComb public override string Nickname { get => StringConverter8.GetString(Nickname_Trash); - set => StringConverter8.SetString(Nickname_Trash, value.AsSpan(), 12, StringConverterOption.None); + set => StringConverter8.SetString(Nickname_Trash, value, 12, StringConverterOption.None); } public override ushort Move1 @@ -214,7 +220,7 @@ public sealed class PB7 : G6PKM, IHyperTrain, IAwakened, IScaledSizeValue, IComb public override string HT_Name { get => StringConverter8.GetString(HT_Trash); - set => StringConverter8.SetString(HT_Trash, value.AsSpan(), 12, StringConverterOption.None); + set => StringConverter8.SetString(HT_Trash, value, 12, StringConverterOption.None); } public override int HT_Gender { get => Data[0x92]; set => Data[0x92] = (byte)value; } @@ -251,7 +257,7 @@ public sealed class PB7 : G6PKM, IHyperTrain, IAwakened, IScaledSizeValue, IComb public override string OT_Name { get => StringConverter8.GetString(OT_Trash); - set => StringConverter8.SetString(OT_Trash, value.AsSpan(), 12, StringConverterOption.None); + set => StringConverter8.SetString(OT_Trash, value, 12, StringConverterOption.None); } public override int OT_Friendship { get => Data[0xCA]; set => Data[0xCA] = (byte)value; } @@ -326,7 +332,7 @@ public sealed class PB7 : G6PKM, IHyperTrain, IAwakened, IScaledSizeValue, IComb protected override bool TradeOT(ITrainerInfo tr) { // Check to see if the OT matches the SAV's OT info. - if (!(tr.TID == TID && tr.SID == SID && tr.Gender == OT_Gender && tr.OT == OT_Name)) + if (!(tr.ID32 == ID32 && tr.Gender == OT_Gender && tr.OT == OT_Name)) return false; CurrentHandler = 0; @@ -410,29 +416,29 @@ public sealed class PB7 : G6PKM, IHyperTrain, IAwakened, IScaledSizeValue, IComb return NatureAmpTable[(5 * nature) + index]; } - private static readonly sbyte[] NatureAmpTable = + private static ReadOnlySpan NatureAmpTable => new sbyte[] { 0, 0, 0, 0, 0, // Hardy 1,-1, 0, 0, 0, // Lonely 1, 0, 0, 0,-1, // Brave 1, 0,-1, 0, 0, // Adamant 1, 0, 0,-1, 0, // Naughty - -1, 1, 0, 0, 0, // Bold + -1, 1, 0, 0, 0, // Bold 0, 0, 0, 0, 0, // Docile 0, 1, 0, 0,-1, // Relaxed 0, 1,-1, 0, 0, // Impish 0, 1, 0,-1, 0, // Lax - -1, 0, 0, 0, 1, // Timid + -1, 0, 0, 0, 1, // Timid 0,-1, 0, 0, 1, // Hasty 0, 0, 0, 0, 0, // Serious 0, 0,-1, 0, 1, // Jolly 0, 0, 0,-1, 1, // Naive - -1, 0, 1, 0, 0, // Modest + -1, 0, 1, 0, 0, // Modest 0,-1, 1, 0, 0, // Mild 0, 0, 1, 0,-1, // Quiet 0, 0, 0, 0, 0, // Bashful 0, 0, 1,-1, 0, // Rash - -1, 0, 0, 1, 0, // Calm + -1, 0, 0, 1, 0, // Calm 0,-1, 0, 1, 0, // Gentle 0, 0, 0, 1,-1, // Sassy 0, 0,-1, 1, 0, // Careful @@ -515,7 +521,7 @@ public sealed class PB7 : G6PKM, IHyperTrain, IAwakened, IScaledSizeValue, IComb public void ResetWeight() => WeightAbsolute = CalcWeightAbsolute; [MethodImpl(MethodImplOptions.NoOptimization | MethodImplOptions.NoInlining)] - private static float GetHeightRatio(int heightScalar) + private static float GetHeightRatio(byte heightScalar) { // + 40%, -20 float result = heightScalar / 255f; // 0x437F0000 @@ -525,7 +531,7 @@ public sealed class PB7 : G6PKM, IHyperTrain, IAwakened, IScaledSizeValue, IComb } [MethodImpl(MethodImplOptions.NoOptimization | MethodImplOptions.NoInlining)] - private static float GetWeightRatio(int weightScalar) + private static float GetWeightRatio(byte weightScalar) { // +/- 20% float result = weightScalar / 255f; // 0x437F0000 @@ -535,14 +541,14 @@ public sealed class PB7 : G6PKM, IHyperTrain, IAwakened, IScaledSizeValue, IComb } [MethodImpl(MethodImplOptions.NoOptimization | MethodImplOptions.NoInlining)] - public static float GetHeightAbsolute(IPersonalMisc p, int heightScalar) + public static float GetHeightAbsolute(IPersonalMisc p, byte heightScalar) { float HeightRatio = GetHeightRatio(heightScalar); return HeightRatio * p.Height; } [MethodImpl(MethodImplOptions.NoOptimization | MethodImplOptions.NoInlining)] - public static float GetWeightAbsolute(IPersonalMisc p, int heightScalar, int weightScalar) + public static float GetWeightAbsolute(IPersonalMisc p, byte heightScalar, byte weightScalar) { float HeightRatio = GetHeightRatio(heightScalar); float WeightRatio = GetWeightRatio(weightScalar); @@ -588,7 +594,7 @@ public sealed class PB7 : G6PKM, IHyperTrain, IAwakened, IScaledSizeValue, IComb return GetRandomIndex(characterIndex); if (bits is 0) return 0; - Span amps = NatureAmpTable.AsSpan(5 * nature, 5); + var amps = NatureAmpTable.Slice(5 * nature, 5); if (amps[bits - 1] != -1) // not a negative stat return bits; @@ -613,8 +619,8 @@ public sealed class PB7 : G6PKM, IHyperTrain, IAwakened, IScaledSizeValue, IComb { EncryptionConstant = EncryptionConstant, Species = Species, - TID = TID, - SID = SID, + TID16 = TID16, + SID16 = SID16, EXP = EXP, PID = PID, Ability = Ability, diff --git a/PKHeX.Core/PKM/PB8.cs b/PKHeX.Core/PKM/PB8.cs index 2866bd68b..0432d95f4 100644 --- a/PKHeX.Core/PKM/PB8.cs +++ b/PKHeX.Core/PKM/PB8.cs @@ -27,7 +27,8 @@ public sealed class PB8 : G8PKM }; public override IReadOnlyList ExtraBytes => Unused; - public override PersonalInfo PersonalInfo => PersonalTable.BDSP.GetFormEntry(Species, Form); + public override PersonalInfo8BDSP PersonalInfo => PersonalTable.BDSP.GetFormEntry(Species, Form); + public override IPermitRecord Permit => PersonalInfo; public override bool IsNative => BDSP; public override EntityContext Context => EntityContext.Gen8b; @@ -38,7 +39,7 @@ public sealed class PB8 : G8PKM } public PB8(byte[] data) : base(data) { } - public override PKM Clone() => new PB8((byte[])Data.Clone()); + public override PB8 Clone() => new((byte[])Data.Clone()); public bool IsDprIllegal { @@ -51,7 +52,7 @@ public sealed class PB8 : G8PKM if (IsEgg) { // Apply link trade data, only if it left the OT (ignore if dumped & imported, or cloned, etc) - if ((tr.TID != TID) || (tr.SID != SID) || (tr.Gender != OT_Gender) || (tr.OT != OT_Name)) + if ((tr.TID16 != TID16) || (tr.SID16 != SID16) || (tr.Gender != OT_Gender) || (tr.OT != OT_Name)) SetLinkTradeEgg(Day, Month, Year, Locations.LinkTrade6NPC); // Unfortunately, BDSP doesn't return if it's an egg, and can update the HT details & handler. @@ -99,7 +100,7 @@ public sealed class PB8 : G8PKM private bool TradeOT(ITrainerInfo tr) { // Check to see if the OT matches the SAV's OT info. - if (!(tr.TID == TID && tr.SID == SID && tr.Gender == OT_Gender && tr.OT == OT_Name)) + if (!(tr.ID32 == ID32 && tr.Gender == OT_Gender && tr.OT == OT_Name)) return false; CurrentHandler = 0; diff --git a/PKHeX.Core/PKM/PK1.cs b/PKHeX.Core/PKM/PK1.cs index d8181061f..0a8192c90 100644 --- a/PKHeX.Core/PKM/PK1.cs +++ b/PKHeX.Core/PKM/PK1.cs @@ -7,7 +7,7 @@ namespace PKHeX.Core; /// Generation 1 format. public sealed class PK1 : GBPKML, IPersonalType { - public override PersonalInfo PersonalInfo => PersonalTable.Y[Species]; + public override PersonalInfo1 PersonalInfo => PersonalTable.Y[Species]; public override bool Valid => Species <= 151 && (Data[0] == 0 || Species != 0); @@ -27,9 +27,9 @@ public sealed class PK1 : GBPKML, IPersonalType return data; } - public override PKM Clone() + public override PK1 Clone() { - var clone = new PK1((byte[])Data.Clone(), Japanese); + PK1 clone = new((byte[])Data.Clone(), Japanese); OT_Trash.CopyTo(clone.OT_Trash); Nickname_Trash.CopyTo(clone.Nickname_Trash); return clone; @@ -38,8 +38,8 @@ public sealed class PK1 : GBPKML, IPersonalType protected override byte[] Encrypt() => new PokeList1(this).Write(); #region Stored Attributes - public byte SpeciesID1 { get => Data[0]; set => Data[0] = value; } // raw access - public override ushort Species { get => SpeciesConverter.GetG1Species(SpeciesID1); set => SetSpeciesValues(value); } + public byte SpeciesInternal { get => Data[0]; set => Data[0] = value; } // raw access + public override ushort Species { get => SpeciesConverter.GetNational1(SpeciesInternal); set => SetSpeciesValues(value); } public override int Stat_HPCurrent { get => ReadUInt16BigEndian(Data.AsSpan(0x1)); set => WriteUInt16BigEndian(Data.AsSpan(0x1), (ushort)value); } public int Stat_LevelBox { get => Data[3]; set => Data[3] = (byte)value; } public override int Status_Condition { get => Data[4]; set => Data[4] = (byte)value; } @@ -50,7 +50,7 @@ public sealed class PK1 : GBPKML, IPersonalType public override ushort Move2 { get => Data[9]; set => Data[9] = (byte)value; } public override ushort Move3 { get => Data[10]; set => Data[10] = (byte)value; } public override ushort Move4 { get => Data[11]; set => Data[11] = (byte)value; } - public override int TID { get => ReadUInt16BigEndian(Data.AsSpan(0xC)); set => WriteUInt16BigEndian(Data.AsSpan(0xC), (ushort)value); } + public override ushort TID16 { get => ReadUInt16BigEndian(Data.AsSpan(0xC)); set => WriteUInt16BigEndian(Data.AsSpan(0xC), value); } public override uint EXP { get => ReadUInt32BigEndian(Data.AsSpan(0xE)) >> 8; set => WriteUInt32BigEndian(Data.AsSpan(0xE), (value << 8) | Data[0x11]); } public override int EV_HP { get => ReadUInt16BigEndian(Data.AsSpan(0x11)); set => WriteUInt16BigEndian(Data.AsSpan(0x11), (ushort)value); } public override int EV_ATK { get => ReadUInt16BigEndian(Data.AsSpan(0x13)); set => WriteUInt16BigEndian(Data.AsSpan(0x13), (ushort)value); } @@ -94,11 +94,11 @@ public sealed class PK1 : GBPKML, IPersonalType private void SetSpeciesValues(ushort value) { - var updated = SpeciesConverter.SetG1Species(value); - if (SpeciesID1 == updated) + var updated = SpeciesConverter.GetInternal1(value); + if (SpeciesInternal == updated) return; - SpeciesID1 = updated; + SpeciesInternal = updated; var pi = PersonalTable.RB[value]; Type1 = pi.Type1; @@ -166,14 +166,14 @@ public sealed class PK1 : GBPKML, IPersonalType { EncryptionConstant = rnd.Rand32(), Species = Species, - TID = TID, + TID16 = TID16, CurrentLevel = CurrentLevel, EXP = EXP, Met_Level = CurrentLevel, Nature = Experience.GetNatureVC(EXP), PID = rnd.Rand32(), Ball = 4, - MetDate = DateTime.Now, + MetDate = DateOnly.FromDateTime(DateTime.Now), Version = (int)GameVersion.RD, // Default to red Move1 = Move1, Move2 = Move2, @@ -215,14 +215,15 @@ public sealed class PK1 : GBPKML, IPersonalType switch (IsShiny ? Shiny.Always : Shiny.Never) { case Shiny.Always when !pk7.IsShiny: // Force Square - pk7.PID = (uint)(((pk7.TID ^ 0 ^ (pk7.PID & 0xFFFF) ^ 0) << 16) | (pk7.PID & 0xFFFF)); + var low = pk7.PID & 0xFFFF; + pk7.PID = (low ^ pk7.TID16 ^ 0u) << 16 | low; break; case Shiny.Never when pk7.IsShiny: // Force Not Shiny pk7.PID ^= 0x1000_0000; break; } - int abil = Legal.TransferSpeciesDefaultAbilityGen1(Species) ? 0 : 2; // Hidden + int abil = TransporterLogic.IsHiddenDisallowedVC1(Species) ? 0 : 2; // Hidden pk7.RefreshAbility(abil); // 0/1/2 (not 1/2/4) if (Species == (int)Core.Species.Mew) // Mew gets special treatment. diff --git a/PKHeX.Core/PKM/PK2.cs b/PKHeX.Core/PKM/PK2.cs index f38858196..713b4e48f 100644 --- a/PKHeX.Core/PKM/PK2.cs +++ b/PKHeX.Core/PKM/PK2.cs @@ -6,7 +6,7 @@ namespace PKHeX.Core; /// Generation 2 format. public sealed class PK2 : GBPKML, ICaughtData2 { - public override PersonalInfo PersonalInfo => PersonalTable.C[Species]; + public override PersonalInfo2 PersonalInfo => PersonalTable.C[Species]; internal const byte EggSpeciesValue = 0xFD; public override bool Valid => Species is <= Legal.MaxSpeciesID_2 or EggSpeciesValue; // egg @@ -27,9 +27,9 @@ public sealed class PK2 : GBPKML, ICaughtData2 return data; } - public override PKM Clone() + public override PK2 Clone() { - var clone = new PK2((byte[])Data.Clone(), Japanese) { IsEgg = IsEgg }; + PK2 clone = new((byte[])Data.Clone(), Japanese) { IsEgg = IsEgg }; OT_Trash.CopyTo(clone.OT_Trash); Nickname_Trash.CopyTo(clone.Nickname_Trash); return clone; @@ -45,7 +45,7 @@ public sealed class PK2 : GBPKML, ICaughtData2 public override ushort Move2 { get => Data[3]; set => Data[3] = (byte)value; } public override ushort Move3 { get => Data[4]; set => Data[4] = (byte)value; } public override ushort Move4 { get => Data[5]; set => Data[5] = (byte)value; } - public override int TID { get => ReadUInt16BigEndian(Data.AsSpan(6)); set => WriteUInt16BigEndian(Data.AsSpan(6), (ushort)value); } + public override ushort TID16 { get => ReadUInt16BigEndian(Data.AsSpan(6)); set => WriteUInt16BigEndian(Data.AsSpan(6), value); } public override uint EXP { get => ReadUInt32BigEndian(Data.AsSpan(0x08)) >> 8; set => WriteUInt32BigEndian(Data.AsSpan(8), (value << 8) | Data[0xB]); } public override int EV_HP { get => ReadUInt16BigEndian(Data.AsSpan(0x0B)); set => WriteUInt16BigEndian(Data.AsSpan(0xB), (ushort)value); } public override int EV_ATK { get => ReadUInt16BigEndian(Data.AsSpan(0x0D)); set => WriteUInt16BigEndian(Data.AsSpan(0xD), (ushort)value); } @@ -136,14 +136,14 @@ public sealed class PK2 : GBPKML, ICaughtData2 { EncryptionConstant = rnd.Rand32(), Species = Species, - TID = TID, + TID16 = TID16, CurrentLevel = CurrentLevel, EXP = EXP, Met_Level = CurrentLevel, Nature = Experience.GetNatureVC(EXP), PID = rnd.Rand32(), Ball = 4, - MetDate = DateTime.Now, + MetDate = DateOnly.FromDateTime(DateTime.Now), Version = HasOriginalMetLocation ? (int)GameVersion.C : (int)GameVersion.SI, Move1 = Move1, Move2 = Move2, @@ -182,14 +182,15 @@ public sealed class PK2 : GBPKML, ICaughtData2 switch (IsShiny ? Shiny.Always : Shiny.Never) { case Shiny.Always when !pk7.IsShiny: // Force Square - pk7.PID = (uint)(((pk7.TID ^ 0 ^ (pk7.PID & 0xFFFF) ^ 0) << 16) | (pk7.PID & 0xFFFF)); + var low = pk7.PID & 0xFFFF; + pk7.PID = (low ^ pk7.TID16 ^ 0u) << 16 | low; break; case Shiny.Never when pk7.IsShiny: // Force Not Shiny pk7.PID ^= 0x1000_0000; break; } - int abil = Legal.TransferSpeciesDefaultAbilityGen2(Species) ? 0 : 2; // Hidden + int abil = TransporterLogic.IsHiddenDisallowedVC2(Species) ? 0 : 2; // Hidden pk7.RefreshAbility(abil); // 0/1/2 (not 1/2/4) if (special) @@ -233,7 +234,7 @@ public sealed class PK2 : GBPKML, ICaughtData2 Move2 = Move2, Move3 = Move3, Move4 = Move4, - TID = TID, + TID16 = TID16, EXP = EXP, EV_HP = EV_HP, EV_ATK = EV_ATK, diff --git a/PKHeX.Core/PKM/PK3.cs b/PKHeX.Core/PKM/PK3.cs index 178d6c607..cdb6d568e 100644 --- a/PKHeX.Core/PKM/PK3.cs +++ b/PKHeX.Core/PKM/PK3.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Numerics; using static System.Buffers.Binary.BinaryPrimitives; namespace PKHeX.Core; @@ -15,7 +16,7 @@ public sealed class PK3 : G3PKM, ISanityChecksum public override int SIZE_PARTY => PokeCrypto.SIZE_3PARTY; public override int SIZE_STORED => PokeCrypto.SIZE_3STORED; public override EntityContext Context => EntityContext.Gen3; - public override PersonalInfo PersonalInfo => PersonalTable.RS[Species]; + public override PersonalInfo3 PersonalInfo => PersonalTable.RS[Species]; public override IReadOnlyList ExtraBytes => Unused; @@ -29,11 +30,11 @@ public sealed class PK3 : G3PKM, ISanityChecksum return data; } - public override PKM Clone() + public override PK3 Clone() { // Don't use the byte[] constructor, the DecryptIfEncrypted call is based on checksum. // An invalid checksum will shuffle the data; we already know it's un-shuffled. Set up manually. - var pk = new PK3(); + PK3 pk = new(); Data.CopyTo(pk.Data, 0); return pk; } @@ -48,12 +49,13 @@ public sealed class PK3 : G3PKM, ISanityChecksum // 0x20 Intro public override uint PID { get => ReadUInt32LittleEndian(Data.AsSpan(0x00)); set => WriteUInt32LittleEndian(Data.AsSpan(0x00), value); } - public override int TID { get => ReadUInt16LittleEndian(Data.AsSpan(0x04)); set => WriteUInt16LittleEndian(Data.AsSpan(0x04), (ushort)value); } - public override int SID { get => ReadUInt16LittleEndian(Data.AsSpan(0x06)); set => WriteUInt16LittleEndian(Data.AsSpan(0x06), (ushort)value); } + public override uint ID32 { get => ReadUInt32LittleEndian(Data.AsSpan(0x04)); set => WriteUInt32LittleEndian(Data.AsSpan(0x04), value); } + public override ushort TID16 { get => ReadUInt16LittleEndian(Data.AsSpan(0x04)); set => WriteUInt16LittleEndian(Data.AsSpan(0x04), value); } + public override ushort SID16 { get => ReadUInt16LittleEndian(Data.AsSpan(0x06)); set => WriteUInt16LittleEndian(Data.AsSpan(0x06), value); } public override string Nickname { get => StringConverter3.GetString(Nickname_Trash, Japanese); - set => StringConverter3.SetString(Nickname_Trash, (IsEgg ? EggNameJapanese : value).AsSpan(), 10, Japanese, StringConverterOption.None); + set => StringConverter3.SetString(Nickname_Trash, IsEgg ? EggNameJapanese : value, 10, Japanese, StringConverterOption.None); } public override int Language { get => Data[0x12]; set => Data[0x12] = (byte)value; } public bool FlagIsBadEgg { get => (Data[0x13] & 1) != 0; set => Data[0x13] = (byte)((Data[0x13] & ~1) | (value ? 1 : 0)); } @@ -62,22 +64,22 @@ public sealed class PK3 : G3PKM, ISanityChecksum public override string OT_Name { get => StringConverter3.GetString(OT_Trash, Japanese); - set => StringConverter3.SetString(OT_Trash, value.AsSpan(), 7, Japanese, StringConverterOption.None); + set => StringConverter3.SetString(OT_Trash, value, 7, Japanese, StringConverterOption.None); } public override int MarkValue { get => SwapBits(Data[0x1B], 1, 2); set => Data[0x1B] = (byte)SwapBits(value, 1, 2); } public ushort Checksum { get => ReadUInt16LittleEndian(Data.AsSpan(0x1C)); set => WriteUInt16LittleEndian(Data.AsSpan(0x1C), value); } public ushort Sanity { get => ReadUInt16LittleEndian(Data.AsSpan(0x1E)); set => WriteUInt16LittleEndian(Data.AsSpan(0x1E), value); } #region Block A - public override ushort SpeciesID3 { get => ReadUInt16LittleEndian(Data.AsSpan(0x20)); set => WriteUInt16LittleEndian(Data.AsSpan(0x20), value); } // raw access + public override ushort SpeciesInternal { get => ReadUInt16LittleEndian(Data.AsSpan(0x20)); set => WriteUInt16LittleEndian(Data.AsSpan(0x20), value); } // raw access public override ushort Species { - get => SpeciesConverter.GetG4Species(SpeciesID3); + get => SpeciesConverter.GetNational3(SpeciesInternal); set { - var s3 = SpeciesConverter.GetG3Species(value); - FlagHasSpecies = (SpeciesID3 = s3) != 0; + var s3 = SpeciesConverter.GetInternal3(value); + FlagHasSpecies = (SpeciesInternal = s3) != 0; } } @@ -180,6 +182,8 @@ public sealed class PK3 : G3PKM, ISanityChecksum public override bool Unused3 { get => (RIB0 & (1 << 29)) == 1 << 29; set => RIB0 = ((RIB0 & ~(1u << 29)) | (value ? 1u << 29 : 0u)); } public override bool Unused4 { get => (RIB0 & (1 << 30)) == 1 << 30; set => RIB0 = ((RIB0 & ~(1u << 30)) | (value ? 1u << 30 : 0u)); } public override bool FatefulEncounter { get => RIB0 >> 31 == 1; set => RIB0 = (RIB0 & ~(1 << 31)) | (uint)(value ? 1 << 31 : 0); } + public override int RibbonCount => BitOperations.PopCount(RIB0 & 0b00000111_11111111_11111111_11111111); + #endregion #region Battle Stats @@ -216,8 +220,8 @@ public sealed class PK3 : G3PKM, ISanityChecksum { PID = PID, Species = Species, - TID = TID, - SID = SID, + TID16 = TID16, + SID16 = SID16, EXP = IsEgg ? Experience.GetEXP(5, PersonalInfo.EXPGrowth) : EXP, Gender = EntityGender.GetFromPID(Species, PID), Form = Form, @@ -257,7 +261,7 @@ public sealed class PK3 : G3PKM, ISanityChecksum PKRS_Strain = PKRS_Strain, PKRS_Days = PKRS_Days, OT_Gender = OT_Gender, - MetDate = DateTime.Now, + MetDate = DateOnly.FromDateTime(DateTime.Now), Met_Level = CurrentLevel, Met_Location = Locations.Transfer3, // Pal Park @@ -305,14 +309,14 @@ public sealed class PK3 : G3PKM, ISanityChecksum // Yay for reusing string buffers! The game allocates a buffer and reuses it when creating strings. // Trash from the {unknown source} is currently in buffer. Set it to the Nickname region. - var trash = StringConverter345.G4TransferTrashBytes; - if (pk4.Language < trash.Length) - trash[pk4.Language].CopyTo(pk4.Data, 0x48 + 4); + var trash = StringConverter345.GetTrashBytes(pk4.Language); + var nickTrash = pk4.Nickname_Trash[4..]; // min of 1 char and terminator, ignore first 2. + trash.CopyTo(nickTrash); pk4.Nickname = IsEgg ? SpeciesName.GetSpeciesNameGeneration(pk4.Species, pk4.Language, 4) : Nickname; pk4.IsNicknamed = !IsEgg && IsNicknamed; // Trash from the current string (Nickname) is in our string buffer. Slap the OT name over-top. - Buffer.BlockCopy(pk4.Data, 0x48, pk4.Data, 0x68, 0x10); + nickTrash.CopyTo(pk4.OT_Trash); pk4.OT_Name = OT_Name; if (HeldItem > 0) diff --git a/PKHeX.Core/PKM/PK4.cs b/PKHeX.Core/PKM/PK4.cs index 7b6842914..564441802 100644 --- a/PKHeX.Core/PKM/PK4.cs +++ b/PKHeX.Core/PKM/PK4.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Numerics; using static System.Buffers.Binary.BinaryPrimitives; namespace PKHeX.Core; @@ -17,7 +18,7 @@ public sealed class PK4 : G4PKM public override int SIZE_PARTY => PokeCrypto.SIZE_4PARTY; public override int SIZE_STORED => PokeCrypto.SIZE_4STORED; public override EntityContext Context => EntityContext.Gen4; - public override PersonalInfo PersonalInfo => PersonalTable.HGSS.GetFormEntry(Species, Form); + public override PersonalInfo4 PersonalInfo => PersonalTable.HGSS.GetFormEntry(Species, Form); public PK4() : base(PokeCrypto.SIZE_4PARTY) { } public PK4(byte[] data) : base(DecryptParty(data)) { } @@ -29,7 +30,7 @@ public sealed class PK4 : G4PKM return data; } - public override PKM Clone() => new PK4((byte[])Data.Clone()); + public override PK4 Clone() => new((byte[])Data.Clone()); // Structure public override uint PID { get => ReadUInt32LittleEndian(Data.AsSpan(0x00)); set => WriteUInt32LittleEndian(Data.AsSpan(0x00), value); } @@ -39,8 +40,9 @@ public sealed class PK4 : G4PKM #region Block A public override ushort Species { get => ReadUInt16LittleEndian(Data.AsSpan(0x08)); set => WriteUInt16LittleEndian(Data.AsSpan(0x08), value); } public override int HeldItem { get => ReadUInt16LittleEndian(Data.AsSpan(0x0A)); set => WriteUInt16LittleEndian(Data.AsSpan(0x0A), (ushort)value); } - public override int TID { get => ReadUInt16LittleEndian(Data.AsSpan(0x0C)); set => WriteUInt16LittleEndian(Data.AsSpan(0x0C), (ushort)value); } - public override int SID { get => ReadUInt16LittleEndian(Data.AsSpan(0x0E)); set => WriteUInt16LittleEndian(Data.AsSpan(0x0E), (ushort)value); } + public override uint ID32 { get => ReadUInt32LittleEndian(Data.AsSpan(0x0C)); set => WriteUInt32LittleEndian(Data.AsSpan(0x0C), value); } + public override ushort TID16 { get => ReadUInt16LittleEndian(Data.AsSpan(0x0C)); set => WriteUInt16LittleEndian(Data.AsSpan(0x0C), value); } + public override ushort SID16 { get => ReadUInt16LittleEndian(Data.AsSpan(0x0E)); set => WriteUInt16LittleEndian(Data.AsSpan(0x0E), value); } public override uint EXP { get => ReadUInt32LittleEndian(Data.AsSpan(0x10)); set => WriteUInt32LittleEndian(Data.AsSpan(0x10), value); } public override int OT_Friendship { get => Data[0x14]; set => Data[0x14] = (byte)value; } public override int Ability { get => Data[0x15]; set => Data[0x15] = (byte)value; } @@ -95,6 +97,10 @@ public sealed class PK4 : G4PKM public override bool RIB3_5 { get => (RIB3 & (1 << 5)) == 1 << 5; set => RIB3 = (byte)((RIB3 & ~(1 << 5)) | (value ? 1 << 5 : 0)); } // Unused public override bool RIB3_6 { get => (RIB3 & (1 << 6)) == 1 << 6; set => RIB3 = (byte)((RIB3 & ~(1 << 6)) | (value ? 1 << 6 : 0)); } // Unused public override bool RIB3_7 { get => (RIB3 & (1 << 7)) == 1 << 7; set => RIB3 = (byte)((RIB3 & ~(1 << 7)) | (value ? 1 << 7 : 0)); } // Unused + + public override int RibbonCount => BitOperations.PopCount(ReadUInt32LittleEndian(Data.AsSpan(0x30)) & 0b00001111_11111111__11111111_11111111) + + BitOperations.PopCount(ReadUInt32LittleEndian(Data.AsSpan(0x3C))) + + BitOperations.PopCount(ReadUInt32LittleEndian(Data.AsSpan(0x60)) & 0b00000000_00001111__11111111_11111111); #endregion #region Block B @@ -180,7 +186,7 @@ public sealed class PK4 : G4PKM public override string Nickname { get => StringConverter4.GetString(Nickname_Trash); - set => StringConverter4.SetString(Nickname_Trash, value.AsSpan(), 10, StringConverterOption.None); + set => StringConverter4.SetString(Nickname_Trash, value, 10, StringConverterOption.None); } // 0x5E unused @@ -228,7 +234,7 @@ public sealed class PK4 : G4PKM public override string OT_Name { get => StringConverter4.GetString(OT_Trash); - set => StringConverter4.SetString(OT_Trash, value.AsSpan(), 7, StringConverterOption.None); + set => StringConverter4.SetString(OT_Trash, value, 7, StringConverterOption.None); } public override int Egg_Year { get => Data[0x78]; set => Data[0x78] = (byte)value; } @@ -311,7 +317,7 @@ public sealed class PK4 : G4PKM if (Data[0x5F] < 0x10 && ReadUInt16LittleEndian(Data.AsSpan(0x80)) > 0x4000) return new PK5(Data); - DateTime moment = DateTime.Now; + var moment = DateOnly.FromDateTime(DateTime.Now); PK5 pk5 = new(Data.AsSpan(0, PokeCrypto.SIZE_5PARTY).ToArray()) // Convert away! { diff --git a/PKHeX.Core/PKM/PK5.cs b/PKHeX.Core/PKM/PK5.cs index abdf43650..6ddfab057 100644 --- a/PKHeX.Core/PKM/PK5.cs +++ b/PKHeX.Core/PKM/PK5.cs @@ -1,12 +1,13 @@ using System; using System.Collections.Generic; +using System.Numerics; using static System.Buffers.Binary.BinaryPrimitives; namespace PKHeX.Core; /// Generation 5 format. public sealed class PK5 : PKM, ISanityChecksum, - IRibbonSetEvent3, IRibbonSetEvent4, IRibbonSetUnique3, IRibbonSetUnique4, IRibbonSetCommon3, IRibbonSetCommon4, + IRibbonSetEvent3, IRibbonSetEvent4, IRibbonSetUnique3, IRibbonSetUnique4, IRibbonSetCommon3, IRibbonSetCommon4, IRibbonSetRibbons, IContestStats, IGroundTile { private static readonly ushort[] Unused = @@ -24,7 +25,7 @@ public sealed class PK5 : PKM, ISanityChecksum, public override int SIZE_PARTY => PokeCrypto.SIZE_5PARTY; public override int SIZE_STORED => PokeCrypto.SIZE_5STORED; public override EntityContext Context => EntityContext.Gen5; - public override PersonalInfo PersonalInfo => PersonalTable.B2W2.GetFormEntry(Species, Form); + public override PersonalInfo5B2W2 PersonalInfo => PersonalTable.B2W2.GetFormEntry(Species, Form); public PK5() : base(PokeCrypto.SIZE_5PARTY) { } public PK5(byte[] data) : base(DecryptParty(data)) { } @@ -36,11 +37,11 @@ public sealed class PK5 : PKM, ISanityChecksum, return data; } - public override PKM Clone() => new PK5((byte[])Data.Clone()); + public override PK5 Clone() => new((byte[])Data.Clone()); public override void RefreshChecksum() => Checksum = CalculateChecksum(); public override bool ChecksumValid => CalculateChecksum() == Checksum; public override bool Valid { get => Sanity == 0 && ChecksumValid; set { if (!value) return; Sanity = 0; RefreshChecksum(); } } - private ushort CalculateChecksum() => PokeCrypto.GetCHK(Data, PokeCrypto.SIZE_4STORED); + private ushort CalculateChecksum() => PokeCrypto.GetCHK(Data.AsSpan()[8..PokeCrypto.SIZE_4STORED]); // Trash Bytes public override Span Nickname_Trash => Data.AsSpan(0x48, 22); @@ -60,8 +61,9 @@ public sealed class PK5 : PKM, ISanityChecksum, #region Block A public override ushort Species { get => ReadUInt16LittleEndian(Data.AsSpan(0x08)); set => WriteUInt16LittleEndian(Data.AsSpan(0x08), value); } public override int HeldItem { get => ReadUInt16LittleEndian(Data.AsSpan(0x0A)); set => WriteUInt16LittleEndian(Data.AsSpan(0x0A), (ushort)value); } - public override int TID { get => ReadUInt16LittleEndian(Data.AsSpan(0x0C)); set => WriteUInt16LittleEndian(Data.AsSpan(0x0C), (ushort)value); } - public override int SID { get => ReadUInt16LittleEndian(Data.AsSpan(0x0E)); set => WriteUInt16LittleEndian(Data.AsSpan(0x0E), (ushort)value); } + public override uint ID32 { get => ReadUInt32LittleEndian(Data.AsSpan(0x0C)); set => WriteUInt32LittleEndian(Data.AsSpan(0x0C), value); } + public override ushort TID16 { get => ReadUInt16LittleEndian(Data.AsSpan(0x0C)); set => WriteUInt16LittleEndian(Data.AsSpan(0x0C), value); } + public override ushort SID16 { get => ReadUInt16LittleEndian(Data.AsSpan(0x0E)); set => WriteUInt16LittleEndian(Data.AsSpan(0x0E), value); } public override uint EXP { get => ReadUInt32LittleEndian(Data.AsSpan(0x10)); set => WriteUInt32LittleEndian(Data.AsSpan(0x10), value); } public override int OT_Friendship { get => Data[0x14]; set => Data[0x14] = (byte)value; } public override int Ability { get => Data[0x15]; set => Data[0x15] = (byte)value; } @@ -82,8 +84,8 @@ public sealed class PK5 : PKM, ISanityChecksum, private byte RIB0 { get => Data[0x24]; set => Data[0x24] = value; } // Sinnoh 1 private byte RIB1 { get => Data[0x25]; set => Data[0x25] = value; } // Sinnoh 2 - private byte RIB2 { get => Data[0x26]; set => Data[0x26] = value; } // Unova 1 - private byte RIB3 { get => Data[0x27]; set => Data[0x27] = value; } // Unova 2 + private byte RIB2 { get => Data[0x26]; set => Data[0x26] = value; } // Sinnoh 3 + private byte RIB3 { get => Data[0x27]; set => Data[0x27] = value; } // Sinnoh 4 public bool RibbonChampionSinnoh { get => (RIB0 & (1 << 0)) == 1 << 0; set => RIB0 = (byte)((RIB0 & ~(1 << 0)) | (value ? 1 << 0 : 0)); } public bool RibbonAbility { get => (RIB0 & (1 << 1)) == 1 << 1; set => RIB0 = (byte)((RIB0 & ~(1 << 1)) | (value ? 1 << 1 : 0)); } public bool RibbonAbilityGreat { get => (RIB0 & (1 << 2)) == 1 << 2; set => RIB0 = (byte)((RIB0 & ~(1 << 2)) | (value ? 1 << 2 : 0)); } @@ -116,6 +118,10 @@ public sealed class PK5 : PKM, ISanityChecksum, public bool RIB3_5 { get => (RIB3 & (1 << 5)) == 1 << 5; set => RIB3 = (byte)((RIB3 & ~(1 << 5)) | (value ? 1 << 5 : 0)); } // Unused public bool RIB3_6 { get => (RIB3 & (1 << 6)) == 1 << 6; set => RIB3 = (byte)((RIB3 & ~(1 << 6)) | (value ? 1 << 6 : 0)); } // Unused public bool RIB3_7 { get => (RIB3 & (1 << 7)) == 1 << 7; set => RIB3 = (byte)((RIB3 & ~(1 << 7)) | (value ? 1 << 7 : 0)); } // Unused + + public int RibbonCount => BitOperations.PopCount(ReadUInt32LittleEndian(Data.AsSpan(0x30)) & 0b00001111_11111111__11111111_11111111) + + BitOperations.PopCount(ReadUInt32LittleEndian(Data.AsSpan(0x3C))) + + BitOperations.PopCount(ReadUInt32LittleEndian(Data.AsSpan(0x60)) & 0b00000000_00001111__11111111_11111111); #endregion #region Block B @@ -188,7 +194,7 @@ public sealed class PK5 : PKM, ISanityChecksum, #endregion #region Block C - public override string Nickname { get => StringConverter5.GetString(Nickname_Trash); set => StringConverter5.SetString(Nickname_Trash, value.AsSpan(), 10, StringConverterOption.None); } + public override string Nickname { get => StringConverter5.GetString(Nickname_Trash); set => StringConverter5.SetString(Nickname_Trash, value, 10, StringConverterOption.None); } // 0x5E unused public override int Version { get => Data[0x5F]; set => Data[0x5F] = (byte)value; } private byte RIB8 { get => Data[0x60]; set => Data[0x60] = value; } // Sinnoh 3 @@ -231,7 +237,7 @@ public sealed class PK5 : PKM, ISanityChecksum, #endregion #region Block D - public override string OT_Name { get => StringConverter5.GetString(OT_Trash); set => StringConverter5.SetString(OT_Trash, value.AsSpan(), 7, StringConverterOption.None); } + public override string OT_Name { get => StringConverter5.GetString(OT_Trash); set => StringConverter5.SetString(OT_Trash, value, 7, StringConverterOption.None); } public override int Egg_Year { get => Data[0x78]; set => Data[0x78] = (byte)value; } public override int Egg_Month { get => Data[0x79]; set => Data[0x79] = (byte)value; } public override int Egg_Day { get => Data[0x7A]; set => Data[0x7A] = (byte)value; } @@ -270,8 +276,8 @@ public sealed class PK5 : PKM, ISanityChecksum, #endregion // Generated Attributes - public override int PSV => (int)(((PID >> 16) ^ (PID & 0xFFFF)) >> 3); - public override int TSV => (TID ^ SID) >> 3; + public override uint PSV => ((PID >> 16) ^ (PID & 0xFFFF)) >> 3; + public override uint TSV => (uint)(TID16 ^ SID16) >> 3; public override int Characteristic { @@ -310,9 +316,9 @@ public sealed class PK5 : PKM, ISanityChecksum, } // Synthetic Trading Logic - public bool Trade(string SAV_Trainer, int SAV_TID, int SAV_SID, int SAV_GENDER, int Day = 1, int Month = 1, int Year = 2013) + public bool Trade(string SAV_Trainer, uint savID32, int SAV_GENDER, int Day = 1, int Month = 1, int Year = 2013) { - if (IsEgg && !(SAV_Trainer == OT_Name && SAV_TID == TID && SAV_SID == SID && SAV_GENDER == OT_Gender)) + if (IsEgg && !(SAV_Trainer == OT_Name && savID32 == ID32 && SAV_GENDER == OT_Gender)) { SetLinkTradeEgg(Day, Month, Year, Locations.LinkTrade5); return true; @@ -348,8 +354,8 @@ public sealed class PK5 : PKM, ISanityChecksum, { EncryptionConstant = PID, Species = Species, - TID = TID, - SID = SID, + TID16 = TID16, + SID16 = SID16, EXP = EXP, PID = PID, Ability = Ability, @@ -539,9 +545,9 @@ public sealed class PK5 : PKM, ISanityChecksum, private int CalculateAbilityIndex() { - var pi = (PersonalInfo5B2W2) PersonalInfo; if (HiddenAbility) return 2; + var pi = PersonalInfo; if (pi.Ability1 == Ability) return 0; if (pi.Ability2 == Ability) diff --git a/PKHeX.Core/PKM/PK6.cs b/PKHeX.Core/PKM/PK6.cs index 93ddde280..70783f23a 100644 --- a/PKHeX.Core/PKM/PK6.cs +++ b/PKHeX.Core/PKM/PK6.cs @@ -1,11 +1,12 @@ using System; using System.Collections.Generic; +using System.Numerics; using static System.Buffers.Binary.BinaryPrimitives; namespace PKHeX.Core; /// Generation 6 format. -public sealed class PK6 : G6PKM, IRibbonSetEvent3, IRibbonSetEvent4, IRibbonSetCommon3, IRibbonSetCommon4, IRibbonSetCommon6, IRibbonSetMemory6, +public sealed class PK6 : G6PKM, IRibbonSetEvent3, IRibbonSetEvent4, IRibbonSetCommon3, IRibbonSetCommon4, IRibbonSetCommon6, IRibbonSetMemory6, IRibbonSetRibbons, IContestStats, IGeoTrack, ISuperTrain, IFormArgument, ITrainerMemories, IAffection, IGroundTile { private static readonly ushort[] Unused = @@ -16,7 +17,7 @@ public sealed class PK6 : G6PKM, IRibbonSetEvent3, IRibbonSetEvent4, IRibbonSetC public override IReadOnlyList ExtraBytes => Unused; public override EntityContext Context => EntityContext.Gen6; - public override PersonalInfo PersonalInfo => PersonalTable.AO.GetFormEntry(Species, Form); + public override PersonalInfo6AO PersonalInfo => PersonalTable.AO.GetFormEntry(Species, Form); public PK6() : base(PokeCrypto.SIZE_6PARTY) { } public PK6(byte[] data) : base(DecryptParty(data)) { } @@ -28,7 +29,7 @@ public sealed class PK6 : G6PKM, IRibbonSetEvent3, IRibbonSetEvent4, IRibbonSetC return data; } - public override PKM Clone() => new PK6((byte[])Data.Clone()); + public override PK6 Clone() => new((byte[])Data.Clone()); // Structure #region Block A @@ -62,16 +63,22 @@ public sealed class PK6 : G6PKM, IRibbonSetEvent3, IRibbonSetEvent4, IRibbonSetC set => WriteUInt16LittleEndian(Data.AsSpan(0x0A), (ushort)value); } - public override int TID + public override uint ID32 { - get => ReadUInt16LittleEndian(Data.AsSpan(0x0C)); - set => WriteUInt16LittleEndian(Data.AsSpan(0x0C), (ushort)value); + get => ReadUInt32LittleEndian(Data.AsSpan(0x0C)); + set => WriteUInt32LittleEndian(Data.AsSpan(0x0C), value); } - public override int SID + public override ushort TID16 + { + get => ReadUInt16LittleEndian(Data.AsSpan(0x0C)); + set => WriteUInt16LittleEndian(Data.AsSpan(0x0C), value); + } + + public override ushort SID16 { get => ReadUInt16LittleEndian(Data.AsSpan(0x0E)); - set => WriteUInt16LittleEndian(Data.AsSpan(0x0E), (ushort)value); + set => WriteUInt16LittleEndian(Data.AsSpan(0x0E), value); } public override uint EXP @@ -215,12 +222,14 @@ public sealed class PK6 : G6PKM, IRibbonSetEvent3, IRibbonSetEvent4, IRibbonSetC public bool Dist8 { get => (DistByte & (1 << 7)) == 1 << 7; set => DistByte = (byte)((DistByte & ~(1 << 7)) | (value ? 1 << 7 : 0)); } public uint FormArgument { get => ReadUInt32LittleEndian(Data.AsSpan(0x3C)); set => WriteUInt32LittleEndian(Data.AsSpan(0x3C), value); } public byte FormArgumentMaximum { get => (byte)FormArgument; set => FormArgument = value & 0xFFu; } + + public int RibbonCount => BitOperations.PopCount(ReadUInt64LittleEndian(Data.AsSpan(0x30)) & 0b00000000_00000000__00111111_11111111__11111111_11111111__11111111_11111111); #endregion #region Block B public override string Nickname { get => StringConverter6.GetString(Nickname_Trash); - set => StringConverter6.SetString(Nickname_Trash, value.AsSpan(), 12, StringConverterOption.None); + set => StringConverter6.SetString(Nickname_Trash, value, 12, StringConverterOption.None); } public override ushort Move1 @@ -297,7 +306,7 @@ public sealed class PK6 : G6PKM, IRibbonSetEvent3, IRibbonSetEvent4, IRibbonSetC public override string HT_Name { get => StringConverter6.GetString(HT_Trash); - set => StringConverter6.SetString(HT_Trash, value.AsSpan(), 12, StringConverterOption.None); + set => StringConverter6.SetString(HT_Trash, value, 12, StringConverterOption.None); } public override int HT_Gender { get => Data[0x92]; set => Data[0x92] = (byte)value; } public override int CurrentHandler { get => Data[0x93]; set => Data[0x93] = (byte)value; } @@ -333,7 +342,7 @@ public sealed class PK6 : G6PKM, IRibbonSetEvent3, IRibbonSetEvent4, IRibbonSetC public override string OT_Name { get => StringConverter6.GetString(OT_Trash); - set => StringConverter6.SetString(OT_Trash, value.AsSpan(), 12, StringConverterOption.None); + set => StringConverter6.SetString(OT_Trash, value, 12, StringConverterOption.None); } public override int OT_Friendship { get => Data[0xCA]; set => Data[0xCA] = (byte)value; } public byte OT_Affection { get => Data[0xCB]; set => Data[0xCB] = value; } @@ -374,23 +383,7 @@ public sealed class PK6 : G6PKM, IRibbonSetEvent3, IRibbonSetEvent4, IRibbonSetC public override int Stat_SPD { get => ReadUInt16LittleEndian(Data.AsSpan(0xFC)); set => WriteUInt16LittleEndian(Data.AsSpan(0xFC), (ushort)value); } #endregion - public int SuperTrainingMedalCount(int maxCount = 30) - { - uint value = SuperTrainBitFlags >> 2; -#if NET6_0_OR_GREATER - return System.Numerics.BitOperations.PopCount(value); -#else - int TrainCount = 0; - for (int i = 0; i < maxCount; i++) - { - if ((value & 1) != 0) - TrainCount++; - value >>= 1; - } - - return TrainCount; -#endif - } + public int SuperTrainingMedalCount(int maxCount = 30) => BitOperations.PopCount(SuperTrainBitFlags >> 2); public bool IsUntradedEvent6 => Geo1_Country == 0 && Geo1_Region == 0 && Met_Location / 10000 == 4 && Gen6; @@ -421,7 +414,7 @@ public sealed class PK6 : G6PKM, IRibbonSetEvent3, IRibbonSetEvent4, IRibbonSetC protected override bool TradeOT(ITrainerInfo tr) { // Check to see if the OT matches the SAV's OT info. - if (!(tr.TID == TID && tr.SID == SID && tr.Gender == OT_Gender && tr.OT == OT_Name)) + if (!(tr.ID32 == ID32 && tr.Gender == OT_Gender && tr.OT == OT_Name)) return false; CurrentHandler = 0; diff --git a/PKHeX.Core/PKM/PK7.cs b/PKHeX.Core/PKM/PK7.cs index fe47c7f10..9dda01197 100644 --- a/PKHeX.Core/PKM/PK7.cs +++ b/PKHeX.Core/PKM/PK7.cs @@ -1,11 +1,12 @@ using System; using System.Collections.Generic; +using System.Numerics; using static System.Buffers.Binary.BinaryPrimitives; namespace PKHeX.Core; /// Generation 7 format. -public sealed class PK7 : G6PKM, IRibbonSetEvent3, IRibbonSetEvent4, IRibbonSetCommon3, IRibbonSetCommon4, IRibbonSetCommon6, IRibbonSetMemory6, IRibbonSetCommon7, +public sealed class PK7 : G6PKM, IRibbonSetEvent3, IRibbonSetEvent4, IRibbonSetCommon3, IRibbonSetCommon4, IRibbonSetCommon6, IRibbonSetMemory6, IRibbonSetCommon7, IRibbonSetRibbons, IContestStats, IHyperTrain, IGeoTrack, ISuperTrain, IFormArgument, ITrainerMemories, IAffection { private static readonly ushort[] Unused = @@ -17,7 +18,7 @@ public sealed class PK7 : G6PKM, IRibbonSetEvent3, IRibbonSetEvent4, IRibbonSetC public override IReadOnlyList ExtraBytes => Unused; public override EntityContext Context => EntityContext.Gen7; - public override PersonalInfo PersonalInfo => PersonalTable.USUM.GetFormEntry(Species, Form); + public override PersonalInfo7 PersonalInfo => PersonalTable.USUM.GetFormEntry(Species, Form); public PK7() : base(PokeCrypto.SIZE_6PARTY) { } public PK7(byte[] data) : base(DecryptParty(data)) { } @@ -29,7 +30,7 @@ public sealed class PK7 : G6PKM, IRibbonSetEvent3, IRibbonSetEvent4, IRibbonSetC return data; } - public override PKM Clone() => new PK7((byte[])Data.Clone()); + public override PK7 Clone() => new((byte[])Data.Clone()); // Structure #region Block A @@ -63,16 +64,22 @@ public sealed class PK7 : G6PKM, IRibbonSetEvent3, IRibbonSetEvent4, IRibbonSetC set => WriteUInt16LittleEndian(Data.AsSpan(0x0A), (ushort)value); } - public override int TID + public override uint ID32 { - get => ReadUInt16LittleEndian(Data.AsSpan(0x0C)); - set => WriteUInt16LittleEndian(Data.AsSpan(0x0C), (ushort)value); + get => ReadUInt32LittleEndian(Data.AsSpan(0x0C)); + set => WriteUInt32LittleEndian(Data.AsSpan(0x0C), value); } - public override int SID + public override ushort TID16 + { + get => ReadUInt16LittleEndian(Data.AsSpan(0x0C)); + set => WriteUInt16LittleEndian(Data.AsSpan(0x0C), value); + } + + public override ushort SID16 { get => ReadUInt16LittleEndian(Data.AsSpan(0x0E)); - set => WriteUInt16LittleEndian(Data.AsSpan(0x0E), (ushort)value); + set => WriteUInt16LittleEndian(Data.AsSpan(0x0E), value); } public override uint EXP @@ -227,6 +234,8 @@ public sealed class PK7 : G6PKM, IRibbonSetEvent3, IRibbonSetEvent4, IRibbonSetC public byte FormArgumentRemain { get => (byte)FormArgument; set => FormArgument = (FormArgument & ~0xFFu) | value; } public byte FormArgumentElapsed { get => (byte)(FormArgument >> 8); set => FormArgument = (FormArgument & ~0xFF00u) | (uint)(value << 8); } public byte FormArgumentMaximum { get => (byte)(FormArgument >> 16); set => FormArgument = (FormArgument & ~0xFF0000u) | (uint)(value << 16); } + + public int RibbonCount => BitOperations.PopCount(ReadUInt64LittleEndian(Data.AsSpan(0x30)) & 0b00000000_00000011__11111111_11111111__11111111_11111111__11111111_11111111); #endregion #region Block B public override string Nickname @@ -239,11 +248,11 @@ public sealed class PK7 : G6PKM, IRibbonSetEvent3, IRibbonSetEvent4, IRibbonSetC int lang = SpeciesName.GetSpeciesNameLanguage(Species, Language, value, 7); if (lang is (int)LanguageID.ChineseS or (int)LanguageID.ChineseT) { - StringConverter7.SetString(Nickname_Trash, value.AsSpan(), 12, lang, StringConverterOption.None, chinese: true); + StringConverter7.SetString(Nickname_Trash, value, 12, lang, StringConverterOption.None, chinese: true); return; } } - StringConverter7.SetString(Nickname_Trash, value.AsSpan(), 12, 0, StringConverterOption.None); + StringConverter7.SetString(Nickname_Trash, value, 12, 0, StringConverterOption.None); } } @@ -321,7 +330,7 @@ public sealed class PK7 : G6PKM, IRibbonSetEvent3, IRibbonSetEvent4, IRibbonSetC public override string HT_Name { get => StringConverter7.GetString(HT_Trash); - set => StringConverter7.SetString(HT_Trash, value.AsSpan(), 12, 0, StringConverterOption.None); + set => StringConverter7.SetString(HT_Trash, value, 12, 0, StringConverterOption.None); } public override int HT_Gender { get => Data[0x92]; set => Data[0x92] = (byte)value; } @@ -358,7 +367,7 @@ public sealed class PK7 : G6PKM, IRibbonSetEvent3, IRibbonSetEvent4, IRibbonSetC public override string OT_Name { get => StringConverter7.GetString(OT_Trash); - set => StringConverter7.SetString(OT_Trash, value.AsSpan(), 12, 0, StringConverterOption.None); + set => StringConverter7.SetString(OT_Trash, value, 12, 0, StringConverterOption.None); } public override int OT_Friendship { get => Data[0xCA]; set => Data[0xCA] = (byte)value; } @@ -407,23 +416,7 @@ public sealed class PK7 : G6PKM, IRibbonSetEvent3, IRibbonSetEvent4, IRibbonSetC public override int Stat_SPD { get => ReadUInt16LittleEndian(Data.AsSpan(0xFC)); set => WriteUInt16LittleEndian(Data.AsSpan(0xFC), (ushort)value); } #endregion - public int SuperTrainingMedalCount(int maxCount = 30) - { - uint value = SuperTrainBitFlags >> 2; -#if NET6_0_OR_GREATER - return System.Numerics.BitOperations.PopCount(value); -#else - int TrainCount = 0; - for (int i = 0; i < maxCount; i++) - { - if ((value & 1) != 0) - TrainCount++; - value >>= 1; - } - - return TrainCount; -#endif - } + public int SuperTrainingMedalCount(int maxCount = 30) => BitOperations.PopCount(SuperTrainBitFlags >> 2); public bool IsUntradedEvent6 => Geo1_Country == 0 && Geo1_Region == 0 && Met_Location / 10000 == 4 && Gen6; @@ -474,7 +467,7 @@ public sealed class PK7 : G6PKM, IRibbonSetEvent3, IRibbonSetEvent4, IRibbonSetC protected override bool TradeOT(ITrainerInfo tr) { // Check to see if the OT matches the SAV's OT info. - if (!(tr.TID == TID && tr.SID == SID && tr.Gender == OT_Gender && tr.OT == OT_Name)) + if (!(tr.ID32 == ID32 && tr.Gender == OT_Gender && tr.OT == OT_Name)) return false; CurrentHandler = 0; @@ -513,8 +506,8 @@ public sealed class PK7 : G6PKM, IRibbonSetEvent3, IRibbonSetEvent4, IRibbonSetC { EncryptionConstant = EncryptionConstant, Species = Species, - TID = TID, - SID = SID, + TID16 = TID16, + SID16 = SID16, EXP = EXP, PID = PID, Ability = Ability, diff --git a/PKHeX.Core/PKM/PK8.cs b/PKHeX.Core/PKM/PK8.cs index eae5ffda5..d4f573e01 100644 --- a/PKHeX.Core/PKM/PK8.cs +++ b/PKHeX.Core/PKM/PK8.cs @@ -28,13 +28,14 @@ public sealed class PK8 : G8PKM }; public override IReadOnlyList ExtraBytes => Unused; - public override PersonalInfo PersonalInfo => PersonalTable.SWSH.GetFormEntry(Species, Form); + public override PersonalInfo8SWSH PersonalInfo => PersonalTable.SWSH.GetFormEntry(Species, Form); + public override IPermitRecord Permit => PersonalInfo; public override bool IsNative => SWSH; public override EntityContext Context => EntityContext.Gen8; public PK8() => AffixedRibbon = -1; // 00 would make it show Kalos Champion :) public PK8(byte[] data) : base(data) { } - public override PKM Clone() => new PK8((byte[])Data.Clone()); + public override PK8 Clone() => new((byte[])Data.Clone()); public void Trade(ITrainerInfo tr, int Day = 1, int Month = 1, int Year = 2015) { @@ -42,7 +43,7 @@ public sealed class PK8 : G8PKM { // Eggs do not have any modifications done if they are traded // Apply link trade data, only if it left the OT (ignore if dumped & imported, or cloned, etc) - if ((tr.TID != TID) || (tr.SID != SID) || (tr.Gender != OT_Gender) || (tr.OT != OT_Name)) + if ((tr.TID16 != TID16) || (tr.SID16 != SID16) || (tr.Gender != OT_Gender) || (tr.OT != OT_Name)) SetLinkTradeEgg(Day, Month, Year, Locations.LinkTrade6); return; } @@ -79,7 +80,7 @@ public sealed class PK8 : G8PKM private bool TradeOT(ITrainerInfo tr) { // Check to see if the OT matches the SAV's OT info. - if (!(tr.TID == TID && tr.SID == SID && tr.Gender == OT_Gender && tr.OT == OT_Name)) + if (!(tr.ID32 == ID32 && tr.Gender == OT_Gender && tr.OT == OT_Name)) return false; CurrentHandler = 0; diff --git a/PKHeX.Core/PKM/PK9.cs b/PKHeX.Core/PKM/PK9.cs index f372ac14c..12380c7d7 100644 --- a/PKHeX.Core/PKM/PK9.cs +++ b/PKHeX.Core/PKM/PK9.cs @@ -1,13 +1,14 @@ using System; using System.Collections.Generic; +using System.Numerics; using static System.Buffers.Binary.BinaryPrimitives; namespace PKHeX.Core; /// Generation 9 format. public sealed class PK9 : PKM, ISanityChecksum, ITeraType, IMoveReset, ITechRecord, IObedienceLevel, - IRibbonSetEvent3, IRibbonSetEvent4, IRibbonSetCommon3, IRibbonSetCommon4, IRibbonSetCommon6, IRibbonSetMemory6, IRibbonSetCommon7, IRibbonSetCommon8, IRibbonSetMark8, IRibbonSetAffixed, IRibbonSetCommon9, IRibbonSetMark9, - IContestStats, IHyperTrain, IScaledSize, IScaledSize3, IFavorite, IRibbonIndex, IHandlerLanguage, IFormArgument, IHomeTrack, IBattleVersion, ITrainerMemories + IContestStats, IHyperTrain, IScaledSize, IScaledSize3, IFavorite, IHandlerLanguage, IFormArgument, IHomeTrack, IBattleVersion, ITrainerMemories, + IRibbonIndex, IRibbonSetAffixed, IRibbonSetRibbons, IRibbonSetEvent3, IRibbonSetEvent4, IRibbonSetCommon3, IRibbonSetCommon4, IRibbonSetCommon6, IRibbonSetMemory6, IRibbonSetCommon7, IRibbonSetCommon8, IRibbonSetCommon9, IRibbonSetMarks, IRibbonSetMark8, IRibbonSetMark9 { private static readonly ushort[] Unused = { @@ -26,7 +27,8 @@ public sealed class PK9 : PKM, ISanityChecksum, ITeraType, IMoveReset, ITechReco }; public override IReadOnlyList ExtraBytes => Unused; - public override PersonalInfo PersonalInfo => PersonalTable.SV.GetFormEntry(Species, Form); + public override PersonalInfo9SV PersonalInfo => PersonalTable.SV.GetFormEntry(Species, Form); + public IPermitRecord Permit => PersonalInfo; public override bool IsNative => SWSH; public override EntityContext Context => EntityContext.Gen9; @@ -38,7 +40,7 @@ public sealed class PK9 : PKM, ISanityChecksum, ITeraType, IMoveReset, ITechReco } public PK9(byte[] data) : base(DecryptParty(data)) { } - public override PKM Clone() => new PK9((byte[])Data.Clone()); + public override PK9 Clone() => new((byte[])Data.Clone()); private static byte[] DecryptParty(byte[] data) { @@ -80,8 +82,8 @@ public sealed class PK9 : PKM, ISanityChecksum, ITeraType, IMoveReset, ITechReco public override int MaxStringLengthOT => 12; public override int MaxStringLengthNickname => 12; - public override int PSV => (int)(((PID >> 16) ^ (PID & 0xFFFF)) >> 4); - public override int TSV => (TID ^ SID) >> 4; + public override uint PSV => ((PID >> 16) ^ (PID & 0xFFFF)) >> 4; + public override uint TSV => (uint)(TID16 ^ SID16) >> 4; public override bool IsUntraded => Data[0xA8] == 0 && Data[0xA8 + 1] == 0 && (IsUnhatchedEgg || Format == Generation); // immediately terminated HT_Name data (\0) public bool IsUnhatchedEgg => Version == 0 && IsEgg; @@ -141,10 +143,12 @@ public sealed class PK9 : PKM, ISanityChecksum, ITeraType, IMoveReset, ITechReco // Structure #region Block A - public override ushort Species { get => ReadUInt16LittleEndian(Data.AsSpan(0x08)); set => WriteUInt16LittleEndian(Data.AsSpan(0x08), value); } + public ushort SpeciesInternal { get => ReadUInt16LittleEndian(Data.AsSpan(0x08)); set => WriteUInt16LittleEndian(Data.AsSpan(0x08), value); } + public override ushort Species { get => SpeciesConverter.GetNational9(SpeciesInternal); set => SpeciesInternal = SpeciesConverter.GetInternal9(value); } public override int HeldItem { get => ReadUInt16LittleEndian(Data.AsSpan(0x0A)); set => WriteUInt16LittleEndian(Data.AsSpan(0x0A), (ushort)value); } - public override int TID { get => ReadUInt16LittleEndian(Data.AsSpan(0x0C)); set => WriteUInt16LittleEndian(Data.AsSpan(0x0C), (ushort)value); } - public override int SID { get => ReadUInt16LittleEndian(Data.AsSpan(0x0E)); set => WriteUInt16LittleEndian(Data.AsSpan(0x0E), (ushort)value); } + public override uint ID32 { get => ReadUInt32LittleEndian(Data.AsSpan(0x0C)); set => WriteUInt32LittleEndian(Data.AsSpan(0x0C), value); } + public override ushort TID16 { get => ReadUInt16LittleEndian(Data.AsSpan(0x0C)); set => WriteUInt16LittleEndian(Data.AsSpan(0x0C), value); } + public override ushort SID16 { get => ReadUInt16LittleEndian(Data.AsSpan(0x0E)); set => WriteUInt16LittleEndian(Data.AsSpan(0x0E), value); } public override uint EXP { get => ReadUInt32LittleEndian(Data.AsSpan(0x10)); set => WriteUInt32LittleEndian(Data.AsSpan(0x10), value); } public override int Ability { get => ReadUInt16LittleEndian(Data.AsSpan(0x14)); set => WriteUInt16LittleEndian(Data.AsSpan(0x14), (ushort)value); } public override int AbilityNumber { get => Data[0x16] & 7; set => Data[0x16] = (byte)((Data[0x16] & ~7) | (value & 7)); } @@ -329,15 +333,16 @@ public sealed class PK9 : PKM, ISanityChecksum, ITeraType, IMoveReset, ITechReco public bool RIB47_6 { get => FlagUtil.GetFlag(Data, 0x47, 6); set => FlagUtil.SetFlag(Data, 0x47, 6, value); } public bool RIB47_7 { get => FlagUtil.GetFlag(Data, 0x47, 7); set => FlagUtil.SetFlag(Data, 0x47, 7, value); } - public bool HasMark() - { - var d = Data.AsSpan(); - if ((ReadUInt16LittleEndian(d[0x3A..]) & 0xFFE0) != 0) - return true; - if (ReadUInt32LittleEndian(d[0x40..]) != 0) - return true; - return (d[0x44] & 3) != 0; - } + public int RibbonCount => BitOperations.PopCount(ReadUInt64LittleEndian(Data.AsSpan(0x34)) & 0b00000000_00011111__11111111_11111111__11111111_11111111__11111111_11111111) + + BitOperations.PopCount(ReadUInt64LittleEndian(Data.AsSpan(0x40)) & 0b00000000_00000000__00000100_00011100__00000000_00000000__00000000_00000000); + public int MarkCount => BitOperations.PopCount(ReadUInt64LittleEndian(Data.AsSpan(0x34)) & 0b11111111_11100000__00000000_00000000__00000000_00000000__00000000_00000000) + + BitOperations.PopCount(ReadUInt64LittleEndian(Data.AsSpan(0x40)) & 0b00000000_00000000__00111011_11100011__11111111_11111111__11111111_11111111); + public int RibbonMarkCount => BitOperations.PopCount(ReadUInt64LittleEndian(Data.AsSpan(0x34)) & 0b11111111_11111111__11111111_11111111__11111111_11111111__11111111_11111111) + + BitOperations.PopCount(ReadUInt64LittleEndian(Data.AsSpan(0x40)) & 0b00000000_00000000__00111111_11111111__11111111_11111111__11111111_11111111); + + public bool HasMarkEncounter8 => BitOperations.PopCount(ReadUInt64LittleEndian(Data.AsSpan(0x34)) & 0b11111111_11100000__00000000_00000000__00000000_00000000__00000000_00000000) + + BitOperations.PopCount(ReadUInt64LittleEndian(Data.AsSpan(0x40)) & 0b00000000_00000000__00000000_00000011__11111111_11111111__11111111_11111111) != 0; + public bool HasMarkEncounter9 => (Data[0x45] & 0b00111000) != 0; public byte HeightScalar { get => Data[0x48]; set => Data[0x48] = value; } public byte WeightScalar { get => Data[0x49]; set => Data[0x49] = value; } @@ -350,7 +355,7 @@ public sealed class PK9 : PKM, ISanityChecksum, ITeraType, IMoveReset, ITechReco public override string Nickname { get => StringConverter8.GetString(Nickname_Trash); - set => StringConverter8.SetString(Nickname_Trash, value.AsSpan(), 12, StringConverterOption.None); + set => StringConverter8.SetString(Nickname_Trash, value, 12, StringConverterOption.None); } // 2 bytes for \0, automatically handled above @@ -397,7 +402,7 @@ public sealed class PK9 : PKM, ISanityChecksum, ITeraType, IMoveReset, ITechReco public override string HT_Name { get => StringConverter8.GetString(HT_Trash); - set => StringConverter8.SetString(HT_Trash, value.AsSpan(), 12, StringConverterOption.None); + set => StringConverter8.SetString(HT_Trash, value, 12, StringConverterOption.None); } public override int HT_Gender { get => Data[0xC2]; set => Data[0xC2] = (byte)value; } @@ -426,7 +431,7 @@ public sealed class PK9 : PKM, ISanityChecksum, ITeraType, IMoveReset, ITechReco public override string OT_Name { get => StringConverter8.GetString(OT_Trash); - set => StringConverter8.SetString(OT_Trash, value.AsSpan(), 12, StringConverterOption.None); + set => StringConverter8.SetString(OT_Trash, value, 12, StringConverterOption.None); } public override int OT_Friendship { get => Data[0x112]; set => Data[0x112] = (byte)value; } @@ -465,8 +470,6 @@ public sealed class PK9 : PKM, ISanityChecksum, ITeraType, IMoveReset, ITechReco internal const int COUNT_RECORD = 200; // Up to 200 TM flags, but not all are used. private const int RecordLength = COUNT_RECORD / 8; internal Span RecordFlags => Data.AsSpan(RecordStart, RecordLength); - public int RecordCountTotal => COUNT_RECORD; - public int RecordCountUsed => PersonalInfo9SV.CountTM; public bool GetMoveRecordFlag(int index) { @@ -500,9 +503,6 @@ public sealed class PK9 : PKM, ISanityChecksum, ITeraType, IMoveReset, ITechReco public override int Stat_SPD { get => ReadUInt16LittleEndian(Data.AsSpan(0x154)); set => WriteUInt16LittleEndian(Data.AsSpan(0x154), (ushort)value); } #endregion - public ReadOnlySpan TechRecordPermitFlags => PersonalInfo.TMHM.AsSpan(); - public ReadOnlySpan TechRecordPermitIndexes => LearnSource9SV.TM_SV.AsSpan(); - public override int MarkingCount => 6; public override int GetMarking(int index) @@ -592,7 +592,7 @@ public sealed class PK9 : PKM, ISanityChecksum, ITeraType, IMoveReset, ITechReco private bool TradeOT(ITrainerInfo tr) { // Check to see if the OT matches the SAV's OT info. - if (!(tr.TID == TID && tr.SID == SID && tr.Gender == OT_Gender && tr.OT == OT_Name)) + if (!(tr.ID32 == ID32 && tr.Gender == OT_Gender && tr.OT == OT_Name)) return false; CurrentHandler = 0; diff --git a/PKHeX.Core/PKM/PKM.cs b/PKHeX.Core/PKM/PKM.cs index bf35e32d4..36ccbe56e 100644 --- a/PKHeX.Core/PKM/PKM.cs +++ b/PKHeX.Core/PKM/PKM.cs @@ -1,14 +1,17 @@ using System; using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; using System.Linq; using static PKHeX.Core.GameVersion; +using static System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes; namespace PKHeX.Core; /// /// Object representing a 's data and derived properties. /// -public abstract class PKM : ISpeciesForm, ITrainerID, IGeneration, IShiny, ILangNick, IGameValueLimit, INature +[DynamicallyAccessedMembers(PublicProperties | NonPublicProperties | PublicParameterlessConstructor)] +public abstract class PKM : ISpeciesForm, ITrainerID32, IGeneration, IShiny, ILangNick, IGameValueLimit, INature, IFatefulEncounter { /// /// Valid file extensions that represent data, without the leading '.' @@ -44,6 +47,7 @@ public abstract class PKM : ISpeciesForm, ITrainerID, IGeneration, IShiny, ILang protected abstract byte[] Encrypt(); public abstract EntityContext Context { get; } public int Format => Context.Generation(); + public TrainerIDFormat TrainerIDDisplayFormat => this.GetTrainerIDFormat(); private byte[] Write() { @@ -64,12 +68,19 @@ public abstract class PKM : ISpeciesForm, ITrainerID, IGeneration, IShiny, ILang public abstract bool IsEgg { get; set; } public abstract bool IsNicknamed { get; set; } public abstract uint EXP { get; set; } - public abstract int TID { get; set; } + public abstract ushort TID16 { get; set; } + public abstract ushort SID16 { get; set; } public abstract string OT_Name { get; set; } public abstract int OT_Gender { get; set; } public abstract int Ball { get; set; } public abstract int Met_Level { get; set; } + // Aliases of ID32 + public uint TrainerTID7 { get => this.GetTrainerTID7(); set => this.SetTrainerTID7(value); } + public uint TrainerSID7 { get => this.GetTrainerSID7(); set => this.SetTrainerSID7(value); } + public uint DisplayTID { get => this.GetDisplayTID(); set => this.SetDisplayTID(value); } + public uint DisplaySID { get => this.GetDisplaySID(); set => this.SetDisplaySID(value); } + // Battle public abstract ushort Move1 { get; set; } public abstract ushort Move2 { get; set; } @@ -107,7 +118,7 @@ public abstract class PKM : ISpeciesForm, ITrainerID, IGeneration, IShiny, ILang // Hidden Properties public abstract int Version { get; set; } - public abstract int SID { get; set; } + public abstract uint ID32 { get; set; } public abstract int PKRS_Strain { get; set; } public abstract int PKRS_Days { get; set; } @@ -117,8 +128,8 @@ public abstract class PKM : ISpeciesForm, ITrainerID, IGeneration, IShiny, ILang // Misc Properties public abstract int Language { get; set; } public abstract bool FatefulEncounter { get; set; } - public abstract int TSV { get; } - public abstract int PSV { get; } + public abstract uint TSV { get; } + public abstract uint PSV { get; } public abstract int Characteristic { get; } public abstract int MarkValue { get; set; } public abstract int Met_Location { get; set; } @@ -148,14 +159,14 @@ public abstract class PKM : ISpeciesForm, ITrainerID, IGeneration, IShiny, ILang /// Not all types support the property. In these cases, this property will return null. /// If null is assigned to this property, it will be cleared. /// - public DateTime? MetDate + public DateOnly? MetDate { get { // Check to see if date is valid if (!DateUtil.IsDateValid(2000 + Met_Year, Met_Month, Met_Day)) return null; - return new DateTime(2000 + Met_Year, Met_Month, Met_Day); + return new DateOnly(2000 + Met_Year, Met_Month, Met_Day); } set { @@ -191,14 +202,14 @@ public abstract class PKM : ISpeciesForm, ITrainerID, IGeneration, IShiny, ILang /// Not all types support the property. In these cases, this property will return null. /// If null is assigned to this property, it will be cleared. /// - public DateTime? EggMetDate + public DateOnly? EggMetDate { get { // Check to see if date is valid if (!DateUtil.IsDateValid(2000 + Egg_Year, Egg_Month, Egg_Day)) return null; - return new DateTime(2000 + Egg_Year, Egg_Month, Egg_Day); + return new DateOnly(2000 + Egg_Year, Egg_Month, Egg_Day); } set { @@ -244,45 +255,16 @@ public abstract class PKM : ISpeciesForm, ITrainerID, IGeneration, IShiny, ILang // Derived public virtual int SpriteItem => HeldItem; public virtual bool IsShiny => TSV == PSV; - public int TrainerID7 { get => (int)((uint)(TID | (SID << 16)) % 1000000); set => SetID7(TrainerSID7, value); } - public int TrainerSID7 { get => (int)((uint)(TID | (SID << 16)) / 1000000); set => SetID7(value, TrainerID7); } - public uint ShinyXor + public ushort ShinyXor { get { - var pid = PID; - var upper = (pid >> 16) ^ (uint)SID; - return (pid & 0xFFFF) ^ (uint)TID ^ upper; + var tmp = ID32 ^ PID; + return (ushort)(tmp ^ (tmp >> 16)); } } - private bool IsDisplay7 => Generation switch - { - >= 7 => true, - -1 when IsEgg && this is PK9 => true, - _ => false, - }; - - public int DisplayTID - { - get => IsDisplay7 ? TrainerID7 : TID; - set { if (IsDisplay7) TrainerID7 = value; else TID = value; } - } - - public int DisplaySID - { - get => IsDisplay7 ? TrainerSID7 : SID; - set { if (IsDisplay7) TrainerSID7 = value; else SID = value; } - } - - private void SetID7(int sid7, int tid7) - { - var oid = (sid7 * 1_000_000) + (tid7 % 1_000_000); - TID = (ushort)oid; - SID = oid >> 16; - } - public bool E => Version == (int)GameVersion.E; public bool FRLG => Version is (int)FR or (int)LG; public bool Pt => (int)GameVersion.Pt == Version; @@ -566,7 +548,7 @@ public abstract class PKM : ISpeciesForm, ITrainerID, IGeneration, IShiny, ILang public virtual bool IsGenderValid() { int gender = Gender; - int gv = PersonalInfo.Gender; + var gv = PersonalInfo.Gender; if (gv == PersonalInfo.RatioMagicGenderless) return gender == 2; if (gv == PersonalInfo.RatioMagicFemale) @@ -830,22 +812,23 @@ public abstract class PKM : ISpeciesForm, ITrainerID, IGeneration, IShiny, ILang } /// - /// Applies a shiny to the . + /// Applies a shiny to the . /// public void SetShinySID(Shiny shiny = Shiny.Random) { if (IsShiny && shiny.IsValid(this)) return; - var xor = TID ^ (PID >> 16) ^ (PID & 0xFFFF); - var bits = shiny switch + ushort bits = shiny switch { Shiny.AlwaysSquare => 0, Shiny.AlwaysStar => 1, - _ => Util.Rand.Next(8), + _ => (ushort)Util.Rand.Next(8), }; - SID = (int)xor ^ bits; + var current = ShinyXor; + current ^= bits; + SID16 ^= current; } /// @@ -965,10 +948,17 @@ public abstract class PKM : ISpeciesForm, ITrainerID, IGeneration, IShiny, ILang /// Count of IVs that should be max. public int GetFlawlessIVCount() { - if (Generation >= 6) + int gen = Generation; + if (gen >= 6) { var species = Species; - if (Legal.Legends.Contains(species) || Legal.SubLegends.Contains(species)) + if (Legal.Mythicals.Contains(species)) + return 3; + if (Legal.Legends.Contains(species)) + return 3; + if (Legal.SubLegends.Contains(species)) + return 3; + if (gen <= 7 && Legal.IsUltraBeast(species)) return 3; } if (XY) diff --git a/PKHeX.Core/PKM/RK4.cs b/PKHeX.Core/PKM/RK4.cs index c174f8dc2..85b4e3f44 100644 --- a/PKHeX.Core/PKM/RK4.cs +++ b/PKHeX.Core/PKM/RK4.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Numerics; using static System.Buffers.Binary.BinaryPrimitives; namespace PKHeX.Core; @@ -20,7 +21,7 @@ public sealed class RK4 : G4PKM public override int SIZE_PARTY => PokeCrypto.SIZE_4RSTORED; public override int SIZE_STORED => PokeCrypto.SIZE_4RSTORED; public override EntityContext Context => EntityContext.Gen4; - public override PersonalInfo PersonalInfo => PersonalTable.Pt.GetFormEntry(Species, Form); + public override PersonalInfo4 PersonalInfo => PersonalTable.Pt.GetFormEntry(Species, Form); public RK4() : base(PokeCrypto.SIZE_4RSTORED) { } public RK4(byte[] data) : base(Decrypt(data)) { } @@ -32,7 +33,7 @@ public sealed class RK4 : G4PKM return data; } - public override PKM Clone() => new RK4((byte[])Data.Clone()); + public override RK4 Clone() => new((byte[])Data.Clone()); // Structure public override uint PID { get => ReadUInt32LittleEndian(Data.AsSpan(0x00)); set => WriteUInt32LittleEndian(Data.AsSpan(0x00), value); } @@ -42,8 +43,9 @@ public sealed class RK4 : G4PKM #region Block A public override ushort Species { get => ReadUInt16LittleEndian(Data.AsSpan(0x08)); set => WriteUInt16LittleEndian(Data.AsSpan(0x08), value); } public override int HeldItem { get => ReadUInt16LittleEndian(Data.AsSpan(0x0A)); set => WriteUInt16LittleEndian(Data.AsSpan(0x0A), (ushort)value); } - public override int TID { get => ReadUInt16LittleEndian(Data.AsSpan(0x0C)); set => WriteUInt16LittleEndian(Data.AsSpan(0x0C), (ushort)value); } - public override int SID { get => ReadUInt16LittleEndian(Data.AsSpan(0x0E)); set => WriteUInt16LittleEndian(Data.AsSpan(0x0E), (ushort)value); } + public override uint ID32 { get => ReadUInt32LittleEndian(Data.AsSpan(0x0C)); set => WriteUInt32LittleEndian(Data.AsSpan(0x0C), value); } + public override ushort TID16 { get => ReadUInt16LittleEndian(Data.AsSpan(0x0C)); set => WriteUInt16LittleEndian(Data.AsSpan(0x0C), value); } + public override ushort SID16 { get => ReadUInt16LittleEndian(Data.AsSpan(0x0E)); set => WriteUInt16LittleEndian(Data.AsSpan(0x0E), value); } public override uint EXP { get => ReadUInt32LittleEndian(Data.AsSpan(0x10)); set => WriteUInt32LittleEndian(Data.AsSpan(0x10), value); } public override int OT_Friendship { get => Data[0x14]; set => Data[0x14] = (byte)value; } public override int Ability { get => Data[0x15]; set => Data[0x15] = (byte)value; } @@ -98,6 +100,10 @@ public sealed class RK4 : G4PKM public override bool RIB3_5 { get => (RIB3 & (1 << 5)) == 1 << 5; set => RIB3 = (byte)((RIB3 & ~(1 << 5)) | (value ? 1 << 5 : 0)); } // Unused public override bool RIB3_6 { get => (RIB3 & (1 << 6)) == 1 << 6; set => RIB3 = (byte)((RIB3 & ~(1 << 6)) | (value ? 1 << 6 : 0)); } // Unused public override bool RIB3_7 { get => (RIB3 & (1 << 7)) == 1 << 7; set => RIB3 = (byte)((RIB3 & ~(1 << 7)) | (value ? 1 << 7 : 0)); } // Unused + + public override int RibbonCount => BitOperations.PopCount(ReadUInt32LittleEndian(Data.AsSpan(0x30)) & 0b00001111_11111111__11111111_11111111) + + BitOperations.PopCount(ReadUInt32LittleEndian(Data.AsSpan(0x3C))) + + BitOperations.PopCount(ReadUInt32LittleEndian(Data.AsSpan(0x60)) & 0b00000000_00001111__11111111_11111111); #endregion #region Block B @@ -183,7 +189,7 @@ public sealed class RK4 : G4PKM public override string Nickname { get => StringConverter4.GetString(Nickname_Trash); - set => StringConverter4.SetString(Nickname_Trash, value.AsSpan(), 10, StringConverterOption.None); + set => StringConverter4.SetString(Nickname_Trash, value, 10, StringConverterOption.None); } // 0x5E unused @@ -231,7 +237,7 @@ public sealed class RK4 : G4PKM public override string OT_Name { get => StringConverter4.GetString(OT_Trash); - set => StringConverter4.SetString(OT_Trash, value.AsSpan(), 7, StringConverterOption.None); + set => StringConverter4.SetString(OT_Trash, value, 7, StringConverterOption.None); } public override int Egg_Year { get => Data[0x78]; set => Data[0x78] = (byte)value; } @@ -311,7 +317,7 @@ public sealed class RK4 : G4PKM public override string HT_Name { get => StringConverter4.GetString(HT_Trash); - set => StringConverter4.SetString(HT_Trash, value.AsSpan(), 7, StringConverterOption.None); + set => StringConverter4.SetString(HT_Trash, value, 7, StringConverterOption.None); } #endregion diff --git a/PKHeX.Core/PKM/SK2.cs b/PKHeX.Core/PKM/SK2.cs index 24aa93376..9efcc905d 100644 --- a/PKHeX.Core/PKM/SK2.cs +++ b/PKHeX.Core/PKM/SK2.cs @@ -6,7 +6,7 @@ namespace PKHeX.Core; /// Generation 2 format for . public sealed class SK2 : GBPKM, ICaughtData2 { - public override PersonalInfo PersonalInfo => PersonalTable.C[Species]; + public override PersonalInfo2 PersonalInfo => PersonalTable.C[Species]; public override bool Valid => Species <= 252; @@ -25,7 +25,7 @@ public sealed class SK2 : GBPKM, ICaughtData2 public SK2(byte[] data) : this(data, IsJapanese(data)) { } public SK2(byte[] data, bool jp) : base(data) => IsEncodingJapanese = jp; - public override PKM Clone() => new SK2((byte[])Data.Clone(), Japanese) + public override SK2 Clone() => new((byte[])Data.Clone(), Japanese) { IsEgg = IsEgg, }; @@ -40,7 +40,7 @@ public sealed class SK2 : GBPKM, ICaughtData2 public override ushort Move2 { get => Data[3]; set => Data[3] = (byte)value; } public override ushort Move3 { get => Data[4]; set => Data[4] = (byte)value; } public override ushort Move4 { get => Data[5]; set => Data[5] = (byte)value; } - public override int TID { get => ReadUInt16BigEndian(Data.AsSpan(6)); set => WriteUInt16BigEndian(Data.AsSpan(6), (ushort)value); } + public override ushort TID16 { get => ReadUInt16BigEndian(Data.AsSpan(6)); set => WriteUInt16BigEndian(Data.AsSpan(6), value); } public override uint EXP { get => ReadUInt32BigEndian(Data.AsSpan(8)); set => WriteUInt32BigEndian(Data.AsSpan(8), value); } // not 3 bytes like in PK2 public override int EV_HP { get => ReadUInt16BigEndian(Data.AsSpan(0x0C)); set => WriteUInt16BigEndian(Data.AsSpan(0x0C), (ushort)value); } public override int EV_ATK { get => ReadUInt16BigEndian(Data.AsSpan(0x0E)); set => WriteUInt16BigEndian(Data.AsSpan(0x0E), (ushort)value); } @@ -94,7 +94,7 @@ public sealed class SK2 : GBPKM, ICaughtData2 public override string Nickname { get => StringConverter12.GetString(Nickname_Trash, Japanese); - set => StringConverter12.SetString(Nickname_Trash, value.AsSpan(), 12, Japanese, StringConverterOption.None); + set => StringConverter12.SetString(Nickname_Trash, value, 12, Japanese, StringConverterOption.None); } public override string OT_Name @@ -107,7 +107,7 @@ public sealed class SK2 : GBPKM, ICaughtData2 OT_Trash.Clear(); return; } - StringConverter12.SetString(OT_Trash, value.AsSpan(), StringLength, Japanese, StringConverterOption.None); + StringConverter12.SetString(OT_Trash, value, StringLength, Japanese, StringConverterOption.None); } } @@ -135,7 +135,7 @@ public sealed class SK2 : GBPKM, ICaughtData2 { var name = SpeciesName.GetSpeciesNameGeneration(Species, language, 2); byte[] data = new byte[name.Length]; - StringConverter12.SetString(data, name.AsSpan(), data.Length, Japanese, StringConverterOption.Clear50); + StringConverter12.SetString(data, name, data.Length, Japanese, StringConverterOption.Clear50); return data; } @@ -160,7 +160,7 @@ public sealed class SK2 : GBPKM, ICaughtData2 Move2 = Move2, Move3 = Move3, Move4 = Move4, - TID = TID, + TID16 = TID16, EXP = EXP, EV_HP = EV_HP, EV_ATK = EV_ATK, diff --git a/PKHeX.Core/PKM/Searching/SearchSettings.cs b/PKHeX.Core/PKM/Searching/SearchSettings.cs index 491b7f0e3..8f4ceb959 100644 --- a/PKHeX.Core/PKM/Searching/SearchSettings.cs +++ b/PKHeX.Core/PKM/Searching/SearchSettings.cs @@ -12,7 +12,7 @@ public sealed class SearchSettings { public int Format { get; init; } public int Generation { get; init; } - public ushort Species { get; init; } + public required ushort Species { get; init; } public int Ability { get; init; } = -1; public int Nature { get; init; } = -1; public int Item { get; init; } = -1; @@ -32,8 +32,8 @@ public sealed class SearchSettings public int EVType { get; init; } public CloneDetectionMethod SearchClones { get; set; } - public IList BatchInstructions { get; init; } = Array.Empty(); - private StringInstruction[] BatchFilters { get; set; } = Array.Empty(); + public string BatchInstructions { get; init; } = string.Empty; + private IReadOnlyList BatchFilters { get; set; } = Array.Empty(); public readonly List Moves = new(); @@ -61,7 +61,7 @@ public sealed class SearchSettings /// Search results that match all criteria public IEnumerable Search(IEnumerable list) { - BatchFilters = StringInstruction.GetFilters(BatchInstructions).ToArray(); + BatchFilters = StringInstruction.GetFilters(BatchInstructions); var result = SearchInner(list); if (SearchClones != CloneDetectionMethod.None) @@ -80,7 +80,7 @@ public sealed class SearchSettings /// Search results that match all criteria public IEnumerable Search(IEnumerable list) { - BatchFilters = StringInstruction.GetFilters(BatchInstructions).ToArray(); + BatchFilters = StringInstruction.GetFilters(BatchInstructions); var result = SearchInner(list); if (SearchClones != CloneDetectionMethod.None) @@ -175,7 +175,7 @@ public sealed class SearchSettings return false; if (SearchLegal != null && new LegalityAnalysis(pk).Valid != SearchLegal) return false; - if (BatchFilters.Length != 0 && !SearchUtil.SatisfiesFilterBatchInstruction(pk, BatchFilters)) + if (BatchFilters.Count != 0 && !SearchUtil.SatisfiesFilterBatchInstruction(pk, BatchFilters)) return false; return true; diff --git a/PKHeX.Core/PKM/Shared/G3PKM.cs b/PKHeX.Core/PKM/Shared/G3PKM.cs index 0ed7d1447..236b11406 100644 --- a/PKHeX.Core/PKM/Shared/G3PKM.cs +++ b/PKHeX.Core/PKM/Shared/G3PKM.cs @@ -5,11 +5,13 @@ namespace PKHeX.Core; /// /// Generation 3 Base Class /// -public abstract class G3PKM : PKM, IRibbonSetEvent3, IRibbonSetCommon3, IRibbonSetUnique3, IRibbonSetOnly3, IContestStats +public abstract class G3PKM : PKM, IRibbonSetEvent3, IRibbonSetCommon3, IRibbonSetUnique3, IRibbonSetOnly3, IRibbonSetRibbons, IContestStats { protected G3PKM(byte[] data) : base(data) { } protected G3PKM(int size) : base(size) { } + public abstract override PersonalInfo3 PersonalInfo { get; } + // Maximums public sealed override ushort MaxMoveID => Legal.MaxMoveID_3; public sealed override ushort MaxSpeciesID => Legal.MaxSpeciesID_3; @@ -23,11 +25,11 @@ public abstract class G3PKM : PKM, IRibbonSetEvent3, IRibbonSetCommon3, IRibbonS public sealed override int MaxStringLengthNickname => 10; // Generated Attributes - public sealed override int PSV => (int)(((PID >> 16) ^ (PID & 0xFFFF)) >> 3); - public sealed override int TSV => (TID ^ SID) >> 3; + public sealed override uint PSV => ((PID >> 16) ^ (PID & 0xFFFF)) >> 3; + public sealed override uint TSV => (uint)(TID16 ^ SID16) >> 3; public sealed override bool Japanese => Language == (int)LanguageID.Japanese; - public sealed override int Ability { get => ((PersonalInfo3)PersonalInfo).GetAbility(AbilityBit); set { } } + public sealed override int Ability { get => PersonalInfo.GetAbility(AbilityBit); set { } } public sealed override uint EncryptionConstant { get => PID; set { } } public sealed override int Nature { get => (int)(PID % 25); set { } } public sealed override bool IsNicknamed { get => SpeciesName.IsNicknamed(Species, Nickname, Language, 3); set { } } @@ -52,7 +54,7 @@ public abstract class G3PKM : PKM, IRibbonSetEvent3, IRibbonSetCommon3, IRibbonS MarkValue = (MarkValue & ~(1 << index)) | ((value & 1) << index); } - public abstract ushort SpeciesID3 { get; set; } // raw access + public abstract ushort SpeciesInternal { get; set; } // raw access public sealed override byte Form { @@ -74,7 +76,7 @@ public abstract class G3PKM : PKM, IRibbonSetEvent3, IRibbonSetCommon3, IRibbonS { if (Species is (int)Core.Species.Granbull or (int)Core.Species.Vibrava or (int)Core.Species.Flygon) return; - AbilityBit = n == 1 && ((PersonalInfo3)PersonalInfo).HasSecondAbility; + AbilityBit = n == 1 && PersonalInfo.HasSecondAbility; } public override bool Valid { get => true; set { } } @@ -102,6 +104,7 @@ public abstract class G3PKM : PKM, IRibbonSetEvent3, IRibbonSetCommon3, IRibbonS public abstract bool Unused2 { get; set; } public abstract bool Unused3 { get; set; } public abstract bool Unused4 { get; set; } + public abstract int RibbonCount { get; } public abstract byte CNT_Cool { get; set; } public abstract byte CNT_Beauty { get; set; } @@ -137,11 +140,11 @@ public abstract class G3PKM : PKM, IRibbonSetEvent3, IRibbonSetCommon3, IRibbonS /// New object with transferred properties. protected T ConvertTo() where T : G3PKM, new() => new() { - SpeciesID3 = SpeciesID3, + SpeciesInternal = SpeciesInternal, Language = Language, PID = PID, - TID = TID, - SID = SID, + TID16 = TID16, + SID16 = SID16, EXP = EXP, HeldItem = HeldItem, AbilityBit = AbilityBit, diff --git a/PKHeX.Core/PKM/Shared/G4PKM.cs b/PKHeX.Core/PKM/Shared/G4PKM.cs index 504e0a142..568a33bff 100644 --- a/PKHeX.Core/PKM/Shared/G4PKM.cs +++ b/PKHeX.Core/PKM/Shared/G4PKM.cs @@ -4,7 +4,7 @@ namespace PKHeX.Core; /// Generation 4 format. public abstract class G4PKM : PKM, - IRibbonSetEvent3, IRibbonSetEvent4, IRibbonSetUnique3, IRibbonSetUnique4, IRibbonSetCommon3, IRibbonSetCommon4, IContestStats, IGroundTile + IRibbonSetEvent3, IRibbonSetEvent4, IRibbonSetUnique3, IRibbonSetUnique4, IRibbonSetCommon3, IRibbonSetCommon4, IRibbonSetRibbons, IContestStats, IGroundTile { protected G4PKM(byte[] data) : base(data) { } protected G4PKM(int size) : base(size) { } @@ -21,8 +21,8 @@ public abstract class G4PKM : PKM, public sealed override int MaxStringLengthOT => 7; public sealed override int MaxStringLengthNickname => 10; - public sealed override int PSV => (int)(((PID >> 16) ^ (PID & 0xFFFF)) >> 3); - public sealed override int TSV => (TID ^ SID) >> 3; + public sealed override uint PSV => (((PID >> 16) ^ (PID & 0xFFFF)) >> 3); + public sealed override uint TSV => (uint)(TID16 ^ SID16) >> 3; protected bool PtHGSS => Pt || HGSS; @@ -48,7 +48,7 @@ public abstract class G4PKM : PKM, public sealed override void RefreshChecksum() => Checksum = CalculateChecksum(); public sealed override bool ChecksumValid => CalculateChecksum() == Checksum; public override bool Valid { get => Sanity == 0 && ChecksumValid; set { if (!value) return; Sanity = 0; RefreshChecksum(); } } - protected virtual ushort CalculateChecksum() => PokeCrypto.GetCHK(Data, PokeCrypto.SIZE_4STORED); + protected virtual ushort CalculateChecksum() => PokeCrypto.GetCHK(Data.AsSpan()[8..PokeCrypto.SIZE_4STORED]); // Trash Bytes public sealed override Span Nickname_Trash => Data.AsSpan(0x48, 22); @@ -144,6 +144,7 @@ public abstract class G4PKM : PKM, public abstract bool RibbonFootprint { get; set; } public abstract bool RibbonRecord { get; set; } public abstract bool RibbonLegend { get; set; } + public abstract int RibbonCount { get; } // Unused public abstract bool RIB3_4 { get; set; } @@ -282,10 +283,10 @@ public abstract class G4PKM : PKM, } // Synthetic Trading Logic - public bool Trade(string SAV_Trainer, int SAV_TID, int SAV_SID, int SAV_GENDER, int Day = 1, int Month = 1, int Year = 2009) + public bool Trade(string SAV_Trainer, uint savID32, int SAV_GENDER, int Day = 1, int Month = 1, int Year = 2009) { // Eggs do not have any modifications done if they are traded - if (IsEgg && !(SAV_Trainer == OT_Name && SAV_TID == TID && SAV_SID == SID && SAV_GENDER == OT_Gender)) + if (IsEgg && !(SAV_Trainer == OT_Name && savID32 == ID32 && SAV_GENDER == OT_Gender)) { SetLinkTradeEgg(Day, Month, Year, Locations.LinkTrade4); return true; @@ -309,8 +310,8 @@ public abstract class G4PKM : PKM, PID = PID, Species = Species, HeldItem = HeldItem, - TID = TID, - SID = SID, + TID16 = TID16, + SID16 = SID16, EXP = EXP, OT_Friendship = OT_Friendship, Ability = Ability, diff --git a/PKHeX.Core/PKM/Shared/G6PKM.cs b/PKHeX.Core/PKM/Shared/G6PKM.cs index 1b542c53a..381e9bcf6 100644 --- a/PKHeX.Core/PKM/Shared/G6PKM.cs +++ b/PKHeX.Core/PKM/Shared/G6PKM.cs @@ -43,8 +43,8 @@ public abstract class G6PKM : PKM, ISanityChecksum set { if (CurrentHandler == 1) OT_Friendship = value; else HT_Friendship = value; } } - public sealed override int PSV => (int)(((PID >> 16) ^ (PID & 0xFFFF)) >> 4); - public sealed override int TSV => (TID ^ SID) >> 4; + public sealed override uint PSV => ((PID >> 16) ^ (PID & 0xFFFF)) >> 4; + public sealed override uint TSV => (uint)(TID16 ^ SID16) >> 4; public sealed override bool IsUntraded => Data[0x78] == 0 && Data[0x78 + 1] == 0 && Format == Generation; // immediately terminated HT_Name data (\0) // Complex Generated Attributes @@ -105,7 +105,7 @@ public abstract class G6PKM : PKM, ISanityChecksum { // Eggs do not have any modifications done if they are traded // Apply link trade data, only if it left the OT (ignore if dumped & imported, or cloned, etc) - if ((tr.TID != TID) || (tr.SID != SID) || (tr.Gender != OT_Gender) || (tr.OT != OT_Name)) + if ((tr.TID16 != TID16) || (tr.SID16 != SID16) || (tr.Gender != OT_Gender) || (tr.OT != OT_Name)) SetLinkTradeEgg(Day, Month, Year, Locations.LinkTrade6); return; } diff --git a/PKHeX.Core/PKM/Shared/G8PKM.cs b/PKHeX.Core/PKM/Shared/G8PKM.cs index 7b92d01d7..dc181b23f 100644 --- a/PKHeX.Core/PKM/Shared/G8PKM.cs +++ b/PKHeX.Core/PKM/Shared/G8PKM.cs @@ -1,12 +1,13 @@ using System; +using System.Numerics; using static System.Buffers.Binary.BinaryPrimitives; namespace PKHeX.Core; /// Generation 8 format. public abstract class G8PKM : PKM, ISanityChecksum, IMoveReset, - IRibbonSetEvent3, IRibbonSetEvent4, IRibbonSetCommon3, IRibbonSetCommon4, IRibbonSetCommon6, IRibbonSetMemory6, IRibbonSetCommon7, IRibbonSetCommon8, IRibbonSetMark8, IRibbonSetAffixed, ITechRecord, ISociability, - IContestStats, IHyperTrain, IScaledSize, IGigantamax, IFavorite, IDynamaxLevel, IRibbonIndex, IHandlerLanguage, IFormArgument, IHomeTrack, IBattleVersion, ITrainerMemories + ITechRecord, ISociability, IContestStats, IHyperTrain, IScaledSize, IGigantamax, IFavorite, IDynamaxLevel, IHandlerLanguage, IFormArgument, IHomeTrack, IBattleVersion, ITrainerMemories, + IRibbonIndex, IRibbonSetAffixed, IRibbonSetRibbons, IRibbonSetEvent3, IRibbonSetEvent4, IRibbonSetCommon3, IRibbonSetCommon4, IRibbonSetCommon6, IRibbonSetMemory6, IRibbonSetCommon7, IRibbonSetCommon8, IRibbonSetMarks, IRibbonSetMark8 { protected G8PKM() : base(PokeCrypto.SIZE_8PARTY) { } protected G8PKM(byte[] data) : base(DecryptParty(data)) { } @@ -29,10 +30,7 @@ public abstract class G8PKM : PKM, ISanityChecksum, IMoveReset, } // Simple Generated Attributes - public ReadOnlySpan TechRecordPermitFlags => PersonalInfo.TMHM.AsSpan(PersonalInfo8SWSH.CountTM); - public ReadOnlySpan TechRecordPermitIndexes => LearnSource8SWSH.TR_SWSH.AsSpan(); - public int RecordCountTotal => 112; - public int RecordCountUsed => PersonalInfo8SWSH.CountTR; + public abstract IPermitRecord Permit { get; } // PersonalInfo derived metadata public override int CurrentFriendship { @@ -58,8 +56,8 @@ public abstract class G8PKM : PKM, ISanityChecksum, IMoveReset, public override int MaxStringLengthOT => 12; public override int MaxStringLengthNickname => 12; - public override int PSV => (int)(((PID >> 16) ^ (PID & 0xFFFF)) >> 4); - public override int TSV => (TID ^ SID) >> 4; + public override uint PSV => ((PID >> 16) ^ (PID & 0xFFFF)) >> 4; + public override uint TSV => (uint)(TID16 ^ SID16) >> 4; public override bool IsUntraded => Data[0xA8] == 0 && Data[0xA8 + 1] == 0 && Format == Generation; // immediately terminated HT_Name data (\0) // Complex Generated Attributes @@ -120,12 +118,13 @@ public abstract class G8PKM : PKM, ISanityChecksum, IMoveReset, #region Block A public override ushort Species { get => ReadUInt16LittleEndian(Data.AsSpan(0x08)); set => WriteUInt16LittleEndian(Data.AsSpan(0x08), value); } public override int HeldItem { get => ReadUInt16LittleEndian(Data.AsSpan(0x0A)); set => WriteUInt16LittleEndian(Data.AsSpan(0x0A), (ushort)value); } - public override int TID { get => ReadUInt16LittleEndian(Data.AsSpan(0x0C)); set => WriteUInt16LittleEndian(Data.AsSpan(0x0C), (ushort)value); } - public override int SID { get => ReadUInt16LittleEndian(Data.AsSpan(0x0E)); set => WriteUInt16LittleEndian(Data.AsSpan(0x0E), (ushort)value); } + public override uint ID32 { get => ReadUInt32LittleEndian(Data.AsSpan(0x0C)); set => WriteUInt32LittleEndian(Data.AsSpan(0x0C), value); } + public override ushort TID16 { get => ReadUInt16LittleEndian(Data.AsSpan(0x0C)); set => WriteUInt16LittleEndian(Data.AsSpan(0x0C), value); } + public override ushort SID16 { get => ReadUInt16LittleEndian(Data.AsSpan(0x0E)); set => WriteUInt16LittleEndian(Data.AsSpan(0x0E), value); } public override uint EXP { get => ReadUInt32LittleEndian(Data.AsSpan(0x10)); set => WriteUInt32LittleEndian(Data.AsSpan(0x10), value); } public override int Ability { get => ReadUInt16LittleEndian(Data.AsSpan(0x14)); set => WriteUInt16LittleEndian(Data.AsSpan(0x14), (ushort)value); } public override int AbilityNumber { get => Data[0x16] & 7; set => Data[0x16] = (byte)((Data[0x16] & ~7) | (value & 7)); } - public bool IsFavorite { get => (Data[0x16] & 8) != 0; set => Data[0x16] = (byte)((Data[0x16] & ~8) | ((value ? 1 : 0) << 3)); } // unused, was in LGPE but not in SWSH + public bool IsFavorite { get => (Data[0x16] & 8) != 0; set => Data[0x16] = (byte)((Data[0x16] & ~8) | ((value ? 1 : 0) << 3)); } // unused, was in LGP/E but not in SW/SH public bool CanGigantamax { get => (Data[0x16] & 16) != 0; set => Data[0x16] = (byte)((Data[0x16] & ~16) | (value ? 16 : 0)); } // 0x17 alignment unused public override int MarkValue { get => ReadUInt16LittleEndian(Data.AsSpan(0x18)); set => WriteUInt16LittleEndian(Data.AsSpan(0x18), (ushort)value); } @@ -309,15 +308,14 @@ public abstract class G8PKM : PKM, ISanityChecksum, IMoveReset, public bool RIB47_6 { get => FlagUtil.GetFlag(Data, 0x47, 6); set => FlagUtil.SetFlag(Data, 0x47, 6, value); } public bool RIB47_7 { get => FlagUtil.GetFlag(Data, 0x47, 7); set => FlagUtil.SetFlag(Data, 0x47, 7, value); } - public bool HasMark() - { - var d = Data.AsSpan(); - if ((ReadUInt16LittleEndian(d[0x3A..]) & 0xFFE0) != 0) - return true; - if (ReadUInt32LittleEndian(d[0x40..]) != 0) - return true; - return (d[0x44] & 3) != 0; - } + public int RibbonCount => BitOperations.PopCount(ReadUInt64LittleEndian(Data.AsSpan(0x34)) & 0b00000000_00011111__11111111_11111111__11111111_11111111__11111111_11111111) + + BitOperations.PopCount(ReadUInt64LittleEndian(Data.AsSpan(0x40)) & 0b00000000_00000000__00000000_00001100__00000000_00000000__00000000_00000000); + public int MarkCount => BitOperations.PopCount(ReadUInt64LittleEndian(Data.AsSpan(0x34)) & 0b11111111_11100000__00000000_00000000__00000000_00000000__00000000_00000000) + + BitOperations.PopCount(ReadUInt64LittleEndian(Data.AsSpan(0x40)) & 0b00000000_00000000__00000000_00000011__11111111_11111111__11111111_11111111); + public int RibbonMarkCount => BitOperations.PopCount(ReadUInt64LittleEndian(Data.AsSpan(0x34)) & 0b11111111_11111111__11111111_11111111__11111111_11111111__11111111_11111111) + + BitOperations.PopCount(ReadUInt64LittleEndian(Data.AsSpan(0x40)) & 0b00000000_00000000__00000000_00001111__11111111_11111111__11111111_11111111); + + public bool HasMarkEncounter8 => MarkCount != 0; public uint Sociability { get => ReadUInt32LittleEndian(Data.AsSpan(0x48)); set => WriteUInt32LittleEndian(Data.AsSpan(0x48), value); } @@ -333,7 +331,7 @@ public abstract class G8PKM : PKM, ISanityChecksum, IMoveReset, public override string Nickname { get => StringConverter8.GetString(Nickname_Trash); - set => StringConverter8.SetString(Nickname_Trash, value.AsSpan(), 12, StringConverterOption.None); + set => StringConverter8.SetString(Nickname_Trash, value, 12, StringConverterOption.None); } // 2 bytes for \0, automatically handled above @@ -383,7 +381,7 @@ public abstract class G8PKM : PKM, ISanityChecksum, IMoveReset, public override string HT_Name { get => StringConverter8.GetString(HT_Trash); - set => StringConverter8.SetString(HT_Trash, value.AsSpan(), 12, StringConverterOption.None); + set => StringConverter8.SetString(HT_Trash, value, 12, StringConverterOption.None); } public override int HT_Gender { get => Data[0xC2]; set => Data[0xC2] = (byte)value; } @@ -421,8 +419,8 @@ public abstract class G8PKM : PKM, ISanityChecksum, IMoveReset, public override byte Enjoyment { get => Data[0xDD]; set => Data[0xDD] = value; } public override int Version { get => Data[0xDE]; set => Data[0xDE] = (byte)value; } public byte BattleVersion { get => Data[0xDF]; set => Data[0xDF] = value; } - // public override int Region { get => Data[0xE0]; set => Data[0xE0] = (byte)value; } - // public override int ConsoleRegion { get => Data[0xE1]; set => Data[0xE1] = (byte)value; } + // public override byte Region { get => Data[0xE0]; set => Data[0xE0] = (byte)value; } + // public override byte ConsoleRegion { get => Data[0xE1]; set => Data[0xE1] = (byte)value; } public override int Language { get => Data[0xE2]; set => Data[0xE2] = (byte)value; } // 0xE3 alignment public uint FormArgument { get => ReadUInt32LittleEndian(Data.AsSpan(0xE4)); set => WriteUInt32LittleEndian(Data.AsSpan(0xE4), value); } @@ -437,7 +435,7 @@ public abstract class G8PKM : PKM, ISanityChecksum, IMoveReset, public override string OT_Name { get => StringConverter8.GetString(OT_Trash); - set => StringConverter8.SetString(OT_Trash, value.AsSpan(), 12, StringConverterOption.None); + set => StringConverter8.SetString(OT_Trash, value, 12, StringConverterOption.None); } public override int OT_Friendship { get => Data[0x112]; set => Data[0x112] = (byte)value; } @@ -570,8 +568,8 @@ public abstract class G8PKM : PKM, ISanityChecksum, IMoveReset, Nature = Nature, StatNature = StatNature, - TID = TID, - SID = SID, + TID16 = TID16, + SID16 = SID16, EXP = EXP, Ability = Ability, AbilityNumber = AbilityNumber, diff --git a/PKHeX.Core/PKM/Shared/GBPKM.cs b/PKHeX.Core/PKM/Shared/GBPKM.cs index e28a76402..05dcd3a32 100644 --- a/PKHeX.Core/PKM/Shared/GBPKM.cs +++ b/PKHeX.Core/PKM/Shared/GBPKM.cs @@ -106,15 +106,16 @@ public abstract class GBPKM : PKM public sealed override int Nature { get => 0; set { } } public sealed override bool ChecksumValid => true; public sealed override bool FatefulEncounter { get => false; set { } } - public sealed override int TSV => 0x0000; - public sealed override int PSV => 0xFFFF; + public sealed override uint TSV => 0x0000; + public sealed override uint PSV => 0xFFFF; public sealed override int Characteristic => -1; public sealed override int MarkValue { get => 0; set { } } public sealed override int Ability { get => -1; set { } } public sealed override int CurrentHandler { get => 0; set { } } public sealed override int Egg_Location { get => 0; set { } } public sealed override int Ball { get => 0; set { } } - public sealed override int SID { get => 0; set { } } + public sealed override uint ID32 { get => TID16; set => TID16 = (ushort)value; } + public sealed override ushort SID16 { get => 0; set { } } #endregion public sealed override bool IsShiny => IV_DEF == 10 && IV_SPE == 10 && IV_SPC == 10 && (IV_ATK & 2) == 2; diff --git a/PKHeX.Core/PKM/Shared/GBPKML.cs b/PKHeX.Core/PKM/Shared/GBPKML.cs index cb14c76f7..cddb55001 100644 --- a/PKHeX.Core/PKM/Shared/GBPKML.cs +++ b/PKHeX.Core/PKM/Shared/GBPKML.cs @@ -1,4 +1,4 @@ -using System; +using System; namespace PKHeX.Core; @@ -50,7 +50,7 @@ public abstract class GBPKML : GBPKM var name = SpeciesName.GetSpeciesNameGeneration(Species, language, Format); var len = Nickname_Trash.Length; byte[] data = new byte[len]; - SetString(name.AsSpan(), data, len, StringConverterOption.Clear50); + SetString(name, data, len, StringConverterOption.Clear50); if (!Korean) { // Decimal point<->period fix @@ -83,7 +83,7 @@ public abstract class GBPKML : GBPKM if (!IsNicknamed && Nickname == value) return; - SetStringKeepTerminatorStyle(value.AsSpan(), RawNickname); + SetStringKeepTerminatorStyle(value, RawNickname); } } @@ -92,14 +92,14 @@ public abstract class GBPKML : GBPKM get { if (Korean) - return StringConverter2KOR.GetString(RawOT.AsSpan()); - return StringConverter12.GetString(RawOT.AsSpan(), Japanese); + return StringConverter2KOR.GetString(RawOT); + return StringConverter12.GetString(RawOT, Japanese); } set { if (value == OT_Name) return; - SetStringKeepTerminatorStyle(value.AsSpan(), RawOT); + SetStringKeepTerminatorStyle(value, RawOT); } } diff --git a/PKHeX.Core/PKM/Shared/IObedienceLevel.cs b/PKHeX.Core/PKM/Shared/IObedienceLevel.cs index 42eace854..5908c59d2 100644 --- a/PKHeX.Core/PKM/Shared/IObedienceLevel.cs +++ b/PKHeX.Core/PKM/Shared/IObedienceLevel.cs @@ -22,4 +22,3 @@ public static class ObedienceExtensions return (byte)originalMet; } } - diff --git a/PKHeX.Core/PKM/Shared/PokeList1.cs b/PKHeX.Core/PKM/Shared/PokeList1.cs index 6d5671854..bd6b8b51e 100644 --- a/PKHeX.Core/PKM/Shared/PokeList1.cs +++ b/PKHeX.Core/PKM/Shared/PokeList1.cs @@ -7,7 +7,7 @@ namespace PKHeX.Core; /// public sealed class PokeList1 : PokeListGB { - protected override byte GetSpeciesBoxIdentifier(PK1 pk) => SpeciesConverter.SetG1Species(pk.Species); + protected override byte GetSpeciesBoxIdentifier(PK1 pk) => SpeciesConverter.GetInternal1(pk.Species); protected override PK1 GetEntry(byte[] dat, ReadOnlySpan otname, ReadOnlySpan nick, bool egg) { var result = new PK1(dat, Japanese); // no eggs diff --git a/PKHeX.Core/PKM/Strings/StringConverter.cs b/PKHeX.Core/PKM/Strings/StringConverter.cs index 463a72ae3..27dcc4297 100644 --- a/PKHeX.Core/PKM/Strings/StringConverter.cs +++ b/PKHeX.Core/PKM/Strings/StringConverter.cs @@ -31,6 +31,31 @@ public static class StringConverter _ => throw new ArgumentOutOfRangeException(nameof(generation)), }; + /// + /// Converts bytes to a string according to the input parameters. + /// + /// Encoded data + /// Decoded character result buffer + /// Generation string format + /// Encoding is Japanese + /// Encoding is Big Endian + /// Decoded string. + public static int LoadString(ReadOnlySpan data, Span result, int generation, bool jp, bool isBigEndian = false) => generation switch + { + 3 when isBigEndian => StringConverter3GC.LoadString(data, result), + 4 when isBigEndian => StringConverter4GC.LoadString(data, result), + + 1 or 2 => StringConverter12.LoadString(data, result, jp), + 3 => StringConverter3.LoadString(data, result, jp), + 4 => StringConverter4.LoadString(data, result), + 5 => StringConverter5.LoadString(data, result), + 6 => StringConverter6.LoadString(data, result), + 7 => StringConverter7.LoadString(data, result), + 8 => StringConverter8.LoadString(data, result), + 9 => StringConverter8.LoadString(data, result), + _ => throw new ArgumentOutOfRangeException(nameof(generation)), + }; + /// /// Gets the bytes for a Generation specific string according to the input parameters. /// diff --git a/PKHeX.Core/PKM/Strings/StringConverter12.cs b/PKHeX.Core/PKM/Strings/StringConverter12.cs index 829f05115..05cdf22e5 100644 --- a/PKHeX.Core/PKM/Strings/StringConverter12.cs +++ b/PKHeX.Core/PKM/Strings/StringConverter12.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; namespace PKHeX.Core; @@ -64,12 +64,14 @@ public static class StringConverter12 { foreach (var b in data) { - if (b is >= 0xC0 and <= 0xC6) + if (IsGermanicGlyph(b)) return true; } return false; } + private static bool IsGermanicGlyph(byte b) => b - 0xC0u <= 6; + /// /// Checks if the input byte array is definitely of German origin (any ÄÖÜäöü) /// @@ -83,7 +85,7 @@ public static class StringConverter12 if (!table.TryGetValue(c, out var b)) continue; - if (b is >= 0xC0 and <= 0xC6) + if (IsGermanicGlyph(b)) return true; } return false; @@ -99,10 +101,15 @@ public static class StringConverter12 { Span result = stackalloc char[data.Length]; int length = LoadString(data, result, jp); - return new string(result[..length].ToArray()); + return new string(result[..length]); } - private static int LoadString(ReadOnlySpan data, Span result, bool jp) + /// + /// Encoded data + /// Decoded character result buffer + /// Data source is Japanese. + /// Character count loaded. + public static int LoadString(ReadOnlySpan data, Span result, bool jp) { if (data[0] == G1TradeOTCode) { diff --git a/PKHeX.Core/PKM/Strings/StringConverter12Transporter.cs b/PKHeX.Core/PKM/Strings/StringConverter12Transporter.cs index d9dee8e50..b2d8ac835 100644 --- a/PKHeX.Core/PKM/Strings/StringConverter12Transporter.cs +++ b/PKHeX.Core/PKM/Strings/StringConverter12Transporter.cs @@ -1,4 +1,4 @@ -using System; +using System; namespace PKHeX.Core; @@ -18,11 +18,16 @@ public static class StringConverter12Transporter public static string GetString(ReadOnlySpan data, bool jp) { Span result = stackalloc char[data.Length]; - int length = LoadString1(data, result, jp); - return new string(result[..length].ToArray()); + int length = LoadString(data, result, jp); + return new string(result[..length]); } - private static int LoadString1(ReadOnlySpan data, Span result, bool jp) + /// + /// Encoded data + /// Decoded character result buffer + /// Data source is Japanese. + /// Character count loaded. + public static int LoadString(ReadOnlySpan data, Span result, bool jp) { var table = jp ? jp_table : us_table; int i = 0; @@ -51,10 +56,9 @@ public static class StringConverter12Transporter if (!IsHiragana(chars)) return; - var span = Katakana.AsSpan(); for (int i = 0; i < chars.Length; i++) { - int index = span.IndexOf(chars[i]); + int index = Katakana.IndexOf(chars[i]); if (index == -1) continue; chars[i] = Hiragana[index]; @@ -63,13 +67,7 @@ public static class StringConverter12Transporter private static bool IsKata(ReadOnlySpan chars) { - var span = Katakana.AsSpan(); - foreach (var c in chars) - { - if (span.IndexOf(c) != -1) - return true; - } - return false; + return chars.IndexOfAny(Katakana) != -1; } private static bool IsHiragana(ReadOnlySpan chars) @@ -84,8 +82,8 @@ public static class StringConverter12Transporter return true; } - private static readonly char[] Katakana = { 'ベ', 'ペ', 'ヘ', 'リ' }; - private static readonly char[] Hiragana = { 'べ', 'ぺ', 'へ', 'り' }; + private const string Katakana = "ベペヘリ"; + private const string Hiragana = "べぺへり"; /// /// International 1->7 character translation table diff --git a/PKHeX.Core/PKM/Strings/StringConverter2KOR.cs b/PKHeX.Core/PKM/Strings/StringConverter2KOR.cs index 3c84988ec..acf399032 100644 --- a/PKHeX.Core/PKM/Strings/StringConverter2KOR.cs +++ b/PKHeX.Core/PKM/Strings/StringConverter2KOR.cs @@ -1,6 +1,5 @@ -using System; +using System; using System.Collections.Generic; -using System.Linq; using static PKHeX.Core.StringConverter12; @@ -16,10 +15,18 @@ public static class StringConverter2KOR /// public static bool GetIsG2Korean(ReadOnlySpan str) { - var dict = U2GSC_KOR; + var all = U2GSC_KOR; foreach (var c in str) { - if (!dict.Any(d => d.ContainsKey(c))) + bool any = false; + foreach (var dict in all) + { + if (!dict.ContainsKey(c)) + continue; + any = true; + break; + } + if (!any) return false; } return true; @@ -34,10 +41,14 @@ public static class StringConverter2KOR { Span result = stackalloc char[data.Length]; int length = LoadString(data, result); - return new string(result[..length].ToArray()); + return new string(result[..length]); } - private static int LoadString(ReadOnlySpan data, Span result) + /// + /// Encoded data + /// Decoded character result buffer + /// Character count loaded. + public static int LoadString(ReadOnlySpan data, Span result) { if (data[0] == G1TradeOTCode) { @@ -129,7 +140,7 @@ public static class StringConverter2KOR /// Localized Name for Generation 2 public static string LocalizeKOR2(string nick) { - if (KorG2Localized.TryGetValue(nick, out string localized)) + if (KorG2Localized.TryGetValue(nick, out var localized)) return localized; return nick; } diff --git a/PKHeX.Core/PKM/Strings/StringConverter3.cs b/PKHeX.Core/PKM/Strings/StringConverter3.cs index bd3270fec..1ddcf1819 100644 --- a/PKHeX.Core/PKM/Strings/StringConverter3.cs +++ b/PKHeX.Core/PKM/Strings/StringConverter3.cs @@ -1,4 +1,4 @@ -using System; +using System; namespace PKHeX.Core; @@ -19,6 +19,17 @@ public static class StringConverter3 public static string GetString(ReadOnlySpan data, bool jp) { Span result = stackalloc char[data.Length]; + int i = LoadString(data, result, jp); + return new string(result[..i]); + } + + /// + /// Encoded data + /// Decoded character result buffer + /// Data source is Japanese. + /// Character count loaded. + public static int LoadString(ReadOnlySpan data, Span result, bool jp) + { int i = 0; for (; i < data.Length; i++) { @@ -28,7 +39,7 @@ public static class StringConverter3 break; result[i] = c; } - return new string(result[..i].ToArray()); + return i; } /// @@ -47,7 +58,7 @@ public static class StringConverter3 value = value[..maxLength]; // Hard cap if (option is StringConverterOption.ClearFF) - buffer.Fill(0xFF); + buffer.Fill(TerminatorByte); else if (option is StringConverterOption.ClearZero) buffer.Clear(); diff --git a/PKHeX.Core/PKM/Strings/StringConverter345.cs b/PKHeX.Core/PKM/Strings/StringConverter345.cs index 18e32d23b..41832325b 100644 --- a/PKHeX.Core/PKM/Strings/StringConverter345.cs +++ b/PKHeX.Core/PKM/Strings/StringConverter345.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using static System.Buffers.Binary.BinaryPrimitives; @@ -13,17 +13,28 @@ public static class StringConverter345 /// Trash Bytes for Generation 3->4 /// /// String buffers are reused, data is not cleared which yields the trash bytes. - public static readonly byte[][] G4TransferTrashBytes = { - Array.Empty(), // Unused - new byte[] { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, - new byte[] { 0x18, 0x20, 0x0D, 0x02, 0x42, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0xA1, 0x0C, 0x02, 0xE0, 0xFF }, - new byte[] { 0x74, 0x20, 0x0D, 0x02, 0x42, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA4, 0xA1, 0x0C, 0x02, 0xE0, 0xFF }, - new byte[] { 0x54, 0x20, 0x0D, 0x02, 0x42, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x84, 0xA1, 0x0C, 0x02, 0xE0, 0xFF }, - new byte[] { 0x74, 0x20, 0x0D, 0x02, 0x42, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA4, 0xA1, 0x0C, 0x02, 0xE0, 0xFF }, - Array.Empty(), // Unused - new byte[] { 0x74, 0x20, 0x0D, 0x02, 0x42, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA4, 0xA1, 0x0C, 0x02, 0xE0, 0xFF }, + private static ReadOnlySpan G4TransferTrashBytes => new byte[] + { + 0x18, 0x20, 0x0D, 0x02, 0x42, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0xA1, 0x0C, 0x02, 0xE0, 0xFF, // 2 + 0x74, 0x20, 0x0D, 0x02, 0x42, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA4, 0xA1, 0x0C, 0x02, 0xE0, 0xFF, // 3 + 0x54, 0x20, 0x0D, 0x02, 0x42, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x84, 0xA1, 0x0C, 0x02, 0xE0, 0xFF, // 4 + 0x74, 0x20, 0x0D, 0x02, 0x42, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA4, 0xA1, 0x0C, 0x02, 0xE0, 0xFF, // 5 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 6 + 0x74, 0x20, 0x0D, 0x02, 0x42, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA4, 0xA1, 0x0C, 0x02, 0xE0, 0xFF, // 7 }; + private const int TrashByteLanguages = 6; // rows + private const int TrashByteLayerWidth = 18; // columns + + public static ReadOnlySpan GetTrashBytes(int language) + { + language -= 2; + if ((uint)language >= TrashByteLanguages) + return ReadOnlySpan.Empty; + var offset = language * TrashByteLayerWidth; + return G4TransferTrashBytes.Slice(offset, TrashByteLayerWidth); + } + /// /// Remaps Gen5 Glyphs to unicode codepoint. /// diff --git a/PKHeX.Core/PKM/Strings/StringConverter3GC.cs b/PKHeX.Core/PKM/Strings/StringConverter3GC.cs index b834537ec..8f8c2039f 100644 --- a/PKHeX.Core/PKM/Strings/StringConverter3GC.cs +++ b/PKHeX.Core/PKM/Strings/StringConverter3GC.cs @@ -1,4 +1,4 @@ -using System; +using System; using static System.Buffers.Binary.BinaryPrimitives; namespace PKHeX.Core; @@ -17,10 +17,14 @@ public static class StringConverter3GC { Span result = stackalloc char[data.Length]; int length = LoadString(data, result); - return new string(result[..length].ToArray()); + return new string(result[..length]); } - private static int LoadString(ReadOnlySpan data, Span result) + /// + /// Encoded data + /// Decoded character result buffer + /// Character count loaded. + public static int LoadString(ReadOnlySpan data, Span result) { int i = 0; for (; i < data.Length; i += 2) diff --git a/PKHeX.Core/PKM/Strings/StringConverter4.cs b/PKHeX.Core/PKM/Strings/StringConverter4.cs index 22f123c0f..f0edbf40f 100644 --- a/PKHeX.Core/PKM/Strings/StringConverter4.cs +++ b/PKHeX.Core/PKM/Strings/StringConverter4.cs @@ -1,4 +1,4 @@ -using System; +using System; using static PKHeX.Core.StringConverter4Util; using static System.Buffers.Binary.BinaryPrimitives; @@ -19,10 +19,14 @@ public static class StringConverter4 { Span result = stackalloc char[data.Length]; var length = LoadString(data, result); - return new string(result[..length].ToArray()); + return new string(result[..length]); } - private static int LoadString(ReadOnlySpan data, Span result) + /// + /// Encoded data + /// Decoded character result buffer + /// Character count loaded. + public static int LoadString(ReadOnlySpan data, Span result) { int i = 0; for (; i < data.Length; i += 2) diff --git a/PKHeX.Core/PKM/Strings/StringConverter4GC.cs b/PKHeX.Core/PKM/Strings/StringConverter4GC.cs index db5af440b..3435a331d 100644 --- a/PKHeX.Core/PKM/Strings/StringConverter4GC.cs +++ b/PKHeX.Core/PKM/Strings/StringConverter4GC.cs @@ -1,4 +1,4 @@ -using System; +using System; using static PKHeX.Core.StringConverter4Util; using static System.Buffers.Binary.BinaryPrimitives; @@ -21,10 +21,14 @@ public static class StringConverter4GC { Span result = stackalloc char[data.Length]; var length = LoadString(data, result); - return new string(result[..length].ToArray()); + return new string(result[..length]); } - private static int LoadString(ReadOnlySpan data, Span result) + /// + /// Encoded data + /// Decoded character result buffer + /// Character count loaded. + public static int LoadString(ReadOnlySpan data, Span result) { int i = 0; for (; i < data.Length; i += 2) @@ -83,10 +87,14 @@ public static class StringConverter4GC { Span result = stackalloc char[data.Length]; var length = LoadStringUnicode(data, result); - return new string(result[..length].ToArray()); + return new string(result[..length]); } - private static int LoadStringUnicode(ReadOnlySpan data, Span result) + /// + /// Encoded data + /// Decoded character result buffer + /// Character count loaded. + public static int LoadStringUnicode(ReadOnlySpan data, Span result) { int i = 0; for (; i < data.Length; i += 2) diff --git a/PKHeX.Core/PKM/Strings/StringConverter5.cs b/PKHeX.Core/PKM/Strings/StringConverter5.cs index c9a10c5c3..420462b6f 100644 --- a/PKHeX.Core/PKM/Strings/StringConverter5.cs +++ b/PKHeX.Core/PKM/Strings/StringConverter5.cs @@ -1,4 +1,4 @@ -using System; +using System; using static System.Buffers.Binary.BinaryPrimitives; namespace PKHeX.Core; @@ -17,10 +17,14 @@ public static class StringConverter5 { Span result = stackalloc char[data.Length]; int length = LoadString(data, result); - return new string(result[..length].ToArray()); + return new string(result[..length]); } - private static int LoadString(ReadOnlySpan data, Span result) + /// + /// Encoded data + /// Decoded character result buffer + /// Character count loaded. + public static int LoadString(ReadOnlySpan data, Span result) { int i = 0; for (; i < data.Length; i += 2) diff --git a/PKHeX.Core/PKM/Strings/StringConverter6.cs b/PKHeX.Core/PKM/Strings/StringConverter6.cs index c42cc00be..6c55d7e7e 100644 --- a/PKHeX.Core/PKM/Strings/StringConverter6.cs +++ b/PKHeX.Core/PKM/Strings/StringConverter6.cs @@ -1,4 +1,4 @@ -using System; +using System; using static System.Buffers.Binary.BinaryPrimitives; namespace PKHeX.Core; @@ -18,10 +18,14 @@ public static class StringConverter6 { Span result = stackalloc char[data.Length]; int length = LoadString(data, result); - return new string(result[..length].ToArray()); + return new string(result[..length]); } - private static int LoadString(ReadOnlySpan data, Span result) + /// + /// Encoded data + /// Decoded character result buffer + /// Character count loaded. + public static int LoadString(ReadOnlySpan data, Span result) { int i = 0; for (; i < data.Length; i += 2) diff --git a/PKHeX.Core/PKM/Strings/StringConverter7.cs b/PKHeX.Core/PKM/Strings/StringConverter7.cs index 233d354bb..df376cb1d 100644 --- a/PKHeX.Core/PKM/Strings/StringConverter7.cs +++ b/PKHeX.Core/PKM/Strings/StringConverter7.cs @@ -1,4 +1,4 @@ -using System; +using System; using static System.Buffers.Binary.BinaryPrimitives; namespace PKHeX.Core; @@ -18,10 +18,14 @@ public static class StringConverter7 { Span result = stackalloc char[data.Length]; int length = LoadString(data, result); - return new string(result[..length].ToArray()); + return new string(result[..length]); } - private static int LoadString(ReadOnlySpan data, Span result) + /// + /// Encoded data + /// Decoded character result buffer + /// Character count loaded. + public static int LoadString(ReadOnlySpan data, Span result) { int i = 0; for (; i < data.Length; i += 2) diff --git a/PKHeX.Core/PKM/Strings/StringConverter8.cs b/PKHeX.Core/PKM/Strings/StringConverter8.cs index b221d0fdc..4bf9720c8 100644 --- a/PKHeX.Core/PKM/Strings/StringConverter8.cs +++ b/PKHeX.Core/PKM/Strings/StringConverter8.cs @@ -1,4 +1,4 @@ -using System; +using System; using static System.Buffers.Binary.BinaryPrimitives; namespace PKHeX.Core; @@ -18,10 +18,14 @@ public static class StringConverter8 { Span result = stackalloc char[data.Length]; int length = LoadString(data, result); - return new string(result[..length].ToArray()); + return new string(result[..length]); } - private static int LoadString(ReadOnlySpan data, Span result) + /// + /// Encoded data + /// Decoded character result buffer + /// Character count loaded. + public static int LoadString(ReadOnlySpan data, Span result) { int i = 0; for (; i < data.Length; i += 2) diff --git a/PKHeX.Core/PKM/Util/Conversion/FormConverter.cs b/PKHeX.Core/PKM/Util/Conversion/FormConverter.cs index 6b021b2ca..ef4a780b8 100644 --- a/PKHeX.Core/PKM/Util/Conversion/FormConverter.cs +++ b/PKHeX.Core/PKM/Util/Conversion/FormConverter.cs @@ -797,9 +797,9 @@ public static class FormConverter { Tauros => new[] { types[0], // Normal - forms[Paldean], - forms[Paldean] + $" ({types[(int)MoveType.Fire]})", - forms[Paldean] + $" ({types[(int)MoveType.Water]})", + $"{forms[Paldean]} {forms[PaldeanCombat]}", + $"{forms[Paldean]} {forms[PaldeanBlaze]}", + $"{forms[Paldean]} {forms[PaldeanAqua]}", }, _ => new[] { @@ -878,6 +878,9 @@ public static class FormConverter private const int Drive = 1120; private const int Aquatic = 1121; private const int Glide = 1122; + private const int PaldeanCombat = 1123; + private const int PaldeanBlaze = 1124; + private const int PaldeanAqua = 1125; public static string GetGigantamaxName(IReadOnlyList forms) => forms[Gigantamax]; @@ -896,8 +899,8 @@ public static class FormConverter result[8 * 7] = forms[RainbowSwirl]; const int deco = 7; - const int fc = 9; - for (int f = 0; f < fc; f++) + const byte fc = 9; + for (byte f = 0; f < fc; f++) { int start = f * deco; // iterate downwards using form0 as pattern ref, replacing on final loop diff --git a/PKHeX.Core/PKM/Util/Conversion/SpeciesConverter.cs b/PKHeX.Core/PKM/Util/Conversion/SpeciesConverter.cs index c6e040029..663310a9b 100644 --- a/PKHeX.Core/PKM/Util/Conversion/SpeciesConverter.cs +++ b/PKHeX.Core/PKM/Util/Conversion/SpeciesConverter.cs @@ -1,95 +1,173 @@ +using System; + namespace PKHeX.Core; /// /// Logic for converting a National Pokédex Species ID to/from generation specific values. /// -/// Generation 4+ always use the national dex ID. Prior generations do not. +/// Specific generations store their Species IDs in different orders from the National Dex ID. public static class SpeciesConverter { /// - /// Converts Generation 1 species ID to National Dex ID. - /// - /// Generation 1 species ID. - /// National Dex ID. - public static byte GetG1Species(byte raw) => table1_National[raw]; - - /// - /// Converts a National Dex ID to Generation 1 species ID. + /// Converts a National Dex ID to Generation 1 internal species ID. /// /// National Dex ID. /// Generation 1 species ID. - public static byte SetG1Species(ushort species) => species >= table1_Internal.Length ? (byte)0 : table1_Internal[species]; + public static byte GetInternal1(ushort species) => species >= Table1NationalToInternal.Length ? (byte)0 : Table1NationalToInternal[species]; /// - /// Converts a National Dex ID to Generation 3 species ID. + /// Converts a Generation 1 internal species ID to National Dex ID. + /// + /// Generation 1 species ID. + /// National Dex ID. + public static byte GetNational1(byte raw) => Table1InternalToNational[raw]; + + /// + /// Converts a National Dex ID to Generation 3 internal species ID. /// /// National Dex ID /// Generation 3 species ID. - public static ushort GetG3Species(ushort species) => species >= table3_Internal.Length ? (ushort)0 : table3_Internal[species]; + public static ushort GetInternal3(ushort species) + { + var shift = species - FirstUnalignedNational3; + var table = Table3NationalToInternal; + if ((uint)shift >= table.Length) + return species; + return (ushort)(species + table[shift]); + } /// - /// Converts Generation 3 species ID to National Dex ID. + /// Converts a Generation 3 internal species ID to National Dex ID. /// /// Generation 3 species ID. /// National Dex ID. - public static ushort GetG4Species(ushort raw) => raw >= table3_National.Length ? (ushort)0 : table3_National[raw]; + public static ushort GetNational3(ushort raw) + { + if (raw < FirstUnalignedNational3) + return raw; + var shift = raw - FirstUnalignedInternal3; + var table = Table3InternalToNational; + if ((uint)shift >= table.Length) + return 0; + return (ushort)(raw + table[shift]); + } + + /// + /// Converts a National Dex ID to Generation 9 internal species ID. + /// + /// National Dex ID + /// Generation 9 species ID. + public static ushort GetInternal9(ushort species) + { + var shift = species - FirstUnalignedNational9; + var table = Table9NationalToInternal; + if ((uint)shift >= table.Length) + return species; + return (ushort)(species + table[shift]); + } + + /// + /// Converts a Generation 9 internal species ID to National Dex ID. + /// + /// Generation 9 species ID. + /// National Dex ID. + public static ushort GetNational9(ushort raw) + { + var table = Table9InternalToNational; + var shift = raw - FirstUnalignedInternal9; + if ((uint)shift >= table.Length) + return raw; + return (ushort)(raw + table[shift]); + } // both tables are 0x100 bytes to eliminate bounds checks when requesting byte indexes - private static readonly byte[] table1_Internal = { 0x00, 0x99, 0x09, 0x9A, 0xB0, 0xB2, 0xB4, 0xB1, 0xB3, 0x1C, 0x7B, 0x7C, 0x7D, 0x70, 0x71, 0x72, 0x24, 0x96, 0x97, 0xA5, 0xA6, 0x05, 0x23, 0x6C, 0x2D, 0x54, 0x55, 0x60, 0x61, 0x0F, 0xA8, 0x10, 0x03, 0xA7, 0x07, 0x04, 0x8E, 0x52, 0x53, 0x64, 0x65, 0x6B, 0x82, 0xB9, 0xBA, 0xBB, 0x6D, 0x2E, 0x41, 0x77, 0x3B, 0x76, 0x4D, 0x90, 0x2F, 0x80, 0x39, 0x75, 0x21, 0x14, 0x47, 0x6E, 0x6F, 0x94, 0x26, 0x95, 0x6A, 0x29, 0x7E, 0xBC, 0xBD, 0xBE, 0x18, 0x9B, 0xA9, 0x27, 0x31, 0xA3, 0xA4, 0x25, 0x08, 0xAD, 0x36, 0x40, 0x46, 0x74, 0x3A, 0x78, 0x0D, 0x88, 0x17, 0x8B, 0x19, 0x93, 0x0E, 0x22, 0x30, 0x81, 0x4E, 0x8A, 0x06, 0x8D, 0x0C, 0x0A, 0x11, 0x91, 0x2B, 0x2C, 0x0B, 0x37, 0x8F, 0x12, 0x01, 0x28, 0x1E, 0x02, 0x5C, 0x5D, 0x9D, 0x9E, 0x1B, 0x98, 0x2A, 0x1A, 0x48, 0x35, 0x33, 0x1D, 0x3C, 0x85, 0x16, 0x13, 0x4C, 0x66, 0x69, 0x68, 0x67, 0xAA, 0x62, 0x63, 0x5A, 0x5B, 0xAB, 0x84, 0x4A, 0x4B, 0x49, 0x58, 0x59, 0x42, 0x83, 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; - private static readonly byte[] table1_National = { 0x00, 0x70, 0x73, 0x20, 0x23, 0x15, 0x64, 0x22, 0x50, 0x02, 0x67, 0x6C, 0x66, 0x58, 0x5E, 0x1D, 0x1F, 0x68, 0x6F, 0x83, 0x3B, 0x97, 0x82, 0x5A, 0x48, 0x5C, 0x7B, 0x78, 0x09, 0x7F, 0x72, 0x00, 0x00, 0x3A, 0x5F, 0x16, 0x10, 0x4F, 0x40, 0x4B, 0x71, 0x43, 0x7A, 0x6A, 0x6B, 0x18, 0x2F, 0x36, 0x60, 0x4C, 0x00, 0x7E, 0x00, 0x7D, 0x52, 0x6D, 0x00, 0x38, 0x56, 0x32, 0x80, 0x00, 0x00, 0x00, 0x53, 0x30, 0x95, 0x00, 0x00, 0x00, 0x54, 0x3C, 0x7C, 0x92, 0x90, 0x91, 0x84, 0x34, 0x62, 0x00, 0x00, 0x00, 0x25, 0x26, 0x19, 0x1A, 0x00, 0x00, 0x93, 0x94, 0x8C, 0x8D, 0x74, 0x75, 0x00, 0x00, 0x1B, 0x1C, 0x8A, 0x8B, 0x27, 0x28, 0x85, 0x88, 0x87, 0x86, 0x42, 0x29, 0x17, 0x2E, 0x3D, 0x3E, 0x0D, 0x0E, 0x0F, 0x00, 0x55, 0x39, 0x33, 0x31, 0x57, 0x00, 0x00, 0x0A, 0x0B, 0x0C, 0x44, 0x00, 0x37, 0x61, 0x2A, 0x96, 0x8F, 0x81, 0x00, 0x00, 0x59, 0x00, 0x63, 0x5B, 0x00, 0x65, 0x24, 0x6E, 0x35, 0x69, 0x00, 0x5D, 0x3F, 0x41, 0x11, 0x12, 0x79, 0x01, 0x03, 0x49, 0x00, 0x76, 0x77, 0x00, 0x00, 0x00, 0x00, 0x4D, 0x4E, 0x13, 0x14, 0x21, 0x1E, 0x4A, 0x89, 0x8E, 0x00, 0x51, 0x00, 0x00, 0x04, 0x07, 0x05, 0x08, 0x06, 0x00, 0x00, 0x00, 0x00, 0x2B, 0x2C, 0x2D, 0x45, 0x46, 0x47, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; + private static ReadOnlySpan Table1NationalToInternal => new byte[] { 0x00, 0x99, 0x09, 0x9A, 0xB0, 0xB2, 0xB4, 0xB1, 0xB3, 0x1C, 0x7B, 0x7C, 0x7D, 0x70, 0x71, 0x72, 0x24, 0x96, 0x97, 0xA5, 0xA6, 0x05, 0x23, 0x6C, 0x2D, 0x54, 0x55, 0x60, 0x61, 0x0F, 0xA8, 0x10, 0x03, 0xA7, 0x07, 0x04, 0x8E, 0x52, 0x53, 0x64, 0x65, 0x6B, 0x82, 0xB9, 0xBA, 0xBB, 0x6D, 0x2E, 0x41, 0x77, 0x3B, 0x76, 0x4D, 0x90, 0x2F, 0x80, 0x39, 0x75, 0x21, 0x14, 0x47, 0x6E, 0x6F, 0x94, 0x26, 0x95, 0x6A, 0x29, 0x7E, 0xBC, 0xBD, 0xBE, 0x18, 0x9B, 0xA9, 0x27, 0x31, 0xA3, 0xA4, 0x25, 0x08, 0xAD, 0x36, 0x40, 0x46, 0x74, 0x3A, 0x78, 0x0D, 0x88, 0x17, 0x8B, 0x19, 0x93, 0x0E, 0x22, 0x30, 0x81, 0x4E, 0x8A, 0x06, 0x8D, 0x0C, 0x0A, 0x11, 0x91, 0x2B, 0x2C, 0x0B, 0x37, 0x8F, 0x12, 0x01, 0x28, 0x1E, 0x02, 0x5C, 0x5D, 0x9D, 0x9E, 0x1B, 0x98, 0x2A, 0x1A, 0x48, 0x35, 0x33, 0x1D, 0x3C, 0x85, 0x16, 0x13, 0x4C, 0x66, 0x69, 0x68, 0x67, 0xAA, 0x62, 0x63, 0x5A, 0x5B, 0xAB, 0x84, 0x4A, 0x4B, 0x49, 0x58, 0x59, 0x42, 0x83, 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; + private static ReadOnlySpan Table1InternalToNational => new byte[] { 0x00, 0x70, 0x73, 0x20, 0x23, 0x15, 0x64, 0x22, 0x50, 0x02, 0x67, 0x6C, 0x66, 0x58, 0x5E, 0x1D, 0x1F, 0x68, 0x6F, 0x83, 0x3B, 0x97, 0x82, 0x5A, 0x48, 0x5C, 0x7B, 0x78, 0x09, 0x7F, 0x72, 0x00, 0x00, 0x3A, 0x5F, 0x16, 0x10, 0x4F, 0x40, 0x4B, 0x71, 0x43, 0x7A, 0x6A, 0x6B, 0x18, 0x2F, 0x36, 0x60, 0x4C, 0x00, 0x7E, 0x00, 0x7D, 0x52, 0x6D, 0x00, 0x38, 0x56, 0x32, 0x80, 0x00, 0x00, 0x00, 0x53, 0x30, 0x95, 0x00, 0x00, 0x00, 0x54, 0x3C, 0x7C, 0x92, 0x90, 0x91, 0x84, 0x34, 0x62, 0x00, 0x00, 0x00, 0x25, 0x26, 0x19, 0x1A, 0x00, 0x00, 0x93, 0x94, 0x8C, 0x8D, 0x74, 0x75, 0x00, 0x00, 0x1B, 0x1C, 0x8A, 0x8B, 0x27, 0x28, 0x85, 0x88, 0x87, 0x86, 0x42, 0x29, 0x17, 0x2E, 0x3D, 0x3E, 0x0D, 0x0E, 0x0F, 0x00, 0x55, 0x39, 0x33, 0x31, 0x57, 0x00, 0x00, 0x0A, 0x0B, 0x0C, 0x44, 0x00, 0x37, 0x61, 0x2A, 0x96, 0x8F, 0x81, 0x00, 0x00, 0x59, 0x00, 0x63, 0x5B, 0x00, 0x65, 0x24, 0x6E, 0x35, 0x69, 0x00, 0x5D, 0x3F, 0x41, 0x11, 0x12, 0x79, 0x01, 0x03, 0x49, 0x00, 0x76, 0x77, 0x00, 0x00, 0x00, 0x00, 0x4D, 0x4E, 0x13, 0x14, 0x21, 0x1E, 0x4A, 0x89, 0x8E, 0x00, 0x51, 0x00, 0x00, 0x04, 0x07, 0x05, 0x08, 0x06, 0x00, 0x00, 0x00, 0x00, 0x2B, 0x2C, 0x2D, 0x45, 0x46, 0x47, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; + + // Use a static span to avoid allocations -- these delta tables shift between the two representations. + // Since most values are A<->A, we only need to store table values for those that are non-zero delta values. + private const int FirstUnalignedNational3 = Legal.MaxSpeciesID_2 + 1; // 252 + private const int FirstUnalignedInternal3 = 277; + + private const int FirstUnalignedNational9 = 917; + private const int FirstUnalignedInternal9 = FirstUnalignedNational9; /// - /// National Dex IDs (index) and the associated Gen3 Species IDs (value) + /// Difference of National Dex IDs (index) and the associated Gen3 Species IDs (value) /// - private static readonly ushort[] table3_Internal = + private static ReadOnlySpan Table3NationalToInternal => new sbyte[] { - 000, 001, 002, 003, 004, 005, 006, 007, 008, 009, 010, 011, 012, 013, 014, 015, 016, 017, 018, 019, - 020, 021, 022, 023, 024, 025, 026, 027, 028, 029, 030, 031, 032, 033, 034, 035, 036, 037, 038, 039, - 040, 041, 042, 043, 044, 045, 046, 047, 048, 049, 050, 051, 052, 053, 054, 055, 056, 057, 058, 059, - 060, 061, 062, 063, 064, 065, 066, 067, 068, 069, 070, 071, 072, 073, 074, 075, 076, 077, 078, 079, - 080, 081, 082, 083, 084, 085, 086, 087, 088, 089, 090, 091, 092, 093, 094, 095, 096, 097, 098, 099, - 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, - 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, - 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, - 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, - 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, - 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, - 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, - 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 277, 278, 279, 280, 281, 282, 283, 284, - 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, 295, 296, 297, 298, 299, 300, 304, 305, 309, 310, - 392, 393, 394, 311, 312, 306, 307, 364, 365, 366, 301, 302, 303, 370, 371, 372, 335, 336, 350, 320, - 315, 316, 322, 355, 382, 383, 384, 356, 357, 337, 338, 353, 354, 386, 387, 363, 367, 368, 330, 331, - 313, 314, 339, 340, 321, 351, 352, 308, 332, 333, 334, 344, 345, 358, 359, 380, 379, 348, 349, 323, - 324, 326, 327, 318, 319, 388, 389, 390, 391, 328, 329, 385, 317, 377, 378, 361, 362, 369, 411, 376, - 360, 346, 347, 341, 342, 343, 373, 374, 375, 381, 325, 395, 396, 397, 398, 399, 400, 401, 402, 403, - 407, 408, 404, 405, 406, 409, 410, + 025, 025, 025, 025, 025, 025, 025, 025, + 025, 025, 025, 025, 025, 025, 025, 025, 025, 025, + 025, 025, 025, 025, 025, 025, 028, 028, 031, 031, + 112, 112, 112, 028, 028, 021, 021, 077, 077, 077, + 011, 011, 011, 077, 077, 077, 039, 039, 052, 021, + 015, 015, 020, 052, 078, 078, 078, 049, 049, 028, + 028, 042, 042, 073, 073, 048, 051, 051, 012, 012, + -07, -07, 017, 017, -03, 026, 026, -19, 004, 004, + 004, 013, 013, 025, 025, 045, 043, 011, 011, -16, + -16, -15, -15, -25, -25, 043, 043, 043, 043, -21, + -21, 034, -35, 024, 024, 006, 006, 012, 053, 017, + 000, -15, -15, -22, -22, -22, 007, 007, 007, 012, + -45, 024, 024, 024, 024, 024, 024, 024, 024, 024, + 027, 027, 022, 022, 022, 024, 024, }; /// - /// Gen3 Species IDs (index) and the associated National Dex IDs (value) + /// Difference of Gen3 Species IDs (index) and the associated National Dex IDs (value) /// - private static readonly ushort[] table3_National = + private static ReadOnlySpan Table3InternalToNational => new sbyte[] { - 000, 001, 002, 003, 004, 005, 006, 007, 008, 009, 010, 011, 012, 013, 014, 015, 016, 017, 018, 019, - 020, 021, 022, 023, 024, 025, 026, 027, 028, 029, 030, 031, 032, 033, 034, 035, 036, 037, 038, 039, - 040, 041, 042, 043, 044, 045, 046, 047, 048, 049, 050, 051, 052, 053, 054, 055, 056, 057, 058, 059, - 060, 061, 062, 063, 064, 065, 066, 067, 068, 069, 070, 071, 072, 073, 074, 075, 076, 077, 078, 079, - 080, 081, 082, 083, 084, 085, 086, 087, 088, 089, 090, 091, 092, 093, 094, 095, 096, 097, 098, 099, - 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, - 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, - 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, - 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, - 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, - 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, - 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, - 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 000, 000, 000, 000, 000, 000, 000, 000, - 000, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000, 252, 253, 254, - 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, - 275, 290, 291, 292, 276, 277, 285, 286, 327, 278, 279, 283, 284, 320, 321, 300, 301, 352, 343, 344, - 299, 324, 302, 339, 340, 370, 341, 342, 349, 350, 318, 319, 328, 329, 330, 296, 297, 309, 310, 322, - 323, 363, 364, 365, 331, 332, 361, 362, 337, 338, 298, 325, 326, 311, 312, 303, 307, 308, 333, 334, - 360, 355, 356, 315, 287, 288, 289, 316, 317, 357, 293, 294, 295, 366, 367, 368, 359, 353, 354, 336, - 335, 369, 304, 305, 306, 351, 313, 314, 345, 346, 347, 348, 280, 281, 282, 371, 372, 373, 374, 375, - 376, 377, 378, 379, 382, 383, 384, 380, 381, 385, 386, 358, + -25, -25, -25, + -25, -25, -25, -25, -25, -25, -25, -25, -25, -25, + -25, -25, -25, -25, -25, -25, -25, -25, -25, -25, + -25, -11, -11, -11, -28, -28, -21, -21, 019, -31, + -31, -28, -28, 007, 007, -15, -15, 035, 025, 025, + -21, 003, -20, 016, 016, 045, 015, 015, 021, 021, + -12, -12, -04, -04, -04, -39, -39, -28, -28, -17, + -17, 022, 022, 022, -13, -13, 015, 015, -11, -11, + -52, -26, -26, -42, -42, -52, -49, -49, -25, -25, + 000, -06, -06, -48, -77, -77, -77, -51, -51, -12, + -77, -77, -77, -07, -07, -07, -17, -24, -24, -43, + -45, -12, -78, -78, -78, -34, -73, -73, -43, -43, + -43, -43,-112,-112,-112, -24, -24, -24, -24, -24, + -24, -24, -24, -24, -22, -22, -22, -27, -27, -24, + -24, -53, + }; + + /// + /// Difference of National Dex IDs (index) and the associated Gen9 Species IDs (value) + /// + private static ReadOnlySpan Table9NationalToInternal => new sbyte[] + { + 001, 001, 001, + 001, 033, 033, 033, 021, 021, 044, 044, 007, 007, + 007, 029, 031, 031, 031, 068, 068, 068, 002, 002, + 017, 017, 030, 030, 024, 024, 028, 028, 058, 058, + 012, -13, -13, -31, -31, -29, -29, 043, 043, 043, + -31, -31, -03, -30, -30, -23, -23, -14, -24, -03, + -03, -47, -47, -12, -27, -27, -44, -46, -26, 031, + 029, -53, -65, 025, -06, -03, -07, -04, -04, -08, + -04, 001, -03, -03, -06, -04, -47, -47, -47, -23, + -23, -05, -07, -09, -07, -20, -13, -09, -09, -29, + -23, + }; + + /// + /// Difference of Gen9 Species IDs (index) and the associated National Dex IDs (value) + /// + private static ReadOnlySpan Table9InternalToNational => new sbyte[] + { + 065, -01, -01, + -01, -01, 031, 031, 047, 047, 029, 029, 053, 031, + 031, 046, 044, 030, 030, -07, -07, -07, 013, 013, + -02, -02, 023, 023, 024, -21, -21, 027, 027, 047, + 047, 047, 026, 014, -33, -33, -33, -17, -17, 003, + -29, 012, -12, -31, -31, -31, 003, 003, -24, -24, + -44, -44, -30, -30, -28, -28, 023, 023, 006, 007, + 029, 008, 003, 004, 004, 020, 004, 023, 006, 003, + 003, 004, -01, 013, 009, 007, 005, 007, 009, 009, + -43, -43, -43, -68, -68, -68, -58, -58, -25, -29, + -31, }; } diff --git a/PKHeX.Core/PKM/Util/Conversion/TransporterLogic.cs b/PKHeX.Core/PKM/Util/Conversion/TransporterLogic.cs new file mode 100644 index 000000000..b911917aa --- /dev/null +++ b/PKHeX.Core/PKM/Util/Conversion/TransporterLogic.cs @@ -0,0 +1,34 @@ +using static PKHeX.Core.Species; + +namespace PKHeX.Core; + +/// +/// Logic rules for Pokémon Bank's Transporter functionality. +/// +public static class TransporterLogic +{ + /// + /// Checks if the must have its First ability rather than Hidden ability. + /// + /// For Generation 1 games transferring to Generation 7. + public static bool IsHiddenDisallowedVC1(ushort species) + { + System.Diagnostics.Debug.Assert(species <= Legal.MaxSpeciesID_1); + return species is (int)Gastly or (int)Haunter or (int)Gengar + or (int)Koffing or (int)Weezing + or (int)Mew; + } + + /// + /// Checks if the must have its First ability rather than Hidden ability. + /// + /// For Generation 2 games transferring to Generation 7. + public static bool IsHiddenDisallowedVC2(ushort species) + { + System.Diagnostics.Debug.Assert(species <= Legal.MaxSpeciesID_2); + return species is (int)Gastly or (int)Haunter or (int)Gengar + or (int)Koffing or (int)Weezing + or (int)Misdreavus or (int)Unown + or (int)Mew or (int)Celebi; + } +} diff --git a/PKHeX.Core/PKM/Util/EntityBlank.cs b/PKHeX.Core/PKM/Util/EntityBlank.cs index bc6cff589..4a356b248 100644 --- a/PKHeX.Core/PKM/Util/EntityBlank.cs +++ b/PKHeX.Core/PKM/Util/EntityBlank.cs @@ -18,7 +18,7 @@ public static class EntityBlank { var constructors = type.GetTypeInfo().DeclaredConstructors.Where(z => !z.IsStatic); var argCount = constructors.Min(z => z.GetParameters().Length); - return (PKM)Activator.CreateInstance(type, new object[argCount]); + return (PKM)(Activator.CreateInstance(type, new object[argCount]) ?? throw new ArgumentException(null, nameof(type))); } public static PKM GetBlank(int gen, GameVersion ver) => gen switch diff --git a/PKHeX.Core/PKM/Util/EntityFileExtension.cs b/PKHeX.Core/PKM/Util/EntityFileExtension.cs index 66f3586cc..2d9575096 100644 --- a/PKHeX.Core/PKM/Util/EntityFileExtension.cs +++ b/PKHeX.Core/PKM/Util/EntityFileExtension.cs @@ -50,12 +50,12 @@ public static class EntityFileExtension /// File extension. /// Preference if not a valid extension, usually the highest acceptable format. /// Format hint that the file is. - public static EntityContext GetContextFromExtension(string ext, EntityContext prefer = EntityContext.None) + public static EntityContext GetContextFromExtension(ReadOnlySpan ext, EntityContext prefer = EntityContext.None) { if (ext.Length == 0) return prefer; - static bool Is(string ext, string str) => ext.EndsWith(str, StringComparison.InvariantCultureIgnoreCase); + static bool Is(ReadOnlySpan ext, ReadOnlySpan str) => ext.EndsWith(str, StringComparison.InvariantCultureIgnoreCase); if (Is(ext, "b8")) return EntityContext.Gen8b; if (Is(ext, "k8")) return EntityContext.Gen8; if (Is(ext, "b7")) return EntityContext.Gen7b; diff --git a/PKHeX.Core/PKM/Util/EntityFileNamer.cs b/PKHeX.Core/PKM/Util/EntityFileNamer.cs index 5bd4015d5..189101f34 100644 --- a/PKHeX.Core/PKM/Util/EntityFileNamer.cs +++ b/PKHeX.Core/PKM/Util/EntityFileNamer.cs @@ -1,4 +1,6 @@ -namespace PKHeX.Core; +using System; + +namespace PKHeX.Core; public static class EntityFileNamer { @@ -29,23 +31,23 @@ public sealed class DefaultEntityNamer : IFileNamer private static string GetRegular(PKM pk) { - string form = pk.Form > 0 ? $"-{pk.Form:00}" : string.Empty; - string star = pk.IsShiny ? " ★" : string.Empty; - var chk = pk is ISanityChecksum s ? s.Checksum : PokeCrypto.GetCHK(pk.Data, pk.SIZE_STORED); + var chk = pk is ISanityChecksum s ? s.Checksum : PokeCrypto.GetCHK(pk.Data.AsSpan()[8..pk.SIZE_STORED]); + var form = pk.Form != 0 ? $"-{pk.Form:00}" : string.Empty; + var star = pk.IsShiny ? " ★" : string.Empty; return $"{pk.Species:000}{form}{star} - {pk.Nickname} - {chk:X4}{pk.EncryptionConstant:X8}"; } private static string GetGBPKM(GBPKM gb) { - string form = gb.Form > 0 ? $"-{gb.Form:00}" : string.Empty; - string star = gb.IsShiny ? " ★" : string.Empty; - var raw = gb switch + ReadOnlySpan raw = gb switch { PK1 pk1 => new PokeList1(pk1).Write(), PK2 pk2 => new PokeList2(pk2).Write(), _ => gb.Data, }; var checksum = Checksums.CRC16_CCITT(raw); + var form = gb.Form != 0 ? $"-{gb.Form:00}" : string.Empty; + var star = gb.IsShiny ? " ★" : string.Empty; return $"{gb.Species:000}{form}{star} - {gb.Nickname} - {checksum:X4}"; } } diff --git a/PKHeX.Core/PKM/Util/EntityFormat.cs b/PKHeX.Core/PKM/Util/EntityFormat.cs index e07278651..e8f5de319 100644 --- a/PKHeX.Core/PKM/Util/EntityFormat.cs +++ b/PKHeX.Core/PKM/Util/EntityFormat.cs @@ -58,7 +58,7 @@ public static class EntityFormat return true; } - if (ReadUInt16LittleEndian(data[0x06..]) == GetCHK(data, SIZE_6STORED)) + if (ReadUInt16LittleEndian(data[0x06..]) == GetCHK(data[8..SIZE_6STORED])) return true; // decrypted return false; } diff --git a/PKHeX.Core/PKM/Util/EntityGender.cs b/PKHeX.Core/PKM/Util/EntityGender.cs index bcafa0b90..667effa25 100644 --- a/PKHeX.Core/PKM/Util/EntityGender.cs +++ b/PKHeX.Core/PKM/Util/EntityGender.cs @@ -1,3 +1,5 @@ +using System; + namespace PKHeX.Core; public static class EntityGender @@ -7,7 +9,7 @@ public static class EntityGender /// /// Gender string /// Gender integer - public static int GetFromString(string s) + public static int GetFromString(ReadOnlySpan s) { if (s.Length != 1) return 2; @@ -33,11 +35,11 @@ public static class EntityGender /// This method should only be used for Generations 3-5 origin. public static int GetFromPID(ushort species, uint pid) { - int gt = PKX.Personal[species].Gender; + var gt = PKX.Personal[species].Gender; return GetFromPIDAndRatio(pid, gt); } - public static int GetFromPIDAndRatio(uint pid, int gr) => gr switch + public static int GetFromPIDAndRatio(uint pid, byte gr) => gr switch { PersonalInfo.RatioMagicGenderless => 2, PersonalInfo.RatioMagicFemale => 1, diff --git a/PKHeX.Core/PKM/Util/EntitySorting.cs b/PKHeX.Core/PKM/Util/EntitySorting.cs index aa448b7ea..a92db5572 100644 --- a/PKHeX.Core/PKM/Util/EntitySorting.cs +++ b/PKHeX.Core/PKM/Util/EntitySorting.cs @@ -217,8 +217,8 @@ public static class EntitySorting { return list.ThenBy(p => p.OT_Name) .ThenBy(p => p.OT_Gender) - .ThenBy(p => p.TID) - .ThenBy(p => p.SID); + .ThenBy(p => p.TID16) + .ThenBy(p => p.SID16); } /// @@ -234,7 +234,7 @@ public static class EntitySorting return pk.CurrentHandler != 1; if (checkGame && trainer.Game != pk.Version) return false; - if (trainer.TID != pk.TID || trainer.SID != pk.SID) + if (trainer.TID16 != pk.TID16 || trainer.SID16 != pk.SID16) return false; if (trainer.Gender != pk.OT_Gender) return false; diff --git a/PKHeX.Core/PKM/Util/Language.cs b/PKHeX.Core/PKM/Util/Language.cs index b651c52db..d3ab01ca1 100644 --- a/PKHeX.Core/PKM/Util/Language.cs +++ b/PKHeX.Core/PKM/Util/Language.cs @@ -8,7 +8,7 @@ namespace PKHeX.Core; /// public static class Language { - private static readonly byte[] Languages = + private static ReadOnlySpan Languages => new[] { (byte)Japanese, (byte)English, @@ -25,8 +25,8 @@ public static class Language }; // check Korean for the VC case, never possible to match string outside of this case - private static ReadOnlySpan Languages_GB => Languages.AsSpan(0, 7); // [..KOR] - private static ReadOnlySpan Languages_3 => Languages.AsSpan(0, 6); // [..KOR) + private static ReadOnlySpan Languages_GB => Languages[..7]; // [..KOR] + private static ReadOnlySpan Languages_3 => Languages[..6]; // [..KOR) private const LanguageID SafeLanguage = English; public static ReadOnlySpan GetAvailableGameLanguages(int generation = PKX.Generation) => generation switch diff --git a/PKHeX.Core/PKM/Util/PokeCrypto.cs b/PKHeX.Core/PKM/Util/PokeCrypto.cs index a1728ddfb..74a7d283e 100644 --- a/PKHeX.Core/PKM/Util/PokeCrypto.cs +++ b/PKHeX.Core/PKM/Util/PokeCrypto.cs @@ -59,7 +59,7 @@ public static class PokeCrypto /// /// Positions for shuffling. /// - private static readonly byte[] BlockPosition = + private static ReadOnlySpan BlockPosition => new byte[] { 0, 1, 2, 3, 0, 1, 3, 2, @@ -100,7 +100,7 @@ public static class PokeCrypto /// /// Positions for unshuffling. /// - internal static readonly byte[] blockPositionInvert = + private static ReadOnlySpan blockPositionInvert => new byte[] { 0, 1, 2, 4, 3, 5, 6, 7, 12, 18, 13, 19, 8, 10, 14, 20, 16, 22, 9, 11, 15, 21, 17, 23, 0, 1, 2, 4, 3, 5, 6, 7, // duplicates of 0-7 to eliminate modulus @@ -117,7 +117,7 @@ public static class PokeCrypto public static byte[] ShuffleArray(ReadOnlySpan data, uint sv, int blockSize) { byte[] sdata = data.ToArray(); - uint index = sv * 4; + int index = (int)sv * 4; const int start = 8; for (int block = 0; block < 4; block++) { @@ -183,7 +183,7 @@ public static class PokeCrypto uint pv = ReadUInt32LittleEndian(pk); uint sv = (pv >> 13) & 31; - byte[] ekm = ShuffleArray(pk, blockPositionInvert[sv], SIZE_8BLOCK); + byte[] ekm = ShuffleArray(pk, blockPositionInvert[(int)sv], SIZE_8BLOCK); CryptPKM(ekm, pv, SIZE_8BLOCK); return ekm; } @@ -197,7 +197,7 @@ public static class PokeCrypto uint pv = ReadUInt32LittleEndian(pk); uint sv = (pv >> 13) & 31; - byte[] ekm = ShuffleArray(pk, blockPositionInvert[sv], SIZE_8ABLOCK); + byte[] ekm = ShuffleArray(pk, blockPositionInvert[(int)sv], SIZE_8ABLOCK); CryptPKM(ekm, pv, SIZE_8ABLOCK); return ekm; } @@ -211,7 +211,7 @@ public static class PokeCrypto uint pv = ReadUInt32LittleEndian(pk); uint sv = (pv >> 13) & 31; - byte[] ekm = ShuffleArray(pk, blockPositionInvert[sv], SIZE_9BLOCK); + byte[] ekm = ShuffleArray(pk, blockPositionInvert[(int)sv], SIZE_9BLOCK); CryptPKM(ekm, pv, SIZE_9BLOCK); return ekm; } @@ -240,7 +240,7 @@ public static class PokeCrypto uint pv = ReadUInt32LittleEndian(pk); uint sv = (pv >> 13) & 31; - byte[] ekm = ShuffleArray(pk, blockPositionInvert[sv], SIZE_6BLOCK); + byte[] ekm = ShuffleArray(pk, blockPositionInvert[(int)sv], SIZE_6BLOCK); CryptPKM(ekm, pv, SIZE_6BLOCK); return ekm; } @@ -271,7 +271,7 @@ public static class PokeCrypto uint chk = ReadUInt16LittleEndian(pk[6..]); uint sv = (pv >> 13) & 31; - byte[] ekm = ShuffleArray(pk, blockPositionInvert[sv], SIZE_4BLOCK); + byte[] ekm = ShuffleArray(pk, blockPositionInvert[(int)sv], SIZE_4BLOCK); CryptPKM45(ekm, pv, chk, SIZE_4BLOCK); return ekm; } @@ -297,7 +297,7 @@ public static class PokeCrypto { uint pv = ReadUInt32BigEndian(pk); uint sv = (pv >> 13) & 31; - return ShuffleArray(pk, blockPositionInvert[sv], SIZE_4BLOCK); + return ShuffleArray(pk, blockPositionInvert[(int)sv], SIZE_4BLOCK); } [MethodImpl(MethodImplOptions.AggressiveInlining)] @@ -367,7 +367,7 @@ public static class PokeCrypto private static byte[] ShuffleArray3(ReadOnlySpan data, uint sv) { byte[] sdata = data.ToArray(); - uint index = sv * 4; + int index = (int)sv * 4; for (int block = 0; block < 4; block++) { int ofs = BlockPosition[index + block]; @@ -392,7 +392,7 @@ public static class PokeCrypto uint OID = ReadUInt32LittleEndian(pk[4..]); uint seed = PID ^ OID; - byte[] ekm = ShuffleArray3(pk, blockPositionInvert[PID % 24]); + byte[] ekm = ShuffleArray3(pk, blockPositionInvert[(int)(PID % 24)]); var toEncrypt = ekm.AsSpan()[SIZE_3HEADER..SIZE_3STORED]; for (int i = 0; i < toEncrypt.Length; i += 4) @@ -406,16 +406,14 @@ public static class PokeCrypto } /// - /// Gets the checksum of a 232 byte array. + /// Gets the 16-bit checksum of a byte array. /// /// Decrypted Pokémon data. - /// Offset at which the Stored data ends and the Party data starts. - public static ushort GetCHK(ReadOnlySpan data, int partyStart) + public static ushort GetCHK(ReadOnlySpan data) { ushort chk = 0; - var span = data[0x08..partyStart]; - for (int i = 0; i < span.Length; i += 2) - chk += ReadUInt16LittleEndian(span[i..]); + for (int i = 0; i < data.Length; i += 2) + chk += ReadUInt16LittleEndian(data[i..]); return chk; } @@ -424,14 +422,7 @@ public static class PokeCrypto /// /// Decrypted Pokémon data. [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static ushort GetCHK3(ReadOnlySpan data) - { - ushort chk = 0; - var span = data[0x20..SIZE_3STORED]; - for (int i = 0; i < span.Length; i += 2) - chk += ReadUInt16LittleEndian(span[i..]); - return chk; - } + public static ushort GetCHK3(ReadOnlySpan data) => GetCHK(data[0x20..SIZE_3STORED]); /// /// Decrypts the input data into a new array if it is encrypted, and updates the reference. diff --git a/PKHeX.Core/PKM/Util/SpeciesName.cs b/PKHeX.Core/PKM/Util/SpeciesName.cs index 2f6f1984a..afc372986 100644 --- a/PKHeX.Core/PKM/Util/SpeciesName.cs +++ b/PKHeX.Core/PKM/Util/SpeciesName.cs @@ -68,7 +68,7 @@ public static class SpeciesName return EggNames[language]; var arr = SpeciesLang[language]; - if ((uint)species >= arr.Count) + if (species >= arr.Count) return string.Empty; return arr[species]; @@ -104,7 +104,7 @@ public static class SpeciesName if (species == 0) return GetEggName1234(species, language, generation); - string nick = GetSpeciesName(species, language); + var nick = GetSpeciesName(species, language); switch (language) { case (int)LanguageID.Korean when generation == 2: @@ -115,7 +115,7 @@ public static class SpeciesName } Span result = stackalloc char[nick.Length]; - nick.AsSpan().CopyTo(result); + nick.CopyTo(result); // All names are uppercase. for (int i = 0; i < result.Length; i++) @@ -125,7 +125,7 @@ public static class SpeciesName // Gen1/2 species names do not have spaces. if (generation >= 3) - return new string(result.ToArray()); + return new string(result); int indexSpace = result.IndexOf(' '); if (indexSpace != -1) @@ -134,7 +134,7 @@ public static class SpeciesName result[(indexSpace+1)..].CopyTo(result[indexSpace..]); result = result[..^1]; } - return new string(result.ToArray()); + return new string(result); } private static string GetEggName1234(ushort species, int language, int generation) @@ -193,7 +193,7 @@ public static class SpeciesName /// Current name /// Generation specific formatting option /// True if it does not match any language name, False if not nicknamed - public static bool IsNicknamedAnyLanguage(ushort species, string nickname, int generation = LatestGeneration) + public static bool IsNicknamedAnyLanguage(ushort species, ReadOnlySpan nickname, int generation = LatestGeneration) { var langs = Language.GetAvailableGameLanguages(generation); foreach (var language in langs) @@ -212,9 +212,10 @@ public static class SpeciesName /// Language ID of the Pokémon /// Generation specific formatting option /// True if it does not match the language name, False if not nicknamed (matches). - public static bool IsNicknamed(ushort species, string nickname, int language, int generation = LatestGeneration) + public static bool IsNicknamed(ushort species, ReadOnlySpan nickname, int language, int generation = LatestGeneration) { - return GetSpeciesNameGeneration(species, language, generation) != nickname; + var expect = GetSpeciesNameGeneration(species, language, generation); + return !nickname.SequenceEqual(expect); } /// @@ -225,13 +226,14 @@ public static class SpeciesName /// Current name /// Generation specific formatting option /// Language ID if it does not match any language name, -1 if no matches - public static int GetSpeciesNameLanguage(ushort species, int priorityLanguage, string nickname, int generation = LatestGeneration) + public static int GetSpeciesNameLanguage(ushort species, int priorityLanguage, ReadOnlySpan nickname, int generation = LatestGeneration) { var langs = Language.GetAvailableGameLanguages(generation); var priorityIndex = langs.IndexOf((byte)priorityLanguage); if (priorityIndex != -1) { - if (GetSpeciesNameGeneration(species, priorityLanguage, generation) == nickname) + var expect = GetSpeciesNameGeneration(species, priorityLanguage, generation); + if (nickname.SequenceEqual(expect)) return priorityLanguage; } @@ -245,17 +247,18 @@ public static class SpeciesName /// Current name /// Generation specific formatting option /// Language ID if it does not match any language name, -1 if no matches - public static int GetSpeciesNameLanguage(ushort species, string nickname, int generation = LatestGeneration) + public static int GetSpeciesNameLanguage(ushort species, ReadOnlySpan nickname, int generation = LatestGeneration) { var langs = Language.GetAvailableGameLanguages(generation); return GetSpeciesNameLanguage(species, nickname, generation, langs); } - private static int GetSpeciesNameLanguage(ushort species, string nickname, int generation, ReadOnlySpan langs) + private static int GetSpeciesNameLanguage(ushort species, ReadOnlySpan nickname, int generation, ReadOnlySpan langs) { foreach (var lang in langs) { - if (GetSpeciesNameGeneration(species, lang, generation) == nickname) + var expect = GetSpeciesNameGeneration(species, lang, generation); + if (nickname.SequenceEqual(expect)) return lang; } return -1; diff --git a/PKHeX.Core/PKM/XK3.cs b/PKHeX.Core/PKM/XK3.cs index dda656d4c..366b219e4 100644 --- a/PKHeX.Core/PKM/XK3.cs +++ b/PKHeX.Core/PKM/XK3.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Numerics; using static System.Buffers.Binary.BinaryPrimitives; namespace PKHeX.Core; @@ -20,10 +21,10 @@ public sealed class XK3 : G3PKM, IShadowCapture public override int SIZE_PARTY => PokeCrypto.SIZE_3XSTORED; public override int SIZE_STORED => PokeCrypto.SIZE_3XSTORED; public override EntityContext Context => EntityContext.Gen3; - public override PersonalInfo PersonalInfo => PersonalTable.RS[Species]; + public override PersonalInfo3 PersonalInfo => PersonalTable.RS[Species]; public XK3(byte[] data) : base(data) { } public XK3() : base(PokeCrypto.SIZE_3XSTORED) { } - public override PKM Clone() => new XK3((byte[])Data.Clone()){Purification = Purification}; + public override XK3 Clone() => new((byte[])Data.Clone()) { Purification = Purification }; public override void RefreshChecksum() => Valid = true; // Trash Bytes @@ -31,8 +32,8 @@ public sealed class XK3 : G3PKM, IShadowCapture public override Span Nickname_Trash => Data.AsSpan(0x4E, 22); public Span NicknameCopy_Trash => Data.AsSpan(0x64, 22); - public override ushort SpeciesID3 { get => ReadUInt16BigEndian(Data.AsSpan(0x00)); set => WriteUInt16BigEndian(Data.AsSpan(0x00), value); } // raw access - public override ushort Species { get => SpeciesConverter.GetG4Species(SpeciesID3); set => SpeciesID3 = SpeciesConverter.GetG3Species(value); } + public override ushort SpeciesInternal { get => ReadUInt16BigEndian(Data.AsSpan(0x00)); set => WriteUInt16BigEndian(Data.AsSpan(0x00), value); } // raw access + public override ushort Species { get => SpeciesConverter.GetNational3(SpeciesInternal); set => SpeciesInternal = SpeciesConverter.GetInternal3(value); } public override int SpriteItem => ItemConverter.GetItemFuture3((ushort)HeldItem); public override int HeldItem { get => ReadUInt16BigEndian(Data.AsSpan(0x02)); set => WriteUInt16BigEndian(Data.AsSpan(0x02), (ushort)value); } public override int Stat_HPCurrent { get => ReadUInt16BigEndian(Data.AsSpan(0x04)); set => WriteUInt16BigEndian(Data.AsSpan(0x04), (ushort)value); } @@ -60,8 +61,9 @@ public sealed class XK3 : G3PKM, IShadowCapture public override bool IsEgg { get => (XDPKMFLAGS & (1 << 7)) == 1 << 7; set => XDPKMFLAGS = (XDPKMFLAGS & ~(1 << 7)) | (value ? 1 << 7 : 0); } // 0x1E-0x1F Unknown public override uint EXP { get => ReadUInt32BigEndian(Data.AsSpan(0x20)); set => WriteUInt32BigEndian(Data.AsSpan(0x20), value); } - public override int SID { get => ReadUInt16BigEndian(Data.AsSpan(0x24)); set => WriteUInt16BigEndian(Data.AsSpan(0x24), (ushort)value); } - public override int TID { get => ReadUInt16BigEndian(Data.AsSpan(0x26)); set => WriteUInt16BigEndian(Data.AsSpan(0x26), (ushort)value); } + public override uint ID32 { get => ReadUInt32BigEndian(Data.AsSpan(0x24)); set => WriteUInt32BigEndian(Data.AsSpan(0x24), value); } + public override ushort SID16 { get => ReadUInt16BigEndian(Data.AsSpan(0x24)); set => WriteUInt16BigEndian(Data.AsSpan(0x24), value); } + public override ushort TID16 { get => ReadUInt16BigEndian(Data.AsSpan(0x26)); set => WriteUInt16BigEndian(Data.AsSpan(0x26), value); } public override uint PID { get => ReadUInt32BigEndian(Data.AsSpan(0x28)); set => WriteUInt32BigEndian(Data.AsSpan(0x28), value); } // 0x2A-0x2B Unknown // 0x2C-0x2F Battle Related @@ -88,9 +90,9 @@ public sealed class XK3 : G3PKM, IShadowCapture public int CurrentRegion { get => Data[0x35]; set => Data[0x35] = (byte)value; } public int OriginalRegion { get => Data[0x36]; set => Data[0x36] = (byte)value; } public override int Language { get => Core.Language.GetMainLangIDfromGC(Data[0x37]); set => Data[0x37] = Core.Language.GetGCLangIDfromMain((byte)value); } - public override string OT_Name { get => StringConverter3GC.GetString(OT_Trash); set => StringConverter3GC.SetString(OT_Trash, value.AsSpan(), 10, StringConverterOption.None); } - public override string Nickname { get => StringConverter3GC.GetString(Nickname_Trash); set { StringConverter3GC.SetString(Nickname_Trash, value.AsSpan(), 10, StringConverterOption.None); NicknameCopy = value; } } - public string NicknameCopy { get => StringConverter3GC.GetString(NicknameCopy_Trash); set => StringConverter3GC.SetString(NicknameCopy_Trash, value.AsSpan(), 10, StringConverterOption.None); } + public override string OT_Name { get => StringConverter3GC.GetString(OT_Trash); set => StringConverter3GC.SetString(OT_Trash, value, 10, StringConverterOption.None); } + public override string Nickname { get => StringConverter3GC.GetString(Nickname_Trash); set { StringConverter3GC.SetString(Nickname_Trash, value, 10, StringConverterOption.None); NicknameCopy = value; } } + public string NicknameCopy { get => StringConverter3GC.GetString(NicknameCopy_Trash); set => StringConverter3GC.SetString(NicknameCopy_Trash, value, 10, StringConverterOption.None); } // 0x7A-0x7B Unknown private ushort RIB0 { get => ReadUInt16BigEndian(Data.AsSpan(0x7C)); set => WriteUInt16BigEndian(Data.AsSpan(0x7C), value); } public override bool RibbonChampionG3 { get => (RIB0 & (1 << 15)) == 1 << 15; set => RIB0 = (ushort)((RIB0 & ~(1 << 15)) | (value ? 1 << 15 : 0)); } @@ -109,6 +111,7 @@ public sealed class XK3 : G3PKM, IShadowCapture public override bool Unused2 { get => (RIB0 & (1 << 02)) == 1 << 02; set => RIB0 = (ushort)((RIB0 & ~(1 << 02)) | (value ? 1 << 02 : 0)); } public override bool Unused3 { get => (RIB0 & (1 << 01)) == 1 << 01; set => RIB0 = (ushort)((RIB0 & ~(1 << 01)) | (value ? 1 << 01 : 0)); } public override bool Unused4 { get => (RIB0 & (1 << 00)) == 1 << 00; set => RIB0 = (ushort)((RIB0 & ~(1 << 00)) | (value ? 1 << 00 : 0)); } + public override int RibbonCount => BitOperations.PopCount((uint)(RIB0 & 0b1111_1111_1111_0000)) + RibbonCountG3Cool + RibbonCountG3Beauty + RibbonCountG3Cute + RibbonCountG3Smart + RibbonCountG3Tough; // 0x7E-0x7F Unknown // Moves @@ -221,7 +224,7 @@ public sealed class XK3 : G3PKM, IShadowCapture pk.FatefulEncounter = true; } } - pk.FlagHasSpecies = pk.SpeciesID3 != 0; // Update Flag + pk.FlagHasSpecies = pk.SpeciesInternal != 0; // Update Flag pk.RefreshChecksum(); return pk; } diff --git a/PKHeX.Core/PersonalInfo/Info/PersonalInfo1.cs b/PKHeX.Core/PersonalInfo/Info/PersonalInfo1.cs index 46f713a73..a2392d086 100644 --- a/PKHeX.Core/PersonalInfo/Info/PersonalInfo1.cs +++ b/PKHeX.Core/PersonalInfo/Info/PersonalInfo1.cs @@ -5,24 +5,15 @@ namespace PKHeX.Core; /// /// class with values from Generation 1 games. /// -public sealed class PersonalInfo1 : PersonalInfo +public sealed class PersonalInfo1 : PersonalInfo, IPersonalInfoTM { public const int SIZE = 0x1C; private readonly byte[] Data; - public PersonalInfo1(byte[] data) - { - Data = data; - TMHM = GetBits(Data.AsSpan(0x14, 0x8)); - } + public PersonalInfo1(byte[] data) => Data = data; + public override byte[] Write() => Data; - public override byte[] Write() - { - SetBits(TMHM, Data.AsSpan(0x14)); - return Data; - } - - public override int Gender { get => Data[0x00]; set => Data[0x00] = (byte)value; } + public override byte Gender { get => Data[0x00]; set => Data[0x00] = value; } public override int HP { get => Data[0x01]; set => Data[0x01] = (byte)value; } public override int ATK { get => Data[0x02]; set => Data[0x02] = (byte)value; } public override int DEF { get => Data[0x03]; set => Data[0x03] = (byte)value; } @@ -67,4 +58,35 @@ public sealed class PersonalInfo1 : PersonalInfo value[1] = Move2; value[0] = Move1; } + + private const int TMHM = 0x14; + private const int CountTMHM = 50 + 5; // 50 TMs, 5 HMs + private const int ByteCountTM = (CountTMHM + 7) / 8; + + public bool GetIsLearnTM(int index) + { + if ((uint)index >= CountTMHM) + return false; + return (Data[TMHM + (index >> 3)] & (1 << (index & 7))) != 0; + } + + public void SetIsLearnTM(int index, bool value) + { + if ((uint)index >= CountTMHM) + return; + if (value) + Data[TMHM + (index >> 3)] |= (byte)(1 << (index & 7)); + else + Data[TMHM + (index >> 3)] &= (byte)~(1 << (index & 7)); + } + + public void SetAllLearnTM(Span result, ReadOnlySpan moves) + { + var span = Data.AsSpan(TMHM, ByteCountTM); + for (int index = CountTMHM - 1; index >= 0; index--) + { + if ((span[index >> 3] & (1 << (index & 7))) != 0) + result[moves[index]] = true; + } + } } diff --git a/PKHeX.Core/PersonalInfo/Info/PersonalInfo2.cs b/PKHeX.Core/PersonalInfo/Info/PersonalInfo2.cs index 499d25a5b..efda1adb5 100644 --- a/PKHeX.Core/PersonalInfo/Info/PersonalInfo2.cs +++ b/PKHeX.Core/PersonalInfo/Info/PersonalInfo2.cs @@ -1,27 +1,17 @@ using System; -using System.Collections.Generic; namespace PKHeX.Core; /// /// class with values from Generation 2 games. /// -public sealed class PersonalInfo2 : PersonalInfo +public sealed class PersonalInfo2 : PersonalInfo, IPersonalInfoTM, IPersonalInfoTutorType { public const int SIZE = 0x20; private readonly byte[] Data; - public PersonalInfo2(byte[] data) - { - Data = data; - TMHM = GetBits(Data.AsSpan(0x18, 0x8)); - } - - public override byte[] Write() - { - SetBits(TMHM, Data.AsSpan(0x18)); - return Data; - } + public PersonalInfo2(byte[] data) => Data = data; + public override byte[] Write() => Data; public int DEX_ID { get => Data[0x00]; set => Data[0x00] = (byte)value; } public override int HP { get => Data[0x01]; set => Data[0x01] = (byte)value; } @@ -36,23 +26,12 @@ public sealed class PersonalInfo2 : PersonalInfo public override int BaseEXP { get => Data[0x0A]; set => Data[0x0A] = (byte)value; } public int Item1 { get => Data[0xB]; set => Data[0xB] = (byte)value; } public int Item2 { get => Data[0xC]; set => Data[0xC] = (byte)value; } - public override int Gender { get => Data[0xD]; set => Data[0xD] = (byte)value; } + public override byte Gender { get => Data[0xD]; set => Data[0xD] = value; } public override int HatchCycles { get => Data[0xF]; set => Data[0xF] = (byte)value; } public override byte EXPGrowth { get => Data[0x16]; set => Data[0x16] = value; } public override int EggGroup1 { get => Data[0x17] & 0xF; set => Data[0x17] = (byte)((Data[0x17] & 0xF0) | value); } public override int EggGroup2 { get => Data[0x17] >> 4; set => Data[0x17] = (byte)((Data[0x17] & 0x0F) | (value << 4)); } - public IReadOnlyList Items - { - get => new[] { Item1, Item2 }; - set - { - if (value.Count != 2) return; - Item1 = value[0]; - Item2 = value[1]; - } - } - // EV Yields are just aliases for base stats in Gen II public override int EV_HP { get => HP; set { } } public override int EV_ATK { get => ATK; set { } } @@ -68,4 +47,67 @@ public sealed class PersonalInfo2 : PersonalInfo public override int BaseFriendship { get => 70; set { } } public override int EscapeRate { get => 0; set { } } public override int Color { get => 0; set { } } + + private const int TMHM = 0x18; + private const int CountTMHM = 50 + 7; // 50 TMs, 7 HMs + private const int ByteCountTM = 8; + + public bool GetIsLearnTM(int index) + { + if ((uint)index >= CountTMHM) + return false; + return (Data[TMHM + (index >> 3)] & (1 << (index & 7))) != 0; + } + + public void SetIsLearnTM(int index, bool value) + { + if ((uint)index >= CountTMHM) + return; + if (value) + Data[TMHM + (index >> 3)] |= (byte)(1 << (index & 7)); + else + Data[TMHM + (index >> 3)] &= (byte)~(1 << (index & 7)); + } + + public void SetAllLearnTM(Span result, ReadOnlySpan moves) + { + var span = Data.AsSpan(TMHM, ByteCountTM); + for (int index = CountTMHM - 1; index >= 0; index--) + { + if ((span[index >> 3] & (1 << (index & 7))) != 0) + result[moves[index]] = true; + } + } + + private const int TutorTypeCount = 3; + + public bool GetIsLearnTutorType(int index) + { + if ((uint)index >= TutorTypeCount) + return false; + index += CountTMHM; + return (Data[TMHM + (index >> 3)] & (1 << (index & 7))) != 0; + } + + public void SetIsLearnTutorType(int index, bool value) + { + if ((uint)index >= TutorTypeCount) + throw new ArgumentOutOfRangeException(nameof(index), index, null); + index += CountTMHM; + if (value) + Data[TMHM + (index >> 3)] |= (byte)(1 << (index & 7)); + else + Data[TMHM + (index >> 3)] &= (byte)~(1 << (index & 7)); + } + + public void SetAllLearnTutorType(Span result, ReadOnlySpan moves) + { + var span = Data.AsSpan(TMHM, ByteCountTM); + for (int index = TutorTypeCount - 1; index >= 0; index--) + { + var i = index + CountTMHM; + if ((span[i >> 3] & (1 << (i & 7))) != 0) + result[moves[index]] = true; + } + } } diff --git a/PKHeX.Core/PersonalInfo/Info/PersonalInfo3.cs b/PKHeX.Core/PersonalInfo/Info/PersonalInfo3.cs index 449ce0f1a..cef163ee9 100644 --- a/PKHeX.Core/PersonalInfo/Info/PersonalInfo3.cs +++ b/PKHeX.Core/PersonalInfo/Info/PersonalInfo3.cs @@ -34,7 +34,7 @@ public sealed class PersonalInfo3 : PersonalInfo, IPersonalAbility12 public override int EV_SPD { get => (EVYield >> 10) & 0x3; set => EVYield = (EVYield & ~(0x3 << 10)) | ((value & 0x3) << 10); } public int Item1 { get => ReadInt16LittleEndian(Data.AsSpan(0xC)); set => WriteInt16LittleEndian(Data.AsSpan(0xC), (short)value); } public int Item2 { get => ReadInt16LittleEndian(Data.AsSpan(0xE)); set => WriteInt16LittleEndian(Data.AsSpan(0xE), (short)value); } - public override int Gender { get => Data[0x10]; set => Data[0x10] = (byte)value; } + public override byte Gender { get => Data[0x10]; set => Data[0x10] = value; } public override int HatchCycles { get => Data[0x11]; set => Data[0x11] = (byte)value; } public override int BaseFriendship { get => Data[0x12]; set => Data[0x12] = (byte)value; } public override byte EXPGrowth { get => Data[0x13]; set => Data[0x13] = value; } @@ -57,4 +57,24 @@ public sealed class PersonalInfo3 : PersonalInfo, IPersonalAbility12 public int GetAbility(bool second) => second && HasSecondAbility ? Ability2 : Ability1; public bool HasSecondAbility => Ability1 != Ability2; + + public void AddTMHM(ReadOnlySpan data) => TMHM = FlagUtil.GitBitFlagArray(data); + + public void AddTypeTutors(ReadOnlySpan data) => TypeTutors = FlagUtil.GitBitFlagArray(data); + + /// + /// TM/HM learn compatibility flags for individual moves. + /// + public bool[] TMHM { get; private set; } = Array.Empty(); + + /// + /// Grass-Fire-Water-Etc typed learn compatibility flags for individual moves. + /// + public bool[] TypeTutors { get; private set; } = Array.Empty(); + + public void CopyFrom(PersonalInfo3 other) + { + TMHM = other.TMHM; + TypeTutors = other.TypeTutors; + } } diff --git a/PKHeX.Core/PersonalInfo/Info/PersonalInfo4.cs b/PKHeX.Core/PersonalInfo/Info/PersonalInfo4.cs index c1363a0b2..467a90ee2 100644 --- a/PKHeX.Core/PersonalInfo/Info/PersonalInfo4.cs +++ b/PKHeX.Core/PersonalInfo/Info/PersonalInfo4.cs @@ -6,24 +6,13 @@ namespace PKHeX.Core; /// /// class with values from Generation 4 games. /// -public sealed class PersonalInfo4 : PersonalInfo, IPersonalAbility12 +public sealed class PersonalInfo4 : PersonalInfo, IPersonalAbility12, IPersonalInfoTM, IPersonalInfoTutorType { public const int SIZE = 0x2C; private readonly byte[] Data; - public PersonalInfo4(byte[] data) - { - Data = data; - // Unpack TMHM & Tutors - TMHM = GetBits(Data.AsSpan(0x1C, 0x0D)); - //TypeTutors = Array.Empty(); // not stored in personal -- default value - } - - public override byte[] Write() - { - SetBits(TMHM, Data.AsSpan(0x1C)); - return Data; - } + public PersonalInfo4(byte[] data) => Data = data; + public override byte[] Write() => Data; public override int HP { get => Data[0x00]; set => Data[0x00] = (byte)value; } public override int ATK { get => Data[0x01]; set => Data[0x01] = (byte)value; } @@ -44,7 +33,7 @@ public sealed class PersonalInfo4 : PersonalInfo, IPersonalAbility12 public override int EV_SPD { get => (EVYield >> 10) & 0x3; set => EVYield = (EVYield & ~(0x3 << 10)) | ((value & 0x3) << 10); } public int Item1 { get => ReadInt16LittleEndian(Data.AsSpan(0xC)); set => WriteInt16LittleEndian(Data.AsSpan(0xC), (short)value); } public int Item2 { get => ReadInt16LittleEndian(Data.AsSpan(0xE)); set => WriteInt16LittleEndian(Data.AsSpan(0xE), (short)value); } - public override int Gender { get => Data[0x10]; set => Data[0x10] = (byte)value; } + public override byte Gender { get => Data[0x10]; set => Data[0x10] = value; } public override int HatchCycles { get => Data[0x11]; set => Data[0x11] = (byte)value; } public override int BaseFriendship { get => Data[0x12]; set => Data[0x12] = (byte)value; } public override byte EXPGrowth { get => Data[0x13]; set => Data[0x13] = value; } @@ -71,4 +60,87 @@ public sealed class PersonalInfo4 : PersonalInfo, IPersonalAbility12 // Manually added attributes public override byte FormCount { get => Data[0x29]; set {} } public override int FormStatsIndex { get => ReadUInt16LittleEndian(Data.AsSpan(0x2A)); set {} } + + public void AddTypeTutors(ReadOnlySpan data) => TypeTutors = FlagUtil.GitBitFlagArray(data); + public void CopyTypeTutors(PersonalInfo4 other) => TypeTutors = other.TypeTutors; + + /// + /// Grass-Fire-Water-Etc typed learn compatibility flags for individual moves. + /// + public bool[] TypeTutors { get; private set; } = Array.Empty(); + + private const int TMHM = 0x1C; + private const int CountTM = 92; + private const int CountHM = 8; + private const int CountTMHM = CountTM + CountHM; + private const int ByteCountTM = (CountTMHM + 7) / 8; + private const int CountTutor = 0x34; + + public bool GetIsLearnTM(int index) + { + if ((uint)index >= CountTM) + return false; + return (Data[TMHM + (index >> 3)] & (1 << (index & 7))) != 0; + } + + public void SetIsLearnTM(int index, bool value) + { + if ((uint)index >= CountTM) + return; + if (value) + Data[TMHM + (index >> 3)] |= (byte)(1 << (index & 7)); + else + Data[TMHM + (index >> 3)] &= (byte)~(1 << (index & 7)); + } + + public void SetAllLearnTM(Span result, ReadOnlySpan moves) + { + var span = Data.AsSpan(TMHM, ByteCountTM); + for (int i = CountTM - 1; i >= 0; i--) + { + if ((span[i >> 3] & (i & 7)) != 0) + result[moves[i]] = true; + } + } + + public bool GetIsLearnTutorType(int index) + { + if ((uint)index >= CountTutor) + return false; + return TypeTutors[index]; + } + + public void SetIsLearnTutorType(int index, bool value) + { + if ((uint)index >= CountTutor) + throw new ArgumentOutOfRangeException(nameof(index), index, null); + TypeTutors[index] = value; + } + + public void SetAllLearnTutorType(Span result, ReadOnlySpan moves) + { + for (int i = CountTutor - 1; i >= 0; i--) + { + if (TypeTutors[i]) + result[moves[i]] = true; + } + } + + public bool GetIsLearnHM(int index) + { + if ((uint)index >= CountHM) + return false; + index += CountTM; + return (Data[TMHM + (index >> 3)] & (1 << (index & 7))) != 0; + } + + public void SetAllLearnHM(Span result, ReadOnlySpan moves) + { + var span = Data.AsSpan(TMHM, ByteCountTM); + for (int i = CountTM + CountHM - 1; i >= CountTM; i--) + { + if ((span[i >> 3] & (i & 7)) != 0) + result[moves[i - CountTM]] = true; + } + } } diff --git a/PKHeX.Core/PersonalInfo/Info/PersonalInfo5B2W2.cs b/PKHeX.Core/PersonalInfo/Info/PersonalInfo5B2W2.cs index 9754b7790..db3e74d88 100644 --- a/PKHeX.Core/PersonalInfo/Info/PersonalInfo5B2W2.cs +++ b/PKHeX.Core/PersonalInfo/Info/PersonalInfo5B2W2.cs @@ -6,36 +6,13 @@ namespace PKHeX.Core; /// /// class with values from the Black 2 & White 2 games. /// -public sealed class PersonalInfo5B2W2 : PersonalInfo, IPersonalAbility12H +public sealed class PersonalInfo5B2W2 : PersonalInfo, IPersonalAbility12H, IPersonalInfoTM, IPersonalInfoTutorType { public const int SIZE = 0x4C; private readonly byte[] Data; - public PersonalInfo5B2W2(byte[] data) - { - Data = data; - // Unpack TMHM & Tutors - TMHM = GetBits(data.AsSpan(0x28, 0x10)); - TypeTutors = GetBits(data.AsSpan(0x38, 0x4)); - SpecialTutors = new[] - { - GetBits(data.AsSpan(0x3C, 0x04)), - GetBits(data.AsSpan(0x40, 0x04)), - GetBits(data.AsSpan(0x44, 0x04)), - GetBits(data.AsSpan(0x48, 0x04)), - }; - } - - public override byte[] Write() - { - SetBits(TMHM, Data.AsSpan(0x28)); - SetBits(TypeTutors, Data.AsSpan(0x38)); - SetBits(SpecialTutors[0], Data.AsSpan(0x3C)); - SetBits(SpecialTutors[1], Data.AsSpan(0x40)); - SetBits(SpecialTutors[2], Data.AsSpan(0x44)); - SetBits(SpecialTutors[3], Data.AsSpan(0x48)); - return Data; - } + public PersonalInfo5B2W2(byte[] data) => Data = data; + public override byte[] Write() => Data; public override int HP { get => Data[0x00]; set => Data[0x00] = (byte)value; } public override int ATK { get => Data[0x01]; set => Data[0x01] = (byte)value; } @@ -58,7 +35,7 @@ public sealed class PersonalInfo5B2W2 : PersonalInfo, IPersonalAbility12H public int Item1 { get => ReadInt16LittleEndian(Data.AsSpan(0x0C)); set => WriteInt16LittleEndian(Data.AsSpan(0x0C), (short)value); } public int Item2 { get => ReadInt16LittleEndian(Data.AsSpan(0x0E)); set => WriteInt16LittleEndian(Data.AsSpan(0x0E), (short)value); } public int Item3 { get => ReadInt16LittleEndian(Data.AsSpan(0x10)); set => WriteInt16LittleEndian(Data.AsSpan(0x10), (short)value); } - public override int Gender { get => Data[0x12]; set => Data[0x12] = (byte)value; } + public override byte Gender { get => Data[0x12]; set => Data[0x12] = value; } public override int HatchCycles { get => Data[0x13]; set => Data[0x13] = (byte)value; } public override int BaseFriendship { get => Data[0x14]; set => Data[0x14] = (byte)value; } public override byte EXPGrowth { get => Data[0x15]; set => Data[0x15] = value; } @@ -90,5 +67,237 @@ public sealed class PersonalInfo5B2W2 : PersonalInfo, IPersonalAbility12H _ => throw new ArgumentOutOfRangeException(nameof(abilityIndex), abilityIndex, null), }; + private const int TMHM = 0x28; + private const int CountTMHM = 101; + private const int ByteCountTMHM = (CountTMHM + 7) / 8; + private const int TypeTutors = 0x38; + private const int TypeTutorsCount = 8; + public bool HasHiddenAbility => AbilityH != Ability1; + + public bool GetIsLearnTM(int index) + { + if ((uint)index >= CountTMHM) + return false; + return (Data[0x28 + (index >> 3)] & (1 << (index & 7))) != 0; + } + + public void SetIsLearnTM(int index, bool value) + { + if ((uint)index >= CountTMHM) + throw new ArgumentOutOfRangeException(nameof(index), index, null); + if (value) + Data[TMHM + (index >> 3)] |= (byte)(1 << (index & 7)); + else + Data[TMHM + (index >> 3)] &= (byte)~(1 << (index & 7)); + } + + public bool GetIsLearnTutorType(int index) + { + if ((uint)index >= TypeTutorsCount) + return false; + return (Data[TypeTutors + (index >> 3)] & (1 << (index & 7))) != 0; + } + + public void SetIsLearnTutorType(int index, bool value) + { + if ((uint)index >= TypeTutorsCount) + throw new ArgumentOutOfRangeException(nameof(index), index, null); + if (value) + Data[TypeTutors + (index >> 3)] |= (byte)(1 << (index & 7)); + else + Data[TypeTutors + (index >> 3)] &= (byte)~(1 << (index & 7)); + } + + public void SetAllLearnTM(Span result, ReadOnlySpan moves) + { + var span = Data.AsSpan(TMHM, ByteCountTMHM); + for (int index = CountTMHM - 1; index >= 0; index--) + { + if ((span[index >> 3] & (1 << (index & 7))) != 0) + result[moves[index]] = true; + } + } + + public void SetAllLearnTutorType(Span result, ReadOnlySpan moves) + { + var tutor = Data[TypeTutors]; + for (int index = TypeTutorsCount - 1; index >= 0; index--) + { + if ((tutor & (1 << (index & 7))) != 0) + result[moves[index]] = true; + } + } + + private const int Tutor1 = 0x3C; // Driftveil + private const int Tutor2 = 0x40; // Lentimas + private const int Tutor3 = 0x44; // Humilau + private const int Tutor4 = 0x48; // Nacrene + + private const int CountTutor1 = 15; + private const int CountTutor2 = 17; + private const int CountTutor3 = 13; + private const int CountTutor4 = 15; + + public bool GetIsLearnTutor1(int index) + { + if ((uint)index >= CountTutor1) + return false; + return (Data[Tutor1 + (index >> 3)] & (1 << (index & 7))) != 0; + } + + public bool GetIsLearnTutor1(ushort move) + { + var index = Array.IndexOf(TutorMoves1, move); + return index >= 0 && (Data[Tutor1 + (index >> 3)] & (1 << (index & 7))) != 0; + } + + public void SetIsLearnTutor1(int index, bool value) + { + if ((uint)index >= CountTutor1) + throw new ArgumentOutOfRangeException(nameof(index), index, null); + if (value) + Data[Tutor1 + (index >> 3)] |= (byte)(1 << (index & 7)); + else + Data[Tutor1 + (index >> 3)] &= (byte)~(1 << (index & 7)); + } + + public bool GetIsLearnTutor2(int index) + { + if ((uint)index >= CountTutor2) + return false; + return (Data[Tutor2 + (index >> 3)] & (1 << (index & 7))) != 0; + } + + public bool GetIsLearnTutor2(ushort move) + { + var index = Array.IndexOf(TutorMoves2, move); + return index >= 0 && (Data[Tutor2 + (index >> 3)] & (1 << (index & 7))) != 0; + } + + public void SetIsLearnTutor2(int index, bool value) + { + if ((uint)index >= CountTutor2) + throw new ArgumentOutOfRangeException(nameof(index), index, null); + if (value) + Data[Tutor2 + (index >> 3)] |= (byte)(1 << (index & 7)); + else + Data[Tutor2 + (index >> 3)] &= (byte)~(1 << (index & 7)); + } + + public bool GetIsLearnTutor3(int index) + { + if ((uint)index >= CountTutor3) + return false; + return (Data[Tutor3 + (index >> 3)] & (1 << (index & 7))) != 0; + } + + public bool GetIsLearnTutor3(ushort move) + { + var index = Array.IndexOf(TutorMoves3, move); + return index >= 0 && (Data[Tutor3 + (index >> 3)] & (1 << (index & 7))) != 0; + } + + public void SetIsLearnTutor3(int index, bool value) + { + if ((uint)index >= CountTutor3) + throw new ArgumentOutOfRangeException(nameof(index), index, null); + if (value) + Data[Tutor3 + (index >> 3)] |= (byte)(1 << (index & 7)); + else + Data[Tutor3 + (index >> 3)] &= (byte)~(1 << (index & 7)); + } + + public bool GetIsLearnTutor4(int index) + { + if ((uint)index >= CountTutor4) + return false; + return (Data[Tutor4 + (index >> 3)] & (1 << (index & 7))) != 0; + } + + public bool GetIsLearnTutor4(ushort move) + { + var index = Array.IndexOf(TutorMoves4, move); + return index >= 0 && (Data[Tutor4 + (index >> 3)] & (1 << (index & 7))) != 0; + } + + public void SetIsLearnTutor4(int index, bool value) + { + if ((uint)index >= CountTutor4) + throw new ArgumentOutOfRangeException(nameof(index), index, null); + if (value) + Data[Tutor4 + (index >> 3)] |= (byte)(1 << (index & 7)); + else + Data[Tutor4 + (index >> 3)] &= (byte)~(1 << (index & 7)); + } + + public void SetAllLearnTutor1(Span result) + { + var moves = TutorMoves1; + var span = Data.AsSpan(Tutor1, 4); + for (int index = CountTutor1 - 1; index >= 0; index--) + { + if ((span[index >> 3] & (1 << (index & 7))) != 0) + result[moves[index]] = true; + } + } + + public void SetAllLearnTutor2(Span result) + { + var moves = TutorMoves2; + var span = Data.AsSpan(Tutor2, 4); + for (int index = CountTutor2 - 1; index >= 0; index--) + { + if ((span[index >> 3] & (1 << (index & 7))) != 0) + result[moves[index]] = true; + } + } + + public void SetAllLearnTutor3(Span result) + { + var moves = TutorMoves3; + var span = Data.AsSpan(Tutor3, 4); + for (int index = CountTutor3 - 1; index >= 0; index--) + { + if ((span[index >> 3] & (1 << (index & 7))) != 0) + result[moves[index]] = true; + } + } + + public void SetAllLearnTutor4(Span result) + { + var moves = TutorMoves4; + var span = Data.AsSpan(Tutor4, 4); + for (int index = CountTutor4 - 1; index >= 0; index--) + { + if ((span[index >> 3] & (1 << (index & 7))) != 0) + result[moves[index]] = true; + } + } + + private static readonly ushort[] TutorMoves1 = { 450, 343, 162, 530, 324, 442, 402, 529, 340, 067, 441, 253, 009, 007, 008 }; // Driftveil + private static readonly ushort[] TutorMoves2 = { 277, 335, 414, 492, 356, 393, 334, 387, 276, 527, 196, 401, 399, 428, 406, 304, 231 }; // Lentimas + private static readonly ushort[] TutorMoves3 = { 020, 173, 282, 235, 257, 272, 215, 366, 143, 220, 202, 409, 355 }; // Humilau + private static readonly ushort[] TutorMoves4 = { 380, 388, 180, 495, 270, 271, 478, 472, 283, 200, 278, 289, 446, 214, 285 }; // Nacrene + + public bool GetIsTutorSpecial(ushort move) + { + if (GetIsLearnTutor1(move)) + return true; + if (GetIsLearnTutor2(move)) + return true; + if (GetIsLearnTutor3(move)) + return true; + if (GetIsLearnTutor4(move)) + return true; + return false; + } + + public void SetAllLearnTutorSpecial(Span result) + { + SetAllLearnTutor1(result); + SetAllLearnTutor2(result); + SetAllLearnTutor3(result); + SetAllLearnTutor4(result); + } } diff --git a/PKHeX.Core/PersonalInfo/Info/PersonalInfo5BW.cs b/PKHeX.Core/PersonalInfo/Info/PersonalInfo5BW.cs index 85e690d47..b3b916ffc 100644 --- a/PKHeX.Core/PersonalInfo/Info/PersonalInfo5BW.cs +++ b/PKHeX.Core/PersonalInfo/Info/PersonalInfo5BW.cs @@ -6,25 +6,13 @@ namespace PKHeX.Core; /// /// class with values from the Black & White games. /// -public sealed class PersonalInfo5BW : PersonalInfo, IPersonalAbility12H +public sealed class PersonalInfo5BW : PersonalInfo, IPersonalAbility12H, IPersonalInfoTM, IPersonalInfoTutorType { public const int SIZE = 0x3C; private readonly byte[] Data; - public PersonalInfo5BW(byte[] data) - { - Data = data; - // Unpack TMHM & Tutors - TMHM = GetBits(data.AsSpan(0x28, 0x10)); - TypeTutors = GetBits(data.AsSpan(0x38, 0x4)); - } - - public override byte[] Write() - { - SetBits(TMHM, Data.AsSpan(0x28)); - SetBits(TypeTutors, Data.AsSpan(0x38)); - return Data; - } + public PersonalInfo5BW(byte[] data) => Data = data; + public override byte[] Write() => Data; public override int HP { get => Data[0x00]; set => Data[0x00] = (byte)value; } public override int ATK { get => Data[0x01]; set => Data[0x01] = (byte)value; } @@ -47,7 +35,7 @@ public sealed class PersonalInfo5BW : PersonalInfo, IPersonalAbility12H public int Item1 { get => ReadInt16LittleEndian(Data.AsSpan(0x0C)); set => WriteInt16LittleEndian(Data.AsSpan(0x0C), (short)value); } public int Item2 { get => ReadInt16LittleEndian(Data.AsSpan(0x0E)); set => WriteInt16LittleEndian(Data.AsSpan(0x0E), (short)value); } public int Item3 { get => ReadInt16LittleEndian(Data.AsSpan(0x10)); set => WriteInt16LittleEndian(Data.AsSpan(0x10), (short)value); } - public override int Gender { get => Data[0x12]; set => Data[0x12] = (byte)value; } + public override byte Gender { get => Data[0x12]; set => Data[0x12] = value; } public override int HatchCycles { get => Data[0x13]; set => Data[0x13] = (byte)value; } public override int BaseFriendship { get => Data[0x14]; set => Data[0x14] = (byte)value; } public override byte EXPGrowth { get => Data[0x15]; set => Data[0x15] = value; } @@ -78,4 +66,64 @@ public sealed class PersonalInfo5BW : PersonalInfo, IPersonalAbility12H 2 => AbilityH, _ => throw new ArgumentOutOfRangeException(nameof(abilityIndex), abilityIndex, null), }; + + private const int TMHM = 0x28; + private const int CountTMHM = 101; + private const int ByteCountTM = (CountTMHM + 7) / 8; + private const int TypeTutors = 0x38; + private const int TypeTutorsCount = 8; + + public bool GetIsLearnTM(int index) + { + if ((uint)index >= CountTMHM) + return false; + return (Data[0x28 + (index >> 3)] & (1 << (index & 7))) != 0; + } + + public void SetIsLearnTM(int index, bool value) + { + if ((uint)index >= CountTMHM) + throw new ArgumentOutOfRangeException(nameof(index), index, null); + if (value) + Data[TMHM + (index >> 3)] |= (byte)(1 << (index & 7)); + else + Data[TMHM + (index >> 3)] &= (byte)~(1 << (index & 7)); + } + + public bool GetIsLearnTutorType(int index) + { + if ((uint)index >= TypeTutorsCount) + return false; + return (Data[TypeTutors + (index >> 3)] & (1 << (index & 7))) != 0; + } + + public void SetIsLearnTutorType(int index, bool value) + { + if ((uint)index >= TypeTutorsCount) + throw new ArgumentOutOfRangeException(nameof(index), index, null); + if (value) + Data[TypeTutors + (index >> 3)] |= (byte)(1 << (index & 7)); + else + Data[TypeTutors + (index >> 3)] &= (byte)~(1 << (index & 7)); + } + + public void SetAllLearnTM(Span result, ReadOnlySpan moves) + { + var span = Data.AsSpan(TMHM, ByteCountTM); + for (int index = CountTMHM - 1; index >= 0; index--) + { + if ((span[index >> 3] & (1 << (index & 7))) != 0) + result[moves[index]] = true; + } + } + + public void SetAllLearnTutorType(Span result, ReadOnlySpan moves) + { + var tutor = Data[TypeTutors]; + for (int index = TypeTutorsCount - 1; index >= 0; index--) + { + if ((tutor & (1 << (index & 7))) != 0) + result[moves[index]] = true; + } + } } diff --git a/PKHeX.Core/PersonalInfo/Info/PersonalInfo6AO.cs b/PKHeX.Core/PersonalInfo/Info/PersonalInfo6AO.cs index e7a80b0d4..57e7488d4 100644 --- a/PKHeX.Core/PersonalInfo/Info/PersonalInfo6AO.cs +++ b/PKHeX.Core/PersonalInfo/Info/PersonalInfo6AO.cs @@ -6,37 +6,13 @@ namespace PKHeX.Core; /// /// class with values from the OR & AS games. /// -public sealed class PersonalInfo6AO : PersonalInfo, IPersonalAbility12H +public sealed class PersonalInfo6AO : PersonalInfo, IPersonalAbility12H, IPersonalInfoTM, IPersonalInfoTutorType { public const int SIZE = 0x50; private readonly byte[] Data; - public PersonalInfo6AO(byte[] data) - { - Data = data; - // Unpack TMHM & Tutors - TMHM = GetBits(Data.AsSpan(0x28, 0x10)); - TypeTutors = GetBits(Data.AsSpan(0x38, 0x4)); - // 0x3C-0x40 unknown - SpecialTutors = new[] - { - GetBits(Data.AsSpan(0x40, 0x04)), - GetBits(Data.AsSpan(0x44, 0x04)), - GetBits(Data.AsSpan(0x48, 0x04)), - GetBits(Data.AsSpan(0x4C, 0x04)), - }; - } - - public override byte[] Write() - { - SetBits(TMHM, Data.AsSpan(0x28)); - SetBits(TypeTutors, Data.AsSpan(0x38)); - SetBits(SpecialTutors[0], Data.AsSpan(0x40)); - SetBits(SpecialTutors[1], Data.AsSpan(0x44)); - SetBits(SpecialTutors[2], Data.AsSpan(0x48)); - SetBits(SpecialTutors[3], Data.AsSpan(0x4C)); - return Data; - } + public PersonalInfo6AO(byte[] data) => Data = data; + public override byte[] Write() => Data; public override int HP { get => Data[0x00]; set => Data[0x00] = (byte)value; } public override int ATK { get => Data[0x01]; set => Data[0x01] = (byte)value; } @@ -59,7 +35,7 @@ public sealed class PersonalInfo6AO : PersonalInfo, IPersonalAbility12H public int Item1 { get => ReadInt16LittleEndian(Data.AsSpan(0x0C)); set => WriteInt16LittleEndian(Data.AsSpan(0x0C), (short)value); } public int Item2 { get => ReadInt16LittleEndian(Data.AsSpan(0x0E)); set => WriteInt16LittleEndian(Data.AsSpan(0x0E), (short)value); } public int Item3 { get => ReadInt16LittleEndian(Data.AsSpan(0x10)); set => WriteInt16LittleEndian(Data.AsSpan(0x10), (short)value); } - public override int Gender { get => Data[0x12]; set => Data[0x12] = (byte)value; } + public override byte Gender { get => Data[0x12]; set => Data[0x12] = value; } public override int HatchCycles { get => Data[0x13]; set => Data[0x13] = (byte)value; } public override int BaseFriendship { get => Data[0x14]; set => Data[0x14] = (byte)value; } public override byte EXPGrowth { get => Data[0x15]; set => Data[0x15] = value; } @@ -90,4 +66,246 @@ public sealed class PersonalInfo6AO : PersonalInfo, IPersonalAbility12H 2 => AbilityH, _ => throw new ArgumentOutOfRangeException(nameof(abilityIndex), abilityIndex, null), }; + + private const int TMHM = 0x28; + private const int CountTM = 100; + private const int CountHM = 7; + private const int CountTMHM = CountTM + CountHM; + private const int ByteCountTM = (CountTMHM + 7) / 8; + private const int TypeTutor = 0x38; + private const int TypeTutorCount = 7; + + public bool GetIsLearnTM(int index) + { + if ((uint)index >= CountTMHM) + return false; + return (Data[TMHM + (index >> 3)] & (1 << (index & 7))) != 0; + } + + public void SetIsLearnTM(int index, bool value) + { + if ((uint)index >= CountTMHM) + return; + if (value) + Data[TMHM + (index >> 3)] |= (byte)(1 << (index & 7)); + else + Data[TMHM + (index >> 3)] &= (byte)~(1 << (index & 7)); + } + + public void SetAllLearnTM(Span result, ReadOnlySpan moves) + { + var span = Data.AsSpan(TMHM, ByteCountTM); + for (int i = CountTMHM - 1; i >= 0; i--) + { + if ((span[i >> 3] & (1 << (i & 7))) != 0) + result[moves[i]] = true; + } + } + + public bool GetIsLearnTutorType(int index) + { + if ((uint)index >= 8) + return false; + return (Data[TypeTutor + (index >> 3)] & (1 << (index & 7))) != 0; + } + + public void SetIsLearnTutorType(int index, bool value) + { + if ((uint)index >= TypeTutorCount) + throw new ArgumentOutOfRangeException(nameof(index), index, null); + if (value) + Data[TypeTutor + (index >> 3)] |= (byte)(1 << (index & 7)); + else + Data[TypeTutor + (index >> 3)] &= (byte)~(1 << (index & 7)); + } + + public void SetAllLearnTutorType(Span result, ReadOnlySpan moves) + { + var tutor = Data[TypeTutor]; + for (int i = TypeTutorCount - 1; i >= 0; i--) + { + if ((tutor & (1 << (i & 7))) != 0) + result[moves[i]] = true; + } + } + + private const int Tutor1 = 0x40; + private const int Tutor2 = 0x44; + private const int Tutor3 = 0x48; + private const int Tutor4 = 0x4C; + + private const int CountTutor1 = 15; + private const int CountTutor2 = 17; + private const int CountTutor3 = 13; + private const int CountTutor4 = 15; + + public bool GetIsTutor1(int index) + { + if ((uint)index >= CountTutor1) + return false; + return (Data[Tutor1 + (index >> 3)] & (1 << (index & 7))) != 0; + } + + public bool GetIsTutor1(ushort move) + { + var index = Array.IndexOf(TutorMoves1, move); + return index >= 0 && (Data[Tutor1 + (index >> 3)] & (1 << (index & 7))) != 0; + } + + public void SetIsLearnTutor1(int index, bool value) + { + if ((uint)index >= CountTutor1) + throw new ArgumentOutOfRangeException(nameof(index), index, null); + if (value) + Data[Tutor1 + (index >> 3)] |= (byte)(1 << (index & 7)); + else + Data[Tutor1 + (index >> 3)] &= (byte)~(1 << (index & 7)); + } + + public bool GetIsLearnTutor2(int index) + { + if ((uint)index >= CountTutor2) + return false; + return (Data[Tutor2 + (index >> 3)] & (1 << (index & 7))) != 0; + } + + public bool GetIsLearnTutor2(ushort move) + { + var index = Array.IndexOf(TutorMoves2, move); + return index >= 0 && (Data[Tutor2 + (index >> 3)] & (1 << (index & 7))) != 0; + } + + public void SetIsLearnTutor2(int index, bool value) + { + if ((uint)index >= CountTutor2) + throw new ArgumentOutOfRangeException(nameof(index), index, null); + if (value) + Data[Tutor2 + (index >> 3)] |= (byte)(1 << (index & 7)); + else + Data[Tutor2 + (index >> 3)] &= (byte)~(1 << (index & 7)); + } + + public bool GetIsLearnTutor3(int index) + { + if ((uint)index >= CountTutor3) + return false; + return (Data[Tutor3 + (index >> 3)] & (1 << (index & 7))) != 0; + } + + public bool GetIsLearnTutor3(ushort move) + { + var index = Array.IndexOf(TutorMoves3, move); + return index >= 0 && (Data[Tutor3 + (index >> 3)] & (1 << (index & 7))) != 0; + } + + public void SetIsLearnTutor3(int index, bool value) + { + if ((uint)index >= CountTutor3) + throw new ArgumentOutOfRangeException(nameof(index), index, null); + if (value) + Data[Tutor3 + (index >> 3)] |= (byte)(1 << (index & 7)); + else + Data[Tutor3 + (index >> 3)] &= (byte)~(1 << (index & 7)); + } + + public bool GetIsLearnTutor4(int index) + { + if ((uint)index >= CountTutor4) + return false; + return (Data[Tutor4 + (index >> 3)] & (1 << (index & 7))) != 0; + } + + public bool GetIsLearnTutor4(ushort move) + { + var index = Array.IndexOf(TutorMoves4, move); + return index >= 0 && (Data[Tutor4 + (index >> 3)] & (1 << (index & 7))) != 0; + } + + public void SetIsLearnTutor4(int index, bool value) + { + if ((uint)index >= CountTutor4) + throw new ArgumentOutOfRangeException(nameof(index), index, null); + if (value) + Data[Tutor4 + (index >> 3)] |= (byte)(1 << (index & 7)); + else + Data[Tutor4 + (index >> 3)] &= (byte)~(1 << (index & 7)); + } + + public void SetAllLearnTutor1(Span result) + { + var moves = TutorMoves1; + var span = Data.AsSpan(Tutor1, 4); + for (int index = CountTutor1 - 1; index >= 0; index--) + { + if ((span[index >> 3] & (1 << (index & 7))) != 0) + result[moves[index]] = true; + } + } + + public void SetAllLearnTutor2(Span result) + { + var moves = TutorMoves2; + var span = Data.AsSpan(Tutor2, 4); + for (int index = CountTutor2 - 1; index >= 0; index--) + { + if ((span[index >> 3] & (1 << (index & 7))) != 0) + result[moves[index]] = true; + } + } + + public void SetAllLearnTutor3(Span result) + { + var moves = TutorMoves3; + var span = Data.AsSpan(Tutor3, 4); + for (int index = CountTutor3 - 1; index >= 0; index--) + { + if ((span[index >> 3] & (1 << (index & 7))) != 0) + result[moves[index]] = true; + } + } + + public void SetAllLearnTutor4(Span result) + { + var moves = TutorMoves4; + var span = Data.AsSpan(Tutor4, 4); + for (int index = CountTutor4 - 1; index >= 0; index--) + { + if ((span[index >> 3] & (1 << (index & 7))) != 0) + result[moves[index]] = true; + } + } + + private static readonly ushort[] TutorMoves1 = { 450, 343, 162, 530, 324, 442, 402, 529, 340, 067, 441, 253, 009, 007, 008 }; + private static readonly ushort[] TutorMoves2 = { 277, 335, 414, 492, 356, 393, 334, 387, 276, 527, 196, 401, 399, 428, 406, 304, 231 }; + private static readonly ushort[] TutorMoves3 = { 020, 173, 282, 235, 257, 272, 215, 366, 143, 220, 202, 409, 355, 264, 351, 352 }; // Last 3 added, Different from G5 Humilau + private static readonly ushort[] TutorMoves4 = { 380, 388, 180, 495, 270, 271, 478, 472, 283, 200, 278, 289, 446, 214, 285 }; + + public bool GetIsTutorSpecial(ushort move) + { + if (GetIsTutor1(move)) + return true; + if (GetIsLearnTutor2(move)) + return true; + if (GetIsLearnTutor3(move)) + return true; + if (GetIsLearnTutor4(move)) + return true; + return false; + } + + public void SetAllLearnTutorSpecial(Span result) + { + SetAllLearnTutor1(result); + SetAllLearnTutor2(result); + SetAllLearnTutor3(result); + SetAllLearnTutor4(result); + } + + public bool GetIsLearnHM(int index) + { + if ((uint)index >= CountHM) + return false; + index += CountTM; + return (Data[TMHM + (index >> 3)] & (1 << (index & 7))) != 0; + } } diff --git a/PKHeX.Core/PersonalInfo/Info/PersonalInfo6XY.cs b/PKHeX.Core/PersonalInfo/Info/PersonalInfo6XY.cs index 5ff35b760..436f53172 100644 --- a/PKHeX.Core/PersonalInfo/Info/PersonalInfo6XY.cs +++ b/PKHeX.Core/PersonalInfo/Info/PersonalInfo6XY.cs @@ -6,26 +6,13 @@ namespace PKHeX.Core; /// /// class with values from the X & Y games. /// -public sealed class PersonalInfo6XY : PersonalInfo, IPersonalAbility12H +public sealed class PersonalInfo6XY : PersonalInfo, IPersonalAbility12H, IPersonalInfoTM, IPersonalInfoTutorType { public const int SIZE = 0x40; private readonly byte[] Data; - public PersonalInfo6XY(byte[] data) - { - Data = data; - // Unpack TMHM & Tutors - TMHM = GetBits(Data.AsSpan(0x28, 0x10)); - TypeTutors = GetBits(Data.AsSpan(0x38, 0x4)); - // 0x3C-0x40 unknown - } - - public override byte[] Write() - { - SetBits(TMHM, Data.AsSpan(0x28)); - SetBits(TypeTutors, Data.AsSpan(0x38)); - return Data; - } + public PersonalInfo6XY(byte[] data) => Data = data; + public override byte[] Write() => Data; public override int HP { get => Data[0x00]; set => Data[0x00] = (byte)value; } public override int ATK { get => Data[0x01]; set => Data[0x01] = (byte)value; } @@ -48,7 +35,7 @@ public sealed class PersonalInfo6XY : PersonalInfo, IPersonalAbility12H public int Item1 { get => ReadInt16LittleEndian(Data.AsSpan(0x0C)); set => WriteInt16LittleEndian(Data.AsSpan(0x0C), (short)value); } public int Item2 { get => ReadInt16LittleEndian(Data.AsSpan(0x0E)); set => WriteInt16LittleEndian(Data.AsSpan(0x0E), (short)value); } public int Item3 { get => ReadInt16LittleEndian(Data.AsSpan(0x10)); set => WriteInt16LittleEndian(Data.AsSpan(0x10), (short)value); } - public override int Gender { get => Data[0x12]; set => Data[0x12] = (byte)value; } + public override byte Gender { get => Data[0x12]; set => Data[0x12] = value; } public override int HatchCycles { get => Data[0x13]; set => Data[0x13] = (byte)value; } public override int BaseFriendship { get => Data[0x14]; set => Data[0x14] = (byte)value; } public override byte EXPGrowth { get => Data[0x15]; set => Data[0x15] = value; } @@ -79,4 +66,66 @@ public sealed class PersonalInfo6XY : PersonalInfo, IPersonalAbility12H 2 => AbilityH, _ => throw new ArgumentOutOfRangeException(nameof(abilityIndex), abilityIndex, null), }; + + private const int TMHM = 0x28; + private const int CountTM = 100; + private const int CountHM = 5; + private const int CountTMHM = CountTM + CountHM; + private const int ByteCountTM = (CountTMHM + 7) / 8; + private const int TypeTutor = 0x38; + private const int TypeTutorCount = 7; + + public bool GetIsLearnTM(int index) + { + if ((uint)index >= CountTMHM) + return false; + return (Data[TMHM + (index >> 3)] & (1 << (index & 7))) != 0; + } + + public void SetIsLearnTM(int index, bool value) + { + if ((uint)index >= CountTMHM) + return; + if (value) + Data[TMHM + (index >> 3)] |= (byte)(1 << (index & 7)); + else + Data[TMHM + (index >> 3)] &= (byte)~(1 << (index & 7)); + } + + public void SetAllLearnTM(Span result, ReadOnlySpan moves) + { + var span = Data.AsSpan(TMHM, ByteCountTM); + for (int i = CountTMHM - 1; i >= 0; i--) + { + if ((span[i >> 3] & (1 << (i & 7))) != 0) + result[moves[i]] = true; + } + } + + public bool GetIsLearnTutorType(int index) + { + if ((uint)index >= 8) + return false; + return (Data[TypeTutor + (index >> 3)] & (1 << (index & 7))) != 0; + } + + public void SetIsLearnTutorType(int index, bool value) + { + if ((uint)index >= TypeTutorCount) + throw new ArgumentOutOfRangeException(nameof(index), index, null); + if (value) + Data[TypeTutor + (index >> 3)] |= (byte)(1 << (index & 7)); + else + Data[TypeTutor + (index >> 3)] &= (byte)~(1 << (index & 7)); + } + + public void SetAllLearnTutorType(Span result, ReadOnlySpan moves) + { + var tutor = Data[TypeTutor]; + for (int i = TypeTutorCount - 1; i >= 0; i--) + { + if ((tutor & (1 << (i & 7))) != 0) + result[moves[i]] = true; + } + } } diff --git a/PKHeX.Core/PersonalInfo/Info/PersonalInfo7.cs b/PKHeX.Core/PersonalInfo/Info/PersonalInfo7.cs index ab12433b7..b1084dc4b 100644 --- a/PKHeX.Core/PersonalInfo/Info/PersonalInfo7.cs +++ b/PKHeX.Core/PersonalInfo/Info/PersonalInfo7.cs @@ -6,30 +6,13 @@ namespace PKHeX.Core; /// /// class with values from the Sun & Moon games. /// -public sealed class PersonalInfo7 : PersonalInfo, IPersonalAbility12H +public sealed class PersonalInfo7 : PersonalInfo, IPersonalAbility12H, IPersonalInfoTM, IPersonalInfoTutorType { public const int SIZE = 0x54; private readonly byte[] Data; - public PersonalInfo7(byte[] data) - { - Data = data; - TMHM = GetBits(Data.AsSpan(0x28, 0x10)); // 36-39 - TypeTutors = GetBits(Data.AsSpan(0x38, 0x4)); // 40 - - SpecialTutors = new[] - { - GetBits(Data.AsSpan(0x3C, 0x0A)), - }; - } - - public override byte[] Write() - { - SetBits(TMHM, Data.AsSpan(0x28)); - SetBits(TypeTutors, Data.AsSpan(0x38)); - SetBits(SpecialTutors[0], Data.AsSpan(0x3C)); - return Data; - } + public PersonalInfo7(byte[] data) => Data = data; + public override byte[] Write() => Data; public override int HP { get => Data[0x00]; set => Data[0x00] = (byte)value; } public override int ATK { get => Data[0x01]; set => Data[0x01] = (byte)value; } @@ -52,7 +35,7 @@ public sealed class PersonalInfo7 : PersonalInfo, IPersonalAbility12H public int Item1 { get => ReadInt16LittleEndian(Data.AsSpan(0x0C)); set => WriteInt16LittleEndian(Data.AsSpan(0x0C), (short)value); } public int Item2 { get => ReadInt16LittleEndian(Data.AsSpan(0x0E)); set => WriteInt16LittleEndian(Data.AsSpan(0x0E), (short)value); } public int Item3 { get => ReadInt16LittleEndian(Data.AsSpan(0x10)); set => WriteInt16LittleEndian(Data.AsSpan(0x10), (short)value); } - public override int Gender { get => Data[0x12]; set => Data[0x12] = (byte)value; } + public override byte Gender { get => Data[0x12]; set => Data[0x12] = value; } public override int HatchCycles { get => Data[0x13]; set => Data[0x13] = (byte)value; } public override int BaseFriendship { get => Data[0x14]; set => Data[0x14] = (byte)value; } public override byte EXPGrowth { get => Data[0x15]; set => Data[0x15] = value; } @@ -88,4 +71,106 @@ public sealed class PersonalInfo7 : PersonalInfo, IPersonalAbility12H 2 => AbilityH, _ => throw new ArgumentOutOfRangeException(nameof(abilityIndex), abilityIndex, null), }; + + private const int TMHM = 0x28; + private const int CountTM = 100; + private const int CountHM = 5; + private const int CountTMHM = CountTM + CountHM; + private const int ByteCountTM = (CountTMHM + 7) / 8; + private const int TypeTutor = 0x38; + private const int TypeTutorCount = 7; + + public bool GetIsLearnTM(int index) + { + if ((uint)index >= CountTMHM) + return false; + return (Data[TMHM + (index >> 3)] & (1 << (index & 7))) != 0; + } + + public void SetIsLearnTM(int index, bool value) + { + if ((uint)index >= CountTMHM) + return; + if (value) + Data[TMHM + (index >> 3)] |= (byte)(1 << (index & 7)); + else + Data[TMHM + (index >> 3)] &= (byte)~(1 << (index & 7)); + } + + public void SetAllLearnTM(Span result, ReadOnlySpan moves) + { + var span = Data.AsSpan(TMHM, ByteCountTM); + for (int i = CountTMHM - 1; i >= 0; i--) + { + if ((span[i >> 3] & (1 << (i & 7))) != 0) + result[moves[i]] = true; + } + } + + public bool GetIsLearnTutorType(int index) + { + if ((uint)index >= 8) + return false; + return (Data[TypeTutor + (index >> 3)] & (1 << (index & 7))) != 0; + } + + public void SetIsLearnTutorType(int index, bool value) + { + if ((uint)index >= TypeTutorCount) + throw new ArgumentOutOfRangeException(nameof(index), index, null); + if (value) + Data[TypeTutor + (index >> 3)] |= (byte)(1 << (index & 7)); + else + Data[TypeTutor + (index >> 3)] &= (byte)~(1 << (index & 7)); + } + + public void SetAllLearnTutorType(Span result, ReadOnlySpan moves) + { + var tutor = Data[TypeTutor]; + for (int i = TypeTutorCount - 1; i >= 0; i--) + { + if ((tutor & (1 << (i & 7))) != 0) + result[moves[i]] = true; + } + } + + private const int Tutor1 = 0x3C; + private const int TutorCount1 = 67; + private const int ByteCountTutor1 = (TutorCount1 + 7) / 8; + + public bool GetIsLearnTutorSpecial(int index) + { + if ((uint)index >= TutorCount1) + return false; + return (Data[Tutor1 + (index >> 3)] & (1 << (index & 7))) != 0; + } + + public bool GetIsLearnTutorSpecial(ushort move) + { + var index = Array.IndexOf(Tutors_USUM, move); + if (index < 0) + return false; + return (Data[Tutor1 + (index >> 3)] & (1 << (index & 7))) != 0; + } + + public void SetAllLearnTutorSpecial(Span result) + { + var moves = Tutors_USUM; + var span = Data.AsSpan(Tutor1, ByteCountTutor1); + for (int i = 0; i < moves.Length; i++) + { + if ((span[i >> 3] & (1 << (i & 7))) != 0) + result[moves[i]] = true; + } + } + + private static readonly ushort[] Tutors_USUM = + { + 450, 343, 162, 530, 324, 442, 402, 529, 340, 067, 441, 253, 009, 007, 008, + 277, 335, 414, 492, 356, 393, 334, 387, 276, 527, 196, 401, 428, 406, 304, 231, + 020, 173, 282, 235, 257, 272, 215, 366, 143, 220, 202, 409, 264, 351, 352, + 380, 388, 180, 495, 270, 271, 478, 472, 283, 200, 278, 289, 446, 285, + + 477, 502, 432, 710, 707, 675, 673, + }; } diff --git a/PKHeX.Core/PersonalInfo/Info/PersonalInfo7GG.cs b/PKHeX.Core/PersonalInfo/Info/PersonalInfo7GG.cs index 7f2cbd66a..908ca06ce 100644 --- a/PKHeX.Core/PersonalInfo/Info/PersonalInfo7GG.cs +++ b/PKHeX.Core/PersonalInfo/Info/PersonalInfo7GG.cs @@ -6,24 +6,13 @@ namespace PKHeX.Core; /// /// class with values from the games. /// -public sealed class PersonalInfo7GG : PersonalInfo, IPersonalAbility12H +public sealed class PersonalInfo7GG : PersonalInfo, IPersonalAbility12H, IPersonalInfoTM { public const int SIZE = 0x54; private readonly byte[] Data; - public PersonalInfo7GG(byte[] data) - { - Data = data; - TMHM = GetBits(Data.AsSpan(0x28, 8)); // only 60 TMs used - TypeTutors = GetBits(Data.AsSpan(0x38, 1)); // at most 8 flags used - } - - public override byte[] Write() - { - SetBits(TMHM, Data.AsSpan(0x28)); - SetBits(TypeTutors, Data.AsSpan(0x38)); - return Data; - } + public PersonalInfo7GG(byte[] data) => Data = data; + public override byte[] Write() => Data; public override int HP { get => Data[0x00]; set => Data[0x00] = (byte)value; } public override int ATK { get => Data[0x01]; set => Data[0x01] = (byte)value; } @@ -46,7 +35,7 @@ public sealed class PersonalInfo7GG : PersonalInfo, IPersonalAbility12H public int Item1 { get => ReadInt16LittleEndian(Data.AsSpan(0x0C)); set => WriteInt16LittleEndian(Data.AsSpan(0x0C), (short)value); } public int Item2 { get => ReadInt16LittleEndian(Data.AsSpan(0x0E)); set => WriteInt16LittleEndian(Data.AsSpan(0x0E), (short)value); } public int Item3 { get => ReadInt16LittleEndian(Data.AsSpan(0x10)); set => WriteInt16LittleEndian(Data.AsSpan(0x10), (short)value); } - public override int Gender { get => Data[0x12]; set => Data[0x12] = (byte)value; } + public override byte Gender { get => Data[0x12]; set => Data[0x12] = value; } public override int HatchCycles { get => Data[0x13]; set => Data[0x13] = (byte)value; } public override int BaseFriendship { get => Data[0x14]; set => Data[0x14] = (byte)value; } public override byte EXPGrowth { get => Data[0x15]; set => Data[0x15] = value; } @@ -83,4 +72,35 @@ public sealed class PersonalInfo7GG : PersonalInfo, IPersonalAbility12H 2 => AbilityH, _ => throw new ArgumentOutOfRangeException(nameof(abilityIndex), abilityIndex, null), }; + + private const int TMHM = 0x28; + private const int CountTMHM = 60; + private const int ByteCountTM = (CountTMHM + 7) / 8; + + public bool GetIsLearnTM(int index) + { + if ((uint)index >= CountTMHM) + return false; + return (Data[0x28 + (index >> 3)] & (1 << (index & 7))) != 0; + } + + public void SetIsLearnTM(int index, bool value) + { + if ((uint)index >= CountTMHM) + throw new ArgumentOutOfRangeException(nameof(index), index, null); + if (value) + Data[TMHM + (index >> 3)] |= (byte)(1 << (index & 7)); + else + Data[TMHM + (index >> 3)] &= (byte)~(1 << (index & 7)); + } + + public void SetAllLearnTM(Span result, ReadOnlySpan moves) + { + var span = Data.AsSpan(TMHM, ByteCountTM); + for (int index = CountTMHM - 1; index >= 0; index--) + { + if ((span[index >> 3] & (1 << (index & 7))) != 0) + result[moves[index]] = true; + } + } } diff --git a/PKHeX.Core/PersonalInfo/Info/PersonalInfo8BDSP.cs b/PKHeX.Core/PersonalInfo/Info/PersonalInfo8BDSP.cs index 4977fea87..0f23dc98d 100644 --- a/PKHeX.Core/PersonalInfo/Info/PersonalInfo8BDSP.cs +++ b/PKHeX.Core/PersonalInfo/Info/PersonalInfo8BDSP.cs @@ -6,34 +6,19 @@ namespace PKHeX.Core; /// /// class with values from the games. /// -public sealed class PersonalInfo8BDSP : PersonalInfo, IPersonalAbility12H +public sealed class PersonalInfo8BDSP : PersonalInfo, IPersonalAbility12H, IPersonalInfoTM, IPersonalInfoTutorType, IPermitRecord { public const int SIZE = 0x44; - private const int CountTM = 100; private readonly byte[] Data; - public PersonalInfo8BDSP(byte[] data) - { - Data = data; - TMHM = new bool[CountTM]; - for (var i = 0; i < CountTM; i++) - TMHM[i] = FlagUtil.GetFlag(data, 0x28 + (i >> 3), i); + public PersonalInfo8BDSP(byte[] data) => Data = data; - // 0x38-0x3B type tutors, but only 8 bits are valid flags. - var typeTutors = new bool[8]; - for (int i = 0; i < typeTutors.Length; i++) - typeTutors[i] = FlagUtil.GetFlag(data, 0x38, i); - TypeTutors = typeTutors; - } + public override byte[] Write() => Data; - public override byte[] Write() - { - for (var i = 0; i < CountTM; i++) - FlagUtil.SetFlag(Data, 0x28 + (i >> 3), i, TMHM[i]); - for (int i = 0; i < TypeTutors.Length; i++) - FlagUtil.SetFlag(Data, 0x38, i, TypeTutors[i]); - return Data; - } + public bool IsRecordPermitted(int index) => false; + public ReadOnlySpan RecordPermitIndexes => PersonalInfo8SWSH.RecordedMoves; + public int RecordCountTotal => 112; + public int RecordCountUsed => PersonalInfo8SWSH.RecordedMoves.Length; public override int HP { get => Data[0x00]; set => Data[0x00] = (byte)value; } public override int ATK { get => Data[0x01]; set => Data[0x01] = (byte)value; } @@ -55,7 +40,7 @@ public sealed class PersonalInfo8BDSP : PersonalInfo, IPersonalAbility12H public int Item1 { get => ReadInt16LittleEndian(Data.AsSpan(0x0C)); set => WriteInt16LittleEndian(Data.AsSpan(0x0C), (short)value); } public int Item2 { get => ReadInt16LittleEndian(Data.AsSpan(0x0E)); set => WriteInt16LittleEndian(Data.AsSpan(0x0E), (short)value); } public int Item3 { get => ReadInt16LittleEndian(Data.AsSpan(0x10)); set => WriteInt16LittleEndian(Data.AsSpan(0x10), (short)value); } - public override int Gender { get => Data[0x12]; set => Data[0x12] = (byte)value; } + public override byte Gender { get => Data[0x12]; set => Data[0x12] = value; } public override int HatchCycles { get => Data[0x13]; set => Data[0x13] = (byte)value; } public override int BaseFriendship { get => Data[0x14]; set => Data[0x14] = (byte)value; } public override byte EXPGrowth { get => Data[0x15]; set => Data[0x15] = value; } @@ -98,4 +83,64 @@ public sealed class PersonalInfo8BDSP : PersonalInfo, IPersonalAbility12H /// Checks if the entry shows up in any of the built-in Pokédex. /// public bool IsInDex => PokeDexIndex != 0; + + private const int TMHM = 0x28; + private const int CountTM = 100; + private const int ByteCountTM = 112 / 8; + private const int TypeTutors = 0x38; + private const int TypeTutorsCount = 4; + + public bool GetIsLearnTM(int index) + { + if ((uint)index >= CountTM) + return false; + return (Data[0x28 + (index >> 3)] & (1 << (index & 7))) != 0; + } + + public void SetIsLearnTM(int index, bool value) + { + if ((uint)index >= CountTM) + throw new ArgumentOutOfRangeException(nameof(index), index, null); + if (value) + Data[TMHM + (index >> 3)] |= (byte)(1 << (index & 7)); + else + Data[TMHM + (index >> 3)] &= (byte)~(1 << (index & 7)); + } + + public bool GetIsLearnTutorType(int index) + { + if ((uint)index >= TypeTutorsCount) + return false; + return (Data[TypeTutors + (index >> 3)] & (1 << (index & 7))) != 0; + } + + public void SetIsLearnTutorType(int index, bool value) + { + if ((uint)index >= TypeTutorsCount) + throw new ArgumentOutOfRangeException(nameof(index), index, null); + if (value) + Data[TypeTutors + (index >> 3)] |= (byte)(1 << (index & 7)); + else + Data[TypeTutors + (index >> 3)] &= (byte)~(1 << (index & 7)); + } + + public void SetAllLearnTM(Span result, ReadOnlySpan moves) + { + var span = Data.AsSpan(TMHM, ByteCountTM); + for (int index = CountTM - 1; index >= 0; index--) + { + if ((span[index >> 3] & (1 << (index & 7))) != 0) + result[moves[index]] = true; + } + } + + public void SetAllLearnTutorType(Span result, ReadOnlySpan moves) + { + var tutor = Data[TypeTutors]; + for (int index = TypeTutorsCount - 1; index >= 0; index--) + { + if ((tutor & (1 << (index & 7))) != 0) + result[moves[index]] = true; + } + } } diff --git a/PKHeX.Core/PersonalInfo/Info/PersonalInfo8LA.cs b/PKHeX.Core/PersonalInfo/Info/PersonalInfo8LA.cs index 3d7f8ba92..9d028c338 100644 --- a/PKHeX.Core/PersonalInfo/Info/PersonalInfo8LA.cs +++ b/PKHeX.Core/PersonalInfo/Info/PersonalInfo8LA.cs @@ -6,32 +6,13 @@ namespace PKHeX.Core; /// /// class with values from the games. /// -public sealed class PersonalInfo8LA : PersonalInfo, IPersonalAbility12H +public sealed class PersonalInfo8LA : PersonalInfo, IPersonalAbility12H, IPermitRecord { public const int SIZE = 0xB0; private readonly byte[] Data; - public PersonalInfo8LA(byte[] data) - { - Data = data; - // TM/TR and Special Tutors are inaccessible; dummy data. - - // 0xA8-0xAF are armor type tutors, one bit for each type - var moveShop = new bool[Legal.MoveShop8_LA.Length]; - for (int i = 0; i < moveShop.Length; i++) - moveShop[i] = FlagUtil.GetFlag(Data, 0xA8 + (i >> 3), i); - SpecialTutors = new[] - { - moveShop, - }; - } - - public override byte[] Write() - { - for (int i = 0; i < SpecialTutors[0].Length; i++) - FlagUtil.SetFlag(Data, 0xA8 + (i >> 3), i, SpecialTutors[0][i]); - return Data; - } + public PersonalInfo8LA(byte[] data) => Data = data; + public override byte[] Write() => Data; public override int HP { get => Data[0x00]; set => Data[0x00] = (byte)value; } public override int ATK { get => Data[0x01]; set => Data[0x01] = (byte)value; } @@ -53,7 +34,7 @@ public sealed class PersonalInfo8LA : PersonalInfo, IPersonalAbility12H public int Item1 { get => ReadInt16LittleEndian(Data.AsSpan(0x0C)); set => WriteInt16LittleEndian(Data.AsSpan(0x0C), (short)value); } public int Item2 { get => ReadInt16LittleEndian(Data.AsSpan(0x0E)); set => WriteInt16LittleEndian(Data.AsSpan(0x0E), (short)value); } public int Item3 { get => ReadInt16LittleEndian(Data.AsSpan(0x10)); set => WriteInt16LittleEndian(Data.AsSpan(0x10), (short)value); } - public override int Gender { get => Data[0x12]; set => Data[0x12] = (byte)value; } + public override byte Gender { get => Data[0x12]; set => Data[0x12] = value; } public override int HatchCycles { get => Data[0x13]; set => Data[0x13] = (byte)value; } public override int BaseFriendship { get => Data[0x14]; set => Data[0x14] = (byte)value; } public override byte EXPGrowth { get => Data[0x15]; set => Data[0x15] = value; } @@ -96,31 +77,127 @@ public sealed class PersonalInfo8LA : PersonalInfo, IPersonalAbility12H _ => throw new ArgumentOutOfRangeException(nameof(abilityIndex), abilityIndex, null), }; - public int GetMoveShopCount() - { - // Return a count of true indexes from Tutors - var arr = SpecialTutors[0]; - int count = 0; - foreach (var index in arr) - { - if (index) - count++; - } - return count; - } + private const int MoveShop = 0xA8; + private const int MoveShopCount = 61; + + private ulong MoveShopBits => ReadUInt64LittleEndian(Data.AsSpan(MoveShop)); + + public int GetMoveShopCount() => System.Numerics.BitOperations.PopCount(MoveShopBits); public int GetMoveShopIndex(int randIndexFromCount) { // Return a count of true indexes from Tutors - var arr = SpecialTutors[0]; - for (var i = 0; i < arr.Length; i++) + var bits = MoveShopBits; + for (int i = 0; i < MoveShopCount; i++) { - var index = arr[i]; - if (!index) - continue; - if (randIndexFromCount-- == 0) - return i; + if ((bits & 1) == 1) + { + if (randIndexFromCount-- == 0) + return i; + } + bits >>= 1; } throw new ArgumentOutOfRangeException(nameof(randIndexFromCount)); } + + public bool IsRecordPermitted(int index) + { + return (MoveShopBits & (1ul << index)) != 0; + } + + public bool GetIsLearnMoveShop(ushort move) + { + var moves = MoveShopMoves.AsSpan(); + var index = moves.IndexOf(move); + return index != -1 && IsRecordPermitted(index); + } + + public ReadOnlySpan RecordPermitIndexes => MoveShopMoves; + public int RecordCountTotal => 64; + public int RecordCountUsed => MoveShopCount; + public bool HasMoveShop => MoveShopBits != 0; + + private static readonly ushort[] MoveShopMoves = + { + (int)Move.FalseSwipe, + (int)Move.FireFang, + (int)Move.ThunderFang, + (int)Move.IceFang, + (int)Move.IceBall, + (int)Move.RockSmash, + (int)Move.Spikes, + (int)Move.Bulldoze, + (int)Move.AerialAce, + (int)Move.StealthRock, + (int)Move.Swift, + (int)Move.TriAttack, + (int)Move.MagicalLeaf, + (int)Move.OminousWind, + (int)Move.PowerShift, + (int)Move.FocusEnergy, + (int)Move.BulkUp, + (int)Move.CalmMind, + (int)Move.Rest, + (int)Move.BabyDollEyes, + (int)Move.FirePunch, + (int)Move.ThunderPunch, + (int)Move.IcePunch, + (int)Move.DrainPunch, + (int)Move.PoisonJab, + (int)Move.PsychoCut, + (int)Move.ZenHeadbutt, + (int)Move.LeechLife, + (int)Move.XScissor, + (int)Move.RockSlide, + (int)Move.ShadowClaw, + (int)Move.IronHead, + (int)Move.IronTail, + (int)Move.MysticalFire, + (int)Move.WaterPulse, + (int)Move.ChargeBeam, + (int)Move.EnergyBall, + (int)Move.IcyWind, + (int)Move.SludgeBomb, + (int)Move.EarthPower, + (int)Move.ShadowBall, + (int)Move.Snarl, + (int)Move.FlashCannon, + (int)Move.DazzlingGleam, + (int)Move.GigaImpact, + (int)Move.AquaTail, + (int)Move.WildCharge, + (int)Move.HighHorsepower, + (int)Move.Megahorn, + (int)Move.StoneEdge, + (int)Move.Outrage, + (int)Move.PlayRough, + (int)Move.HyperBeam, + (int)Move.Flamethrower, + (int)Move.Thunderbolt, + (int)Move.IceBeam, + (int)Move.Psychic, + (int)Move.DarkPulse, + (int)Move.DracoMeteor, + (int)Move.SteelBeam, + (int)Move.VoltTackle, + }; + + public static ushort GetMoveShopMove(int index) + { + if ((uint)index >= MoveShopCount) + throw new ArgumentOutOfRangeException(nameof(index), index, null); + return MoveShopMoves[index]; + } + + public void SetAllLearnMoveShop(Span result) + { + var moves = MoveShopMoves; + var bits = MoveShopBits; + for (int i = 0 ; i < MoveShopCount; i++) + { + if ((bits & 1) == 1) + result[moves[i]] = true; + bits >>= 1; + } + } } diff --git a/PKHeX.Core/PersonalInfo/Info/PersonalInfo8SWSH.cs b/PKHeX.Core/PersonalInfo/Info/PersonalInfo8SWSH.cs index f6e1e14a4..906185234 100644 --- a/PKHeX.Core/PersonalInfo/Info/PersonalInfo8SWSH.cs +++ b/PKHeX.Core/PersonalInfo/Info/PersonalInfo8SWSH.cs @@ -6,52 +6,13 @@ namespace PKHeX.Core; /// /// class with values from the games. /// -public sealed class PersonalInfo8SWSH : PersonalInfo, IPersonalAbility12H +public sealed class PersonalInfo8SWSH : PersonalInfo, IPersonalAbility12H, IPersonalInfoTM, IPersonalInfoTR, IPersonalInfoTutorType, IPermitRecord { public const int SIZE = 0xB0; - public const int CountTM = 100; - public const int CountTR = 100; private readonly byte[] Data; - public PersonalInfo8SWSH(byte[] data) - { - Data = data; - TMHM = new bool[200]; - for (var i = 0; i < CountTR; i++) - { - TMHM[i] = FlagUtil.GetFlag(Data, 0x28 + (i >> 3), i); - TMHM[i + CountTM] = FlagUtil.GetFlag(Data, 0x3C + (i >> 3), i); - } - - // 0x38-0x3B type tutors, but only 8 bits are valid flags. - var typeTutors = new bool[8]; - for (int i = 0; i < typeTutors.Length; i++) - typeTutors[i] = FlagUtil.GetFlag(Data, 0x38, i); - TypeTutors = typeTutors; - - // 0xA8-0xAF are armor type tutors, one bit for each type - var armorTutors = new bool[18]; - for (int i = 0; i < armorTutors.Length; i++) - armorTutors[i] = FlagUtil.GetFlag(Data, 0xA8 + (i >> 3), i); - SpecialTutors = new[] - { - armorTutors, - }; - } - - public override byte[] Write() - { - for (var i = 0; i < CountTR; i++) - { - FlagUtil.SetFlag(Data, 0x28 + (i >> 3), i, TMHM[i]); - FlagUtil.SetFlag(Data, 0x3C + (i >> 3), i, TMHM[i + CountTM]); - } - for (int i = 0; i < TypeTutors.Length; i++) - FlagUtil.SetFlag(Data, 0x38, i, TypeTutors[i]); - for (int i = 0; i < SpecialTutors[0].Length; i++) - FlagUtil.SetFlag(Data, 0xA8 + (i >> 3), i, SpecialTutors[0][i]); - return Data; - } + public PersonalInfo8SWSH(byte[] data) => Data = data; + public override byte[] Write() => Data; public override int HP { get => Data[0x00]; set => Data[0x00] = (byte)value; } public override int ATK { get => Data[0x01]; set => Data[0x01] = (byte)value; } @@ -73,7 +34,7 @@ public sealed class PersonalInfo8SWSH : PersonalInfo, IPersonalAbility12H public int Item1 { get => ReadInt16LittleEndian(Data.AsSpan(0x0C)); set => WriteInt16LittleEndian(Data.AsSpan(0x0C), (short)value); } public int Item2 { get => ReadInt16LittleEndian(Data.AsSpan(0x0E)); set => WriteInt16LittleEndian(Data.AsSpan(0x0E), (short)value); } public int Item3 { get => ReadInt16LittleEndian(Data.AsSpan(0x10)); set => WriteInt16LittleEndian(Data.AsSpan(0x10), (short)value); } - public override int Gender { get => Data[0x12]; set => Data[0x12] = (byte)value; } + public override byte Gender { get => Data[0x12]; set => Data[0x12] = value; } public override int HatchCycles { get => Data[0x13]; set => Data[0x13] = (byte)value; } public override int BaseFriendship { get => Data[0x14]; set => Data[0x14] = (byte)value; } public override byte EXPGrowth { get => Data[0x15]; set => Data[0x15] = value; } @@ -123,4 +84,198 @@ public sealed class PersonalInfo8SWSH : PersonalInfo, IPersonalAbility12H 2 => AbilityH, _ => throw new ArgumentOutOfRangeException(nameof(abilityIndex), abilityIndex, null), }; + + private const int TM = 0x28; + private const int TR = 0x3C; + private const int TutorType = 0x38; + private const int TutorArmor = 0xA8; + private const int CountTM = 100; + private const int CountTR = 100; + private const int ByteCountTM = (CountTM + 7) / 8; + private const int CountTutorType = 8; + private const int CountTutorArmor = 18; + + public bool GetIsLearnTM(int index) + { + if ((uint)index >= CountTM) + return false; + return (Data[TM + (index >> 3)] & (1 << (index & 7))) != 0; + } + + public void SetIsLearnTM(int index, bool value) + { + if ((uint)index >= CountTM) + return; + if (value) + Data[TM + (index >> 3)] |= (byte)(1 << (index & 7)); + else + Data[TM + (index >> 3)] &= (byte)~(1 << (index & 7)); + } + + public void SetAllLearnTM(Span result) + { + var moves = TM_SWSH; + var span = Data.AsSpan(TM, ByteCountTM); + for (int i = moves.Length - 1; i >= 0; i--) + { + if ((span[i >> 3] & (1 << (i & 7))) != 0) + result[moves[i]] = true; + } + } + + public bool GetIsLearnTR(int index) + { + if ((uint)index >= CountTR) + return false; + return (Data[TR + (index >> 3)] & (1 << (index & 7))) != 0; + } + + public void SetIsLearnTR(int index, bool value) + { + if ((uint)index >= CountTR) + return; + if (value) + Data[TR + (index >> 3)] |= (byte)(1 << (index & 7)); + else + Data[TR + (index >> 3)] &= (byte)~(1 << (index & 7)); + } + + public bool GetIsLearnTutorType(int index) + { + if ((uint)index >= CountTutorType) + return false; + return (Data[TutorType + (index >> 3)] & (1 << (index & 7))) != 0; + } + + public void SetIsLearnTutorType(int index, bool value) + { + if ((uint)index >= CountTutorType) + throw new ArgumentOutOfRangeException(nameof(index), index, null); + if (value) + Data[TutorType + (index >> 3)] |= (byte)(1 << (index & 7)); + else + Data[TutorType + (index >> 3)] &= (byte)~(1 << (index & 7)); + } + + public void SetAllLearnTutorType(Span result) + { + var moves = TypeTutor8; + var tutor = Data[TutorType]; + for (int i = moves.Length - 1; i >= 0; i--) + { + if ((tutor & (1 << (i & 7))) != 0) + result[moves[i]] = true; + } + } + + public bool GetIsLearnTutorSpecial(int index) + { + if ((uint)index >= CountTutorArmor) + return false; + return (Data[TutorArmor + (index >> 3)] & (1 << (index & 7))) != 0; + } + + public void SetIsLearnTutorSpecial(int index, bool value) + { + if ((uint)index >= CountTutorArmor) + return; + if (value) + Data[TutorArmor + (index >> 3)] |= (byte)(1 << (index & 7)); + else + Data[TutorArmor + (index >> 3)] &= (byte)~(1 << (index & 7)); + } + + public void SetAllLearnTutorSpecial(Span result) + { + var moves = Tutors_SWSH; + var span = Data.AsSpan(TutorArmor, 3); + for (int i = moves.Length - 1; i >= 0; i--) + { + if ((span[i >> 3] & (1 << (i & 7))) != 0) + result[moves[i]] = true; + } + } + + public void SetAllLearnTR(Span result) + { + var moves = TR_SWSH; + var span = Data.AsSpan(TR, ByteCountTM); + for (int i = moves.Length - 1; i >= 0; i--) + { + if ((span[i >> 3] & (1 << (i & 7))) != 0) + result[moves[i]] = true; + } + } + + private static readonly ushort[] TM_SWSH = + { + 005, 025, 006, 007, 008, 009, 019, 042, 063, 416, + 345, 076, 669, 083, 086, 091, 103, 113, 115, 219, + 120, 156, 157, 168, 173, 182, 184, 196, 202, 204, + 211, 213, 201, 240, 241, 258, 250, 251, 261, 263, + 129, 270, 279, 280, 286, 291, 311, 313, 317, 328, + 331, 333, 340, 341, 350, 362, 369, 371, 372, 374, + 384, 385, 683, 409, 419, 421, 422, 423, 424, 427, + 433, 472, 478, 440, 474, 490, 496, 506, 512, 514, + 521, 523, 527, 534, 541, 555, 566, 577, 580, 581, + 604, 678, 595, 598, 206, 403, 684, 693, 707, 784, + }; + + private static readonly ushort[] TR_SWSH = + { + 014, 034, 053, 056, 057, 058, 059, 067, 085, 087, + 089, 094, 097, 116, 118, 126, 127, 133, 141, 161, + 164, 179, 188, 191, 200, 473, 203, 214, 224, 226, + 227, 231, 242, 247, 248, 253, 257, 269, 271, 276, + 285, 299, 304, 315, 322, 330, 334, 337, 339, 347, + 348, 349, 360, 370, 390, 394, 396, 398, 399, 402, + 404, 405, 406, 408, 411, 412, 413, 414, 417, 428, + 430, 437, 438, 441, 442, 444, 446, 447, 482, 484, + 486, 492, 500, 502, 503, 526, 528, 529, 535, 542, + 583, 599, 605, 663, 667, 675, 676, 706, 710, 776, + }; + + private static readonly ushort[] TypeTutor8 = + { + (int)Move.GrassPledge, + (int)Move.FirePledge, + (int)Move.WaterPledge, + (int)Move.FrenzyPlant, + (int)Move.BlastBurn, + (int)Move.HydroCannon, + (int)Move.DracoMeteor, + (int)Move.SteelBeam, + }; + + private static readonly ushort[] Tutors_SWSH = + { + 805, 807, 812, 804, 803, 813, 811, 810, + 815, 814, 797, 806, 800, 809, 799, 808, + 798, 802, + }; + + public bool IsRecordPermitted(int index) => GetIsLearnTR(index); + + public bool GetIsLearnTM(ushort move) + { + var index = TM_SWSH.AsSpan().IndexOf(move); + return GetIsLearnTM(index); + } + + public bool GetIsLearnTutorType(ushort move) + { + var index = TypeTutor8.AsSpan().IndexOf(move); + return GetIsLearnTutorType(index); + } + + public bool GetIsLearnTutorSpecial(ushort move) + { + var index = Tutors_SWSH.AsSpan().IndexOf(move); + return GetIsLearnTutorSpecial(index); + } + + public static ReadOnlySpan RecordedMoves => TR_SWSH; + public ReadOnlySpan RecordPermitIndexes => TR_SWSH; + public int RecordCountTotal => 112; + public int RecordCountUsed => CountTR; } diff --git a/PKHeX.Core/PersonalInfo/Info/PersonalInfo9SV.cs b/PKHeX.Core/PersonalInfo/Info/PersonalInfo9SV.cs index d964170f7..069ec5980 100644 --- a/PKHeX.Core/PersonalInfo/Info/PersonalInfo9SV.cs +++ b/PKHeX.Core/PersonalInfo/Info/PersonalInfo9SV.cs @@ -6,30 +6,13 @@ namespace PKHeX.Core; /// /// class with values from the games. /// -public sealed class PersonalInfo9SV : PersonalInfo, IPersonalAbility12H +public sealed class PersonalInfo9SV : PersonalInfo, IPersonalAbility12H, IPersonalInfoTM, IPermitRecord { public const int SIZE = 0x44; private readonly byte[] Data; - public const int CountTM = 172; - - public PersonalInfo9SV(byte[] data) - { - Data = data; - TMHM = new bool[CountTM]; - - var tm = Data.AsSpan(0x2C); - for (var i = 0; i < CountTM; i++) - TMHM[i] = FlagUtil.GetFlag(tm, i >> 3, i); - } - - public override byte[] Write() - { - var tm = Data.AsSpan(0x2C); - for (var i = 0; i < CountTM; i++) - FlagUtil.SetFlag(tm, i >> 3, i, TMHM[i]); - return Data; - } + public PersonalInfo9SV(byte[] data) => Data = data; + public override byte[] Write() => Data; public override int HP { get => Data[0x00]; set => Data[0x00] = (byte)value; } public override int ATK { get => Data[0x01]; set => Data[0x01] = (byte)value; } @@ -48,7 +31,7 @@ public sealed class PersonalInfo9SV : PersonalInfo, IPersonalAbility12H public override int EV_SPE { get => (EVYield >> 6) & 0x3; set => EVYield = (EVYield & ~(0x3 << 6)) | ((value & 0x3) << 6); } public override int EV_SPA { get => (EVYield >> 8) & 0x3; set => EVYield = (EVYield & ~(0x3 << 8)) | ((value & 0x3) << 8); } public override int EV_SPD { get => (EVYield >> 10) & 0x3; set => EVYield = (EVYield & ~(0x3 << 10)) | ((value & 0x3) << 10); } - public override int Gender { get => Data[0x0C]; set => Data[0x0C] = (byte)value; } + public override byte Gender { get => Data[0x0C]; set => Data[0x0C] = value; } public override int HatchCycles { get => Data[0x0D]; set => Data[0x0D] = (byte)value; } public override int BaseFriendship { get => Data[0x0E]; set => Data[0x0E] = (byte)value; } public override byte EXPGrowth { get => Data[0x0F]; set => Data[0x0F] = value; } @@ -93,4 +76,64 @@ public sealed class PersonalInfo9SV : PersonalInfo, IPersonalAbility12H 2 => AbilityH, _ => throw new ArgumentOutOfRangeException(nameof(abilityIndex), abilityIndex, null), }; + + private const int TM = 0x2C; + private const int CountTM = 172; + private const int ByteCountTM = (CountTM + 7) / 8; + + public bool GetIsLearnTM(int index) + { + if ((uint)index >= CountTM) + return false; + return (Data[TM + (index >> 3)] & (1 << (index & 7))) != 0; + } + + public void SetIsLearnTM(int index, bool value) + { + if ((uint)index >= CountTM) + return; + if (value) + Data[TM + (index >> 3)] |= (byte)(1 << (index & 7)); + else + Data[TM + (index >> 3)] &= (byte)~(1 << (index & 7)); + } + + public void SetAllLearnTM(Span result) + { + var moves = TM_SV; + var span = Data.AsSpan(TM, ByteCountTM); + for (int i = CountTM - 1; i >= 0; i--) + { + if ((span[i >> 3] & (1 << (i & 7))) != 0) + result[moves[i]] = true; + } + } + + public bool IsRecordPermitted(int index) => GetIsLearnTM(index); + + public ReadOnlySpan RecordPermitIndexes => TM_SV; + public int RecordCountTotal => 200; + public int RecordCountUsed => CountTM; + + private static readonly ushort[] TM_SV = + { + 005, 036, 204, 313, 097, 189, 184, 182, 424, 422, + 423, 352, 067, 491, 512, 522, 060, 109, 168, 574, + 885, 884, 886, 451, 083, 263, 342, 332, 523, 506, + 555, 232, 129, 345, 196, 341, 317, 577, 488, 490, + 314, 500, 101, 374, 525, 474, 419, 203, 521, 241, + 240, 201, 883, 684, 473, 091, 331, 206, 280, 428, + 369, 421, 492, 706, 339, 403, 034, 007, 009, 008, + 214, 402, 486, 409, 115, 113, 350, 127, 337, 605, + 118, 447, 086, 398, 707, 156, 157, 269, 014, 776, + 191, 390, 286, 430, 399, 141, 598, 019, 285, 442, + 349, 408, 441, 164, 334, 404, 529, 261, 242, 271, + 710, 202, 396, 366, 247, 406, 446, 304, 257, 412, + 094, 484, 227, 057, 861, 053, 085, 583, 133, 347, + 270, 676, 226, 414, 179, 058, 604, 580, 678, 581, + 417, 126, 056, 059, 519, 518, 520, 528, 188, 089, + 444, 566, 416, 307, 308, 338, 200, 315, 411, 437, + 542, 433, 405, 063, 413, 394, 087, 370, 076, 434, + 796, 851, + }; } diff --git a/PKHeX.Core/PersonalInfo/Interfaces/IBaseStat.cs b/PKHeX.Core/PersonalInfo/Interfaces/IBaseStat.cs index 42d74f7ff..078db86aa 100644 --- a/PKHeX.Core/PersonalInfo/Interfaces/IBaseStat.cs +++ b/PKHeX.Core/PersonalInfo/Interfaces/IBaseStat.cs @@ -38,7 +38,7 @@ public interface IBaseStat int SPE { get; set; } } -public static class IBaseStatExtensions +public static class BaseStatExtensions { /// /// Base Stat Total sum of all stats. @@ -59,6 +59,11 @@ public static class IBaseStatExtensions _ => throw new ArgumentOutOfRangeException(nameof(index)), }; + /// + /// Gathers the base stat values into the then sorts (by value) lowest to highest. + /// + /// Stat implementation to load from + /// Result storage public static void GetSortedStatIndexes(this IBaseStat pi, Span<(int Index, int Stat)> span) { for (int i = 0; i < span.Length; i++) diff --git a/PKHeX.Core/PersonalInfo/Interfaces/IPersonalInfo.cs b/PKHeX.Core/PersonalInfo/Interfaces/IPersonalInfo.cs index 5ceedd8cb..27f34ca2d 100644 --- a/PKHeX.Core/PersonalInfo/Interfaces/IPersonalInfo.cs +++ b/PKHeX.Core/PersonalInfo/Interfaces/IPersonalInfo.cs @@ -13,7 +13,7 @@ public interface IPersonalInfo : IBaseStat, IEffortValueYield, IGenderDetail, IP /// /// Gender Ratio value determining if the entry is a fixed gender or bi-gendered. /// - int Gender { get; set; } + byte Gender { get; set; } /// /// Experience-Level Growth Rate type diff --git a/PKHeX.Core/PersonalInfo/PersonalInfo.cs b/PKHeX.Core/PersonalInfo/PersonalInfo.cs index 6890a5cb7..34fce3c64 100644 --- a/PKHeX.Core/PersonalInfo/PersonalInfo.cs +++ b/PKHeX.Core/PersonalInfo/PersonalInfo.cs @@ -1,5 +1,3 @@ -using System; - namespace PKHeX.Core; /// @@ -26,7 +24,7 @@ public abstract class PersonalInfo : IPersonalInfo public abstract int EggGroup2 { get; set; } public abstract int CatchRate { get; set; } public virtual int EvoStage { get; set; } - public abstract int Gender { get; set; } + public abstract byte Gender { get; set; } public abstract int HatchCycles { get; set; } public abstract int BaseFriendship { get; set; } public abstract byte EXPGrowth { get; set; } @@ -41,38 +39,6 @@ public abstract class PersonalInfo : IPersonalInfo public virtual int Height { get; set; } public virtual int Weight { get; set; } - /// - /// TM/HM learn compatibility flags for individual moves. - /// - public bool[] TMHM = Array.Empty(); - - /// - /// Grass-Fire-Water-Etc typed learn compatibility flags for individual moves. - /// - public bool[] TypeTutors = Array.Empty(); - - /// - /// Special tutor learn compatibility flags for individual moves. - /// - public bool[][] SpecialTutors = Array.Empty(); - - protected static bool[] GetBits(ReadOnlySpan data) - { - bool[] result = new bool[data.Length << 3]; - for (int i = result.Length - 1; i >= 0; i--) - result[i] = ((data[i >> 3] >> (i & 7)) & 0x1) == 1; - return result; - } - - protected static void SetBits(ReadOnlySpan bits, Span data) - { - for (int i = bits.Length - 1; i >= 0; i--) - data[i>>3] |= (byte)(bits[i] ? 1 << (i&0x7) : 0); - } - - public void AddTMHM(ReadOnlySpan data) => TMHM = GetBits(data); - public void AddTypeTutors(ReadOnlySpan data) => TypeTutors = GetBits(data); - public int FormIndex(ushort species, byte form) { if (!HasForm(form)) @@ -91,13 +57,13 @@ public abstract class PersonalInfo : IPersonalInfo return true; } - public const int RatioMagicGenderless = 255; - public const int RatioMagicFemale = 254; - public const int RatioMagicMale = 0; + public const byte RatioMagicGenderless = 255; + public const byte RatioMagicFemale = 254; + public const byte RatioMagicMale = 0; - public static bool IsSingleGender(int gt) => (uint)(gt - 1) >= 253; + public static bool IsSingleGender(byte gt) => gt - 1u >= 253; - public bool IsDualGender => (uint)(Gender - 1) < 253; + public bool IsDualGender => Gender - 1u < 253; public bool Genderless => Gender == RatioMagicGenderless; public bool OnlyFemale => Gender == RatioMagicFemale; public bool OnlyMale => Gender == RatioMagicMale; @@ -115,3 +81,21 @@ public abstract class PersonalInfo : IPersonalInfo return form < FormCount; } } + +public interface IPersonalInfoTM +{ + bool GetIsLearnTM(int index); + void SetIsLearnTM(int index, bool value); +} + +public interface IPersonalInfoTutorType +{ + bool GetIsLearnTutorType(int index); + void SetIsLearnTutorType(int index, bool value); +} + +public interface IPersonalInfoTR +{ + bool GetIsLearnTR(int index); + void SetIsLearnTR(int index, bool value); +} diff --git a/PKHeX.Core/PersonalInfo/Table/PersonalTable1.cs b/PKHeX.Core/PersonalInfo/Table/PersonalTable1.cs index fa7e10d5e..78e73d412 100644 --- a/PKHeX.Core/PersonalInfo/Table/PersonalTable1.cs +++ b/PKHeX.Core/PersonalInfo/Table/PersonalTable1.cs @@ -28,7 +28,7 @@ public sealed class PersonalTable1 : IPersonalTable, IPersonalTable Table[GetFormIndex(species, form)]; public int GetFormIndex(ushort species, byte form) => IsSpeciesInGame(species) ? species : 0; - public bool IsSpeciesInGame(ushort species) => (uint)species <= MaxSpecies; + public bool IsSpeciesInGame(ushort species) => species <= MaxSpecies; public bool IsPresentInGame(ushort species, byte form) => form == 0 && IsSpeciesInGame(species); PersonalInfo IPersonalTable.this[int index] => this[index]; diff --git a/PKHeX.Core/PersonalInfo/Table/PersonalTable2.cs b/PKHeX.Core/PersonalInfo/Table/PersonalTable2.cs index 22ac711f3..7b80db2d4 100644 --- a/PKHeX.Core/PersonalInfo/Table/PersonalTable2.cs +++ b/PKHeX.Core/PersonalInfo/Table/PersonalTable2.cs @@ -28,7 +28,7 @@ public sealed class PersonalTable2 : IPersonalTable, IPersonalTable Table[GetFormIndex(species, form)]; public int GetFormIndex(ushort species, byte form) => IsSpeciesInGame(species) ? species : 0; - public bool IsSpeciesInGame(ushort species) => (uint)species <= MaxSpecies; + public bool IsSpeciesInGame(ushort species) => species <= MaxSpecies; public bool IsPresentInGame(ushort species, byte form) { if (!IsSpeciesInGame(species)) diff --git a/PKHeX.Core/PersonalInfo/Table/PersonalTable3.cs b/PKHeX.Core/PersonalInfo/Table/PersonalTable3.cs index 5a1d9b13b..598c87f2f 100644 --- a/PKHeX.Core/PersonalInfo/Table/PersonalTable3.cs +++ b/PKHeX.Core/PersonalInfo/Table/PersonalTable3.cs @@ -28,7 +28,7 @@ public sealed class PersonalTable3 : IPersonalTable, IPersonalTable Table[GetFormIndex(species, form)]; public int GetFormIndex(ushort species, byte form) => IsSpeciesInGame(species) ? species : 0; - public bool IsSpeciesInGame(ushort species) => (uint)species <= MaxSpecies; + public bool IsSpeciesInGame(ushort species) => species <= MaxSpecies; public bool IsPresentInGame(ushort species, byte form) { if (!IsSpeciesInGame(species)) @@ -63,11 +63,6 @@ public sealed class PersonalTable3 : IPersonalTable, IPersonalTable= 1; i--) - { - var entry = table[i]; - var source = other[i]; - entry.TMHM = source.TMHM; - entry.TypeTutors = source.TypeTutors; - } + table[i].CopyFrom(other[i]); } } diff --git a/PKHeX.Core/PersonalInfo/Table/PersonalTable4.cs b/PKHeX.Core/PersonalInfo/Table/PersonalTable4.cs index fcdbd9cad..67b387e46 100644 --- a/PKHeX.Core/PersonalInfo/Table/PersonalTable4.cs +++ b/PKHeX.Core/PersonalInfo/Table/PersonalTable4.cs @@ -30,12 +30,12 @@ public sealed class PersonalTable4 : IPersonalTable, IPersonalTable (uint)species <= MaxSpecies; + public bool IsSpeciesInGame(ushort species) => species <= MaxSpecies; public bool IsPresentInGame(ushort species, byte form) { if (!IsSpeciesInGame(species)) @@ -74,7 +74,7 @@ public sealed class PersonalTable4 : IPersonalTable, IPersonalTable (uint)species <= MaxSpecies; + public bool IsSpeciesInGame(ushort species) => species <= MaxSpecies; public bool IsPresentInGame(ushort species, byte form) { if (!IsSpeciesInGame(species)) diff --git a/PKHeX.Core/PersonalInfo/Table/PersonalTable5BW.cs b/PKHeX.Core/PersonalInfo/Table/PersonalTable5BW.cs index 26ffc5b47..04b8b622d 100644 --- a/PKHeX.Core/PersonalInfo/Table/PersonalTable5BW.cs +++ b/PKHeX.Core/PersonalInfo/Table/PersonalTable5BW.cs @@ -30,12 +30,12 @@ public sealed class PersonalTable5BW : IPersonalTable, IPersonalTable (uint)species <= MaxSpecies; + public bool IsSpeciesInGame(ushort species) => species <= MaxSpecies; public bool IsPresentInGame(ushort species, byte form) { if (!IsSpeciesInGame(species)) diff --git a/PKHeX.Core/PersonalInfo/Table/PersonalTable6AO.cs b/PKHeX.Core/PersonalInfo/Table/PersonalTable6AO.cs index 22820ec98..cdbb58bb7 100644 --- a/PKHeX.Core/PersonalInfo/Table/PersonalTable6AO.cs +++ b/PKHeX.Core/PersonalInfo/Table/PersonalTable6AO.cs @@ -30,12 +30,12 @@ public sealed class PersonalTable6AO : IPersonalTable, IPersonalTable (uint)species <= MaxSpecies; + public bool IsSpeciesInGame(ushort species) => species <= MaxSpecies; public bool IsPresentInGame(ushort species, byte form) { if (!IsSpeciesInGame(species)) diff --git a/PKHeX.Core/PersonalInfo/Table/PersonalTable6XY.cs b/PKHeX.Core/PersonalInfo/Table/PersonalTable6XY.cs index 6386fc74c..c1e57f8ce 100644 --- a/PKHeX.Core/PersonalInfo/Table/PersonalTable6XY.cs +++ b/PKHeX.Core/PersonalInfo/Table/PersonalTable6XY.cs @@ -30,12 +30,12 @@ public sealed class PersonalTable6XY : IPersonalTable, IPersonalTable (uint)species <= MaxSpecies; + public bool IsSpeciesInGame(ushort species) => species <= MaxSpecies; public bool IsPresentInGame(ushort species, byte form) { if (!IsSpeciesInGame(species)) diff --git a/PKHeX.Core/PersonalInfo/Table/PersonalTable7.cs b/PKHeX.Core/PersonalInfo/Table/PersonalTable7.cs index df1adb538..a5db57be6 100644 --- a/PKHeX.Core/PersonalInfo/Table/PersonalTable7.cs +++ b/PKHeX.Core/PersonalInfo/Table/PersonalTable7.cs @@ -30,12 +30,12 @@ public sealed class PersonalTable7 : IPersonalTable, IPersonalTable (uint)species <= MaxSpeciesID; + public bool IsSpeciesInGame(ushort species) => species <= MaxSpeciesID; public bool IsPresentInGame(ushort species, byte form) { if (!IsSpeciesInGame(species)) diff --git a/PKHeX.Core/PersonalInfo/Table/PersonalTable7GG.cs b/PKHeX.Core/PersonalInfo/Table/PersonalTable7GG.cs index 85237e5ed..7af82883b 100644 --- a/PKHeX.Core/PersonalInfo/Table/PersonalTable7GG.cs +++ b/PKHeX.Core/PersonalInfo/Table/PersonalTable7GG.cs @@ -29,12 +29,12 @@ public sealed class PersonalTable7GG : IPersonalTable, IPersonalTable (uint)species is <= Legal.MaxSpeciesID_1 or (int)Species.Meltan or (int)Species.Melmetal; + public bool IsSpeciesInGame(ushort species) => species is <= Legal.MaxSpeciesID_1 or (int)Species.Meltan or (int)Species.Melmetal; public bool IsPresentInGame(ushort species, byte form) { if (!IsSpeciesInGame(species)) diff --git a/PKHeX.Core/PersonalInfo/Table/PersonalTable8BDSP.cs b/PKHeX.Core/PersonalInfo/Table/PersonalTable8BDSP.cs index 6a724392f..8cb1f2877 100644 --- a/PKHeX.Core/PersonalInfo/Table/PersonalTable8BDSP.cs +++ b/PKHeX.Core/PersonalInfo/Table/PersonalTable8BDSP.cs @@ -29,12 +29,12 @@ public sealed class PersonalTable8BDSP : IPersonalTable, IPersonalTable (uint)species <= MaxSpecies; + public bool IsSpeciesInGame(ushort species) => species <= MaxSpecies; public bool IsPresentInGame(ushort species, byte form) { if (!IsSpeciesInGame(species)) diff --git a/PKHeX.Core/PersonalInfo/Table/PersonalTable8LA.cs b/PKHeX.Core/PersonalInfo/Table/PersonalTable8LA.cs index 538ef765b..63bf1f486 100644 --- a/PKHeX.Core/PersonalInfo/Table/PersonalTable8LA.cs +++ b/PKHeX.Core/PersonalInfo/Table/PersonalTable8LA.cs @@ -29,14 +29,14 @@ public sealed class PersonalTable8LA : IPersonalTable, IPersonalTable MaxSpecies) + if (species > MaxSpecies) return false; var form0 = Table[species]; @@ -55,7 +55,7 @@ public sealed class PersonalTable8LA : IPersonalTable, IPersonalTable MaxSpecies) + if (species > MaxSpecies) return false; var form0 = Table[species]; diff --git a/PKHeX.Core/PersonalInfo/Table/PersonalTable8SWSH.cs b/PKHeX.Core/PersonalInfo/Table/PersonalTable8SWSH.cs index ff1e42b79..b66008ba9 100644 --- a/PKHeX.Core/PersonalInfo/Table/PersonalTable8SWSH.cs +++ b/PKHeX.Core/PersonalInfo/Table/PersonalTable8SWSH.cs @@ -29,14 +29,14 @@ public sealed class PersonalTable8SWSH : IPersonalTable, IPersonalTable MaxSpeciesID) + if (species > MaxSpeciesID) return false; var form0 = Table[species]; @@ -55,7 +55,7 @@ public sealed class PersonalTable8SWSH : IPersonalTable, IPersonalTable MaxSpeciesID) + if (species > MaxSpeciesID) return false; var form0 = Table[species]; diff --git a/PKHeX.Core/PersonalInfo/Table/PersonalTable9SV.cs b/PKHeX.Core/PersonalInfo/Table/PersonalTable9SV.cs index 348677a2a..0daed6e73 100644 --- a/PKHeX.Core/PersonalInfo/Table/PersonalTable9SV.cs +++ b/PKHeX.Core/PersonalInfo/Table/PersonalTable9SV.cs @@ -29,14 +29,14 @@ public sealed class PersonalTable9SV : IPersonalTable, IPersonalTable MaxSpeciesID) + if (species > MaxSpeciesID) return false; var form0 = Table[species]; @@ -55,7 +55,7 @@ public sealed class PersonalTable9SV : IPersonalTable, IPersonalTable MaxSpeciesID) + if (species > MaxSpeciesID) return false; var form0 = Table[species]; diff --git a/PKHeX.Core/Resources/byte/eggmove/eggmove_sv.pkl b/PKHeX.Core/Resources/byte/eggmove/eggmove_sv.pkl index 3455675e6..cda14e02d 100644 Binary files a/PKHeX.Core/Resources/byte/eggmove/eggmove_sv.pkl and b/PKHeX.Core/Resources/byte/eggmove/eggmove_sv.pkl differ diff --git a/PKHeX.Core/Resources/byte/evolve/evos_sv.pkl b/PKHeX.Core/Resources/byte/evolve/evos_sv.pkl index 1d3605788..1344dbdc5 100644 Binary files a/PKHeX.Core/Resources/byte/evolve/evos_sv.pkl and b/PKHeX.Core/Resources/byte/evolve/evos_sv.pkl differ diff --git a/PKHeX.Core/Resources/byte/levelup/lvlmove_sv.pkl b/PKHeX.Core/Resources/byte/levelup/lvlmove_sv.pkl index 29157b8de..f80308477 100644 Binary files a/PKHeX.Core/Resources/byte/levelup/lvlmove_sv.pkl and b/PKHeX.Core/Resources/byte/levelup/lvlmove_sv.pkl differ diff --git a/PKHeX.Core/Resources/byte/personal/personal_sv b/PKHeX.Core/Resources/byte/personal/personal_sv index b91fe8091..a9f471e57 100644 Binary files a/PKHeX.Core/Resources/byte/personal/personal_sv and b/PKHeX.Core/Resources/byte/personal/personal_sv differ diff --git a/PKHeX.Core/Resources/byte/personal/reminder_sv.pkl b/PKHeX.Core/Resources/byte/personal/reminder_sv.pkl index 76470b0a3..48c9c599e 100644 Binary files a/PKHeX.Core/Resources/byte/personal/reminder_sv.pkl and b/PKHeX.Core/Resources/byte/personal/reminder_sv.pkl differ diff --git a/PKHeX.Core/Resources/legality/checks/LegalityCheckStrings_de.txt b/PKHeX.Core/Resources/legality/checks/LegalityCheckStrings_de.txt index 692bbf346..97acf3cc5 100644 --- a/PKHeX.Core/Resources/legality/checks/LegalityCheckStrings_de.txt +++ b/PKHeX.Core/Resources/legality/checks/LegalityCheckStrings_de.txt @@ -188,7 +188,7 @@ LG2TreeID = Found a tree for Crystal headbutt encounter that matches OTID. LG3EReader = Non Japanese Shadow E-reader Pokémon. Unreleased encounter. LG3OTGender = OT from Colosseum/XD cannot be female. LG4InvalidTileR45Surf = Johto Route 45 surfing encounter. Unreachable Water tiles. -LG5ID_N = The Name/TID/SID of N is incorrect. +LG5ID_N = The Name/TID16/SID16 of N is incorrect. LG5IVAll30 = All IVs of N's Pokémon should be 30. LG5OTGenderN = N's Pokémon must have a male OT gender. LG5PIDShinyGrotto = Hidden Grotto captures cannot be shiny. @@ -330,12 +330,12 @@ LNickMatchLanguageFail = Nickname does not match species name. LNickMatchLanguageFlag = Nickname flagged, matches species name. LNickMatchNoOthers = Nickname does not match another species name. LNickMatchNoOthersFail = Nickname matches another species name (+language). -LOT_IDEqual = TID and SID are equal. +LOT_IDEqual = TID16 and SID16 are equal. LOT_IDInvalid = TID and SID combination is not possible. -LOT_IDs0 = TID and SID are 0. -LOT_SID0 = SID is zero. -LOT_SID0Invalid = SID should be 0. -LOT_TID0 = TID is zero. +LOT_IDs0 = TID16 and SID16 are 0. +LOT_SID0 = SID16 is zero. +LOT_SID0Invalid = SID16 should be 0. +LOT_TID0 = TID16 is zero. LOTLanguage = Language ID should be {0}, not {1}. LOTLong = OT Name too long. LOTShort = OT Name too short. diff --git a/PKHeX.Core/Resources/legality/checks/LegalityCheckStrings_en.txt b/PKHeX.Core/Resources/legality/checks/LegalityCheckStrings_en.txt index aaecb83b7..0ed3bac24 100644 --- a/PKHeX.Core/Resources/legality/checks/LegalityCheckStrings_en.txt +++ b/PKHeX.Core/Resources/legality/checks/LegalityCheckStrings_en.txt @@ -188,7 +188,7 @@ LG2TreeID = Found a tree for Crystal headbutt encounter that matches OTID. LG3EReader = Non Japanese Shadow E-reader Pokémon. Unreleased encounter. LG3OTGender = OT from Colosseum/XD cannot be female. LG4InvalidTileR45Surf = Johto Route 45 surfing encounter. Unreachable Water tiles. -LG5ID_N = The Name/TID/SID of N is incorrect. +LG5ID_N = The Name/TID16/SID16 of N is incorrect. LG5IVAll30 = All IVs of N's Pokémon should be 30. LG5OTGenderN = N's Pokémon must have a male OT gender. LG5PIDShinyGrotto = Hidden Grotto captures cannot be shiny. @@ -330,12 +330,12 @@ LNickMatchLanguageFail = Nickname does not match species name. LNickMatchLanguageFlag = Nickname flagged, matches species name. LNickMatchNoOthers = Nickname does not match another species name. LNickMatchNoOthersFail = Nickname matches another species name (+language). -LOT_IDEqual = TID and SID are equal. +LOT_IDEqual = TID16 and SID16 are equal. LOT_IDInvalid = TID and SID combination is not possible. -LOT_IDs0 = TID and SID are 0. -LOT_SID0 = SID is zero. -LOT_SID0Invalid = SID should be 0. -LOT_TID0 = TID is zero. +LOT_IDs0 = TID16 and SID16 are 0. +LOT_SID0 = SID16 is zero. +LOT_SID0Invalid = SID16 should be 0. +LOT_TID0 = TID16 is zero. LOTLanguage = Language ID should be {0}, not {1}. LOTLong = OT Name too long. LOTShort = OT Name too short. diff --git a/PKHeX.Core/Resources/legality/checks/LegalityCheckStrings_es.txt b/PKHeX.Core/Resources/legality/checks/LegalityCheckStrings_es.txt index 82f21ccc3..056b1d75c 100644 --- a/PKHeX.Core/Resources/legality/checks/LegalityCheckStrings_es.txt +++ b/PKHeX.Core/Resources/legality/checks/LegalityCheckStrings_es.txt @@ -188,7 +188,7 @@ LG2TreeID = Se encontró un árbol para el encuentro mediante Cabezazo en Crista LG3EReader = Pokémon oscuro de E-Reader japonés. Encuentro no liberado. LG3OTGender = EO de Colosseum/XD no puede ser femenino. LG4InvalidTileR45Surf = Encuentro mediante Surf en la ruta 45 de Johto. Zonas de agua inalcanzables. -LG5ID_N = El nombre/TID/SID de N es incorrecto. +LG5ID_N = El nombre/TID16/SID16 de N es incorrecto. LG5IVAll30 = Todos los IVs de los Pokémon de N deberían ser 30. LG5OTGenderN = Los Pokémon de N deben tener un género OT masculino. LG5PIDShinyGrotto = Las Capturas en Los Claros Ocultos no pueden ser variocolor. @@ -330,12 +330,12 @@ LNickMatchLanguageFail = El mote no coincide con el de la especie. LNickMatchLanguageFlag = Mote marcado, coincide con el de la especie. LNickMatchNoOthers = El mote no coincide con el de otra especie. LNickMatchNoOthersFail = El Mote coincide con el de otra especie (+Idioma). -LOT_IDEqual = El TID y el SID son iguales. +LOT_IDEqual = El TID16 y el SID16 son iguales. LOT_IDInvalid = La combinación TID y SID no es posible. -LOT_IDs0 = El TID y el SID son 0. -LOT_SID0 = El SID es cero. -LOT_SID0Invalid = El SID debería ser 0. -LOT_TID0 = El TID es cero. +LOT_IDs0 = El TID16 y el SID16 son 0. +LOT_SID0 = El SID16 es cero. +LOT_SID0Invalid = El SID16 debería ser 0. +LOT_TID0 = El TID16 es cero. LOTLanguage = El ID del lenguaje debería de ser {0}, no {1}. LOTLong = El nombre del EO demasiado largo. LOTShort = El nombre del EO es muy corto. diff --git a/PKHeX.Core/Resources/legality/checks/LegalityCheckStrings_it.txt b/PKHeX.Core/Resources/legality/checks/LegalityCheckStrings_it.txt index f8758fd02..e611b5f1a 100644 --- a/PKHeX.Core/Resources/legality/checks/LegalityCheckStrings_it.txt +++ b/PKHeX.Core/Resources/legality/checks/LegalityCheckStrings_it.txt @@ -188,7 +188,7 @@ LG2TreeID = Trovato un albero per un incontro Bottintesta su Cristallo che corri LG3EReader = Incontro Ombra E-Reader non Giapponese. Evento non rilasciato. LG3OTGender = AO di Colosseum/XD non possono essere femmina. LG4InvalidTileR45Surf = Incontro da surf nel Percorso 45 di Johto, la casella d'acqua è irraggiungibile. -LG5ID_N = Il Nome/TID/SID di N non è corretto. +LG5ID_N = Il Nome/TID16/SID16 di N non è corretto. LG5IVAll30 = Tutti gli IV dei Pokémon di N dovrebbero essere 30. LG5OTGenderN = I Pokémon di N devono avere il sesso dell'AO maschio. LG5PIDShinyGrotto = Gli incontri del Meandro Nascosto non possono essere Shiny. @@ -330,12 +330,12 @@ LNickMatchLanguageFail = Il soprannome non corrisponde alla specie. LNickMatchLanguageFlag = Soprannome segnalato, corrisponde al nome della specie. LNickMatchNoOthers = Il soprannome non corrisponde al nome di un altra specie. LNickMatchNoOthersFail = Il soprannome corrisponde al nome di un'altra specie (+language). -LOT_IDEqual = TID e SID sono uguali. +LOT_IDEqual = TID16 e SID16 sono uguali. LOT_IDInvalid = la combinazione di TID e SID non è possibile. -LOT_IDs0 = TID e SID sono 0. -LOT_SID0 = SID è zero. -LOT_SID0Invalid = SID dovrebbe essere 0. -LOT_TID0 = TID è zero. +LOT_IDs0 = TID16 e SID16 sono 0. +LOT_SID0 = SID16 è zero. +LOT_SID0Invalid = SID16 dovrebbe essere 0. +LOT_TID0 = TID16 è zero. LOTLanguage = Language ID dovrebbe essere {0}, non {1}. LOTLong = Nome AO troppo lungo. LOTShort = Nome AO troppo corto. diff --git a/PKHeX.Core/Resources/legality/checks/LegalityCheckStrings_ja.txt b/PKHeX.Core/Resources/legality/checks/LegalityCheckStrings_ja.txt index b70668ee4..1eef597ee 100644 --- a/PKHeX.Core/Resources/legality/checks/LegalityCheckStrings_ja.txt +++ b/PKHeX.Core/Resources/legality/checks/LegalityCheckStrings_ja.txt @@ -188,7 +188,7 @@ LG2TreeID = Found a tree for Crystal headbutt encounter that matches OTID. LG3EReader = Non Japanese Shadow E-reader Pokémon. Unreleased encounter. LG3OTGender = 「ポケモンコロシアム」「ポケモンXD」では女性トレーナーは選択できません LG4InvalidTileR45Surf = Johto Route 45 surfing encounter. Unreachable Water tiles. -LG5ID_N = The Name/TID/SID of N is incorrect. +LG5ID_N = The Name/TID16/SID16 of N is incorrect. LG5IVAll30 = All IVs of N's Pokémon should be 30. LG5OTGenderN = N's Pokémon must have a male OT gender. LG5PIDShinyGrotto = Hidden Grotto captures cannot be shiny. @@ -330,12 +330,12 @@ LNickMatchLanguageFail = Nickname does not match species name. LNickMatchLanguageFlag = Nickname flagged, matches species name. LNickMatchNoOthers = Nickname does not match another species name. LNickMatchNoOthersFail = Nickname matches another species name (+language). -LOT_IDEqual = TID and SID are equal. +LOT_IDEqual = TID16 and SID16 are equal. LOT_IDInvalid = TID and SID combination is not possible. -LOT_IDs0 = TID and SID are 0. -LOT_SID0 = SID is zero. +LOT_IDs0 = TID16 and SID16 are 0. +LOT_SID0 = SID16 is zero. LOT_SID0Invalid = 裏IDは「00000」でなければなりません -LOT_TID0 = TID is zero. +LOT_TID0 = TID16 is zero. LOTLanguage = Language ID should be {0}, not {1}. LOTLong = トレーナー名の文字数が超過しています LOTShort = トレーナー名が空白です diff --git a/PKHeX.Core/Resources/legality/checks/LegalityCheckStrings_ko.txt b/PKHeX.Core/Resources/legality/checks/LegalityCheckStrings_ko.txt index cc9bcde90..fca4b0b23 100644 --- a/PKHeX.Core/Resources/legality/checks/LegalityCheckStrings_ko.txt +++ b/PKHeX.Core/Resources/legality/checks/LegalityCheckStrings_ko.txt @@ -188,7 +188,7 @@ LG2TreeID = 크리스탈 버전 어버이 ID와 일치하는 박치기 인카운 LG3EReader = 일본판이 아닌 버전의 섀도우 E-reader 포켓몬입니다. 배포되지 않은 인카운터입니다. LG3OTGender = 콜로세움/XD 버전에서는 여성 어버이를 사용할 수 없습니다. LG4InvalidTileR45Surf = 성도 45번 도로는 물 타일에 접근할 수 없으므로 파도타기 인카운터가 불가능합니다. -LG5ID_N = N의 이름/TID/SID가 잘못되었습니다. +LG5ID_N = N의 이름/TID16/SID16가 잘못되었습니다. LG5IVAll30 = N이 소유한 포켓몬의 IV는 30이어야 합니다. LG5OTGenderN = N's Pokémon must have a male OT gender. LG5PIDShinyGrotto = 은혈에서 포획한 포켓몬은 색이 다를 수 없습니다. @@ -330,12 +330,12 @@ LNickMatchLanguageFail = 이름이 포켓몬 종류와 일치하지 않습니다 LNickMatchLanguageFlag = 이름 플래그가 켜져 있으나 이름이 포켓몬 종류와 일치합니다. LNickMatchNoOthers = 이름이 다른 포켓몬 종류와 일치하지 않습니다. LNickMatchNoOthersFail = 이름이 다른 포켓몬 종류와 일치합니다 (+언어). -LOT_IDEqual = TID와 SID가 동일합니다. +LOT_IDEqual = TID16와 SID16가 동일합니다. LOT_IDInvalid = TID and SID combination is not possible. -LOT_IDs0 = TID와 SID가 0입니다. -LOT_SID0 = SID가 0입니다. -LOT_SID0Invalid = SID는 0이어야 합니다. -LOT_TID0 = TID가 0입니다. +LOT_IDs0 = TID16와 SID16가 0입니다. +LOT_SID0 = SID16가 0입니다. +LOT_SID0Invalid = SID16는 0이어야 합니다. +LOT_TID0 = TID16가 0입니다. LOTLanguage = 언어 ID는 {1}이 아니라 {0}이어야 합니다. LOTLong = 어버이 이름이 너무 깁니다. LOTShort = 어버이의 이름이 너무 짧습니다. diff --git a/PKHeX.Core/Resources/legality/wild/Gen9/encounter_fixed_paldea.pkl b/PKHeX.Core/Resources/legality/wild/Gen9/encounter_fixed_paldea.pkl index cf9d6a563..8a31dc5fd 100644 Binary files a/PKHeX.Core/Resources/legality/wild/Gen9/encounter_fixed_paldea.pkl and b/PKHeX.Core/Resources/legality/wild/Gen9/encounter_fixed_paldea.pkl differ diff --git a/PKHeX.Core/Resources/legality/wild/Gen9/encounter_gem_paldea.pkl b/PKHeX.Core/Resources/legality/wild/Gen9/encounter_gem_paldea.pkl index cef6110ec..9a56a82e0 100644 Binary files a/PKHeX.Core/Resources/legality/wild/Gen9/encounter_gem_paldea.pkl and b/PKHeX.Core/Resources/legality/wild/Gen9/encounter_gem_paldea.pkl differ diff --git a/PKHeX.Core/Resources/legality/wild/Gen9/encounter_wild_paldea.pkl b/PKHeX.Core/Resources/legality/wild/Gen9/encounter_wild_paldea.pkl index 440f7f0ba..a45cf49ee 100644 Binary files a/PKHeX.Core/Resources/legality/wild/Gen9/encounter_wild_paldea.pkl and b/PKHeX.Core/Resources/legality/wild/Gen9/encounter_wild_paldea.pkl differ diff --git a/PKHeX.Core/Resources/text/other/de/text_Forms_de.txt b/PKHeX.Core/Resources/text/other/de/text_Forms_de.txt index e58cc8817..98fe1bb92 100644 --- a/PKHeX.Core/Resources/text/other/de/text_Forms_de.txt +++ b/PKHeX.Core/Resources/text/other/de/text_Forms_de.txt @@ -1120,4 +1120,7 @@ Kompletter Begrenzter Fahr Wasser -Gleit \ No newline at end of file +Gleit +Gefecht +Flammen +Fluten \ No newline at end of file diff --git a/PKHeX.Core/Resources/text/other/de/text_Species_de.txt b/PKHeX.Core/Resources/text/other/de/text_Species_de.txt index d59027bf6..5a84a75c2 100644 --- a/PKHeX.Core/Resources/text/other/de/text_Species_de.txt +++ b/PKHeX.Core/Resources/text/other/de/text_Species_de.txt @@ -915,97 +915,97 @@ Fuentente Bailonda Ferkuli Fragrunz -Dummimisel Tarundel Spinsidias Micrick Lextremo -Relluk -Skarabaks -Gruff -Friedwuff -Flattutu -Psiopatra -Farigiraf -Schligda -Schligdri -Heerashai -Agiluza -Normifin -Delfinator -Olini -Olivinio -Olithena -Chilingel -Halupenjo -Blipp -Wampitz -Knattox -Knattatox -Schlurm -Zwieps -Famieps -Flaniwal -Kolowal -Frospino -Cryospino -Espinodon -Nigiragi -Mopex Pamo Pamamo Pamomamo -Voltrel -Voltrean -Adebom +Zwieps +Famieps +Hefel +Backel +Olini +Olivinio +Olithena Krawalloro -Flaminkno -Klibbe Geosali Sedisal Saltigant -Lumispross -Lumiflora -Sproxi -Affiti -Hefel -Backel -Mobtiff -Mastifioso -Weherba -Horrerba -Gierspenst -Monetigo -Riesenzahn -Wutpilz -AKETUBAN -Sandfell -Brüllschweif -Flatterhaar -Kriechflügel -Donnersichel -Eisenrad -BKETUBAN -Eisenfalter -Eisenhand -Eisenhals -Eisendorn -Eisenbündel -Eisenkrieger -Dinglu -Baojian -Chongjian -Yuyu -Koraidon -Miraidon -Forgita -Tafforgita -Granforgita Knarbon Crimanzo Azugladis +Blipp +Wampitz +Voltrel +Voltrean +Mobtiff +Mastifioso +Sproxi +Affiti +Weherba +Horrerba Tentagra Tenterra -Gladimperio +Klibbe +Chilingel +Halupenjo +Relluk +Skarabaks +Flattutu +Psiopatra +Forgita +Tafforgita +Granforgita +Schligda +Schligdri +Adebom +Normifin +Delfinator +Knattox +Knattatox +Mopex +Schlurm +Lumispross +Lumiflora +Gruff +Friedwuff +Flaminkno +Flaniwal +Kolowal +Agiluza +Heerashai +Nigiragi +Epitaff Suelord -Epitaff \ No newline at end of file +Farigiraf +Dummimisel +Gladimperio +Riesenzahn +Brüllschweif +Wutpilz +Flatterhaar +Kriechflügel +Sandfell +Eisenrad +Eisenbündel +Eisenhand +Eisenhals +Eisenfalter +Eisendorn +Frospino +Cryospino +Espinodon +Gierspenst +Monetigo +Chongjian +Baojian +Dinglu +Yuyu +Donnersichel +Eisenkrieger +Koraidon +Miraidon +AKETUBAN +BKETUBAN \ No newline at end of file diff --git a/PKHeX.Core/Resources/text/other/en/text_Forms_en.txt b/PKHeX.Core/Resources/text/other/en/text_Forms_en.txt index 946008595..679d1bb06 100644 --- a/PKHeX.Core/Resources/text/other/en/text_Forms_en.txt +++ b/PKHeX.Core/Resources/text/other/en/text_Forms_en.txt @@ -1120,4 +1120,7 @@ Ultimate Low-Power Drive Aquatic -Glide \ No newline at end of file +Glide +Combat +Blaze +Aqua \ No newline at end of file diff --git a/PKHeX.Core/Resources/text/other/en/text_Species_en.txt b/PKHeX.Core/Resources/text/other/en/text_Species_en.txt index c02a586e9..82b95aea2 100644 --- a/PKHeX.Core/Resources/text/other/en/text_Species_en.txt +++ b/PKHeX.Core/Resources/text/other/en/text_Species_en.txt @@ -915,97 +915,97 @@ Quaxwell Quaquaval Lechonk Oinkologne -Dudunsparce Tarountula Spidops Nymble Lokix -Rellor -Rabsca -Greavard -Houndstone -Flittle -Espathra -Farigiraf -Wiglett -Wugtrio -Dondozo -Veluza -Finizen -Palafin -Smoliv -Dolliv -Arboliva -Capsakid -Scovillain -Tadbulb -Bellibolt -Varoom -Revavroom -Orthworm -Tandemaus -Maushold -Cetoddle -Cetitan -Frigibax -Arctibax -Baxcalibur -Tatsugiri -Cyclizar Pawmi Pawmo Pawmot -Wattrel -Kilowattrel -Bombirdier +Tandemaus +Maushold +Fidough +Dachsbun +Smoliv +Dolliv +Arboliva Squawkabilly -Flamigo -Klawf Nacli Naclstack Garganacl -Glimmet -Glimmora -Shroodle -Grafaiai -Fidough -Dachsbun -Maschiff -Mabosstiff -Bramblin -Brambleghast -Gimmighoul -Gholdengo -Great Tusk -Brute Bonnet -AKETUBAN -Sandy Shocks -Scream Tail -Flutter Mane -Slither Wing -Roaring Moon -Iron Treads -BKETUBAN -Iron Moth -Iron Hands -Iron Jugulis -Iron Thorns -Iron Bundle -Iron Valiant -Ting-Lu -Chien-Pao -Wo-Chien -Chi-Yu -Koraidon -Miraidon -Tinkatink -Tinkatuff -Tinkaton Charcadet Armarouge Ceruledge +Tadbulb +Bellibolt +Wattrel +Kilowattrel +Maschiff +Mabosstiff +Shroodle +Grafaiai +Bramblin +Brambleghast Toedscool Toedscruel -Kingambit +Klawf +Capsakid +Scovillain +Rellor +Rabsca +Flittle +Espathra +Tinkatink +Tinkatuff +Tinkaton +Wiglett +Wugtrio +Bombirdier +Finizen +Palafin +Varoom +Revavroom +Cyclizar +Orthworm +Glimmet +Glimmora +Greavard +Houndstone +Flamigo +Cetoddle +Cetitan +Veluza +Dondozo +Tatsugiri +Annihilape Clodsire -Annihilape \ No newline at end of file +Farigiraf +Dudunsparce +Kingambit +Great Tusk +Scream Tail +Brute Bonnet +Flutter Mane +Slither Wing +Sandy Shocks +Iron Treads +Iron Bundle +Iron Hands +Iron Jugulis +Iron Moth +Iron Thorns +Frigibax +Arctibax +Baxcalibur +Gimmighoul +Gholdengo +Wo-Chien +Chien-Pao +Ting-Lu +Chi-Yu +Roaring Moon +Iron Valiant +Koraidon +Miraidon +AKETUBAN +BKETUBAN \ No newline at end of file diff --git a/PKHeX.Core/Resources/text/other/es/text_Forms_es.txt b/PKHeX.Core/Resources/text/other/es/text_Forms_es.txt index 0e992ab7f..aec442e89 100644 --- a/PKHeX.Core/Resources/text/other/es/text_Forms_es.txt +++ b/PKHeX.Core/Resources/text/other/es/text_Forms_es.txt @@ -1120,4 +1120,7 @@ Pleno Limitado Conducción Flote -Planeo \ No newline at end of file +Planeo +Combatiente +Ardiente +Acuática \ No newline at end of file diff --git a/PKHeX.Core/Resources/text/other/es/text_Species_es.txt b/PKHeX.Core/Resources/text/other/es/text_Species_es.txt index e28fab1ef..4e73156d7 100644 --- a/PKHeX.Core/Resources/text/other/es/text_Species_es.txt +++ b/PKHeX.Core/Resources/text/other/es/text_Species_es.txt @@ -915,97 +915,97 @@ Quaxwell Quaquaval Lechonk Oinkologne -Dudunsparce Tarountula Spidops Nymble Lokix -Rellor -Rabsca -Greavard -Houndstone -Flittle -Espathra -Farigiraf -Wiglett -Wugtrio -Dondozo -Veluza -Finizen -Palafin -Smoliv -Dolliv -Arboliva -Capsakid -Scovillain -Tadbulb -Bellibolt -Varoom -Revavroom -Orthworm -Tandemaus -Maushold -Cetoddle -Cetitan -Frigibax -Arctibax -Baxcalibur -Tatsugiri -Cyclizar Pawmi Pawmo Pawmot -Wattrel -Kilowattrel -Bombirdier +Tandemaus +Maushold +Fidough +Dachsbun +Smoliv +Dolliv +Arboliva Squawkabilly -Flamigo -Klawf Nacli Naclstack Garganacl -Glimmet -Glimmora -Shroodle -Grafaiai -Fidough -Dachsbun -Maschiff -Mabosstiff -Bramblin -Brambleghast -Gimmighoul -Gholdengo -Colmilargo -Furioseta -AKETUBAN -Pelarena -Colagrito -Melenaleteo -Reptalada -Bramaluna -Ferrodada -BKETUBAN -Ferropolilla -Ferropalmas -Ferrocuello -Ferropúas -Ferrosaco -Ferropaladín -Ting-Lu -Chien-Pao -Wo-Chien -Chi-Yu -Koraidon -Miraidon -Tinkatink -Tinkatuff -Tinkaton Charcadet Armarouge Ceruledge +Tadbulb +Bellibolt +Wattrel +Kilowattrel +Maschiff +Mabosstiff +Shroodle +Grafaiai +Bramblin +Brambleghast Toedscool Toedscruel -Kingambit +Klawf +Capsakid +Scovillain +Rellor +Rabsca +Flittle +Espathra +Tinkatink +Tinkatuff +Tinkaton +Wiglett +Wugtrio +Bombirdier +Finizen +Palafin +Varoom +Revavroom +Cyclizar +Orthworm +Glimmet +Glimmora +Greavard +Houndstone +Flamigo +Cetoddle +Cetitan +Veluza +Dondozo +Tatsugiri +Annihilape Clodsire -Annihilape \ No newline at end of file +Farigiraf +Dudunsparce +Kingambit +Colmilargo +Colagrito +Furioseta +Melenaleteo +Reptalada +Pelarena +Ferrodada +Ferrosaco +Ferropalmas +Ferrocuello +Ferropolilla +Ferropúas +Frigibax +Arctibax +Baxcalibur +Gimmighoul +Gholdengo +Wo-Chien +Chien-Pao +Ting-Lu +Chi-Yu +Bramaluna +Ferropaladín +Koraidon +Miraidon +AKETUBAN +BKETUBAN \ No newline at end of file diff --git a/PKHeX.Core/Resources/text/other/fr/text_Forms_fr.txt b/PKHeX.Core/Resources/text/other/fr/text_Forms_fr.txt index 6b8259178..46f1adfd2 100644 --- a/PKHeX.Core/Resources/text/other/fr/text_Forms_fr.txt +++ b/PKHeX.Core/Resources/text/other/fr/text_Forms_fr.txt @@ -1120,4 +1120,7 @@ Ultime Bridé Terrestre Aquatique -Aérien \ No newline at end of file +Aérien +Combative +Flamboyante +Aquatique \ No newline at end of file diff --git a/PKHeX.Core/Resources/text/other/fr/text_Species_fr.txt b/PKHeX.Core/Resources/text/other/fr/text_Species_fr.txt index 81da6a01b..e0592624d 100644 --- a/PKHeX.Core/Resources/text/other/fr/text_Species_fr.txt +++ b/PKHeX.Core/Resources/text/other/fr/text_Species_fr.txt @@ -915,97 +915,97 @@ Canarbello Palmaval Gourmelet Fragroin -Deusolourdo Tissenboule Filentrappe Lilliterelle Gambex -Léboulérou -Bérasca -Toutombe -Tomberro -Flotillon -Cléopsytra -Farigiraf -Taupikeau -Triopikeau -Oyacata -Délestin -Dofin -Superdofin -Olivini -Olivado -Arboliva -Pimito -Scovilain -Têtampoule -Ampibidou -Vrombi -Vrombotor -Ferdeter -Compagnol -Famignol -Piétacé -Balbalèze -Frigodo -Cryodo -Glaivodo -Nigirigon -Motorizard Pohm Pohmotte Pohmarmotte -Zapétrel -Fulgulairo -Lestombaile +Compagnol +Famignol +Pâtachiot +Briochien +Olivini +Olivado +Arboliva Tapatoès -Flamenroule -Craparoi Selutin Amassel Gigansel -Germéclat -Floréclat -Gribouraigne -Tag-Tag -Pâtachiot -Briochien -Grondogue -Dogrino -Virovent -Virevorreur -Mordudor -Gromago -Fort-Ivoire -Fongus-Furie -AKETUBAN -Pelage-Sablé -Hurle-Queue -Flotte-Mèche -Rampe-Ailes -Rugit-Lune -Roue-de-Fer -BKETUBAN -Mite-de-Fer -Paume-de-Fer -Têtes-de-Fer -Épine-de-Fer -Hotte-de-Fer -Garde-de-Fer -Dinglu -Baojian -Chongjian -Yuyu -Koraidon -Miraidon -Forgerette -Forgella -Forgelina Charbambin Carmadura Malvalame +Têtampoule +Ampibidou +Zapétrel +Fulgulairo +Grondogue +Dogrino +Gribouraigne +Tag-Tag +Virovent +Virevorreur Terracool Terracruel -Scalpereur +Craparoi +Pimito +Scovilain +Léboulérou +Bérasca +Flotillon +Cléopsytra +Forgerette +Forgella +Forgelina +Taupikeau +Triopikeau +Lestombaile +Dofin +Superdofin +Vrombi +Vrombotor +Motorizard +Ferdeter +Germéclat +Floréclat +Toutombe +Tomberro +Flamenroule +Piétacé +Balbalèze +Délestin +Oyacata +Nigirigon +Courrousinge Terraiste -Courrousinge \ No newline at end of file +Farigiraf +Deusolourdo +Scalpereur +Fort-Ivoire +Hurle-Queue +Fongus-Furie +Flotte-Mèche +Rampe-Ailes +Pelage-Sablé +Roue-de-Fer +Hotte-de-Fer +Paume-de-Fer +Têtes-de-Fer +Mite-de-Fer +Épine-de-Fer +Frigodo +Cryodo +Glaivodo +Mordudor +Gromago +Chongjian +Baojian +Dinglu +Yuyu +Rugit-Lune +Garde-de-Fer +Koraidon +Miraidon +AKETUBAN +BKETUBAN \ No newline at end of file diff --git a/PKHeX.Core/Resources/text/other/it/text_Forms_it.txt b/PKHeX.Core/Resources/text/other/it/text_Forms_it.txt index 15512feb6..fd0b5663a 100644 --- a/PKHeX.Core/Resources/text/other/it/text_Forms_it.txt +++ b/PKHeX.Core/Resources/text/other/it/text_Forms_it.txt @@ -1120,4 +1120,7 @@ Completo Limitato Sprint Nuoto -Planata \ No newline at end of file +Planata +Combattiva +Infuocata +Acquatica \ No newline at end of file diff --git a/PKHeX.Core/Resources/text/other/it/text_Species_it.txt b/PKHeX.Core/Resources/text/other/it/text_Species_it.txt index 60f05d660..8de1bfe70 100644 --- a/PKHeX.Core/Resources/text/other/it/text_Species_it.txt +++ b/PKHeX.Core/Resources/text/other/it/text_Species_it.txt @@ -915,97 +915,97 @@ Quaxwell Quaquaval Lechonk Oinkologne -Dudunsparce Tarountula Spidops Nymble Lokix -Rellor -Rabsca -Greavard -Houndstone -Flittle -Espathra -Farigiraf -Wiglett -Wugtrio -Dondozo -Veluza -Finizen -Palafin -Smoliv -Dolliv -Arboliva -Capsakid -Scovillain -Tadbulb -Bellibolt -Varoom -Revavroom -Orthworm -Tandemaus -Maushold -Cetoddle -Cetitan -Frigibax -Arctibax -Baxcalibur -Tatsugiri -Cyclizar Pawmi Pawmo Pawmot -Wattrel -Kilowattrel -Bombirdier +Tandemaus +Maushold +Fidough +Dachsbun +Smoliv +Dolliv +Arboliva Squawkabilly -Flamigo -Klawf Nacli Naclstack Garganacl -Glimmet -Glimmora -Shroodle -Grafaiai -Fidough -Dachsbun -Maschiff -Mabosstiff -Bramblin -Brambleghast -Gimmighoul -Gholdengo -Grandizanne -Fungofurioso -AKETUBAN -Peldisabbia -Codaurlante -Crinealato -Alirasenti -Lunaruggente -Solcoferreo -BKETUBAN -Falenaferrea -Manoferrea -Colloferreo -Spineferree -Saccoferreo -Eroeferreo -Ting-Lu -Chien-Pao -Wo-Chien -Chi-Yu -Koraidon -Miraidon -Tinkatink -Tinkatuff -Tinkaton Charcadet Armarouge Ceruledge +Tadbulb +Bellibolt +Wattrel +Kilowattrel +Maschiff +Mabosstiff +Shroodle +Grafaiai +Bramblin +Brambleghast Toedscool Toedscruel -Kingambit +Klawf +Capsakid +Scovillain +Rellor +Rabsca +Flittle +Espathra +Tinkatink +Tinkatuff +Tinkaton +Wiglett +Wugtrio +Bombirdier +Finizen +Palafin +Varoom +Revavroom +Cyclizar +Orthworm +Glimmet +Glimmora +Greavard +Houndstone +Flamigo +Cetoddle +Cetitan +Veluza +Dondozo +Tatsugiri +Annihilape Clodsire -Annihilape \ No newline at end of file +Farigiraf +Dudunsparce +Kingambit +Grandizanne +Codaurlante +Fungofurioso +Crinealato +Alirasenti +Peldisabbia +Solcoferreo +Saccoferreo +Manoferrea +Colloferreo +Falenaferrea +Spineferree +Frigibax +Arctibax +Baxcalibur +Gimmighoul +Gholdengo +Wo-Chien +Chien-Pao +Ting-Lu +Chi-Yu +Lunaruggente +Eroeferreo +Koraidon +Miraidon +AKETUBAN +BKETUBAN \ No newline at end of file diff --git a/PKHeX.Core/Resources/text/other/ja/text_Forms_ja.txt b/PKHeX.Core/Resources/text/other/ja/text_Forms_ja.txt index 2519715b3..3bc5593fc 100644 --- a/PKHeX.Core/Resources/text/other/ja/text_Forms_ja.txt +++ b/PKHeX.Core/Resources/text/other/ja/text_Forms_ja.txt @@ -1120,4 +1120,7 @@ リミテッド ドライブ フロート -グライド \ No newline at end of file +グライド +コンバット +ブレイズ +ウォーター \ No newline at end of file diff --git a/PKHeX.Core/Resources/text/other/ja/text_Species_ja.txt b/PKHeX.Core/Resources/text/other/ja/text_Species_ja.txt index 59bfd3a95..6a4fbf1bc 100644 --- a/PKHeX.Core/Resources/text/other/ja/text_Species_ja.txt +++ b/PKHeX.Core/Resources/text/other/ja/text_Species_ja.txt @@ -915,97 +915,97 @@ ウェーニバル グルトン パフュートン -ノココッチ タマンチュラ ワナイダー マメバッタ エクスレッグ -シガロコ -ベラカス -ボチ -ハカドッグ -ヒラヒナ -クエスパトラ -リキキリン -ウミディグダ -ウミトリオ -ヘイラッシャ -ミガルーサ -ナミイルカ -イルカマン -ミニーブ -オリーニョ -オリーヴァ -カプサイジ -スコヴィラン -ズピカ -ハラバリー -ブロロン -ブロロローム -ミミズズ -ワッカネズミ -イッカネズミ -アルクジラ -ハルクジラ -セビエ -セゴール -セグレイブ -シャリタツ -モトトカゲ パモ パモット パーモット -カイデン -タイカイデン -オトシドリ +ワッカネズミ +イッカネズミ +パピモッチ +バウッツェル +ミニーブ +オリーニョ +オリーヴァ イキリンコ -カラミンゴ -ガケガニ コジオ ジオヅム キョジオーン -キラーメ -キラフロル -シルシュルー -タギングル -パピモッチ -バウッツェル -オラチフ -マフィティフ -アノクサ -アノホラグサ -コレクレー -サーフゴー -イダイナキバ -アラブルタケ -AKETUBAN -スナノケガワ -サケブシッポ -ハバタクカミ -チヲハウハネ -トドロクツキ -テツノワダチ -BKETUBAN -テツノドクガ -テツノカイナ -テツノコウベ -テツノイバラ -テツノツツミ -テツノブジン -ディンルー -パオジアン -チオンジェン -イーユイ -コライドン -ミライドン -カヌチャン -ナカヌチャン -デカヌチャン カルボウ グレンアルマ ソウブレイズ +ズピカ +ハラバリー +カイデン +タイカイデン +オラチフ +マフィティフ +シルシュルー +タギングル +アノクサ +アノホラグサ ノノクラゲ リククラゲ -ドドゲザン +ガケガニ +カプサイジ +スコヴィラン +シガロコ +ベラカス +ヒラヒナ +クエスパトラ +カヌチャン +ナカヌチャン +デカヌチャン +ウミディグダ +ウミトリオ +オトシドリ +ナミイルカ +イルカマン +ブロロン +ブロロローム +モトトカゲ +ミミズズ +キラーメ +キラフロル +ボチ +ハカドッグ +カラミンゴ +アルクジラ +ハルクジラ +ミガルーサ +ヘイラッシャ +シャリタツ +コノヨザル ドオー -コノヨザル \ No newline at end of file +リキキリン +ノココッチ +ドドゲザン +イダイナキバ +サケブシッポ +アラブルタケ +ハバタクカミ +チヲハウハネ +スナノケガワ +テツノワダチ +テツノツツミ +テツノカイナ +テツノコウベ +テツノドクガ +テツノイバラ +セビエ +セゴール +セグレイブ +コレクレー +サーフゴー +チオンジェン +パオジアン +ディンルー +イーユイ +トドロクツキ +テツノブジン +コライドン +ミライドン +AKETUBAN +BKETUBAN \ No newline at end of file diff --git a/PKHeX.Core/Resources/text/other/ko/text_Forms_ko.txt b/PKHeX.Core/Resources/text/other/ko/text_Forms_ko.txt index ba09b057e..da53a3c6e 100644 --- a/PKHeX.Core/Resources/text/other/ko/text_Forms_ko.txt +++ b/PKHeX.Core/Resources/text/other/ko/text_Forms_ko.txt @@ -1120,4 +1120,7 @@ 리미티드 드라이브 플로트 -글라이드 \ No newline at end of file +글라이드 +컴뱃 +블레이즈 +워터 \ No newline at end of file diff --git a/PKHeX.Core/Resources/text/other/ko/text_Species_ko.txt b/PKHeX.Core/Resources/text/other/ko/text_Species_ko.txt index 97afc9c02..ad53e8ab2 100644 --- a/PKHeX.Core/Resources/text/other/ko/text_Species_ko.txt +++ b/PKHeX.Core/Resources/text/other/ko/text_Species_ko.txt @@ -915,97 +915,97 @@ 웨이니발 맛보돈 퍼퓨돈 -노고고치 타랜툴라 트래피더 콩알뚜기 엑스레그 -구르데 -베라카스 -망망이 -묘두기 -하느라기 -클레스퍼트라 -키키링 -바다그다 -바닥트리오 -어써러셔 -가비루사 -맨돌핀 -돌핀맨 -미니브 -올리뇨 -올리르바 -캡싸이 -스코빌런 -빈나두 -찌리배리 -부르롱 -부르르룸 -꿈트렁 -두리쥐 -파밀리쥐 -터벅고래 -우락고래 -드니차 -드니꽁 -드닐레이브 -싸리용 -모토마 빠모 빠모트 빠르모트 -찌리비 -찌리비크 -떨구새 +두리쥐 +파밀리쥐 +쫀도기 +바우첼 +미니브 +올리뇨 +올리르바 시비꼬 -꼬이밍고 -절벼게 베베솔트 스태솔트 콜로솔트 -초롱순 -킬라플로르 -땃쭈르 -태깅구르 -쫀도기 -바우첼 -오라티프 -마피티프 -그푸리 -공푸리 -모으령 -타부자고 -위대한엄니 -사나운버섯 -AKETUBAN -모래털가죽 -우렁찬꼬리 -날개치는머리 -땅을기는날개 -고동치는달 -무쇠바퀴 -BKETUBAN -무쇠독나방 -무쇠손 -무쇠머리 -무쇠가시 -무쇠보따리 -무쇠무인 -딩루 -파오젠 -총지엔 -위유이 -코라이돈 -미라이돈 -어리짱 -벼리짱 -두드리짱 카르본 카디나르마 파라블레이즈 +빈나두 +찌리배리 +찌리비 +찌리비크 +오라티프 +마피티프 +땃쭈르 +태깅구르 +그푸리 +공푸리 들눈해 육파리 -대도각참 +절벼게 +캡싸이 +스코빌런 +구르데 +베라카스 +하느라기 +클레스퍼트라 +어리짱 +벼리짱 +두드리짱 +바다그다 +바닥트리오 +떨구새 +맨돌핀 +돌핀맨 +부르롱 +부르르룸 +모토마 +꿈트렁 +초롱순 +킬라플로르 +망망이 +묘두기 +꼬이밍고 +터벅고래 +우락고래 +가비루사 +어써러셔 +싸리용 +저승갓숭 토오 -저승갓숭 \ No newline at end of file +키키링 +노고고치 +대도각참 +위대한엄니 +우렁찬꼬리 +사나운버섯 +날개치는머리 +땅을기는날개 +모래털가죽 +무쇠바퀴 +무쇠보따리 +무쇠손 +무쇠머리 +무쇠독나방 +무쇠가시 +드니차 +드니꽁 +드닐레이브 +모으령 +타부자고 +총지엔 +파오젠 +딩루 +위유이 +고동치는달 +무쇠무인 +코라이돈 +미라이돈 +AKETUBAN +BKETUBAN \ No newline at end of file diff --git a/PKHeX.Core/Resources/text/other/zh/text_Forms_zh.txt b/PKHeX.Core/Resources/text/other/zh/text_Forms_zh.txt index a17077c69..48a0fa6d9 100644 --- a/PKHeX.Core/Resources/text/other/zh/text_Forms_zh.txt +++ b/PKHeX.Core/Resources/text/other/zh/text_Forms_zh.txt @@ -1121,3 +1121,6 @@ 行驶模式 浮水模式 滑翔模式 +鬥戰 +火熾 +水瀾 \ No newline at end of file diff --git a/PKHeX.Core/Resources/text/other/zh/text_Forms_zh2.txt b/PKHeX.Core/Resources/text/other/zh/text_Forms_zh2.txt index 8114788ea..cd9340196 100644 --- a/PKHeX.Core/Resources/text/other/zh/text_Forms_zh2.txt +++ b/PKHeX.Core/Resources/text/other/zh/text_Forms_zh2.txt @@ -1120,4 +1120,7 @@ Mega蒂安希 受限模式 行駛模式 浮水模式 -滑翔模式 \ No newline at end of file +滑翔模式 +鬥戰 +火熾 +水瀾 \ No newline at end of file diff --git a/PKHeX.Core/Resources/text/other/zh/text_Species_zh.txt b/PKHeX.Core/Resources/text/other/zh/text_Species_zh.txt index 35e925ad2..e827c061c 100644 --- a/PKHeX.Core/Resources/text/other/zh/text_Species_zh.txt +++ b/PKHeX.Core/Resources/text/other/zh/text_Species_zh.txt @@ -915,97 +915,97 @@ 狂欢浪舞鸭 爱吃豚 飘香豚 -土龙节节 团珠蛛 操陷蛛 豆蟋蟀 烈腿蝗 -虫滚泥 -虫甲圣 -墓仔狗 -墓扬犬 -飘飘雏 -超能艳鸵 -奇麒麟 -海地鼠 -三海地鼠 -吃吼霸 -轻身鳕 -波普海豚 -海豚侠 -迷你芙 -奥利纽 -奥利瓦 -热辣娃 -狠辣椒 -光蚪仔 -电肚蛙 -噗隆隆 -普隆隆姆 -拖拖蚓 -一对鼠 -一家鼠 -走鲸 -浩大鲸 -凉脊龙 -冻脊龙 -戟脊龙 -米立龙 -摩托蜥 布拨 布土拨 巴布土拨 -电海燕 -大电海燕 -下石鸟 +一对鼠 +一家鼠 +狗仔包 +麻花犬 +迷你芙 +奥利纽 +奥利瓦 怒鹦哥 -缠红鹤 -毛崖蟹 盐石宝 盐石垒 盐石巨灵 -晶光芽 -晶光花 -滋汁鼹 -涂标客 -狗仔包 -麻花犬 -偶叫獒 -獒教父 -纳噬草 -怖纳噬草 -索财灵 -赛富豪 -雄伟牙 -猛恶菇 -AKETUBAN -沙铁皮 -吼叫尾 -振翼发 -爬地翅 -轰鸣月 -铁辙迹 -BKETUBAN -铁毒蛾 -铁臂膀 -铁脖颈 -铁荆棘 -铁包袱 -铁武者 -古鼎鹿 -古剑豹 -古简蜗 -古玉鱼 -故勒顿 -密勒顿 -小锻匠 -巧锻匠 -巨锻匠 炭小侍 红莲铠骑 苍炎刃鬼 +光蚪仔 +电肚蛙 +电海燕 +大电海燕 +偶叫獒 +獒教父 +滋汁鼹 +涂标客 +纳噬草 +怖纳噬草 原野水母 陆地水母 -仆刀将军 +毛崖蟹 +热辣娃 +狠辣椒 +虫滚泥 +虫甲圣 +飘飘雏 +超能艳鸵 +小锻匠 +巧锻匠 +巨锻匠 +海地鼠 +三海地鼠 +下石鸟 +波普海豚 +海豚侠 +噗隆隆 +普隆隆姆 +摩托蜥 +拖拖蚓 +晶光芽 +晶光花 +墓仔狗 +墓扬犬 +缠红鹤 +走鲸 +浩大鲸 +轻身鳕 +吃吼霸 +米立龙 +弃世猴 土王 -弃世猴 \ No newline at end of file +奇麒麟 +土龙节节 +仆刀将军 +雄伟牙 +吼叫尾 +猛恶菇 +振翼发 +爬地翅 +沙铁皮 +铁辙迹 +铁包袱 +铁臂膀 +铁脖颈 +铁毒蛾 +铁荆棘 +凉脊龙 +冻脊龙 +戟脊龙 +索财灵 +赛富豪 +古简蜗 +古剑豹 +古鼎鹿 +古玉鱼 +轰鸣月 +铁武者 +故勒顿 +密勒顿 +AKETUBAN +BKETUBAN \ No newline at end of file diff --git a/PKHeX.Core/Resources/text/other/zh/text_Species_zh2.txt b/PKHeX.Core/Resources/text/other/zh/text_Species_zh2.txt index 34268ca9e..9569cd04b 100644 --- a/PKHeX.Core/Resources/text/other/zh/text_Species_zh2.txt +++ b/PKHeX.Core/Resources/text/other/zh/text_Species_zh2.txt @@ -915,97 +915,97 @@ 狂歡浪舞鴨 愛吃豚 飄香豚 -土龍節節 團珠蛛 操陷蛛 豆蟋蟀 烈腿蝗 -蟲滾泥 -蟲甲聖 -墓仔狗 -墓揚犬 -飄飄雛 -超能豔鴕 -奇麒麟 -海地鼠 -三海地鼠 -吃吼霸 -輕身鱈 -波普海豚 -海豚俠 -迷你芙 -奧利紐 -奧利瓦 -熱辣娃 -狠辣椒 -光蚪仔 -電肚蛙 -噗隆隆 -普隆隆姆 -拖拖蚓 -一對鼠 -一家鼠 -走鯨 -浩大鯨 -涼脊龍 -凍脊龍 -戟脊龍 -米立龍 -摩托蜥 布撥 布土撥 巴布土撥 -電海燕 -大電海燕 -下石鳥 +一對鼠 +一家鼠 +狗仔包 +麻花犬 +迷你芙 +奧利紐 +奧利瓦 怒鸚哥 -纏紅鶴 -毛崖蟹 鹽石寶 鹽石壘 鹽石巨靈 -晶光芽 -晶光花 -滋汁鼴 -塗標客 -狗仔包 -麻花犬 -偶叫獒 -獒教父 -納噬草 -怖納噬草 -索財靈 -賽富豪 -雄偉牙 -猛惡菇 -AKETUBAN -沙鐵皮 -吼叫尾 -振翼髮 -爬地翅 -轟鳴月 -鐵轍跡 -BKETUBAN -鐵毒蛾 -鐵臂膀 -鐵脖頸 -鐵荊棘 -鐵包袱 -鐵武者 -古鼎鹿 -古劍豹 -古簡蝸 -古玉魚 -故勒頓 -密勒頓 -小鍛匠 -巧鍛匠 -巨鍛匠 炭小侍 紅蓮鎧騎 蒼炎刃鬼 +光蚪仔 +電肚蛙 +電海燕 +大電海燕 +偶叫獒 +獒教父 +滋汁鼴 +塗標客 +納噬草 +怖納噬草 原野水母 陸地水母 -仆斬將軍 +毛崖蟹 +熱辣娃 +狠辣椒 +蟲滾泥 +蟲甲聖 +飄飄雛 +超能豔鴕 +小鍛匠 +巧鍛匠 +巨鍛匠 +海地鼠 +三海地鼠 +下石鳥 +波普海豚 +海豚俠 +噗隆隆 +普隆隆姆 +摩托蜥 +拖拖蚓 +晶光芽 +晶光花 +墓仔狗 +墓揚犬 +纏紅鶴 +走鯨 +浩大鯨 +輕身鱈 +吃吼霸 +米立龍 +棄世猴 土王 -棄世猴 \ No newline at end of file +奇麒麟 +土龍節節 +仆斬將軍 +雄偉牙 +吼叫尾 +猛惡菇 +振翼髮 +爬地翅 +沙鐵皮 +鐵轍跡 +鐵包袱 +鐵臂膀 +鐵脖頸 +鐵毒蛾 +鐵荊棘 +涼脊龍 +凍脊龍 +戟脊龍 +索財靈 +賽富豪 +古簡蝸 +古劍豹 +古鼎鹿 +古玉魚 +轟鳴月 +鐵武者 +故勒頓 +密勒頓 +AKETUBAN +BKETUBAN \ No newline at end of file diff --git a/PKHeX.Core/Ribbons/IRibbonSetCommon6.cs b/PKHeX.Core/Ribbons/IRibbonSetCommon6.cs index cba498a8b..f3f483bb7 100644 --- a/PKHeX.Core/Ribbons/IRibbonSetCommon6.cs +++ b/PKHeX.Core/Ribbons/IRibbonSetCommon6.cs @@ -23,7 +23,7 @@ internal static partial class RibbonExtensions /// /// Checks if the has all five contest stat ribbons true. /// - public static bool HasAllContestRibbons(this IRibbonSetCommon6 set) => set.RibbonMasterCoolness && set.RibbonMasterBeauty && set.RibbonMasterCuteness && set.RibbonMasterCleverness && set.RibbonMasterToughness; + public static bool HasAllContestRibbons(this IRibbonSetCommon6 set) => set is { RibbonMasterCoolness: true, RibbonMasterBeauty: true, RibbonMasterCuteness: true, RibbonMasterCleverness: true, RibbonMasterToughness: true }; internal static void CopyRibbonSetCommon6(this IRibbonSetCommon6 set, IRibbonSetCommon6 dest) { diff --git a/PKHeX.Core/Ribbons/IRibbonSetMark8.cs b/PKHeX.Core/Ribbons/IRibbonSetMark8.cs index 8a20f1f8e..d48fc3838 100644 --- a/PKHeX.Core/Ribbons/IRibbonSetMark8.cs +++ b/PKHeX.Core/Ribbons/IRibbonSetMark8.cs @@ -1,4 +1,4 @@ -namespace PKHeX.Core; +namespace PKHeX.Core; /// Marks introduced in Generation 8 public interface IRibbonSetMark8 @@ -49,7 +49,18 @@ public interface IRibbonSetMark8 bool RibbonMarkVigor { get; set; } bool RibbonMarkSlump { get; set; } - bool HasMark(); + bool HasMarkEncounter8 { get; } +} + +public interface IRibbonSetRibbons +{ + int RibbonCount { get; } +} + +public interface IRibbonSetMarks +{ + int MarkCount { get; } + int RibbonMarkCount { get; } } internal static partial class RibbonExtensions @@ -57,112 +68,9 @@ internal static partial class RibbonExtensions public static bool HasWeatherMark(this IRibbonSetMark8 m) { return m.RibbonMarkCloudy || m.RibbonMarkRainy || m.RibbonMarkStormy || m.RibbonMarkSnowy - || m.RibbonMarkBlizzard || m.RibbonMarkDry || m.RibbonMarkSandstorm || m.RibbonMarkMisty; + || m.RibbonMarkBlizzard || m.RibbonMarkDry || m.RibbonMarkSandstorm || m.RibbonMarkMisty; } - private static readonly string[] RibbonSetNamesMark8 = - { - nameof(IRibbonSetMark8.RibbonMarkLunchtime), - nameof(IRibbonSetMark8.RibbonMarkSleepyTime), - nameof(IRibbonSetMark8.RibbonMarkDusk), - nameof(IRibbonSetMark8.RibbonMarkDawn), - nameof(IRibbonSetMark8.RibbonMarkCloudy), - nameof(IRibbonSetMark8.RibbonMarkRainy), - nameof(IRibbonSetMark8.RibbonMarkStormy), - nameof(IRibbonSetMark8.RibbonMarkSnowy), - nameof(IRibbonSetMark8.RibbonMarkBlizzard), - nameof(IRibbonSetMark8.RibbonMarkDry), - nameof(IRibbonSetMark8.RibbonMarkSandstorm), - nameof(IRibbonSetMark8.RibbonMarkMisty), - nameof(IRibbonSetMark8.RibbonMarkDestiny), - nameof(IRibbonSetMark8.RibbonMarkFishing), - nameof(IRibbonSetMark8.RibbonMarkCurry), - nameof(IRibbonSetMark8.RibbonMarkUncommon), - nameof(IRibbonSetMark8.RibbonMarkRare), - nameof(IRibbonSetMark8.RibbonMarkRowdy), - nameof(IRibbonSetMark8.RibbonMarkAbsentMinded), - nameof(IRibbonSetMark8.RibbonMarkJittery), - nameof(IRibbonSetMark8.RibbonMarkExcited), - nameof(IRibbonSetMark8.RibbonMarkCharismatic), - nameof(IRibbonSetMark8.RibbonMarkCalmness), - nameof(IRibbonSetMark8.RibbonMarkIntense), - nameof(IRibbonSetMark8.RibbonMarkZonedOut), - nameof(IRibbonSetMark8.RibbonMarkJoyful), - nameof(IRibbonSetMark8.RibbonMarkAngry), - nameof(IRibbonSetMark8.RibbonMarkSmiley), - nameof(IRibbonSetMark8.RibbonMarkTeary), - nameof(IRibbonSetMark8.RibbonMarkUpbeat), - nameof(IRibbonSetMark8.RibbonMarkPeeved), - nameof(IRibbonSetMark8.RibbonMarkIntellectual), - nameof(IRibbonSetMark8.RibbonMarkFerocious), - nameof(IRibbonSetMark8.RibbonMarkCrafty), - nameof(IRibbonSetMark8.RibbonMarkScowling), - nameof(IRibbonSetMark8.RibbonMarkKindly), - nameof(IRibbonSetMark8.RibbonMarkFlustered), - nameof(IRibbonSetMark8.RibbonMarkPumpedUp), - nameof(IRibbonSetMark8.RibbonMarkZeroEnergy), - nameof(IRibbonSetMark8.RibbonMarkPrideful), - nameof(IRibbonSetMark8.RibbonMarkUnsure), - nameof(IRibbonSetMark8.RibbonMarkHumble), - nameof(IRibbonSetMark8.RibbonMarkThorny), - nameof(IRibbonSetMark8.RibbonMarkVigor), - nameof(IRibbonSetMark8.RibbonMarkSlump), - }; - - internal static bool[] RibbonBits(this IRibbonSetMark8 set) - { - return new[] - { - set.RibbonMarkLunchtime, - set.RibbonMarkSleepyTime, - set.RibbonMarkDusk, - set.RibbonMarkDawn, - set.RibbonMarkCloudy, - set.RibbonMarkRainy, - set.RibbonMarkStormy, - set.RibbonMarkSnowy, - set.RibbonMarkBlizzard, - set.RibbonMarkDry, - set.RibbonMarkSandstorm, - set.RibbonMarkMisty, - set.RibbonMarkDestiny, - set.RibbonMarkFishing, - set.RibbonMarkCurry, - set.RibbonMarkUncommon, - set.RibbonMarkRare, - set.RibbonMarkRowdy, - set.RibbonMarkAbsentMinded, - set.RibbonMarkJittery, - set.RibbonMarkExcited, - set.RibbonMarkCharismatic, - set.RibbonMarkCalmness, - set.RibbonMarkIntense, - set.RibbonMarkZonedOut, - set.RibbonMarkJoyful, - set.RibbonMarkAngry, - set.RibbonMarkSmiley, - set.RibbonMarkTeary, - set.RibbonMarkUpbeat, - set.RibbonMarkPeeved, - set.RibbonMarkIntellectual, - set.RibbonMarkFerocious, - set.RibbonMarkCrafty, - set.RibbonMarkScowling, - set.RibbonMarkKindly, - set.RibbonMarkFlustered, - set.RibbonMarkPumpedUp, - set.RibbonMarkZeroEnergy, - set.RibbonMarkPrideful, - set.RibbonMarkUnsure, - set.RibbonMarkHumble, - set.RibbonMarkThorny, - set.RibbonMarkVigor, - set.RibbonMarkSlump, - }; - } - - internal static string[] RibbonNames(this IRibbonSetMark8 _) => RibbonSetNamesMark8; - internal static void CopyRibbonSetMark8(this IRibbonSetMark8 set, IRibbonSetMark8 dest) { dest.RibbonMarkLunchtime = set.RibbonMarkLunchtime; diff --git a/PKHeX.Core/Ribbons/IRibbonSetMark9.cs b/PKHeX.Core/Ribbons/IRibbonSetMark9.cs index 4f4714d94..d6a9b3c91 100644 --- a/PKHeX.Core/Ribbons/IRibbonSetMark9.cs +++ b/PKHeX.Core/Ribbons/IRibbonSetMark9.cs @@ -12,40 +12,11 @@ public interface IRibbonSetMark9 bool RibbonMarkMightiest { get; set; } bool RibbonMarkTitan { get; set; } - bool HasMark(); + bool HasMarkEncounter9 { get; } } internal static partial class RibbonExtensions { - private static readonly string[] RibbonSetNamesMark9 = - { - nameof(IRibbonSetMark9.RibbonMarkJumbo), - nameof(IRibbonSetMark9.RibbonMarkMini), - nameof(IRibbonSetMark9.RibbonMarkItemfinder), - nameof(IRibbonSetMark9.RibbonMarkPartner), - nameof(IRibbonSetMark9.RibbonMarkGourmand), - nameof(IRibbonSetMark9.RibbonMarkAlpha), - nameof(IRibbonSetMark9.RibbonMarkMightiest), - nameof(IRibbonSetMark9.RibbonMarkTitan), - }; - - internal static bool[] RibbonBits(this IRibbonSetMark9 set) - { - return new[] - { - set.RibbonMarkJumbo, - set.RibbonMarkMini, - set.RibbonMarkItemfinder, - set.RibbonMarkPartner, - set.RibbonMarkGourmand, - set.RibbonMarkAlpha, - set.RibbonMarkMightiest, - set.RibbonMarkTitan, - }; - } - - internal static string[] RibbonNames(this IRibbonSetMark9 _) => RibbonSetNamesMark9; - internal static void CopyRibbonSetMark9(this IRibbonSetMark9 set, IRibbonSetMark9 dest) { dest.RibbonMarkJumbo = set.RibbonMarkJumbo; diff --git a/PKHeX.Core/Ribbons/RibbonIndex.cs b/PKHeX.Core/Ribbons/RibbonIndex.cs index 9266f67b5..60532c15f 100644 --- a/PKHeX.Core/Ribbons/RibbonIndex.cs +++ b/PKHeX.Core/Ribbons/RibbonIndex.cs @@ -129,7 +129,9 @@ public static class RibbonIndexExtensions { public static bool GetRibbonIndex(this IRibbonIndex x, RibbonIndex r) => x.GetRibbon((int)r); public static void SetRibbonIndex(this IRibbonIndex x, RibbonIndex r, bool value = true) => x.SetRibbon((int)r, value); - public static bool IsEncounterMark(this RibbonIndex r) => r is >= MarkLunchtime and <= MarkSlump; + public static bool IsEncounterMark8(this RibbonIndex r) => r is >= MarkLunchtime and <= MarkSlump; + public static bool IsEncounterMark9(this RibbonIndex r) => r is >= MarkAlpha and <= MarkTitan; + public static bool IsRibbon(this RibbonIndex r) => r < MAX_COUNT && !r.IsEncounterMark8() && r.IsEncounterMark9(); /// /// Checks if the ribbon index is one of the specific wild encounter-only marks. These marks are granted when the encounter spawns in the wild. @@ -174,7 +176,7 @@ public static class RibbonIndexExtensions private static RibbonIndexGroup GetGroup(this RibbonIndex r) { - if (r.IsEncounterMark()) + if (r.IsEncounterMark8()) return RibbonIndexGroup.EncounterMark; return r switch { @@ -374,7 +376,7 @@ public static class RibbonIndexExtensions } return; default: - throw new ArgumentOutOfRangeException(); + throw new ArgumentOutOfRangeException(nameof(r), r, null); } } diff --git a/PKHeX.Core/Saves/Access/ISaveBlockAccessor.cs b/PKHeX.Core/Saves/Access/ISaveBlockAccessor.cs index 7b8d30217..9572c4c44 100644 --- a/PKHeX.Core/Saves/Access/ISaveBlockAccessor.cs +++ b/PKHeX.Core/Saves/Access/ISaveBlockAccessor.cs @@ -1,10 +1,12 @@ -using System.Collections.Generic; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; namespace PKHeX.Core; /// /// Interface for Accessing named blocks within a save file. /// +[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] public interface ISaveBlockAccessor { /// diff --git a/PKHeX.Core/Saves/Access/SCBlockAccessor.cs b/PKHeX.Core/Saves/Access/SCBlockAccessor.cs index 51c4755f6..6b3d45f88 100644 --- a/PKHeX.Core/Saves/Access/SCBlockAccessor.cs +++ b/PKHeX.Core/Saves/Access/SCBlockAccessor.cs @@ -34,15 +34,12 @@ public abstract class SCBlockAccessor : ISaveBlockAccessor #endregion #region Ease of Use Overloads - /// + /// /// Block name (un-hashed) - public SCBlock GetBlock(string name) => GetBlock(Hash(name.AsSpan())); - - /// public SCBlock GetBlock(ReadOnlySpan name) => GetBlock(Hash(name)); private static uint Hash(ReadOnlySpan name) => (uint)FnvHash.HashFnv1a_64(name); - /// + /// public SCBlock GetBlock(ReadOnlySpan name) => GetBlock(Hash(name)); private static uint Hash(ReadOnlySpan name) => (uint)FnvHash.HashFnv1a_64(name); #endregion diff --git a/PKHeX.Core/Saves/Access/SaveBlockAccessor6AO.cs b/PKHeX.Core/Saves/Access/SaveBlockAccessor6AO.cs index 9cf936055..b3295ebb7 100644 --- a/PKHeX.Core/Saves/Access/SaveBlockAccessor6AO.cs +++ b/PKHeX.Core/Saves/Access/SaveBlockAccessor6AO.cs @@ -1,4 +1,4 @@ -using System.Collections.Generic; +using System.Collections.Generic; namespace PKHeX.Core; @@ -116,7 +116,7 @@ public sealed class SaveBlockAccessor6AO : ISaveBlockAccessor, ISave Maison = new MaisonBlock(sav, 0x1BA00); MysteryGift = new MysteryBlock6(sav, 0x1CC00); SUBE = new SubEventLog6AO(sav, 0x1E800); - Records = new RecordBlock6(sav, 0x1F400); + Records = new RecordBlock6AO(sav, 0x1F400); SuperTrain = new SuperTrainBlock(sav, 0x20200); Link = new LinkBlock6(sav, 0x20E00); SecretBase = new SecretBase6Block(sav, 0x23A00); diff --git a/PKHeX.Core/Saves/Access/SaveBlockAccessor6AODemo.cs b/PKHeX.Core/Saves/Access/SaveBlockAccessor6AODemo.cs index 053beb5c9..8facd22f1 100644 --- a/PKHeX.Core/Saves/Access/SaveBlockAccessor6AODemo.cs +++ b/PKHeX.Core/Saves/Access/SaveBlockAccessor6AODemo.cs @@ -1,4 +1,4 @@ -using System.Collections.Generic; +using System.Collections.Generic; namespace PKHeX.Core; @@ -48,7 +48,7 @@ public sealed class SaveBlockAccessor6AODemo : ISaveBlockAccessor, I Situation = new Situation6(sav, 0x01000); Played = new PlayTime6(sav, 0x01400); Status = new MyStatus6(sav, 0x03C00); - Records = new RecordBlock6(sav, 0x05400); + Records = new RecordBlock6AO(sav, 0x05400); Misc = new Misc6AO(sav, 0x03A00); } } diff --git a/PKHeX.Core/Saves/Access/SaveBlockAccessor6XY.cs b/PKHeX.Core/Saves/Access/SaveBlockAccessor6XY.cs index 4697dc47f..8df090532 100644 --- a/PKHeX.Core/Saves/Access/SaveBlockAccessor6XY.cs +++ b/PKHeX.Core/Saves/Access/SaveBlockAccessor6XY.cs @@ -1,4 +1,4 @@ -using System.Collections.Generic; +using System.Collections.Generic; namespace PKHeX.Core; @@ -100,7 +100,7 @@ public sealed class SaveBlockAccessor6XY : ISaveBlockAccessor, ISave Encount = new Encount6(sav, 0x17E00); MysteryGift = new MysteryBlock6(sav, 0x1BC00); SUBE = new SubEventLog6XY(sav, 0x1D800); - Records = new RecordBlock6(sav, 0x1E400); + Records = new RecordBlock6XY(sav, 0x1E400); SuperTrain = new SuperTrainBlock(sav, 0x1F200); Link = new LinkBlock6(sav, 0x1FE00); Maison = new MaisonBlock(sav, 0x1B000); diff --git a/PKHeX.Core/Saves/Access/SaveBlockAccessor7SM.cs b/PKHeX.Core/Saves/Access/SaveBlockAccessor7SM.cs index 4b60fd510..3edf76a42 100644 --- a/PKHeX.Core/Saves/Access/SaveBlockAccessor7SM.cs +++ b/PKHeX.Core/Saves/Access/SaveBlockAccessor7SM.cs @@ -1,4 +1,4 @@ -using System.Collections.Generic; +using System.Collections.Generic; namespace PKHeX.Core; @@ -72,7 +72,7 @@ public sealed class SaveBlockAccessor7SM : ISaveBlockAccessor, ISave Festa = new JoinFesta7(sav, bi[21].Offset); PokeFinder = new PokeFinder7(sav, bi[26].Offset); MysteryGift = new MysteryBlock7(sav, bi[27].Offset); - Records = new RecordBlock6(sav, bi[28].Offset); + Records = new RecordBlock7SM(sav, bi[28].Offset); BattleTree = new BattleTree7(sav, bi[32].Offset); Daycare = new Daycare7(sav, bi[33].Offset); } diff --git a/PKHeX.Core/Saves/Access/SaveBlockAccessor7USUM.cs b/PKHeX.Core/Saves/Access/SaveBlockAccessor7USUM.cs index 418f76e26..9ad3e92fb 100644 --- a/PKHeX.Core/Saves/Access/SaveBlockAccessor7USUM.cs +++ b/PKHeX.Core/Saves/Access/SaveBlockAccessor7USUM.cs @@ -1,4 +1,4 @@ -using System.Collections.Generic; +using System.Collections.Generic; namespace PKHeX.Core; @@ -74,7 +74,7 @@ public sealed class SaveBlockAccessor7USUM : ISaveBlockAccessor, ISa Festa = new JoinFesta7(sav, bi[21].Offset); PokeFinder = new PokeFinder7(sav, bi[26].Offset); MysteryGift = new MysteryBlock7(sav, bi[27].Offset); - Records = new RecordBlock6(sav, bi[28].Offset); + Records = new RecordBlock7USUM(sav, bi[28].Offset); BattleTree = new BattleTree7(sav, bi[32].Offset); Daycare = new Daycare7(sav, bi[33].Offset); BattleAgency = new BattleAgency7(sav, bi[37].Offset); diff --git a/PKHeX.Core/Saves/Access/SaveBlockAccessor8LA.cs b/PKHeX.Core/Saves/Access/SaveBlockAccessor8LA.cs index c7837ca0d..ce67aa7ee 100644 --- a/PKHeX.Core/Saves/Access/SaveBlockAccessor8LA.cs +++ b/PKHeX.Core/Saves/Access/SaveBlockAccessor8LA.cs @@ -3,7 +3,7 @@ using System.Collections.Generic; namespace PKHeX.Core; // ReSharper disable UnusedMember.Local -#pragma warning disable IDE0051 // Remove unused private members +#pragma warning disable IDE0051, RCS1213 // Remove unused private members public sealed class SaveBlockAccessor8LA : SCBlockAccessor, ISaveBlock8LA { public override IReadOnlyList BlockInfo { get; } diff --git a/PKHeX.Core/Saves/Access/SaveBlockAccessor8SWSH.cs b/PKHeX.Core/Saves/Access/SaveBlockAccessor8SWSH.cs index 34354ec5a..40d832cdf 100644 --- a/PKHeX.Core/Saves/Access/SaveBlockAccessor8SWSH.cs +++ b/PKHeX.Core/Saves/Access/SaveBlockAccessor8SWSH.cs @@ -1,6 +1,6 @@ using System.Collections.Generic; // ReSharper disable UnusedMember.Local -#pragma warning disable IDE0051 // Remove unused private members +#pragma warning disable IDE0051, RCS1213 // Remove unused private members namespace PKHeX.Core; @@ -44,7 +44,7 @@ public sealed class SaveBlockAccessor8SWSH : SCBlockAccessor, ISaveBlock8Main Played = new PlayTime8(sav, GetBlock(KPlayTime)); Fused = new Fused8(sav, GetBlock(KFused)); Daycare = new Daycare8(sav, GetBlock(KDaycare)); - Records = new Record8(sav, GetBlock(KRecord), Core.Records.MaxType_SWSH); + Records = new Record8(sav, GetBlock(KRecord)); Fashion = new FashionUnlock8(sav, GetBlock(KFashionUnlock)); Raid = new RaidSpawnList8(sav, GetBlock(KRaidSpawnList), RaidSpawnList8.RaidCountLegal_O0); RaidArmor = new RaidSpawnList8(sav, GetBlockSafe(KRaidSpawnListR1), RaidSpawnList8.RaidCountLegal_R1); diff --git a/PKHeX.Core/Saves/Blocks/BlockInfo.cs b/PKHeX.Core/Saves/Blocks/BlockInfo.cs index f8406c675..41c2e2dd8 100644 --- a/PKHeX.Core/Saves/Blocks/BlockInfo.cs +++ b/PKHeX.Core/Saves/Blocks/BlockInfo.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; namespace PKHeX.Core; @@ -64,17 +64,18 @@ public abstract class BlockInfo list = new List(); for (int i = 0; i < blocks.Count; i++) { - if (blocks[i].Length + blocks[i].Offset > data.Length) + var block = blocks[i]; + if (block.Length + block.Offset > data.Length) { list.Add($"Block {i} Invalid Offset/Length."); return invalid; } - if (blocks[i].ChecksumValid(data)) + if (block.ChecksumValid(data)) continue; invalid++; - list.Add($"Invalid: {i:X2} @ Region {blocks[i].Offset:X5}"); + list.Add($"Invalid: {i:X2} @ Region {block.Offset:X5}"); } return invalid; } diff --git a/PKHeX.Core/Saves/Blocks/RecordBlock.cs b/PKHeX.Core/Saves/Blocks/RecordBlock.cs index 56a0d12fc..c50e03920 100644 --- a/PKHeX.Core/Saves/Blocks/RecordBlock.cs +++ b/PKHeX.Core/Saves/Blocks/RecordBlock.cs @@ -1,10 +1,10 @@ -using System.Collections.Generic; +using System; namespace PKHeX.Core; public abstract class RecordBlock : SaveBlock, IRecordStatStorage where T : SaveFile { - protected abstract IReadOnlyList RecordMax { get; } + protected abstract ReadOnlySpan RecordMax { get; } public abstract int GetRecord(int recordID); public abstract void SetRecord(int recordID, int value); diff --git a/PKHeX.Core/Saves/Encryption/MemeCrypto/MemeCrypto.cs b/PKHeX.Core/Saves/Encryption/MemeCrypto/MemeCrypto.cs index 6e1ed5778..60d728b8b 100644 --- a/PKHeX.Core/Saves/Encryption/MemeCrypto/MemeCrypto.cs +++ b/PKHeX.Core/Saves/Encryption/MemeCrypto/MemeCrypto.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Security.Cryptography; using static System.Buffers.Binary.BinaryPrimitives; @@ -20,7 +20,7 @@ public static class MemeCrypto public static bool VerifyMemePOKE(ReadOnlySpan input, out byte[] output) { - if (input.Length < 0x60) + if (input.Length < MemeKey.SignatureLength) throw new ArgumentException("Invalid POKE buffer!"); var memeLen = input.Length - 8; var memeIndex = MemeKeyIndex.PokedexAndSaveFile; @@ -40,10 +40,10 @@ public static class MemeCrypto foreach (var len in new[] { memeLen, memeLen - 2 }) // Account for Pokédex QR Edge case { - if (VerifyMemeData(input, out output, 0, len, memeIndex)) + if (VerifyMemeData(input[..len], out output, memeIndex)) return true; - if (VerifyMemeData(input, out output, 0, len, MemeKeyIndex.PokedexAndSaveFile)) + if (VerifyMemeData(input[..len], out output, MemeKeyIndex.PokedexAndSaveFile)) return true; } @@ -64,49 +64,38 @@ public static class MemeCrypto public static bool VerifyMemeData(ReadOnlySpan input, out byte[] output, MemeKeyIndex keyIndex) { - if (input.Length < 0x60) + if (input.Length < MemeKey.SignatureLength) { output = Array.Empty(); return false; } var key = new MemeKey(keyIndex); + Span sigBuffer = stackalloc byte[MemeKey.SignatureLength]; + var inputSig = input[^MemeKey.SignatureLength..]; + key.RsaPublic(inputSig, sigBuffer); + output = input.ToArray(); - - var sigBuffer = key.RsaPublic(input[^0x60..]); - using var sha1 = SHA1.Create(); - if (DecryptCompare(output, sigBuffer, key, sha1)) + if (DecryptCompare(output, sigBuffer, key)) return true; + sigBuffer[0x0] |= 0x80; - if (DecryptCompare(output, sigBuffer, key, sha1)) + + output = input.ToArray(); + if (DecryptCompare(output, sigBuffer, key)) return true; output = Array.Empty(); return false; } - private static bool DecryptCompare(byte[] output, ReadOnlySpan sigBuffer, MemeKey key, SHA1 sha1) + private static bool DecryptCompare(Span output, ReadOnlySpan sigBuffer, MemeKey key) { - sigBuffer.CopyTo(output.AsSpan(output.Length - 0x60)); - key.AesDecrypt(output).CopyTo(output); + sigBuffer.CopyTo(output[^MemeKey.SignatureLength..]); + key.AesDecrypt(output); // Check for 8-byte equality. - var hash = sha1.ComputeHash(output, 0, output.Length - 0x8); - var computed = ReadUInt64LittleEndian(hash.AsSpan()); - var existing = ReadUInt64LittleEndian(output.AsSpan(output.Length - 0x8)); - return computed == existing; - } - - public static bool VerifyMemeData(ReadOnlySpan input, out byte[] output, int offset, int length) - { - var data = input.Slice(offset, length).ToArray(); - if (VerifyMemeData(data, out output)) - { - var newOutput = input.ToArray(); - output.CopyTo(newOutput, offset); - output = newOutput; - return true; - } - output = Array.Empty(); - return false; + Span hash = stackalloc byte[SHA1.HashSizeInBytes]; + SHA1.HashData(output[..^8], hash); + return hash[..8].SequenceEqual(output[^8..]); } public static bool VerifyMemeData(ReadOnlySpan input, out byte[] output, int offset, int length, MemeKeyIndex keyIndex) @@ -125,62 +114,66 @@ public static class MemeCrypto public static byte[] SignMemeData(ReadOnlySpan input, MemeKeyIndex keyIndex = MemeKeyIndex.PokedexAndSaveFile) { - // Validate Input - if (input.Length < 0x60) - throw new ArgumentException("Cannot memesign a buffer less than 0x60 bytes in size!"); - var key = new MemeKey(keyIndex); - if (!key.CanResign) - throw new ArgumentException("Cannot sign with the specified memekey!"); - var output = input.ToArray(); - - // Copy in the SHA1 signature - using (var sha1 = SHA1.Create()) - { - var hash = sha1.ComputeHash(output, 0, output.Length - 8); - hash.AsSpan(0, 8).CopyTo(output.AsSpan(output.Length - 8, 8)); - } - - // Perform AES operations - output = key.AesEncrypt(output); - var sigBuffer = output.AsSpan(output.Length - 0x60, 0x60); - sigBuffer[0] &= 0x7F; - var signed = key.RsaPrivate(sigBuffer); - signed.CopyTo(sigBuffer); + SignMemeDataInPlace(output, keyIndex); return output; } + private static void SignMemeDataInPlace(Span data, MemeKeyIndex keyIndex = MemeKeyIndex.PokedexAndSaveFile) + { + // Validate Input + if (data.Length < MemeKey.SignatureLength) + throw new ArgumentException("Cannot sign a buffer less than 0x60 bytes in size!"); + var key = new MemeKey(keyIndex); + if (!key.CanResign) + throw new ArgumentException("Cannot sign with the specified key!"); + + // SHA1 the entire payload except for the last 8 bytes; store the first 8 bytes of hash at the end of the input. + var payload = data[..^8]; + var hash = data[^8..]; + Span tmp = stackalloc byte[SHA1.HashSizeInBytes]; + SHA1.HashData(payload, tmp); + + // Copy in the SHA1 signature + tmp[..hash.Length].CopyTo(hash); + + // Perform AES operations + key.AesEncrypt(data); + var sigBuffer = data[^MemeKey.SignatureLength..]; + sigBuffer[0] &= 0x7F; // chop off sign bit + key.RsaPrivate(sigBuffer, sigBuffer); + } + + public const int SaveFileSignatureOffset = 0x100; + public const int SaveFileSignatureLength = 0x80; + /// /// Resigns save data. /// - /// Save file data to resign + /// Save file data to resign /// The resigned save data. Invalid input returns null. - public static byte[] Resign7(ReadOnlySpan sav7) + public static void SignInPlace(Span span) { - if (sav7.Length is not (SaveUtil.SIZE_G7SM or SaveUtil.SIZE_G7USUM)) + if (span.Length is not (SaveUtil.SIZE_G7SM or SaveUtil.SIZE_G7USUM)) throw new ArgumentException("Should not be using this for unsupported saves."); - // Save Chunks are 0x200 bytes each; Memecrypto signature is 0x100 bytes into the 2nd to last chunk. - var isUSUM = sav7.Length == SaveUtil.SIZE_G7USUM; - var ChecksumTableOffset = sav7.Length - 0x200; - var MemeCryptoOffset = isUSUM ? 0x6C100 : 0x6BB00; + var isUSUM = span.Length == SaveUtil.SIZE_G7USUM; + var ChecksumTableOffset = span.Length - 0x200; var ChecksumSignatureLength = isUSUM ? 0x150 : 0x140; - const int MemeCryptoSignatureLength = 0x80; + var MemeCryptoOffset = (isUSUM ? 0x6C000 : 0x6BA00) + SaveFileSignatureOffset; - var result = sav7.ToArray(); + // data[0x80]. Region is initially zero when exporting (nothing set). + // Store a SHA256[0x20] hash of checksums at [..0x20]. + // Compute the signature over this 0x80 region, store at [0x20..] + var sigSpan = span.Slice(MemeCryptoOffset, SaveFileSignatureLength); + var chkBlockSpan = span.Slice(ChecksumTableOffset, ChecksumSignatureLength); - // Store current signature - var oldSig = sav7.Slice(MemeCryptoOffset, MemeCryptoSignatureLength).ToArray(); + SignInPlace(sigSpan, chkBlockSpan); + } - using var sha256 = SHA256.Create(); - var newSig = sha256.ComputeHash(result, ChecksumTableOffset, ChecksumSignatureLength); - Span sigSpan = stackalloc byte[MemeCryptoSignatureLength]; - newSig.CopyTo(sigSpan); - - if (VerifyMemeData(oldSig, out var memeSig, MemeKeyIndex.PokedexAndSaveFile)) - memeSig.AsSpan()[0x20..0x80].CopyTo(sigSpan[0x20..]); - - SignMemeData(sigSpan).CopyTo(result, MemeCryptoOffset); - return result; + public static void SignInPlace(Span sigSpan, ReadOnlySpan chkBlockSpan) + { + SHA256.HashData(chkBlockSpan, sigSpan); + SignMemeDataInPlace(sigSpan); } } diff --git a/PKHeX.Core/Saves/Encryption/MemeCrypto/MemeKey.cs b/PKHeX.Core/Saves/Encryption/MemeCrypto/MemeKey.cs index 3d9572b0d..8289d85c9 100644 --- a/PKHeX.Core/Saves/Encryption/MemeCrypto/MemeKey.cs +++ b/PKHeX.Core/Saves/Encryption/MemeCrypto/MemeKey.cs @@ -1,18 +1,17 @@ using System; using System.Diagnostics; -using System.IO; using System.Numerics; using System.Security.Cryptography; +using static PKHeX.Core.MemeKeyIndex; namespace PKHeX.Core; /// /// Key for crypto with binaries. /// -public sealed class MemeKey +public readonly ref struct MemeKey { - /// Distinguished Encoding Rules - private readonly byte[] DER; + private readonly ReadOnlySpan DER; /// Private Exponent, BigInteger private readonly BigInteger D; @@ -26,286 +25,233 @@ public sealed class MemeKey // Constructor public MemeKey(MemeKeyIndex key) { - DER = GetMemeData(key); - var _N = DER.AsSpan(0x18, 0x61).ToArray(); - var _E = DER.AsSpan(0x7B, 3).ToArray(); - _N.AsSpan().Reverse(); - _E.AsSpan().Reverse(); - N = new BigInteger(_N); - E = new BigInteger(_E); + DER = GetMemeDataVerify(key); + var all = DER; + N = new BigInteger(all.Slice(0x18, 0x61), isUnsigned: true, isBigEndian: true); + E = new BigInteger(all.Slice(0x7B, 0x03), isUnsigned: true, isBigEndian: true); - if (key == MemeKeyIndex.PokedexAndSaveFile) - { - var _D = D_3.AsSpan().ToArray(); - _D.AsSpan().Reverse(); - D = new BigInteger(_D); - } + if (key.CanSign()) + D = new BigInteger(GetMemeDataSign(key), isUnsigned: true, isBigEndian: true); else - { - D = INVALID; - } + D = default; } /// /// Indicates if this key can be used to resign messages. /// - public bool CanResign => D != INVALID; + public bool CanResign => D != default; + + public const int SignatureLength = 0x60; + private const int chunk = 0x10; + + /// + /// Performs Aes Decryption + /// + internal void AesDecrypt(Span data) + { + var payload = data[..^SignatureLength]; + var sig = data[^SignatureLength..]; + AesDecrypt(payload, sig); + } + + /// + /// Perform Aes Encryption + /// + internal void AesEncrypt(Span data) + { + var payload = data[..^SignatureLength]; + var sig = data[^SignatureLength..]; + AesEncrypt(payload, sig); + } + + private void AesDecrypt(ReadOnlySpan data, Span sig) + { + using var aes = GetAesImpl(data); + Span temp = stackalloc byte[chunk]; + Span nextXor = stackalloc byte[chunk]; + + for (var i = sig.Length - chunk; i >= 0; i -= chunk) + { + var slice = sig.Slice(i, chunk); + Xor(temp, slice); + aes.DecryptEcb(temp, temp, PaddingMode.None); + temp.CopyTo(slice); + } + + Xor(temp, sig[^chunk..]); + GetSubKey(temp, nextXor); + for (var i = 0; i < sig.Length; i += chunk) + Xor(sig.Slice(i, chunk), nextXor); + + nextXor.Clear(); + for (var i = 0; i < sig.Length; i += chunk) + { + var slice = sig.Slice(i, chunk); + slice.CopyTo(temp); + aes.DecryptEcb(slice, slice, PaddingMode.None); + Xor(slice, nextXor); + temp.CopyTo(nextXor); + } + } + + private void AesEncrypt(Span data, Span sig) + { + using var aes = GetAesImpl(data); + Span temp = stackalloc byte[chunk]; + Span nextXor = stackalloc byte[chunk]; + + for (var i = 0; i < sig.Length; i += chunk) + { + var slice = sig.Slice(i, chunk); + Xor(slice, temp); + aes.EncryptEcb(slice, slice, PaddingMode.None); + slice.CopyTo(temp); + } + + Xor(temp, sig[..chunk]); + GetSubKey(temp, nextXor); + for (var i = 0; i < sig.Length; i += chunk) + Xor(sig.Slice(i, chunk), nextXor); + + temp.Clear(); + for (var i = sig.Length - chunk; i >= 0; i -= chunk) + { + var slice = sig.Slice(i, chunk); + slice.CopyTo(nextXor); + aes.EncryptEcb(slice, slice, PaddingMode.None); + Xor(slice, temp); + nextXor.CopyTo(temp); + } + } + + private Aes GetAesImpl(ReadOnlySpan payload) + { + // The C# implementation of AES isn't fully allocation-free, so some allocation on key & implementation is needed. + var key = GetAesKey(payload); + + // Don't dispose in this method, let the consumer dispose. + var aes = Aes.Create(); + aes.Mode = CipherMode.ECB; + aes.Padding = PaddingMode.None; + aes.Key = key; + // no IV -- all zero. + return aes; + } /// /// Get the AES key for this MemeKey /// private byte[] GetAesKey(ReadOnlySpan data) { - if (data.Length < 0x60) - throw new ArgumentException("Memebuffers must be atleast 0x60 bytes long!"); - - var buffer = new byte[DER.Length + data.Length - 0x60]; - DER.CopyTo(buffer, 0); - data[..(buffer.Length - DER.Length)].CopyTo(buffer.AsSpan(DER.Length)); - - using var sha1 = SHA1.Create(); - var result = sha1.ComputeHash(buffer); - return result.AsSpan(0, 0x10).ToArray(); - } - - /// - /// Performs Aes Decryption - /// - internal byte[] AesDecrypt(ReadOnlySpan input) - { - var key = GetAesKey(input); - var data = input[^0x60..]; - var curblock = new byte[0x10]; - var outdata = new byte[data.Length]; - for (var i = data.Length - 0x10; i >= 0; i -= 0x10) // Reverse Phase 2 - { - var slice = data.Slice(i, 0x10); - Xor(curblock, slice, curblock); - curblock = AesEcbDecrypt(key, curblock); - curblock.CopyTo(outdata, i); - } - - // At this point we have Phase1(buf) ^ subkey. - // Subkey is (block first ^ block last) << 1 - // We don't have block first or block last, though? - // How can we derive subkey? - // Well, (a ^ a) = 0. so (block first ^ subkey) ^ (block last ^ subkey) - // = block first ^ block last ;) - var last = outdata.AsSpan(((data.Length / 0x10) - 1) * 0x10, 0x10); - var first = outdata.AsSpan(0, 0x10); - - Span subkey = stackalloc byte[0x10]; - Xor(last, first, curblock); - GetSubKey(curblock, subkey); - for (var i = 0; i < data.Length; i += 0x10) - { - var slice = outdata.AsSpan(i, 0x10); - Xor(slice, subkey, slice); - } - - // Now we have Phase1Encrypt(buf). - curblock.AsSpan().Clear(); // Clear to all zero - Span temp = stackalloc byte[0x10]; - for (var i = 0; i < data.Length; i += 0x10) // Phase 1: CBC Encryption. - { - var slice = outdata.AsSpan(i, 0x10); - slice.CopyTo(curblock); - var temp1 = AesEcbDecrypt(key, curblock); - Xor(temp1, temp, slice); - curblock.CopyTo(temp); - } - - var outbuf = input.ToArray(); - outdata.AsSpan()[..0x60].CopyTo(outbuf.AsSpan()[^0x60..]); - return outbuf; - } - - /// - /// Perform Aes Encryption - /// - internal byte[] AesEncrypt(ReadOnlySpan input) - { - var key = GetAesKey(input); - var data = input[^0x60..]; - var curblock = new byte[0x10]; - var outdata = new byte[data.Length]; - for (var i = 0; i < data.Length; i += 0x10) // Phase 1: CBC Encryption. - { - var slice = data.Slice(i, 0x10); - Xor(curblock, slice, curblock); - curblock = AesEcbEncrypt(key, curblock); - curblock.CopyTo(outdata, i); - } - - // In between - CMAC stuff - var inbet = outdata.AsSpan(0, 0x10); - Xor(curblock, inbet, curblock); - - Span subkey = stackalloc byte[0x10]; - GetSubKey(curblock, subkey); - - Span temp = stackalloc byte[0x10]; - curblock.AsSpan().Clear(); // Memcpy from an all-zero buffer - for (var i = data.Length - 0x10; i >= 0; i -= 0x10) - { - var slice = outdata.AsSpan(i, 0x10); - Xor(slice, subkey, curblock); - byte[] temp1 = AesEcbEncrypt(key, curblock); - Xor(temp1, temp, slice); - curblock.CopyTo(temp); - } - - var outbuf = input.ToArray(); - outdata.AsSpan()[..0x60].CopyTo(outbuf.AsSpan()[^0x60..]); - - return outbuf; + // HashLengthInBytes is 20. + Span hash = stackalloc byte[20]; + using var h = IncrementalHash.CreateHash(HashAlgorithmName.SHA1); + h.AppendData(DER); + h.AppendData(data); + h.TryGetCurrentHash(hash, out _); + return hash[..chunk].ToArray(); // need a byte[0x10] (not 0x14) for the AES impl } private static void GetSubKey(ReadOnlySpan temp, Span subkey) { - for (var ofs = 0; ofs < 0x10; ofs += 2) // Imperfect ROL implementation + for (var i = 0; i < temp.Length; i += 2) // Imperfect ROL implementation { - byte b1 = temp[ofs + 0], b2 = temp[ofs + 1]; - subkey[ofs + 0] = (byte)((2 * b1) + (b2 >> 7)); - subkey[ofs + 1] = (byte)(2 * b2); - if (ofs + 2 < temp.Length) - subkey[ofs + 1] += (byte)(temp[ofs + 2] >> 7); + byte b1 = temp[i + 0], b2 = temp[i + 1]; + subkey[i + 0] = (byte)((2 * b1) + (b2 >> 7)); + subkey[i + 1] = (byte)(2 * b2); + if (i + 2 < temp.Length) + subkey[i + 1] += (byte)(temp[i + 2] >> 7); } if ((temp[0] & 0x80) != 0) subkey[0xF] ^= 0x87; } - private static void Xor(ReadOnlySpan b1, ReadOnlySpan b2, Span result) + private static void Xor(Span b1, Span b2) { - Debug.Assert(b1.Length == b2.Length); - for (var i = 0; i < b1.Length; i++) - result[i] = (byte)(b1[i] ^ b2[i]); + Debug.Assert(b1.Length <= b2.Length); + for (var i = 0; i < b2.Length; i++) + b1[i] ^= b2[i]; } /// /// Perform Rsa Decryption /// - internal byte[] RsaPrivate(ReadOnlySpan data) + internal void RsaPrivate(ReadOnlySpan data, Span outSig) { - var _M = new byte[data.Length + 1]; - data.CopyTo(_M.AsSpan(1)); - Array.Reverse(_M); - var M = new BigInteger(_M); - - return Exponentiate(M, D); + var M = new BigInteger(data, isUnsigned: true, isBigEndian: true); + Exponentiate(M, D, outSig); } /// /// Perform Rsa Encryption /// - internal byte[] RsaPublic(ReadOnlySpan data) + internal void RsaPublic(ReadOnlySpan data, Span outSig) { - var _M = new byte[data.Length + 1]; - data.CopyTo(_M.AsSpan(1)); - Array.Reverse(_M); - var M = new BigInteger(_M); - - return Exponentiate(M, E); + var M = new BigInteger(data, isUnsigned: true, isBigEndian: true); + Exponentiate(M, E, outSig); } #region MemeKey Helper Methods - /// Indicator value for a bad Exponent - private static readonly BigInteger INVALID = BigInteger.MinusOne; // Helper method for Modular Exponentiation - private byte[] Exponentiate(BigInteger M, BigInteger Power) + private void Exponentiate(BigInteger M, BigInteger Power, Span result) { - var rawSig = BigInteger.ModPow(M, Power, N).ToByteArray(); - Array.Reverse(rawSig); - var outSig = new byte[0x60]; - if (rawSig.Length < 0x60) - Array.Copy(rawSig, 0, outSig, 0x60 - rawSig.Length, rawSig.Length); - else if (rawSig.Length > 0x60) - Array.Copy(rawSig, rawSig.Length - 0x60, outSig, 0, 0x60); - else - Array.Copy(rawSig, outSig, 0x60); - return outSig; + var raw = BigInteger.ModPow(M, Power, N); + raw.TryWriteBytes(result, out _, isUnsigned: true, isBigEndian: true); } - private static byte[] GetMemeData(MemeKeyIndex key) => key switch + private static ReadOnlySpan GetMemeDataVerify(MemeKeyIndex key) => key switch { - MemeKeyIndex.LocalWireless => DER_LW, - MemeKeyIndex.FriendlyCompetition => DER_0, - MemeKeyIndex.LiveCompetition => DER_1, - MemeKeyIndex.RentalTeam => DER_2, - MemeKeyIndex.PokedexAndSaveFile => DER_3, - MemeKeyIndex.GaOle => DER_4, - MemeKeyIndex.MagearnaEvent => DER_5, - MemeKeyIndex.MoncolleGet => DER_6, - MemeKeyIndex.IslandScanEventSpecial => DER_7, - MemeKeyIndex.TvTokyoDataBroadcasting => DER_8, - MemeKeyIndex.CapPikachuEvent => DER_9, - MemeKeyIndex.Unknown10 => DER_A, - MemeKeyIndex.Unknown11 => DER_B, - MemeKeyIndex.Unknown12 => DER_C, - MemeKeyIndex.Unknown13 => DER_D, + LocalWireless => DER_LW, + FriendlyCompetition => DER_0, + LiveCompetition => DER_1, + RentalTeam => DER_2, + PokedexAndSaveFile => DER_3, + GaOle => DER_4, + MagearnaEvent => DER_5, + MoncolleGet => DER_6, + IslandScanEventSpecial => DER_7, + TvTokyoDataBroadcasting => DER_8, + CapPikachuEvent => DER_9, + Unknown10 => DER_A, + Unknown11 => DER_B, + Unknown12 => DER_C, + Unknown13 => DER_D, _ => throw new ArgumentOutOfRangeException(nameof(key), key, null), }; - private static readonly byte[] rgbIV = new byte[0x10]; - - // Helper Method to perform AES ECB Encryption - private static byte[] AesEcbEncrypt(byte[] key, byte[] data) + private static ReadOnlySpan GetMemeDataSign(MemeKeyIndex key) => key switch { - using var ms = new MemoryStream(data.Length); - using var aes = Aes.Create(); - aes.Mode = CipherMode.ECB; - aes.Padding = PaddingMode.None; - - using var enc = aes.CreateEncryptor(key, rgbIV); - using var cs = new CryptoStream(ms, enc, CryptoStreamMode.Write); - cs.Write(data, 0, data.Length); - cs.FlushFinalBlock(); - - return ms.ToArray(); - } - - // Helper Method to perform AES ECB Decryption - private static byte[] AesEcbDecrypt(byte[] key, byte[] data) - { - using var ms = new MemoryStream(data.Length); - using var aes = Aes.Create(); - aes.Mode = CipherMode.ECB; - aes.Padding = PaddingMode.None; - - using var cs = new CryptoStream(ms, aes.CreateDecryptor(key, rgbIV), CryptoStreamMode.Write); - cs.Write(data, 0, data.Length); - cs.FlushFinalBlock(); - - return ms.ToArray(); - } + PokedexAndSaveFile => D_3, + _ => throw new ArgumentOutOfRangeException(nameof(key), key, null), + }; public static bool IsValidPokeKeyIndex(int index) { if (!Enum.IsDefined(typeof(MemeKeyIndex), index)) return false; - return (MemeKeyIndex)index != MemeKeyIndex.LocalWireless; + return (MemeKeyIndex)index != LocalWireless; } #endregion #region Official Keydata - private static readonly byte[] DER_0 = "307C300D06092A864886F70D0101010500036B003068026100B3D68C9B1090F6B1B88ECFA9E2F60E9C62C3033B5B64282F262CD393B433D97BD3DB7EBA470B1A77A3DB3C18A1E7616972229BDAD54FB02A19546C65FA4773AABE9B8C926707E7B7DDE4C867C01C0802985E438656168A4430F3F3B9662D7D010203010001".ToByteArray(); - private static readonly byte[] DER_1 = "307C300D06092A864886F70D0101010500036B003068026100C10F4097FD3C781A8FDE101EF3B2F091F82BEE4742324B9206C581766EAF2FBB42C7D60D749B999C529B0E22AD05E0C880231219AD473114EC454380A92898D7A8B54D9432584897D6AFE4860235126190A328DD6525D97B9058D98640B0FA050203010001".ToByteArray(); - private static readonly byte[] DER_2 = "307C300D06092A864886F70D0101010500036B003068026100C3C8D89F55D6A236A115C77594D4B318F0A0A0E3252CC0D6345EB9E33A43A5A56DC9D10B7B59C135396159EC4D01DEBC5FB3A4CAE47853E205FE08982DFCC0C39F0557449F97D41FED13B886AEBEEA918F4767E8FBE0494FFF6F6EE3508E3A3F0203010001".ToByteArray(); - private static readonly byte[] DER_3 = "307C300D06092A864886F70D0101010500036B003068026100B61E192091F90A8F76A6EAAA9A3CE58C863F39AE253F037816F5975854E07A9A456601E7C94C29759FE155C064EDDFA111443F81EF1A428CF6CD32F9DAC9D48E94CFB3F690120E8E6B9111ADDAF11E7C96208C37C0143FF2BF3D7E831141A9730203010001".ToByteArray(); - private static readonly byte[] DER_4 = "307C300D06092A864886F70D0101010500036B003068026100A0F2AC80B408E2E4D58916A1C706BEE7A24758A62CE9B50AF1B31409DFCB382E885AA8BB8C0E4AD1BCF6FF64FB3037757D2BEA10E4FE9007C850FFDCF70D2AFAA4C53FAFE38A9917D467862F50FE375927ECFEF433E61BF817A645FA5665D9CF0203010001".ToByteArray(); - private static readonly byte[] DER_5 = "307C300D06092A864886F70D0101010500036B003068026100D046F2872868A5089205B226DE13D86DA552646AC152C84615BE8E0A5897C3EA45871028F451860EA226D53B68DDD5A77D1AD82FAF857EA52CF7933112EEC367A06C0761E580D3D70B6B9C837BAA3F16D1FF7AA20D87A2A5E2BCC6E383BF12D50203010001".ToByteArray(); - private static readonly byte[] DER_6 = "307C300D06092A864886F70D0101010500036B003068026100D379919001D7FF40AC59DF475CF6C6368B1958DD4E870DFD1CE11218D5EA9D88DD7AD530E2806B0B092C02E25DB092518908EDA574A0968D49B0503954B24284FA75445A074CE6E1ABCEC8FD01DAA0D21A0DD97B417BC3E54BEB7253FC06D3F30203010001".ToByteArray(); - private static readonly byte[] DER_7 = "307C300D06092A864886F70D0101010500036B003068026100B751CB7D282625F2961A7138650ABE1A6AA80D69548BA3AE9DFF065B2805EB3675D960C62096C2835B1DF1C290FC19411944AFDF3458E3B1BC81A98C3F3E95D0EE0C20A0259E614399404354D90F0C69111A4E525F425FBB31A38B8C558F23730203010001".ToByteArray(); - private static readonly byte[] DER_8 = "307C300D06092A864886F70D0101010500036B003068026100B328FE4CC41627882B04FBA0A396A15285A8564B6112C1203048766D827E8E4E5655D44B266B2836575AE68C8301632A3E58B1F4362131E97B0AA0AFC38F2F7690CBD4F3F4652072BFD8E9421D2BEEF177873CD7D08B6C0D1022109CA3ED5B630203010001".ToByteArray(); - private static readonly byte[] DER_9 = "307C300D06092A864886F70D0101010500036B003068026100C4B32FD1161CC30D04BD569F409E878AA2815C91DD009A5AE8BFDAEA7D116BF24966BF10FCC0014B258DFEF6614E55FB6DAB2357CD6DF5B63A5F059F724469C0178D83F88F45048982EAE7A7CC249F84667FC393684DA5EFE1856EB10027D1D70203010001".ToByteArray(); - private static readonly byte[] DER_A = "307C300D06092A864886F70D0101010500036B003068026100C5B75401E83352A64EEC8916C4206F17EC338A24A6F7FD515260696D7228496ABC1423E1FF30514149FC199720E95E682539892E510B239A8C7A413DE4EEE74594F073815E9B434711F6807E8B9E7C10C281F89CF3B1C14E3F0ADF83A2805F090203010001".ToByteArray(); - private static readonly byte[] DER_B = "307C300D06092A864886F70D0101010500036B003068026100AC36B88D00C399C660B4846287FFC7F9DF5C07487EAAE3CD4EFD0029D3B86ED3658AD7DEE4C7F5DA25F9F6008885F343122274994CAB647776F0ADCFBA1E0ECEC8BF57CAAB8488BDD59A55195A0167C7D2C4A9CF679D0EFF4A62B5C8568E09770203010001".ToByteArray(); - private static readonly byte[] DER_C = "307C300D06092A864886F70D0101010500036B003068026100CAC0514D4B6A3F70771C461B01BDE3B6D47A0ADA078074DDA50703D8CC28089379DA64FB3A34AD3435D24F7331383BDADC4877662EFB555DA2077619B70AB0342EBE6EE888EBF3CF4B7E8BCCA95C61E993BDD6104C10D11115DC84178A5894350203010001".ToByteArray(); - private static readonly byte[] DER_D = "307C300D06092A864886F70D0101010500036B003068026100B906466740F5A9428DA84B418C7FA6146F7E24C783373D671F9214B40948A4A317C1A4460111B45D2DADD093815401573E52F0178890D35CBD95712EFAAE0D20AD47187648775CD9569431B1FC3C784113E3A48436D30B2CD162218D6781F5ED0203010001".ToByteArray(); + private static ReadOnlySpan DER_LW=> new byte[] { 0x30, 0x7C, 0x30, 0x0D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x6B, 0x00, 0x30, 0x68, 0x02, 0x61, 0x00, 0xB7, 0x56, 0xE1, 0xDC, 0xD8, 0xCE, 0xCE, 0x78, 0xE1, 0x48, 0x10, 0x7B, 0x1B, 0xAC, 0x11, 0x5F, 0xDB, 0x17, 0xDE, 0x84, 0x34, 0x53, 0xCA, 0xB7, 0xD4, 0xE6, 0xDF, 0x8D, 0xD2, 0x1F, 0x5A, 0x3D, 0x17, 0xB4, 0x47, 0x7A, 0x8A, 0x53, 0x1D, 0x97, 0xD5, 0x7E, 0xB5, 0x58, 0xF0, 0xD5, 0x8A, 0x4A, 0xF5, 0xBF, 0xAD, 0xDD, 0xA4, 0xA0, 0xBC, 0x1D, 0xC2, 0x2F, 0xF8, 0x75, 0x76, 0xC7, 0x26, 0x8B, 0x94, 0x28, 0x19, 0xD4, 0xC8, 0x3F, 0x78, 0xE1, 0xEE, 0x92, 0xD4, 0x06, 0x66, 0x2F, 0x4E, 0x68, 0x47, 0x1E, 0x4D, 0xE8, 0x33, 0xE5, 0x12, 0x6C, 0x32, 0xEB, 0x63, 0xA8, 0x68, 0x34, 0x5D, 0x1D, 0x02, 0x03, 0x01, 0x00, 0x01 }; + private static ReadOnlySpan DER_0 => new byte[] { 0x30, 0x7C, 0x30, 0x0D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x6B, 0x00, 0x30, 0x68, 0x02, 0x61, 0x00, 0xB3, 0xD6, 0x8C, 0x9B, 0x10, 0x90, 0xF6, 0xB1, 0xB8, 0x8E, 0xCF, 0xA9, 0xE2, 0xF6, 0x0E, 0x9C, 0x62, 0xC3, 0x03, 0x3B, 0x5B, 0x64, 0x28, 0x2F, 0x26, 0x2C, 0xD3, 0x93, 0xB4, 0x33, 0xD9, 0x7B, 0xD3, 0xDB, 0x7E, 0xBA, 0x47, 0x0B, 0x1A, 0x77, 0xA3, 0xDB, 0x3C, 0x18, 0xA1, 0xE7, 0x61, 0x69, 0x72, 0x22, 0x9B, 0xDA, 0xD5, 0x4F, 0xB0, 0x2A, 0x19, 0x54, 0x6C, 0x65, 0xFA, 0x47, 0x73, 0xAA, 0xBE, 0x9B, 0x8C, 0x92, 0x67, 0x07, 0xE7, 0xB7, 0xDD, 0xE4, 0xC8, 0x67, 0xC0, 0x1C, 0x08, 0x02, 0x98, 0x5E, 0x43, 0x86, 0x56, 0x16, 0x8A, 0x44, 0x30, 0xF3, 0xF3, 0xB9, 0x66, 0x2D, 0x7D, 0x01, 0x02, 0x03, 0x01, 0x00, 0x01 }; + private static ReadOnlySpan DER_1 => new byte[] { 0x30, 0x7C, 0x30, 0x0D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x6B, 0x00, 0x30, 0x68, 0x02, 0x61, 0x00, 0xC1, 0x0F, 0x40, 0x97, 0xFD, 0x3C, 0x78, 0x1A, 0x8F, 0xDE, 0x10, 0x1E, 0xF3, 0xB2, 0xF0, 0x91, 0xF8, 0x2B, 0xEE, 0x47, 0x42, 0x32, 0x4B, 0x92, 0x06, 0xC5, 0x81, 0x76, 0x6E, 0xAF, 0x2F, 0xBB, 0x42, 0xC7, 0xD6, 0x0D, 0x74, 0x9B, 0x99, 0x9C, 0x52, 0x9B, 0x0E, 0x22, 0xAD, 0x05, 0xE0, 0xC8, 0x80, 0x23, 0x12, 0x19, 0xAD, 0x47, 0x31, 0x14, 0xEC, 0x45, 0x43, 0x80, 0xA9, 0x28, 0x98, 0xD7, 0xA8, 0xB5, 0x4D, 0x94, 0x32, 0x58, 0x48, 0x97, 0xD6, 0xAF, 0xE4, 0x86, 0x02, 0x35, 0x12, 0x61, 0x90, 0xA3, 0x28, 0xDD, 0x65, 0x25, 0xD9, 0x7B, 0x90, 0x58, 0xD9, 0x86, 0x40, 0xB0, 0xFA, 0x05, 0x02, 0x03, 0x01, 0x00, 0x01 }; + private static ReadOnlySpan DER_2 => new byte[] { 0x30, 0x7C, 0x30, 0x0D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x6B, 0x00, 0x30, 0x68, 0x02, 0x61, 0x00, 0xC3, 0xC8, 0xD8, 0x9F, 0x55, 0xD6, 0xA2, 0x36, 0xA1, 0x15, 0xC7, 0x75, 0x94, 0xD4, 0xB3, 0x18, 0xF0, 0xA0, 0xA0, 0xE3, 0x25, 0x2C, 0xC0, 0xD6, 0x34, 0x5E, 0xB9, 0xE3, 0x3A, 0x43, 0xA5, 0xA5, 0x6D, 0xC9, 0xD1, 0x0B, 0x7B, 0x59, 0xC1, 0x35, 0x39, 0x61, 0x59, 0xEC, 0x4D, 0x01, 0xDE, 0xBC, 0x5F, 0xB3, 0xA4, 0xCA, 0xE4, 0x78, 0x53, 0xE2, 0x05, 0xFE, 0x08, 0x98, 0x2D, 0xFC, 0xC0, 0xC3, 0x9F, 0x05, 0x57, 0x44, 0x9F, 0x97, 0xD4, 0x1F, 0xED, 0x13, 0xB8, 0x86, 0xAE, 0xBE, 0xEA, 0x91, 0x8F, 0x47, 0x67, 0xE8, 0xFB, 0xE0, 0x49, 0x4F, 0xFF, 0x6F, 0x6E, 0xE3, 0x50, 0x8E, 0x3A, 0x3F, 0x02, 0x03, 0x01, 0x00, 0x01 }; + private static ReadOnlySpan DER_3 => new byte[] { 0x30, 0x7C, 0x30, 0x0D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x6B, 0x00, 0x30, 0x68, 0x02, 0x61, 0x00, 0xB6, 0x1E, 0x19, 0x20, 0x91, 0xF9, 0x0A, 0x8F, 0x76, 0xA6, 0xEA, 0xAA, 0x9A, 0x3C, 0xE5, 0x8C, 0x86, 0x3F, 0x39, 0xAE, 0x25, 0x3F, 0x03, 0x78, 0x16, 0xF5, 0x97, 0x58, 0x54, 0xE0, 0x7A, 0x9A, 0x45, 0x66, 0x01, 0xE7, 0xC9, 0x4C, 0x29, 0x75, 0x9F, 0xE1, 0x55, 0xC0, 0x64, 0xED, 0xDF, 0xA1, 0x11, 0x44, 0x3F, 0x81, 0xEF, 0x1A, 0x42, 0x8C, 0xF6, 0xCD, 0x32, 0xF9, 0xDA, 0xC9, 0xD4, 0x8E, 0x94, 0xCF, 0xB3, 0xF6, 0x90, 0x12, 0x0E, 0x8E, 0x6B, 0x91, 0x11, 0xAD, 0xDA, 0xF1, 0x1E, 0x7C, 0x96, 0x20, 0x8C, 0x37, 0xC0, 0x14, 0x3F, 0xF2, 0xBF, 0x3D, 0x7E, 0x83, 0x11, 0x41, 0xA9, 0x73, 0x02, 0x03, 0x01, 0x00, 0x01 }; + private static ReadOnlySpan DER_4 => new byte[] { 0x30, 0x7C, 0x30, 0x0D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x6B, 0x00, 0x30, 0x68, 0x02, 0x61, 0x00, 0xA0, 0xF2, 0xAC, 0x80, 0xB4, 0x08, 0xE2, 0xE4, 0xD5, 0x89, 0x16, 0xA1, 0xC7, 0x06, 0xBE, 0xE7, 0xA2, 0x47, 0x58, 0xA6, 0x2C, 0xE9, 0xB5, 0x0A, 0xF1, 0xB3, 0x14, 0x09, 0xDF, 0xCB, 0x38, 0x2E, 0x88, 0x5A, 0xA8, 0xBB, 0x8C, 0x0E, 0x4A, 0xD1, 0xBC, 0xF6, 0xFF, 0x64, 0xFB, 0x30, 0x37, 0x75, 0x7D, 0x2B, 0xEA, 0x10, 0xE4, 0xFE, 0x90, 0x07, 0xC8, 0x50, 0xFF, 0xDC, 0xF7, 0x0D, 0x2A, 0xFA, 0xA4, 0xC5, 0x3F, 0xAF, 0xE3, 0x8A, 0x99, 0x17, 0xD4, 0x67, 0x86, 0x2F, 0x50, 0xFE, 0x37, 0x59, 0x27, 0xEC, 0xFE, 0xF4, 0x33, 0xE6, 0x1B, 0xF8, 0x17, 0xA6, 0x45, 0xFA, 0x56, 0x65, 0xD9, 0xCF, 0x02, 0x03, 0x01, 0x00, 0x01 }; + private static ReadOnlySpan DER_5 => new byte[] { 0x30, 0x7C, 0x30, 0x0D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x6B, 0x00, 0x30, 0x68, 0x02, 0x61, 0x00, 0xD0, 0x46, 0xF2, 0x87, 0x28, 0x68, 0xA5, 0x08, 0x92, 0x05, 0xB2, 0x26, 0xDE, 0x13, 0xD8, 0x6D, 0xA5, 0x52, 0x64, 0x6A, 0xC1, 0x52, 0xC8, 0x46, 0x15, 0xBE, 0x8E, 0x0A, 0x58, 0x97, 0xC3, 0xEA, 0x45, 0x87, 0x10, 0x28, 0xF4, 0x51, 0x86, 0x0E, 0xA2, 0x26, 0xD5, 0x3B, 0x68, 0xDD, 0xD5, 0xA7, 0x7D, 0x1A, 0xD8, 0x2F, 0xAF, 0x85, 0x7E, 0xA5, 0x2C, 0xF7, 0x93, 0x31, 0x12, 0xEE, 0xC3, 0x67, 0xA0, 0x6C, 0x07, 0x61, 0xE5, 0x80, 0xD3, 0xD7, 0x0B, 0x6B, 0x9C, 0x83, 0x7B, 0xAA, 0x3F, 0x16, 0xD1, 0xFF, 0x7A, 0xA2, 0x0D, 0x87, 0xA2, 0xA5, 0xE2, 0xBC, 0xC6, 0xE3, 0x83, 0xBF, 0x12, 0xD5, 0x02, 0x03, 0x01, 0x00, 0x01 }; + private static ReadOnlySpan DER_6 => new byte[] { 0x30, 0x7C, 0x30, 0x0D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x6B, 0x00, 0x30, 0x68, 0x02, 0x61, 0x00, 0xD3, 0x79, 0x91, 0x90, 0x01, 0xD7, 0xFF, 0x40, 0xAC, 0x59, 0xDF, 0x47, 0x5C, 0xF6, 0xC6, 0x36, 0x8B, 0x19, 0x58, 0xDD, 0x4E, 0x87, 0x0D, 0xFD, 0x1C, 0xE1, 0x12, 0x18, 0xD5, 0xEA, 0x9D, 0x88, 0xDD, 0x7A, 0xD5, 0x30, 0xE2, 0x80, 0x6B, 0x0B, 0x09, 0x2C, 0x02, 0xE2, 0x5D, 0xB0, 0x92, 0x51, 0x89, 0x08, 0xED, 0xA5, 0x74, 0xA0, 0x96, 0x8D, 0x49, 0xB0, 0x50, 0x39, 0x54, 0xB2, 0x42, 0x84, 0xFA, 0x75, 0x44, 0x5A, 0x07, 0x4C, 0xE6, 0xE1, 0xAB, 0xCE, 0xC8, 0xFD, 0x01, 0xDA, 0xA0, 0xD2, 0x1A, 0x0D, 0xD9, 0x7B, 0x41, 0x7B, 0xC3, 0xE5, 0x4B, 0xEB, 0x72, 0x53, 0xFC, 0x06, 0xD3, 0xF3, 0x02, 0x03, 0x01, 0x00, 0x01 }; + private static ReadOnlySpan DER_7 => new byte[] { 0x30, 0x7C, 0x30, 0x0D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x6B, 0x00, 0x30, 0x68, 0x02, 0x61, 0x00, 0xB7, 0x51, 0xCB, 0x7D, 0x28, 0x26, 0x25, 0xF2, 0x96, 0x1A, 0x71, 0x38, 0x65, 0x0A, 0xBE, 0x1A, 0x6A, 0xA8, 0x0D, 0x69, 0x54, 0x8B, 0xA3, 0xAE, 0x9D, 0xFF, 0x06, 0x5B, 0x28, 0x05, 0xEB, 0x36, 0x75, 0xD9, 0x60, 0xC6, 0x20, 0x96, 0xC2, 0x83, 0x5B, 0x1D, 0xF1, 0xC2, 0x90, 0xFC, 0x19, 0x41, 0x19, 0x44, 0xAF, 0xDF, 0x34, 0x58, 0xE3, 0xB1, 0xBC, 0x81, 0xA9, 0x8C, 0x3F, 0x3E, 0x95, 0xD0, 0xEE, 0x0C, 0x20, 0xA0, 0x25, 0x9E, 0x61, 0x43, 0x99, 0x40, 0x43, 0x54, 0xD9, 0x0F, 0x0C, 0x69, 0x11, 0x1A, 0x4E, 0x52, 0x5F, 0x42, 0x5F, 0xBB, 0x31, 0xA3, 0x8B, 0x8C, 0x55, 0x8F, 0x23, 0x73, 0x02, 0x03, 0x01, 0x00, 0x01 }; + private static ReadOnlySpan DER_8 => new byte[] { 0x30, 0x7C, 0x30, 0x0D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x6B, 0x00, 0x30, 0x68, 0x02, 0x61, 0x00, 0xB3, 0x28, 0xFE, 0x4C, 0xC4, 0x16, 0x27, 0x88, 0x2B, 0x04, 0xFB, 0xA0, 0xA3, 0x96, 0xA1, 0x52, 0x85, 0xA8, 0x56, 0x4B, 0x61, 0x12, 0xC1, 0x20, 0x30, 0x48, 0x76, 0x6D, 0x82, 0x7E, 0x8E, 0x4E, 0x56, 0x55, 0xD4, 0x4B, 0x26, 0x6B, 0x28, 0x36, 0x57, 0x5A, 0xE6, 0x8C, 0x83, 0x01, 0x63, 0x2A, 0x3E, 0x58, 0xB1, 0xF4, 0x36, 0x21, 0x31, 0xE9, 0x7B, 0x0A, 0xA0, 0xAF, 0xC3, 0x8F, 0x2F, 0x76, 0x90, 0xCB, 0xD4, 0xF3, 0xF4, 0x65, 0x20, 0x72, 0xBF, 0xD8, 0xE9, 0x42, 0x1D, 0x2B, 0xEE, 0xF1, 0x77, 0x87, 0x3C, 0xD7, 0xD0, 0x8B, 0x6C, 0x0D, 0x10, 0x22, 0x10, 0x9C, 0xA3, 0xED, 0x5B, 0x63, 0x02, 0x03, 0x01, 0x00, 0x01 }; + private static ReadOnlySpan DER_9 => new byte[] { 0x30, 0x7C, 0x30, 0x0D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x6B, 0x00, 0x30, 0x68, 0x02, 0x61, 0x00, 0xC4, 0xB3, 0x2F, 0xD1, 0x16, 0x1C, 0xC3, 0x0D, 0x04, 0xBD, 0x56, 0x9F, 0x40, 0x9E, 0x87, 0x8A, 0xA2, 0x81, 0x5C, 0x91, 0xDD, 0x00, 0x9A, 0x5A, 0xE8, 0xBF, 0xDA, 0xEA, 0x7D, 0x11, 0x6B, 0xF2, 0x49, 0x66, 0xBF, 0x10, 0xFC, 0xC0, 0x01, 0x4B, 0x25, 0x8D, 0xFE, 0xF6, 0x61, 0x4E, 0x55, 0xFB, 0x6D, 0xAB, 0x23, 0x57, 0xCD, 0x6D, 0xF5, 0xB6, 0x3A, 0x5F, 0x05, 0x9F, 0x72, 0x44, 0x69, 0xC0, 0x17, 0x8D, 0x83, 0xF8, 0x8F, 0x45, 0x04, 0x89, 0x82, 0xEA, 0xE7, 0xA7, 0xCC, 0x24, 0x9F, 0x84, 0x66, 0x7F, 0xC3, 0x93, 0x68, 0x4D, 0xA5, 0xEF, 0xE1, 0x85, 0x6E, 0xB1, 0x00, 0x27, 0xD1, 0xD7, 0x02, 0x03, 0x01, 0x00, 0x01 }; + private static ReadOnlySpan DER_A => new byte[] { 0x30, 0x7C, 0x30, 0x0D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x6B, 0x00, 0x30, 0x68, 0x02, 0x61, 0x00, 0xC5, 0xB7, 0x54, 0x01, 0xE8, 0x33, 0x52, 0xA6, 0x4E, 0xEC, 0x89, 0x16, 0xC4, 0x20, 0x6F, 0x17, 0xEC, 0x33, 0x8A, 0x24, 0xA6, 0xF7, 0xFD, 0x51, 0x52, 0x60, 0x69, 0x6D, 0x72, 0x28, 0x49, 0x6A, 0xBC, 0x14, 0x23, 0xE1, 0xFF, 0x30, 0x51, 0x41, 0x49, 0xFC, 0x19, 0x97, 0x20, 0xE9, 0x5E, 0x68, 0x25, 0x39, 0x89, 0x2E, 0x51, 0x0B, 0x23, 0x9A, 0x8C, 0x7A, 0x41, 0x3D, 0xE4, 0xEE, 0xE7, 0x45, 0x94, 0xF0, 0x73, 0x81, 0x5E, 0x9B, 0x43, 0x47, 0x11, 0xF6, 0x80, 0x7E, 0x8B, 0x9E, 0x7C, 0x10, 0xC2, 0x81, 0xF8, 0x9C, 0xF3, 0xB1, 0xC1, 0x4E, 0x3F, 0x0A, 0xDF, 0x83, 0xA2, 0x80, 0x5F, 0x09, 0x02, 0x03, 0x01, 0x00, 0x01 }; + private static ReadOnlySpan DER_B => new byte[] { 0x30, 0x7C, 0x30, 0x0D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x6B, 0x00, 0x30, 0x68, 0x02, 0x61, 0x00, 0xAC, 0x36, 0xB8, 0x8D, 0x00, 0xC3, 0x99, 0xC6, 0x60, 0xB4, 0x84, 0x62, 0x87, 0xFF, 0xC7, 0xF9, 0xDF, 0x5C, 0x07, 0x48, 0x7E, 0xAA, 0xE3, 0xCD, 0x4E, 0xFD, 0x00, 0x29, 0xD3, 0xB8, 0x6E, 0xD3, 0x65, 0x8A, 0xD7, 0xDE, 0xE4, 0xC7, 0xF5, 0xDA, 0x25, 0xF9, 0xF6, 0x00, 0x88, 0x85, 0xF3, 0x43, 0x12, 0x22, 0x74, 0x99, 0x4C, 0xAB, 0x64, 0x77, 0x76, 0xF0, 0xAD, 0xCF, 0xBA, 0x1E, 0x0E, 0xCE, 0xC8, 0xBF, 0x57, 0xCA, 0xAB, 0x84, 0x88, 0xBD, 0xD5, 0x9A, 0x55, 0x19, 0x5A, 0x01, 0x67, 0xC7, 0xD2, 0xC4, 0xA9, 0xCF, 0x67, 0x9D, 0x0E, 0xFF, 0x4A, 0x62, 0xB5, 0xC8, 0x56, 0x8E, 0x09, 0x77, 0x02, 0x03, 0x01, 0x00, 0x01 }; + private static ReadOnlySpan DER_C => new byte[] { 0x30, 0x7C, 0x30, 0x0D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x6B, 0x00, 0x30, 0x68, 0x02, 0x61, 0x00, 0xCA, 0xC0, 0x51, 0x4D, 0x4B, 0x6A, 0x3F, 0x70, 0x77, 0x1C, 0x46, 0x1B, 0x01, 0xBD, 0xE3, 0xB6, 0xD4, 0x7A, 0x0A, 0xDA, 0x07, 0x80, 0x74, 0xDD, 0xA5, 0x07, 0x03, 0xD8, 0xCC, 0x28, 0x08, 0x93, 0x79, 0xDA, 0x64, 0xFB, 0x3A, 0x34, 0xAD, 0x34, 0x35, 0xD2, 0x4F, 0x73, 0x31, 0x38, 0x3B, 0xDA, 0xDC, 0x48, 0x77, 0x66, 0x2E, 0xFB, 0x55, 0x5D, 0xA2, 0x07, 0x76, 0x19, 0xB7, 0x0A, 0xB0, 0x34, 0x2E, 0xBE, 0x6E, 0xE8, 0x88, 0xEB, 0xF3, 0xCF, 0x4B, 0x7E, 0x8B, 0xCC, 0xA9, 0x5C, 0x61, 0xE9, 0x93, 0xBD, 0xD6, 0x10, 0x4C, 0x10, 0xD1, 0x11, 0x15, 0xDC, 0x84, 0x17, 0x8A, 0x58, 0x94, 0x35, 0x02, 0x03, 0x01, 0x00, 0x01 }; + private static ReadOnlySpan DER_D => new byte[] { 0x30, 0x7C, 0x30, 0x0D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x6B, 0x00, 0x30, 0x68, 0x02, 0x61, 0x00, 0xB9, 0x06, 0x46, 0x67, 0x40, 0xF5, 0xA9, 0x42, 0x8D, 0xA8, 0x4B, 0x41, 0x8C, 0x7F, 0xA6, 0x14, 0x6F, 0x7E, 0x24, 0xC7, 0x83, 0x37, 0x3D, 0x67, 0x1F, 0x92, 0x14, 0xB4, 0x09, 0x48, 0xA4, 0xA3, 0x17, 0xC1, 0xA4, 0x46, 0x01, 0x11, 0xB4, 0x5D, 0x2D, 0xAD, 0xD0, 0x93, 0x81, 0x54, 0x01, 0x57, 0x3E, 0x52, 0xF0, 0x17, 0x88, 0x90, 0xD3, 0x5C, 0xBD, 0x95, 0x71, 0x2E, 0xFA, 0xAE, 0x0D, 0x20, 0xAD, 0x47, 0x18, 0x76, 0x48, 0x77, 0x5C, 0xD9, 0x56, 0x94, 0x31, 0xB1, 0xFC, 0x3C, 0x78, 0x41, 0x13, 0xE3, 0xA4, 0x84, 0x36, 0xD3, 0x0B, 0x2C, 0xD1, 0x62, 0x21, 0x8D, 0x67, 0x81, 0xF5, 0xED, 0x02, 0x03, 0x01, 0x00, 0x01 }; - private static readonly byte[] DER_LW = "307C300D06092A864886F70D0101010500036B003068026100B756E1DCD8CECE78E148107B1BAC115FDB17DE843453CAB7D4E6DF8DD21F5A3D17B4477A8A531D97D57EB558F0D58A4AF5BFADDDA4A0BC1DC22FF87576C7268B942819D4C83F78E1EE92D406662F4E68471E4DE833E5126C32EB63A868345D1D0203010001".ToByteArray(); - - private static readonly byte[] D_3 = "00775455668FFF3CBA3026C2D0B26B8085895958341157AEB03B6B0495EE57803E2186EB6CB2EB62A71DF18A3C9C6579077670961B3A6102DABE5A194AB58C3250AED597FC78978A326DB1D7B28DCCCB2A3E014EDBD397AD33B8F28CD525054251".ToByteArray(); + // Signing Keys + private static ReadOnlySpan D_3 => new byte[] { 0x00, 0x77, 0x54, 0x55, 0x66, 0x8F, 0xFF, 0x3C, 0xBA, 0x30, 0x26, 0xC2, 0xD0, 0xB2, 0x6B, 0x80, 0x85, 0x89, 0x59, 0x58, 0x34, 0x11, 0x57, 0xAE, 0xB0, 0x3B, 0x6B, 0x04, 0x95, 0xEE, 0x57, 0x80, 0x3E, 0x21, 0x86, 0xEB, 0x6C, 0xB2, 0xEB, 0x62, 0xA7, 0x1D, 0xF1, 0x8A, 0x3C, 0x9C, 0x65, 0x79, 0x07, 0x76, 0x70, 0x96, 0x1B, 0x3A, 0x61, 0x02, 0xDA, 0xBE, 0x5A, 0x19, 0x4A, 0xB5, 0x8C, 0x32, 0x50, 0xAE, 0xD5, 0x97, 0xFC, 0x78, 0x97, 0x8A, 0x32, 0x6D, 0xB1, 0xD7, 0xB2, 0x8D, 0xCC, 0xCB, 0x2A, 0x3E, 0x01, 0x4E, 0xDB, 0xD3, 0x97, 0xAD, 0x33, 0xB8, 0xF2, 0x8C, 0xD5, 0x25, 0x05, 0x42, 0x51 }; #endregion } diff --git a/PKHeX.Core/Saves/Encryption/MemeCrypto/MemeKeyIndex.cs b/PKHeX.Core/Saves/Encryption/MemeCrypto/MemeKeyIndex.cs index 08ecbb756..3262105ac 100644 --- a/PKHeX.Core/Saves/Encryption/MemeCrypto/MemeKeyIndex.cs +++ b/PKHeX.Core/Saves/Encryption/MemeCrypto/MemeKeyIndex.cs @@ -21,3 +21,8 @@ public enum MemeKeyIndex Unknown12 = 12, Unknown13 = 13, } + +public static class MemeKeyIndexExtensions +{ + public static bool CanSign(this MemeKeyIndex key) => key is MemeKeyIndex.PokedexAndSaveFile; +} diff --git a/PKHeX.Core/Saves/Encryption/SwishCrypto/SCBlock.cs b/PKHeX.Core/Saves/Encryption/SwishCrypto/SCBlock.cs index 89a001694..2b65cf924 100644 --- a/PKHeX.Core/Saves/Encryption/SwishCrypto/SCBlock.cs +++ b/PKHeX.Core/Saves/Encryption/SwishCrypto/SCBlock.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Diagnostics; using System.IO; using static System.Buffers.Binary.BinaryPrimitives; @@ -187,9 +187,7 @@ public sealed class SCBlock offset += num_bytes; for (int i = 0; i < arr.Length; i++) arr[i] ^= (byte)xk.Next(); -#if DEBUG - Debug.Assert(sub > SCTypeCode.Array || (sub == SCTypeCode.Bool3 && Array.TrueForAll(arr, z => z <= 2)) || Array.TrueForAll(arr, z => z <= 1)); -#endif + EnsureArrayIsSane(sub, arr); return new SCBlock(key, arr, sub); } @@ -205,6 +203,15 @@ public sealed class SCBlock } } + [Conditional("DEBUG")] + private static void EnsureArrayIsSane(SCTypeCode sub, ReadOnlySpan arr) + { + if (sub == SCTypeCode.Bool3) + Debug.Assert(arr.IndexOfAnyExcept(0, 1, 2) == -1); + else + Debug.Assert(sub > SCTypeCode.Array); + } + /// /// Merges the properties from into this object. /// diff --git a/PKHeX.Core/Saves/Encryption/SwishCrypto/SCBlockCompare.cs b/PKHeX.Core/Saves/Encryption/SwishCrypto/SCBlockCompare.cs index d6b5d587c..ce418d7c0 100644 --- a/PKHeX.Core/Saves/Encryption/SwishCrypto/SCBlockCompare.cs +++ b/PKHeX.Core/Saves/Encryption/SwishCrypto/SCBlockCompare.cs @@ -1,5 +1,7 @@ using System.Collections.Generic; using System.Linq; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; namespace PKHeX.Core; @@ -92,16 +94,22 @@ public sealed class SCBlockCompare var aType = s1.GetType(); var b1n = aType.GetAllPropertiesOfType(s1); var names = aType.GetAllConstantsOfType(); - Add(b1n, b1); - Add(b1n, b2); + ReplaceLabels(b1n, b1); + ReplaceLabels(b1n, b2); - void Add(Dictionary list, IEnumerable blocks) + // Replace all const name labels with explicit block property names if they exist. + // Since our Block classes do not retain the u32 key they originated from, we need to compare the buffers to see if they match. + // Could have just checked ContainsKey then indexed in, but I wanted to play with the higher performance API method to get the bucket and mutate directly. + void ReplaceLabels(Dictionary list, IEnumerable blocks) { foreach (var b in blocks) { var match = list.FirstOrDefault(z => ReferenceEquals(z.Key.Data, b.Data)); - if (match.Value != null && names.ContainsKey(b.Key)) - names[b.Key] = match.Value; + if (match.Value is not { } x) + continue; + ref var exist = ref CollectionsMarshal.GetValueRefOrNullRef(names, b.Key); + if (!Unsafe.IsNullRef(ref exist)) + exist = x; } } return names; diff --git a/PKHeX.Core/Saves/Encryption/SwishCrypto/SCBlockMetadata.cs b/PKHeX.Core/Saves/Encryption/SwishCrypto/SCBlockMetadata.cs index 468fb0822..0fbedde68 100644 --- a/PKHeX.Core/Saves/Encryption/SwishCrypto/SCBlockMetadata.cs +++ b/PKHeX.Core/Saves/Encryption/SwishCrypto/SCBlockMetadata.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using System.ComponentModel; using System.Globalization; @@ -44,9 +44,9 @@ public sealed class SCBlockMetadata /// Tab separated text file expected. /// Currently loaded list of block names /// Tab separated key-value pair list of block names. - public static void AddExtraKeyNames(IDictionary names, IEnumerable lines) + public static void AddExtraKeyNames(Dictionary names, IEnumerable lines) { - foreach (var line in lines) + foreach (ReadOnlySpan line in lines) { var split = line.IndexOf('\t'); if (split < 0) @@ -55,9 +55,8 @@ public sealed class SCBlockMetadata if (!ulong.TryParse(hex, NumberStyles.HexNumber, CultureInfo.CurrentCulture, out var value)) continue; - var name = line[(split + 1)..]; - if (!names.ContainsKey((uint) value)) - names[(uint) value] = name; + var name = line[(split + 1)..].ToString(); + names.TryAdd((uint)value, name); } } @@ -97,7 +96,7 @@ public sealed class SCBlockMetadata if (block.Data.Length != 0) { var obj = BlockList.FirstOrDefault(z => ReferenceEquals(z.Key.Data, block.Data)); - if (obj.Key != null) + if (obj is not (null, null)) { saveBlock = obj.Key; return obj.Value; diff --git a/PKHeX.Core/Saves/Encryption/SwishCrypto/SCBlockUtil.cs b/PKHeX.Core/Saves/Encryption/SwishCrypto/SCBlockUtil.cs index 19c0474fd..181741998 100644 --- a/PKHeX.Core/Saves/Encryption/SwishCrypto/SCBlockUtil.cs +++ b/PKHeX.Core/Saves/Encryption/SwishCrypto/SCBlockUtil.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using System.IO; using System.Text; @@ -30,16 +30,16 @@ public static class SCBlockUtil private static void ExportBlock(SCBlock block, BinaryWriter bw, int blockIndex, SCBlockExportOption option) { - if (option.HasFlagFast(SCBlockExportOption.DataOnly) && block.Data.Length == 0) + if (option.HasFlag(SCBlockExportOption.DataOnly) && block.Data.Length == 0) return; - if (option.HasFlagFast(SCBlockExportOption.FakeHeader)) + if (option.HasFlag(SCBlockExportOption.FakeHeader)) bw.Write($"BLOCK{blockIndex:0000} {block.Key:X8}"); - if (option.HasFlagFast(SCBlockExportOption.Key)) + if (option.HasFlag(SCBlockExportOption.Key)) bw.Write(block.Key); - if (option.HasFlagFast(SCBlockExportOption.TypeInfo)) + if (option.HasFlag(SCBlockExportOption.TypeInfo)) { bw.Write((byte) block.Type); bw.Write((byte) block.SubType); @@ -142,11 +142,3 @@ public enum SCBlockExportOption /// All = DataOnly | Key | TypeInfo | FakeHeader, } - -internal static class ScBlockExportOptionExtensions -{ - public static bool HasFlagFast(this SCBlockExportOption value, SCBlockExportOption flag) - { - return (value & flag) != 0; - } -} diff --git a/PKHeX.Core/Saves/Encryption/SwishCrypto/SCXorShift32.cs b/PKHeX.Core/Saves/Encryption/SwishCrypto/SCXorShift32.cs index a8aed34f4..451d8038e 100644 --- a/PKHeX.Core/Saves/Encryption/SwishCrypto/SCXorShift32.cs +++ b/PKHeX.Core/Saves/Encryption/SwishCrypto/SCXorShift32.cs @@ -13,18 +13,14 @@ public ref struct SCXorShift32 private int Counter; private uint Seed; - public SCXorShift32(uint seed) + public SCXorShift32(uint seed) => Seed = GetInitialSeed(seed); + + private static uint GetInitialSeed(uint seed) { -#if NET6_0_OR_GREATER var pop_count = System.Numerics.BitOperations.PopCount(seed); -#else - var pop_count = PopCount(seed); -#endif for (var i = 0; i < pop_count; i++) seed = XorshiftAdvance(seed); - - Counter = 0; - Seed = seed; + return seed; } /// @@ -62,19 +58,4 @@ public ref struct SCXorShift32 key ^= key << 13; return key; } - -#if !NET6_0_OR_GREATER - /// - /// Count of bits set in value - /// - private static uint PopCount(uint x) - { - x -= ((x >> 1) & 0x55555555u); - x = (x & 0x33333333u) + ((x >> 2) & 0x33333333u); - x = (x + (x >> 4)) & 0x0F0F0F0Fu; - x += (x >> 8); - x += (x >> 16); - return x & 0x0000003Fu; - } -#endif } diff --git a/PKHeX.Core/Saves/Encryption/SwishCrypto/SwishCrypto.cs b/PKHeX.Core/Saves/Encryption/SwishCrypto/SwishCrypto.cs index 4b819f82f..556ac7f0a 100644 --- a/PKHeX.Core/Saves/Encryption/SwishCrypto/SwishCrypto.cs +++ b/PKHeX.Core/Saves/Encryption/SwishCrypto/SwishCrypto.cs @@ -1,6 +1,8 @@ using System; using System.Collections.Generic; using System.IO; +using System.Numerics; +using System.Runtime.InteropServices; using System.Security.Cryptography; namespace PKHeX.Core; @@ -9,7 +11,7 @@ namespace PKHeX.Core; /// MemeCrypto V2 - The Next Generation /// /// -/// A variant of encryption and obfuscation used in and . +/// A variant of encryption and obfuscation used in and future in-house titles. ///
Individual save blocks are stored in a hash map, with some object-type details prefixing the block's raw data.
///
Once the raw save file data is dumped, the binary is hashed with SHA256 using a static Intro salt and static Outro salt.
///
With the hash computed, the data is encrypted with a repeating irregular-sized static xor cipher.
@@ -18,7 +20,7 @@ public static class SwishCrypto { private const int SIZE_HASH = 0x20; - private static readonly byte[] IntroHashBytes = + private static ReadOnlySpan IntroHashBytes => new byte[] { 0x9E, 0xC9, 0x9C, 0xD7, 0x0E, 0xD3, 0x3C, 0x44, 0xFB, 0x93, 0x03, 0xDC, 0xEB, 0x39, 0xB4, 0x2A, 0x19, 0x47, 0xE9, 0x63, 0x4B, 0xA2, 0x33, 0x44, 0x16, 0xBF, 0x82, 0xA2, 0xBA, 0x63, 0x55, 0xB6, @@ -26,7 +28,7 @@ public static class SwishCrypto 0x3A, 0x05, 0x90, 0x00, 0xE8, 0xA8, 0x10, 0x3D, 0xE2, 0xEC, 0xF0, 0x0C, 0xB2, 0xED, 0x4F, 0x6D, }; - private static readonly byte[] OutroHashBytes = + private static ReadOnlySpan OutroHashBytes => new byte[] { 0xD6, 0xC0, 0x1C, 0x59, 0x8B, 0xC8, 0xB8, 0xCB, 0x46, 0xE1, 0x53, 0xFC, 0x82, 0x8C, 0x75, 0x75, 0x13, 0xE0, 0x45, 0xDF, 0x32, 0x69, 0x3C, 0x75, 0xF0, 0x59, 0xF8, 0xD9, 0xA2, 0x5F, 0xB2, 0x17, @@ -34,7 +36,7 @@ public static class SwishCrypto 0xF1, 0x26, 0xE0, 0x03, 0x0A, 0xE6, 0x6F, 0xF6, 0x41, 0xBF, 0x7E, 0x59, 0xC2, 0xAE, 0x55, 0xFD, }; - private static readonly byte[] StaticXorpad = + private static ReadOnlySpan StaticXorpad => new byte[] { 0xA0, 0x92, 0xD1, 0x06, 0x07, 0xDB, 0x32, 0xA1, 0xAE, 0x01, 0xF5, 0xC5, 0x1E, 0x84, 0x4F, 0xE3, 0x53, 0xCA, 0x37, 0xF4, 0xA7, 0xB0, 0x4D, 0xA0, 0x18, 0xB7, 0xC2, 0x97, 0xDA, 0x5F, 0x53, 0x2B, @@ -43,36 +45,39 @@ public static class SwishCrypto 0xD2, 0xD1, 0x50, 0x3D, 0xDE, 0x5B, 0x2E, 0x0E, 0x52, 0xFD, 0xDF, 0x2F, 0x7B, 0xCA, 0x63, 0x50, 0xA4, 0x67, 0x5D, 0x23, 0x17, 0xC0, 0x52, 0xE1, 0xA6, 0x30, 0x7C, 0x2B, 0xB6, 0x70, 0x36, 0x5B, 0x2A, 0x27, 0x69, 0x33, 0xF5, 0x63, 0x7B, 0x36, 0x3F, 0x26, 0x9B, 0xA3, 0xED, 0x7A, 0x53, 0x00, - 0xA4, 0x48, 0xB3, 0x50, 0x9E, 0x14, 0xA0, 0x52, 0xDE, 0x7E, 0x10, 0x2B, 0x1B, 0x77, 0x6E, + 0xA4, 0x48, 0xB3, 0x50, 0x9E, 0x14, 0xA0, 0x52, 0xDE, 0x7E, 0x10, 0x2B, 0x1B, 0x77, 0x6E, 0, // aligned to 0x80 }; public static void CryptStaticXorpadBytes(Span data) { + // Apply the xorpad over each chunk of xorpad-sized spans. + // This is 30x as fast as a single loop with a modulus operation (benchmarked; modulo is slower). + // Marshal as a vectorized operation to speed up the process. + // Due to the xorpad being extended 0x7F->0x80, if len%7F==0, we miss the last vectored xor. + // Subtract 1 from the data size in the event that the length is an even multiple, to get one less iteration. var xp = StaticXorpad; - var region = data[..^SIZE_HASH]; - for (var i = 0; i < region.Length; i++) - region[i] ^= xp[i % xp.Length]; + var xp64 = MemoryMarshal.Cast>(xp); + var size = xp.Length - 1; + int iterations = (data.Length - 1) / size; + do + { + var slice = MemoryMarshal.Cast>(data[..xp.Length]); + for (int i = slice.Length - 1; i >= 0; i--) + slice[i] ^= xp64[i]; + data = data[size..]; + } while (--iterations != 0); + // Xor the remainder. + for (int i = data.Length - 1; i >= 0; i--) + data[i] ^= xp[i]; } - private static byte[] ComputeHash(byte[] data) + private static void ComputeHash(ReadOnlySpan data, Span hash) { -#if !NET46 using var h = IncrementalHash.CreateHash(HashAlgorithmName.SHA256); h.AppendData(IntroHashBytes); - h.AppendData(data, 0, data.Length - SIZE_HASH); + h.AppendData(data); h.AppendData(OutroHashBytes); - return h.GetHashAndReset(); -#else - var intro = IntroHashBytes; - var outro = OutroHashBytes; - using var stream = new MemoryStream(intro.Length + data.Length - SIZE_HASH + outro.Length); - stream.Write(intro, 0, intro.Length); - stream.Write(data, 0, data.Length - SIZE_HASH); // hash is at the end - stream.Write(outro, 0, outro.Length); - stream.Seek(0, SeekOrigin.Begin); - using var sha = SHA256.Create(); - return sha.ComputeHash(stream); -#endif + h.TryGetCurrentHash(hash, out _); } /// @@ -80,11 +85,12 @@ public static class SwishCrypto /// /// Encrypted save data /// True if hash matches - public static bool GetIsHashValid(byte[] data) + public static bool GetIsHashValid(ReadOnlySpan data) { - var hash = ComputeHash(data); - var span = data.AsSpan()[^hash.Length..]; - return span.SequenceEqual(hash); + Span computed = stackalloc byte[SIZE_HASH]; + ComputeHash(data[..^SIZE_HASH], computed); + var stored = data[^computed.Length..]; + return computed.SequenceEqual(stored); } /// @@ -97,8 +103,10 @@ public static class SwishCrypto /// public static IReadOnlyList Decrypt(Span data) { - CryptStaticXorpadBytes(data); - return ReadBlocks(data); + // ignore hash + var payload = data[..^SIZE_HASH]; + CryptStaticXorpadBytes(payload); + return ReadBlocks(payload); } private const int BlockDataRatioEstimate1 = 777; // bytes per block, on average (generous) @@ -108,7 +116,7 @@ public static class SwishCrypto { var result = new List(data.Length / BlockDataRatioEstimate2); int offset = 0; - while (offset < data.Length - SIZE_HASH) + while (offset < data.Length) { var block = SCBlock.ReadFromOffset(data, ref offset); result.Add(block); @@ -125,11 +133,10 @@ public static class SwishCrypto public static byte[] Encrypt(IReadOnlyList blocks) { var result = GetDecryptedRawData(blocks); - CryptStaticXorpadBytes(result); - - var hash = ComputeHash(result); - hash.CopyTo(result, result.Length - SIZE_HASH); - + var span = result.AsSpan(); + var payload = span[..^SIZE_HASH]; + CryptStaticXorpadBytes(payload); + ComputeHash(payload, span[^SIZE_HASH..]); return result; } @@ -144,10 +151,10 @@ public static class SwishCrypto foreach (var block in blocks) block.WriteBlock(bw); - // Allocate hash bytes at the end - for (int i = 0; i < SIZE_HASH; i++) - bw.Write((byte)0); - - return ms.ToArray(); + var result = new byte[ms.Position + SIZE_HASH]; + var payload = result.AsSpan()[..^SIZE_HASH]; + ms.Position = 0; + ms.ReadExactly(payload); + return result; } } diff --git a/PKHeX.Core/Saves/SAV1.cs b/PKHeX.Core/Saves/SAV1.cs index f5621918b..3f63e4ebe 100644 --- a/PKHeX.Core/Saves/SAV1.cs +++ b/PKHeX.Core/Saves/SAV1.cs @@ -18,8 +18,8 @@ public sealed class SAV1 : SaveFile, ILangDeviantSave, IEventFlagArray public bool Japanese { get; } public bool Korean => false; - private readonly PersonalTable1 Table; - public override IPersonalTable Personal => Table; + public override PersonalTable1 Personal { get; } + public override IReadOnlyList HeldItems => Array.Empty(); public override IReadOnlyList PKMExtensions => Array.FindAll(PKM.Extensions, f => @@ -33,7 +33,7 @@ public sealed class SAV1 : SaveFile, ILangDeviantSave, IEventFlagArray Version = version; Japanese = japanese; Offsets = Japanese ? SAV1Offsets.JPN : SAV1Offsets.INT; - Table = version == GameVersion.YW ? PersonalTable.Y : PersonalTable.RB; + Personal = version == GameVersion.YW ? PersonalTable.Y : PersonalTable.RB; Initialize(version); ClearBoxes(); } @@ -44,7 +44,7 @@ public sealed class SAV1 : SaveFile, ILangDeviantSave, IEventFlagArray Offsets = Japanese ? SAV1Offsets.JPN : SAV1Offsets.INT; Version = versionOverride != GameVersion.Any ? versionOverride : SaveUtil.GetIsG1SAV(data); - Table = Version == GameVersion.YW ? PersonalTable.Y : PersonalTable.RB; + Personal = Version == GameVersion.YW ? PersonalTable.Y : PersonalTable.RB; if (Version == GameVersion.Invalid) return; @@ -129,7 +129,7 @@ public sealed class SAV1 : SaveFile, ILangDeviantSave, IEventFlagArray { var slotOfs = boxDest + (i * SIZE_STORED); var slotData = Data.AsSpan(slotOfs, SIZE_STORED); - PK1 pk = (PK1)GetPKM(slotData.ToArray()); + PK1 pk = GetPKM(slotData.ToArray()); if (pk.Species > 0) boxPL[slot++] = pk; } @@ -176,7 +176,7 @@ public sealed class SAV1 : SaveFile, ILangDeviantSave, IEventFlagArray int pSlot = 0; for (int i = 0; i < 6; i++) { - PK1 partyPK = (PK1)GetPKM(GetData(GetPartyOffset(i), SIZE_STORED)); + PK1 partyPK = GetPKM(GetData(GetPartyOffset(i), SIZE_STORED)); if (partyPK.Species > 0) partyPL[pSlot++] = partyPK; } @@ -192,7 +192,7 @@ public sealed class SAV1 : SaveFile, ILangDeviantSave, IEventFlagArray dc.CopyTo(Data.AsSpan(Offsets.Daycare)); SetChecksums(); - return Data.AsSpan()[..^SIZE_RESERVED].ToArray(); + return Data[..^SIZE_RESERVED]; } private int GetBoxRawDataOffset(int box) @@ -203,7 +203,7 @@ public sealed class SAV1 : SaveFile, ILangDeviantSave, IEventFlagArray } // Configuration - protected override SaveFile CloneInternal() => new SAV1(Write(), Version); + protected override SAV1 CloneInternal() => new(Write(), Version); protected override int SIZE_STORED => Japanese ? PokeCrypto.SIZE_1JLIST : PokeCrypto.SIZE_1ULIST; protected override int SIZE_PARTY => Japanese ? PokeCrypto.SIZE_1JLIST : PokeCrypto.SIZE_1ULIST; @@ -211,7 +211,7 @@ public sealed class SAV1 : SaveFile, ILangDeviantSave, IEventFlagArray private int SIZE_STOREDBOX => PokeList1.GetDataLength(Japanese ? PokeListType.StoredJP : PokeListType.Stored, Japanese); private int SIZE_STOREDPARTY => PokeList1.GetDataLength(PokeListType.Party, Japanese); - public override PKM BlankPKM => new PK1(Japanese); + public override PK1 BlankPKM => new(Japanese); public override Type PKMType => typeof(PK1); public override ushort MaxMoveID => Legal.MaxMoveID_1; @@ -258,7 +258,7 @@ public sealed class SAV1 : SaveFile, ILangDeviantSave, IEventFlagArray public override string OT { get => GetString(Offsets.OT, MaxStringLengthOT); - set => SetString(Data.AsSpan(Offsets.OT, MaxStringLengthOT + 1), value.AsSpan(), MaxStringLengthOT, StringConverterOption.ClearZero); + set => SetString(Data.AsSpan(Offsets.OT, MaxStringLengthOT + 1), value, MaxStringLengthOT, StringConverterOption.ClearZero); } public Span OT_Trash { get => Data.AsSpan(Offsets.OT, StringLength); set { if (value.Length == StringLength) value.CopyTo(Data.AsSpan(Offsets.OT)); } } @@ -269,18 +269,24 @@ public sealed class SAV1 : SaveFile, ILangDeviantSave, IEventFlagArray set { } } - public override int TID + public override uint ID32 { - get => ReadUInt16BigEndian(Data.AsSpan(Offsets.TID)); - set => WriteUInt16BigEndian(Data.AsSpan(Offsets.TID), (ushort)value); + get => TID16; + set => TID16 = (ushort)value; } - public override int SID { get => 0; set { } } + public override ushort TID16 + { + get => ReadUInt16BigEndian(Data.AsSpan(Offsets.TID16)); + set => WriteUInt16BigEndian(Data.AsSpan(Offsets.TID16), value); + } + + public override ushort SID16 { get => 0; set { } } public string Rival { get => GetString(Offsets.Rival, MaxStringLengthOT); - set => SetString(Data.AsSpan(Offsets.Rival, MaxStringLengthOT), value.AsSpan(), MaxStringLengthOT, StringConverterOption.Clear50); + set => SetString(Data.AsSpan(Offsets.Rival, MaxStringLengthOT), value, MaxStringLengthOT, StringConverterOption.Clear50); } public Span Rival_Trash { get => Data.AsSpan(Offsets.Rival, StringLength); set { if (value.Length == StringLength) value.CopyTo(Data.AsSpan(Offsets.Rival)); } } @@ -475,19 +481,21 @@ public sealed class SAV1 : SaveFile, ILangDeviantSave, IEventFlagArray public override string GetBoxName(int box) { + if (Japanese) + return $"ボックス{box + 1}"; return $"BOX {box + 1}"; } - public override void SetBoxName(int box, string value) + public override void SetBoxName(int box, ReadOnlySpan value) { // Don't allow for custom box names } - protected override PKM GetPKM(byte[] data) + protected override PK1 GetPKM(byte[] data) { if (data.Length == SIZE_STORED) return new PokeList1(data, PokeListType.Single, Japanese)[0]; - return new PK1(data); + return new(data); } protected override byte[] DecryptPKM(byte[] data) diff --git a/PKHeX.Core/Saves/SAV1Stadium.cs b/PKHeX.Core/Saves/SAV1Stadium.cs index 11058e767..6b5fe2284 100644 --- a/PKHeX.Core/Saves/SAV1Stadium.cs +++ b/PKHeX.Core/Saves/SAV1Stadium.cs @@ -12,12 +12,12 @@ public sealed class SAV1Stadium : SAV_STADIUM public override int SaveRevision => Japanese ? 0 : 1; public override string SaveRevisionString => Japanese ? "J" : "U"; - public override IPersonalTable Personal => PersonalTable.Y; + public override PersonalTable1 Personal => PersonalTable.Y; public override int MaxEV => ushort.MaxValue; public override IReadOnlyList HeldItems => Array.Empty(); public override GameVersion Version { get; protected set; } = GameVersion.Stadium; - protected override SaveFile CloneInternal() => new SAV1Stadium((byte[])Data.Clone(), Japanese); + protected override SAV1Stadium CloneInternal() => new((byte[])Data.Clone(), Japanese); public override int Generation => 1; public override EntityContext Context => EntityContext.Gen1; @@ -35,7 +35,7 @@ public sealed class SAV1Stadium : SAV_STADIUM public override int MaxItemID => Legal.MaxItemID_1; public override Type PKMType => typeof(PK1); - public override PKM BlankPKM => new PK1(Japanese); + public override PK1 BlankPKM => new(Japanese); private const int SIZE_PK1J = PokeCrypto.SIZE_1STORED + (2 * StringLengthJ); // 0x2D private const int SIZE_PK1U = PokeCrypto.SIZE_1STORED + (2 * StringLengthU); // 0x37 protected override int SIZE_STORED => Japanese ? SIZE_PK1J : SIZE_PK1U; @@ -108,7 +108,7 @@ public sealed class SAV1Stadium : SAV_STADIUM Data[bdata - 1] = (byte)count; } - protected override PKM GetPKM(byte[] data) + protected override PK1 GetPKM(byte[] data) { int len = StringLength; var nick = data.AsSpan(PokeCrypto.SIZE_1STORED, len); diff --git a/PKHeX.Core/Saves/SAV1StadiumJ.cs b/PKHeX.Core/Saves/SAV1StadiumJ.cs index e9e82f8b2..cc2623323 100644 --- a/PKHeX.Core/Saves/SAV1StadiumJ.cs +++ b/PKHeX.Core/Saves/SAV1StadiumJ.cs @@ -13,12 +13,12 @@ public sealed class SAV1StadiumJ : SAV_STADIUM public override int SaveRevision => 0; public override string SaveRevisionString => "0"; // so we're different from Japanese SAV1Stadium naming... - public override IPersonalTable Personal => PersonalTable.Y; + public override PersonalTable1 Personal => PersonalTable.Y; public override int MaxEV => ushort.MaxValue; public override IReadOnlyList HeldItems => Array.Empty(); public override GameVersion Version { get; protected set; } = GameVersion.StadiumJ; - protected override SaveFile CloneInternal() => new SAV1StadiumJ((byte[])Data.Clone()); + protected override SAV1StadiumJ CloneInternal() => new((byte[])Data.Clone()); public override int Generation => 1; public override EntityContext Context => EntityContext.Gen1; @@ -37,7 +37,7 @@ public sealed class SAV1StadiumJ : SAV_STADIUM protected override int SIZE_PARTY => SIZE_PK1J; public override Type PKMType => typeof(PK1); - public override PKM BlankPKM => new PK1(true); + public override PK1 BlankPKM => new(true); private const int ListHeaderSize = 0x14; private const int ListFooterSize = 6; // POKE + 2byte checksum @@ -81,7 +81,7 @@ public sealed class SAV1StadiumJ : SAV_STADIUM // Not implemented } - protected override PKM GetPKM(byte[] data) + protected override PK1 GetPKM(byte[] data) { const int len = StringLength; var nick = data.AsSpan(0x21, len); diff --git a/PKHeX.Core/Saves/SAV2.cs b/PKHeX.Core/Saves/SAV2.cs index f7bc5252f..7ea8b8c73 100644 --- a/PKHeX.Core/Saves/SAV2.cs +++ b/PKHeX.Core/Saves/SAV2.cs @@ -18,7 +18,7 @@ public sealed class SAV2 : SaveFile, ILangDeviantSave, IEventFlagArray, IEventWo public bool Japanese { get; } public bool Korean { get; } - public override IPersonalTable Personal { get; } + public override PersonalTable2 Personal { get; } public override IReadOnlyList HeldItems => Legal.HeldItems_GSC; public override IReadOnlyList PKMExtensions => Array.FindAll(PKM.Extensions, f => @@ -180,7 +180,7 @@ public sealed class SAV2 : SaveFile, ILangDeviantSave, IEventFlagArray, IEventWo int slot = 0; for (int j = 0; j < boxPL.Pokemon.Length; j++) { - PK2 boxPK = (PK2) GetPKM(GetData(GetBoxOffset(i) + (j * SIZE_STORED), SIZE_STORED)); + PK2 boxPK = GetPKM(GetData(GetBoxOffset(i) + (j * SIZE_STORED), SIZE_STORED)); if (boxPK.Species > 0) boxPL[slot++] = boxPK; } @@ -195,7 +195,7 @@ public sealed class SAV2 : SaveFile, ILangDeviantSave, IEventFlagArray, IEventWo int pSlot = 0; for (int i = 0; i < 6; i++) { - PK2 partyPK = (PK2)GetPKM(GetData(GetPartyOffset(i), SIZE_STORED)); + PK2 partyPK = GetPKM(GetData(GetPartyOffset(i), SIZE_STORED)); if (partyPK.Species > 0) partyPL[pSlot++] = partyPK; } @@ -245,17 +245,15 @@ public sealed class SAV2 : SaveFile, ILangDeviantSave, IEventFlagArray, IEventWo break; } } - byte[] outData = new byte[Data.Length - SIZE_RESERVED]; - Array.Copy(Data, outData, outData.Length); - return outData; + return Data[..^SIZE_RESERVED]; } // Configuration - protected override SaveFile CloneInternal() => new SAV2(Write(), Version); + protected override SAV2 CloneInternal() => new(Write(), Version); protected override int SIZE_STORED => Japanese ? PokeCrypto.SIZE_2JLIST : PokeCrypto.SIZE_2ULIST; protected override int SIZE_PARTY => Japanese ? PokeCrypto.SIZE_2JLIST : PokeCrypto.SIZE_2ULIST; - public override PKM BlankPKM => new PK2(jp: Japanese); + public override PK2 BlankPKM => new(jp: Japanese); public override Type PKMType => typeof(PK2); private int SIZE_BOX => BoxSlotCount*SIZE_STORED; @@ -324,7 +322,7 @@ public sealed class SAV2 : SaveFile, ILangDeviantSave, IEventFlagArray, IEventWo public override string OT { get => GetString(Offsets.Trainer1 + 2, (Korean ? 2 : 1) * MaxStringLengthOT); - set => SetString(Data.AsSpan(Offsets.Trainer1 + 2, (Korean ? 2 : 1) * MaxStringLengthOT), value.AsSpan(), 8, StringConverterOption.Clear50); + set => SetString(Data.AsSpan(Offsets.Trainer1 + 2, (Korean ? 2 : 1) * MaxStringLengthOT), value, 8, StringConverterOption.Clear50); } public Span OT_Trash @@ -336,7 +334,7 @@ public sealed class SAV2 : SaveFile, ILangDeviantSave, IEventFlagArray, IEventWo public string Rival { get => GetString(Offsets.Rival, (Korean ? 2 : 1) * MaxStringLengthOT); - set => SetString(Data.AsSpan(Offsets.Rival, (Korean ? 2 : 1) * MaxStringLengthOT), value.AsSpan(), 8, StringConverterOption.Clear50); + set => SetString(Data.AsSpan(Offsets.Rival, (Korean ? 2 : 1) * MaxStringLengthOT), value, 8, StringConverterOption.Clear50); } public Span Rival_Trash @@ -357,13 +355,19 @@ public sealed class SAV2 : SaveFile, ILangDeviantSave, IEventFlagArray, IEventWo } } - public override int TID + public override uint ID32 { - get => ReadUInt16BigEndian(Data.AsSpan(Offsets.Trainer1)); - set => WriteUInt16BigEndian(Data.AsSpan(Offsets.Trainer1), (ushort)value); + get => TID16; + set => TID16 = (ushort)value; } - public override int SID { get => 0; set { } } + public override ushort TID16 + { + get => ReadUInt16BigEndian(Data.AsSpan(Offsets.Trainer1)); + set => WriteUInt16BigEndian(Data.AsSpan(Offsets.Trainer1), value); + } + + public override ushort SID16 { get => 0; set { } } public override int PlayedHours { @@ -556,18 +560,18 @@ public sealed class SAV2 : SaveFile, ILangDeviantSave, IEventFlagArray, IEventWo return GetString(Offsets.BoxNames + (box * len), len); } - public override void SetBoxName(int box, string value) + public override void SetBoxName(int box, ReadOnlySpan value) { int len = Korean ? 17 : 9; var span = Data.AsSpan(Offsets.BoxNames + (box * len), len); - SetString(span, value.AsSpan(), 8, StringConverterOption.Clear50); + SetString(span, value, 8, StringConverterOption.Clear50); } - protected override PKM GetPKM(byte[] data) + protected override PK2 GetPKM(byte[] data) { if (data.Length == SIZE_STORED) return new PokeList2(data, PokeListType.Single, Japanese)[0]; - return new PK2(data); + return new(data); } protected override byte[] DecryptPKM(byte[] data) @@ -709,7 +713,7 @@ public sealed class SAV2 : SaveFile, ILangDeviantSave, IEventFlagArray, IEventWo private ushort GetResetKey() { - var value = (TID >> 8) + (TID & 0xFF) + ((Money >> 16) & 0xFF) + ((Money >> 8) & 0xFF) + (Money & 0xFF); + var value = (TID16 >> 8) + (TID16 & 0xFF) + ((Money >> 16) & 0xFF) + ((Money >> 8) & 0xFF) + (Money & 0xFF); var ot = Data.AsSpan(Offsets.Trainer1 + 2, 5); var sum = 0; foreach (var b in ot) diff --git a/PKHeX.Core/Saves/SAV2Stadium.cs b/PKHeX.Core/Saves/SAV2Stadium.cs index f7ea5f26c..9351bf57b 100644 --- a/PKHeX.Core/Saves/SAV2Stadium.cs +++ b/PKHeX.Core/Saves/SAV2Stadium.cs @@ -12,12 +12,12 @@ public sealed class SAV2Stadium : SAV_STADIUM public override int SaveRevision => Japanese ? 0 : 1; public override string SaveRevisionString => Japanese ? "J" : "U"; - public override IPersonalTable Personal => PersonalTable.C; + public override PersonalTable2 Personal => PersonalTable.C; public override int MaxEV => ushort.MaxValue; public override IReadOnlyList HeldItems => Legal.HeldItems_GSC; public override GameVersion Version { get; protected set; } = GameVersion.Stadium2; - protected override SaveFile CloneInternal() => new SAV2Stadium((byte[])Data.Clone(), Japanese); + protected override SAV2Stadium CloneInternal() => new((byte[])Data.Clone(), Japanese); public override int Generation => 2; public override EntityContext Context => EntityContext.Gen2; @@ -33,8 +33,8 @@ public sealed class SAV2Stadium : SAV_STADIUM public override int MaxItemID => Legal.MaxItemID_2; public override Type PKMType => typeof(SK2); - public override PKM BlankPKM => new SK2(Japanese); - protected override PKM GetPKM(byte[] data) => new SK2(data, Japanese); + public override SK2 BlankPKM => new(Japanese); + protected override SK2 GetPKM(byte[] data) => new(data, Japanese); private const int SIZE_SK2 = PokeCrypto.SIZE_2STADIUM; // 60 protected override int SIZE_STORED => SIZE_SK2; @@ -99,7 +99,7 @@ public sealed class SAV2Stadium : SAV_STADIUM Data[boxOfs] = 1; Data[boxOfs + 1] = (byte)count; Data[boxOfs + 4] = StringConverter12.G1TerminatorCode; - StringConverter12.SetString(Data.AsSpan(boxOfs + 0x10, 4), "1234".AsSpan(), 4, Japanese, StringConverterOption.None); + StringConverter12.SetString(Data.AsSpan(boxOfs + 0x10, 4), "1234", 4, Japanese, StringConverterOption.None); } else { diff --git a/PKHeX.Core/Saves/SAV3.cs b/PKHeX.Core/Saves/SAV3.cs index 58e77ff6e..2bbb6f043 100644 --- a/PKHeX.Core/Saves/SAV3.cs +++ b/PKHeX.Core/Saves/SAV3.cs @@ -155,7 +155,7 @@ public abstract class SAV3 : SaveFile, ILangDeviantSave, IEventFlag37 protected sealed override int SIZE_STORED => PokeCrypto.SIZE_3STORED; protected sealed override int SIZE_PARTY => PokeCrypto.SIZE_3PARTY; - public sealed override PKM BlankPKM => new PK3(); + public sealed override PK3 BlankPKM => new(); public sealed override Type PKMType => typeof(PK3); public sealed override ushort MaxMoveID => Legal.MaxMoveID_3; @@ -197,7 +197,7 @@ public abstract class SAV3 : SaveFile, ILangDeviantSave, IEventFlag37 public sealed override bool HasParty => true; public sealed override bool IsPKMPresent(ReadOnlySpan data) => EntityDetection.IsPresentGBA(data); - protected sealed override PKM GetPKM(byte[] data) => new PK3(data); + protected sealed override PK3 GetPKM(byte[] data) => new(data); protected sealed override byte[] DecryptPKM(byte[] data) => PokeCrypto.DecryptArray3(data); protected sealed override byte[] BoxBuffer => Storage; @@ -306,7 +306,7 @@ public abstract class SAV3 : SaveFile, ILangDeviantSave, IEventFlag37 set { int len = Japanese ? 5 : MaxStringLengthOT; - SetString(Small.AsSpan(0, len), value.AsSpan(), len, StringConverterOption.ClearFF); + SetString(Small.AsSpan(0, len), value, len, StringConverterOption.ClearFF); } } @@ -316,16 +316,22 @@ public abstract class SAV3 : SaveFile, ILangDeviantSave, IEventFlag37 set => Small[8] = (byte)value; } - public sealed override int TID + public sealed override uint ID32 { - get => ReadUInt16LittleEndian(Small.AsSpan(0xA)); - set => WriteUInt16LittleEndian(Small.AsSpan(0xA), (ushort)value); + get => ReadUInt32LittleEndian(Small.AsSpan(0x0A)); + set => WriteUInt32LittleEndian(Small.AsSpan(0x0A), value); } - public sealed override int SID + public sealed override ushort TID16 + { + get => ReadUInt16LittleEndian(Small.AsSpan(0xA)); + set => WriteUInt16LittleEndian(Small.AsSpan(0xA), value); + } + + public sealed override ushort SID16 { get => ReadUInt16LittleEndian(Small.AsSpan(0xC)); - set => WriteUInt16LittleEndian(Small.AsSpan(0xC), (ushort)value); + set => WriteUInt16LittleEndian(Small.AsSpan(0xC), value); } public sealed override int PlayedHours @@ -470,11 +476,11 @@ public abstract class SAV3 : SaveFile, ILangDeviantSave, IEventFlag37 return StringConverter3.GetString(Storage.AsSpan(offset + (box * COUNT_BOXNAME), COUNT_BOXNAME), Japanese); } - public sealed override void SetBoxName(int box, string value) + public sealed override void SetBoxName(int box, ReadOnlySpan value) { int offset = GetBoxOffset(COUNT_BOX); var dest = Storage.AsSpan(offset + (box * COUNT_BOXNAME), COUNT_BOXNAME); - SetString(dest, value.AsSpan(), COUNT_BOXNAME - 1, StringConverterOption.ClearZero); + SetString(dest, value, COUNT_BOXNAME - 1, StringConverterOption.ClearZero); } #endregion diff --git a/PKHeX.Core/Saves/SAV3Colosseum.cs b/PKHeX.Core/Saves/SAV3Colosseum.cs index f7c45905d..d4b35c406 100644 --- a/PKHeX.Core/Saves/SAV3Colosseum.cs +++ b/PKHeX.Core/Saves/SAV3Colosseum.cs @@ -12,7 +12,7 @@ public sealed class SAV3Colosseum : SaveFile, IGCSaveFile { protected internal override string ShortSummary => $"{OT} ({Version}) - {PlayTimeString}"; public override string Extension => this.GCExtension(); - public override IPersonalTable Personal => PersonalTable.RS; + public override PersonalTable3 Personal => PersonalTable.RS; public override IReadOnlyList HeldItems => Legal.HeldItems_COLO; public SAV3GCMemoryCard? MemoryCard { get; init; } @@ -28,6 +28,8 @@ public sealed class SAV3Colosseum : SaveFile, IGCSaveFile private const int SLOT_START = 0x6000; private const int SLOT_COUNT = 3; + private const int sha1HashSize = 20; + private int SaveCount = -1; private int SaveIndex = -1; private readonly StrategyMemo StrategyMemo; @@ -67,7 +69,7 @@ public sealed class SAV3Colosseum : SaveFile, IGCSaveFile PartyCount++; } - var memo = new StrategyMemo(Data, Memo, xd: false); + var memo = new StrategyMemo(Data.AsSpan(Memo), xd: false); return memo; } @@ -89,8 +91,8 @@ public sealed class SAV3Colosseum : SaveFile, IGCSaveFile { int slotOffset = SLOT_START + (SaveIndex * SLOT_SIZE); ReadOnlySpan slot = Data.AsSpan(slotOffset, SLOT_SIZE); - Span digest = stackalloc byte[20]; - slot[^20..].CopyTo(digest); + Span digest = stackalloc byte[sha1HashSize]; + slot[^sha1HashSize..].CopyTo(digest); // Decrypt Slot Data = DecryptColosseum(slot, digest); @@ -116,26 +118,22 @@ public sealed class SAV3Colosseum : SaveFile, IGCSaveFile // Get updated save slot data ReadOnlySpan slot = Data; - Span digest = stackalloc byte[20]; - slot[^20..].CopyTo(digest); + Span digest = stackalloc byte[sha1HashSize]; + slot[^sha1HashSize..].CopyTo(digest); byte[] newSAV = EncryptColosseum(slot, digest); // Put save slot back in original save data - byte[] newFile = MemoryCard != null ? MemoryCard.ReadSaveGameData() : (byte[])BAK.Clone(); + byte[] newFile = MemoryCard != null ? MemoryCard.ReadSaveGameData().ToArray() : (byte[])BAK.Clone(); Array.Copy(newSAV, 0, newFile, SLOT_START + (SaveIndex * SLOT_SIZE), newSAV.Length); return newFile; } // Configuration - protected override SaveFile CloneInternal() - { - var data = GetInnerData(); - return new SAV3Colosseum(data) { MemoryCard = MemoryCard }; - } + protected override SAV3Colosseum CloneInternal() => new(GetInnerData()) { MemoryCard = MemoryCard }; protected override int SIZE_STORED => PokeCrypto.SIZE_3CSTORED; protected override int SIZE_PARTY => PokeCrypto.SIZE_3CSTORED; // unused - public override PKM BlankPKM => new CK3(); + public override CK3 BlankPKM => new(); public override Type PKMType => typeof(CK3); public override ushort MaxMoveID => Legal.MaxMoveID_3; @@ -159,21 +157,21 @@ public sealed class SAV3Colosseum : SaveFile, IGCSaveFile private static byte[] EncryptColosseum(ReadOnlySpan input, Span digest) { if (input.Length != SLOT_SIZE) - throw new ArgumentException(nameof(input)); + throw new ArgumentException("Incorrect slot size", nameof(input)); byte[] output = input.ToArray(); // NOT key - for (int i = 0; i < 20; i++) + for (int i = 0; i < digest.Length; i++) digest[i] = (byte)~digest[i]; - using var sha1 = SHA1.Create(); - for (int i = 0x18; i < 0x1DFD8; i += 20) + var crypt = output.AsSpan(0x18, SLOT_SIZE - (2 * sha1HashSize)); + for (int i = 0; i < crypt.Length; i += sha1HashSize) { - for (int j = 0; j < 20; j++) - output[i + j] ^= digest[j]; - byte[] key = sha1.ComputeHash(output, i, 20); // update digest - key.AsSpan(0, 20).CopyTo(digest); // for use in next loop + var slice = crypt.Slice(i, digest.Length); + for (int j = 0; j < digest.Length; j++) + slice[j] ^= digest[j]; + SHA1.HashData(slice, digest); // update digest } return output; } @@ -181,77 +179,82 @@ public sealed class SAV3Colosseum : SaveFile, IGCSaveFile private static byte[] DecryptColosseum(ReadOnlySpan input, Span digest) { if (input.Length != SLOT_SIZE) - throw new ArgumentException(nameof(input)); + throw new ArgumentException("Incorrect slot size", nameof(input)); byte[] output = input.ToArray(); // NOT key - for (int i = 0; i < 20; i++) + for (int i = 0; i < digest.Length; i++) digest[i] = (byte)~digest[i]; - using var sha1 = SHA1.Create(); - for (int i = 0x18; i < 0x1DFD8; i += 20) + Span hash = stackalloc byte[sha1HashSize]; + var crypt = output.AsSpan(0x18, SLOT_SIZE - (2 * sha1HashSize)); + for (int i = 0; i < crypt.Length; i += sha1HashSize) { - byte[] key = sha1.ComputeHash(output, i, 20); // update digest - for (int j = 0; j < 20; j++) - output[i + j] ^= digest[j]; - key.AsSpan(0, 20).CopyTo(digest); // for use in next loop + var slice = crypt.Slice(i, sha1HashSize); + SHA1.HashData(slice, hash); // update digest + for (int j = 0; j < digest.Length; j++) + slice[j] ^= digest[j]; + hash.CopyTo(digest); // for use in next loop } return output; } protected override void SetChecksums() { + var data = Data.AsSpan(); + var header = data[..0x20]; + var payload = data[..(SLOT_SIZE - (2 * sha1HashSize))]; + var hash = data[^sha1HashSize..]; + var headerCHK = data[0x0C..]; + // Clear Header Checksum - var headerCHK = Data.AsSpan(12); WriteInt32BigEndian(headerCHK, 0); // Compute checksum of data - using var sha1 = SHA1.Create(); - byte[] checksum = sha1.ComputeHash(Data, 0, 0x1DFD8); - // Set Checksum to end - var checkSpan = checksum.AsSpan(); - checkSpan.CopyTo(Data.AsSpan(Data.Length - checkSpan.Length)); + SHA1.HashData(payload, hash); // Compute new header checksum - var header = Data.AsSpan(0, 0x20); - int newHC = 0; - for (int i = 0; i < 0x18; i += 4) - newHC -= ReadInt32BigEndian(header[i..]); - newHC -= ReadInt32BigEndian(header[0x18..]) ^ ~ReadInt32BigEndian(checkSpan); - newHC -= ReadInt32BigEndian(header[0x1C..]) ^ ~ReadInt32BigEndian(checkSpan[4..]); + int newHC = ComputeHeaderChecksum(header, hash); // Set Header Checksum WriteInt32BigEndian(headerCHK, newHC); } + private static int ComputeHeaderChecksum(Span header, Span hash) + { + int result = 0; + for (int i = 0; i < 0x18; i += 4) + result -= ReadInt32BigEndian(header[i..]); + result -= ReadInt32BigEndian(header[0x18..]) ^ ~ReadInt32BigEndian(hash); + result -= ReadInt32BigEndian(header[0x1C..]) ^ ~ReadInt32BigEndian(hash[4..]); + return result; + } + public override bool ChecksumsValid => !ChecksumInfo.Contains("Invalid"); public override string ChecksumInfo { get { - byte[] data = (byte[])Data.Clone(); - var hc = data.AsSpan(12); + var data = Data.AsSpan(); + var header = data[..0x20]; + var payload = data[..(SLOT_SIZE - (2 * sha1HashSize))]; + var storedHash = data[^sha1HashSize..]; + var hc = header[0x0C..]; + int oldHC = ReadInt32BigEndian(hc); // Clear Header Checksum - WriteUInt32BigEndian(hc, 0); - using var sha1 = SHA1.Create(); - byte[] checksum = sha1.ComputeHash(data, 0, 0x1DFD8); - var checkSpan = checksum.AsSpan(); + WriteInt32BigEndian(hc, 0); + Span currentHash = stackalloc byte[sha1HashSize]; + SHA1.HashData(payload, currentHash); // Compute new header checksum - var header = data.AsSpan(0, 0x20); - int newHC = 0; - for (int i = 0; i < 0x18; i += 4) - newHC -= ReadInt32BigEndian(header[i..]); - - newHC -= ReadInt32BigEndian(header[0x18..]) ^ ~ReadInt32BigEndian(checkSpan); - newHC -= ReadInt32BigEndian(header[0x1C..]) ^ ~ReadInt32BigEndian(checkSpan[4..]); - - var chk = data.AsSpan(data.Length - 20, 20); + int newHC = ComputeHeaderChecksum(header, currentHash); + // Restore old header checksum + WriteInt32BigEndian(hc, oldHC); bool isHeaderValid = newHC == oldHC; - bool isBodyValid = chk.SequenceEqual(checkSpan); + bool isBodyValid = storedHash.SequenceEqual(currentHash); static string valid(bool s) => s ? "Valid" : "Invalid"; return $"Header Checksum {valid(isHeaderValid)}, Body Checksum {valid(isBodyValid)}."; } @@ -276,16 +279,16 @@ public sealed class SAV3Colosseum : SaveFile, IGCSaveFile return GetString(Box + (0x24A4 * box), 16); } - public override void SetBoxName(int box, string value) + public override void SetBoxName(int box, ReadOnlySpan value) { - SetString(Data.AsSpan(Box + (0x24A4 * box), 16), value.AsSpan(), 8, StringConverterOption.ClearZero); + SetString(Data.AsSpan(Box + (0x24A4 * box), 16), value, 8, StringConverterOption.ClearZero); } - protected override PKM GetPKM(byte[] data) + protected override CK3 GetPKM(byte[] data) { if (data.Length != SIZE_STORED) Array.Resize(ref data, SIZE_STORED); - return new CK3(data); + return new(data); } protected override byte[] DecryptPKM(byte[] data) => data; @@ -312,10 +315,9 @@ public sealed class SAV3Colosseum : SaveFile, IGCSaveFile { entry.Species = pk.Species; entry.PID = pk.PID; - entry.TID = pk.TID; - entry.SID = pk.SID; + entry.ID32 = pk.ID32; } - if (entry.Matches(pk.Species, pk.PID, pk.TID, pk.SID)) + if (entry.Matches(pk.Species, pk.PID, pk.ID32)) { entry.Seen = true; entry.Owned = true; @@ -357,15 +359,17 @@ public sealed class SAV3Colosseum : SaveFile, IGCSaveFile } // Trainer Info (offset 0x78, length 0xB18, end @ 0xB90) - public override string OT { get => GetString(0x78, 20); set { SetString(Data.AsSpan(0x78, 20), value.AsSpan(), 10, StringConverterOption.ClearZero); OT2 = value; } } - public string OT2 { get => GetString(0x8C, 20); set => SetString(Data.AsSpan(0x8C, 20), value.AsSpan(), 10, StringConverterOption.ClearZero); } - public override int SID { get => ReadUInt16BigEndian(Data.AsSpan(0xA4)); set => WriteUInt16BigEndian(Data.AsSpan(0xA4), (ushort)value); } - public override int TID { get => ReadUInt16BigEndian(Data.AsSpan(0xA6)); set => WriteUInt16BigEndian(Data.AsSpan(0xA6), (ushort)value); } + public override string OT { get => GetString(0x78, 20); set { SetString(Data.AsSpan(0x78, 20), value, 10, StringConverterOption.ClearZero); OT2 = value; } } + public string OT2 { get => GetString(0x8C, 20); set => SetString(Data.AsSpan(0x8C, 20), value, 10, StringConverterOption.ClearZero); } + + public override uint ID32 { get => ReadUInt32BigEndian(Data.AsSpan(0xA4)); set => WriteUInt32BigEndian(Data.AsSpan(0xA4), value); } + public override ushort SID16 { get => ReadUInt16BigEndian(Data.AsSpan(0xA4)); set => WriteUInt16BigEndian(Data.AsSpan(0xA4), value); } + public override ushort TID16 { get => ReadUInt16BigEndian(Data.AsSpan(0xA6)); set => WriteUInt16BigEndian(Data.AsSpan(0xA6), value); } public override int Gender { get => Data[0xAF8]; set => Data[0xAF8] = (byte)value; } public override uint Money { get => ReadUInt32BigEndian(Data.AsSpan(0xAFC)); set => WriteUInt32BigEndian(Data.AsSpan(0xAFC), value); } public uint Coupons { get => ReadUInt32BigEndian(Data.AsSpan(0xB00)); set => WriteUInt32BigEndian(Data.AsSpan(0xB00), value); } - public string RUI_Name { get => GetString(0xB3A, 20); set => SetString(Data.AsSpan(0xB3A, 20), value.AsSpan(), 10, StringConverterOption.ClearZero); } + public string RUI_Name { get => GetString(0xB3A, 20); set => SetString(Data.AsSpan(0xB3A, 20), value, 10, StringConverterOption.ClearZero); } public override IReadOnlyList Inventory { diff --git a/PKHeX.Core/Saves/SAV3E.cs b/PKHeX.Core/Saves/SAV3E.cs index 6422f37f7..70cf4c3ab 100644 --- a/PKHeX.Core/Saves/SAV3E.cs +++ b/PKHeX.Core/Saves/SAV3E.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using static System.Buffers.Binary.BinaryPrimitives; @@ -11,9 +11,9 @@ namespace PKHeX.Core; public sealed class SAV3E : SAV3, IGen3Hoenn, IGen3Joyful, IGen3Wonder { // Configuration - protected override SaveFile CloneInternal() => new SAV3E(Write()); + protected override SAV3E CloneInternal() => new(Write()); public override GameVersion Version { get => GameVersion.E; protected set { } } - public override IPersonalTable Personal => PersonalTable.E; + public override PersonalTable3 Personal => PersonalTable.E; public override int EventFlagCount => 8 * 300; public override int EventWorkCount => 0x100; diff --git a/PKHeX.Core/Saves/SAV3FRLG.cs b/PKHeX.Core/Saves/SAV3FRLG.cs index 013b3c244..8f8e71512 100644 --- a/PKHeX.Core/Saves/SAV3FRLG.cs +++ b/PKHeX.Core/Saves/SAV3FRLG.cs @@ -10,10 +10,10 @@ namespace PKHeX.Core; public sealed class SAV3FRLG : SAV3, IGen3Joyful, IGen3Wonder { // Configuration - protected override SaveFile CloneInternal() => new SAV3FRLG(Write()); + protected override SAV3FRLG CloneInternal() => new(Write()); public override GameVersion Version { get; protected set; } = GameVersion.FR; // allow mutation private PersonalTable3 _personal = PersonalTable.FR; - public override IPersonalTable Personal => _personal; + public override PersonalTable3 Personal => _personal; public override int EventFlagCount => 8 * 288; public override int EventWorkCount => 0x100; @@ -175,7 +175,7 @@ public sealed class SAV3FRLG : SAV3, IGen3Joyful, IGen3Wonder public string RivalName { get => GetString(Large.AsSpan(0x3A4C, 8)); - set => SetString(Large.AsSpan(0x3A4C, 8), value.AsSpan(), 7, StringConverterOption.ClearZero); + set => SetString(Large.AsSpan(0x3A4C, 8), value, 7, StringConverterOption.ClearZero); } #endregion diff --git a/PKHeX.Core/Saves/SAV3GCMemoryCard.cs b/PKHeX.Core/Saves/SAV3GCMemoryCard.cs index 00d4296b6..6e257e434 100644 --- a/PKHeX.Core/Saves/SAV3GCMemoryCard.cs +++ b/PKHeX.Core/Saves/SAV3GCMemoryCard.cs @@ -325,7 +325,7 @@ public sealed class SAV3GCMemoryCard return $"{Makercode}-{GameCode}-{Util.TrimFromZero(FileName)}.gci"; } - public byte[] ReadSaveGameData() + public ReadOnlyMemory ReadSaveGameData() { var entry = EntrySelected; if (entry < 0) @@ -333,14 +333,14 @@ public sealed class SAV3GCMemoryCard return ReadSaveGameData(entry); } - private byte[] ReadSaveGameData(int entry) + private ReadOnlyMemory ReadSaveGameData(int entry) { int offset = (DirectoryBlock_Used * BLOCK_SIZE) + (entry * DENTRY_SIZE); var span = Data.AsSpan(offset); int blockFirst = ReadUInt16BigEndian(span[0x36..]); int blockCount = ReadUInt16BigEndian(span[0x38..]); - return Data.AsSpan(blockFirst * BLOCK_SIZE, blockCount * BLOCK_SIZE).ToArray(); + return Data.AsMemory(blockFirst * BLOCK_SIZE, blockCount * BLOCK_SIZE); } public void WriteSaveGameData(ReadOnlySpan data) diff --git a/PKHeX.Core/Saves/SAV3RS.cs b/PKHeX.Core/Saves/SAV3RS.cs index a4c283446..c3385a0d8 100644 --- a/PKHeX.Core/Saves/SAV3RS.cs +++ b/PKHeX.Core/Saves/SAV3RS.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using static System.Buffers.Binary.BinaryPrimitives; @@ -11,9 +11,9 @@ namespace PKHeX.Core; public sealed class SAV3RS : SAV3, IGen3Hoenn { // Configuration - protected override SaveFile CloneInternal() => new SAV3RS(Write()); + protected override SAV3RS CloneInternal() => new(Write()); public override GameVersion Version { get => GameVersion.RS; protected set { } } - public override IPersonalTable Personal => PersonalTable.RS; + public override PersonalTable3 Personal => PersonalTable.RS; public override int EventFlagCount => 8 * 288; public override int EventWorkCount => 0x100; diff --git a/PKHeX.Core/Saves/SAV3RSBox.cs b/PKHeX.Core/Saves/SAV3RSBox.cs index 3bd305074..cb97519fc 100644 --- a/PKHeX.Core/Saves/SAV3RSBox.cs +++ b/PKHeX.Core/Saves/SAV3RSBox.cs @@ -12,7 +12,7 @@ public sealed class SAV3RSBox : SaveFile, IGCSaveFile { protected internal override string ShortSummary => $"{Version} #{SaveCount:0000}"; public override string Extension => this.GCExtension(); - public override IPersonalTable Personal => PersonalTable.RS; + public override PersonalTable3 Personal => PersonalTable.RS; public override IReadOnlyList HeldItems => Legal.HeldItems_RS; public SAV3GCMemoryCard? MemoryCard { get; init; } private readonly bool Japanese; @@ -95,16 +95,11 @@ public sealed class SAV3RSBox : SaveFile, IGCSaveFile } // Configuration - protected override SaveFile CloneInternal() - { - var data = GetInnerData(); - var sav = MemoryCard is not null ? new SAV3RSBox(data, MemoryCard) : new SAV3RSBox(data); - return sav; - } + protected override SAV3RSBox CloneInternal() => new(GetInnerData()) { MemoryCard = MemoryCard }; protected override int SIZE_STORED => PokeCrypto.SIZE_3STORED + 4; protected override int SIZE_PARTY => PokeCrypto.SIZE_3PARTY; // unused - public override PKM BlankPKM => new PK3(); + public override PK3 BlankPKM => new(); public override Type PKMType => typeof(PK3); public override ushort MaxMoveID => Legal.MaxMoveID_3; @@ -168,7 +163,7 @@ public sealed class SAV3RSBox : SaveFile, IGCSaveFile return boxName; } - public override void SetBoxName(int box, string value) + public override void SetBoxName(int box, ReadOnlySpan value) { int offset = Box + 0x1EC38 + (9 * box); var span = Data.AsSpan(offset, 9); @@ -177,14 +172,14 @@ public sealed class SAV3RSBox : SaveFile, IGCSaveFile span.Clear(); return; } - SetString(span, value.AsSpan(), 8, StringConverterOption.ClearZero); + SetString(span, value, 8, StringConverterOption.ClearZero); } - protected override PKM GetPKM(byte[] data) + protected override PK3 GetPKM(byte[] data) { if (data.Length != PokeCrypto.SIZE_3STORED) Array.Resize(ref data, PokeCrypto.SIZE_3STORED); - return new PK3(data); + return new(data); } protected override byte[] DecryptPKM(byte[] data) @@ -199,8 +194,8 @@ public sealed class SAV3RSBox : SaveFile, IGCSaveFile public override void WriteBoxSlot(PKM pk, Span data, int offset) { base.WriteBoxSlot(pk, data, offset); - WriteUInt16LittleEndian(data[(PokeCrypto.SIZE_3STORED)..], (ushort)pk.TID); - WriteUInt16LittleEndian(data[(PokeCrypto.SIZE_3STORED + 2)..], (ushort)pk.SID); + WriteUInt16LittleEndian(data[(PokeCrypto.SIZE_3STORED)..], pk.TID16); + WriteUInt16LittleEndian(data[(PokeCrypto.SIZE_3STORED + 2)..], pk.SID16); } public override string GetString(ReadOnlySpan data) => StringConverter3.GetString(data, Japanese); diff --git a/PKHeX.Core/Saves/SAV3XD.cs b/PKHeX.Core/Saves/SAV3XD.cs index 105eec704..9fdc60290 100644 --- a/PKHeX.Core/Saves/SAV3XD.cs +++ b/PKHeX.Core/Saves/SAV3XD.cs @@ -54,7 +54,7 @@ public sealed class SAV3XD : SaveFile, IGCSaveFile Initialize(); } - public override IPersonalTable Personal => PersonalTable.RS; + public override PersonalTable3 Personal => PersonalTable.RS; public override IReadOnlyList HeldItems => Legal.HeldItems_XD; private readonly bool Japanese; @@ -95,7 +95,7 @@ public sealed class SAV3XD : SaveFile, IGCSaveFile // Purifier = subOffsets[14] + 0xA8; bool jp = subLength[7] == 0x1E00; - memo = new StrategyMemo(Data, Memo, xd: true); + memo = new StrategyMemo(Data.AsSpan(Memo, subLength[5]), xd: true); info = new ShadowInfoTableXD(Data.AsSpan(Shadow, subLength[7]), jp); return jp; } @@ -157,7 +157,7 @@ public sealed class SAV3XD : SaveFile, IGCSaveFile // Put save slot back in original save data var destOffset = SLOT_START + (SaveIndex * SLOT_SIZE); - byte[] dest = MemoryCard != null ? MemoryCard.ReadSaveGameData() : (byte[])BAK.Clone(); + byte[] dest = MemoryCard != null ? MemoryCard.ReadSaveGameData().ToArray() : (byte[])BAK.Clone(); var destSpan = dest.AsSpan(destOffset, Data.Length); // Get updated save slot data @@ -172,15 +172,11 @@ public sealed class SAV3XD : SaveFile, IGCSaveFile } // Configuration - protected override SaveFile CloneInternal() - { - var data = GetInnerData(); - return new SAV3XD(data) { MemoryCard = MemoryCard }; - } + protected override SAV3XD CloneInternal() => new(GetInnerData()) { MemoryCard = MemoryCard }; protected override int SIZE_STORED => PokeCrypto.SIZE_3XSTORED; protected override int SIZE_PARTY => PokeCrypto.SIZE_3XSTORED; // unused - public override PKM BlankPKM => new XK3(); + public override XK3 BlankPKM => new(); public override Type PKMType => typeof(XK3); public override ushort MaxMoveID => Legal.MaxMoveID_3; @@ -324,9 +320,10 @@ public sealed class SAV3XD : SaveFile, IGCSaveFile // Trainer Info public override GameVersion Version { get => GameVersion.XD; protected set { } } - public override string OT { get => GetString(Trainer1 + 0x00, 20); set => SetString(Data.AsSpan(Trainer1 + 0x00, 20), value.AsSpan(), 10, StringConverterOption.ClearZero); } - public override int SID { get => ReadUInt16BigEndian(Data.AsSpan(Trainer1 + 0x2C)); set => WriteUInt16BigEndian(Data.AsSpan(Trainer1 + 0x2C), (ushort)value); } - public override int TID { get => ReadUInt16BigEndian(Data.AsSpan(Trainer1 + 0x2E)); set => WriteUInt16BigEndian(Data.AsSpan(Trainer1 + 0x2E), (ushort)value); } + public override string OT { get => GetString(Trainer1 + 0x00, 20); set => SetString(Data.AsSpan(Trainer1 + 0x00, 20), value, 10, StringConverterOption.ClearZero); } + public override uint ID32 { get => ReadUInt32BigEndian(Data.AsSpan(Trainer1 + 0x2C)); set => WriteUInt32BigEndian(Data.AsSpan(Trainer1 + 0x2C), value); } + public override ushort SID16 { get => ReadUInt16BigEndian(Data.AsSpan(Trainer1 + 0x2C)); set => WriteUInt16BigEndian(Data.AsSpan(Trainer1 + 0x2C), value); } + public override ushort TID16 { get => ReadUInt16BigEndian(Data.AsSpan(Trainer1 + 0x2E)); set => WriteUInt16BigEndian(Data.AsSpan(Trainer1 + 0x2E), value); } public override int Gender { get => Data[Trainer1 + 0x8E0]; set => Data[Trainer1 + 0x8E0] = (byte)value; } public override uint Money { get => ReadUInt32BigEndian(Data.AsSpan(Trainer1 + 0x8E4)); set => WriteUInt32BigEndian(Data.AsSpan(Trainer1 + 0x8E4), value); } @@ -338,22 +335,22 @@ public sealed class SAV3XD : SaveFile, IGCSaveFile public override int GetBoxOffset(int box) => GetBoxInfoOffset(box) + 20; public override string GetBoxName(int box) => GetString(GetBoxInfoOffset(box), 16); - public override void SetBoxName(int box, string value) + public override void SetBoxName(int box, ReadOnlySpan value) { - SetString(Data.AsSpan(GetBoxInfoOffset(box), 20), value.AsSpan(), 8, StringConverterOption.ClearZero); + SetString(Data.AsSpan(GetBoxInfoOffset(box), 20), value, 8, StringConverterOption.ClearZero); } - protected override PKM GetPKM(byte[] data) + protected override XK3 GetPKM(byte[] data) { if (data.Length != SIZE_STORED) Array.Resize(ref data, SIZE_STORED); - return new XK3(data); + return new(data); } protected override byte[] DecryptPKM(byte[] data) => data; - public override PKM GetPartySlot(byte[] data, int offset) => GetStoredSlot(data, offset); + public override XK3 GetPartySlot(byte[] data, int offset) => GetStoredSlot(data, offset); - public override PKM GetStoredSlot(byte[] data, int offset) + public override XK3 GetStoredSlot(byte[] data, int offset) { // Get Shadow Data var pk = (XK3)base.GetStoredSlot(data, offset); @@ -400,10 +397,10 @@ public sealed class SAV3XD : SaveFile, IGCSaveFile { entry.Species = pk.Species; entry.PID = pk.PID; - entry.TID = pk.TID; - entry.SID = pk.SID; + entry.TID16 = pk.TID16; + entry.SID16 = pk.SID16; } - if (entry.Matches(pk.Species, pk.PID, pk.TID, pk.SID)) + if (entry.Matches(pk.Species, pk.PID, pk.TID16, pk.SID16)) { entry.Seen = true; entry.Owned = true; diff --git a/PKHeX.Core/Saves/SAV4.cs b/PKHeX.Core/Saves/SAV4.cs index bd3310b83..c349251c0 100644 --- a/PKHeX.Core/Saves/SAV4.cs +++ b/PKHeX.Core/Saves/SAV4.cs @@ -53,7 +53,7 @@ public abstract class SAV4 : SaveFile, IEventFlag37 } // Configuration - protected sealed override SaveFile CloneInternal() + protected sealed override SAV4 CloneInternal() { var sav = CloneInternal4(); SetData(sav.General, General, 0); @@ -73,7 +73,7 @@ public abstract class SAV4 : SaveFile, IEventFlag37 protected sealed override int SIZE_STORED => PokeCrypto.SIZE_4STORED; protected sealed override int SIZE_PARTY => PokeCrypto.SIZE_4PARTY; - public sealed override PKM BlankPKM => new PK4(); + public sealed override PK4 BlankPKM => new(); public sealed override Type PKMType => typeof(PK4); public sealed override int BoxCount => 18; @@ -163,19 +163,25 @@ public abstract class SAV4 : SaveFile, IEventFlag37 public override string OT { get => GetString(General.AsSpan(Trainer1, 16)); - set => SetString(General.AsSpan(Trainer1, 16), value.AsSpan(), MaxStringLengthOT, StringConverterOption.ClearZero); + set => SetString(General.AsSpan(Trainer1, 16), value, MaxStringLengthOT, StringConverterOption.ClearZero); } - public override int TID + public override uint ID32 + { + get => ReadUInt32LittleEndian(General.AsSpan(Trainer1 + 0x10)); + set => WriteUInt32LittleEndian(General.AsSpan(Trainer1 + 0x10), value); + } + + public override ushort TID16 { get => ReadUInt16LittleEndian(General.AsSpan(Trainer1 + 0x10)); - set => WriteUInt16LittleEndian(General.AsSpan(Trainer1 + 0x10), (ushort)value); + set => WriteUInt16LittleEndian(General.AsSpan(Trainer1 + 0x10), value); } - public override int SID + public override ushort SID16 { get => ReadUInt16LittleEndian(General.AsSpan(Trainer1 + 0x12)); - set => WriteUInt16LittleEndian(General.AsSpan(Trainer1 + 0x12), (ushort)value); + set => WriteUInt16LittleEndian(General.AsSpan(Trainer1 + 0x12), value); } public override uint Money @@ -239,7 +245,7 @@ public abstract class SAV4 : SaveFile, IEventFlag37 public string Rival { get => GetString(Rival_Trash); - set => SetString(Rival_Trash, value.AsSpan(), MaxStringLengthOT, StringConverterOption.ClearZero); + set => SetString(Rival_Trash, value, MaxStringLengthOT, StringConverterOption.ClearZero); } public abstract Span Rival_Trash { get; set; } @@ -251,7 +257,7 @@ public abstract class SAV4 : SaveFile, IEventFlag37 public override uint SecondsToStart { get => ReadUInt32LittleEndian(General.AsSpan(AdventureInfo + 0x34)); set => WriteUInt32LittleEndian(General.AsSpan(AdventureInfo + 0x34), value); } public override uint SecondsToFame { get => ReadUInt32LittleEndian(General.AsSpan(AdventureInfo + 0x3C)); set => WriteUInt32LittleEndian(General.AsSpan(AdventureInfo + 0x3C), value); } - protected sealed override PKM GetPKM(byte[] data) => new PK4(data); + protected sealed override PK4 GetPKM(byte[] data) => new(data); protected sealed override byte[] DecryptPKM(byte[] data) => PokeCrypto.DecryptArray45(data); protected sealed override void SetPKM(PKM pk, bool isParty = false) @@ -259,7 +265,7 @@ public abstract class SAV4 : SaveFile, IEventFlag37 var pk4 = (PK4)pk; // Apply to this Save File DateTime Date = DateTime.Now; - if (pk4.Trade(OT, TID, SID, Gender, Date.Day, Date.Month, Date.Year)) + if (pk4.Trade(OT, ID32, Gender, Date.Day, Date.Month, Date.Year)) pk.RefreshChecksum(); } diff --git a/PKHeX.Core/Saves/SAV4BR.cs b/PKHeX.Core/Saves/SAV4BR.cs index eeb0b054a..461ccd0b1 100644 --- a/PKHeX.Core/Saves/SAV4BR.cs +++ b/PKHeX.Core/Saves/SAV4BR.cs @@ -11,7 +11,7 @@ public sealed class SAV4BR : SaveFile { protected internal override string ShortSummary => $"{Version} #{SaveCount:0000}"; public override string Extension => string.Empty; - public override IPersonalTable Personal => PersonalTable.DP; + public override PersonalTable4 Personal => PersonalTable.DP; public override IReadOnlyList HeldItems => Legal.HeldItems_DP; private const int SAVE_COUNT = 4; @@ -71,7 +71,7 @@ public sealed class SAV4BR : SaveFile } // Configuration - protected override SaveFile CloneInternal() => new SAV4BR(Write()); + protected override SAV4BR CloneInternal() => new(Write()); public readonly IReadOnlyList SaveNames = new string[SAVE_COUNT]; @@ -94,7 +94,7 @@ public sealed class SAV4BR : SaveFile protected override int SIZE_STORED => PokeCrypto.SIZE_4STORED; protected override int SIZE_PARTY => PokeCrypto.SIZE_4STORED + 4; - public override PKM BlankPKM => new BK4(); + public override BK4 BlankPKM => new(); public override Type PKMType => typeof(BK4); public override ushort MaxMoveID => 467; @@ -163,11 +163,11 @@ public sealed class SAV4BR : SaveFile return GetString(span); } - private void SetOTName(int slot, string name) + private void SetOTName(int slot, ReadOnlySpan name) { var ofs = 0x390 + (0x6FF00 * slot); var span = Data.AsSpan(ofs, 16); - SetString(span, name.AsSpan(), 7, StringConverterOption.ClearZero); + SetString(span, name, 7, StringConverterOption.ClearZero); } public string CurrentOT { get => GetOTName(_currentSlot); set => SetOTName(_currentSlot, value); } @@ -176,9 +176,9 @@ public sealed class SAV4BR : SaveFile public override int GetPartyOffset(int slot) => Party + (SIZE_PARTY * slot); public override int GetBoxOffset(int box) => Box + (SIZE_STORED * box * 30); - public override int TID + public override ushort TID16 { - get => (Data[(_currentSlot * SIZE_SLOT) + 0x12867] << 8) | Data[(_currentSlot * SIZE_SLOT) + 0x12860]; + get => (ushort)((Data[(_currentSlot * SIZE_SLOT) + 0x12867] << 8) | Data[(_currentSlot * SIZE_SLOT) + 0x12860]); set { Data[(_currentSlot * SIZE_SLOT) + 0x12867] = (byte)(value >> 8); @@ -186,9 +186,9 @@ public sealed class SAV4BR : SaveFile } } - public override int SID + public override ushort SID16 { - get => (Data[(_currentSlot * SIZE_SLOT) + 0x12865] << 8) | Data[(_currentSlot * SIZE_SLOT) + 0x12866]; + get => (ushort)((Data[(_currentSlot * SIZE_SLOT) + 0x12865] << 8) | Data[(_currentSlot * SIZE_SLOT) + 0x12866]); set { Data[(_currentSlot * SIZE_SLOT) + 0x12865] = (byte)(value >> 8); @@ -212,7 +212,7 @@ public sealed class SAV4BR : SaveFile return GetString(ofs, BoxNameLength); } - public override void SetBoxName(int box, string value) + public override void SetBoxName(int box, ReadOnlySpan value) { if (BoxName < 0) return; @@ -222,10 +222,10 @@ public sealed class SAV4BR : SaveFile if (ReadUInt16BigEndian(span) == 0) return; - SetString(span, value.AsSpan(), BoxNameLength / 2, StringConverterOption.ClearZero); + SetString(span, value, BoxNameLength / 2, StringConverterOption.ClearZero); } - protected override PKM GetPKM(byte[] data) + protected override BK4 GetPKM(byte[] data) { if (data.Length != SIZE_STORED) Array.Resize(ref data, SIZE_STORED); @@ -241,7 +241,7 @@ public sealed class SAV4BR : SaveFile var pk4 = (BK4)pk; // Apply to this Save File DateTime Date = DateTime.Now; - if (pk4.Trade(OT, TID, SID, Gender, Date.Day, Date.Month, Date.Year)) + if (pk4.Trade(OT, ID32, Gender, Date.Day, Date.Month, Date.Year)) pk.RefreshChecksum(); } diff --git a/PKHeX.Core/Saves/SAV4DP.cs b/PKHeX.Core/Saves/SAV4DP.cs index 77b7adc92..e687b4e01 100644 --- a/PKHeX.Core/Saves/SAV4DP.cs +++ b/PKHeX.Core/Saves/SAV4DP.cs @@ -24,7 +24,7 @@ public sealed class SAV4DP : SAV4Sinnoh public override Zukan4 Dex { get; } protected override SAV4 CloneInternal4() => State.Exportable ? new SAV4DP((byte[])Data.Clone()) : new SAV4DP(); - public override IPersonalTable Personal => PersonalTable.DP; + public override PersonalTable4 Personal => PersonalTable.DP; public override IReadOnlyList HeldItems => Legal.HeldItems_DP; public override int MaxItemID => Legal.MaxItemID_4_DP; diff --git a/PKHeX.Core/Saves/SAV4HGSS.cs b/PKHeX.Core/Saves/SAV4HGSS.cs index 757f68756..57f0e3121 100644 --- a/PKHeX.Core/Saves/SAV4HGSS.cs +++ b/PKHeX.Core/Saves/SAV4HGSS.cs @@ -25,7 +25,7 @@ public sealed class SAV4HGSS : SAV4 public override Zukan4 Dex { get; } protected override SAV4 CloneInternal4() => State.Exportable ? new SAV4HGSS((byte[])Data.Clone()) : new SAV4HGSS(); - public override IPersonalTable Personal => PersonalTable.HGSS; + public override PersonalTable4 Personal => PersonalTable.HGSS; public override IReadOnlyList HeldItems => Legal.HeldItems_HGSS; public override int MaxItemID => Legal.MaxItemID_4_HGSS; private const int GeneralSize = 0xF628; @@ -109,11 +109,11 @@ public sealed class SAV4HGSS : SAV4 public override string GetBoxName(int box) => GetString(Storage.AsSpan(GetBoxNameOffset(box), BOX_NAME_LEN)); - public override void SetBoxName(int box, string value) + public override void SetBoxName(int box, ReadOnlySpan value) { const int maxlen = 8; var span = Storage.AsSpan(GetBoxNameOffset(box), BOX_NAME_LEN); - SetString(span, value.AsSpan(), maxlen, StringConverterOption.ClearZero); + SetString(span, value, maxlen, StringConverterOption.ClearZero); } private static int AdjustWallpaper(int value, int shift) @@ -244,8 +244,8 @@ public sealed class SAV4HGSS : SAV4 public uint PokewalkerSteps { get => ReadUInt32LittleEndian(General.AsSpan(OFS_WALKER)); set => WriteUInt32LittleEndian(General.AsSpan(OFS_WALKER), value); } public uint PokewalkerWatts { get => ReadUInt32LittleEndian(General.AsSpan(OFS_WALKER + 0x4)); set => WriteUInt32LittleEndian(General.AsSpan(OFS_WALKER + 4), value); } - public bool[] GetPokewalkerCoursesUnlocked() => ArrayUtil.GitBitFlagArray(General.AsSpan(OFS_WALKER + 0x8), 32); - public void SetPokewalkerCoursesUnlocked(ReadOnlySpan value) => ArrayUtil.SetBitFlagArray(General.AsSpan(OFS_WALKER + 0x8), value); + public bool[] GetPokewalkerCoursesUnlocked() => FlagUtil.GitBitFlagArray(General.AsSpan(OFS_WALKER + 0x8), 32); + public void SetPokewalkerCoursesUnlocked(ReadOnlySpan value) => FlagUtil.SetBitFlagArray(General.AsSpan(OFS_WALKER + 0x8), value); public void PokewalkerCoursesSetAll(uint value = 0x07FF_FFFFu) => WriteUInt32LittleEndian(General.AsSpan(OFS_WALKER + 0x8), value); diff --git a/PKHeX.Core/Saves/SAV4Pt.cs b/PKHeX.Core/Saves/SAV4Pt.cs index ef1d519db..25a4184a6 100644 --- a/PKHeX.Core/Saves/SAV4Pt.cs +++ b/PKHeX.Core/Saves/SAV4Pt.cs @@ -23,7 +23,7 @@ public sealed class SAV4Pt : SAV4Sinnoh public override Zukan4 Dex { get; } protected override SAV4 CloneInternal4() => State.Exportable ? new SAV4Pt((byte[])Data.Clone()) : new SAV4Pt(); - public override IPersonalTable Personal => PersonalTable.Pt; + public override PersonalTable4 Personal => PersonalTable.Pt; public override IReadOnlyList HeldItems => Legal.HeldItems_Pt; public override int MaxItemID => Legal.MaxItemID_4_Pt; diff --git a/PKHeX.Core/Saves/SAV4Sinnoh.cs b/PKHeX.Core/Saves/SAV4Sinnoh.cs index 047bf7eba..01d3c5b4c 100644 --- a/PKHeX.Core/Saves/SAV4Sinnoh.cs +++ b/PKHeX.Core/Saves/SAV4Sinnoh.cs @@ -45,11 +45,11 @@ public abstract class SAV4Sinnoh : SAV4 public override string GetBoxName(int box) => GetString(Storage.AsSpan(GetBoxNameOffset(box), BOX_NAME_LEN)); - public override void SetBoxName(int box, string value) + public override void SetBoxName(int box, ReadOnlySpan value) { const int maxlen = 8; var span = Storage.AsSpan(GetBoxNameOffset(box), BOX_NAME_LEN); - SetString(span, value.AsSpan(), maxlen, StringConverterOption.ClearZero); + SetString(span, value, maxlen, StringConverterOption.ClearZero); } #endregion @@ -127,9 +127,9 @@ public abstract class SAV4Sinnoh : SAV4 SetData(General, tree.Data, OFS_HONEY + (HONEY_SIZE * index)); } - public MunchlaxTreeSet4 GetMunchlaxTrees() => CalculateMunchlaxTrees(TID, SID); + public MunchlaxTreeSet4 GetMunchlaxTrees() => CalculateMunchlaxTrees(TID16, SID16); - public static MunchlaxTreeSet4 CalculateMunchlaxTrees(int tid, int sid) + public static MunchlaxTreeSet4 CalculateMunchlaxTrees(ushort tid, ushort sid) { int A = (tid >> 8) % 21; int B = (tid & 0x00FF) % 21; diff --git a/PKHeX.Core/Saves/SAV5.cs b/PKHeX.Core/Saves/SAV5.cs index b758cb127..58d181b81 100644 --- a/PKHeX.Core/Saves/SAV5.cs +++ b/PKHeX.Core/Saves/SAV5.cs @@ -9,7 +9,7 @@ namespace PKHeX.Core; /// public abstract class SAV5 : SaveFile, ISaveBlock5BW, IEventFlag37 { - protected override PKM GetPKM(byte[] data) => new PK5(data); + protected override PK5 GetPKM(byte[] data) => new(data); protected override byte[] DecryptPKM(byte[] data) => PokeCrypto.DecryptArray45(data); protected internal override string ShortSummary => $"{OT} ({(GameVersion)Game}) - {PlayTimeString}"; @@ -18,7 +18,7 @@ public abstract class SAV5 : SaveFile, ISaveBlock5BW, IEventFlag37 public override IReadOnlyList HeldItems => Legal.HeldItems_BW; protected override int SIZE_STORED => PokeCrypto.SIZE_5STORED; protected override int SIZE_PARTY => PokeCrypto.SIZE_5PARTY; - public override PKM BlankPKM => new PK5(); + public override PK5 BlankPKM => new(); public override Type PKMType => typeof(PK5); public override int BoxCount => 24; @@ -99,7 +99,7 @@ public abstract class SAV5 : SaveFile, ISaveBlock5BW, IEventFlag37 public override int GetBoxWallpaper(int box) => BoxLayout.GetBoxWallpaper(box); public override void SetBoxWallpaper(int box, int value) => BoxLayout.SetBoxWallpaper(box, value); public override string GetBoxName(int box) => BoxLayout[box]; - public override void SetBoxName(int box, string value) => BoxLayout[box] = value; + public override void SetBoxName(int box, ReadOnlySpan value) => BoxLayout.SetBoxName(box, value); public override int CurrentBox { get => BoxLayout.CurrentBox; set => BoxLayout.CurrentBox = value; } protected int BattleBoxOffset; @@ -115,14 +115,15 @@ public abstract class SAV5 : SaveFile, ISaveBlock5BW, IEventFlag37 var pk5 = (PK5)pk; // Apply to this Save File DateTime Date = DateTime.Now; - if (pk5.Trade(OT, TID, SID, Gender, Date.Day, Date.Month, Date.Year)) + if (pk5.Trade(OT, ID32, Gender, Date.Day, Date.Month, Date.Year)) pk.RefreshChecksum(); } // Player Data public override string OT { get => PlayerData.OT; set => PlayerData.OT = value; } - public override int TID { get => PlayerData.TID; set => PlayerData.TID = value; } - public override int SID { get => PlayerData.SID; set => PlayerData.SID = value; } + public override uint ID32 { get => PlayerData.ID32; set => PlayerData.ID32 = value; } + public override ushort TID16 { get => PlayerData.TID16; set => PlayerData.TID16 = value; } + public override ushort SID16 { get => PlayerData.SID16; set => PlayerData.SID16 = value; } public override int Language { get => PlayerData.Language; set => PlayerData.Language = value; } public override int Game { get => PlayerData.Game; set => PlayerData.Game = value; } public override int Gender { get => PlayerData.Gender; set => PlayerData.Gender = value; } diff --git a/PKHeX.Core/Saves/SAV5B2W2.cs b/PKHeX.Core/Saves/SAV5B2W2.cs index cf5a8be5c..d513eb530 100644 --- a/PKHeX.Core/Saves/SAV5B2W2.cs +++ b/PKHeX.Core/Saves/SAV5B2W2.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; namespace PKHeX.Core; @@ -21,9 +21,9 @@ public sealed class SAV5B2W2 : SAV5, ISaveBlock5B2W2 Initialize(); } - public override IPersonalTable Personal => PersonalTable.B2W2; + public override PersonalTable5B2W2 Personal => PersonalTable.B2W2; public SaveBlockAccessor5B2W2 Blocks { get; } - protected override SaveFile CloneInternal() => new SAV5B2W2((byte[]) Data.Clone()); + protected override SAV5B2W2 CloneInternal() => new((byte[]) Data.Clone()); public override int EventWorkCount => 0x1AF; // this doesn't seem right? public override int EventFlagCount => 0xBF8; protected override int EventWorkOffset => 0x1FF00; @@ -61,7 +61,7 @@ public sealed class SAV5B2W2 : SAV5, ISaveBlock5B2W2 public string Rival { get => GetString(Rival_Trash); - set => SetString(Rival_Trash, value.AsSpan(), MaxStringLengthOT, StringConverterOption.ClearZero); + set => SetString(Rival_Trash, value, MaxStringLengthOT, StringConverterOption.ClearZero); } public Span Rival_Trash diff --git a/PKHeX.Core/Saves/SAV5BW.cs b/PKHeX.Core/Saves/SAV5BW.cs index b97e7005b..a67a8a2bc 100644 --- a/PKHeX.Core/Saves/SAV5BW.cs +++ b/PKHeX.Core/Saves/SAV5BW.cs @@ -1,4 +1,4 @@ -using System.Collections.Generic; +using System.Collections.Generic; namespace PKHeX.Core; @@ -20,9 +20,9 @@ public sealed class SAV5BW : SAV5 Initialize(); } - public override IPersonalTable Personal => PersonalTable.BW; + public override PersonalTable5BW Personal => PersonalTable.BW; public SaveBlockAccessor5BW Blocks { get; } - protected override SaveFile CloneInternal() => new SAV5BW((byte[])Data.Clone()); + protected override SAV5BW CloneInternal() => new((byte[])Data.Clone()); public override int EventWorkCount => 0x13E; public override int EventFlagCount => 0xB60; protected override int EventWorkOffset => 0x20100; diff --git a/PKHeX.Core/Saves/SAV6.cs b/PKHeX.Core/Saves/SAV6.cs index 1d976c441..6eed01de9 100644 --- a/PKHeX.Core/Saves/SAV6.cs +++ b/PKHeX.Core/Saves/SAV6.cs @@ -19,7 +19,7 @@ public abstract class SAV6 : SAV_BEEF, ITrainerStatRecord, ISaveBlock6Core, IReg // Configuration protected override int SIZE_STORED => PokeCrypto.SIZE_6STORED; protected override int SIZE_PARTY => PokeCrypto.SIZE_6PARTY; - public override PKM BlankPKM => new PK6(); + public override PK6 BlankPKM => new(); public override Type PKMType => typeof(PK6); public override int BoxCount => 31; @@ -39,7 +39,7 @@ public abstract class SAV6 : SAV_BEEF, ITrainerStatRecord, ISaveBlock6Core, IReg public override int MaxBallID => Legal.MaxBallID_6; public override int MaxGameID => Legal.MaxGameID_6; // OR - protected override PKM GetPKM(byte[] data) => new PK6(data); + protected override PK6 GetPKM(byte[] data) => new(data); protected override byte[] DecryptPKM(byte[] data) => PokeCrypto.DecryptArray6(data); protected int WondercardFlags { get; set; } = int.MinValue; @@ -58,8 +58,9 @@ public abstract class SAV6 : SAV_BEEF, ITrainerStatRecord, ISaveBlock6Core, IReg protected internal const int ShortStringLength = 0x1A; // bytes, not characters // Player Information - public override int TID { get => Status.TID; set => Status.TID = value; } - public override int SID { get => Status.SID; set => Status.SID = value; } + public override uint ID32 { get => Status.ID32; set => Status.ID32 = value; } + public override ushort TID16 { get => Status.TID16; set => Status.TID16 = value; } + public override ushort SID16 { get => Status.SID16; set => Status.SID16 = value; } public override int Game { get => Status.Game; set => Status.Game = value; } public override int Gender { get => Status.Gender; set => Status.Gender = value; } public override int Language { get => Status.Language; set => Status.Language = value; } @@ -99,10 +100,10 @@ public abstract class SAV6 : SAV_BEEF, ITrainerStatRecord, ISaveBlock6Core, IReg return GetString(Data.AsSpan(GetBoxNameOffset(box), LongStringLength)); } - public override void SetBoxName(int box, string value) + public override void SetBoxName(int box, ReadOnlySpan value) { var span = Data.AsSpan(GetBoxNameOffset(box), LongStringLength); - SetString(span, value.AsSpan(), LongStringLength / 2, StringConverterOption.ClearZero); + SetString(span, value, LongStringLength / 2, StringConverterOption.ClearZero); } protected override void SetPKM(PKM pk, bool isParty = false) diff --git a/PKHeX.Core/Saves/SAV6AO.cs b/PKHeX.Core/Saves/SAV6AO.cs index b7cabff1b..be9698bff 100644 --- a/PKHeX.Core/Saves/SAV6AO.cs +++ b/PKHeX.Core/Saves/SAV6AO.cs @@ -23,10 +23,10 @@ public sealed class SAV6AO : SAV6, ISaveBlock6AO, IMultiplayerSprite ClearBoxes(); } - public override IPersonalTable Personal => PersonalTable.AO; + public override PersonalTable6AO Personal => PersonalTable.AO; public override IReadOnlyList HeldItems => Legal.HeldItem_AO; public SaveBlockAccessor6AO Blocks { get; } - protected override SaveFile CloneInternal() => new SAV6AO((byte[])Data.Clone()); + protected override SAV6AO CloneInternal() => new((byte[])Data.Clone()); public override ushort MaxMoveID => Legal.MaxMoveID_6_AO; public override int MaxItemID => Legal.MaxItemID_6_AO; public override int MaxAbilityID => Legal.MaxAbilityID_6_AO; diff --git a/PKHeX.Core/Saves/SAV6AODemo.cs b/PKHeX.Core/Saves/SAV6AODemo.cs index 32530d437..cab844a5b 100644 --- a/PKHeX.Core/Saves/SAV6AODemo.cs +++ b/PKHeX.Core/Saves/SAV6AODemo.cs @@ -20,9 +20,9 @@ public sealed class SAV6AODemo : SAV6 Initialize(); } - public override IPersonalTable Personal => PersonalTable.AO; + public override PersonalTable6AO Personal => PersonalTable.AO; public override IReadOnlyList HeldItems => Legal.HeldItem_AO; - protected override SaveFile CloneInternal() => new SAV6AODemo((byte[])Data.Clone()); + protected override SAV6AODemo CloneInternal() => new((byte[])Data.Clone()); public override ushort MaxMoveID => Legal.MaxMoveID_6_AO; public override int MaxItemID => Legal.MaxItemID_6_AO; public override int MaxAbilityID => Legal.MaxAbilityID_6_AO; diff --git a/PKHeX.Core/Saves/SAV6XY.cs b/PKHeX.Core/Saves/SAV6XY.cs index 1a2df969e..d4c8ee363 100644 --- a/PKHeX.Core/Saves/SAV6XY.cs +++ b/PKHeX.Core/Saves/SAV6XY.cs @@ -23,10 +23,10 @@ public sealed class SAV6XY : SAV6, ISaveBlock6XY, IMultiplayerSprite ClearBoxes(); } - public override IPersonalTable Personal => PersonalTable.XY; + public override PersonalTable6XY Personal => PersonalTable.XY; public override IReadOnlyList HeldItems => Legal.HeldItem_XY; public SaveBlockAccessor6XY Blocks { get; } - protected override SaveFile CloneInternal() => new SAV6XY((byte[])Data.Clone()); + protected override SAV6XY CloneInternal() => new((byte[])Data.Clone()); public override ushort MaxMoveID => Legal.MaxMoveID_6_XY; public override int MaxItemID => Legal.MaxItemID_6_XY; public override int MaxAbilityID => Legal.MaxAbilityID_6_XY; diff --git a/PKHeX.Core/Saves/SAV7.cs b/PKHeX.Core/Saves/SAV7.cs index ed2cb0095..3a6e10473 100644 --- a/PKHeX.Core/Saves/SAV7.cs +++ b/PKHeX.Core/Saves/SAV7.cs @@ -1,6 +1,5 @@ using System; using System.Collections.Generic; -using System.Diagnostics; using static System.Buffers.Binary.BinaryPrimitives; namespace PKHeX.Core; @@ -30,7 +29,7 @@ public abstract class SAV7 : SAV_BEEF, ITrainerStatRecord, ISaveBlock7Main, IReg protected void ReloadBattleTeams() { - var demo = this is SAV7SM && new ReadOnlySpan(Data, BoxLayout.Offset, 0x4C4).IsRangeEmpty(); // up to Battle Box values + var demo = this is SAV7SM && Data.AsSpan(BoxLayout.Offset, 0x4C4).IndexOfAnyExcept(0) == -1; // up to Battle Box values if (demo || !State.Exportable) { BoxLayout.ClearBattleTeams(); @@ -67,7 +66,7 @@ public abstract class SAV7 : SAV_BEEF, ITrainerStatRecord, ISaveBlock7Main, IReg // Configuration protected override int SIZE_STORED => PokeCrypto.SIZE_6STORED; protected override int SIZE_PARTY => PokeCrypto.SIZE_6PARTY; - public override PKM BlankPKM => new PK7(); + public override PK7 BlankPKM => new(); public override Type PKMType => typeof(PK7); public override int BoxCount => 32; @@ -85,7 +84,7 @@ public abstract class SAV7 : SAV_BEEF, ITrainerStatRecord, ISaveBlock7Main, IReg public override int MaxBallID => Legal.MaxBallID_7; // 26 public override int MaxGameID => Legal.MaxGameID_7; - protected override PKM GetPKM(byte[] data) => new PK7(data); + protected override PK7 GetPKM(byte[] data) => new(data); protected override byte[] DecryptPKM(byte[] data) => PokeCrypto.DecryptArray6(data); // Feature Overrides @@ -95,15 +94,19 @@ public abstract class SAV7 : SAV_BEEF, ITrainerStatRecord, ISaveBlock7Main, IReg protected void ClearMemeCrypto() { - new byte[0x80].CopyTo(Data, AllBlocks[MemeCryptoBlock].Offset + 0x100); + // The MemeCrypto block is always zero -- they could have hidden a secret inside it, but they didn't. + Data.AsSpan(AllBlocks[MemeCryptoBlock].Offset + 0x100, MemeCrypto.SaveFileSignatureLength).Clear(); } protected override byte[] GetFinalData() { BoxLayout.SaveBattleTeams(); SetChecksums(); - var result = MemeCrypto.Resign7(Data); - Debug.Assert(result != Data); + + // Applying the MemeCrypto signature will invalidate the checksum for that block. + // This logic is not set up to revert that block after returning, so just return a copy of our data. + var result = (byte[])Data.Clone(); + MemeCrypto.SignInPlace(result); return result; } @@ -124,8 +127,9 @@ public abstract class SAV7 : SAV_BEEF, ITrainerStatRecord, ISaveBlock7Main, IReg } // Player Information - public override int TID { get => MyStatus.TID; set => MyStatus.TID = value; } - public override int SID { get => MyStatus.SID; set => MyStatus.SID = value; } + public override uint ID32 { get => MyStatus.ID32; set => MyStatus.ID32 = value; } + public override ushort TID16 { get => MyStatus.TID16; set => MyStatus.TID16 = value; } + public override ushort SID16 { get => MyStatus.SID16; set => MyStatus.SID16 = value; } public override int Game { get => MyStatus.Game; set => MyStatus.Game = value; } public override int Gender { get => MyStatus.Gender; set => MyStatus.Gender = value; } public int GameSyncIDSize => MyStatus7.GameSyncIDSize; // 64 bits @@ -161,7 +165,7 @@ public abstract class SAV7 : SAV_BEEF, ITrainerStatRecord, ISaveBlock7Main, IReg public override int GetBoxWallpaper(int box) => BoxLayout.GetBoxWallpaper(box); public override void SetBoxWallpaper(int box, int value) => BoxLayout.SetBoxWallpaper(box, value); public override string GetBoxName(int box) => BoxLayout[box]; - public override void SetBoxName(int box, string value) => BoxLayout[box] = value; + public override void SetBoxName(int box, ReadOnlySpan value) => BoxLayout.SetBoxName(box, value); public override int CurrentBox { get => BoxLayout.CurrentBox; set => BoxLayout.CurrentBox = value; } public override int BoxesUnlocked { get => BoxLayout.BoxesUnlocked; set => BoxLayout.BoxesUnlocked = value; } public override byte[] BoxFlags { get => BoxLayout.BoxFlags; set => BoxLayout.BoxFlags = value; } diff --git a/PKHeX.Core/Saves/SAV7SM.cs b/PKHeX.Core/Saves/SAV7SM.cs index cb57fc905..30d5cee01 100644 --- a/PKHeX.Core/Saves/SAV7SM.cs +++ b/PKHeX.Core/Saves/SAV7SM.cs @@ -33,9 +33,9 @@ public sealed class SAV7SM : SAV7, ISaveBlock7SM ReloadBattleTeams(); } - public override IPersonalTable Personal => PersonalTable.SM; + public override PersonalTable7 Personal => PersonalTable.SM; public override IReadOnlyList HeldItems => Legal.HeldItems_SM; - protected override SaveFile CloneInternal() => new SAV7SM((byte[])Data.Clone()); + protected override SAV7SM CloneInternal() => new((byte[])Data.Clone()); #region Blocks public SaveBlockAccessor7SM Blocks { get; } diff --git a/PKHeX.Core/Saves/SAV7USUM.cs b/PKHeX.Core/Saves/SAV7USUM.cs index 34574c8ee..01eb425fb 100644 --- a/PKHeX.Core/Saves/SAV7USUM.cs +++ b/PKHeX.Core/Saves/SAV7USUM.cs @@ -30,9 +30,9 @@ public sealed class SAV7USUM : SAV7, ISaveBlock7USUM ReloadBattleTeams(); } - public override IPersonalTable Personal => PersonalTable.USUM; + public override PersonalTable7 Personal => PersonalTable.USUM; public override IReadOnlyList HeldItems => Legal.HeldItems_USUM; - protected override SaveFile CloneInternal() => new SAV7USUM((byte[])Data.Clone()); + protected override SAV7USUM CloneInternal() => new((byte[])Data.Clone()); public override int EventFlagCount => 4960; public override ushort MaxMoveID => Legal.MaxMoveID_7_USUM; public override ushort MaxSpeciesID => Legal.MaxSpeciesID_7_USUM; diff --git a/PKHeX.Core/Saves/SAV7b.cs b/PKHeX.Core/Saves/SAV7b.cs index cf998a429..667694f3d 100644 --- a/PKHeX.Core/Saves/SAV7b.cs +++ b/PKHeX.Core/Saves/SAV7b.cs @@ -13,16 +13,16 @@ public sealed class SAV7b : SAV_BEEF, ISaveBlock7b, IGameSync, IEventFlagArray public override IReadOnlyList PKMExtensions => EntityFileExtension.Extensions7b; public override Type PKMType => typeof(PB7); - public override PKM BlankPKM => new PB7(); + public override PB7 BlankPKM => new(); protected override int SIZE_STORED => PokeCrypto.SIZE_6PARTY; protected override int SIZE_PARTY => PokeCrypto.SIZE_6PARTY; public override int SIZE_BOXSLOT => PokeCrypto.SIZE_6PARTY; public override byte[] GetDataForBox(PKM pk) => pk.EncryptedPartyData; - public override IPersonalTable Personal => PersonalTable.GG; + public override PersonalTable7GG Personal => PersonalTable.GG; public override IReadOnlyList HeldItems => Legal.HeldItems_GG; - protected override SaveFile CloneInternal() => new SAV7b((byte[])Data.Clone()); + protected override SAV7b CloneInternal() => new((byte[])Data.Clone()); public SaveBlockAccessor7b Blocks { get; } public override IReadOnlyList AllBlocks => Blocks.BlockInfo; @@ -102,7 +102,7 @@ public sealed class SAV7b : SAV_BEEF, ISaveBlock7b, IGameSync, IEventFlagArray public override bool GetCaught(ushort species) => Blocks.Zukan.GetCaught(species); public override bool GetSeen(ushort species) => Blocks.Zukan.GetSeen(species); - protected override PKM GetPKM(byte[] data) => new PB7(data); + protected override PB7 GetPKM(byte[] data) => new(data); protected override byte[] DecryptPKM(byte[] data) => PokeCrypto.DecryptArray6(data); public override int GetBoxOffset(int box) => Box + (box * BoxSlotCount * SIZE_BOXSLOT); protected override IList[] SlotPointers => new[] { Blocks.Storage.PokeListInfo }; @@ -124,7 +124,7 @@ public sealed class SAV7b : SAV_BEEF, ISaveBlock7b, IGameSync, IEventFlagArray } public override string GetBoxName(int box) => $"Box {box + 1}"; - public override void SetBoxName(int box, string value) { } + public override void SetBoxName(int box, ReadOnlySpan value) { } public override string GetString(ReadOnlySpan data) => StringConverter8.GetString(data); @@ -141,8 +141,9 @@ public sealed class SAV7b : SAV_BEEF, ISaveBlock7b, IGameSync, IEventFlagArray }; // Player Information - public override int TID { get => Blocks.Status.TID; set => Blocks.Status.TID = value; } - public override int SID { get => Blocks.Status.SID; set => Blocks.Status.SID = value; } + public override uint ID32 { get => Blocks.Status.ID32; set => Blocks.Status.ID32 = value; } + public override ushort TID16 { get => Blocks.Status.TID16; set => Blocks.Status.TID16 = value; } + public override ushort SID16 { get => Blocks.Status.SID16; set => Blocks.Status.SID16 = value; } public override int Game { get => Blocks.Status.Game; set => Blocks.Status.Game = value; } public override int Gender { get => Blocks.Status.Gender; set => Blocks.Status.Gender = value; } public override int Language { get => Blocks.Status.Language; set => Blocks.Config.Language = Blocks.Status.Language = value; } // stored in multiple places diff --git a/PKHeX.Core/Saves/SAV8BS.cs b/PKHeX.Core/Saves/SAV8BS.cs index f8a0e469a..7b5dd8cbc 100644 --- a/PKHeX.Core/Saves/SAV8BS.cs +++ b/PKHeX.Core/Saves/SAV8BS.cs @@ -102,7 +102,7 @@ public sealed class SAV8BS : SaveFile, ISaveFileRevision, ITrainerStatRecord, IE protected override int SIZE_STORED => PokeCrypto.SIZE_8STORED; protected override int SIZE_PARTY => PokeCrypto.SIZE_8PARTY; public override int SIZE_BOXSLOT => PokeCrypto.SIZE_8PARTY; - public override PKM BlankPKM => new PB8(); + public override PB8 BlankPKM => new(); public override Type PKMType => typeof(PB8); public override int BoxCount => BoxLayout8b.BoxCount; @@ -110,7 +110,7 @@ public sealed class SAV8BS : SaveFile, ISaveFileRevision, ITrainerStatRecord, IE public override int Generation => 8; public override EntityContext Context => EntityContext.Gen8b; - public override IPersonalTable Personal => PersonalTable.BDSP; + public override PersonalTable8BDSP Personal => PersonalTable.BDSP; public override int MaxStringLengthOT => 12; public override int MaxStringLengthNickname => 12; public override ushort MaxMoveID => Legal.MaxMoveID_8b; @@ -132,7 +132,7 @@ public sealed class SAV8BS : SaveFile, ISaveFileRevision, ITrainerStatRecord, IE public string SaveRevisionString => ((Gem8Version)SaveRevision).GetSuffixString(); public override IReadOnlyList HeldItems => Legal.HeldItems_BS; - protected override SaveFile CloneInternal() => new SAV8BS((byte[])(Data.Clone())); + protected override SAV8BS CloneInternal() => new((byte[])(Data.Clone())); protected override byte[] GetFinalData() { @@ -163,35 +163,33 @@ public sealed class SAV8BS : SaveFile, ISaveFileRevision, ITrainerStatRecord, IE #region Checksums - private const int HashOffset = SaveUtil.SIZE_G8BDSP - 0x10; - private Span CurrentHash => Data.AsSpan(SaveUtil.SIZE_G8BDSP - 0x10, 0x10); - - private byte[] ComputeHash() + private const int HashLength = 0x10; + private const int HashOffset = SaveUtil.SIZE_G8BDSP - HashLength; + private Span CurrentHash => Data.AsSpan(HashOffset, HashLength); + private static void ComputeHash(ReadOnlySpan data, Span dest) { - CurrentHash.Clear(); - using var md5 = new MD5CryptoServiceProvider(); - return md5.ComputeHash(Data); + using var h = IncrementalHash.CreateHash(HashAlgorithmName.MD5); + h.AppendData(data[..HashOffset]); + Span zeroes = stackalloc byte[HashLength]; // Hash is zeroed prior to computing over the payload. Treat it as zero. + h.AppendData(zeroes); + h.AppendData(data[(HashOffset + HashLength)..]); + h.TryGetCurrentHash(dest, out _); } - protected override void SetChecksums() => ComputeHash().CopyTo(Data, HashOffset); + protected override void SetChecksums() => ComputeHash(Data, CurrentHash); + public override bool ChecksumsValid => GetIsHashValid(Data, CurrentHash); public override string ChecksumInfo => !ChecksumsValid ? "MD5 Hash Invalid" : string.Empty; - public override bool ChecksumsValid + public static bool GetIsHashValid(ReadOnlySpan data, ReadOnlySpan currentHash) { - get - { - // Cache hash and restore it after computation - var original = CurrentHash.ToArray(); - var newHash = ComputeHash(); - var result = newHash.AsSpan().SequenceEqual(original); - original.AsSpan().CopyTo(CurrentHash); - return result; - } + Span computed = stackalloc byte[HashLength]; + ComputeHash(data, computed); + return computed.SequenceEqual(currentHash); } #endregion - protected override PKM GetPKM(byte[] data) => new PB8(data); + protected override PB8 GetPKM(byte[] data) => new(data); protected override byte[] DecryptPKM(byte[] data) => PokeCrypto.DecryptArray8(data); #region Blocks @@ -255,8 +253,9 @@ public sealed class SAV8BS : SaveFile, ISaveFileRevision, ITrainerStatRecord, IE public void SetEventFlag(int flagNumber, bool value) => FlagWork.SetFlag(flagNumber, value); // Player Information - public override int TID { get => MyStatus.TID; set => MyStatus.TID = value; } - public override int SID { get => MyStatus.SID; set => MyStatus.SID = value; } + public override uint ID32 { get => MyStatus.ID32; set => MyStatus.ID32 = value; } + public override ushort TID16 { get => MyStatus.TID16; set => MyStatus.TID16 = value; } + public override ushort SID16 { get => MyStatus.SID16; set => MyStatus.SID16 = value; } public override int Game { get => MyStatus.Game; set => MyStatus.Game = value; } public override int Gender { get => MyStatus.Male ? 0 : 1; set => MyStatus.Male = value == 0; } public override int Language { get => Config.Language; set => Config.Language = value; } @@ -277,7 +276,7 @@ public sealed class SAV8BS : SaveFile, ISaveFileRevision, ITrainerStatRecord, IE public override int GetBoxWallpaper(int box) => BoxLayout.GetBoxWallpaper(box); public override void SetBoxWallpaper(int box, int value) => BoxLayout.SetBoxWallpaper(box, value); public override string GetBoxName(int box) => BoxLayout[box]; - public override void SetBoxName(int box, string value) => BoxLayout[box] = value; + public override void SetBoxName(int box, ReadOnlySpan value) => BoxLayout.SetBoxName(box, value); public override byte[] GetDataForBox(PKM pk) => pk.EncryptedPartyData; public override int CurrentBox { get => BoxLayout.CurrentBox; set => BoxLayout.CurrentBox = (byte)value; } public override int BoxesUnlocked { get => BoxLayout.BoxesUnlocked; set => BoxLayout.BoxesUnlocked = (byte)value; } @@ -285,7 +284,7 @@ public sealed class SAV8BS : SaveFile, ISaveFileRevision, ITrainerStatRecord, IE public string Rival { get => GetString(0x55F4, 0x1A); - set => SetString(Data.AsSpan(0x55F4, 0x1A), value.AsSpan(), MaxStringLengthOT, StringConverterOption.ClearZero); + set => SetString(Data.AsSpan(0x55F4, 0x1A), value, MaxStringLengthOT, StringConverterOption.ClearZero); } public short ZoneID // map @@ -333,8 +332,8 @@ public sealed class SAV8BS : SaveFile, ISaveFileRevision, ITrainerStatRecord, IE protected set => PartyInfo.PartyCount = value; } - public override PKM GetDecryptedPKM(byte[] data) => GetPKM(DecryptPKM(data)); - public override PKM GetBoxSlot(int offset) => GetDecryptedPKM(GetData(Data, offset, SIZE_PARTY)); // party format in boxes! + public override PB8 GetDecryptedPKM(byte[] data) => GetPKM(DecryptPKM(data)); + public override PB8 GetBoxSlot(int offset) => GetDecryptedPKM(GetData(Data, offset, SIZE_PARTY)); // party format in boxes! public enum TopMenuItemType { diff --git a/PKHeX.Core/Saves/SAV8LA.cs b/PKHeX.Core/Saves/SAV8LA.cs index f96f4c444..8f86952a1 100644 --- a/PKHeX.Core/Saves/SAV8LA.cs +++ b/PKHeX.Core/Saves/SAV8LA.cs @@ -55,10 +55,10 @@ public sealed class SAV8LA : SaveFile, ISaveBlock8LA, ISCBlockArray, ISaveFileRe protected override int SIZE_STORED => PokeCrypto.SIZE_8ASTORED; protected override int SIZE_PARTY => PokeCrypto.SIZE_8APARTY; public override int SIZE_BOXSLOT => PokeCrypto.SIZE_8ASTORED; - protected override PKM GetPKM(byte[] data) => new PA8(data); + protected override PA8 GetPKM(byte[] data) => new(data); protected override byte[] DecryptPKM(byte[] data) => PokeCrypto.DecryptArray8A(data); - public override PKM BlankPKM => new PA8(); + public override PA8 BlankPKM => new(); public override Type PKMType => typeof(PA8); public override int MaxEV => 252; public override int Generation => 8; @@ -69,8 +69,9 @@ public sealed class SAV8LA : SaveFile, ISaveBlock8LA, ISCBlockArray, ISaveFileRe public override bool ChecksumsValid => true; public override string ChecksumInfo => string.Empty; public override int BoxCount => BoxLayout8a.BoxCount; // 32 - public override int TID { get => MyStatus.TID; set => MyStatus.TID = value; } - public override int SID { get => MyStatus.SID; set => MyStatus.SID = value; } + public override uint ID32 { get => MyStatus.ID32; set => MyStatus.ID32 = value; } + public override ushort TID16 { get => MyStatus.TID16; set => MyStatus.TID16 = value; } + public override ushort SID16 { get => MyStatus.SID16; set => MyStatus.SID16 = value; } public override int Game { get => MyStatus.Game; set => MyStatus.Game = value; } public override int Gender { get => MyStatus.Gender; set => MyStatus.Gender = value; } public override int Language { get => MyStatus.Language; set => MyStatus.Language = value; } @@ -85,15 +86,15 @@ public sealed class SAV8LA : SaveFile, ISaveBlock8LA, ISCBlockArray, ISaveFileRe protected override void SetChecksums() { } // None! protected override byte[] GetFinalData() => SwishCrypto.Encrypt(AllBlocks); - public override IPersonalTable Personal => PersonalTable.LA; + public override PersonalTable8LA Personal => PersonalTable.LA; public override IReadOnlyList HeldItems => Legal.HeldItems_LA; - protected override SaveFile CloneInternal() + protected override SAV8LA CloneInternal() { var blockCopy = new SCBlock[AllBlocks.Count]; for (int i = 0; i < AllBlocks.Count; i++) blockCopy[i] = AllBlocks[i].Clone(); - return new SAV8LA(blockCopy); + return new(blockCopy); } public override ushort MaxMoveID => Legal.MaxMoveID_8a; @@ -212,7 +213,7 @@ public sealed class SAV8LA : SaveFile, ISaveBlock8LA, ISCBlockArray, ISaveFileRe public override int GetBoxOffset(int box) => Box + (SIZE_BOXSLOT * box * 30); public override string GetBoxName(int box) => BoxLayout.GetBoxName(box); - public override void SetBoxName(int box, string value) => BoxLayout.SetBoxName(box, value); + public override void SetBoxName(int box, ReadOnlySpan value) => BoxLayout.SetBoxName(box, value); public override int GetBoxWallpaper(int box) { diff --git a/PKHeX.Core/Saves/SAV8SWSH.cs b/PKHeX.Core/Saves/SAV8SWSH.cs index 3d8945d39..a167974b1 100644 --- a/PKHeX.Core/Saves/SAV8SWSH.cs +++ b/PKHeX.Core/Saves/SAV8SWSH.cs @@ -53,7 +53,7 @@ public sealed class SAV8SWSH : SaveFile, ISaveBlock8SWSH, ITrainerStatRecord, IS protected override void SetChecksums() { } // None! protected override byte[] GetFinalData() => SwishCrypto.Encrypt(AllBlocks); - public override IPersonalTable Personal => PersonalTable.SWSH; + public override PersonalTable8SWSH Personal => PersonalTable.SWSH; public override IReadOnlyList HeldItems => Legal.HeldItems_SWSH; #region Blocks @@ -81,12 +81,12 @@ public sealed class SAV8SWSH : SaveFile, ISaveBlock8SWSH, ITrainerStatRecord, IS public TeamIndexes8 TeamIndexes => Blocks.TeamIndexes; #endregion - protected override SaveFile CloneInternal() + protected override SAV8SWSH CloneInternal() { var blockCopy = new SCBlock[AllBlocks.Count]; for (int i = 0; i < AllBlocks.Count; i++) blockCopy[i] = AllBlocks[i].Clone(); - return new SAV8SWSH(blockCopy); + return new(blockCopy); } private ushort m_spec, m_item, m_move, m_abil; @@ -142,7 +142,7 @@ public sealed class SAV8SWSH : SaveFile, ISaveBlock8SWSH, ITrainerStatRecord, IS protected override int SIZE_STORED => PokeCrypto.SIZE_8STORED; protected override int SIZE_PARTY => PokeCrypto.SIZE_8PARTY; public override int SIZE_BOXSLOT => PokeCrypto.SIZE_8PARTY; - public override PKM BlankPKM => new PK8(); + public override PK8 BlankPKM => new(); public override Type PKMType => typeof(PK8); public override int BoxCount => BoxLayout8.BoxCount; @@ -151,7 +151,7 @@ public sealed class SAV8SWSH : SaveFile, ISaveBlock8SWSH, ITrainerStatRecord, IS public override EntityContext Context => EntityContext.Gen8; public override int MaxStringLengthOT => 12; public override int MaxStringLengthNickname => 12; - protected override PKM GetPKM(byte[] data) => new PK8(data); + protected override PK8 GetPKM(byte[] data) => new(data); protected override byte[] DecryptPKM(byte[] data) => PokeCrypto.DecryptArray8(data); public override GameVersion Version => Game switch @@ -166,8 +166,9 @@ public sealed class SAV8SWSH : SaveFile, ISaveBlock8SWSH, ITrainerStatRecord, IS => StringConverter8.SetString(destBuffer, value, maxLength, option); // Player Information - public override int TID { get => MyStatus.TID; set => MyStatus.TID = value; } - public override int SID { get => MyStatus.SID; set => MyStatus.SID = value; } + public override uint ID32 { get => MyStatus.ID32; set => MyStatus.ID32 = value; } + public override ushort TID16 { get => MyStatus.TID16; set => MyStatus.TID16 = value; } + public override ushort SID16 { get => MyStatus.SID16; set => MyStatus.SID16 = value; } public override int Game { get => MyStatus.Game; set => MyStatus.Game = value; } public override int Gender { get => MyStatus.Gender; set => MyStatus.Gender = value; } public override int Language { get => MyStatus.Language; set => MyStatus.Language = value; } @@ -186,7 +187,7 @@ public sealed class SAV8SWSH : SaveFile, ISaveBlock8SWSH, ITrainerStatRecord, IS public override int GetPartyOffset(int slot) => Party + (SIZE_PARTY * slot); public override int GetBoxOffset(int box) => Box + (SIZE_PARTY * box * 30); public override string GetBoxName(int box) => BoxLayout[box]; - public override void SetBoxName(int box, string value) => BoxLayout[box] = value; + public override void SetBoxName(int box, ReadOnlySpan value) => BoxLayout.SetBoxName(box, value); public override byte[] GetDataForBox(PKM pk) => pk.EncryptedPartyData; protected override void SetPKM(PKM pk, bool isParty = false) @@ -247,8 +248,8 @@ public sealed class SAV8SWSH : SaveFile, ISaveBlock8SWSH, ITrainerStatRecord, IS protected override byte[] BoxBuffer => BoxInfo.Data; protected override byte[] PartyBuffer => PartyInfo.Data; - public override PKM GetDecryptedPKM(byte[] data) => GetPKM(DecryptPKM(data)); - public override PKM GetBoxSlot(int offset) => GetDecryptedPKM(GetData(BoxInfo.Data, offset, SIZE_PARTY)); // party format in boxes! + public override PK8 GetDecryptedPKM(byte[] data) => GetPKM(DecryptPKM(data)); + public override PK8 GetBoxSlot(int offset) => GetDecryptedPKM(GetData(BoxInfo.Data, offset, SIZE_PARTY)); // party format in boxes! public int GetRecord(int recordID) => Records.GetRecord(recordID); public void SetRecord(int recordID, int value) => Records.SetRecord(recordID, value); diff --git a/PKHeX.Core/Saves/SAV9SV.cs b/PKHeX.Core/Saves/SAV9SV.cs index ce048bfc9..12932928c 100644 --- a/PKHeX.Core/Saves/SAV9SV.cs +++ b/PKHeX.Core/Saves/SAV9SV.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using static System.Buffers.Binary.BinaryPrimitives; namespace PKHeX.Core; @@ -52,7 +53,7 @@ public sealed class SAV9SV : SaveFile, ISaveBlock9Main, ISCBlockArray, ISaveFile protected override void SetChecksums() { } // None! protected override byte[] GetFinalData() => SwishCrypto.Encrypt(AllBlocks); - public override IPersonalTable Personal => PersonalTable.SV; + public override PersonalTable9SV Personal => PersonalTable.SV; public override IReadOnlyList HeldItems => Legal.HeldItems_SV; #region Blocks @@ -77,12 +78,12 @@ public sealed class SAV9SV : SaveFile, ISaveBlock9Main, ISCBlockArray, ISaveFile public RaidSevenStar9 RaidSevenStar => Blocks.RaidSevenStar; #endregion - protected override SaveFile CloneInternal() + protected override SAV9SV CloneInternal() { var blockCopy = new SCBlock[AllBlocks.Count]; for (int i = 0; i < AllBlocks.Count; i++) blockCopy[i] = AllBlocks[i].Clone(); - return new SAV9SV(blockCopy); + return new(blockCopy); } public override ushort MaxMoveID => Legal.MaxMoveID_9; @@ -110,7 +111,7 @@ public sealed class SAV9SV : SaveFile, ISaveBlock9Main, ISCBlockArray, ISaveFile protected override int SIZE_STORED => PokeCrypto.SIZE_9STORED; protected override int SIZE_PARTY => PokeCrypto.SIZE_9PARTY; public override int SIZE_BOXSLOT => PokeCrypto.SIZE_9PARTY; - public override PKM BlankPKM => new PK9(); + public override PK9 BlankPKM => new(); public override Type PKMType => typeof(PK9); public override int BoxCount => BoxLayout9.BoxCount; @@ -119,7 +120,7 @@ public sealed class SAV9SV : SaveFile, ISaveBlock9Main, ISCBlockArray, ISaveFile public override EntityContext Context => EntityContext.Gen9; public override int MaxStringLengthOT => 12; public override int MaxStringLengthNickname => 12; - protected override PKM GetPKM(byte[] data) => new PK9(data); + protected override PK9 GetPKM(byte[] data) => new(data); protected override byte[] DecryptPKM(byte[] data) => PokeCrypto.DecryptArray9(data); public override GameVersion Version => Game switch @@ -134,8 +135,9 @@ public sealed class SAV9SV : SaveFile, ISaveBlock9Main, ISCBlockArray, ISaveFile => StringConverter8.SetString(destBuffer, value, maxLength, option); // Player Information - public override int TID { get => MyStatus.TID; set => MyStatus.TID = value; } - public override int SID { get => MyStatus.SID; set => MyStatus.SID = value; } + public override uint ID32 { get => MyStatus.ID32; set => MyStatus.ID32 = value; } + public override ushort TID16 { get => MyStatus.TID16; set => MyStatus.TID16 = value; } + public override ushort SID16 { get => MyStatus.SID16; set => MyStatus.SID16 = value; } public override int Game { get => MyStatus.Game; set => MyStatus.Game = value; } public override int Gender { get => MyStatus.Gender; set => MyStatus.Gender = value; } public override int Language { get => MyStatus.Language; set => MyStatus.Language = value; } @@ -154,7 +156,7 @@ public sealed class SAV9SV : SaveFile, ISaveBlock9Main, ISCBlockArray, ISaveFile public override int GetPartyOffset(int slot) => Party + (SIZE_PARTY * slot); public override int GetBoxOffset(int box) => Box + (SIZE_PARTY * box * 30); public override string GetBoxName(int box) => BoxLayout[box]; - public override void SetBoxName(int box, string value) => BoxLayout[box] = value; + public override void SetBoxName(int box, ReadOnlySpan value) => BoxLayout.SetBoxName(box, value); public override byte[] GetDataForBox(PKM pk) => pk.EncryptedPartyData; protected override void SetPKM(PKM pk, bool isParty = false) @@ -217,8 +219,8 @@ public sealed class SAV9SV : SaveFile, ISaveBlock9Main, ISCBlockArray, ISaveFile protected override byte[] BoxBuffer => BoxInfo.Data; protected override byte[] PartyBuffer => PartyInfo.Data; - public override PKM GetDecryptedPKM(byte[] data) => GetPKM(DecryptPKM(data)); - public override PKM GetBoxSlot(int offset) => GetDecryptedPKM(GetData(BoxInfo.Data, offset, SIZE_PARTY)); // party format in boxes! + public override PK9 GetDecryptedPKM(byte[] data) => GetPKM(DecryptPKM(data)); + public override PK9 GetBoxSlot(int offset) => GetDecryptedPKM(GetData(BoxInfo.Data, offset, SIZE_PARTY)); // party format in boxes! //public int GetRecord(int recordID) => Records.GetRecord(recordID); //public void SetRecord(int recordID, int value) => Records.SetRecord(recordID, value); @@ -287,7 +289,7 @@ public sealed class SAV9SV : SaveFile, ISaveBlock9Main, ISCBlockArray, ISaveFile { for (int f = 1; f <= 8; f++) { - var flag = $"FEVT_SUB_{i:000}_KUI_{f:00}_RELEASE".AsSpan(); + var flag = $"FEVT_SUB_{i:000}_KUI_{f:00}_RELEASE"; var hash = (uint)FnvHash.HashFnv1a_64(flag); var block = Accessor.GetBlock(hash); block.ChangeBooleanType(SCTypeCode.Bool2); @@ -310,7 +312,7 @@ public sealed class SAV9SV : SaveFile, ISaveBlock9Main, ISCBlockArray, ISaveFile { for (int i = 1; i <= 171; i++) { - var flag = $"FSYS_UI_WAZA_MACHINE_RELEASE_{i:000}".AsSpan(); + var flag = $"FSYS_UI_WAZA_MACHINE_RELEASE_{i:000}"; var hash = (uint)FnvHash.HashFnv1a_64(flag); var block = Accessor.GetBlock(hash); block.ChangeBooleanType(SCTypeCode.Bool2); diff --git a/PKHeX.Core/Saves/SAV_STADIUM.cs b/PKHeX.Core/Saves/SAV_STADIUM.cs index 1590ba577..4766a8cc5 100644 --- a/PKHeX.Core/Saves/SAV_STADIUM.cs +++ b/PKHeX.Core/Saves/SAV_STADIUM.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Buffers.Binary; using System.Runtime.InteropServices; @@ -49,7 +49,7 @@ public abstract class SAV_STADIUM : SaveFile, ILangDeviantSave protected sealed override byte[] DecryptPKM(byte[] data) => data; public sealed override int GetPartyOffset(int slot) => -1; public override string GetBoxName(int box) => $"Box {box + 1}"; - public sealed override void SetBoxName(int box, string value) { } + public sealed override void SetBoxName(int box, ReadOnlySpan value) { } public sealed override bool ChecksumsValid => GetBoxChecksumsValid(); public sealed override string ChecksumInfo => ChecksumsValid ? "Checksum valid." : "Checksum invalid"; protected abstract void SetBoxChecksum(int box); diff --git a/PKHeX.Core/Saves/SaveFile.cs b/PKHeX.Core/Saves/SaveFile.cs index 44ae13f23..504e6d7f2 100644 --- a/PKHeX.Core/Saves/SaveFile.cs +++ b/PKHeX.Core/Saves/SaveFile.cs @@ -70,8 +70,9 @@ public abstract class SaveFile : ITrainerInfo, IGameValueLimit, IBoxDetailWallpa public byte[] GetData(int offset, int length) => GetData(Data, offset, length); protected static byte[] GetData(byte[] data, int offset, int length) => data.Slice(offset, length); public void SetData(byte[] input, int offset) => SetData(Data, input, offset); + public void SetData(ReadOnlySpan input, int offset) => SetData(Data, input, offset); - public void SetData(Span dest, Span input, int offset) + public void SetData(Span dest, ReadOnlySpan input, int offset) { input.CopyTo(dest[offset..]); State.Edited = true; @@ -141,8 +142,9 @@ public abstract class SaveFile : ITrainerInfo, IGameValueLimit, IBoxDetailWallpa public virtual int Gender { get; set; } public virtual int Language { get => -1; set { } } public virtual int Game { get => (int)GameVersion.Any; set { } } - public virtual int TID { get; set; } - public virtual int SID { get; set; } + public virtual uint ID32 { get; set; } + public virtual ushort TID16 { get; set; } + public virtual ushort SID16 { get; set; } public virtual string OT { get; set; } = "PKHeX"; public virtual int PlayedHours { get; set; } public virtual int PlayedMinutes { get; set; } @@ -152,31 +154,17 @@ public abstract class SaveFile : ITrainerInfo, IGameValueLimit, IBoxDetailWallpa public virtual uint Money { get; set; } public abstract int BoxCount { get; } public virtual int SlotCount => BoxCount * BoxSlotCount; - public int TrainerID7 { get => (int)((uint)(TID | (SID << 16)) % 1000000); set => SetID7(TrainerSID7, value); } - public int TrainerSID7 { get => (int)((uint)(TID | (SID << 16)) / 1000000); set => SetID7(value, TrainerID7); } public virtual int MaxMoney => 9999999; public virtual int MaxCoins => 9999; - public int DisplayTID - { - get => Generation >= 7 ? TrainerID7 : TID; - set { if (Generation >= 7) TrainerID7 = value; else TID = value; } - } + public TrainerIDFormat TrainerIDDisplayFormat => this.GetTrainerIDFormat(); + public uint TrainerTID7 { get => this.GetTrainerTID7(); set => this.SetTrainerTID7(value); } + public uint TrainerSID7 { get => this.GetTrainerSID7(); set => this.SetTrainerSID7(value); } + public uint DisplayTID { get => this.GetDisplayTID(); set => this.SetDisplayTID(value); } + public uint DisplaySID { get => this.GetDisplaySID(); set => this.SetDisplaySID(value); } - public int DisplaySID - { - get => Generation >= 7 ? TrainerSID7 : SID; - set { if (Generation >= 7) TrainerSID7 = value; else SID = value; } - } #endregion - private void SetID7(int sid7, int tid7) - { - var oid = (sid7 * 1_000_000) + (tid7 % 1_000_000); - TID = (ushort)oid; - SID = oid >> 16; - } - #region Party public virtual int PartyCount { get; protected set; } protected int Party { get; set; } = int.MinValue; @@ -524,8 +512,8 @@ public abstract class SaveFile : ITrainerInfo, IGameValueLimit, IBoxDetailWallpa protected virtual IList[] SlotPointers => new[] { TeamSlots }; public virtual StorageSlotSource GetSlotFlags(int index) => StorageSlotSource.None; public StorageSlotSource GetSlotFlags(int box, int slot) => GetSlotFlags((box * BoxSlotCount) + slot); - public bool IsSlotLocked(int box, int slot) => GetSlotFlags(box, slot).HasFlagFast(StorageSlotSource.Locked); - public bool IsSlotLocked(int index) => GetSlotFlags(index).HasFlagFast(StorageSlotSource.Locked); + public bool IsSlotLocked(int box, int slot) => GetSlotFlags(box, slot).HasFlag(StorageSlotSource.Locked); + public bool IsSlotLocked(int index) => GetSlotFlags(index).HasFlag(StorageSlotSource.Locked); public bool IsSlotOverwriteProtected(int box, int slot) => GetSlotFlags(box, slot).IsOverwriteProtected(); public bool IsSlotOverwriteProtected(int index) => GetSlotFlags(index).IsOverwriteProtected(); @@ -569,7 +557,7 @@ public abstract class SaveFile : ITrainerInfo, IGameValueLimit, IBoxDetailWallpa { foreach (int slotIndex in arrays) { - if (!GetSlotFlags(slotIndex).HasFlagFast(StorageSlotSource.Locked)) + if (!GetSlotFlags(slotIndex).HasFlag(StorageSlotSource.Locked)) continue; if (ArrayUtil.WithinRange(slotIndex, BoxStart * BoxSlotCount, (BoxEnd + 1) * BoxSlotCount)) return true; @@ -834,7 +822,7 @@ public abstract class SaveFile : ITrainerInfo, IGameValueLimit, IBoxDetailWallpa public virtual bool HasNamableBoxes => HasBoxWallpapers; public abstract string GetBoxName(int box); - public abstract void SetBoxName(int box, string value); + public abstract void SetBoxName(int box, ReadOnlySpan value); protected virtual int GetBoxWallpaperOffset(int box) => -1; public virtual int GetBoxWallpaper(int box) @@ -942,4 +930,15 @@ public static class StorageUtil return true; } + + public static int FindSlotIndex(this SaveFile sav, Func method, int maxCount) + { + for (int i = 0; i < maxCount; i++) + { + var pk = sav.GetBoxSlotAtIndex(i); + if (method(pk)) + return i; + } + return -1; + } } diff --git a/PKHeX.Core/Saves/SaveFileMetadata.cs b/PKHeX.Core/Saves/SaveFileMetadata.cs index be0ff0a43..c2f92661e 100644 --- a/PKHeX.Core/Saves/SaveFileMetadata.cs +++ b/PKHeX.Core/Saves/SaveFileMetadata.cs @@ -52,9 +52,9 @@ public sealed record SaveFileMetadata(SaveFile SAV) /// Final save file data. public byte[] Finalize(byte[] data, BinaryExportSetting setting) { - if (Footer.Length > 0 && setting.HasFlagFast(BinaryExportSetting.IncludeFooter)) + if (Footer.Length > 0 && setting.HasFlag(BinaryExportSetting.IncludeFooter)) return ArrayUtil.ConcatAll(data, Footer); - if (Header.Length > 0 && setting.HasFlagFast(BinaryExportSetting.IncludeHeader)) + if (Header.Length > 0 && setting.HasFlag(BinaryExportSetting.IncludeHeader)) return ArrayUtil.ConcatAll(Header, data); return data; } diff --git a/PKHeX.Core/Saves/Storage/Bank3.cs b/PKHeX.Core/Saves/Storage/Bank3.cs index af90c6c3a..36c5e8fdf 100644 --- a/PKHeX.Core/Saves/Storage/Bank3.cs +++ b/PKHeX.Core/Saves/Storage/Bank3.cs @@ -9,9 +9,9 @@ public sealed class Bank3 : BulkStorage { public Bank3(byte[] data) : base(data, typeof(PK3), 0) => Version = GameVersion.RS; - public override IPersonalTable Personal => PersonalTable.RS; + public override PersonalTable3 Personal => PersonalTable.RS; public override IReadOnlyList HeldItems => Legal.HeldItems_RS; - protected override SaveFile CloneInternal() => new Bank3((byte[])Data.Clone()); + protected override Bank3 CloneInternal() => new((byte[])Data.Clone()); public override string PlayTimeString => Checksums.CRC16Invert(Data).ToString("X4"); protected internal override string ShortSummary => PlayTimeString; public override string Extension => ".gst"; diff --git a/PKHeX.Core/Saves/Storage/Bank4.cs b/PKHeX.Core/Saves/Storage/Bank4.cs index 991a5d7c1..6d0c8838f 100644 --- a/PKHeX.Core/Saves/Storage/Bank4.cs +++ b/PKHeX.Core/Saves/Storage/Bank4.cs @@ -9,9 +9,9 @@ public sealed class Bank4 : BulkStorage { public Bank4(byte[] data) : base(data, typeof(PK4), 0) => Version = GameVersion.HGSS; - public override IPersonalTable Personal => PersonalTable.HGSS; + public override PersonalTable4 Personal => PersonalTable.HGSS; public override IReadOnlyList HeldItems => Legal.HeldItems_HGSS; - protected override SaveFile CloneInternal() => new Bank4((byte[])Data.Clone()); + protected override Bank4 CloneInternal() => new((byte[])Data.Clone()); public override string PlayTimeString => Checksums.CRC16Invert(Data).ToString("X4"); protected internal override string ShortSummary => PlayTimeString; public override string Extension => ".stk"; diff --git a/PKHeX.Core/Saves/Storage/Bank7.cs b/PKHeX.Core/Saves/Storage/Bank7.cs index 0b126dd18..b0ac33453 100644 --- a/PKHeX.Core/Saves/Storage/Bank7.cs +++ b/PKHeX.Core/Saves/Storage/Bank7.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using static System.Buffers.Binary.BinaryPrimitives; @@ -11,9 +11,9 @@ public sealed class Bank7 : BulkStorage { public Bank7(byte[] data, Type t, int start, int slotsPerBox = 30) : base(data, t, start, slotsPerBox) => Version = GameVersion.USUM; - public override IPersonalTable Personal => PersonalTable.USUM; + public override PersonalTable7 Personal => PersonalTable.USUM; public override IReadOnlyList HeldItems => Legal.HeldItems_SM; - protected override SaveFile CloneInternal() => new Bank7((byte[])Data.Clone(), PKMType, BoxStart, SlotsPerBox); + protected override Bank7 CloneInternal() => new((byte[])Data.Clone(), PKMType, BoxStart, SlotsPerBox); public override string PlayTimeString => $"{Year:00}{Month:00}{Day:00}_{Hours:00}ː{Minutes:00}"; protected internal override string ShortSummary => PlayTimeString; private const int GroupNameSize = 0x20; diff --git a/PKHeX.Core/Saves/Storage/BulkStorage.cs b/PKHeX.Core/Saves/Storage/BulkStorage.cs index 620fa5d64..6544f71f1 100644 --- a/PKHeX.Core/Saves/Storage/BulkStorage.cs +++ b/PKHeX.Core/Saves/Storage/BulkStorage.cs @@ -51,7 +51,7 @@ public abstract class BulkStorage : SaveFile public override int GetBoxOffset(int box) => Box + (box * (SlotsPerBox * SIZE_STORED)); public override string GetBoxName(int box) => $"Box {box + 1:d2}"; - public sealed override void SetBoxName(int box, string value) { } + public sealed override void SetBoxName(int box, ReadOnlySpan value) { } public sealed override int GetPartyOffset(int slot) => int.MinValue; public override string GetString(ReadOnlySpan data) diff --git a/PKHeX.Core/Saves/Storage/SAV4Ranch.cs b/PKHeX.Core/Saves/Storage/SAV4Ranch.cs index 0df4110ef..8b721b866 100644 --- a/PKHeX.Core/Saves/Storage/SAV4Ranch.cs +++ b/PKHeX.Core/Saves/Storage/SAV4Ranch.cs @@ -33,13 +33,13 @@ public sealed class SAV4Ranch : BulkStorage, ISaveFileRevision public int MaxToys => RanchLevel.GetMaxToys(CurrentRanchLevelIndex); public int MaxMiiCount => RanchLevel.GetMaxMiis(CurrentRanchLevelIndex); - public override IPersonalTable Personal => PersonalTable.Pt; + public override PersonalTable4 Personal => PersonalTable.Pt; public override IReadOnlyList HeldItems => Legal.HeldItems_Pt; - protected override SaveFile CloneInternal() => new SAV4Ranch((byte[])Data.Clone()); + protected override SAV4Ranch CloneInternal() => new((byte[])Data.Clone()); protected internal override string ShortSummary => $"{OT} {PlayTimeString}"; public override string Extension => ".bin"; - protected override PKM GetPKM(byte[] data) => new RK4(data); + protected override RK4 GetPKM(byte[] data) => new(data); public override StorageSlotSource GetSlotFlags(int index) => index >= SlotCount ? StorageSlotSource.Locked : StorageSlotSource.None; protected override bool IsSlotSwapProtected(int box, int slot) => IsSlotOverwriteProtected(box, slot); public override bool IsPKMPresent(ReadOnlySpan data) => EntityDetection.IsPresentSAV4Ranch(data); @@ -145,17 +145,19 @@ public sealed class SAV4Ranch : BulkStorage, ISaveFileRevision SetData(Data, mii.Data, offset); } + private const int sha1HashSize = 20; + protected override void SetChecksums() { - // ensure the final data is written if the user screws stuff up - WriteInt32BigEndian(Data.AsSpan(DataEndMarkerOffset), DataEndMarker); - var goodlen = (DataEndMarkerOffset + 4); - Array.Clear(Data, goodlen, Data.Length - goodlen); + var data = Data.AsSpan(); + // ensure the final data is cleared if the user screws stuff up + WriteInt32BigEndian(data[DataEndMarkerOffset..], DataEndMarker); + data[(DataEndMarkerOffset + 4)..].Clear(); // 20 byte SHA checksum at the top of the file, which covers all data that follows. - using var hash = SHA1.Create(); - var result = hash.ComputeHash(Data, 20, Data.Length - 20); - SetData(result, 0); + var hash = data[..sha1HashSize]; + var payload = data[sha1HashSize..]; + SHA1.HashData(payload, hash); } protected override byte[] DecryptPKM(byte[] data) diff --git a/PKHeX.Core/Saves/Storage/StorageSlotSource.cs b/PKHeX.Core/Saves/Storage/StorageSlotSource.cs index 2583af8e1..74a3dccf7 100644 --- a/PKHeX.Core/Saves/Storage/StorageSlotSource.cs +++ b/PKHeX.Core/Saves/Storage/StorageSlotSource.cs @@ -1,4 +1,4 @@ -using System; +using System; namespace PKHeX.Core; @@ -33,8 +33,6 @@ public enum StorageSlotSource public static class StorageSlotSourceExtensions { - public static bool HasFlagFast(this StorageSlotSource value, StorageSlotSource source) => (value & source) != 0; - /// /// Checks to see if the prevents the corresponding slot from being overwritten. /// @@ -42,10 +40,10 @@ public static class StorageSlotSourceExtensions /// True if write protected public static bool IsOverwriteProtected(this StorageSlotSource value) { - if (value.HasFlagFast(StorageSlotSource.Locked)) + if (value.HasFlag(StorageSlotSource.Locked)) return true; - if (value.HasFlagFast(StorageSlotSource.Starter)) + if (value.HasFlag(StorageSlotSource.Starter)) return true; return value.IsBattleTeam() >= 0; @@ -58,17 +56,17 @@ public static class StorageSlotSourceExtensions /// Battle Team ID if valid, -1 otherwise. public static int IsBattleTeam(this StorageSlotSource value) { - if (value.HasFlagFast(StorageSlotSource.BattleTeam1)) + if (value.HasFlag(StorageSlotSource.BattleTeam1)) return 0; - if (value.HasFlagFast(StorageSlotSource.BattleTeam2)) + if (value.HasFlag(StorageSlotSource.BattleTeam2)) return 1; - if (value.HasFlagFast(StorageSlotSource.BattleTeam3)) + if (value.HasFlag(StorageSlotSource.BattleTeam3)) return 2; - if (value.HasFlagFast(StorageSlotSource.BattleTeam4)) + if (value.HasFlag(StorageSlotSource.BattleTeam4)) return 3; - if (value.HasFlagFast(StorageSlotSource.BattleTeam5)) + if (value.HasFlag(StorageSlotSource.BattleTeam5)) return 4; - if (value.HasFlagFast(StorageSlotSource.BattleTeam6)) + if (value.HasFlag(StorageSlotSource.BattleTeam6)) return 5; return -1; @@ -81,17 +79,17 @@ public static class StorageSlotSourceExtensions /// [0,5] if valid, -1 otherwise. public static int IsParty(this StorageSlotSource value) { - if (value.HasFlagFast(StorageSlotSource.Party1)) + if (value.HasFlag(StorageSlotSource.Party1)) return 0; - if (value.HasFlagFast(StorageSlotSource.Party2)) + if (value.HasFlag(StorageSlotSource.Party2)) return 1; - if (value.HasFlagFast(StorageSlotSource.Party3)) + if (value.HasFlag(StorageSlotSource.Party3)) return 2; - if (value.HasFlagFast(StorageSlotSource.Party4)) + if (value.HasFlag(StorageSlotSource.Party4)) return 3; - if (value.HasFlagFast(StorageSlotSource.Party5)) + if (value.HasFlag(StorageSlotSource.Party5)) return 4; - if (value.HasFlagFast(StorageSlotSource.Party6)) + if (value.HasFlag(StorageSlotSource.Party6)) return 5; return -1; diff --git a/PKHeX.Core/Saves/Substructures/Battle Videos/BV3.cs b/PKHeX.Core/Saves/Substructures/Battle Videos/BV3.cs index 4369d8af4..fad8ea1dc 100644 --- a/PKHeX.Core/Saves/Substructures/Battle Videos/BV3.cs +++ b/PKHeX.Core/Saves/Substructures/Battle Videos/BV3.cs @@ -10,7 +10,7 @@ public sealed class BV3 : BattleVideo internal const int SIZE = 0xF80; public override int Generation => 3; - public override IReadOnlyList BattlePKMs => PlayerTeams.SelectMany(z => z).ToArray(); + public override IReadOnlyList BattlePKMs => PlayerTeams.SelectMany(z => z).ToArray(); public readonly byte[] Data; @@ -18,10 +18,13 @@ public sealed class BV3 : BattleVideo { if (data.Length != SIZE) return false; - var chk = ReadUInt32LittleEndian(data[(SIZE-4)..]); + var chkSpan = data[^4..]; + var chk = ReadUInt32LittleEndian(chkSpan); if (chk > 0xF7080) return false; // max if all are FF - var expect = GetChecksum8(data); + + var chkRegion = data[..^4]; + var expect = GetByteSum(chkRegion); return chk == expect; } @@ -93,13 +96,13 @@ public sealed class BV3 : BattleVideo set => WriteUInt32LittleEndian(Data.AsSpan(SIZE - 4), value); } - public bool IsChecksumValid() => Checksum == GetChecksum8(Data); + public bool IsChecksumValid() => Checksum == GetByteSum(Data.AsSpan()[..^4]); - public static uint GetChecksum8(ReadOnlySpan data) + public static uint GetByteSum(ReadOnlySpan data) { uint result = 0; - for (int i = 0; i < data.Length - 4; i++) - result += data[i]; + foreach (byte b in data) + result += b; return result; } } diff --git a/PKHeX.Core/Saves/Substructures/Battle Videos/BV6.cs b/PKHeX.Core/Saves/Substructures/Battle Videos/BV6.cs index 850eb9d4d..21afbe1b9 100644 --- a/PKHeX.Core/Saves/Substructures/Battle Videos/BV6.cs +++ b/PKHeX.Core/Saves/Substructures/Battle Videos/BV6.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using System.Linq; using static System.Buffers.Binary.BinaryPrimitives; @@ -13,7 +13,7 @@ public sealed class BV6 : BattleVideo private readonly byte[] Data; private const int PlayerCount = 4; - public override IReadOnlyList BattlePKMs => PlayerTeams.SelectMany(t => t).ToArray(); + public override IReadOnlyList BattlePKMs => PlayerTeams.SelectMany(t => t).ToArray(); public override int Generation => 6; internal new static bool IsValid(ReadOnlySpan data) @@ -30,13 +30,13 @@ public sealed class BV6 : BattleVideo public string Debug1 { get => StringConverter6.GetString(Data.AsSpan(0x6, 0x1A)); - set => StringConverter6.SetString(Data.AsSpan(0x6, 0x1A), value.AsSpan(), 12, StringConverterOption.ClearZero); + set => StringConverter6.SetString(Data.AsSpan(0x6, 0x1A), value, 12, StringConverterOption.ClearZero); } public string Debug2 { get => StringConverter6.GetString(Data.AsSpan(0x50, 0x1A)); - set => StringConverter6.SetString(Data.AsSpan(0x50, 0x1A), value.AsSpan(), 12, StringConverterOption.ClearZero); + set => StringConverter6.SetString(Data.AsSpan(0x50, 0x1A), value, 12, StringConverterOption.ClearZero); } public ulong RNGConst1 { get => ReadUInt64LittleEndian(Data.AsSpan(0x1A0)); set => WriteUInt64LittleEndian(Data.AsSpan(0x1A0), value); } @@ -70,15 +70,15 @@ public sealed class BV6 : BattleVideo { var span = Data.AsSpan(0xEC + (0x1A * i), 0x1A); string tr = value[i] == NPC ? string.Empty : value[i]; - StringConverter6.SetString(span, tr.AsSpan(), 12, StringConverterOption.ClearZero); + StringConverter6.SetString(span, tr, 12, StringConverterOption.ClearZero); } } - public IReadOnlyList PlayerTeams + public IReadOnlyList PlayerTeams { get { - var Teams = new PKM[PlayerCount][]; + var Teams = new PK6[PlayerCount][]; for (int t = 0; t < PlayerCount; t++) Teams[t] = GetTeam(t); return Teams; @@ -91,9 +91,9 @@ public sealed class BV6 : BattleVideo } } - public PKM[] GetTeam(int t) + public PK6[] GetTeam(int t) { - var team = new PKM[6]; + var team = new PK6[6]; const int start = 0xE18; for (int p = 0; p < 6; p++) { @@ -105,7 +105,7 @@ public sealed class BV6 : BattleVideo return team; } - public void SetTeam(IReadOnlyList team, int t) + public void SetTeam(IReadOnlyList team, int t) { const int start = 0xE18; for (int p = 0; p < 6; p++) diff --git a/PKHeX.Core/Saves/Substructures/Battle Videos/BV7.cs b/PKHeX.Core/Saves/Substructures/Battle Videos/BV7.cs index ba198f2ea..85433c35c 100644 --- a/PKHeX.Core/Saves/Substructures/Battle Videos/BV7.cs +++ b/PKHeX.Core/Saves/Substructures/Battle Videos/BV7.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using System.Linq; using static System.Buffers.Binary.BinaryPrimitives; @@ -14,18 +14,18 @@ public sealed class BV7 : BattleVideo public override int Generation => 7; private readonly byte[] Data; - public override IReadOnlyList BattlePKMs => PlayerTeams.SelectMany(t => t).ToArray(); + public override IReadOnlyList BattlePKMs => PlayerTeams.SelectMany(t => t).ToArray(); internal new static bool IsValid(ReadOnlySpan data) => data.Length == SIZE; public BV7(byte[] data) => Data = (byte[])data.Clone(); private static readonly int[] offsets = { 0xE41, 0x145E, 0x1A7B, 0x2098 }; - public IReadOnlyList PlayerTeams + public IReadOnlyList PlayerTeams { get { - var Teams = new PKM[PlayerCount][]; + var Teams = new PK7[PlayerCount][]; for (int t = 0; t < PlayerCount; t++) Teams[t] = GetTeam(t); return Teams; @@ -37,9 +37,9 @@ public sealed class BV7 : BattleVideo } } - public PKM[] GetTeam(int teamIndex) + public PK7[] GetTeam(int teamIndex) { - var team = new PKM[6]; + var team = new PK7[6]; var ofs = offsets[teamIndex]; for (int p = 0; p < 6; p++) { @@ -50,7 +50,7 @@ public sealed class BV7 : BattleVideo return team; } - public void SetTeam(IReadOnlyList team, int teamIndex) + public void SetTeam(IReadOnlyList team, int teamIndex) { var ofs = offsets[teamIndex]; for (int p = 0; p < 6; p++) @@ -81,7 +81,7 @@ public sealed class BV7 : BattleVideo { string tr = value[i] == NPC ? string.Empty : value[i]; var span = Data.AsSpan(0x12C + +(0x1A * i), 0x1A); - StringConverter7.SetString(span, tr.AsSpan(), 12, 0, StringConverterOption.ClearZero); + StringConverter7.SetString(span, tr, 12, 0, StringConverterOption.ClearZero); } } diff --git a/PKHeX.Core/Saves/Substructures/Battle Videos/BVRequestUtil.cs b/PKHeX.Core/Saves/Substructures/Battle Videos/BVRequestUtil.cs index e9ceec317..42977c474 100644 --- a/PKHeX.Core/Saves/Substructures/Battle Videos/BVRequestUtil.cs +++ b/PKHeX.Core/Saves/Substructures/Battle Videos/BVRequestUtil.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Diagnostics; using static System.Buffers.Binary.BinaryPrimitives; @@ -16,10 +16,10 @@ public static class BVRequestUtil return $"https://ctr-bnda-live.s3.amazonaws.com/10.CTR_BNDA_datastore/ds/1/data/{video_id:D11}-00001"; // Sun datastore } - public static ulong StrToU64(string input, out bool valid) + public static ulong StrToU64(ReadOnlySpan input, out bool valid) { - var chk = Pull(0, 4) >> 4; // first four chars are checksum bits - var result = Pull(4, input.Length); // next 12 chars are the 70 value bits + var chk = Pull(input[..4]) >> 4; // first four chars are checksum bits + var result = Pull(input[4..]); // next 12 chars are the 70 value bits Span temp = stackalloc byte[8]; WriteUInt64LittleEndian(temp, result); @@ -27,12 +27,11 @@ public static class BVRequestUtil valid = chk == actual; return result; - ulong Pull(int start, int count) + static ulong Pull(ReadOnlySpan input) { ulong val = 0; - for (int i = start; i < count; i++) + foreach (char c in input) { - var c = input[i]; if (c == '-') continue; @@ -48,32 +47,32 @@ public static class BVRequestUtil Span temp = stackalloc byte[8]; WriteUInt64LittleEndian(temp, input); uint chk = Checksums.CRC16_CCITT(temp); - var buff = new char[16]; + Span buff = stackalloc char[16]; int ctr = 15; - Push(input, 12); // store value bits - Push(chk << 4, 4); // store checksum bits - return !insertDash ? string.Concat(buff) : GetStringWithDashesEvery(buff, 4); + Push(buff, ref ctr, 12, input); // store value bits + Push(buff, ref ctr, 04, chk << 4); // store checksum bits + return !insertDash ? new string(buff) : GetStringWithDashesEvery(buff, 4); - void Push(ulong v, int count) + static void Push(Span buff, ref int ctr, int bit5Chunks, ulong value) { - for (int i = 0; i < count; i++) + for (int i = 0; i < bit5Chunks; i++) { - buff[ctr--] = Set5BitToChar((char)(v & 0b11111)); - v >>= 5; + buff[ctr--] = Set5BitToChar((char)(value & 0x1F)); + value >>= 5; } } } - private static string GetStringWithDashesEvery(char[] buff, int spacer) + private static string GetStringWithDashesEvery(ReadOnlySpan buff, int spacer) { - var buff2 = new char[buff.Length + ((buff.Length / spacer) - 1)]; + Span buff2 = stackalloc char[buff.Length + ((buff.Length / spacer) - 1)]; for (int i = 0, ctr = 0; i < buff.Length; i++) { buff2[ctr++] = buff[i]; if (i % spacer == 3 && ctr < buff2.Length) buff2[ctr++] = '-'; // add dash between every chunk of size {spacer} } - return string.Concat(buff2); + return new string(buff2); } private static char Set5BitToChar(char c) diff --git a/PKHeX.Core/Saves/Substructures/Gen12/G1OverworldSpawner.cs b/PKHeX.Core/Saves/Substructures/Gen12/G1OverworldSpawner.cs index ccfdbac40..05d2bc450 100644 --- a/PKHeX.Core/Saves/Substructures/Gen12/G1OverworldSpawner.cs +++ b/PKHeX.Core/Saves/Substructures/Gen12/G1OverworldSpawner.cs @@ -1,8 +1,10 @@ -using System.Collections.Generic; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; // ReSharper disable UnusedAutoPropertyAccessor.Local namespace PKHeX.Core; +[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.NonPublicProperties)] public sealed class G1OverworldSpawner { private readonly SAV1 SAV; @@ -51,7 +53,6 @@ public sealed class G1OverworldSpawner } } -#pragma warning disable IDE0052 // Remove unread private members public const string FlagPropertyPrefix = "Flag"; // reflection private FlagPairG1 FlagMewtwo { get; } private FlagPairG1 FlagArticuno { get; } @@ -74,7 +75,6 @@ public sealed class G1OverworldSpawner private FlagPairG1? FlagBulbasaur { get; } private FlagPairG1? FlagSquirtle { get; } private FlagPairG1? FlagCharmander { get; } -#pragma warning restore IDE0052 // Remove unread private members public void Save() { diff --git a/PKHeX.Core/Saves/Substructures/Gen12/SAV1Offsets.cs b/PKHeX.Core/Saves/Substructures/Gen12/SAV1Offsets.cs index 860cf7d20..db7c347d8 100644 --- a/PKHeX.Core/Saves/Substructures/Gen12/SAV1Offsets.cs +++ b/PKHeX.Core/Saves/Substructures/Gen12/SAV1Offsets.cs @@ -14,7 +14,7 @@ internal sealed class SAV1Offsets Rival = 0x25F6, Options = 0x2601, Badges = 0x2602, - TID = 0x2605, + TID16 = 0x2605, PikaFriendship = 0x271C, PikaBeachScore = 0x2741, PrinterBrightness = 0x2744, @@ -40,7 +40,7 @@ internal sealed class SAV1Offsets Rival = 0x25F1, Options = 0x25F7, Badges = 0x25F8, - TID = 0x25FB, + TID16 = 0x25FB, PikaFriendship = 0x2712, PikaBeachScore = 0x2737, PrinterBrightness = 0x273A, @@ -65,7 +65,7 @@ internal sealed class SAV1Offsets public int Rival { get; private init; } public int Options { get; private init; } public int Badges { get; private init; } - public int TID { get; private init; } + public int TID16 { get; private init; } public int PikaFriendship { get; private init; } public int PikaBeachScore { get; private init; } public int PrinterBrightness { get; private init; } diff --git a/PKHeX.Core/Saves/Substructures/Gen3/CXD/ShadowInfoEntryXD.cs b/PKHeX.Core/Saves/Substructures/Gen3/CXD/ShadowInfoEntryXD.cs index 9a7a74e9f..09d83ef40 100644 --- a/PKHeX.Core/Saves/Substructures/Gen3/CXD/ShadowInfoEntryXD.cs +++ b/PKHeX.Core/Saves/Substructures/Gen3/CXD/ShadowInfoEntryXD.cs @@ -21,7 +21,7 @@ public abstract class ShadowInfoEntryXD // Gen3 Species ID public ushort RawSpecies { get => ReadUInt16BigEndian(Data.AsSpan(0x1A)); set => WriteUInt16BigEndian(Data.AsSpan(0x1A), value); } - public ushort Species { get => SpeciesConverter.GetG4Species(RawSpecies); set => RawSpecies = SpeciesConverter.GetG3Species(value); } + public ushort Species { get => SpeciesConverter.GetNational3(RawSpecies); set => RawSpecies = SpeciesConverter.GetInternal3(value); } public uint PID { get => ReadUInt32BigEndian(Data.AsSpan(0x1C)); set => WriteUInt32BigEndian(Data.AsSpan(0x1C), value); } public int Purification { get => ReadInt32BigEndian(Data.AsSpan(0x24)); set => WriteInt32BigEndian(Data.AsSpan(0x24), value); } diff --git a/PKHeX.Core/Saves/Substructures/Gen3/EReaderBerrySettings.cs b/PKHeX.Core/Saves/Substructures/Gen3/EReaderBerrySettings.cs index 4cdb509f3..fdbb64eff 100644 --- a/PKHeX.Core/Saves/Substructures/Gen3/EReaderBerrySettings.cs +++ b/PKHeX.Core/Saves/Substructures/Gen3/EReaderBerrySettings.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using static PKHeX.Core.EReaderBerryMatch; @@ -16,7 +15,7 @@ public static class EReaderBerrySettings private static string Name { get; set; } = string.Empty; /// e-Reader Berry Name formatted in Title Case - public static string DisplayName => string.Format(LegalityCheckStrings.L_XEnigmaBerry_0, Util.ToTitleCase(Name.AsSpan())); + public static string DisplayName => string.Format(LegalityCheckStrings.L_XEnigmaBerry_0, Util.ToTitleCase(Name)); private static int Language { get; set; } diff --git a/PKHeX.Core/Saves/Substructures/Gen3/HallFame3.cs b/PKHeX.Core/Saves/Substructures/Gen3/HallFame3.cs index c2f8eb019..9d8e600bd 100644 --- a/PKHeX.Core/Saves/Substructures/Gen3/HallFame3.cs +++ b/PKHeX.Core/Saves/Substructures/Gen3/HallFame3.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Diagnostics; using static System.Buffers.Binary.BinaryPrimitives; @@ -56,7 +56,7 @@ public sealed class HallFame3Entry } } -public sealed class HallFame3PKM +public sealed class HallFame3PKM : ISpeciesForm { public const int SIZE = 20; @@ -71,14 +71,15 @@ public sealed class HallFame3PKM private readonly int Offset; private readonly bool Japanese; - public int TID { get => ReadUInt16LittleEndian(Data.AsSpan(0 + Offset)); set => WriteUInt16LittleEndian(Data.AsSpan(0 + Offset), (ushort)value); } - public int SID { get => ReadUInt16LittleEndian(Data.AsSpan(2 + Offset)); set => WriteUInt16LittleEndian(Data.AsSpan(2 + Offset), (ushort)value); } + public int TID16 { get => ReadUInt16LittleEndian(Data.AsSpan(0 + Offset)); set => WriteUInt16LittleEndian(Data.AsSpan(0 + Offset), (ushort)value); } + public int SID16 { get => ReadUInt16LittleEndian(Data.AsSpan(2 + Offset)); set => WriteUInt16LittleEndian(Data.AsSpan(2 + Offset), (ushort)value); } public uint PID { get => ReadUInt32LittleEndian(Data.AsSpan(4 + Offset)); set => WriteUInt32LittleEndian(Data.AsSpan(4 + Offset), value); } private int SpecLevel { get => ReadUInt16LittleEndian(Data.AsSpan(8 + Offset)); set => WriteUInt16LittleEndian(Data.AsSpan(8 + Offset), (ushort)value); } private Span Nickname_Trash => Data.AsSpan(10 + Offset, 10); - public string Nickname { get => StringConverter3.GetString(Nickname_Trash, Japanese); set => StringConverter3.SetString(Nickname_Trash, value.AsSpan(), 10, Japanese, StringConverterOption.ClearZero); } + public string Nickname { get => StringConverter3.GetString(Nickname_Trash, Japanese); set => StringConverter3.SetString(Nickname_Trash, value, 10, Japanese, StringConverterOption.ClearZero); } - public int Species { get => SpecLevel & 0x1FF; set => SpecLevel = (SpecLevel & 0xFE00) | value; } + public ushort Species { get => (ushort)(SpecLevel & 0x1FF); set => SpecLevel = (SpecLevel & 0xFE00) | value; } + public byte Form => 0; // no forms; derive Unown's from PID else use the Version for Deoxys. public int Level { get => SpecLevel >> 9; set => SpecLevel = (SpecLevel & 0x1FF) | (value << 9); } } diff --git a/PKHeX.Core/Saves/Substructures/Gen3/PokeBlock3.cs b/PKHeX.Core/Saves/Substructures/Gen3/PokeBlock3.cs index 9f221439a..9f735b518 100644 --- a/PKHeX.Core/Saves/Substructures/Gen3/PokeBlock3.cs +++ b/PKHeX.Core/Saves/Substructures/Gen3/PokeBlock3.cs @@ -27,7 +27,7 @@ public sealed class PokeBlock3 Color = PokeBlock3Color.Gold; } - public void SetBlock(byte[] data, int offset) => Data.CopyTo(data, offset); + public void SetBlock(Span data) => Data.CopyTo(data); public static PokeBlock3 GetBlock(ReadOnlySpan data, int offset) { diff --git a/PKHeX.Core/Saves/Substructures/Gen3/PokeBlock3Case.cs b/PKHeX.Core/Saves/Substructures/Gen3/PokeBlock3Case.cs index 8a6f952f1..95498a2ea 100644 --- a/PKHeX.Core/Saves/Substructures/Gen3/PokeBlock3Case.cs +++ b/PKHeX.Core/Saves/Substructures/Gen3/PokeBlock3Case.cs @@ -18,7 +18,7 @@ public sealed class PokeBlock3Case { byte[] result = new byte[Count*PokeBlock3.SIZE]; for (int i = 0; i < Blocks.Length; i++) - Blocks[i].SetBlock(result, i * PokeBlock3.SIZE); + Blocks[i].SetBlock(result.AsSpan(i * PokeBlock3.SIZE)); return result; } diff --git a/PKHeX.Core/Saves/Substructures/Gen3/Record3.cs b/PKHeX.Core/Saves/Substructures/Gen3/Record3.cs index 7aa12e052..9b4033f6e 100644 --- a/PKHeX.Core/Saves/Substructures/Gen3/Record3.cs +++ b/PKHeX.Core/Saves/Substructures/Gen3/Record3.cs @@ -49,7 +49,7 @@ public sealed class Record3 for (int i = 0; i < result.Length; i++) { var replaced = names[i].Replace('_', ' '); - var titled = Util.ToTitleCase(replaced.AsSpan()); + var titled = Util.ToTitleCase(replaced); result[i] = new ComboItem(titled, values[i]); } return result; diff --git a/PKHeX.Core/Saves/Substructures/Gen3/Roamer3.cs b/PKHeX.Core/Saves/Substructures/Gen3/Roamer3.cs index 31ec9bd11..2b3807419 100644 --- a/PKHeX.Core/Saves/Substructures/Gen3/Roamer3.cs +++ b/PKHeX.Core/Saves/Substructures/Gen3/Roamer3.cs @@ -36,8 +36,8 @@ public sealed class Roamer3 : IContestStats public ushort Species { - get => SpeciesConverter.GetG4Species(ReadUInt16LittleEndian(Data.AsSpan(Offset + 8))); - set => WriteUInt16LittleEndian(Data.AsSpan(Offset + 8), SpeciesConverter.GetG3Species(value)); + get => SpeciesConverter.GetNational3(ReadUInt16LittleEndian(Data.AsSpan(Offset + 8))); + set => WriteUInt16LittleEndian(Data.AsSpan(Offset + 8), SpeciesConverter.GetInternal3(value)); } public int HP_Current @@ -98,7 +98,8 @@ public sealed class Roamer3 : IContestStats /// Indication if the PID is shiny for the trainer. public bool IsShiny(uint pid) { - var xor = (ushort)(SAV.SID ^ SAV.TID ^ (pid >> 16) ^ pid); + var tmp = SAV.ID32 ^ pid; + var xor = (tmp >> 16) ^ (tmp & 0xFFFF); return xor < 8; } diff --git a/PKHeX.Core/Saves/Substructures/Gen3/SecretBase3.cs b/PKHeX.Core/Saves/Substructures/Gen3/SecretBase3.cs index 304fac559..3e8271f02 100644 --- a/PKHeX.Core/Saves/Substructures/Gen3/SecretBase3.cs +++ b/PKHeX.Core/Saves/Substructures/Gen3/SecretBase3.cs @@ -38,7 +38,7 @@ public sealed class SecretBase3 public string OT_Name { get => StringConverter3.GetString(Data.AsSpan(Offset + 2, 7), Japanese); - set => StringConverter3.SetString(Data.AsSpan(Offset + 2, 7), value.AsSpan(), 7, Japanese, StringConverterOption.ClearFF); + set => StringConverter3.SetString(Data.AsSpan(Offset + 2, 7), value, 7, Japanese, StringConverterOption.ClearFF); } public uint OT_ID @@ -59,11 +59,11 @@ public sealed class SecretBase3 public byte TimesEntered { get => Data[Offset + 0x10]; set => Data[Offset + 0x10] = value; } public int Unused11 { get => Data[Offset + 0x11]; set => Data[Offset + 0x11] = (byte)value; } // alignment padding - public byte[] GetDecorations() => Data.Slice(Offset + 0x12, 0x10); - public void SetDecorations(byte[] value) => value.CopyTo(Data, Offset + 0x12); + public Span GetDecorations() => Data.AsSpan(Offset + 0x12, 0x10); + public void SetDecorations(Span value) => value.CopyTo(Data.AsSpan(Offset + 0x12, 0x10)); - public byte[] GetDecorationCoordinates() => Data.Slice(Offset + 0x22, 0x10); - public void SetDecorationCoordinates(byte[] value) => value.CopyTo(Data, Offset + 0x22); + public Span GetDecorationCoordinates() => Data.Slice(Offset + 0x22, 0x10); + public void SetDecorationCoordinates(Span value) => value.CopyTo(Data.AsSpan(Offset + 0x22, 0x10)); public SecretBase3Team Team { @@ -71,15 +71,15 @@ public sealed class SecretBase3 set => value.Write().CopyTo(Data, Offset + 50); } - public int TID + public int TID16 { get => (ushort)OT_ID; - set => OT_ID = (ushort)(SID | (ushort)value); + set => OT_ID = (ushort)(SID16 | (ushort)value); } - public int SID + public int SID16 { get => (ushort)OT_ID >> 8; - set => OT_ID = (ushort)(((ushort)value << 16) | TID); + set => OT_ID = (ushort)(((ushort)value << 16) | TID16); } } diff --git a/PKHeX.Core/Saves/Substructures/Gen3/StrategyMemo.cs b/PKHeX.Core/Saves/Substructures/Gen3/StrategyMemo.cs index 5c6959652..e5c9481d8 100644 --- a/PKHeX.Core/Saves/Substructures/Gen3/StrategyMemo.cs +++ b/PKHeX.Core/Saves/Substructures/Gen3/StrategyMemo.cs @@ -10,31 +10,31 @@ public sealed class StrategyMemo public const int SIZE_ENTRY = 12; private readonly List Entries; public const int MAX_COUNT = 500; - private StrategyMemoEntry? this[int Species] => Entries.Find(e => e.Species == Species); + private StrategyMemoEntry? this[ushort Species] => Entries.Find(e => e.Species == Species); private readonly ushort _unk; - public StrategyMemo(bool xd = true) : this(new byte[4], 0, xd) { } + public StrategyMemo(bool xd = true) : this(stackalloc byte[4], xd) { } - public StrategyMemo(byte[] input, int offset, bool xd) + public StrategyMemo(Span block, bool xd) { XD = xd; - int count = ReadUInt16BigEndian(input.AsSpan(offset)); + int count = ReadUInt16BigEndian(block); if (count > MAX_COUNT) count = MAX_COUNT; - _unk = ReadUInt16BigEndian(input.AsSpan(offset + 2)); + _unk = ReadUInt16BigEndian(block[2..]); Entries = new List(count); for (int i = 0; i < count; i++) { - var entry = Read(input, offset, i); + var entry = Read(block, i); Entries.Add(entry); } } - private StrategyMemoEntry Read(byte[] input, int offset, int index) + private StrategyMemoEntry Read(Span block, int index) { - var ofs = 4 + offset + (SIZE_ENTRY * index); - var span = input.AsSpan(ofs, SIZE_ENTRY); + var ofs = 4 + (SIZE_ENTRY * index); + var span = block.Slice(ofs, SIZE_ENTRY); var data = span.ToArray(); return new StrategyMemoEntry(XD, data); } @@ -51,7 +51,7 @@ public sealed class StrategyMemo return result; } - public StrategyMemoEntry GetEntry(int Species) + public StrategyMemoEntry GetEntry(ushort Species) { return this[Species] ?? new StrategyMemoEntry(XD); } @@ -84,11 +84,11 @@ public sealed class StrategyMemoEntry get { var val = (ushort)(ReadUInt16BigEndian(Data.AsSpan(0)) & 0x1FF); - return SpeciesConverter.GetG4Species(val); + return SpeciesConverter.GetNational3(val); } set { - var val = SpeciesConverter.GetG3Species(value); + var val = SpeciesConverter.GetInternal3(value); var cval = ReadUInt16BigEndian(Data.AsSpan(0)); cval &= 0xE00; val &= 0x1FF; cval |= val; WriteUInt16BigEndian(Data.AsSpan(0x00), cval); @@ -97,8 +97,14 @@ public sealed class StrategyMemoEntry private bool Flag0 { get => Data[0] >> 6 == 1; set { Data[0] &= 0xBF; if (value) Data[0] |= 0x40; } } // Unused private bool Flag1 { get => Data[0] >> 7 == 1; set { Data[0] &= 0x7F; if (value) Data[0] |= 0x80; } } // Complete Entry - public int SID { get => ReadUInt16BigEndian(Data.AsSpan(4)); set => WriteUInt16BigEndian(Data.AsSpan(4), (ushort)value); } - public int TID { get => ReadUInt16BigEndian(Data.AsSpan(6)); set => WriteUInt16BigEndian(Data.AsSpan(6), (ushort)value); } + + public uint ID32 + { + get => ReadUInt32BigEndian(Data.AsSpan(0x04)); + set => WriteUInt32BigEndian(Data.AsSpan(0x04), value); + } + public ushort SID16 { get => ReadUInt16BigEndian(Data.AsSpan(4)); set => WriteUInt16BigEndian(Data.AsSpan(4), value); } + public ushort TID16 { get => ReadUInt16BigEndian(Data.AsSpan(6)); set => WriteUInt16BigEndian(Data.AsSpan(6), value); } public uint PID { get => ReadUInt32BigEndian(Data.AsSpan(8)); set => WriteUInt32BigEndian(Data.AsSpan(8), value); } public bool Seen @@ -136,5 +142,5 @@ public sealed class StrategyMemoEntry } public bool IsEmpty => Species == 0; - public bool Matches(ushort species, uint pid, int tid, int sid) => Species == species && PID == pid && TID == tid && SID == sid; + public bool Matches(ushort species, uint pid, uint id32) => Species == species && PID == pid && ID32 == id32; } diff --git a/PKHeX.Core/Saves/Substructures/Gen3/Swarm3.cs b/PKHeX.Core/Saves/Substructures/Gen3/Swarm3.cs index b1aa8828c..c7e12f0af 100644 --- a/PKHeX.Core/Saves/Substructures/Gen3/Swarm3.cs +++ b/PKHeX.Core/Saves/Substructures/Gen3/Swarm3.cs @@ -32,7 +32,7 @@ public sealed class Swarm3 public Swarm3(Species species, byte level, byte map, Move m1, Move m2 = 0, Move m3 = 0, Move m4 = 0) : this(new byte[SIZE]) { - Gen3Species = SpeciesConverter.GetG3Species((ushort)species); + Gen3Species = SpeciesConverter.GetInternal3((ushort)species); Level = level; MapNum = map; Move1 = (ushort)m1; diff --git a/PKHeX.Core/Saves/Substructures/Gen4/Dendou4.cs b/PKHeX.Core/Saves/Substructures/Gen4/Dendou4.cs index e50984b7f..33a0d2149 100644 --- a/PKHeX.Core/Saves/Substructures/Gen4/Dendou4.cs +++ b/PKHeX.Core/Saves/Substructures/Gen4/Dendou4.cs @@ -1,4 +1,4 @@ -using System; +using System; using static System.Buffers.Binary.BinaryPrimitives; namespace PKHeX.Core; @@ -103,12 +103,12 @@ public readonly ref struct Dendou4Entity public string Nickname { get => StringConverter4.GetString(Nickname_Trash); - set => StringConverter4.SetString(Nickname_Trash, value.AsSpan(), 10, StringConverterOption.None); + set => StringConverter4.SetString(Nickname_Trash, value, 10, StringConverterOption.None); } public string OT_Name { get => StringConverter4.GetString(OT_Trash); - set => StringConverter4.SetString(OT_Trash, value.AsSpan(), 7, StringConverterOption.None); + set => StringConverter4.SetString(OT_Trash, value, 7, StringConverterOption.None); } public ushort Move1 { get => ReadUInt16LittleEndian(Data[0x32..]); set => WriteUInt16LittleEndian(Data[0x32..], value); } diff --git a/PKHeX.Core/Saves/Substructures/Gen4/Hall4.cs b/PKHeX.Core/Saves/Substructures/Gen4/Hall4.cs index 2c3a8d2a7..1192a3b26 100644 --- a/PKHeX.Core/Saves/Substructures/Gen4/Hall4.cs +++ b/PKHeX.Core/Saves/Substructures/Gen4/Hall4.cs @@ -40,7 +40,7 @@ public sealed class Hall4 private static int GetRecordOffset(int battleType, ushort species) { - if ((uint)species > Legal.MaxSpeciesID_4) + if (species > Legal.MaxSpeciesID_4) throw new ArgumentOutOfRangeException(nameof(species)); if ((uint)battleType > 2) throw new ArgumentOutOfRangeException(nameof(battleType)); diff --git a/PKHeX.Core/Saves/Substructures/Gen4/Ranch/RanchMii.cs b/PKHeX.Core/Saves/Substructures/Gen4/Ranch/RanchMii.cs index b4ae3091a..276e89254 100644 --- a/PKHeX.Core/Saves/Substructures/Gen4/Ranch/RanchMii.cs +++ b/PKHeX.Core/Saves/Substructures/Gen4/Ranch/RanchMii.cs @@ -17,6 +17,6 @@ public sealed class RanchMii public string MiiName { get => StringConverter4GC.GetStringUnicode(Name_Trash); - set => StringConverter4GC.SetStringUnicode(value.AsSpan(), Name_Trash, value.Length, StringConverterOption.None); + set => StringConverter4GC.SetStringUnicode(value, Name_Trash, value.Length, StringConverterOption.None); } } diff --git a/PKHeX.Core/Saves/Substructures/Gen4/Ranch/RanchTrainerMii.cs b/PKHeX.Core/Saves/Substructures/Gen4/Ranch/RanchTrainerMii.cs index 0eb3f8497..8b5685f3e 100644 --- a/PKHeX.Core/Saves/Substructures/Gen4/Ranch/RanchTrainerMii.cs +++ b/PKHeX.Core/Saves/Substructures/Gen4/Ranch/RanchTrainerMii.cs @@ -28,6 +28,6 @@ public sealed class RanchTrainerMii public string TrainerName { get => StringConverter4.GetString(Trainer_Trash); - set => StringConverter4.SetString(Trainer_Trash, value.AsSpan(), 7); + set => StringConverter4.SetString(Trainer_Trash, value, 7); } } diff --git a/PKHeX.Core/Saves/Substructures/Gen5/BoxLayout5.cs b/PKHeX.Core/Saves/Substructures/Gen5/BoxLayout5.cs index 69e8614c7..547af7b9d 100644 --- a/PKHeX.Core/Saves/Substructures/Gen5/BoxLayout5.cs +++ b/PKHeX.Core/Saves/Substructures/Gen5/BoxLayout5.cs @@ -1,4 +1,4 @@ -using System; +using System; namespace PKHeX.Core; @@ -34,9 +34,9 @@ public sealed class BoxLayout5 : SaveBlock return SAV.GetString(GetBoxNameSpan(box)); } - public void SetBoxName(int box, string value) + public void SetBoxName(int box, ReadOnlySpan value) { - SAV.SetString(GetBoxNameSpan(box), value.AsSpan(), 13, StringConverterOption.ClearZero); + SAV.SetString(GetBoxNameSpan(box), value, 13, StringConverterOption.ClearZero); } public string this[int i] diff --git a/PKHeX.Core/Saves/Substructures/Gen5/CGearBackground.cs b/PKHeX.Core/Saves/Substructures/Gen5/CGearBackground.cs index 34307cb80..788aef5f0 100644 --- a/PKHeX.Core/Saves/Substructures/Gen5/CGearBackground.cs +++ b/PKHeX.Core/Saves/Substructures/Gen5/CGearBackground.cs @@ -12,7 +12,7 @@ namespace PKHeX.Core; public sealed class CGearBackground { public const string Extension = "cgb"; - public const string Filter = "C-Gear Background|*.cgb"; + public const string Filter = $"C-Gear Background|*.{Extension}"; public const int Width = 256; // px public const int Height = 192; // px public const int SIZE_CGB = 0x2600; @@ -47,7 +47,7 @@ public sealed class CGearBackground public CGearBackground(byte[] data) { if (data.Length != SIZE_CGB) - throw new ArgumentException(nameof(data)); + throw new ArgumentOutOfRangeException(nameof(data)); // decode for easy handling if (!IsCGB(data)) @@ -155,22 +155,29 @@ public sealed class CGearBackground private static byte[] PSKtoCGB(ReadOnlySpan psk) { byte[] cgb = psk.ToArray(); - for (int i = 0x2000; i < 0x2600; i += 2) + var tileRegion = cgb.AsSpan(0x2000, 0x600); + ConvertTilesPSKtoCGB(tileRegion); + return cgb; + } + + private static void ConvertTilesPSKtoCGB(Span tileRegion) + { + for (int i = 0; i < tileRegion.Length; i += 2) { - int val = ReadUInt16LittleEndian(psk[i..]); - int index = ValToIndex(val); + var exist = tileRegion.Slice(i, 2); + var value = ReadUInt16LittleEndian(exist); + var index = ValToIndex(value); byte tile = (byte)index; byte rot = (byte)(index >> 8); if (tile == 0xFF) tile = 0; - cgb[i] = tile; - cgb[i + 1] = rot; + exist[i] = tile; + exist[i + 1] = rot; } - return cgb; } - private static int ValToIndex(int val) + private static int ValToIndex(ushort val) { var trunc = (val & 0x3FF); if (trunc is < 0xA0 or > 0x280) @@ -219,7 +226,7 @@ public sealed class CGearBackground return (ushort)val; } - private static readonly byte[] Convert5To8 = // 0x20 entries + private static ReadOnlySpan Convert5To8 => new byte[] // 0x20 entries { 0x00,0x08,0x10,0x18,0x20,0x29,0x31,0x39, 0x41,0x4A,0x52,0x5A,0x62,0x6A,0x73,0x7B, diff --git a/PKHeX.Core/Saves/Substructures/Gen5/Daycare5.cs b/PKHeX.Core/Saves/Substructures/Gen5/Daycare5.cs index 5b2bc854d..12cf10df6 100644 --- a/PKHeX.Core/Saves/Substructures/Gen5/Daycare5.cs +++ b/PKHeX.Core/Saves/Substructures/Gen5/Daycare5.cs @@ -1,4 +1,4 @@ -using System; +using System; using static System.Buffers.Binary.BinaryPrimitives; namespace PKHeX.Core; @@ -26,7 +26,7 @@ public sealed class Daycare5 : SaveBlock return ReadUInt64LittleEndian(Data.AsSpan(Offset + 0x1CC)); } - public void SetSeed(string value) + public void SetSeed(ReadOnlySpan value) { if (SAV is not SAV5B2W2) return; diff --git a/PKHeX.Core/Saves/Substructures/Gen5/FestaBlock5.cs b/PKHeX.Core/Saves/Substructures/Gen5/FestaBlock5.cs index 94fb8d800..75673a6f5 100644 --- a/PKHeX.Core/Saves/Substructures/Gen5/FestaBlock5.cs +++ b/PKHeX.Core/Saves/Substructures/Gen5/FestaBlock5.cs @@ -1,4 +1,4 @@ -using System; +using System; using static System.Buffers.Binary.BinaryPrimitives; namespace PKHeX.Core; @@ -218,14 +218,10 @@ public enum Funfest5Mission TheBerryHuntingAdventure = 44, } -public record struct Funfest5Score +public record struct Funfest5Score(uint RawValue) { - public uint RawValue { get; set; } - public Funfest5Score(uint raw) => RawValue = raw; - - public Funfest5Score(int total, int score, int level, bool isNew) + public Funfest5Score(int total, int score, int level, bool isNew) : this(0) { - RawValue = 0; Total = total; Score = score; Level = level; diff --git a/PKHeX.Core/Saves/Substructures/Gen5/MyItem5B2W2.cs b/PKHeX.Core/Saves/Substructures/Gen5/MyItem5B2W2.cs index 1fc00f1f1..3b65e19a3 100644 --- a/PKHeX.Core/Saves/Substructures/Gen5/MyItem5B2W2.cs +++ b/PKHeX.Core/Saves/Substructures/Gen5/MyItem5B2W2.cs @@ -1,4 +1,4 @@ -using System.Collections.Generic; +using System.Collections.Generic; namespace PKHeX.Core; @@ -23,13 +23,13 @@ public sealed class MyItem5B2W2 : MyItem { get { - InventoryPouch[] pouch = + InventoryPouch4[] pouch = { - new InventoryPouch4(InventoryType.Items, LegalItems, 999, Offset + HeldItem), - new InventoryPouch4(InventoryType.KeyItems, LegalKeyItems, 1, Offset + KeyItem), - new InventoryPouch4(InventoryType.TMHMs, LegalTMHMs, 1, Offset + TMHM), - new InventoryPouch4(InventoryType.Medicine, LegalMedicine, 999, Offset + Medicine), - new InventoryPouch4(InventoryType.Berries, LegalBerries, 999, Offset + Berry), + new(InventoryType.Items, LegalItems, 999, Offset + HeldItem), + new(InventoryType.KeyItems, LegalKeyItems, 1, Offset + KeyItem), + new(InventoryType.TMHMs, LegalTMHMs, 1, Offset + TMHM), + new(InventoryType.Medicine, LegalMedicine, 999, Offset + Medicine), + new(InventoryType.Berries, LegalBerries, 999, Offset + Berry), }; return pouch.LoadAll(Data); } diff --git a/PKHeX.Core/Saves/Substructures/Gen5/MyItem5BW.cs b/PKHeX.Core/Saves/Substructures/Gen5/MyItem5BW.cs index 085a7114a..ce0124085 100644 --- a/PKHeX.Core/Saves/Substructures/Gen5/MyItem5BW.cs +++ b/PKHeX.Core/Saves/Substructures/Gen5/MyItem5BW.cs @@ -1,4 +1,4 @@ -using System.Collections.Generic; +using System.Collections.Generic; namespace PKHeX.Core; @@ -23,13 +23,13 @@ public sealed class MyItem5BW : MyItem { get { - InventoryPouch[] pouch = + InventoryPouch4[] pouch = { - new InventoryPouch4(InventoryType.Items, LegalItems, 999, Offset + HeldItem), - new InventoryPouch4(InventoryType.KeyItems, LegalKeyItems, 1, Offset + KeyItem), - new InventoryPouch4(InventoryType.TMHMs, LegalTMHMs, 1, Offset + TMHM), - new InventoryPouch4(InventoryType.Medicine, LegalMedicine, 999, Offset + Medicine), - new InventoryPouch4(InventoryType.Berries, LegalBerries, 999, Offset + Berry), + new(InventoryType.Items, LegalItems, 999, Offset + HeldItem), + new(InventoryType.KeyItems, LegalKeyItems, 1, Offset + KeyItem), + new(InventoryType.TMHMs, LegalTMHMs, 1, Offset + TMHM), + new(InventoryType.Medicine, LegalMedicine, 999, Offset + Medicine), + new(InventoryType.Berries, LegalBerries, 999, Offset + Berry), }; return pouch.LoadAll(Data); } diff --git a/PKHeX.Core/Saves/Substructures/Gen5/PlayerData5.cs b/PKHeX.Core/Saves/Substructures/Gen5/PlayerData5.cs index ab42e9776..3d9cd0ffc 100644 --- a/PKHeX.Core/Saves/Substructures/Gen5/PlayerData5.cs +++ b/PKHeX.Core/Saves/Substructures/Gen5/PlayerData5.cs @@ -1,4 +1,4 @@ -using System; +using System; using static System.Buffers.Binary.BinaryPrimitives; namespace PKHeX.Core; @@ -16,19 +16,25 @@ public sealed class PlayerData5 : SaveBlock public string OT { get => SAV.GetString(OT_Trash); - set => SAV.SetString(OT_Trash, value.AsSpan(), SAV.MaxStringLengthOT, StringConverterOption.ClearZero); + set => SAV.SetString(OT_Trash, value, SAV.MaxStringLengthOT, StringConverterOption.ClearZero); } - public int TID + public uint ID32 + { + get => ReadUInt32LittleEndian(Data.AsSpan(Offset + 0x14)); + set => WriteUInt32LittleEndian(Data.AsSpan(Offset + 0x14), value); + } + + public ushort TID16 { get => ReadUInt16LittleEndian(Data.AsSpan(Offset + 0x14 + 0)); - set => WriteUInt16LittleEndian(Data.AsSpan(Offset + 0x14 + 0), (ushort)value); + set => WriteUInt16LittleEndian(Data.AsSpan(Offset + 0x14 + 0), value); } - public int SID + public ushort SID16 { get => ReadUInt16LittleEndian(Data.AsSpan(Offset + 0x14 + 2)); - set => WriteUInt16LittleEndian(Data.AsSpan(Offset + 0x14 + 2), (ushort)value); + set => WriteUInt16LittleEndian(Data.AsSpan(Offset + 0x14 + 2), value); } public int Language diff --git a/PKHeX.Core/Saves/Substructures/Gen6/BoxLayout6.cs b/PKHeX.Core/Saves/Substructures/Gen6/BoxLayout6.cs index 773ed5698..2b338cab8 100644 --- a/PKHeX.Core/Saves/Substructures/Gen6/BoxLayout6.cs +++ b/PKHeX.Core/Saves/Substructures/Gen6/BoxLayout6.cs @@ -1,4 +1,4 @@ -using System; +using System; namespace PKHeX.Core; @@ -42,10 +42,10 @@ public sealed class BoxLayout6 : SaveBlock, IBoxDetailName, IBoxDetailWall public string GetBoxName(int box) => SAV.GetString(Data.AsSpan(GetBoxNameOffset(box), StringMaxByteCount)); - public void SetBoxName(int box, string value) + public void SetBoxName(int box, ReadOnlySpan value) { var span = Data.AsSpan(GetBoxNameOffset(box) + (StringMaxByteCount * box), StringMaxByteCount); - SAV.SetString(span, value.AsSpan(), StringMaxLength, StringConverterOption.ClearZero); + SAV.SetString(span, value, StringMaxLength, StringConverterOption.ClearZero); } public byte[] BoxFlags diff --git a/PKHeX.Core/Saves/Substructures/Gen6/Encount6.cs b/PKHeX.Core/Saves/Substructures/Gen6/Encount6.cs index f572e3436..d78e926a1 100644 --- a/PKHeX.Core/Saves/Substructures/Gen6/Encount6.cs +++ b/PKHeX.Core/Saves/Substructures/Gen6/Encount6.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.ComponentModel; using static System.Buffers.Binary.BinaryPrimitives; @@ -114,7 +114,7 @@ public sealed class Roamer6 public override string ToString() => ((Species)Species).ToString(); private ushort SpecForm { get => ReadUInt16LittleEndian(Data.AsSpan(0x00)); set => WriteUInt16LittleEndian(Data.AsSpan(0x00), value); } - public int Species { get => SpecForm & 0x3FF; set => SpecForm = (ushort)((SpecForm & ~0x3FF) | (value & 0x3FF)); } + public ushort Species { get => (ushort)(SpecForm & 0x3FF); set => SpecForm = (ushort)((SpecForm & ~0x3FF) | (value & 0x3FF)); } public bool Flag1 { get => SpecForm >> 14 != 0; set => SpecForm = (ushort)((SpecForm & 0xBFFF) | (value ? (1 << 14) : 0)); } public bool Flag2 { get => SpecForm >> 15 != 0; set => SpecForm = (ushort)((SpecForm & 0x7FFF) | (value ? (1 << 15) : 0)); } diff --git a/PKHeX.Core/Saves/Substructures/Gen6/Fashion6XY.cs b/PKHeX.Core/Saves/Substructures/Gen6/Fashion6XY.cs index 4a62bbfe9..3f8a79bcd 100644 --- a/PKHeX.Core/Saves/Substructures/Gen6/Fashion6XY.cs +++ b/PKHeX.Core/Saves/Substructures/Gen6/Fashion6XY.cs @@ -1,4 +1,6 @@ -namespace PKHeX.Core; +using System; + +namespace PKHeX.Core; public sealed class Fashion6XY : SaveBlock { @@ -9,7 +11,7 @@ public sealed class Fashion6XY : SaveBlock SAV.SetData(AllAccessories, Offset); } - private static readonly byte[] AllAccessories = + private static ReadOnlySpan AllAccessories => new byte[] { 0xFE,0xFF,0xFF,0x7E,0xFF,0xFD,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xEF,0xFF,0xFF,0xFF,0xF9,0xFF,0xFB,0xFF,0xF7,0xFF,0xFF,0x0F,0x00,0x00,0x00, diff --git a/PKHeX.Core/Saves/Substructures/Gen6/HallFame6Entity.cs b/PKHeX.Core/Saves/Substructures/Gen6/HallFame6Entity.cs index 64a623ceb..d631ae992 100644 --- a/PKHeX.Core/Saves/Substructures/Gen6/HallFame6Entity.cs +++ b/PKHeX.Core/Saves/Substructures/Gen6/HallFame6Entity.cs @@ -17,8 +17,8 @@ public readonly ref struct HallFame6Entity public ushort Move4 { get => ReadUInt16LittleEndian(Data[0x0A..]); set => WriteUInt16LittleEndian(Data[0x0A..], value); } public uint EncryptionConstant { get => ReadUInt32LittleEndian(Data[0x0C..]); set => WriteUInt32LittleEndian(Data[0x0C..], value); } - public ushort TID { get => ReadUInt16LittleEndian(Data[0x10..]); set => WriteUInt16LittleEndian(Data[0x10..], value); } - public ushort SID { get => ReadUInt16LittleEndian(Data[0x12..]); set => WriteUInt16LittleEndian(Data[0x12..], value); } + public ushort TID16 { get => ReadUInt16LittleEndian(Data[0x10..]); set => WriteUInt16LittleEndian(Data[0x10..], value); } + public ushort SID16 { get => ReadUInt16LittleEndian(Data[0x12..]); set => WriteUInt16LittleEndian(Data[0x12..], value); } private uint Pack { get => ReadUInt32LittleEndian(Data[0x14..]); set => WriteUInt32LittleEndian(Data[0x14..], value); } public byte Form { get => (byte)(Pack & 0x1Fu); set => Pack = (Pack & ~0x1Fu) | (value & 0x1Fu); } @@ -47,12 +47,12 @@ public readonly ref struct HallFame6Entity public string Nickname { get => StringConverter6.GetString(Nick_Trash); - set => StringConverter6.SetString(Nick_Trash, value.AsSpan(), 12, Option); + set => StringConverter6.SetString(Nick_Trash, value, 12, Option); } public string OT_Name { get => StringConverter6.GetString(OT_Trash); - set => StringConverter6.SetString(OT_Trash, value.AsSpan(), 12, Option); + set => StringConverter6.SetString(OT_Trash, value, 12, Option); } } diff --git a/PKHeX.Core/Saves/Substructures/Gen6/MyItem6AO.cs b/PKHeX.Core/Saves/Substructures/Gen6/MyItem6AO.cs index ce99d2c19..bbac261ba 100644 --- a/PKHeX.Core/Saves/Substructures/Gen6/MyItem6AO.cs +++ b/PKHeX.Core/Saves/Substructures/Gen6/MyItem6AO.cs @@ -1,4 +1,4 @@ -using System.Collections.Generic; +using System.Collections.Generic; namespace PKHeX.Core; @@ -17,13 +17,13 @@ public sealed class MyItem6AO : MyItem { get { - InventoryPouch[] pouch = + InventoryPouch4[] pouch = { - new InventoryPouch4(InventoryType.Items, Legal.Pouch_Items_AO, 999, Offset + HeldItem), - new InventoryPouch4(InventoryType.KeyItems, Legal.Pouch_Key_AO, 1, Offset + KeyItem), - new InventoryPouch4(InventoryType.TMHMs, Legal.Pouch_TMHM_AO, 1, Offset + TMHM), - new InventoryPouch4(InventoryType.Medicine, Legal.Pouch_Medicine_AO, 999, Offset + Medicine), - new InventoryPouch4(InventoryType.Berries, Legal.Pouch_Berry_XY, 999, Offset + Berry), + new(InventoryType.Items, Legal.Pouch_Items_AO, 999, Offset + HeldItem), + new(InventoryType.KeyItems, Legal.Pouch_Key_AO, 1, Offset + KeyItem), + new(InventoryType.TMHMs, Legal.Pouch_TMHM_AO, 1, Offset + TMHM), + new(InventoryType.Medicine, Legal.Pouch_Medicine_AO, 999, Offset + Medicine), + new(InventoryType.Berries, Legal.Pouch_Berry_XY, 999, Offset + Berry), }; return pouch.LoadAll(Data); } diff --git a/PKHeX.Core/Saves/Substructures/Gen6/MyItem6XY.cs b/PKHeX.Core/Saves/Substructures/Gen6/MyItem6XY.cs index ba213cca5..4a5e61eb1 100644 --- a/PKHeX.Core/Saves/Substructures/Gen6/MyItem6XY.cs +++ b/PKHeX.Core/Saves/Substructures/Gen6/MyItem6XY.cs @@ -1,4 +1,4 @@ -using System.Collections.Generic; +using System.Collections.Generic; namespace PKHeX.Core; @@ -16,13 +16,13 @@ public sealed class MyItem6XY : MyItem { get { - InventoryPouch[] pouch = + InventoryPouch4[] pouch = { - new InventoryPouch4(InventoryType.Items, Legal.Pouch_Items_XY, 999, Offset + HeldItem), - new InventoryPouch4(InventoryType.KeyItems, Legal.Pouch_Key_XY, 1, Offset + KeyItem), - new InventoryPouch4(InventoryType.TMHMs, Legal.Pouch_TMHM_XY, 1, Offset + TMHM), - new InventoryPouch4(InventoryType.Medicine, Legal.Pouch_Medicine_XY, 999, Offset + Medicine), - new InventoryPouch4(InventoryType.Berries, Legal.Pouch_Berry_XY, 999, Offset + Berry), + new(InventoryType.Items, Legal.Pouch_Items_XY, 999, Offset + HeldItem), + new(InventoryType.KeyItems, Legal.Pouch_Key_XY, 1, Offset + KeyItem), + new(InventoryType.TMHMs, Legal.Pouch_TMHM_XY, 1, Offset + TMHM), + new(InventoryType.Medicine, Legal.Pouch_Medicine_XY, 999, Offset + Medicine), + new(InventoryType.Berries, Legal.Pouch_Berry_XY, 999, Offset + Berry), }; return pouch.LoadAll(Data); } diff --git a/PKHeX.Core/Saves/Substructures/Gen6/MyStatus6.cs b/PKHeX.Core/Saves/Substructures/Gen6/MyStatus6.cs index 5a21e3973..074796ab4 100644 --- a/PKHeX.Core/Saves/Substructures/Gen6/MyStatus6.cs +++ b/PKHeX.Core/Saves/Substructures/Gen6/MyStatus6.cs @@ -7,16 +7,22 @@ public class MyStatus6 : SaveBlock, IRegionOrigin { public MyStatus6(SAV6 sav, int offset) : base(sav) => Offset = offset; - public int TID + public uint ID32 { - get => ReadUInt16LittleEndian(Data.AsSpan(Offset + 0)); - set => WriteUInt16LittleEndian(Data.AsSpan(Offset + 0), (ushort)value); + get => ReadUInt32LittleEndian(Data.AsSpan(Offset + 0)); + set => WriteUInt32LittleEndian(Data.AsSpan(Offset + 0), value); } - public int SID + public ushort TID16 + { + get => ReadUInt16LittleEndian(Data.AsSpan(Offset + 0)); + set => WriteUInt16LittleEndian(Data.AsSpan(Offset + 0), value); + } + + public ushort SID16 { get => ReadUInt16LittleEndian(Data.AsSpan(Offset + 2)); - set => WriteUInt16LittleEndian(Data.AsSpan(Offset + 2), (ushort)value); + set => WriteUInt16LittleEndian(Data.AsSpan(Offset + 2), value); } public int Game @@ -47,7 +53,7 @@ public class MyStatus6 : SaveBlock, IRegionOrigin public string GameSyncID { - get => Util.GetHexStringFromBytes(Data, Offset + 0x08, GameSyncIDSize / 2); + get => Util.GetHexStringFromBytes(Data.AsSpan(Offset + 0x08, GameSyncIDSize / 2)); set { if (value.Length != GameSyncIDSize) @@ -99,13 +105,13 @@ public class MyStatus6 : SaveBlock, IRegionOrigin public string OT { get => SAV.GetString(OT_Trash); - set => SAV.SetString(OT_Trash, value.AsSpan(), SAV.MaxStringLengthOT, StringConverterOption.ClearZero); + set => SAV.SetString(OT_Trash, value, SAV.MaxStringLengthOT, StringConverterOption.ClearZero); } private Span GetSayingSpan(int say) => Data.AsSpan(GetSayingOffset(say), SAV6.LongStringLength); private int GetSayingOffset(int say) => Offset + 0x7C + (SAV6.LongStringLength * say); private string GetSaying(int say) => SAV.GetString(GetSayingSpan(say)); - private void SetSaying(int say, string value) => SAV.SetString(GetSayingSpan(say), value.AsSpan(), SAV6.LongStringLength / 2, StringConverterOption.ClearZero); + private void SetSaying(int say, ReadOnlySpan value) => SAV.SetString(GetSayingSpan(say), value, SAV6.LongStringLength / 2, StringConverterOption.ClearZero); public string Saying1 { get => GetSaying(0); set => SetSaying(0, value); } public string Saying2 { get => GetSaying(1); set => SetSaying(1, value); } diff --git a/PKHeX.Core/Saves/Substructures/Gen6/MyStatus6XY.cs b/PKHeX.Core/Saves/Substructures/Gen6/MyStatus6XY.cs index 6cbbc1334..5f3f2a2f6 100644 --- a/PKHeX.Core/Saves/Substructures/Gen6/MyStatus6XY.cs +++ b/PKHeX.Core/Saves/Substructures/Gen6/MyStatus6XY.cs @@ -1,4 +1,4 @@ -using System; +using System; using static System.Buffers.Binary.BinaryPrimitives; namespace PKHeX.Core; @@ -22,7 +22,7 @@ public sealed class MyStatus6XY : MyStatus6 public string OT_Nick { get => SAV.GetString(Nickname_Trash); - set => SAV.SetString(Nickname_Trash, value.AsSpan(), 12, StringConverterOption.ClearZero); + set => SAV.SetString(Nickname_Trash, value, 12, StringConverterOption.ClearZero); } public short EyeColor diff --git a/PKHeX.Core/Saves/Substructures/Gen6/MysteryBlock6.cs b/PKHeX.Core/Saves/Substructures/Gen6/MysteryBlock6.cs index 920c9ef3d..fe057e176 100644 --- a/PKHeX.Core/Saves/Substructures/Gen6/MysteryBlock6.cs +++ b/PKHeX.Core/Saves/Substructures/Gen6/MysteryBlock6.cs @@ -13,13 +13,13 @@ public sealed class MysteryBlock6 : SaveBlock public MysteryBlock6(SAV6XY sav, int offset) : base(sav) => Offset = offset; public MysteryBlock6(SAV6AO sav, int offset) : base(sav) => Offset = offset; - public bool[] GetReceivedFlags() => ArrayUtil.GitBitFlagArray(Data.AsSpan(Offset + FlagStart), MaxReceivedFlag); + public bool[] GetReceivedFlags() => FlagUtil.GitBitFlagArray(Data.AsSpan(Offset + FlagStart), MaxReceivedFlag); public void SetReceivedFlags(ReadOnlySpan value) { if (value.Length != MaxReceivedFlag) return; - ArrayUtil.SetBitFlagArray(Data.AsSpan(Offset + FlagStart), value); + FlagUtil.SetBitFlagArray(Data.AsSpan(Offset + FlagStart), value); SAV.State.Edited = true; } @@ -59,7 +59,7 @@ public sealed class MysteryBlock6 : SaveBlock if (wc6.Data.Length != WC6.Size) throw new InvalidCastException(nameof(wc6)); - if (wc6.CardID == 2048 && wc6.ItemID == 726) // Eon Ticket (OR/AS) + if (wc6 is { CardID: 2048, ItemID: 726 }) // Eon Ticket (OR/AS) { if (SAV is not SAV6AO ao) return; diff --git a/PKHeX.Core/Saves/Substructures/Gen6/OPower/OPower6.cs b/PKHeX.Core/Saves/Substructures/Gen6/OPower/OPower6.cs index 88688deda..1a937ceb4 100644 --- a/PKHeX.Core/Saves/Substructures/Gen6/OPower/OPower6.cs +++ b/PKHeX.Core/Saves/Substructures/Gen6/OPower/OPower6.cs @@ -1,4 +1,4 @@ -using System; +using System; using static PKHeX.Core.OPower6Type; namespace PKHeX.Core; @@ -35,7 +35,7 @@ public sealed class OPower6 : SaveBlock public OPower6(SAV6XY sav, int offset) : base(sav) => Offset = offset; public OPower6(SAV6AO sav, int offset) : base(sav) => Offset = offset; - private static OPowerFlagSet Get(OPower6Type type) => Array.Find(Mapping, t => t.Identifier == type); + private static OPowerFlagSet Get(OPower6Type type) => Array.Find(Mapping, t => t.Identifier == type) ?? throw new ArgumentOutOfRangeException(nameof(type)); public static int GetOPowerCount(OPower6Type type) => Get(type).BaseCount; public int GetOPowerLevel(OPower6Type type) => Get(type).GetOPowerLevel(Data.AsSpan(Offset)); diff --git a/PKHeX.Core/Saves/Substructures/Gen6/RecordBlock6.cs b/PKHeX.Core/Saves/Substructures/Gen6/RecordBlock6.cs index 95ab3e375..86c1c31e7 100644 --- a/PKHeX.Core/Saves/Substructures/Gen6/RecordBlock6.cs +++ b/PKHeX.Core/Saves/Substructures/Gen6/RecordBlock6.cs @@ -1,49 +1,19 @@ -using System; -using System.Collections.Generic; +using System; using System.Diagnostics; using static System.Buffers.Binary.BinaryPrimitives; namespace PKHeX.Core; -public sealed class RecordBlock6 : RecordBlock // 6 or 7 +public abstract class RecordBlock6 : RecordBlock // 6 or 7 { public const int RecordCount = 200; - protected override IReadOnlyList RecordMax { get; } + + protected RecordBlock6(SaveFile sav, int offset) : base(sav) => Offset = offset; // Structure: // uint[100]; // ushort[100]; - public RecordBlock6(SAV6XY sav, int offset) : base(sav) - { - Offset = offset; - RecordMax = Records.MaxType_XY; - } - - public RecordBlock6(SAV6AO sav, int offset) : base(sav) - { - Offset = offset; - RecordMax = Records.MaxType_AO; - } - - public RecordBlock6(SAV6AODemo sav, int offset) : base(sav) - { - Offset = offset; - RecordMax = Records.MaxType_AO; - } - - public RecordBlock6(SAV7SM sav, int offset) : base(sav) - { - Offset = offset; - RecordMax = Records.MaxType_SM; - } - - public RecordBlock6(SAV7USUM sav, int offset) : base(sav) - { - Offset = offset; - RecordMax = Records.MaxType_USUM; - } - public override int GetRecord(int recordID) { int ofs = Records.GetOffset(Offset, recordID); @@ -81,3 +51,128 @@ public sealed class RecordBlock6 : RecordBlock // 6 or 7 } } } + +public sealed class RecordBlock6XY : RecordBlock6 +{ + public RecordBlock6XY(SAV6XY sav, int offset) : base(sav, offset) { } + protected override ReadOnlySpan RecordMax => MaxType_XY; + + private static ReadOnlySpan MaxType_XY => new byte[] + { + 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 2, 2, 2, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, + 3, 0, 0, 1, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 7, 5, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 6, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + }; +} + +public sealed class RecordBlock6AO : RecordBlock6 +{ + public RecordBlock6AO(SAV6AO sav, int offset) : base(sav, offset) { } + public RecordBlock6AO(SAV6AODemo sav, int offset) : base(sav, offset) { } + protected override ReadOnlySpan RecordMax => MaxType_AO; + + private static ReadOnlySpan MaxType_AO => new byte[] + { + 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 2, 2, 2, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, + 3, 0, 0, 1, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, + + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 7, 5, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 6, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 7, 7, 7, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + }; +} + +public sealed class RecordBlock7SM : RecordBlock6 +{ + public RecordBlock7SM(SAV7SM sav, int offset) : base(sav, offset) { } + protected override ReadOnlySpan RecordMax => MaxType_SM; + + private static ReadOnlySpan MaxType_SM => new byte[] + { + 0, 0, 0, 0, 0, 0, 2, 2, 2, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 2, 2, 2, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 2, 2, 2, 0, 0, 0, 2, 2, 0, + 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 6, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + }; +} + +public sealed class RecordBlock7USUM : RecordBlock6 +{ + public RecordBlock7USUM(SAV7USUM sav, int offset) : base(sav, offset) { } + protected override ReadOnlySpan RecordMax => MaxType_USUM; + + private static ReadOnlySpan MaxType_USUM => new byte[] + { + 0, 0, 0, 0, 0, 0, 2, 2, 2, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 2, 2, 2, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 2, 2, 2, 0, 0, 0, 2, 2, 0, + 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, + 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 6, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 4, 4, 4, 5, 5, 4, 5, 5, + }; +} diff --git a/PKHeX.Core/Saves/Substructures/Gen6/SangoInfoBlock.cs b/PKHeX.Core/Saves/Substructures/Gen6/SangoInfoBlock.cs index 0361a9d64..f4213f7f3 100644 --- a/PKHeX.Core/Saves/Substructures/Gen6/SangoInfoBlock.cs +++ b/PKHeX.Core/Saves/Substructures/Gen6/SangoInfoBlock.cs @@ -1,4 +1,4 @@ -using System; +using System; using static System.Buffers.Binary.BinaryPrimitives; namespace PKHeX.Core; @@ -18,7 +18,7 @@ public sealed class SangoInfoBlock : SaveBlock public string SecretBaseQRText // 0x319BC -- 17*u16 { get => SAV.GetString(Data.AsSpan(Offset + 0x63BC, 36)); - set => SAV.SetString(Data.AsSpan(Offset + 0x63BC, 36), value.AsSpan(), 0x10, StringConverterOption.ClearZero); + set => SAV.SetString(Data.AsSpan(Offset + 0x63BC, 36), value, 0x10, StringConverterOption.ClearZero); } public uint EonTicketSendMagic // 0x319DE diff --git a/PKHeX.Core/Saves/Substructures/Gen6/SecretBase/SecretBase6.cs b/PKHeX.Core/Saves/Substructures/Gen6/SecretBase/SecretBase6.cs index e11c8b9d1..8c4b95f47 100644 --- a/PKHeX.Core/Saves/Substructures/Gen6/SecretBase/SecretBase6.cs +++ b/PKHeX.Core/Saves/Substructures/Gen6/SecretBase/SecretBase6.cs @@ -1,4 +1,4 @@ -using System; +using System; using static System.Buffers.Binary.BinaryPrimitives; namespace PKHeX.Core; @@ -92,12 +92,12 @@ public class SecretBase6 public string TrainerName { get => StringConverter6.GetString(Data.AsSpan(Offset + 0x21A, NameLengthBytes)); - set => StringConverter6.SetString(Data.AsSpan(Offset + 0x21A, NameLengthBytes), value.AsSpan(), NameLength, StringConverterOption.ClearZero); + set => StringConverter6.SetString(Data.AsSpan(Offset + 0x21A, NameLengthBytes), value, NameLength, StringConverterOption.ClearZero); } private Span GetMessageSpan(int index) => Data.AsSpan(Offset + 0x234 + (MessageLengthBytes * index), MessageLengthBytes); private string GetMessage(int index) => StringConverter6.GetString(GetMessageSpan(index)); - private void SetMessage(int index, string value) => StringConverter6.SetString(GetMessageSpan(index), value.AsSpan(), MessageLength, StringConverterOption.ClearZero); + private void SetMessage(int index, ReadOnlySpan value) => StringConverter6.SetString(GetMessageSpan(index), value, MessageLength, StringConverterOption.ClearZero); public string TeamName { get => GetMessage(0); set => SetMessage(0, value); } public string TeamSlogan { get => GetMessage(1); set => SetMessage(1, value); } diff --git a/PKHeX.Core/Saves/Substructures/Gen6/SecretBase/SecretBase6PKM.cs b/PKHeX.Core/Saves/Substructures/Gen6/SecretBase/SecretBase6PKM.cs index f966766cc..fa4253224 100644 --- a/PKHeX.Core/Saves/Substructures/Gen6/SecretBase/SecretBase6PKM.cs +++ b/PKHeX.Core/Saves/Substructures/Gen6/SecretBase/SecretBase6PKM.cs @@ -3,7 +3,7 @@ using static System.Buffers.Binary.BinaryPrimitives; namespace PKHeX.Core; -public sealed class SecretBase6PKM : ISanityChecksum +public sealed class SecretBase6PKM : ISanityChecksum, IFatefulEncounter { public const int SIZE = 0x34; public readonly byte[] Data; diff --git a/PKHeX.Core/Saves/Substructures/Gen7/BoxLayout7.cs b/PKHeX.Core/Saves/Substructures/Gen7/BoxLayout7.cs index 19eafe351..6e15517ec 100644 --- a/PKHeX.Core/Saves/Substructures/Gen7/BoxLayout7.cs +++ b/PKHeX.Core/Saves/Substructures/Gen7/BoxLayout7.cs @@ -1,4 +1,4 @@ -using System; +using System; using static System.Buffers.Binary.BinaryPrimitives; namespace PKHeX.Core; @@ -41,7 +41,7 @@ public sealed class BoxLayout7 : SaveBlock, IBoxDetailName, IBoxDetailWall private Span GetBoxNameSpan(int box) => Data.AsSpan(GetBoxNameOffset(box), SAV6.LongStringLength); private int GetBoxNameOffset(int box) => Offset + (SAV6.LongStringLength * box); public string GetBoxName(int box) => SAV.GetString(GetBoxNameSpan(box)); - public void SetBoxName(int box, string value) => SAV.SetString(GetBoxNameSpan(box), value.AsSpan(), StringMaxLength, StringConverterOption.ClearZero); + public void SetBoxName(int box, ReadOnlySpan value) => SAV.SetString(GetBoxNameSpan(box), value, StringMaxLength, StringConverterOption.ClearZero); public byte[] BoxFlags { diff --git a/PKHeX.Core/Saves/Substructures/Gen7/Daycare7.cs b/PKHeX.Core/Saves/Substructures/Gen7/Daycare7.cs index cdc9fd4d7..52f3c0af2 100644 --- a/PKHeX.Core/Saves/Substructures/Gen7/Daycare7.cs +++ b/PKHeX.Core/Saves/Substructures/Gen7/Daycare7.cs @@ -1,4 +1,6 @@ -namespace PKHeX.Core; +using System; + +namespace PKHeX.Core; public sealed class Daycare7 : SaveBlock { @@ -30,7 +32,7 @@ public sealed class Daycare7 : SaveBlock public string RNGSeed { - get => Util.GetHexStringFromBytes(Data, Offset + 0x1DC, DaycareSeedSize / 2); + get => Util.GetHexStringFromBytes(Data.AsSpan(Offset + 0x1DC, DaycareSeedSize / 2)); set { if (value.Length != DaycareSeedSize) diff --git a/PKHeX.Core/Saves/Substructures/Gen7/FestaFacility.cs b/PKHeX.Core/Saves/Substructures/Gen7/FestaFacility.cs index e2dd869ee..32ae31a73 100644 --- a/PKHeX.Core/Saves/Substructures/Gen7/FestaFacility.cs +++ b/PKHeX.Core/Saves/Substructures/Gen7/FestaFacility.cs @@ -23,7 +23,7 @@ public sealed class FestaFacility public int Color { get => Data[0x01]; set => Data[0x01] = (byte)value; } public bool IsIntroduced { get => Data[0x02] != 0; set => Data[0x02] = value ? (byte)1 : (byte)0; } public int Gender { get => Data[0x03]; set => Data[0x03] = (byte)value; } - public string OT_Name { get => StringConverter7.GetString(Data.AsSpan(0x04, 0x1A)); set => StringConverter7.SetString(Data.AsSpan(0x04, 0x1A), value.AsSpan(), 12, Language, StringConverterOption.ClearZero); } + public string OT_Name { get => StringConverter7.GetString(Data.AsSpan(0x04, 0x1A)); set => StringConverter7.SetString(Data.AsSpan(0x04, 0x1A), value, 12, Language, StringConverterOption.ClearZero); } private int MessageMeet { get => ReadUInt16LittleEndian(Data.AsSpan(0x1E)); set => WriteUInt16LittleEndian(Data.AsSpan(0x1E), (ushort)value); } private int MessagePart { get => ReadUInt16LittleEndian(Data.AsSpan(0x20)); set => WriteUInt16LittleEndian(Data.AsSpan(0x20), (ushort)value); } diff --git a/PKHeX.Core/Saves/Substructures/Gen7/FieldMenu7.cs b/PKHeX.Core/Saves/Substructures/Gen7/FieldMenu7.cs index 4b7f1bffe..a72835013 100644 --- a/PKHeX.Core/Saves/Substructures/Gen7/FieldMenu7.cs +++ b/PKHeX.Core/Saves/Substructures/Gen7/FieldMenu7.cs @@ -1,4 +1,4 @@ -using System; +using System; using static System.Buffers.Binary.BinaryPrimitives; namespace PKHeX.Core; @@ -21,6 +21,6 @@ public sealed class FieldMenu7 : SaveBlock public string RotomOT { get => SAV.GetString(Offset + 0x30, 0x1A); - set => SAV.SetString(Data.AsSpan(Offset + 0x30, 0x1A), value.AsSpan(), SAV.MaxStringLengthOT, StringConverterOption.ClearZero); + set => SAV.SetString(Data.AsSpan(Offset + 0x30, 0x1A), value, SAV.MaxStringLengthOT, StringConverterOption.ClearZero); } } diff --git a/PKHeX.Core/Saves/Substructures/Gen7/JoinFesta7.cs b/PKHeX.Core/Saves/Substructures/Gen7/JoinFesta7.cs index e1032911d..67f90ae31 100644 --- a/PKHeX.Core/Saves/Substructures/Gen7/JoinFesta7.cs +++ b/PKHeX.Core/Saves/Substructures/Gen7/JoinFesta7.cs @@ -1,4 +1,4 @@ -using System; +using System; using static System.Buffers.Binary.BinaryPrimitives; namespace PKHeX.Core; @@ -37,7 +37,7 @@ public sealed class JoinFesta7 : SaveBlock public string FestivalPlazaName { get => StringConverter7.GetString(FestivalPlazaNameSpan); - set => StringConverter7.SetString(FestivalPlazaNameSpan, value.AsSpan(), 20, 0, StringConverterOption.ClearZero); + set => StringConverter7.SetString(FestivalPlazaNameSpan, value, 20, 0, StringConverterOption.ClearZero); } public ushort FestaRank { get => ReadUInt16LittleEndian(Data.AsSpan(Offset + 0x53A)); set => WriteUInt16LittleEndian(Data.AsSpan(Offset + 0x53A), value); } diff --git a/PKHeX.Core/Saves/Substructures/Gen7/LGPE/GP1.cs b/PKHeX.Core/Saves/Substructures/Gen7/LGPE/GP1.cs index 7c3bc5c15..e9349f7dc 100644 --- a/PKHeX.Core/Saves/Substructures/Gen7/LGPE/GP1.cs +++ b/PKHeX.Core/Saves/Substructures/Gen7/LGPE/GP1.cs @@ -24,7 +24,7 @@ public sealed class GP1 : IEncounterInfo, IFixedAbilityNumber, IScaledSizeReadOn public PKM ConvertToPKM(ITrainerInfo tr, EncounterCriteria criteria) => ConvertToPB7(tr, criteria); public GP1(byte[] data) => Data = data; - public GP1() : this((byte[])Blank.Clone()) { } + public GP1() : this(new byte[SIZE]) => InitializeBlank(Data); public void WriteTo(byte[] data, int offset) => Data.CopyTo(data, offset); public static GP1 FromData(byte[] data, int offset) @@ -35,15 +35,15 @@ public sealed class GP1 : IEncounterInfo, IFixedAbilityNumber, IScaledSizeReadOn private static GP1 FromData(ReadOnlySpan span) { - var gpkm = new GP1(); - span[..SIZE].CopyTo(gpkm.Data); - return gpkm; + var result = new GP1(); + span[..SIZE].CopyTo(result.Data); + return result; } /// /// First 0x20 bytes of an empty , all other bytes are 0. /// - private static readonly byte[] Blank20 = + private static ReadOnlySpan Blank20 => new byte[] { 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x3F, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0x3F, @@ -51,17 +51,10 @@ public sealed class GP1 : IEncounterInfo, IFixedAbilityNumber, IScaledSizeReadOn 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x85, 0xEC, 0x33, 0x01, }; - public static readonly byte[] Blank = GetBlank(); + public static void InitializeBlank(Span data) => Blank20.CopyTo(data); - public static byte[] GetBlank() - { - byte[] data = new byte[SIZE]; - Blank20.CopyTo(data, 0x20); - return data; - } - - public string Username1 => Util.TrimFromZero(Encoding.ASCII.GetString(Data, 0x00, 0x10)); - public string Username2 => Util.TrimFromZero(Encoding.ASCII.GetString(Data, 0x10, 0x20)); + public string Username1 => Util.TrimFromZero(Encoding.ASCII.GetString(Data.AsSpan(0x00, 0x10))); + public string Username2 => Util.TrimFromZero(Encoding.ASCII.GetString(Data.AsSpan(0x10, 0x10))); public ushort Species => ReadUInt16LittleEndian(Data.AsSpan(0x28)); // s32, just read as u16 public int CP => ReadInt32LittleEndian(Data.AsSpan(0x2C)); @@ -138,6 +131,11 @@ public sealed class GP1 : IEncounterInfo, IFixedAbilityNumber, IScaledSizeReadOn public string StatMove => $"{IV_HP:00}/{IV_ATK:00}/{IV_DEF:00}, CP {CP:0000} (Moves {Move1:000}, {Move2:000})"; public string Dump(IReadOnlyList speciesNames, int index) => $"{index:000} {Nickname} ({speciesNames[Species]}{FormString} {ShinyString}[{GenderString}]) @ Lv. {Level:00} - {StatMove}, {GeoTime}."; + /// + /// GO Park transfers start with 2 AVs for all stats. + /// + public const byte InitialAV = 2; + public PB7 ConvertToPB7(ITrainerInfo sav) => ConvertToPB7(sav, EncounterCriteria.Unrestricted); public PB7 ConvertToPB7(ITrainerInfo sav, EncounterCriteria criteria) @@ -156,8 +154,8 @@ public sealed class GP1 : IEncounterInfo, IFixedAbilityNumber, IScaledSizeReadOn Met_Day = Day, CurrentLevel = Level, Met_Level = Level, - TID = sav.TID, - SID = sav.SID, + TID16 = sav.TID16, + SID16 = sav.SID16, OT_Name = sav.OT, Ball = 4, Language = sav.Language, @@ -186,9 +184,14 @@ public sealed class GP1 : IEncounterInfo, IFixedAbilityNumber, IScaledSizeReadOn bool isShiny = pk.IsShiny; if (IsShiny && !isShiny) // Force Square - pk.PID = (uint)(((sav.TID ^ sav.SID ^ (pk.PID & 0xFFFF) ^ 0) << 16) | (pk.PID & 0xFFFF)); + { + var low = pk.PID & 0xFFFF; + pk.PID = ((low ^ sav.TID16 ^ sav.SID16) << 16) | low; + } else if (isShiny) + { pk.PID ^= 0x1000_0000; + } Span moves = stackalloc ushort[4]; MoveLevelUp.GetEncounterMoves(moves, pk, pk.CurrentLevel, GameVersion.GO); @@ -199,7 +202,7 @@ public sealed class GP1 : IEncounterInfo, IFixedAbilityNumber, IScaledSizeReadOn pk.HeightScalar = HeightScalar; pk.WeightScalar = WeightScalar; - pk.AwakeningSetAllTo(2); + pk.AwakeningSetAllTo(InitialAV); // 2 pk.ResetCalculatedValues(); return pk; diff --git a/PKHeX.Core/Saves/Substructures/Gen7/LGPE/Misc7b.cs b/PKHeX.Core/Saves/Substructures/Gen7/LGPE/Misc7b.cs index b056cfbbe..9d047e3f1 100644 --- a/PKHeX.Core/Saves/Substructures/Gen7/LGPE/Misc7b.cs +++ b/PKHeX.Core/Saves/Substructures/Gen7/LGPE/Misc7b.cs @@ -18,6 +18,6 @@ public sealed class Misc7b : SaveBlock public string Rival { get => SAV.GetString(Rival_Trash); - set => SAV.SetString(Rival_Trash, value.AsSpan(), SAV.MaxStringLengthOT, StringConverterOption.ClearZero); + set => SAV.SetString(Rival_Trash, value, SAV.MaxStringLengthOT, StringConverterOption.ClearZero); } } diff --git a/PKHeX.Core/Saves/Substructures/Gen7/LGPE/MyItem7b.cs b/PKHeX.Core/Saves/Substructures/Gen7/LGPE/MyItem7b.cs index 69511e473..cf103435c 100644 --- a/PKHeX.Core/Saves/Substructures/Gen7/LGPE/MyItem7b.cs +++ b/PKHeX.Core/Saves/Substructures/Gen7/LGPE/MyItem7b.cs @@ -18,15 +18,15 @@ public sealed class MyItem7b : MyItem { get { - var pouch = new[] + InventoryPouch7b[] pouch = { - new InventoryPouch7b(InventoryType.Medicine, Legal.Pouch_Medicine_GG, 999, Medicine, PouchSize7b.Medicine), - new InventoryPouch7b(InventoryType.TMHMs, Legal.Pouch_TM_GG, 1, TM, PouchSize7b.TM), - new InventoryPouch7b(InventoryType.Balls, Legal.Pouch_Catching_GG, 999, Catching, PouchSize7b.Catching), - new InventoryPouch7b(InventoryType.Items, Legal.Pouch_Regular_GG, 999, Key, PouchSize7b.Items), - new InventoryPouch7b(InventoryType.BattleItems, Legal.Pouch_Battle_GG, 999, Battle, PouchSize7b.Battle), - new InventoryPouch7b(InventoryType.ZCrystals, Legal.Pouch_PowerUp_GG, 999, PowerUp, PouchSize7b.PowerUp), - new InventoryPouch7b(InventoryType.Candy, Legal.Pouch_Candy_GG, 999, Candy, PouchSize7b.Candy), + new(InventoryType.Medicine, Legal.Pouch_Medicine_GG, 999, Medicine, PouchSize7b.Medicine), + new(InventoryType.TMHMs, Legal.Pouch_TM_GG, 1, TM, PouchSize7b.TM), + new(InventoryType.Balls, Legal.Pouch_Catching_GG, 999, Catching, PouchSize7b.Catching), + new(InventoryType.Items, Legal.Pouch_Regular_GG, 999, Key, PouchSize7b.Items), + new(InventoryType.BattleItems, Legal.Pouch_Battle_GG, 999, Battle, PouchSize7b.Battle), + new(InventoryType.ZCrystals, Legal.Pouch_PowerUp_GG, 999, PowerUp, PouchSize7b.PowerUp), + new(InventoryType.Candy, Legal.Pouch_Candy_GG, 999, Candy, PouchSize7b.Candy), }; return pouch.LoadAll(Data); } diff --git a/PKHeX.Core/Saves/Substructures/Gen7/LGPE/MyStatus7b.cs b/PKHeX.Core/Saves/Substructures/Gen7/LGPE/MyStatus7b.cs index e3bad6912..c862f053c 100644 --- a/PKHeX.Core/Saves/Substructures/Gen7/LGPE/MyStatus7b.cs +++ b/PKHeX.Core/Saves/Substructures/Gen7/LGPE/MyStatus7b.cs @@ -11,16 +11,22 @@ public sealed class MyStatus7b : SaveBlock // idb uint8 offset: 0x58 - public int TID + public uint ID32 { - get => ReadUInt16LittleEndian(Data.AsSpan(Offset + 0)); - set => WriteUInt16LittleEndian(Data.AsSpan(Offset + 0), (ushort)value); + get => ReadUInt32LittleEndian(Data.AsSpan(Offset + 0)); + set => WriteUInt32LittleEndian(Data.AsSpan(Offset + 0), value); } - public int SID + public ushort TID16 + { + get => ReadUInt16LittleEndian(Data.AsSpan(Offset + 0)); + set => WriteUInt16LittleEndian(Data.AsSpan(Offset + 0), value); + } + + public ushort SID16 { get => ReadUInt16LittleEndian(Data.AsSpan(Offset + 2)); - set => WriteUInt16LittleEndian(Data.AsSpan(Offset + 2), (ushort)value); + set => WriteUInt16LittleEndian(Data.AsSpan(Offset + 2), value); } public int Game @@ -39,7 +45,7 @@ public sealed class MyStatus7b : SaveBlock public string GameSyncID { - get => Util.GetHexStringFromBytes(Data, Offset + 0x10, GameSyncIDSize / 2); + get => Util.GetHexStringFromBytes(Data.AsSpan(Offset + 0x10, GameSyncIDSize / 2)); set { if (value.Length > 16) @@ -61,7 +67,7 @@ public sealed class MyStatus7b : SaveBlock public string OT { get => SAV.GetString(OT_Trash); - set => SAV.SetString(OT_Trash, value.AsSpan(), SAV.MaxStringLengthOT, StringConverterOption.ClearZero); + set => SAV.SetString(OT_Trash, value, SAV.MaxStringLengthOT, StringConverterOption.ClearZero); } // The value here corresponds to a Trainer Class string (ranging from 000 to 383, use pkNX to get a full list). diff --git a/PKHeX.Core/Saves/Substructures/Gen7/LGPE/PokeListHeader.cs b/PKHeX.Core/Saves/Substructures/Gen7/LGPE/PokeListHeader.cs index c083f1a74..3ec689976 100644 --- a/PKHeX.Core/Saves/Substructures/Gen7/LGPE/PokeListHeader.cs +++ b/PKHeX.Core/Saves/Substructures/Gen7/LGPE/PokeListHeader.cs @@ -1,7 +1,6 @@ using System; using System.Collections.Generic; using System.Diagnostics; -using System.Linq; using static System.Buffers.Binary.BinaryPrimitives; namespace PKHeX.Core; @@ -148,7 +147,8 @@ public sealed class PokeListHeader : SaveBlock { // uh oh, we lost the starter! might have been moved out of its proper slot incorrectly. var species = SAV.Version == GameVersion.GP ? 25 : 133; - int index = Array.FindIndex(SAV.BoxData.ToArray(), z => z.Species == species && z.Form != 0); + bool IsStarter(PKM pk) => pk.Species == species && pk.Form != 0; + var index = SAV.FindSlotIndex(IsStarter, count); if (index >= 0) arr[6] = index; } diff --git a/PKHeX.Core/Saves/Substructures/Gen7/MyItem7SM.cs b/PKHeX.Core/Saves/Substructures/Gen7/MyItem7SM.cs index 71dadde09..9ea7ee9a7 100644 --- a/PKHeX.Core/Saves/Substructures/Gen7/MyItem7SM.cs +++ b/PKHeX.Core/Saves/Substructures/Gen7/MyItem7SM.cs @@ -1,4 +1,4 @@ -using System.Collections.Generic; +using System.Collections.Generic; namespace PKHeX.Core; @@ -17,14 +17,14 @@ public sealed class MyItem7SM : MyItem { get { - InventoryPouch[] pouch = + InventoryPouch7[] pouch = { - new InventoryPouch7(InventoryType.Medicine, Legal.Pouch_Medicine_SM, 999, Offset + Medicine), - new InventoryPouch7(InventoryType.Items, Legal.Pouch_Items_SM, 999, Offset + HeldItem), - new InventoryPouch7(InventoryType.TMHMs, Legal.Pouch_TMHM_SM, 1, Offset + TMHM), - new InventoryPouch7(InventoryType.Berries, Legal.Pouch_Berries_SM, 999, Offset + Berry), - new InventoryPouch7(InventoryType.KeyItems, Legal.Pouch_Key_SM, 1, Offset + KeyItem), - new InventoryPouch7(InventoryType.ZCrystals, Legal.Pouch_ZCrystal_SM, 1, Offset + ZCrystals), + new(InventoryType.Medicine, Legal.Pouch_Medicine_SM, 999, Offset + Medicine), + new(InventoryType.Items, Legal.Pouch_Items_SM, 999, Offset + HeldItem), + new(InventoryType.TMHMs, Legal.Pouch_TMHM_SM, 1, Offset + TMHM), + new(InventoryType.Berries, Legal.Pouch_Berries_SM, 999, Offset + Berry), + new(InventoryType.KeyItems, Legal.Pouch_Key_SM, 1, Offset + KeyItem), + new(InventoryType.ZCrystals, Legal.Pouch_ZCrystal_SM, 1, Offset + ZCrystals), }; return pouch.LoadAll(Data); } diff --git a/PKHeX.Core/Saves/Substructures/Gen7/MyItem7USUM.cs b/PKHeX.Core/Saves/Substructures/Gen7/MyItem7USUM.cs index 5359688f0..3f0dcb627 100644 --- a/PKHeX.Core/Saves/Substructures/Gen7/MyItem7USUM.cs +++ b/PKHeX.Core/Saves/Substructures/Gen7/MyItem7USUM.cs @@ -1,4 +1,4 @@ -using System.Collections.Generic; +using System.Collections.Generic; namespace PKHeX.Core; @@ -18,15 +18,15 @@ public sealed class MyItem7USUM : MyItem { get { - InventoryPouch[] pouch = + InventoryPouch7[] pouch = { - new InventoryPouch7(InventoryType.Medicine, Legal.Pouch_Medicine_SM, 999, Medicine), - new InventoryPouch7(InventoryType.Items, Legal.Pouch_Items_SM, 999, HeldItem), - new InventoryPouch7(InventoryType.TMHMs, Legal.Pouch_TMHM_SM, 1, TMHM), - new InventoryPouch7(InventoryType.Berries, Legal.Pouch_Berries_SM, 999, Berry), - new InventoryPouch7(InventoryType.KeyItems, Legal.Pouch_Key_USUM, 1, KeyItem), - new InventoryPouch7(InventoryType.ZCrystals, Legal.Pouch_ZCrystal_USUM, 1, ZCrystals), - new InventoryPouch7(InventoryType.BattleItems, Legal.Pouch_Roto_USUM, 999, BattleItems), + new(InventoryType.Medicine, Legal.Pouch_Medicine_SM, 999, Medicine), + new(InventoryType.Items, Legal.Pouch_Items_SM, 999, HeldItem), + new(InventoryType.TMHMs, Legal.Pouch_TMHM_SM, 1, TMHM), + new(InventoryType.Berries, Legal.Pouch_Berries_SM, 999, Berry), + new(InventoryType.KeyItems, Legal.Pouch_Key_USUM, 1, KeyItem), + new(InventoryType.ZCrystals, Legal.Pouch_ZCrystal_USUM, 1, ZCrystals), + new(InventoryType.BattleItems, Legal.Pouch_Roto_USUM, 999, BattleItems), }; return pouch.LoadAll(Data); } diff --git a/PKHeX.Core/Saves/Substructures/Gen7/MyStatus7.cs b/PKHeX.Core/Saves/Substructures/Gen7/MyStatus7.cs index d5601f04a..2380a3c4a 100644 --- a/PKHeX.Core/Saves/Substructures/Gen7/MyStatus7.cs +++ b/PKHeX.Core/Saves/Substructures/Gen7/MyStatus7.cs @@ -1,4 +1,4 @@ -using System; +using System; using static System.Buffers.Binary.BinaryPrimitives; namespace PKHeX.Core; @@ -10,16 +10,22 @@ public sealed class MyStatus7 : SaveBlock, IRegionOrigin public MyStatus7(SAV7 sav, int offset) : base(sav) => Offset = offset; - public int TID + public uint ID32 { - get => ReadUInt16LittleEndian(Data.AsSpan(Offset + 0)); - set => WriteUInt16LittleEndian(Data.AsSpan(Offset + 0), (ushort)value); + get => ReadUInt32LittleEndian(Data.AsSpan(Offset + 0)); + set => WriteUInt32LittleEndian(Data.AsSpan(Offset + 0), value); } - public int SID + public ushort TID16 + { + get => ReadUInt16LittleEndian(Data.AsSpan(Offset + 0)); + set => WriteUInt16LittleEndian(Data.AsSpan(Offset + 0), value); + } + + public ushort SID16 { get => ReadUInt16LittleEndian(Data.AsSpan(Offset + 2)); - set => WriteUInt16LittleEndian(Data.AsSpan(Offset + 2), (ushort)value); + set => WriteUInt16LittleEndian(Data.AsSpan(Offset + 2), value); } public int Game @@ -36,7 +42,7 @@ public sealed class MyStatus7 : SaveBlock, IRegionOrigin public string GameSyncID { - get => Util.GetHexStringFromBytes(Data, Offset + 0x10, GameSyncIDSize / 2); + get => Util.GetHexStringFromBytes(Data.AsSpan(Offset + 0x10, GameSyncIDSize / 2)); set { if (value.Length != GameSyncIDSize) @@ -49,7 +55,7 @@ public sealed class MyStatus7 : SaveBlock, IRegionOrigin public string NexUniqueID { - get => Util.GetHexStringFromBytes(Data, Offset + 0x18, NexUniqueIDSize / 2); + get => Util.GetHexStringFromBytes(Data.AsSpan(Offset + 0x18, NexUniqueIDSize / 2)); set { if (value.Length != NexUniqueIDSize) @@ -95,7 +101,7 @@ public sealed class MyStatus7 : SaveBlock, IRegionOrigin public string OT { get => SAV.GetString(OT_Trash); - set => SAV.SetString(OT_Trash, value.AsSpan(), SAV.MaxStringLengthOT, StringConverterOption.ClearZero); + set => SAV.SetString(OT_Trash, value, SAV.MaxStringLengthOT, StringConverterOption.ClearZero); } public int DressUpSkinColor diff --git a/PKHeX.Core/Saves/Substructures/Gen7/MysteryBlock7.cs b/PKHeX.Core/Saves/Substructures/Gen7/MysteryBlock7.cs index 92c863ad0..eaf11c460 100644 --- a/PKHeX.Core/Saves/Substructures/Gen7/MysteryBlock7.cs +++ b/PKHeX.Core/Saves/Substructures/Gen7/MysteryBlock7.cs @@ -15,12 +15,12 @@ public sealed class MysteryBlock7 : SaveBlock // Mystery Gift public bool[] MysteryGiftReceivedFlags { - get => ArrayUtil.GitBitFlagArray(Data.AsSpan(Offset + FlagStart), MaxReceivedFlag); + get => FlagUtil.GitBitFlagArray(Data.AsSpan(Offset + FlagStart), MaxReceivedFlag); set { if (value.Length != MaxReceivedFlag) return; - ArrayUtil.SetBitFlagArray(Data.AsSpan(Offset + FlagStart), value); + FlagUtil.SetBitFlagArray(Data.AsSpan(Offset + FlagStart), value); SAV.State.Edited = true; } } diff --git a/PKHeX.Core/Saves/Substructures/Gen7/QR7.cs b/PKHeX.Core/Saves/Substructures/Gen7/QR7.cs index 7f547b139..7b0a1f728 100644 --- a/PKHeX.Core/Saves/Substructures/Gen7/QR7.cs +++ b/PKHeX.Core/Saves/Substructures/Gen7/QR7.cs @@ -34,20 +34,10 @@ public static class QR7 464, 465, 473, 521, 592, 593, 668, 678, }; - private static readonly byte[] BaseQR = + private static void GetRawQR(Span dest, ushort species, byte form, bool shiny, byte gender) { - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xD2, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - }; - - private static byte[] GetRawQR(ushort species, byte form, bool shiny, int gender) - { - var basedata = (byte[])BaseQR.Clone(); - WriteUInt16LittleEndian(basedata.AsSpan(0x28), species); + dest[..6].Fill(0xFF); + WriteUInt16LittleEndian(dest[0x28..], species); var pi = PersonalTable.USUM.GetFormEntry(species, form); bool biGender = false; @@ -60,11 +50,10 @@ public static class QR7 else biGender = !GenderDifferences.Contains(species); - basedata[0x2A] = (byte)form; - basedata[0x2B] = (byte)gender; - basedata[0x2C] = shiny ? (byte)1 : (byte)0; - basedata[0x2D] = biGender ? (byte)1 : (byte)0; - return basedata; + dest[0x2A] = form; + dest[0x2B] = gender; + dest[0x2C] = shiny ? (byte)1 : (byte)0; + dest[0x2D] = biGender ? (byte)1 : (byte)0; } public static byte[] GenerateQRData(PK7 pk7, int box = 0, int slot = 0, int num_copies = 1) @@ -89,7 +78,7 @@ public static class QR7 WriteInt32LittleEndian(span[0x10..], num_copies); // No need to check max num_copies, payload parser handles it on-console. pk7.EncryptedPartyData.CopyTo(span[0x30..]); // Copy in pokemon data - GetRawQR(pk7.Species, pk7.Form, pk7.IsShiny, pk7.Gender).CopyTo(span[0x140..]); + GetRawQR(span[0x140..], pk7.Species, pk7.Form, pk7.IsShiny, (byte)pk7.Gender); var chk = Checksums.CRC16Invert(span[..0x1A0]); WriteUInt16LittleEndian(span[0x1A0..], chk); diff --git a/PKHeX.Core/Saves/Substructures/Gen8/BS/BattleTowerWork8b.cs b/PKHeX.Core/Saves/Substructures/Gen8/BS/BattleTowerWork8b.cs index 7766d9698..e047ed70a 100644 --- a/PKHeX.Core/Saves/Substructures/Gen8/BS/BattleTowerWork8b.cs +++ b/PKHeX.Core/Saves/Substructures/Gen8/BS/BattleTowerWork8b.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using System.ComponentModel; using static System.Buffers.Binary.BinaryPrimitives; @@ -49,7 +49,7 @@ public sealed class BattleTowerWork8b : SaveBlock private static void SetRecords(IReadOnlyList value) { if (value.Count != COUNT_CLASSDATA) - throw new ArgumentOutOfRangeException(nameof(value.Count)); + throw new ArgumentException($"Expected {COUNT_CLASSDATA} items, received {value.Count}.", nameof(value)); // data is already hard-referencing the original byte array. This is mostly a hack for Property Grid displays. } } diff --git a/PKHeX.Core/Saves/Substructures/Gen8/BS/BoxLayout8b.cs b/PKHeX.Core/Saves/Substructures/Gen8/BS/BoxLayout8b.cs index 889595e39..3d155ea37 100644 --- a/PKHeX.Core/Saves/Substructures/Gen8/BS/BoxLayout8b.cs +++ b/PKHeX.Core/Saves/Substructures/Gen8/BS/BoxLayout8b.cs @@ -1,4 +1,4 @@ -using System; +using System; using static System.Buffers.Binary.BinaryPrimitives; namespace PKHeX.Core; @@ -28,10 +28,10 @@ public sealed class BoxLayout8b : SaveBlock, IBoxDetailName return SAV.GetString(span); } - public void SetBoxName(int box, string value) + public void SetBoxName(int box, ReadOnlySpan value) { var span = Data.AsSpan(Offset + GetBoxNameOffset(box), SAV6.LongStringLength); - SAV.SetString(span, value.AsSpan(), StringMaxLength, StringConverterOption.ClearZero); + SAV.SetString(span, value, StringMaxLength, StringConverterOption.ClearZero); } public string GetTeamName(int team) @@ -43,11 +43,11 @@ public sealed class BoxLayout8b : SaveBlock, IBoxDetailName return SAV.GetString(span); } - public void SetTeamName(int team, string value) + public void SetTeamName(int team, ReadOnlySpan value) { var offset = Offset + GetTeamNameOffset(team); var span = Data.AsSpan(offset, TeamNameLength); - SAV.SetString(span, value.AsSpan(), TeamNameLength/2, StringConverterOption.ClearZero); + SAV.SetString(span, value, TeamNameLength/2, StringConverterOption.ClearZero); } public string this[int i] diff --git a/PKHeX.Core/Saves/Substructures/Gen8/BS/MyStatus8b.cs b/PKHeX.Core/Saves/Substructures/Gen8/BS/MyStatus8b.cs index 1790ed3ba..51222dc12 100644 --- a/PKHeX.Core/Saves/Substructures/Gen8/BS/MyStatus8b.cs +++ b/PKHeX.Core/Saves/Substructures/Gen8/BS/MyStatus8b.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.ComponentModel; using static System.Buffers.Binary.BinaryPrimitives; @@ -21,19 +21,25 @@ public sealed class MyStatus8b : SaveBlock public string OT { get => SAV.GetString(OT_Trash); - set => SAV.SetString(OT_Trash, value.AsSpan(), SAV.MaxStringLengthOT, StringConverterOption.ClearZero); + set => SAV.SetString(OT_Trash, value, SAV.MaxStringLengthOT, StringConverterOption.ClearZero); } - public int TID + public uint ID32 + { + get => ReadUInt32LittleEndian(Data.AsSpan(Offset + 0x1C)); + set => WriteUInt32LittleEndian(Data.AsSpan(Offset + 0x1C), value); + } + + public ushort TID16 { get => ReadUInt16LittleEndian(Data.AsSpan(Offset + 0x1C)); - set => WriteUInt16LittleEndian(Data.AsSpan(Offset + 0x1C), (ushort)value); + set => WriteUInt16LittleEndian(Data.AsSpan(Offset + 0x1C), value); } - public int SID + public ushort SID16 { get => ReadUInt16LittleEndian(Data.AsSpan(Offset + 0x1E)); - set => WriteUInt16LittleEndian(Data.AsSpan(Offset + 0x1E), (ushort)value); + set => WriteUInt16LittleEndian(Data.AsSpan(Offset + 0x1E), value); } public uint Money diff --git a/PKHeX.Core/Saves/Substructures/Gen8/BS/MysteryBlock8b.cs b/PKHeX.Core/Saves/Substructures/Gen8/BS/MysteryBlock8b.cs index 41a25ede3..7ff0b70f3 100644 --- a/PKHeX.Core/Saves/Substructures/Gen8/BS/MysteryBlock8b.cs +++ b/PKHeX.Core/Saves/Substructures/Gen8/BS/MysteryBlock8b.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using System.ComponentModel; using static System.Buffers.Binary.BinaryPrimitives; @@ -191,7 +191,7 @@ public sealed class RecvData8b public string OT { get => StringConverter8.GetString(Data.AsSpan(Offset + 0x1E, 0x1A)); - set => StringConverter8.SetString(Data.AsSpan(Offset + 0x1E, 0x1A), value.AsSpan(), 12, StringConverterOption.ClearZero); + set => StringConverter8.SetString(Data.AsSpan(Offset + 0x1E, 0x1A), value, 12, StringConverterOption.ClearZero); } public byte OT_Gender { get => Data[Offset + 0x38]; set => Data[Offset + 0x38] = value; } diff --git a/PKHeX.Core/Saves/Substructures/Gen8/BS/PoffinSaveData8b.cs b/PKHeX.Core/Saves/Substructures/Gen8/BS/PoffinSaveData8b.cs index de4b0155d..5c64128ac 100644 --- a/PKHeX.Core/Saves/Substructures/Gen8/BS/PoffinSaveData8b.cs +++ b/PKHeX.Core/Saves/Substructures/Gen8/BS/PoffinSaveData8b.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using System.ComponentModel; using System.Linq; @@ -44,7 +44,7 @@ public sealed class PoffinSaveData8b : SaveBlock public void SetPoffins(IReadOnlyCollection value) { if (value.Count != COUNT_POFFIN) - throw new ArgumentOutOfRangeException(nameof(value.Count)); + throw new ArgumentException($"Expected {COUNT_POFFIN} items, received {value.Count}.", nameof(value)); var ordered = value.OrderBy(z => z.IsNull).ThenBy(z => z.IsNew); int ctr = 0; foreach (var p in ordered) diff --git a/PKHeX.Core/Saves/Substructures/Gen8/BS/RandomGroup8b.cs b/PKHeX.Core/Saves/Substructures/Gen8/BS/RandomGroup8b.cs index bd698239c..a3242f328 100644 --- a/PKHeX.Core/Saves/Substructures/Gen8/BS/RandomGroup8b.cs +++ b/PKHeX.Core/Saves/Substructures/Gen8/BS/RandomGroup8b.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using System.ComponentModel; using static System.Buffers.Binary.BinaryPrimitives; @@ -69,13 +69,13 @@ public sealed class RandomSeed8b public string GroupName { get => StringConverter8.GetString(Data.AsSpan(Offset + OFS_GROUPNAME, GROUP_NAME_SIZE * 2)); - set => StringConverter8.SetString(Data.AsSpan(Offset + OFS_GROUPNAME, GROUP_NAME_SIZE * 2), value.AsSpan(), GROUP_NAME_SIZE, StringConverterOption.ClearZero); + set => StringConverter8.SetString(Data.AsSpan(Offset + OFS_GROUPNAME, GROUP_NAME_SIZE * 2), value, GROUP_NAME_SIZE, StringConverterOption.ClearZero); } public string PlayerName { get => StringConverter8.GetString(Data.AsSpan(Offset + OFS_PLAYERNAME, PERSON_NAME_SIZE * 2)); - set => StringConverter8.SetString(Data.AsSpan(Offset + OFS_PLAYERNAME, PERSON_NAME_SIZE * 2), value.AsSpan(), PERSON_NAME_SIZE, StringConverterOption.ClearZero); + set => StringConverter8.SetString(Data.AsSpan(Offset + OFS_PLAYERNAME, PERSON_NAME_SIZE * 2), value, PERSON_NAME_SIZE, StringConverterOption.ClearZero); } public bool Male { get => Data[Offset + OFS_GENDER] == 1; set => Data[Offset + OFS_GENDER] = (byte)(value ? 1 : 0); } diff --git a/PKHeX.Core/Saves/Substructures/Gen8/BS/Record8b.cs b/PKHeX.Core/Saves/Substructures/Gen8/BS/Record8b.cs index 6bd3b079c..b3ad686d4 100644 --- a/PKHeX.Core/Saves/Substructures/Gen8/BS/Record8b.cs +++ b/PKHeX.Core/Saves/Substructures/Gen8/BS/Record8b.cs @@ -1,4 +1,5 @@ -using System; +using System; +using System.Collections.Generic; using static System.Buffers.Binary.BinaryPrimitives; namespace PKHeX.Core; @@ -15,11 +16,11 @@ public sealed class Record8b : SaveBlock, IRecordStatStorage public Record8b(SAV8BS sav, int offset) : base(sav) => Offset = offset; - public static int GetMax(int recordID) => Records.MaxValue_BDSP[recordID]; + public static int GetMax(int recordID) => MaxValue_BDSP[recordID]; private static int ClampRecord(int recordID, int value) { - var max = Records.MaxValue_BDSP[recordID]; + var max = MaxValue_BDSP[recordID]; return Math.Min(max, value); } @@ -46,4 +47,72 @@ public sealed class Record8b : SaveBlock, IRecordStatStorage } public void AddRecord(int recordID, int count = 1) => SetRecord(recordID, GetRecord(recordID) + count); + + public static readonly IReadOnlyList MaxValue_BDSP = new[] + { + int.MaxValue, // CLEAR_TIME + 9_999, // DENDOU_CNT + 999_999, // CAPTURE_POKE + 999_999, // FISHING_SUCCESS + 999_999, // TAMAGO_HATCHING + 999_999, // BEAT_DOWN_POKE + 9_999, // RENSHOU_SINGLE + 9_999, // RENSHOU_SINGLE_NOW + 9_999, // RENSHOU_DOUBLE + 9_999, // RENSHOU_DOUBLE_NOW + 9_999, // RENSHOU_MASTER_SINGLE + 9_999, // RENSHOU_MASTER_SINGLE_NOW + 9_999, // RENSHOU_MASTER_DOUBLE + 9_999, // RENSHOU_MASTER_DOUBLE_NOW + 7, // BTL_TOWER_AVERAGE + 5, // CONTEST_STYLE_RANK + 5, // CONTEST_BEATIFUL_RANK + 5, // CONTEST_CUTE_RANK + 5, // CONTEST_CLEVER_RANK + 5, // CONTEST_STRONG_RANK + 9_999, // CONTEST_PLAY_SINGLE + 9_999, // CONTEST_PLAY_LOCAL + 9_999, // CONTEST_PLAY_NETWORK + 9_999, // CONTEST_WIN_SINGLE + 9_999, // CONTEST_WIN_LOCAL + 9_999, // CONTEST_WIN_NETWORK + 100, // CONTEST_RATE_SINGLE + 100, // CONTEST_RATE_LOCAL + 100, // CONTEST_RATE_NETWORK + 65_536,// CONTEST_GET_RIBBON + }; + + public static readonly Dictionary RecordList_8b = new() + { + { 00, "CLEAR_TIME" }, + { 01, "DENDOU_CNT" }, + { 02, "CAPTURE_POKE" }, + { 03, "FISHING_SUCCESS" }, + { 04, "TAMAGO_HATCHING" }, + { 05, "BEAT_DOWN_POKE" }, + { 06, "RENSHOU_SINGLE" }, + { 07, "RENSHOU_SINGLE_NOW" }, + { 08, "RENSHOU_DOUBLE" }, + { 09, "RENSHOU_DOUBLE_NOW" }, + { 10, "RENSHOU_MASTER_SINGLE" }, + { 11, "RENSHOU_MASTER_SINGLE_NOW" }, + { 12, "RENSHOU_MASTER_DOUBLE" }, + { 13, "RENSHOU_MASTER_DOUBLE_NOW" }, + { 14, "BTL_TOWER_AVERAGE" }, + { 15, "CONTEST_STYLE_RANK" }, + { 16, "CONTEST_BEATIFUL_RANK" }, + { 17, "CONTEST_CUTE_RANK" }, + { 18, "CONTEST_CLEVER_RANK" }, + { 19, "CONTEST_STRONG_RANK" }, + { 20, "CONTEST_PLAY_SINGLE" }, + { 21, "CONTEST_PLAY_LOCAL" }, + { 22, "CONTEST_PLAY_NETWORK" }, + { 23, "CONTEST_WIN_SINGLE" }, + { 24, "CONTEST_WIN_LOCAL" }, + { 25, "CONTEST_WIN_NETWORK" }, + { 26, "CONTEST_RATE_SINGLE" }, + { 27, "CONTEST_RATE_LOCAL" }, + { 28, "CONTEST_RATE_NETWORK" }, + { 29, "CONTEST_GET_RIBBON" }, + }; } diff --git a/PKHeX.Core/Saves/Substructures/Gen8/BS/RecordAddData8b.cs b/PKHeX.Core/Saves/Substructures/Gen8/BS/RecordAddData8b.cs index 4a48cc863..66494b251 100644 --- a/PKHeX.Core/Saves/Substructures/Gen8/BS/RecordAddData8b.cs +++ b/PKHeX.Core/Saves/Substructures/Gen8/BS/RecordAddData8b.cs @@ -1,4 +1,4 @@ -using System; +using System; using static System.Buffers.Binary.BinaryPrimitives; namespace PKHeX.Core; @@ -38,12 +38,11 @@ public sealed class RecordAddData8b : SaveBlock if (string.IsNullOrWhiteSpace(r.OT)) continue; - if (oldTrainer.OT != r.OT || oldTrainer.TID != r.TID || oldTrainer.SID != r.SID) + if (oldTrainer.OT != r.OT || oldTrainer.ID32 != r.ID32) continue; r.OT = newTrainer.OT; - r.SID = newTrainer.SID; - r.TID = newTrainer.TID; + r.ID32 = newTrainer.ID32; } } } @@ -63,7 +62,7 @@ public sealed class RecordAdd8b public string OT { get => StringConverter8.GetString(Data.AsSpan(Offset + 0, 0x1A)); - set => StringConverter8.SetString(Data.AsSpan(Offset + 0, 0x1A), value.AsSpan(), 12, StringConverterOption.ClearZero); + set => StringConverter8.SetString(Data.AsSpan(Offset + 0, 0x1A), value, 12, StringConverterOption.ClearZero); } // 1A reserved byte // 1B reserved byte @@ -85,16 +84,22 @@ public sealed class RecordAdd8b set => WriteInt32LittleEndian(Data.AsSpan(Offset + 0x24), value); } - public int TID + public uint ID32 { - get => ReadUInt16LittleEndian(Data.AsSpan(Offset + 0x28)); - set => WriteUInt16LittleEndian(Data.AsSpan(Offset + 0x28), (ushort)value); + get => ReadUInt32LittleEndian(Data.AsSpan(Offset + 0x28)); + set => WriteUInt32LittleEndian(Data.AsSpan(Offset + 0x28), value); } - public int SID + public ushort TID16 + { + get => ReadUInt16LittleEndian(Data.AsSpan(Offset + 0x28)); + set => WriteUInt16LittleEndian(Data.AsSpan(Offset + 0x28), value); + } + + public ushort SID16 { get => ReadUInt16LittleEndian(Data.AsSpan(Offset + 0x2A)); - set => WriteUInt16LittleEndian(Data.AsSpan(Offset + 0x2A), (ushort)value); + set => WriteUInt16LittleEndian(Data.AsSpan(Offset + 0x2A), value); } // 0x2C int32 reserved diff --git a/PKHeX.Core/Saves/Substructures/Gen8/BS/SealDeco8b.cs b/PKHeX.Core/Saves/Substructures/Gen8/BS/SealDeco8b.cs index 3bc84d042..5265642c5 100644 --- a/PKHeX.Core/Saves/Substructures/Gen8/BS/SealDeco8b.cs +++ b/PKHeX.Core/Saves/Substructures/Gen8/BS/SealDeco8b.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using System.ComponentModel; using static System.Buffers.Binary.BinaryPrimitives; @@ -39,7 +39,7 @@ public sealed class SealBallDecoData8b : SaveBlock private static void SetCapsules(IReadOnlyList value) { if (value.Count != COUNT_CAPSULE) - throw new ArgumentOutOfRangeException(nameof(value.Count)); + throw new ArgumentException($"Expected {COUNT_CAPSULE} items, received {value.Count}.", nameof(value)); // data is already hard-referencing the original byte array. This is mostly a hack for Property Grid displays. } } @@ -81,7 +81,7 @@ public sealed class SealCapsule8b private static void SetSeals(IReadOnlyList value) { if (value.Count != COUNT_SEAL) - throw new ArgumentOutOfRangeException(nameof(value.Count)); + throw new ArgumentException($"Expected {COUNT_SEAL} items, received {value.Count}.", nameof(value)); // data is already hard-referencing the original byte array. This is mostly a hack for Property Grid displays. } } diff --git a/PKHeX.Core/Saves/Substructures/Gen8/BS/Zukan8b.cs b/PKHeX.Core/Saves/Substructures/Gen8/BS/Zukan8b.cs index 5e281de66..125a17311 100644 --- a/PKHeX.Core/Saves/Substructures/Gen8/BS/Zukan8b.cs +++ b/PKHeX.Core/Saves/Substructures/Gen8/BS/Zukan8b.cs @@ -7,7 +7,7 @@ namespace PKHeX.Core; /// Pokédex structure used for Brilliant Diamond & Shining Pearl. ///
/// size 0x30B8, struct_name ZUKAN_WORK -public sealed class Zukan8b : ZukanBase +public sealed class Zukan8b : ZukanBase { /* Structure Notes: u32 [493] state: None/HeardOf/Seen/Captured @@ -137,7 +137,7 @@ public sealed class Zukan8b : ZukanBase public ZukanState8b GetState(ushort species) { - if ((uint)species > Legal.MaxSpeciesID_4) + if (species > Legal.MaxSpeciesID_4) throw new ArgumentOutOfRangeException(nameof(species)); var index = species - 1; @@ -147,7 +147,7 @@ public sealed class Zukan8b : ZukanBase public void SetState(ushort species, ZukanState8b state) { - if ((uint)species > Legal.MaxSpeciesID_4) + if (species > Legal.MaxSpeciesID_4) throw new ArgumentOutOfRangeException(nameof(species)); var index = species - 1; @@ -191,7 +191,7 @@ public sealed class Zukan8b : ZukanBase public bool GetLanguageFlag(ushort species, int language) { - if ((uint)species > Legal.MaxSpeciesID_4) + if (species > Legal.MaxSpeciesID_4) throw new ArgumentOutOfRangeException(nameof(species)); var languageBit = GetLanguageBit(language); if (languageBit == -1) @@ -205,7 +205,7 @@ public sealed class Zukan8b : ZukanBase public void SetLanguageFlag(ushort species, int language, bool value) { - if ((uint)species > Legal.MaxSpeciesID_4) + if (species > Legal.MaxSpeciesID_4) throw new ArgumentOutOfRangeException(nameof(species)); var languageBit = GetLanguageBit(language); if (languageBit == -1) @@ -221,7 +221,7 @@ public sealed class Zukan8b : ZukanBase public void SetLanguageFlags(ushort species, int value) { - if ((uint)species > Legal.MaxSpeciesID_4) + if (species > Legal.MaxSpeciesID_4) throw new ArgumentOutOfRangeException(nameof(species)); var index = species - 1; @@ -347,7 +347,7 @@ public sealed class Zukan8b : ZukanBase SetLanguageFlag(species, pk.Language, true); SetHasFormFlag(species, pk.Form, shiny, true); if (species is (int)Species.Spinda) - ((SAV8BS)SAV).ZukanExtra.SetDex(originalState, pk.EncryptionConstant, pk.Gender, shiny); + SAV.ZukanExtra.SetDex(originalState, pk.EncryptionConstant, pk.Gender, shiny); } private void SetGenderFlag(ushort species, int gender, bool shiny) @@ -464,7 +464,7 @@ public sealed class Zukan8b : ZukanBase { SetState(species, ZukanState8b.None); SetGenderFlags(species, false, false, false, false); - + var formCount = GetFormCount(species); if (formCount is not 0) { diff --git a/PKHeX.Core/Saves/Substructures/Gen8/LA/BoxLayout8a.cs b/PKHeX.Core/Saves/Substructures/Gen8/LA/BoxLayout8a.cs index 0822839a4..6c60671c9 100644 --- a/PKHeX.Core/Saves/Substructures/Gen8/LA/BoxLayout8a.cs +++ b/PKHeX.Core/Saves/Substructures/Gen8/LA/BoxLayout8a.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.ComponentModel; namespace PKHeX.Core; @@ -18,7 +18,7 @@ public sealed class BoxLayout8a : SaveBlock, IBoxDetailName private static int GetBoxNameOffset(int box) => SAV6.LongStringLength * box; private Span GetBoxNameSpan(int box) => Data.AsSpan(GetBoxNameOffset(box), SAV6.LongStringLength); public string GetBoxName(int box) => SAV.GetString(GetBoxNameSpan(box)); - public void SetBoxName(int box, string value) => SAV.SetString(GetBoxNameSpan(box), value.AsSpan(), StringMaxLength, StringConverterOption.ClearZero); + public void SetBoxName(int box, ReadOnlySpan value) => SAV.SetString(GetBoxNameSpan(box), value, StringMaxLength, StringConverterOption.ClearZero); public string this[int i] { diff --git a/PKHeX.Core/Saves/Substructures/Gen8/LA/Coordinates8a.cs b/PKHeX.Core/Saves/Substructures/Gen8/LA/Coordinates8a.cs index b89979032..6ff638e29 100644 --- a/PKHeX.Core/Saves/Substructures/Gen8/LA/Coordinates8a.cs +++ b/PKHeX.Core/Saves/Substructures/Gen8/LA/Coordinates8a.cs @@ -1,5 +1,6 @@ -using System; +using System; using System.ComponentModel; +using static System.Buffers.Binary.BinaryPrimitives; namespace PKHeX.Core; diff --git a/PKHeX.Core/Saves/Substructures/Gen8/LA/MyStatus8a.cs b/PKHeX.Core/Saves/Substructures/Gen8/LA/MyStatus8a.cs index 93ad8d029..9377e69f5 100644 --- a/PKHeX.Core/Saves/Substructures/Gen8/LA/MyStatus8a.cs +++ b/PKHeX.Core/Saves/Substructures/Gen8/LA/MyStatus8a.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.ComponentModel; using static System.Buffers.Binary.BinaryPrimitives; @@ -12,16 +12,22 @@ public sealed class MyStatus8a : SaveBlock { public MyStatus8a(SAV8LA sav, SCBlock block) : base(sav, block.Data) { } - public int TID + public uint ID32 { - get => ReadUInt16LittleEndian(Data.AsSpan(0x10)); - set => WriteUInt16LittleEndian(Data.AsSpan(0x10), (ushort)value); + get => ReadUInt32LittleEndian(Data.AsSpan(0x10)); + set => WriteUInt32LittleEndian(Data.AsSpan(0x10), value); } - public int SID + public ushort TID16 + { + get => ReadUInt16LittleEndian(Data.AsSpan(0x10)); + set => WriteUInt16LittleEndian(Data.AsSpan(0x10), value); + } + + public ushort SID16 { get => ReadUInt16LittleEndian(Data.AsSpan(0x12)); - set => WriteUInt16LittleEndian(Data.AsSpan(0x12), (ushort)value); + set => WriteUInt16LittleEndian(Data.AsSpan(0x12), value); } public int Game @@ -58,7 +64,7 @@ public sealed class MyStatus8a : SaveBlock public string OT { get => SAV.GetString(OT_Trash); - set => SAV.SetString(OT_Trash, value.AsSpan(), SAV.MaxStringLengthOT, StringConverterOption.ClearZero); + set => SAV.SetString(OT_Trash, value, SAV.MaxStringLengthOT, StringConverterOption.ClearZero); } public byte Unk_0x50 diff --git a/PKHeX.Core/Saves/Substructures/Gen8/LA/Pokedex/PokedexConstants8a.cs b/PKHeX.Core/Saves/Substructures/Gen8/LA/Pokedex/PokedexConstants8a.cs index 05449f09f..3d3fb5c7e 100644 --- a/PKHeX.Core/Saves/Substructures/Gen8/LA/Pokedex/PokedexConstants8a.cs +++ b/PKHeX.Core/Saves/Substructures/Gen8/LA/Pokedex/PokedexConstants8a.cs @@ -1,4 +1,6 @@ -namespace PKHeX.Core; +using System; + +namespace PKHeX.Core; /// /// Thresholds and research tasks used for Pokédex entries. @@ -48,7 +50,7 @@ public static class PokedexConstants8a 39113, 41161, 43209, 45257, 47305, 49353, 51401, 53449, 55497, }; - public static readonly byte[] PokemonInfoGenders = + public static ReadOnlySpan PokemonInfoGenders => new byte[] { 0x04, 0x03, 0x03, 0x08, 0x08, 0x08, 0x08, 0x03, 0x03, 0x08, 0x08, 0x08, 0x08, 0x08, 0x03, 0x03, 0x08, 0x08, 0x08, 0x08, diff --git a/PKHeX.Core/Saves/Substructures/Gen8/LA/Pokedex/PokedexSave8a.cs b/PKHeX.Core/Saves/Substructures/Gen8/LA/Pokedex/PokedexSave8a.cs index 4a01ed763..2932eef0c 100644 --- a/PKHeX.Core/Saves/Substructures/Gen8/LA/Pokedex/PokedexSave8a.cs +++ b/PKHeX.Core/Saves/Substructures/Gen8/LA/Pokedex/PokedexSave8a.cs @@ -32,7 +32,7 @@ public sealed class PokedexSave8a public static ushort GetDexIndex(PokedexType8a which, ushort species) { // Check species is valid - if ((uint)species > MaxSpeciesID) + if (species > MaxSpeciesID) return DexInvalid; // Check each form diff --git a/PKHeX.Core/Saves/Substructures/Gen8/LA/Spawners/Spawner8a.cs b/PKHeX.Core/Saves/Substructures/Gen8/LA/Spawners/Spawner8a.cs index 748be7f47..f30638c36 100644 --- a/PKHeX.Core/Saves/Substructures/Gen8/LA/Spawners/Spawner8a.cs +++ b/PKHeX.Core/Saves/Substructures/Gen8/LA/Spawners/Spawner8a.cs @@ -1,4 +1,4 @@ -using System; +using System; namespace PKHeX.Core; diff --git a/PKHeX.Core/Saves/Substructures/Gen8/SWSH/BoxLayout8.cs b/PKHeX.Core/Saves/Substructures/Gen8/SWSH/BoxLayout8.cs index c4777ef9f..5b28c5b50 100644 --- a/PKHeX.Core/Saves/Substructures/Gen8/SWSH/BoxLayout8.cs +++ b/PKHeX.Core/Saves/Substructures/Gen8/SWSH/BoxLayout8.cs @@ -1,4 +1,4 @@ -using System; +using System; namespace PKHeX.Core; @@ -13,7 +13,7 @@ public sealed class BoxLayout8 : SaveBlock, IBoxDetailName private static int GetBoxNameOffset(int box) => SAV6.LongStringLength * box; private Span GetBoxNameSpan(int box) => Data.AsSpan(GetBoxNameOffset(box), SAV6.LongStringLength); public string GetBoxName(int box) => SAV.GetString(GetBoxNameSpan(box)); - public void SetBoxName(int box, string value) => SAV.SetString(GetBoxNameSpan(box), value.AsSpan(), StringMaxLength, StringConverterOption.ClearZero); + public void SetBoxName(int box, ReadOnlySpan value) => SAV.SetString(GetBoxNameSpan(box), value, StringMaxLength, StringConverterOption.ClearZero); public string this[int i] { diff --git a/PKHeX.Core/Saves/Substructures/Gen8/SWSH/FashionUnlock8.cs b/PKHeX.Core/Saves/Substructures/Gen8/SWSH/FashionUnlock8.cs index 37713f72e..e44348003 100644 --- a/PKHeX.Core/Saves/Substructures/Gen8/SWSH/FashionUnlock8.cs +++ b/PKHeX.Core/Saves/Substructures/Gen8/SWSH/FashionUnlock8.cs @@ -10,13 +10,13 @@ public sealed class FashionUnlock8 : SaveBlock public FashionUnlock8(SAV8SWSH sav, SCBlock block) : base(sav, block.Data) { } - public bool[] GetArrayOwnedFlag(int region) => ArrayUtil.GitBitFlagArray(Data.AsSpan(region * SIZE_ENTRY), SIZE_ENTRY * 8); - public bool[] GetArrayNewFlag(int region) => ArrayUtil.GitBitFlagArray(Data.AsSpan((region + REGIONS) * SIZE_ENTRY), SIZE_ENTRY * 8); + public bool[] GetArrayOwnedFlag(int region) => FlagUtil.GitBitFlagArray(Data.AsSpan(region * SIZE_ENTRY), SIZE_ENTRY * 8); + public bool[] GetArrayNewFlag(int region) => FlagUtil.GitBitFlagArray(Data.AsSpan((region + REGIONS) * SIZE_ENTRY), SIZE_ENTRY * 8); public int[] GetIndexesOwnedFlag(int region) => GetIndexes(GetArrayOwnedFlag(region)); public int[] GetIndexesNewFlag(int region) => GetIndexes(GetArrayNewFlag(region)); - public void SetArrayOwnedFlag(int region, Span value) => ArrayUtil.SetBitFlagArray(Data.AsSpan(region * SIZE_ENTRY), value); - public void SetArrayNewFlag(int region, Span value) => ArrayUtil.SetBitFlagArray(Data.AsSpan((region + REGIONS) * SIZE_ENTRY), value); + public void SetArrayOwnedFlag(int region, Span value) => FlagUtil.SetBitFlagArray(Data.AsSpan(region * SIZE_ENTRY), value); + public void SetArrayNewFlag(int region, Span value) => FlagUtil.SetBitFlagArray(Data.AsSpan((region + REGIONS) * SIZE_ENTRY), value); public void SetIndexesOwnedFlag(int region, ReadOnlySpan value) => SetArrayOwnedFlag(region, SetIndexes(value)); public void SetIndexesNewFlag(int region, ReadOnlySpan value) => SetArrayNewFlag(region, SetIndexes(value)); diff --git a/PKHeX.Core/Saves/Substructures/Gen8/SWSH/MyItem8.cs b/PKHeX.Core/Saves/Substructures/Gen8/SWSH/MyItem8.cs index 1ad4d0bec..4d40196ae 100644 --- a/PKHeX.Core/Saves/Substructures/Gen8/SWSH/MyItem8.cs +++ b/PKHeX.Core/Saves/Substructures/Gen8/SWSH/MyItem8.cs @@ -21,17 +21,17 @@ public sealed class MyItem8 : MyItem { get { - var pouch = new InventoryPouch[] + InventoryPouch8[] pouch = { - new InventoryPouch8(InventoryType.Medicine, Legal.Pouch_Medicine_SWSH, 999, Medicine, PouchSize8.Medicine, IsItemLegal), - new InventoryPouch8(InventoryType.Balls, Legal.Pouch_Ball_SWSH, 999, Balls, PouchSize8.Balls, IsItemLegal), - new InventoryPouch8(InventoryType.BattleItems, Legal.Pouch_Battle_SWSH, 999, Battle, PouchSize8.Battle, IsItemLegal), - new InventoryPouch8(InventoryType.Berries, Legal.Pouch_Berries_SWSH, 999, Berries, PouchSize8.Berries, IsItemLegal), - new InventoryPouch8(InventoryType.Items, Legal.Pouch_Regular_SWSH, 999, Items, PouchSize8.Items, IsItemLegal), - new InventoryPouch8(InventoryType.TMHMs, Legal.Pouch_TMHM_SWSH, 999, TMs, PouchSize8.TMs, IsItemLegal), - new InventoryPouch8(InventoryType.MailItems, Legal.Pouch_Treasure_SWSH, 999, Treasures, PouchSize8.Treasures, IsItemLegal), - new InventoryPouch8(InventoryType.Candy, Legal.Pouch_Ingredients_SWSH, 999, Ingredients, PouchSize8.Ingredients, IsItemLegal), - new InventoryPouch8(InventoryType.KeyItems, Legal.Pouch_Key_SWSH, 1, Key, PouchSize8.Key), + new(InventoryType.Medicine, Legal.Pouch_Medicine_SWSH, 999, Medicine, PouchSize8.Medicine, IsItemLegal), + new(InventoryType.Balls, Legal.Pouch_Ball_SWSH, 999, Balls, PouchSize8.Balls, IsItemLegal), + new(InventoryType.BattleItems, Legal.Pouch_Battle_SWSH, 999, Battle, PouchSize8.Battle, IsItemLegal), + new(InventoryType.Berries, Legal.Pouch_Berries_SWSH, 999, Berries, PouchSize8.Berries, IsItemLegal), + new(InventoryType.Items, Legal.Pouch_Regular_SWSH, 999, Items, PouchSize8.Items, IsItemLegal), + new(InventoryType.TMHMs, Legal.Pouch_TMHM_SWSH, 999, TMs, PouchSize8.TMs, IsItemLegal), + new(InventoryType.MailItems, Legal.Pouch_Treasure_SWSH, 999, Treasures, PouchSize8.Treasures, IsItemLegal), + new(InventoryType.Candy, Legal.Pouch_Ingredients_SWSH, 999, Ingredients, PouchSize8.Ingredients, IsItemLegal), + new(InventoryType.KeyItems, Legal.Pouch_Key_SWSH, 1, Key, PouchSize8.Key), }; return pouch.LoadAll(Data); } diff --git a/PKHeX.Core/Saves/Substructures/Gen8/SWSH/MyStatus8.cs b/PKHeX.Core/Saves/Substructures/Gen8/SWSH/MyStatus8.cs index 87903999a..a40d8b3cc 100644 --- a/PKHeX.Core/Saves/Substructures/Gen8/SWSH/MyStatus8.cs +++ b/PKHeX.Core/Saves/Substructures/Gen8/SWSH/MyStatus8.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Text; using static System.Buffers.Binary.BinaryPrimitives; @@ -120,17 +120,22 @@ public sealed class MyStatus8 : SaveBlock } // 8C - 9F - - public int TID + public uint ID32 { - get => ReadUInt16LittleEndian(Data.AsSpan(0xA0)); - set => WriteUInt16LittleEndian(Data.AsSpan(0xA0), (ushort)value); + get => ReadUInt32LittleEndian(Data.AsSpan(0xA0)); + set => WriteUInt32LittleEndian(Data.AsSpan(0xA0), value); } - public int SID + public ushort TID16 + { + get => ReadUInt16LittleEndian(Data.AsSpan(0xA0)); + set => WriteUInt16LittleEndian(Data.AsSpan(0xA0), value); + } + + public ushort SID16 { get => ReadUInt16LittleEndian(Data.AsSpan(0xA2)); - set => WriteUInt16LittleEndian(Data.AsSpan(0xA2), (ushort)value); + set => WriteUInt16LittleEndian(Data.AsSpan(0xA2), value); } public int Game @@ -167,7 +172,7 @@ public sealed class MyStatus8 : SaveBlock public string OT { get => SAV.GetString(OT_Trash); - set => SAV.SetString(OT_Trash, value.AsSpan(), SAV.MaxStringLengthOT, StringConverterOption.ClearZero); + set => SAV.SetString(OT_Trash, value, SAV.MaxStringLengthOT, StringConverterOption.ClearZero); } // D0 diff --git a/PKHeX.Core/Saves/Substructures/Gen8/SWSH/RaidSpawnList8.cs b/PKHeX.Core/Saves/Substructures/Gen8/SWSH/RaidSpawnList8.cs index ddc09d6b4..673ae6d83 100644 --- a/PKHeX.Core/Saves/Substructures/Gen8/SWSH/RaidSpawnList8.cs +++ b/PKHeX.Core/Saves/Substructures/Gen8/SWSH/RaidSpawnList8.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.ComponentModel; using static System.Buffers.Binary.BinaryPrimitives; @@ -46,8 +46,8 @@ public sealed class RaidSpawnList8 : SaveBlock { if (i == 16) // Watchtower, special continue; - var star = (byte)rnd.Next(0, 5); - var rand = (byte)rnd.Next(1, 101); + var star = (byte)rnd.Next(5); + var rand = (byte)(1 + rnd.Next(100)); GetRaid(i).Activate(star, rand, rare, isEvent); } } diff --git a/PKHeX.Core/Saves/Substructures/Gen8/SWSH/Record8.cs b/PKHeX.Core/Saves/Substructures/Gen8/SWSH/Record8.cs index 35b598008..40047d4a7 100644 --- a/PKHeX.Core/Saves/Substructures/Gen8/SWSH/Record8.cs +++ b/PKHeX.Core/Saves/Substructures/Gen8/SWSH/Record8.cs @@ -1,5 +1,4 @@ -using System; -using System.Collections.Generic; +using System; using System.Diagnostics; using static System.Buffers.Binary.BinaryPrimitives; @@ -9,10 +8,9 @@ public sealed class Record8 : RecordBlock { public const int RecordCount = 50; public const int WattTotal = 22; - protected override IReadOnlyList RecordMax { get; } + protected override ReadOnlySpan RecordMax => MaxType_SWSH; - public Record8(SAV8SWSH sav, SCBlock block, IReadOnlyList maxes) : base(sav, block.Data) => - RecordMax = maxes; + public Record8(SAV8SWSH sav, SCBlock block) : base(sav, block.Data) { } public override int GetRecord(int recordID) { @@ -36,4 +34,13 @@ public sealed class Record8 : RecordBlock else Trace.Fail(nameof(recordID)); } + + private static ReadOnlySpan MaxType_SWSH => new byte[] + { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + }; } diff --git a/PKHeX.Core/Saves/Substructures/Gen8/SWSH/RentalTeam8.cs b/PKHeX.Core/Saves/Substructures/Gen8/SWSH/RentalTeam8.cs index f6627d25b..72997fc69 100644 --- a/PKHeX.Core/Saves/Substructures/Gen8/SWSH/RentalTeam8.cs +++ b/PKHeX.Core/Saves/Substructures/Gen8/SWSH/RentalTeam8.cs @@ -32,10 +32,10 @@ public sealed class RentalTeam8 : IRentalTeam, IPokeGroup public RentalTeam8(byte[] data) => Data = data; public ulong ID { get => ReadUInt64LittleEndian(GetMetadataStart()); set => WriteUInt64LittleEndian(GetMetadataStart(), value); } - public string TeamID { get => StringConverter8.GetString(GetMetadataStart().Slice(8, 0x1C)); set => StringConverter8.SetString(GetMetadataStart().Slice(8, 0x1C), value.AsSpan(), 0x1C / 2); } + public string TeamID { get => StringConverter8.GetString(GetMetadataStart().Slice(8, 0x1C)); set => StringConverter8.SetString(GetMetadataStart().Slice(8, 0x1C), value, 0x1C / 2); } // 2 unused bytes, probably null terminator for TeamID - public string TeamName { get => StringConverter8.GetString(GetMetadataStart().Slice(0x26, 0x16)); set => StringConverter8.SetString(GetMetadataStart().Slice(0x26, 0x16), value.AsSpan(), 0x16 / 2); } - public string PlayerName { get => StringConverter8.GetString(GetMetadataStart().Slice(0x3C, 0x1A)); set => StringConverter8.SetString(GetMetadataStart().Slice(0x3C, 0x1A), value.AsSpan(), 0x1A / 2); } + public string TeamName { get => StringConverter8.GetString(GetMetadataStart().Slice(0x26, 0x16)); set => StringConverter8.SetString(GetMetadataStart().Slice(0x26, 0x16), value, 0x16 / 2); } + public string PlayerName { get => StringConverter8.GetString(GetMetadataStart().Slice(0x3C, 0x1A)); set => StringConverter8.SetString(GetMetadataStart().Slice(0x3C, 0x1A), value, 0x1A / 2); } public PK8 GetSlot(int slot) { diff --git a/PKHeX.Core/Saves/Substructures/Gen8/SWSH/TrainerCard8.cs b/PKHeX.Core/Saves/Substructures/Gen8/SWSH/TrainerCard8.cs index 8e0f99977..c5e2841d4 100644 --- a/PKHeX.Core/Saves/Substructures/Gen8/SWSH/TrainerCard8.cs +++ b/PKHeX.Core/Saves/Substructures/Gen8/SWSH/TrainerCard8.cs @@ -14,7 +14,7 @@ public sealed class TrainerCard8 : SaveBlock public string OT { get => SAV.GetString(OT_Trash); - set => SAV.SetString(OT_Trash, value.AsSpan(), SAV.MaxStringLengthOT, StringConverterOption.ClearZero); + set => SAV.SetString(OT_Trash, value, SAV.MaxStringLengthOT, StringConverterOption.ClearZero); } public byte Language diff --git a/PKHeX.Core/Saves/Substructures/Gen9/BoxLayout9.cs b/PKHeX.Core/Saves/Substructures/Gen9/BoxLayout9.cs index 772df1ba1..ffd789ce9 100644 --- a/PKHeX.Core/Saves/Substructures/Gen9/BoxLayout9.cs +++ b/PKHeX.Core/Saves/Substructures/Gen9/BoxLayout9.cs @@ -21,10 +21,10 @@ public sealed class BoxLayout9 : SaveBlock, IBoxDetailName return SAV.GetString(span); } - public void SetBoxName(int box, string value) + public void SetBoxName(int box, ReadOnlySpan value) { var span = GetBoxNameSpan(box); - SAV.SetString(span, value.AsSpan(), StringMaxLength, StringConverterOption.ClearZero); + SAV.SetString(span, value, StringMaxLength, StringConverterOption.ClearZero); } public string this[int i] diff --git a/PKHeX.Core/Saves/Substructures/Gen9/ConfigSave9.cs b/PKHeX.Core/Saves/Substructures/Gen9/ConfigSave9.cs index c5634f70e..cdf244ae5 100644 --- a/PKHeX.Core/Saves/Substructures/Gen9/ConfigSave9.cs +++ b/PKHeX.Core/Saves/Substructures/Gen9/ConfigSave9.cs @@ -29,7 +29,6 @@ public sealed class ConfigSave9 : SaveBlock * Last 8 bits unused? */ - public int ConfigValue { get => BinaryPrimitives.ReadInt32LittleEndian(Data.AsSpan(Offset)); diff --git a/PKHeX.Core/Saves/Substructures/Gen9/FixedSpawnList9.cs b/PKHeX.Core/Saves/Substructures/Gen9/FixedSpawnList9.cs index 2e9e646ec..c34150f6a 100644 --- a/PKHeX.Core/Saves/Substructures/Gen9/FixedSpawnList9.cs +++ b/PKHeX.Core/Saves/Substructures/Gen9/FixedSpawnList9.cs @@ -63,7 +63,7 @@ public sealed class FixedSpawnDetail private const string General = nameof(General); private const string Misc = nameof(Misc); - + [Category(Misc), Description("Unknown Hash.")] public ulong Hash { diff --git a/PKHeX.Core/Saves/Substructures/Gen9/MyItem9.cs b/PKHeX.Core/Saves/Substructures/Gen9/MyItem9.cs index 8d75ad19c..38583714a 100644 --- a/PKHeX.Core/Saves/Substructures/Gen9/MyItem9.cs +++ b/PKHeX.Core/Saves/Substructures/Gen9/MyItem9.cs @@ -31,7 +31,7 @@ public sealed class MyItem9 : MyItem item.Pouch = GetPouchIndex(GetType(itemIndex)); item.Write(span); } - + public static InventoryType GetType(ushort itemIndex) { var types = new[] @@ -93,7 +93,7 @@ public sealed class MyItem9 : MyItem } } - private InventoryPouch9 MakePouch(InventoryType type, Func? isLegal = null) + private static InventoryPouch9 MakePouch(InventoryType type, Func? isLegal = null) { ushort[] legal = GetLegal(type); var max = GetMax(type); diff --git a/PKHeX.Core/Saves/Substructures/Gen9/MyStatus9.cs b/PKHeX.Core/Saves/Substructures/Gen9/MyStatus9.cs index 5dfac04f1..56af9f53f 100644 --- a/PKHeX.Core/Saves/Substructures/Gen9/MyStatus9.cs +++ b/PKHeX.Core/Saves/Substructures/Gen9/MyStatus9.cs @@ -7,16 +7,22 @@ public sealed class MyStatus9 : SaveBlock { public MyStatus9(SAV9SV sav, SCBlock block) : base(sav, block.Data) { } - public int TID + public uint ID32 { - get => ReadUInt16LittleEndian(Data.AsSpan(0x00)); - set => WriteUInt16LittleEndian(Data.AsSpan(0x00), (ushort)value); + get => ReadUInt32LittleEndian(Data); + set => WriteUInt32LittleEndian(Data, value); } - public int SID + public ushort TID16 + { + get => ReadUInt16LittleEndian(Data.AsSpan(0x00)); + set => WriteUInt16LittleEndian(Data.AsSpan(0x00), value); + } + + public ushort SID16 { get => ReadUInt16LittleEndian(Data.AsSpan(0x02)); - set => WriteUInt16LittleEndian(Data.AsSpan(0x02), (ushort)value); + set => WriteUInt16LittleEndian(Data.AsSpan(0x02), value); } public int Game @@ -53,7 +59,7 @@ public sealed class MyStatus9 : SaveBlock public string OT { get => SAV.GetString(OT_Trash); - set => SAV.SetString(OT_Trash, value.AsSpan(), SAV.MaxStringLengthOT, StringConverterOption.ClearZero); + set => SAV.SetString(OT_Trash, value, SAV.MaxStringLengthOT, StringConverterOption.ClearZero); } public byte BirthMonth { get => Data[0x5A]; set => Data[0x5A] = value; } diff --git a/PKHeX.Core/Saves/Substructures/Gen9/RentalTeam9.cs b/PKHeX.Core/Saves/Substructures/Gen9/RentalTeam9.cs index 8fa0333ee..73fa7e78d 100644 --- a/PKHeX.Core/Saves/Substructures/Gen9/RentalTeam9.cs +++ b/PKHeX.Core/Saves/Substructures/Gen9/RentalTeam9.cs @@ -53,13 +53,13 @@ public sealed class RentalTeam9 : IRentalTeam, IPokeGroup public string PlayerName { get => StringConverter8.GetString(Player_Trash); - set => StringConverter8.SetString(Player_Trash, value.AsSpan(), 10); + set => StringConverter8.SetString(Player_Trash, value, 10); } public string TeamName { get => StringConverter8.GetString(TeamName_Trash); - set => StringConverter8.SetString(TeamName_Trash, value.AsSpan(), LEN_TEAMNAME); + set => StringConverter8.SetString(TeamName_Trash, value, LEN_TEAMNAME); } public uint EntityCount diff --git a/PKHeX.Core/Saves/Substructures/Gen9/TeamIndexes9.cs b/PKHeX.Core/Saves/Substructures/Gen9/TeamIndexes9.cs index a90102674..2f74d3694 100644 --- a/PKHeX.Core/Saves/Substructures/Gen9/TeamIndexes9.cs +++ b/PKHeX.Core/Saves/Substructures/Gen9/TeamIndexes9.cs @@ -21,7 +21,7 @@ public sealed class TeamIndexes9 : SaveBlock, ITeamIndexSet for (int i = 0; i < TeamCount * 6; i++) { - short val = ReadInt16LittleEndian(Data.AsSpan(Offset + (i * 2))); + short val = ReadInt16LittleEndian(Data.AsSpan(i * 2)); if (val < 0) { TeamSlots[i] = NONE_SELECTED; @@ -49,7 +49,7 @@ public sealed class TeamIndexes9 : SaveBlock, ITeamIndexSet public void SaveBattleTeams() { - var span = Data.AsSpan(Offset); + var span = Data.AsSpan(); for (int i = 0; i < TeamCount * 6; i++) { int index = TeamSlots[i]; diff --git a/PKHeX.Core/Saves/Substructures/Inventory/Pouch/InventoryPouch.cs b/PKHeX.Core/Saves/Substructures/Inventory/Pouch/InventoryPouch.cs index c5509b8f8..bdadc2b9f 100644 --- a/PKHeX.Core/Saves/Substructures/Inventory/Pouch/InventoryPouch.cs +++ b/PKHeX.Core/Saves/Substructures/Inventory/Pouch/InventoryPouch.cs @@ -274,7 +274,7 @@ public abstract class InventoryPouch public static class InventoryPouchExtensions { - public static IReadOnlyList LoadAll(this IReadOnlyList value, ReadOnlySpan data) + public static IReadOnlyList LoadAll(this IReadOnlyList value, ReadOnlySpan data) where T : InventoryPouch { foreach (var p in value) p.GetPouch(data); diff --git a/PKHeX.Core/Saves/Substructures/Inventory/Pouch/InventoryPouch7.cs b/PKHeX.Core/Saves/Substructures/Inventory/Pouch/InventoryPouch7.cs index 46351d5df..3892a1425 100644 --- a/PKHeX.Core/Saves/Substructures/Inventory/Pouch/InventoryPouch7.cs +++ b/PKHeX.Core/Saves/Substructures/Inventory/Pouch/InventoryPouch7.cs @@ -11,7 +11,7 @@ public sealed class InventoryPouch7 : InventoryPouch public InventoryPouch7(InventoryType type, ushort[] legal, int maxCount, int offset) : base(type, legal, maxCount, offset) { } - public override InventoryItem GetEmpty(int itemID = 0, int count = 0) => new InventoryItem7 { Index = itemID, Count = count }; + public override InventoryItem7 GetEmpty(int itemID = 0, int count = 0) => new() { Index = itemID, Count = count }; public override void GetPouch(ReadOnlySpan data) { diff --git a/PKHeX.Core/Saves/Substructures/Inventory/Pouch/InventoryPouch7b.cs b/PKHeX.Core/Saves/Substructures/Inventory/Pouch/InventoryPouch7b.cs index 34e596f62..ba55b4ff3 100644 --- a/PKHeX.Core/Saves/Substructures/Inventory/Pouch/InventoryPouch7b.cs +++ b/PKHeX.Core/Saves/Substructures/Inventory/Pouch/InventoryPouch7b.cs @@ -11,7 +11,7 @@ public sealed class InventoryPouch7b : InventoryPouch public bool SetNew { get; set; } private int[] OriginalItems = Array.Empty(); - public override InventoryItem GetEmpty(int itemID = 0, int count = 0) => new InventoryItem7b { Index = itemID, Count = count }; + public override InventoryItem7b GetEmpty(int itemID = 0, int count = 0) => new() { Index = itemID, Count = count }; public InventoryPouch7b(InventoryType type, ushort[] legal, int maxCount, int offset, int size) : base(type, legal, maxCount, offset, size) { } diff --git a/PKHeX.Core/Saves/Substructures/Inventory/Pouch/InventoryPouch8.cs b/PKHeX.Core/Saves/Substructures/Inventory/Pouch/InventoryPouch8.cs index 8a3d09fe1..4bd491301 100644 --- a/PKHeX.Core/Saves/Substructures/Inventory/Pouch/InventoryPouch8.cs +++ b/PKHeX.Core/Saves/Substructures/Inventory/Pouch/InventoryPouch8.cs @@ -14,7 +14,7 @@ public sealed class InventoryPouch8 : InventoryPouch public InventoryPouch8(InventoryType type, ushort[] legal, int maxCount, int offset, int size, Func? isLegal = null) : base(type, legal, maxCount, offset, size, isLegal) { } - public override InventoryItem GetEmpty(int itemID = 0, int count = 0) => new InventoryItem8 { Index = itemID, Count = count }; + public override InventoryItem8 GetEmpty(int itemID = 0, int count = 0) => new() { Index = itemID, Count = count }; public override void GetPouch(ReadOnlySpan data) { diff --git a/PKHeX.Core/Saves/Substructures/Inventory/Pouch/InventoryPouch8a.cs b/PKHeX.Core/Saves/Substructures/Inventory/Pouch/InventoryPouch8a.cs index 285228ac2..19c2d5565 100644 --- a/PKHeX.Core/Saves/Substructures/Inventory/Pouch/InventoryPouch8a.cs +++ b/PKHeX.Core/Saves/Substructures/Inventory/Pouch/InventoryPouch8a.cs @@ -16,7 +16,7 @@ public sealed class InventoryPouch8a : InventoryPouch Func? isLegal = null) : base(type, legal, maxCount, offset, isLegal: isLegal) => MaxSize = size; - public override InventoryItem GetEmpty(int itemID = 0, int count = 0) => new InventoryItem8a { Index = itemID, Count = count }; + public override InventoryItem8a GetEmpty(int itemID = 0, int count = 0) => new() { Index = itemID, Count = count }; public override void GetPouch(ReadOnlySpan data) { diff --git a/PKHeX.Core/Saves/Substructures/Inventory/Pouch/InventoryPouch8b.cs b/PKHeX.Core/Saves/Substructures/Inventory/Pouch/InventoryPouch8b.cs index 933f29f6f..315a54dbb 100644 --- a/PKHeX.Core/Saves/Substructures/Inventory/Pouch/InventoryPouch8b.cs +++ b/PKHeX.Core/Saves/Substructures/Inventory/Pouch/InventoryPouch8b.cs @@ -12,7 +12,7 @@ public sealed class InventoryPouch8b : InventoryPouch Func? isLegal) : base(type, legal, maxCount, offset, isLegal: isLegal) { } - public override InventoryItem GetEmpty(int itemID = 0, int count = 0) => new InventoryItem8b { Index = itemID, Count = count, IsNew = true }; + public override InventoryItem8b GetEmpty(int itemID = 0, int count = 0) => new() { Index = itemID, Count = count, IsNew = true }; public override void GetPouch(ReadOnlySpan data) { diff --git a/PKHeX.Core/Saves/Substructures/Inventory/Pouch/InventoryPouch9.cs b/PKHeX.Core/Saves/Substructures/Inventory/Pouch/InventoryPouch9.cs index f4663ed1c..04c2faf43 100644 --- a/PKHeX.Core/Saves/Substructures/Inventory/Pouch/InventoryPouch9.cs +++ b/PKHeX.Core/Saves/Substructures/Inventory/Pouch/InventoryPouch9.cs @@ -16,7 +16,7 @@ public sealed class InventoryPouch9 : InventoryPouch PouchIndex = pouch; } - public override InventoryItem GetEmpty(int itemID = 0, int count = 0) => new InventoryItem9 { Index = itemID, Count = count, IsNew = true }; + public override InventoryItem9 GetEmpty(int itemID = 0, int count = 0) => new() { Index = itemID, Count = count, IsNew = true }; public override void GetPouch(ReadOnlySpan data) { @@ -36,7 +36,7 @@ public sealed class InventoryPouch9 : InventoryPouch Items = items; } - public InventoryItem9 GetItem(ReadOnlySpan data, ushort itemID) + public static InventoryItem9 GetItem(ReadOnlySpan data, ushort itemID) { var ofs = GetItemOffset(itemID); return InventoryItem9.Read(itemID, data[ofs..]); @@ -85,17 +85,17 @@ public sealed class InventoryPouch9 : InventoryPouch } } - public static int GetItemOffset(ushort index) => (InventoryItem9.SIZE * index); + public static int GetItemOffset(ushort index) => InventoryItem9.SIZE * index; - public void ClearItem(Span data, ushort index) => InventoryItem9.Clear(data, GetItemOffset(index)); + public static void ClearItem(Span data, ushort index) => InventoryItem9.Clear(data, GetItemOffset(index)); public static int GetSuggestedCount(InventoryType t, int item, int requestVal) { - bool pick = item is >= 2334 and <= 2342 || item is >= 2385 and <= 2394; + bool pick = item is (>= 2334 and <= 2342) or (>= 2385 and <= 2394); return t switch { // Picnic table accessories are clamped to 1, let actual ingredients and sandwich picks be whatever - InventoryType.Ingredients => !pick && item is >= 2311 and <= 2400 ? 1 : requestVal, + InventoryType.Ingredients => !pick && item is (>= 2311 and <= 2400) ? 1 : requestVal, _ => requestVal, }; } diff --git a/PKHeX.Core/Saves/Substructures/Mail/Mail2.cs b/PKHeX.Core/Saves/Substructures/Mail/Mail2.cs index 33e76c32c..8ba0e22f0 100644 --- a/PKHeX.Core/Saves/Substructures/Mail/Mail2.cs +++ b/PKHeX.Core/Saves/Substructures/Mail/Mail2.cs @@ -27,7 +27,7 @@ public sealed class Mail2 : MailDetail public Mail2(SAV2 sav, int index) : base(sav.GetData(GetMailOffset(index), 0x2F), GetMailOffset(index)) { - US = !sav.Japanese && !sav.Korean; + US = sav is { Japanese: false, Korean: false }; } private static int GetMailOffset(int index) @@ -72,7 +72,7 @@ public sealed class Mail2 : MailDetail set { var span = Data.AsSpan(0, LINE_LENGTH); - SetString(span[..^1], value.AsSpan(), LINE_LENGTH - 1); + SetString(span[..^1], value, LINE_LENGTH - 1); span[^1] = 0x4E; } } @@ -83,7 +83,7 @@ public sealed class Mail2 : MailDetail set { var span = Data.AsSpan(LINE_LENGTH, LINE_LENGTH); - SetString(span[..^1], value.AsSpan(), LINE_LENGTH - 1); + SetString(span[..^1], value, LINE_LENGTH - 1); span[^1] = 0x4E; } } @@ -96,7 +96,7 @@ public sealed class Mail2 : MailDetail get => GetString(Data.AsSpan(OFS_AUTHOR, AUTHOR_LENGTH + 1)); set { - SetString(Data.AsSpan(OFS_AUTHOR, 8), value.AsSpan(), AUTHOR_LENGTH); + SetString(Data.AsSpan(OFS_AUTHOR, 8), value, AUTHOR_LENGTH); Nationality = 0; // ?? } } diff --git a/PKHeX.Core/Saves/Substructures/Mail/Mail3.cs b/PKHeX.Core/Saves/Substructures/Mail/Mail3.cs index f5015c36c..9eabac92d 100644 --- a/PKHeX.Core/Saves/Substructures/Mail/Mail3.cs +++ b/PKHeX.Core/Saves/Substructures/Mail/Mail3.cs @@ -36,7 +36,7 @@ public sealed class Mail3 : MailDetail set { var span = Data.AsSpan(0x12, 8); - StringConverter3.SetString(span, value.AsSpan(), 7, JP, StringConverterOption.ClearFF); + StringConverter3.SetString(span, value, 7, JP, StringConverterOption.ClearFF); } } diff --git a/PKHeX.Core/Saves/Substructures/Mail/Mail4.cs b/PKHeX.Core/Saves/Substructures/Mail/Mail4.cs index bfbd8e64f..8610b1ce6 100644 --- a/PKHeX.Core/Saves/Substructures/Mail/Mail4.cs +++ b/PKHeX.Core/Saves/Substructures/Mail/Mail4.cs @@ -44,7 +44,7 @@ public sealed class Mail4 : MailDetail public override byte AuthorLanguage { get => Data[5]; set => Data[5] = value; } public override byte AuthorVersion { get => Data[6]; set => Data[6] = value; } public override int MailType { get => Data[7]; set => Data[7] = (byte)value; } - public override string AuthorName { get => StringConverter4.GetString(Data.AsSpan(8, 0x10)); set => StringConverter4.SetString(Data.AsSpan(8, 0x10), value.AsSpan(), 7, StringConverterOption.ClearFF); } + public override string AuthorName { get => StringConverter4.GetString(Data.AsSpan(8, 0x10)); set => StringConverter4.SetString(Data.AsSpan(8, 0x10), value, 7, StringConverterOption.ClearFF); } public ushort GetAppearSpecies(int index) => ReadUInt16LittleEndian(Data.AsSpan(0x1C - (index * 2))); public void SetAppearSpecies(int index, ushort value) => WriteUInt16LittleEndian(Data.AsSpan(0x1C - (index * 2)), (ushort)(value == 0 ? 0xFFFF : value)); public override ushort GetMessage(int index1, int index2) => ReadUInt16LittleEndian(Data.AsSpan(0x20 + (((index1 * 4) + index2) * 2))); diff --git a/PKHeX.Core/Saves/Substructures/Mail/Mail5.cs b/PKHeX.Core/Saves/Substructures/Mail/Mail5.cs index 0bc91e2d7..6d8857f31 100644 --- a/PKHeX.Core/Saves/Substructures/Mail/Mail5.cs +++ b/PKHeX.Core/Saves/Substructures/Mail/Mail5.cs @@ -1,4 +1,4 @@ -using System; +using System; using static System.Buffers.Binary.BinaryPrimitives; namespace PKHeX.Core; @@ -40,7 +40,7 @@ public sealed class Mail5 : MailDetail public override byte AuthorLanguage { get => Data[5]; set => Data[5] = value; } public override byte AuthorVersion { get => Data[6]; set => Data[6] = value; } public override int MailType { get => Data[7]; set => Data[7] = (byte)value; } - public override string AuthorName { get => StringConverter5.GetString(Data.AsSpan(8, 0x10)); set => StringConverter5.SetString(Data.AsSpan(8, 0x10), value.AsSpan(), 7, StringConverterOption.ClearZero); } + public override string AuthorName { get => StringConverter5.GetString(Data.AsSpan(8, 0x10)); set => StringConverter5.SetString(Data.AsSpan(8, 0x10), value, 7, StringConverterOption.ClearZero); } public int GetMisc(int index) => ReadUInt16LittleEndian(Data.AsSpan(0x1C - (index * 2))); public void SetMisc(int index, int value) => WriteUInt16LittleEndian(Data.AsSpan(0x1C - (index * 2)), (ushort)value); public ushort MessageEnding { get => ReadUInt16LittleEndian(Data.AsSpan(0x1E)); set => WriteUInt16LittleEndian(Data.AsSpan(0x1E), value); } diff --git a/PKHeX.Core/Saves/Substructures/Misc/IBoxDetailName.cs b/PKHeX.Core/Saves/Substructures/Misc/IBoxDetailName.cs index 69984ee4f..b4eecec5b 100644 --- a/PKHeX.Core/Saves/Substructures/Misc/IBoxDetailName.cs +++ b/PKHeX.Core/Saves/Substructures/Misc/IBoxDetailName.cs @@ -1,4 +1,6 @@ -namespace PKHeX.Core; +using System; + +namespace PKHeX.Core; /// /// Provides details about box names within the save file. @@ -6,5 +8,5 @@ public interface IBoxDetailName { public string GetBoxName(int box); - public void SetBoxName(int box, string value); + public void SetBoxName(int box, ReadOnlySpan value); } diff --git a/PKHeX.Core/Saves/Substructures/PokeDex/PokeDexEntry9SV.cs b/PKHeX.Core/Saves/Substructures/PokeDex/PokeDexEntry9SV.cs index 0b8828240..b1400404a 100644 --- a/PKHeX.Core/Saves/Substructures/PokeDex/PokeDexEntry9SV.cs +++ b/PKHeX.Core/Saves/Substructures/PokeDex/PokeDexEntry9SV.cs @@ -62,10 +62,8 @@ public readonly ref struct PokeDexEntry9SV public void SetCaught(bool value) => SetState(value ? 3u : 2u); public void SetSeen(bool value) { - if (!value) - SetState(1); - else - SetState(GetState() | 2); + var newValue = !value ? 1 : Math.Min(GetState(), 2); + SetState(newValue); } public bool GetIsGenderSeen(int gender) => (FlagsGenderSeen & (1u << gender)) != 0; diff --git a/PKHeX.Core/Saves/Substructures/PokeDex/Zukan.cs b/PKHeX.Core/Saves/Substructures/PokeDex/Zukan.cs index 94c467dca..4fe9ef285 100644 --- a/PKHeX.Core/Saves/Substructures/PokeDex/Zukan.cs +++ b/PKHeX.Core/Saves/Substructures/PokeDex/Zukan.cs @@ -5,12 +5,12 @@ namespace PKHeX.Core; /// /// Base class for Pokédex logic operations. /// -public abstract class ZukanBase +public abstract class ZukanBase where T : SaveFile { - protected readonly SaveFile SAV; + protected readonly T SAV; public readonly int PokeDex; - protected ZukanBase(SaveFile sav, int dex) + protected ZukanBase(T sav, int dex) { SAV = sav; PokeDex = dex; @@ -76,11 +76,11 @@ public abstract class ZukanBase /// /// Base class for Pokédex operations, exposing the shared structure features used by Generations 5, 6, and 7. /// -public abstract class Zukan : ZukanBase +public abstract class Zukan : ZukanBase where T : SaveFile { protected readonly int PokeDexLanguageFlags; - protected Zukan(SaveFile sav, int dex, int langflag) : base(sav, dex) + protected Zukan(T sav, int dex, int langflag) : base(sav, dex) { PokeDexLanguageFlags = langflag; if (langflag > dex) @@ -287,7 +287,7 @@ public abstract class Zukan : ZukanBase var entry = SAV.Personal[species]; int baseBit = species - 1; - int fc = entry.FormCount; + var fc = entry.FormCount; for (byte f = 0; f < fc; f++) { if (!entry.OnlyFemale) @@ -296,7 +296,7 @@ public abstract class Zukan : ZukanBase if (shinyToo) SetAllDexSeenFlags(baseBit, f, 0, true, seen); } - if (!entry.OnlyMale && !entry.Genderless) + if (entry is { OnlyMale: false, Genderless: false }) { SetAllDexSeenFlags(baseBit, f, 1, false, seen); if (shinyToo) diff --git a/PKHeX.Core/Saves/Substructures/PokeDex/Zukan4.cs b/PKHeX.Core/Saves/Substructures/PokeDex/Zukan4.cs index f7196a880..f2cad26de 100644 --- a/PKHeX.Core/Saves/Substructures/PokeDex/Zukan4.cs +++ b/PKHeX.Core/Saves/Substructures/PokeDex/Zukan4.cs @@ -6,7 +6,7 @@ namespace PKHeX.Core; /// /// Pokédex structure used by games. /// -public sealed class Zukan4 : ZukanBase +public sealed class Zukan4 : ZukanBase { private readonly byte[] Data; private readonly int Offset; diff --git a/PKHeX.Core/Saves/Substructures/PokeDex/Zukan5.cs b/PKHeX.Core/Saves/Substructures/PokeDex/Zukan5.cs index 5c7af5d54..3593c3eac 100644 --- a/PKHeX.Core/Saves/Substructures/PokeDex/Zukan5.cs +++ b/PKHeX.Core/Saves/Substructures/PokeDex/Zukan5.cs @@ -5,7 +5,7 @@ namespace PKHeX.Core; /// /// Pokédex structure used for Generation 5 games. /// -public sealed class Zukan5 : Zukan +public sealed class Zukan5 : Zukan { protected override int OFS_SEEN => OFS_CAUGHT + BitSeenSize; protected override int OFS_CAUGHT => 0x8; @@ -23,7 +23,7 @@ public sealed class Zukan5 : Zukan DexFormIndexFetcher = DexFormUtil.GetDexFormIndexBW; } - public readonly Func DexFormIndexFetcher; + public readonly Func DexFormIndexFetcher; protected override int GetDexLangFlag(int lang) { @@ -122,7 +122,7 @@ public sealed class Zukan5 : Zukan private void SetFormFlags(ushort species, byte form, int shiny, bool value = true) { - int fc = SAV.Personal[species].FormCount; + var fc = SAV.Personal[species].FormCount; int f = DexFormIndexFetcher(species, fc); if (f < 0) return; @@ -140,9 +140,9 @@ public sealed class Zukan5 : Zukan public bool GetFormFlag(int formIndex, int flagRegion) => GetFlag(FormDex + (FormLen * flagRegion), formIndex); public void SetFormFlag(int formIndex, int flagRegion, bool value = true) => SetFlag(FormDex + (FormLen * flagRegion), formIndex, value); - private bool GetIsFormDisplayed(int f, int fc) + private bool GetIsFormDisplayed(int f, byte formCount) { - for (int i = 0; i < fc; i++) + for (byte i = 0; i < formCount; i++) { var index = f + i; if (GetFormFlag(index, 2)) // Nonshiny @@ -165,7 +165,7 @@ public sealed class Zukan5 : Zukan return result; } - public void SetLanguageBitflags(ushort species, bool[] value) + public void SetLanguageBitflags(ushort species, ReadOnlySpan value) { int bit = species - 1; for (int i = 0; i < DexLangIDCount; i++) diff --git a/PKHeX.Core/Saves/Substructures/PokeDex/Zukan6.cs b/PKHeX.Core/Saves/Substructures/PokeDex/Zukan6.cs index a6da02fc6..9e5a5af5c 100644 --- a/PKHeX.Core/Saves/Substructures/PokeDex/Zukan6.cs +++ b/PKHeX.Core/Saves/Substructures/PokeDex/Zukan6.cs @@ -7,7 +7,7 @@ namespace PKHeX.Core; /// /// Pokédex structure used for Generation 6 games. /// -public abstract class Zukan6 : Zukan +public abstract class Zukan6 : Zukan { protected override int OFS_SEEN => OFS_CAUGHT + BitSeenSize; protected override int OFS_CAUGHT => 0x8; @@ -21,7 +21,7 @@ public abstract class Zukan6 : Zukan DexFormIndexFetcher = DexFormUtil.GetDexFormIndexXY; } - private Func DexFormIndexFetcher { get; } + private Func DexFormIndexFetcher { get; } protected Zukan6(SAV6AO sav, int dex, int langflag) : base(sav, dex, langflag) { @@ -100,7 +100,7 @@ public abstract class Zukan6 : Zukan private void SetFormFlags(ushort species, byte form, int shiny, bool value = true) { - int fc = SAV.Personal[species].FormCount; + var fc = SAV.Personal[species].FormCount; int f = DexFormIndexFetcher(species, fc); if (f < 0) return; @@ -115,11 +115,11 @@ public abstract class Zukan6 : Zukan SetFormFlag(bit, 2 + shiny, value); } - private bool GetIsFormDisplayed(int f, int fc) + private bool GetIsFormDisplayed(int form, byte formCount) { - for (int i = 0; i < fc; i++) + for (byte i = 0; i < formCount; i++) { - var index = f + i; + var index = form + i; if (GetFormFlag(index, 2)) // Nonshiny return true; // already set if (GetFormFlag(index, 3)) // Shiny @@ -146,7 +146,7 @@ public abstract class Zukan6 : Zukan return result; } - public void SetLanguageBitflags(ushort species, bool[] value) + public void SetLanguageBitflags(ushort species, ReadOnlySpan value) { int bit = species - 1; for (int i = 0; i < DexLangIDCount; i++) diff --git a/PKHeX.Core/Saves/Substructures/PokeDex/Zukan7.cs b/PKHeX.Core/Saves/Substructures/PokeDex/Zukan7.cs index 9fe9e006b..83d7aca75 100644 --- a/PKHeX.Core/Saves/Substructures/PokeDex/Zukan7.cs +++ b/PKHeX.Core/Saves/Substructures/PokeDex/Zukan7.cs @@ -8,7 +8,7 @@ namespace PKHeX.Core; /// /// Pokédex structure used for Generation 7 games. /// > -public class Zukan7 : Zukan +public class Zukan7 : Zukan { private const int MAGIC = 0x2F120F17; private const int SIZE_MAGIC = 4; @@ -29,14 +29,14 @@ public class Zukan7 : Zukan public Zukan7(SAV7USUM sav, int dex, int langflag) : this(sav, dex, langflag, DexFormUtil.GetDexFormIndexUSUM) { } protected Zukan7(SAV7b sav, int dex, int langflag) : this(sav, dex, langflag, DexFormUtil.GetDexFormIndexGG) { } - private Zukan7(SaveFile sav, int dex, int langflag, Func form) : base(sav, dex, langflag) + private Zukan7(SaveFile sav, int dex, int langflag, Func form) : base(sav, dex, langflag) { DexFormIndexFetcher = form; FormBaseSpecies = GetFormIndexBaseSpeciesList(); Debug.Assert(!SAV.State.Exportable || ReadUInt32LittleEndian(SAV.Data.AsSpan(PokeDex)) == MAGIC); } - public Func DexFormIndexFetcher { get; } + public Func DexFormIndexFetcher { get; } protected sealed override void SetAllDexSeenFlags(int baseBit, byte form, int gender, bool isShiny, bool value = true) { @@ -60,7 +60,7 @@ public class Zukan7 : Zukan int formBit = baseBit; if (f > 0) // Override the bit to overwrite { - int fc = SAV.Personal[species].FormCount; + var fc = SAV.Personal[species].FormCount; if (fc > 1) // actually has forms { int index = DexFormIndexFetcher(species, fc, SAV.MaxSpeciesID - 1); @@ -190,9 +190,9 @@ public class Zukan7 : Zukan } } - public int GetDexFormIndex(ushort species, int fc, int f) + public int GetDexFormIndex(ushort species, byte formCount, int form) { - var index = DexFormIndexFetcher(species, fc, f); + var index = DexFormIndexFetcher(species, formCount, form); if (index < 0) return index; return index + SAV.MaxSpeciesID - 1; @@ -209,7 +209,7 @@ public class Zukan7 : Zukan int ctr = max + 1; for (ushort species = 1; species <= max; species++) { - int c = SAV.Personal[species].FormCount; + var c = SAV.Personal[species].FormCount; for (int f = 1; f < c; f++) { int x = GetDexFormIndex(species, c, f); @@ -228,7 +228,7 @@ public class Zukan7 : Zukan var baseSpecies = new List(); for (ushort species = 1; species <= SAV.MaxSpeciesID; species++) { - int c = SAV.Personal[species].FormCount; + var c = SAV.Personal[species].FormCount; for (int f = 1; f < c; f++) { int x = GetDexFormIndex(species, c, f); @@ -239,7 +239,7 @@ public class Zukan7 : Zukan return baseSpecies; } - public int GetBaseSpeciesGenderValue(int index) + public byte GetBaseSpeciesGenderValue(int index) { // meowstic special handling const int meow = 678; @@ -285,7 +285,7 @@ public class Zukan7 : Zukan return result; } - public void SetLanguageBitflags(ushort species, bool[] value) + public void SetLanguageBitflags(ushort species, ReadOnlySpan value) { int bit = species - 1; for (int i = 0; i < DexLangIDCount; i++) diff --git a/PKHeX.Core/Saves/Substructures/PokeDex/Zukan7b.cs b/PKHeX.Core/Saves/Substructures/PokeDex/Zukan7b.cs index b998ba36d..69a7a0947 100644 --- a/PKHeX.Core/Saves/Substructures/PokeDex/Zukan7b.cs +++ b/PKHeX.Core/Saves/Substructures/PokeDex/Zukan7b.cs @@ -29,9 +29,9 @@ public sealed class Zukan7b : Zukan7 private static bool IsBuddy(ushort species, byte form) => (species == (int)Species.Pikachu && form == 8) || (species == (int)Species.Eevee && form == 1); - public const int DefaultEntryValue = 0x7F; + public const byte DefaultEntryValue = 0x7F; - public bool GetSizeData(DexSizeType group, ushort species, byte form, out int height, out int weight) + public bool GetSizeData(DexSizeType group, ushort species, byte form, out byte height, out byte weight) { height = weight = DefaultEntryValue; if (TryGetSizeEntryIndex(species, form, out var index)) @@ -39,16 +39,16 @@ public sealed class Zukan7b : Zukan7 return false; } - public bool GetSizeData(DexSizeType group, int index, out int height, out int weight) + public bool GetSizeData(DexSizeType group, int index, out byte height, out byte weight) { var ofs = GetDexSizeOffset(group, index); var entry = SAV.Data.AsSpan(ofs); - height = ReadUInt16LittleEndian(entry) >> 1; - weight = ReadUInt16LittleEndian(entry[2..]); + height = entry[1]; + weight = entry[2]; return !IsEntryUnset(height, weight); } - private static bool IsEntryUnset(int height, int weight) => height == DefaultEntryValue && weight == DefaultEntryValue; + private static bool IsEntryUnset(byte height, byte weight) => height == DefaultEntryValue && weight == DefaultEntryValue; private void SetSizeData(PB7 pk) { @@ -61,7 +61,7 @@ public sealed class Zukan7b : Zukan7 { int ofs = GetDexSizeOffset(DexSizeType.MinHeight, index); var entry = SAV.Data.AsSpan(ofs); - var minHeight = ReadUInt16LittleEndian(entry) >> 1; + var minHeight = entry[1]; var calcHeight = PB7.GetHeightAbsolute(pk.PersonalInfo, minHeight); if (Math.Round(pk.HeightAbsolute) < Math.Round(calcHeight) || ReadUInt32LittleEndian(entry) == 0x007F00FE) // unset SetSizeData(pk, DexSizeType.MinHeight); @@ -70,7 +70,7 @@ public sealed class Zukan7b : Zukan7 { int ofs = GetDexSizeOffset(DexSizeType.MaxHeight, index); var entry = SAV.Data.AsSpan(ofs); - var maxHeight = ReadUInt16LittleEndian(entry) >> 1; + var maxHeight = entry[1]; var calcHeight = PB7.GetHeightAbsolute(pk.PersonalInfo, maxHeight); if (Math.Round(pk.HeightAbsolute) > Math.Round(calcHeight) || ReadUInt32LittleEndian(entry) == 0x007F00FE) // unset SetSizeData(pk, DexSizeType.MaxHeight); @@ -80,8 +80,8 @@ public sealed class Zukan7b : Zukan7 { int ofs = GetDexSizeOffset(DexSizeType.MinWeight, index); var entry = SAV.Data.AsSpan(ofs); - var minHeight = ReadUInt16LittleEndian(entry) >> 1; - var minWeight = ReadUInt16LittleEndian(entry[2..]); + var minHeight = entry[1]; + var minWeight = entry[2]; var calcWeight = PB7.GetWeightAbsolute(pk.PersonalInfo, minHeight, minWeight); if (Math.Round(pk.WeightAbsolute) < Math.Round(calcWeight) || ReadUInt32LittleEndian(entry) == 0x007F00FE) // unset SetSizeData(pk, DexSizeType.MinWeight); @@ -90,8 +90,8 @@ public sealed class Zukan7b : Zukan7 { int ofs = GetDexSizeOffset(DexSizeType.MaxWeight, index); var entry = SAV.Data.AsSpan(ofs); - var maxHeight = ReadUInt16LittleEndian(entry) >> 1; - var maxWeight = ReadUInt16LittleEndian(entry[2..]); + var maxHeight = entry[1]; + var maxWeight = entry[2]; var calcWeight = PB7.GetWeightAbsolute(pk.PersonalInfo, maxHeight, maxWeight); if (Math.Round(pk.WeightAbsolute) > Math.Round(calcWeight) || ReadUInt32LittleEndian(entry) == 0x007F00FE) // unset SetSizeData(pk, DexSizeType.MaxWeight); @@ -106,8 +106,8 @@ public sealed class Zukan7b : Zukan7 ushort species = pk.Species; var form = pk.Form; - int height = pk.HeightScalar; - int weight = pk.WeightScalar; + byte height = pk.HeightScalar; + byte weight = pk.WeightScalar; // update for all species in potential lineage var allspec = tree.GetEvolutionsAndPreEvolutions(species, form); @@ -115,18 +115,20 @@ public sealed class Zukan7b : Zukan7 SetSizeData(group, s, f, height, weight); } - public void SetSizeData(DexSizeType group, ushort species, byte form, int height, int weight) + public void SetSizeData(DexSizeType group, ushort species, byte form, byte height, byte weight) { if (TryGetSizeEntryIndex(species, form, out var index)) SetSizeData(group, index, height, weight); } - public void SetSizeData(DexSizeType group, int index, int height, int weight) + public void SetSizeData(DexSizeType group, int index, byte height, byte weight) { var ofs = GetDexSizeOffset(group, index); var span = SAV.Data.AsSpan(ofs); - WriteUInt16LittleEndian(span, (ushort)(height << 1)); - WriteUInt16LittleEndian(span[2..], (ushort)weight); + span[0] = 0; + span[1] = height; + span[2] = weight; + span[3] = 0; } public static bool TryGetSizeEntryIndex(ushort species, byte form, out int index) diff --git a/PKHeX.Core/Saves/Substructures/PokeDex/Zukan8.cs b/PKHeX.Core/Saves/Substructures/PokeDex/Zukan8.cs index 11c16cd26..a0a83d4b3 100644 --- a/PKHeX.Core/Saves/Substructures/PokeDex/Zukan8.cs +++ b/PKHeX.Core/Saves/Substructures/PokeDex/Zukan8.cs @@ -7,7 +7,7 @@ namespace PKHeX.Core; /// /// Pokédex structure used for . /// > -public sealed class Zukan8 : ZukanBase +public sealed class Zukan8 : ZukanBase { private readonly SCBlock Galar; private readonly SCBlock Rigel1; @@ -26,7 +26,7 @@ public sealed class Zukan8 : ZukanBase Rigel1 = rigel1; Rigel2 = rigel2; var revision = GetRevision(); - DexLookup = GetDexLookup(PersonalTable.SWSH, revision, Zukan8Index.TotalCount); + DexLookup = GetDexLookup(sav.Personal, revision, Zukan8Index.TotalCount); } /// @@ -134,10 +134,8 @@ public sealed class Zukan8 : ZukanBase public IList GetEntryNames(IReadOnlyList speciesNames) { var dex = new List(); - foreach (var d in DexLookup) + foreach (var (species, entry) in DexLookup) { - var species = d.Key; - var entry = d.Value; var name = entry.GetEntryName(speciesNames, species); dex.Add(name); } @@ -217,7 +215,7 @@ public sealed class Zukan8 : ZukanBase { if ((uint)region >= SeenRegionCount) throw new ArgumentOutOfRangeException(nameof(region)); - if ((uint)form > 63) + if (form > 63) return false; var dex = entry.DexType; @@ -539,10 +537,10 @@ public sealed class Zukan8 : ZukanBase SetAllSeen(true, shinyToo); } - private void SeenAll(ushort species, byte fc, bool shinyToo, bool value = true) + private void SeenAll(ushort species, byte formCount, bool shinyToo, bool value = true) { - var pt = PersonalTable.SWSH; - for (byte form = 0; form < fc; form++) + var pt = SAV.Personal; + for (byte form = 0; form < formCount; form++) { var pi = pt.GetFormEntry(species, form); SeenAll(species, form, value, pi, shinyToo); @@ -608,7 +606,7 @@ public sealed class Zukan8 : ZukanBase if (value) { - var pi = PersonalTable.SWSH[species]; + var pi = SAV.Personal[species]; if (shinyToo) SetDisplayShiny(species); @@ -633,7 +631,7 @@ public sealed class Zukan8 : ZukanBase private void SetAllSeen(ushort species, bool value = true, bool shinyToo = false) { - var pi = PersonalTable.SWSH[species]; + var pi = SAV.Personal[species]; var fc = pi.FormCount; if (species == (int) Species.Eternatus) fc = 1; // ignore gigantamax diff --git a/PKHeX.Core/Saves/Substructures/PokeDex/Zukan9.cs b/PKHeX.Core/Saves/Substructures/PokeDex/Zukan9.cs index 3a8494c6e..f58c49d13 100644 --- a/PKHeX.Core/Saves/Substructures/PokeDex/Zukan9.cs +++ b/PKHeX.Core/Saves/Substructures/PokeDex/Zukan9.cs @@ -5,7 +5,7 @@ namespace PKHeX.Core; /// /// Pokédex structure used for . /// > -public sealed class Zukan9 : ZukanBase +public sealed class Zukan9 : ZukanBase { private readonly SCBlock Paldea; @@ -127,9 +127,9 @@ public sealed class Zukan9 : ZukanBase return 0; } - public static (byte Group, ushort Index) GetDexIndex(ushort species) + public (byte Group, ushort Index) GetDexIndex(ushort species) { - var pt = PersonalTable.SV; + var pt = SAV.Personal; // For each form including form 0, check the dex index. var pi = pt.GetFormEntry(species, 0); if (pi.DexIndex != 0) @@ -163,36 +163,38 @@ public sealed class Zukan9 : ZukanBase SetAllSeen(true, shinyToo); } - private void SeenAll(ushort species, byte fc, bool value = true, bool shinyToo = false) + private void SeenAll(ushort species, byte formCount, bool value = true, bool shinyToo = false) { - var pt = PersonalTable.SV; - for (byte form = 0; form < fc; form++) + var pt = SAV.Personal; + for (byte form = 0; form < formCount; form++) { var pi = pt.GetFormEntry(species, form); - var val = value && pi.IsPresentInGame; - SeenAll(species, form, val, pi, shinyToo); + var seenSpecies = value; + bool seenForm = seenSpecies && pi.IsPresentInGame; + SeenAll(species, form, pi, shinyToo, seenSpecies, seenForm); } } - private void SeenAll(ushort species, byte form, bool value, IGenderDetail pi, bool shinyToo) + private void SeenAll(ushort species, byte form, IGenderDetail pi, bool shinyToo, bool seenSpecies, bool seenForm) { var entry = Get(species); - if (value && !entry.IsSeen) - entry.SetSeen(value); - if (pi.IsDualGender || !value) + if (seenSpecies && !entry.IsSeen) + entry.SetSeen(seenSpecies); + + if (!seenSpecies || (seenForm && pi.IsDualGender)) { - entry.SetIsGenderSeen(0, value); - entry.SetIsGenderSeen(1, value); + entry.SetIsGenderSeen(0, seenForm); + entry.SetIsGenderSeen(1, seenForm); } else { var gender = pi.FixedGender(); - entry.SetIsGenderSeen(gender, value); + entry.SetIsGenderSeen(gender, seenForm); } - entry.SetIsFormSeen(form, value); + entry.SetIsFormSeen(form, seenForm); - if (!value || shinyToo) - entry.SetSeenIsShiny(value); + if (!seenSpecies || shinyToo) + entry.SetSeenIsShiny(seenSpecies); } public override void CompleteDex(bool shinyToo = false) diff --git a/PKHeX.Core/Saves/Substructures/Records.cs b/PKHeX.Core/Saves/Substructures/Records.cs index 8d86231f1..2cd21e1b2 100644 --- a/PKHeX.Core/Saves/Substructures/Records.cs +++ b/PKHeX.Core/Saves/Substructures/Records.cs @@ -1,4 +1,5 @@ -using System.Collections.Generic; +using System; +using System.Collections.Generic; namespace PKHeX.Core; @@ -17,7 +18,7 @@ public static class Records /// Record ID to retrieve the maximum for /// Maximum enum values for each record /// Maximum the record can be - public static int GetMax(int recordID, IReadOnlyList maxes) + public static int GetMax(int recordID, ReadOnlySpan maxes) { if ((byte)recordID >= Count) return 0; @@ -33,13 +34,13 @@ public static class Records private static readonly int[] MaxByType = {999_999_999, 9_999_999, 999_999, 99_999, 65535, 9_999, 999, 7}; - public static byte[] DailyPairs_6 = {29, 30, 110, 111, 112, 113, 114, 115, 116, 117}; - public static byte[] DailyPairs_7 = {22, 23, 110, 111, 112, 113, 114, 115, 116, 117}; + public static ReadOnlySpan DailyPairs_6 => new byte[] {29, 30, 110, 111, 112, 113, 114, 115, 116, 117}; + public static ReadOnlySpan DailyPairs_7 => new byte[] {22, 23, 110, 111, 112, 113, 114, 115, 116, 117}; /// /// Festa pairs; if updating the lower index record, update the Festa Mission record if currently active? /// - public static byte[] FestaPairs_7 = + public static ReadOnlySpan FestaPairs_7 => new byte[] { 175, 6, 176, 33, @@ -51,116 +52,10 @@ public static class Records 184, 159, 185, 9, }; +} - public static readonly IReadOnlyList MaxType_XY = new byte[] - { - 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 2, 2, 2, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, - 3, 0, 0, 1, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - - 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, - 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, - 5, 7, 5, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, - 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, - 5, 5, 5, 5, 5, 5, 5, 6, 5, 5, - 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, - 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, - 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, - }; - - public static readonly IReadOnlyList MaxType_AO = new byte[] - { - 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 2, 2, 2, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, - 3, 0, 0, 1, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, - - 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, - 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, - 5, 7, 5, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, - 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, - 5, 5, 5, 5, 5, 5, 5, 6, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 7, 7, 7, 5, 5, 5, 5, 5, 5, 5, - 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, - }; - - public static readonly IReadOnlyList MaxType_SM = new byte[] - { - 0, 0, 0, 0, 0, 0, 2, 2, 2, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 2, 2, 2, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 2, 2, 2, 0, 0, 0, 2, 2, 0, - 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - - 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, - 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, - 5, 5, 5, 5, 5, 5, 6, 5, 5, 5, - 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, - 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, - 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, - 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, - 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, - 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, - 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, - }; - - public static readonly IReadOnlyList MaxType_USUM = new byte[] - { - 0, 0, 0, 0, 0, 0, 2, 2, 2, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 2, 2, 2, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 2, 2, 2, 0, 0, 0, 2, 2, 0, - 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, - 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - - 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, - 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, - 5, 5, 5, 5, 5, 5, 6, 5, 5, 5, - 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, - 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, - 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, - 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, - 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, - 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, - 5, 5, 4, 4, 4, 5, 5, 4, 5, 5, - }; - - public static readonly IReadOnlyList MaxType_SWSH = new byte[] - { - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - }; - +public static class RecordLists +{ public static readonly Dictionary RecordList_6 = new() { {000, "Steps Taken"}, @@ -591,72 +486,4 @@ public static class Records public const int G8BattleTowerSingleWin = 47; public const int G8BattleTowerDoubleWin = 48; - - public static readonly IReadOnlyList MaxValue_BDSP = new[] - { - int.MaxValue, // CLEAR_TIME - 9_999, // DENDOU_CNT - 999_999, // CAPTURE_POKE - 999_999, // FISHING_SUCCESS - 999_999, // TAMAGO_HATCHING - 999_999, // BEAT_DOWN_POKE - 9_999, // RENSHOU_SINGLE - 9_999, // RENSHOU_SINGLE_NOW - 9_999, // RENSHOU_DOUBLE - 9_999, // RENSHOU_DOUBLE_NOW - 9_999, // RENSHOU_MASTER_SINGLE - 9_999, // RENSHOU_MASTER_SINGLE_NOW - 9_999, // RENSHOU_MASTER_DOUBLE - 9_999, // RENSHOU_MASTER_DOUBLE_NOW - 7, // BTL_TOWER_AVERAGE - 5, // CONTEST_STYLE_RANK - 5, // CONTEST_BEATIFUL_RANK - 5, // CONTEST_CUTE_RANK - 5, // CONTEST_CLEVER_RANK - 5, // CONTEST_STRONG_RANK - 9_999, // CONTEST_PLAY_SINGLE - 9_999, // CONTEST_PLAY_LOCAL - 9_999, // CONTEST_PLAY_NETWORK - 9_999, // CONTEST_WIN_SINGLE - 9_999, // CONTEST_WIN_LOCAL - 9_999, // CONTEST_WIN_NETWORK - 100, // CONTEST_RATE_SINGLE - 100, // CONTEST_RATE_LOCAL - 100, // CONTEST_RATE_NETWORK - 65_536,// CONTEST_GET_RIBBON - }; - - public static readonly Dictionary RecordList_8b = new() - { - { 00, "CLEAR_TIME" }, - { 01, "DENDOU_CNT" }, - { 02, "CAPTURE_POKE" }, - { 03, "FISHING_SUCCESS" }, - { 04, "TAMAGO_HATCHING" }, - { 05, "BEAT_DOWN_POKE" }, - { 06, "RENSHOU_SINGLE" }, - { 07, "RENSHOU_SINGLE_NOW" }, - { 08, "RENSHOU_DOUBLE" }, - { 09, "RENSHOU_DOUBLE_NOW" }, - { 10, "RENSHOU_MASTER_SINGLE" }, - { 11, "RENSHOU_MASTER_SINGLE_NOW" }, - { 12, "RENSHOU_MASTER_DOUBLE" }, - { 13, "RENSHOU_MASTER_DOUBLE_NOW" }, - { 14, "BTL_TOWER_AVERAGE" }, - { 15, "CONTEST_STYLE_RANK" }, - { 16, "CONTEST_BEATIFUL_RANK" }, - { 17, "CONTEST_CUTE_RANK" }, - { 18, "CONTEST_CLEVER_RANK" }, - { 19, "CONTEST_STRONG_RANK" }, - { 20, "CONTEST_PLAY_SINGLE" }, - { 21, "CONTEST_PLAY_LOCAL" }, - { 22, "CONTEST_PLAY_NETWORK" }, - { 23, "CONTEST_WIN_SINGLE" }, - { 24, "CONTEST_WIN_LOCAL" }, - { 25, "CONTEST_WIN_NETWORK" }, - { 26, "CONTEST_RATE_SINGLE" }, - { 27, "CONTEST_RATE_LOCAL" }, - { 28, "CONTEST_RATE_NETWORK" }, - { 29, "CONTEST_GET_RIBBON" }, - }; } diff --git a/PKHeX.Core/Saves/Util/BinaryExportSetting.cs b/PKHeX.Core/Saves/Util/BinaryExportSetting.cs index c85db1ed2..181dcca6e 100644 --- a/PKHeX.Core/Saves/Util/BinaryExportSetting.cs +++ b/PKHeX.Core/Saves/Util/BinaryExportSetting.cs @@ -1,4 +1,4 @@ -using System; +using System; namespace PKHeX.Core; @@ -9,8 +9,3 @@ public enum BinaryExportSetting IncludeFooter = 1 << 0, IncludeHeader = 1 << 1, } - -public static class BinaryExportSettingExtensions -{ - public static bool HasFlagFast(this BinaryExportSetting value, BinaryExportSetting setting) => (value & setting) != 0; -} diff --git a/PKHeX.Core/Saves/Util/DexFormUtil.cs b/PKHeX.Core/Saves/Util/DexFormUtil.cs index a86b29783..8ab6f92d7 100644 --- a/PKHeX.Core/Saves/Util/DexFormUtil.cs +++ b/PKHeX.Core/Saves/Util/DexFormUtil.cs @@ -7,9 +7,9 @@ namespace PKHeX.Core; /// public static class DexFormUtil { - public static int GetDexFormIndexSM(ushort species, int formCount, int start) => GetDexFormBitIndex(species, formCount, start, formtable_SM); - public static int GetDexFormIndexUSUM(ushort species, int formCount, int start) => GetDexFormBitIndex(species, formCount, start, formtable_USUM); - public static int GetDexFormIndexGG(ushort species, int formCount, int start) => GetDexFormBitIndex(species, formCount, start, formtable_GG); + public static int GetDexFormIndexSM(ushort species, byte formCount, int start) => GetDexFormBitIndex(species, formCount, start, formtable_SM); + public static int GetDexFormIndexUSUM(ushort species, byte formCount, int start) => GetDexFormBitIndex(species, formCount, start, formtable_USUM); + public static int GetDexFormIndexGG(ushort species, byte formCount, int start) => GetDexFormBitIndex(species, formCount, start, formtable_GG); public static int GetDexFormCountSM(ushort species) => GetDexFormCount(species, formtable_SM); public static int GetDexFormCountUSUM(ushort species) => GetDexFormCount(species, formtable_USUM); public static int GetDexFormCountGG(ushort species) => GetDexFormCount(species, formtable_GG); @@ -94,7 +94,7 @@ public static class DexFormUtil 0x007F, 0x0002, 0x0082, 0x0002, 0x008E, 0x0002, 0x0096, 0x0003, }; - private static int GetDexFormBitIndex(ushort species, int formCount, int start, IReadOnlyList formTable) + private static int GetDexFormBitIndex(ushort species, byte formCount, int start, IReadOnlyList formTable) { int formIndex = start; for (int i = 0; i < formTable.Count; i += 2) @@ -119,7 +119,7 @@ public static class DexFormUtil return 0; } - public static int GetDexFormIndexBW(ushort species, int formCount) + public static int GetDexFormIndexBW(ushort species, byte formCount) { if (formCount < 1 || species > Legal.MaxSpeciesID_5) return -1; // invalid @@ -145,7 +145,7 @@ public static class DexFormUtil }; } - public static int GetDexFormIndexB2W2(ushort species, int formCount) + public static int GetDexFormIndexB2W2(ushort species, byte formCount) { if (formCount < 1 || species > Legal.MaxSpeciesID_5) return -1; // invalid @@ -160,7 +160,7 @@ public static class DexFormUtil }; } - public static int GetDexFormIndexXY(ushort species, int formCount) + public static int GetDexFormIndexXY(ushort species, byte formCount) { if (formCount < 1 || species > Legal.MaxSpeciesID_6) return -1; // invalid @@ -206,7 +206,7 @@ public static class DexFormUtil }; } - public static int GetDexFormIndexORAS(ushort species, int formCount) + public static int GetDexFormIndexORAS(ushort species, byte formCount) { if (formCount < 1 || species > Legal.MaxSpeciesID_6) return -1; // invalid diff --git a/PKHeX.Core/Saves/Util/Recognition/SaveHandlerGCI.cs b/PKHeX.Core/Saves/Util/Recognition/SaveHandlerGCI.cs index 83f86273f..23e6f1265 100644 --- a/PKHeX.Core/Saves/Util/Recognition/SaveHandlerGCI.cs +++ b/PKHeX.Core/Saves/Util/Recognition/SaveHandlerGCI.cs @@ -20,7 +20,7 @@ public sealed class SaveHandlerGCI : ISaveHandler { foreach (var header in headers) { - if (IsGameMatchHeader(data, header.AsSpan())) + if (IsGameMatchHeader(data, header)) return true; } return false; diff --git a/PKHeX.Core/Saves/Util/SaveUtil.cs b/PKHeX.Core/Saves/Util/SaveUtil.cs index 0699193f0..0a4f7d965 100644 --- a/PKHeX.Core/Saves/Util/SaveUtil.cs +++ b/PKHeX.Core/Saves/Util/SaveUtil.cs @@ -142,7 +142,7 @@ public static class SaveUtil /// Determines the type of the provided save data. /// Save data of which to determine the origins of /// Version Identifier or Invalid if type cannot be determined. - private static GameVersion GetSAVType(byte[] data) + private static GameVersion GetSAVType(ReadOnlySpan data) { GameVersion ver; if ((ver = GetIsG1SAV(data)) != Invalid) @@ -524,7 +524,7 @@ public static class SaveUtil /// Checks to see if the data belongs to a Gen8 save /// Save data of which to determine the type /// Version Identifier or Invalid if type cannot be determined. - private static GameVersion GetIsG8SAV(byte[] data) + private static GameVersion GetIsG8SAV(ReadOnlySpan data) { if (!SizesSWSH.Contains(data.Length)) return Invalid; @@ -544,7 +544,7 @@ public static class SaveUtil return BDSP; } - private static GameVersion GetIsG8SAV_LA(byte[] data) + private static GameVersion GetIsG8SAV_LA(ReadOnlySpan data) { if (data.Length is not (SIZE_G8LA or SIZE_G8LA_1)) return Invalid; @@ -555,7 +555,7 @@ public static class SaveUtil /// Checks to see if the data belongs to a Gen8 save /// Save data of which to determine the type /// Version Identifier or Invalid if type cannot be determined. - private static GameVersion GetIsG9SAV(byte[] data) + private static GameVersion GetIsG9SAV(ReadOnlySpan data) { if (!SizesSV.Contains(data.Length)) return Invalid; @@ -695,13 +695,12 @@ public static class SaveUtil public static SaveFile? GetVariantSAV(SAV3GCMemoryCard memCard) { // Pre-check for header/footer signatures - byte[] data = memCard.ReadSaveGameData(); - if (data.Length == 0) + var memory = memCard.ReadSaveGameData(); + if (memory.Length == 0) return null; - var split = DolphinHandler.TrySplit(data); - if (split != null) - data = split.Data; + var split = DolphinHandler.TrySplit(memory.Span); + var data = split != null ? split.Data : memory.ToArray(); SaveFile sav; switch (memCard.SelectedGameVersion) @@ -755,16 +754,8 @@ public static class SaveUtil sav.Language = (int)language; // Secondary Properties may not be used but can be filled in as template. - if (sav.Generation >= 7) - { - sav.TrainerID7 = 123456; - sav.TrainerSID7 = 1234; - } - else - { - sav.TID = 12345; - sav.SID = 54321; - } + (uint tid, uint sid) = sav.Generation >= 7 ? (123456u, 1234u) : (12345u, 54321u); + sav.SetDisplayID(tid, sid); sav.Language = (int)language; // Only set geolocation data for 3DS titles diff --git a/PKHeX.Core/Util/ArrayUtil.cs b/PKHeX.Core/Util/ArrayUtil.cs index 4bfa7cae0..01e3f3ba7 100644 --- a/PKHeX.Core/Util/ArrayUtil.cs +++ b/PKHeX.Core/Util/ArrayUtil.cs @@ -8,16 +8,6 @@ namespace PKHeX.Core; /// public static class ArrayUtil { - public static bool IsRangeEmpty(this ReadOnlySpan data, byte value = 0) - { - for (int i = data.Length - 1; i >= 0; i--) - { - if (data[i] != value) - return false; - } - return true; - } - public static int Count(this Span data, T value) where T : IEquatable { return ((ReadOnlySpan)data).Count(value); @@ -47,6 +37,9 @@ public static class ArrayUtil public static byte[] Slice(this byte[] src, int offset, int length) => src.AsSpan(offset, length).ToArray(); public static T[] Slice(this T[] src, int offset, int length) => src.AsSpan(offset, length).ToArray(); + /// + /// Checks the range (exclusive max) if the is inside. + /// public static bool WithinRange(int value, int min, int max) => min <= value && value < max; public static IEnumerable EnumerateSplit(T[] bin, int size, int start = 0) @@ -55,27 +48,6 @@ public static class ArrayUtil yield return bin.Slice(i, size); } - public static bool[] GitBitFlagArray(ReadOnlySpan data, int count) - { - bool[] result = new bool[count]; - for (int i = 0; i < result.Length; i++) - result[i] = ((data[i >> 3] >> (i & 7)) & 0x1) == 1; - return result; - } - - public static void SetBitFlagArray(Span data, ReadOnlySpan value) - { - for (int i = 0; i < value.Length; i++) - { - var ofs = i >> 3; - var mask = (1 << (i & 7)); - if (value[i]) - data[ofs] |= (byte)mask; - else - data[ofs] &= (byte)~mask; - } - } - /// /// Copies a list to the destination list, with an option to copy to a starting point. /// diff --git a/PKHeX.Core/Util/ComboItemUtil.cs b/PKHeX.Core/Util/ComboItemUtil.cs index 2bd06532b..6ded1e949 100644 --- a/PKHeX.Core/Util/ComboItemUtil.cs +++ b/PKHeX.Core/Util/ComboItemUtil.cs @@ -19,7 +19,7 @@ public static partial class Util var arr = new List(inputCSV.Count); foreach (var line in inputCSV) { - var text = StringUtil.GetNthEntry(line.AsSpan(), index, 4); + var text = StringUtil.GetNthEntry(line, index, 4); var value = line.AsSpan(0, 3); var item = new ComboItem(text, ToInt32(value)); arr.Add(item); @@ -72,7 +72,7 @@ public static partial class Util list.Add(item); } - public static void AddCBWithOffset(List cbList, IReadOnlyList inStrings, int offset, byte[] allowed) + public static void AddCBWithOffset(List cbList, IReadOnlyList inStrings, int offset, ReadOnlySpan allowed) { int beginCount = cbList.Count; cbList.Capacity += allowed.Length; @@ -136,6 +136,11 @@ public static partial class Util { private readonly Comparison Comparison; public FunctorComparer(Comparison comparison) => Comparison = comparison; - public int Compare(T x, T y) => Comparison(x, y); + public int Compare(T? x, T? y) + { + if (x == null) + return y == null ? 0 : -1; + return y == null ? 1 : Comparison(x, y); + } } } diff --git a/PKHeX.Core/Util/DateUtil.cs b/PKHeX.Core/Util/DateUtil.cs index 25d1434a9..5407592ca 100644 --- a/PKHeX.Core/Util/DateUtil.cs +++ b/PKHeX.Core/Util/DateUtil.cs @@ -1,4 +1,4 @@ -using System; +using System; namespace PKHeX.Core; @@ -57,7 +57,7 @@ public static class DateUtil var sb = new System.Text.StringBuilder(); if (value >= SecondsPerDay) sb.Append(value / SecondsPerDay).Append("d "); - sb.Append(new DateTime(0).AddSeconds(value).ToString("HH:mm:ss")); + sb.Append(new TimeOnly(ticks: value * TimeSpan.TicksPerSecond).ToString("HH:mm:ss")); if (secondsBias >= 0) sb.Append(Environment.NewLine).Append("Date: ").Append(Epoch2000.AddSeconds(value + secondsBias)); return sb.ToString(); @@ -70,13 +70,13 @@ public static class DateUtil /// Last valid date /// Random to use /// Date within the specified range, inclusive. - public static DateTime GetRandomDateWithin(DateTime start, DateTime end, Random r) + public static DateOnly GetRandomDateWithin(DateOnly start, DateOnly end, Random r) { - var delta = end - start; - var bias = r.Next(delta.Days + 1); + var delta = end.DayNumber - start.DayNumber; + var bias = r.Next(delta + 1); return start.AddDays(bias); } - /// - public static DateTime GetRandomDateWithin(DateTime start, DateTime end) => GetRandomDateWithin(start, end, Util.Rand); + /// + public static DateOnly GetRandomDateWithin(DateOnly start, DateOnly end) => GetRandomDateWithin(start, end, Util.Rand); } diff --git a/PKHeX.Core/Util/FileUtil.cs b/PKHeX.Core/Util/FileUtil.cs index 631072116..e9d95e61e 100644 --- a/PKHeX.Core/Util/FileUtil.cs +++ b/PKHeX.Core/Util/FileUtil.cs @@ -46,7 +46,7 @@ public static class FileUtil /// File extension used as a hint. /// Reference savefile used for PC Binary compatibility checks. /// Supported file object reference, null if none found. - public static object? GetSupportedFile(byte[] data, string ext, SaveFile? reference = null) + public static object? GetSupportedFile(byte[] data, ReadOnlySpan ext, SaveFile? reference = null) { if (TryGetSAV(data, out var sav)) return sav; @@ -175,7 +175,7 @@ public static class FileUtil /// Format hint /// Reference savefile used for PC Binary compatibility checks. /// True if file object reference is valid, false if none found. - public static bool TryGetPKM(byte[] data, [NotNullWhen(true)] out PKM? pk, string ext, ITrainerInfo? sav = null) + public static bool TryGetPKM(byte[] data, [NotNullWhen(true)] out PKM? pk, ReadOnlySpan ext, ITrainerInfo? sav = null) { if (ext == ".pgt") // size collision with pk6 { @@ -230,7 +230,7 @@ public static class FileUtil /// Output result /// Format hint /// True if file object reference is valid, false if none found. - public static bool TryGetMysteryGift(byte[] data, [NotNullWhen(true)] out MysteryGift? mg, string ext) + public static bool TryGetMysteryGift(byte[] data, [NotNullWhen(true)] out MysteryGift? mg, ReadOnlySpan ext) { mg = MysteryGift.GetMysteryGift(data, ext); return mg != null; diff --git a/PKHeX.Core/Util/FlagUtil.cs b/PKHeX.Core/Util/FlagUtil.cs index 5e7b16eb1..057fe457a 100644 --- a/PKHeX.Core/Util/FlagUtil.cs +++ b/PKHeX.Core/Util/FlagUtil.cs @@ -33,4 +33,27 @@ public static class FlagUtil var newValue = current | ((value ? 1 : 0) << bitIndex); arr[offset] = (byte)newValue; } + + public static bool[] GitBitFlagArray(ReadOnlySpan data, int count) + { + var result = new bool[count]; + for (int i = 0; i < count; i++) + result[i] = (data[i >> 3] & (1 << (i & 7))) != 0; + return result; + } + + public static bool[] GitBitFlagArray(ReadOnlySpan data) => GitBitFlagArray(data, data.Length << 3); + + public static void SetBitFlagArray(Span data, ReadOnlySpan value) + { + for (int i = 0; i < value.Length; i++) + { + var ofs = i >> 3; + var mask = (1 << (i & 7)); + if (value[i]) + data[ofs] |= (byte)mask; + else + data[ofs] &= (byte)~mask; + } + } } diff --git a/PKHeX.Core/Util/MessageStrings.cs b/PKHeX.Core/Util/MessageStrings.cs index b048bfb0d..18b9afe59 100644 --- a/PKHeX.Core/Util/MessageStrings.cs +++ b/PKHeX.Core/Util/MessageStrings.cs @@ -1,10 +1,13 @@ // ReSharper disable AutoPropertyCanBeMadeGetOnly.Global +using System.Diagnostics.CodeAnalysis; + namespace PKHeX.Core; /// /// Generic Message Strings used for messages shown to the user. /// +[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicProperties)] public static class MessageStrings { #region Generic Program Messages diff --git a/PKHeX.Core/Util/NetFramework/BinaryPrimitives.cs b/PKHeX.Core/Util/NetFramework/BinaryPrimitives.cs deleted file mode 100644 index 1e1a16faa..000000000 --- a/PKHeX.Core/Util/NetFramework/BinaryPrimitives.cs +++ /dev/null @@ -1,86 +0,0 @@ -#if !NET6_0_OR_GREATER -global using static PKHeX.Core.Buffers.Binary.Extra.BinaryPrimitives; -using System; -using System.Runtime.InteropServices; - -namespace PKHeX.Core.Buffers.Binary.Extra; - -internal static class BinaryPrimitives -{ - public static float ReadSingleLittleEndian(ReadOnlySpan data) - { - var value = MemoryMarshal.Read(data); - if (BitConverter.IsLittleEndian) - return value; - return ReverseEndianness(value); - } - - public static double ReadDoubleLittleEndian(ReadOnlySpan data) - { - var value = MemoryMarshal.Read(data); - if (BitConverter.IsLittleEndian) - return value; - return ReverseEndianness(value); - } - - public static float ReadSingleBigEndian(Span data) - { - var value = MemoryMarshal.Read(data); - if (!BitConverter.IsLittleEndian) - return value; - return ReverseEndianness(value); - } - - public static double ReadDoubleBigEndian(Span data) - { - var value = MemoryMarshal.Read(data); - if (!BitConverter.IsLittleEndian) - return value; - return ReverseEndianness(value); - } - - public static void WriteSingleLittleEndian(Span data, float value) - { - if (!BitConverter.IsLittleEndian) - value = ReverseEndianness(value); - MemoryMarshal.Write(data, ref value); - } - - public static void WriteDoubleLittleEndian(Span data, double value) - { - if (!BitConverter.IsLittleEndian) - value = ReverseEndianness(value); - MemoryMarshal.Write(data, ref value); - } - - public static void WriteSingleBigEndian(Span data, float value) - { - if (BitConverter.IsLittleEndian) - value = ReverseEndianness(value); - MemoryMarshal.Write(data, ref value); - } - - public static void WriteDoubleBigEndian(Span data, double value) - { - if (BitConverter.IsLittleEndian) - value = ReverseEndianness(value); - MemoryMarshal.Write(data, ref value); - } - - public static float ReverseEndianness(float input) - { - Span span = stackalloc byte[4]; - MemoryMarshal.Write(span, ref input); - span.Reverse(); - return MemoryMarshal.Read(span); - } - - public static double ReverseEndianness(double input) - { - Span span = stackalloc byte[8]; - MemoryMarshal.Write(span, ref input); - span.Reverse(); - return MemoryMarshal.Read(span); - } -} -#endif diff --git a/PKHeX.Core/Util/NetFramework/CodeAnalysis.cs b/PKHeX.Core/Util/NetFramework/CodeAnalysis.cs deleted file mode 100644 index 9f2cbec65..000000000 --- a/PKHeX.Core/Util/NetFramework/CodeAnalysis.cs +++ /dev/null @@ -1,16 +0,0 @@ -#if !NET6_0_OR_GREATER -namespace System.Diagnostics.CodeAnalysis; - -[AttributeUsage(AttributeTargets.Parameter)] -internal sealed class NotNullWhenAttribute : Attribute -{ - /// Initializes the attribute with the specified return value condition. - /// - /// The return value condition. If the method returns this value, the associated parameter will not be null. - /// - public NotNullWhenAttribute(bool returnValue) => ReturnValue = returnValue; - - /// Gets the return value condition. - public bool ReturnValue { get; } -} -#endif diff --git a/PKHeX.Core/Util/NetFramework/CompilerServices.cs b/PKHeX.Core/Util/NetFramework/CompilerServices.cs deleted file mode 100644 index 0aa82063f..000000000 --- a/PKHeX.Core/Util/NetFramework/CompilerServices.cs +++ /dev/null @@ -1,15 +0,0 @@ -#if !NET6_0_OR_GREATER -using System.Diagnostics; -using System.Diagnostics.CodeAnalysis; - -namespace System.Runtime.CompilerServices; - -/// -/// Reserved to be used by the compiler for tracking metadata. -/// This class should not be used by developers in source code. -/// -[ExcludeFromCodeCoverage, DebuggerNonUserCode] -internal static class IsExternalInit -{ -} -#endif diff --git a/PKHeX.Core/Util/NetFramework/System.cs b/PKHeX.Core/Util/NetFramework/System.cs deleted file mode 100644 index 85da8cb54..000000000 --- a/PKHeX.Core/Util/NetFramework/System.cs +++ /dev/null @@ -1,11 +0,0 @@ -#if !NET6_0_OR_GREATER -namespace System; - -public static class FutureFeatures -{ - public static bool StartsWith(this string str, char value) => str.Length != 0 && str[0] == value; - - public static bool Contains(this ReadOnlySpan data, T value) where T : IEquatable => data.IndexOf(value) != -1; - public static bool Contains(this Span data, T value) where T : IEquatable => data.IndexOf(value) != -1; -} -#endif diff --git a/PKHeX.Core/Util/NetUtil.cs b/PKHeX.Core/Util/NetUtil.cs index a969ed6e0..2ca23d0e5 100644 --- a/PKHeX.Core/Util/NetUtil.cs +++ b/PKHeX.Core/Util/NetUtil.cs @@ -1,7 +1,7 @@ -using System; +using System; using System.Diagnostics; using System.IO; -using System.Net; +using System.Net.Http; namespace PKHeX.Core; @@ -28,12 +28,11 @@ public static class NetUtil private static Stream? GetStreamFromURL(Uri url) { - var httpWebRequest = (HttpWebRequest)WebRequest.Create(url); - // The GitHub API will fail if no user agent is provided - httpWebRequest.UserAgent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.113 Safari/537.36"; - - var httpWebResponse = httpWebRequest.GetResponse(); - return httpWebResponse.GetResponseStream(); + using var client = new HttpClient(); + const string agent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.113 Safari/537.36"; + client.DefaultRequestHeaders.Add("User-Agent", agent); + var response = client.GetAsync(url).Result; + return response.IsSuccessStatusCode ? response.Content.ReadAsStreamAsync().Result : null; } } diff --git a/PKHeX.Core/Util/RandUtil.cs b/PKHeX.Core/Util/RandUtil.cs index 92bfcc594..e505cc46b 100644 --- a/PKHeX.Core/Util/RandUtil.cs +++ b/PKHeX.Core/Util/RandUtil.cs @@ -1,21 +1,10 @@ using System; -using System.Threading; namespace PKHeX.Core; public static partial class Util { - // Multithread safe rand, ha - public static Random Rand => _local.Value; - private static int randomSeed = Environment.TickCount; - - private static readonly ThreadLocal _local = new(() => - { - // threads should never really step on each other when starting, but we'll play it safe. - var seed = Interlocked.Increment(ref randomSeed); - var mix = (0x41C64E6D * seed) + 0x00006073; // why not - return new Random(mix); - }); + public static Random Rand => Random.Shared; public static uint Rand32() => Rand32(Rand); public static uint Rand32(this Random rnd) => ((uint)rnd.Next(1 << 30) << 2) | (uint)rnd.Next(1 << 2); diff --git a/PKHeX.Core/Util/ReflectUtil.cs b/PKHeX.Core/Util/ReflectUtil.cs index f461fe8cf..1805174f1 100644 --- a/PKHeX.Core/Util/ReflectUtil.cs +++ b/PKHeX.Core/Util/ReflectUtil.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; using System.Globalization; @@ -9,11 +9,15 @@ namespace PKHeX.Core; public static class ReflectUtil { - public static bool IsValueEqual(this PropertyInfo pi, object obj, object value) + public static int CompareTo(this PropertyInfo pi, object obj, object value) { var v = pi.GetValue(obj, null); var c = ConvertValue(value, pi.PropertyType); - return v.Equals(c); + if (v is null) + return 0; + if (c is IComparable c1 && v is IComparable c2) + return c2.CompareTo(c1); + return 0; } public static void SetValue(PropertyInfo pi, object obj, object value) @@ -24,8 +28,6 @@ public static class ReflectUtil public static object? GetValue(object obj, string name) => GetPropertyInfo(obj.GetType().GetTypeInfo(), name)?.GetValue(obj); public static void SetValue(object obj, string name, object value) => GetPropertyInfo(obj.GetType().GetTypeInfo(), name)?.SetValue(obj, value, null); - public static object GetValue(Type t, string propertyName) => t.GetTypeInfo().GetDeclaredProperty(propertyName).GetValue(null); - public static void SetValue(Type t, string propertyName, object value) => t.GetTypeInfo().GetDeclaredProperty(propertyName).SetValue(null, value); public static IEnumerable GetPropertiesStartWithPrefix(Type type, string prefix) { @@ -46,15 +48,18 @@ public static class ReflectUtil public static IEnumerable GetAllPropertyInfoCanWritePublic(Type type) { return type.GetTypeInfo().GetAllTypeInfo().SelectMany(GetAllProperties) - .Where(p => p.CanWrite && p.SetMethod.IsPublic); + .Where(CanWritePublic); } public static IEnumerable GetAllPropertyInfoPublic(Type type) { return type.GetTypeInfo().GetAllTypeInfo().SelectMany(GetAllProperties) - .Where(p => (p.CanRead && p.GetMethod.IsPublic) || (p.CanWrite && p.SetMethod.IsPublic)); + .Where(p => p.CanReadPublic() || p.CanWritePublic()); } + private static bool CanReadPublic(this PropertyInfo p) => p.CanRead && (p.GetMethod?.IsPublic ?? false); + private static bool CanWritePublic(this PropertyInfo p) => p.CanWrite && (p.SetMethod?.IsPublic ?? false); + public static IEnumerable GetPropertiesPublic(Type type) { return GetAllPropertyInfoPublic(type).Select(p => p.Name) @@ -65,7 +70,7 @@ public static class ReflectUtil public static IEnumerable GetPropertiesCanWritePublicDeclared(Type type) { return type.GetTypeInfo().GetAllProperties() - .Where(p => p.CanWrite && p.SetMethod.IsPublic) + .Where(CanWritePublic) .Select(p => p.Name) .Distinct() ; @@ -73,16 +78,16 @@ public static class ReflectUtil private static object? ConvertValue(object value, Type type) { - if (type == typeof(DateTime?)) // Used for PKM.MetDate and other similar properties + if (type == typeof(DateOnly?)) // Used for PKM.MetDate and other similar properties { - return DateTime.TryParseExact(value.ToString(), "yyyyMMdd", CultureInfo.InvariantCulture, DateTimeStyles.None, out DateTime dateValue) - ? new DateTime?(dateValue) + return DateOnly.TryParseExact(value.ToString(), "yyyyMMdd", CultureInfo.InvariantCulture, DateTimeStyles.None, out DateOnly dateValue) + ? new DateOnly?(dateValue) : null; } if (type.IsEnum) { - var str = value.ToString(); + var str = value.ToString() ?? string.Empty; if (int.TryParse(str, out var integer)) return Convert.ChangeType(integer, type); return Enum.Parse(type, str, true); @@ -143,14 +148,14 @@ public static class ReflectUtil public static Dictionary GetAllConstantsOfType(this Type type) where T : struct { var fields = type.GetFields(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.FlattenHierarchy); - var consts = fields.Where(fi => fi.IsLiteral && !fi.IsInitOnly && fi.FieldType == typeof(T)); - return consts.ToDictionary(x => (T)x.GetRawConstantValue(), z => z.Name); + var consts = fields.Where(fi => fi is { IsLiteral: true, IsInitOnly: false } && fi.FieldType == typeof(T)); + return consts.ToDictionary(z => (T)(z.GetRawConstantValue() ?? throw new NullReferenceException(nameof(z.Name))), z => z.Name); } public static Dictionary GetAllPropertiesOfType(this Type type, object obj) where T : class { var props = type.GetProperties(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly); var ofType = props.Where(fi => typeof(T).IsAssignableFrom(fi.PropertyType)); - return ofType.ToDictionary(x => (T)x.GetValue(obj), z => z.Name); + return ofType.ToDictionary(x => (T)(x.GetValue(obj) ?? throw new NullReferenceException(nameof(x.Name))), z => z.Name); } } diff --git a/PKHeX.Core/Util/ResourceUtil.cs b/PKHeX.Core/Util/ResourceUtil.cs index 2fc79e077..8537b9553 100644 --- a/PKHeX.Core/Util/ResourceUtil.cs +++ b/PKHeX.Core/Util/ResourceUtil.cs @@ -1,5 +1,6 @@ -using System; +using System; using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; using System.IO; using System.Reflection; @@ -157,7 +158,7 @@ public static partial class Util return LoadStringList(fileName, txt); } - public static bool IsStringListCached(string fileName, out string[] result) + public static bool IsStringListCached(string fileName, [NotNullWhen(true)] out string[]? result) { lock (getStringListLoadLock) // Make sure only one thread can read the cache return stringListCache.TryGetValue(fileName, out result); @@ -171,14 +172,11 @@ public static partial class Util { if (txt == null) return Array.Empty(); - string[] raw = FastSplit(txt.AsSpan()); - - lock (getStringListLoadLock) // Make sure only one thread can write to the cache - { - if (!stringListCache.ContainsKey(file)) // Check cache again in case of race condition - stringListCache.Add(file, raw); - } + string[] raw = FastSplit(txt); + // Make sure only one thread can write to the cache + lock (getStringListLoadLock) + stringListCache.TryAdd(file, raw); return raw; } @@ -196,7 +194,7 @@ public static partial class Util return Array.Empty(); var buffer = new byte[resource.Length]; - _ = resource.Read(buffer, 0, (int)resource.Length); + resource.ReadExactly(buffer); return buffer; } diff --git a/PKHeX.Core/Util/StringUtil.cs b/PKHeX.Core/Util/StringUtil.cs index 92d43be4e..4240d618f 100644 --- a/PKHeX.Core/Util/StringUtil.cs +++ b/PKHeX.Core/Util/StringUtil.cs @@ -16,9 +16,17 @@ public static class StringUtil /// Array of strings to search in /// Value to search for /// Index within - public static int FindIndexIgnoreCase(string[] arr, string value) => Array.FindIndex(arr, z => IsMatchIgnoreCase(z, value)); + public static int FindIndexIgnoreCase(string[] arr, ReadOnlySpan value) + { + for (int i = 0; i < arr.Length; i++) + { + if (IsMatchIgnoreCase(arr[i], value)) + return i; + } + return -1; + } - public static bool IsMatchIgnoreCase(string string1, string string2) + public static bool IsMatchIgnoreCase(ReadOnlySpan string1, ReadOnlySpan string2) { if (string1.Length != string2.Length) return false; @@ -36,8 +44,8 @@ public static class StringUtil start = line.IndexOfNth(separator, nth - 1, start + 1); var end = line.IndexOfNth(separator, 1, start + 1); if (end == -1) - return new string(line[(start + 1)..].ToArray()); - return new string(line[(start + 1)..end].ToArray()); + return new string(line[(start + 1)..]); + return new string(line[(start + 1)..end]); } private static int IndexOfNth(this ReadOnlySpan s, char t, int n, int start) @@ -69,22 +77,19 @@ public static class StringUtil return result; } - private static bool IsNum(char c) => (uint)(c - '0') <= 9; - private static bool IsHexUpper(char c) => (uint)(c - 'A') <= 5; - private static byte DecodeTuple(char _0, char _1) { byte result; - if (IsNum(_0)) + if (char.IsAsciiDigit(_0)) result = (byte)((_0 - '0') << 4); - else if (IsHexUpper(_0)) + else if (char.IsAsciiHexDigitUpper(_0)) result = (byte)((_0 - 'A' + 10) << 4); else throw new ArgumentOutOfRangeException(nameof(_0)); - if (IsNum(_1)) + if (char.IsAsciiDigit(_1)) result |= (byte)(_1 - '0'); - else if (IsHexUpper(_1)) + else if (char.IsAsciiHexDigitUpper(_1)) result |= (byte)(_1 - 'A' + 10); else throw new ArgumentOutOfRangeException(nameof(_1)); diff --git a/PKHeX.Core/Util/Util.cs b/PKHeX.Core/Util/Util.cs index bdee63386..e639f9c9e 100644 --- a/PKHeX.Core/Util/Util.cs +++ b/PKHeX.Core/Util/Util.cs @@ -1,30 +1,11 @@ using System; using System.Collections.Generic; using System.Runtime.CompilerServices; -using System.Text; namespace PKHeX.Core; public static partial class Util { - /// - public static int ToInt32(string value) => ToInt32(value.AsSpan()); - - /// - public static uint ToUInt32(string value) => ToUInt32(value.AsSpan()); - - /// - public static uint GetHexValue(string value) => GetHexValue(value.AsSpan()); - - /// - public static ulong GetHexValue64(string value) => GetHexValue64(value.AsSpan()); - - /// - public static byte[] GetBytesFromHexString(string value) => GetBytesFromHexString(value.AsSpan()); - - /// - public static string GetHexStringFromBytes(byte[] data, int offset, int length) => GetHexStringFromBytes(data.AsSpan(offset, length)); - /// /// Parses the string into an , skipping all characters except for valid digits. /// @@ -39,7 +20,7 @@ public static partial class Util bool negative = false; foreach (var c in value) { - if (IsNum(c)) + if (char.IsAsciiDigit(c)) { result *= 10; result += c; @@ -66,7 +47,7 @@ public static partial class Util foreach (var c in value) { - if (!IsNum(c)) + if (!char.IsAsciiDigit(c)) continue; result *= 10; result += (uint)(c - '0'); @@ -87,17 +68,17 @@ public static partial class Util foreach (var c in value) { - if (IsNum(c)) + if (char.IsAsciiDigit(c)) { result <<= 4; result += (uint)(c - '0'); } - else if (IsHexUpper(c)) + else if (char.IsAsciiHexDigitUpper(c)) { result <<= 4; result += (uint)(c - 'A' + 10); } - else if (IsHexLower(c)) + else if (char.IsAsciiHexDigitLower(c)) { result <<= 4; result += (uint)(c - 'a' + 10); @@ -119,17 +100,17 @@ public static partial class Util foreach (var c in value) { - if (IsNum(c)) + if (char.IsAsciiDigit(c)) { result <<= 4; result += (uint)(c - '0'); } - else if (IsHexUpper(c)) + else if (char.IsAsciiHexDigitUpper(c)) { result <<= 4; result += (uint)(c - 'A' + 10); } - else if (IsHexLower(c)) + else if (char.IsAsciiHexDigitLower(c)) { result <<= 4; result += (uint)(c - 'a' + 10); @@ -149,84 +130,73 @@ public static partial class Util return result; } - public static string GetHexStringFromBytes(ReadOnlySpan arr) - { - var sb = new StringBuilder(arr.Length * 2); - for (int i = arr.Length - 1; i >= 0; i--) - sb.AppendFormat("{0:X2}", arr[i]); - return sb.ToString(); - } + private const string HexChars = "0123456789ABCDEF"; - private static bool IsNum(char c) => (uint)(c - '0') <= 9; - private static bool IsHexUpper(char c) => (uint)(c - 'A') <= 5; - private static bool IsHexLower(char c) => (uint)(c - 'a') <= 5; - private static bool IsHex(char c) => IsNum(c) || IsHexUpper(c) || IsHexLower(c); + public static string GetHexStringFromBytes(ReadOnlySpan data) + { + System.Diagnostics.Debug.Assert(data.Length is (4 or 8 or 12 or 16)); + Span result = stackalloc char[data.Length * 2]; + for (int i = 0; i < data.Length; i++) + { + // Write tuples from the opposite side of the result buffer. + var offset = (data.Length - i - 1) * 2; + result[offset + 0] = HexChars[data[i] >> 4]; + result[offset + 1] = HexChars[data[i] & 0xF]; + } + return new string(result); + } /// /// Filters the string down to only valid hex characters, returning a new string. /// /// Input string to filter - public static string GetOnlyHex(string str) + public static string GetOnlyHex(ReadOnlySpan str) { - if (string.IsNullOrWhiteSpace(str)) + if (str.IsWhiteSpace()) return string.Empty; - var sb = new StringBuilder(str.Length); + + int ctr = 0; + Span result = stackalloc char[str.Length]; foreach (var c in str) { - if (IsHex(c)) - sb.Append(c); + if (char.IsAsciiHexDigit(c)) + result[ctr++] = c; } - return sb.ToString(); + return new string(result[..ctr]); } /// /// Returns a new string with each word converted to its appropriate title case. /// - /// Input string to modify - /// Trim ends of whitespace - public static string ToTitleCase(ReadOnlySpan str, bool trim = false) + /// Input string to modify + public static string ToTitleCase(ReadOnlySpan span) { - int start = 0; - if (trim) - { - // Get First index that isn't a space - while (start < str.Length && char.IsWhiteSpace(str[start])) - start++; - } - if (start == str.Length) + if (span.IsEmpty) return string.Empty; - int end = str.Length - 1; - if (trim) - { - // Get Last index that isn't a space - while (end > start && char.IsWhiteSpace(str[end])) - end--; - } - - var span = str.Slice(start, end - start + 1); - var sb = new StringBuilder(span.Length); + Span result = stackalloc char[span.Length]; // Add each word to the string builder. Continue from the first index that isn't a space. // Add the first character as uppercase, then add each successive character as lowercase. bool first = true; - foreach (char c in span) + for (var i = 0; i < span.Length; i++) { + char c = span[i]; if (char.IsWhiteSpace(c)) { first = true; - sb.Append(c); } else if (first) { - sb.Append(char.ToUpper(c)); + c = char.ToUpper(c); first = false; } else { - sb.Append(char.ToLower(c)); + c = char.ToLower(c); } + result[i] = c; } - return sb.ToString(); + return new string(result); } /// @@ -243,18 +213,6 @@ public static partial class Util return index < 0 ? input : input[..index]; } - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static void TrimFromFirst(StringBuilder input, char c) - { - for (int i = 0; i < input.Length; i++) - { - if (input[i] != c) - continue; - input.Remove(i, input.Length - i); - return; - } - } - public static Dictionary[] GetMultiDictionary(IReadOnlyList> nameArray, int start) { var result = new Dictionary[nameArray.Count]; diff --git a/PKHeX.Core/Util/ValueTypeTypeConverter.cs b/PKHeX.Core/Util/ValueTypeTypeConverter.cs index 70fa64223..5f6af3ba9 100644 --- a/PKHeX.Core/Util/ValueTypeTypeConverter.cs +++ b/PKHeX.Core/Util/ValueTypeTypeConverter.cs @@ -9,18 +9,19 @@ namespace PKHeX.Core; /// public sealed class ValueTypeTypeConverter : ExpandableObjectConverter { - public override bool GetCreateInstanceSupported(ITypeDescriptorContext context) => true; + public override bool GetCreateInstanceSupported(ITypeDescriptorContext? context) => true; - public override object? CreateInstance(ITypeDescriptorContext context, IDictionary propertyValues) + public override object? CreateInstance(ITypeDescriptorContext? context, IDictionary propertyValues) { - var pd = context.PropertyDescriptor; - if (pd is null) + if (context?.PropertyDescriptor is not { } pd) return null; - object? boxed = pd.GetValue(context.Instance); + var boxed = pd.GetValue(context.Instance); foreach (DictionaryEntry entry in propertyValues) { - var pi = pd.PropertyType.GetProperty(entry.Key.ToString()); + if (entry.Key.ToString() is not { } propName) + continue; + var pi = pd.PropertyType.GetProperty(propName); if (pi?.CanWrite == true) pi.SetValue(boxed, Convert.ChangeType(entry.Value, pi.PropertyType), null); } @@ -30,24 +31,24 @@ public sealed class ValueTypeTypeConverter : ExpandableObjectConverter public sealed class TypeConverterU32 : TypeConverter { - public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType) + public override bool CanConvertFrom(ITypeDescriptorContext? context, Type sourceType) { return sourceType == typeof(string) || base.CanConvertFrom(context, sourceType); } - public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType) + public override bool CanConvertTo(ITypeDescriptorContext? context, Type? destinationType) { return destinationType == typeof(string) || base.CanConvertTo(context, destinationType); } - public override object? ConvertTo(ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value, Type destinationType) + public override object? ConvertTo(ITypeDescriptorContext? context, System.Globalization.CultureInfo? culture, object? value, Type destinationType) { if (destinationType == typeof(string) && value is uint u) return $"{u:X8}"; // no 0x prefix return base.ConvertTo(context, culture, value, destinationType); } - public override object? ConvertFrom(ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value) + public override object? ConvertFrom(ITypeDescriptorContext? context, System.Globalization.CultureInfo? culture, object value) { if (value is not string input) return base.ConvertFrom(context, culture, value); @@ -59,24 +60,24 @@ public sealed class TypeConverterU32 : TypeConverter public sealed class TypeConverterU64 : TypeConverter { - public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType) + public override bool CanConvertFrom(ITypeDescriptorContext? context, Type sourceType) { return sourceType == typeof(string) || base.CanConvertFrom(context, sourceType); } - public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType) + public override bool CanConvertTo(ITypeDescriptorContext? context, Type? destinationType) { return destinationType == typeof(string) || base.CanConvertTo(context, destinationType); } - public override object? ConvertTo(ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value, Type destinationType) + public override object? ConvertTo(ITypeDescriptorContext? context, System.Globalization.CultureInfo? culture, object? value, Type destinationType) { if (destinationType == typeof(string) && value is ulong u) return $"{u:X16}"; // no 0x prefix return base.ConvertTo(context, culture, value, destinationType); } - public override object? ConvertFrom(ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value) + public override object? ConvertFrom(ITypeDescriptorContext? context, System.Globalization.CultureInfo? culture, object value) { if (value is not string input) return base.ConvertFrom(context, culture, value); diff --git a/PKHeX.Core/app.config b/PKHeX.Core/app.config deleted file mode 100644 index b45f31e87..000000000 --- a/PKHeX.Core/app.config +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/PKHeX.Drawing.Misc/PKHeX.Drawing.Misc.csproj b/PKHeX.Drawing.Misc/PKHeX.Drawing.Misc.csproj index a54f15154..0de5c264b 100644 --- a/PKHeX.Drawing.Misc/PKHeX.Drawing.Misc.csproj +++ b/PKHeX.Drawing.Misc/PKHeX.Drawing.Misc.csproj @@ -1,7 +1,7 @@ - net6.0-windows;net46 + net7.0-windows PKHeX.Drawing.Misc @@ -13,6 +13,7 @@ + @@ -30,9 +31,4 @@ - - - - - \ No newline at end of file diff --git a/PKHeX.Drawing.Misc/Util/MysteryGiftSpriteUtil.cs b/PKHeX.Drawing.Misc/Util/MysteryGiftSpriteUtil.cs index a2ede1e95..284fa58bb 100644 --- a/PKHeX.Drawing.Misc/Util/MysteryGiftSpriteUtil.cs +++ b/PKHeX.Drawing.Misc/Util/MysteryGiftSpriteUtil.cs @@ -24,7 +24,7 @@ public static class MysteryGiftSpriteUtil private static Image GetBaseImage(MysteryGift gift) { - if (gift.IsEgg && gift.Species == (int)Species.Manaphy) // Manaphy Egg + if (gift is { IsEgg: true, Species: (int)Species.Manaphy }) // Manaphy Egg return SpriteUtil.GetMysteryGiftPreviewPoke(gift); if (gift.IsEntity) return SpriteUtil.GetMysteryGiftPreviewPoke(gift); diff --git a/PKHeX.Drawing.PokeSprite/Builder/SpriteBuilder.cs b/PKHeX.Drawing.PokeSprite/Builder/SpriteBuilder.cs index 6dae96bc4..b7cd118ec 100644 --- a/PKHeX.Drawing.PokeSprite/Builder/SpriteBuilder.cs +++ b/PKHeX.Drawing.PokeSprite/Builder/SpriteBuilder.cs @@ -201,7 +201,7 @@ public abstract class SpriteBuilder : ISpriteBuilder Bitmap rare; if (shiny is Shiny.AlwaysSquare) rare = Resources.rare_icon_2; - else if (tweak.HasFlagFast(SpriteBuilderTweak.BoxBackgroundRed)) + else if (tweak.HasFlag(SpriteBuilderTweak.BoxBackgroundRed)) rare = Resources.rare_icon_alt; else rare = Resources.rare_icon; diff --git a/PKHeX.Drawing.PokeSprite/PKHeX.Drawing.PokeSprite.csproj b/PKHeX.Drawing.PokeSprite/PKHeX.Drawing.PokeSprite.csproj index a1cf64807..74883934d 100644 --- a/PKHeX.Drawing.PokeSprite/PKHeX.Drawing.PokeSprite.csproj +++ b/PKHeX.Drawing.PokeSprite/PKHeX.Drawing.PokeSprite.csproj @@ -1,10 +1,14 @@ - net6.0-windows;net46 + net7.0-windows PKHeX.Drawing.PokeSprite + + + + @@ -25,9 +29,4 @@ - - - - - diff --git a/PKHeX.Drawing.PokeSprite/Properties/Resources.Designer.cs b/PKHeX.Drawing.PokeSprite/Properties/Resources.Designer.cs index f3c6c8c4f..1260f73d7 100644 --- a/PKHeX.Drawing.PokeSprite/Properties/Resources.Designer.cs +++ b/PKHeX.Drawing.PokeSprite/Properties/Resources.Designer.cs @@ -550,6 +550,46 @@ namespace PKHeX.Drawing.PokeSprite.Properties { } } + /// + /// Looks up a localized resource of type System.Drawing.Bitmap. + /// + public static System.Drawing.Bitmap a_1007_1 { + get { + object obj = ResourceManager.GetObject("a_1007_1", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// Looks up a localized resource of type System.Drawing.Bitmap. + /// + public static System.Drawing.Bitmap a_1007_2 { + get { + object obj = ResourceManager.GetObject("a_1007_2", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// Looks up a localized resource of type System.Drawing.Bitmap. + /// + public static System.Drawing.Bitmap a_1007_3 { + get { + object obj = ResourceManager.GetObject("a_1007_3", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// Looks up a localized resource of type System.Drawing.Bitmap. + /// + public static System.Drawing.Bitmap a_1007_4 { + get { + object obj = ResourceManager.GetObject("a_1007_4", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + /// /// Looks up a localized resource of type System.Drawing.Bitmap. /// @@ -563,9 +603,39 @@ namespace PKHeX.Drawing.PokeSprite.Properties { /// /// Looks up a localized resource of type System.Drawing.Bitmap. /// - public static System.Drawing.Bitmap a_1009 { + public static System.Drawing.Bitmap a_1008_1 { get { - object obj = ResourceManager.GetObject("a_1009", resourceCulture); + object obj = ResourceManager.GetObject("a_1008_1", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// Looks up a localized resource of type System.Drawing.Bitmap. + /// + public static System.Drawing.Bitmap a_1008_2 { + get { + object obj = ResourceManager.GetObject("a_1008_2", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// Looks up a localized resource of type System.Drawing.Bitmap. + /// + public static System.Drawing.Bitmap a_1008_3 { + get { + object obj = ResourceManager.GetObject("a_1008_3", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// Looks up a localized resource of type System.Drawing.Bitmap. + /// + public static System.Drawing.Bitmap a_1008_4 { + get { + object obj = ResourceManager.GetObject("a_1008_4", resourceCulture); return ((System.Drawing.Bitmap)(obj)); } } @@ -590,16 +660,6 @@ namespace PKHeX.Drawing.PokeSprite.Properties { } } - /// - /// Looks up a localized resource of type System.Drawing.Bitmap. - /// - public static System.Drawing.Bitmap a_1010 { - get { - object obj = ResourceManager.GetObject("a_1010", resourceCulture); - return ((System.Drawing.Bitmap)(obj)); - } - } - /// /// Looks up a localized resource of type System.Drawing.Bitmap. /// @@ -5690,16 +5750,6 @@ namespace PKHeX.Drawing.PokeSprite.Properties { } } - /// - /// Looks up a localized resource of type System.Drawing.Bitmap. - /// - public static System.Drawing.Bitmap a_493_101 { - get { - object obj = ResourceManager.GetObject("a_493_101", resourceCulture); - return ((System.Drawing.Bitmap)(obj)); - } - } - /// /// Looks up a localized resource of type System.Drawing.Bitmap. /// @@ -5710,16 +5760,6 @@ namespace PKHeX.Drawing.PokeSprite.Properties { } } - /// - /// Looks up a localized resource of type System.Drawing.Bitmap. - /// - public static System.Drawing.Bitmap a_493_111 { - get { - object obj = ResourceManager.GetObject("a_493_111", resourceCulture); - return ((System.Drawing.Bitmap)(obj)); - } - } - /// /// Looks up a localized resource of type System.Drawing.Bitmap. /// @@ -5730,16 +5770,6 @@ namespace PKHeX.Drawing.PokeSprite.Properties { } } - /// - /// Looks up a localized resource of type System.Drawing.Bitmap. - /// - public static System.Drawing.Bitmap a_493_121 { - get { - object obj = ResourceManager.GetObject("a_493_121", resourceCulture); - return ((System.Drawing.Bitmap)(obj)); - } - } - /// /// Looks up a localized resource of type System.Drawing.Bitmap. /// @@ -5750,16 +5780,6 @@ namespace PKHeX.Drawing.PokeSprite.Properties { } } - /// - /// Looks up a localized resource of type System.Drawing.Bitmap. - /// - public static System.Drawing.Bitmap a_493_131 { - get { - object obj = ResourceManager.GetObject("a_493_131", resourceCulture); - return ((System.Drawing.Bitmap)(obj)); - } - } - /// /// Looks up a localized resource of type System.Drawing.Bitmap. /// @@ -5770,16 +5790,6 @@ namespace PKHeX.Drawing.PokeSprite.Properties { } } - /// - /// Looks up a localized resource of type System.Drawing.Bitmap. - /// - public static System.Drawing.Bitmap a_493_141 { - get { - object obj = ResourceManager.GetObject("a_493_141", resourceCulture); - return ((System.Drawing.Bitmap)(obj)); - } - } - /// /// Looks up a localized resource of type System.Drawing.Bitmap. /// @@ -5790,16 +5800,6 @@ namespace PKHeX.Drawing.PokeSprite.Properties { } } - /// - /// Looks up a localized resource of type System.Drawing.Bitmap. - /// - public static System.Drawing.Bitmap a_493_151 { - get { - object obj = ResourceManager.GetObject("a_493_151", resourceCulture); - return ((System.Drawing.Bitmap)(obj)); - } - } - /// /// Looks up a localized resource of type System.Drawing.Bitmap. /// @@ -5810,16 +5810,6 @@ namespace PKHeX.Drawing.PokeSprite.Properties { } } - /// - /// Looks up a localized resource of type System.Drawing.Bitmap. - /// - public static System.Drawing.Bitmap a_493_161 { - get { - object obj = ResourceManager.GetObject("a_493_161", resourceCulture); - return ((System.Drawing.Bitmap)(obj)); - } - } - /// /// Looks up a localized resource of type System.Drawing.Bitmap. /// @@ -5830,16 +5820,6 @@ namespace PKHeX.Drawing.PokeSprite.Properties { } } - /// - /// Looks up a localized resource of type System.Drawing.Bitmap. - /// - public static System.Drawing.Bitmap a_493_171 { - get { - object obj = ResourceManager.GetObject("a_493_171", resourceCulture); - return ((System.Drawing.Bitmap)(obj)); - } - } - /// /// Looks up a localized resource of type System.Drawing.Bitmap. /// @@ -5850,26 +5830,6 @@ namespace PKHeX.Drawing.PokeSprite.Properties { } } - /// - /// Looks up a localized resource of type System.Drawing.Bitmap. - /// - public static System.Drawing.Bitmap a_493_181 { - get { - object obj = ResourceManager.GetObject("a_493_181", resourceCulture); - return ((System.Drawing.Bitmap)(obj)); - } - } - - /// - /// Looks up a localized resource of type System.Drawing.Bitmap. - /// - public static System.Drawing.Bitmap a_493_19 { - get { - object obj = ResourceManager.GetObject("a_493_19", resourceCulture); - return ((System.Drawing.Bitmap)(obj)); - } - } - /// /// Looks up a localized resource of type System.Drawing.Bitmap. /// @@ -5880,16 +5840,6 @@ namespace PKHeX.Drawing.PokeSprite.Properties { } } - /// - /// Looks up a localized resource of type System.Drawing.Bitmap. - /// - public static System.Drawing.Bitmap a_493_21 { - get { - object obj = ResourceManager.GetObject("a_493_21", resourceCulture); - return ((System.Drawing.Bitmap)(obj)); - } - } - /// /// Looks up a localized resource of type System.Drawing.Bitmap. /// @@ -5900,16 +5850,6 @@ namespace PKHeX.Drawing.PokeSprite.Properties { } } - /// - /// Looks up a localized resource of type System.Drawing.Bitmap. - /// - public static System.Drawing.Bitmap a_493_31 { - get { - object obj = ResourceManager.GetObject("a_493_31", resourceCulture); - return ((System.Drawing.Bitmap)(obj)); - } - } - /// /// Looks up a localized resource of type System.Drawing.Bitmap. /// @@ -5920,16 +5860,6 @@ namespace PKHeX.Drawing.PokeSprite.Properties { } } - /// - /// Looks up a localized resource of type System.Drawing.Bitmap. - /// - public static System.Drawing.Bitmap a_493_41 { - get { - object obj = ResourceManager.GetObject("a_493_41", resourceCulture); - return ((System.Drawing.Bitmap)(obj)); - } - } - /// /// Looks up a localized resource of type System.Drawing.Bitmap. /// @@ -5940,16 +5870,6 @@ namespace PKHeX.Drawing.PokeSprite.Properties { } } - /// - /// Looks up a localized resource of type System.Drawing.Bitmap. - /// - public static System.Drawing.Bitmap a_493_51 { - get { - object obj = ResourceManager.GetObject("a_493_51", resourceCulture); - return ((System.Drawing.Bitmap)(obj)); - } - } - /// /// Looks up a localized resource of type System.Drawing.Bitmap. /// @@ -5960,16 +5880,6 @@ namespace PKHeX.Drawing.PokeSprite.Properties { } } - /// - /// Looks up a localized resource of type System.Drawing.Bitmap. - /// - public static System.Drawing.Bitmap a_493_61 { - get { - object obj = ResourceManager.GetObject("a_493_61", resourceCulture); - return ((System.Drawing.Bitmap)(obj)); - } - } - /// /// Looks up a localized resource of type System.Drawing.Bitmap. /// @@ -5980,16 +5890,6 @@ namespace PKHeX.Drawing.PokeSprite.Properties { } } - /// - /// Looks up a localized resource of type System.Drawing.Bitmap. - /// - public static System.Drawing.Bitmap a_493_71 { - get { - object obj = ResourceManager.GetObject("a_493_71", resourceCulture); - return ((System.Drawing.Bitmap)(obj)); - } - } - /// /// Looks up a localized resource of type System.Drawing.Bitmap. /// @@ -6000,16 +5900,6 @@ namespace PKHeX.Drawing.PokeSprite.Properties { } } - /// - /// Looks up a localized resource of type System.Drawing.Bitmap. - /// - public static System.Drawing.Bitmap a_493_81 { - get { - object obj = ResourceManager.GetObject("a_493_81", resourceCulture); - return ((System.Drawing.Bitmap)(obj)); - } - } - /// /// Looks up a localized resource of type System.Drawing.Bitmap. /// @@ -6020,16 +5910,6 @@ namespace PKHeX.Drawing.PokeSprite.Properties { } } - /// - /// Looks up a localized resource of type System.Drawing.Bitmap. - /// - public static System.Drawing.Bitmap a_493_91 { - get { - object obj = ResourceManager.GetObject("a_493_91", resourceCulture); - return ((System.Drawing.Bitmap)(obj)); - } - } - /// /// Looks up a localized resource of type System.Drawing.Bitmap. /// @@ -9330,6 +9210,16 @@ namespace PKHeX.Drawing.PokeSprite.Properties { } } + /// + /// Looks up a localized resource of type System.Drawing.Bitmap. + /// + public static System.Drawing.Bitmap a_925_1 { + get { + object obj = ResourceManager.GetObject("a_925_1", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + /// /// Looks up a localized resource of type System.Drawing.Bitmap. /// @@ -9400,6 +9290,36 @@ namespace PKHeX.Drawing.PokeSprite.Properties { } } + /// + /// Looks up a localized resource of type System.Drawing.Bitmap. + /// + public static System.Drawing.Bitmap a_931_1 { + get { + object obj = ResourceManager.GetObject("a_931_1", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// Looks up a localized resource of type System.Drawing.Bitmap. + /// + public static System.Drawing.Bitmap a_931_2 { + get { + object obj = ResourceManager.GetObject("a_931_2", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// Looks up a localized resource of type System.Drawing.Bitmap. + /// + public static System.Drawing.Bitmap a_931_3 { + get { + object obj = ResourceManager.GetObject("a_931_3", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + /// /// Looks up a localized resource of type System.Drawing.Bitmap. /// @@ -9430,16 +9350,6 @@ namespace PKHeX.Drawing.PokeSprite.Properties { } } - /// - /// Looks up a localized resource of type System.Drawing.Bitmap. - /// - public static System.Drawing.Bitmap a_934_1 { - get { - object obj = ResourceManager.GetObject("a_934_1", resourceCulture); - return ((System.Drawing.Bitmap)(obj)); - } - } - /// /// Looks up a localized resource of type System.Drawing.Bitmap. /// @@ -9570,16 +9480,6 @@ namespace PKHeX.Drawing.PokeSprite.Properties { } } - /// - /// Looks up a localized resource of type System.Drawing.Bitmap. - /// - public static System.Drawing.Bitmap a_946_1 { - get { - object obj = ResourceManager.GetObject("a_946_1", resourceCulture); - return ((System.Drawing.Bitmap)(obj)); - } - } - /// /// Looks up a localized resource of type System.Drawing.Bitmap. /// @@ -9650,26 +9550,6 @@ namespace PKHeX.Drawing.PokeSprite.Properties { } } - /// - /// Looks up a localized resource of type System.Drawing.Bitmap. - /// - public static System.Drawing.Bitmap a_952_1 { - get { - object obj = ResourceManager.GetObject("a_952_1", resourceCulture); - return ((System.Drawing.Bitmap)(obj)); - } - } - - /// - /// Looks up a localized resource of type System.Drawing.Bitmap. - /// - public static System.Drawing.Bitmap a_952_2 { - get { - object obj = ResourceManager.GetObject("a_952_2", resourceCulture); - return ((System.Drawing.Bitmap)(obj)); - } - } - /// /// Looks up a localized resource of type System.Drawing.Bitmap. /// @@ -9760,36 +9640,6 @@ namespace PKHeX.Drawing.PokeSprite.Properties { } } - /// - /// Looks up a localized resource of type System.Drawing.Bitmap. - /// - public static System.Drawing.Bitmap a_960_1 { - get { - object obj = ResourceManager.GetObject("a_960_1", resourceCulture); - return ((System.Drawing.Bitmap)(obj)); - } - } - - /// - /// Looks up a localized resource of type System.Drawing.Bitmap. - /// - public static System.Drawing.Bitmap a_960_2 { - get { - object obj = ResourceManager.GetObject("a_960_2", resourceCulture); - return ((System.Drawing.Bitmap)(obj)); - } - } - - /// - /// Looks up a localized resource of type System.Drawing.Bitmap. - /// - public static System.Drawing.Bitmap a_960_3 { - get { - object obj = ResourceManager.GetObject("a_960_3", resourceCulture); - return ((System.Drawing.Bitmap)(obj)); - } - } - /// /// Looks up a localized resource of type System.Drawing.Bitmap. /// @@ -9830,6 +9680,16 @@ namespace PKHeX.Drawing.PokeSprite.Properties { } } + /// + /// Looks up a localized resource of type System.Drawing.Bitmap. + /// + public static System.Drawing.Bitmap a_964_1 { + get { + object obj = ResourceManager.GetObject("a_964_1", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + /// /// Looks up a localized resource of type System.Drawing.Bitmap. /// @@ -9960,16 +9820,6 @@ namespace PKHeX.Drawing.PokeSprite.Properties { } } - /// - /// Looks up a localized resource of type System.Drawing.Bitmap. - /// - public static System.Drawing.Bitmap a_976_1 { - get { - object obj = ResourceManager.GetObject("a_976_1", resourceCulture); - return ((System.Drawing.Bitmap)(obj)); - } - } - /// /// Looks up a localized resource of type System.Drawing.Bitmap. /// @@ -9990,6 +9840,26 @@ namespace PKHeX.Drawing.PokeSprite.Properties { } } + /// + /// Looks up a localized resource of type System.Drawing.Bitmap. + /// + public static System.Drawing.Bitmap a_978_1 { + get { + object obj = ResourceManager.GetObject("a_978_1", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// Looks up a localized resource of type System.Drawing.Bitmap. + /// + public static System.Drawing.Bitmap a_978_2 { + get { + object obj = ResourceManager.GetObject("a_978_2", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + /// /// Looks up a localized resource of type System.Drawing.Bitmap. /// @@ -10010,6 +9880,16 @@ namespace PKHeX.Drawing.PokeSprite.Properties { } } + /// + /// Looks up a localized resource of type System.Drawing.Bitmap. + /// + public static System.Drawing.Bitmap a_980 { + get { + object obj = ResourceManager.GetObject("a_980", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + /// /// Looks up a localized resource of type System.Drawing.Bitmap. /// @@ -10070,6 +9950,16 @@ namespace PKHeX.Drawing.PokeSprite.Properties { } } + /// + /// Looks up a localized resource of type System.Drawing.Bitmap. + /// + public static System.Drawing.Bitmap a_987 { + get { + object obj = ResourceManager.GetObject("a_987", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + /// /// Looks up a localized resource of type System.Drawing.Bitmap. /// @@ -10190,46 +10080,6 @@ namespace PKHeX.Drawing.PokeSprite.Properties { } } - /// - /// Looks up a localized resource of type System.Drawing.Bitmap. - /// - public static System.Drawing.Bitmap a_998_1 { - get { - object obj = ResourceManager.GetObject("a_998_1", resourceCulture); - return ((System.Drawing.Bitmap)(obj)); - } - } - - /// - /// Looks up a localized resource of type System.Drawing.Bitmap. - /// - public static System.Drawing.Bitmap a_998_2 { - get { - object obj = ResourceManager.GetObject("a_998_2", resourceCulture); - return ((System.Drawing.Bitmap)(obj)); - } - } - - /// - /// Looks up a localized resource of type System.Drawing.Bitmap. - /// - public static System.Drawing.Bitmap a_998_3 { - get { - object obj = ResourceManager.GetObject("a_998_3", resourceCulture); - return ((System.Drawing.Bitmap)(obj)); - } - } - - /// - /// Looks up a localized resource of type System.Drawing.Bitmap. - /// - public static System.Drawing.Bitmap a_998_4 { - get { - object obj = ResourceManager.GetObject("a_998_4", resourceCulture); - return ((System.Drawing.Bitmap)(obj)); - } - } - /// /// Looks up a localized resource of type System.Drawing.Bitmap. /// @@ -10250,36 +10100,6 @@ namespace PKHeX.Drawing.PokeSprite.Properties { } } - /// - /// Looks up a localized resource of type System.Drawing.Bitmap. - /// - public static System.Drawing.Bitmap a_999_2 { - get { - object obj = ResourceManager.GetObject("a_999_2", resourceCulture); - return ((System.Drawing.Bitmap)(obj)); - } - } - - /// - /// Looks up a localized resource of type System.Drawing.Bitmap. - /// - public static System.Drawing.Bitmap a_999_3 { - get { - object obj = ResourceManager.GetObject("a_999_3", resourceCulture); - return ((System.Drawing.Bitmap)(obj)); - } - } - - /// - /// Looks up a localized resource of type System.Drawing.Bitmap. - /// - public static System.Drawing.Bitmap a_999_4 { - get { - object obj = ResourceManager.GetObject("a_999_4", resourceCulture); - return ((System.Drawing.Bitmap)(obj)); - } - } - /// /// Looks up a localized resource of type System.Drawing.Bitmap. /// diff --git a/PKHeX.Drawing.PokeSprite/Properties/Resources.resx b/PKHeX.Drawing.PokeSprite/Properties/Resources.resx index 0e3395864..0300f28cf 100644 --- a/PKHeX.Drawing.PokeSprite/Properties/Resources.resx +++ b/PKHeX.Drawing.PokeSprite/Properties/Resources.resx @@ -1327,11 +1327,32 @@ ..\Resources\img\Artwork Pokemon Sprites\a_1007.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + ..\Resources\img\Artwork Pokemon Sprites\a_1007-1.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\Resources\img\Artwork Pokemon Sprites\a_1007-2.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\Resources\img\Artwork Pokemon Sprites\a_1007-3.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\Resources\img\Artwork Pokemon Sprites\a_1007-4.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + ..\Resources\img\Artwork Pokemon Sprites\a_1008.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a - - ..\Resources\img\Artwork Pokemon Sprites\a_1009.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + ..\Resources\img\Artwork Pokemon Sprites\a_1008-1.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\Resources\img\Artwork Pokemon Sprites\a_1008-2.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\Resources\img\Artwork Pokemon Sprites\a_1008-3.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\Resources\img\Artwork Pokemon Sprites\a_1008-4.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a ..\Resources\img\Artwork Pokemon Sprites\a_100-1.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a @@ -1339,9 +1360,6 @@ ..\Resources\img\Artwork Pokemon Sprites\a_101.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a - - ..\Resources\img\Artwork Pokemon Sprites\a_1010.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a - ..\Resources\img\Artwork Pokemon Sprites\a_101-1.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a @@ -2872,108 +2890,54 @@ ..\Resources\img\Artwork Pokemon Sprites\a_493-10.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a - - ..\Resources\img\Artwork Pokemon Sprites\a_493-10.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a - ..\Resources\img\Artwork Pokemon Sprites\a_493-11.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a - - ..\Resources\img\Artwork Pokemon Sprites\a_493-11.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a - ..\Resources\img\Artwork Pokemon Sprites\a_493-12.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a - - ..\Resources\img\Artwork Pokemon Sprites\a_493-12.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a - ..\Resources\img\Artwork Pokemon Sprites\a_493-13.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a - - ..\Resources\img\Artwork Pokemon Sprites\a_493-13.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a - ..\Resources\img\Artwork Pokemon Sprites\a_493-14.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a - - ..\Resources\img\Artwork Pokemon Sprites\a_493-14.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a - ..\Resources\img\Artwork Pokemon Sprites\a_493-15.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a - - ..\Resources\img\Artwork Pokemon Sprites\a_493-15.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a - ..\Resources\img\Artwork Pokemon Sprites\a_493-16.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a - - ..\Resources\img\Artwork Pokemon Sprites\a_493-16.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a - ..\Resources\img\Artwork Pokemon Sprites\a_493-17.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a - - ..\Resources\img\Artwork Pokemon Sprites\a_493-17.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a - ..\Resources\img\Artwork Pokemon Sprites\a_493-18.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a - - ..\Resources\img\Artwork Pokemon Sprites\a_493-18.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a - - - ..\Resources\img\Artwork Pokemon Sprites\a_493-1.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a - ..\Resources\img\Artwork Pokemon Sprites\a_493-2.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a - - ..\Resources\img\Artwork Pokemon Sprites\a_493-2.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a - ..\Resources\img\Artwork Pokemon Sprites\a_493-3.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a - - ..\Resources\img\Artwork Pokemon Sprites\a_493-3.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a - ..\Resources\img\Artwork Pokemon Sprites\a_493-4.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a - - ..\Resources\img\Artwork Pokemon Sprites\a_493-4.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a - ..\Resources\img\Artwork Pokemon Sprites\a_493-5.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a - - ..\Resources\img\Artwork Pokemon Sprites\a_493-5.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a - ..\Resources\img\Artwork Pokemon Sprites\a_493-6.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a - - ..\Resources\img\Artwork Pokemon Sprites\a_493-6.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a - ..\Resources\img\Artwork Pokemon Sprites\a_493-7.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a - - ..\Resources\img\Artwork Pokemon Sprites\a_493-7.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a - ..\Resources\img\Artwork Pokemon Sprites\a_493-8.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a - - ..\Resources\img\Artwork Pokemon Sprites\a_493-8.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a - ..\Resources\img\Artwork Pokemon Sprites\a_493-9.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a - - ..\Resources\img\Artwork Pokemon Sprites\a_493-9.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a - ..\Resources\img\Artwork Pokemon Sprites\a_5.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a @@ -3964,6 +3928,9 @@ ..\Resources\img\Artwork Pokemon Sprites\a_925.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + ..\Resources\img\Artwork Pokemon Sprites\a_925-1.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + ..\Resources\img\Artwork Pokemon Sprites\a_926.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a @@ -3985,6 +3952,15 @@ ..\Resources\img\Artwork Pokemon Sprites\a_931.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + ..\Resources\img\Artwork Pokemon Sprites\a_931-1.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\Resources\img\Artwork Pokemon Sprites\a_931-2.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\Resources\img\Artwork Pokemon Sprites\a_931-3.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + ..\Resources\img\Artwork Pokemon Sprites\a_932.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a @@ -3994,9 +3970,6 @@ ..\Resources\img\Artwork Pokemon Sprites\a_934.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a - - ..\Resources\img\Artwork Pokemon Sprites\a_934-1.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a - ..\Resources\img\Artwork Pokemon Sprites\a_935.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a @@ -4036,9 +4009,6 @@ ..\Resources\img\Artwork Pokemon Sprites\a_946.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a - - ..\Resources\img\Artwork Pokemon Sprites\a_946-1.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a - ..\Resources\img\Artwork Pokemon Sprites\a_947.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a @@ -4060,12 +4030,6 @@ ..\Resources\img\Artwork Pokemon Sprites\a_952.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a - - ..\Resources\img\Artwork Pokemon Sprites\a_952-1.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a - - - ..\Resources\img\Artwork Pokemon Sprites\a_952-2.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a - ..\Resources\img\Artwork Pokemon Sprites\a_953.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a @@ -4093,15 +4057,6 @@ ..\Resources\img\Artwork Pokemon Sprites\a_960.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a - - ..\Resources\img\Artwork Pokemon Sprites\a_960-1.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a - - - ..\Resources\img\Artwork Pokemon Sprites\a_960-2.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a - - - ..\Resources\img\Artwork Pokemon Sprites\a_960-3.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a - ..\Resources\img\Artwork Pokemon Sprites\a_961.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a @@ -4114,6 +4069,9 @@ ..\Resources\img\Artwork Pokemon Sprites\a_964.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + ..\Resources\img\Artwork Pokemon Sprites\a_964-1.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + ..\Resources\img\Artwork Pokemon Sprites\a_965.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a @@ -4153,21 +4111,27 @@ ..\Resources\img\Artwork Pokemon Sprites\a_976.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a - - ..\Resources\img\Artwork Pokemon Sprites\a_976-1.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a - ..\Resources\img\Artwork Pokemon Sprites\a_977.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a ..\Resources\img\Artwork Pokemon Sprites\a_978.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + ..\Resources\img\Artwork Pokemon Sprites\a_978-1.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\Resources\img\Artwork Pokemon Sprites\a_978-2.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + ..\Resources\img\Artwork Pokemon Sprites\a_979.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a ..\Resources\img\Artwork Pokemon Sprites\a_98.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + ..\Resources\img\Artwork Pokemon Sprites\a_980.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + ..\Resources\img\Artwork Pokemon Sprites\a_981.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a @@ -4186,6 +4150,9 @@ ..\Resources\img\Artwork Pokemon Sprites\a_986.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + ..\Resources\img\Artwork Pokemon Sprites\a_987.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + ..\Resources\img\Artwork Pokemon Sprites\a_988.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a @@ -4222,33 +4189,12 @@ ..\Resources\img\Artwork Pokemon Sprites\a_998.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a - - ..\Resources\img\Artwork Pokemon Sprites\a_998-1.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a - - - ..\Resources\img\Artwork Pokemon Sprites\a_998-2.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a - - - ..\Resources\img\Artwork Pokemon Sprites\a_998-3.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a - - - ..\Resources\img\Artwork Pokemon Sprites\a_998-4.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a - ..\Resources\img\Artwork Pokemon Sprites\a_999.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a ..\Resources\img\Artwork Pokemon Sprites\a_999-1.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a - - ..\Resources\img\Artwork Pokemon Sprites\a_999-2.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a - - - ..\Resources\img\Artwork Pokemon Sprites\a_999-3.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a - - - ..\Resources\img\Artwork Pokemon Sprites\a_999-4.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a - ..\Resources\img\Artwork Pokemon Sprites\a_egg.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a diff --git a/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_1000.png b/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_1000.png index a13a6d3f2..71892a81d 100644 Binary files a/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_1000.png and b/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_1000.png differ diff --git a/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_1001.png b/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_1001.png index a9de90f7b..4525bb01a 100644 Binary files a/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_1001.png and b/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_1001.png differ diff --git a/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_1002.png b/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_1002.png index 5bd81c0ba..6f2a6d08f 100644 Binary files a/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_1002.png and b/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_1002.png differ diff --git a/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_1003.png b/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_1003.png index ce5b5447b..6fef493f2 100644 Binary files a/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_1003.png and b/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_1003.png differ diff --git a/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_1004.png b/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_1004.png index 6bc107288..34a8ec476 100644 Binary files a/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_1004.png and b/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_1004.png differ diff --git a/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_1005.png b/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_1005.png index 0bddfcb21..5cc5487e0 100644 Binary files a/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_1005.png and b/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_1005.png differ diff --git a/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_1006.png b/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_1006.png index f13d8b27e..eb7db2f51 100644 Binary files a/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_1006.png and b/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_1006.png differ diff --git a/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_998-1.png b/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_1007-1.png similarity index 100% rename from PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_998-1.png rename to PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_1007-1.png diff --git a/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_998-2.png b/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_1007-2.png similarity index 100% rename from PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_998-2.png rename to PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_1007-2.png diff --git a/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_998-3.png b/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_1007-3.png similarity index 100% rename from PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_998-3.png rename to PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_1007-3.png diff --git a/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_998-4.png b/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_1007-4.png similarity index 100% rename from PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_998-4.png rename to PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_1007-4.png diff --git a/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_1007.png b/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_1007.png index 6ad56a745..d1ef335ae 100644 Binary files a/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_1007.png and b/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_1007.png differ diff --git a/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_999-2.png b/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_1008-1.png similarity index 100% rename from PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_999-2.png rename to PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_1008-1.png diff --git a/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_999-3.png b/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_1008-2.png similarity index 100% rename from PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_999-3.png rename to PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_1008-2.png diff --git a/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_999-4.png b/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_1008-3.png similarity index 100% rename from PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_999-4.png rename to PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_1008-3.png diff --git a/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_1008-4.png b/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_1008-4.png new file mode 100644 index 000000000..7f1b662b8 Binary files /dev/null and b/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_1008-4.png differ diff --git a/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_1008.png b/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_1008.png index c61a81214..7225c0709 100644 Binary files a/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_1008.png and b/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_1008.png differ diff --git a/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_1010.png b/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_1010.png deleted file mode 100644 index e5289cedb..000000000 Binary files a/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_1010.png and /dev/null differ diff --git a/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_917.png b/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_917.png index 61830a474..3255f4054 100644 Binary files a/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_917.png and b/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_917.png differ diff --git a/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_918.png b/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_918.png index 3255f4054..74a9c9f01 100644 Binary files a/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_918.png and b/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_918.png differ diff --git a/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_919.png b/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_919.png index 74a9c9f01..2400e161a 100644 Binary files a/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_919.png and b/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_919.png differ diff --git a/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_920.png b/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_920.png index 2400e161a..dd6de67f5 100644 Binary files a/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_920.png and b/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_920.png differ diff --git a/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_921.png b/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_921.png index dd6de67f5..8dbddaef5 100644 Binary files a/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_921.png and b/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_921.png differ diff --git a/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_922.png b/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_922.png index 2dd3d2385..a81e89578 100644 Binary files a/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_922.png and b/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_922.png differ diff --git a/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_923.png b/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_923.png index 9c9dbe5d1..e1eaec4b4 100644 Binary files a/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_923.png and b/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_923.png differ diff --git a/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_924.png b/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_924.png index abc459c69..5526312a0 100644 Binary files a/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_924.png and b/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_924.png differ diff --git a/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_946-1.png b/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_925-1.png similarity index 100% rename from PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_946-1.png rename to PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_925-1.png diff --git a/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_925.png b/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_925.png index 92cd69356..f6c4d5df4 100644 Binary files a/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_925.png and b/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_925.png differ diff --git a/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_926.png b/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_926.png index a7e405115..ad911b88e 100644 Binary files a/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_926.png and b/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_926.png differ diff --git a/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_927.png b/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_927.png index 670556577..2a09676b8 100644 Binary files a/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_927.png and b/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_927.png differ diff --git a/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_928.png b/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_928.png index d1fb0124a..41979e7fb 100644 Binary files a/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_928.png and b/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_928.png differ diff --git a/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_929.png b/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_929.png index ef16832a3..764e91a86 100644 Binary files a/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_929.png and b/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_929.png differ diff --git a/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_930.png b/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_930.png index c3dfcba02..a6021468f 100644 Binary files a/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_930.png and b/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_930.png differ diff --git a/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_960-1.png b/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_931-1.png similarity index 100% rename from PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_960-1.png rename to PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_931-1.png diff --git a/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_960-2.png b/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_931-2.png similarity index 100% rename from PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_960-2.png rename to PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_931-2.png diff --git a/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_960-3.png b/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_931-3.png similarity index 100% rename from PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_960-3.png rename to PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_931-3.png diff --git a/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_931.png b/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_931.png index ce0475408..08729eb16 100644 Binary files a/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_931.png and b/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_931.png differ diff --git a/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_932.png b/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_932.png index 813daafce..1fcae66d9 100644 Binary files a/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_932.png and b/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_932.png differ diff --git a/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_933.png b/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_933.png index b79ee48a5..2e1a21909 100644 Binary files a/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_933.png and b/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_933.png differ diff --git a/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_934.png b/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_934.png index c2ec182be..bfd49f73b 100644 Binary files a/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_934.png and b/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_934.png differ diff --git a/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_935.png b/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_935.png index 41979e7fb..ce5b5447b 100644 Binary files a/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_935.png and b/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_935.png differ diff --git a/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_936.png b/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_936.png index 764e91a86..6bc107288 100644 Binary files a/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_936.png and b/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_936.png differ diff --git a/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_937.png b/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_937.png index a6021468f..0bddfcb21 100644 Binary files a/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_937.png and b/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_937.png differ diff --git a/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_938.png b/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_938.png index 46497431d..0b52c3f83 100644 Binary files a/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_938.png and b/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_938.png differ diff --git a/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_939.png b/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_939.png index a21d5c824..5baa0a469 100644 Binary files a/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_939.png and b/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_939.png differ diff --git a/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_940.png b/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_940.png index 0b52c3f83..c4600f5b1 100644 Binary files a/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_940.png and b/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_940.png differ diff --git a/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_941.png b/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_941.png index 5baa0a469..784da320b 100644 Binary files a/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_941.png and b/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_941.png differ diff --git a/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_942.png b/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_942.png index 8617aae06..e50f6d8aa 100644 Binary files a/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_942.png and b/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_942.png differ diff --git a/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_943.png b/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_943.png index a5f5d9324..0f4c53645 100644 Binary files a/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_943.png and b/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_943.png differ diff --git a/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_944.png b/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_944.png index 92554a730..5ec1f4af8 100644 Binary files a/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_944.png and b/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_944.png differ diff --git a/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_945.png b/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_945.png index 5526312a0..6b4c3f191 100644 Binary files a/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_945.png and b/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_945.png differ diff --git a/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_946.png b/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_946.png index f6c4d5df4..980eae9f1 100644 Binary files a/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_946.png and b/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_946.png differ diff --git a/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_947.png b/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_947.png index 2fedd2efc..2ca778780 100644 Binary files a/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_947.png and b/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_947.png differ diff --git a/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_948.png b/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_948.png index 5e28a2c49..f13d8b27e 100644 Binary files a/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_948.png and b/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_948.png differ diff --git a/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_949.png b/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_949.png index 2c4462aeb..6ad56a745 100644 Binary files a/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_949.png and b/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_949.png differ diff --git a/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_950.png b/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_950.png index 483d4e3ed..2403c6eca 100644 Binary files a/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_950.png and b/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_950.png differ diff --git a/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_951.png b/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_951.png index 1f67ca15a..46497431d 100644 Binary files a/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_951.png and b/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_951.png differ diff --git a/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_952.png b/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_952.png index 1d82c7eec..a21d5c824 100644 Binary files a/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_952.png and b/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_952.png differ diff --git a/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_953.png b/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_953.png index f167ee251..2dd3d2385 100644 Binary files a/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_953.png and b/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_953.png differ diff --git a/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_954.png b/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_954.png index 8dbddaef5..9c9dbe5d1 100644 Binary files a/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_954.png and b/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_954.png differ diff --git a/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_955.png b/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_955.png index a81e89578..a7e405115 100644 Binary files a/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_955.png and b/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_955.png differ diff --git a/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_956.png b/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_956.png index e1eaec4b4..670556577 100644 Binary files a/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_956.png and b/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_956.png differ diff --git a/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_957.png b/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_957.png index c4600f5b1..a13a6d3f2 100644 Binary files a/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_957.png and b/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_957.png differ diff --git a/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_958.png b/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_958.png index 784da320b..a9de90f7b 100644 Binary files a/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_958.png and b/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_958.png differ diff --git a/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_959.png b/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_959.png index 97fa6e626..5bd81c0ba 100644 Binary files a/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_959.png and b/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_959.png differ diff --git a/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_960.png b/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_960.png index 08729eb16..ef16832a3 100644 Binary files a/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_960.png and b/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_960.png differ diff --git a/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_961.png b/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_961.png index 5a95b0d21..c3dfcba02 100644 Binary files a/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_961.png and b/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_961.png differ diff --git a/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_962.png b/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_962.png index 2403c6eca..97fa6e626 100644 Binary files a/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_962.png and b/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_962.png differ diff --git a/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_963.png b/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_963.png index 1fcae66d9..b79ee48a5 100644 Binary files a/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_963.png and b/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_963.png differ diff --git a/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_934-1.png b/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_964-1.png similarity index 100% rename from PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_934-1.png rename to PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_964-1.png diff --git a/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_964.png b/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_964.png index 2e1a21909..c2ec182be 100644 Binary files a/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_964.png and b/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_964.png differ diff --git a/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_965.png b/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_965.png index bfd49f73b..8617aae06 100644 Binary files a/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_965.png and b/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_965.png differ diff --git a/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_966.png b/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_966.png index fc1873346..a5f5d9324 100644 Binary files a/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_966.png and b/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_966.png differ diff --git a/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_967.png b/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_967.png index 2109aa5a5..f167ee251 100644 Binary files a/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_967.png and b/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_967.png differ diff --git a/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_968.png b/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_968.png index 5ec1f4af8..92554a730 100644 Binary files a/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_968.png and b/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_968.png differ diff --git a/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_969.png b/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_969.png index 6b4c3f191..fc1873346 100644 Binary files a/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_969.png and b/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_969.png differ diff --git a/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_970.png b/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_970.png index ad911b88e..2109aa5a5 100644 Binary files a/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_970.png and b/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_970.png differ diff --git a/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_971.png b/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_971.png index 2a09676b8..abc459c69 100644 Binary files a/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_971.png and b/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_971.png differ diff --git a/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_972.png b/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_972.png index e50f6d8aa..92cd69356 100644 Binary files a/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_972.png and b/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_972.png differ diff --git a/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_973.png b/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_973.png index 0f4c53645..5a95b0d21 100644 Binary files a/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_973.png and b/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_973.png differ diff --git a/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_974.png b/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_974.png index 980eae9f1..2fedd2efc 100644 Binary files a/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_974.png and b/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_974.png differ diff --git a/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_975.png b/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_975.png index 2ca778780..5e28a2c49 100644 Binary files a/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_975.png and b/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_975.png differ diff --git a/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_976-1.png b/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_976-1.png deleted file mode 100644 index 13ad07a88..000000000 Binary files a/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_976-1.png and /dev/null differ diff --git a/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_976.png b/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_976.png index e8dc8e1b3..813daafce 100644 Binary files a/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_976.png and b/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_976.png differ diff --git a/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_977.png b/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_977.png index 71892a81d..ce0475408 100644 Binary files a/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_977.png and b/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_977.png differ diff --git a/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_952-1.png b/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_978-1.png similarity index 100% rename from PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_952-1.png rename to PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_978-1.png diff --git a/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_952-2.png b/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_978-2.png similarity index 100% rename from PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_952-2.png rename to PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_978-2.png diff --git a/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_978.png b/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_978.png index 99177b77d..1d82c7eec 100644 Binary files a/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_978.png and b/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_978.png differ diff --git a/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_979.png b/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_979.png index 16cdfd6ee..e5289cedb 100644 Binary files a/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_979.png and b/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_979.png differ diff --git a/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_1009.png b/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_980.png similarity index 100% rename from PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_1009.png rename to PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_980.png diff --git a/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_981.png b/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_981.png index dd928ef62..d1fb0124a 100644 Binary files a/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_981.png and b/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_981.png differ diff --git a/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_982.png b/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_982.png index 97105a25b..61830a474 100644 Binary files a/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_982.png and b/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_982.png differ diff --git a/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_983.png b/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_983.png index 71484ad71..c61a81214 100644 Binary files a/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_983.png and b/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_983.png differ diff --git a/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_984.png b/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_984.png index 9727cbe23..99177b77d 100644 Binary files a/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_984.png and b/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_984.png differ diff --git a/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_985.png b/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_985.png index 5cc5487e0..97105a25b 100644 Binary files a/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_985.png and b/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_985.png differ diff --git a/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_986.png b/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_986.png index c15be0f93..16cdfd6ee 100644 Binary files a/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_986.png and b/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_986.png differ diff --git a/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_987.png b/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_987.png new file mode 100644 index 000000000..71484ad71 Binary files /dev/null and b/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_987.png differ diff --git a/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_988.png b/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_988.png index 63b275237..9727cbe23 100644 Binary files a/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_988.png and b/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_988.png differ diff --git a/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_989.png b/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_989.png index f4e1825aa..dd928ef62 100644 Binary files a/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_989.png and b/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_989.png differ diff --git a/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_990.png b/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_990.png index 19c6937f3..c15be0f93 100644 Binary files a/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_990.png and b/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_990.png differ diff --git a/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_991.png b/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_991.png index 04ab817e2..f41cc1673 100644 Binary files a/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_991.png and b/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_991.png differ diff --git a/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_992.png b/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_992.png index f41cc1673..f4e1825aa 100644 Binary files a/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_992.png and b/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_992.png differ diff --git a/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_993.png b/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_993.png index eb7db2f51..19c6937f3 100644 Binary files a/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_993.png and b/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_993.png differ diff --git a/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_994.png b/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_994.png index 6fef493f2..63b275237 100644 Binary files a/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_994.png and b/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_994.png differ diff --git a/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_995.png b/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_995.png index 6f2a6d08f..04ab817e2 100644 Binary files a/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_995.png and b/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_995.png differ diff --git a/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_996.png b/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_996.png index 4525bb01a..2c4462aeb 100644 Binary files a/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_996.png and b/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_996.png differ diff --git a/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_997.png b/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_997.png index 34a8ec476..483d4e3ed 100644 Binary files a/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_997.png and b/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_997.png differ diff --git a/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_998.png b/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_998.png index d1ef335ae..1f67ca15a 100644 Binary files a/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_998.png and b/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_998.png differ diff --git a/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_999-1.png b/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_999-1.png index 7f1b662b8..13ad07a88 100644 Binary files a/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_999-1.png and b/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_999-1.png differ diff --git a/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_999.png b/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_999.png index 7225c0709..e8dc8e1b3 100644 Binary files a/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_999.png and b/PKHeX.Drawing.PokeSprite/Resources/img/Artwork Pokemon Sprites/a_999.png differ diff --git a/PKHeX.Drawing.PokeSprite/Util/SpriteUtil.cs b/PKHeX.Drawing.PokeSprite/Util/SpriteUtil.cs index abcb6604d..67bd6c09b 100644 --- a/PKHeX.Drawing.PokeSprite/Util/SpriteUtil.cs +++ b/PKHeX.Drawing.PokeSprite/Util/SpriteUtil.cs @@ -132,14 +132,14 @@ public static class SpriteUtil int team = flags.IsBattleTeam(); if (team >= 0) sprite = ImageUtil.LayerImage(sprite, Resources.team, SlotTeamShiftX, 0); - if (flags.HasFlagFast(StorageSlotSource.Locked)) + if (flags.HasFlag(StorageSlotSource.Locked)) sprite = ImageUtil.LayerImage(sprite, Resources.locked, SlotLockShiftX, 0); // Some games store Party directly in the list of pokemon data (LGP/E). Indicate accordingly. int party = flags.IsParty(); if (party >= 0) sprite = ImageUtil.LayerImage(sprite, PartyMarks[party], PartyMarkShiftX, 0); - if (flags.HasFlagFast(StorageSlotSource.Starter)) + if (flags.HasFlag(StorageSlotSource.Starter)) sprite = ImageUtil.LayerImage(sprite, Resources.starter, 0, 0); } @@ -285,7 +285,7 @@ public static class SpriteUtil public static Image GetMysteryGiftPreviewPoke(MysteryGift gift) { - if (gift.IsEgg && gift.Species == (int)Species.Manaphy) // Manaphy Egg + if (gift is { IsEgg: true, Species: (int)Species.Manaphy }) // Manaphy Egg return GetSprite((int)Species.Manaphy, 0, 2, 0, 0, true, Shiny.Never, gift.Context); var gender = Math.Max(0, gift.Gender); diff --git a/PKHeX.Drawing.PokeSprite/Util/TypeColor.cs b/PKHeX.Drawing.PokeSprite/Util/TypeColor.cs index 0899ff9ea..ae462486a 100644 --- a/PKHeX.Drawing.PokeSprite/Util/TypeColor.cs +++ b/PKHeX.Drawing.PokeSprite/Util/TypeColor.cs @@ -3,31 +3,39 @@ using System.Drawing; using PKHeX.Core; using static PKHeX.Core.MoveType; -namespace PKHeX.Drawing.PokeSprite +namespace PKHeX.Drawing.PokeSprite; + +/// +/// Utility class for getting the color of a . +/// +public static class TypeColor { - public static class TypeColor + /// + /// Gets the color of a . + /// + /// Type to get the color of. + /// Color of the type. + /// + public static Color GetTypeSpriteColor(byte type) => (MoveType)type switch { - public static Color GetTypeSpriteColor(byte type) => (MoveType)type switch - { - Normal => Color.FromArgb(159, 161, 159), - Fighting => Color.FromArgb(255, 128, 000), - Flying => Color.FromArgb(129, 185, 239), - Poison => Color.FromArgb(143, 065, 203), - Ground => Color.FromArgb(145, 081, 033), - Rock => Color.FromArgb(175, 169, 129), - Bug => Color.FromArgb(145, 161, 025), - Ghost => Color.FromArgb(112, 065, 112), - Steel => Color.FromArgb(096, 161, 184), - Fire => Color.FromArgb(230, 040, 041), - Water => Color.FromArgb(041, 128, 239), - Grass => Color.FromArgb(063, 161, 041), - Electric => Color.FromArgb(250, 192, 000), - Psychic => Color.FromArgb(239, 065, 121), - Ice => Color.FromArgb(063, 216, 255), - Dragon => Color.FromArgb(080, 097, 225), - Dark => Color.FromArgb(080, 065, 063), - Fairy => Color.FromArgb(239, 113, 239), - _ => throw new ArgumentOutOfRangeException(nameof(type), type, null), - }; - } + Normal => Color.FromArgb(159, 161, 159), + Fighting => Color.FromArgb(255, 128, 000), + Flying => Color.FromArgb(129, 185, 239), + Poison => Color.FromArgb(143, 065, 203), + Ground => Color.FromArgb(145, 081, 033), + Rock => Color.FromArgb(175, 169, 129), + Bug => Color.FromArgb(145, 161, 025), + Ghost => Color.FromArgb(112, 065, 112), + Steel => Color.FromArgb(096, 161, 184), + Fire => Color.FromArgb(230, 040, 041), + Water => Color.FromArgb(041, 128, 239), + Grass => Color.FromArgb(063, 161, 041), + Electric => Color.FromArgb(250, 192, 000), + Psychic => Color.FromArgb(239, 065, 121), + Ice => Color.FromArgb(063, 216, 255), + Dragon => Color.FromArgb(080, 097, 225), + Dark => Color.FromArgb(080, 065, 063), + Fairy => Color.FromArgb(239, 113, 239), + _ => throw new ArgumentOutOfRangeException(nameof(type), type, null), + }; } diff --git a/PKHeX.Drawing/ColorUtil.cs b/PKHeX.Drawing/ColorUtil.cs index a4126822a..da3fc7455 100644 --- a/PKHeX.Drawing/ColorUtil.cs +++ b/PKHeX.Drawing/ColorUtil.cs @@ -1,14 +1,22 @@ -using System; +using System; using System.Drawing; namespace PKHeX.Drawing; +/// +/// Utility class for manipulating values. +/// public static class ColorUtil { - public static Color ColorBaseStat(int v) + private const byte MaxStat = 180; // shift the green cap down + private const byte MinStat = 0; + + /// + /// Gets the value for the specified value. + /// + public static Color ColorBaseStat(int stat) { - const float maxval = 180; // shift the green cap down - float x = 100f * v / maxval; + float x = (100f * stat) / MaxStat; if (x > 100) x = 100; double red = 255f * (x > 50 ? 1 - (2 * (x - 50) / 100.0) : 1.0); @@ -17,7 +25,13 @@ public static class ColorUtil return Blend(Color.FromArgb((int)red, (int)green, 0), Color.White, 0.4); } - public static Color ColorBaseStatTotal(int tot) => ColorBaseStat((int) (Math.Max(0, tot - 175) / 3f)); + public static Color ColorBaseStatTotal(int tot) + { + const byte sumShiftDown = 175; + const float sumDivisor = 3f; + var sumToSingle = Math.Max(MinStat, tot - sumShiftDown) / sumDivisor; + return ColorBaseStat((int)sumToSingle); + } public static Color Blend(Color color, Color backColor, double amount) { diff --git a/PKHeX.Drawing/ImageUtil.cs b/PKHeX.Drawing/ImageUtil.cs index 16848076b..b755f37c2 100644 --- a/PKHeX.Drawing/ImageUtil.cs +++ b/PKHeX.Drawing/ImageUtil.cs @@ -27,7 +27,7 @@ public static class ImageUtil public static Bitmap ChangeOpacity(Image img, double trans) { var bmp = (Bitmap)img.Clone(); - GetBitmapData(bmp, out BitmapData bmpData, out IntPtr ptr, out byte[] data); + GetBitmapData(bmp, out BitmapData bmpData, out var ptr, out byte[] data); Marshal.Copy(ptr, data, 0, data.Length); SetAllTransparencyTo(data, trans); @@ -40,7 +40,7 @@ public static class ImageUtil public static Bitmap ChangeAllColorTo(Image img, Color c) { var bmp = (Bitmap)img.Clone(); - GetBitmapData(bmp, out BitmapData bmpData, out IntPtr ptr, out byte[] data); + GetBitmapData(bmp, out BitmapData bmpData, out var ptr, out byte[] data); Marshal.Copy(ptr, data, 0, data.Length); ChangeAllColorTo(data, c); @@ -53,7 +53,7 @@ public static class ImageUtil public static Bitmap ChangeTransparentTo(Image img, Color c, byte trans, int start = 0, int end = -1) { var bmp = (Bitmap)img.Clone(); - GetBitmapData(bmp, out BitmapData bmpData, out IntPtr ptr, out byte[] data); + GetBitmapData(bmp, out BitmapData bmpData, out var ptr, out byte[] data); Marshal.Copy(ptr, data, 0, data.Length); if (end == -1) @@ -68,7 +68,7 @@ public static class ImageUtil public static Bitmap BlendTransparentTo(Image img, Color c, byte trans, int start = 0, int end = -1) { var bmp = (Bitmap)img.Clone(); - GetBitmapData(bmp, out BitmapData bmpData, out IntPtr ptr, out byte[] data); + GetBitmapData(bmp, out BitmapData bmpData, out var ptr, out byte[] data); Marshal.Copy(ptr, data, 0, data.Length); if (end == -1) @@ -83,7 +83,7 @@ public static class ImageUtil public static Bitmap WritePixels(Image img, Color c, int start, int end) { var bmp = (Bitmap)img.Clone(); - GetBitmapData(bmp, out BitmapData bmpData, out IntPtr ptr, out byte[] data); + GetBitmapData(bmp, out BitmapData bmpData, out var ptr, out byte[] data); Marshal.Copy(ptr, data, 0, data.Length); ChangeAllTo(data, c, start, end); @@ -96,7 +96,7 @@ public static class ImageUtil public static Bitmap ToGrayscale(Image img) { var bmp = (Bitmap)img.Clone(); - GetBitmapData(bmp, out BitmapData bmpData, out IntPtr ptr, out byte[] data); + GetBitmapData(bmp, out BitmapData bmpData, out var ptr, out byte[] data); Marshal.Copy(ptr, data, 0, data.Length); SetAllColorToGrayScale(data); @@ -106,7 +106,7 @@ public static class ImageUtil return bmp; } - private static void GetBitmapData(Bitmap bmp, out BitmapData bmpData, out IntPtr ptr, out byte[] data) + private static void GetBitmapData(Bitmap bmp, out BitmapData bmpData, out nint ptr, out byte[] data) { bmpData = bmp.LockBits(new Rectangle(0, 0, bmp.Width, bmp.Height), ImageLockMode.ReadWrite, PixelFormat.Format32bppArgb); ptr = bmpData.Scan0; diff --git a/PKHeX.Drawing/PKHeX.Drawing.csproj b/PKHeX.Drawing/PKHeX.Drawing.csproj index e1df5561a..9610174c9 100644 --- a/PKHeX.Drawing/PKHeX.Drawing.csproj +++ b/PKHeX.Drawing/PKHeX.Drawing.csproj @@ -1,16 +1,12 @@ - net6.0-windows;net46 + net7.0-windows PKHeX.Drawing - - - - - - + + diff --git a/PKHeX.WinForms/Controls/PKM Editor/CatchRate.Designer.cs b/PKHeX.WinForms/Controls/PKM Editor/CatchRate.Designer.cs index cb897a305..7aa9dc3b2 100644 --- a/PKHeX.WinForms/Controls/PKM Editor/CatchRate.Designer.cs +++ b/PKHeX.WinForms/Controls/PKM Editor/CatchRate.Designer.cs @@ -35,9 +35,9 @@ this.flowLayoutPanel1.SuspendLayout(); ((System.ComponentModel.ISupportInitialize)(this.NUD_CatchRate)).BeginInit(); this.SuspendLayout(); - // + // // flowLayoutPanel1 - // + // this.flowLayoutPanel1.Controls.Add(this.NUD_CatchRate); this.flowLayoutPanel1.Controls.Add(this.B_Clear); this.flowLayoutPanel1.Controls.Add(this.B_Reset); @@ -45,19 +45,20 @@ this.flowLayoutPanel1.Location = new System.Drawing.Point(0, 0); this.flowLayoutPanel1.Margin = new System.Windows.Forms.Padding(0); this.flowLayoutPanel1.Name = "flowLayoutPanel1"; - this.flowLayoutPanel1.Size = new System.Drawing.Size(162, 25); + this.flowLayoutPanel1.Size = new System.Drawing.Size(184, 25); this.flowLayoutPanel1.TabIndex = 1; - // + // // NUD_CatchRate - // - this.NUD_CatchRate.Location = new System.Drawing.Point(3, 3); + // + this.NUD_CatchRate.Location = new System.Drawing.Point(0, 0); + this.NUD_CatchRate.Margin = new System.Windows.Forms.Padding(0); this.NUD_CatchRate.Maximum = new decimal(new int[] { 255, 0, 0, 0}); this.NUD_CatchRate.Name = "NUD_CatchRate"; - this.NUD_CatchRate.Size = new System.Drawing.Size(40, 20); + this.NUD_CatchRate.Size = new System.Drawing.Size(40, 23); this.NUD_CatchRate.TabIndex = 0; this.NUD_CatchRate.Value = new decimal(new int[] { 255, @@ -65,35 +66,35 @@ 0, 0}); this.NUD_CatchRate.ValueChanged += new System.EventHandler(this.ChangeValue); - // + // // B_Clear - // - this.B_Clear.Location = new System.Drawing.Point(47, 1); - this.B_Clear.Margin = new System.Windows.Forms.Padding(1, 1, 1, 3); + // + this.B_Clear.Location = new System.Drawing.Point(40, 0); + this.B_Clear.Margin = new System.Windows.Forms.Padding(0); this.B_Clear.Name = "B_Clear"; - this.B_Clear.Size = new System.Drawing.Size(55, 23); + this.B_Clear.Size = new System.Drawing.Size(64, 23); this.B_Clear.TabIndex = 1; this.B_Clear.Text = "Clear"; this.B_Clear.UseVisualStyleBackColor = true; this.B_Clear.Click += new System.EventHandler(this.Clear); - // + // // B_Reset - // - this.B_Reset.Location = new System.Drawing.Point(104, 1); - this.B_Reset.Margin = new System.Windows.Forms.Padding(1, 1, 1, 3); + // + this.B_Reset.Location = new System.Drawing.Point(104, 0); + this.B_Reset.Margin = new System.Windows.Forms.Padding(0); this.B_Reset.Name = "B_Reset"; - this.B_Reset.Size = new System.Drawing.Size(55, 23); + this.B_Reset.Size = new System.Drawing.Size(64, 23); this.B_Reset.TabIndex = 2; this.B_Reset.Text = "Reset"; this.B_Reset.UseVisualStyleBackColor = true; this.B_Reset.Click += new System.EventHandler(this.Reset); - // + // // CatchRate - // + // this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Inherit; this.Controls.Add(this.flowLayoutPanel1); this.Name = "CatchRate"; - this.Size = new System.Drawing.Size(162, 25); + this.Size = new System.Drawing.Size(184, 25); this.flowLayoutPanel1.ResumeLayout(false); ((System.ComponentModel.ISupportInitialize)(this.NUD_CatchRate)).EndInit(); this.ResumeLayout(false); diff --git a/PKHeX.WinForms/Controls/PKM Editor/ContestStat.Designer.cs b/PKHeX.WinForms/Controls/PKM Editor/ContestStat.Designer.cs index 6173809ee..90564e72d 100644 --- a/PKHeX.WinForms/Controls/PKM Editor/ContestStat.Designer.cs +++ b/PKHeX.WinForms/Controls/PKM Editor/ContestStat.Designer.cs @@ -1,4 +1,4 @@ -namespace PKHeX.WinForms.Controls +namespace PKHeX.WinForms.Controls { partial class ContestStat { @@ -36,21 +36,28 @@ this.TB_Cool = new System.Windows.Forms.MaskedTextBox(); this.Label_Sheen = new System.Windows.Forms.Label(); this.Label_Tough = new System.Windows.Forms.Label(); - this.Label_Clever = new System.Windows.Forms.Label(); this.Label_Cute = new System.Windows.Forms.Label(); this.Label_Beauty = new System.Windows.Forms.Label(); this.Label_Cool = new System.Windows.Forms.Label(); this.Label_ContestStats = new System.Windows.Forms.Label(); this.Label_Smart = new System.Windows.Forms.Label(); + this.tableLayoutPanel1 = new System.Windows.Forms.TableLayoutPanel(); + this.FLP_SmartClever = new System.Windows.Forms.FlowLayoutPanel(); + this.Label_Clever = new System.Windows.Forms.Label(); + this.tableLayoutPanel1.SuspendLayout(); + this.FLP_SmartClever.SuspendLayout(); this.SuspendLayout(); // // TB_Sheen // + this.TB_Sheen.Anchor = System.Windows.Forms.AnchorStyles.None; this.TB_Sheen.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; - this.TB_Sheen.Location = new System.Drawing.Point(192, 30); + this.TB_Sheen.Location = new System.Drawing.Point(248, 16); + this.TB_Sheen.Margin = new System.Windows.Forms.Padding(0); this.TB_Sheen.Mask = "000"; + this.TB_Sheen.MinimumSize = new System.Drawing.Size(32, 23); this.TB_Sheen.Name = "TB_Sheen"; - this.TB_Sheen.Size = new System.Drawing.Size(31, 20); + this.TB_Sheen.Size = new System.Drawing.Size(32, 23); this.TB_Sheen.TabIndex = 58; this.TB_Sheen.TextAlign = System.Windows.Forms.HorizontalAlignment.Center; this.TB_Sheen.Click += new System.EventHandler(this.ClickTextBox); @@ -58,11 +65,14 @@ // // TB_Tough // + this.TB_Tough.Anchor = System.Windows.Forms.AnchorStyles.None; this.TB_Tough.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; - this.TB_Tough.Location = new System.Drawing.Point(155, 30); + this.TB_Tough.Location = new System.Drawing.Point(200, 16); + this.TB_Tough.Margin = new System.Windows.Forms.Padding(0); this.TB_Tough.Mask = "000"; + this.TB_Tough.MinimumSize = new System.Drawing.Size(32, 23); this.TB_Tough.Name = "TB_Tough"; - this.TB_Tough.Size = new System.Drawing.Size(31, 20); + this.TB_Tough.Size = new System.Drawing.Size(32, 23); this.TB_Tough.TabIndex = 57; this.TB_Tough.TextAlign = System.Windows.Forms.HorizontalAlignment.Center; this.TB_Tough.Click += new System.EventHandler(this.ClickTextBox); @@ -70,11 +80,14 @@ // // TB_Smart // + this.TB_Smart.Anchor = System.Windows.Forms.AnchorStyles.None; this.TB_Smart.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; - this.TB_Smart.Location = new System.Drawing.Point(118, 30); + this.TB_Smart.Location = new System.Drawing.Point(152, 16); + this.TB_Smart.Margin = new System.Windows.Forms.Padding(0); this.TB_Smart.Mask = "000"; + this.TB_Smart.MinimumSize = new System.Drawing.Size(32, 23); this.TB_Smart.Name = "TB_Smart"; - this.TB_Smart.Size = new System.Drawing.Size(31, 20); + this.TB_Smart.Size = new System.Drawing.Size(32, 23); this.TB_Smart.TabIndex = 56; this.TB_Smart.TextAlign = System.Windows.Forms.HorizontalAlignment.Center; this.TB_Smart.Click += new System.EventHandler(this.ClickTextBox); @@ -82,11 +95,14 @@ // // TB_Cute // + this.TB_Cute.Anchor = System.Windows.Forms.AnchorStyles.None; this.TB_Cute.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; - this.TB_Cute.Location = new System.Drawing.Point(81, 30); + this.TB_Cute.Location = new System.Drawing.Point(104, 16); + this.TB_Cute.Margin = new System.Windows.Forms.Padding(0); this.TB_Cute.Mask = "000"; + this.TB_Cute.MinimumSize = new System.Drawing.Size(32, 23); this.TB_Cute.Name = "TB_Cute"; - this.TB_Cute.Size = new System.Drawing.Size(31, 20); + this.TB_Cute.Size = new System.Drawing.Size(32, 23); this.TB_Cute.TabIndex = 55; this.TB_Cute.TextAlign = System.Windows.Forms.HorizontalAlignment.Center; this.TB_Cute.Click += new System.EventHandler(this.ClickTextBox); @@ -94,11 +110,14 @@ // // TB_Beauty // + this.TB_Beauty.Anchor = System.Windows.Forms.AnchorStyles.None; this.TB_Beauty.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; - this.TB_Beauty.Location = new System.Drawing.Point(44, 30); + this.TB_Beauty.Location = new System.Drawing.Point(56, 16); + this.TB_Beauty.Margin = new System.Windows.Forms.Padding(0); this.TB_Beauty.Mask = "000"; + this.TB_Beauty.MinimumSize = new System.Drawing.Size(32, 23); this.TB_Beauty.Name = "TB_Beauty"; - this.TB_Beauty.Size = new System.Drawing.Size(31, 20); + this.TB_Beauty.Size = new System.Drawing.Size(32, 23); this.TB_Beauty.TabIndex = 54; this.TB_Beauty.TextAlign = System.Windows.Forms.HorizontalAlignment.Center; this.TB_Beauty.Click += new System.EventHandler(this.ClickTextBox); @@ -106,11 +125,14 @@ // // TB_Cool // + this.TB_Cool.Anchor = System.Windows.Forms.AnchorStyles.None; this.TB_Cool.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; - this.TB_Cool.Location = new System.Drawing.Point(7, 30); + this.TB_Cool.Location = new System.Drawing.Point(8, 16); + this.TB_Cool.Margin = new System.Windows.Forms.Padding(0); this.TB_Cool.Mask = "000"; + this.TB_Cool.MinimumSize = new System.Drawing.Size(32, 23); this.TB_Cool.Name = "TB_Cool"; - this.TB_Cool.Size = new System.Drawing.Size(31, 20); + this.TB_Cool.Size = new System.Drawing.Size(32, 23); this.TB_Cool.TabIndex = 53; this.TB_Cool.TextAlign = System.Windows.Forms.HorizontalAlignment.Center; this.TB_Cool.Click += new System.EventHandler(this.ClickTextBox); @@ -118,61 +140,62 @@ // // Label_Sheen // - this.Label_Sheen.Location = new System.Drawing.Point(186, 17); + this.Label_Sheen.Anchor = System.Windows.Forms.AnchorStyles.None; + this.Label_Sheen.Location = new System.Drawing.Point(240, 0); + this.Label_Sheen.Margin = new System.Windows.Forms.Padding(0); this.Label_Sheen.Name = "Label_Sheen"; - this.Label_Sheen.Size = new System.Drawing.Size(43, 13); + this.Label_Sheen.Size = new System.Drawing.Size(48, 16); this.Label_Sheen.TabIndex = 65; this.Label_Sheen.Text = "Sheen"; this.Label_Sheen.TextAlign = System.Drawing.ContentAlignment.MiddleCenter; // // Label_Tough // - this.Label_Tough.Location = new System.Drawing.Point(149, 17); + this.Label_Tough.Anchor = System.Windows.Forms.AnchorStyles.None; + this.Label_Tough.Location = new System.Drawing.Point(192, 0); + this.Label_Tough.Margin = new System.Windows.Forms.Padding(0); this.Label_Tough.Name = "Label_Tough"; - this.Label_Tough.Size = new System.Drawing.Size(43, 13); + this.Label_Tough.Size = new System.Drawing.Size(48, 16); this.Label_Tough.TabIndex = 64; this.Label_Tough.Text = "Tough"; this.Label_Tough.TextAlign = System.Drawing.ContentAlignment.MiddleCenter; // - // Label_Clever - // - this.Label_Clever.Location = new System.Drawing.Point(112, 17); - this.Label_Clever.Name = "Label_Clever"; - this.Label_Clever.Size = new System.Drawing.Size(43, 13); - this.Label_Clever.TabIndex = 63; - this.Label_Clever.Text = "Clever"; - this.Label_Clever.TextAlign = System.Drawing.ContentAlignment.MiddleCenter; - // // Label_Cute // - this.Label_Cute.Location = new System.Drawing.Point(75, 17); + this.Label_Cute.Anchor = System.Windows.Forms.AnchorStyles.None; + this.Label_Cute.Location = new System.Drawing.Point(96, 0); + this.Label_Cute.Margin = new System.Windows.Forms.Padding(0); this.Label_Cute.Name = "Label_Cute"; - this.Label_Cute.Size = new System.Drawing.Size(43, 13); + this.Label_Cute.Size = new System.Drawing.Size(48, 16); this.Label_Cute.TabIndex = 62; this.Label_Cute.Text = "Cute"; this.Label_Cute.TextAlign = System.Drawing.ContentAlignment.MiddleCenter; // // Label_Beauty // - this.Label_Beauty.Location = new System.Drawing.Point(38, 17); + this.Label_Beauty.Anchor = System.Windows.Forms.AnchorStyles.None; + this.Label_Beauty.Location = new System.Drawing.Point(48, 0); + this.Label_Beauty.Margin = new System.Windows.Forms.Padding(0); this.Label_Beauty.Name = "Label_Beauty"; - this.Label_Beauty.Size = new System.Drawing.Size(43, 13); + this.Label_Beauty.Size = new System.Drawing.Size(48, 16); this.Label_Beauty.TabIndex = 61; this.Label_Beauty.Text = "Beauty"; this.Label_Beauty.TextAlign = System.Drawing.ContentAlignment.MiddleCenter; // // Label_Cool // - this.Label_Cool.Location = new System.Drawing.Point(1, 17); + this.Label_Cool.Anchor = System.Windows.Forms.AnchorStyles.None; + this.Label_Cool.Location = new System.Drawing.Point(0, 0); + this.Label_Cool.Margin = new System.Windows.Forms.Padding(0); this.Label_Cool.Name = "Label_Cool"; - this.Label_Cool.Size = new System.Drawing.Size(43, 13); + this.Label_Cool.Size = new System.Drawing.Size(48, 16); this.Label_Cool.TabIndex = 60; this.Label_Cool.Text = "Cool"; this.Label_Cool.TextAlign = System.Drawing.ContentAlignment.MiddleCenter; // // Label_ContestStats // - this.Label_ContestStats.Location = new System.Drawing.Point(46, 1); + this.Label_ContestStats.Location = new System.Drawing.Point(74, 1); this.Label_ContestStats.Name = "Label_ContestStats"; this.Label_ContestStats.Size = new System.Drawing.Size(140, 13); this.Label_ContestStats.TabIndex = 59; @@ -181,34 +204,79 @@ // // Label_Smart // - this.Label_Smart.Location = new System.Drawing.Point(112, 17); + this.Label_Smart.Anchor = System.Windows.Forms.AnchorStyles.None; + this.Label_Smart.Location = new System.Drawing.Point(0, 0); + this.Label_Smart.Margin = new System.Windows.Forms.Padding(0); this.Label_Smart.Name = "Label_Smart"; - this.Label_Smart.Size = new System.Drawing.Size(43, 13); + this.Label_Smart.Size = new System.Drawing.Size(48, 16); this.Label_Smart.TabIndex = 66; this.Label_Smart.Text = "Smart"; this.Label_Smart.TextAlign = System.Drawing.ContentAlignment.MiddleCenter; // + // tableLayoutPanel1 + // + this.tableLayoutPanel1.ColumnCount = 6; + this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 48F)); + this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 48F)); + this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 48F)); + this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 48F)); + this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 48F)); + this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 48F)); + this.tableLayoutPanel1.Controls.Add(this.TB_Cool, 0, 1); + this.tableLayoutPanel1.Controls.Add(this.Label_Tough, 4, 0); + this.tableLayoutPanel1.Controls.Add(this.Label_Sheen, 5, 0); + this.tableLayoutPanel1.Controls.Add(this.TB_Sheen, 5, 1); + this.tableLayoutPanel1.Controls.Add(this.TB_Beauty, 1, 1); + this.tableLayoutPanel1.Controls.Add(this.TB_Tough, 4, 1); + this.tableLayoutPanel1.Controls.Add(this.Label_Cute, 2, 0); + this.tableLayoutPanel1.Controls.Add(this.TB_Cute, 2, 1); + this.tableLayoutPanel1.Controls.Add(this.Label_Beauty, 1, 0); + this.tableLayoutPanel1.Controls.Add(this.TB_Smart, 3, 1); + this.tableLayoutPanel1.Controls.Add(this.Label_Cool, 0, 0); + this.tableLayoutPanel1.Controls.Add(this.FLP_SmartClever, 3, 0); + this.tableLayoutPanel1.Location = new System.Drawing.Point(0, 16); + this.tableLayoutPanel1.Margin = new System.Windows.Forms.Padding(0); + this.tableLayoutPanel1.Name = "tableLayoutPanel1"; + this.tableLayoutPanel1.RowCount = 2; + this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 16F)); + this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle()); + this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 20F)); + this.tableLayoutPanel1.Size = new System.Drawing.Size(288, 40); + this.tableLayoutPanel1.TabIndex = 67; + // + // FLP_SmartClever + // + this.FLP_SmartClever.Controls.Add(this.Label_Smart); + this.FLP_SmartClever.Controls.Add(this.Label_Clever); + this.FLP_SmartClever.Dock = System.Windows.Forms.DockStyle.Fill; + this.FLP_SmartClever.Location = new System.Drawing.Point(144, 0); + this.FLP_SmartClever.Margin = new System.Windows.Forms.Padding(0); + this.FLP_SmartClever.Name = "FLP_SmartClever"; + this.FLP_SmartClever.Size = new System.Drawing.Size(48, 16); + this.FLP_SmartClever.TabIndex = 66; + // + // Label_Clever + // + this.Label_Clever.Anchor = System.Windows.Forms.AnchorStyles.None; + this.Label_Clever.Location = new System.Drawing.Point(0, 16); + this.Label_Clever.Margin = new System.Windows.Forms.Padding(0); + this.Label_Clever.Name = "Label_Clever"; + this.Label_Clever.Size = new System.Drawing.Size(48, 16); + this.Label_Clever.TabIndex = 67; + this.Label_Clever.Text = "Clever"; + this.Label_Clever.TextAlign = System.Drawing.ContentAlignment.MiddleCenter; + // // ContestStat // this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Inherit; - this.Controls.Add(this.TB_Sheen); - this.Controls.Add(this.TB_Tough); - this.Controls.Add(this.TB_Smart); - this.Controls.Add(this.TB_Cute); - this.Controls.Add(this.TB_Beauty); - this.Controls.Add(this.TB_Cool); - this.Controls.Add(this.Label_Sheen); - this.Controls.Add(this.Label_Tough); - this.Controls.Add(this.Label_Clever); - this.Controls.Add(this.Label_Cute); - this.Controls.Add(this.Label_Beauty); - this.Controls.Add(this.Label_Cool); + this.Controls.Add(this.tableLayoutPanel1); this.Controls.Add(this.Label_ContestStats); - this.Controls.Add(this.Label_Smart); this.Name = "ContestStat"; - this.Size = new System.Drawing.Size(230, 50); + this.Size = new System.Drawing.Size(288, 56); + this.tableLayoutPanel1.ResumeLayout(false); + this.tableLayoutPanel1.PerformLayout(); + this.FLP_SmartClever.ResumeLayout(false); this.ResumeLayout(false); - this.PerformLayout(); } @@ -222,11 +290,13 @@ private System.Windows.Forms.MaskedTextBox TB_Cool; private System.Windows.Forms.Label Label_Sheen; private System.Windows.Forms.Label Label_Tough; - private System.Windows.Forms.Label Label_Clever; private System.Windows.Forms.Label Label_Cute; private System.Windows.Forms.Label Label_Beauty; private System.Windows.Forms.Label Label_Cool; private System.Windows.Forms.Label Label_ContestStats; private System.Windows.Forms.Label Label_Smart; + private System.Windows.Forms.TableLayoutPanel tableLayoutPanel1; + private System.Windows.Forms.Label Label_Clever; + private System.Windows.Forms.FlowLayoutPanel FLP_SmartClever; } } diff --git a/PKHeX.WinForms/Controls/PKM Editor/DrawConfig.cs b/PKHeX.WinForms/Controls/PKM Editor/DrawConfig.cs index 69a7c1735..895b8d312 100644 --- a/PKHeX.WinForms/Controls/PKM Editor/DrawConfig.cs +++ b/PKHeX.WinForms/Controls/PKM Editor/DrawConfig.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.ComponentModel; +using System.Diagnostics.CodeAnalysis; using System.Drawing; using PKHeX.Core; @@ -10,6 +11,7 @@ namespace PKHeX.WinForms; /// Drawing Configuration for painting and updating controls /// [Serializable] +[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicProperties)] public sealed class DrawConfig : IDisposable { private const string PKM = "Pokémon Editor"; diff --git a/PKHeX.WinForms/Controls/PKM Editor/EditPK1.cs b/PKHeX.WinForms/Controls/PKM Editor/EditPK1.cs index 448f49106..54a249d48 100644 --- a/PKHeX.WinForms/Controls/PKM Editor/EditPK1.cs +++ b/PKHeX.WinForms/Controls/PKM Editor/EditPK1.cs @@ -1,4 +1,4 @@ -using System; +using System; using PKHeX.Core; namespace PKHeX.WinForms.Controls; @@ -11,7 +11,7 @@ public partial class PKMEditor throw new FormatException(nameof(Entity)); LoadMisc1(pk1); - TID_Trainer.LoadIDValues(pk1); + TID_Trainer.LoadIDValues(pk1, pk1.Format); CR_PK1.LoadPK1(pk1); // Attempt to detect language diff --git a/PKHeX.WinForms/Controls/PKM Editor/EditPK2.cs b/PKHeX.WinForms/Controls/PKM Editor/EditPK2.cs index 66e134df8..ec13807e3 100644 --- a/PKHeX.WinForms/Controls/PKM Editor/EditPK2.cs +++ b/PKHeX.WinForms/Controls/PKM Editor/EditPK2.cs @@ -1,4 +1,4 @@ -using System; +using System; using PKHeX.Core; namespace PKHeX.WinForms.Controls; @@ -18,7 +18,7 @@ public partial class PKMEditor LoadMisc1(pk2); LoadMisc2(pk2); - TID_Trainer.LoadIDValues(pk2); + TID_Trainer.LoadIDValues(pk2, pk2.Format); TB_MetLevel.Text = c2.Met_Level.ToString(); CB_MetLocation.SelectedValue = c2.Met_Location; CB_MetTimeOfDay.SelectedIndex = c2.Met_TimeOfDay; diff --git a/PKHeX.WinForms/Controls/PKM Editor/EntityInstructionBuilder.Designer.cs b/PKHeX.WinForms/Controls/PKM Editor/EntityInstructionBuilder.Designer.cs index a7e17682a..cec9ca4f8 100644 --- a/PKHeX.WinForms/Controls/PKM Editor/EntityInstructionBuilder.Designer.cs +++ b/PKHeX.WinForms/Controls/PKM Editor/EntityInstructionBuilder.Designer.cs @@ -43,18 +43,20 @@ namespace PKHeX.WinForms.Controls // this.L_PropValue.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); this.L_PropValue.AutoSize = true; - this.L_PropValue.Location = new System.Drawing.Point(171, 24); + this.L_PropValue.Location = new System.Drawing.Point(200, 28); + this.L_PropValue.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); this.L_PropValue.Name = "L_PropValue"; - this.L_PropValue.Size = new System.Drawing.Size(73, 13); + this.L_PropValue.Size = new System.Drawing.Size(80, 15); this.L_PropValue.TabIndex = 18; this.L_PropValue.Text = "PropertyValue"; // // L_PropType // this.L_PropType.AutoSize = true; - this.L_PropType.Location = new System.Drawing.Point(47, 24); + this.L_PropType.Location = new System.Drawing.Point(55, 28); + this.L_PropType.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); this.L_PropType.Name = "L_PropType"; - this.L_PropType.Size = new System.Drawing.Size(70, 13); + this.L_PropType.Size = new System.Drawing.Size(76, 15); this.L_PropType.TabIndex = 17; this.L_PropType.Text = "PropertyType"; // @@ -64,12 +66,17 @@ namespace PKHeX.WinForms.Controls this.CB_Require.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; this.CB_Require.FormattingEnabled = true; this.CB_Require.Items.AddRange(new object[] { - "Set Equal To", - "Require Equals", - "Require Not Equals"}); - this.CB_Require.Location = new System.Drawing.Point(174, 0); + "Set", + "==", + "!=", + ">", + ">=", + "<", + "<="}); + this.CB_Require.Location = new System.Drawing.Point(203, 0); + this.CB_Require.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3); this.CB_Require.Name = "CB_Require"; - this.CB_Require.Size = new System.Drawing.Size(116, 21); + this.CB_Require.Size = new System.Drawing.Size(135, 23); this.CB_Require.TabIndex = 16; // // CB_Property @@ -80,9 +87,10 @@ namespace PKHeX.WinForms.Controls this.CB_Property.AutoCompleteSource = System.Windows.Forms.AutoCompleteSource.ListItems; this.CB_Property.DropDownWidth = 200; this.CB_Property.FormattingEnabled = true; - this.CB_Property.Location = new System.Drawing.Point(50, 0); + this.CB_Property.Location = new System.Drawing.Point(58, 0); + this.CB_Property.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3); this.CB_Property.Name = "CB_Property"; - this.CB_Property.Size = new System.Drawing.Size(118, 21); + this.CB_Property.Size = new System.Drawing.Size(137, 23); this.CB_Property.TabIndex = 15; this.CB_Property.SelectedIndexChanged += new System.EventHandler(this.CB_Property_SelectedIndexChanged); // @@ -91,22 +99,24 @@ namespace PKHeX.WinForms.Controls this.CB_Format.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; this.CB_Format.FormattingEnabled = true; this.CB_Format.Location = new System.Drawing.Point(0, 0); + this.CB_Format.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3); this.CB_Format.Name = "CB_Format"; - this.CB_Format.Size = new System.Drawing.Size(44, 21); + this.CB_Format.Size = new System.Drawing.Size(51, 23); this.CB_Format.TabIndex = 14; this.CB_Format.SelectedIndexChanged += new System.EventHandler(this.CB_Format_SelectedIndexChanged); // // EntityInstructionBuilder // - this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); + this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 15F); this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; this.Controls.Add(this.L_PropValue); this.Controls.Add(this.L_PropType); this.Controls.Add(this.CB_Require); this.Controls.Add(this.CB_Property); this.Controls.Add(this.CB_Format); + this.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3); this.Name = "EntityInstructionBuilder"; - this.Size = new System.Drawing.Size(290, 40); + this.Size = new System.Drawing.Size(338, 46); this.ResumeLayout(false); this.PerformLayout(); diff --git a/PKHeX.WinForms/Controls/PKM Editor/IMainEditor.cs b/PKHeX.WinForms/Controls/PKM Editor/IMainEditor.cs index 22998727e..ac28435e0 100644 --- a/PKHeX.WinForms/Controls/PKM Editor/IMainEditor.cs +++ b/PKHeX.WinForms/Controls/PKM Editor/IMainEditor.cs @@ -1,3 +1,4 @@ +using System; using PKHeX.Core; namespace PKHeX.WinForms.Controls; @@ -10,3 +11,10 @@ public interface IMainEditor : IPKMView void UpdateIVsGB(bool skipForm); void ChangeNature(int newNature); } + +[Flags] +public enum UpdateLegalityArgs +{ + None, + SkipMoveRepopulation = 1 << 0, +} diff --git a/PKHeX.WinForms/Controls/PKM Editor/LoadSave.cs b/PKHeX.WinForms/Controls/PKM Editor/LoadSave.cs index 08d5c45f6..587bbcfda 100644 --- a/PKHeX.WinForms/Controls/PKM Editor/LoadSave.cs +++ b/PKHeX.WinForms/Controls/PKM Editor/LoadSave.cs @@ -1,8 +1,7 @@ using System; +using System.Drawing; using System.Windows.Forms; using PKHeX.Core; -using PKHeX.Drawing; -using PKHeX.Drawing.PokeSprite; namespace PKHeX.WinForms.Controls; @@ -10,13 +9,13 @@ public partial class PKMEditor { private void LoadNickname(PKM pk) { - CHK_Nicknamed.Checked = pk.IsNicknamed; + CHK_NicknamedFlag.Checked = pk.IsNicknamed; TB_Nickname.Text = pk.Nickname; } private void SaveNickname(PKM pk) { - pk.IsNicknamed = CHK_Nicknamed.Checked; + pk.IsNicknamed = CHK_NicknamedFlag.Checked; pk.Nickname = TB_Nickname.Text; } @@ -98,34 +97,34 @@ public partial class PKMEditor private void LoadMoves(PKM pk) { - CB_Move1.SelectedValue = (int)pk.Move1; - CB_Move2.SelectedValue = (int)pk.Move2; - CB_Move3.SelectedValue = (int)pk.Move3; - CB_Move4.SelectedValue = (int)pk.Move4; - LoadClamp(CB_PPu1, pk.Move1_PPUps); - LoadClamp(CB_PPu2, pk.Move2_PPUps); - LoadClamp(CB_PPu3, pk.Move3_PPUps); - LoadClamp(CB_PPu4, pk.Move4_PPUps); - TB_PP1.Text = pk.Move1_PP.ToString(); - TB_PP2.Text = pk.Move2_PP.ToString(); - TB_PP3.Text = pk.Move3_PP.ToString(); - TB_PP4.Text = pk.Move4_PP.ToString(); + MC_Move1.SelectedMove = pk.Move1; + MC_Move2.SelectedMove = pk.Move2; + MC_Move3.SelectedMove = pk.Move3; + MC_Move4.SelectedMove = pk.Move4; + MC_Move1.PPUps = pk.Move1_PPUps; + MC_Move2.PPUps = pk.Move2_PPUps; + MC_Move3.PPUps = pk.Move3_PPUps; + MC_Move4.PPUps = pk.Move4_PPUps; + MC_Move1.PP = pk.Move1_PP; + MC_Move2.PP = pk.Move2_PP; + MC_Move3.PP = pk.Move3_PP; + MC_Move4.PP = pk.Move4_PP; } private void SaveMoves(PKM pk) { - pk.Move1 = (ushort)WinFormsUtil.GetIndex(CB_Move1); - pk.Move2 = (ushort)WinFormsUtil.GetIndex(CB_Move2); - pk.Move3 = (ushort)WinFormsUtil.GetIndex(CB_Move3); - pk.Move4 = (ushort)WinFormsUtil.GetIndex(CB_Move4); - pk.Move1_PP = WinFormsUtil.GetIndex(CB_Move1) > 0 ? Util.ToInt32(TB_PP1.Text) : 0; - pk.Move2_PP = WinFormsUtil.GetIndex(CB_Move2) > 0 ? Util.ToInt32(TB_PP2.Text) : 0; - pk.Move3_PP = WinFormsUtil.GetIndex(CB_Move3) > 0 ? Util.ToInt32(TB_PP3.Text) : 0; - pk.Move4_PP = WinFormsUtil.GetIndex(CB_Move4) > 0 ? Util.ToInt32(TB_PP4.Text) : 0; - pk.Move1_PPUps = WinFormsUtil.GetIndex(CB_Move1) > 0 ? CB_PPu1.SelectedIndex : 0; - pk.Move2_PPUps = WinFormsUtil.GetIndex(CB_Move2) > 0 ? CB_PPu2.SelectedIndex : 0; - pk.Move3_PPUps = WinFormsUtil.GetIndex(CB_Move3) > 0 ? CB_PPu3.SelectedIndex : 0; - pk.Move4_PPUps = WinFormsUtil.GetIndex(CB_Move4) > 0 ? CB_PPu4.SelectedIndex : 0; + pk.Move1 = MC_Move1.SelectedMove; + pk.Move2 = MC_Move2.SelectedMove; + pk.Move3 = MC_Move3.SelectedMove; + pk.Move4 = MC_Move4.SelectedMove; + pk.Move1_PP = MC_Move1.PP; + pk.Move2_PP = MC_Move2.PP; + pk.Move3_PP = MC_Move3.PP; + pk.Move4_PP = MC_Move4.PP; + pk.Move1_PPUps = MC_Move1.PPUps; + pk.Move2_PPUps = MC_Move2.PPUps; + pk.Move3_PPUps = MC_Move3.PPUps; + pk.Move4_PPUps = MC_Move4.PPUps; } private void LoadShadow3(IShadowCapture pk) @@ -249,7 +248,7 @@ public partial class PKMEditor if (pk is IContestStatsReadOnly s) s.CopyContestStatsTo(Contest); - TID_Trainer.LoadIDValues(pk); + TID_Trainer.LoadIDValues(pk, pk.Format); // Load Extrabyte Value var offset = Convert.ToInt32(CB_ExtraBytes.Text, 16); @@ -276,8 +275,8 @@ public partial class PKMEditor private void LoadMisc4(PKM pk) { - CAL_MetDate.Value = pk.MetDate ?? new DateTime(2000, 1, 1); - if (!Legal.IsMetAsEgg(pk)) + CAL_MetDate.Value = pk.MetDate?.ToDateTime(new TimeOnly()) ?? new(2000, 1, 1); + if (!EncounterStateUtil.IsMetAsEgg(pk)) { CHK_AsEgg.Checked = GB_EggConditions.Enabled = false; CAL_EggDate.Value = new DateTime(2000, 01, 01); @@ -286,7 +285,7 @@ public partial class PKMEditor { // Was obtained initially as an egg. CHK_AsEgg.Checked = GB_EggConditions.Enabled = true; - CAL_EggDate.Value = pk.EggMetDate ?? new DateTime(2000, 1, 1); + CAL_EggDate.Value = pk.EggMetDate?.ToDateTime(new TimeOnly()) ?? new(2000, 1, 1); } CB_EggLocation.SelectedValue = pk.Egg_Location; } @@ -295,7 +294,7 @@ public partial class PKMEditor { if (CHK_AsEgg.Checked) // If encountered as an egg, load the Egg Met data from fields. { - pk.EggMetDate = CAL_EggDate.Value; + pk.EggMetDate = DateOnly.FromDateTime(CAL_EggDate.Value); pk.Egg_Location = WinFormsUtil.GetIndex(CB_EggLocation); } else // Default Dates @@ -308,7 +307,7 @@ public partial class PKMEditor if (pk.IsEgg && pk.Met_Location == LocationEdits.GetNoneLocation(pk)) // If still an egg, it has no hatch location/date. Zero it! pk.MetDate = null; // clear else - pk.MetDate = CAL_MetDate.Value; + pk.MetDate = DateOnly.FromDateTime(CAL_MetDate.Value); pk.Ability = WinFormsUtil.GetIndex(HaX ? DEV_Ability : CB_Ability); } @@ -367,8 +366,8 @@ public partial class PKMEditor TB_HT.Text = handler; UC_HTGender.Gender = gender; - if (handler.Length == 0) - UC_HTGender.Visible = false; + bool hasValue = handler.Length != 0; + L_CurrentHandler.Visible = CB_Handler.Visible = UC_HTGender.Visible = hasValue; // Indicate who is currently in possession of the PKM UpadteHandlingTrainerBackground(pk.CurrentHandler); @@ -376,16 +375,17 @@ public partial class PKMEditor private void UpadteHandlingTrainerBackground(int handler) { - var activeColor = ImageUtil.ChangeOpacity(SpriteUtil.Spriter.Set, 0.5); if (handler == 0) // OT { - GB_OT.BackgroundImage = activeColor; - GB_nOT.BackgroundImage = null; + GB_OT.ForeColor = Color.Red; + GB_nOT.ResetForeColor(); + CB_Handler.SelectedIndex = 0; } else // Handling Trainer { - GB_nOT.BackgroundImage = activeColor; - GB_OT.BackgroundImage = null; + GB_nOT.ForeColor = Color.Red; + GB_OT.ResetForeColor(); + CB_Handler.SelectedIndex = 1; } } diff --git a/PKHeX.WinForms/Controls/PKM Editor/MoveChoice.Designer.cs b/PKHeX.WinForms/Controls/PKM Editor/MoveChoice.Designer.cs new file mode 100644 index 000000000..90e4164fe --- /dev/null +++ b/PKHeX.WinForms/Controls/PKM Editor/MoveChoice.Designer.cs @@ -0,0 +1,122 @@ +namespace PKHeX.WinForms.Controls +{ + partial class MoveChoice + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Component Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.PB_Triangle = new System.Windows.Forms.PictureBox(); + this.TB_PP = new System.Windows.Forms.MaskedTextBox(); + this.CB_PPUps = new System.Windows.Forms.ComboBox(); + this.CB_Move = new System.Windows.Forms.ComboBox(); + this.FLP_Move = new System.Windows.Forms.FlowLayoutPanel(); + ((System.ComponentModel.ISupportInitialize)(this.PB_Triangle)).BeginInit(); + this.FLP_Move.SuspendLayout(); + this.SuspendLayout(); + // + // PB_Triangle + // + this.PB_Triangle.Image = global::PKHeX.WinForms.Properties.Resources.warn; + this.PB_Triangle.Location = new System.Drawing.Point(0, 0); + this.PB_Triangle.Name = "PB_Triangle"; + this.PB_Triangle.Size = new System.Drawing.Size(24, 24); + this.PB_Triangle.SizeMode = System.Windows.Forms.PictureBoxSizeMode.CenterImage; + this.PB_Triangle.TabIndex = 15; + this.PB_Triangle.TabStop = false; + this.PB_Triangle.Visible = false; + // + // TB_PP + // + this.TB_PP.Location = new System.Drawing.Point(128, 0); + this.TB_PP.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); + this.TB_PP.Mask = "000"; + this.TB_PP.Name = "TB_PP"; + this.TB_PP.PromptChar = ' '; + this.TB_PP.Size = new System.Drawing.Size(32, 23); + this.TB_PP.TabIndex = 1; + // + // CB_PPUps + // + this.CB_PPUps.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; + this.CB_PPUps.FormattingEnabled = true; + this.CB_PPUps.Items.AddRange(new object[] { + "0", + "1", + "2", + "3"}); + this.CB_PPUps.Location = new System.Drawing.Point(164, 0); + this.CB_PPUps.Margin = new System.Windows.Forms.Padding(0, 0, 4, 0); + this.CB_PPUps.Name = "CB_PPUps"; + this.CB_PPUps.Size = new System.Drawing.Size(40, 23); + this.CB_PPUps.TabIndex = 2; + // + // CB_Move + // + this.CB_Move.AutoCompleteMode = System.Windows.Forms.AutoCompleteMode.SuggestAppend; + this.CB_Move.AutoCompleteSource = System.Windows.Forms.AutoCompleteSource.ListItems; + this.CB_Move.DrawMode = System.Windows.Forms.DrawMode.OwnerDrawVariable; + this.CB_Move.DropDownHeight = 400; + this.CB_Move.FormattingEnabled = true; + this.CB_Move.IntegralHeight = false; + this.CB_Move.Location = new System.Drawing.Point(0, 0); + this.CB_Move.Margin = new System.Windows.Forms.Padding(0, 0, 4, 0); + this.CB_Move.Name = "CB_Move"; + this.CB_Move.Size = new System.Drawing.Size(120, 24); + this.CB_Move.TabIndex = 0; + // + // FLP_Move + // + this.FLP_Move.Controls.Add(this.CB_Move); + this.FLP_Move.Controls.Add(this.TB_PP); + this.FLP_Move.Controls.Add(this.CB_PPUps); + this.FLP_Move.Location = new System.Drawing.Point(24, 0); + this.FLP_Move.Name = "FLP_Move"; + this.FLP_Move.Size = new System.Drawing.Size(216, 24); + this.FLP_Move.TabIndex = 18; + // + // MoveChoice + // + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Inherit; + this.Controls.Add(this.PB_Triangle); + this.Controls.Add(this.FLP_Move); + this.Name = "MoveChoice"; + this.Size = new System.Drawing.Size(240, 24); + ((System.ComponentModel.ISupportInitialize)(this.PB_Triangle)).EndInit(); + this.FLP_Move.ResumeLayout(false); + this.FLP_Move.PerformLayout(); + this.ResumeLayout(false); + + } + + #endregion + + private System.Windows.Forms.PictureBox PB_Triangle; + private System.Windows.Forms.MaskedTextBox TB_PP; + internal System.Windows.Forms.ComboBox CB_PPUps; + private System.Windows.Forms.FlowLayoutPanel FLP_Move; + internal System.Windows.Forms.ComboBox CB_Move; + } +} diff --git a/PKHeX.WinForms/Controls/PKM Editor/MoveChoice.cs b/PKHeX.WinForms/Controls/PKM Editor/MoveChoice.cs new file mode 100644 index 000000000..1bd04e231 --- /dev/null +++ b/PKHeX.WinForms/Controls/PKM Editor/MoveChoice.cs @@ -0,0 +1,45 @@ +using System.Windows.Forms; +using PKHeX.Core; + +namespace PKHeX.WinForms.Controls; + +public partial class MoveChoice : UserControl +{ + public MoveChoice() + { + InitializeComponent(); + CB_Move.InitializeBinding(); + } + + public ushort SelectedMove { get => (ushort)WinFormsUtil.GetIndex(CB_Move); set => CB_Move.SelectedValue = (int)value; } + public int PP { get => SelectedMove == 0 ? 0 : Util.ToInt32(TB_PP.Text); set => TB_PP.Text = value.ToString(); } + public int PPUps { get => SelectedMove == 0 ? 0 : CB_PPUps.SelectedIndex; set => LoadClamp(CB_PPUps, value); } + public bool HideLegality { private get; set; } + + private static void LoadClamp(ComboBox cb, int value) + { + var max = cb.Items.Count - 1; + if (value > max) + value = max; + else if (value < -1) + value = 0; + cb.SelectedIndex = value; + } + + public void UpdateLegality(MoveResult move, PKM entity, int i) + { + if (HideLegality) + { + PB_Triangle.Visible = false; + return; + } + PB_Triangle.Visible = true; + PB_Triangle.Image = MoveDisplay.GetMoveImage(!move.Valid, entity, i); + } + + public void HealPP(PKM pk) + { + var move = SelectedMove; + PP = move <= 0 ? (PPUps = 0) : pk.GetMovePP(move, PPUps); + } +} diff --git a/PKHeX.WinForms/Controls/PKM Editor/PKMEditor.Designer.cs b/PKHeX.WinForms/Controls/PKM Editor/PKMEditor.Designer.cs index eb9a16d01..77b7446a7 100644 --- a/PKHeX.WinForms/Controls/PKM Editor/PKMEditor.Designer.cs +++ b/PKHeX.WinForms/Controls/PKM Editor/PKMEditor.Designer.cs @@ -28,9 +28,9 @@ namespace PKHeX.WinForms.Controls ///
private void InitializeComponent() { - this.components = new System.ComponentModel.Container(); - this.tabMain = new System.Windows.Forms.TabControl(); - this.Tab_Main = new System.Windows.Forms.TabPage(); + System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(PKMEditor)); + this.Hidden_TC = new System.Windows.Forms.TabControl(); + this.Hidden_Main = new System.Windows.Forms.TabPage(); this.FLP_Main = new System.Windows.Forms.FlowLayoutPanel(); this.FLP_PID = new System.Windows.Forms.FlowLayoutPanel(); this.FLP_PIDLeft = new System.Windows.Forms.FlowLayoutPanel(); @@ -47,7 +47,8 @@ namespace PKHeX.WinForms.Controls this.CB_Species = new System.Windows.Forms.ComboBox(); this.FLP_Nickname = new System.Windows.Forms.FlowLayoutPanel(); this.FLP_NicknameLeft = new System.Windows.Forms.FlowLayoutPanel(); - this.CHK_Nicknamed = new System.Windows.Forms.CheckBox(); + this.CHK_Nicknamed = new System.Windows.Forms.Label(); + this.CHK_NicknamedFlag = new System.Windows.Forms.CheckBox(); this.TB_Nickname = new System.Windows.Forms.TextBox(); this.FLP_EXPLevel = new System.Windows.Forms.FlowLayoutPanel(); this.Label_EXP = new System.Windows.Forms.Label(); @@ -64,6 +65,7 @@ namespace PKHeX.WinForms.Controls this.FLP_Form = new System.Windows.Forms.FlowLayoutPanel(); this.FLP_FormLeft = new System.Windows.Forms.FlowLayoutPanel(); this.Label_Form = new System.Windows.Forms.Label(); + this.L_FormArgument = new System.Windows.Forms.Label(); this.FLP_FormRight = new System.Windows.Forms.FlowLayoutPanel(); this.CB_Form = new System.Windows.Forms.ComboBox(); this.FA_Form = new PKHeX.WinForms.Controls.FormArgument(); @@ -97,15 +99,6 @@ namespace PKHeX.WinForms.Controls this.CB_PKRSStrain = new System.Windows.Forms.ComboBox(); this.Label_PKRSdays = new System.Windows.Forms.Label(); this.CB_PKRSDays = new System.Windows.Forms.ComboBox(); - this.FLP_Country = new System.Windows.Forms.FlowLayoutPanel(); - this.Label_Country = new System.Windows.Forms.Label(); - this.CB_Country = new System.Windows.Forms.ComboBox(); - this.FLP_SubRegion = new System.Windows.Forms.FlowLayoutPanel(); - this.Label_SubRegion = new System.Windows.Forms.Label(); - this.CB_SubRegion = new System.Windows.Forms.ComboBox(); - this.FLP_3DSRegion = new System.Windows.Forms.FlowLayoutPanel(); - this.Label_3DSRegion = new System.Windows.Forms.Label(); - this.CB_3DSReg = new System.Windows.Forms.ComboBox(); this.FLP_NSparkle = new System.Windows.Forms.FlowLayoutPanel(); this.L_NSparkle = new System.Windows.Forms.Label(); this.CHK_NSparkle = new System.Windows.Forms.CheckBox(); @@ -116,17 +109,10 @@ namespace PKHeX.WinForms.Controls this.L_HeartGauge = new System.Windows.Forms.Label(); this.NUD_Purification = new System.Windows.Forms.NumericUpDown(); this.CHK_Shadow = new System.Windows.Forms.CheckBox(); - this.FLP_ShinyLeaf = new System.Windows.Forms.FlowLayoutPanel(); - this.L_ShinyLeaf = new System.Windows.Forms.Label(); - this.ShinyLeaf = new PKHeX.WinForms.Controls.ShinyLeaf(); this.FLP_CatchRate = new System.Windows.Forms.FlowLayoutPanel(); this.L_CatchRate = new System.Windows.Forms.Label(); this.CR_PK1 = new PKHeX.WinForms.Controls.CatchRate(); - this.FLP_SizeCP = new System.Windows.Forms.FlowLayoutPanel(); - this.SizeCP = new PKHeX.WinForms.Controls.SizeCP(); - this.Tab_Met = new System.Windows.Forms.TabPage(); - this.TB_HomeTracker = new System.Windows.Forms.TextBox(); - this.L_HomeTracker = new System.Windows.Forms.Label(); + this.Hidden_Met = new System.Windows.Forms.TabPage(); this.CHK_AsEgg = new System.Windows.Forms.CheckBox(); this.GB_EggConditions = new System.Windows.Forms.GroupBox(); this.CB_EggLocation = new System.Windows.Forms.ComboBox(); @@ -164,19 +150,14 @@ namespace PKHeX.WinForms.Controls this.FLP_TimeOfDay = new System.Windows.Forms.FlowLayoutPanel(); this.L_MetTimeOfDay = new System.Windows.Forms.Label(); this.CB_MetTimeOfDay = new System.Windows.Forms.ComboBox(); - this.Tab_Stats = new System.Windows.Forms.TabPage(); + this.Hidden_Stats = new System.Windows.Forms.TabPage(); this.Stats = new PKHeX.WinForms.Controls.StatEditor(); - this.Contest = new PKHeX.WinForms.Controls.ContestStat(); - this.Tab_Attacks = new System.Windows.Forms.TabPage(); + this.Hidden_Moves = new System.Windows.Forms.TabPage(); this.L_AlphaMastered = new System.Windows.Forms.Label(); this.CB_AlphaMastered = new System.Windows.Forms.ComboBox(); this.FLP_MoveFlags = new System.Windows.Forms.FlowLayoutPanel(); - this.B_Records = new System.Windows.Forms.Button(); + this.B_RelearnFlags = new System.Windows.Forms.Button(); this.B_MoveShop = new System.Windows.Forms.Button(); - this.PB_WarnMove4 = new System.Windows.Forms.PictureBox(); - this.PB_WarnMove3 = new System.Windows.Forms.PictureBox(); - this.PB_WarnMove2 = new System.Windows.Forms.PictureBox(); - this.PB_WarnMove1 = new System.Windows.Forms.PictureBox(); this.GB_RelearnMoves = new System.Windows.Forms.GroupBox(); this.PB_WarnRelearn4 = new System.Windows.Forms.PictureBox(); this.PB_WarnRelearn3 = new System.Windows.Forms.PictureBox(); @@ -187,35 +168,20 @@ namespace PKHeX.WinForms.Controls this.CB_RelearnMove2 = new System.Windows.Forms.ComboBox(); this.CB_RelearnMove1 = new System.Windows.Forms.ComboBox(); this.GB_CurrentMoves = new System.Windows.Forms.GroupBox(); - this.TB_PP4 = new System.Windows.Forms.MaskedTextBox(); - this.TB_PP3 = new System.Windows.Forms.MaskedTextBox(); - this.TB_PP2 = new System.Windows.Forms.MaskedTextBox(); - this.TB_PP1 = new System.Windows.Forms.MaskedTextBox(); + this.FLP_Moves = new System.Windows.Forms.FlowLayoutPanel(); + this.MC_Move1 = new PKHeX.WinForms.Controls.MoveChoice(); + this.MC_Move2 = new PKHeX.WinForms.Controls.MoveChoice(); + this.MC_Move3 = new PKHeX.WinForms.Controls.MoveChoice(); + this.MC_Move4 = new PKHeX.WinForms.Controls.MoveChoice(); this.Label_CurPP = new System.Windows.Forms.Label(); this.Label_PPups = new System.Windows.Forms.Label(); - this.CB_PPu4 = new System.Windows.Forms.ComboBox(); - this.CB_PPu3 = new System.Windows.Forms.ComboBox(); - this.CB_PPu2 = new System.Windows.Forms.ComboBox(); - this.CB_Move4 = new System.Windows.Forms.ComboBox(); - this.CB_PPu1 = new System.Windows.Forms.ComboBox(); - this.CB_Move3 = new System.Windows.Forms.ComboBox(); - this.CB_Move2 = new System.Windows.Forms.ComboBox(); - this.CB_Move1 = new System.Windows.Forms.ComboBox(); - this.Tab_OTMisc = new System.Windows.Forms.TabPage(); - this.PB_BattleVersion = new System.Windows.Forms.PictureBox(); - this.PB_Origin = new System.Windows.Forms.PictureBox(); - this.PB_Favorite = new System.Windows.Forms.PictureBox(); + this.Hidden_Cosmetic = new System.Windows.Forms.TabPage(); + this.Contest = new PKHeX.WinForms.Controls.ContestStat(); this.FLP_PKMEditors = new System.Windows.Forms.FlowLayoutPanel(); this.BTN_Ribbons = new System.Windows.Forms.Button(); this.BTN_Medals = new System.Windows.Forms.Button(); this.BTN_History = new System.Windows.Forms.Button(); - this.TB_EC = new System.Windows.Forms.TextBox(); - this.GB_nOT = new System.Windows.Forms.GroupBox(); - this.UC_HTGender = new PKHeX.WinForms.Controls.GenderToggle(); - this.CB_HTLanguage = new System.Windows.Forms.ComboBox(); - this.TB_HT = new System.Windows.Forms.TextBox(); - this.Label_PrevOT = new System.Windows.Forms.Label(); - this.BTN_RerollEC = new System.Windows.Forms.Button(); + this.FLP_CosmeticTop = new System.Windows.Forms.FlowLayoutPanel(); this.GB_Markings = new System.Windows.Forms.GroupBox(); this.PB_Mark6 = new System.Windows.Forms.PictureBox(); this.PB_Mark3 = new System.Windows.Forms.PictureBox(); @@ -225,21 +191,58 @@ namespace PKHeX.WinForms.Controls this.PB_MarkShiny = new System.Windows.Forms.PictureBox(); this.PB_Mark1 = new System.Windows.Forms.PictureBox(); this.PB_Mark4 = new System.Windows.Forms.PictureBox(); - this.GB_ExtraBytes = new System.Windows.Forms.GroupBox(); - this.TB_ExtraByte = new System.Windows.Forms.MaskedTextBox(); - this.CB_ExtraBytes = new System.Windows.Forms.ComboBox(); - this.GB_OT = new System.Windows.Forms.GroupBox(); - this.UC_OTGender = new PKHeX.WinForms.Controls.GenderToggle(); + this.FLP_BigMarkings = new System.Windows.Forms.FlowLayoutPanel(); + this.PB_Favorite = new System.Windows.Forms.PictureBox(); + this.PB_Origin = new System.Windows.Forms.PictureBox(); + this.PB_BattleVersion = new System.Windows.Forms.PictureBox(); + this.SizeCP = new PKHeX.WinForms.Controls.SizeCP(); + this.ShinyLeaf = new PKHeX.WinForms.Controls.ShinyLeaf(); + this.Hidden_OTMisc = new System.Windows.Forms.TabPage(); + this.FLP_OTMisc = new System.Windows.Forms.FlowLayoutPanel(); + this.GB_OT = new System.Windows.Forms.Label(); this.TID_Trainer = new PKHeX.WinForms.Controls.TrainerID(); - this.TB_OT = new System.Windows.Forms.TextBox(); + this.FLP_OT = new System.Windows.Forms.FlowLayoutPanel(); this.Label_OT = new System.Windows.Forms.Label(); + this.TB_OT = new System.Windows.Forms.TextBox(); + this.UC_OTGender = new PKHeX.WinForms.Controls.GenderToggle(); + this.FLP_Country = new System.Windows.Forms.FlowLayoutPanel(); + this.Label_Country = new System.Windows.Forms.Label(); + this.CB_Country = new System.Windows.Forms.ComboBox(); + this.FLP_SubRegion = new System.Windows.Forms.FlowLayoutPanel(); + this.Label_SubRegion = new System.Windows.Forms.Label(); + this.CB_SubRegion = new System.Windows.Forms.ComboBox(); + this.FLP_3DSRegion = new System.Windows.Forms.FlowLayoutPanel(); + this.Label_3DSRegion = new System.Windows.Forms.Label(); + this.CB_3DSReg = new System.Windows.Forms.ComboBox(); + this.FLP_Handler = new System.Windows.Forms.FlowLayoutPanel(); + this.L_CurrentHandler = new System.Windows.Forms.Label(); + this.CB_Handler = new System.Windows.Forms.ComboBox(); + this.GB_nOT = new System.Windows.Forms.Label(); + this.FLP_HT = new System.Windows.Forms.FlowLayoutPanel(); + this.Label_PrevOT = new System.Windows.Forms.Label(); + this.TB_HT = new System.Windows.Forms.TextBox(); + this.UC_HTGender = new PKHeX.WinForms.Controls.GenderToggle(); + this.FLP_HTLanguage = new System.Windows.Forms.FlowLayoutPanel(); + this.L_LanguageHT = new System.Windows.Forms.Label(); + this.CB_HTLanguage = new System.Windows.Forms.ComboBox(); + this.FLP_ExtraBytes = new System.Windows.Forms.FlowLayoutPanel(); + this.L_ExtraBytes = new System.Windows.Forms.Label(); + this.CB_ExtraBytes = new System.Windows.Forms.ComboBox(); + this.TB_ExtraByte = new System.Windows.Forms.MaskedTextBox(); + this.L_HomeTracker = new System.Windows.Forms.Label(); + this.TB_HomeTracker = new System.Windows.Forms.TextBox(); this.Label_EncryptionConstant = new System.Windows.Forms.Label(); - this.SpeciesIDTip = new System.Windows.Forms.ToolTip(this.components); - this.NatureTip = new System.Windows.Forms.ToolTip(this.components); - this.Tip3 = new System.Windows.Forms.ToolTip(this.components); - this.L_FormArgument = new System.Windows.Forms.Label(); - this.tabMain.SuspendLayout(); - this.Tab_Main.SuspendLayout(); + this.TB_EC = new System.Windows.Forms.TextBox(); + this.BTN_RerollEC = new System.Windows.Forms.Button(); + this.TC_Editor = new PKHeX.WinForms.Controls.VerticalTabControlEntityEditor(); + this.Tab_Main = new System.Windows.Forms.TabPage(); + this.Tab_Met = new System.Windows.Forms.TabPage(); + this.Tab_Stats = new System.Windows.Forms.TabPage(); + this.Tab_Moves = new System.Windows.Forms.TabPage(); + this.Tab_Cosmetic = new System.Windows.Forms.TabPage(); + this.Tab_OTMisc = new System.Windows.Forms.TabPage(); + this.Hidden_TC.SuspendLayout(); + this.Hidden_Main.SuspendLayout(); this.FLP_Main.SuspendLayout(); this.FLP_PID.SuspendLayout(); this.FLP_PIDLeft.SuspendLayout(); @@ -268,18 +271,13 @@ namespace PKHeX.WinForms.Controls this.FLP_EggPKRSRight.SuspendLayout(); this.FLP_PKRS.SuspendLayout(); this.FLP_PKRSRight.SuspendLayout(); - this.FLP_Country.SuspendLayout(); - this.FLP_SubRegion.SuspendLayout(); - this.FLP_3DSRegion.SuspendLayout(); this.FLP_NSparkle.SuspendLayout(); this.FLP_ShadowID.SuspendLayout(); ((System.ComponentModel.ISupportInitialize)(this.NUD_ShadowID)).BeginInit(); this.FLP_Purification.SuspendLayout(); ((System.ComponentModel.ISupportInitialize)(this.NUD_Purification)).BeginInit(); - this.FLP_ShinyLeaf.SuspendLayout(); this.FLP_CatchRate.SuspendLayout(); - this.FLP_SizeCP.SuspendLayout(); - this.Tab_Met.SuspendLayout(); + this.Hidden_Met.SuspendLayout(); this.GB_EggConditions.SuspendLayout(); this.FLP_Met.SuspendLayout(); this.FLP_OriginGame.SuspendLayout(); @@ -293,25 +291,19 @@ namespace PKHeX.WinForms.Controls this.FLP_ObedienceLevel.SuspendLayout(); this.FLP_GroundTile.SuspendLayout(); this.FLP_TimeOfDay.SuspendLayout(); - this.Tab_Stats.SuspendLayout(); - this.Tab_Attacks.SuspendLayout(); + this.Hidden_Stats.SuspendLayout(); + this.Hidden_Moves.SuspendLayout(); this.FLP_MoveFlags.SuspendLayout(); - ((System.ComponentModel.ISupportInitialize)(this.PB_WarnMove4)).BeginInit(); - ((System.ComponentModel.ISupportInitialize)(this.PB_WarnMove3)).BeginInit(); - ((System.ComponentModel.ISupportInitialize)(this.PB_WarnMove2)).BeginInit(); - ((System.ComponentModel.ISupportInitialize)(this.PB_WarnMove1)).BeginInit(); this.GB_RelearnMoves.SuspendLayout(); ((System.ComponentModel.ISupportInitialize)(this.PB_WarnRelearn4)).BeginInit(); ((System.ComponentModel.ISupportInitialize)(this.PB_WarnRelearn3)).BeginInit(); ((System.ComponentModel.ISupportInitialize)(this.PB_WarnRelearn2)).BeginInit(); ((System.ComponentModel.ISupportInitialize)(this.PB_WarnRelearn1)).BeginInit(); this.GB_CurrentMoves.SuspendLayout(); - this.Tab_OTMisc.SuspendLayout(); - ((System.ComponentModel.ISupportInitialize)(this.PB_BattleVersion)).BeginInit(); - ((System.ComponentModel.ISupportInitialize)(this.PB_Origin)).BeginInit(); - ((System.ComponentModel.ISupportInitialize)(this.PB_Favorite)).BeginInit(); + this.FLP_Moves.SuspendLayout(); + this.Hidden_Cosmetic.SuspendLayout(); this.FLP_PKMEditors.SuspendLayout(); - this.GB_nOT.SuspendLayout(); + this.FLP_CosmeticTop.SuspendLayout(); this.GB_Markings.SuspendLayout(); ((System.ComponentModel.ISupportInitialize)(this.PB_Mark6)).BeginInit(); ((System.ComponentModel.ISupportInitialize)(this.PB_Mark3)).BeginInit(); @@ -321,35 +313,54 @@ namespace PKHeX.WinForms.Controls ((System.ComponentModel.ISupportInitialize)(this.PB_MarkShiny)).BeginInit(); ((System.ComponentModel.ISupportInitialize)(this.PB_Mark1)).BeginInit(); ((System.ComponentModel.ISupportInitialize)(this.PB_Mark4)).BeginInit(); - this.GB_ExtraBytes.SuspendLayout(); - this.GB_OT.SuspendLayout(); + this.FLP_BigMarkings.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.PB_Favorite)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.PB_Origin)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.PB_BattleVersion)).BeginInit(); + this.Hidden_OTMisc.SuspendLayout(); + this.FLP_OTMisc.SuspendLayout(); + this.FLP_OT.SuspendLayout(); + this.FLP_Country.SuspendLayout(); + this.FLP_SubRegion.SuspendLayout(); + this.FLP_3DSRegion.SuspendLayout(); + this.FLP_Handler.SuspendLayout(); + this.FLP_HT.SuspendLayout(); + this.FLP_HTLanguage.SuspendLayout(); + this.FLP_ExtraBytes.SuspendLayout(); + this.TC_Editor.SuspendLayout(); this.SuspendLayout(); // - // tabMain + // Hidden_TC // - this.tabMain.AllowDrop = true; - this.tabMain.Controls.Add(this.Tab_Main); - this.tabMain.Controls.Add(this.Tab_Met); - this.tabMain.Controls.Add(this.Tab_Stats); - this.tabMain.Controls.Add(this.Tab_Attacks); - this.tabMain.Controls.Add(this.Tab_OTMisc); - this.tabMain.Dock = System.Windows.Forms.DockStyle.Fill; - this.tabMain.Location = new System.Drawing.Point(0, 0); - this.tabMain.Name = "tabMain"; - this.tabMain.SelectedIndex = 0; - this.tabMain.Size = new System.Drawing.Size(315, 565); - this.tabMain.TabIndex = 1; + this.Hidden_TC.AllowDrop = true; + this.Hidden_TC.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left))); + this.Hidden_TC.Controls.Add(this.Hidden_Main); + this.Hidden_TC.Controls.Add(this.Hidden_Met); + this.Hidden_TC.Controls.Add(this.Hidden_Stats); + this.Hidden_TC.Controls.Add(this.Hidden_Moves); + this.Hidden_TC.Controls.Add(this.Hidden_Cosmetic); + this.Hidden_TC.Controls.Add(this.Hidden_OTMisc); + this.Hidden_TC.ItemSize = new System.Drawing.Size(0, 1); + this.Hidden_TC.Location = new System.Drawing.Point(96, -3); + this.Hidden_TC.Margin = new System.Windows.Forms.Padding(0); + this.Hidden_TC.Name = "Hidden_TC"; + this.Hidden_TC.SelectedIndex = 0; + this.Hidden_TC.Size = new System.Drawing.Size(304, 400); + this.Hidden_TC.SizeMode = System.Windows.Forms.TabSizeMode.Fixed; + this.Hidden_TC.TabIndex = 1; // - // Tab_Main + // Hidden_Main // - this.Tab_Main.AllowDrop = true; - this.Tab_Main.Controls.Add(this.FLP_Main); - this.Tab_Main.Location = new System.Drawing.Point(4, 22); - this.Tab_Main.Name = "Tab_Main"; - this.Tab_Main.Size = new System.Drawing.Size(307, 539); - this.Tab_Main.TabIndex = 0; - this.Tab_Main.Text = "Main"; - this.Tab_Main.UseVisualStyleBackColor = true; + this.Hidden_Main.AllowDrop = true; + this.Hidden_Main.Controls.Add(this.FLP_Main); + this.Hidden_Main.Location = new System.Drawing.Point(4, 5); + this.Hidden_Main.Margin = new System.Windows.Forms.Padding(0); + this.Hidden_Main.Name = "Hidden_Main"; + this.Hidden_Main.Size = new System.Drawing.Size(296, 391); + this.Hidden_Main.TabIndex = 0; + this.Hidden_Main.Text = "Main"; + this.Hidden_Main.UseVisualStyleBackColor = true; // // FLP_Main // @@ -366,20 +377,16 @@ namespace PKHeX.WinForms.Controls this.FLP_Main.Controls.Add(this.FLP_Language); this.FLP_Main.Controls.Add(this.FLP_EggPKRS); this.FLP_Main.Controls.Add(this.FLP_PKRS); - this.FLP_Main.Controls.Add(this.FLP_Country); - this.FLP_Main.Controls.Add(this.FLP_SubRegion); - this.FLP_Main.Controls.Add(this.FLP_3DSRegion); this.FLP_Main.Controls.Add(this.FLP_NSparkle); this.FLP_Main.Controls.Add(this.FLP_ShadowID); this.FLP_Main.Controls.Add(this.FLP_Purification); - this.FLP_Main.Controls.Add(this.FLP_ShinyLeaf); this.FLP_Main.Controls.Add(this.FLP_CatchRate); - this.FLP_Main.Controls.Add(this.FLP_SizeCP); this.FLP_Main.Dock = System.Windows.Forms.DockStyle.Fill; this.FLP_Main.Location = new System.Drawing.Point(0, 0); this.FLP_Main.Margin = new System.Windows.Forms.Padding(0); this.FLP_Main.Name = "FLP_Main"; - this.FLP_Main.Size = new System.Drawing.Size(307, 539); + this.FLP_Main.Padding = new System.Windows.Forms.Padding(0, 16, 0, 0); + this.FLP_Main.Size = new System.Drawing.Size(296, 391); this.FLP_Main.TabIndex = 103; // // FLP_PID @@ -387,10 +394,10 @@ namespace PKHeX.WinForms.Controls this.FLP_PID.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right))); this.FLP_PID.Controls.Add(this.FLP_PIDLeft); this.FLP_PID.Controls.Add(this.FLP_PIDRight); - this.FLP_PID.Location = new System.Drawing.Point(0, 0); + this.FLP_PID.Location = new System.Drawing.Point(0, 16); this.FLP_PID.Margin = new System.Windows.Forms.Padding(0); this.FLP_PID.Name = "FLP_PID"; - this.FLP_PID.Size = new System.Drawing.Size(272, 22); + this.FLP_PID.Size = new System.Drawing.Size(272, 24); this.FLP_PID.TabIndex = 0; // // FLP_PIDLeft @@ -404,17 +411,16 @@ namespace PKHeX.WinForms.Controls this.FLP_PIDLeft.Location = new System.Drawing.Point(0, 0); this.FLP_PIDLeft.Margin = new System.Windows.Forms.Padding(0); this.FLP_PIDLeft.Name = "FLP_PIDLeft"; - this.FLP_PIDLeft.Size = new System.Drawing.Size(98, 22); + this.FLP_PIDLeft.Size = new System.Drawing.Size(104, 24); this.FLP_PIDLeft.TabIndex = 0; // // Label_PID // this.Label_PID.Anchor = System.Windows.Forms.AnchorStyles.Right; - this.Label_PID.AutoSize = true; - this.Label_PID.Location = new System.Drawing.Point(70, 5); - this.Label_PID.Margin = new System.Windows.Forms.Padding(0, 5, 0, 4); + this.Label_PID.Location = new System.Drawing.Point(72, 0); + this.Label_PID.Margin = new System.Windows.Forms.Padding(0); this.Label_PID.Name = "Label_PID"; - this.Label_PID.Size = new System.Drawing.Size(28, 13); + this.Label_PID.Size = new System.Drawing.Size(32, 24); this.Label_PID.TabIndex = 0; this.Label_PID.Text = "PID:"; this.Label_PID.TextAlign = System.Drawing.ContentAlignment.MiddleRight; @@ -422,10 +428,10 @@ namespace PKHeX.WinForms.Controls // BTN_Shinytize // this.BTN_Shinytize.Anchor = System.Windows.Forms.AnchorStyles.Right; - this.BTN_Shinytize.Location = new System.Drawing.Point(46, 0); + this.BTN_Shinytize.Location = new System.Drawing.Point(48, 0); this.BTN_Shinytize.Margin = new System.Windows.Forms.Padding(0); this.BTN_Shinytize.Name = "BTN_Shinytize"; - this.BTN_Shinytize.Size = new System.Drawing.Size(24, 22); + this.BTN_Shinytize.Size = new System.Drawing.Size(24, 24); this.BTN_Shinytize.TabIndex = 1; this.BTN_Shinytize.Text = "☆"; this.BTN_Shinytize.UseVisualStyleBackColor = true; @@ -436,10 +442,10 @@ namespace PKHeX.WinForms.Controls this.PB_ShinyStar.Anchor = System.Windows.Forms.AnchorStyles.Right; this.PB_ShinyStar.Image = global::PKHeX.WinForms.Properties.Resources.rare_icon; this.PB_ShinyStar.InitialImage = global::PKHeX.WinForms.Properties.Resources.rare_icon; - this.PB_ShinyStar.Location = new System.Drawing.Point(24, 2); - this.PB_ShinyStar.Margin = new System.Windows.Forms.Padding(0, 2, 2, 0); + this.PB_ShinyStar.Location = new System.Drawing.Point(24, 0); + this.PB_ShinyStar.Margin = new System.Windows.Forms.Padding(0); this.PB_ShinyStar.Name = "PB_ShinyStar"; - this.PB_ShinyStar.Size = new System.Drawing.Size(20, 20); + this.PB_ShinyStar.Size = new System.Drawing.Size(24, 24); this.PB_ShinyStar.SizeMode = System.Windows.Forms.PictureBoxSizeMode.CenterImage; this.PB_ShinyStar.TabIndex = 62; this.PB_ShinyStar.TabStop = false; @@ -450,10 +456,10 @@ namespace PKHeX.WinForms.Controls this.PB_ShinySquare.Anchor = System.Windows.Forms.AnchorStyles.Right; this.PB_ShinySquare.Image = global::PKHeX.WinForms.Properties.Resources.rare_icon_2; this.PB_ShinySquare.InitialImage = global::PKHeX.WinForms.Properties.Resources.rare_icon_2; - this.PB_ShinySquare.Location = new System.Drawing.Point(2, 2); - this.PB_ShinySquare.Margin = new System.Windows.Forms.Padding(0, 2, 2, 0); + this.PB_ShinySquare.Location = new System.Drawing.Point(0, 0); + this.PB_ShinySquare.Margin = new System.Windows.Forms.Padding(0); this.PB_ShinySquare.Name = "PB_ShinySquare"; - this.PB_ShinySquare.Size = new System.Drawing.Size(20, 20); + this.PB_ShinySquare.Size = new System.Drawing.Size(24, 24); this.PB_ShinySquare.SizeMode = System.Windows.Forms.PictureBoxSizeMode.CenterImage; this.PB_ShinySquare.TabIndex = 62; this.PB_ShinySquare.TabStop = false; @@ -465,47 +471,48 @@ namespace PKHeX.WinForms.Controls this.FLP_PIDRight.Controls.Add(this.TB_PID); this.FLP_PIDRight.Controls.Add(this.UC_Gender); this.FLP_PIDRight.Controls.Add(this.BTN_RerollPID); - this.FLP_PIDRight.Location = new System.Drawing.Point(98, 0); + this.FLP_PIDRight.Location = new System.Drawing.Point(104, 0); this.FLP_PIDRight.Margin = new System.Windows.Forms.Padding(0); this.FLP_PIDRight.Name = "FLP_PIDRight"; - this.FLP_PIDRight.Size = new System.Drawing.Size(162, 22); + this.FLP_PIDRight.Size = new System.Drawing.Size(162, 24); this.FLP_PIDRight.TabIndex = 104; // // TB_PID // this.TB_PID.Anchor = System.Windows.Forms.AnchorStyles.Left; this.TB_PID.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; - this.TB_PID.Font = new System.Drawing.Font("Courier New", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); - this.TB_PID.Location = new System.Drawing.Point(0, 1); - this.TB_PID.Margin = new System.Windows.Forms.Padding(0, 1, 0, 0); + this.TB_PID.Font = new System.Drawing.Font("Courier New", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); + this.TB_PID.Location = new System.Drawing.Point(0, 3); + this.TB_PID.Margin = new System.Windows.Forms.Padding(0, 2, 0, 0); this.TB_PID.MaxLength = 8; this.TB_PID.Name = "TB_PID"; - this.TB_PID.Size = new System.Drawing.Size(60, 20); + this.TB_PID.PlaceholderText = "12345678"; + this.TB_PID.Size = new System.Drawing.Size(64, 20); this.TB_PID.TabIndex = 1; - this.TB_PID.Text = "12345678"; this.TB_PID.MouseHover += new System.EventHandler(this.UpdateTSV); this.TB_PID.Validated += new System.EventHandler(this.Update_ID); // // UC_Gender // this.UC_Gender.AllowClick = false; + this.UC_Gender.BackgroundImage = ((System.Drawing.Image)(resources.GetObject("UC_Gender.BackgroundImage"))); this.UC_Gender.BackgroundImageLayout = System.Windows.Forms.ImageLayout.Center; this.UC_Gender.Gender = 0; - this.UC_Gender.Location = new System.Drawing.Point(63, 2); - this.UC_Gender.Margin = new System.Windows.Forms.Padding(3, 2, 2, 1); + this.UC_Gender.Location = new System.Drawing.Point(64, 0); + this.UC_Gender.Margin = new System.Windows.Forms.Padding(0); this.UC_Gender.Name = "UC_Gender"; - this.UC_Gender.Size = new System.Drawing.Size(18, 18); + this.UC_Gender.Size = new System.Drawing.Size(24, 24); this.UC_Gender.TabIndex = 56; this.UC_Gender.Click += new System.EventHandler(this.ClickGender); // // BTN_RerollPID // this.BTN_RerollPID.Anchor = System.Windows.Forms.AnchorStyles.Left; - this.BTN_RerollPID.Font = new System.Drawing.Font("Microsoft Sans Serif", 6.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); - this.BTN_RerollPID.Location = new System.Drawing.Point(83, 1); - this.BTN_RerollPID.Margin = new System.Windows.Forms.Padding(0, 1, 0, 0); + this.BTN_RerollPID.Font = new System.Drawing.Font("Microsoft Sans Serif", 6.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); + this.BTN_RerollPID.Location = new System.Drawing.Point(88, 0); + this.BTN_RerollPID.Margin = new System.Windows.Forms.Padding(0); this.BTN_RerollPID.Name = "BTN_RerollPID"; - this.BTN_RerollPID.Size = new System.Drawing.Size(58, 20); + this.BTN_RerollPID.Size = new System.Drawing.Size(56, 24); this.BTN_RerollPID.TabIndex = 1; this.BTN_RerollPID.Text = "Reroll"; this.BTN_RerollPID.UseVisualStyleBackColor = true; @@ -516,10 +523,10 @@ namespace PKHeX.WinForms.Controls this.FLP_Species.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right))); this.FLP_Species.Controls.Add(this.Label_Species); this.FLP_Species.Controls.Add(this.CB_Species); - this.FLP_Species.Location = new System.Drawing.Point(0, 22); + this.FLP_Species.Location = new System.Drawing.Point(0, 40); this.FLP_Species.Margin = new System.Windows.Forms.Padding(0); this.FLP_Species.Name = "FLP_Species"; - this.FLP_Species.Size = new System.Drawing.Size(272, 21); + this.FLP_Species.Size = new System.Drawing.Size(272, 24); this.FLP_Species.TabIndex = 1; // // Label_Species @@ -528,7 +535,7 @@ namespace PKHeX.WinForms.Controls this.Label_Species.Location = new System.Drawing.Point(0, 0); this.Label_Species.Margin = new System.Windows.Forms.Padding(0); this.Label_Species.Name = "Label_Species"; - this.Label_Species.Size = new System.Drawing.Size(98, 21); + this.Label_Species.Size = new System.Drawing.Size(104, 24); this.Label_Species.TabIndex = 1; this.Label_Species.Text = "Species:"; this.Label_Species.TextAlign = System.Drawing.ContentAlignment.MiddleRight; @@ -539,10 +546,10 @@ namespace PKHeX.WinForms.Controls this.CB_Species.AutoCompleteMode = System.Windows.Forms.AutoCompleteMode.SuggestAppend; this.CB_Species.AutoCompleteSource = System.Windows.Forms.AutoCompleteSource.ListItems; this.CB_Species.FormattingEnabled = true; - this.CB_Species.Location = new System.Drawing.Point(98, 0); + this.CB_Species.Location = new System.Drawing.Point(104, 0); this.CB_Species.Margin = new System.Windows.Forms.Padding(0); this.CB_Species.Name = "CB_Species"; - this.CB_Species.Size = new System.Drawing.Size(140, 21); + this.CB_Species.Size = new System.Drawing.Size(144, 23); this.CB_Species.TabIndex = 3; this.CB_Species.SelectedIndexChanged += new System.EventHandler(this.ValidateComboBox2); this.CB_Species.SelectedValueChanged += new System.EventHandler(this.UpdateSpecies); @@ -553,44 +560,57 @@ namespace PKHeX.WinForms.Controls this.FLP_Nickname.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right))); this.FLP_Nickname.Controls.Add(this.FLP_NicknameLeft); this.FLP_Nickname.Controls.Add(this.TB_Nickname); - this.FLP_Nickname.Location = new System.Drawing.Point(0, 43); + this.FLP_Nickname.Location = new System.Drawing.Point(0, 64); this.FLP_Nickname.Margin = new System.Windows.Forms.Padding(0); this.FLP_Nickname.Name = "FLP_Nickname"; - this.FLP_Nickname.Size = new System.Drawing.Size(272, 22); + this.FLP_Nickname.Size = new System.Drawing.Size(272, 24); this.FLP_Nickname.TabIndex = 2; // // FLP_NicknameLeft // this.FLP_NicknameLeft.Anchor = System.Windows.Forms.AnchorStyles.Right; this.FLP_NicknameLeft.Controls.Add(this.CHK_Nicknamed); + this.FLP_NicknameLeft.Controls.Add(this.CHK_NicknamedFlag); this.FLP_NicknameLeft.FlowDirection = System.Windows.Forms.FlowDirection.RightToLeft; this.FLP_NicknameLeft.Location = new System.Drawing.Point(0, 0); this.FLP_NicknameLeft.Margin = new System.Windows.Forms.Padding(0); this.FLP_NicknameLeft.Name = "FLP_NicknameLeft"; - this.FLP_NicknameLeft.Size = new System.Drawing.Size(98, 21); + this.FLP_NicknameLeft.Size = new System.Drawing.Size(104, 24); this.FLP_NicknameLeft.TabIndex = 109; // // CHK_Nicknamed // this.CHK_Nicknamed.AutoSize = true; - this.CHK_Nicknamed.Location = new System.Drawing.Point(24, 3); - this.CHK_Nicknamed.Margin = new System.Windows.Forms.Padding(0, 3, 0, 3); + this.CHK_Nicknamed.Location = new System.Drawing.Point(40, 0); + this.CHK_Nicknamed.Margin = new System.Windows.Forms.Padding(0); + this.CHK_Nicknamed.MinimumSize = new System.Drawing.Size(0, 24); this.CHK_Nicknamed.Name = "CHK_Nicknamed"; - this.CHK_Nicknamed.Size = new System.Drawing.Size(74, 17); - this.CHK_Nicknamed.TabIndex = 4; - this.CHK_Nicknamed.Text = "Nickname"; + this.CHK_Nicknamed.Size = new System.Drawing.Size(64, 24); + this.CHK_Nicknamed.TabIndex = 5; + this.CHK_Nicknamed.Text = "Nickname:"; this.CHK_Nicknamed.TextAlign = System.Drawing.ContentAlignment.MiddleRight; - this.CHK_Nicknamed.UseVisualStyleBackColor = true; - this.CHK_Nicknamed.CheckedChanged += new System.EventHandler(this.UpdateNickname); + this.CHK_Nicknamed.Click += new System.EventHandler(this.CHK_Nicknamed_Click); + // + // CHK_NicknamedFlag + // + this.CHK_NicknamedFlag.Anchor = System.Windows.Forms.AnchorStyles.Right; + this.CHK_NicknamedFlag.Location = new System.Drawing.Point(24, 0); + this.CHK_NicknamedFlag.Margin = new System.Windows.Forms.Padding(0); + this.CHK_NicknamedFlag.Name = "CHK_NicknamedFlag"; + this.CHK_NicknamedFlag.Size = new System.Drawing.Size(16, 24); + this.CHK_NicknamedFlag.TabIndex = 4; + this.CHK_NicknamedFlag.TextAlign = System.Drawing.ContentAlignment.MiddleRight; + this.CHK_NicknamedFlag.UseVisualStyleBackColor = true; + this.CHK_NicknamedFlag.CheckedChanged += new System.EventHandler(this.UpdateNickname); // // TB_Nickname // this.TB_Nickname.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; - this.TB_Nickname.Location = new System.Drawing.Point(98, 0); + this.TB_Nickname.Location = new System.Drawing.Point(104, 0); this.TB_Nickname.Margin = new System.Windows.Forms.Padding(0); this.TB_Nickname.MaxLength = 12; this.TB_Nickname.Name = "TB_Nickname"; - this.TB_Nickname.Size = new System.Drawing.Size(140, 20); + this.TB_Nickname.Size = new System.Drawing.Size(144, 23); this.TB_Nickname.TabIndex = 5; this.TB_Nickname.TextChanged += new System.EventHandler(this.UpdateIsNicknamed); this.TB_Nickname.MouseDown += new System.Windows.Forms.MouseEventHandler(this.UpdateNicknameClick); @@ -600,10 +620,10 @@ namespace PKHeX.WinForms.Controls this.FLP_EXPLevel.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right))); this.FLP_EXPLevel.Controls.Add(this.Label_EXP); this.FLP_EXPLevel.Controls.Add(this.FLP_EXPLevelRight); - this.FLP_EXPLevel.Location = new System.Drawing.Point(0, 65); + this.FLP_EXPLevel.Location = new System.Drawing.Point(0, 88); this.FLP_EXPLevel.Margin = new System.Windows.Forms.Padding(0); this.FLP_EXPLevel.Name = "FLP_EXPLevel"; - this.FLP_EXPLevel.Size = new System.Drawing.Size(272, 21); + this.FLP_EXPLevel.Size = new System.Drawing.Size(272, 24); this.FLP_EXPLevel.TabIndex = 3; // // Label_EXP @@ -611,7 +631,7 @@ namespace PKHeX.WinForms.Controls this.Label_EXP.Location = new System.Drawing.Point(0, 0); this.Label_EXP.Margin = new System.Windows.Forms.Padding(0); this.Label_EXP.Name = "Label_EXP"; - this.Label_EXP.Size = new System.Drawing.Size(98, 21); + this.Label_EXP.Size = new System.Drawing.Size(104, 24); this.Label_EXP.TabIndex = 3; this.Label_EXP.Text = "EXP:"; this.Label_EXP.TextAlign = System.Drawing.ContentAlignment.MiddleRight; @@ -622,10 +642,10 @@ namespace PKHeX.WinForms.Controls this.FLP_EXPLevelRight.Controls.Add(this.TB_EXP); this.FLP_EXPLevelRight.Controls.Add(this.Label_CurLevel); this.FLP_EXPLevelRight.Controls.Add(this.TB_Level); - this.FLP_EXPLevelRight.Location = new System.Drawing.Point(98, 0); + this.FLP_EXPLevelRight.Location = new System.Drawing.Point(104, 0); this.FLP_EXPLevelRight.Margin = new System.Windows.Forms.Padding(0); this.FLP_EXPLevelRight.Name = "FLP_EXPLevelRight"; - this.FLP_EXPLevelRight.Size = new System.Drawing.Size(162, 21); + this.FLP_EXPLevelRight.Size = new System.Drawing.Size(160, 24); this.FLP_EXPLevelRight.TabIndex = 0; // // TB_EXP @@ -636,14 +656,14 @@ namespace PKHeX.WinForms.Controls this.TB_EXP.Margin = new System.Windows.Forms.Padding(0); this.TB_EXP.Mask = "0000000"; this.TB_EXP.Name = "TB_EXP"; - this.TB_EXP.Size = new System.Drawing.Size(46, 20); + this.TB_EXP.Size = new System.Drawing.Size(48, 23); this.TB_EXP.TabIndex = 7; this.TB_EXP.TextAlign = System.Windows.Forms.HorizontalAlignment.Center; this.TB_EXP.TextChanged += new System.EventHandler(this.UpdateEXPLevel); // // Label_CurLevel // - this.Label_CurLevel.Location = new System.Drawing.Point(46, 0); + this.Label_CurLevel.Location = new System.Drawing.Point(48, 0); this.Label_CurLevel.Margin = new System.Windows.Forms.Padding(0); this.Label_CurLevel.Name = "Label_CurLevel"; this.Label_CurLevel.Size = new System.Drawing.Size(72, 21); @@ -655,12 +675,13 @@ namespace PKHeX.WinForms.Controls // TB_Level // this.TB_Level.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; - this.TB_Level.Location = new System.Drawing.Point(118, 0); + this.TB_Level.Location = new System.Drawing.Point(120, 0); this.TB_Level.Margin = new System.Windows.Forms.Padding(0); this.TB_Level.Mask = "000"; this.TB_Level.Name = "TB_Level"; - this.TB_Level.Size = new System.Drawing.Size(22, 20); + this.TB_Level.Size = new System.Drawing.Size(24, 23); this.TB_Level.TabIndex = 8; + this.TB_Level.TextAlign = System.Windows.Forms.HorizontalAlignment.Center; this.TB_Level.Click += new System.EventHandler(this.ClickLevel); this.TB_Level.TextChanged += new System.EventHandler(this.UpdateEXPLevel); // @@ -669,10 +690,10 @@ namespace PKHeX.WinForms.Controls this.FLP_Nature.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right))); this.FLP_Nature.Controls.Add(this.Label_Nature); this.FLP_Nature.Controls.Add(this.CB_Nature); - this.FLP_Nature.Location = new System.Drawing.Point(0, 86); + this.FLP_Nature.Location = new System.Drawing.Point(0, 112); this.FLP_Nature.Margin = new System.Windows.Forms.Padding(0); this.FLP_Nature.Name = "FLP_Nature"; - this.FLP_Nature.Size = new System.Drawing.Size(272, 21); + this.FLP_Nature.Size = new System.Drawing.Size(272, 24); this.FLP_Nature.TabIndex = 4; // // Label_Nature @@ -680,7 +701,7 @@ namespace PKHeX.WinForms.Controls this.Label_Nature.Location = new System.Drawing.Point(0, 0); this.Label_Nature.Margin = new System.Windows.Forms.Padding(0); this.Label_Nature.Name = "Label_Nature"; - this.Label_Nature.Size = new System.Drawing.Size(98, 21); + this.Label_Nature.Size = new System.Drawing.Size(104, 24); this.Label_Nature.TabIndex = 8; this.Label_Nature.Text = "Nature:"; this.Label_Nature.TextAlign = System.Drawing.ContentAlignment.MiddleRight; @@ -691,10 +712,10 @@ namespace PKHeX.WinForms.Controls this.CB_Nature.AutoCompleteMode = System.Windows.Forms.AutoCompleteMode.SuggestAppend; this.CB_Nature.AutoCompleteSource = System.Windows.Forms.AutoCompleteSource.ListItems; this.CB_Nature.FormattingEnabled = true; - this.CB_Nature.Location = new System.Drawing.Point(98, 0); + this.CB_Nature.Location = new System.Drawing.Point(104, 0); this.CB_Nature.Margin = new System.Windows.Forms.Padding(0); this.CB_Nature.Name = "CB_Nature"; - this.CB_Nature.Size = new System.Drawing.Size(140, 21); + this.CB_Nature.Size = new System.Drawing.Size(144, 23); this.CB_Nature.TabIndex = 9; this.CB_Nature.SelectedIndexChanged += new System.EventHandler(this.ValidateComboBox2); this.CB_Nature.Validating += new System.ComponentModel.CancelEventHandler(this.ValidateComboBox); @@ -704,10 +725,10 @@ namespace PKHeX.WinForms.Controls this.FLP_OriginalNature.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right))); this.FLP_OriginalNature.Controls.Add(this.L_OriginalNature); this.FLP_OriginalNature.Controls.Add(this.CB_StatNature); - this.FLP_OriginalNature.Location = new System.Drawing.Point(0, 107); + this.FLP_OriginalNature.Location = new System.Drawing.Point(0, 136); this.FLP_OriginalNature.Margin = new System.Windows.Forms.Padding(0); this.FLP_OriginalNature.Name = "FLP_OriginalNature"; - this.FLP_OriginalNature.Size = new System.Drawing.Size(272, 21); + this.FLP_OriginalNature.Size = new System.Drawing.Size(272, 24); this.FLP_OriginalNature.TabIndex = 5; // // L_OriginalNature @@ -715,7 +736,7 @@ namespace PKHeX.WinForms.Controls this.L_OriginalNature.Location = new System.Drawing.Point(0, 0); this.L_OriginalNature.Margin = new System.Windows.Forms.Padding(0); this.L_OriginalNature.Name = "L_OriginalNature"; - this.L_OriginalNature.Size = new System.Drawing.Size(98, 21); + this.L_OriginalNature.Size = new System.Drawing.Size(104, 24); this.L_OriginalNature.TabIndex = 8; this.L_OriginalNature.Text = "Stat Nature:"; this.L_OriginalNature.TextAlign = System.Drawing.ContentAlignment.MiddleRight; @@ -726,10 +747,10 @@ namespace PKHeX.WinForms.Controls this.CB_StatNature.AutoCompleteMode = System.Windows.Forms.AutoCompleteMode.SuggestAppend; this.CB_StatNature.AutoCompleteSource = System.Windows.Forms.AutoCompleteSource.ListItems; this.CB_StatNature.FormattingEnabled = true; - this.CB_StatNature.Location = new System.Drawing.Point(98, 0); + this.CB_StatNature.Location = new System.Drawing.Point(104, 0); this.CB_StatNature.Margin = new System.Windows.Forms.Padding(0); this.CB_StatNature.Name = "CB_StatNature"; - this.CB_StatNature.Size = new System.Drawing.Size(140, 21); + this.CB_StatNature.Size = new System.Drawing.Size(144, 23); this.CB_StatNature.TabIndex = 10; this.CB_StatNature.SelectedIndexChanged += new System.EventHandler(this.ValidateComboBox2); this.CB_StatNature.Validating += new System.ComponentModel.CancelEventHandler(this.ValidateComboBox); @@ -739,10 +760,10 @@ namespace PKHeX.WinForms.Controls this.FLP_Form.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right))); this.FLP_Form.Controls.Add(this.FLP_FormLeft); this.FLP_Form.Controls.Add(this.FLP_FormRight); - this.FLP_Form.Location = new System.Drawing.Point(0, 128); + this.FLP_Form.Location = new System.Drawing.Point(0, 160); this.FLP_Form.Margin = new System.Windows.Forms.Padding(0); this.FLP_Form.Name = "FLP_Form"; - this.FLP_Form.Size = new System.Drawing.Size(307, 21); + this.FLP_Form.Size = new System.Drawing.Size(338, 24); this.FLP_Form.TabIndex = 6; // // FLP_FormLeft @@ -754,7 +775,7 @@ namespace PKHeX.WinForms.Controls this.FLP_FormLeft.Location = new System.Drawing.Point(0, 0); this.FLP_FormLeft.Margin = new System.Windows.Forms.Padding(0); this.FLP_FormLeft.Name = "FLP_FormLeft"; - this.FLP_FormLeft.Size = new System.Drawing.Size(98, 21); + this.FLP_FormLeft.Size = new System.Drawing.Size(104, 24); this.FLP_FormLeft.TabIndex = 0; // // Label_Form @@ -762,20 +783,30 @@ namespace PKHeX.WinForms.Controls this.Label_Form.Location = new System.Drawing.Point(0, 0); this.Label_Form.Margin = new System.Windows.Forms.Padding(0); this.Label_Form.Name = "Label_Form"; - this.Label_Form.Size = new System.Drawing.Size(98, 21); + this.Label_Form.Size = new System.Drawing.Size(104, 24); this.Label_Form.TabIndex = 11; this.Label_Form.Text = "Form:"; this.Label_Form.TextAlign = System.Drawing.ContentAlignment.MiddleRight; // + // L_FormArgument + // + this.L_FormArgument.Location = new System.Drawing.Point(6, 24); + this.L_FormArgument.Margin = new System.Windows.Forms.Padding(0); + this.L_FormArgument.Name = "L_FormArgument"; + this.L_FormArgument.Size = new System.Drawing.Size(98, 21); + this.L_FormArgument.TabIndex = 12; + this.L_FormArgument.Text = "Form Argument:"; + this.L_FormArgument.TextAlign = System.Drawing.ContentAlignment.MiddleRight; + // // FLP_FormRight // this.FLP_FormRight.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right))); this.FLP_FormRight.Controls.Add(this.CB_Form); this.FLP_FormRight.Controls.Add(this.FA_Form); - this.FLP_FormRight.Location = new System.Drawing.Point(98, 0); + this.FLP_FormRight.Location = new System.Drawing.Point(104, 0); this.FLP_FormRight.Margin = new System.Windows.Forms.Padding(0); this.FLP_FormRight.Name = "FLP_FormRight"; - this.FLP_FormRight.Size = new System.Drawing.Size(207, 21); + this.FLP_FormRight.Size = new System.Drawing.Size(224, 24); this.FLP_FormRight.TabIndex = 104; // // CB_Form @@ -789,16 +820,16 @@ namespace PKHeX.WinForms.Controls this.CB_Form.Location = new System.Drawing.Point(0, 0); this.CB_Form.Margin = new System.Windows.Forms.Padding(0); this.CB_Form.Name = "CB_Form"; - this.CB_Form.Size = new System.Drawing.Size(123, 21); + this.CB_Form.Size = new System.Drawing.Size(128, 23); this.CB_Form.TabIndex = 12; this.CB_Form.SelectedIndexChanged += new System.EventHandler(this.UpdateForm); // // FA_Form // - this.FA_Form.Location = new System.Drawing.Point(123, 0); + this.FA_Form.Location = new System.Drawing.Point(128, 0); this.FA_Form.Margin = new System.Windows.Forms.Padding(0); this.FA_Form.Name = "FA_Form"; - this.FA_Form.Size = new System.Drawing.Size(75, 21); + this.FA_Form.Size = new System.Drawing.Size(80, 24); this.FA_Form.TabIndex = 19; this.FA_Form.ValueChanged += new System.EventHandler(this.UpdateFormArgument); // @@ -807,10 +838,10 @@ namespace PKHeX.WinForms.Controls this.FLP_HeldItem.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right))); this.FLP_HeldItem.Controls.Add(this.Label_HeldItem); this.FLP_HeldItem.Controls.Add(this.CB_HeldItem); - this.FLP_HeldItem.Location = new System.Drawing.Point(0, 149); + this.FLP_HeldItem.Location = new System.Drawing.Point(0, 184); this.FLP_HeldItem.Margin = new System.Windows.Forms.Padding(0); this.FLP_HeldItem.Name = "FLP_HeldItem"; - this.FLP_HeldItem.Size = new System.Drawing.Size(272, 21); + this.FLP_HeldItem.Size = new System.Drawing.Size(272, 24); this.FLP_HeldItem.TabIndex = 7; // // Label_HeldItem @@ -819,7 +850,7 @@ namespace PKHeX.WinForms.Controls this.Label_HeldItem.Location = new System.Drawing.Point(0, 0); this.Label_HeldItem.Margin = new System.Windows.Forms.Padding(0); this.Label_HeldItem.Name = "Label_HeldItem"; - this.Label_HeldItem.Size = new System.Drawing.Size(98, 21); + this.Label_HeldItem.Size = new System.Drawing.Size(104, 24); this.Label_HeldItem.TabIndex = 51; this.Label_HeldItem.Text = "Held Item:"; this.Label_HeldItem.TextAlign = System.Drawing.ContentAlignment.MiddleRight; @@ -829,10 +860,10 @@ namespace PKHeX.WinForms.Controls this.CB_HeldItem.AutoCompleteMode = System.Windows.Forms.AutoCompleteMode.SuggestAppend; this.CB_HeldItem.AutoCompleteSource = System.Windows.Forms.AutoCompleteSource.ListItems; this.CB_HeldItem.FormattingEnabled = true; - this.CB_HeldItem.Location = new System.Drawing.Point(98, 0); + this.CB_HeldItem.Location = new System.Drawing.Point(104, 0); this.CB_HeldItem.Margin = new System.Windows.Forms.Padding(0); this.CB_HeldItem.Name = "CB_HeldItem"; - this.CB_HeldItem.Size = new System.Drawing.Size(140, 21); + this.CB_HeldItem.Size = new System.Drawing.Size(144, 23); this.CB_HeldItem.TabIndex = 10; this.CB_HeldItem.SelectedIndexChanged += new System.EventHandler(this.ValidateComboBox2); this.CB_HeldItem.Validating += new System.ComponentModel.CancelEventHandler(this.ValidateComboBox); @@ -842,10 +873,10 @@ namespace PKHeX.WinForms.Controls this.FLP_Ability.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right))); this.FLP_Ability.Controls.Add(this.Label_Ability); this.FLP_Ability.Controls.Add(this.FLP_AbilityRight); - this.FLP_Ability.Location = new System.Drawing.Point(0, 170); + this.FLP_Ability.Location = new System.Drawing.Point(0, 208); this.FLP_Ability.Margin = new System.Windows.Forms.Padding(0); this.FLP_Ability.Name = "FLP_Ability"; - this.FLP_Ability.Size = new System.Drawing.Size(272, 21); + this.FLP_Ability.Size = new System.Drawing.Size(272, 24); this.FLP_Ability.TabIndex = 8; // // Label_Ability @@ -853,7 +884,7 @@ namespace PKHeX.WinForms.Controls this.Label_Ability.Location = new System.Drawing.Point(0, 0); this.Label_Ability.Margin = new System.Windows.Forms.Padding(0); this.Label_Ability.Name = "Label_Ability"; - this.Label_Ability.Size = new System.Drawing.Size(98, 21); + this.Label_Ability.Size = new System.Drawing.Size(104, 24); this.Label_Ability.TabIndex = 10; this.Label_Ability.Text = "Ability:"; this.Label_Ability.TextAlign = System.Drawing.ContentAlignment.MiddleRight; @@ -864,10 +895,10 @@ namespace PKHeX.WinForms.Controls this.FLP_AbilityRight.Controls.Add(this.CB_Ability); this.FLP_AbilityRight.Controls.Add(this.DEV_Ability); this.FLP_AbilityRight.Controls.Add(this.TB_AbilityNumber); - this.FLP_AbilityRight.Location = new System.Drawing.Point(98, 0); + this.FLP_AbilityRight.Location = new System.Drawing.Point(104, 0); this.FLP_AbilityRight.Margin = new System.Windows.Forms.Padding(0); this.FLP_AbilityRight.Name = "FLP_AbilityRight"; - this.FLP_AbilityRight.Size = new System.Drawing.Size(162, 21); + this.FLP_AbilityRight.Size = new System.Drawing.Size(160, 24); this.FLP_AbilityRight.TabIndex = 109; // // CB_Ability @@ -878,7 +909,7 @@ namespace PKHeX.WinForms.Controls this.CB_Ability.Location = new System.Drawing.Point(0, 0); this.CB_Ability.Margin = new System.Windows.Forms.Padding(0); this.CB_Ability.Name = "CB_Ability"; - this.CB_Ability.Size = new System.Drawing.Size(140, 21); + this.CB_Ability.Size = new System.Drawing.Size(144, 23); this.CB_Ability.TabIndex = 13; this.CB_Ability.SelectedIndexChanged += new System.EventHandler(this.ValidateComboBox2); this.CB_Ability.Validating += new System.ComponentModel.CancelEventHandler(this.ValidateComboBox); @@ -889,21 +920,21 @@ namespace PKHeX.WinForms.Controls this.DEV_Ability.AutoCompleteSource = System.Windows.Forms.AutoCompleteSource.ListItems; this.DEV_Ability.Enabled = false; this.DEV_Ability.FormattingEnabled = true; - this.DEV_Ability.Location = new System.Drawing.Point(0, 21); + this.DEV_Ability.Location = new System.Drawing.Point(0, 23); this.DEV_Ability.Margin = new System.Windows.Forms.Padding(0); this.DEV_Ability.Name = "DEV_Ability"; - this.DEV_Ability.Size = new System.Drawing.Size(126, 21); + this.DEV_Ability.Size = new System.Drawing.Size(126, 23); this.DEV_Ability.TabIndex = 14; this.DEV_Ability.Visible = false; // // TB_AbilityNumber // this.TB_AbilityNumber.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; - this.TB_AbilityNumber.Location = new System.Drawing.Point(126, 21); + this.TB_AbilityNumber.Location = new System.Drawing.Point(126, 23); this.TB_AbilityNumber.Margin = new System.Windows.Forms.Padding(0); this.TB_AbilityNumber.Mask = "0"; this.TB_AbilityNumber.Name = "TB_AbilityNumber"; - this.TB_AbilityNumber.Size = new System.Drawing.Size(19, 20); + this.TB_AbilityNumber.Size = new System.Drawing.Size(19, 23); this.TB_AbilityNumber.TabIndex = 14; this.TB_AbilityNumber.TextAlign = System.Windows.Forms.HorizontalAlignment.Center; this.TB_AbilityNumber.Visible = false; @@ -913,10 +944,10 @@ namespace PKHeX.WinForms.Controls this.FLP_Friendship.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right))); this.FLP_Friendship.Controls.Add(this.FLP_FriendshipLeft); this.FLP_Friendship.Controls.Add(this.FLP_FriendshipRight); - this.FLP_Friendship.Location = new System.Drawing.Point(0, 191); + this.FLP_Friendship.Location = new System.Drawing.Point(0, 232); this.FLP_Friendship.Margin = new System.Windows.Forms.Padding(0); this.FLP_Friendship.Name = "FLP_Friendship"; - this.FLP_Friendship.Size = new System.Drawing.Size(272, 21); + this.FLP_Friendship.Size = new System.Drawing.Size(272, 24); this.FLP_Friendship.TabIndex = 9; // // FLP_FriendshipLeft @@ -928,15 +959,15 @@ namespace PKHeX.WinForms.Controls this.FLP_FriendshipLeft.Location = new System.Drawing.Point(0, 0); this.FLP_FriendshipLeft.Margin = new System.Windows.Forms.Padding(0); this.FLP_FriendshipLeft.Name = "FLP_FriendshipLeft"; - this.FLP_FriendshipLeft.Size = new System.Drawing.Size(98, 21); + this.FLP_FriendshipLeft.Size = new System.Drawing.Size(104, 24); this.FLP_FriendshipLeft.TabIndex = 0; // // Label_Friendship // - this.Label_Friendship.Location = new System.Drawing.Point(-5, 0); + this.Label_Friendship.Location = new System.Drawing.Point(0, 0); this.Label_Friendship.Margin = new System.Windows.Forms.Padding(0); this.Label_Friendship.Name = "Label_Friendship"; - this.Label_Friendship.Size = new System.Drawing.Size(103, 21); + this.Label_Friendship.Size = new System.Drawing.Size(104, 24); this.Label_Friendship.TabIndex = 9; this.Label_Friendship.Text = "Friendship:"; this.Label_Friendship.TextAlign = System.Drawing.ContentAlignment.MiddleRight; @@ -944,7 +975,7 @@ namespace PKHeX.WinForms.Controls // // Label_HatchCounter // - this.Label_HatchCounter.Location = new System.Drawing.Point(-12, 21); + this.Label_HatchCounter.Location = new System.Drawing.Point(-6, 24); this.Label_HatchCounter.Margin = new System.Windows.Forms.Padding(0); this.Label_HatchCounter.Name = "Label_HatchCounter"; this.Label_HatchCounter.Size = new System.Drawing.Size(110, 21); @@ -957,10 +988,10 @@ namespace PKHeX.WinForms.Controls // this.FLP_FriendshipRight.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right))); this.FLP_FriendshipRight.Controls.Add(this.TB_Friendship); - this.FLP_FriendshipRight.Location = new System.Drawing.Point(98, 0); + this.FLP_FriendshipRight.Location = new System.Drawing.Point(104, 0); this.FLP_FriendshipRight.Margin = new System.Windows.Forms.Padding(0); this.FLP_FriendshipRight.Name = "FLP_FriendshipRight"; - this.FLP_FriendshipRight.Size = new System.Drawing.Size(162, 21); + this.FLP_FriendshipRight.Size = new System.Drawing.Size(160, 24); this.FLP_FriendshipRight.TabIndex = 104; // // TB_Friendship @@ -970,7 +1001,7 @@ namespace PKHeX.WinForms.Controls this.TB_Friendship.Margin = new System.Windows.Forms.Padding(0); this.TB_Friendship.Mask = "000"; this.TB_Friendship.Name = "TB_Friendship"; - this.TB_Friendship.Size = new System.Drawing.Size(22, 20); + this.TB_Friendship.Size = new System.Drawing.Size(24, 23); this.TB_Friendship.TabIndex = 11; this.TB_Friendship.TextAlign = System.Windows.Forms.HorizontalAlignment.Center; this.TB_Friendship.Validated += new System.EventHandler(this.Update255_MTB); @@ -980,10 +1011,10 @@ namespace PKHeX.WinForms.Controls this.FLP_Language.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right))); this.FLP_Language.Controls.Add(this.Label_Language); this.FLP_Language.Controls.Add(this.CB_Language); - this.FLP_Language.Location = new System.Drawing.Point(0, 212); + this.FLP_Language.Location = new System.Drawing.Point(0, 256); this.FLP_Language.Margin = new System.Windows.Forms.Padding(0); this.FLP_Language.Name = "FLP_Language"; - this.FLP_Language.Size = new System.Drawing.Size(272, 21); + this.FLP_Language.Size = new System.Drawing.Size(272, 24); this.FLP_Language.TabIndex = 10; // // Label_Language @@ -991,7 +1022,7 @@ namespace PKHeX.WinForms.Controls this.Label_Language.Location = new System.Drawing.Point(0, 0); this.Label_Language.Margin = new System.Windows.Forms.Padding(0); this.Label_Language.Name = "Label_Language"; - this.Label_Language.Size = new System.Drawing.Size(98, 21); + this.Label_Language.Size = new System.Drawing.Size(104, 24); this.Label_Language.TabIndex = 12; this.Label_Language.Text = "Language:"; this.Label_Language.TextAlign = System.Drawing.ContentAlignment.MiddleRight; @@ -1001,10 +1032,10 @@ namespace PKHeX.WinForms.Controls this.CB_Language.Anchor = System.Windows.Forms.AnchorStyles.Left; this.CB_Language.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; this.CB_Language.FormattingEnabled = true; - this.CB_Language.Location = new System.Drawing.Point(98, 0); + this.CB_Language.Location = new System.Drawing.Point(104, 0); this.CB_Language.Margin = new System.Windows.Forms.Padding(0); this.CB_Language.Name = "CB_Language"; - this.CB_Language.Size = new System.Drawing.Size(140, 21); + this.CB_Language.Size = new System.Drawing.Size(144, 23); this.CB_Language.TabIndex = 15; this.CB_Language.SelectedIndexChanged += new System.EventHandler(this.UpdateNickname); // @@ -1013,10 +1044,10 @@ namespace PKHeX.WinForms.Controls this.FLP_EggPKRS.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right))); this.FLP_EggPKRS.Controls.Add(this.FLP_EggPKRSLeft); this.FLP_EggPKRS.Controls.Add(this.FLP_EggPKRSRight); - this.FLP_EggPKRS.Location = new System.Drawing.Point(0, 233); + this.FLP_EggPKRS.Location = new System.Drawing.Point(0, 280); this.FLP_EggPKRS.Margin = new System.Windows.Forms.Padding(0); this.FLP_EggPKRS.Name = "FLP_EggPKRS"; - this.FLP_EggPKRS.Size = new System.Drawing.Size(272, 21); + this.FLP_EggPKRS.Size = new System.Drawing.Size(272, 24); this.FLP_EggPKRS.TabIndex = 11; // // FLP_EggPKRSLeft @@ -1027,16 +1058,16 @@ namespace PKHeX.WinForms.Controls this.FLP_EggPKRSLeft.Location = new System.Drawing.Point(0, 0); this.FLP_EggPKRSLeft.Margin = new System.Windows.Forms.Padding(0); this.FLP_EggPKRSLeft.Name = "FLP_EggPKRSLeft"; - this.FLP_EggPKRSLeft.Size = new System.Drawing.Size(98, 21); + this.FLP_EggPKRSLeft.Size = new System.Drawing.Size(104, 24); this.FLP_EggPKRSLeft.TabIndex = 0; // // CHK_IsEgg // this.CHK_IsEgg.AutoSize = true; - this.CHK_IsEgg.Location = new System.Drawing.Point(42, 3); + this.CHK_IsEgg.Location = new System.Drawing.Point(47, 3); this.CHK_IsEgg.Margin = new System.Windows.Forms.Padding(0, 3, 0, 3); this.CHK_IsEgg.Name = "CHK_IsEgg"; - this.CHK_IsEgg.Size = new System.Drawing.Size(56, 17); + this.CHK_IsEgg.Size = new System.Drawing.Size(57, 19); this.CHK_IsEgg.TabIndex = 16; this.CHK_IsEgg.Text = "Is Egg"; this.CHK_IsEgg.TextAlign = System.Drawing.ContentAlignment.MiddleRight; @@ -1048,10 +1079,10 @@ namespace PKHeX.WinForms.Controls this.FLP_EggPKRSRight.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right))); this.FLP_EggPKRSRight.Controls.Add(this.CHK_Infected); this.FLP_EggPKRSRight.Controls.Add(this.CHK_Cured); - this.FLP_EggPKRSRight.Location = new System.Drawing.Point(98, 0); + this.FLP_EggPKRSRight.Location = new System.Drawing.Point(104, 0); this.FLP_EggPKRSRight.Margin = new System.Windows.Forms.Padding(0); this.FLP_EggPKRSRight.Name = "FLP_EggPKRSRight"; - this.FLP_EggPKRSRight.Size = new System.Drawing.Size(162, 21); + this.FLP_EggPKRSRight.Size = new System.Drawing.Size(160, 24); this.FLP_EggPKRSRight.TabIndex = 104; // // CHK_Infected @@ -1060,7 +1091,7 @@ namespace PKHeX.WinForms.Controls this.CHK_Infected.Location = new System.Drawing.Point(0, 3); this.CHK_Infected.Margin = new System.Windows.Forms.Padding(0, 3, 0, 3); this.CHK_Infected.Name = "CHK_Infected"; - this.CHK_Infected.Size = new System.Drawing.Size(65, 17); + this.CHK_Infected.Size = new System.Drawing.Size(69, 19); this.CHK_Infected.TabIndex = 17; this.CHK_Infected.Text = "Infected"; this.CHK_Infected.TextAlign = System.Drawing.ContentAlignment.MiddleRight; @@ -1070,10 +1101,10 @@ namespace PKHeX.WinForms.Controls // CHK_Cured // this.CHK_Cured.AutoSize = true; - this.CHK_Cured.Location = new System.Drawing.Point(65, 3); + this.CHK_Cured.Location = new System.Drawing.Point(69, 3); this.CHK_Cured.Margin = new System.Windows.Forms.Padding(0, 3, 0, 3); this.CHK_Cured.Name = "CHK_Cured"; - this.CHK_Cured.Size = new System.Drawing.Size(54, 17); + this.CHK_Cured.Size = new System.Drawing.Size(58, 19); this.CHK_Cured.TabIndex = 18; this.CHK_Cured.Text = "Cured"; this.CHK_Cured.TextAlign = System.Drawing.ContentAlignment.MiddleRight; @@ -1085,10 +1116,10 @@ namespace PKHeX.WinForms.Controls this.FLP_PKRS.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right))); this.FLP_PKRS.Controls.Add(this.Label_PKRS); this.FLP_PKRS.Controls.Add(this.FLP_PKRSRight); - this.FLP_PKRS.Location = new System.Drawing.Point(0, 254); + this.FLP_PKRS.Location = new System.Drawing.Point(0, 304); this.FLP_PKRS.Margin = new System.Windows.Forms.Padding(0); this.FLP_PKRS.Name = "FLP_PKRS"; - this.FLP_PKRS.Size = new System.Drawing.Size(272, 21); + this.FLP_PKRS.Size = new System.Drawing.Size(272, 24); this.FLP_PKRS.TabIndex = 12; // // Label_PKRS @@ -1096,7 +1127,7 @@ namespace PKHeX.WinForms.Controls this.Label_PKRS.Location = new System.Drawing.Point(0, 0); this.Label_PKRS.Margin = new System.Windows.Forms.Padding(0); this.Label_PKRS.Name = "Label_PKRS"; - this.Label_PKRS.Size = new System.Drawing.Size(98, 21); + this.Label_PKRS.Size = new System.Drawing.Size(104, 24); this.Label_PKRS.TabIndex = 14; this.Label_PKRS.Text = "PkRs:"; this.Label_PKRS.TextAlign = System.Drawing.ContentAlignment.MiddleRight; @@ -1108,10 +1139,10 @@ namespace PKHeX.WinForms.Controls this.FLP_PKRSRight.Controls.Add(this.CB_PKRSStrain); this.FLP_PKRSRight.Controls.Add(this.Label_PKRSdays); this.FLP_PKRSRight.Controls.Add(this.CB_PKRSDays); - this.FLP_PKRSRight.Location = new System.Drawing.Point(98, 0); + this.FLP_PKRSRight.Location = new System.Drawing.Point(104, 0); this.FLP_PKRSRight.Margin = new System.Windows.Forms.Padding(0); this.FLP_PKRSRight.Name = "FLP_PKRSRight"; - this.FLP_PKRSRight.Size = new System.Drawing.Size(162, 21); + this.FLP_PKRSRight.Size = new System.Drawing.Size(160, 24); this.FLP_PKRSRight.TabIndex = 105; // // CB_PKRSStrain @@ -1138,14 +1169,14 @@ namespace PKHeX.WinForms.Controls this.CB_PKRSStrain.Location = new System.Drawing.Point(0, 0); this.CB_PKRSStrain.Margin = new System.Windows.Forms.Padding(0); this.CB_PKRSStrain.Name = "CB_PKRSStrain"; - this.CB_PKRSStrain.Size = new System.Drawing.Size(43, 21); + this.CB_PKRSStrain.Size = new System.Drawing.Size(40, 23); this.CB_PKRSStrain.TabIndex = 19; this.CB_PKRSStrain.Visible = false; this.CB_PKRSStrain.SelectedValueChanged += new System.EventHandler(this.UpdatePKRSstrain); // // Label_PKRSdays // - this.Label_PKRSdays.Location = new System.Drawing.Point(43, 0); + this.Label_PKRSdays.Location = new System.Drawing.Point(40, 0); this.Label_PKRSdays.Margin = new System.Windows.Forms.Padding(0); this.Label_PKRSdays.Name = "Label_PKRSdays"; this.Label_PKRSdays.Size = new System.Drawing.Size(25, 21); @@ -1158,123 +1189,23 @@ namespace PKHeX.WinForms.Controls // this.CB_PKRSDays.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; this.CB_PKRSDays.FormattingEnabled = true; - this.CB_PKRSDays.Location = new System.Drawing.Point(68, 0); + this.CB_PKRSDays.Location = new System.Drawing.Point(65, 0); this.CB_PKRSDays.Margin = new System.Windows.Forms.Padding(0); this.CB_PKRSDays.Name = "CB_PKRSDays"; - this.CB_PKRSDays.Size = new System.Drawing.Size(30, 21); + this.CB_PKRSDays.Size = new System.Drawing.Size(32, 23); this.CB_PKRSDays.TabIndex = 20; this.CB_PKRSDays.Visible = false; this.CB_PKRSDays.SelectedIndexChanged += new System.EventHandler(this.UpdatePKRSdays); // - // FLP_Country - // - this.FLP_Country.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right))); - this.FLP_Country.Controls.Add(this.Label_Country); - this.FLP_Country.Controls.Add(this.CB_Country); - this.FLP_Country.Location = new System.Drawing.Point(0, 275); - this.FLP_Country.Margin = new System.Windows.Forms.Padding(0); - this.FLP_Country.Name = "FLP_Country"; - this.FLP_Country.Size = new System.Drawing.Size(272, 21); - this.FLP_Country.TabIndex = 13; - // - // Label_Country - // - this.Label_Country.Location = new System.Drawing.Point(0, 0); - this.Label_Country.Margin = new System.Windows.Forms.Padding(0); - this.Label_Country.Name = "Label_Country"; - this.Label_Country.Size = new System.Drawing.Size(98, 21); - this.Label_Country.TabIndex = 16; - this.Label_Country.Text = "Country:"; - this.Label_Country.TextAlign = System.Drawing.ContentAlignment.MiddleRight; - // - // CB_Country - // - this.CB_Country.AutoCompleteMode = System.Windows.Forms.AutoCompleteMode.SuggestAppend; - this.CB_Country.AutoCompleteSource = System.Windows.Forms.AutoCompleteSource.ListItems; - this.CB_Country.DropDownWidth = 180; - this.CB_Country.FormattingEnabled = true; - this.CB_Country.Location = new System.Drawing.Point(98, 0); - this.CB_Country.Margin = new System.Windows.Forms.Padding(0); - this.CB_Country.Name = "CB_Country"; - this.CB_Country.Size = new System.Drawing.Size(140, 21); - this.CB_Country.TabIndex = 21; - this.CB_Country.SelectedIndexChanged += new System.EventHandler(this.UpdateCountry); - this.CB_Country.Validating += new System.ComponentModel.CancelEventHandler(this.ValidateComboBox); - // - // FLP_SubRegion - // - this.FLP_SubRegion.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right))); - this.FLP_SubRegion.Controls.Add(this.Label_SubRegion); - this.FLP_SubRegion.Controls.Add(this.CB_SubRegion); - this.FLP_SubRegion.Location = new System.Drawing.Point(0, 296); - this.FLP_SubRegion.Margin = new System.Windows.Forms.Padding(0); - this.FLP_SubRegion.Name = "FLP_SubRegion"; - this.FLP_SubRegion.Size = new System.Drawing.Size(272, 21); - this.FLP_SubRegion.TabIndex = 14; - // - // Label_SubRegion - // - this.Label_SubRegion.Location = new System.Drawing.Point(0, 0); - this.Label_SubRegion.Margin = new System.Windows.Forms.Padding(0); - this.Label_SubRegion.Name = "Label_SubRegion"; - this.Label_SubRegion.Size = new System.Drawing.Size(98, 21); - this.Label_SubRegion.TabIndex = 17; - this.Label_SubRegion.Text = "Sub Region:"; - this.Label_SubRegion.TextAlign = System.Drawing.ContentAlignment.MiddleRight; - // - // CB_SubRegion - // - this.CB_SubRegion.AutoCompleteMode = System.Windows.Forms.AutoCompleteMode.SuggestAppend; - this.CB_SubRegion.AutoCompleteSource = System.Windows.Forms.AutoCompleteSource.ListItems; - this.CB_SubRegion.DropDownWidth = 180; - this.CB_SubRegion.FormattingEnabled = true; - this.CB_SubRegion.Location = new System.Drawing.Point(98, 0); - this.CB_SubRegion.Margin = new System.Windows.Forms.Padding(0); - this.CB_SubRegion.Name = "CB_SubRegion"; - this.CB_SubRegion.Size = new System.Drawing.Size(140, 21); - this.CB_SubRegion.TabIndex = 22; - this.CB_SubRegion.Validating += new System.ComponentModel.CancelEventHandler(this.ValidateComboBox); - // - // FLP_3DSRegion - // - this.FLP_3DSRegion.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right))); - this.FLP_3DSRegion.Controls.Add(this.Label_3DSRegion); - this.FLP_3DSRegion.Controls.Add(this.CB_3DSReg); - this.FLP_3DSRegion.Location = new System.Drawing.Point(0, 317); - this.FLP_3DSRegion.Margin = new System.Windows.Forms.Padding(0); - this.FLP_3DSRegion.Name = "FLP_3DSRegion"; - this.FLP_3DSRegion.Size = new System.Drawing.Size(272, 21); - this.FLP_3DSRegion.TabIndex = 15; - // - // Label_3DSRegion - // - this.Label_3DSRegion.Location = new System.Drawing.Point(0, 0); - this.Label_3DSRegion.Margin = new System.Windows.Forms.Padding(0); - this.Label_3DSRegion.Name = "Label_3DSRegion"; - this.Label_3DSRegion.Size = new System.Drawing.Size(98, 21); - this.Label_3DSRegion.TabIndex = 18; - this.Label_3DSRegion.Text = "3DS Region:"; - this.Label_3DSRegion.TextAlign = System.Drawing.ContentAlignment.MiddleRight; - // - // CB_3DSReg - // - this.CB_3DSReg.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; - this.CB_3DSReg.FormattingEnabled = true; - this.CB_3DSReg.Location = new System.Drawing.Point(98, 0); - this.CB_3DSReg.Margin = new System.Windows.Forms.Padding(0); - this.CB_3DSReg.Name = "CB_3DSReg"; - this.CB_3DSReg.Size = new System.Drawing.Size(140, 21); - this.CB_3DSReg.TabIndex = 23; - // // FLP_NSparkle // this.FLP_NSparkle.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right))); this.FLP_NSparkle.Controls.Add(this.L_NSparkle); this.FLP_NSparkle.Controls.Add(this.CHK_NSparkle); - this.FLP_NSparkle.Location = new System.Drawing.Point(0, 338); + this.FLP_NSparkle.Location = new System.Drawing.Point(0, 328); this.FLP_NSparkle.Margin = new System.Windows.Forms.Padding(0); this.FLP_NSparkle.Name = "FLP_NSparkle"; - this.FLP_NSparkle.Size = new System.Drawing.Size(272, 21); + this.FLP_NSparkle.Size = new System.Drawing.Size(272, 24); this.FLP_NSparkle.TabIndex = 16; // // L_NSparkle @@ -1282,7 +1213,7 @@ namespace PKHeX.WinForms.Controls this.L_NSparkle.Location = new System.Drawing.Point(0, 0); this.L_NSparkle.Margin = new System.Windows.Forms.Padding(0); this.L_NSparkle.Name = "L_NSparkle"; - this.L_NSparkle.Size = new System.Drawing.Size(98, 21); + this.L_NSparkle.Size = new System.Drawing.Size(104, 24); this.L_NSparkle.TabIndex = 17; this.L_NSparkle.Text = "N\'s Sparkle:"; this.L_NSparkle.TextAlign = System.Drawing.ContentAlignment.MiddleRight; @@ -1290,10 +1221,10 @@ namespace PKHeX.WinForms.Controls // CHK_NSparkle // this.CHK_NSparkle.AutoSize = true; - this.CHK_NSparkle.Location = new System.Drawing.Point(98, 3); + this.CHK_NSparkle.Location = new System.Drawing.Point(104, 3); this.CHK_NSparkle.Margin = new System.Windows.Forms.Padding(0, 3, 0, 3); this.CHK_NSparkle.Name = "CHK_NSparkle"; - this.CHK_NSparkle.Size = new System.Drawing.Size(56, 17); + this.CHK_NSparkle.Size = new System.Drawing.Size(59, 19); this.CHK_NSparkle.TabIndex = 18; this.CHK_NSparkle.Text = "Active"; this.CHK_NSparkle.TextAlign = System.Drawing.ContentAlignment.MiddleRight; @@ -1304,10 +1235,10 @@ namespace PKHeX.WinForms.Controls this.FLP_ShadowID.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right))); this.FLP_ShadowID.Controls.Add(this.L_ShadowID); this.FLP_ShadowID.Controls.Add(this.NUD_ShadowID); - this.FLP_ShadowID.Location = new System.Drawing.Point(0, 359); + this.FLP_ShadowID.Location = new System.Drawing.Point(0, 352); this.FLP_ShadowID.Margin = new System.Windows.Forms.Padding(0); this.FLP_ShadowID.Name = "FLP_ShadowID"; - this.FLP_ShadowID.Size = new System.Drawing.Size(272, 21); + this.FLP_ShadowID.Size = new System.Drawing.Size(272, 24); this.FLP_ShadowID.TabIndex = 17; // // L_ShadowID @@ -1315,14 +1246,14 @@ namespace PKHeX.WinForms.Controls this.L_ShadowID.Location = new System.Drawing.Point(0, 0); this.L_ShadowID.Margin = new System.Windows.Forms.Padding(0); this.L_ShadowID.Name = "L_ShadowID"; - this.L_ShadowID.Size = new System.Drawing.Size(98, 21); + this.L_ShadowID.Size = new System.Drawing.Size(104, 24); this.L_ShadowID.TabIndex = 9; this.L_ShadowID.Text = "Shadow ID:"; this.L_ShadowID.TextAlign = System.Drawing.ContentAlignment.MiddleRight; // // NUD_ShadowID // - this.NUD_ShadowID.Location = new System.Drawing.Point(98, 1); + this.NUD_ShadowID.Location = new System.Drawing.Point(104, 1); this.NUD_ShadowID.Margin = new System.Windows.Forms.Padding(0, 1, 0, 0); this.NUD_ShadowID.Maximum = new decimal(new int[] { 127, @@ -1330,7 +1261,7 @@ namespace PKHeX.WinForms.Controls 0, 0}); this.NUD_ShadowID.Name = "NUD_ShadowID"; - this.NUD_ShadowID.Size = new System.Drawing.Size(51, 20); + this.NUD_ShadowID.Size = new System.Drawing.Size(48, 23); this.NUD_ShadowID.TabIndex = 103; this.NUD_ShadowID.ValueChanged += new System.EventHandler(this.UpdateShadowID); // @@ -1340,10 +1271,10 @@ namespace PKHeX.WinForms.Controls this.FLP_Purification.Controls.Add(this.L_HeartGauge); this.FLP_Purification.Controls.Add(this.NUD_Purification); this.FLP_Purification.Controls.Add(this.CHK_Shadow); - this.FLP_Purification.Location = new System.Drawing.Point(0, 380); + this.FLP_Purification.Location = new System.Drawing.Point(0, 376); this.FLP_Purification.Margin = new System.Windows.Forms.Padding(0); this.FLP_Purification.Name = "FLP_Purification"; - this.FLP_Purification.Size = new System.Drawing.Size(272, 21); + this.FLP_Purification.Size = new System.Drawing.Size(272, 24); this.FLP_Purification.TabIndex = 18; // // L_HeartGauge @@ -1351,14 +1282,14 @@ namespace PKHeX.WinForms.Controls this.L_HeartGauge.Location = new System.Drawing.Point(0, 0); this.L_HeartGauge.Margin = new System.Windows.Forms.Padding(0); this.L_HeartGauge.Name = "L_HeartGauge"; - this.L_HeartGauge.Size = new System.Drawing.Size(98, 21); + this.L_HeartGauge.Size = new System.Drawing.Size(104, 24); this.L_HeartGauge.TabIndex = 9; this.L_HeartGauge.Text = "Heart Gauge:"; this.L_HeartGauge.TextAlign = System.Drawing.ContentAlignment.MiddleRight; // // NUD_Purification // - this.NUD_Purification.Location = new System.Drawing.Point(98, 1); + this.NUD_Purification.Location = new System.Drawing.Point(104, 1); this.NUD_Purification.Margin = new System.Windows.Forms.Padding(0, 1, 0, 0); this.NUD_Purification.Maximum = new decimal(new int[] { 2147483647, @@ -1371,62 +1302,32 @@ namespace PKHeX.WinForms.Controls 0, -2147483648}); this.NUD_Purification.Name = "NUD_Purification"; - this.NUD_Purification.Size = new System.Drawing.Size(51, 20); + this.NUD_Purification.Size = new System.Drawing.Size(48, 23); this.NUD_Purification.TabIndex = 103; this.NUD_Purification.ValueChanged += new System.EventHandler(this.UpdatePurification); // // CHK_Shadow // this.CHK_Shadow.AutoSize = true; - this.CHK_Shadow.Location = new System.Drawing.Point(149, 3); + this.CHK_Shadow.Location = new System.Drawing.Point(152, 3); this.CHK_Shadow.Margin = new System.Windows.Forms.Padding(0, 3, 0, 3); this.CHK_Shadow.Name = "CHK_Shadow"; - this.CHK_Shadow.Size = new System.Drawing.Size(65, 17); + this.CHK_Shadow.Size = new System.Drawing.Size(68, 19); this.CHK_Shadow.TabIndex = 16; this.CHK_Shadow.Text = "Shadow"; this.CHK_Shadow.TextAlign = System.Drawing.ContentAlignment.MiddleRight; this.CHK_Shadow.UseVisualStyleBackColor = true; this.CHK_Shadow.CheckedChanged += new System.EventHandler(this.UpdateShadowCHK); // - // FLP_ShinyLeaf - // - this.FLP_ShinyLeaf.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right))); - this.FLP_ShinyLeaf.Controls.Add(this.L_ShinyLeaf); - this.FLP_ShinyLeaf.Controls.Add(this.ShinyLeaf); - this.FLP_ShinyLeaf.Location = new System.Drawing.Point(0, 401); - this.FLP_ShinyLeaf.Margin = new System.Windows.Forms.Padding(0); - this.FLP_ShinyLeaf.Name = "FLP_ShinyLeaf"; - this.FLP_ShinyLeaf.Size = new System.Drawing.Size(272, 56); - this.FLP_ShinyLeaf.TabIndex = 19; - // - // L_ShinyLeaf - // - this.L_ShinyLeaf.Location = new System.Drawing.Point(0, 0); - this.L_ShinyLeaf.Margin = new System.Windows.Forms.Padding(0); - this.L_ShinyLeaf.Name = "L_ShinyLeaf"; - this.L_ShinyLeaf.Size = new System.Drawing.Size(98, 56); - this.L_ShinyLeaf.TabIndex = 9; - this.L_ShinyLeaf.Text = "Shiny Leaf:"; - this.L_ShinyLeaf.TextAlign = System.Drawing.ContentAlignment.MiddleRight; - this.L_ShinyLeaf.Click += new System.EventHandler(this.ClickShinyLeaf); - // - // ShinyLeaf - // - this.ShinyLeaf.Location = new System.Drawing.Point(98, 0); - this.ShinyLeaf.Margin = new System.Windows.Forms.Padding(0); - this.ShinyLeaf.Name = "ShinyLeaf"; - this.ShinyLeaf.Size = new System.Drawing.Size(140, 56); - this.ShinyLeaf.TabIndex = 116; - // // FLP_CatchRate // this.FLP_CatchRate.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right))); this.FLP_CatchRate.Controls.Add(this.L_CatchRate); this.FLP_CatchRate.Controls.Add(this.CR_PK1); - this.FLP_CatchRate.Location = new System.Drawing.Point(0, 457); + this.FLP_CatchRate.Location = new System.Drawing.Point(0, 400); this.FLP_CatchRate.Margin = new System.Windows.Forms.Padding(0); this.FLP_CatchRate.Name = "FLP_CatchRate"; - this.FLP_CatchRate.Size = new System.Drawing.Size(272, 25); + this.FLP_CatchRate.Size = new System.Drawing.Size(288, 24); this.FLP_CatchRate.TabIndex = 20; // // L_CatchRate @@ -1434,81 +1335,40 @@ namespace PKHeX.WinForms.Controls this.L_CatchRate.Location = new System.Drawing.Point(0, 0); this.L_CatchRate.Margin = new System.Windows.Forms.Padding(0); this.L_CatchRate.Name = "L_CatchRate"; - this.L_CatchRate.Size = new System.Drawing.Size(110, 21); + this.L_CatchRate.Size = new System.Drawing.Size(104, 24); this.L_CatchRate.TabIndex = 9; this.L_CatchRate.Text = "Catch Rate:"; this.L_CatchRate.TextAlign = System.Drawing.ContentAlignment.MiddleRight; // // CR_PK1 // - this.CR_PK1.Location = new System.Drawing.Point(110, 0); + this.CR_PK1.Location = new System.Drawing.Point(104, 0); this.CR_PK1.Margin = new System.Windows.Forms.Padding(0); this.CR_PK1.Name = "CR_PK1"; - this.CR_PK1.Size = new System.Drawing.Size(162, 25); + this.CR_PK1.Size = new System.Drawing.Size(184, 25); this.CR_PK1.TabIndex = 10; // - // FLP_SizeCP + // Hidden_Met // - this.FLP_SizeCP.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right))); - this.FLP_SizeCP.Controls.Add(this.SizeCP); - this.FLP_SizeCP.Location = new System.Drawing.Point(0, 482); - this.FLP_SizeCP.Margin = new System.Windows.Forms.Padding(0); - this.FLP_SizeCP.Name = "FLP_SizeCP"; - this.FLP_SizeCP.Size = new System.Drawing.Size(272, 90); - this.FLP_SizeCP.TabIndex = 21; - // - // SizeCP - // - this.SizeCP.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); - this.SizeCP.Location = new System.Drawing.Point(50, 0); - this.SizeCP.Margin = new System.Windows.Forms.Padding(50, 0, 0, 0); - this.SizeCP.Name = "SizeCP"; - this.SizeCP.Size = new System.Drawing.Size(204, 90); - this.SizeCP.TabIndex = 0; - // - // Tab_Met - // - this.Tab_Met.AllowDrop = true; - this.Tab_Met.Controls.Add(this.TB_HomeTracker); - this.Tab_Met.Controls.Add(this.L_HomeTracker); - this.Tab_Met.Controls.Add(this.CHK_AsEgg); - this.Tab_Met.Controls.Add(this.GB_EggConditions); - this.Tab_Met.Controls.Add(this.FLP_Met); - this.Tab_Met.Location = new System.Drawing.Point(4, 22); - this.Tab_Met.Name = "Tab_Met"; - this.Tab_Met.Padding = new System.Windows.Forms.Padding(3); - this.Tab_Met.Size = new System.Drawing.Size(192, 74); - this.Tab_Met.TabIndex = 1; - this.Tab_Met.Text = "Met"; - this.Tab_Met.UseVisualStyleBackColor = true; - // - // TB_HomeTracker - // - this.TB_HomeTracker.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; - this.TB_HomeTracker.Font = new System.Drawing.Font("Courier New", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); - this.TB_HomeTracker.Location = new System.Drawing.Point(110, 296); - this.TB_HomeTracker.MaxLength = 16; - this.TB_HomeTracker.Name = "TB_HomeTracker"; - this.TB_HomeTracker.Size = new System.Drawing.Size(118, 20); - this.TB_HomeTracker.TabIndex = 10; - this.TB_HomeTracker.Text = "0123456789ABCDEF"; - this.TB_HomeTracker.Validated += new System.EventHandler(this.Update_ID64); - // - // L_HomeTracker - // - this.L_HomeTracker.Location = new System.Drawing.Point(-13, 298); - this.L_HomeTracker.Name = "L_HomeTracker"; - this.L_HomeTracker.Size = new System.Drawing.Size(120, 13); - this.L_HomeTracker.TabIndex = 9; - this.L_HomeTracker.Text = "HOME Tracker:"; - this.L_HomeTracker.TextAlign = System.Drawing.ContentAlignment.MiddleRight; + this.Hidden_Met.AllowDrop = true; + this.Hidden_Met.Controls.Add(this.CHK_AsEgg); + this.Hidden_Met.Controls.Add(this.GB_EggConditions); + this.Hidden_Met.Controls.Add(this.FLP_Met); + this.Hidden_Met.Location = new System.Drawing.Point(4, 5); + this.Hidden_Met.Margin = new System.Windows.Forms.Padding(0); + this.Hidden_Met.Name = "Hidden_Met"; + this.Hidden_Met.Padding = new System.Windows.Forms.Padding(0, 16, 0, 0); + this.Hidden_Met.Size = new System.Drawing.Size(296, 391); + this.Hidden_Met.TabIndex = 1; + this.Hidden_Met.Text = "Met"; + this.Hidden_Met.UseVisualStyleBackColor = true; // // CHK_AsEgg // this.CHK_AsEgg.AutoSize = true; - this.CHK_AsEgg.Location = new System.Drawing.Point(110, 198); + this.CHK_AsEgg.Location = new System.Drawing.Point(104, 216); this.CHK_AsEgg.Name = "CHK_AsEgg"; - this.CHK_AsEgg.Size = new System.Drawing.Size(60, 17); + this.CHK_AsEgg.Size = new System.Drawing.Size(62, 19); this.CHK_AsEgg.TabIndex = 2; this.CHK_AsEgg.Text = "As Egg"; this.CHK_AsEgg.UseVisualStyleBackColor = true; @@ -1521,9 +1381,9 @@ namespace PKHeX.WinForms.Controls this.GB_EggConditions.Controls.Add(this.Label_EggDate); this.GB_EggConditions.Controls.Add(this.Label_EggLocation); this.GB_EggConditions.Enabled = false; - this.GB_EggConditions.Location = new System.Drawing.Point(39, 220); + this.GB_EggConditions.Location = new System.Drawing.Point(32, 232); this.GB_EggConditions.Name = "GB_EggConditions"; - this.GB_EggConditions.Size = new System.Drawing.Size(200, 67); + this.GB_EggConditions.Size = new System.Drawing.Size(240, 72); this.GB_EggConditions.TabIndex = 3; this.GB_EggConditions.TabStop = false; this.GB_EggConditions.Text = "Egg Met Conditions"; @@ -1533,9 +1393,9 @@ namespace PKHeX.WinForms.Controls this.CB_EggLocation.AutoCompleteMode = System.Windows.Forms.AutoCompleteMode.SuggestAppend; this.CB_EggLocation.AutoCompleteSource = System.Windows.Forms.AutoCompleteSource.ListItems; this.CB_EggLocation.FormattingEnabled = true; - this.CB_EggLocation.Location = new System.Drawing.Point(71, 19); + this.CB_EggLocation.Location = new System.Drawing.Point(72, 19); this.CB_EggLocation.Name = "CB_EggLocation"; - this.CB_EggLocation.Size = new System.Drawing.Size(122, 21); + this.CB_EggLocation.Size = new System.Drawing.Size(160, 23); this.CB_EggLocation.TabIndex = 4; this.CB_EggLocation.SelectedIndexChanged += new System.EventHandler(this.ValidateLocation); this.CB_EggLocation.Validating += new System.ComponentModel.CancelEventHandler(this.ValidateComboBox); @@ -1544,28 +1404,28 @@ namespace PKHeX.WinForms.Controls // this.CAL_EggDate.CustomFormat = "MM/dd/yyyy"; this.CAL_EggDate.Format = System.Windows.Forms.DateTimePickerFormat.Short; - this.CAL_EggDate.Location = new System.Drawing.Point(71, 40); + this.CAL_EggDate.Location = new System.Drawing.Point(72, 40); this.CAL_EggDate.MaxDate = new System.DateTime(2099, 12, 31, 0, 0, 0, 0); this.CAL_EggDate.MinDate = new System.DateTime(2000, 1, 1, 0, 0, 0, 0); this.CAL_EggDate.Name = "CAL_EggDate"; - this.CAL_EggDate.Size = new System.Drawing.Size(122, 20); + this.CAL_EggDate.Size = new System.Drawing.Size(136, 23); this.CAL_EggDate.TabIndex = 5; this.CAL_EggDate.Value = new System.DateTime(2000, 1, 1, 0, 0, 0, 0); // // Label_EggDate // - this.Label_EggDate.Location = new System.Drawing.Point(5, 44); + this.Label_EggDate.Location = new System.Drawing.Point(8, 44); this.Label_EggDate.Name = "Label_EggDate"; - this.Label_EggDate.Size = new System.Drawing.Size(63, 13); + this.Label_EggDate.Size = new System.Drawing.Size(64, 13); this.Label_EggDate.TabIndex = 8; this.Label_EggDate.Text = "Date:"; this.Label_EggDate.TextAlign = System.Drawing.ContentAlignment.MiddleRight; // // Label_EggLocation // - this.Label_EggLocation.Location = new System.Drawing.Point(5, 24); + this.Label_EggLocation.Location = new System.Drawing.Point(8, 24); this.Label_EggLocation.Name = "Label_EggLocation"; - this.Label_EggLocation.Size = new System.Drawing.Size(63, 13); + this.Label_EggLocation.Size = new System.Drawing.Size(64, 13); this.Label_EggLocation.TabIndex = 6; this.Label_EggLocation.Text = "Location:"; this.Label_EggLocation.TextAlign = System.Drawing.ContentAlignment.MiddleRight; @@ -1581,9 +1441,11 @@ namespace PKHeX.WinForms.Controls this.FLP_Met.Controls.Add(this.FLP_ObedienceLevel); this.FLP_Met.Controls.Add(this.FLP_GroundTile); this.FLP_Met.Controls.Add(this.FLP_TimeOfDay); - this.FLP_Met.Location = new System.Drawing.Point(0, 24); + this.FLP_Met.Dock = System.Windows.Forms.DockStyle.Fill; + this.FLP_Met.Location = new System.Drawing.Point(0, 16); + this.FLP_Met.Margin = new System.Windows.Forms.Padding(0); this.FLP_Met.Name = "FLP_Met"; - this.FLP_Met.Size = new System.Drawing.Size(272, 189); + this.FLP_Met.Size = new System.Drawing.Size(296, 375); this.FLP_Met.TabIndex = 1; // // FLP_OriginGame @@ -1594,7 +1456,7 @@ namespace PKHeX.WinForms.Controls this.FLP_OriginGame.Location = new System.Drawing.Point(0, 0); this.FLP_OriginGame.Margin = new System.Windows.Forms.Padding(0); this.FLP_OriginGame.Name = "FLP_OriginGame"; - this.FLP_OriginGame.Size = new System.Drawing.Size(272, 21); + this.FLP_OriginGame.Size = new System.Drawing.Size(280, 24); this.FLP_OriginGame.TabIndex = 1; // // Label_OriginGame @@ -1602,7 +1464,7 @@ namespace PKHeX.WinForms.Controls this.Label_OriginGame.Location = new System.Drawing.Point(0, 0); this.Label_OriginGame.Margin = new System.Windows.Forms.Padding(0); this.Label_OriginGame.Name = "Label_OriginGame"; - this.Label_OriginGame.Size = new System.Drawing.Size(98, 21); + this.Label_OriginGame.Size = new System.Drawing.Size(104, 24); this.Label_OriginGame.TabIndex = 0; this.Label_OriginGame.Text = "Origin Game:"; this.Label_OriginGame.TextAlign = System.Drawing.ContentAlignment.MiddleRight; @@ -1611,10 +1473,10 @@ namespace PKHeX.WinForms.Controls // this.CB_GameOrigin.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; this.CB_GameOrigin.FormattingEnabled = true; - this.CB_GameOrigin.Location = new System.Drawing.Point(98, 0); + this.CB_GameOrigin.Location = new System.Drawing.Point(104, 0); this.CB_GameOrigin.Margin = new System.Windows.Forms.Padding(0); this.CB_GameOrigin.Name = "CB_GameOrigin"; - this.CB_GameOrigin.Size = new System.Drawing.Size(134, 21); + this.CB_GameOrigin.Size = new System.Drawing.Size(136, 23); this.CB_GameOrigin.TabIndex = 1; this.CB_GameOrigin.SelectedIndexChanged += new System.EventHandler(this.UpdateOriginGame); // @@ -1623,10 +1485,10 @@ namespace PKHeX.WinForms.Controls this.FLP_BattleVersion.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right))); this.FLP_BattleVersion.Controls.Add(this.L_BattleVersion); this.FLP_BattleVersion.Controls.Add(this.CB_BattleVersion); - this.FLP_BattleVersion.Location = new System.Drawing.Point(0, 21); + this.FLP_BattleVersion.Location = new System.Drawing.Point(0, 24); this.FLP_BattleVersion.Margin = new System.Windows.Forms.Padding(0); this.FLP_BattleVersion.Name = "FLP_BattleVersion"; - this.FLP_BattleVersion.Size = new System.Drawing.Size(272, 21); + this.FLP_BattleVersion.Size = new System.Drawing.Size(280, 24); this.FLP_BattleVersion.TabIndex = 8; // // L_BattleVersion @@ -1634,7 +1496,7 @@ namespace PKHeX.WinForms.Controls this.L_BattleVersion.Location = new System.Drawing.Point(0, 0); this.L_BattleVersion.Margin = new System.Windows.Forms.Padding(0); this.L_BattleVersion.Name = "L_BattleVersion"; - this.L_BattleVersion.Size = new System.Drawing.Size(98, 21); + this.L_BattleVersion.Size = new System.Drawing.Size(104, 24); this.L_BattleVersion.TabIndex = 0; this.L_BattleVersion.Text = "Battle Version:"; this.L_BattleVersion.TextAlign = System.Drawing.ContentAlignment.MiddleRight; @@ -1643,10 +1505,10 @@ namespace PKHeX.WinForms.Controls // this.CB_BattleVersion.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; this.CB_BattleVersion.FormattingEnabled = true; - this.CB_BattleVersion.Location = new System.Drawing.Point(98, 0); + this.CB_BattleVersion.Location = new System.Drawing.Point(104, 0); this.CB_BattleVersion.Margin = new System.Windows.Forms.Padding(0); this.CB_BattleVersion.Name = "CB_BattleVersion"; - this.CB_BattleVersion.Size = new System.Drawing.Size(134, 21); + this.CB_BattleVersion.Size = new System.Drawing.Size(136, 23); this.CB_BattleVersion.TabIndex = 1; this.CB_BattleVersion.SelectedValueChanged += new System.EventHandler(this.CB_BattleVersion_SelectedValueChanged); // @@ -1655,10 +1517,10 @@ namespace PKHeX.WinForms.Controls this.FLP_MetLocation.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right))); this.FLP_MetLocation.Controls.Add(this.Label_MetLocation); this.FLP_MetLocation.Controls.Add(this.CB_MetLocation); - this.FLP_MetLocation.Location = new System.Drawing.Point(0, 42); + this.FLP_MetLocation.Location = new System.Drawing.Point(0, 48); this.FLP_MetLocation.Margin = new System.Windows.Forms.Padding(0); this.FLP_MetLocation.Name = "FLP_MetLocation"; - this.FLP_MetLocation.Size = new System.Drawing.Size(272, 21); + this.FLP_MetLocation.Size = new System.Drawing.Size(280, 24); this.FLP_MetLocation.TabIndex = 2; // // Label_MetLocation @@ -1666,7 +1528,7 @@ namespace PKHeX.WinForms.Controls this.Label_MetLocation.Location = new System.Drawing.Point(0, 0); this.Label_MetLocation.Margin = new System.Windows.Forms.Padding(0); this.Label_MetLocation.Name = "Label_MetLocation"; - this.Label_MetLocation.Size = new System.Drawing.Size(98, 21); + this.Label_MetLocation.Size = new System.Drawing.Size(104, 24); this.Label_MetLocation.TabIndex = 1; this.Label_MetLocation.Text = "Met Location:"; this.Label_MetLocation.TextAlign = System.Drawing.ContentAlignment.MiddleRight; @@ -1678,10 +1540,10 @@ namespace PKHeX.WinForms.Controls this.CB_MetLocation.AutoCompleteSource = System.Windows.Forms.AutoCompleteSource.ListItems; this.CB_MetLocation.Dock = System.Windows.Forms.DockStyle.Fill; this.CB_MetLocation.FormattingEnabled = true; - this.CB_MetLocation.Location = new System.Drawing.Point(98, 0); + this.CB_MetLocation.Location = new System.Drawing.Point(104, 0); this.CB_MetLocation.Margin = new System.Windows.Forms.Padding(0); this.CB_MetLocation.Name = "CB_MetLocation"; - this.CB_MetLocation.Size = new System.Drawing.Size(162, 21); + this.CB_MetLocation.Size = new System.Drawing.Size(160, 23); this.CB_MetLocation.TabIndex = 2; this.CB_MetLocation.SelectedIndexChanged += new System.EventHandler(this.ValidateLocation); this.CB_MetLocation.Validating += new System.ComponentModel.CancelEventHandler(this.ValidateComboBox); @@ -1691,10 +1553,10 @@ namespace PKHeX.WinForms.Controls this.FLP_Ball.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right))); this.FLP_Ball.Controls.Add(this.FLP_BallLeft); this.FLP_Ball.Controls.Add(this.CB_Ball); - this.FLP_Ball.Location = new System.Drawing.Point(0, 63); + this.FLP_Ball.Location = new System.Drawing.Point(0, 72); this.FLP_Ball.Margin = new System.Windows.Forms.Padding(0); this.FLP_Ball.Name = "FLP_Ball"; - this.FLP_Ball.Size = new System.Drawing.Size(272, 21); + this.FLP_Ball.Size = new System.Drawing.Size(280, 24); this.FLP_Ball.TabIndex = 3; // // FLP_BallLeft @@ -1706,7 +1568,7 @@ namespace PKHeX.WinForms.Controls this.FLP_BallLeft.Location = new System.Drawing.Point(0, 0); this.FLP_BallLeft.Margin = new System.Windows.Forms.Padding(0); this.FLP_BallLeft.Name = "FLP_BallLeft"; - this.FLP_BallLeft.Size = new System.Drawing.Size(98, 21); + this.FLP_BallLeft.Size = new System.Drawing.Size(104, 24); this.FLP_BallLeft.TabIndex = 4; this.FLP_BallLeft.Click += new System.EventHandler(this.ClickBall); // @@ -1714,11 +1576,11 @@ namespace PKHeX.WinForms.Controls // this.Label_Ball.Anchor = System.Windows.Forms.AnchorStyles.Right; this.Label_Ball.AutoSize = true; - this.Label_Ball.Location = new System.Drawing.Point(71, 0); + this.Label_Ball.Location = new System.Drawing.Point(75, 1); this.Label_Ball.Margin = new System.Windows.Forms.Padding(0); this.Label_Ball.Name = "Label_Ball"; this.Label_Ball.Padding = new System.Windows.Forms.Padding(0, 3, 0, 3); - this.Label_Ball.Size = new System.Drawing.Size(27, 19); + this.Label_Ball.Size = new System.Drawing.Size(29, 21); this.Label_Ball.TabIndex = 2; this.Label_Ball.Text = "Ball:"; this.Label_Ball.TextAlign = System.Drawing.ContentAlignment.MiddleRight; @@ -1726,10 +1588,11 @@ namespace PKHeX.WinForms.Controls // // PB_Ball // + this.PB_Ball.BackgroundImageLayout = System.Windows.Forms.ImageLayout.Center; this.PB_Ball.Location = new System.Drawing.Point(48, 0); this.PB_Ball.Margin = new System.Windows.Forms.Padding(0, 0, 3, 0); this.PB_Ball.Name = "PB_Ball"; - this.PB_Ball.Size = new System.Drawing.Size(20, 20); + this.PB_Ball.Size = new System.Drawing.Size(24, 24); this.PB_Ball.TabIndex = 3; this.PB_Ball.TabStop = false; this.PB_Ball.Click += new System.EventHandler(this.ClickBall); @@ -1739,10 +1602,10 @@ namespace PKHeX.WinForms.Controls this.CB_Ball.AutoCompleteMode = System.Windows.Forms.AutoCompleteMode.SuggestAppend; this.CB_Ball.AutoCompleteSource = System.Windows.Forms.AutoCompleteSource.ListItems; this.CB_Ball.FormattingEnabled = true; - this.CB_Ball.Location = new System.Drawing.Point(98, 0); + this.CB_Ball.Location = new System.Drawing.Point(104, 0); this.CB_Ball.Margin = new System.Windows.Forms.Padding(0); this.CB_Ball.Name = "CB_Ball"; - this.CB_Ball.Size = new System.Drawing.Size(134, 21); + this.CB_Ball.Size = new System.Drawing.Size(136, 23); this.CB_Ball.TabIndex = 3; this.CB_Ball.SelectedIndexChanged += new System.EventHandler(this.ValidateComboBox2); this.CB_Ball.SelectedValueChanged += new System.EventHandler(this.UpdateBall); @@ -1753,10 +1616,10 @@ namespace PKHeX.WinForms.Controls this.FLP_MetDate.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right))); this.FLP_MetDate.Controls.Add(this.Label_MetDate); this.FLP_MetDate.Controls.Add(this.CAL_MetDate); - this.FLP_MetDate.Location = new System.Drawing.Point(0, 84); + this.FLP_MetDate.Location = new System.Drawing.Point(0, 96); this.FLP_MetDate.Margin = new System.Windows.Forms.Padding(0); this.FLP_MetDate.Name = "FLP_MetDate"; - this.FLP_MetDate.Size = new System.Drawing.Size(272, 21); + this.FLP_MetDate.Size = new System.Drawing.Size(280, 24); this.FLP_MetDate.TabIndex = 5; // // Label_MetDate @@ -1764,7 +1627,7 @@ namespace PKHeX.WinForms.Controls this.Label_MetDate.Location = new System.Drawing.Point(0, 0); this.Label_MetDate.Margin = new System.Windows.Forms.Padding(0); this.Label_MetDate.Name = "Label_MetDate"; - this.Label_MetDate.Size = new System.Drawing.Size(98, 21); + this.Label_MetDate.Size = new System.Drawing.Size(104, 24); this.Label_MetDate.TabIndex = 4; this.Label_MetDate.Text = "Met Date:"; this.Label_MetDate.TextAlign = System.Drawing.ContentAlignment.MiddleRight; @@ -1773,12 +1636,12 @@ namespace PKHeX.WinForms.Controls // this.CAL_MetDate.CustomFormat = "MM/dd/yyyy"; this.CAL_MetDate.Format = System.Windows.Forms.DateTimePickerFormat.Short; - this.CAL_MetDate.Location = new System.Drawing.Point(98, 0); + this.CAL_MetDate.Location = new System.Drawing.Point(104, 0); this.CAL_MetDate.Margin = new System.Windows.Forms.Padding(0); this.CAL_MetDate.MaxDate = new System.DateTime(2099, 12, 31, 0, 0, 0, 0); this.CAL_MetDate.MinDate = new System.DateTime(2000, 1, 1, 0, 0, 0, 0); this.CAL_MetDate.Name = "CAL_MetDate"; - this.CAL_MetDate.Size = new System.Drawing.Size(134, 20); + this.CAL_MetDate.Size = new System.Drawing.Size(136, 23); this.CAL_MetDate.TabIndex = 5; this.CAL_MetDate.Value = new System.DateTime(2000, 1, 1, 0, 0, 0, 0); // @@ -1788,10 +1651,10 @@ namespace PKHeX.WinForms.Controls this.FLP_MetLevel.Controls.Add(this.Label_MetLevel); this.FLP_MetLevel.Controls.Add(this.TB_MetLevel); this.FLP_MetLevel.Controls.Add(this.CHK_Fateful); - this.FLP_MetLevel.Location = new System.Drawing.Point(0, 105); + this.FLP_MetLevel.Location = new System.Drawing.Point(0, 120); this.FLP_MetLevel.Margin = new System.Windows.Forms.Padding(0); this.FLP_MetLevel.Name = "FLP_MetLevel"; - this.FLP_MetLevel.Size = new System.Drawing.Size(272, 21); + this.FLP_MetLevel.Size = new System.Drawing.Size(280, 24); this.FLP_MetLevel.TabIndex = 4; // // Label_MetLevel @@ -1799,7 +1662,7 @@ namespace PKHeX.WinForms.Controls this.Label_MetLevel.Location = new System.Drawing.Point(0, 0); this.Label_MetLevel.Margin = new System.Windows.Forms.Padding(0); this.Label_MetLevel.Name = "Label_MetLevel"; - this.Label_MetLevel.Size = new System.Drawing.Size(98, 21); + this.Label_MetLevel.Size = new System.Drawing.Size(104, 24); this.Label_MetLevel.TabIndex = 3; this.Label_MetLevel.Text = "Met Level:"; this.Label_MetLevel.TextAlign = System.Drawing.ContentAlignment.MiddleRight; @@ -1807,21 +1670,21 @@ namespace PKHeX.WinForms.Controls // TB_MetLevel // this.TB_MetLevel.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; - this.TB_MetLevel.Location = new System.Drawing.Point(98, 0); + this.TB_MetLevel.Location = new System.Drawing.Point(104, 0); this.TB_MetLevel.Margin = new System.Windows.Forms.Padding(0); this.TB_MetLevel.Mask = "000"; this.TB_MetLevel.Name = "TB_MetLevel"; - this.TB_MetLevel.Size = new System.Drawing.Size(22, 20); + this.TB_MetLevel.Size = new System.Drawing.Size(22, 23); this.TB_MetLevel.TabIndex = 4; this.TB_MetLevel.Validated += new System.EventHandler(this.Update255_MTB); // // CHK_Fateful // this.CHK_Fateful.AutoSize = true; - this.CHK_Fateful.Location = new System.Drawing.Point(125, 3); + this.CHK_Fateful.Location = new System.Drawing.Point(131, 3); this.CHK_Fateful.Margin = new System.Windows.Forms.Padding(5, 3, 3, 3); this.CHK_Fateful.Name = "CHK_Fateful"; - this.CHK_Fateful.Size = new System.Drawing.Size(110, 17); + this.CHK_Fateful.Size = new System.Drawing.Size(119, 19); this.CHK_Fateful.TabIndex = 6; this.CHK_Fateful.Text = "Fateful Encounter"; this.CHK_Fateful.UseVisualStyleBackColor = true; @@ -1831,10 +1694,10 @@ namespace PKHeX.WinForms.Controls this.FLP_ObedienceLevel.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right))); this.FLP_ObedienceLevel.Controls.Add(this.L_ObedienceLevel); this.FLP_ObedienceLevel.Controls.Add(this.TB_ObedienceLevel); - this.FLP_ObedienceLevel.Location = new System.Drawing.Point(0, 126); + this.FLP_ObedienceLevel.Location = new System.Drawing.Point(0, 144); this.FLP_ObedienceLevel.Margin = new System.Windows.Forms.Padding(0); this.FLP_ObedienceLevel.Name = "FLP_ObedienceLevel"; - this.FLP_ObedienceLevel.Size = new System.Drawing.Size(272, 21); + this.FLP_ObedienceLevel.Size = new System.Drawing.Size(280, 24); this.FLP_ObedienceLevel.TabIndex = 4; // // L_ObedienceLevel @@ -1842,7 +1705,7 @@ namespace PKHeX.WinForms.Controls this.L_ObedienceLevel.Location = new System.Drawing.Point(0, 0); this.L_ObedienceLevel.Margin = new System.Windows.Forms.Padding(0); this.L_ObedienceLevel.Name = "L_ObedienceLevel"; - this.L_ObedienceLevel.Size = new System.Drawing.Size(98, 21); + this.L_ObedienceLevel.Size = new System.Drawing.Size(104, 24); this.L_ObedienceLevel.TabIndex = 3; this.L_ObedienceLevel.Text = "Obedience Level:"; this.L_ObedienceLevel.TextAlign = System.Drawing.ContentAlignment.MiddleRight; @@ -1851,11 +1714,11 @@ namespace PKHeX.WinForms.Controls // TB_ObedienceLevel // this.TB_ObedienceLevel.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; - this.TB_ObedienceLevel.Location = new System.Drawing.Point(98, 0); + this.TB_ObedienceLevel.Location = new System.Drawing.Point(104, 0); this.TB_ObedienceLevel.Margin = new System.Windows.Forms.Padding(0); this.TB_ObedienceLevel.Mask = "000"; this.TB_ObedienceLevel.Name = "TB_ObedienceLevel"; - this.TB_ObedienceLevel.Size = new System.Drawing.Size(22, 20); + this.TB_ObedienceLevel.Size = new System.Drawing.Size(22, 23); this.TB_ObedienceLevel.TabIndex = 4; // // FLP_GroundTile @@ -1863,10 +1726,10 @@ namespace PKHeX.WinForms.Controls this.FLP_GroundTile.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right))); this.FLP_GroundTile.Controls.Add(this.Label_GroundTile); this.FLP_GroundTile.Controls.Add(this.CB_GroundTile); - this.FLP_GroundTile.Location = new System.Drawing.Point(0, 147); + this.FLP_GroundTile.Location = new System.Drawing.Point(0, 168); this.FLP_GroundTile.Margin = new System.Windows.Forms.Padding(0); this.FLP_GroundTile.Name = "FLP_GroundTile"; - this.FLP_GroundTile.Size = new System.Drawing.Size(272, 21); + this.FLP_GroundTile.Size = new System.Drawing.Size(280, 24); this.FLP_GroundTile.TabIndex = 6; // // Label_GroundTile @@ -1874,7 +1737,7 @@ namespace PKHeX.WinForms.Controls this.Label_GroundTile.Location = new System.Drawing.Point(0, 0); this.Label_GroundTile.Margin = new System.Windows.Forms.Padding(0); this.Label_GroundTile.Name = "Label_GroundTile"; - this.Label_GroundTile.Size = new System.Drawing.Size(98, 21); + this.Label_GroundTile.Size = new System.Drawing.Size(104, 24); this.Label_GroundTile.TabIndex = 5; this.Label_GroundTile.Text = "Encounter:"; this.Label_GroundTile.TextAlign = System.Drawing.ContentAlignment.MiddleRight; @@ -1884,10 +1747,10 @@ namespace PKHeX.WinForms.Controls this.CB_GroundTile.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; this.CB_GroundTile.DropDownWidth = 160; this.CB_GroundTile.FormattingEnabled = true; - this.CB_GroundTile.Location = new System.Drawing.Point(98, 0); + this.CB_GroundTile.Location = new System.Drawing.Point(104, 0); this.CB_GroundTile.Margin = new System.Windows.Forms.Padding(0); this.CB_GroundTile.Name = "CB_GroundTile"; - this.CB_GroundTile.Size = new System.Drawing.Size(134, 21); + this.CB_GroundTile.Size = new System.Drawing.Size(136, 23); this.CB_GroundTile.TabIndex = 7; // // FLP_TimeOfDay @@ -1895,10 +1758,10 @@ namespace PKHeX.WinForms.Controls this.FLP_TimeOfDay.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right))); this.FLP_TimeOfDay.Controls.Add(this.L_MetTimeOfDay); this.FLP_TimeOfDay.Controls.Add(this.CB_MetTimeOfDay); - this.FLP_TimeOfDay.Location = new System.Drawing.Point(0, 168); + this.FLP_TimeOfDay.Location = new System.Drawing.Point(0, 192); this.FLP_TimeOfDay.Margin = new System.Windows.Forms.Padding(0); this.FLP_TimeOfDay.Name = "FLP_TimeOfDay"; - this.FLP_TimeOfDay.Size = new System.Drawing.Size(272, 21); + this.FLP_TimeOfDay.Size = new System.Drawing.Size(280, 24); this.FLP_TimeOfDay.TabIndex = 7; // // L_MetTimeOfDay @@ -1906,7 +1769,7 @@ namespace PKHeX.WinForms.Controls this.L_MetTimeOfDay.Location = new System.Drawing.Point(0, 0); this.L_MetTimeOfDay.Margin = new System.Windows.Forms.Padding(0); this.L_MetTimeOfDay.Name = "L_MetTimeOfDay"; - this.L_MetTimeOfDay.Size = new System.Drawing.Size(98, 21); + this.L_MetTimeOfDay.Size = new System.Drawing.Size(104, 24); this.L_MetTimeOfDay.TabIndex = 10; this.L_MetTimeOfDay.Text = "Time of Day:"; this.L_MetTimeOfDay.TextAlign = System.Drawing.ContentAlignment.MiddleRight; @@ -1921,80 +1784,64 @@ namespace PKHeX.WinForms.Controls "Morning", "Day", "Night"}); - this.CB_MetTimeOfDay.Location = new System.Drawing.Point(98, 0); + this.CB_MetTimeOfDay.Location = new System.Drawing.Point(104, 0); this.CB_MetTimeOfDay.Margin = new System.Windows.Forms.Padding(0); this.CB_MetTimeOfDay.Name = "CB_MetTimeOfDay"; - this.CB_MetTimeOfDay.Size = new System.Drawing.Size(134, 21); + this.CB_MetTimeOfDay.Size = new System.Drawing.Size(136, 23); this.CB_MetTimeOfDay.TabIndex = 11; // - // Tab_Stats + // Hidden_Stats // - this.Tab_Stats.AllowDrop = true; - this.Tab_Stats.Controls.Add(this.Stats); - this.Tab_Stats.Controls.Add(this.Contest); - this.Tab_Stats.Location = new System.Drawing.Point(4, 22); - this.Tab_Stats.Name = "Tab_Stats"; - this.Tab_Stats.Padding = new System.Windows.Forms.Padding(3); - this.Tab_Stats.Size = new System.Drawing.Size(192, 74); - this.Tab_Stats.TabIndex = 2; - this.Tab_Stats.Text = "Stats"; - this.Tab_Stats.UseVisualStyleBackColor = true; + this.Hidden_Stats.AllowDrop = true; + this.Hidden_Stats.Controls.Add(this.Stats); + this.Hidden_Stats.Location = new System.Drawing.Point(4, 5); + this.Hidden_Stats.Margin = new System.Windows.Forms.Padding(0); + this.Hidden_Stats.Name = "Hidden_Stats"; + this.Hidden_Stats.Padding = new System.Windows.Forms.Padding(0, 8, 0, 0); + this.Hidden_Stats.Size = new System.Drawing.Size(296, 391); + this.Hidden_Stats.TabIndex = 2; + this.Hidden_Stats.Text = "Stats"; + this.Hidden_Stats.UseVisualStyleBackColor = true; // // Stats // + this.Stats.Dock = System.Windows.Forms.DockStyle.Fill; this.Stats.EVsFishy = System.Drawing.Color.LightYellow; this.Stats.EVsInvalid = System.Drawing.Color.Red; this.Stats.EVsMaxed = System.Drawing.Color.Honeydew; this.Stats.HaX = false; - this.Stats.Location = new System.Drawing.Point(0, 0); + this.Stats.Location = new System.Drawing.Point(0, 8); + this.Stats.Margin = new System.Windows.Forms.Padding(0); this.Stats.Name = "Stats"; - this.Stats.Size = new System.Drawing.Size(270, 280); + this.Stats.Size = new System.Drawing.Size(296, 383); this.Stats.StatDecreased = System.Drawing.Color.Blue; this.Stats.StatHyperTrained = System.Drawing.Color.LightGreen; this.Stats.StatIncreased = System.Drawing.Color.Red; - this.Stats.TabIndex = 1; + this.Stats.TabIndex = 0; // - // Contest + // Hidden_Moves // - this.Contest.CNT_Beauty = ((byte)(0)); - this.Contest.CNT_Cool = ((byte)(0)); - this.Contest.CNT_Cute = ((byte)(0)); - this.Contest.CNT_Sheen = ((byte)(0)); - this.Contest.CNT_Smart = ((byte)(0)); - this.Contest.CNT_Tough = ((byte)(0)); - this.Contest.Location = new System.Drawing.Point(32, 290); - this.Contest.Margin = new System.Windows.Forms.Padding(0); - this.Contest.Name = "Contest"; - this.Contest.Size = new System.Drawing.Size(230, 50); - this.Contest.TabIndex = 2; - // - // Tab_Attacks - // - this.Tab_Attacks.AllowDrop = true; - this.Tab_Attacks.Controls.Add(this.L_AlphaMastered); - this.Tab_Attacks.Controls.Add(this.CB_AlphaMastered); - this.Tab_Attacks.Controls.Add(this.FLP_MoveFlags); - this.Tab_Attacks.Controls.Add(this.PB_WarnMove4); - this.Tab_Attacks.Controls.Add(this.PB_WarnMove3); - this.Tab_Attacks.Controls.Add(this.PB_WarnMove2); - this.Tab_Attacks.Controls.Add(this.PB_WarnMove1); - this.Tab_Attacks.Controls.Add(this.GB_RelearnMoves); - this.Tab_Attacks.Controls.Add(this.GB_CurrentMoves); - this.Tab_Attacks.Location = new System.Drawing.Point(4, 22); - this.Tab_Attacks.Name = "Tab_Attacks"; - this.Tab_Attacks.Padding = new System.Windows.Forms.Padding(3); - this.Tab_Attacks.Size = new System.Drawing.Size(192, 74); - this.Tab_Attacks.TabIndex = 3; - this.Tab_Attacks.Text = "Attacks"; - this.Tab_Attacks.UseVisualStyleBackColor = true; + this.Hidden_Moves.AllowDrop = true; + this.Hidden_Moves.Controls.Add(this.L_AlphaMastered); + this.Hidden_Moves.Controls.Add(this.CB_AlphaMastered); + this.Hidden_Moves.Controls.Add(this.FLP_MoveFlags); + this.Hidden_Moves.Controls.Add(this.GB_RelearnMoves); + this.Hidden_Moves.Controls.Add(this.GB_CurrentMoves); + this.Hidden_Moves.Location = new System.Drawing.Point(4, 5); + this.Hidden_Moves.Margin = new System.Windows.Forms.Padding(0); + this.Hidden_Moves.Name = "Hidden_Moves"; + this.Hidden_Moves.Size = new System.Drawing.Size(296, 391); + this.Hidden_Moves.TabIndex = 3; + this.Hidden_Moves.Text = "Attacks"; + this.Hidden_Moves.UseVisualStyleBackColor = true; // // L_AlphaMastered // - this.L_AlphaMastered.Location = new System.Drawing.Point(8, 317); + this.L_AlphaMastered.Location = new System.Drawing.Point(8, 328); this.L_AlphaMastered.Margin = new System.Windows.Forms.Padding(0); this.L_AlphaMastered.Name = "L_AlphaMastered"; - this.L_AlphaMastered.Size = new System.Drawing.Size(112, 21); - this.L_AlphaMastered.TabIndex = 21; + this.L_AlphaMastered.Size = new System.Drawing.Size(112, 22); + this.L_AlphaMastered.TabIndex = 101; this.L_AlphaMastered.Text = "Alpha Mastered:"; this.L_AlphaMastered.TextAlign = System.Drawing.ContentAlignment.MiddleRight; // @@ -2003,10 +1850,10 @@ namespace PKHeX.WinForms.Controls this.CB_AlphaMastered.AutoCompleteMode = System.Windows.Forms.AutoCompleteMode.SuggestAppend; this.CB_AlphaMastered.AutoCompleteSource = System.Windows.Forms.AutoCompleteSource.ListItems; this.CB_AlphaMastered.FormattingEnabled = true; - this.CB_AlphaMastered.Location = new System.Drawing.Point(123, 317); + this.CB_AlphaMastered.Location = new System.Drawing.Point(120, 328); this.CB_AlphaMastered.Name = "CB_AlphaMastered"; - this.CB_AlphaMastered.Size = new System.Drawing.Size(124, 21); - this.CB_AlphaMastered.TabIndex = 20; + this.CB_AlphaMastered.Size = new System.Drawing.Size(124, 23); + this.CB_AlphaMastered.TabIndex = 12; this.CB_AlphaMastered.SelectedIndexChanged += new System.EventHandler(this.ValidateMove); // // FLP_MoveFlags @@ -2015,24 +1862,24 @@ namespace PKHeX.WinForms.Controls | System.Windows.Forms.AnchorStyles.Right))); this.FLP_MoveFlags.AutoSize = true; this.FLP_MoveFlags.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink; - this.FLP_MoveFlags.Controls.Add(this.B_Records); + this.FLP_MoveFlags.Controls.Add(this.B_RelearnFlags); this.FLP_MoveFlags.Controls.Add(this.B_MoveShop); - this.FLP_MoveFlags.Location = new System.Drawing.Point(8, 286); + this.FLP_MoveFlags.Location = new System.Drawing.Point(5, 301); this.FLP_MoveFlags.Name = "FLP_MoveFlags"; this.FLP_MoveFlags.Size = new System.Drawing.Size(292, 25); - this.FLP_MoveFlags.TabIndex = 11; + this.FLP_MoveFlags.TabIndex = 100; this.FLP_MoveFlags.WrapContents = false; // - // B_Records + // B_RelearnFlags // - this.B_Records.Location = new System.Drawing.Point(1, 1); - this.B_Records.Margin = new System.Windows.Forms.Padding(1); - this.B_Records.Name = "B_Records"; - this.B_Records.Size = new System.Drawing.Size(144, 23); - this.B_Records.TabIndex = 8; - this.B_Records.Text = "Technical Records"; - this.B_Records.UseVisualStyleBackColor = true; - this.B_Records.Click += new System.EventHandler(this.B_Records_Click); + this.B_RelearnFlags.Location = new System.Drawing.Point(1, 1); + this.B_RelearnFlags.Margin = new System.Windows.Forms.Padding(1); + this.B_RelearnFlags.Name = "B_RelearnFlags"; + this.B_RelearnFlags.Size = new System.Drawing.Size(144, 23); + this.B_RelearnFlags.TabIndex = 10; + this.B_RelearnFlags.Text = "Relearn Flags"; + this.B_RelearnFlags.UseVisualStyleBackColor = true; + this.B_RelearnFlags.Click += new System.EventHandler(this.B_Records_Click); // // B_MoveShop // @@ -2040,51 +1887,11 @@ namespace PKHeX.WinForms.Controls this.B_MoveShop.Margin = new System.Windows.Forms.Padding(1); this.B_MoveShop.Name = "B_MoveShop"; this.B_MoveShop.Size = new System.Drawing.Size(144, 23); - this.B_MoveShop.TabIndex = 9; + this.B_MoveShop.TabIndex = 11; this.B_MoveShop.Text = "Move Shop"; this.B_MoveShop.UseVisualStyleBackColor = true; this.B_MoveShop.Click += new System.EventHandler(this.B_MoveShop_Click); // - // PB_WarnMove4 - // - this.PB_WarnMove4.Image = global::PKHeX.WinForms.Properties.Resources.warn; - this.PB_WarnMove4.Location = new System.Drawing.Point(8, 113); - this.PB_WarnMove4.Name = "PB_WarnMove4"; - this.PB_WarnMove4.Size = new System.Drawing.Size(16, 16); - this.PB_WarnMove4.TabIndex = 5; - this.PB_WarnMove4.TabStop = false; - this.PB_WarnMove4.Visible = false; - // - // PB_WarnMove3 - // - this.PB_WarnMove3.Image = global::PKHeX.WinForms.Properties.Resources.warn; - this.PB_WarnMove3.Location = new System.Drawing.Point(8, 91); - this.PB_WarnMove3.Name = "PB_WarnMove3"; - this.PB_WarnMove3.Size = new System.Drawing.Size(16, 16); - this.PB_WarnMove3.TabIndex = 4; - this.PB_WarnMove3.TabStop = false; - this.PB_WarnMove3.Visible = false; - // - // PB_WarnMove2 - // - this.PB_WarnMove2.Image = global::PKHeX.WinForms.Properties.Resources.warn; - this.PB_WarnMove2.Location = new System.Drawing.Point(8, 69); - this.PB_WarnMove2.Name = "PB_WarnMove2"; - this.PB_WarnMove2.Size = new System.Drawing.Size(16, 16); - this.PB_WarnMove2.TabIndex = 3; - this.PB_WarnMove2.TabStop = false; - this.PB_WarnMove2.Visible = false; - // - // PB_WarnMove1 - // - this.PB_WarnMove1.Image = global::PKHeX.WinForms.Properties.Resources.warn; - this.PB_WarnMove1.Location = new System.Drawing.Point(8, 47); - this.PB_WarnMove1.Name = "PB_WarnMove1"; - this.PB_WarnMove1.Size = new System.Drawing.Size(16, 16); - this.PB_WarnMove1.TabIndex = 2; - this.PB_WarnMove1.TabStop = false; - this.PB_WarnMove1.Visible = false; - // // GB_RelearnMoves // this.GB_RelearnMoves.Controls.Add(this.PB_WarnRelearn4); @@ -2095,19 +1902,21 @@ namespace PKHeX.WinForms.Controls this.GB_RelearnMoves.Controls.Add(this.CB_RelearnMove3); this.GB_RelearnMoves.Controls.Add(this.CB_RelearnMove2); this.GB_RelearnMoves.Controls.Add(this.CB_RelearnMove1); - this.GB_RelearnMoves.Location = new System.Drawing.Point(27, 160); + this.GB_RelearnMoves.Location = new System.Drawing.Point(64, 160); this.GB_RelearnMoves.Name = "GB_RelearnMoves"; - this.GB_RelearnMoves.Size = new System.Drawing.Size(220, 120); - this.GB_RelearnMoves.TabIndex = 1; + this.GB_RelearnMoves.Size = new System.Drawing.Size(168, 128); + this.GB_RelearnMoves.TabIndex = 5; this.GB_RelearnMoves.TabStop = false; this.GB_RelearnMoves.Text = "Relearn Moves"; // // PB_WarnRelearn4 // this.PB_WarnRelearn4.Image = global::PKHeX.WinForms.Properties.Resources.warn; - this.PB_WarnRelearn4.Location = new System.Drawing.Point(22, 94); + this.PB_WarnRelearn4.Location = new System.Drawing.Point(8, 96); + this.PB_WarnRelearn4.Margin = new System.Windows.Forms.Padding(0); this.PB_WarnRelearn4.Name = "PB_WarnRelearn4"; - this.PB_WarnRelearn4.Size = new System.Drawing.Size(16, 16); + this.PB_WarnRelearn4.Size = new System.Drawing.Size(24, 24); + this.PB_WarnRelearn4.SizeMode = System.Windows.Forms.PictureBoxSizeMode.CenterImage; this.PB_WarnRelearn4.TabIndex = 19; this.PB_WarnRelearn4.TabStop = false; this.PB_WarnRelearn4.Visible = false; @@ -2115,9 +1924,11 @@ namespace PKHeX.WinForms.Controls // PB_WarnRelearn3 // this.PB_WarnRelearn3.Image = global::PKHeX.WinForms.Properties.Resources.warn; - this.PB_WarnRelearn3.Location = new System.Drawing.Point(22, 72); + this.PB_WarnRelearn3.Location = new System.Drawing.Point(8, 72); + this.PB_WarnRelearn3.Margin = new System.Windows.Forms.Padding(0); this.PB_WarnRelearn3.Name = "PB_WarnRelearn3"; - this.PB_WarnRelearn3.Size = new System.Drawing.Size(16, 16); + this.PB_WarnRelearn3.Size = new System.Drawing.Size(24, 24); + this.PB_WarnRelearn3.SizeMode = System.Windows.Forms.PictureBoxSizeMode.CenterImage; this.PB_WarnRelearn3.TabIndex = 18; this.PB_WarnRelearn3.TabStop = false; this.PB_WarnRelearn3.Visible = false; @@ -2125,9 +1936,11 @@ namespace PKHeX.WinForms.Controls // PB_WarnRelearn2 // this.PB_WarnRelearn2.Image = global::PKHeX.WinForms.Properties.Resources.warn; - this.PB_WarnRelearn2.Location = new System.Drawing.Point(22, 50); + this.PB_WarnRelearn2.Location = new System.Drawing.Point(8, 48); + this.PB_WarnRelearn2.Margin = new System.Windows.Forms.Padding(0); this.PB_WarnRelearn2.Name = "PB_WarnRelearn2"; - this.PB_WarnRelearn2.Size = new System.Drawing.Size(16, 16); + this.PB_WarnRelearn2.Size = new System.Drawing.Size(24, 24); + this.PB_WarnRelearn2.SizeMode = System.Windows.Forms.PictureBoxSizeMode.CenterImage; this.PB_WarnRelearn2.TabIndex = 17; this.PB_WarnRelearn2.TabStop = false; this.PB_WarnRelearn2.Visible = false; @@ -2135,9 +1948,11 @@ namespace PKHeX.WinForms.Controls // PB_WarnRelearn1 // this.PB_WarnRelearn1.Image = global::PKHeX.WinForms.Properties.Resources.warn; - this.PB_WarnRelearn1.Location = new System.Drawing.Point(22, 28); + this.PB_WarnRelearn1.Location = new System.Drawing.Point(8, 24); + this.PB_WarnRelearn1.Margin = new System.Windows.Forms.Padding(0); this.PB_WarnRelearn1.Name = "PB_WarnRelearn1"; - this.PB_WarnRelearn1.Size = new System.Drawing.Size(16, 16); + this.PB_WarnRelearn1.Size = new System.Drawing.Size(24, 24); + this.PB_WarnRelearn1.SizeMode = System.Windows.Forms.PictureBoxSizeMode.CenterImage; this.PB_WarnRelearn1.TabIndex = 6; this.PB_WarnRelearn1.TabStop = false; this.PB_WarnRelearn1.Visible = false; @@ -2147,10 +1962,10 @@ namespace PKHeX.WinForms.Controls this.CB_RelearnMove4.AutoCompleteMode = System.Windows.Forms.AutoCompleteMode.SuggestAppend; this.CB_RelearnMove4.AutoCompleteSource = System.Windows.Forms.AutoCompleteSource.ListItems; this.CB_RelearnMove4.FormattingEnabled = true; - this.CB_RelearnMove4.Location = new System.Drawing.Point(48, 92); + this.CB_RelearnMove4.Location = new System.Drawing.Point(32, 96); this.CB_RelearnMove4.Name = "CB_RelearnMove4"; - this.CB_RelearnMove4.Size = new System.Drawing.Size(124, 21); - this.CB_RelearnMove4.TabIndex = 16; + this.CB_RelearnMove4.Size = new System.Drawing.Size(124, 23); + this.CB_RelearnMove4.TabIndex = 9; this.CB_RelearnMove4.SelectedIndexChanged += new System.EventHandler(this.ValidateMove); this.CB_RelearnMove4.Leave += new System.EventHandler(this.ValidateComboBox2); this.CB_RelearnMove4.Validating += new System.ComponentModel.CancelEventHandler(this.ValidateComboBox); @@ -2160,10 +1975,10 @@ namespace PKHeX.WinForms.Controls this.CB_RelearnMove3.AutoCompleteMode = System.Windows.Forms.AutoCompleteMode.SuggestAppend; this.CB_RelearnMove3.AutoCompleteSource = System.Windows.Forms.AutoCompleteSource.ListItems; this.CB_RelearnMove3.FormattingEnabled = true; - this.CB_RelearnMove3.Location = new System.Drawing.Point(48, 70); + this.CB_RelearnMove3.Location = new System.Drawing.Point(32, 72); this.CB_RelearnMove3.Name = "CB_RelearnMove3"; - this.CB_RelearnMove3.Size = new System.Drawing.Size(124, 21); - this.CB_RelearnMove3.TabIndex = 15; + this.CB_RelearnMove3.Size = new System.Drawing.Size(124, 23); + this.CB_RelearnMove3.TabIndex = 8; this.CB_RelearnMove3.SelectedIndexChanged += new System.EventHandler(this.ValidateMove); this.CB_RelearnMove3.Leave += new System.EventHandler(this.ValidateComboBox2); this.CB_RelearnMove3.Validating += new System.ComponentModel.CancelEventHandler(this.ValidateComboBox); @@ -2173,10 +1988,10 @@ namespace PKHeX.WinForms.Controls this.CB_RelearnMove2.AutoCompleteMode = System.Windows.Forms.AutoCompleteMode.SuggestAppend; this.CB_RelearnMove2.AutoCompleteSource = System.Windows.Forms.AutoCompleteSource.ListItems; this.CB_RelearnMove2.FormattingEnabled = true; - this.CB_RelearnMove2.Location = new System.Drawing.Point(48, 48); + this.CB_RelearnMove2.Location = new System.Drawing.Point(32, 48); this.CB_RelearnMove2.Name = "CB_RelearnMove2"; - this.CB_RelearnMove2.Size = new System.Drawing.Size(124, 21); - this.CB_RelearnMove2.TabIndex = 14; + this.CB_RelearnMove2.Size = new System.Drawing.Size(124, 23); + this.CB_RelearnMove2.TabIndex = 7; this.CB_RelearnMove2.SelectedIndexChanged += new System.EventHandler(this.ValidateMove); this.CB_RelearnMove2.Leave += new System.EventHandler(this.ValidateComboBox2); this.CB_RelearnMove2.Validating += new System.ComponentModel.CancelEventHandler(this.ValidateComboBox); @@ -2186,302 +2001,143 @@ namespace PKHeX.WinForms.Controls this.CB_RelearnMove1.AutoCompleteMode = System.Windows.Forms.AutoCompleteMode.SuggestAppend; this.CB_RelearnMove1.AutoCompleteSource = System.Windows.Forms.AutoCompleteSource.ListItems; this.CB_RelearnMove1.FormattingEnabled = true; - this.CB_RelearnMove1.Location = new System.Drawing.Point(48, 26); + this.CB_RelearnMove1.Location = new System.Drawing.Point(32, 24); this.CB_RelearnMove1.Name = "CB_RelearnMove1"; - this.CB_RelearnMove1.Size = new System.Drawing.Size(124, 21); - this.CB_RelearnMove1.TabIndex = 13; + this.CB_RelearnMove1.Size = new System.Drawing.Size(124, 23); + this.CB_RelearnMove1.TabIndex = 6; this.CB_RelearnMove1.SelectedIndexChanged += new System.EventHandler(this.ValidateMove); this.CB_RelearnMove1.Leave += new System.EventHandler(this.ValidateComboBox2); this.CB_RelearnMove1.Validating += new System.ComponentModel.CancelEventHandler(this.ValidateComboBox); // // GB_CurrentMoves // - this.GB_CurrentMoves.Controls.Add(this.TB_PP4); - this.GB_CurrentMoves.Controls.Add(this.TB_PP3); - this.GB_CurrentMoves.Controls.Add(this.TB_PP2); - this.GB_CurrentMoves.Controls.Add(this.TB_PP1); + this.GB_CurrentMoves.Controls.Add(this.FLP_Moves); this.GB_CurrentMoves.Controls.Add(this.Label_CurPP); this.GB_CurrentMoves.Controls.Add(this.Label_PPups); - this.GB_CurrentMoves.Controls.Add(this.CB_PPu4); - this.GB_CurrentMoves.Controls.Add(this.CB_PPu3); - this.GB_CurrentMoves.Controls.Add(this.CB_PPu2); - this.GB_CurrentMoves.Controls.Add(this.CB_Move4); - this.GB_CurrentMoves.Controls.Add(this.CB_PPu1); - this.GB_CurrentMoves.Controls.Add(this.CB_Move3); - this.GB_CurrentMoves.Controls.Add(this.CB_Move2); - this.GB_CurrentMoves.Controls.Add(this.CB_Move1); - this.GB_CurrentMoves.Location = new System.Drawing.Point(27, 19); + this.GB_CurrentMoves.Location = new System.Drawing.Point(16, 16); this.GB_CurrentMoves.Name = "GB_CurrentMoves"; - this.GB_CurrentMoves.Size = new System.Drawing.Size(220, 120); + this.GB_CurrentMoves.Size = new System.Drawing.Size(248, 136); this.GB_CurrentMoves.TabIndex = 0; this.GB_CurrentMoves.TabStop = false; this.GB_CurrentMoves.Text = "Current Moves"; // - // TB_PP4 + // FLP_Moves // - this.TB_PP4.Location = new System.Drawing.Point(135, 93); - this.TB_PP4.Mask = "000"; - this.TB_PP4.Name = "TB_PP4"; - this.TB_PP4.PromptChar = ' '; - this.TB_PP4.Size = new System.Drawing.Size(31, 20); - this.TB_PP4.TabIndex = 16; - this.TB_PP4.Validated += new System.EventHandler(this.Update255_MTB); + this.FLP_Moves.Controls.Add(this.MC_Move1); + this.FLP_Moves.Controls.Add(this.MC_Move2); + this.FLP_Moves.Controls.Add(this.MC_Move3); + this.FLP_Moves.Controls.Add(this.MC_Move4); + this.FLP_Moves.Location = new System.Drawing.Point(8, 32); + this.FLP_Moves.Margin = new System.Windows.Forms.Padding(0); + this.FLP_Moves.Name = "FLP_Moves"; + this.FLP_Moves.Size = new System.Drawing.Size(240, 96); + this.FLP_Moves.TabIndex = 14; // - // TB_PP3 + // MC_Move1 // - this.TB_PP3.Location = new System.Drawing.Point(135, 71); - this.TB_PP3.Mask = "000"; - this.TB_PP3.Name = "TB_PP3"; - this.TB_PP3.PromptChar = ' '; - this.TB_PP3.Size = new System.Drawing.Size(31, 20); - this.TB_PP3.TabIndex = 15; - this.TB_PP3.Validated += new System.EventHandler(this.Update255_MTB); + this.MC_Move1.Location = new System.Drawing.Point(0, 0); + this.MC_Move1.Margin = new System.Windows.Forms.Padding(0); + this.MC_Move1.Name = "MC_Move1"; + this.MC_Move1.PP = 0; + this.MC_Move1.PPUps = 0; + this.MC_Move1.SelectedMove = ((ushort)(0)); + this.MC_Move1.Size = new System.Drawing.Size(240, 24); + this.MC_Move1.TabIndex = 1; // - // TB_PP2 + // MC_Move2 // - this.TB_PP2.Location = new System.Drawing.Point(135, 49); - this.TB_PP2.Mask = "000"; - this.TB_PP2.Name = "TB_PP2"; - this.TB_PP2.PromptChar = ' '; - this.TB_PP2.Size = new System.Drawing.Size(31, 20); - this.TB_PP2.TabIndex = 14; - this.TB_PP2.Validated += new System.EventHandler(this.Update255_MTB); + this.MC_Move2.Location = new System.Drawing.Point(0, 24); + this.MC_Move2.Margin = new System.Windows.Forms.Padding(0); + this.MC_Move2.Name = "MC_Move2"; + this.MC_Move2.PP = 0; + this.MC_Move2.PPUps = 0; + this.MC_Move2.SelectedMove = ((ushort)(0)); + this.MC_Move2.Size = new System.Drawing.Size(240, 24); + this.MC_Move2.TabIndex = 2; // - // TB_PP1 + // MC_Move3 // - this.TB_PP1.Location = new System.Drawing.Point(135, 27); - this.TB_PP1.Mask = "000"; - this.TB_PP1.Name = "TB_PP1"; - this.TB_PP1.PromptChar = ' '; - this.TB_PP1.Size = new System.Drawing.Size(31, 20); - this.TB_PP1.TabIndex = 13; - this.TB_PP1.Validated += new System.EventHandler(this.Update255_MTB); + this.MC_Move3.Location = new System.Drawing.Point(0, 48); + this.MC_Move3.Margin = new System.Windows.Forms.Padding(0); + this.MC_Move3.Name = "MC_Move3"; + this.MC_Move3.PP = 0; + this.MC_Move3.PPUps = 0; + this.MC_Move3.SelectedMove = ((ushort)(0)); + this.MC_Move3.Size = new System.Drawing.Size(240, 24); + this.MC_Move3.TabIndex = 3; + // + // MC_Move4 + // + this.MC_Move4.Location = new System.Drawing.Point(0, 72); + this.MC_Move4.Margin = new System.Windows.Forms.Padding(0); + this.MC_Move4.Name = "MC_Move4"; + this.MC_Move4.PP = 0; + this.MC_Move4.PPUps = 0; + this.MC_Move4.SelectedMove = ((ushort)(0)); + this.MC_Move4.Size = new System.Drawing.Size(240, 24); + this.MC_Move4.TabIndex = 4; // // Label_CurPP // - this.Label_CurPP.Location = new System.Drawing.Point(133, 12); + this.Label_CurPP.Location = new System.Drawing.Point(160, 16); this.Label_CurPP.Name = "Label_CurPP"; - this.Label_CurPP.Size = new System.Drawing.Size(35, 13); + this.Label_CurPP.Size = new System.Drawing.Size(32, 16); this.Label_CurPP.TabIndex = 2; this.Label_CurPP.Text = "PP"; - this.Label_CurPP.TextAlign = System.Drawing.ContentAlignment.MiddleCenter; + this.Label_CurPP.TextAlign = System.Drawing.ContentAlignment.BottomCenter; this.Label_CurPP.Click += new System.EventHandler(this.ClickPP); // // Label_PPups // - this.Label_PPups.Location = new System.Drawing.Point(169, 12); + this.Label_PPups.Location = new System.Drawing.Point(192, 16); this.Label_PPups.Name = "Label_PPups"; - this.Label_PPups.Size = new System.Drawing.Size(45, 13); + this.Label_PPups.Size = new System.Drawing.Size(48, 16); this.Label_PPups.TabIndex = 12; this.Label_PPups.Text = "PP Ups"; - this.Label_PPups.TextAlign = System.Drawing.ContentAlignment.MiddleCenter; + this.Label_PPups.TextAlign = System.Drawing.ContentAlignment.BottomCenter; this.Label_PPups.Click += new System.EventHandler(this.ClickPPUps); // - // CB_PPu4 + // Hidden_Cosmetic // - this.CB_PPu4.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; - this.CB_PPu4.FormattingEnabled = true; - this.CB_PPu4.Items.AddRange(new object[] { - "0", - "1", - "2", - "3"}); - this.CB_PPu4.Location = new System.Drawing.Point(172, 92); - this.CB_PPu4.Name = "CB_PPu4"; - this.CB_PPu4.Size = new System.Drawing.Size(38, 21); - this.CB_PPu4.TabIndex = 12; - this.CB_PPu4.SelectedIndexChanged += new System.EventHandler(this.UpdatePP); + this.Hidden_Cosmetic.Controls.Add(this.Contest); + this.Hidden_Cosmetic.Controls.Add(this.FLP_PKMEditors); + this.Hidden_Cosmetic.Controls.Add(this.FLP_CosmeticTop); + this.Hidden_Cosmetic.Location = new System.Drawing.Point(4, 5); + this.Hidden_Cosmetic.Name = "Hidden_Cosmetic"; + this.Hidden_Cosmetic.Size = new System.Drawing.Size(296, 391); + this.Hidden_Cosmetic.TabIndex = 5; + this.Hidden_Cosmetic.Text = "Cosmetic"; + this.Hidden_Cosmetic.UseVisualStyleBackColor = true; // - // CB_PPu3 + // Contest // - this.CB_PPu3.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; - this.CB_PPu3.FormattingEnabled = true; - this.CB_PPu3.Items.AddRange(new object[] { - "0", - "1", - "2", - "3"}); - this.CB_PPu3.Location = new System.Drawing.Point(172, 70); - this.CB_PPu3.Name = "CB_PPu3"; - this.CB_PPu3.Size = new System.Drawing.Size(38, 21); - this.CB_PPu3.TabIndex = 9; - this.CB_PPu3.SelectedIndexChanged += new System.EventHandler(this.UpdatePP); - // - // CB_PPu2 - // - this.CB_PPu2.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; - this.CB_PPu2.FormattingEnabled = true; - this.CB_PPu2.Items.AddRange(new object[] { - "0", - "1", - "2", - "3"}); - this.CB_PPu2.Location = new System.Drawing.Point(172, 48); - this.CB_PPu2.Name = "CB_PPu2"; - this.CB_PPu2.Size = new System.Drawing.Size(38, 21); - this.CB_PPu2.TabIndex = 6; - this.CB_PPu2.SelectedIndexChanged += new System.EventHandler(this.UpdatePP); - // - // CB_Move4 - // - this.CB_Move4.AutoCompleteMode = System.Windows.Forms.AutoCompleteMode.SuggestAppend; - this.CB_Move4.AutoCompleteSource = System.Windows.Forms.AutoCompleteSource.ListItems; - this.CB_Move4.DrawMode = System.Windows.Forms.DrawMode.OwnerDrawVariable; - this.CB_Move4.DropDownHeight = 392; - this.CB_Move4.FormattingEnabled = true; - this.CB_Move4.IntegralHeight = false; - this.CB_Move4.Location = new System.Drawing.Point(9, 92); - this.CB_Move4.Name = "CB_Move4"; - this.CB_Move4.Size = new System.Drawing.Size(121, 21); - this.CB_Move4.TabIndex = 10; - this.CB_Move4.DrawItem += new System.Windows.Forms.DrawItemEventHandler(this.ValidateMovePaint); - this.CB_Move4.DropDown += new System.EventHandler(this.ValidateMoveDropDown); - this.CB_Move4.MeasureItem += new System.Windows.Forms.MeasureItemEventHandler(this.MeasureDropDownHeight); - this.CB_Move4.SelectedIndexChanged += new System.EventHandler(this.ValidateMove); - this.CB_Move4.Leave += new System.EventHandler(this.ValidateComboBox2); - this.CB_Move4.Validating += new System.ComponentModel.CancelEventHandler(this.ValidateComboBox); - // - // CB_PPu1 - // - this.CB_PPu1.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; - this.CB_PPu1.FormattingEnabled = true; - this.CB_PPu1.Items.AddRange(new object[] { - "0", - "1", - "2", - "3"}); - this.CB_PPu1.Location = new System.Drawing.Point(172, 26); - this.CB_PPu1.Name = "CB_PPu1"; - this.CB_PPu1.Size = new System.Drawing.Size(38, 21); - this.CB_PPu1.TabIndex = 3; - this.CB_PPu1.SelectedIndexChanged += new System.EventHandler(this.UpdatePP); - // - // CB_Move3 - // - this.CB_Move3.AutoCompleteMode = System.Windows.Forms.AutoCompleteMode.SuggestAppend; - this.CB_Move3.AutoCompleteSource = System.Windows.Forms.AutoCompleteSource.ListItems; - this.CB_Move3.DrawMode = System.Windows.Forms.DrawMode.OwnerDrawVariable; - this.CB_Move3.DropDownHeight = 392; - this.CB_Move3.FormattingEnabled = true; - this.CB_Move3.IntegralHeight = false; - this.CB_Move3.Location = new System.Drawing.Point(9, 70); - this.CB_Move3.Name = "CB_Move3"; - this.CB_Move3.Size = new System.Drawing.Size(121, 21); - this.CB_Move3.TabIndex = 7; - this.CB_Move3.DrawItem += new System.Windows.Forms.DrawItemEventHandler(this.ValidateMovePaint); - this.CB_Move3.DropDown += new System.EventHandler(this.ValidateMoveDropDown); - this.CB_Move3.MeasureItem += new System.Windows.Forms.MeasureItemEventHandler(this.MeasureDropDownHeight); - this.CB_Move3.SelectedIndexChanged += new System.EventHandler(this.ValidateMove); - this.CB_Move3.Leave += new System.EventHandler(this.ValidateComboBox2); - this.CB_Move3.Validating += new System.ComponentModel.CancelEventHandler(this.ValidateComboBox); - // - // CB_Move2 - // - this.CB_Move2.AutoCompleteMode = System.Windows.Forms.AutoCompleteMode.SuggestAppend; - this.CB_Move2.AutoCompleteSource = System.Windows.Forms.AutoCompleteSource.ListItems; - this.CB_Move2.DrawMode = System.Windows.Forms.DrawMode.OwnerDrawVariable; - this.CB_Move2.DropDownHeight = 392; - this.CB_Move2.FormattingEnabled = true; - this.CB_Move2.IntegralHeight = false; - this.CB_Move2.Location = new System.Drawing.Point(9, 48); - this.CB_Move2.Name = "CB_Move2"; - this.CB_Move2.Size = new System.Drawing.Size(121, 21); - this.CB_Move2.TabIndex = 4; - this.CB_Move2.DrawItem += new System.Windows.Forms.DrawItemEventHandler(this.ValidateMovePaint); - this.CB_Move2.DropDown += new System.EventHandler(this.ValidateMoveDropDown); - this.CB_Move2.MeasureItem += new System.Windows.Forms.MeasureItemEventHandler(this.MeasureDropDownHeight); - this.CB_Move2.SelectedIndexChanged += new System.EventHandler(this.ValidateMove); - this.CB_Move2.Leave += new System.EventHandler(this.ValidateComboBox2); - this.CB_Move2.Validating += new System.ComponentModel.CancelEventHandler(this.ValidateComboBox); - // - // CB_Move1 - // - this.CB_Move1.AutoCompleteMode = System.Windows.Forms.AutoCompleteMode.SuggestAppend; - this.CB_Move1.AutoCompleteSource = System.Windows.Forms.AutoCompleteSource.ListItems; - this.CB_Move1.DrawMode = System.Windows.Forms.DrawMode.OwnerDrawVariable; - this.CB_Move1.DropDownHeight = 392; - this.CB_Move1.FormattingEnabled = true; - this.CB_Move1.IntegralHeight = false; - this.CB_Move1.Location = new System.Drawing.Point(9, 26); - this.CB_Move1.Name = "CB_Move1"; - this.CB_Move1.Size = new System.Drawing.Size(121, 21); - this.CB_Move1.TabIndex = 1; - this.CB_Move1.DrawItem += new System.Windows.Forms.DrawItemEventHandler(this.ValidateMovePaint); - this.CB_Move1.DropDown += new System.EventHandler(this.ValidateMoveDropDown); - this.CB_Move1.MeasureItem += new System.Windows.Forms.MeasureItemEventHandler(this.MeasureDropDownHeight); - this.CB_Move1.SelectedIndexChanged += new System.EventHandler(this.ValidateMove); - this.CB_Move1.Leave += new System.EventHandler(this.ValidateComboBox2); - this.CB_Move1.Validating += new System.ComponentModel.CancelEventHandler(this.ValidateComboBox); - // - // Tab_OTMisc - // - this.Tab_OTMisc.AllowDrop = true; - this.Tab_OTMisc.Controls.Add(this.PB_BattleVersion); - this.Tab_OTMisc.Controls.Add(this.PB_Origin); - this.Tab_OTMisc.Controls.Add(this.PB_Favorite); - this.Tab_OTMisc.Controls.Add(this.FLP_PKMEditors); - this.Tab_OTMisc.Controls.Add(this.TB_EC); - this.Tab_OTMisc.Controls.Add(this.GB_nOT); - this.Tab_OTMisc.Controls.Add(this.BTN_RerollEC); - this.Tab_OTMisc.Controls.Add(this.GB_Markings); - this.Tab_OTMisc.Controls.Add(this.GB_ExtraBytes); - this.Tab_OTMisc.Controls.Add(this.GB_OT); - this.Tab_OTMisc.Controls.Add(this.Label_EncryptionConstant); - this.Tab_OTMisc.Location = new System.Drawing.Point(4, 22); - this.Tab_OTMisc.Name = "Tab_OTMisc"; - this.Tab_OTMisc.Padding = new System.Windows.Forms.Padding(3); - this.Tab_OTMisc.Size = new System.Drawing.Size(192, 74); - this.Tab_OTMisc.TabIndex = 4; - this.Tab_OTMisc.Text = "OT/Misc"; - this.Tab_OTMisc.UseVisualStyleBackColor = true; - // - // PB_BattleVersion - // - this.PB_BattleVersion.Image = global::PKHeX.WinForms.Properties.Resources.icon_btlrom; - this.PB_BattleVersion.InitialImage = global::PKHeX.WinForms.Properties.Resources.icon_btlrom; - this.PB_BattleVersion.Location = new System.Drawing.Point(251, 228); - this.PB_BattleVersion.Name = "PB_BattleVersion"; - this.PB_BattleVersion.Size = new System.Drawing.Size(40, 40); - this.PB_BattleVersion.SizeMode = System.Windows.Forms.PictureBoxSizeMode.CenterImage; - this.PB_BattleVersion.TabIndex = 12; - this.PB_BattleVersion.TabStop = false; - this.PB_BattleVersion.Click += new System.EventHandler(this.ClickVersionMarking); - // - // PB_Origin - // - this.PB_Origin.Location = new System.Drawing.Point(209, 228); - this.PB_Origin.Name = "PB_Origin"; - this.PB_Origin.Size = new System.Drawing.Size(40, 40); - this.PB_Origin.SizeMode = System.Windows.Forms.PictureBoxSizeMode.CenterImage; - this.PB_Origin.TabIndex = 11; - this.PB_Origin.TabStop = false; - this.PB_Origin.Click += new System.EventHandler(this.ClickVersionMarking); - // - // PB_Favorite - // - this.PB_Favorite.Image = global::PKHeX.WinForms.Properties.Resources.icon_favo; - this.PB_Favorite.InitialImage = global::PKHeX.WinForms.Properties.Resources.icon_favo; - this.PB_Favorite.Location = new System.Drawing.Point(22, 228); - this.PB_Favorite.Name = "PB_Favorite"; - this.PB_Favorite.Size = new System.Drawing.Size(40, 40); - this.PB_Favorite.SizeMode = System.Windows.Forms.PictureBoxSizeMode.CenterImage; - this.PB_Favorite.TabIndex = 10; - this.PB_Favorite.TabStop = false; - this.PB_Favorite.Click += new System.EventHandler(this.ClickFavorite); + this.Contest.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.Contest.CNT_Beauty = ((byte)(0)); + this.Contest.CNT_Cool = ((byte)(0)); + this.Contest.CNT_Cute = ((byte)(0)); + this.Contest.CNT_Sheen = ((byte)(0)); + this.Contest.CNT_Smart = ((byte)(0)); + this.Contest.CNT_Tough = ((byte)(0)); + this.Contest.Location = new System.Drawing.Point(4, 328); + this.Contest.Margin = new System.Windows.Forms.Padding(0); + this.Contest.Name = "Contest"; + this.Contest.Size = new System.Drawing.Size(288, 56); + this.Contest.TabIndex = 50; // // FLP_PKMEditors // - this.FLP_PKMEditors.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) + this.FLP_PKMEditors.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left) | System.Windows.Forms.AnchorStyles.Right))); this.FLP_PKMEditors.AutoSize = true; this.FLP_PKMEditors.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink; this.FLP_PKMEditors.Controls.Add(this.BTN_Ribbons); this.FLP_PKMEditors.Controls.Add(this.BTN_Medals); this.FLP_PKMEditors.Controls.Add(this.BTN_History); - this.FLP_PKMEditors.Location = new System.Drawing.Point(49, 275); + this.FLP_PKMEditors.Location = new System.Drawing.Point(56, 288); this.FLP_PKMEditors.Name = "FLP_PKMEditors"; - this.FLP_PKMEditors.Size = new System.Drawing.Size(175, 25); - this.FLP_PKMEditors.TabIndex = 9; + this.FLP_PKMEditors.Size = new System.Drawing.Size(191, 27); + this.FLP_PKMEditors.TabIndex = 6; this.FLP_PKMEditors.WrapContents = false; // // BTN_Ribbons @@ -2494,8 +2150,8 @@ namespace PKHeX.WinForms.Controls this.BTN_Ribbons.Location = new System.Drawing.Point(1, 1); this.BTN_Ribbons.Margin = new System.Windows.Forms.Padding(1); this.BTN_Ribbons.Name = "BTN_Ribbons"; - this.BTN_Ribbons.Size = new System.Drawing.Size(56, 23); - this.BTN_Ribbons.TabIndex = 5; + this.BTN_Ribbons.Size = new System.Drawing.Size(60, 25); + this.BTN_Ribbons.TabIndex = 28; this.BTN_Ribbons.Text = "Ribbons"; this.BTN_Ribbons.UseVisualStyleBackColor = true; this.BTN_Ribbons.Click += new System.EventHandler(this.OpenRibbons); @@ -2507,11 +2163,11 @@ namespace PKHeX.WinForms.Controls | System.Windows.Forms.AnchorStyles.Right))); this.BTN_Medals.AutoSize = true; this.BTN_Medals.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink; - this.BTN_Medals.Location = new System.Drawing.Point(59, 1); + this.BTN_Medals.Location = new System.Drawing.Point(63, 1); this.BTN_Medals.Margin = new System.Windows.Forms.Padding(1); this.BTN_Medals.Name = "BTN_Medals"; - this.BTN_Medals.Size = new System.Drawing.Size(51, 23); - this.BTN_Medals.TabIndex = 7; + this.BTN_Medals.Size = new System.Drawing.Size(55, 25); + this.BTN_Medals.TabIndex = 29; this.BTN_Medals.Text = "Medals"; this.BTN_Medals.UseVisualStyleBackColor = true; this.BTN_Medals.Click += new System.EventHandler(this.OpenMedals); @@ -2523,94 +2179,27 @@ namespace PKHeX.WinForms.Controls | System.Windows.Forms.AnchorStyles.Right))); this.BTN_History.AutoSize = true; this.BTN_History.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink; - this.BTN_History.Location = new System.Drawing.Point(112, 1); + this.BTN_History.Location = new System.Drawing.Point(120, 1); this.BTN_History.Margin = new System.Windows.Forms.Padding(1); this.BTN_History.Name = "BTN_History"; - this.BTN_History.Size = new System.Drawing.Size(62, 23); - this.BTN_History.TabIndex = 6; + this.BTN_History.Size = new System.Drawing.Size(70, 25); + this.BTN_History.TabIndex = 30; this.BTN_History.Text = "Memories"; this.BTN_History.UseVisualStyleBackColor = true; this.BTN_History.Click += new System.EventHandler(this.OpenHistory); // - // TB_EC + // FLP_CosmeticTop // - this.TB_EC.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; - this.TB_EC.Font = new System.Drawing.Font("Courier New", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); - this.TB_EC.Location = new System.Drawing.Point(192, 307); - this.TB_EC.MaxLength = 8; - this.TB_EC.Name = "TB_EC"; - this.TB_EC.Size = new System.Drawing.Size(60, 20); - this.TB_EC.TabIndex = 8; - this.TB_EC.Text = "12345678"; - this.TB_EC.Validated += new System.EventHandler(this.Update_ID); - // - // GB_nOT - // - this.GB_nOT.Controls.Add(this.UC_HTGender); - this.GB_nOT.Controls.Add(this.CB_HTLanguage); - this.GB_nOT.Controls.Add(this.TB_HT); - this.GB_nOT.Controls.Add(this.Label_PrevOT); - this.GB_nOT.Location = new System.Drawing.Point(40, 85); - this.GB_nOT.Name = "GB_nOT"; - this.GB_nOT.Size = new System.Drawing.Size(190, 75); - this.GB_nOT.TabIndex = 2; - this.GB_nOT.TabStop = false; - this.GB_nOT.Text = "Latest (not OT) Handler"; - // - // UC_HTGender - // - this.UC_HTGender.AllowClick = true; - this.UC_HTGender.BackgroundImageLayout = System.Windows.Forms.ImageLayout.Center; - this.UC_HTGender.Gender = 0; - this.UC_HTGender.Location = new System.Drawing.Point(142, 22); - this.UC_HTGender.Margin = new System.Windows.Forms.Padding(3, 2, 2, 1); - this.UC_HTGender.Name = "UC_HTGender"; - this.UC_HTGender.Size = new System.Drawing.Size(18, 18); - this.UC_HTGender.TabIndex = 58; - // - // CB_HTLanguage - // - this.CB_HTLanguage.Anchor = System.Windows.Forms.AnchorStyles.Left; - this.CB_HTLanguage.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; - this.CB_HTLanguage.FormattingEnabled = true; - this.CB_HTLanguage.Location = new System.Drawing.Point(46, 43); - this.CB_HTLanguage.Margin = new System.Windows.Forms.Padding(0); - this.CB_HTLanguage.Name = "CB_HTLanguage"; - this.CB_HTLanguage.Size = new System.Drawing.Size(126, 21); - this.CB_HTLanguage.TabIndex = 15; - // - // TB_HT - // - this.TB_HT.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; - this.TB_HT.Location = new System.Drawing.Point(46, 20); - this.TB_HT.MaxLength = 12; - this.TB_HT.Name = "TB_HT"; - this.TB_HT.Size = new System.Drawing.Size(94, 20); - this.TB_HT.TabIndex = 1; - this.TB_HT.WordWrap = false; - this.TB_HT.TextChanged += new System.EventHandler(this.UpdateNotOT); - this.TB_HT.MouseDown += new System.Windows.Forms.MouseEventHandler(this.UpdateNicknameClick); - // - // Label_PrevOT - // - this.Label_PrevOT.Location = new System.Drawing.Point(4, 23); - this.Label_PrevOT.Name = "Label_PrevOT"; - this.Label_PrevOT.Size = new System.Drawing.Size(40, 13); - this.Label_PrevOT.TabIndex = 42; - this.Label_PrevOT.Text = "OT:"; - this.Label_PrevOT.TextAlign = System.Drawing.ContentAlignment.MiddleRight; - this.Label_PrevOT.Click += new System.EventHandler(this.ClickCT); - // - // BTN_RerollEC - // - this.BTN_RerollEC.Font = new System.Drawing.Font("Microsoft Sans Serif", 6.75F); - this.BTN_RerollEC.Location = new System.Drawing.Point(128, 307); - this.BTN_RerollEC.Name = "BTN_RerollEC"; - this.BTN_RerollEC.Size = new System.Drawing.Size(62, 20); - this.BTN_RerollEC.TabIndex = 7; - this.BTN_RerollEC.Text = "Reroll"; - this.BTN_RerollEC.UseVisualStyleBackColor = true; - this.BTN_RerollEC.Click += new System.EventHandler(this.UpdateRandomEC); + this.FLP_CosmeticTop.Controls.Add(this.GB_Markings); + this.FLP_CosmeticTop.Controls.Add(this.FLP_BigMarkings); + this.FLP_CosmeticTop.Controls.Add(this.SizeCP); + this.FLP_CosmeticTop.Controls.Add(this.ShinyLeaf); + this.FLP_CosmeticTop.Dock = System.Windows.Forms.DockStyle.Top; + this.FLP_CosmeticTop.Location = new System.Drawing.Point(0, 0); + this.FLP_CosmeticTop.Name = "FLP_CosmeticTop"; + this.FLP_CosmeticTop.Padding = new System.Windows.Forms.Padding(0, 16, 0, 0); + this.FLP_CosmeticTop.Size = new System.Drawing.Size(296, 280); + this.FLP_CosmeticTop.TabIndex = 0; // // GB_Markings // @@ -2622,10 +2211,13 @@ namespace PKHeX.WinForms.Controls this.GB_Markings.Controls.Add(this.PB_MarkShiny); this.GB_Markings.Controls.Add(this.PB_Mark1); this.GB_Markings.Controls.Add(this.PB_Mark4); - this.GB_Markings.Location = new System.Drawing.Point(68, 213); + this.FLP_CosmeticTop.SetFlowBreak(this.GB_Markings, true); + this.GB_Markings.Location = new System.Drawing.Point(64, 16); + this.GB_Markings.Margin = new System.Windows.Forms.Padding(64, 0, 8, 0); this.GB_Markings.Name = "GB_Markings"; - this.GB_Markings.Size = new System.Drawing.Size(135, 58); - this.GB_Markings.TabIndex = 4; + this.GB_Markings.Padding = new System.Windows.Forms.Padding(0); + this.GB_Markings.Size = new System.Drawing.Size(160, 72); + this.GB_Markings.TabIndex = 1; this.GB_Markings.TabStop = false; this.GB_Markings.Text = "Markings"; // @@ -2633,10 +2225,10 @@ namespace PKHeX.WinForms.Controls // this.PB_Mark6.Image = global::PKHeX.WinForms.Properties.Resources.box_mark_06; this.PB_Mark6.InitialImage = global::PKHeX.WinForms.Properties.Resources.box_mark_06; - this.PB_Mark6.Location = new System.Drawing.Point(110, 36); - this.PB_Mark6.Margin = new System.Windows.Forms.Padding(1); + this.PB_Mark6.Location = new System.Drawing.Point(128, 40); + this.PB_Mark6.Margin = new System.Windows.Forms.Padding(0); this.PB_Mark6.Name = "PB_Mark6"; - this.PB_Mark6.Size = new System.Drawing.Size(20, 20); + this.PB_Mark6.Size = new System.Drawing.Size(24, 24); this.PB_Mark6.SizeMode = System.Windows.Forms.PictureBoxSizeMode.CenterImage; this.PB_Mark6.TabIndex = 5; this.PB_Mark6.TabStop = false; @@ -2646,10 +2238,10 @@ namespace PKHeX.WinForms.Controls // this.PB_Mark3.Image = global::PKHeX.WinForms.Properties.Resources.box_mark_03; this.PB_Mark3.InitialImage = global::PKHeX.WinForms.Properties.Resources.box_mark_03; - this.PB_Mark3.Location = new System.Drawing.Point(47, 36); - this.PB_Mark3.Margin = new System.Windows.Forms.Padding(1); + this.PB_Mark3.Location = new System.Drawing.Point(56, 40); + this.PB_Mark3.Margin = new System.Windows.Forms.Padding(0); this.PB_Mark3.Name = "PB_Mark3"; - this.PB_Mark3.Size = new System.Drawing.Size(20, 20); + this.PB_Mark3.Size = new System.Drawing.Size(24, 24); this.PB_Mark3.SizeMode = System.Windows.Forms.PictureBoxSizeMode.CenterImage; this.PB_Mark3.TabIndex = 2; this.PB_Mark3.TabStop = false; @@ -2659,10 +2251,10 @@ namespace PKHeX.WinForms.Controls // this.PB_Mark5.Image = global::PKHeX.WinForms.Properties.Resources.box_mark_05; this.PB_Mark5.InitialImage = global::PKHeX.WinForms.Properties.Resources.box_mark_05; - this.PB_Mark5.Location = new System.Drawing.Point(89, 36); - this.PB_Mark5.Margin = new System.Windows.Forms.Padding(1); + this.PB_Mark5.Location = new System.Drawing.Point(104, 40); + this.PB_Mark5.Margin = new System.Windows.Forms.Padding(0); this.PB_Mark5.Name = "PB_Mark5"; - this.PB_Mark5.Size = new System.Drawing.Size(20, 20); + this.PB_Mark5.Size = new System.Drawing.Size(24, 24); this.PB_Mark5.SizeMode = System.Windows.Forms.PictureBoxSizeMode.CenterImage; this.PB_Mark5.TabIndex = 4; this.PB_Mark5.TabStop = false; @@ -2672,21 +2264,23 @@ namespace PKHeX.WinForms.Controls // this.PB_MarkCured.Image = global::PKHeX.WinForms.Properties.Resources.anti_pokerus_icon; this.PB_MarkCured.InitialImage = global::PKHeX.WinForms.Properties.Resources.anti_pokerus_icon; - this.PB_MarkCured.Location = new System.Drawing.Point(67, 15); + this.PB_MarkCured.Location = new System.Drawing.Point(80, 16); + this.PB_MarkCured.Margin = new System.Windows.Forms.Padding(0); this.PB_MarkCured.Name = "PB_MarkCured"; - this.PB_MarkCured.Size = new System.Drawing.Size(22, 20); + this.PB_MarkCured.Size = new System.Drawing.Size(24, 24); this.PB_MarkCured.SizeMode = System.Windows.Forms.PictureBoxSizeMode.CenterImage; this.PB_MarkCured.TabIndex = 7; this.PB_MarkCured.TabStop = false; + this.PB_MarkCured.Click += new System.EventHandler(this.PB_MarkCured_Click); // // PB_Mark2 // this.PB_Mark2.Image = global::PKHeX.WinForms.Properties.Resources.box_mark_02; this.PB_Mark2.InitialImage = global::PKHeX.WinForms.Properties.Resources.box_mark_02; - this.PB_Mark2.Location = new System.Drawing.Point(26, 36); - this.PB_Mark2.Margin = new System.Windows.Forms.Padding(1); + this.PB_Mark2.Location = new System.Drawing.Point(32, 40); + this.PB_Mark2.Margin = new System.Windows.Forms.Padding(0); this.PB_Mark2.Name = "PB_Mark2"; - this.PB_Mark2.Size = new System.Drawing.Size(20, 20); + this.PB_Mark2.Size = new System.Drawing.Size(24, 24); this.PB_Mark2.SizeMode = System.Windows.Forms.PictureBoxSizeMode.CenterImage; this.PB_Mark2.TabIndex = 1; this.PB_Mark2.TabStop = false; @@ -2696,21 +2290,23 @@ namespace PKHeX.WinForms.Controls // this.PB_MarkShiny.Image = global::PKHeX.WinForms.Properties.Resources.rare_icon; this.PB_MarkShiny.InitialImage = global::PKHeX.WinForms.Properties.Resources.rare_icon; - this.PB_MarkShiny.Location = new System.Drawing.Point(46, 15); + this.PB_MarkShiny.Location = new System.Drawing.Point(56, 16); + this.PB_MarkShiny.Margin = new System.Windows.Forms.Padding(0); this.PB_MarkShiny.Name = "PB_MarkShiny"; - this.PB_MarkShiny.Size = new System.Drawing.Size(22, 20); + this.PB_MarkShiny.Size = new System.Drawing.Size(24, 24); this.PB_MarkShiny.SizeMode = System.Windows.Forms.PictureBoxSizeMode.CenterImage; this.PB_MarkShiny.TabIndex = 6; this.PB_MarkShiny.TabStop = false; + this.PB_MarkShiny.Click += new System.EventHandler(this.PB_MarkShiny_Click); // // PB_Mark1 // this.PB_Mark1.Image = global::PKHeX.WinForms.Properties.Resources.box_mark_01; this.PB_Mark1.InitialImage = global::PKHeX.WinForms.Properties.Resources.box_mark_01; - this.PB_Mark1.Location = new System.Drawing.Point(5, 36); - this.PB_Mark1.Margin = new System.Windows.Forms.Padding(1); + this.PB_Mark1.Location = new System.Drawing.Point(8, 40); + this.PB_Mark1.Margin = new System.Windows.Forms.Padding(0); this.PB_Mark1.Name = "PB_Mark1"; - this.PB_Mark1.Size = new System.Drawing.Size(20, 20); + this.PB_Mark1.Size = new System.Drawing.Size(24, 24); this.PB_Mark1.SizeMode = System.Windows.Forms.PictureBoxSizeMode.CenterImage; this.PB_Mark1.TabIndex = 0; this.PB_Mark1.TabStop = false; @@ -2720,128 +2316,604 @@ namespace PKHeX.WinForms.Controls // this.PB_Mark4.Image = global::PKHeX.WinForms.Properties.Resources.box_mark_04; this.PB_Mark4.InitialImage = global::PKHeX.WinForms.Properties.Resources.box_mark_04; - this.PB_Mark4.Location = new System.Drawing.Point(68, 36); - this.PB_Mark4.Margin = new System.Windows.Forms.Padding(1); + this.PB_Mark4.Location = new System.Drawing.Point(80, 40); + this.PB_Mark4.Margin = new System.Windows.Forms.Padding(0); this.PB_Mark4.Name = "PB_Mark4"; - this.PB_Mark4.Size = new System.Drawing.Size(20, 20); + this.PB_Mark4.Size = new System.Drawing.Size(24, 24); this.PB_Mark4.SizeMode = System.Windows.Forms.PictureBoxSizeMode.CenterImage; this.PB_Mark4.TabIndex = 3; this.PB_Mark4.TabStop = false; this.PB_Mark4.Click += new System.EventHandler(this.ClickMarking); // - // GB_ExtraBytes + // FLP_BigMarkings // - this.GB_ExtraBytes.Controls.Add(this.TB_ExtraByte); - this.GB_ExtraBytes.Controls.Add(this.CB_ExtraBytes); - this.GB_ExtraBytes.Location = new System.Drawing.Point(68, 165); - this.GB_ExtraBytes.Name = "GB_ExtraBytes"; - this.GB_ExtraBytes.Size = new System.Drawing.Size(135, 48); - this.GB_ExtraBytes.TabIndex = 3; - this.GB_ExtraBytes.TabStop = false; - this.GB_ExtraBytes.Text = "Extra Bytes"; + this.FLP_BigMarkings.Anchor = System.Windows.Forms.AnchorStyles.None; + this.FLP_BigMarkings.AutoSize = true; + this.FLP_BigMarkings.Controls.Add(this.PB_Favorite); + this.FLP_BigMarkings.Controls.Add(this.PB_Origin); + this.FLP_BigMarkings.Controls.Add(this.PB_BattleVersion); + this.FLP_BigMarkings.Location = new System.Drawing.Point(72, 96); + this.FLP_BigMarkings.Margin = new System.Windows.Forms.Padding(72, 8, 0, 0); + this.FLP_BigMarkings.Name = "FLP_BigMarkings"; + this.FLP_BigMarkings.Size = new System.Drawing.Size(144, 48); + this.FLP_BigMarkings.TabIndex = 2; // - // TB_ExtraByte + // PB_Favorite // - this.TB_ExtraByte.Location = new System.Drawing.Point(87, 19); - this.TB_ExtraByte.Mask = "000"; - this.TB_ExtraByte.Name = "TB_ExtraByte"; - this.TB_ExtraByte.Size = new System.Drawing.Size(28, 20); - this.TB_ExtraByte.TabIndex = 2; - this.TB_ExtraByte.TextAlign = System.Windows.Forms.HorizontalAlignment.Center; - this.TB_ExtraByte.Validated += new System.EventHandler(this.UpdateExtraByteValue); + this.PB_Favorite.Anchor = System.Windows.Forms.AnchorStyles.None; + this.PB_Favorite.Image = global::PKHeX.WinForms.Properties.Resources.icon_favo; + this.PB_Favorite.InitialImage = global::PKHeX.WinForms.Properties.Resources.icon_favo; + this.PB_Favorite.Location = new System.Drawing.Point(0, 0); + this.PB_Favorite.Margin = new System.Windows.Forms.Padding(0); + this.PB_Favorite.Name = "PB_Favorite"; + this.PB_Favorite.Size = new System.Drawing.Size(48, 48); + this.PB_Favorite.SizeMode = System.Windows.Forms.PictureBoxSizeMode.CenterImage; + this.PB_Favorite.TabIndex = 10; + this.PB_Favorite.TabStop = false; + this.PB_Favorite.Click += new System.EventHandler(this.ClickFavorite); + // + // PB_Origin + // + this.PB_Origin.Anchor = System.Windows.Forms.AnchorStyles.None; + this.PB_Origin.Location = new System.Drawing.Point(48, 0); + this.PB_Origin.Margin = new System.Windows.Forms.Padding(0); + this.PB_Origin.Name = "PB_Origin"; + this.PB_Origin.Size = new System.Drawing.Size(48, 48); + this.PB_Origin.SizeMode = System.Windows.Forms.PictureBoxSizeMode.CenterImage; + this.PB_Origin.TabIndex = 11; + this.PB_Origin.TabStop = false; + this.PB_Origin.Click += new System.EventHandler(this.ClickVersionMarking); + // + // PB_BattleVersion + // + this.PB_BattleVersion.Anchor = System.Windows.Forms.AnchorStyles.None; + this.PB_BattleVersion.Image = global::PKHeX.WinForms.Properties.Resources.icon_btlrom; + this.PB_BattleVersion.InitialImage = global::PKHeX.WinForms.Properties.Resources.icon_btlrom; + this.PB_BattleVersion.Location = new System.Drawing.Point(96, 0); + this.PB_BattleVersion.Margin = new System.Windows.Forms.Padding(0); + this.PB_BattleVersion.Name = "PB_BattleVersion"; + this.PB_BattleVersion.Size = new System.Drawing.Size(48, 48); + this.PB_BattleVersion.SizeMode = System.Windows.Forms.PictureBoxSizeMode.CenterImage; + this.PB_BattleVersion.TabIndex = 12; + this.PB_BattleVersion.TabStop = false; + this.PB_BattleVersion.Click += new System.EventHandler(this.ClickVersionMarking); + // + // SizeCP + // + this.SizeCP.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); + this.SizeCP.Location = new System.Drawing.Point(48, 152); + this.SizeCP.Margin = new System.Windows.Forms.Padding(48, 8, 0, 0); + this.SizeCP.Name = "SizeCP"; + this.SizeCP.Size = new System.Drawing.Size(224, 72); + this.SizeCP.TabIndex = 3; + // + // ShinyLeaf + // + this.ShinyLeaf.Location = new System.Drawing.Point(56, 232); + this.ShinyLeaf.Margin = new System.Windows.Forms.Padding(56, 8, 0, 0); + this.ShinyLeaf.Name = "ShinyLeaf"; + this.ShinyLeaf.Size = new System.Drawing.Size(200, 64); + this.ShinyLeaf.TabIndex = 4; + // + // Hidden_OTMisc + // + this.Hidden_OTMisc.AllowDrop = true; + this.Hidden_OTMisc.Controls.Add(this.FLP_OTMisc); + this.Hidden_OTMisc.Location = new System.Drawing.Point(4, 5); + this.Hidden_OTMisc.Margin = new System.Windows.Forms.Padding(0); + this.Hidden_OTMisc.Name = "Hidden_OTMisc"; + this.Hidden_OTMisc.Size = new System.Drawing.Size(296, 391); + this.Hidden_OTMisc.TabIndex = 4; + this.Hidden_OTMisc.Text = "OT/Misc"; + this.Hidden_OTMisc.UseVisualStyleBackColor = true; + // + // FLP_OTMisc + // + this.FLP_OTMisc.Controls.Add(this.GB_OT); + this.FLP_OTMisc.Controls.Add(this.TID_Trainer); + this.FLP_OTMisc.Controls.Add(this.FLP_OT); + this.FLP_OTMisc.Controls.Add(this.FLP_Country); + this.FLP_OTMisc.Controls.Add(this.FLP_SubRegion); + this.FLP_OTMisc.Controls.Add(this.FLP_3DSRegion); + this.FLP_OTMisc.Controls.Add(this.FLP_Handler); + this.FLP_OTMisc.Controls.Add(this.GB_nOT); + this.FLP_OTMisc.Controls.Add(this.FLP_HT); + this.FLP_OTMisc.Controls.Add(this.FLP_HTLanguage); + this.FLP_OTMisc.Controls.Add(this.FLP_ExtraBytes); + this.FLP_OTMisc.Controls.Add(this.L_HomeTracker); + this.FLP_OTMisc.Controls.Add(this.TB_HomeTracker); + this.FLP_OTMisc.Controls.Add(this.Label_EncryptionConstant); + this.FLP_OTMisc.Controls.Add(this.TB_EC); + this.FLP_OTMisc.Controls.Add(this.BTN_RerollEC); + this.FLP_OTMisc.Dock = System.Windows.Forms.DockStyle.Fill; + this.FLP_OTMisc.Location = new System.Drawing.Point(0, 0); + this.FLP_OTMisc.Name = "FLP_OTMisc"; + this.FLP_OTMisc.Size = new System.Drawing.Size(296, 391); + this.FLP_OTMisc.TabIndex = 46; + // + // GB_OT + // + this.FLP_OTMisc.SetFlowBreak(this.GB_OT, true); + this.GB_OT.Location = new System.Drawing.Point(56, 16); + this.GB_OT.Margin = new System.Windows.Forms.Padding(56, 16, 0, 0); + this.GB_OT.Name = "GB_OT"; + this.GB_OT.Size = new System.Drawing.Size(216, 24); + this.GB_OT.TabIndex = 47; + this.GB_OT.Text = "Trainer Information"; + this.GB_OT.TextAlign = System.Drawing.ContentAlignment.MiddleLeft; + // + // TID_Trainer + // + this.TID_Trainer.Location = new System.Drawing.Point(64, 40); + this.TID_Trainer.Margin = new System.Windows.Forms.Padding(64, 0, 0, 0); + this.TID_Trainer.Name = "TID_Trainer"; + this.TID_Trainer.Size = new System.Drawing.Size(208, 24); + this.TID_Trainer.TabIndex = 1; + // + // FLP_OT + // + this.FLP_OT.Controls.Add(this.Label_OT); + this.FLP_OT.Controls.Add(this.TB_OT); + this.FLP_OT.Controls.Add(this.UC_OTGender); + this.FLP_OT.Location = new System.Drawing.Point(0, 64); + this.FLP_OT.Margin = new System.Windows.Forms.Padding(0); + this.FLP_OT.Name = "FLP_OT"; + this.FLP_OT.Size = new System.Drawing.Size(272, 24); + this.FLP_OT.TabIndex = 2; + // + // Label_OT + // + this.Label_OT.Location = new System.Drawing.Point(0, 0); + this.Label_OT.Margin = new System.Windows.Forms.Padding(0); + this.Label_OT.Name = "Label_OT"; + this.Label_OT.Size = new System.Drawing.Size(104, 24); + this.Label_OT.TabIndex = 2; + this.Label_OT.Text = "OT:"; + this.Label_OT.TextAlign = System.Drawing.ContentAlignment.MiddleRight; + this.Label_OT.Click += new System.EventHandler(this.ClickOT); + // + // TB_OT + // + this.TB_OT.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; + this.TB_OT.Location = new System.Drawing.Point(104, 0); + this.TB_OT.Margin = new System.Windows.Forms.Padding(0); + this.TB_OT.MaxLength = 12; + this.TB_OT.Name = "TB_OT"; + this.TB_OT.Size = new System.Drawing.Size(94, 23); + this.TB_OT.TabIndex = 3; + this.TB_OT.MouseDown += new System.Windows.Forms.MouseEventHandler(this.UpdateNicknameClick); + // + // UC_OTGender + // + this.UC_OTGender.AllowClick = true; + this.UC_OTGender.BackgroundImage = ((System.Drawing.Image)(resources.GetObject("UC_OTGender.BackgroundImage"))); + this.UC_OTGender.BackgroundImageLayout = System.Windows.Forms.ImageLayout.Center; + this.UC_OTGender.Gender = 0; + this.UC_OTGender.Location = new System.Drawing.Point(198, 0); + this.UC_OTGender.Margin = new System.Windows.Forms.Padding(0); + this.UC_OTGender.Name = "UC_OTGender"; + this.UC_OTGender.Size = new System.Drawing.Size(24, 24); + this.UC_OTGender.TabIndex = 4; + // + // FLP_Country + // + this.FLP_Country.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right))); + this.FLP_Country.Controls.Add(this.Label_Country); + this.FLP_Country.Controls.Add(this.CB_Country); + this.FLP_Country.Location = new System.Drawing.Point(0, 88); + this.FLP_Country.Margin = new System.Windows.Forms.Padding(0); + this.FLP_Country.Name = "FLP_Country"; + this.FLP_Country.Size = new System.Drawing.Size(272, 24); + this.FLP_Country.TabIndex = 3; + // + // Label_Country + // + this.Label_Country.Location = new System.Drawing.Point(0, 0); + this.Label_Country.Margin = new System.Windows.Forms.Padding(0); + this.Label_Country.Name = "Label_Country"; + this.Label_Country.Size = new System.Drawing.Size(104, 24); + this.Label_Country.TabIndex = 16; + this.Label_Country.Text = "Country:"; + this.Label_Country.TextAlign = System.Drawing.ContentAlignment.MiddleRight; + // + // CB_Country + // + this.CB_Country.AutoCompleteMode = System.Windows.Forms.AutoCompleteMode.SuggestAppend; + this.CB_Country.AutoCompleteSource = System.Windows.Forms.AutoCompleteSource.ListItems; + this.CB_Country.DropDownWidth = 180; + this.CB_Country.FormattingEnabled = true; + this.CB_Country.Location = new System.Drawing.Point(104, 0); + this.CB_Country.Margin = new System.Windows.Forms.Padding(0); + this.CB_Country.Name = "CB_Country"; + this.CB_Country.Size = new System.Drawing.Size(126, 23); + this.CB_Country.TabIndex = 21; + this.CB_Country.SelectedIndexChanged += new System.EventHandler(this.UpdateCountry); + this.CB_Country.Validating += new System.ComponentModel.CancelEventHandler(this.ValidateComboBox); + // + // FLP_SubRegion + // + this.FLP_SubRegion.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right))); + this.FLP_SubRegion.Controls.Add(this.Label_SubRegion); + this.FLP_SubRegion.Controls.Add(this.CB_SubRegion); + this.FLP_SubRegion.Location = new System.Drawing.Point(0, 112); + this.FLP_SubRegion.Margin = new System.Windows.Forms.Padding(0); + this.FLP_SubRegion.Name = "FLP_SubRegion"; + this.FLP_SubRegion.Size = new System.Drawing.Size(272, 24); + this.FLP_SubRegion.TabIndex = 4; + // + // Label_SubRegion + // + this.Label_SubRegion.Location = new System.Drawing.Point(0, 0); + this.Label_SubRegion.Margin = new System.Windows.Forms.Padding(0); + this.Label_SubRegion.Name = "Label_SubRegion"; + this.Label_SubRegion.Size = new System.Drawing.Size(104, 24); + this.Label_SubRegion.TabIndex = 17; + this.Label_SubRegion.Text = "Sub Region:"; + this.Label_SubRegion.TextAlign = System.Drawing.ContentAlignment.MiddleRight; + // + // CB_SubRegion + // + this.CB_SubRegion.AutoCompleteMode = System.Windows.Forms.AutoCompleteMode.SuggestAppend; + this.CB_SubRegion.AutoCompleteSource = System.Windows.Forms.AutoCompleteSource.ListItems; + this.CB_SubRegion.DropDownWidth = 180; + this.CB_SubRegion.FormattingEnabled = true; + this.CB_SubRegion.Location = new System.Drawing.Point(104, 0); + this.CB_SubRegion.Margin = new System.Windows.Forms.Padding(0); + this.CB_SubRegion.Name = "CB_SubRegion"; + this.CB_SubRegion.Size = new System.Drawing.Size(126, 23); + this.CB_SubRegion.TabIndex = 22; + this.CB_SubRegion.Validating += new System.ComponentModel.CancelEventHandler(this.ValidateComboBox); + // + // FLP_3DSRegion + // + this.FLP_3DSRegion.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right))); + this.FLP_3DSRegion.Controls.Add(this.Label_3DSRegion); + this.FLP_3DSRegion.Controls.Add(this.CB_3DSReg); + this.FLP_3DSRegion.Location = new System.Drawing.Point(0, 136); + this.FLP_3DSRegion.Margin = new System.Windows.Forms.Padding(0); + this.FLP_3DSRegion.Name = "FLP_3DSRegion"; + this.FLP_3DSRegion.Size = new System.Drawing.Size(272, 24); + this.FLP_3DSRegion.TabIndex = 5; + // + // Label_3DSRegion + // + this.Label_3DSRegion.Location = new System.Drawing.Point(0, 0); + this.Label_3DSRegion.Margin = new System.Windows.Forms.Padding(0); + this.Label_3DSRegion.Name = "Label_3DSRegion"; + this.Label_3DSRegion.Size = new System.Drawing.Size(104, 24); + this.Label_3DSRegion.TabIndex = 18; + this.Label_3DSRegion.Text = "3DS Region:"; + this.Label_3DSRegion.TextAlign = System.Drawing.ContentAlignment.MiddleRight; + // + // CB_3DSReg + // + this.CB_3DSReg.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; + this.CB_3DSReg.FormattingEnabled = true; + this.CB_3DSReg.Location = new System.Drawing.Point(104, 0); + this.CB_3DSReg.Margin = new System.Windows.Forms.Padding(0); + this.CB_3DSReg.Name = "CB_3DSReg"; + this.CB_3DSReg.Size = new System.Drawing.Size(126, 23); + this.CB_3DSReg.TabIndex = 23; + // + // FLP_Handler + // + this.FLP_Handler.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right))); + this.FLP_Handler.Controls.Add(this.L_CurrentHandler); + this.FLP_Handler.Controls.Add(this.CB_Handler); + this.FLP_Handler.Location = new System.Drawing.Point(0, 176); + this.FLP_Handler.Margin = new System.Windows.Forms.Padding(0, 16, 0, 8); + this.FLP_Handler.Name = "FLP_Handler"; + this.FLP_Handler.Size = new System.Drawing.Size(272, 24); + this.FLP_Handler.TabIndex = 49; + // + // L_CurrentHandler + // + this.L_CurrentHandler.Location = new System.Drawing.Point(0, 0); + this.L_CurrentHandler.Margin = new System.Windows.Forms.Padding(0); + this.L_CurrentHandler.Name = "L_CurrentHandler"; + this.L_CurrentHandler.Size = new System.Drawing.Size(128, 24); + this.L_CurrentHandler.TabIndex = 18; + this.L_CurrentHandler.Text = "Current Handler:"; + this.L_CurrentHandler.TextAlign = System.Drawing.ContentAlignment.MiddleRight; + // + // CB_Handler + // + this.CB_Handler.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; + this.CB_Handler.FormattingEnabled = true; + this.CB_Handler.Items.AddRange(new object[] { + "OT", + "HT"}); + this.CB_Handler.Location = new System.Drawing.Point(128, 0); + this.CB_Handler.Margin = new System.Windows.Forms.Padding(0); + this.CB_Handler.Name = "CB_Handler"; + this.CB_Handler.Size = new System.Drawing.Size(48, 23); + this.CB_Handler.TabIndex = 4; + this.CB_Handler.SelectedIndexChanged += new System.EventHandler(this.ChangeHandlerIndex); + // + // GB_nOT + // + this.FLP_OTMisc.SetFlowBreak(this.GB_nOT, true); + this.GB_nOT.Location = new System.Drawing.Point(56, 208); + this.GB_nOT.Margin = new System.Windows.Forms.Padding(56, 0, 0, 0); + this.GB_nOT.Name = "GB_nOT"; + this.GB_nOT.Size = new System.Drawing.Size(216, 24); + this.GB_nOT.TabIndex = 48; + this.GB_nOT.Text = "Latest (not OT) Handler"; + this.GB_nOT.TextAlign = System.Drawing.ContentAlignment.MiddleLeft; + // + // FLP_HT + // + this.FLP_HT.Controls.Add(this.Label_PrevOT); + this.FLP_HT.Controls.Add(this.TB_HT); + this.FLP_HT.Controls.Add(this.UC_HTGender); + this.FLP_HT.Location = new System.Drawing.Point(0, 232); + this.FLP_HT.Margin = new System.Windows.Forms.Padding(0); + this.FLP_HT.Name = "FLP_HT"; + this.FLP_HT.Size = new System.Drawing.Size(272, 24); + this.FLP_HT.TabIndex = 10; + // + // Label_PrevOT + // + this.Label_PrevOT.Location = new System.Drawing.Point(0, 0); + this.Label_PrevOT.Margin = new System.Windows.Forms.Padding(0); + this.Label_PrevOT.Name = "Label_PrevOT"; + this.Label_PrevOT.Size = new System.Drawing.Size(104, 24); + this.Label_PrevOT.TabIndex = 1; + this.Label_PrevOT.Text = "OT:"; + this.Label_PrevOT.TextAlign = System.Drawing.ContentAlignment.MiddleRight; + this.Label_PrevOT.Click += new System.EventHandler(this.ClickCT); + // + // TB_HT + // + this.TB_HT.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; + this.TB_HT.Location = new System.Drawing.Point(104, 0); + this.TB_HT.Margin = new System.Windows.Forms.Padding(0); + this.TB_HT.MaxLength = 12; + this.TB_HT.Name = "TB_HT"; + this.TB_HT.Size = new System.Drawing.Size(94, 23); + this.TB_HT.TabIndex = 2; + this.TB_HT.WordWrap = false; + this.TB_HT.TextChanged += new System.EventHandler(this.UpdateNotOT); + this.TB_HT.MouseDown += new System.Windows.Forms.MouseEventHandler(this.UpdateNicknameClick); + // + // UC_HTGender + // + this.UC_HTGender.AllowClick = true; + this.UC_HTGender.BackgroundImage = ((System.Drawing.Image)(resources.GetObject("UC_HTGender.BackgroundImage"))); + this.UC_HTGender.BackgroundImageLayout = System.Windows.Forms.ImageLayout.Center; + this.UC_HTGender.Gender = 0; + this.UC_HTGender.Location = new System.Drawing.Point(198, 0); + this.UC_HTGender.Margin = new System.Windows.Forms.Padding(0); + this.UC_HTGender.Name = "UC_HTGender"; + this.UC_HTGender.Size = new System.Drawing.Size(24, 24); + this.UC_HTGender.TabIndex = 3; + // + // FLP_HTLanguage + // + this.FLP_HTLanguage.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right))); + this.FLP_HTLanguage.Controls.Add(this.L_LanguageHT); + this.FLP_HTLanguage.Controls.Add(this.CB_HTLanguage); + this.FLP_HTLanguage.Location = new System.Drawing.Point(0, 256); + this.FLP_HTLanguage.Margin = new System.Windows.Forms.Padding(0); + this.FLP_HTLanguage.Name = "FLP_HTLanguage"; + this.FLP_HTLanguage.Size = new System.Drawing.Size(272, 24); + this.FLP_HTLanguage.TabIndex = 11; + // + // L_LanguageHT + // + this.L_LanguageHT.Location = new System.Drawing.Point(0, 0); + this.L_LanguageHT.Margin = new System.Windows.Forms.Padding(0); + this.L_LanguageHT.Name = "L_LanguageHT"; + this.L_LanguageHT.Size = new System.Drawing.Size(104, 24); + this.L_LanguageHT.TabIndex = 18; + this.L_LanguageHT.Text = "Language:"; + this.L_LanguageHT.TextAlign = System.Drawing.ContentAlignment.MiddleRight; + // + // CB_HTLanguage + // + this.CB_HTLanguage.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; + this.CB_HTLanguage.FormattingEnabled = true; + this.CB_HTLanguage.Location = new System.Drawing.Point(104, 0); + this.CB_HTLanguage.Margin = new System.Windows.Forms.Padding(0); + this.CB_HTLanguage.Name = "CB_HTLanguage"; + this.CB_HTLanguage.Size = new System.Drawing.Size(126, 23); + this.CB_HTLanguage.TabIndex = 4; + // + // FLP_ExtraBytes + // + this.FLP_ExtraBytes.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right))); + this.FLP_ExtraBytes.Controls.Add(this.L_ExtraBytes); + this.FLP_ExtraBytes.Controls.Add(this.CB_ExtraBytes); + this.FLP_ExtraBytes.Controls.Add(this.TB_ExtraByte); + this.FLP_ExtraBytes.Location = new System.Drawing.Point(0, 304); + this.FLP_ExtraBytes.Margin = new System.Windows.Forms.Padding(0, 24, 0, 8); + this.FLP_ExtraBytes.Name = "FLP_ExtraBytes"; + this.FLP_ExtraBytes.Size = new System.Drawing.Size(272, 24); + this.FLP_ExtraBytes.TabIndex = 20; + // + // L_ExtraBytes + // + this.L_ExtraBytes.Location = new System.Drawing.Point(0, 0); + this.L_ExtraBytes.Margin = new System.Windows.Forms.Padding(0); + this.L_ExtraBytes.Name = "L_ExtraBytes"; + this.L_ExtraBytes.Size = new System.Drawing.Size(128, 24); + this.L_ExtraBytes.TabIndex = 18; + this.L_ExtraBytes.Text = "Extra Bytes:"; + this.L_ExtraBytes.TextAlign = System.Drawing.ContentAlignment.MiddleRight; // // CB_ExtraBytes // this.CB_ExtraBytes.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; this.CB_ExtraBytes.FormattingEnabled = true; - this.CB_ExtraBytes.Location = new System.Drawing.Point(20, 18); + this.CB_ExtraBytes.Location = new System.Drawing.Point(128, 0); + this.CB_ExtraBytes.Margin = new System.Windows.Forms.Padding(0); this.CB_ExtraBytes.Name = "CB_ExtraBytes"; - this.CB_ExtraBytes.Size = new System.Drawing.Size(57, 21); + this.CB_ExtraBytes.Size = new System.Drawing.Size(64, 23); this.CB_ExtraBytes.TabIndex = 1; this.CB_ExtraBytes.SelectedIndexChanged += new System.EventHandler(this.UpdateExtraByteIndex); // - // GB_OT + // TB_ExtraByte // - this.GB_OT.Controls.Add(this.UC_OTGender); - this.GB_OT.Controls.Add(this.TID_Trainer); - this.GB_OT.Controls.Add(this.TB_OT); - this.GB_OT.Controls.Add(this.Label_OT); - this.GB_OT.Location = new System.Drawing.Point(40, 8); - this.GB_OT.Name = "GB_OT"; - this.GB_OT.Size = new System.Drawing.Size(190, 75); - this.GB_OT.TabIndex = 1; - this.GB_OT.TabStop = false; - this.GB_OT.Text = "Trainer Information"; + this.TB_ExtraByte.Location = new System.Drawing.Point(200, 0); + this.TB_ExtraByte.Margin = new System.Windows.Forms.Padding(8, 0, 0, 0); + this.TB_ExtraByte.Mask = "000"; + this.TB_ExtraByte.Name = "TB_ExtraByte"; + this.TB_ExtraByte.Size = new System.Drawing.Size(32, 23); + this.TB_ExtraByte.TabIndex = 2; + this.TB_ExtraByte.TextAlign = System.Windows.Forms.HorizontalAlignment.Center; + this.TB_ExtraByte.Validated += new System.EventHandler(this.UpdateExtraByteValue); // - // UC_OTGender + // L_HomeTracker // - this.UC_OTGender.AllowClick = true; - this.UC_OTGender.BackgroundImageLayout = System.Windows.Forms.ImageLayout.Center; - this.UC_OTGender.Gender = 0; - this.UC_OTGender.Location = new System.Drawing.Point(142, 48); - this.UC_OTGender.Margin = new System.Windows.Forms.Padding(3, 2, 2, 1); - this.UC_OTGender.Name = "UC_OTGender"; - this.UC_OTGender.Size = new System.Drawing.Size(18, 18); - this.UC_OTGender.TabIndex = 58; + this.L_HomeTracker.Location = new System.Drawing.Point(0, 336); + this.L_HomeTracker.Margin = new System.Windows.Forms.Padding(0); + this.L_HomeTracker.Name = "L_HomeTracker"; + this.L_HomeTracker.Size = new System.Drawing.Size(128, 24); + this.L_HomeTracker.TabIndex = 30; + this.L_HomeTracker.Text = "HOME Tracker:"; + this.L_HomeTracker.TextAlign = System.Drawing.ContentAlignment.MiddleRight; // - // TID_Trainer + // TB_HomeTracker // - this.TID_Trainer.Location = new System.Drawing.Point(13, 18); - this.TID_Trainer.Name = "TID_Trainer"; - this.TID_Trainer.Size = new System.Drawing.Size(178, 27); - this.TID_Trainer.TabIndex = 57; - // - // TB_OT - // - this.TB_OT.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; - this.TB_OT.Location = new System.Drawing.Point(46, 46); - this.TB_OT.MaxLength = 12; - this.TB_OT.Name = "TB_OT"; - this.TB_OT.Size = new System.Drawing.Size(94, 20); - this.TB_OT.TabIndex = 3; - this.TB_OT.MouseDown += new System.Windows.Forms.MouseEventHandler(this.UpdateNicknameClick); - // - // Label_OT - // - this.Label_OT.Location = new System.Drawing.Point(4, 48); - this.Label_OT.Name = "Label_OT"; - this.Label_OT.Size = new System.Drawing.Size(40, 13); - this.Label_OT.TabIndex = 5; - this.Label_OT.Text = "OT:"; - this.Label_OT.TextAlign = System.Drawing.ContentAlignment.MiddleRight; - this.Label_OT.Click += new System.EventHandler(this.ClickOT); + this.TB_HomeTracker.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; + this.TB_HomeTracker.Font = new System.Drawing.Font("Courier New", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); + this.TB_HomeTracker.Location = new System.Drawing.Point(128, 338); + this.TB_HomeTracker.Margin = new System.Windows.Forms.Padding(0, 2, 0, 0); + this.TB_HomeTracker.MaxLength = 16; + this.TB_HomeTracker.Name = "TB_HomeTracker"; + this.TB_HomeTracker.PlaceholderText = "0123456789ABCDEF"; + this.TB_HomeTracker.Size = new System.Drawing.Size(120, 20); + this.TB_HomeTracker.TabIndex = 31; + this.TB_HomeTracker.Validated += new System.EventHandler(this.Update_ID64); // // Label_EncryptionConstant // - this.Label_EncryptionConstant.Location = new System.Drawing.Point(1, 309); + this.Label_EncryptionConstant.Location = new System.Drawing.Point(0, 360); + this.Label_EncryptionConstant.Margin = new System.Windows.Forms.Padding(0); this.Label_EncryptionConstant.Name = "Label_EncryptionConstant"; - this.Label_EncryptionConstant.Size = new System.Drawing.Size(130, 16); - this.Label_EncryptionConstant.TabIndex = 1; + this.Label_EncryptionConstant.Size = new System.Drawing.Size(128, 24); + this.Label_EncryptionConstant.TabIndex = 32; this.Label_EncryptionConstant.Text = "Encryption Constant:"; this.Label_EncryptionConstant.TextAlign = System.Drawing.ContentAlignment.MiddleRight; // - // L_FormArgument + // TB_EC // - this.L_FormArgument.Location = new System.Drawing.Point(0, 21); - this.L_FormArgument.Margin = new System.Windows.Forms.Padding(0); - this.L_FormArgument.Name = "L_FormArgument"; - this.L_FormArgument.Size = new System.Drawing.Size(98, 21); - this.L_FormArgument.TabIndex = 12; - this.L_FormArgument.Text = "Form Argument:"; - this.L_FormArgument.TextAlign = System.Drawing.ContentAlignment.MiddleRight; + this.TB_EC.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; + this.TB_EC.Font = new System.Drawing.Font("Courier New", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); + this.TB_EC.Location = new System.Drawing.Point(128, 362); + this.TB_EC.Margin = new System.Windows.Forms.Padding(0, 2, 0, 0); + this.TB_EC.MaxLength = 8; + this.TB_EC.Name = "TB_EC"; + this.TB_EC.PlaceholderText = "12345678"; + this.TB_EC.Size = new System.Drawing.Size(64, 20); + this.TB_EC.TabIndex = 33; + this.TB_EC.Validated += new System.EventHandler(this.Update_ID); + // + // BTN_RerollEC + // + this.BTN_RerollEC.Font = new System.Drawing.Font("Microsoft Sans Serif", 6.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); + this.BTN_RerollEC.Location = new System.Drawing.Point(192, 360); + this.BTN_RerollEC.Margin = new System.Windows.Forms.Padding(0); + this.BTN_RerollEC.Name = "BTN_RerollEC"; + this.BTN_RerollEC.Size = new System.Drawing.Size(56, 24); + this.BTN_RerollEC.TabIndex = 34; + this.BTN_RerollEC.Text = "Reroll"; + this.BTN_RerollEC.UseVisualStyleBackColor = true; + this.BTN_RerollEC.Click += new System.EventHandler(this.UpdateRandomEC); + // + // TC_Editor + // + this.TC_Editor.Alignment = System.Windows.Forms.TabAlignment.Right; + this.TC_Editor.Controls.Add(this.Tab_Main); + this.TC_Editor.Controls.Add(this.Tab_Met); + this.TC_Editor.Controls.Add(this.Tab_Stats); + this.TC_Editor.Controls.Add(this.Tab_Moves); + this.TC_Editor.Controls.Add(this.Tab_Cosmetic); + this.TC_Editor.Controls.Add(this.Tab_OTMisc); + this.TC_Editor.DrawMode = System.Windows.Forms.TabDrawMode.OwnerDrawFixed; + this.TC_Editor.ItemSize = new System.Drawing.Size(40, 96); + this.TC_Editor.Location = new System.Drawing.Point(0, 56); + this.TC_Editor.Margin = new System.Windows.Forms.Padding(0); + this.TC_Editor.Multiline = true; + this.TC_Editor.Name = "TC_Editor"; + this.TC_Editor.Padding = new System.Drawing.Point(0, 0); + this.TC_Editor.SelectedIndex = 0; + this.TC_Editor.Size = new System.Drawing.Size(96, 320); + this.TC_Editor.SizeMode = System.Windows.Forms.TabSizeMode.Fixed; + this.TC_Editor.TabIndex = 2; + this.TC_Editor.SelectedIndexChanged += new System.EventHandler(this.ChangeSelectedTabIndex); + // + // Tab_Main + // + this.Tab_Main.Location = new System.Drawing.Point(4, 4); + this.Tab_Main.Margin = new System.Windows.Forms.Padding(0); + this.Tab_Main.Name = "Tab_Main"; + this.Tab_Main.Size = new System.Drawing.Size(0, 312); + this.Tab_Main.TabIndex = 0; + this.Tab_Main.Text = "Main"; + this.Tab_Main.UseVisualStyleBackColor = true; + // + // Tab_Met + // + this.Tab_Met.Location = new System.Drawing.Point(4, 4); + this.Tab_Met.Margin = new System.Windows.Forms.Padding(0); + this.Tab_Met.Name = "Tab_Met"; + this.Tab_Met.Size = new System.Drawing.Size(0, 312); + this.Tab_Met.TabIndex = 1; + this.Tab_Met.Text = "Met"; + this.Tab_Met.UseVisualStyleBackColor = true; + // + // Tab_Stats + // + this.Tab_Stats.Location = new System.Drawing.Point(4, 4); + this.Tab_Stats.Margin = new System.Windows.Forms.Padding(0); + this.Tab_Stats.Name = "Tab_Stats"; + this.Tab_Stats.Size = new System.Drawing.Size(0, 312); + this.Tab_Stats.TabIndex = 2; + this.Tab_Stats.Text = "Stats"; + this.Tab_Stats.UseVisualStyleBackColor = true; + // + // Tab_Moves + // + this.Tab_Moves.Location = new System.Drawing.Point(4, 4); + this.Tab_Moves.Margin = new System.Windows.Forms.Padding(0); + this.Tab_Moves.Name = "Tab_Moves"; + this.Tab_Moves.Size = new System.Drawing.Size(0, 312); + this.Tab_Moves.TabIndex = 3; + this.Tab_Moves.Text = "Moves"; + this.Tab_Moves.UseVisualStyleBackColor = true; + // + // Tab_Cosmetic + // + this.Tab_Cosmetic.Location = new System.Drawing.Point(4, 4); + this.Tab_Cosmetic.Name = "Tab_Cosmetic"; + this.Tab_Cosmetic.Size = new System.Drawing.Size(0, 312); + this.Tab_Cosmetic.TabIndex = 5; + this.Tab_Cosmetic.Text = "Cosmetic"; + this.Tab_Cosmetic.UseVisualStyleBackColor = true; + // + // Tab_OTMisc + // + this.Tab_OTMisc.Location = new System.Drawing.Point(4, 4); + this.Tab_OTMisc.Margin = new System.Windows.Forms.Padding(0); + this.Tab_OTMisc.Name = "Tab_OTMisc"; + this.Tab_OTMisc.Size = new System.Drawing.Size(0, 312); + this.Tab_OTMisc.TabIndex = 4; + this.Tab_OTMisc.Text = "OT/Misc"; + this.Tab_OTMisc.UseVisualStyleBackColor = true; // // PKMEditor // this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Inherit; - this.Controls.Add(this.tabMain); + this.Controls.Add(this.TC_Editor); + this.Controls.Add(this.Hidden_TC); this.Name = "PKMEditor"; - this.Size = new System.Drawing.Size(315, 565); - this.tabMain.ResumeLayout(false); - this.Tab_Main.ResumeLayout(false); + this.Size = new System.Drawing.Size(400, 400); + this.Hidden_TC.ResumeLayout(false); + this.Hidden_Main.ResumeLayout(false); this.FLP_Main.ResumeLayout(false); this.FLP_PID.ResumeLayout(false); this.FLP_PIDLeft.ResumeLayout(false); - this.FLP_PIDLeft.PerformLayout(); ((System.ComponentModel.ISupportInitialize)(this.PB_ShinyStar)).EndInit(); ((System.ComponentModel.ISupportInitialize)(this.PB_ShinySquare)).EndInit(); this.FLP_PIDRight.ResumeLayout(false); @@ -2875,9 +2947,6 @@ namespace PKHeX.WinForms.Controls this.FLP_EggPKRSRight.PerformLayout(); this.FLP_PKRS.ResumeLayout(false); this.FLP_PKRSRight.ResumeLayout(false); - this.FLP_Country.ResumeLayout(false); - this.FLP_SubRegion.ResumeLayout(false); - this.FLP_3DSRegion.ResumeLayout(false); this.FLP_NSparkle.ResumeLayout(false); this.FLP_NSparkle.PerformLayout(); this.FLP_ShadowID.ResumeLayout(false); @@ -2885,11 +2954,9 @@ namespace PKHeX.WinForms.Controls this.FLP_Purification.ResumeLayout(false); this.FLP_Purification.PerformLayout(); ((System.ComponentModel.ISupportInitialize)(this.NUD_Purification)).EndInit(); - this.FLP_ShinyLeaf.ResumeLayout(false); this.FLP_CatchRate.ResumeLayout(false); - this.FLP_SizeCP.ResumeLayout(false); - this.Tab_Met.ResumeLayout(false); - this.Tab_Met.PerformLayout(); + this.Hidden_Met.ResumeLayout(false); + this.Hidden_Met.PerformLayout(); this.GB_EggConditions.ResumeLayout(false); this.FLP_Met.ResumeLayout(false); this.FLP_OriginGame.ResumeLayout(false); @@ -2906,30 +2973,23 @@ namespace PKHeX.WinForms.Controls this.FLP_ObedienceLevel.PerformLayout(); this.FLP_GroundTile.ResumeLayout(false); this.FLP_TimeOfDay.ResumeLayout(false); - this.Tab_Stats.ResumeLayout(false); - this.Tab_Attacks.ResumeLayout(false); - this.Tab_Attacks.PerformLayout(); + this.Hidden_Stats.ResumeLayout(false); + this.Hidden_Moves.ResumeLayout(false); + this.Hidden_Moves.PerformLayout(); this.FLP_MoveFlags.ResumeLayout(false); - ((System.ComponentModel.ISupportInitialize)(this.PB_WarnMove4)).EndInit(); - ((System.ComponentModel.ISupportInitialize)(this.PB_WarnMove3)).EndInit(); - ((System.ComponentModel.ISupportInitialize)(this.PB_WarnMove2)).EndInit(); - ((System.ComponentModel.ISupportInitialize)(this.PB_WarnMove1)).EndInit(); this.GB_RelearnMoves.ResumeLayout(false); ((System.ComponentModel.ISupportInitialize)(this.PB_WarnRelearn4)).EndInit(); ((System.ComponentModel.ISupportInitialize)(this.PB_WarnRelearn3)).EndInit(); ((System.ComponentModel.ISupportInitialize)(this.PB_WarnRelearn2)).EndInit(); ((System.ComponentModel.ISupportInitialize)(this.PB_WarnRelearn1)).EndInit(); this.GB_CurrentMoves.ResumeLayout(false); - this.GB_CurrentMoves.PerformLayout(); - this.Tab_OTMisc.ResumeLayout(false); - this.Tab_OTMisc.PerformLayout(); - ((System.ComponentModel.ISupportInitialize)(this.PB_BattleVersion)).EndInit(); - ((System.ComponentModel.ISupportInitialize)(this.PB_Origin)).EndInit(); - ((System.ComponentModel.ISupportInitialize)(this.PB_Favorite)).EndInit(); + this.FLP_Moves.ResumeLayout(false); + this.Hidden_Cosmetic.ResumeLayout(false); + this.Hidden_Cosmetic.PerformLayout(); this.FLP_PKMEditors.ResumeLayout(false); this.FLP_PKMEditors.PerformLayout(); - this.GB_nOT.ResumeLayout(false); - this.GB_nOT.PerformLayout(); + this.FLP_CosmeticTop.ResumeLayout(false); + this.FLP_CosmeticTop.PerformLayout(); this.GB_Markings.ResumeLayout(false); ((System.ComponentModel.ISupportInitialize)(this.PB_Mark6)).EndInit(); ((System.ComponentModel.ISupportInitialize)(this.PB_Mark3)).EndInit(); @@ -2939,18 +2999,33 @@ namespace PKHeX.WinForms.Controls ((System.ComponentModel.ISupportInitialize)(this.PB_MarkShiny)).EndInit(); ((System.ComponentModel.ISupportInitialize)(this.PB_Mark1)).EndInit(); ((System.ComponentModel.ISupportInitialize)(this.PB_Mark4)).EndInit(); - this.GB_ExtraBytes.ResumeLayout(false); - this.GB_ExtraBytes.PerformLayout(); - this.GB_OT.ResumeLayout(false); - this.GB_OT.PerformLayout(); + this.FLP_BigMarkings.ResumeLayout(false); + ((System.ComponentModel.ISupportInitialize)(this.PB_Favorite)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.PB_Origin)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.PB_BattleVersion)).EndInit(); + this.Hidden_OTMisc.ResumeLayout(false); + this.FLP_OTMisc.ResumeLayout(false); + this.FLP_OTMisc.PerformLayout(); + this.FLP_OT.ResumeLayout(false); + this.FLP_OT.PerformLayout(); + this.FLP_Country.ResumeLayout(false); + this.FLP_SubRegion.ResumeLayout(false); + this.FLP_3DSRegion.ResumeLayout(false); + this.FLP_Handler.ResumeLayout(false); + this.FLP_HT.ResumeLayout(false); + this.FLP_HT.PerformLayout(); + this.FLP_HTLanguage.ResumeLayout(false); + this.FLP_ExtraBytes.ResumeLayout(false); + this.FLP_ExtraBytes.PerformLayout(); + this.TC_Editor.ResumeLayout(false); this.ResumeLayout(false); } #endregion - private System.Windows.Forms.TabControl tabMain; - private System.Windows.Forms.TabPage Tab_Main; + private System.Windows.Forms.TabControl Hidden_TC; + private System.Windows.Forms.TabPage Hidden_Main; private System.Windows.Forms.FlowLayoutPanel FLP_Main; private System.Windows.Forms.FlowLayoutPanel FLP_PID; private System.Windows.Forms.FlowLayoutPanel FLP_PIDLeft; @@ -2966,7 +3041,7 @@ namespace PKHeX.WinForms.Controls private System.Windows.Forms.ComboBox CB_Species; private System.Windows.Forms.FlowLayoutPanel FLP_Nickname; private System.Windows.Forms.FlowLayoutPanel FLP_NicknameLeft; - private System.Windows.Forms.CheckBox CHK_Nicknamed; + private System.Windows.Forms.CheckBox CHK_NicknamedFlag; private System.Windows.Forms.TextBox TB_Nickname; private System.Windows.Forms.FlowLayoutPanel FLP_EXPLevel; private System.Windows.Forms.Label Label_EXP; @@ -3027,7 +3102,7 @@ namespace PKHeX.WinForms.Controls private System.Windows.Forms.Label L_HeartGauge; private System.Windows.Forms.NumericUpDown NUD_Purification; private System.Windows.Forms.CheckBox CHK_Shadow; - private System.Windows.Forms.TabPage Tab_Met; + private System.Windows.Forms.TabPage Hidden_Met; private System.Windows.Forms.CheckBox CHK_AsEgg; private System.Windows.Forms.GroupBox GB_EggConditions; private System.Windows.Forms.ComboBox CB_EggLocation; @@ -3039,7 +3114,6 @@ namespace PKHeX.WinForms.Controls private System.Windows.Forms.Label Label_OriginGame; private System.Windows.Forms.ComboBox CB_GameOrigin; private System.Windows.Forms.FlowLayoutPanel FLP_MetLocation; - private System.Windows.Forms.Label Label_MetLocation; private System.Windows.Forms.ComboBox CB_MetLocation; private System.Windows.Forms.FlowLayoutPanel FLP_Ball; private System.Windows.Forms.FlowLayoutPanel FLP_BallLeft; @@ -3059,12 +3133,8 @@ namespace PKHeX.WinForms.Controls private System.Windows.Forms.FlowLayoutPanel FLP_TimeOfDay; private System.Windows.Forms.Label L_MetTimeOfDay; private System.Windows.Forms.ComboBox CB_MetTimeOfDay; - private System.Windows.Forms.TabPage Tab_Stats; - private System.Windows.Forms.TabPage Tab_Attacks; - private System.Windows.Forms.PictureBox PB_WarnMove4; - private System.Windows.Forms.PictureBox PB_WarnMove3; - private System.Windows.Forms.PictureBox PB_WarnMove2; - private System.Windows.Forms.PictureBox PB_WarnMove1; + private System.Windows.Forms.TabPage Hidden_Stats; + private System.Windows.Forms.TabPage Hidden_Moves; private System.Windows.Forms.GroupBox GB_RelearnMoves; private System.Windows.Forms.PictureBox PB_WarnRelearn4; private System.Windows.Forms.PictureBox PB_WarnRelearn3; @@ -3075,27 +3145,14 @@ namespace PKHeX.WinForms.Controls private System.Windows.Forms.ComboBox CB_RelearnMove2; private System.Windows.Forms.ComboBox CB_RelearnMove1; private System.Windows.Forms.GroupBox GB_CurrentMoves; - private System.Windows.Forms.MaskedTextBox TB_PP4; - private System.Windows.Forms.MaskedTextBox TB_PP3; - private System.Windows.Forms.MaskedTextBox TB_PP2; - private System.Windows.Forms.MaskedTextBox TB_PP1; private System.Windows.Forms.Label Label_CurPP; private System.Windows.Forms.Label Label_PPups; - private System.Windows.Forms.ComboBox CB_PPu4; - private System.Windows.Forms.ComboBox CB_PPu3; - private System.Windows.Forms.ComboBox CB_PPu2; - private System.Windows.Forms.ComboBox CB_Move4; - private System.Windows.Forms.ComboBox CB_PPu1; - private System.Windows.Forms.ComboBox CB_Move3; - private System.Windows.Forms.ComboBox CB_Move2; - private System.Windows.Forms.ComboBox CB_Move1; - private System.Windows.Forms.TabPage Tab_OTMisc; + private System.Windows.Forms.TabPage Hidden_OTMisc; private System.Windows.Forms.FlowLayoutPanel FLP_PKMEditors; private System.Windows.Forms.Button BTN_Ribbons; private System.Windows.Forms.Button BTN_Medals; private System.Windows.Forms.Button BTN_History; private System.Windows.Forms.TextBox TB_EC; - private System.Windows.Forms.GroupBox GB_nOT; private System.Windows.Forms.TextBox TB_HT; private System.Windows.Forms.Label Label_PrevOT; private System.Windows.Forms.Button BTN_RerollEC; @@ -3108,34 +3165,23 @@ namespace PKHeX.WinForms.Controls private System.Windows.Forms.PictureBox PB_MarkShiny; private System.Windows.Forms.PictureBox PB_Mark1; private System.Windows.Forms.PictureBox PB_Mark4; - private System.Windows.Forms.GroupBox GB_ExtraBytes; private System.Windows.Forms.MaskedTextBox TB_ExtraByte; private System.Windows.Forms.ComboBox CB_ExtraBytes; - private System.Windows.Forms.GroupBox GB_OT; private System.Windows.Forms.TextBox TB_OT; private System.Windows.Forms.Label Label_OT; private System.Windows.Forms.Label Label_EncryptionConstant; - private System.Windows.Forms.FlowLayoutPanel FLP_ShinyLeaf; - private System.Windows.Forms.Label L_ShinyLeaf; private Controls.ShinyLeaf ShinyLeaf; - private ContestStat Contest; - private StatEditor Stats; - private TrainerID TID_Trainer; private System.Windows.Forms.FlowLayoutPanel FLP_CatchRate; private System.Windows.Forms.Label L_CatchRate; private CatchRate CR_PK1; - private System.Windows.Forms.FlowLayoutPanel FLP_SizeCP; private SizeCP SizeCP; private System.Windows.Forms.PictureBox PB_Favorite; - private System.Windows.Forms.ToolTip SpeciesIDTip; - private System.Windows.Forms.ToolTip NatureTip; - private System.Windows.Forms.ToolTip Tip3; private System.Windows.Forms.FlowLayoutPanel FLP_OriginalNature; private System.Windows.Forms.Label L_OriginalNature; private System.Windows.Forms.ComboBox CB_StatNature; private System.Windows.Forms.PictureBox PB_Origin; private System.Windows.Forms.ComboBox CB_HTLanguage; - private System.Windows.Forms.Button B_Records; + private System.Windows.Forms.Button B_RelearnFlags; private System.Windows.Forms.FlowLayoutPanel FLP_Form; private System.Windows.Forms.FlowLayoutPanel FLP_FormLeft; private System.Windows.Forms.FlowLayoutPanel FLP_FormRight; @@ -3158,5 +3204,37 @@ namespace PKHeX.WinForms.Controls private System.Windows.Forms.Label L_ObedienceLevel; private System.Windows.Forms.MaskedTextBox TB_ObedienceLevel; private System.Windows.Forms.Label L_FormArgument; + private System.Windows.Forms.Label Label_MetLocation; + private System.Windows.Forms.FlowLayoutPanel FLP_Moves; + private MoveChoice MC_Move1; + private MoveChoice MC_Move2; + private MoveChoice MC_Move3; + private MoveChoice MC_Move4; + private PKHeX.WinForms.Controls.VerticalTabControlEntityEditor TC_Editor; + private System.Windows.Forms.TabPage Tab_Main; + private System.Windows.Forms.TabPage Tab_Met; + private System.Windows.Forms.TabPage Tab_Stats; + private System.Windows.Forms.TabPage Tab_Moves; + private System.Windows.Forms.TabPage Tab_OTMisc; + private System.Windows.Forms.TabPage Hidden_Cosmetic; + private System.Windows.Forms.TabPage Tab_Cosmetic; + private System.Windows.Forms.FlowLayoutPanel FLP_CosmeticTop; + private System.Windows.Forms.FlowLayoutPanel FLP_BigMarkings; + private StatEditor Stats; + private ContestStat Contest; + private TrainerID TID_Trainer; + private System.Windows.Forms.Label CHK_Nicknamed; + private System.Windows.Forms.FlowLayoutPanel FLP_OTMisc; + private System.Windows.Forms.Label GB_OT; + private System.Windows.Forms.FlowLayoutPanel FLP_OT; + private System.Windows.Forms.Label GB_nOT; + private System.Windows.Forms.FlowLayoutPanel FLP_HT; + private System.Windows.Forms.FlowLayoutPanel FLP_HTLanguage; + private System.Windows.Forms.Label L_LanguageHT; + private System.Windows.Forms.FlowLayoutPanel FLP_ExtraBytes; + private System.Windows.Forms.Label L_ExtraBytes; + private System.Windows.Forms.FlowLayoutPanel FLP_Handler; + private System.Windows.Forms.Label L_CurrentHandler; + private System.Windows.Forms.ComboBox CB_Handler; } } diff --git a/PKHeX.WinForms/Controls/PKM Editor/PKMEditor.cs b/PKHeX.WinForms/Controls/PKM Editor/PKMEditor.cs index 814acd731..d51fe70df 100644 --- a/PKHeX.WinForms/Controls/PKM Editor/PKMEditor.cs +++ b/PKHeX.WinForms/Controls/PKM Editor/PKMEditor.cs @@ -16,6 +16,9 @@ namespace PKHeX.WinForms.Controls; public sealed partial class PKMEditor : UserControl, IMainEditor { public bool IsInitialized { get; private set; } + private readonly ToolTip SpeciesIDTip = new(); + private readonly ToolTip NatureTip = new(); + private readonly ToolTip Tip3 = new(); public PKMEditor() { @@ -31,21 +34,18 @@ public sealed partial class PKMEditor : UserControl, IMainEditor TB_Nickname.Font = TB_OT.Font = TB_HT.Font = font; // Commonly reused Control arrays - Moves = new[] { CB_Move1, CB_Move2, CB_Move3, CB_Move4 }; + Moves = new[] { MC_Move1, MC_Move2, MC_Move3, MC_Move4 }; Relearn = new[] { CB_RelearnMove1, CB_RelearnMove2, CB_RelearnMove3, CB_RelearnMove4 }; - PPUps = new[] { CB_PPu1, CB_PPu2, CB_PPu3, CB_PPu4 }; - MovePP = new[] { TB_PP1, TB_PP2, TB_PP3, TB_PP4 }; Markings = new[] { PB_Mark1, PB_Mark2, PB_Mark3, PB_Mark4, PB_Mark5, PB_Mark6 }; // Legality Indicators relearnPB = new[] { PB_WarnRelearn1, PB_WarnRelearn2, PB_WarnRelearn3, PB_WarnRelearn4 }; - movePB = new[] { PB_WarnMove1, PB_WarnMove2, PB_WarnMove3, PB_WarnMove4 }; // Validation of incompletely entered data fields bool Criteria(Control c) => c.BackColor == Draw.InvalidSelection && c is ComboBox { Items.Count: not 0 }; ValidatedControls = new ValidationRequiredSet[] { - new(Moves, _ => true, Criteria), + new(Moves, _ => true, z => Criteria(((MoveChoice)z).CB_Move)), new(new[] {CB_Species}, _ => true, Criteria), new(new[] {CB_HeldItem}, pk => pk.Format >= 2, Criteria), new(new[] {CB_Ability, CB_Nature, CB_MetLocation, CB_Ball}, pk => pk.Format >= 3, Criteria), @@ -58,6 +58,18 @@ public sealed partial class PKMEditor : UserControl, IMainEditor foreach (var c in WinFormsUtil.GetAllControlsOfType(this)) c.KeyDown += WinFormsUtil.RemoveDropCB; + foreach (var m in Moves) + { + m.CB_Move.KeyDown += WinFormsUtil.RemoveDropCB; + m.CB_PPUps.KeyDown += WinFormsUtil.RemoveDropCB; + m.CB_PPUps.SelectedIndexChanged += (_, _) => m.HealPP(Entity); + m.CB_Move.DrawItem += ValidateMovePaint; + m.CB_Move.DropDown += ValidateMoveDropDown; + m.CB_Move.MeasureItem += MeasureDropDownHeight; + m.CB_Move.SelectedIndexChanged += ValidateMove; + m.CB_Move.Leave += ValidateComboBox2; + m.CB_Move.Validating += ValidateComboBox; + } Stats.MainEditor = this; LoadShowdownSet = LoadShowdownSetDefault; @@ -98,7 +110,7 @@ public sealed partial class PKMEditor : UserControl, IMainEditor CB_GroundTile, CB_GameOrigin, CB_BattleVersion, CB_Ability, CB_MetLocation, CB_EggLocation, CB_Language, CB_HTLanguage, CB_AlphaMastered, }; - foreach (var cb in cbs.Concat(Moves.Concat(Relearn))) + foreach (var cb in cbs.Concat(Relearn)) cb.InitializeBinding(); IsInitialized = true; @@ -180,13 +192,13 @@ public sealed partial class PKMEditor : UserControl, IMainEditor public event ReturnSAVEventHandler SaveFileRequested = null!; public delegate SaveFile ReturnSAVEventHandler(object sender, EventArgs e); - private readonly PictureBox[] movePB, relearnPB; + private readonly PictureBox[] relearnPB; public SaveFile RequestSaveFile => SaveFileRequested.Invoke(this, EventArgs.Empty); public bool PKMIsUnsaved => FieldsLoaded && LastData.Any(b => b != 0) && !LastData.SequenceEqual(CurrentPKM.Data); - private readonly ComboBox[] Moves, Relearn, PPUps; + private readonly MoveChoice[] Moves; + private readonly ComboBox[] Relearn; private readonly ValidationRequiredSet[] ValidatedControls; - private readonly MaskedTextBox[] MovePP; private readonly PictureBox[] Markings; private bool forceValidation; @@ -222,11 +234,11 @@ public sealed partial class PKMEditor : UserControl, IMainEditor } if (cb != null) - tabMain.SelectedTab = WinFormsUtil.FindFirstControlOfType(cb); + Hidden_TC.SelectedTab = WinFormsUtil.FindFirstControlOfType(cb); else if (!Stats.Valid) - tabMain.SelectedTab = Tab_Stats; + Hidden_TC.SelectedTab = Hidden_Stats; else if (WinFormsUtil.GetIndex(CB_Species) == 0 && !HaX) // can't set an empty slot... - tabMain.SelectedTab = Tab_Main; + Hidden_TC.SelectedTab = Hidden_Main; else return true; @@ -265,11 +277,11 @@ public sealed partial class PKMEditor : UserControl, IMainEditor private void SetPKMFormatExtraBytes(PKM pk) { var extraBytes = pk.ExtraBytes; - GB_ExtraBytes.Visible = GB_ExtraBytes.Enabled = extraBytes.Count != 0; + FLP_ExtraBytes.Visible = FLP_ExtraBytes.Enabled = extraBytes.Count != 0; CB_ExtraBytes.Items.Clear(); foreach (var b in extraBytes) CB_ExtraBytes.Items.Add($"0x{b:X2}"); - if (GB_ExtraBytes.Enabled) + if (FLP_ExtraBytes.Enabled) CB_ExtraBytes.SelectedIndex = 0; } @@ -278,7 +290,7 @@ public sealed partial class PKMEditor : UserControl, IMainEditor private void LoadFieldsFromPKM(PKM pk, bool focus = true, bool skipConversionCheck = true) { if (focus) - Tab_Main.Focus(); + Hidden_Main.Focus(); if (!skipConversionCheck && !EntityConverter.TryMakePKMCompatible(pk, Entity, out var c, out pk)) { @@ -316,7 +328,7 @@ public sealed partial class PKMEditor : UserControl, IMainEditor LastData = PreparePKM().Data; } - public void UpdateLegality(LegalityAnalysis? la = null, bool skipMoveRepop = false) + public void UpdateLegality(LegalityAnalysis? la = null, UpdateLegalityArgs args = 0) { if (!FieldsLoaded) return; @@ -324,7 +336,7 @@ public sealed partial class PKMEditor : UserControl, IMainEditor Legality = la ?? new LegalityAnalysis(Entity, RequestSaveFile.Personal); if (!Legality.Parsed || HaX || Entity.Species == 0) { - PB_WarnMove1.Visible = PB_WarnMove2.Visible = PB_WarnMove3.Visible = PB_WarnMove4.Visible = false; + MC_Move1.HideLegality = MC_Move2.HideLegality = MC_Move3.HideLegality = MC_Move4.HideLegality = true; PB_WarnRelearn1.Visible = PB_WarnRelearn2.Visible = PB_WarnRelearn3.Visible = PB_WarnRelearn4.Visible = false; LegalityChanged?.Invoke(Legality.Valid, EventArgs.Empty); return; @@ -334,11 +346,7 @@ public sealed partial class PKMEditor : UserControl, IMainEditor var info = Legality.Info; var moves = info.Moves; for (int i = 0; i < 4; i++) - { - var pb = movePB[i]; - pb.Visible = true; - pb.Image = GetMoveImage(!moves[i].Valid, Entity, i); - } + Moves[i].UpdateLegality(moves[i], Entity, i); if (Entity.Format >= 6) { @@ -347,7 +355,7 @@ public sealed partial class PKMEditor : UserControl, IMainEditor relearnPB[i].Visible = !relearn[i].Valid; } - if (skipMoveRepop) + if (args.HasFlag(UpdateLegalityArgs.SkipMoveRepopulation)) return; // Resort moves FieldsLoaded = false; @@ -356,16 +364,6 @@ public sealed partial class PKMEditor : UserControl, IMainEditor LegalityChanged?.Invoke(Legality.Valid, EventArgs.Empty); } - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private static Bitmap? GetMoveImage(bool isIllegal, PKM pk, int index) - { - if (isIllegal) - return Resources.warn; - if (pk.Format >= 8 && MoveInfo.GetDummiedMovesHashSet(pk.Context).Contains(pk.GetMove(index))) - return Resources.hint; - return null; - } - public void UpdateUnicode(IReadOnlyList symbols) { gendersymbols = symbols; @@ -479,13 +477,12 @@ public sealed partial class PKMEditor : UserControl, IMainEditor bool tmp = FieldsLoaded; FieldsLoaded = false; - CB_Ability.DataSource = GameInfo.FilteredSources.GetAbilityList(Entity); - CB_Ability.SelectedIndex = GetSafeIndex(CB_Ability, abil); // restore original index if available + var items = GameInfo.FilteredSources.GetAbilityList(Entity); + CB_Ability.DataSource = items; + CB_Ability.SelectedIndex = Math.Clamp(abil, 0, items.Count - 1); // restore original index if available FieldsLoaded = tmp; } - private static int GetSafeIndex(ComboBox cb, int index) => Math.Max(0, Math.Min(cb.Items.Count - 1, index)); - private void UpdateIsShiny() { // Set the Controls @@ -603,8 +600,8 @@ public sealed partial class PKMEditor : UserControl, IMainEditor private void ClickPP(object sender, EventArgs e) { - for (int i = 0; i < MovePP.Length; i++) - RefreshMovePP(i); + foreach (var cb in Moves) + cb.HealPP(Entity); } private void ClickPPUps(object sender, EventArgs e) @@ -612,20 +609,13 @@ public sealed partial class PKMEditor : UserControl, IMainEditor bool min = (ModifierKeys & Keys.Control) != 0 || !Legal.IsPPUpAvailable(Entity); if (min) { - CB_PPu1.SelectedIndex = CB_PPu2.SelectedIndex = CB_PPu3.SelectedIndex = CB_PPu4.SelectedIndex = 0; + MC_Move1.PPUps = MC_Move2.PPUps = MC_Move3.PPUps = MC_Move4.PPUps = 0; return; } - - static int GetValue(ListControl cb) - { - ushort move = (ushort)WinFormsUtil.GetIndex(cb); - return Legal.IsPPUpAvailable(move) ? 3 : 0; - } - CB_PPu1.SelectedIndex = GetValue(CB_Move1); - CB_PPu2.SelectedIndex = GetValue(CB_Move2); - CB_PPu3.SelectedIndex = GetValue(CB_Move3); - CB_PPu4.SelectedIndex = GetValue(CB_Move4); + static int GetValue(ushort move) => Legal.IsPPUpAvailable(move) ? 3 : 0; + foreach (var cb in Moves) + cb.PPUps = GetValue(cb.SelectedMove); } private void ClickMarking(object sender, EventArgs e) @@ -666,15 +656,13 @@ public sealed partial class PKMEditor : UserControl, IMainEditor CB_Ball.SelectedValue = frm.BallChoice; } - private void ClickShinyLeaf(object sender, EventArgs e) => ShinyLeaf.CheckAll(ModifierKeys != Keys.Control); - private void ClickMetLocation(object sender, EventArgs e) { if (HaX) return; Entity = PreparePKM(); - UpdateLegality(skipMoveRepop: true); + UpdateLegality(args: UpdateLegalityArgs.SkipMoveRepopulation); if (Legality.Valid) return; if (!SetSuggestedMetLocation()) @@ -689,12 +677,23 @@ public sealed partial class PKMEditor : UserControl, IMainEditor if (!GB_nOT.Visible) return; + int handler = 0; if (sender == GB_OT) - Entity.CurrentHandler = 0; + handler = 0; else if (TB_HT.Text.Length > 0) - Entity.CurrentHandler = 1; - UpadteHandlingTrainerBackground(Entity.CurrentHandler); + handler = 1; + UpdateHandlerSelected(handler); + } + private void ChangeHandlerIndex(object sender, EventArgs e) + { + UpdateHandlerSelected(CB_Handler.SelectedIndex & 1); + } + + private void UpdateHandlerSelected(int handler) + { + Entity.CurrentHandler = handler; + UpadteHandlingTrainerBackground(Entity.CurrentHandler); ReloadToFriendshipTextBox(Entity); } @@ -710,7 +709,7 @@ public sealed partial class PKMEditor : UserControl, IMainEditor private void ClickMoves(object? sender, EventArgs e) { - UpdateLegality(skipMoveRepop: true); + UpdateLegality(args: UpdateLegalityArgs.SkipMoveRepopulation); if (sender == GB_CurrentMoves) { bool random = ModifierKeys == Keys.Control; @@ -831,7 +830,7 @@ public sealed partial class PKMEditor : UserControl, IMainEditor if (encounter.HasGroundTile(Entity.Format)) CB_GroundTile.SelectedValue = (int)encounter.GetSuggestedGroundTile(); - if (Entity.Gen6 && Entity.WasEgg && ModifyPKM) + if (Entity is { Gen6: true, WasEgg: true } && ModifyPKM) Entity.SetHatchMemory6(); } @@ -1010,37 +1009,6 @@ public sealed partial class PKMEditor : UserControl, IMainEditor L_FormArgument.Visible = FA_Form.LoadArgument(f, Entity.Species, Entity.Form, Entity.Format); } - private void UpdatePP(object sender, EventArgs e) - { - if (sender is not ComboBox cb) - return; - int index = Array.IndexOf(Moves, cb); - if (index < 0) - index = Array.IndexOf(PPUps, cb); - if (index < 0) - return; - - RefreshMovePP(index); - } - - private void RefreshMovePP(int index) - { - var moveCB = Moves[index]; - var ppText = MovePP[index]; - var ppUps = PPUps[index]; - int move = WinFormsUtil.GetIndex(moveCB); - if (move <= 0) - { - ppUps.SelectedIndex = 0; - ppText.Text = 0.ToString(); - } - else - { - int ppUpCount = ppUps.SelectedIndex; - ppText.Text = Entity.GetMovePP((ushort)move, ppUpCount).ToString(); - } - } - private void UpdatePKRSstrain(object sender, EventArgs e) { // Change the PKRS Days to the legal bounds. @@ -1157,7 +1125,7 @@ public sealed partial class PKMEditor : UserControl, IMainEditor UC_Gender.Gender = Entity.GetSaneGender(); // If species changes and no nickname, set the new name == speciesName. - if (!CHK_Nicknamed.Checked) + if (!CHK_NicknamedFlag.Checked) UpdateNickname(sender, e); UpdateLegality(); @@ -1186,7 +1154,7 @@ public sealed partial class PKMEditor : UserControl, IMainEditor return; PB_Origin.Image = GetOriginSprite(Entity); - TID_Trainer.LoadIDValues(Entity); + TID_Trainer.LoadIDValues(Entity, Entity.Format); UpdateLegality(); } @@ -1284,7 +1252,7 @@ public sealed partial class PKMEditor : UserControl, IMainEditor return; Entity.Nickname = TB_Nickname.Text; - if (CHK_Nicknamed.Checked) + if (CHK_NicknamedFlag.Checked) return; var species = (ushort)WinFormsUtil.GetIndex(CB_Species); @@ -1295,7 +1263,7 @@ public sealed partial class PKMEditor : UserControl, IMainEditor species = 0; // get the egg name. if (SpeciesName.IsNicknamedAnyLanguage(species, TB_Nickname.Text, Entity.Format)) - CHK_Nicknamed.Checked = true; + CHK_NicknamedFlag.Checked = true; } private void UpdateNickname(object sender, EventArgs e) @@ -1311,7 +1279,7 @@ public sealed partial class PKMEditor : UserControl, IMainEditor } } - if (CHK_Nicknamed.Checked) + if (CHK_NicknamedFlag.Checked) return; // Fetch Current Species and set it as Nickname Text @@ -1421,7 +1389,7 @@ public sealed partial class PKMEditor : UserControl, IMainEditor if (Entity.Format >= 4) { var sav = SaveFileRequested.Invoke(this, e); - bool isTraded = sav.OT != TB_OT.Text || sav.TID != Entity.TID || sav.SID != Entity.SID; + bool isTraded = sav.OT != TB_OT.Text || sav.TID16 != Entity.TID16 || sav.SID16 != Entity.SID16; var loc = isTraded ? Locations.TradedEggLocation(sav.Generation, sav.Version) : LocationEdits.GetNoneLocation(Entity); @@ -1433,7 +1401,7 @@ public sealed partial class PKMEditor : UserControl, IMainEditor TB_OT.Text = Entity.OT_Name; } - CHK_Nicknamed.Checked = EggStateLegality.IsNicknameFlagSet(Entity); + CHK_NicknamedFlag.Checked = EggStateLegality.IsNicknameFlagSet(Entity); TB_Nickname.Text = SpeciesName.GetEggName(WinFormsUtil.GetIndex(CB_Language), Entity.Format); // Wipe egg memories @@ -1445,7 +1413,7 @@ public sealed partial class PKMEditor : UserControl, IMainEditor } else // Not Egg { - if (!CHK_Nicknamed.Checked) + if (!CHK_NicknamedFlag.Checked) UpdateNickname(this, EventArgs.Empty); TB_Friendship.Text = Entity.PersonalInfo.BaseFriendship.ToString(); @@ -1465,7 +1433,7 @@ public sealed partial class PKMEditor : UserControl, IMainEditor var nick = SpeciesName.GetEggName(WinFormsUtil.GetIndex(CB_Language), Entity.Format); if (TB_Nickname.Text == nick) - CHK_Nicknamed.Checked = false; + CHK_NicknamedFlag.Checked = false; } UpdateNickname(this, EventArgs.Empty); @@ -1631,7 +1599,7 @@ public sealed partial class PKMEditor : UserControl, IMainEditor cb.ResetBackColor(); } - private void ValidateComboBox(object sender, CancelEventArgs e) + private void ValidateComboBox(object? sender, CancelEventArgs e) { if (sender is not ComboBox cb) return; @@ -1640,7 +1608,7 @@ public sealed partial class PKMEditor : UserControl, IMainEditor UpdateSprite(); } - private void ValidateComboBox2(object sender, EventArgs e) + private void ValidateComboBox2(object? sender, EventArgs e) { if (!FieldsLoaded) return; @@ -1676,7 +1644,7 @@ public sealed partial class PKMEditor : UserControl, IMainEditor } } - private void ValidateMove(object sender, EventArgs e) + private void ValidateMove(object? sender, EventArgs e) { if (!FieldsLoaded || sender is not ComboBox cb) return; @@ -1685,10 +1653,10 @@ public sealed partial class PKMEditor : UserControl, IMainEditor // Store value back, repopulate legality. var value = (ushort)WinFormsUtil.GetIndex(cb); - int index = Array.IndexOf(Moves, cb); + int index = Array.FindIndex(Moves, z => z.CB_Move == cb); if (index != -1) { - UpdatePP(sender, e); + Moves[index].HealPP(Entity); Entity.SetMove(index, value); } else if ((index = Array.IndexOf(Relearn, cb)) != -1) @@ -1704,15 +1672,17 @@ public sealed partial class PKMEditor : UserControl, IMainEditor // Shouldn't hit here. throw new InvalidOperationException(); } - UpdateLegality(skipMoveRepop: true); + UpdateLegality(args: UpdateLegalityArgs.SkipMoveRepopulation); } - private void ValidateMovePaint(object sender, DrawItemEventArgs e) + private void ValidateMovePaint(object? sender, DrawItemEventArgs e) { - if (e.Index < 0) + if (sender is null || e.Index < 0) return; - var (text, value) = (ComboItem)((ComboBox)sender).Items[e.Index]; + var cb = (ComboBox)sender; + var item = cb.Items[e.Index]; + var (text, value) = (ComboItem)item; var valid = LegalMoveSource.Info.CanLearn((ushort)value) && !HaX; var current = (e.State & DrawItemState.Selected) != 0; @@ -1731,12 +1701,13 @@ public sealed partial class PKMEditor : UserControl, IMainEditor TextRenderer.DrawText(e.Graphics, text, e.Font, rec, textColor, flags); } - private void MeasureDropDownHeight(object sender, MeasureItemEventArgs e) => e.ItemHeight = CB_RelearnMove1.ItemHeight; + private void MeasureDropDownHeight(object? sender, MeasureItemEventArgs e) => e.ItemHeight = CB_RelearnMove1.ItemHeight; - private void ValidateMoveDropDown(object sender, EventArgs e) + private void ValidateMoveDropDown(object? sender, EventArgs e) { - var s = (ComboBox) sender; - var index = Array.IndexOf(Moves, s); + if (sender is not ComboBox s) + return; + var index = Array.FindIndex(Moves, z => z.CB_Move == s); // Populating the combobox drop-down list is deferred until the dropdown is entered into at least once. // Saves some lag delays when viewing a pk. @@ -1848,7 +1819,7 @@ public sealed partial class PKMEditor : UserControl, IMainEditor int gen = t.Format; FLP_Purification.Visible = FLP_ShadowID.Visible = t is IShadowCapture; bool sizeCP = gen >= 8 || pb7; - FLP_SizeCP.Visible = sizeCP; + SizeCP.Visible = sizeCP; if (sizeCP) SizeCP.ToggleVisibility(t); PB_Favorite.Visible = t is IFavorite; @@ -1858,9 +1829,9 @@ public sealed partial class PKMEditor : UserControl, IMainEditor BTN_Medals.Visible = gen is 6 or 7 && !pb7; FLP_Country.Visible = FLP_SubRegion.Visible = FLP_3DSRegion.Visible = t is IRegionOrigin; FLP_OriginalNature.Visible = gen >= 8; - B_Records.Visible = t is ITechRecord; + B_RelearnFlags.Visible = t is ITechRecord; B_MoveShop.Visible = t is IMoveShop8Mastery; - CB_HTLanguage.Visible = gen >= 8; + FLP_HTLanguage.Visible = gen >= 8; L_AlphaMastered.Visible = CB_AlphaMastered.Visible = t is PA8; FLP_ObedienceLevel.Visible = t is IObedienceLevel; Contest.ToggleInterface(Entity, Entity.Context); @@ -1880,19 +1851,19 @@ public sealed partial class PKMEditor : UserControl, IMainEditor private void ToggleInterface(int gen) { ToggleSecrets(HideSecretValues, gen); - GB_nOT.Visible = GB_RelearnMoves.Visible = gen >= 6; + FLP_Handler.Visible = GB_nOT.Visible = FLP_HT.Visible = GB_RelearnMoves.Visible = gen >= 6; PB_Origin.Visible = gen >= 6; FLP_NSparkle.Visible = L_NSparkle.Visible = CHK_NSparkle.Visible = gen == 5; CHK_AsEgg.Visible = GB_EggConditions.Visible = PB_Mark5.Visible = PB_Mark6.Visible = gen >= 4; - FLP_ShinyLeaf.Visible = L_ShinyLeaf.Visible = ShinyLeaf.Visible = gen == 4; + ShinyLeaf.Visible = gen == 4; DEV_Ability.Enabled = DEV_Ability.Visible = gen > 3 && HaX; CB_Ability.Visible = !DEV_Ability.Enabled && gen >= 3; FLP_Nature.Visible = gen >= 3; FLP_Ability.Visible = gen >= 3; - GB_ExtraBytes.Visible = GB_ExtraBytes.Enabled = gen >= 3; + FLP_ExtraBytes.Visible = gen >= 3; GB_Markings.Visible = gen >= 3; CB_Form.Enabled = gen >= 3; FA_Form.Visible = gen >= 6; @@ -1901,7 +1872,7 @@ public sealed partial class PKMEditor : UserControl, IMainEditor FLP_HeldItem.Visible = gen >= 2; CHK_IsEgg.Visible = gen >= 2; FLP_PKRS.Visible = FLP_EggPKRSRight.Visible = gen >= 2; - UC_Gender.Visible = gen >= 2; + UC_Gender.Visible = UC_OTGender.Visible = gen >= 2; FLP_CatchRate.Visible = gen == 1; // HaX override, needs to be after DEV_Ability enabled assignment. @@ -1933,13 +1904,27 @@ public sealed partial class PKMEditor : UserControl, IMainEditor TB_Nickname.MaxLength = Entity.MaxStringLengthNickname; // Hide Unused Tabs - if (Entity.Format == 1 && tabMain.TabPages.Contains(Tab_Met)) + if (Entity.Format == 1 && Hidden_TC.TabPages.Contains(Hidden_Met)) { - tabMain.TabPages.Remove(Tab_Met); + Hidden_TC.TabPages.Remove(Hidden_Met); + TC_Editor.TabPages.Remove(Tab_Met); } - else if (Entity.Format != 1 && !tabMain.TabPages.Contains(Tab_Met)) + else if (Entity.Format != 1 && !Hidden_TC.TabPages.Contains(Hidden_Met)) { - tabMain.TabPages.Insert(1, Tab_Met); + Hidden_TC.TabPages.Insert(1, Hidden_Met); + TC_Editor.TabPages.Insert(1, Tab_Met); + TranslationRequired = true; + } + + if (Entity.Format <= 2 && Hidden_TC.TabPages.Contains(Hidden_Cosmetic)) + { + Hidden_TC.TabPages.Remove(Hidden_Cosmetic); + TC_Editor.TabPages.Remove(Tab_Cosmetic); + } + else if (Entity.Format > 2 && !Hidden_TC.TabPages.Contains(Hidden_Cosmetic)) + { + Hidden_TC.TabPages.Insert(4, Hidden_Cosmetic); + TC_Editor.TabPages.Insert(4, Tab_Cosmetic); TranslationRequired = true; } @@ -1965,7 +1950,7 @@ public sealed partial class PKMEditor : UserControl, IMainEditor private void CenterSubEditors() { // Recenter PKM SubEditors - var firstTabArea = tabMain.TabPages[0]; // first is always initialized + var firstTabArea = Hidden_Main; // first is always initialized FLP_PKMEditors.HorizontallyCenter(firstTabArea); FLP_MoveFlags.HorizontallyCenter(firstTabArea); } @@ -1974,7 +1959,7 @@ public sealed partial class PKMEditor : UserControl, IMainEditor { AllowDrop = true; DragDrop += drop; - foreach (var tab in tabMain.TabPages.OfType()) + foreach (var tab in Hidden_TC.TabPages.OfType()) { tab.AllowDrop = true; tab.DragEnter += enter; @@ -2010,7 +1995,7 @@ public sealed partial class PKMEditor : UserControl, IMainEditor private void ClickVersionMarking(object sender, EventArgs e) { - tabMain.SelectedTab = Tab_Met; + TC_Editor.SelectedTab = Tab_Met; if (sender == PB_BattleVersion) CB_BattleVersion.DroppedDown = true; else @@ -2028,8 +2013,8 @@ public sealed partial class PKMEditor : UserControl, IMainEditor public void FlickerInterface() { - tabMain.SelectedTab = Tab_Met; // parent tab of CB_GameOrigin - tabMain.SelectedTab = Tab_Main; // first tab + TC_Editor.SelectedTab = Tab_Met; // parent tab of CB_GameOrigin + TC_Editor.SelectedTab = Tab_Main; // first tab } private void L_Obedience_Click(object sender, EventArgs e) @@ -2104,9 +2089,59 @@ public sealed partial class PKMEditor : UserControl, IMainEditor // Set the Move ComboBoxes too.. LegalMoveSource.ChangeMoveSource(source.Moves); - foreach (var cb in Moves.Concat(Relearn)) + foreach (var cb in Relearn) SetIfDifferentCount(source.Moves, cb, force); + foreach (var cb in Moves) + SetIfDifferentCount(source.Moves, cb.CB_Move, force); if (sav is SAV8LA) SetIfDifferentCount(source.Moves, CB_AlphaMastered, force); } + + private void ChangeSelectedTabIndex(object? sender, EventArgs e) => Hidden_TC.SelectedIndex = TC_Editor.SelectedIndex; + private void CHK_Nicknamed_Click(object? sender, EventArgs e) => CHK_NicknamedFlag.Checked ^= true; + + private void PB_MarkShiny_Click(object sender, EventArgs e) + { + if (Entity.Format <= 2) + { + TC_Editor.SelectedTab = Tab_Stats; + Stats.Focus(); + return; + } + TC_Editor.SelectedTab = Tab_Main; + TB_PID.Focus(); + } + + private void PB_MarkCured_Click(object sender, EventArgs e) + { + // Toggle Pokérus cured state. + if (!CHK_Cured.Checked) + { + CHK_Infected.Checked = true; + if (CB_PKRSDays.SelectedIndex != 0) + CB_PKRSDays.SelectedIndex = 0; + } + else + { + CHK_Cured.Checked = false; + } + TC_Editor.SelectedTab = Tab_Main; + CB_PKRSStrain.DroppedDown = true; + } +} + +public static class MoveDisplay +{ + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Bitmap? GetMoveImage(bool isIllegal, PKM pk, int index) + { + if (isIllegal) + return Resources.warn; + + var dummied = MoveInfo.GetDummiedMovesHashSet(pk.Context); + if (dummied?.Contains(pk.GetMove(index)) == true) + return Resources.hint; + + return null; + } } diff --git a/PKHeX.WinForms/Controls/PKM Editor/PKMEditor.resx b/PKHeX.WinForms/Controls/PKM Editor/PKMEditor.resx index 3d0d627b4..54cade7ae 100644 --- a/PKHeX.WinForms/Controls/PKM Editor/PKMEditor.resx +++ b/PKHeX.WinForms/Controls/PKM Editor/PKMEditor.resx @@ -1,64 +1,4 @@ - - - + @@ -117,13 +57,41 @@ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - 17, 17 - - - 17, 56 - - - 17, 95 - + + + + iVBORw0KGgoAAAANSUhEUgAAABIAAAASCAYAAABWzo5XAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8 + YQUAAAAJcEhZcwAADsIAAA7CARUoSoAAAAFaSURBVDhPlZPbLwNBFMb338STiFtQ4n57QDyQ8EC0CSGa + tjyQoC4PmuqDyPLgLlGX16aRqCAIJXLsOTszO7PG2P6SL7tz9vu+nezFkimrSUMpYjEVnTGIWNxFZ0BV + tx5AOP4BkUTxlybmX6G8dod8xhLU0Q0YmVsG4TUWdQxdwdYuQGof6OgnsR6wyK9CkTUwYmslFlWG9uA6 + z9IS8eQ/RRgM9Z2JtbwTXE9G3+jcWGRfkIf4dvTlnhJtA5fkia646z+Lcs+uQUdD97Hw4UNGFjY0RV3D + 3rtu6j2l2WqaDRy4DzUaKdBsfOZJzETRVOydLiYzaogj76iiLgPN/efig0SJopHwPQXyL15RY88JzZCq + FlvMdRJFeBfO7R3Ats0WDtmcuksu7Y5Q7YNZFvV4+AS6iezjUor8/1t95yHMLgEsbgKMTT+KuUlUwtEZ + gojFVXRGk1jMwbJ+AHMbYLkuAlJ/AAAAAElFTkSuQmCC + + + + + iVBORw0KGgoAAAANSUhEUgAAABIAAAASCAYAAABWzo5XAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8 + YQUAAAAJcEhZcwAADsIAAA7CARUoSoAAAAFaSURBVDhPlZPbLwNBFMb338STiFtQ4n57QDyQ8EC0CSGa + tjyQoC4PmuqDyPLgLlGX16aRqCAIJXLsOTszO7PG2P6SL7tz9vu+nezFkimrSUMpYjEVnTGIWNxFZ0BV + tx5AOP4BkUTxlybmX6G8dod8xhLU0Q0YmVsG4TUWdQxdwdYuQGof6OgnsR6wyK9CkTUwYmslFlWG9uA6 + z9IS8eQ/RRgM9Z2JtbwTXE9G3+jcWGRfkIf4dvTlnhJtA5fkia646z+Lcs+uQUdD97Hw4UNGFjY0RV3D + 3rtu6j2l2WqaDRy4DzUaKdBsfOZJzETRVOydLiYzaogj76iiLgPN/efig0SJopHwPQXyL15RY88JzZCq + FlvMdRJFeBfO7R3Ats0WDtmcuksu7Y5Q7YNZFvV4+AS6iezjUor8/1t95yHMLgEsbgKMTT+KuUlUwtEZ + gojFVXRGk1jMwbJ+AHMbYLkuAlJ/AAAAAElFTkSuQmCC + + + + + iVBORw0KGgoAAAANSUhEUgAAABIAAAASCAYAAABWzo5XAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8 + YQUAAAAJcEhZcwAADsIAAA7CARUoSoAAAAFaSURBVDhPlZPbLwNBFMb338STiFtQ4n57QDyQ8EC0CSGa + tjyQoC4PmuqDyPLgLlGX16aRqCAIJXLsOTszO7PG2P6SL7tz9vu+nezFkimrSUMpYjEVnTGIWNxFZ0BV + tx5AOP4BkUTxlybmX6G8dod8xhLU0Q0YmVsG4TUWdQxdwdYuQGof6OgnsR6wyK9CkTUwYmslFlWG9uA6 + z9IS8eQ/RRgM9Z2JtbwTXE9G3+jcWGRfkIf4dvTlnhJtA5fkia646z+Lcs+uQUdD97Hw4UNGFjY0RV3D + 3rtu6j2l2WqaDRy4DzUaKdBsfOZJzETRVOydLiYzaogj76iiLgPN/efig0SJopHwPQXyL15RY88JzZCq + FlvMdRJFeBfO7R3Ats0WDtmcuksu7Y5Q7YNZFvV4+AS6iezjUor8/1t95yHMLgEsbgKMTT+KuUlUwtEZ + gojFVXRGk1jMwbJ+AHMbYLkuAlJ/AAAAAElFTkSuQmCC + + \ No newline at end of file diff --git a/PKHeX.WinForms/Controls/PKM Editor/ShinyLeaf.Designer.cs b/PKHeX.WinForms/Controls/PKM Editor/ShinyLeaf.Designer.cs index 0384b3d69..6071484a8 100644 --- a/PKHeX.WinForms/Controls/PKM Editor/ShinyLeaf.Designer.cs +++ b/PKHeX.WinForms/Controls/PKM Editor/ShinyLeaf.Designer.cs @@ -48,8 +48,9 @@ this.flowLayoutPanel1.Controls.Add(this.CHK_C); this.flowLayoutPanel1.Dock = System.Windows.Forms.DockStyle.Fill; this.flowLayoutPanel1.Location = new System.Drawing.Point(0, 0); + this.flowLayoutPanel1.Margin = new System.Windows.Forms.Padding(0); this.flowLayoutPanel1.Name = "flowLayoutPanel1"; - this.flowLayoutPanel1.Size = new System.Drawing.Size(140, 56); + this.flowLayoutPanel1.Size = new System.Drawing.Size(200, 64); this.flowLayoutPanel1.TabIndex = 0; // // CHK_1 @@ -58,7 +59,7 @@ this.CHK_1.Location = new System.Drawing.Point(0, 0); this.CHK_1.Margin = new System.Windows.Forms.Padding(0); this.CHK_1.Name = "CHK_1"; - this.CHK_1.Size = new System.Drawing.Size(40, 30); + this.CHK_1.Size = new System.Drawing.Size(40, 32); this.CHK_1.TabIndex = 0; this.CHK_1.UseVisualStyleBackColor = true; this.CHK_1.CheckedChanged += new System.EventHandler(this.UpdateFlagState); @@ -69,7 +70,7 @@ this.CHK_2.Location = new System.Drawing.Point(40, 0); this.CHK_2.Margin = new System.Windows.Forms.Padding(0); this.CHK_2.Name = "CHK_2"; - this.CHK_2.Size = new System.Drawing.Size(40, 30); + this.CHK_2.Size = new System.Drawing.Size(40, 32); this.CHK_2.TabIndex = 1; this.CHK_2.UseVisualStyleBackColor = true; this.CHK_2.CheckedChanged += new System.EventHandler(this.UpdateFlagState); @@ -80,7 +81,7 @@ this.CHK_3.Location = new System.Drawing.Point(80, 0); this.CHK_3.Margin = new System.Windows.Forms.Padding(0); this.CHK_3.Name = "CHK_3"; - this.CHK_3.Size = new System.Drawing.Size(40, 30); + this.CHK_3.Size = new System.Drawing.Size(40, 32); this.CHK_3.TabIndex = 2; this.CHK_3.UseVisualStyleBackColor = true; this.CHK_3.CheckedChanged += new System.EventHandler(this.UpdateFlagState); @@ -88,10 +89,10 @@ // CHK_4 // this.CHK_4.Image = global::PKHeX.WinForms.Properties.Resources.leaf; - this.CHK_4.Location = new System.Drawing.Point(0, 30); + this.CHK_4.Location = new System.Drawing.Point(120, 0); this.CHK_4.Margin = new System.Windows.Forms.Padding(0); this.CHK_4.Name = "CHK_4"; - this.CHK_4.Size = new System.Drawing.Size(40, 30); + this.CHK_4.Size = new System.Drawing.Size(40, 32); this.CHK_4.TabIndex = 3; this.CHK_4.UseVisualStyleBackColor = true; this.CHK_4.CheckedChanged += new System.EventHandler(this.UpdateFlagState); @@ -99,10 +100,10 @@ // CHK_5 // this.CHK_5.Image = global::PKHeX.WinForms.Properties.Resources.leaf; - this.CHK_5.Location = new System.Drawing.Point(40, 30); + this.CHK_5.Location = new System.Drawing.Point(160, 0); this.CHK_5.Margin = new System.Windows.Forms.Padding(0); this.CHK_5.Name = "CHK_5"; - this.CHK_5.Size = new System.Drawing.Size(40, 30); + this.CHK_5.Size = new System.Drawing.Size(40, 32); this.CHK_5.TabIndex = 4; this.CHK_5.UseVisualStyleBackColor = true; this.CHK_5.CheckedChanged += new System.EventHandler(this.UpdateFlagState); @@ -110,21 +111,22 @@ // CHK_C // this.CHK_C.Image = global::PKHeX.WinForms.Properties.Resources.crown; - this.CHK_C.Location = new System.Drawing.Point(80, 30); + this.CHK_C.Location = new System.Drawing.Point(0, 32); this.CHK_C.Margin = new System.Windows.Forms.Padding(0); this.CHK_C.Name = "CHK_C"; - this.CHK_C.Size = new System.Drawing.Size(60, 28); + this.CHK_C.Size = new System.Drawing.Size(64, 32); this.CHK_C.TabIndex = 5; this.CHK_C.UseVisualStyleBackColor = true; this.CHK_C.CheckedChanged += new System.EventHandler(this.UpdateFlagState); // // ShinyLeaf // - this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); + this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 15F); this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; this.Controls.Add(this.flowLayoutPanel1); + this.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3); this.Name = "ShinyLeaf"; - this.Size = new System.Drawing.Size(140, 56); + this.Size = new System.Drawing.Size(200, 64); this.flowLayoutPanel1.ResumeLayout(false); this.ResumeLayout(false); diff --git a/PKHeX.WinForms/Controls/PKM Editor/ShinyLeaf.resx b/PKHeX.WinForms/Controls/PKM Editor/ShinyLeaf.resx index 1af7de150..f298a7be8 100644 --- a/PKHeX.WinForms/Controls/PKM Editor/ShinyLeaf.resx +++ b/PKHeX.WinForms/Controls/PKM Editor/ShinyLeaf.resx @@ -1,64 +1,4 @@ - - - + diff --git a/PKHeX.WinForms/Controls/PKM Editor/SizeCP.Designer.cs b/PKHeX.WinForms/Controls/PKM Editor/SizeCP.Designer.cs index 9bc4b81d5..19774a4eb 100644 --- a/PKHeX.WinForms/Controls/PKM Editor/SizeCP.Designer.cs +++ b/PKHeX.WinForms/Controls/PKM Editor/SizeCP.Designer.cs @@ -61,10 +61,10 @@ namespace PKHeX.WinForms.Controls // this.FLP_CP.Controls.Add(this.MT_CP); this.FLP_CP.Controls.Add(this.CHK_Auto); - this.FLP_CP.Location = new System.Drawing.Point(63, 69); + this.FLP_CP.Location = new System.Drawing.Point(80, 72); this.FLP_CP.Margin = new System.Windows.Forms.Padding(0); this.FLP_CP.Name = "FLP_CP"; - this.FLP_CP.Size = new System.Drawing.Size(140, 20); + this.FLP_CP.Size = new System.Drawing.Size(120, 24); this.FLP_CP.TabIndex = 1; // // MT_CP @@ -73,16 +73,16 @@ namespace PKHeX.WinForms.Controls this.MT_CP.Margin = new System.Windows.Forms.Padding(0); this.MT_CP.Mask = "00000"; this.MT_CP.Name = "MT_CP"; - this.MT_CP.Size = new System.Drawing.Size(36, 20); + this.MT_CP.Size = new System.Drawing.Size(32, 23); this.MT_CP.TabIndex = 5; this.MT_CP.TextChanged += new System.EventHandler(this.MT_CP_TextChanged); // // CHK_Auto // - this.CHK_Auto.AutoSize = true; - this.CHK_Auto.Location = new System.Drawing.Point(39, 3); + this.CHK_Auto.Location = new System.Drawing.Point(40, 0); + this.CHK_Auto.Margin = new System.Windows.Forms.Padding(8, 0, 0, 0); this.CHK_Auto.Name = "CHK_Auto"; - this.CHK_Auto.Size = new System.Drawing.Size(48, 17); + this.CHK_Auto.Size = new System.Drawing.Size(64, 24); this.CHK_Auto.TabIndex = 6; this.CHK_Auto.Text = "Auto"; this.CHK_Auto.UseVisualStyleBackColor = true; @@ -91,9 +91,10 @@ namespace PKHeX.WinForms.Controls // L_CP // this.L_CP.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); - this.L_CP.Location = new System.Drawing.Point(3, 69); + this.L_CP.Location = new System.Drawing.Point(0, 72); + this.L_CP.Margin = new System.Windows.Forms.Padding(0); this.L_CP.Name = "L_CP"; - this.L_CP.Size = new System.Drawing.Size(57, 20); + this.L_CP.Size = new System.Drawing.Size(80, 24); this.L_CP.TabIndex = 0; this.L_CP.Text = "CP:"; this.L_CP.TextAlign = System.Drawing.ContentAlignment.MiddleRight; @@ -101,9 +102,10 @@ namespace PKHeX.WinForms.Controls // L_Height // this.L_Height.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); - this.L_Height.Location = new System.Drawing.Point(3, 0); + this.L_Height.Location = new System.Drawing.Point(0, 0); + this.L_Height.Margin = new System.Windows.Forms.Padding(0); this.L_Height.Name = "L_Height"; - this.L_Height.Size = new System.Drawing.Size(57, 20); + this.L_Height.Size = new System.Drawing.Size(80, 24); this.L_Height.TabIndex = 1; this.L_Height.Text = "Height:"; this.L_Height.TextAlign = System.Drawing.ContentAlignment.MiddleRight; @@ -111,9 +113,10 @@ namespace PKHeX.WinForms.Controls // L_Weight // this.L_Weight.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); - this.L_Weight.Location = new System.Drawing.Point(3, 23); + this.L_Weight.Location = new System.Drawing.Point(0, 24); + this.L_Weight.Margin = new System.Windows.Forms.Padding(0); this.L_Weight.Name = "L_Weight"; - this.L_Weight.Size = new System.Drawing.Size(57, 20); + this.L_Weight.Size = new System.Drawing.Size(80, 24); this.L_Weight.TabIndex = 2; this.L_Weight.Text = "Weight:"; this.L_Weight.TextAlign = System.Drawing.ContentAlignment.MiddleRight; @@ -128,7 +131,7 @@ namespace PKHeX.WinForms.Controls 0, 0}); this.NUD_HeightScalar.Name = "NUD_HeightScalar"; - this.NUD_HeightScalar.Size = new System.Drawing.Size(40, 20); + this.NUD_HeightScalar.Size = new System.Drawing.Size(40, 23); this.NUD_HeightScalar.TabIndex = 1; this.NUD_HeightScalar.Value = new decimal(new int[] { 255, @@ -143,7 +146,7 @@ namespace PKHeX.WinForms.Controls this.TB_HeightAbs.Location = new System.Drawing.Point(40, 0); this.TB_HeightAbs.Margin = new System.Windows.Forms.Padding(0); this.TB_HeightAbs.Name = "TB_HeightAbs"; - this.TB_HeightAbs.Size = new System.Drawing.Size(67, 20); + this.TB_HeightAbs.Size = new System.Drawing.Size(64, 23); this.TB_HeightAbs.TabIndex = 2; this.TB_HeightAbs.Text = "123.456789"; this.TB_HeightAbs.TextChanged += new System.EventHandler(this.TB_HeightAbs_TextChanged); @@ -151,8 +154,8 @@ namespace PKHeX.WinForms.Controls // tableLayoutPanel1 // this.tableLayoutPanel1.ColumnCount = 2; - this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 31F)); - this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 69F)); + this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 80F)); + this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100F)); this.tableLayoutPanel1.Controls.Add(this.L_Scale, 0, 2); this.tableLayoutPanel1.Controls.Add(this.FLP_Weight, 1, 1); this.tableLayoutPanel1.Controls.Add(this.L_Weight, 0, 1); @@ -165,19 +168,20 @@ namespace PKHeX.WinForms.Controls this.tableLayoutPanel1.Margin = new System.Windows.Forms.Padding(0); this.tableLayoutPanel1.Name = "tableLayoutPanel1"; this.tableLayoutPanel1.RowCount = 4; - this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 50F)); - this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 50F)); - this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 23F)); - this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 20F)); - this.tableLayoutPanel1.Size = new System.Drawing.Size(204, 90); + this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 24F)); + this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 24F)); + this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 24F)); + this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 24F)); + this.tableLayoutPanel1.Size = new System.Drawing.Size(200, 96); this.tableLayoutPanel1.TabIndex = 2; // // L_Scale // this.L_Scale.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); - this.L_Scale.Location = new System.Drawing.Point(3, 46); + this.L_Scale.Location = new System.Drawing.Point(0, 48); + this.L_Scale.Margin = new System.Windows.Forms.Padding(0); this.L_Scale.Name = "L_Scale"; - this.L_Scale.Size = new System.Drawing.Size(57, 20); + this.L_Scale.Size = new System.Drawing.Size(80, 24); this.L_Scale.TabIndex = 6; this.L_Scale.Text = "Scale:"; this.L_Scale.TextAlign = System.Drawing.ContentAlignment.MiddleRight; @@ -187,10 +191,10 @@ namespace PKHeX.WinForms.Controls this.FLP_Weight.Controls.Add(this.NUD_WeightScalar); this.FLP_Weight.Controls.Add(this.TB_WeightAbs); this.FLP_Weight.Controls.Add(this.L_SizeW); - this.FLP_Weight.Location = new System.Drawing.Point(63, 23); + this.FLP_Weight.Location = new System.Drawing.Point(80, 24); this.FLP_Weight.Margin = new System.Windows.Forms.Padding(0); this.FLP_Weight.Name = "FLP_Weight"; - this.FLP_Weight.Size = new System.Drawing.Size(140, 20); + this.FLP_Weight.Size = new System.Drawing.Size(120, 24); this.FLP_Weight.TabIndex = 4; // // NUD_WeightScalar @@ -203,7 +207,7 @@ namespace PKHeX.WinForms.Controls 0, 0}); this.NUD_WeightScalar.Name = "NUD_WeightScalar"; - this.NUD_WeightScalar.Size = new System.Drawing.Size(40, 20); + this.NUD_WeightScalar.Size = new System.Drawing.Size(40, 23); this.NUD_WeightScalar.TabIndex = 3; this.NUD_WeightScalar.Value = new decimal(new int[] { 255, @@ -218,7 +222,7 @@ namespace PKHeX.WinForms.Controls this.TB_WeightAbs.Location = new System.Drawing.Point(40, 0); this.TB_WeightAbs.Margin = new System.Windows.Forms.Padding(0); this.TB_WeightAbs.Name = "TB_WeightAbs"; - this.TB_WeightAbs.Size = new System.Drawing.Size(67, 20); + this.TB_WeightAbs.Size = new System.Drawing.Size(64, 23); this.TB_WeightAbs.TabIndex = 4; this.TB_WeightAbs.Text = "123.456789"; this.TB_WeightAbs.TextChanged += new System.EventHandler(this.TB_WeightAbs_TextChanged); @@ -226,9 +230,10 @@ namespace PKHeX.WinForms.Controls // L_SizeW // this.L_SizeW.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); - this.L_SizeW.Location = new System.Drawing.Point(110, 0); + this.L_SizeW.Location = new System.Drawing.Point(8, 23); + this.L_SizeW.Margin = new System.Windows.Forms.Padding(8, 0, 0, 0); this.L_SizeW.Name = "L_SizeW"; - this.L_SizeW.Size = new System.Drawing.Size(24, 20); + this.L_SizeW.Size = new System.Drawing.Size(32, 20); this.L_SizeW.TabIndex = 9; this.L_SizeW.Text = "XS"; this.L_SizeW.TextAlign = System.Drawing.ContentAlignment.MiddleLeft; @@ -238,18 +243,19 @@ namespace PKHeX.WinForms.Controls this.FLP_Height.Controls.Add(this.NUD_HeightScalar); this.FLP_Height.Controls.Add(this.TB_HeightAbs); this.FLP_Height.Controls.Add(this.L_SizeH); - this.FLP_Height.Location = new System.Drawing.Point(63, 0); + this.FLP_Height.Location = new System.Drawing.Point(80, 0); this.FLP_Height.Margin = new System.Windows.Forms.Padding(0); this.FLP_Height.Name = "FLP_Height"; - this.FLP_Height.Size = new System.Drawing.Size(140, 21); + this.FLP_Height.Size = new System.Drawing.Size(120, 24); this.FLP_Height.TabIndex = 3; // // L_SizeH // this.L_SizeH.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); - this.L_SizeH.Location = new System.Drawing.Point(110, 0); + this.L_SizeH.Location = new System.Drawing.Point(8, 23); + this.L_SizeH.Margin = new System.Windows.Forms.Padding(8, 0, 0, 0); this.L_SizeH.Name = "L_SizeH"; - this.L_SizeH.Size = new System.Drawing.Size(24, 20); + this.L_SizeH.Size = new System.Drawing.Size(32, 20); this.L_SizeH.TabIndex = 8; this.L_SizeH.Text = "XL"; this.L_SizeH.TextAlign = System.Drawing.ContentAlignment.MiddleLeft; @@ -258,10 +264,10 @@ namespace PKHeX.WinForms.Controls // this.FLP_Scale3.Controls.Add(this.NUD_Scale); this.FLP_Scale3.Controls.Add(this.L_SizeS); - this.FLP_Scale3.Location = new System.Drawing.Point(63, 46); + this.FLP_Scale3.Location = new System.Drawing.Point(80, 48); this.FLP_Scale3.Margin = new System.Windows.Forms.Padding(0); this.FLP_Scale3.Name = "FLP_Scale3"; - this.FLP_Scale3.Size = new System.Drawing.Size(140, 20); + this.FLP_Scale3.Size = new System.Drawing.Size(120, 24); this.FLP_Scale3.TabIndex = 5; // // NUD_Scale @@ -274,7 +280,7 @@ namespace PKHeX.WinForms.Controls 0, 0}); this.NUD_Scale.Name = "NUD_Scale"; - this.NUD_Scale.Size = new System.Drawing.Size(40, 20); + this.NUD_Scale.Size = new System.Drawing.Size(40, 23); this.NUD_Scale.TabIndex = 3; this.NUD_Scale.Value = new decimal(new int[] { 255, @@ -287,9 +293,10 @@ namespace PKHeX.WinForms.Controls // L_SizeS // this.L_SizeS.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); - this.L_SizeS.Location = new System.Drawing.Point(43, 0); + this.L_SizeS.Location = new System.Drawing.Point(48, 0); + this.L_SizeS.Margin = new System.Windows.Forms.Padding(8, 0, 0, 0); this.L_SizeS.Name = "L_SizeS"; - this.L_SizeS.Size = new System.Drawing.Size(44, 20); + this.L_SizeS.Size = new System.Drawing.Size(40, 20); this.L_SizeS.TabIndex = 9; this.L_SizeS.Text = "XXXS"; this.L_SizeS.TextAlign = System.Drawing.ContentAlignment.MiddleLeft; @@ -299,7 +306,7 @@ namespace PKHeX.WinForms.Controls this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Inherit; this.Controls.Add(this.tableLayoutPanel1); this.Name = "SizeCP"; - this.Size = new System.Drawing.Size(200, 90); + this.Size = new System.Drawing.Size(200, 96); this.FLP_CP.ResumeLayout(false); this.FLP_CP.PerformLayout(); ((System.ComponentModel.ISupportInitialize)(this.NUD_HeightScalar)).EndInit(); diff --git a/PKHeX.WinForms/Controls/PKM Editor/StatEditor.Designer.cs b/PKHeX.WinForms/Controls/PKM Editor/StatEditor.Designer.cs index ae43e3323..7ec9fa8d7 100644 --- a/PKHeX.WinForms/Controls/PKM Editor/StatEditor.Designer.cs +++ b/PKHeX.WinForms/Controls/PKM Editor/StatEditor.Designer.cs @@ -28,7 +28,6 @@ namespace PKHeX.WinForms.Controls ///
private void InitializeComponent() { - this.components = new System.ComponentModel.Container(); this.FLP_Stats = new System.Windows.Forms.FlowLayoutPanel(); this.FLP_StatHeader = new System.Windows.Forms.FlowLayoutPanel(); this.FLP_HackedStats = new System.Windows.Forms.FlowLayoutPanel(); @@ -132,7 +131,6 @@ namespace PKHeX.WinForms.Controls this.FLP_AlphaNoble = new System.Windows.Forms.FlowLayoutPanel(); this.CHK_IsAlpha = new System.Windows.Forms.CheckBox(); this.CHK_IsNoble = new System.Windows.Forms.CheckBox(); - this.EVTip = new System.Windows.Forms.ToolTip(this.components); this.FLP_Stats.SuspendLayout(); this.FLP_StatHeader.SuspendLayout(); this.FLP_HackedStats.SuspendLayout(); @@ -184,7 +182,7 @@ namespace PKHeX.WinForms.Controls this.FLP_Stats.Dock = System.Windows.Forms.DockStyle.Fill; this.FLP_Stats.Location = new System.Drawing.Point(0, 0); this.FLP_Stats.Name = "FLP_Stats"; - this.FLP_Stats.Size = new System.Drawing.Size(312, 381); + this.FLP_Stats.Size = new System.Drawing.Size(320, 400); this.FLP_Stats.TabIndex = 106; // // FLP_StatHeader @@ -205,17 +203,17 @@ namespace PKHeX.WinForms.Controls this.FLP_HackedStats.Location = new System.Drawing.Point(0, 0); this.FLP_HackedStats.Margin = new System.Windows.Forms.Padding(0); this.FLP_HackedStats.Name = "FLP_HackedStats"; - this.FLP_HackedStats.Size = new System.Drawing.Size(75, 21); + this.FLP_HackedStats.Size = new System.Drawing.Size(72, 24); this.FLP_HackedStats.TabIndex = 122; // // CHK_HackedStats // this.CHK_HackedStats.Enabled = false; - this.CHK_HackedStats.Location = new System.Drawing.Point(0, 3); - this.CHK_HackedStats.Margin = new System.Windows.Forms.Padding(0, 3, 0, 3); + this.CHK_HackedStats.Location = new System.Drawing.Point(0, 0); + this.CHK_HackedStats.Margin = new System.Windows.Forms.Padding(0); this.CHK_HackedStats.Name = "CHK_HackedStats"; - this.CHK_HackedStats.Size = new System.Drawing.Size(72, 17); - this.CHK_HackedStats.TabIndex = 18; + this.CHK_HackedStats.Size = new System.Drawing.Size(72, 24); + this.CHK_HackedStats.TabIndex = 0; this.CHK_HackedStats.Text = "Hacked"; this.CHK_HackedStats.UseVisualStyleBackColor = true; this.CHK_HackedStats.Visible = false; @@ -230,10 +228,10 @@ namespace PKHeX.WinForms.Controls this.FLP_StatsHeaderRight.Controls.Add(this.Label_AVs); this.FLP_StatsHeaderRight.Controls.Add(this.Label_GVs); this.FLP_StatsHeaderRight.Controls.Add(this.Label_Stats); - this.FLP_StatsHeaderRight.Location = new System.Drawing.Point(75, 0); + this.FLP_StatsHeaderRight.Location = new System.Drawing.Point(72, 1); this.FLP_StatsHeaderRight.Margin = new System.Windows.Forms.Padding(0); this.FLP_StatsHeaderRight.Name = "FLP_StatsHeaderRight"; - this.FLP_StatsHeaderRight.Size = new System.Drawing.Size(237, 21); + this.FLP_StatsHeaderRight.Size = new System.Drawing.Size(232, 21); this.FLP_StatsHeaderRight.TabIndex = 123; // // Label_Base @@ -241,57 +239,57 @@ namespace PKHeX.WinForms.Controls this.Label_Base.Location = new System.Drawing.Point(0, 0); this.Label_Base.Margin = new System.Windows.Forms.Padding(0); this.Label_Base.Name = "Label_Base"; - this.Label_Base.Size = new System.Drawing.Size(34, 21); + this.Label_Base.Size = new System.Drawing.Size(48, 24); this.Label_Base.TabIndex = 30; this.Label_Base.Text = "Base"; - this.Label_Base.TextAlign = System.Drawing.ContentAlignment.MiddleLeft; + this.Label_Base.TextAlign = System.Drawing.ContentAlignment.MiddleCenter; // // Label_IVs // - this.Label_IVs.Location = new System.Drawing.Point(34, 0); + this.Label_IVs.Location = new System.Drawing.Point(48, 0); this.Label_IVs.Margin = new System.Windows.Forms.Padding(0); this.Label_IVs.Name = "Label_IVs"; - this.Label_IVs.Size = new System.Drawing.Size(30, 21); + this.Label_IVs.Size = new System.Drawing.Size(32, 24); this.Label_IVs.TabIndex = 29; this.Label_IVs.Text = "IVs"; this.Label_IVs.TextAlign = System.Drawing.ContentAlignment.MiddleCenter; // // Label_EVs // - this.Label_EVs.Location = new System.Drawing.Point(64, 0); + this.Label_EVs.Location = new System.Drawing.Point(80, 0); this.Label_EVs.Margin = new System.Windows.Forms.Padding(0); this.Label_EVs.Name = "Label_EVs"; - this.Label_EVs.Size = new System.Drawing.Size(35, 21); + this.Label_EVs.Size = new System.Drawing.Size(40, 24); this.Label_EVs.TabIndex = 27; this.Label_EVs.Text = "EVs"; this.Label_EVs.TextAlign = System.Drawing.ContentAlignment.MiddleCenter; // // Label_AVs // - this.Label_AVs.Location = new System.Drawing.Point(99, 0); + this.Label_AVs.Location = new System.Drawing.Point(120, 0); this.Label_AVs.Margin = new System.Windows.Forms.Padding(0); this.Label_AVs.Name = "Label_AVs"; - this.Label_AVs.Size = new System.Drawing.Size(35, 21); + this.Label_AVs.Size = new System.Drawing.Size(40, 24); this.Label_AVs.TabIndex = 31; this.Label_AVs.Text = "AVs"; this.Label_AVs.TextAlign = System.Drawing.ContentAlignment.MiddleCenter; // // Label_GVs // - this.Label_GVs.Location = new System.Drawing.Point(134, 0); + this.Label_GVs.Location = new System.Drawing.Point(160, 0); this.Label_GVs.Margin = new System.Windows.Forms.Padding(0); this.Label_GVs.Name = "Label_GVs"; - this.Label_GVs.Size = new System.Drawing.Size(35, 21); + this.Label_GVs.Size = new System.Drawing.Size(32, 24); this.Label_GVs.TabIndex = 32; this.Label_GVs.Text = "GVs"; this.Label_GVs.TextAlign = System.Drawing.ContentAlignment.MiddleCenter; // // Label_Stats // - this.Label_Stats.Location = new System.Drawing.Point(169, 0); + this.Label_Stats.Location = new System.Drawing.Point(192, 0); this.Label_Stats.Margin = new System.Windows.Forms.Padding(0); this.Label_Stats.Name = "Label_Stats"; - this.Label_Stats.Size = new System.Drawing.Size(35, 21); + this.Label_Stats.Size = new System.Drawing.Size(40, 24); this.Label_Stats.TabIndex = 28; this.Label_Stats.Text = "Stats"; this.Label_Stats.TextAlign = System.Drawing.ContentAlignment.MiddleCenter; @@ -304,7 +302,7 @@ namespace PKHeX.WinForms.Controls this.FLP_HP.Location = new System.Drawing.Point(0, 22); this.FLP_HP.Margin = new System.Windows.Forms.Padding(0); this.FLP_HP.Name = "FLP_HP"; - this.FLP_HP.Size = new System.Drawing.Size(312, 21); + this.FLP_HP.Size = new System.Drawing.Size(312, 24); this.FLP_HP.TabIndex = 123; // // Label_HP @@ -312,7 +310,7 @@ namespace PKHeX.WinForms.Controls this.Label_HP.Location = new System.Drawing.Point(0, 0); this.Label_HP.Margin = new System.Windows.Forms.Padding(0); this.Label_HP.Name = "Label_HP"; - this.Label_HP.Size = new System.Drawing.Size(77, 21); + this.Label_HP.Size = new System.Drawing.Size(80, 24); this.Label_HP.TabIndex = 19; this.Label_HP.Text = "HP:"; this.Label_HP.TextAlign = System.Drawing.ContentAlignment.MiddleRight; @@ -321,41 +319,42 @@ namespace PKHeX.WinForms.Controls // FLP_HPRight // this.FLP_HPRight.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right))); + this.FLP_HPRight.AutoSize = true; this.FLP_HPRight.Controls.Add(this.TB_BaseHP); this.FLP_HPRight.Controls.Add(this.TB_IVHP); this.FLP_HPRight.Controls.Add(this.TB_EVHP); this.FLP_HPRight.Controls.Add(this.TB_AVHP); this.FLP_HPRight.Controls.Add(this.TB_GVHP); this.FLP_HPRight.Controls.Add(this.Stat_HP); - this.FLP_HPRight.Location = new System.Drawing.Point(77, 0); + this.FLP_HPRight.Location = new System.Drawing.Point(80, 0); this.FLP_HPRight.Margin = new System.Windows.Forms.Padding(0); this.FLP_HPRight.Name = "FLP_HPRight"; - this.FLP_HPRight.Size = new System.Drawing.Size(217, 21); - this.FLP_HPRight.TabIndex = 121; + this.FLP_HPRight.Size = new System.Drawing.Size(228, 23); + this.FLP_HPRight.TabIndex = 1; // // TB_BaseHP // this.TB_BaseHP.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; this.TB_BaseHP.Enabled = false; this.TB_BaseHP.Location = new System.Drawing.Point(0, 0); - this.TB_BaseHP.Margin = new System.Windows.Forms.Padding(0, 0, 7, 0); + this.TB_BaseHP.Margin = new System.Windows.Forms.Padding(0, 0, 8, 0); this.TB_BaseHP.Mask = "000"; this.TB_BaseHP.Name = "TB_BaseHP"; this.TB_BaseHP.PromptChar = ' '; this.TB_BaseHP.ReadOnly = true; - this.TB_BaseHP.Size = new System.Drawing.Size(28, 20); - this.TB_BaseHP.TabIndex = 46; + this.TB_BaseHP.Size = new System.Drawing.Size(32, 23); + this.TB_BaseHP.TabIndex = 0; this.TB_BaseHP.TabStop = false; this.TB_BaseHP.TextAlign = System.Windows.Forms.HorizontalAlignment.Center; // // TB_IVHP // this.TB_IVHP.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; - this.TB_IVHP.Location = new System.Drawing.Point(35, 0); - this.TB_IVHP.Margin = new System.Windows.Forms.Padding(0, 0, 3, 0); + this.TB_IVHP.Location = new System.Drawing.Point(40, 0); + this.TB_IVHP.Margin = new System.Windows.Forms.Padding(0, 0, 8, 0); this.TB_IVHP.Mask = "00"; this.TB_IVHP.Name = "TB_IVHP"; - this.TB_IVHP.Size = new System.Drawing.Size(22, 20); + this.TB_IVHP.Size = new System.Drawing.Size(24, 23); this.TB_IVHP.TabIndex = 1; this.TB_IVHP.TextAlign = System.Windows.Forms.HorizontalAlignment.Center; this.TB_IVHP.Click += new System.EventHandler(this.ClickIV); @@ -364,12 +363,12 @@ namespace PKHeX.WinForms.Controls // TB_EVHP // this.TB_EVHP.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; - this.TB_EVHP.Location = new System.Drawing.Point(63, 0); - this.TB_EVHP.Margin = new System.Windows.Forms.Padding(3, 0, 3, 0); + this.TB_EVHP.Location = new System.Drawing.Point(72, 0); + this.TB_EVHP.Margin = new System.Windows.Forms.Padding(0, 0, 8, 0); this.TB_EVHP.Mask = "000"; this.TB_EVHP.Name = "TB_EVHP"; - this.TB_EVHP.Size = new System.Drawing.Size(28, 20); - this.TB_EVHP.TabIndex = 7; + this.TB_EVHP.Size = new System.Drawing.Size(32, 23); + this.TB_EVHP.TabIndex = 2; this.TB_EVHP.TextAlign = System.Windows.Forms.HorizontalAlignment.Center; this.TB_EVHP.Click += new System.EventHandler(this.ClickEV); this.TB_EVHP.TextChanged += new System.EventHandler(this.UpdateEVs); @@ -377,12 +376,12 @@ namespace PKHeX.WinForms.Controls // TB_AVHP // this.TB_AVHP.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; - this.TB_AVHP.Location = new System.Drawing.Point(97, 0); - this.TB_AVHP.Margin = new System.Windows.Forms.Padding(3, 0, 3, 0); + this.TB_AVHP.Location = new System.Drawing.Point(112, 0); + this.TB_AVHP.Margin = new System.Windows.Forms.Padding(0, 0, 8, 0); this.TB_AVHP.Mask = "000"; this.TB_AVHP.Name = "TB_AVHP"; - this.TB_AVHP.Size = new System.Drawing.Size(28, 20); - this.TB_AVHP.TabIndex = 47; + this.TB_AVHP.Size = new System.Drawing.Size(32, 23); + this.TB_AVHP.TabIndex = 3; this.TB_AVHP.TextAlign = System.Windows.Forms.HorizontalAlignment.Center; this.TB_AVHP.Click += new System.EventHandler(this.ClickAV); this.TB_AVHP.TextChanged += new System.EventHandler(this.UpdateAVs); @@ -390,12 +389,12 @@ namespace PKHeX.WinForms.Controls // TB_GVHP // this.TB_GVHP.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; - this.TB_GVHP.Location = new System.Drawing.Point(131, 0); - this.TB_GVHP.Margin = new System.Windows.Forms.Padding(3, 0, 3, 0); + this.TB_GVHP.Location = new System.Drawing.Point(152, 0); + this.TB_GVHP.Margin = new System.Windows.Forms.Padding(0, 0, 8, 0); this.TB_GVHP.Mask = "000"; this.TB_GVHP.Name = "TB_GVHP"; - this.TB_GVHP.Size = new System.Drawing.Size(28, 20); - this.TB_GVHP.TabIndex = 48; + this.TB_GVHP.Size = new System.Drawing.Size(28, 23); + this.TB_GVHP.TabIndex = 4; this.TB_GVHP.TextAlign = System.Windows.Forms.HorizontalAlignment.Center; this.TB_GVHP.Click += new System.EventHandler(this.ClickGV); this.TB_GVHP.TextChanged += new System.EventHandler(this.UpdateGVs); @@ -404,13 +403,13 @@ namespace PKHeX.WinForms.Controls // this.Stat_HP.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; this.Stat_HP.Enabled = false; - this.Stat_HP.Location = new System.Drawing.Point(165, 0); - this.Stat_HP.Margin = new System.Windows.Forms.Padding(3, 0, 3, 0); + this.Stat_HP.Location = new System.Drawing.Point(188, 0); + this.Stat_HP.Margin = new System.Windows.Forms.Padding(0); this.Stat_HP.Mask = "00000"; this.Stat_HP.Name = "Stat_HP"; this.Stat_HP.PromptChar = ' '; - this.Stat_HP.Size = new System.Drawing.Size(36, 20); - this.Stat_HP.TabIndex = 45; + this.Stat_HP.Size = new System.Drawing.Size(40, 23); + this.Stat_HP.TabIndex = 10; this.Stat_HP.TextAlign = System.Windows.Forms.HorizontalAlignment.Center; this.Stat_HP.TextChanged += new System.EventHandler(this.UpdateHackedStatText); // @@ -419,10 +418,10 @@ namespace PKHeX.WinForms.Controls this.FLP_Atk.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right))); this.FLP_Atk.Controls.Add(this.Label_ATK); this.FLP_Atk.Controls.Add(this.FLP_AtkRight); - this.FLP_Atk.Location = new System.Drawing.Point(0, 43); + this.FLP_Atk.Location = new System.Drawing.Point(0, 46); this.FLP_Atk.Margin = new System.Windows.Forms.Padding(0); this.FLP_Atk.Name = "FLP_Atk"; - this.FLP_Atk.Size = new System.Drawing.Size(312, 21); + this.FLP_Atk.Size = new System.Drawing.Size(312, 24); this.FLP_Atk.TabIndex = 124; // // Label_ATK @@ -430,7 +429,7 @@ namespace PKHeX.WinForms.Controls this.Label_ATK.Location = new System.Drawing.Point(0, 0); this.Label_ATK.Margin = new System.Windows.Forms.Padding(0); this.Label_ATK.Name = "Label_ATK"; - this.Label_ATK.Size = new System.Drawing.Size(77, 21); + this.Label_ATK.Size = new System.Drawing.Size(80, 24); this.Label_ATK.TabIndex = 20; this.Label_ATK.Text = "Atk:"; this.Label_ATK.TextAlign = System.Drawing.ContentAlignment.MiddleRight; @@ -439,42 +438,43 @@ namespace PKHeX.WinForms.Controls // FLP_AtkRight // this.FLP_AtkRight.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right))); + this.FLP_AtkRight.AutoSize = true; this.FLP_AtkRight.Controls.Add(this.TB_BaseATK); this.FLP_AtkRight.Controls.Add(this.TB_IVATK); this.FLP_AtkRight.Controls.Add(this.TB_EVATK); this.FLP_AtkRight.Controls.Add(this.TB_AVATK); this.FLP_AtkRight.Controls.Add(this.TB_GVATK); this.FLP_AtkRight.Controls.Add(this.Stat_ATK); - this.FLP_AtkRight.Location = new System.Drawing.Point(77, 0); + this.FLP_AtkRight.Location = new System.Drawing.Point(80, 0); this.FLP_AtkRight.Margin = new System.Windows.Forms.Padding(0); this.FLP_AtkRight.Name = "FLP_AtkRight"; - this.FLP_AtkRight.Size = new System.Drawing.Size(217, 21); - this.FLP_AtkRight.TabIndex = 123; + this.FLP_AtkRight.Size = new System.Drawing.Size(228, 23); + this.FLP_AtkRight.TabIndex = 2; // // TB_BaseATK // this.TB_BaseATK.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; this.TB_BaseATK.Enabled = false; this.TB_BaseATK.Location = new System.Drawing.Point(0, 0); - this.TB_BaseATK.Margin = new System.Windows.Forms.Padding(0, 0, 7, 0); + this.TB_BaseATK.Margin = new System.Windows.Forms.Padding(0, 0, 8, 0); this.TB_BaseATK.Mask = "000"; this.TB_BaseATK.Name = "TB_BaseATK"; this.TB_BaseATK.PromptChar = ' '; this.TB_BaseATK.ReadOnly = true; - this.TB_BaseATK.Size = new System.Drawing.Size(28, 20); - this.TB_BaseATK.TabIndex = 47; + this.TB_BaseATK.Size = new System.Drawing.Size(32, 23); + this.TB_BaseATK.TabIndex = 0; this.TB_BaseATK.TabStop = false; this.TB_BaseATK.TextAlign = System.Windows.Forms.HorizontalAlignment.Center; // // TB_IVATK // this.TB_IVATK.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; - this.TB_IVATK.Location = new System.Drawing.Point(35, 0); - this.TB_IVATK.Margin = new System.Windows.Forms.Padding(0, 0, 3, 0); + this.TB_IVATK.Location = new System.Drawing.Point(40, 0); + this.TB_IVATK.Margin = new System.Windows.Forms.Padding(0, 0, 8, 0); this.TB_IVATK.Mask = "00"; this.TB_IVATK.Name = "TB_IVATK"; - this.TB_IVATK.Size = new System.Drawing.Size(22, 20); - this.TB_IVATK.TabIndex = 2; + this.TB_IVATK.Size = new System.Drawing.Size(24, 23); + this.TB_IVATK.TabIndex = 1; this.TB_IVATK.TextAlign = System.Windows.Forms.HorizontalAlignment.Center; this.TB_IVATK.Click += new System.EventHandler(this.ClickIV); this.TB_IVATK.TextChanged += new System.EventHandler(this.UpdateIVs); @@ -482,12 +482,12 @@ namespace PKHeX.WinForms.Controls // TB_EVATK // this.TB_EVATK.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; - this.TB_EVATK.Location = new System.Drawing.Point(63, 0); - this.TB_EVATK.Margin = new System.Windows.Forms.Padding(3, 0, 3, 0); + this.TB_EVATK.Location = new System.Drawing.Point(72, 0); + this.TB_EVATK.Margin = new System.Windows.Forms.Padding(0, 0, 8, 0); this.TB_EVATK.Mask = "000"; this.TB_EVATK.Name = "TB_EVATK"; - this.TB_EVATK.Size = new System.Drawing.Size(28, 20); - this.TB_EVATK.TabIndex = 8; + this.TB_EVATK.Size = new System.Drawing.Size(32, 23); + this.TB_EVATK.TabIndex = 2; this.TB_EVATK.TextAlign = System.Windows.Forms.HorizontalAlignment.Center; this.TB_EVATK.Click += new System.EventHandler(this.ClickEV); this.TB_EVATK.TextChanged += new System.EventHandler(this.UpdateEVs); @@ -495,12 +495,12 @@ namespace PKHeX.WinForms.Controls // TB_AVATK // this.TB_AVATK.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; - this.TB_AVATK.Location = new System.Drawing.Point(97, 0); - this.TB_AVATK.Margin = new System.Windows.Forms.Padding(3, 0, 3, 0); + this.TB_AVATK.Location = new System.Drawing.Point(112, 0); + this.TB_AVATK.Margin = new System.Windows.Forms.Padding(0, 0, 8, 0); this.TB_AVATK.Mask = "000"; this.TB_AVATK.Name = "TB_AVATK"; - this.TB_AVATK.Size = new System.Drawing.Size(28, 20); - this.TB_AVATK.TabIndex = 48; + this.TB_AVATK.Size = new System.Drawing.Size(32, 23); + this.TB_AVATK.TabIndex = 3; this.TB_AVATK.TextAlign = System.Windows.Forms.HorizontalAlignment.Center; this.TB_AVATK.Click += new System.EventHandler(this.ClickAV); this.TB_AVATK.TextChanged += new System.EventHandler(this.UpdateAVs); @@ -508,12 +508,12 @@ namespace PKHeX.WinForms.Controls // TB_GVATK // this.TB_GVATK.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; - this.TB_GVATK.Location = new System.Drawing.Point(131, 0); - this.TB_GVATK.Margin = new System.Windows.Forms.Padding(3, 0, 3, 0); + this.TB_GVATK.Location = new System.Drawing.Point(152, 0); + this.TB_GVATK.Margin = new System.Windows.Forms.Padding(0, 0, 8, 0); this.TB_GVATK.Mask = "000"; this.TB_GVATK.Name = "TB_GVATK"; - this.TB_GVATK.Size = new System.Drawing.Size(28, 20); - this.TB_GVATK.TabIndex = 49; + this.TB_GVATK.Size = new System.Drawing.Size(28, 23); + this.TB_GVATK.TabIndex = 4; this.TB_GVATK.TextAlign = System.Windows.Forms.HorizontalAlignment.Center; this.TB_GVATK.Click += new System.EventHandler(this.ClickGV); this.TB_GVATK.TextChanged += new System.EventHandler(this.UpdateGVs); @@ -522,13 +522,13 @@ namespace PKHeX.WinForms.Controls // this.Stat_ATK.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; this.Stat_ATK.Enabled = false; - this.Stat_ATK.Location = new System.Drawing.Point(165, 0); - this.Stat_ATK.Margin = new System.Windows.Forms.Padding(3, 0, 3, 0); + this.Stat_ATK.Location = new System.Drawing.Point(188, 0); + this.Stat_ATK.Margin = new System.Windows.Forms.Padding(0); this.Stat_ATK.Mask = "00000"; this.Stat_ATK.Name = "Stat_ATK"; this.Stat_ATK.PromptChar = ' '; - this.Stat_ATK.Size = new System.Drawing.Size(36, 20); - this.Stat_ATK.TabIndex = 46; + this.Stat_ATK.Size = new System.Drawing.Size(40, 23); + this.Stat_ATK.TabIndex = 10; this.Stat_ATK.TextAlign = System.Windows.Forms.HorizontalAlignment.Center; this.Stat_ATK.TextChanged += new System.EventHandler(this.UpdateHackedStatText); // @@ -537,10 +537,10 @@ namespace PKHeX.WinForms.Controls this.FLP_Def.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right))); this.FLP_Def.Controls.Add(this.Label_DEF); this.FLP_Def.Controls.Add(this.FLP_DefRight); - this.FLP_Def.Location = new System.Drawing.Point(0, 64); + this.FLP_Def.Location = new System.Drawing.Point(0, 70); this.FLP_Def.Margin = new System.Windows.Forms.Padding(0); this.FLP_Def.Name = "FLP_Def"; - this.FLP_Def.Size = new System.Drawing.Size(312, 21); + this.FLP_Def.Size = new System.Drawing.Size(312, 24); this.FLP_Def.TabIndex = 125; // // Label_DEF @@ -548,7 +548,7 @@ namespace PKHeX.WinForms.Controls this.Label_DEF.Location = new System.Drawing.Point(0, 0); this.Label_DEF.Margin = new System.Windows.Forms.Padding(0); this.Label_DEF.Name = "Label_DEF"; - this.Label_DEF.Size = new System.Drawing.Size(77, 21); + this.Label_DEF.Size = new System.Drawing.Size(80, 24); this.Label_DEF.TabIndex = 21; this.Label_DEF.Text = "Def:"; this.Label_DEF.TextAlign = System.Drawing.ContentAlignment.MiddleRight; @@ -557,42 +557,43 @@ namespace PKHeX.WinForms.Controls // FLP_DefRight // this.FLP_DefRight.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right))); + this.FLP_DefRight.AutoSize = true; this.FLP_DefRight.Controls.Add(this.TB_BaseDEF); this.FLP_DefRight.Controls.Add(this.TB_IVDEF); this.FLP_DefRight.Controls.Add(this.TB_EVDEF); this.FLP_DefRight.Controls.Add(this.TB_AVDEF); this.FLP_DefRight.Controls.Add(this.TB_GVDEF); this.FLP_DefRight.Controls.Add(this.Stat_DEF); - this.FLP_DefRight.Location = new System.Drawing.Point(77, 0); + this.FLP_DefRight.Location = new System.Drawing.Point(80, 0); this.FLP_DefRight.Margin = new System.Windows.Forms.Padding(0); this.FLP_DefRight.Name = "FLP_DefRight"; - this.FLP_DefRight.Size = new System.Drawing.Size(217, 21); - this.FLP_DefRight.TabIndex = 123; + this.FLP_DefRight.Size = new System.Drawing.Size(228, 23); + this.FLP_DefRight.TabIndex = 3; // // TB_BaseDEF // this.TB_BaseDEF.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; this.TB_BaseDEF.Enabled = false; this.TB_BaseDEF.Location = new System.Drawing.Point(0, 0); - this.TB_BaseDEF.Margin = new System.Windows.Forms.Padding(0, 0, 7, 0); + this.TB_BaseDEF.Margin = new System.Windows.Forms.Padding(0, 0, 8, 0); this.TB_BaseDEF.Mask = "000"; this.TB_BaseDEF.Name = "TB_BaseDEF"; this.TB_BaseDEF.PromptChar = ' '; this.TB_BaseDEF.ReadOnly = true; - this.TB_BaseDEF.Size = new System.Drawing.Size(28, 20); - this.TB_BaseDEF.TabIndex = 48; + this.TB_BaseDEF.Size = new System.Drawing.Size(32, 23); + this.TB_BaseDEF.TabIndex = 0; this.TB_BaseDEF.TabStop = false; this.TB_BaseDEF.TextAlign = System.Windows.Forms.HorizontalAlignment.Center; // // TB_IVDEF // this.TB_IVDEF.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; - this.TB_IVDEF.Location = new System.Drawing.Point(35, 0); - this.TB_IVDEF.Margin = new System.Windows.Forms.Padding(0, 0, 3, 0); + this.TB_IVDEF.Location = new System.Drawing.Point(40, 0); + this.TB_IVDEF.Margin = new System.Windows.Forms.Padding(0, 0, 8, 0); this.TB_IVDEF.Mask = "00"; this.TB_IVDEF.Name = "TB_IVDEF"; - this.TB_IVDEF.Size = new System.Drawing.Size(22, 20); - this.TB_IVDEF.TabIndex = 3; + this.TB_IVDEF.Size = new System.Drawing.Size(24, 23); + this.TB_IVDEF.TabIndex = 1; this.TB_IVDEF.TextAlign = System.Windows.Forms.HorizontalAlignment.Center; this.TB_IVDEF.Click += new System.EventHandler(this.ClickIV); this.TB_IVDEF.TextChanged += new System.EventHandler(this.UpdateIVs); @@ -600,12 +601,12 @@ namespace PKHeX.WinForms.Controls // TB_EVDEF // this.TB_EVDEF.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; - this.TB_EVDEF.Location = new System.Drawing.Point(63, 0); - this.TB_EVDEF.Margin = new System.Windows.Forms.Padding(3, 0, 3, 0); + this.TB_EVDEF.Location = new System.Drawing.Point(72, 0); + this.TB_EVDEF.Margin = new System.Windows.Forms.Padding(0, 0, 8, 0); this.TB_EVDEF.Mask = "000"; this.TB_EVDEF.Name = "TB_EVDEF"; - this.TB_EVDEF.Size = new System.Drawing.Size(28, 20); - this.TB_EVDEF.TabIndex = 9; + this.TB_EVDEF.Size = new System.Drawing.Size(32, 23); + this.TB_EVDEF.TabIndex = 2; this.TB_EVDEF.TextAlign = System.Windows.Forms.HorizontalAlignment.Center; this.TB_EVDEF.Click += new System.EventHandler(this.ClickEV); this.TB_EVDEF.TextChanged += new System.EventHandler(this.UpdateEVs); @@ -613,12 +614,12 @@ namespace PKHeX.WinForms.Controls // TB_AVDEF // this.TB_AVDEF.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; - this.TB_AVDEF.Location = new System.Drawing.Point(97, 0); - this.TB_AVDEF.Margin = new System.Windows.Forms.Padding(3, 0, 3, 0); + this.TB_AVDEF.Location = new System.Drawing.Point(112, 0); + this.TB_AVDEF.Margin = new System.Windows.Forms.Padding(0, 0, 8, 0); this.TB_AVDEF.Mask = "000"; this.TB_AVDEF.Name = "TB_AVDEF"; - this.TB_AVDEF.Size = new System.Drawing.Size(28, 20); - this.TB_AVDEF.TabIndex = 49; + this.TB_AVDEF.Size = new System.Drawing.Size(32, 23); + this.TB_AVDEF.TabIndex = 3; this.TB_AVDEF.TextAlign = System.Windows.Forms.HorizontalAlignment.Center; this.TB_AVDEF.Click += new System.EventHandler(this.ClickAV); this.TB_AVDEF.TextChanged += new System.EventHandler(this.UpdateAVs); @@ -626,12 +627,12 @@ namespace PKHeX.WinForms.Controls // TB_GVDEF // this.TB_GVDEF.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; - this.TB_GVDEF.Location = new System.Drawing.Point(131, 0); - this.TB_GVDEF.Margin = new System.Windows.Forms.Padding(3, 0, 3, 0); + this.TB_GVDEF.Location = new System.Drawing.Point(152, 0); + this.TB_GVDEF.Margin = new System.Windows.Forms.Padding(0, 0, 8, 0); this.TB_GVDEF.Mask = "000"; this.TB_GVDEF.Name = "TB_GVDEF"; - this.TB_GVDEF.Size = new System.Drawing.Size(28, 20); - this.TB_GVDEF.TabIndex = 50; + this.TB_GVDEF.Size = new System.Drawing.Size(28, 23); + this.TB_GVDEF.TabIndex = 4; this.TB_GVDEF.TextAlign = System.Windows.Forms.HorizontalAlignment.Center; this.TB_GVDEF.Click += new System.EventHandler(this.ClickGV); this.TB_GVDEF.TextChanged += new System.EventHandler(this.UpdateGVs); @@ -640,13 +641,13 @@ namespace PKHeX.WinForms.Controls // this.Stat_DEF.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; this.Stat_DEF.Enabled = false; - this.Stat_DEF.Location = new System.Drawing.Point(165, 0); - this.Stat_DEF.Margin = new System.Windows.Forms.Padding(3, 0, 3, 0); + this.Stat_DEF.Location = new System.Drawing.Point(188, 0); + this.Stat_DEF.Margin = new System.Windows.Forms.Padding(0); this.Stat_DEF.Mask = "00000"; this.Stat_DEF.Name = "Stat_DEF"; this.Stat_DEF.PromptChar = ' '; - this.Stat_DEF.Size = new System.Drawing.Size(36, 20); - this.Stat_DEF.TabIndex = 47; + this.Stat_DEF.Size = new System.Drawing.Size(40, 23); + this.Stat_DEF.TabIndex = 10; this.Stat_DEF.TextAlign = System.Windows.Forms.HorizontalAlignment.Center; this.Stat_DEF.TextChanged += new System.EventHandler(this.UpdateHackedStatText); // @@ -655,10 +656,10 @@ namespace PKHeX.WinForms.Controls this.FLP_SpA.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right))); this.FLP_SpA.Controls.Add(this.FLP_SpALeft); this.FLP_SpA.Controls.Add(this.FLP_SpARight); - this.FLP_SpA.Location = new System.Drawing.Point(0, 85); + this.FLP_SpA.Location = new System.Drawing.Point(0, 94); this.FLP_SpA.Margin = new System.Windows.Forms.Padding(0); this.FLP_SpA.Name = "FLP_SpA"; - this.FLP_SpA.Size = new System.Drawing.Size(312, 21); + this.FLP_SpA.Size = new System.Drawing.Size(312, 24); this.FLP_SpA.TabIndex = 126; // // FLP_SpALeft @@ -670,7 +671,7 @@ namespace PKHeX.WinForms.Controls this.FLP_SpALeft.Location = new System.Drawing.Point(0, 0); this.FLP_SpALeft.Margin = new System.Windows.Forms.Padding(0); this.FLP_SpALeft.Name = "FLP_SpALeft"; - this.FLP_SpALeft.Size = new System.Drawing.Size(77, 21); + this.FLP_SpALeft.Size = new System.Drawing.Size(80, 24); this.FLP_SpALeft.TabIndex = 124; // // Label_SPA @@ -678,7 +679,7 @@ namespace PKHeX.WinForms.Controls this.Label_SPA.Location = new System.Drawing.Point(0, 0); this.Label_SPA.Margin = new System.Windows.Forms.Padding(0); this.Label_SPA.Name = "Label_SPA"; - this.Label_SPA.Size = new System.Drawing.Size(77, 21); + this.Label_SPA.Size = new System.Drawing.Size(80, 24); this.Label_SPA.TabIndex = 22; this.Label_SPA.Text = "SpA:"; this.Label_SPA.TextAlign = System.Drawing.ContentAlignment.MiddleRight; @@ -686,10 +687,10 @@ namespace PKHeX.WinForms.Controls // // Label_SPC // - this.Label_SPC.Location = new System.Drawing.Point(-33, 21); + this.Label_SPC.Location = new System.Drawing.Point(0, 24); this.Label_SPC.Margin = new System.Windows.Forms.Padding(0); this.Label_SPC.Name = "Label_SPC"; - this.Label_SPC.Size = new System.Drawing.Size(110, 21); + this.Label_SPC.Size = new System.Drawing.Size(80, 24); this.Label_SPC.TabIndex = 125; this.Label_SPC.Text = "SpC:"; this.Label_SPC.TextAlign = System.Drawing.ContentAlignment.MiddleRight; @@ -698,42 +699,43 @@ namespace PKHeX.WinForms.Controls // FLP_SpARight // this.FLP_SpARight.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right))); + this.FLP_SpARight.AutoSize = true; this.FLP_SpARight.Controls.Add(this.TB_BaseSPA); this.FLP_SpARight.Controls.Add(this.TB_IVSPA); this.FLP_SpARight.Controls.Add(this.TB_EVSPA); this.FLP_SpARight.Controls.Add(this.TB_AVSPA); this.FLP_SpARight.Controls.Add(this.TB_GVSPA); this.FLP_SpARight.Controls.Add(this.Stat_SPA); - this.FLP_SpARight.Location = new System.Drawing.Point(77, 0); + this.FLP_SpARight.Location = new System.Drawing.Point(80, 0); this.FLP_SpARight.Margin = new System.Windows.Forms.Padding(0); this.FLP_SpARight.Name = "FLP_SpARight"; - this.FLP_SpARight.Size = new System.Drawing.Size(217, 21); - this.FLP_SpARight.TabIndex = 123; + this.FLP_SpARight.Size = new System.Drawing.Size(228, 23); + this.FLP_SpARight.TabIndex = 4; // // TB_BaseSPA // this.TB_BaseSPA.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; this.TB_BaseSPA.Enabled = false; this.TB_BaseSPA.Location = new System.Drawing.Point(0, 0); - this.TB_BaseSPA.Margin = new System.Windows.Forms.Padding(0, 0, 7, 0); + this.TB_BaseSPA.Margin = new System.Windows.Forms.Padding(0, 0, 8, 0); this.TB_BaseSPA.Mask = "000"; this.TB_BaseSPA.Name = "TB_BaseSPA"; this.TB_BaseSPA.PromptChar = ' '; this.TB_BaseSPA.ReadOnly = true; - this.TB_BaseSPA.Size = new System.Drawing.Size(28, 20); - this.TB_BaseSPA.TabIndex = 49; + this.TB_BaseSPA.Size = new System.Drawing.Size(32, 23); + this.TB_BaseSPA.TabIndex = 0; this.TB_BaseSPA.TabStop = false; this.TB_BaseSPA.TextAlign = System.Windows.Forms.HorizontalAlignment.Center; // // TB_IVSPA // this.TB_IVSPA.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; - this.TB_IVSPA.Location = new System.Drawing.Point(35, 0); - this.TB_IVSPA.Margin = new System.Windows.Forms.Padding(0, 0, 3, 0); + this.TB_IVSPA.Location = new System.Drawing.Point(40, 0); + this.TB_IVSPA.Margin = new System.Windows.Forms.Padding(0, 0, 8, 0); this.TB_IVSPA.Mask = "00"; this.TB_IVSPA.Name = "TB_IVSPA"; - this.TB_IVSPA.Size = new System.Drawing.Size(22, 20); - this.TB_IVSPA.TabIndex = 4; + this.TB_IVSPA.Size = new System.Drawing.Size(24, 23); + this.TB_IVSPA.TabIndex = 1; this.TB_IVSPA.TextAlign = System.Windows.Forms.HorizontalAlignment.Center; this.TB_IVSPA.Click += new System.EventHandler(this.ClickIV); this.TB_IVSPA.TextChanged += new System.EventHandler(this.UpdateIVs); @@ -741,12 +743,12 @@ namespace PKHeX.WinForms.Controls // TB_EVSPA // this.TB_EVSPA.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; - this.TB_EVSPA.Location = new System.Drawing.Point(63, 0); - this.TB_EVSPA.Margin = new System.Windows.Forms.Padding(3, 0, 3, 0); + this.TB_EVSPA.Location = new System.Drawing.Point(72, 0); + this.TB_EVSPA.Margin = new System.Windows.Forms.Padding(0, 0, 8, 0); this.TB_EVSPA.Mask = "000"; this.TB_EVSPA.Name = "TB_EVSPA"; - this.TB_EVSPA.Size = new System.Drawing.Size(28, 20); - this.TB_EVSPA.TabIndex = 10; + this.TB_EVSPA.Size = new System.Drawing.Size(32, 23); + this.TB_EVSPA.TabIndex = 2; this.TB_EVSPA.TextAlign = System.Windows.Forms.HorizontalAlignment.Center; this.TB_EVSPA.Click += new System.EventHandler(this.ClickEV); this.TB_EVSPA.TextChanged += new System.EventHandler(this.UpdateEVs); @@ -754,12 +756,12 @@ namespace PKHeX.WinForms.Controls // TB_AVSPA // this.TB_AVSPA.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; - this.TB_AVSPA.Location = new System.Drawing.Point(97, 0); - this.TB_AVSPA.Margin = new System.Windows.Forms.Padding(3, 0, 3, 0); + this.TB_AVSPA.Location = new System.Drawing.Point(112, 0); + this.TB_AVSPA.Margin = new System.Windows.Forms.Padding(0, 0, 8, 0); this.TB_AVSPA.Mask = "000"; this.TB_AVSPA.Name = "TB_AVSPA"; - this.TB_AVSPA.Size = new System.Drawing.Size(28, 20); - this.TB_AVSPA.TabIndex = 50; + this.TB_AVSPA.Size = new System.Drawing.Size(32, 23); + this.TB_AVSPA.TabIndex = 3; this.TB_AVSPA.TextAlign = System.Windows.Forms.HorizontalAlignment.Center; this.TB_AVSPA.Click += new System.EventHandler(this.ClickAV); this.TB_AVSPA.TextChanged += new System.EventHandler(this.UpdateAVs); @@ -767,12 +769,12 @@ namespace PKHeX.WinForms.Controls // TB_GVSPA // this.TB_GVSPA.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; - this.TB_GVSPA.Location = new System.Drawing.Point(131, 0); - this.TB_GVSPA.Margin = new System.Windows.Forms.Padding(3, 0, 3, 0); + this.TB_GVSPA.Location = new System.Drawing.Point(152, 0); + this.TB_GVSPA.Margin = new System.Windows.Forms.Padding(0, 0, 8, 0); this.TB_GVSPA.Mask = "000"; this.TB_GVSPA.Name = "TB_GVSPA"; - this.TB_GVSPA.Size = new System.Drawing.Size(28, 20); - this.TB_GVSPA.TabIndex = 51; + this.TB_GVSPA.Size = new System.Drawing.Size(28, 23); + this.TB_GVSPA.TabIndex = 4; this.TB_GVSPA.TextAlign = System.Windows.Forms.HorizontalAlignment.Center; this.TB_GVSPA.Click += new System.EventHandler(this.ClickGV); this.TB_GVSPA.TextChanged += new System.EventHandler(this.UpdateGVs); @@ -781,13 +783,13 @@ namespace PKHeX.WinForms.Controls // this.Stat_SPA.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; this.Stat_SPA.Enabled = false; - this.Stat_SPA.Location = new System.Drawing.Point(165, 0); - this.Stat_SPA.Margin = new System.Windows.Forms.Padding(3, 0, 3, 0); + this.Stat_SPA.Location = new System.Drawing.Point(188, 0); + this.Stat_SPA.Margin = new System.Windows.Forms.Padding(0); this.Stat_SPA.Mask = "00000"; this.Stat_SPA.Name = "Stat_SPA"; this.Stat_SPA.PromptChar = ' '; - this.Stat_SPA.Size = new System.Drawing.Size(36, 20); - this.Stat_SPA.TabIndex = 48; + this.Stat_SPA.Size = new System.Drawing.Size(40, 23); + this.Stat_SPA.TabIndex = 10; this.Stat_SPA.TextAlign = System.Windows.Forms.HorizontalAlignment.Center; this.Stat_SPA.TextChanged += new System.EventHandler(this.UpdateHackedStatText); // @@ -796,10 +798,10 @@ namespace PKHeX.WinForms.Controls this.FLP_SpD.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right))); this.FLP_SpD.Controls.Add(this.Label_SPD); this.FLP_SpD.Controls.Add(this.FLP_SpDRight); - this.FLP_SpD.Location = new System.Drawing.Point(0, 106); + this.FLP_SpD.Location = new System.Drawing.Point(0, 118); this.FLP_SpD.Margin = new System.Windows.Forms.Padding(0); this.FLP_SpD.Name = "FLP_SpD"; - this.FLP_SpD.Size = new System.Drawing.Size(312, 21); + this.FLP_SpD.Size = new System.Drawing.Size(312, 24); this.FLP_SpD.TabIndex = 127; // // Label_SPD @@ -807,7 +809,7 @@ namespace PKHeX.WinForms.Controls this.Label_SPD.Location = new System.Drawing.Point(0, 0); this.Label_SPD.Margin = new System.Windows.Forms.Padding(0); this.Label_SPD.Name = "Label_SPD"; - this.Label_SPD.Size = new System.Drawing.Size(77, 21); + this.Label_SPD.Size = new System.Drawing.Size(80, 24); this.Label_SPD.TabIndex = 23; this.Label_SPD.Text = "SpD:"; this.Label_SPD.TextAlign = System.Drawing.ContentAlignment.MiddleRight; @@ -816,42 +818,43 @@ namespace PKHeX.WinForms.Controls // FLP_SpDRight // this.FLP_SpDRight.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right))); + this.FLP_SpDRight.AutoSize = true; this.FLP_SpDRight.Controls.Add(this.TB_BaseSPD); this.FLP_SpDRight.Controls.Add(this.TB_IVSPD); this.FLP_SpDRight.Controls.Add(this.TB_EVSPD); this.FLP_SpDRight.Controls.Add(this.TB_AVSPD); this.FLP_SpDRight.Controls.Add(this.TB_GVSPD); this.FLP_SpDRight.Controls.Add(this.Stat_SPD); - this.FLP_SpDRight.Location = new System.Drawing.Point(77, 0); + this.FLP_SpDRight.Location = new System.Drawing.Point(80, 0); this.FLP_SpDRight.Margin = new System.Windows.Forms.Padding(0); this.FLP_SpDRight.Name = "FLP_SpDRight"; - this.FLP_SpDRight.Size = new System.Drawing.Size(217, 21); - this.FLP_SpDRight.TabIndex = 123; + this.FLP_SpDRight.Size = new System.Drawing.Size(228, 23); + this.FLP_SpDRight.TabIndex = 5; // // TB_BaseSPD // this.TB_BaseSPD.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; this.TB_BaseSPD.Enabled = false; this.TB_BaseSPD.Location = new System.Drawing.Point(0, 0); - this.TB_BaseSPD.Margin = new System.Windows.Forms.Padding(0, 0, 7, 0); + this.TB_BaseSPD.Margin = new System.Windows.Forms.Padding(0, 0, 8, 0); this.TB_BaseSPD.Mask = "000"; this.TB_BaseSPD.Name = "TB_BaseSPD"; this.TB_BaseSPD.PromptChar = ' '; this.TB_BaseSPD.ReadOnly = true; - this.TB_BaseSPD.Size = new System.Drawing.Size(28, 20); - this.TB_BaseSPD.TabIndex = 50; + this.TB_BaseSPD.Size = new System.Drawing.Size(32, 23); + this.TB_BaseSPD.TabIndex = 0; this.TB_BaseSPD.TabStop = false; this.TB_BaseSPD.TextAlign = System.Windows.Forms.HorizontalAlignment.Center; // // TB_IVSPD // this.TB_IVSPD.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; - this.TB_IVSPD.Location = new System.Drawing.Point(35, 0); - this.TB_IVSPD.Margin = new System.Windows.Forms.Padding(0, 0, 3, 0); + this.TB_IVSPD.Location = new System.Drawing.Point(40, 0); + this.TB_IVSPD.Margin = new System.Windows.Forms.Padding(0, 0, 8, 0); this.TB_IVSPD.Mask = "00"; this.TB_IVSPD.Name = "TB_IVSPD"; - this.TB_IVSPD.Size = new System.Drawing.Size(22, 20); - this.TB_IVSPD.TabIndex = 5; + this.TB_IVSPD.Size = new System.Drawing.Size(24, 23); + this.TB_IVSPD.TabIndex = 1; this.TB_IVSPD.TextAlign = System.Windows.Forms.HorizontalAlignment.Center; this.TB_IVSPD.Click += new System.EventHandler(this.ClickIV); this.TB_IVSPD.TextChanged += new System.EventHandler(this.UpdateIVs); @@ -859,12 +862,12 @@ namespace PKHeX.WinForms.Controls // TB_EVSPD // this.TB_EVSPD.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; - this.TB_EVSPD.Location = new System.Drawing.Point(63, 0); - this.TB_EVSPD.Margin = new System.Windows.Forms.Padding(3, 0, 3, 0); + this.TB_EVSPD.Location = new System.Drawing.Point(72, 0); + this.TB_EVSPD.Margin = new System.Windows.Forms.Padding(0, 0, 8, 0); this.TB_EVSPD.Mask = "000"; this.TB_EVSPD.Name = "TB_EVSPD"; - this.TB_EVSPD.Size = new System.Drawing.Size(28, 20); - this.TB_EVSPD.TabIndex = 11; + this.TB_EVSPD.Size = new System.Drawing.Size(32, 23); + this.TB_EVSPD.TabIndex = 2; this.TB_EVSPD.TextAlign = System.Windows.Forms.HorizontalAlignment.Center; this.TB_EVSPD.Click += new System.EventHandler(this.ClickEV); this.TB_EVSPD.TextChanged += new System.EventHandler(this.UpdateEVs); @@ -872,12 +875,12 @@ namespace PKHeX.WinForms.Controls // TB_AVSPD // this.TB_AVSPD.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; - this.TB_AVSPD.Location = new System.Drawing.Point(97, 0); - this.TB_AVSPD.Margin = new System.Windows.Forms.Padding(3, 0, 3, 0); + this.TB_AVSPD.Location = new System.Drawing.Point(112, 0); + this.TB_AVSPD.Margin = new System.Windows.Forms.Padding(0, 0, 8, 0); this.TB_AVSPD.Mask = "000"; this.TB_AVSPD.Name = "TB_AVSPD"; - this.TB_AVSPD.Size = new System.Drawing.Size(28, 20); - this.TB_AVSPD.TabIndex = 51; + this.TB_AVSPD.Size = new System.Drawing.Size(32, 23); + this.TB_AVSPD.TabIndex = 3; this.TB_AVSPD.TextAlign = System.Windows.Forms.HorizontalAlignment.Center; this.TB_AVSPD.Click += new System.EventHandler(this.ClickAV); this.TB_AVSPD.TextChanged += new System.EventHandler(this.UpdateAVs); @@ -885,12 +888,12 @@ namespace PKHeX.WinForms.Controls // TB_GVSPD // this.TB_GVSPD.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; - this.TB_GVSPD.Location = new System.Drawing.Point(131, 0); - this.TB_GVSPD.Margin = new System.Windows.Forms.Padding(3, 0, 3, 0); + this.TB_GVSPD.Location = new System.Drawing.Point(152, 0); + this.TB_GVSPD.Margin = new System.Windows.Forms.Padding(0, 0, 8, 0); this.TB_GVSPD.Mask = "000"; this.TB_GVSPD.Name = "TB_GVSPD"; - this.TB_GVSPD.Size = new System.Drawing.Size(28, 20); - this.TB_GVSPD.TabIndex = 52; + this.TB_GVSPD.Size = new System.Drawing.Size(28, 23); + this.TB_GVSPD.TabIndex = 4; this.TB_GVSPD.TextAlign = System.Windows.Forms.HorizontalAlignment.Center; this.TB_GVSPD.Click += new System.EventHandler(this.ClickGV); this.TB_GVSPD.TextChanged += new System.EventHandler(this.UpdateGVs); @@ -899,13 +902,13 @@ namespace PKHeX.WinForms.Controls // this.Stat_SPD.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; this.Stat_SPD.Enabled = false; - this.Stat_SPD.Location = new System.Drawing.Point(165, 0); - this.Stat_SPD.Margin = new System.Windows.Forms.Padding(3, 0, 3, 0); + this.Stat_SPD.Location = new System.Drawing.Point(188, 0); + this.Stat_SPD.Margin = new System.Windows.Forms.Padding(0); this.Stat_SPD.Mask = "00000"; this.Stat_SPD.Name = "Stat_SPD"; this.Stat_SPD.PromptChar = ' '; - this.Stat_SPD.Size = new System.Drawing.Size(36, 20); - this.Stat_SPD.TabIndex = 49; + this.Stat_SPD.Size = new System.Drawing.Size(40, 23); + this.Stat_SPD.TabIndex = 10; this.Stat_SPD.TextAlign = System.Windows.Forms.HorizontalAlignment.Center; this.Stat_SPD.TextChanged += new System.EventHandler(this.UpdateHackedStatText); // @@ -914,10 +917,10 @@ namespace PKHeX.WinForms.Controls this.FLP_Spe.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right))); this.FLP_Spe.Controls.Add(this.Label_SPE); this.FLP_Spe.Controls.Add(this.FLP_SpeRight); - this.FLP_Spe.Location = new System.Drawing.Point(0, 127); + this.FLP_Spe.Location = new System.Drawing.Point(0, 142); this.FLP_Spe.Margin = new System.Windows.Forms.Padding(0); this.FLP_Spe.Name = "FLP_Spe"; - this.FLP_Spe.Size = new System.Drawing.Size(312, 21); + this.FLP_Spe.Size = new System.Drawing.Size(312, 24); this.FLP_Spe.TabIndex = 128; // // Label_SPE @@ -925,7 +928,7 @@ namespace PKHeX.WinForms.Controls this.Label_SPE.Location = new System.Drawing.Point(0, 0); this.Label_SPE.Margin = new System.Windows.Forms.Padding(0); this.Label_SPE.Name = "Label_SPE"; - this.Label_SPE.Size = new System.Drawing.Size(77, 21); + this.Label_SPE.Size = new System.Drawing.Size(80, 24); this.Label_SPE.TabIndex = 24; this.Label_SPE.Text = "Spe:"; this.Label_SPE.TextAlign = System.Drawing.ContentAlignment.MiddleRight; @@ -934,42 +937,43 @@ namespace PKHeX.WinForms.Controls // FLP_SpeRight // this.FLP_SpeRight.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right))); + this.FLP_SpeRight.AutoSize = true; this.FLP_SpeRight.Controls.Add(this.TB_BaseSPE); this.FLP_SpeRight.Controls.Add(this.TB_IVSPE); this.FLP_SpeRight.Controls.Add(this.TB_EVSPE); this.FLP_SpeRight.Controls.Add(this.TB_AVSPE); this.FLP_SpeRight.Controls.Add(this.TB_GVSPE); this.FLP_SpeRight.Controls.Add(this.Stat_SPE); - this.FLP_SpeRight.Location = new System.Drawing.Point(77, 0); + this.FLP_SpeRight.Location = new System.Drawing.Point(80, 0); this.FLP_SpeRight.Margin = new System.Windows.Forms.Padding(0); this.FLP_SpeRight.Name = "FLP_SpeRight"; - this.FLP_SpeRight.Size = new System.Drawing.Size(217, 21); - this.FLP_SpeRight.TabIndex = 123; + this.FLP_SpeRight.Size = new System.Drawing.Size(228, 23); + this.FLP_SpeRight.TabIndex = 6; // // TB_BaseSPE // this.TB_BaseSPE.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; this.TB_BaseSPE.Enabled = false; this.TB_BaseSPE.Location = new System.Drawing.Point(0, 0); - this.TB_BaseSPE.Margin = new System.Windows.Forms.Padding(0, 0, 7, 0); + this.TB_BaseSPE.Margin = new System.Windows.Forms.Padding(0, 0, 8, 0); this.TB_BaseSPE.Mask = "000"; this.TB_BaseSPE.Name = "TB_BaseSPE"; this.TB_BaseSPE.PromptChar = ' '; this.TB_BaseSPE.ReadOnly = true; - this.TB_BaseSPE.Size = new System.Drawing.Size(28, 20); - this.TB_BaseSPE.TabIndex = 51; + this.TB_BaseSPE.Size = new System.Drawing.Size(32, 23); + this.TB_BaseSPE.TabIndex = 0; this.TB_BaseSPE.TabStop = false; this.TB_BaseSPE.TextAlign = System.Windows.Forms.HorizontalAlignment.Center; // // TB_IVSPE // this.TB_IVSPE.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; - this.TB_IVSPE.Location = new System.Drawing.Point(35, 0); - this.TB_IVSPE.Margin = new System.Windows.Forms.Padding(0, 0, 3, 0); + this.TB_IVSPE.Location = new System.Drawing.Point(40, 0); + this.TB_IVSPE.Margin = new System.Windows.Forms.Padding(0, 0, 8, 0); this.TB_IVSPE.Mask = "00"; this.TB_IVSPE.Name = "TB_IVSPE"; - this.TB_IVSPE.Size = new System.Drawing.Size(22, 20); - this.TB_IVSPE.TabIndex = 6; + this.TB_IVSPE.Size = new System.Drawing.Size(24, 23); + this.TB_IVSPE.TabIndex = 1; this.TB_IVSPE.TextAlign = System.Windows.Forms.HorizontalAlignment.Center; this.TB_IVSPE.Click += new System.EventHandler(this.ClickIV); this.TB_IVSPE.TextChanged += new System.EventHandler(this.UpdateIVs); @@ -977,12 +981,12 @@ namespace PKHeX.WinForms.Controls // TB_EVSPE // this.TB_EVSPE.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; - this.TB_EVSPE.Location = new System.Drawing.Point(63, 0); - this.TB_EVSPE.Margin = new System.Windows.Forms.Padding(3, 0, 3, 0); + this.TB_EVSPE.Location = new System.Drawing.Point(72, 0); + this.TB_EVSPE.Margin = new System.Windows.Forms.Padding(0, 0, 8, 0); this.TB_EVSPE.Mask = "000"; this.TB_EVSPE.Name = "TB_EVSPE"; - this.TB_EVSPE.Size = new System.Drawing.Size(28, 20); - this.TB_EVSPE.TabIndex = 12; + this.TB_EVSPE.Size = new System.Drawing.Size(32, 23); + this.TB_EVSPE.TabIndex = 2; this.TB_EVSPE.TextAlign = System.Windows.Forms.HorizontalAlignment.Center; this.TB_EVSPE.Click += new System.EventHandler(this.ClickEV); this.TB_EVSPE.TextChanged += new System.EventHandler(this.UpdateEVs); @@ -990,12 +994,12 @@ namespace PKHeX.WinForms.Controls // TB_AVSPE // this.TB_AVSPE.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; - this.TB_AVSPE.Location = new System.Drawing.Point(97, 0); - this.TB_AVSPE.Margin = new System.Windows.Forms.Padding(3, 0, 3, 0); + this.TB_AVSPE.Location = new System.Drawing.Point(112, 0); + this.TB_AVSPE.Margin = new System.Windows.Forms.Padding(0, 0, 8, 0); this.TB_AVSPE.Mask = "000"; this.TB_AVSPE.Name = "TB_AVSPE"; - this.TB_AVSPE.Size = new System.Drawing.Size(28, 20); - this.TB_AVSPE.TabIndex = 52; + this.TB_AVSPE.Size = new System.Drawing.Size(32, 23); + this.TB_AVSPE.TabIndex = 3; this.TB_AVSPE.TextAlign = System.Windows.Forms.HorizontalAlignment.Center; this.TB_AVSPE.Click += new System.EventHandler(this.ClickAV); this.TB_AVSPE.TextChanged += new System.EventHandler(this.UpdateAVs); @@ -1003,12 +1007,12 @@ namespace PKHeX.WinForms.Controls // TB_GVSPE // this.TB_GVSPE.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; - this.TB_GVSPE.Location = new System.Drawing.Point(131, 0); - this.TB_GVSPE.Margin = new System.Windows.Forms.Padding(3, 0, 3, 0); + this.TB_GVSPE.Location = new System.Drawing.Point(152, 0); + this.TB_GVSPE.Margin = new System.Windows.Forms.Padding(0, 0, 8, 0); this.TB_GVSPE.Mask = "000"; this.TB_GVSPE.Name = "TB_GVSPE"; - this.TB_GVSPE.Size = new System.Drawing.Size(28, 20); - this.TB_GVSPE.TabIndex = 53; + this.TB_GVSPE.Size = new System.Drawing.Size(28, 23); + this.TB_GVSPE.TabIndex = 4; this.TB_GVSPE.TextAlign = System.Windows.Forms.HorizontalAlignment.Center; this.TB_GVSPE.Click += new System.EventHandler(this.ClickGV); this.TB_GVSPE.TextChanged += new System.EventHandler(this.UpdateGVs); @@ -1017,25 +1021,26 @@ namespace PKHeX.WinForms.Controls // this.Stat_SPE.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; this.Stat_SPE.Enabled = false; - this.Stat_SPE.Location = new System.Drawing.Point(165, 0); - this.Stat_SPE.Margin = new System.Windows.Forms.Padding(3, 0, 3, 0); + this.Stat_SPE.Location = new System.Drawing.Point(188, 0); + this.Stat_SPE.Margin = new System.Windows.Forms.Padding(0); this.Stat_SPE.Mask = "00000"; this.Stat_SPE.Name = "Stat_SPE"; this.Stat_SPE.PromptChar = ' '; - this.Stat_SPE.Size = new System.Drawing.Size(36, 20); - this.Stat_SPE.TabIndex = 50; + this.Stat_SPE.Size = new System.Drawing.Size(40, 23); + this.Stat_SPE.TabIndex = 10; this.Stat_SPE.TextAlign = System.Windows.Forms.HorizontalAlignment.Center; this.Stat_SPE.TextChanged += new System.EventHandler(this.UpdateHackedStatText); // // FLP_StatsTotal // this.FLP_StatsTotal.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right))); + this.FLP_StatsTotal.AutoSize = true; this.FLP_StatsTotal.Controls.Add(this.Label_Total); this.FLP_StatsTotal.Controls.Add(this.FLP_StatsTotalRight); - this.FLP_StatsTotal.Location = new System.Drawing.Point(0, 148); - this.FLP_StatsTotal.Margin = new System.Windows.Forms.Padding(0); + this.FLP_StatsTotal.Location = new System.Drawing.Point(0, 166); + this.FLP_StatsTotal.Margin = new System.Windows.Forms.Padding(0, 0, 0, 8); this.FLP_StatsTotal.Name = "FLP_StatsTotal"; - this.FLP_StatsTotal.Size = new System.Drawing.Size(312, 21); + this.FLP_StatsTotal.Size = new System.Drawing.Size(288, 24); this.FLP_StatsTotal.TabIndex = 129; // // Label_Total @@ -1043,7 +1048,7 @@ namespace PKHeX.WinForms.Controls this.Label_Total.Location = new System.Drawing.Point(0, 0); this.Label_Total.Margin = new System.Windows.Forms.Padding(0); this.Label_Total.Name = "Label_Total"; - this.Label_Total.Size = new System.Drawing.Size(77, 21); + this.Label_Total.Size = new System.Drawing.Size(80, 24); this.Label_Total.TabIndex = 25; this.Label_Total.Text = "Total:"; this.Label_Total.TextAlign = System.Drawing.ContentAlignment.MiddleRight; @@ -1051,40 +1056,41 @@ namespace PKHeX.WinForms.Controls // FLP_StatsTotalRight // this.FLP_StatsTotalRight.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right))); + this.FLP_StatsTotalRight.AutoSize = true; this.FLP_StatsTotalRight.Controls.Add(this.TB_BST); this.FLP_StatsTotalRight.Controls.Add(this.TB_IVTotal); this.FLP_StatsTotalRight.Controls.Add(this.TB_EVTotal); this.FLP_StatsTotalRight.Controls.Add(this.TB_AVTotal); this.FLP_StatsTotalRight.Controls.Add(this.L_Potential); - this.FLP_StatsTotalRight.Location = new System.Drawing.Point(77, 0); + this.FLP_StatsTotalRight.Location = new System.Drawing.Point(80, 0); this.FLP_StatsTotalRight.Margin = new System.Windows.Forms.Padding(0); this.FLP_StatsTotalRight.Name = "FLP_StatsTotalRight"; - this.FLP_StatsTotalRight.Size = new System.Drawing.Size(190, 21); - this.FLP_StatsTotalRight.TabIndex = 123; + this.FLP_StatsTotalRight.Size = new System.Drawing.Size(208, 24); + this.FLP_StatsTotalRight.TabIndex = 7; // // TB_BST // this.TB_BST.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; this.TB_BST.Enabled = false; this.TB_BST.Location = new System.Drawing.Point(0, 0); - this.TB_BST.Margin = new System.Windows.Forms.Padding(0, 0, 7, 0); + this.TB_BST.Margin = new System.Windows.Forms.Padding(0, 0, 8, 0); this.TB_BST.MaxLength = 3; this.TB_BST.Name = "TB_BST"; this.TB_BST.ReadOnly = true; - this.TB_BST.Size = new System.Drawing.Size(28, 20); - this.TB_BST.TabIndex = 43; + this.TB_BST.Size = new System.Drawing.Size(32, 23); + this.TB_BST.TabIndex = 0; this.TB_BST.TabStop = false; this.TB_BST.TextAlign = System.Windows.Forms.HorizontalAlignment.Center; // // TB_IVTotal // this.TB_IVTotal.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; - this.TB_IVTotal.Location = new System.Drawing.Point(35, 0); - this.TB_IVTotal.Margin = new System.Windows.Forms.Padding(0, 0, 3, 0); - this.TB_IVTotal.MaxLength = 3; + this.TB_IVTotal.Location = new System.Drawing.Point(40, 0); + this.TB_IVTotal.Margin = new System.Windows.Forms.Padding(0, 0, 8, 0); + this.TB_IVTotal.MaxLength = 1; this.TB_IVTotal.Name = "TB_IVTotal"; this.TB_IVTotal.ReadOnly = true; - this.TB_IVTotal.Size = new System.Drawing.Size(22, 20); + this.TB_IVTotal.Size = new System.Drawing.Size(24, 23); this.TB_IVTotal.TabIndex = 41; this.TB_IVTotal.TabStop = false; this.TB_IVTotal.TextAlign = System.Windows.Forms.HorizontalAlignment.Center; @@ -1092,12 +1098,12 @@ namespace PKHeX.WinForms.Controls // TB_EVTotal // this.TB_EVTotal.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; - this.TB_EVTotal.Location = new System.Drawing.Point(63, 0); - this.TB_EVTotal.Margin = new System.Windows.Forms.Padding(3, 0, 3, 0); - this.TB_EVTotal.MaxLength = 3; + this.TB_EVTotal.Location = new System.Drawing.Point(72, 0); + this.TB_EVTotal.Margin = new System.Windows.Forms.Padding(0, 0, 8, 0); + this.TB_EVTotal.MaxLength = 4; this.TB_EVTotal.Name = "TB_EVTotal"; this.TB_EVTotal.ReadOnly = true; - this.TB_EVTotal.Size = new System.Drawing.Size(28, 20); + this.TB_EVTotal.Size = new System.Drawing.Size(32, 23); this.TB_EVTotal.TabIndex = 18; this.TB_EVTotal.TabStop = false; this.TB_EVTotal.TextAlign = System.Windows.Forms.HorizontalAlignment.Center; @@ -1105,45 +1111,46 @@ namespace PKHeX.WinForms.Controls // TB_AVTotal // this.TB_AVTotal.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; - this.TB_AVTotal.Location = new System.Drawing.Point(97, 0); - this.TB_AVTotal.Margin = new System.Windows.Forms.Padding(3, 0, 3, 0); - this.TB_AVTotal.MaxLength = 3; + this.TB_AVTotal.Location = new System.Drawing.Point(112, 0); + this.TB_AVTotal.Margin = new System.Windows.Forms.Padding(0, 0, 8, 0); + this.TB_AVTotal.MaxLength = 4; this.TB_AVTotal.Name = "TB_AVTotal"; this.TB_AVTotal.ReadOnly = true; - this.TB_AVTotal.Size = new System.Drawing.Size(28, 20); - this.TB_AVTotal.TabIndex = 44; + this.TB_AVTotal.Size = new System.Drawing.Size(32, 23); + this.TB_AVTotal.TabIndex = 3; this.TB_AVTotal.TabStop = false; this.TB_AVTotal.TextAlign = System.Windows.Forms.HorizontalAlignment.Center; // // L_Potential // - this.L_Potential.Font = new System.Drawing.Font("Microsoft Sans Serif", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); - this.L_Potential.Location = new System.Drawing.Point(0, 20); + this.L_Potential.Font = new System.Drawing.Font("Courier New", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); + this.L_Potential.Location = new System.Drawing.Point(152, 0); this.L_Potential.Margin = new System.Windows.Forms.Padding(0); this.L_Potential.Name = "L_Potential"; - this.L_Potential.Size = new System.Drawing.Size(96, 21); + this.L_Potential.Size = new System.Drawing.Size(56, 24); this.L_Potential.TabIndex = 42; - this.L_Potential.Text = "(potential)"; + this.L_Potential.Text = "12345"; this.L_Potential.TextAlign = System.Drawing.ContentAlignment.MiddleLeft; // // FLP_HPType // this.FLP_HPType.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right))); + this.FLP_HPType.AutoSize = true; this.FLP_HPType.Controls.Add(this.Label_HiddenPowerPrefix); this.FLP_HPType.Controls.Add(this.CB_HPType); this.FLP_HPType.Controls.Add(this.Label_HiddenPowerPower); - this.FLP_HPType.Location = new System.Drawing.Point(0, 169); + this.FLP_HPType.Location = new System.Drawing.Point(0, 198); this.FLP_HPType.Margin = new System.Windows.Forms.Padding(0); this.FLP_HPType.Name = "FLP_HPType"; - this.FLP_HPType.Size = new System.Drawing.Size(279, 21); - this.FLP_HPType.TabIndex = 130; + this.FLP_HPType.Size = new System.Drawing.Size(256, 24); + this.FLP_HPType.TabIndex = 10; // // Label_HiddenPowerPrefix // this.Label_HiddenPowerPrefix.Location = new System.Drawing.Point(0, 0); this.Label_HiddenPowerPrefix.Margin = new System.Windows.Forms.Padding(0); this.Label_HiddenPowerPrefix.Name = "Label_HiddenPowerPrefix"; - this.Label_HiddenPowerPrefix.Size = new System.Drawing.Size(140, 21); + this.Label_HiddenPowerPrefix.Size = new System.Drawing.Size(152, 24); this.Label_HiddenPowerPrefix.TabIndex = 29; this.Label_HiddenPowerPrefix.Text = "Hidden Power Type:"; this.Label_HiddenPowerPrefix.TextAlign = System.Drawing.ContentAlignment.MiddleRight; @@ -1153,10 +1160,10 @@ namespace PKHeX.WinForms.Controls this.CB_HPType.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; this.CB_HPType.DropDownWidth = 80; this.CB_HPType.FormattingEnabled = true; - this.CB_HPType.Location = new System.Drawing.Point(140, 0); + this.CB_HPType.Location = new System.Drawing.Point(152, 0); this.CB_HPType.Margin = new System.Windows.Forms.Padding(0); this.CB_HPType.Name = "CB_HPType"; - this.CB_HPType.Size = new System.Drawing.Size(70, 21); + this.CB_HPType.Size = new System.Drawing.Size(72, 23); this.CB_HPType.TabIndex = 44; this.CB_HPType.SelectedIndexChanged += new System.EventHandler(this.UpdateHPType); // @@ -1164,10 +1171,10 @@ namespace PKHeX.WinForms.Controls // this.Label_HiddenPowerPower.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) | System.Windows.Forms.AnchorStyles.Right))); - this.Label_HiddenPowerPower.Location = new System.Drawing.Point(210, 0); + this.Label_HiddenPowerPower.Location = new System.Drawing.Point(224, 0); this.Label_HiddenPowerPower.Margin = new System.Windows.Forms.Padding(0); this.Label_HiddenPowerPower.Name = "Label_HiddenPowerPower"; - this.Label_HiddenPowerPower.Size = new System.Drawing.Size(28, 21); + this.Label_HiddenPowerPower.Size = new System.Drawing.Size(32, 24); this.Label_HiddenPowerPower.TabIndex = 29; this.Label_HiddenPowerPower.Text = "60"; this.Label_HiddenPowerPower.TextAlign = System.Drawing.ContentAlignment.MiddleLeft; @@ -1175,30 +1182,31 @@ namespace PKHeX.WinForms.Controls // FLP_Characteristic // this.FLP_Characteristic.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right))); + this.FLP_Characteristic.AutoSize = true; this.FLP_Characteristic.Controls.Add(this.Label_CharacteristicPrefix); this.FLP_Characteristic.Controls.Add(this.L_Characteristic); - this.FLP_Characteristic.Location = new System.Drawing.Point(0, 190); - this.FLP_Characteristic.Margin = new System.Windows.Forms.Padding(0); + this.FLP_Characteristic.Location = new System.Drawing.Point(0, 222); + this.FLP_Characteristic.Margin = new System.Windows.Forms.Padding(0, 0, 0, 8); this.FLP_Characteristic.Name = "FLP_Characteristic"; - this.FLP_Characteristic.Size = new System.Drawing.Size(272, 21); - this.FLP_Characteristic.TabIndex = 131; + this.FLP_Characteristic.Size = new System.Drawing.Size(280, 24); + this.FLP_Characteristic.TabIndex = 11; // // Label_CharacteristicPrefix // this.Label_CharacteristicPrefix.Location = new System.Drawing.Point(0, 0); this.Label_CharacteristicPrefix.Margin = new System.Windows.Forms.Padding(0); this.Label_CharacteristicPrefix.Name = "Label_CharacteristicPrefix"; - this.Label_CharacteristicPrefix.Size = new System.Drawing.Size(110, 21); + this.Label_CharacteristicPrefix.Size = new System.Drawing.Size(112, 24); this.Label_CharacteristicPrefix.TabIndex = 43; this.Label_CharacteristicPrefix.Text = "Characteristic:"; this.Label_CharacteristicPrefix.TextAlign = System.Drawing.ContentAlignment.MiddleRight; // // L_Characteristic // - this.L_Characteristic.Location = new System.Drawing.Point(110, 0); + this.L_Characteristic.Location = new System.Drawing.Point(112, 0); this.L_Characteristic.Margin = new System.Windows.Forms.Padding(0); this.L_Characteristic.Name = "L_Characteristic"; - this.L_Characteristic.Size = new System.Drawing.Size(150, 21); + this.L_Characteristic.Size = new System.Drawing.Size(168, 24); this.L_Characteristic.TabIndex = 40; this.L_Characteristic.Text = "(char)"; this.L_Characteristic.TextAlign = System.Drawing.ContentAlignment.MiddleLeft; @@ -1208,11 +1216,11 @@ namespace PKHeX.WinForms.Controls this.FLP_TeraType.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right))); this.FLP_TeraType.Controls.Add(this.FLP_TeraInner); this.FLP_TeraType.Controls.Add(this.PB_TeraType); - this.FLP_TeraType.Location = new System.Drawing.Point(0, 211); - this.FLP_TeraType.Margin = new System.Windows.Forms.Padding(0); + this.FLP_TeraType.Location = new System.Drawing.Point(0, 254); + this.FLP_TeraType.Margin = new System.Windows.Forms.Padding(0, 0, 0, 8); this.FLP_TeraType.Name = "FLP_TeraType"; - this.FLP_TeraType.Size = new System.Drawing.Size(312, 61); - this.FLP_TeraType.TabIndex = 135; + this.FLP_TeraType.Size = new System.Drawing.Size(312, 64); + this.FLP_TeraType.TabIndex = 12; // // FLP_TeraInner // @@ -1237,15 +1245,15 @@ namespace PKHeX.WinForms.Controls this.FLP_TeraTypeDefaultPane.Location = new System.Drawing.Point(0, 0); this.FLP_TeraTypeDefaultPane.Margin = new System.Windows.Forms.Padding(0); this.FLP_TeraTypeDefaultPane.Name = "FLP_TeraTypeDefaultPane"; - this.FLP_TeraTypeDefaultPane.Size = new System.Drawing.Size(210, 10); + this.FLP_TeraTypeDefaultPane.Size = new System.Drawing.Size(208, 8); this.FLP_TeraTypeDefaultPane.TabIndex = 137; // // PB_TeraType2 // - this.PB_TeraType2.Location = new System.Drawing.Point(175, 0); + this.PB_TeraType2.Location = new System.Drawing.Point(168, 0); this.PB_TeraType2.Margin = new System.Windows.Forms.Padding(0); this.PB_TeraType2.Name = "PB_TeraType2"; - this.PB_TeraType2.Size = new System.Drawing.Size(35, 10); + this.PB_TeraType2.Size = new System.Drawing.Size(40, 8); this.PB_TeraType2.SizeMode = System.Windows.Forms.PictureBoxSizeMode.Zoom; this.PB_TeraType2.TabIndex = 46; this.PB_TeraType2.TabStop = false; @@ -1253,10 +1261,10 @@ namespace PKHeX.WinForms.Controls // // PB_TeraType1 // - this.PB_TeraType1.Location = new System.Drawing.Point(140, 0); + this.PB_TeraType1.Location = new System.Drawing.Point(128, 0); this.PB_TeraType1.Margin = new System.Windows.Forms.Padding(0); this.PB_TeraType1.Name = "PB_TeraType1"; - this.PB_TeraType1.Size = new System.Drawing.Size(35, 10); + this.PB_TeraType1.Size = new System.Drawing.Size(40, 8); this.PB_TeraType1.SizeMode = System.Windows.Forms.PictureBoxSizeMode.Zoom; this.PB_TeraType1.TabIndex = 47; this.PB_TeraType1.TabStop = false; @@ -1264,11 +1272,11 @@ namespace PKHeX.WinForms.Controls // // L_TeraTypeOriginal // - this.L_TeraTypeOriginal.Location = new System.Drawing.Point(0, 10); + this.L_TeraTypeOriginal.Location = new System.Drawing.Point(0, 8); this.L_TeraTypeOriginal.Margin = new System.Windows.Forms.Padding(0); this.L_TeraTypeOriginal.Name = "L_TeraTypeOriginal"; - this.L_TeraTypeOriginal.Size = new System.Drawing.Size(140, 21); - this.L_TeraTypeOriginal.TabIndex = 29; + this.L_TeraTypeOriginal.Size = new System.Drawing.Size(128, 21); + this.L_TeraTypeOriginal.TabIndex = 0; this.L_TeraTypeOriginal.Text = "Original Tera Type:"; this.L_TeraTypeOriginal.TextAlign = System.Drawing.ContentAlignment.MiddleRight; this.L_TeraTypeOriginal.Click += new System.EventHandler(this.L_TeraTypeOriginal_Click); @@ -1278,11 +1286,11 @@ namespace PKHeX.WinForms.Controls this.CB_TeraTypeOriginal.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; this.CB_TeraTypeOriginal.DropDownWidth = 80; this.CB_TeraTypeOriginal.FormattingEnabled = true; - this.CB_TeraTypeOriginal.Location = new System.Drawing.Point(140, 10); + this.CB_TeraTypeOriginal.Location = new System.Drawing.Point(128, 8); this.CB_TeraTypeOriginal.Margin = new System.Windows.Forms.Padding(0); this.CB_TeraTypeOriginal.Name = "CB_TeraTypeOriginal"; - this.CB_TeraTypeOriginal.Size = new System.Drawing.Size(70, 21); - this.CB_TeraTypeOriginal.TabIndex = 44; + this.CB_TeraTypeOriginal.Size = new System.Drawing.Size(80, 23); + this.CB_TeraTypeOriginal.TabIndex = 1; this.CB_TeraTypeOriginal.SelectedIndexChanged += new System.EventHandler(this.ChangeTeraType); // // L_TeraTypeOverride @@ -1290,8 +1298,8 @@ namespace PKHeX.WinForms.Controls this.L_TeraTypeOverride.Location = new System.Drawing.Point(0, 31); this.L_TeraTypeOverride.Margin = new System.Windows.Forms.Padding(0); this.L_TeraTypeOverride.Name = "L_TeraTypeOverride"; - this.L_TeraTypeOverride.Size = new System.Drawing.Size(140, 21); - this.L_TeraTypeOverride.TabIndex = 29; + this.L_TeraTypeOverride.Size = new System.Drawing.Size(128, 21); + this.L_TeraTypeOverride.TabIndex = 10; this.L_TeraTypeOverride.Text = "Override Tera Type:"; this.L_TeraTypeOverride.TextAlign = System.Drawing.ContentAlignment.MiddleRight; this.L_TeraTypeOverride.Click += new System.EventHandler(this.L_TeraTypeOverride_Click); @@ -1301,11 +1309,11 @@ namespace PKHeX.WinForms.Controls this.CB_TeraTypeOverride.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; this.CB_TeraTypeOverride.DropDownWidth = 80; this.CB_TeraTypeOverride.FormattingEnabled = true; - this.CB_TeraTypeOverride.Location = new System.Drawing.Point(140, 31); + this.CB_TeraTypeOverride.Location = new System.Drawing.Point(128, 31); this.CB_TeraTypeOverride.Margin = new System.Windows.Forms.Padding(0); this.CB_TeraTypeOverride.Name = "CB_TeraTypeOverride"; - this.CB_TeraTypeOverride.Size = new System.Drawing.Size(70, 21); - this.CB_TeraTypeOverride.TabIndex = 44; + this.CB_TeraTypeOverride.Size = new System.Drawing.Size(80, 23); + this.CB_TeraTypeOverride.TabIndex = 11; this.CB_TeraTypeOverride.SelectedIndexChanged += new System.EventHandler(this.ChangeTeraType); // // PB_TeraType @@ -1313,7 +1321,7 @@ namespace PKHeX.WinForms.Controls this.PB_TeraType.Location = new System.Drawing.Point(214, 0); this.PB_TeraType.Margin = new System.Windows.Forms.Padding(0); this.PB_TeraType.Name = "PB_TeraType"; - this.PB_TeraType.Size = new System.Drawing.Size(60, 60); + this.PB_TeraType.Size = new System.Drawing.Size(64, 64); this.PB_TeraType.SizeMode = System.Windows.Forms.PictureBoxSizeMode.Zoom; this.PB_TeraType.TabIndex = 45; this.PB_TeraType.TabStop = false; @@ -1324,37 +1332,39 @@ namespace PKHeX.WinForms.Controls this.PAN_BTN.Controls.Add(this.BTN_RandomAVs); this.PAN_BTN.Controls.Add(this.BTN_RandomIVs); this.PAN_BTN.Controls.Add(this.BTN_RandomEVs); - this.PAN_BTN.Location = new System.Drawing.Point(3, 275); + this.PAN_BTN.Location = new System.Drawing.Point(0, 326); + this.PAN_BTN.Margin = new System.Windows.Forms.Padding(0, 0, 0, 8); this.PAN_BTN.Name = "PAN_BTN"; - this.PAN_BTN.Size = new System.Drawing.Size(267, 31); - this.PAN_BTN.TabIndex = 132; + this.PAN_BTN.Size = new System.Drawing.Size(288, 24); + this.PAN_BTN.TabIndex = 20; // // BTN_RandomAVs // - this.BTN_RandomAVs.Location = new System.Drawing.Point(137, 3); + this.BTN_RandomAVs.Location = new System.Drawing.Point(136, 0); this.BTN_RandomAVs.Name = "BTN_RandomAVs"; - this.BTN_RandomAVs.Size = new System.Drawing.Size(92, 23); - this.BTN_RandomAVs.TabIndex = 106; + this.BTN_RandomAVs.Size = new System.Drawing.Size(104, 24); + this.BTN_RandomAVs.TabIndex = 3; this.BTN_RandomAVs.Text = "Randomize AVs"; this.BTN_RandomAVs.UseVisualStyleBackColor = true; this.BTN_RandomAVs.Click += new System.EventHandler(this.UpdateRandomAVs); // // BTN_RandomIVs // - this.BTN_RandomIVs.Location = new System.Drawing.Point(38, 3); + this.BTN_RandomIVs.Location = new System.Drawing.Point(32, 0); + this.BTN_RandomIVs.Margin = new System.Windows.Forms.Padding(0); this.BTN_RandomIVs.Name = "BTN_RandomIVs"; - this.BTN_RandomIVs.Size = new System.Drawing.Size(92, 23); - this.BTN_RandomIVs.TabIndex = 104; + this.BTN_RandomIVs.Size = new System.Drawing.Size(104, 24); + this.BTN_RandomIVs.TabIndex = 0; this.BTN_RandomIVs.Text = "Randomize IVs"; this.BTN_RandomIVs.UseVisualStyleBackColor = true; this.BTN_RandomIVs.Click += new System.EventHandler(this.UpdateRandomIVs); // // BTN_RandomEVs // - this.BTN_RandomEVs.Location = new System.Drawing.Point(137, 3); + this.BTN_RandomEVs.Location = new System.Drawing.Point(136, 0); this.BTN_RandomEVs.Name = "BTN_RandomEVs"; - this.BTN_RandomEVs.Size = new System.Drawing.Size(92, 23); - this.BTN_RandomEVs.TabIndex = 105; + this.BTN_RandomEVs.Size = new System.Drawing.Size(104, 24); + this.BTN_RandomEVs.TabIndex = 2; this.BTN_RandomEVs.Text = "Randomize EVs"; this.BTN_RandomEVs.UseVisualStyleBackColor = true; this.BTN_RandomEVs.Click += new System.EventHandler(this.UpdateRandomEVs); @@ -1365,19 +1375,19 @@ namespace PKHeX.WinForms.Controls this.FLP_DynamaxLevel.Controls.Add(this.L_DynamaxLevel); this.FLP_DynamaxLevel.Controls.Add(this.CB_DynamaxLevel); this.FLP_DynamaxLevel.Controls.Add(this.CHK_Gigantamax); - this.FLP_DynamaxLevel.Location = new System.Drawing.Point(0, 309); + this.FLP_DynamaxLevel.Location = new System.Drawing.Point(0, 358); this.FLP_DynamaxLevel.Margin = new System.Windows.Forms.Padding(0); this.FLP_DynamaxLevel.Name = "FLP_DynamaxLevel"; - this.FLP_DynamaxLevel.Size = new System.Drawing.Size(272, 21); - this.FLP_DynamaxLevel.TabIndex = 133; + this.FLP_DynamaxLevel.Size = new System.Drawing.Size(272, 24); + this.FLP_DynamaxLevel.TabIndex = 30; // // L_DynamaxLevel // this.L_DynamaxLevel.Location = new System.Drawing.Point(0, 0); this.L_DynamaxLevel.Margin = new System.Windows.Forms.Padding(0); this.L_DynamaxLevel.Name = "L_DynamaxLevel"; - this.L_DynamaxLevel.Size = new System.Drawing.Size(120, 21); - this.L_DynamaxLevel.TabIndex = 43; + this.L_DynamaxLevel.Size = new System.Drawing.Size(120, 24); + this.L_DynamaxLevel.TabIndex = 0; this.L_DynamaxLevel.Text = "Dynamax Level:"; this.L_DynamaxLevel.TextAlign = System.Drawing.ContentAlignment.MiddleRight; this.L_DynamaxLevel.Click += new System.EventHandler(this.L_DynamaxLevel_Click); @@ -1401,16 +1411,16 @@ namespace PKHeX.WinForms.Controls this.CB_DynamaxLevel.Location = new System.Drawing.Point(120, 0); this.CB_DynamaxLevel.Margin = new System.Windows.Forms.Padding(0); this.CB_DynamaxLevel.Name = "CB_DynamaxLevel"; - this.CB_DynamaxLevel.Size = new System.Drawing.Size(40, 21); - this.CB_DynamaxLevel.TabIndex = 44; + this.CB_DynamaxLevel.Size = new System.Drawing.Size(40, 23); + this.CB_DynamaxLevel.TabIndex = 1; // // CHK_Gigantamax // this.CHK_Gigantamax.AutoSize = true; this.CHK_Gigantamax.Location = new System.Drawing.Point(163, 3); this.CHK_Gigantamax.Name = "CHK_Gigantamax"; - this.CHK_Gigantamax.Size = new System.Drawing.Size(82, 17); - this.CHK_Gigantamax.TabIndex = 44; + this.CHK_Gigantamax.Size = new System.Drawing.Size(90, 19); + this.CHK_Gigantamax.TabIndex = 2; this.CHK_Gigantamax.Text = "Gigantamax"; this.CHK_Gigantamax.UseVisualStyleBackColor = true; this.CHK_Gigantamax.CheckedChanged += new System.EventHandler(this.CHK_Gigantamax_CheckedChanged); @@ -1420,32 +1430,30 @@ namespace PKHeX.WinForms.Controls this.FLP_AlphaNoble.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right))); this.FLP_AlphaNoble.Controls.Add(this.CHK_IsAlpha); this.FLP_AlphaNoble.Controls.Add(this.CHK_IsNoble); - this.FLP_AlphaNoble.Location = new System.Drawing.Point(0, 330); - this.FLP_AlphaNoble.Margin = new System.Windows.Forms.Padding(0); + this.FLP_AlphaNoble.Location = new System.Drawing.Point(80, 382); + this.FLP_AlphaNoble.Margin = new System.Windows.Forms.Padding(80, 0, 0, 0); this.FLP_AlphaNoble.Name = "FLP_AlphaNoble"; - this.FLP_AlphaNoble.Size = new System.Drawing.Size(270, 31); - this.FLP_AlphaNoble.TabIndex = 134; + this.FLP_AlphaNoble.Size = new System.Drawing.Size(176, 24); + this.FLP_AlphaNoble.TabIndex = 40; // // CHK_IsAlpha // - this.CHK_IsAlpha.AutoSize = true; - this.CHK_IsAlpha.Location = new System.Drawing.Point(95, 8); - this.CHK_IsAlpha.Margin = new System.Windows.Forms.Padding(95, 8, 3, 3); + this.CHK_IsAlpha.Location = new System.Drawing.Point(0, 0); + this.CHK_IsAlpha.Margin = new System.Windows.Forms.Padding(0); this.CHK_IsAlpha.Name = "CHK_IsAlpha"; - this.CHK_IsAlpha.Size = new System.Drawing.Size(53, 17); - this.CHK_IsAlpha.TabIndex = 44; + this.CHK_IsAlpha.Size = new System.Drawing.Size(72, 24); + this.CHK_IsAlpha.TabIndex = 0; this.CHK_IsAlpha.Text = "Alpha"; this.CHK_IsAlpha.UseVisualStyleBackColor = true; this.CHK_IsAlpha.CheckedChanged += new System.EventHandler(this.CHK_IsAlpha_CheckedChanged); // // CHK_IsNoble // - this.CHK_IsNoble.AutoSize = true; - this.CHK_IsNoble.Location = new System.Drawing.Point(154, 8); - this.CHK_IsNoble.Margin = new System.Windows.Forms.Padding(3, 8, 3, 3); + this.CHK_IsNoble.Location = new System.Drawing.Point(72, 0); + this.CHK_IsNoble.Margin = new System.Windows.Forms.Padding(0); this.CHK_IsNoble.Name = "CHK_IsNoble"; - this.CHK_IsNoble.Size = new System.Drawing.Size(54, 17); - this.CHK_IsNoble.TabIndex = 44; + this.CHK_IsNoble.Size = new System.Drawing.Size(72, 24); + this.CHK_IsNoble.TabIndex = 1; this.CHK_IsNoble.Text = "Noble"; this.CHK_IsNoble.UseVisualStyleBackColor = true; // @@ -1454,31 +1462,39 @@ namespace PKHeX.WinForms.Controls this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Inherit; this.Controls.Add(this.FLP_Stats); this.Name = "StatEditor"; - this.Size = new System.Drawing.Size(312, 381); + this.Size = new System.Drawing.Size(320, 400); this.FLP_Stats.ResumeLayout(false); + this.FLP_Stats.PerformLayout(); this.FLP_StatHeader.ResumeLayout(false); this.FLP_HackedStats.ResumeLayout(false); this.FLP_StatsHeaderRight.ResumeLayout(false); this.FLP_HP.ResumeLayout(false); + this.FLP_HP.PerformLayout(); this.FLP_HPRight.ResumeLayout(false); this.FLP_HPRight.PerformLayout(); this.FLP_Atk.ResumeLayout(false); + this.FLP_Atk.PerformLayout(); this.FLP_AtkRight.ResumeLayout(false); this.FLP_AtkRight.PerformLayout(); this.FLP_Def.ResumeLayout(false); + this.FLP_Def.PerformLayout(); this.FLP_DefRight.ResumeLayout(false); this.FLP_DefRight.PerformLayout(); this.FLP_SpA.ResumeLayout(false); + this.FLP_SpA.PerformLayout(); this.FLP_SpALeft.ResumeLayout(false); this.FLP_SpARight.ResumeLayout(false); this.FLP_SpARight.PerformLayout(); this.FLP_SpD.ResumeLayout(false); + this.FLP_SpD.PerformLayout(); this.FLP_SpDRight.ResumeLayout(false); this.FLP_SpDRight.PerformLayout(); this.FLP_Spe.ResumeLayout(false); + this.FLP_Spe.PerformLayout(); this.FLP_SpeRight.ResumeLayout(false); this.FLP_SpeRight.PerformLayout(); this.FLP_StatsTotal.ResumeLayout(false); + this.FLP_StatsTotal.PerformLayout(); this.FLP_StatsTotalRight.ResumeLayout(false); this.FLP_StatsTotalRight.PerformLayout(); this.FLP_HPType.ResumeLayout(false); @@ -1493,7 +1509,6 @@ namespace PKHeX.WinForms.Controls this.FLP_DynamaxLevel.ResumeLayout(false); this.FLP_DynamaxLevel.PerformLayout(); this.FLP_AlphaNoble.ResumeLayout(false); - this.FLP_AlphaNoble.PerformLayout(); this.ResumeLayout(false); } @@ -1579,7 +1594,6 @@ namespace PKHeX.WinForms.Controls private System.Windows.Forms.MaskedTextBox TB_AVSPE; private System.Windows.Forms.TextBox TB_AVTotal; private System.Windows.Forms.Button BTN_RandomAVs; - private System.Windows.Forms.ToolTip EVTip; private System.Windows.Forms.FlowLayoutPanel FLP_DynamaxLevel; private System.Windows.Forms.Label L_DynamaxLevel; public System.Windows.Forms.ComboBox CB_DynamaxLevel; diff --git a/PKHeX.WinForms/Controls/PKM Editor/StatEditor.cs b/PKHeX.WinForms/Controls/PKM Editor/StatEditor.cs index a287daa1a..19a7c3ac2 100644 --- a/PKHeX.WinForms/Controls/PKM Editor/StatEditor.cs +++ b/PKHeX.WinForms/Controls/PKM Editor/StatEditor.cs @@ -35,6 +35,8 @@ public partial class StatEditor : UserControl public IMainEditor MainEditor { private get; set; } = null!; public bool HaX { get => CHK_HackedStats.Enabled; set => CHK_HackedStats.Enabled = CHK_HackedStats.Visible = value; } + private readonly ToolTip EVTip = new(); + public bool Valid { get @@ -421,7 +423,7 @@ public partial class StatEditor : UserControl if (ModifierKeys == Keys.Control) ivs.Fill(Entity.MaxIV); else if (ModifierKeys == Keys.Alt) - ivs.Fill(0); + ivs.Clear(); else Entity.SetRandomIVs(ivs); @@ -448,7 +450,7 @@ public partial class StatEditor : UserControl a.SetSuggestedAwakenedValues(Entity); break; case Keys.Alt: - a.AwakeningClear(); + a.AwakeningMinimum(); // will still set AVs by level gain break; default: a.AwakeningSetRandom(); diff --git a/PKHeX.WinForms/Controls/PKM Editor/TrainerID.Designer.cs b/PKHeX.WinForms/Controls/PKM Editor/TrainerID.Designer.cs index cf8b0e3c2..e5f55db9e 100644 --- a/PKHeX.WinForms/Controls/PKM Editor/TrainerID.Designer.cs +++ b/PKHeX.WinForms/Controls/PKM Editor/TrainerID.Designer.cs @@ -50,17 +50,17 @@ this.FLP.Controls.Add(this.TB_SID7); this.FLP.Dock = System.Windows.Forms.DockStyle.Fill; this.FLP.Location = new System.Drawing.Point(0, 0); + this.FLP.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3); this.FLP.Name = "FLP"; - this.FLP.Size = new System.Drawing.Size(125, 54); + this.FLP.Size = new System.Drawing.Size(128, 48); this.FLP.TabIndex = 0; // // Label_TID // - this.Label_TID.AutoSize = true; - this.Label_TID.Location = new System.Drawing.Point(3, 6); - this.Label_TID.Margin = new System.Windows.Forms.Padding(3, 6, 2, 0); + this.Label_TID.Location = new System.Drawing.Point(0, 0); + this.Label_TID.Margin = new System.Windows.Forms.Padding(0); this.Label_TID.Name = "Label_TID"; - this.Label_TID.Size = new System.Drawing.Size(28, 13); + this.Label_TID.Size = new System.Drawing.Size(40, 24); this.Label_TID.TabIndex = 7; this.Label_TID.Text = "TID:"; this.Label_TID.TextAlign = System.Drawing.ContentAlignment.MiddleRight; @@ -68,12 +68,12 @@ // TB_TID // this.TB_TID.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; - this.TB_TID.Location = new System.Drawing.Point(33, 3); - this.TB_TID.Margin = new System.Windows.Forms.Padding(0, 3, 3, 0); + this.TB_TID.Location = new System.Drawing.Point(40, 0); + this.TB_TID.Margin = new System.Windows.Forms.Padding(0); this.TB_TID.Mask = "00000"; this.TB_TID.Name = "TB_TID"; - this.TB_TID.Size = new System.Drawing.Size(40, 20); - this.TB_TID.TabIndex = 5; + this.TB_TID.Size = new System.Drawing.Size(40, 23); + this.TB_TID.TabIndex = 1; this.TB_TID.Text = "12345"; this.TB_TID.TextAlign = System.Windows.Forms.HorizontalAlignment.Center; this.TB_TID.TextChanged += new System.EventHandler(this.Update_ID); @@ -82,12 +82,12 @@ // TB_TID7 // this.TB_TID7.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; - this.TB_TID7.Location = new System.Drawing.Point(76, 3); - this.TB_TID7.Margin = new System.Windows.Forms.Padding(0, 3, 3, 0); + this.TB_TID7.Location = new System.Drawing.Point(80, 0); + this.TB_TID7.Margin = new System.Windows.Forms.Padding(0); this.TB_TID7.Mask = "000000"; this.TB_TID7.Name = "TB_TID7"; - this.TB_TID7.Size = new System.Drawing.Size(42, 20); - this.TB_TID7.TabIndex = 9; + this.TB_TID7.Size = new System.Drawing.Size(48, 23); + this.TB_TID7.TabIndex = 2; this.TB_TID7.Text = "123456"; this.TB_TID7.TextAlign = System.Windows.Forms.HorizontalAlignment.Center; this.TB_TID7.TextChanged += new System.EventHandler(this.Update_ID); @@ -95,11 +95,10 @@ // // Label_SID // - this.Label_SID.AutoSize = true; - this.Label_SID.Location = new System.Drawing.Point(3, 29); - this.Label_SID.Margin = new System.Windows.Forms.Padding(3, 6, 2, 0); + this.Label_SID.Location = new System.Drawing.Point(0, 24); + this.Label_SID.Margin = new System.Windows.Forms.Padding(0); this.Label_SID.Name = "Label_SID"; - this.Label_SID.Size = new System.Drawing.Size(28, 13); + this.Label_SID.Size = new System.Drawing.Size(40, 24); this.Label_SID.TabIndex = 8; this.Label_SID.Text = "SID:"; this.Label_SID.TextAlign = System.Drawing.ContentAlignment.MiddleRight; @@ -107,12 +106,12 @@ // TB_SID // this.TB_SID.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; - this.TB_SID.Location = new System.Drawing.Point(33, 26); - this.TB_SID.Margin = new System.Windows.Forms.Padding(0, 3, 3, 0); + this.TB_SID.Location = new System.Drawing.Point(40, 24); + this.TB_SID.Margin = new System.Windows.Forms.Padding(0); this.TB_SID.Mask = "00000"; this.TB_SID.Name = "TB_SID"; - this.TB_SID.Size = new System.Drawing.Size(40, 20); - this.TB_SID.TabIndex = 6; + this.TB_SID.Size = new System.Drawing.Size(40, 23); + this.TB_SID.TabIndex = 3; this.TB_SID.Text = "12345"; this.TB_SID.TextAlign = System.Windows.Forms.HorizontalAlignment.Center; this.TB_SID.TextChanged += new System.EventHandler(this.Update_ID); @@ -121,12 +120,12 @@ // TB_SID7 // this.TB_SID7.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; - this.TB_SID7.Location = new System.Drawing.Point(76, 26); - this.TB_SID7.Margin = new System.Windows.Forms.Padding(0, 3, 3, 0); + this.TB_SID7.Location = new System.Drawing.Point(80, 24); + this.TB_SID7.Margin = new System.Windows.Forms.Padding(0); this.TB_SID7.Mask = "0000"; this.TB_SID7.Name = "TB_SID7"; - this.TB_SID7.Size = new System.Drawing.Size(30, 20); - this.TB_SID7.TabIndex = 10; + this.TB_SID7.Size = new System.Drawing.Size(32, 23); + this.TB_SID7.TabIndex = 4; this.TB_SID7.Text = "1234"; this.TB_SID7.TextAlign = System.Windows.Forms.HorizontalAlignment.Center; this.TB_SID7.TextChanged += new System.EventHandler(this.Update_ID); @@ -134,11 +133,11 @@ // // TrainerID // - this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); - this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Inherit; this.Controls.Add(this.FLP); + this.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3); this.Name = "TrainerID"; - this.Size = new System.Drawing.Size(125, 54); + this.Size = new System.Drawing.Size(128, 48); this.FLP.ResumeLayout(false); this.FLP.PerformLayout(); this.ResumeLayout(false); diff --git a/PKHeX.WinForms/Controls/PKM Editor/TrainerID.cs b/PKHeX.WinForms/Controls/PKM Editor/TrainerID.cs index 7e3b8e093..db3168b6b 100644 --- a/PKHeX.WinForms/Controls/PKM Editor/TrainerID.cs +++ b/PKHeX.WinForms/Controls/PKM Editor/TrainerID.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using System.Windows.Forms; using PKHeX.Core; @@ -10,45 +10,48 @@ public partial class TrainerID : UserControl public TrainerID() => InitializeComponent(); public event EventHandler? UpdatedID; - private int Format = -1; - private ITrainerID Trainer = null!; + private bool LoadingFields; + + private int XorFormat; + private TrainerIDFormat DisplayType { get; set; } + private ITrainerID32 Trainer = null!; public void UpdateTSV() { var tsv = GetTSV(); - if (tsv < 0) + if (tsv > ushort.MaxValue) return; - string IDstr = $"TSV: {tsv:d4}{Environment.NewLine}{GetAlternateRepresentation(Trainer, Format)}"; + string IDstr = $"TSV: {tsv:d4}{Environment.NewLine}{GetAlternateRepresentation(Trainer, DisplayType)}"; TSVTooltip.SetToolTip(TB_TID, IDstr); TSVTooltip.SetToolTip(TB_SID, IDstr); TSVTooltip.SetToolTip(TB_TID7, IDstr); TSVTooltip.SetToolTip(TB_SID7, IDstr); } - private static string GetAlternateRepresentation(ITrainerID tr, int format) + private static string GetAlternateRepresentation(ITrainerID32 tr, TrainerIDFormat format) { - if (format >= 7) - return $"ID: {tr.TID:D5}/{tr.SID:D5}"; - var repack = (uint)((tr.SID << 16) | tr.TID); // 32bit - return $"G7ID: ({repack / 1_000_000:D4}){repack % 1_000_000:D6}"; + if (format is not TrainerIDFormat.SixteenBit) + return $"ID: {tr.TID16:D5}/{tr.SID16:D5}"; + var id = tr.ID32; + return $"G7ID: ({id / 1_000_000:D4}){id % 1_000_000:D6}"; } - private int GetTSV() + private uint GetTSV() { - if (Format <= 2) - return -1; - var xor = Trainer.SID ^ Trainer.TID; - if (Format <= 5) + if (DisplayType is TrainerIDFormat.None) + return uint.MaxValue; + var xor = (uint)(Trainer.SID16 ^ Trainer.TID16); + if (XorFormat <= 5) return xor >> 3; return xor >> 4; } - public void LoadIDValues(ITrainerID tr) + public void LoadIDValues(ITrainerID32 tr, int format) { Trainer = tr; - int format = tr.GetTrainerIDFormat(); - SetFormat(format); + var display = tr.GetTrainerIDFormat(); + SetFormat(display, format); LoadValues(); } @@ -56,43 +59,41 @@ public partial class TrainerID : UserControl public void LoadInfo(ITrainerInfo info) { - Trainer.TID = info.TID; - Trainer.SID = info.SID; + Trainer.TID16 = info.TID16; + Trainer.SID16 = info.SID16; LoadValues(); } private void LoadValues() { - if (Format <= 2) - TB_TID.Text = Trainer.TID.ToString(); - else if (Format <= 6) - LoadTID(Trainer.TID, Trainer.SID); + LoadingFields = true; + if (XorFormat <= 2) + TB_TID.Text = Trainer.TID16.ToString(); + else if (DisplayType == TrainerIDFormat.SixteenBit) + LoadTID(Trainer); else - LoadTID7(Trainer.TID, Trainer.SID); + LoadTID7(Trainer); + LoadingFields = false; } - private void LoadTID(int tid, int sid) + private void LoadTID(ITrainerID32 tr) { - TB_TID.Text = tid.ToString("D5"); - TB_SID.Text = sid.ToString("D5"); + TB_TID.Text = tr.TID16.ToString(TrainerIDExtensions.TID16); + TB_SID.Text = tr.SID16.ToString(TrainerIDExtensions.SID16); } - private void LoadTID7(int tid, int sid) + private void LoadTID7(ITrainerID32 tr) { - var repack = (uint)((sid << 16) | tid); - sid = (int)(repack / 1_000_000); - tid = (int)(repack % 1_000_000); - - TB_TID7.Text = tid.ToString("D6"); - TB_SID7.Text = sid.ToString("D4"); + TB_TID7.Text = tr.GetTrainerTID7().ToString(TrainerIDExtensions.TID7); + TB_SID7.Text = tr.GetTrainerSID7().ToString(TrainerIDExtensions.SID7); } - private void SetFormat(int format) + private void SetFormat(TrainerIDFormat display, int format) { - if (format == Format) + if ((display, format) == (DisplayType, XorFormat)) return; - var controls = GetControlsForFormat(format); + var controls = GetControlsForFormat(display); FLP.Controls.Clear(); int i = 0; foreach (var c in controls) { @@ -100,14 +101,14 @@ public partial class TrainerID : UserControl FLP.Controls.SetChildIndex(c, i++); // because you don't listen the first time } - Format = format; + (DisplayType, XorFormat) = (display, format); } - private IEnumerable GetControlsForFormat(int format) => format switch + private IEnumerable GetControlsForFormat(TrainerIDFormat format) => format switch { - >= 7 => new Control[] {Label_SID, TB_SID7, Label_TID, TB_TID7}, - >= 3 => new Control[] {Label_TID, TB_TID, Label_SID, TB_SID }, - _ => new Control[] {Label_TID, TB_TID}, // Gen1/2 + TrainerIDFormat.SixDigit => new Control[] {Label_SID, TB_SID7, Label_TID, TB_TID7}, + TrainerIDFormat.SixteenBitSingle => new Control[] {Label_TID, TB_TID}, // Gen1/2 + _ => new Control[] { Label_TID, TB_TID, Label_SID, TB_SID }, }; private void UpdateTSV(object sender, EventArgs e) => UpdateTSV(); @@ -117,7 +118,7 @@ public partial class TrainerID : UserControl if (sender is not MaskedTextBox mt) return; - if (!int.TryParse(mt.Text, out var value)) + if (!uint.TryParse(mt.Text, out var value)) value = 0; if (mt == TB_TID7) { @@ -126,7 +127,7 @@ public partial class TrainerID : UserControl mt.Text = "999999"; return; } - if (!int.TryParse(TB_SID7.Text, out var sid)) + if (!uint.TryParse(TB_SID7.Text, out var sid)) sid = 0; SanityCheckSID7(value, sid); } @@ -137,7 +138,7 @@ public partial class TrainerID : UserControl mt.Text = "4294"; return; } - if (!int.TryParse(TB_TID7.Text, out var tid)) + if (!uint.TryParse(TB_TID7.Text, out var tid)) tid = 0; SanityCheckSID7(tid, value); } @@ -147,24 +148,25 @@ public partial class TrainerID : UserControl mt.Text = (value = ushort.MaxValue).ToString(); if (mt == TB_TID) - Trainer.TID = value; + Trainer.TID16 = (ushort)value; else - Trainer.SID = value; + Trainer.SID16 = (ushort)value; } UpdatedID?.Invoke(sender, e); } - private void SanityCheckSID7(int tid, int sid) + private void SanityCheckSID7(uint tid, uint sid) { - var repack = ((long)sid * 1_000_000) + tid; + if (LoadingFields) + return; + + var repack = ((ulong)sid * 1_000_000) + tid; if (repack > uint.MaxValue) { TB_SID7.Text = (sid - 1).ToString(); - return; + return; // GUI triggers change event, so we'll eventually reach below. } - - Trainer.SID = (ushort)(repack >> 16); - Trainer.TID = (ushort)repack; + Trainer.SetTrainerID7(sid, tid); } } diff --git a/PKHeX.WinForms/Controls/PKM Editor/VerticalTabControl.cs b/PKHeX.WinForms/Controls/PKM Editor/VerticalTabControl.cs new file mode 100644 index 000000000..59b07c3bf --- /dev/null +++ b/PKHeX.WinForms/Controls/PKM Editor/VerticalTabControl.cs @@ -0,0 +1,87 @@ +using System.Drawing; +using System.Drawing.Drawing2D; +using System.Windows.Forms; + +namespace PKHeX.WinForms.Controls; + +public class VerticalTabControl : TabControl +{ + public VerticalTabControl() + { + Alignment = TabAlignment.Right; + DrawMode = TabDrawMode.OwnerDrawFixed; + SizeMode = TabSizeMode.Fixed; + } + + protected override void OnDrawItem(DrawItemEventArgs e) + { + var index = e.Index; + var bounds = GetTabRect(index); + + var graphics = e.Graphics; + if (e.State == DrawItemState.Selected) + { + using var brush = new LinearGradientBrush(bounds, Color.White, Color.LightGray, 90f); + graphics.FillRectangle(brush, bounds); + } + else + { + e.DrawBackground(); + } + + using var flags = new StringFormat + { + Alignment = StringAlignment.Center, + LineAlignment = StringAlignment.Center, + }; + using var text = new SolidBrush(ForeColor); + var tab = TabPages[index]; + graphics.DrawString(tab.Text, Font, text, bounds, flags); + base.OnDrawItem(e); + } +} + +public sealed class VerticalTabControlEntityEditor : VerticalTabControl +{ + private static readonly Color[] SelectedTags = + { + Color.FromArgb(248, 152, 096), + Color.FromArgb(128, 152, 248), + Color.FromArgb(248, 168, 208), + Color.FromArgb(112, 224, 112), + Color.FromArgb(248, 240, 056), + Color.RosyBrown, + }; + + protected override void OnDrawItem(DrawItemEventArgs e) + { + var index = e.Index; + var bounds = GetTabRect(index); + + var graphics = e.Graphics; + if (e.State == DrawItemState.Selected) + { + using var brush = new LinearGradientBrush(bounds, Color.White, Color.LightGray, 90f); + graphics.FillRectangle(brush, bounds); + + using var pipBrush = new SolidBrush(SelectedTags[index]); + var pip = GetTabRect(index) with { Width = bounds.Width / 8 }; + graphics.FillRectangle(pipBrush, pip); + bounds = bounds with { Width = bounds.Width - pip.Width, X = bounds.X + pip.Width }; + } + else + { + // no need to shift text + e.DrawBackground(); + } + + using var flags = new StringFormat + { + Alignment = StringAlignment.Center, + LineAlignment = StringAlignment.Center, + }; + using var text = new SolidBrush(ForeColor); + var tab = TabPages[index]; + graphics.DrawString(tab.Text, Font, text, bounds, flags); + } +} diff --git a/PKHeX.WinForms/Controls/SAV Editor/BitmapAnimator.cs b/PKHeX.WinForms/Controls/SAV Editor/BitmapAnimator.cs index 9b0469f18..f7428b5f4 100644 --- a/PKHeX.WinForms/Controls/SAV Editor/BitmapAnimator.cs +++ b/PKHeX.WinForms/Controls/SAV Editor/BitmapAnimator.cs @@ -7,19 +7,18 @@ using Timer = System.Timers.Timer; namespace PKHeX.WinForms.Controls; -public sealed class BitmapAnimator : Timer +public sealed class BitmapAnimator : IDisposable { - public BitmapAnimator() - { - Elapsed += TimerElapsed; - } + public BitmapAnimator() => Timer.Elapsed += TimerElapsed; + + private readonly Timer Timer = new(); private int imgWidth; private int imgHeight; private byte[]? GlowData; private Image? ExtraLayer; private Image?[]? GlowCache; - public Image? OriginalBackground; + private Image? OriginalBackground; private readonly object Lock = new(); private PictureBox? pb; @@ -29,10 +28,9 @@ public sealed class BitmapAnimator : Timer public int GlowFps { get; set; } = 60; public Color GlowToColor { get; set; } = Color.LightSkyBlue; public Color GlowFromColor { get; set; } = Color.White; + public bool Enabled { get => Timer.Enabled; set => Timer.Enabled = value; } - public new static void Start() => throw new ArgumentException(); - - public new void Stop() + public void Stop() { if (pb == null || !Enabled) return; @@ -51,7 +49,7 @@ public sealed class BitmapAnimator : Timer GlowCache[i] = null; } - public void Start(PictureBox pbox, Image baseImage, byte[] glowData, Image original, Image extra) + public void Start(PictureBox pbox, Image baseImage, byte[] glowData, Image? original, Image extra) { Enabled = false; imgWidth = baseImage.Width; @@ -60,7 +58,7 @@ public sealed class BitmapAnimator : Timer GlowCounter = 0; GlowCache = new Image[GlowFps]; GlowInterval = 1000 / GlowFps; - Interval = GlowInterval; + Timer.Interval = GlowInterval; lock (Lock) { pb = pbox; @@ -115,4 +113,12 @@ public sealed class BitmapAnimator : Timer } private Color GetFrameColor(double elapsedFraction) => ColorUtil.Blend(GlowToColor, GlowFromColor, elapsedFraction); + + public void Dispose() + { + GlowCache = null; + Timer.Enabled = false; + Timer.Elapsed -= TimerElapsed; + Timer.Dispose(); + } } diff --git a/PKHeX.WinForms/Controls/SAV Editor/BoxEditor.Designer.cs b/PKHeX.WinForms/Controls/SAV Editor/BoxEditor.Designer.cs index 1038393a9..67cb5caa7 100644 --- a/PKHeX.WinForms/Controls/SAV Editor/BoxEditor.Designer.cs +++ b/PKHeX.WinForms/Controls/SAV Editor/BoxEditor.Designer.cs @@ -37,10 +37,11 @@ // B_BoxRight // this.B_BoxRight.FlatStyle = System.Windows.Forms.FlatStyle.System; - this.B_BoxRight.Location = new System.Drawing.Point(193, -1); + this.B_BoxRight.Location = new System.Drawing.Point(200, 0); + this.B_BoxRight.Margin = new System.Windows.Forms.Padding(0); this.B_BoxRight.Name = "B_BoxRight"; - this.B_BoxRight.Size = new System.Drawing.Size(27, 23); - this.B_BoxRight.TabIndex = 65; + this.B_BoxRight.Size = new System.Drawing.Size(24, 24); + this.B_BoxRight.TabIndex = 2; this.B_BoxRight.Text = ">>"; this.B_BoxRight.UseVisualStyleBackColor = true; this.B_BoxRight.Click += new System.EventHandler(this.ClickBoxRight); @@ -48,10 +49,11 @@ // B_BoxLeft // this.B_BoxLeft.FlatStyle = System.Windows.Forms.FlatStyle.System; - this.B_BoxLeft.Location = new System.Drawing.Point(31, -1); + this.B_BoxLeft.Location = new System.Drawing.Point(32, 0); + this.B_BoxLeft.Margin = new System.Windows.Forms.Padding(0); this.B_BoxLeft.Name = "B_BoxLeft"; - this.B_BoxLeft.Size = new System.Drawing.Size(27, 23); - this.B_BoxLeft.TabIndex = 64; + this.B_BoxLeft.Size = new System.Drawing.Size(24, 24); + this.B_BoxLeft.TabIndex = 0; this.B_BoxLeft.Text = "<<"; this.B_BoxLeft.UseVisualStyleBackColor = true; this.B_BoxLeft.Click += new System.EventHandler(this.ClickBoxLeft); @@ -92,10 +94,12 @@ "Box 29", "Box 30", "Box 31"}); - this.CB_BoxSelect.Location = new System.Drawing.Point(62, 0); + this.CB_BoxSelect.Location = new System.Drawing.Point(64, 0); + this.CB_BoxSelect.Margin = new System.Windows.Forms.Padding(0); + this.CB_BoxSelect.MinimumSize = new System.Drawing.Size(128, 0); this.CB_BoxSelect.Name = "CB_BoxSelect"; - this.CB_BoxSelect.Size = new System.Drawing.Size(127, 21); - this.CB_BoxSelect.TabIndex = 63; + this.CB_BoxSelect.Size = new System.Drawing.Size(128, 23); + this.CB_BoxSelect.TabIndex = 1; this.CB_BoxSelect.SelectedIndexChanged += new System.EventHandler(this.GetBox); // // BoxPokeGrid @@ -105,7 +109,7 @@ this.BoxPokeGrid.Margin = new System.Windows.Forms.Padding(0); this.BoxPokeGrid.Name = "BoxPokeGrid"; this.BoxPokeGrid.Size = new System.Drawing.Size(251, 160); - this.BoxPokeGrid.TabIndex = 66; + this.BoxPokeGrid.TabIndex = 3; // // BoxEditor // diff --git a/PKHeX.WinForms/Controls/SAV Editor/BoxMenuStrip.cs b/PKHeX.WinForms/Controls/SAV Editor/BoxMenuStrip.cs index 182465248..87fb89b7a 100644 --- a/PKHeX.WinForms/Controls/SAV Editor/BoxMenuStrip.cs +++ b/PKHeX.WinForms/Controls/SAV Editor/BoxMenuStrip.cs @@ -72,6 +72,8 @@ public sealed class BoxMenuStrip : ContextMenuStrip [BoxManipType.SortBST] = Resources.vallohi, [BoxManipType.SortCP] = Resources.vallohi, [BoxManipType.SortScale] = Resources.vallohi, + [BoxManipType.SortRibbons] = Resources.valhilo, + [BoxManipType.SortMarks] = Resources.valhilo, [BoxManipType.SortLegal] = Resources.export, [BoxManipType.SortEncounterType] = Resources.about, diff --git a/PKHeX.WinForms/Controls/SAV Editor/ContextMenuSAV.cs b/PKHeX.WinForms/Controls/SAV Editor/ContextMenuSAV.cs index 557faa1ec..e226d230a 100644 --- a/PKHeX.WinForms/Controls/SAV Editor/ContextMenuSAV.cs +++ b/PKHeX.WinForms/Controls/SAV Editor/ContextMenuSAV.cs @@ -12,7 +12,7 @@ public partial class ContextMenuSAV : UserControl public ContextMenuSAV() => InitializeComponent(); public SaveDataEditor Editor { private get; set; } = null!; - public SlotChangeManager Manager { get; set; } = null!; + public required SlotChangeManager Manager { get; init; } public Action? RequestEditorLegality; @@ -116,7 +116,9 @@ public partial class ContextMenuSAV : UserControl { var items = ((ContextMenuStrip)sender).Items; - object ctrl = ((ContextMenuStrip)sender).SourceControl; + object? ctrl = ((ContextMenuStrip)sender).SourceControl; + if (ctrl is null) + return; var info = GetSenderInfo(ref ctrl); bool SlotFull = (ctrl as PictureBox)?.Image != null; bool Editable = info.Slot.CanWriteTo(info.View.SAV); diff --git a/PKHeX.WinForms/Controls/SAV Editor/SAVEditor.Designer.cs b/PKHeX.WinForms/Controls/SAV Editor/SAVEditor.Designer.cs index 804e631f4..35f421739 100644 --- a/PKHeX.WinForms/Controls/SAV Editor/SAVEditor.Designer.cs +++ b/PKHeX.WinForms/Controls/SAV Editor/SAVEditor.Designer.cs @@ -53,14 +53,6 @@ namespace PKHeX.WinForms.Controls this.DayCare_HasEgg = new System.Windows.Forms.CheckBox(); this.L_ReadOnlyOther = new System.Windows.Forms.Label(); this.Tab_SAV = new System.Windows.Forms.TabPage(); - this.FLP_SAVToolsMisc = new System.Windows.Forms.FlowLayoutPanel(); - this.B_SaveBoxBin = new System.Windows.Forms.Button(); - this.B_VerifyCHK = new System.Windows.Forms.Button(); - this.B_VerifySaveEntities = new System.Windows.Forms.Button(); - this.Menu_ExportBAK = new System.Windows.Forms.Button(); - this.B_JPEG = new System.Windows.Forms.Button(); - this.CB_SaveSlot = new System.Windows.Forms.ComboBox(); - this.GB_SAVtools = new System.Windows.Forms.GroupBox(); this.FLP_SAVtools = new System.Windows.Forms.FlowLayoutPanel(); this.B_OpenTrainerInfo = new System.Windows.Forms.Button(); this.B_OpenItemPouch = new System.Windows.Forms.Button(); @@ -97,6 +89,13 @@ namespace PKHeX.WinForms.Controls this.B_OpenSealStickers = new System.Windows.Forms.Button(); this.B_Poffins = new System.Windows.Forms.Button(); this.B_RaidsSevenStar = new System.Windows.Forms.Button(); + this.FLP_SAVToolsMisc = new System.Windows.Forms.FlowLayoutPanel(); + this.B_SaveBoxBin = new System.Windows.Forms.Button(); + this.B_VerifyCHK = new System.Windows.Forms.Button(); + this.B_VerifySaveEntities = new System.Windows.Forms.Button(); + this.Menu_ExportBAK = new System.Windows.Forms.Button(); + this.B_JPEG = new System.Windows.Forms.Button(); + this.CB_SaveSlot = new System.Windows.Forms.ComboBox(); this.L_SaveSlot = new System.Windows.Forms.Label(); this.L_Secure2 = new System.Windows.Forms.Label(); this.TB_Secure2 = new System.Windows.Forms.TextBox(); @@ -112,9 +111,8 @@ namespace PKHeX.WinForms.Controls ((System.ComponentModel.ISupportInitialize)(this.dcpkx2)).BeginInit(); ((System.ComponentModel.ISupportInitialize)(this.dcpkx1)).BeginInit(); this.Tab_SAV.SuspendLayout(); - this.FLP_SAVToolsMisc.SuspendLayout(); - this.GB_SAVtools.SuspendLayout(); this.FLP_SAVtools.SuspendLayout(); + this.FLP_SAVToolsMisc.SuspendLayout(); this.SuspendLayout(); // // tabBoxMulti @@ -138,10 +136,10 @@ namespace PKHeX.WinForms.Controls // this.Tab_Box.AllowDrop = true; this.Tab_Box.Controls.Add(this.Box); - this.Tab_Box.Location = new System.Drawing.Point(4, 22); + this.Tab_Box.Location = new System.Drawing.Point(4, 24); this.Tab_Box.Name = "Tab_Box"; this.Tab_Box.Padding = new System.Windows.Forms.Padding(3); - this.Tab_Box.Size = new System.Drawing.Size(441, 337); + this.Tab_Box.Size = new System.Drawing.Size(441, 335); this.Tab_Box.TabIndex = 0; this.Tab_Box.Text = "Box"; this.Tab_Box.UseVisualStyleBackColor = true; @@ -166,10 +164,10 @@ namespace PKHeX.WinForms.Controls // this.Tab_PartyBattle.AllowDrop = true; this.Tab_PartyBattle.Controls.Add(this.SL_Party); - this.Tab_PartyBattle.Location = new System.Drawing.Point(4, 22); + this.Tab_PartyBattle.Location = new System.Drawing.Point(4, 24); this.Tab_PartyBattle.Name = "Tab_PartyBattle"; this.Tab_PartyBattle.Padding = new System.Windows.Forms.Padding(3); - this.Tab_PartyBattle.Size = new System.Drawing.Size(441, 337); + this.Tab_PartyBattle.Size = new System.Drawing.Size(441, 335); this.Tab_PartyBattle.TabIndex = 1; this.Tab_PartyBattle.Text = "Party"; this.Tab_PartyBattle.UseVisualStyleBackColor = true; @@ -178,10 +176,10 @@ namespace PKHeX.WinForms.Controls // this.SL_Party.AutoSize = true; this.SL_Party.FlagIllegal = false; - this.SL_Party.Location = new System.Drawing.Point(6, 6); + this.SL_Party.Location = new System.Drawing.Point(8, 8); this.SL_Party.M = null; this.SL_Party.Name = "SL_Party"; - this.SL_Party.Size = new System.Drawing.Size(251, 185); + this.SL_Party.Size = new System.Drawing.Size(256, 184); this.SL_Party.TabIndex = 0; // // Tab_Other @@ -189,9 +187,9 @@ namespace PKHeX.WinForms.Controls this.Tab_Other.Controls.Add(this.SL_Extra); this.Tab_Other.Controls.Add(this.GB_Daycare); this.Tab_Other.Controls.Add(this.L_ReadOnlyOther); - this.Tab_Other.Location = new System.Drawing.Point(4, 22); + this.Tab_Other.Location = new System.Drawing.Point(4, 24); this.Tab_Other.Name = "Tab_Other"; - this.Tab_Other.Size = new System.Drawing.Size(441, 337); + this.Tab_Other.Size = new System.Drawing.Size(441, 335); this.Tab_Other.TabIndex = 2; this.Tab_Other.Text = "Other"; this.Tab_Other.UseVisualStyleBackColor = true; @@ -200,10 +198,10 @@ namespace PKHeX.WinForms.Controls // this.SL_Extra.Dock = System.Windows.Forms.DockStyle.Right; this.SL_Extra.FlagIllegal = false; - this.SL_Extra.Location = new System.Drawing.Point(341, 0); + this.SL_Extra.Location = new System.Drawing.Point(337, 0); this.SL_Extra.Name = "SL_Extra"; this.SL_Extra.SAV = null; - this.SL_Extra.Size = new System.Drawing.Size(100, 337); + this.SL_Extra.Size = new System.Drawing.Size(104, 335); this.SL_Extra.TabIndex = 30; this.SL_Extra.ViewIndex = -1; // @@ -220,89 +218,89 @@ namespace PKHeX.WinForms.Controls this.GB_Daycare.Controls.Add(this.dcpkx2); this.GB_Daycare.Controls.Add(this.dcpkx1); this.GB_Daycare.Controls.Add(this.DayCare_HasEgg); - this.GB_Daycare.Location = new System.Drawing.Point(16, 4); + this.GB_Daycare.Location = new System.Drawing.Point(16, 8); this.GB_Daycare.Name = "GB_Daycare"; - this.GB_Daycare.Size = new System.Drawing.Size(205, 191); + this.GB_Daycare.Size = new System.Drawing.Size(200, 196); this.GB_Daycare.TabIndex = 28; this.GB_Daycare.TabStop = false; this.GB_Daycare.Text = "Daycare"; // // L_XP2 // - this.L_XP2.AutoSize = true; - this.L_XP2.Location = new System.Drawing.Point(84, 110); + this.L_XP2.Location = new System.Drawing.Point(80, 104); this.L_XP2.Name = "L_XP2"; - this.L_XP2.Size = new System.Drawing.Size(30, 13); + this.L_XP2.Size = new System.Drawing.Size(40, 24); this.L_XP2.TabIndex = 17; this.L_XP2.Text = "+XP:"; + this.L_XP2.TextAlign = System.Drawing.ContentAlignment.MiddleLeft; // // L_XP1 // - this.L_XP1.AutoSize = true; - this.L_XP1.Location = new System.Drawing.Point(84, 47); + this.L_XP1.Location = new System.Drawing.Point(80, 40); this.L_XP1.Name = "L_XP1"; - this.L_XP1.Size = new System.Drawing.Size(30, 13); + this.L_XP1.Size = new System.Drawing.Size(40, 24); this.L_XP1.TabIndex = 16; this.L_XP1.Text = "+XP:"; + this.L_XP1.TextAlign = System.Drawing.ContentAlignment.MiddleLeft; // // TB_Daycare2XP // - this.TB_Daycare2XP.Location = new System.Drawing.Point(118, 107); + this.TB_Daycare2XP.Location = new System.Drawing.Point(120, 104); this.TB_Daycare2XP.Name = "TB_Daycare2XP"; this.TB_Daycare2XP.ReadOnly = true; - this.TB_Daycare2XP.Size = new System.Drawing.Size(73, 20); + this.TB_Daycare2XP.Size = new System.Drawing.Size(73, 23); this.TB_Daycare2XP.TabIndex = 15; // // TB_Daycare1XP // - this.TB_Daycare1XP.Location = new System.Drawing.Point(118, 44); + this.TB_Daycare1XP.Location = new System.Drawing.Point(120, 40); this.TB_Daycare1XP.Name = "TB_Daycare1XP"; this.TB_Daycare1XP.ReadOnly = true; - this.TB_Daycare1XP.Size = new System.Drawing.Size(73, 20); + this.TB_Daycare1XP.Size = new System.Drawing.Size(73, 23); this.TB_Daycare1XP.TabIndex = 14; // // L_DC2 // this.L_DC2.AutoSize = true; - this.L_DC2.Location = new System.Drawing.Point(84, 93); + this.L_DC2.Location = new System.Drawing.Point(80, 88); this.L_DC2.Name = "L_DC2"; - this.L_DC2.Size = new System.Drawing.Size(19, 13); + this.L_DC2.Size = new System.Drawing.Size(19, 15); this.L_DC2.TabIndex = 13; this.L_DC2.Text = "2: "; // // L_DC1 // this.L_DC1.AutoSize = true; - this.L_DC1.Location = new System.Drawing.Point(84, 30); + this.L_DC1.Location = new System.Drawing.Point(80, 24); this.L_DC1.Name = "L_DC1"; - this.L_DC1.Size = new System.Drawing.Size(19, 13); + this.L_DC1.Size = new System.Drawing.Size(19, 15); this.L_DC1.TabIndex = 12; this.L_DC1.Text = "1: "; // // L_DaycareSeed // - this.L_DaycareSeed.AutoSize = true; - this.L_DaycareSeed.Location = new System.Drawing.Point(23, 167); + this.L_DaycareSeed.Location = new System.Drawing.Point(16, 168); this.L_DaycareSeed.Name = "L_DaycareSeed"; - this.L_DaycareSeed.Size = new System.Drawing.Size(35, 13); + this.L_DaycareSeed.Size = new System.Drawing.Size(48, 24); this.L_DaycareSeed.TabIndex = 9; this.L_DaycareSeed.Text = "Seed:"; + this.L_DaycareSeed.TextAlign = System.Drawing.ContentAlignment.MiddleRight; // // TB_RNGSeed // - this.TB_RNGSeed.Font = new System.Drawing.Font("Courier New", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); - this.TB_RNGSeed.Location = new System.Drawing.Point(61, 164); + this.TB_RNGSeed.Font = new System.Drawing.Font("Courier New", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); + this.TB_RNGSeed.Location = new System.Drawing.Point(64, 168); this.TB_RNGSeed.MaxLength = 16; this.TB_RNGSeed.Name = "TB_RNGSeed"; + this.TB_RNGSeed.PlaceholderText = "0123456789ABCDEF"; this.TB_RNGSeed.Size = new System.Drawing.Size(120, 20); this.TB_RNGSeed.TabIndex = 8; - this.TB_RNGSeed.Text = "0123456789ABCDEF"; this.TB_RNGSeed.Validated += new System.EventHandler(this.UpdateStringSeed); // // dcpkx2 // this.dcpkx2.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; - this.dcpkx2.Location = new System.Drawing.Point(11, 81); + this.dcpkx2.Location = new System.Drawing.Point(8, 80); this.dcpkx2.Name = "dcpkx2"; this.dcpkx2.Size = new System.Drawing.Size(70, 58); this.dcpkx2.SizeMode = System.Windows.Forms.PictureBoxSizeMode.AutoSize; @@ -312,7 +310,7 @@ namespace PKHeX.WinForms.Controls // dcpkx1 // this.dcpkx1.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; - this.dcpkx1.Location = new System.Drawing.Point(11, 19); + this.dcpkx1.Location = new System.Drawing.Point(8, 16); this.dcpkx1.Name = "dcpkx1"; this.dcpkx1.Size = new System.Drawing.Size(70, 58); this.dcpkx1.SizeMode = System.Windows.Forms.PictureBoxSizeMode.AutoSize; @@ -323,9 +321,9 @@ namespace PKHeX.WinForms.Controls // this.DayCare_HasEgg.AutoSize = true; this.DayCare_HasEgg.Enabled = false; - this.DayCare_HasEgg.Location = new System.Drawing.Point(61, 147); + this.DayCare_HasEgg.Location = new System.Drawing.Point(64, 146); this.DayCare_HasEgg.Name = "DayCare_HasEgg"; - this.DayCare_HasEgg.Size = new System.Drawing.Size(91, 17); + this.DayCare_HasEgg.Size = new System.Drawing.Size(97, 19); this.DayCare_HasEgg.TabIndex = 7; this.DayCare_HasEgg.Text = "Egg Available"; this.DayCare_HasEgg.UseVisualStyleBackColor = true; @@ -333,18 +331,18 @@ namespace PKHeX.WinForms.Controls // L_ReadOnlyOther // this.L_ReadOnlyOther.ForeColor = System.Drawing.Color.Red; - this.L_ReadOnlyOther.Location = new System.Drawing.Point(33, 198); + this.L_ReadOnlyOther.Location = new System.Drawing.Point(32, 208); this.L_ReadOnlyOther.Name = "L_ReadOnlyOther"; - this.L_ReadOnlyOther.Size = new System.Drawing.Size(170, 13); + this.L_ReadOnlyOther.Size = new System.Drawing.Size(176, 24); this.L_ReadOnlyOther.TabIndex = 29; this.L_ReadOnlyOther.Text = "This tab is read only."; this.L_ReadOnlyOther.TextAlign = System.Drawing.ContentAlignment.MiddleCenter; // // Tab_SAV // + this.Tab_SAV.Controls.Add(this.FLP_SAVtools); this.Tab_SAV.Controls.Add(this.FLP_SAVToolsMisc); this.Tab_SAV.Controls.Add(this.CB_SaveSlot); - this.Tab_SAV.Controls.Add(this.GB_SAVtools); this.Tab_SAV.Controls.Add(this.L_SaveSlot); this.Tab_SAV.Controls.Add(this.L_Secure2); this.Tab_SAV.Controls.Add(this.TB_Secure2); @@ -352,97 +350,13 @@ namespace PKHeX.WinForms.Controls this.Tab_SAV.Controls.Add(this.TB_Secure1); this.Tab_SAV.Controls.Add(this.L_GameSync); this.Tab_SAV.Controls.Add(this.TB_GameSync); - this.Tab_SAV.Location = new System.Drawing.Point(4, 22); + this.Tab_SAV.Location = new System.Drawing.Point(4, 24); this.Tab_SAV.Name = "Tab_SAV"; - this.Tab_SAV.Size = new System.Drawing.Size(441, 337); + this.Tab_SAV.Size = new System.Drawing.Size(441, 335); this.Tab_SAV.TabIndex = 3; this.Tab_SAV.Text = "SAV"; this.Tab_SAV.UseVisualStyleBackColor = true; // - // FLP_SAVToolsMisc - // - this.FLP_SAVToolsMisc.Controls.Add(this.B_SaveBoxBin); - this.FLP_SAVToolsMisc.Controls.Add(this.B_VerifyCHK); - this.FLP_SAVToolsMisc.Controls.Add(this.B_VerifySaveEntities); - this.FLP_SAVToolsMisc.Controls.Add(this.Menu_ExportBAK); - this.FLP_SAVToolsMisc.Controls.Add(this.B_JPEG); - this.FLP_SAVToolsMisc.Location = new System.Drawing.Point(3, 5); - this.FLP_SAVToolsMisc.Name = "FLP_SAVToolsMisc"; - this.FLP_SAVToolsMisc.Size = new System.Drawing.Size(432, 52); - this.FLP_SAVToolsMisc.TabIndex = 104; - // - // B_SaveBoxBin - // - this.B_SaveBoxBin.Location = new System.Drawing.Point(3, 3); - this.B_SaveBoxBin.Name = "B_SaveBoxBin"; - this.B_SaveBoxBin.Size = new System.Drawing.Size(80, 45); - this.B_SaveBoxBin.TabIndex = 8; - this.B_SaveBoxBin.Text = "Save Box Data++"; - this.B_SaveBoxBin.UseVisualStyleBackColor = true; - this.B_SaveBoxBin.Click += new System.EventHandler(this.B_SaveBoxBin_Click); - // - // B_VerifyCHK - // - this.B_VerifyCHK.Location = new System.Drawing.Point(89, 3); - this.B_VerifyCHK.Name = "B_VerifyCHK"; - this.B_VerifyCHK.Size = new System.Drawing.Size(80, 45); - this.B_VerifyCHK.TabIndex = 2; - this.B_VerifyCHK.Text = "Verify Checksums"; - this.B_VerifyCHK.UseVisualStyleBackColor = true; - this.B_VerifyCHK.Click += new System.EventHandler(this.ClickVerifyCHK); - // - // B_VerifySaveEntities - // - this.B_VerifySaveEntities.Location = new System.Drawing.Point(175, 3); - this.B_VerifySaveEntities.Name = "B_VerifySaveEntities"; - this.B_VerifySaveEntities.Size = new System.Drawing.Size(80, 45); - this.B_VerifySaveEntities.TabIndex = 104; - this.B_VerifySaveEntities.Text = "Verify All PKMs"; - this.B_VerifySaveEntities.UseVisualStyleBackColor = true; - this.B_VerifySaveEntities.Click += new System.EventHandler(this.ClickVerifyStoredEntities); - // - // Menu_ExportBAK - // - this.Menu_ExportBAK.Location = new System.Drawing.Point(261, 3); - this.Menu_ExportBAK.Name = "Menu_ExportBAK"; - this.Menu_ExportBAK.Size = new System.Drawing.Size(80, 45); - this.Menu_ExportBAK.TabIndex = 103; - this.Menu_ExportBAK.Text = "Export Backup"; - this.Menu_ExportBAK.UseVisualStyleBackColor = true; - this.Menu_ExportBAK.Click += new System.EventHandler(this.Menu_ExportBAK_Click); - // - // B_JPEG - // - this.B_JPEG.Location = new System.Drawing.Point(347, 3); - this.B_JPEG.Name = "B_JPEG"; - this.B_JPEG.Size = new System.Drawing.Size(80, 45); - this.B_JPEG.TabIndex = 12; - this.B_JPEG.Text = "Save PGL .JPEG"; - this.B_JPEG.UseVisualStyleBackColor = true; - this.B_JPEG.Click += new System.EventHandler(this.B_JPEG_Click); - // - // CB_SaveSlot - // - this.CB_SaveSlot.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; - this.CB_SaveSlot.FormattingEnabled = true; - this.CB_SaveSlot.Location = new System.Drawing.Point(150, 148); - this.CB_SaveSlot.Name = "CB_SaveSlot"; - this.CB_SaveSlot.Size = new System.Drawing.Size(121, 21); - this.CB_SaveSlot.TabIndex = 20; - this.CB_SaveSlot.SelectedIndexChanged += new System.EventHandler(this.UpdateSaveSlot); - // - // GB_SAVtools - // - this.GB_SAVtools.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) - | System.Windows.Forms.AnchorStyles.Left) - | System.Windows.Forms.AnchorStyles.Right))); - this.GB_SAVtools.Controls.Add(this.FLP_SAVtools); - this.GB_SAVtools.Location = new System.Drawing.Point(0, 175); - this.GB_SAVtools.Name = "GB_SAVtools"; - this.GB_SAVtools.Size = new System.Drawing.Size(441, 162); - this.GB_SAVtools.TabIndex = 102; - this.GB_SAVtools.TabStop = false; - // // FLP_SAVtools // this.FLP_SAVtools.AutoScroll = true; @@ -481,17 +395,19 @@ namespace PKHeX.WinForms.Controls this.FLP_SAVtools.Controls.Add(this.B_OpenSealStickers); this.FLP_SAVtools.Controls.Add(this.B_Poffins); this.FLP_SAVtools.Controls.Add(this.B_RaidsSevenStar); - this.FLP_SAVtools.Dock = System.Windows.Forms.DockStyle.Fill; - this.FLP_SAVtools.Location = new System.Drawing.Point(3, 16); + this.FLP_SAVtools.Dock = System.Windows.Forms.DockStyle.Bottom; + this.FLP_SAVtools.Location = new System.Drawing.Point(0, 175); + this.FLP_SAVtools.Margin = new System.Windows.Forms.Padding(0); this.FLP_SAVtools.Name = "FLP_SAVtools"; - this.FLP_SAVtools.Size = new System.Drawing.Size(435, 143); + this.FLP_SAVtools.Size = new System.Drawing.Size(441, 160); this.FLP_SAVtools.TabIndex = 101; // // B_OpenTrainerInfo // - this.B_OpenTrainerInfo.Location = new System.Drawing.Point(3, 3); + this.B_OpenTrainerInfo.Location = new System.Drawing.Point(4, 4); + this.B_OpenTrainerInfo.Margin = new System.Windows.Forms.Padding(4); this.B_OpenTrainerInfo.Name = "B_OpenTrainerInfo"; - this.B_OpenTrainerInfo.Size = new System.Drawing.Size(95, 30); + this.B_OpenTrainerInfo.Size = new System.Drawing.Size(96, 32); this.B_OpenTrainerInfo.TabIndex = 1; this.B_OpenTrainerInfo.Text = "Trainer Info"; this.B_OpenTrainerInfo.UseVisualStyleBackColor = true; @@ -499,9 +415,10 @@ namespace PKHeX.WinForms.Controls // // B_OpenItemPouch // - this.B_OpenItemPouch.Location = new System.Drawing.Point(104, 3); + this.B_OpenItemPouch.Location = new System.Drawing.Point(108, 4); + this.B_OpenItemPouch.Margin = new System.Windows.Forms.Padding(4); this.B_OpenItemPouch.Name = "B_OpenItemPouch"; - this.B_OpenItemPouch.Size = new System.Drawing.Size(95, 30); + this.B_OpenItemPouch.Size = new System.Drawing.Size(96, 32); this.B_OpenItemPouch.TabIndex = 1; this.B_OpenItemPouch.Text = "Items"; this.B_OpenItemPouch.UseVisualStyleBackColor = true; @@ -509,9 +426,10 @@ namespace PKHeX.WinForms.Controls // // B_OpenBoxLayout // - this.B_OpenBoxLayout.Location = new System.Drawing.Point(205, 3); + this.B_OpenBoxLayout.Location = new System.Drawing.Point(212, 4); + this.B_OpenBoxLayout.Margin = new System.Windows.Forms.Padding(4); this.B_OpenBoxLayout.Name = "B_OpenBoxLayout"; - this.B_OpenBoxLayout.Size = new System.Drawing.Size(95, 30); + this.B_OpenBoxLayout.Size = new System.Drawing.Size(96, 32); this.B_OpenBoxLayout.TabIndex = 1; this.B_OpenBoxLayout.Text = "Box Layout"; this.B_OpenBoxLayout.UseVisualStyleBackColor = true; @@ -519,9 +437,10 @@ namespace PKHeX.WinForms.Controls // // B_OpenWondercards // - this.B_OpenWondercards.Location = new System.Drawing.Point(306, 3); + this.B_OpenWondercards.Location = new System.Drawing.Point(316, 4); + this.B_OpenWondercards.Margin = new System.Windows.Forms.Padding(4); this.B_OpenWondercards.Name = "B_OpenWondercards"; - this.B_OpenWondercards.Size = new System.Drawing.Size(95, 30); + this.B_OpenWondercards.Size = new System.Drawing.Size(96, 32); this.B_OpenWondercards.TabIndex = 1; this.B_OpenWondercards.Text = "Wondercard"; this.B_OpenWondercards.UseVisualStyleBackColor = true; @@ -529,9 +448,10 @@ namespace PKHeX.WinForms.Controls // // B_OpenOPowers // - this.B_OpenOPowers.Location = new System.Drawing.Point(3, 39); + this.B_OpenOPowers.Location = new System.Drawing.Point(4, 44); + this.B_OpenOPowers.Margin = new System.Windows.Forms.Padding(4); this.B_OpenOPowers.Name = "B_OpenOPowers"; - this.B_OpenOPowers.Size = new System.Drawing.Size(95, 30); + this.B_OpenOPowers.Size = new System.Drawing.Size(96, 32); this.B_OpenOPowers.TabIndex = 1; this.B_OpenOPowers.Text = "O-Powers"; this.B_OpenOPowers.UseVisualStyleBackColor = true; @@ -539,9 +459,10 @@ namespace PKHeX.WinForms.Controls // // B_OpenEventFlags // - this.B_OpenEventFlags.Location = new System.Drawing.Point(104, 39); + this.B_OpenEventFlags.Location = new System.Drawing.Point(108, 44); + this.B_OpenEventFlags.Margin = new System.Windows.Forms.Padding(4); this.B_OpenEventFlags.Name = "B_OpenEventFlags"; - this.B_OpenEventFlags.Size = new System.Drawing.Size(95, 30); + this.B_OpenEventFlags.Size = new System.Drawing.Size(96, 32); this.B_OpenEventFlags.TabIndex = 1; this.B_OpenEventFlags.Text = "Event Flags"; this.B_OpenEventFlags.UseVisualStyleBackColor = true; @@ -549,9 +470,10 @@ namespace PKHeX.WinForms.Controls // // B_OpenPokedex // - this.B_OpenPokedex.Location = new System.Drawing.Point(205, 39); + this.B_OpenPokedex.Location = new System.Drawing.Point(212, 44); + this.B_OpenPokedex.Margin = new System.Windows.Forms.Padding(4); this.B_OpenPokedex.Name = "B_OpenPokedex"; - this.B_OpenPokedex.Size = new System.Drawing.Size(95, 30); + this.B_OpenPokedex.Size = new System.Drawing.Size(96, 32); this.B_OpenPokedex.TabIndex = 1; this.B_OpenPokedex.Text = "Pokédex"; this.B_OpenPokedex.UseVisualStyleBackColor = true; @@ -559,9 +481,10 @@ namespace PKHeX.WinForms.Controls // // B_OpenLinkInfo // - this.B_OpenLinkInfo.Location = new System.Drawing.Point(306, 39); + this.B_OpenLinkInfo.Location = new System.Drawing.Point(316, 44); + this.B_OpenLinkInfo.Margin = new System.Windows.Forms.Padding(4); this.B_OpenLinkInfo.Name = "B_OpenLinkInfo"; - this.B_OpenLinkInfo.Size = new System.Drawing.Size(95, 30); + this.B_OpenLinkInfo.Size = new System.Drawing.Size(96, 32); this.B_OpenLinkInfo.TabIndex = 1; this.B_OpenLinkInfo.Text = "Link Data"; this.B_OpenLinkInfo.UseVisualStyleBackColor = true; @@ -569,9 +492,10 @@ namespace PKHeX.WinForms.Controls // // B_OpenBerryField // - this.B_OpenBerryField.Location = new System.Drawing.Point(3, 75); + this.B_OpenBerryField.Location = new System.Drawing.Point(4, 84); + this.B_OpenBerryField.Margin = new System.Windows.Forms.Padding(4); this.B_OpenBerryField.Name = "B_OpenBerryField"; - this.B_OpenBerryField.Size = new System.Drawing.Size(95, 30); + this.B_OpenBerryField.Size = new System.Drawing.Size(96, 32); this.B_OpenBerryField.TabIndex = 1; this.B_OpenBerryField.Text = "Berry Field"; this.B_OpenBerryField.UseVisualStyleBackColor = true; @@ -579,9 +503,10 @@ namespace PKHeX.WinForms.Controls // // B_OpenPokeblocks // - this.B_OpenPokeblocks.Location = new System.Drawing.Point(104, 75); + this.B_OpenPokeblocks.Location = new System.Drawing.Point(108, 84); + this.B_OpenPokeblocks.Margin = new System.Windows.Forms.Padding(4); this.B_OpenPokeblocks.Name = "B_OpenPokeblocks"; - this.B_OpenPokeblocks.Size = new System.Drawing.Size(95, 30); + this.B_OpenPokeblocks.Size = new System.Drawing.Size(96, 32); this.B_OpenPokeblocks.TabIndex = 1; this.B_OpenPokeblocks.Text = "Pokéblocks"; this.B_OpenPokeblocks.UseVisualStyleBackColor = true; @@ -590,9 +515,10 @@ namespace PKHeX.WinForms.Controls // // B_OpenSecretBase // - this.B_OpenSecretBase.Location = new System.Drawing.Point(205, 75); + this.B_OpenSecretBase.Location = new System.Drawing.Point(212, 84); + this.B_OpenSecretBase.Margin = new System.Windows.Forms.Padding(4); this.B_OpenSecretBase.Name = "B_OpenSecretBase"; - this.B_OpenSecretBase.Size = new System.Drawing.Size(95, 30); + this.B_OpenSecretBase.Size = new System.Drawing.Size(96, 32); this.B_OpenSecretBase.TabIndex = 1; this.B_OpenSecretBase.Text = "Secret Base"; this.B_OpenSecretBase.UseVisualStyleBackColor = true; @@ -601,9 +527,10 @@ namespace PKHeX.WinForms.Controls // // B_OpenPokepuffs // - this.B_OpenPokepuffs.Location = new System.Drawing.Point(306, 75); + this.B_OpenPokepuffs.Location = new System.Drawing.Point(316, 84); + this.B_OpenPokepuffs.Margin = new System.Windows.Forms.Padding(4); this.B_OpenPokepuffs.Name = "B_OpenPokepuffs"; - this.B_OpenPokepuffs.Size = new System.Drawing.Size(95, 30); + this.B_OpenPokepuffs.Size = new System.Drawing.Size(96, 32); this.B_OpenPokepuffs.TabIndex = 1; this.B_OpenPokepuffs.Text = "‎Poké Puffs"; this.B_OpenPokepuffs.UseVisualStyleBackColor = true; @@ -611,10 +538,11 @@ namespace PKHeX.WinForms.Controls // // B_OpenSuperTraining // - this.B_OpenSuperTraining.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); - this.B_OpenSuperTraining.Location = new System.Drawing.Point(3, 111); + this.B_OpenSuperTraining.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); + this.B_OpenSuperTraining.Location = new System.Drawing.Point(4, 124); + this.B_OpenSuperTraining.Margin = new System.Windows.Forms.Padding(4); this.B_OpenSuperTraining.Name = "B_OpenSuperTraining"; - this.B_OpenSuperTraining.Size = new System.Drawing.Size(95, 30); + this.B_OpenSuperTraining.Size = new System.Drawing.Size(96, 32); this.B_OpenSuperTraining.TabIndex = 1; this.B_OpenSuperTraining.Text = "Super Train"; this.B_OpenSuperTraining.UseVisualStyleBackColor = true; @@ -622,9 +550,10 @@ namespace PKHeX.WinForms.Controls // // B_OpenHallofFame // - this.B_OpenHallofFame.Location = new System.Drawing.Point(104, 111); + this.B_OpenHallofFame.Location = new System.Drawing.Point(108, 124); + this.B_OpenHallofFame.Margin = new System.Windows.Forms.Padding(4); this.B_OpenHallofFame.Name = "B_OpenHallofFame"; - this.B_OpenHallofFame.Size = new System.Drawing.Size(95, 30); + this.B_OpenHallofFame.Size = new System.Drawing.Size(96, 32); this.B_OpenHallofFame.TabIndex = 1; this.B_OpenHallofFame.Text = "Hall of Fame"; this.B_OpenHallofFame.UseVisualStyleBackColor = true; @@ -632,9 +561,10 @@ namespace PKHeX.WinForms.Controls // // B_OUTPasserby // - this.B_OUTPasserby.Location = new System.Drawing.Point(205, 111); + this.B_OUTPasserby.Location = new System.Drawing.Point(212, 124); + this.B_OUTPasserby.Margin = new System.Windows.Forms.Padding(4); this.B_OUTPasserby.Name = "B_OUTPasserby"; - this.B_OUTPasserby.Size = new System.Drawing.Size(95, 30); + this.B_OUTPasserby.Size = new System.Drawing.Size(96, 32); this.B_OUTPasserby.TabIndex = 1; this.B_OUTPasserby.Text = "Passerby"; this.B_OUTPasserby.UseVisualStyleBackColor = true; @@ -642,9 +572,10 @@ namespace PKHeX.WinForms.Controls // // B_CGearSkin // - this.B_CGearSkin.Location = new System.Drawing.Point(306, 111); + this.B_CGearSkin.Location = new System.Drawing.Point(316, 124); + this.B_CGearSkin.Margin = new System.Windows.Forms.Padding(4); this.B_CGearSkin.Name = "B_CGearSkin"; - this.B_CGearSkin.Size = new System.Drawing.Size(95, 30); + this.B_CGearSkin.Size = new System.Drawing.Size(96, 32); this.B_CGearSkin.TabIndex = 1; this.B_CGearSkin.Text = "C-Gear Skin"; this.B_CGearSkin.UseVisualStyleBackColor = true; @@ -652,9 +583,10 @@ namespace PKHeX.WinForms.Controls // // B_OpenPokeBeans // - this.B_OpenPokeBeans.Location = new System.Drawing.Point(3, 147); + this.B_OpenPokeBeans.Location = new System.Drawing.Point(4, 164); + this.B_OpenPokeBeans.Margin = new System.Windows.Forms.Padding(4); this.B_OpenPokeBeans.Name = "B_OpenPokeBeans"; - this.B_OpenPokeBeans.Size = new System.Drawing.Size(95, 30); + this.B_OpenPokeBeans.Size = new System.Drawing.Size(96, 32); this.B_OpenPokeBeans.TabIndex = 1; this.B_OpenPokeBeans.Text = "‎Poké Beans"; this.B_OpenPokeBeans.UseVisualStyleBackColor = true; @@ -662,9 +594,10 @@ namespace PKHeX.WinForms.Controls // // B_CellsStickers // - this.B_CellsStickers.Location = new System.Drawing.Point(104, 147); + this.B_CellsStickers.Location = new System.Drawing.Point(108, 164); + this.B_CellsStickers.Margin = new System.Windows.Forms.Padding(4); this.B_CellsStickers.Name = "B_CellsStickers"; - this.B_CellsStickers.Size = new System.Drawing.Size(95, 30); + this.B_CellsStickers.Size = new System.Drawing.Size(96, 32); this.B_CellsStickers.TabIndex = 1; this.B_CellsStickers.Text = "Cells/Stickers"; this.B_CellsStickers.UseVisualStyleBackColor = true; @@ -672,9 +605,10 @@ namespace PKHeX.WinForms.Controls // // B_OpenMiscEditor // - this.B_OpenMiscEditor.Location = new System.Drawing.Point(205, 147); + this.B_OpenMiscEditor.Location = new System.Drawing.Point(212, 164); + this.B_OpenMiscEditor.Margin = new System.Windows.Forms.Padding(4); this.B_OpenMiscEditor.Name = "B_OpenMiscEditor"; - this.B_OpenMiscEditor.Size = new System.Drawing.Size(95, 30); + this.B_OpenMiscEditor.Size = new System.Drawing.Size(96, 32); this.B_OpenMiscEditor.TabIndex = 1; this.B_OpenMiscEditor.Text = "Misc Edits"; this.B_OpenMiscEditor.UseVisualStyleBackColor = true; @@ -682,9 +616,10 @@ namespace PKHeX.WinForms.Controls // // B_OpenHoneyTreeEditor // - this.B_OpenHoneyTreeEditor.Location = new System.Drawing.Point(306, 147); + this.B_OpenHoneyTreeEditor.Location = new System.Drawing.Point(316, 164); + this.B_OpenHoneyTreeEditor.Margin = new System.Windows.Forms.Padding(4); this.B_OpenHoneyTreeEditor.Name = "B_OpenHoneyTreeEditor"; - this.B_OpenHoneyTreeEditor.Size = new System.Drawing.Size(95, 30); + this.B_OpenHoneyTreeEditor.Size = new System.Drawing.Size(96, 32); this.B_OpenHoneyTreeEditor.TabIndex = 1; this.B_OpenHoneyTreeEditor.Text = "Honey Tree"; this.B_OpenHoneyTreeEditor.UseVisualStyleBackColor = true; @@ -692,9 +627,10 @@ namespace PKHeX.WinForms.Controls // // B_OpenFriendSafari // - this.B_OpenFriendSafari.Location = new System.Drawing.Point(3, 183); + this.B_OpenFriendSafari.Location = new System.Drawing.Point(4, 204); + this.B_OpenFriendSafari.Margin = new System.Windows.Forms.Padding(4); this.B_OpenFriendSafari.Name = "B_OpenFriendSafari"; - this.B_OpenFriendSafari.Size = new System.Drawing.Size(95, 30); + this.B_OpenFriendSafari.Size = new System.Drawing.Size(96, 32); this.B_OpenFriendSafari.TabIndex = 1; this.B_OpenFriendSafari.Text = "Friend Safari"; this.B_OpenFriendSafari.UseVisualStyleBackColor = true; @@ -702,9 +638,10 @@ namespace PKHeX.WinForms.Controls // // B_OpenRTCEditor // - this.B_OpenRTCEditor.Location = new System.Drawing.Point(104, 183); + this.B_OpenRTCEditor.Location = new System.Drawing.Point(108, 204); + this.B_OpenRTCEditor.Margin = new System.Windows.Forms.Padding(4); this.B_OpenRTCEditor.Name = "B_OpenRTCEditor"; - this.B_OpenRTCEditor.Size = new System.Drawing.Size(95, 30); + this.B_OpenRTCEditor.Size = new System.Drawing.Size(96, 32); this.B_OpenRTCEditor.TabIndex = 1; this.B_OpenRTCEditor.Text = "Clock (RTC)"; this.B_OpenRTCEditor.UseVisualStyleBackColor = true; @@ -712,9 +649,10 @@ namespace PKHeX.WinForms.Controls // // B_OpenUGSEditor // - this.B_OpenUGSEditor.Location = new System.Drawing.Point(205, 183); + this.B_OpenUGSEditor.Location = new System.Drawing.Point(212, 204); + this.B_OpenUGSEditor.Margin = new System.Windows.Forms.Padding(4); this.B_OpenUGSEditor.Name = "B_OpenUGSEditor"; - this.B_OpenUGSEditor.Size = new System.Drawing.Size(95, 30); + this.B_OpenUGSEditor.Size = new System.Drawing.Size(96, 32); this.B_OpenUGSEditor.TabIndex = 1; this.B_OpenUGSEditor.Text = "Underground"; this.B_OpenUGSEditor.UseVisualStyleBackColor = true; @@ -722,9 +660,10 @@ namespace PKHeX.WinForms.Controls // // B_Roamer // - this.B_Roamer.Location = new System.Drawing.Point(306, 183); + this.B_Roamer.Location = new System.Drawing.Point(316, 204); + this.B_Roamer.Margin = new System.Windows.Forms.Padding(4); this.B_Roamer.Name = "B_Roamer"; - this.B_Roamer.Size = new System.Drawing.Size(95, 30); + this.B_Roamer.Size = new System.Drawing.Size(96, 32); this.B_Roamer.TabIndex = 1; this.B_Roamer.Text = "Roamer"; this.B_Roamer.UseVisualStyleBackColor = true; @@ -732,9 +671,10 @@ namespace PKHeX.WinForms.Controls // // B_FestivalPlaza // - this.B_FestivalPlaza.Location = new System.Drawing.Point(3, 219); + this.B_FestivalPlaza.Location = new System.Drawing.Point(4, 244); + this.B_FestivalPlaza.Margin = new System.Windows.Forms.Padding(4); this.B_FestivalPlaza.Name = "B_FestivalPlaza"; - this.B_FestivalPlaza.Size = new System.Drawing.Size(95, 30); + this.B_FestivalPlaza.Size = new System.Drawing.Size(96, 32); this.B_FestivalPlaza.TabIndex = 1; this.B_FestivalPlaza.Text = "Festival Plaza"; this.B_FestivalPlaza.UseVisualStyleBackColor = true; @@ -742,9 +682,10 @@ namespace PKHeX.WinForms.Controls // // B_MailBox // - this.B_MailBox.Location = new System.Drawing.Point(104, 219); + this.B_MailBox.Location = new System.Drawing.Point(108, 244); + this.B_MailBox.Margin = new System.Windows.Forms.Padding(4); this.B_MailBox.Name = "B_MailBox"; - this.B_MailBox.Size = new System.Drawing.Size(95, 30); + this.B_MailBox.Size = new System.Drawing.Size(96, 32); this.B_MailBox.TabIndex = 1; this.B_MailBox.Text = "Mail Box"; this.B_MailBox.UseVisualStyleBackColor = true; @@ -752,9 +693,10 @@ namespace PKHeX.WinForms.Controls // // B_OpenApricorn // - this.B_OpenApricorn.Location = new System.Drawing.Point(205, 219); + this.B_OpenApricorn.Location = new System.Drawing.Point(212, 244); + this.B_OpenApricorn.Margin = new System.Windows.Forms.Padding(4); this.B_OpenApricorn.Name = "B_OpenApricorn"; - this.B_OpenApricorn.Size = new System.Drawing.Size(95, 30); + this.B_OpenApricorn.Size = new System.Drawing.Size(96, 32); this.B_OpenApricorn.TabIndex = 1; this.B_OpenApricorn.Text = "Apricorns"; this.B_OpenApricorn.UseVisualStyleBackColor = true; @@ -762,9 +704,10 @@ namespace PKHeX.WinForms.Controls // // B_Raids // - this.B_Raids.Location = new System.Drawing.Point(306, 219); + this.B_Raids.Location = new System.Drawing.Point(316, 244); + this.B_Raids.Margin = new System.Windows.Forms.Padding(4); this.B_Raids.Name = "B_Raids"; - this.B_Raids.Size = new System.Drawing.Size(95, 30); + this.B_Raids.Size = new System.Drawing.Size(96, 32); this.B_Raids.TabIndex = 1; this.B_Raids.Text = "Raids"; this.B_Raids.UseVisualStyleBackColor = true; @@ -772,9 +715,10 @@ namespace PKHeX.WinForms.Controls // // B_RaidArmor // - this.B_RaidArmor.Location = new System.Drawing.Point(3, 255); + this.B_RaidArmor.Location = new System.Drawing.Point(4, 284); + this.B_RaidArmor.Margin = new System.Windows.Forms.Padding(4); this.B_RaidArmor.Name = "B_RaidArmor"; - this.B_RaidArmor.Size = new System.Drawing.Size(95, 30); + this.B_RaidArmor.Size = new System.Drawing.Size(96, 32); this.B_RaidArmor.TabIndex = 2; this.B_RaidArmor.Text = "Raids (DLC 1)"; this.B_RaidArmor.UseVisualStyleBackColor = true; @@ -782,9 +726,10 @@ namespace PKHeX.WinForms.Controls // // B_RaidCrown // - this.B_RaidCrown.Location = new System.Drawing.Point(104, 255); + this.B_RaidCrown.Location = new System.Drawing.Point(108, 284); + this.B_RaidCrown.Margin = new System.Windows.Forms.Padding(4); this.B_RaidCrown.Name = "B_RaidCrown"; - this.B_RaidCrown.Size = new System.Drawing.Size(95, 30); + this.B_RaidCrown.Size = new System.Drawing.Size(96, 32); this.B_RaidCrown.TabIndex = 4; this.B_RaidCrown.Text = "Raids (DLC 2)"; this.B_RaidCrown.UseVisualStyleBackColor = true; @@ -792,9 +737,10 @@ namespace PKHeX.WinForms.Controls // // B_Blocks // - this.B_Blocks.Location = new System.Drawing.Point(205, 255); + this.B_Blocks.Location = new System.Drawing.Point(212, 284); + this.B_Blocks.Margin = new System.Windows.Forms.Padding(4); this.B_Blocks.Name = "B_Blocks"; - this.B_Blocks.Size = new System.Drawing.Size(95, 30); + this.B_Blocks.Size = new System.Drawing.Size(96, 32); this.B_Blocks.TabIndex = 1; this.B_Blocks.Text = "Block Data"; this.B_Blocks.UseVisualStyleBackColor = true; @@ -802,9 +748,10 @@ namespace PKHeX.WinForms.Controls // // B_OtherSlots // - this.B_OtherSlots.Location = new System.Drawing.Point(306, 255); + this.B_OtherSlots.Location = new System.Drawing.Point(316, 284); + this.B_OtherSlots.Margin = new System.Windows.Forms.Padding(4); this.B_OtherSlots.Name = "B_OtherSlots"; - this.B_OtherSlots.Size = new System.Drawing.Size(95, 30); + this.B_OtherSlots.Size = new System.Drawing.Size(96, 32); this.B_OtherSlots.TabIndex = 3; this.B_OtherSlots.Text = "Other Slots"; this.B_OtherSlots.UseVisualStyleBackColor = true; @@ -812,9 +759,10 @@ namespace PKHeX.WinForms.Controls // // B_OpenSealStickers // - this.B_OpenSealStickers.Location = new System.Drawing.Point(3, 291); + this.B_OpenSealStickers.Location = new System.Drawing.Point(4, 324); + this.B_OpenSealStickers.Margin = new System.Windows.Forms.Padding(4); this.B_OpenSealStickers.Name = "B_OpenSealStickers"; - this.B_OpenSealStickers.Size = new System.Drawing.Size(95, 30); + this.B_OpenSealStickers.Size = new System.Drawing.Size(96, 32); this.B_OpenSealStickers.TabIndex = 5; this.B_OpenSealStickers.Text = "Seal Stickers"; this.B_OpenSealStickers.UseVisualStyleBackColor = true; @@ -822,9 +770,10 @@ namespace PKHeX.WinForms.Controls // // B_Poffins // - this.B_Poffins.Location = new System.Drawing.Point(104, 291); + this.B_Poffins.Location = new System.Drawing.Point(108, 324); + this.B_Poffins.Margin = new System.Windows.Forms.Padding(4); this.B_Poffins.Name = "B_Poffins"; - this.B_Poffins.Size = new System.Drawing.Size(95, 30); + this.B_Poffins.Size = new System.Drawing.Size(96, 32); this.B_Poffins.TabIndex = 6; this.B_Poffins.Text = "Poffins"; this.B_Poffins.UseVisualStyleBackColor = true; @@ -832,28 +781,108 @@ namespace PKHeX.WinForms.Controls // // B_RaidsSevenStar // - this.B_RaidsSevenStar.Location = new System.Drawing.Point(205, 291); + this.B_RaidsSevenStar.Location = new System.Drawing.Point(212, 324); + this.B_RaidsSevenStar.Margin = new System.Windows.Forms.Padding(4); this.B_RaidsSevenStar.Name = "B_RaidsSevenStar"; - this.B_RaidsSevenStar.Size = new System.Drawing.Size(95, 30); + this.B_RaidsSevenStar.Size = new System.Drawing.Size(96, 32); this.B_RaidsSevenStar.TabIndex = 7; this.B_RaidsSevenStar.Text = "Raids (7 Star)"; this.B_RaidsSevenStar.UseVisualStyleBackColor = true; this.B_RaidsSevenStar.Click += new System.EventHandler(this.B_OpenRaids_Click); // + // FLP_SAVToolsMisc + // + this.FLP_SAVToolsMisc.Controls.Add(this.B_SaveBoxBin); + this.FLP_SAVToolsMisc.Controls.Add(this.B_VerifyCHK); + this.FLP_SAVToolsMisc.Controls.Add(this.B_VerifySaveEntities); + this.FLP_SAVToolsMisc.Controls.Add(this.Menu_ExportBAK); + this.FLP_SAVToolsMisc.Controls.Add(this.B_JPEG); + this.FLP_SAVToolsMisc.Dock = System.Windows.Forms.DockStyle.Top; + this.FLP_SAVToolsMisc.Location = new System.Drawing.Point(0, 0); + this.FLP_SAVToolsMisc.Margin = new System.Windows.Forms.Padding(0); + this.FLP_SAVToolsMisc.Name = "FLP_SAVToolsMisc"; + this.FLP_SAVToolsMisc.Size = new System.Drawing.Size(441, 52); + this.FLP_SAVToolsMisc.TabIndex = 104; + // + // B_SaveBoxBin + // + this.B_SaveBoxBin.Location = new System.Drawing.Point(0, 0); + this.B_SaveBoxBin.Margin = new System.Windows.Forms.Padding(0); + this.B_SaveBoxBin.Name = "B_SaveBoxBin"; + this.B_SaveBoxBin.Size = new System.Drawing.Size(88, 48); + this.B_SaveBoxBin.TabIndex = 8; + this.B_SaveBoxBin.Text = "Save Box Data++"; + this.B_SaveBoxBin.UseVisualStyleBackColor = true; + this.B_SaveBoxBin.Click += new System.EventHandler(this.B_SaveBoxBin_Click); + // + // B_VerifyCHK + // + this.B_VerifyCHK.Location = new System.Drawing.Point(88, 0); + this.B_VerifyCHK.Margin = new System.Windows.Forms.Padding(0); + this.B_VerifyCHK.Name = "B_VerifyCHK"; + this.B_VerifyCHK.Size = new System.Drawing.Size(88, 48); + this.B_VerifyCHK.TabIndex = 2; + this.B_VerifyCHK.Text = "Verify Checksums"; + this.B_VerifyCHK.UseVisualStyleBackColor = true; + this.B_VerifyCHK.Click += new System.EventHandler(this.ClickVerifyCHK); + // + // B_VerifySaveEntities + // + this.B_VerifySaveEntities.Location = new System.Drawing.Point(176, 0); + this.B_VerifySaveEntities.Margin = new System.Windows.Forms.Padding(0); + this.B_VerifySaveEntities.Name = "B_VerifySaveEntities"; + this.B_VerifySaveEntities.Size = new System.Drawing.Size(88, 48); + this.B_VerifySaveEntities.TabIndex = 104; + this.B_VerifySaveEntities.Text = "Verify All PKMs"; + this.B_VerifySaveEntities.UseVisualStyleBackColor = true; + this.B_VerifySaveEntities.Click += new System.EventHandler(this.ClickVerifyStoredEntities); + // + // Menu_ExportBAK + // + this.Menu_ExportBAK.Location = new System.Drawing.Point(264, 0); + this.Menu_ExportBAK.Margin = new System.Windows.Forms.Padding(0); + this.Menu_ExportBAK.Name = "Menu_ExportBAK"; + this.Menu_ExportBAK.Size = new System.Drawing.Size(88, 48); + this.Menu_ExportBAK.TabIndex = 103; + this.Menu_ExportBAK.Text = "Export Backup"; + this.Menu_ExportBAK.UseVisualStyleBackColor = true; + this.Menu_ExportBAK.Click += new System.EventHandler(this.Menu_ExportBAK_Click); + // + // B_JPEG + // + this.B_JPEG.Location = new System.Drawing.Point(352, 0); + this.B_JPEG.Margin = new System.Windows.Forms.Padding(0); + this.B_JPEG.Name = "B_JPEG"; + this.B_JPEG.Size = new System.Drawing.Size(88, 48); + this.B_JPEG.TabIndex = 12; + this.B_JPEG.Text = "Save PGL .JPEG"; + this.B_JPEG.UseVisualStyleBackColor = true; + this.B_JPEG.Click += new System.EventHandler(this.B_JPEG_Click); + // + // CB_SaveSlot + // + this.CB_SaveSlot.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; + this.CB_SaveSlot.FormattingEnabled = true; + this.CB_SaveSlot.Location = new System.Drawing.Point(152, 144); + this.CB_SaveSlot.Name = "CB_SaveSlot"; + this.CB_SaveSlot.Size = new System.Drawing.Size(121, 23); + this.CB_SaveSlot.TabIndex = 20; + this.CB_SaveSlot.SelectedIndexChanged += new System.EventHandler(this.UpdateSaveSlot); + // // L_SaveSlot // - this.L_SaveSlot.AutoSize = true; - this.L_SaveSlot.Location = new System.Drawing.Point(92, 151); + this.L_SaveSlot.Location = new System.Drawing.Point(32, 144); this.L_SaveSlot.Name = "L_SaveSlot"; - this.L_SaveSlot.Size = new System.Drawing.Size(56, 13); + this.L_SaveSlot.Size = new System.Drawing.Size(120, 24); this.L_SaveSlot.TabIndex = 19; this.L_SaveSlot.Text = "Save Slot:"; + this.L_SaveSlot.TextAlign = System.Drawing.ContentAlignment.MiddleRight; // // L_Secure2 // - this.L_Secure2.Location = new System.Drawing.Point(33, 113); + this.L_Secure2.Location = new System.Drawing.Point(32, 112); this.L_Secure2.Name = "L_Secure2"; - this.L_Secure2.Size = new System.Drawing.Size(115, 20); + this.L_Secure2.Size = new System.Drawing.Size(120, 24); this.L_Secure2.TabIndex = 18; this.L_Secure2.Text = "Secure Value 2:"; this.L_Secure2.TextAlign = System.Drawing.ContentAlignment.MiddleRight; @@ -861,20 +890,21 @@ namespace PKHeX.WinForms.Controls // TB_Secure2 // this.TB_Secure2.Enabled = false; - this.TB_Secure2.Font = new System.Drawing.Font("Courier New", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); - this.TB_Secure2.Location = new System.Drawing.Point(151, 113); + this.TB_Secure2.Font = new System.Drawing.Font("Courier New", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); + this.TB_Secure2.Location = new System.Drawing.Point(152, 112); this.TB_Secure2.MaxLength = 16; + this.TB_Secure2.MinimumSize = new System.Drawing.Size(120, 24); this.TB_Secure2.Name = "TB_Secure2"; - this.TB_Secure2.Size = new System.Drawing.Size(120, 20); + this.TB_Secure2.PlaceholderText = "0000000000000000"; + this.TB_Secure2.Size = new System.Drawing.Size(120, 24); this.TB_Secure2.TabIndex = 17; - this.TB_Secure2.Text = "0000000000000000"; this.TB_Secure2.Validated += new System.EventHandler(this.UpdateStringSeed); // // L_Secure1 // - this.L_Secure1.Location = new System.Drawing.Point(33, 91); + this.L_Secure1.Location = new System.Drawing.Point(32, 88); this.L_Secure1.Name = "L_Secure1"; - this.L_Secure1.Size = new System.Drawing.Size(115, 20); + this.L_Secure1.Size = new System.Drawing.Size(120, 24); this.L_Secure1.TabIndex = 16; this.L_Secure1.Text = "Secure Value 1:"; this.L_Secure1.TextAlign = System.Drawing.ContentAlignment.MiddleRight; @@ -882,20 +912,21 @@ namespace PKHeX.WinForms.Controls // TB_Secure1 // this.TB_Secure1.Enabled = false; - this.TB_Secure1.Font = new System.Drawing.Font("Courier New", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); - this.TB_Secure1.Location = new System.Drawing.Point(151, 91); + this.TB_Secure1.Font = new System.Drawing.Font("Courier New", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); + this.TB_Secure1.Location = new System.Drawing.Point(152, 88); this.TB_Secure1.MaxLength = 16; + this.TB_Secure1.MinimumSize = new System.Drawing.Size(120, 24); this.TB_Secure1.Name = "TB_Secure1"; - this.TB_Secure1.Size = new System.Drawing.Size(120, 20); + this.TB_Secure1.PlaceholderText = "0000000000000000"; + this.TB_Secure1.Size = new System.Drawing.Size(120, 24); this.TB_Secure1.TabIndex = 15; - this.TB_Secure1.Text = "0000000000000000"; this.TB_Secure1.Validated += new System.EventHandler(this.UpdateStringSeed); // // L_GameSync // - this.L_GameSync.Location = new System.Drawing.Point(33, 69); + this.L_GameSync.Location = new System.Drawing.Point(32, 64); this.L_GameSync.Name = "L_GameSync"; - this.L_GameSync.Size = new System.Drawing.Size(115, 20); + this.L_GameSync.Size = new System.Drawing.Size(120, 24); this.L_GameSync.TabIndex = 11; this.L_GameSync.Text = "Game Sync ID:"; this.L_GameSync.TextAlign = System.Drawing.ContentAlignment.MiddleRight; @@ -903,13 +934,14 @@ namespace PKHeX.WinForms.Controls // TB_GameSync // this.TB_GameSync.Enabled = false; - this.TB_GameSync.Font = new System.Drawing.Font("Courier New", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); - this.TB_GameSync.Location = new System.Drawing.Point(151, 69); + this.TB_GameSync.Font = new System.Drawing.Font("Courier New", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); + this.TB_GameSync.Location = new System.Drawing.Point(152, 64); this.TB_GameSync.MaxLength = 16; + this.TB_GameSync.MinimumSize = new System.Drawing.Size(120, 24); this.TB_GameSync.Name = "TB_GameSync"; - this.TB_GameSync.Size = new System.Drawing.Size(120, 20); + this.TB_GameSync.PlaceholderText = "0000000000000000"; + this.TB_GameSync.Size = new System.Drawing.Size(120, 24); this.TB_GameSync.TabIndex = 10; - this.TB_GameSync.Text = "0000000000000000"; this.TB_GameSync.Validated += new System.EventHandler(this.UpdateStringSeed); // // SAVEditor @@ -930,9 +962,8 @@ namespace PKHeX.WinForms.Controls ((System.ComponentModel.ISupportInitialize)(this.dcpkx1)).EndInit(); this.Tab_SAV.ResumeLayout(false); this.Tab_SAV.PerformLayout(); - this.FLP_SAVToolsMisc.ResumeLayout(false); - this.GB_SAVtools.ResumeLayout(false); this.FLP_SAVtools.ResumeLayout(false); + this.FLP_SAVToolsMisc.ResumeLayout(false); this.ResumeLayout(false); } @@ -968,7 +999,6 @@ namespace PKHeX.WinForms.Controls private System.Windows.Forms.TextBox TB_GameSync; private System.Windows.Forms.Button B_SaveBoxBin; private System.Windows.Forms.Button B_VerifyCHK; - private System.Windows.Forms.GroupBox GB_SAVtools; private System.Windows.Forms.FlowLayoutPanel FLP_SAVtools; private System.Windows.Forms.Button B_OpenTrainerInfo; private System.Windows.Forms.Button B_OpenItemPouch; diff --git a/PKHeX.WinForms/Controls/SAV Editor/SAVEditor.cs b/PKHeX.WinForms/Controls/SAV Editor/SAVEditor.cs index ee85e2143..d5f13e912 100644 --- a/PKHeX.WinForms/Controls/SAV Editor/SAVEditor.cs +++ b/PKHeX.WinForms/Controls/SAV Editor/SAVEditor.cs @@ -1098,7 +1098,7 @@ public partial class SAVEditor : UserControl, ISlotViewer, ISaveFile { if (!sav.State.Exportable || sav is BulkStorage) { - GB_SAVtools.Visible = false; + FLP_SAVtools.Visible = false; B_JPEG.Visible = false; SL_Extra.HideAllSlots(); return; @@ -1136,7 +1136,7 @@ public partial class SAVEditor : UserControl, ISlotViewer, ISaveFile B_RaidsSevenStar.Visible = sav is SAV9SV; B_RaidArmor.Visible = sav is SAV8SWSH {SaveRevision: >= 1}; B_RaidCrown.Visible = sav is SAV8SWSH {SaveRevision: >= 2}; - GB_SAVtools.Visible = B_Blocks.Visible = true; + FLP_SAVtools.Visible = B_Blocks.Visible = true; var list = FLP_SAVtools.Controls.OfType().OrderBy(z => z.Text).ToArray(); FLP_SAVtools.Controls.Clear(); diff --git a/PKHeX.WinForms/Controls/SAV Editor/SAVEditor.resx b/PKHeX.WinForms/Controls/SAV Editor/SAVEditor.resx index 1af7de150..f298a7be8 100644 --- a/PKHeX.WinForms/Controls/SAV Editor/SAVEditor.resx +++ b/PKHeX.WinForms/Controls/SAV Editor/SAVEditor.resx @@ -1,64 +1,4 @@ - - - + diff --git a/PKHeX.WinForms/Controls/Slots/CryPlayer.cs b/PKHeX.WinForms/Controls/Slots/CryPlayer.cs index 52d64fa52..75ffb1ba5 100644 --- a/PKHeX.WinForms/Controls/Slots/CryPlayer.cs +++ b/PKHeX.WinForms/Controls/Slots/CryPlayer.cs @@ -44,7 +44,7 @@ public sealed class CryPlayer private static string GetCryFileName(ISpeciesForm pk, EntityContext context) { - if (pk.Species == (int)Species.Urshifu && pk.Form == 1) // same sprite for both forms, but different cries + if (pk is { Species: (int)Species.Urshifu, Form: 1 }) // same sprite for both forms, but different cries return "892-1"; // don't grab sprite of pk, no gender specific cries diff --git a/PKHeX.WinForms/Controls/Slots/DoubleBufferedDataGridView.cs b/PKHeX.WinForms/Controls/Slots/DoubleBufferedDataGridView.cs new file mode 100644 index 000000000..05611620e --- /dev/null +++ b/PKHeX.WinForms/Controls/Slots/DoubleBufferedDataGridView.cs @@ -0,0 +1,8 @@ +using System.Windows.Forms; + +namespace PKHeX.WinForms.Controls; + +internal class DoubleBufferedDataGridView : DataGridView +{ + public DoubleBufferedDataGridView() => SetStyle(ControlStyles.OptimizedDoubleBuffer, true); +} diff --git a/PKHeX.WinForms/Controls/Slots/SlotHoverHandler.cs b/PKHeX.WinForms/Controls/Slots/SlotHoverHandler.cs index 5601492c9..3aa6eb5e4 100644 --- a/PKHeX.WinForms/Controls/Slots/SlotHoverHandler.cs +++ b/PKHeX.WinForms/Controls/Slots/SlotHoverHandler.cs @@ -41,11 +41,12 @@ public sealed class SlotHoverHandler : IDisposable { HoverWorker.Stop(); var hover = Hover; - SpriteUtil.GetSpriteGlow(pk, Draw.GlowInitial.B, Draw.GlowInitial.G, Draw.GlowInitial.R, out var glowdata, out var GlowBase); - bg = ImageUtil.LayerImage(GlowBase, hover, 0, 0); + var glow = Draw.GlowInitial; + SpriteUtil.GetSpriteGlow(pk, glow.B, glow.G, glow.R, out var glowdata, out var imgGlowBase); + bg = ImageUtil.LayerImage(imgGlowBase, hover, 0, 0); HoverWorker.GlowToColor = Draw.GlowFinal; HoverWorker.GlowFromColor = Draw.GlowInitial; - HoverWorker.Start(pb, GlowBase, glowdata, orig, hover); + HoverWorker.Start(pb, imgGlowBase, glowdata, orig, hover); } else { diff --git a/PKHeX.WinForms/Controls/Slots/SlotList.Designer.cs b/PKHeX.WinForms/Controls/Slots/SlotList.Designer.cs index 0c77ab4c0..af3767b5f 100644 --- a/PKHeX.WinForms/Controls/Slots/SlotList.Designer.cs +++ b/PKHeX.WinForms/Controls/Slots/SlotList.Designer.cs @@ -1,4 +1,4 @@ -namespace PKHeX.WinForms.Controls +namespace PKHeX.WinForms.Controls { partial class SlotList { @@ -28,7 +28,7 @@ ///
private void InitializeComponent() { - this.FLP_Slots = new System.Windows.Forms.FlowLayoutPanel(); + this.FLP_Slots = new System.Windows.Forms.TableLayoutPanel(); this.SuspendLayout(); // // FLP_Slots @@ -52,6 +52,6 @@ #endregion - private System.Windows.Forms.FlowLayoutPanel FLP_Slots; + private System.Windows.Forms.TableLayoutPanel FLP_Slots; } } diff --git a/PKHeX.WinForms/Controls/Slots/SlotList.cs b/PKHeX.WinForms/Controls/Slots/SlotList.cs index c012beab0..6b5a5bff8 100644 --- a/PKHeX.WinForms/Controls/Slots/SlotList.cs +++ b/PKHeX.WinForms/Controls/Slots/SlotList.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using System.Windows.Forms; using PKHeX.Core; @@ -9,7 +9,7 @@ namespace PKHeX.WinForms.Controls; public partial class SlotList : UserControl, ISlotViewer { private static readonly string[] names = Enum.GetNames(typeof(StorageSlotType)); - private readonly LabelType[] Labels = new LabelType[names.Length]; + private readonly Label[] Labels = new Label[names.Length]; private readonly List slots = new(); private List SlotOffsets = new(); public int SlotCount { get; private set; } @@ -43,7 +43,7 @@ public partial class SlotList : UserControl, ISlotViewer { if (previous is not SlotInfoMisc m) return; - var index = SlotOffsets.FindIndex(z => m.Equals(z)); + var index = SlotOffsets.FindIndex(m.Equals); if (index < 0) return; var pb = slots[index]; @@ -84,37 +84,52 @@ public partial class SlotList : UserControl, ISlotViewer public int GetSlotOffset(int slot) => SlotOffsets[slot].Offset; public int ViewIndex { get; set; } = -1; - private IEnumerable LoadSlots(int after, Action enableDragDropContext) + private void LoadSlots(int count, Action enableDragDropContext) { - var generated = new List(); - int before = SlotCount; - SlotCount = after; - int diff = after - before; - if (diff > 0) + var controls = FLP_Slots.Controls; + controls.Clear(); + if (count == 0) { - AddSlots(diff); - for (int i = before; i < after; i++) - { - var slot = slots[i]; - enableDragDropContext(slot); - FLP_Slots.Controls.Add(slot); - FLP_Slots.SetFlowBreak(slot, true); - generated.Add(slot); - } + SlotCount = 0; + return; } - else - { - for (int i = before - 1; i >= after; i--) - FLP_Slots.Controls.Remove(slots[i]); - } - SetLabelVisibility(); - return generated; + AddSlots(count, enableDragDropContext); + AddControls(count); + SlotCount = count; } - private void AddSlots(int count) + private void AddControls(int countTotal) { - for (int i = 0; i < count; i++) - slots.Add(GetPictureBox(i, SpriteUtil.Spriter)); + var type = (StorageSlotType)(-1); + int added = -1; + for (int i = 0; i < countTotal; i++) + { + var info = SlotOffsets[i]; + if (type != info.Type) + { + added++; + type = info.Type; + var label = Labels[(int)type]; + FLP_Slots.Controls.Add(label, 0, added++); + } + + var slot = slots[i]; + FLP_Slots.Controls.Add(slot, 0, added); + } + } + + private void AddSlots(int after, Action enableDragDropContext) + { + int before = SlotCount; + int diff = after - before; + if (diff <= 0) + return; + for (int i = 0; i < diff; i++) + { + var slot = GetPictureBox(i, SpriteUtil.Spriter); + enableDragDropContext(slot); + slots.Add(slot); + } } private const int PadPixels = 2; @@ -126,53 +141,24 @@ public partial class SlotList : UserControl, ISlotViewer Height = s.Height + 2, AllowDrop = true, Margin = new Padding(PadPixels), + Padding = Padding.Empty, SizeMode = PictureBoxSizeMode.CenterImage, Name = $"bpkm{index}", }; - private sealed class LabelType : Label - { - public StorageSlotType Type; - } - private void AddLabels() { for (var i = 0; i < names.Length; i++) { var name = names[i]; - bool result = Enum.TryParse(name, out var value); - if (!result) - continue; - - var label = new LabelType + Labels[i] = new Label { Name = $"L_{name}", Text = name, - Type = value, AutoSize = true, - Visible = false, + Margin = Padding.Empty, + Padding = Padding.Empty, }; - Labels[i] = label; - FLP_Slots.Controls.Add(label); - FLP_Slots.SetFlowBreak(label, true); - } - } - - private void SetLabelVisibility() - { - foreach (var l in Labels) - { - int index = SlotOffsets.FindIndex(z => z.Type == l.Type); - if (index < 0) - { - l.Visible = false; - continue; - } - int pos = FLP_Slots.Controls.IndexOf(slots[index]); - if (pos > FLP_Slots.Controls.IndexOf(l)) - pos--; - FLP_Slots.Controls.SetChildIndex(l, pos); - l.Visible = true; } } } diff --git a/PKHeX.WinForms/FodyWeavers.xml b/PKHeX.WinForms/FodyWeavers.xml deleted file mode 100644 index a5dcf04fd..000000000 --- a/PKHeX.WinForms/FodyWeavers.xml +++ /dev/null @@ -1,4 +0,0 @@ - - - - \ No newline at end of file diff --git a/PKHeX.WinForms/FodyWeavers.xsd b/PKHeX.WinForms/FodyWeavers.xsd deleted file mode 100644 index 44a53744f..000000000 --- a/PKHeX.WinForms/FodyWeavers.xsd +++ /dev/null @@ -1,111 +0,0 @@ - - - - - - - - - - - - A list of assembly names to exclude from the default action of "embed all Copy Local references", delimited with line breaks - - - - - A list of assembly names to include from the default action of "embed all Copy Local references", delimited with line breaks. - - - - - A list of unmanaged 32 bit assembly names to include, delimited with line breaks. - - - - - A list of unmanaged 64 bit assembly names to include, delimited with line breaks. - - - - - The order of preloaded assemblies, delimited with line breaks. - - - - - - This will copy embedded files to disk before loading them into memory. This is helpful for some scenarios that expected an assembly to be loaded from a physical file. - - - - - Controls if .pdbs for reference assemblies are also embedded. - - - - - Embedded assemblies are compressed by default, and uncompressed when they are loaded. You can turn compression off with this option. - - - - - As part of Costura, embedded assemblies are no longer included as part of the build. This cleanup can be turned off. - - - - - Costura by default will load as part of the module initialization. This flag disables that behavior. Make sure you call CosturaUtility.Initialize() somewhere in your code. - - - - - Costura will by default use assemblies with a name like 'resources.dll' as a satellite resource and prepend the output path. This flag disables that behavior. - - - - - A list of assembly names to exclude from the default action of "embed all Copy Local references", delimited with | - - - - - A list of assembly names to include from the default action of "embed all Copy Local references", delimited with |. - - - - - A list of unmanaged 32 bit assembly names to include, delimited with |. - - - - - A list of unmanaged 64 bit assembly names to include, delimited with |. - - - - - The order of preloaded assemblies, delimited with |. - - - - - - - - 'true' to run assembly verification (PEVerify) on the target assembly after all weavers have been executed. - - - - - A comma-separated list of error codes that can be safely ignored in assembly verification. - - - - - 'false' to turn off automatic generation of the XML Schema file. - - - - - \ No newline at end of file diff --git a/PKHeX.WinForms/MainWindow/Main.Designer.cs b/PKHeX.WinForms/MainWindow/Main.Designer.cs index 2c314d3e5..c13319091 100644 --- a/PKHeX.WinForms/MainWindow/Main.Designer.cs +++ b/PKHeX.WinForms/MainWindow/Main.Designer.cs @@ -62,22 +62,22 @@ this.L_UpdateAvailable = new System.Windows.Forms.LinkLabel(); this.toolTip = new System.Windows.Forms.ToolTip(this.components); this.splitContainer1 = new System.Windows.Forms.SplitContainer(); + this.dragout = new System.Windows.Forms.PictureBox(); + this.PB_Legal = new System.Windows.Forms.PictureBox(); this.PKME_Tabs = new PKHeX.WinForms.Controls.PKMEditor(); this.C_SAV = new PKHeX.WinForms.Controls.SAVEditor(); this.splitContainer2 = new System.Windows.Forms.SplitContainer(); - this.dragout = new System.Windows.Forms.PictureBox(); - this.PB_Legal = new System.Windows.Forms.PictureBox(); this.menuStrip1.SuspendLayout(); ((System.ComponentModel.ISupportInitialize)(this.splitContainer1)).BeginInit(); this.splitContainer1.Panel1.SuspendLayout(); this.splitContainer1.Panel2.SuspendLayout(); this.splitContainer1.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.dragout)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.PB_Legal)).BeginInit(); ((System.ComponentModel.ISupportInitialize)(this.splitContainer2)).BeginInit(); this.splitContainer2.Panel1.SuspendLayout(); this.splitContainer2.Panel2.SuspendLayout(); this.splitContainer2.SuspendLayout(); - ((System.ComponentModel.ISupportInitialize)(this.dragout)).BeginInit(); - ((System.ComponentModel.ISupportInitialize)(this.PB_Legal)).BeginInit(); this.SuspendLayout(); // // menuStrip1 @@ -89,7 +89,8 @@ this.Menu_Options}); this.menuStrip1.Location = new System.Drawing.Point(0, 0); this.menuStrip1.Name = "menuStrip1"; - this.menuStrip1.Size = new System.Drawing.Size(761, 24); + this.menuStrip1.Padding = new System.Windows.Forms.Padding(7, 2, 0, 2); + this.menuStrip1.Size = new System.Drawing.Size(856, 24); this.menuStrip1.TabIndex = 1; this.menuStrip1.Text = "menuStrip1"; // @@ -377,9 +378,10 @@ // L_UpdateAvailable // this.L_UpdateAvailable.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); - this.L_UpdateAvailable.Location = new System.Drawing.Point(454, 8); + this.L_UpdateAvailable.Location = new System.Drawing.Point(564, 0); + this.L_UpdateAvailable.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); this.L_UpdateAvailable.Name = "L_UpdateAvailable"; - this.L_UpdateAvailable.Size = new System.Drawing.Size(300, 13); + this.L_UpdateAvailable.Size = new System.Drawing.Size(288, 24); this.L_UpdateAvailable.TabIndex = 102; this.L_UpdateAvailable.TabStop = true; this.L_UpdateAvailable.Text = "New Update Available!"; @@ -389,22 +391,56 @@ // splitContainer1 // this.splitContainer1.Dock = System.Windows.Forms.DockStyle.Fill; + this.splitContainer1.FixedPanel = System.Windows.Forms.FixedPanel.Panel1; this.splitContainer1.IsSplitterFixed = true; this.splitContainer1.Location = new System.Drawing.Point(0, 0); + this.splitContainer1.Margin = new System.Windows.Forms.Padding(8); this.splitContainer1.Name = "splitContainer1"; // // splitContainer1.Panel1 // + this.splitContainer1.Panel1.Controls.Add(this.dragout); + this.splitContainer1.Panel1.Controls.Add(this.PB_Legal); this.splitContainer1.Panel1.Controls.Add(this.PKME_Tabs); + this.splitContainer1.Panel1MinSize = 400; // // splitContainer1.Panel2 // this.splitContainer1.Panel2.Controls.Add(this.C_SAV); - this.splitContainer1.Size = new System.Drawing.Size(761, 378); - this.splitContainer1.SplitterDistance = 310; - this.splitContainer1.SplitterWidth = 2; + this.splitContainer1.Panel2.Padding = new System.Windows.Forms.Padding(0, 0, 1, 3); + this.splitContainer1.Size = new System.Drawing.Size(856, 359); + this.splitContainer1.SplitterDistance = 400; + this.splitContainer1.SplitterWidth = 1; this.splitContainer1.TabIndex = 105; // + // dragout + // + this.dragout.BackColor = System.Drawing.Color.Transparent; + this.dragout.Location = new System.Drawing.Point(24, 0); + this.dragout.Margin = new System.Windows.Forms.Padding(0); + this.dragout.Name = "dragout"; + this.dragout.Size = new System.Drawing.Size(72, 56); + this.dragout.SizeMode = System.Windows.Forms.PictureBoxSizeMode.CenterImage; + this.dragout.TabIndex = 107; + this.dragout.TabStop = false; + this.dragout.DragDrop += new System.Windows.Forms.DragEventHandler(this.DragoutDrop); + this.dragout.DragOver += new System.Windows.Forms.DragEventHandler(this.Dragout_DragOver); + this.dragout.MouseDown += new System.Windows.Forms.MouseEventHandler(this.Dragout_MouseDown); + this.dragout.MouseEnter += new System.EventHandler(this.DragoutEnter); + this.dragout.MouseLeave += new System.EventHandler(this.DragoutLeave); + // + // PB_Legal + // + this.PB_Legal.Image = global::PKHeX.WinForms.Properties.Resources.valid; + this.PB_Legal.Location = new System.Drawing.Point(0, 0); + this.PB_Legal.Margin = new System.Windows.Forms.Padding(0); + this.PB_Legal.Name = "PB_Legal"; + this.PB_Legal.Size = new System.Drawing.Size(24, 24); + this.PB_Legal.SizeMode = System.Windows.Forms.PictureBoxSizeMode.CenterImage; + this.PB_Legal.TabIndex = 108; + this.PB_Legal.TabStop = false; + this.PB_Legal.Click += new System.EventHandler(this.ClickLegality); + // // PKME_Tabs // this.PKME_Tabs.ChangingFields = false; @@ -412,9 +448,9 @@ this.PKME_Tabs.Dock = System.Windows.Forms.DockStyle.Fill; this.PKME_Tabs.HaX = false; this.PKME_Tabs.Location = new System.Drawing.Point(0, 0); - this.PKME_Tabs.Margin = new System.Windows.Forms.Padding(5); + this.PKME_Tabs.Margin = new System.Windows.Forms.Padding(0); this.PKME_Tabs.Name = "PKME_Tabs"; - this.PKME_Tabs.Size = new System.Drawing.Size(310, 378); + this.PKME_Tabs.Size = new System.Drawing.Size(400, 359); this.PKME_Tabs.TabIndex = 103; this.PKME_Tabs.Unicode = true; this.PKME_Tabs.LegalityChanged += new System.EventHandler(this.PKME_Tabs_LegalityChanged); @@ -428,11 +464,11 @@ this.C_SAV.Dock = System.Windows.Forms.DockStyle.Fill; this.C_SAV.FlagIllegal = false; this.C_SAV.Location = new System.Drawing.Point(0, 0); - this.C_SAV.Margin = new System.Windows.Forms.Padding(5); + this.C_SAV.Margin = new System.Windows.Forms.Padding(0, 0, 1, 3); this.C_SAV.Menu_Redo = null; this.C_SAV.Menu_Undo = null; this.C_SAV.Name = "C_SAV"; - this.C_SAV.Size = new System.Drawing.Size(449, 378); + this.C_SAV.Size = new System.Drawing.Size(454, 356); this.C_SAV.TabIndex = 104; this.C_SAV.ViewIndex = -1; this.C_SAV.RequestCloneData += new System.EventHandler(this.ClickClone); @@ -443,6 +479,7 @@ this.splitContainer2.Dock = System.Windows.Forms.DockStyle.Fill; this.splitContainer2.IsSplitterFixed = true; this.splitContainer2.Location = new System.Drawing.Point(0, 0); + this.splitContainer2.Margin = new System.Windows.Forms.Padding(0); this.splitContainer2.Name = "splitContainer2"; this.splitContainer2.Orientation = System.Windows.Forms.Orientation.Horizontal; // @@ -450,52 +487,27 @@ // this.splitContainer2.Panel1.Controls.Add(this.L_UpdateAvailable); this.splitContainer2.Panel1.Controls.Add(this.menuStrip1); + this.splitContainer2.Panel1MinSize = 24; // // splitContainer2.Panel2 // this.splitContainer2.Panel2.Controls.Add(this.splitContainer1); - this.splitContainer2.Size = new System.Drawing.Size(761, 405); - this.splitContainer2.SplitterDistance = 26; + this.splitContainer2.Size = new System.Drawing.Size(856, 385); + this.splitContainer2.SplitterDistance = 25; this.splitContainer2.SplitterWidth = 1; this.splitContainer2.TabIndex = 106; // - // dragout - // - this.dragout.BackColor = System.Drawing.Color.Transparent; - this.dragout.Location = new System.Drawing.Point(244, 1); - this.dragout.Name = "dragout"; - this.dragout.Size = new System.Drawing.Size(68, 56); - this.dragout.SizeMode = System.Windows.Forms.PictureBoxSizeMode.CenterImage; - this.dragout.TabIndex = 107; - this.dragout.TabStop = false; - this.dragout.DragDrop += new System.Windows.Forms.DragEventHandler(this.DragoutDrop); - this.dragout.DragOver += new System.Windows.Forms.DragEventHandler(this.Dragout_DragOver); - this.dragout.MouseDown += new System.Windows.Forms.MouseEventHandler(this.Dragout_MouseDown); - this.dragout.MouseEnter += new System.EventHandler(this.DragoutEnter); - this.dragout.MouseLeave += new System.EventHandler(this.DragoutLeave); - // - // PB_Legal - // - this.PB_Legal.Image = global::PKHeX.WinForms.Properties.Resources.valid; - this.PB_Legal.Location = new System.Drawing.Point(222, 2); - this.PB_Legal.Name = "PB_Legal"; - this.PB_Legal.Size = new System.Drawing.Size(16, 16); - this.PB_Legal.TabIndex = 108; - this.PB_Legal.TabStop = false; - this.PB_Legal.Click += new System.EventHandler(this.ClickLegality); - // // Main // this.AllowDrop = true; - this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); - this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; - this.ClientSize = new System.Drawing.Size(761, 405); - this.Controls.Add(this.dragout); - this.Controls.Add(this.PB_Legal); + this.AutoScaleDimensions = new System.Drawing.SizeF(96F, 96F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Dpi; + this.ClientSize = new System.Drawing.Size(856, 385); this.Controls.Add(this.splitContainer2); this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle; this.Icon = global::PKHeX.WinForms.Properties.Resources.Icon; this.KeyPreview = true; + this.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3); this.MaximizeBox = false; this.Name = "Main"; this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen; @@ -508,13 +520,13 @@ this.splitContainer1.Panel2.ResumeLayout(false); ((System.ComponentModel.ISupportInitialize)(this.splitContainer1)).EndInit(); this.splitContainer1.ResumeLayout(false); + ((System.ComponentModel.ISupportInitialize)(this.dragout)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.PB_Legal)).EndInit(); this.splitContainer2.Panel1.ResumeLayout(false); this.splitContainer2.Panel1.PerformLayout(); this.splitContainer2.Panel2.ResumeLayout(false); ((System.ComponentModel.ISupportInitialize)(this.splitContainer2)).EndInit(); this.splitContainer2.ResumeLayout(false); - ((System.ComponentModel.ISupportInitialize)(this.dragout)).EndInit(); - ((System.ComponentModel.ISupportInitialize)(this.PB_Legal)).EndInit(); this.ResumeLayout(false); } diff --git a/PKHeX.WinForms/MainWindow/Main.cs b/PKHeX.WinForms/MainWindow/Main.cs index e7010c93a..9f487e657 100644 --- a/PKHeX.WinForms/MainWindow/Main.cs +++ b/PKHeX.WinForms/MainWindow/Main.cs @@ -6,7 +6,6 @@ using System.Globalization; using System.IO; using System.Linq; using System.Media; -using System.Reflection; using System.Threading; using System.Threading.Tasks; using System.Windows.Forms; @@ -22,7 +21,7 @@ namespace PKHeX.WinForms; public partial class Main : Form { - private static readonly Version CurrentProgramVersion = Assembly.GetExecutingAssembly().GetName().Version!; + private static readonly Version CurrentProgramVersion = Version.Parse(Application.ProductVersion); public Main() { @@ -96,7 +95,7 @@ public partial class Main : Form #region Path Variables - public static readonly string WorkingDirectory = Application.StartupPath; + public static readonly string WorkingDirectory = Path.GetDirectoryName(Environment.ProcessPath)!; public static readonly string DatabasePath = Path.Combine(WorkingDirectory, "pkmdb"); public static readonly string MGDatabasePath = Path.Combine(WorkingDirectory, "mgdb"); public static readonly string ConfigPath = Path.Combine(WorkingDirectory, "cfg.json"); @@ -133,11 +132,7 @@ public partial class Main : Form return true; } -#if !NET6_0_OR_GREATER - var path = Process.GetCurrentProcess().MainModule!.FileName!; -#else var path = Environment.ProcessPath!; -#endif return Path.GetFileNameWithoutExtension(path).EndsWith(nameof(HaX)); } @@ -186,7 +181,8 @@ public partial class Main : Form var sav = SaveUtil.GetBlankSAV(ver, tr, lang); if (sav.Version == GameVersion.Invalid) // will fail to load { - ver = (GameVersion)GameInfo.VersionDataSource.Max(z => z.Value); + var max = GameInfo.VersionDataSource.MaxBy(z => z.Value) ?? throw new Exception(); + ver = (GameVersion)max.Value; sav = SaveUtil.GetBlankSAV(ver, tr, lang); } OpenSAV(sav, string.Empty); @@ -807,11 +803,12 @@ public partial class Main : Form private static string GetProgramTitle() { #if DEBUG - var date = File.GetLastWriteTime(Assembly.GetEntryAssembly()!.Location); + // Get the file path that started this exe. + var date = File.GetLastWriteTime(Environment.ProcessPath!); string version = $"d-{date:yyyyMMdd}"; #else - var ver = CurrentProgramVersion; - string version = $"{2000+ver.Major:00}{ver.Minor:00}{ver.Build:00}"; + var ver = CurrentProgramVersion; + string version = $"{2000+ver.Major:00}{ver.Minor:00}{ver.Build:00}"; #endif return $"PKH{(HaX ? "a" : "e")}X ({version})"; } @@ -1090,7 +1087,9 @@ public partial class Main : Form { pk ??= PreparePKM(false); // don't perform control loss click - dragout.ContextMenuStrip.Enabled = pk.Species != 0 || HaX; // Species + var menu = dragout.ContextMenuStrip; + if (menu != null) + menu.Enabled = pk.Species != 0 || HaX; // Species pb.Image = pk.Sprite(C_SAV.SAV, -1, -1, flagIllegal: false); if (pb.BackColor == SlotUtil.BadDataColor) @@ -1160,7 +1159,7 @@ public partial class Main : Form var newfile = FileUtil.GetPKMTempFileName(pk, encrypt); try { - File.WriteAllBytes(newfile, data); + await File.WriteAllBytesAsync(newfile, data).ConfigureAwait(false); var pb = (PictureBox)sender; if (pb.Image is Bitmap img) diff --git a/PKHeX.WinForms/MainWindow/Main.resx b/PKHeX.WinForms/MainWindow/Main.resx index 4054bfa9a..62f8a3187 100644 --- a/PKHeX.WinForms/MainWindow/Main.resx +++ b/PKHeX.WinForms/MainWindow/Main.resx @@ -1,64 +1,4 @@ - - @@ -126,4 +66,4 @@ 56 - \ No newline at end of file + diff --git a/PKHeX.WinForms/PKHeX.WinForms.csproj b/PKHeX.WinForms/PKHeX.WinForms.csproj index 1775518b6..0ad3a7bfa 100644 --- a/PKHeX.WinForms/PKHeX.WinForms.csproj +++ b/PKHeX.WinForms/PKHeX.WinForms.csproj @@ -1,8 +1,9 @@ - + WinExe - net46;net6.0-windows + net7.0-windows + win-x64 true PKHeX Pokémon Save Editor @@ -12,17 +13,15 @@ PKHeX - - - - all - runtime; build; native; contentfiles; analyzers; buildtransitive - - - - - - + + portable + false + false + true + true + true + true + @@ -37,9 +36,6 @@ True Resources.resx - - Form - diff --git a/PKHeX.WinForms/Program.cs b/PKHeX.WinForms/Program.cs index dda9f56a9..513a02ae7 100644 --- a/PKHeX.WinForms/Program.cs +++ b/PKHeX.WinForms/Program.cs @@ -36,7 +36,7 @@ namespace PKHeX.WinForms new Task(() => splash.ShowDialog()).Start(); new Task(() => EncounterEvent.RefreshMGDB(WinForms.Main.MGDatabasePath)).Start(); var main = new Main(); - splash.Invoke(() => splash.ForceClose()); + splash.Invoke(splash.ForceClose); Application.Run(main); } diff --git a/PKHeX.WinForms/Properties/PKHeXSettings.cs b/PKHeX.WinForms/Properties/PKHeXSettings.cs index 95e6a881b..b7138ec91 100644 --- a/PKHeX.WinForms/Properties/PKHeXSettings.cs +++ b/PKHeX.WinForms/Properties/PKHeXSettings.cs @@ -2,14 +2,18 @@ using System; using System.Collections.Generic; using System.ComponentModel; using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; +using System.Drawing; using System.IO; -using Newtonsoft.Json; +using System.Text.Json; +using System.Text.Json.Serialization; using PKHeX.Core; using PKHeX.Drawing.PokeSprite; namespace PKHeX.WinForms; [Serializable] +[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicProperties)] public sealed class PKHeXSettings { public StartupSettings Startup { get; set; } = new(); @@ -36,6 +40,19 @@ public sealed class PKHeXSettings public MysteryGiftDatabaseSettings MysteryDb { get; set; } = new(); public BulkAnalysisSettings Bulk { get; set; } = new(); + private static JsonSerializerOptions GetOptions() => new() + { + WriteIndented = true, + Converters = { new ColorJsonConverter() }, + }; + + public sealed class ColorJsonConverter : JsonConverter + { + public override Color Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) => ColorTranslator.FromHtml(reader.GetString() ?? string.Empty); + + public override void Write(Utf8JsonWriter writer, Color value, JsonSerializerOptions options) => writer.WriteStringValue($"#{value.R:x2}{value.G:x2}{value.B:x2}"); + } + public static PKHeXSettings GetSettings(string configPath) { if (!File.Exists(configPath)) @@ -44,7 +61,7 @@ public sealed class PKHeXSettings try { var lines = File.ReadAllText(configPath); - return JsonConvert.DeserializeObject(lines) ?? new PKHeXSettings(); + return JsonSerializer.Deserialize(lines, GetOptions()) ?? new PKHeXSettings(); } catch (Exception x) { @@ -57,13 +74,7 @@ public sealed class PKHeXSettings { try { - var settings = new JsonSerializerSettings - { - Formatting = Formatting.Indented, - DefaultValueHandling = DefaultValueHandling.Populate, - NullValueHandling = NullValueHandling.Ignore, - }; - var text = JsonConvert.SerializeObject(cfg, settings); + var text = JsonSerializer.Serialize(cfg, GetOptions()); File.WriteAllText(configPath, text); } catch (Exception x) @@ -76,7 +87,7 @@ public sealed class PKHeXSettings { try { - File.WriteAllLines("config error.txt", new[] { x.ToString() }); + File.WriteAllText("config error.txt", x.ToString()); } catch (Exception) { @@ -95,10 +106,10 @@ public sealed class BackupSettings public bool BAKPrompt { get; set; } [LocalizedDescription("List of extra locations to look for Save Files.")] - public string[] OtherBackupPaths { get; set; } = Array.Empty(); + public List OtherBackupPaths { get; set; } = new(); [LocalizedDescription("Save File file-extensions (no period) that the program should also recognize.")] - public string[] OtherSaveFileExtensions { get; set; } = Array.Empty(); + public List OtherSaveFileExtensions { get; set; } = new(); } [Serializable] @@ -240,7 +251,7 @@ public sealed class AdvancedSettings } [Serializable] -public class EntityDatabaseSettings +public sealed class EntityDatabaseSettings { [LocalizedDescription("When loading content for the PKM Database, search within backup save files.")] public bool SearchBackups { get; set; } = true; diff --git a/PKHeX.WinForms/Subforms/KChart.Designer.cs b/PKHeX.WinForms/Subforms/KChart.Designer.cs index 82084ecda..215b92238 100644 --- a/PKHeX.WinForms/Subforms/KChart.Designer.cs +++ b/PKHeX.WinForms/Subforms/KChart.Designer.cs @@ -1,4 +1,4 @@ -namespace PKHeX.WinForms +namespace PKHeX.WinForms { partial class KChart { @@ -28,7 +28,7 @@ ///
private void InitializeComponent() { - this.DGV = new System.Windows.Forms.DataGridView(); + this.DGV = new PKHeX.WinForms.Controls.DoubleBufferedDataGridView(); this.d_Index = new System.Windows.Forms.DataGridViewTextBoxColumn(); this.Sprite = new System.Windows.Forms.DataGridViewImageColumn(); this.SpecName = new System.Windows.Forms.DataGridViewTextBoxColumn(); @@ -231,7 +231,7 @@ } #endregion - private System.Windows.Forms.DataGridView DGV; + private PKHeX.WinForms.Controls.DoubleBufferedDataGridView DGV; private System.Windows.Forms.DataGridViewTextBoxColumn d_Index; private System.Windows.Forms.DataGridViewImageColumn Sprite; private System.Windows.Forms.DataGridViewTextBoxColumn SpecName; diff --git a/PKHeX.WinForms/Subforms/KChart.cs b/PKHeX.WinForms/Subforms/KChart.cs index 6d3b1db45..352205518 100644 --- a/PKHeX.WinForms/Subforms/KChart.cs +++ b/PKHeX.WinForms/Subforms/KChart.cs @@ -40,8 +40,6 @@ public partial class KChart : Form } } - DGV.DoubleBuffered(true); - DGV.Sort(DGV.Columns[0], ListSortDirection.Ascending); } diff --git a/PKHeX.WinForms/Subforms/Misc/PropertyComparer.cs b/PKHeX.WinForms/Subforms/Misc/PropertyComparer.cs index 1abcf7108..ab5a156df 100644 --- a/PKHeX.WinForms/Subforms/Misc/PropertyComparer.cs +++ b/PKHeX.WinForms/Subforms/Misc/PropertyComparer.cs @@ -26,8 +26,6 @@ public sealed class PropertyComparer : IComparer where T : class public int Compare(T? x, T? y) { - if (x == null) throw new ArgumentNullException(nameof(x)); - if (y == null) throw new ArgumentNullException(nameof(y)); return reverse * comparer.Compare(propertyDescriptor.GetValue(x), propertyDescriptor.GetValue(y)); } diff --git a/PKHeX.WinForms/Subforms/PKM Editors/BatchEditor.cs b/PKHeX.WinForms/Subforms/PKM Editors/BatchEditor.cs index d98fbb1e0..0db4d75ab 100644 --- a/PKHeX.WinForms/Subforms/PKM Editors/BatchEditor.cs +++ b/PKHeX.WinForms/Subforms/PKM Editors/BatchEditor.cs @@ -64,9 +64,10 @@ public partial class BatchEditor : Form { WinFormsUtil.Alert(MsgBEPropertyInvalid); return; } // If we already have text, add a new line (except if the last line is blank). - if (RTB_Instructions.Lines.Length != 0 && RTB_Instructions.Lines[^1].Length > 0) - s = Environment.NewLine + s; - + var tb = RTB_Instructions; + var batchText = tb.Text; + if (batchText.Length > 0 && !batchText.EndsWith('\n')) + tb.AppendText(Environment.NewLine); RTB_Instructions.AppendText(s); } @@ -93,11 +94,11 @@ public partial class BatchEditor : Form private void RunBackgroundWorker() { - var lines = RTB_Instructions.Lines; - if (Array.Exists(lines, line => line.Length == 0)) + ReadOnlySpan text = RTB_Instructions.Text; + if (StringInstructionSet.HasEmptyLine(text)) { WinFormsUtil.Error(MsgBEInstructionInvalid); return; } - var sets = StringInstructionSet.GetBatchSets(lines).ToArray(); + var sets = StringInstructionSet.GetBatchSets(text); if (Array.Exists(sets, s => s.Filters.Any(z => string.IsNullOrWhiteSpace(z.PropertyValue)))) { WinFormsUtil.Error(MsgBEFilterEmpty); return; } diff --git a/PKHeX.WinForms/Subforms/PKM Editors/MemoryAmie.cs b/PKHeX.WinForms/Subforms/PKM Editors/MemoryAmie.cs index addbd79ef..92d24659e 100644 --- a/PKHeX.WinForms/Subforms/PKM Editors/MemoryAmie.cs +++ b/PKHeX.WinForms/Subforms/PKM Editors/MemoryAmie.cs @@ -101,7 +101,7 @@ public partial class MemoryAmie : Form GB_M_OT.Enabled = GB_M_CT.Enabled = GB_Residence.Enabled = BTN_Save.Enabled = M_Fullness.Enabled = M_Enjoyment.Enabled = L_Sociability.Enabled = MT_Sociability.Enabled = - L_Fullness.Enabled = L_Enjoyment.Enabled = !(Entity.IsEgg && Entity.IsUntraded && Entity.HT_Friendship == 0); + L_Fullness.Enabled = L_Enjoyment.Enabled = Entity is not { IsEgg: true, IsUntraded: true, HT_Friendship: 0 }; if (!Entity.IsEgg) { diff --git a/PKHeX.WinForms/Subforms/PKM Editors/MoveShopEditor.cs b/PKHeX.WinForms/Subforms/PKM Editors/MoveShopEditor.cs index 70c653f85..0ac34207a 100644 --- a/PKHeX.WinForms/Subforms/PKM Editors/MoveShopEditor.cs +++ b/PKHeX.WinForms/Subforms/PKM Editors/MoveShopEditor.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.ComponentModel; using System.Windows.Forms; using PKHeX.Core; @@ -102,7 +102,7 @@ public partial class MoveShopEditor : Form private void PopulateRecords() { var names = GameInfo.Strings.Move; - var indexes = Shop.MoveShopPermitIndexes; + var indexes = Shop.Permit.RecordPermitIndexes; dgv.Rows.Add(indexes.Length); for (int i = 0; i < indexes.Length; i++) { diff --git a/PKHeX.WinForms/Subforms/PKM Editors/RibbonEditor.cs b/PKHeX.WinForms/Subforms/PKM Editors/RibbonEditor.cs index f0380ca9d..87bf08c26 100644 --- a/PKHeX.WinForms/Subforms/PKM Editors/RibbonEditor.cs +++ b/PKHeX.WinForms/Subforms/PKM Editors/RibbonEditor.cs @@ -186,7 +186,10 @@ public partial class RibbonEditor : Form nud.ValueChanged += (sender, e) => { - var pb = FLP_Ribbons.Controls[PrefixPB + rib.Name]; + var controlName = PrefixPB + rib.Name; + var pb = FLP_Ribbons.Controls[controlName]; + if (pb is null) + throw new ArgumentException($"{controlName} not found in {FLP_Ribbons.Name}."); pb.Visible = (rib.RibbonCount = (byte)nud.Value) != 0; pb.BackgroundImage = RibbonSpriteUtil.GetRibbonSprite(rib.Name, (int)nud.Maximum, (int)nud.Value); }; @@ -211,7 +214,11 @@ public partial class RibbonEditor : Form chk.CheckedChanged += (sender, e) => { rib.HasRibbon = chk.Checked; - FLP_Ribbons.Controls[PrefixPB + rib.Name].Visible = rib.HasRibbon; + var controlName = PrefixPB + rib.Name; + var control = FLP_Ribbons.Controls[controlName]; + if (control is null) + throw new ArgumentException($"{controlName} not found in {FLP_Ribbons.Name}."); + control.Visible = rib.HasRibbon; }; // Setting value will trigger above event diff --git a/PKHeX.WinForms/Subforms/PKM Editors/TechRecordEditor.cs b/PKHeX.WinForms/Subforms/PKM Editors/TechRecordEditor.cs index b263e7287..e74fd6068 100644 --- a/PKHeX.WinForms/Subforms/PKM Editors/TechRecordEditor.cs +++ b/PKHeX.WinForms/Subforms/PKM Editors/TechRecordEditor.cs @@ -23,7 +23,7 @@ public partial class TechRecordEditor : Form private void PopulateRecords() { var names = GameInfo.Strings.Move; - var indexes = Record.TechRecordPermitIndexes; + var indexes = Record.Permit.RecordPermitIndexes; var lines = new string[indexes.Length]; for (int i = 0; i < lines.Length; i++) lines[i] = $"{i:00} - {names[indexes[i]]}"; @@ -40,14 +40,14 @@ public partial class TechRecordEditor : Form private void LoadRecords() { - var range = Record.TechRecordPermitIndexes; + var range = Record.Permit.RecordPermitIndexes; for (int i = 0; i < range.Length; i++) CLB_Flags.SetItemChecked(i, Record.GetMoveRecordFlag(i)); } private void Save() { - var range = Record.TechRecordPermitIndexes; + var range = Record.Permit.RecordPermitIndexes; for (int i = 0; i < range.Length; i++) Record.SetMoveRecordFlag(i, CLB_Flags.GetItemChecked(i)); } @@ -57,7 +57,7 @@ public partial class TechRecordEditor : Form Save(); if (ModifierKeys == Keys.Shift) { - Record.SetRecordFlags(true, Record.RecordCountUsed); + Record.SetRecordFlags(true, Record.Permit.RecordCountUsed); } else if (ModifierKeys == Keys.Control) { diff --git a/PKHeX.WinForms/Subforms/PKM Editors/Text.cs b/PKHeX.WinForms/Subforms/PKM Editors/Text.cs index b558309c5..a66b805fd 100644 --- a/PKHeX.WinForms/Subforms/PKM Editors/Text.cs +++ b/PKHeX.WinForms/Subforms/PKM Editors/Text.cs @@ -19,11 +19,17 @@ public partial class TrashEditor : Form SAV = sav; FinalString = TB_NN.Text; - Raw = FinalBytes = raw.ToArray(); editing = true; if (raw.Length != 0) + { + Raw = FinalBytes = raw.ToArray(); AddTrashEditing(raw.Length); + } + else + { + Raw = FinalBytes = Array.Empty(); + } var f = FontUtil.GetPKXFont(); AddCharEditing(f); @@ -175,24 +181,24 @@ public partial class TrashEditor : Form Bytes[i].Value = 0; } - private byte[] SetString(string text) + private byte[] SetString(ReadOnlySpan text) { Span temp = stackalloc byte[Raw.Length]; - var written = SAV.SetString(temp, text.AsSpan(), text.Length, StringConverterOption.None); + var written = SAV.SetString(temp, text, text.Length, StringConverterOption.None); return temp[..written].ToArray(); } - private string GetString() => SAV.GetString(Raw.AsSpan()); + private string GetString() => SAV.GetString(Raw); // Helpers - private static Label GetLabel(string str) => new() {Text = str, AutoSize = true}; + private static Label GetLabel(string str) => new() { Text = str, AutoSize = false, Size = new Size(40, 24), TextAlign = ContentAlignment.MiddleRight }; - private static NumericUpDown GetNUD(int min, int max, bool hex) => new() + private static NumericUpDown GetNUD(byte min, byte max, bool hex) => new() { Maximum = max, Minimum = min, Hexadecimal = hex, - Width = 36, + Width = 40, Padding = new Padding(0), Margin = new Padding(0), }; diff --git a/PKHeX.WinForms/Subforms/ReportGrid.Designer.cs b/PKHeX.WinForms/Subforms/ReportGrid.Designer.cs index 6c0678a86..e7e57ac64 100644 --- a/PKHeX.WinForms/Subforms/ReportGrid.Designer.cs +++ b/PKHeX.WinForms/Subforms/ReportGrid.Designer.cs @@ -1,4 +1,4 @@ -namespace PKHeX.WinForms +namespace PKHeX.WinForms { partial class ReportGrid { @@ -29,7 +29,7 @@ private void InitializeComponent() { System.Windows.Forms.DataGridViewCellStyle dataGridViewCellStyle1 = new System.Windows.Forms.DataGridViewCellStyle(); - this.dgData = new System.Windows.Forms.DataGridView(); + this.dgData = new PKHeX.WinForms.Controls.DoubleBufferedDataGridView(); ((System.ComponentModel.ISupportInitialize)(this.dgData)).BeginInit(); this.SuspendLayout(); // @@ -66,6 +66,6 @@ #endregion - private System.Windows.Forms.DataGridView dgData; + private PKHeX.WinForms.Controls.DoubleBufferedDataGridView dgData; } } diff --git a/PKHeX.WinForms/Subforms/ReportGrid.cs b/PKHeX.WinForms/Subforms/ReportGrid.cs index 0c07871dc..d0ac41710 100644 --- a/PKHeX.WinForms/Subforms/ReportGrid.cs +++ b/PKHeX.WinForms/Subforms/ReportGrid.cs @@ -15,7 +15,6 @@ public partial class ReportGrid : Form public ReportGrid() { InitializeComponent(); - dgData.DoubleBuffered(true); CenterToParent(); GetContextMenu(); } @@ -118,8 +117,8 @@ public partial class ReportGrid : Form private async Task Export_CSV(string path) { - using var fs = new FileStream(path, FileMode.Create); - using var s = new StreamWriter(fs, System.Text.Encoding.Unicode); + await using var fs = new FileStream(path, FileMode.Create); + await using var s = new StreamWriter(fs, System.Text.Encoding.Unicode); var headers = dgData.Columns.Cast(); await s.WriteLineAsync(string.Join(",", headers.Skip(1).Select(column => $"\"{column.HeaderText}\""))).ConfigureAwait(false); diff --git a/PKHeX.WinForms/Subforms/SAV_Database.cs b/PKHeX.WinForms/Subforms/SAV_Database.cs index d7500a08d..e1bf3d5e7 100644 --- a/PKHeX.WinForms/Subforms/SAV_Database.cs +++ b/PKHeX.WinForms/Subforms/SAV_Database.cs @@ -502,7 +502,7 @@ public partial class SAV_Database : Form Nature = WinFormsUtil.GetIndex(CB_Nature), Item = WinFormsUtil.GetIndex(CB_HeldItem), - BatchInstructions = RTB_Instructions.Lines, + BatchInstructions = RTB_Instructions.Text, Level = int.TryParse(TB_Level.Text, out var lvl) ? lvl : null, SearchLevel = (SearchComparison)CB_Level.SelectedIndex, @@ -736,9 +736,11 @@ public partial class SAV_Database : Form if (s.Length == 0) { WinFormsUtil.Alert(MsgBEPropertyInvalid); return; } - if (RTB_Instructions.Lines.Length != 0 && RTB_Instructions.Lines[^1].Length > 0) - s = Environment.NewLine + s; - - RTB_Instructions.AppendText(s); + // If we already have text, add a new line (except if the last line is blank). + var tb = RTB_Instructions; + var batchText = tb.Text; + if (batchText.Length > 0 && !batchText.EndsWith('\n')) + tb.AppendText(Environment.NewLine); + tb.AppendText(s); } } diff --git a/PKHeX.WinForms/Subforms/SAV_Encounters.cs b/PKHeX.WinForms/Subforms/SAV_Encounters.cs index 85fe04598..3bba385bc 100644 --- a/PKHeX.WinForms/Subforms/SAV_Encounters.cs +++ b/PKHeX.WinForms/Subforms/SAV_Encounters.cs @@ -89,7 +89,7 @@ public partial class SAV_Encounters : Form private void GetTypeFilters() { - var types = (EncounterOrder[])Enum.GetValues(typeof(EncounterOrder)); + var types = (EncounterTypeGroup[])Enum.GetValues(typeof(EncounterTypeGroup)); var checks = types.Select(z => new CheckBox { Name = z.ToString(), @@ -106,10 +106,10 @@ public partial class SAV_Encounters : Form } } - private EncounterOrder[] GetTypes() + private EncounterTypeGroup[] GetTypes() { return TypeFilters.Controls.OfType().Where(z => z.Checked).Select(z => z.Name) - .Select(z => (EncounterOrder)Enum.Parse(typeof(EncounterOrder), z)).ToArray(); + .Select(z => (EncounterTypeGroup)Enum.Parse(typeof(EncounterTypeGroup), z)).ToArray(); } private readonly PictureBox[] PKXBOXES; @@ -230,7 +230,7 @@ public partial class SAV_Encounters : Form var settings = GetSearchSettings(); // If nothing is specified, instead of just returning all possible encounters, just return nothing. - if (settings.Species == 0 && settings.Moves.Count == 0 && Main.Settings.EncounterDb.ReturnNoneIfEmptySearch) + if (settings is { Species: 0, Moves.Count: 0 } && Main.Settings.EncounterDb.ReturnNoneIfEmptySearch) return Array.Empty(); var pk = SAV.BlankPKM; @@ -266,9 +266,10 @@ public partial class SAV_Encounters : Form if (token.IsCancellationRequested) return results; - if (RTB_Instructions.Lines.Any(line => line.Length > 0)) + ReadOnlySpan batchText = RTB_Instructions.Text; + if (batchText.Length > 0 && !StringInstructionSet.HasEmptyLine(batchText)) { - var filters = StringInstruction.GetFilters(RTB_Instructions.Lines).ToArray(); + var filters = StringInstruction.GetFilters(batchText); BatchEditing.ScreenStrings(filters); results = results.Where(enc => BatchEditing.IsFilterMatch(filters, enc)); // Compare across all filters } @@ -343,7 +344,7 @@ public partial class SAV_Encounters : Form Species = GetU16(CB_Species), - BatchInstructions = RTB_Instructions.Lines, + BatchInstructions = RTB_Instructions.Text, Version = WinFormsUtil.GetIndex(CB_GameOrigin), }; @@ -479,9 +480,11 @@ public partial class SAV_Encounters : Form if (s.Length == 0) { WinFormsUtil.Alert(MsgBEPropertyInvalid); return; } - if (RTB_Instructions.Lines.Length != 0 && RTB_Instructions.Lines[^1].Length > 0) - s = Environment.NewLine + s; - + // If we already have text, add a new line (except if the last line is blank). + var tb = RTB_Instructions; + var batchText = tb.Text; + if (batchText.Length > 0 && !batchText.EndsWith('\n')) + tb.AppendText(Environment.NewLine); RTB_Instructions.AppendText(s); } } diff --git a/PKHeX.WinForms/Subforms/SAV_FolderList.Designer.cs b/PKHeX.WinForms/Subforms/SAV_FolderList.Designer.cs index 872fb7b2a..3269fac12 100644 --- a/PKHeX.WinForms/Subforms/SAV_FolderList.Designer.cs +++ b/PKHeX.WinForms/Subforms/SAV_FolderList.Designer.cs @@ -1,4 +1,4 @@ -namespace PKHeX.WinForms +namespace PKHeX.WinForms { partial class SAV_FolderList { @@ -33,9 +33,9 @@ this.FLP_Buttons = new System.Windows.Forms.FlowLayoutPanel(); this.TC_Tabs = new System.Windows.Forms.TabControl(); this.Tab_Recent = new System.Windows.Forms.TabPage(); - this.dgDataRecent = new System.Windows.Forms.DataGridView(); + this.dgDataRecent = new PKHeX.WinForms.Controls.DoubleBufferedDataGridView(); this.Tab_Backup = new System.Windows.Forms.TabPage(); - this.dgDataBackup = new System.Windows.Forms.DataGridView(); + this.dgDataBackup = new PKHeX.WinForms.Controls.DoubleBufferedDataGridView(); this.Tab_Folders = new System.Windows.Forms.TabPage(); this.CB_FilterColumn = new System.Windows.Forms.ComboBox(); this.TB_FilterTextContains = new System.Windows.Forms.TextBox(); @@ -187,8 +187,8 @@ private System.Windows.Forms.TabPage Tab_Folders; private System.Windows.Forms.TabPage Tab_Recent; private System.Windows.Forms.TabPage Tab_Backup; - private System.Windows.Forms.DataGridView dgDataBackup; - private System.Windows.Forms.DataGridView dgDataRecent; + private PKHeX.WinForms.Controls.DoubleBufferedDataGridView dgDataBackup; + private PKHeX.WinForms.Controls.DoubleBufferedDataGridView dgDataRecent; private System.Windows.Forms.ComboBox CB_FilterColumn; private System.Windows.Forms.TextBox TB_FilterTextContains; } diff --git a/PKHeX.WinForms/Subforms/SAV_FolderList.cs b/PKHeX.WinForms/Subforms/SAV_FolderList.cs index 008e95598..1b54b2bfc 100644 --- a/PKHeX.WinForms/Subforms/SAV_FolderList.cs +++ b/PKHeX.WinForms/Subforms/SAV_FolderList.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using System.Diagnostics; using System.Drawing; @@ -71,9 +71,6 @@ public partial class SAV_FolderList : Form foreach (var loc in Paths) AddButton(loc.DisplayText, loc.Path); - dgDataRecent.DoubleBuffered(true); - dgDataBackup.DoubleBuffered(true); - CenterToParent(); } @@ -86,7 +83,7 @@ public partial class SAV_FolderList : Form locs.AddRange(GetUserPaths()); locs.AddRange(GetConsolePaths(drives)); locs.AddRange(GetSwitchPaths(drives)); - return locs.GroupBy(z => z.Path).Select(z => z.First()) + return locs.DistinctBy(z => z.Path) .OrderByDescending(z => Directory.Exists(z.Path)).ToList(); } @@ -288,12 +285,12 @@ public partial class SAV_FolderList : Form var sav = new SavePreview(next, Paths); void Load() => LoadEntry(dgData, list, sav); - dgData.Invoke((Action)Load); + dgData.Invoke(Load); ctr++; if (ctr < 15 && ctr % 7 == 0) - dgData.Invoke((Action)RefreshResize); + dgData.Invoke(RefreshResize); } - dgData.Invoke((Action)RefreshResize); + dgData.Invoke(RefreshResize); enumerator.Dispose(); }); @@ -347,14 +344,14 @@ public partial class SAV_FolderList : Form { if (dg.RowCount == 0) return; - var cm = (CurrencyManager)BindingContext[dg.DataSource]; - cm.SuspendBinding(); + var cm = (CurrencyManager?)BindingContext?[dg.DataSource]; + cm?.SuspendBinding(); int column = CB_FilterColumn.SelectedIndex - 1; var text = TB_FilterTextContains.Text; for (int i = 0; i < dg.RowCount; i++) ToggleRowVisibility(dg, column, text, i); - cm.ResumeBinding(); + cm?.ResumeBinding(); } private static void ToggleRowVisibility(DataGridView dg, int column, string text, int rowIndex) diff --git a/PKHeX.WinForms/Subforms/SAV_MysteryGiftDB.cs b/PKHeX.WinForms/Subforms/SAV_MysteryGiftDB.cs index 78c8ca45d..d90b0cb23 100644 --- a/PKHeX.WinForms/Subforms/SAV_MysteryGiftDB.cs +++ b/PKHeX.WinForms/Subforms/SAV_MysteryGiftDB.cs @@ -329,9 +329,10 @@ public partial class SAV_MysteryGiftDB : Form slotSelected = -1; // reset the slot last viewed - if (RTB_Instructions.Lines.Any(line => line.Length > 0)) + ReadOnlySpan batchText = RTB_Instructions.Text; + if (batchText.Length > 0 && !StringInstructionSet.HasEmptyLine(batchText)) { - var filters = StringInstruction.GetFilters(RTB_Instructions.Lines).ToArray(); + var filters = StringInstruction.GetFilters(batchText); BatchEditing.ScreenStrings(filters); res = res.Where(pk => BatchEditing.IsFilterMatch(filters, pk)); // Compare across all filters } @@ -450,9 +451,11 @@ public partial class SAV_MysteryGiftDB : Form if (s.Length == 0) { WinFormsUtil.Alert(MsgBEPropertyInvalid); return; } - if (RTB_Instructions.Lines.Length != 0 && RTB_Instructions.Lines[^1].Length > 0) - s = Environment.NewLine + s; - + // If we already have text, add a new line (except if the last line is blank). + var tb = RTB_Instructions; + var batchText = tb.Text; + if (batchText.Length > 0 && !batchText.EndsWith('\n')) + tb.AppendText(Environment.NewLine); RTB_Instructions.AppendText(s); } } diff --git a/PKHeX.WinForms/Subforms/Save Editors/Gen3/SAV_Misc3.cs b/PKHeX.WinForms/Subforms/Save Editors/Gen3/SAV_Misc3.cs index 8c73e8b0a..1e2beb7b1 100644 --- a/PKHeX.WinForms/Subforms/Save Editors/Gen3/SAV_Misc3.cs +++ b/PKHeX.WinForms/Subforms/Save Editors/Gen3/SAV_Misc3.cs @@ -1,6 +1,7 @@ using System; using System.Drawing; using System.Linq; +using System.Text; using System.Windows.Forms; using PKHeX.Core; using static System.Buffers.Binary.BinaryPrimitives; @@ -49,7 +50,7 @@ public partial class SAV_Misc3 : Form cba[i].InitializeBinding(); cba[i].DataSource = new BindingSource(legal, null); var g3Species = SAV.GetWork(0x43 + i); - var species = SpeciesConverter.GetG4Species(g3Species); + var species = SpeciesConverter.GetNational3(g3Species); cba[i].SelectedValue = (int)species; } } @@ -74,7 +75,7 @@ public partial class SAV_Misc3 : Form for (int i = 0; i < cba.Length; i++) { var species = (ushort) WinFormsUtil.GetIndex(cba[i]); - var g3Species = SpeciesConverter.GetG3Species(species); + var g3Species = SpeciesConverter.GetInternal3(species); SAV.SetWork(0x43 + i, g3Species); } } @@ -122,19 +123,30 @@ public partial class SAV_Misc3 : Form itemlist[i] = $"(Item #{i:000})"; } - const int oldsea = 0x178; - int[] tickets = {0x109, 0x113, 0x172, 0x173, oldsea }; // item IDs + const ushort oldsea = 0x178; + Span tickets = stackalloc ushort[] {0x109, 0x113, 0x172, 0x173, oldsea }; // item IDs if (!SAV.Japanese && DialogResult.Yes != WinFormsUtil.Prompt(MessageBoxButtons.YesNo, $"Non Japanese save file. Add {itemlist[oldsea]} (unreleased)?")) - tickets = tickets.Take(tickets.Length - 1).ToArray(); // remove old sea map + tickets = tickets[..^1]; // remove old sea map var p = Pouches.FirstOrDefault(z => z.Type == InventoryType.KeyItems); if (p == null) throw new ArgumentException(nameof(InventoryType)); // check for missing tickets - var missing = tickets.Where(z => !p.Items.Any(item => item.Index == z && item.Count == 1)).ToList(); - var have = tickets.Except(missing).ToList(); - if (missing.Count == 0) + Span have = stackalloc ushort[tickets.Length]; int h = 0; + Span missing = stackalloc ushort[tickets.Length]; int m = 0; + foreach (var item in tickets) + { + bool has = Array.Exists(p.Items, z => z.Index == item); + if (has) + have[h++] = item; + else + missing[m++] = item; + } + have = have[..h]; + missing = missing[..m]; + + if (missing.Length == 0) { WinFormsUtil.Alert("Already have all tickets."); B_GetTickets.Enabled = false; @@ -143,18 +155,29 @@ public partial class SAV_Misc3 : Form // check for space int end = Array.FindIndex(p.Items, static z => z.Index == 0); - if (end + missing.Count >= p.Items.Length) + if (end + missing.Length >= p.Items.Length) { WinFormsUtil.Alert("Not enough space in pouch.", "Please use the InventoryEditor."); B_GetTickets.Enabled = false; return; } - var added = string.Join(", ", missing.Select(u => itemlist[u])); - var addmsg = $"Add the following items?{Environment.NewLine}{added}"; - if (have.Count > 0) + static string Format(ReadOnlySpan items, ReadOnlySpan names) { - string had = string.Join(", ", have.Select(u => itemlist[u])); + var sbAdd = new StringBuilder(); + foreach (var item in items) + { + if (sbAdd.Length > 0) + sbAdd.Append(", "); + sbAdd.Append(names[item]); + } + return sbAdd.ToString(); + } + var added = Format(missing, itemlist); + var addmsg = $"Add the following items?{Environment.NewLine}{added}"; + if (have.Length > 0) + { + string had = Format(have, itemlist); var havemsg = $"Already have:{Environment.NewLine}{had}"; addmsg += Environment.NewLine + Environment.NewLine + havemsg; } @@ -162,7 +185,7 @@ public partial class SAV_Misc3 : Form return; // insert items at the end - for (int i = 0; i < missing.Count; i++) + for (int i = 0; i < missing.Length; i++) { var item = p.Items[end + i]; item.Index = missing[i]; @@ -300,7 +323,7 @@ public partial class SAV_Misc3 : Form int p = BFF[Facility][2 + BFV[BFF[Facility][0]].Length + BattleType] + RBi; const int offset = 0xCDC; var current = ReadUInt32LittleEndian(SAV.Small.AsSpan(offset)); - var update = (current & (uint)~(1 << p)) | (uint)((CHK_Continue.Checked ? 1 : 0) << p); + var update = (current & ~(1u << p)) | (CHK_Continue.Checked ? 1u : 0) << p; WriteUInt32LittleEndian(SAV.Small.AsSpan(offset), update); return; } diff --git a/PKHeX.WinForms/Subforms/Save Editors/Gen4/SAV_HoneyTree.cs b/PKHeX.WinForms/Subforms/Save Editors/Gen4/SAV_HoneyTree.cs index 2b1ac0080..a6f18387b 100644 --- a/PKHeX.WinForms/Subforms/Save Editors/Gen4/SAV_HoneyTree.cs +++ b/PKHeX.WinForms/Subforms/Save Editors/Gen4/SAV_HoneyTree.cs @@ -54,7 +54,7 @@ public partial class SAV_HoneyTree : Form return; if (species == (int)Species.Munchlax && !MunchlaxTrees.Contains(CB_TreeList.SelectedIndex)) - WinFormsUtil.Alert("Catching Munchlax in this tree will make it illegal for this savegame's TID/SID combination."); + WinFormsUtil.Alert("Catching Munchlax in this tree will make it illegal for this savegame's TID16/SID16 combination."); } private static string GetLabelText(ushort species) diff --git a/PKHeX.WinForms/Subforms/Save Editors/Gen4/SAV_Misc4.cs b/PKHeX.WinForms/Subforms/Save Editors/Gen4/SAV_Misc4.cs index dc00a6407..8a910f2f8 100644 --- a/PKHeX.WinForms/Subforms/Save Editors/Gen4/SAV_Misc4.cs +++ b/PKHeX.WinForms/Subforms/Save Editors/Gen4/SAV_Misc4.cs @@ -148,8 +148,8 @@ public partial class SAV_Misc4 : Form if (ofsUGFlagCount > 0) { - uint fc = ReadUInt32LittleEndian(SAV.General.AsSpan(ofsUGFlagCount)) & 0xFFFFF; - NUD_UGFlags.Value = fc > 999999 ? 999999 : fc; + uint flagCount = ReadUInt32LittleEndian(SAV.General.AsSpan(ofsUGFlagCount)) & 0xFFFFF; + NUD_UGFlags.Value = Math.Clamp(flagCount, 0, 999_999); } if (ofsMap > 0) { @@ -170,9 +170,9 @@ public partial class SAV_Misc4 : Form if (FlyDestC[i] < 32) { if (CLB_FlyDest.GetItemChecked(i)) - valFly |= (uint) 1 << FlyDestC[i]; + valFly |= 1u << FlyDestC[i]; else - valFly &= ~((uint) 1 << FlyDestC[i]); + valFly &= ~(1u << FlyDestC[i]); } else { @@ -210,7 +210,7 @@ public partial class SAV_Misc4 : Form #region Poketch private byte[] DotArtistByte = null!; - private byte[] ColorTable = null!; + private static ReadOnlySpan ColorTable => new byte[] { 248, 168, 88, 8 }; private void ReadPoketch(SAV4Sinnoh s) { @@ -227,7 +227,6 @@ public partial class SAV_Misc4 : Form } DotArtistByte = s.GetPoketchDotArtistData(); - ColorTable = new byte[] { 248, 168, 88, 8 }; SetPictureBoxFromFlags(DotArtistByte); string tip = "Guide about D&D ImageFile Format"; tip += Environment.NewLine + " width = 24px"; @@ -256,7 +255,7 @@ public partial class SAV_Misc4 : Form PB_DotArtist.Image = GetDotArt(inp); } - private Bitmap GetDotArt(ReadOnlySpan inp) + private static Bitmap GetDotArt(ReadOnlySpan inp) { byte[] dupbyte = new byte[23040]; for (int iy = 0; iy < 20; iy++) @@ -386,16 +385,8 @@ public partial class SAV_Misc4 : Form private void SetFlagsFromClickPoint(int inpX, int inpY) { - static int Clamp(int value, int min, int max) - { - if (value < min) - return min; - if (value > max) - return max; - return value; - } - inpX = Clamp(inpX, 0, 95); - inpY = Clamp(inpY, 0, 79); + inpX = Math.Clamp(inpX, 0, 95); + inpY = Math.Clamp(inpY, 0, 79); int i = (inpX >> 2) + (24 * (inpY >> 2)); byte[] ndab = new byte[120]; DotArtistByte.CopyTo(ndab, 0); diff --git a/PKHeX.WinForms/Subforms/Save Editors/Gen4/SAV_Pokedex4.cs b/PKHeX.WinForms/Subforms/Save Editors/Gen4/SAV_Pokedex4.cs index cb1b6c5d3..19d7bbfd9 100644 --- a/PKHeX.WinForms/Subforms/Save Editors/Gen4/SAV_Pokedex4.cs +++ b/PKHeX.WinForms/Subforms/Save Editors/Gen4/SAV_Pokedex4.cs @@ -287,6 +287,8 @@ public partial class SAV_Pokedex4 : Form } var item = lb.SelectedItem; + if (item is null) + throw new NullReferenceException(); lb.Items.RemoveAt(lb.SelectedIndex); var dest = lb == LB_Gender ? LB_NGender : LB_Gender; dest.Items.Add(item); @@ -317,6 +319,8 @@ public partial class SAV_Pokedex4 : Form return; var item = lb.SelectedItem; + if (item is null) + throw new NullReferenceException(); lb.Items.Remove(item); lb.Items.Insert(newIndex, item); lb.SelectedIndex = newIndex; @@ -334,6 +338,8 @@ public partial class SAV_Pokedex4 : Form } var item = lb.SelectedItem; + if (item is null) + throw new NullReferenceException(); lb.Items.RemoveAt(lb.SelectedIndex); var dest = lb == LB_Form ? LB_NForm : LB_Form; dest.Items.Add(item); @@ -364,6 +370,8 @@ public partial class SAV_Pokedex4 : Form return; var item = lb.SelectedItem; + if (item is null) + throw new NullReferenceException(); lb.Items.Remove(item); lb.Items.Insert(newIndex, item); lb.SelectedIndex = newIndex; diff --git a/PKHeX.WinForms/Subforms/Save Editors/Gen5/CGearImage.cs b/PKHeX.WinForms/Subforms/Save Editors/Gen5/CGearImage.cs index 0774564c9..3aada5d63 100644 --- a/PKHeX.WinForms/Subforms/Save Editors/Gen5/CGearImage.cs +++ b/PKHeX.WinForms/Subforms/Save Editors/Gen5/CGearImage.cs @@ -7,17 +7,29 @@ using PKHeX.Drawing; namespace PKHeX.WinForms; +/// +/// Utility logic to convert images to C-Gear Backgrounds and reverse. +/// public static class CGearImage { + private const int Width = CGearBackground.Width; + private const int Height = CGearBackground.Height; + + /// + /// Gets the visual image of a . + /// public static Bitmap GetBitmap(CGearBackground bg) { - return ImageUtil.GetBitmap(bg.GetImageData(), CGearBackground.Width, CGearBackground.Height); + var data = bg.GetImageData(); + return ImageUtil.GetBitmap(data, Width, Height); } + /// + /// Converts a to a . + /// + /// public static CGearBackground GetCGearBackground(Bitmap img) { - const int Width = CGearBackground.Width; - const int Height = CGearBackground.Height; if (img.Width != Width) throw new ArgumentException($"Invalid image width. Expected {Width} pixels wide."); if (img.Height != Height) diff --git a/PKHeX.WinForms/Subforms/Save Editors/Gen5/SAV_Misc5.cs b/PKHeX.WinForms/Subforms/Save Editors/Gen5/SAV_Misc5.cs index 9f6b3fb3c..7c8a397b9 100644 --- a/PKHeX.WinForms/Subforms/Save Editors/Gen5/SAV_Misc5.cs +++ b/PKHeX.WinForms/Subforms/Save Editors/Gen5/SAV_Misc5.cs @@ -142,7 +142,7 @@ public partial class SAV_Misc5 : Form } // LibertyPass - valLibPass = keyLibPass ^ (uint)((SAV.SID << 16) | SAV.TID); + valLibPass = keyLibPass ^ SAV.ID32; bLibPass = ReadUInt32LittleEndian(SAV.Data.AsSpan(ofsLibPass)) == valLibPass; CHK_LibertyPass.Checked = bLibPass; } @@ -189,9 +189,9 @@ public partial class SAV_Misc5 : Form if (FlyDestC[i] < 32) { if (CLB_FlyDest.GetItemChecked(i)) - valFly |= (uint) 1 << FlyDestC[i]; + valFly |= 1u << FlyDestC[i]; else - valFly &= ~((uint) 1 << FlyDestC[i]); + valFly &= ~(1u << FlyDestC[i]); } else { @@ -519,7 +519,7 @@ public partial class SAV_Misc5 : Form public static string GetSpeciesName(ushort species) { var arr = GameInfo.Strings.Species; - if ((uint)species >= arr.Count) + if (species >= arr.Count) return $"Invalid: {species}"; return arr[species]; } diff --git a/PKHeX.WinForms/Subforms/Save Editors/Gen5/SAV_Misc5.resx b/PKHeX.WinForms/Subforms/Save Editors/Gen5/SAV_Misc5.resx index 4cb56cb81..94a9c4c42 100644 --- a/PKHeX.WinForms/Subforms/Save Editors/Gen5/SAV_Misc5.resx +++ b/PKHeX.WinForms/Subforms/Save Editors/Gen5/SAV_Misc5.resx @@ -1,64 +1,4 @@ - - - + diff --git a/PKHeX.WinForms/Subforms/Save Editors/Gen5/SAV_Pokedex5.cs b/PKHeX.WinForms/Subforms/Save Editors/Gen5/SAV_Pokedex5.cs index 44860c4e0..3fcc4b575 100644 --- a/PKHeX.WinForms/Subforms/Save Editors/Gen5/SAV_Pokedex5.cs +++ b/PKHeX.WinForms/Subforms/Save Editors/Gen5/SAV_Pokedex5.cs @@ -138,7 +138,7 @@ public partial class SAV_Pokedex5 : Form CLB_FormsSeen.Items.Clear(); CLB_FormDisplayed.Items.Clear(); - int fc = pi.FormCount; + var fc = pi.FormCount; int f = SAV is SAV5B2W2 ? DexFormUtil.GetDexFormIndexB2W2(species, fc) : DexFormUtil.GetDexFormIndexBW(species, fc); if (f < 0) return; @@ -166,7 +166,7 @@ public partial class SAV_Pokedex5 : Form Dex.SetCaught(species, CP[0].Checked); for (int i = 0; i < 4; i++) Dex.SetSeen(species, i, CP[i + 1].Checked); - + for (int i = 0; i < 4; i++) Dex.SetDisplayed(species - 1, i, CP[i + 5].Checked); @@ -176,7 +176,7 @@ public partial class SAV_Pokedex5 : Form Dex.SetLanguageFlag(species - 1, i, CL[i].Checked); } - int fc = SAV.Personal[species].FormCount; + var fc = SAV.Personal[species].FormCount; int f = SAV is SAV5B2W2 ? DexFormUtil.GetDexFormIndexB2W2(species, fc) : DexFormUtil.GetDexFormIndexBW(species, fc); if (f < 0) return; @@ -223,7 +223,7 @@ public partial class SAV_Pokedex5 : Form CHK_P1.Checked = ModifierKeys != Keys.Control; } int index = LB_Species.SelectedIndex+1; - int gt = SAV.Personal[index].Gender; + byte gt = SAV.Personal[index].Gender; bool canBeMale = gt != PersonalInfo.RatioMagicFemale; bool canBeFemale = gt is not (PersonalInfo.RatioMagicMale or PersonalInfo.RatioMagicGenderless); @@ -257,7 +257,7 @@ public partial class SAV_Pokedex5 : Form { for (int i = 0; i < LB_Species.Items.Count; i++) { - int gt = SAV.Personal[i + 1].Gender; + byte gt = SAV.Personal[i + 1].Gender; LB_Species.SelectedIndex = i; foreach (CheckBox t in new[] { CHK_P2, CHK_P3, CHK_P4, CHK_P5 }) t.Checked = mnuSeenNone != sender && t.Enabled; @@ -286,7 +286,7 @@ public partial class SAV_Pokedex5 : Form { for (int i = 0; i < CB_Species.Items.Count; i++) { - int gt = SAV.Personal[i + 1].Gender; + byte gt = SAV.Personal[i + 1].Gender; LB_Species.SelectedIndex = i; foreach (CheckBox t in new[] { CHK_P1 }) t.Checked = mnuCaughtNone != sender; diff --git a/PKHeX.WinForms/Subforms/Save Editors/Gen6/SAV_HallOfFame.Designer.cs b/PKHeX.WinForms/Subforms/Save Editors/Gen6/SAV_HallOfFame.Designer.cs index dbbe827de..49514c9ab 100644 --- a/PKHeX.WinForms/Subforms/Save Editors/Gen6/SAV_HallOfFame.Designer.cs +++ b/PKHeX.WinForms/Subforms/Save Editors/Gen6/SAV_HallOfFame.Designer.cs @@ -378,7 +378,7 @@ this.Label_SID.Name = "Label_SID"; this.Label_SID.Size = new System.Drawing.Size(36, 13); this.Label_SID.TabIndex = 4; - this.Label_SID.Text = "SID:"; + this.Label_SID.Text = "SID16:"; this.Label_SID.TextAlign = System.Drawing.ContentAlignment.MiddleRight; // // Label_TID @@ -387,7 +387,7 @@ this.Label_TID.Name = "Label_TID"; this.Label_TID.Size = new System.Drawing.Size(28, 13); this.Label_TID.TabIndex = 3; - this.Label_TID.Text = "TID:"; + this.Label_TID.Text = "TID16:"; this.Label_TID.TextAlign = System.Drawing.ContentAlignment.MiddleRight; // // L_Victory diff --git a/PKHeX.WinForms/Subforms/Save Editors/Gen6/SAV_HallOfFame.cs b/PKHeX.WinForms/Subforms/Save Editors/Gen6/SAV_HallOfFame.cs index 8dbcec237..7c60b2efb 100644 --- a/PKHeX.WinForms/Subforms/Save Editors/Gen6/SAV_HallOfFame.cs +++ b/PKHeX.WinForms/Subforms/Save Editors/Gen6/SAV_HallOfFame.cs @@ -155,7 +155,7 @@ public partial class SAV_HallOfFame : Form s.Add($"Move 4: {str.Move[entry.Move4]}"); string OTGender = gendersymbols[(int)entry.OT_Gender]; - s.Add($"OT: {entry.OT_Name} ({OTGender}) ({entry.TID}/{entry.SID})"); + s.Add($"OT: {entry.OT_Name} ({OTGender}) ({entry.TID16}/{entry.SID16})"); s.Add(string.Empty); } @@ -178,8 +178,8 @@ public partial class SAV_HallOfFame : Form TB_EC.Text = entry.EncryptionConstant.ToString("X8"); - TB_TID.Text = entry.TID.ToString("00000"); - TB_SID.Text = entry.SID.ToString("00000"); + TB_TID.Text = entry.TID16.ToString("00000"); + TB_SID.Text = entry.SID16.ToString("00000"); TB_Nickname.Text = entry.Nickname; TB_OT.Text = entry.OT_Name; @@ -217,8 +217,8 @@ public partial class SAV_HallOfFame : Form Move3 = Convert.ToUInt16(CB_Move3.SelectedValue), Move4 = Convert.ToUInt16(CB_Move4.SelectedValue), EncryptionConstant = Util.GetHexValue(TB_EC.Text), - TID = Convert.ToUInt16(TB_TID.Text), - SID = Convert.ToUInt16(TB_SID.Text), + TID16 = Convert.ToUInt16(TB_TID.Text), + SID16 = Convert.ToUInt16(TB_SID.Text), Form = (byte)CB_Form.SelectedIndex, Gender = (uint)EntityGender.GetFromString(Label_Gender.Text) & 0x3, Level = Convert.ToUInt16(TB_Level.Text), @@ -375,7 +375,7 @@ public partial class SAV_HallOfFame : Form Array.Copy(data, offset + StructureSize, data, offset, StructureSize * (Count - 1 - index)); // Ensure Last Entry is Cleared - data.AsSpan(StructureSize * (Count - 1), StructureSize).Fill(0); + data.AsSpan(StructureSize * (Count - 1), StructureSize).Clear(); DisplayEntry(LB_DataEntry, EventArgs.Empty); } @@ -391,7 +391,7 @@ public partial class SAV_HallOfFame : Form int offset = (team * (4 + (6 * HallFame6Entity.SIZE))) + (member * HallFame6Entity.SIZE); var nicktrash = data.AsSpan(offset + 0x18, 26); var text = tb.Text; - SAV.SetString(nicktrash, text.AsSpan(), 12, StringConverterOption.ClearZero); + SAV.SetString(nicktrash, text, 12, StringConverterOption.ClearZero); var d = new TrashEditor(tb, nicktrash, SAV); d.ShowDialog(); tb.Text = d.FinalString; diff --git a/PKHeX.WinForms/Subforms/Save Editors/Gen6/SAV_PokedexORAS.cs b/PKHeX.WinForms/Subforms/Save Editors/Gen6/SAV_PokedexORAS.cs index 1f6d9ef15..669019a4b 100644 --- a/PKHeX.WinForms/Subforms/Save Editors/Gen6/SAV_PokedexORAS.cs +++ b/PKHeX.WinForms/Subforms/Save Editors/Gen6/SAV_PokedexORAS.cs @@ -134,7 +134,7 @@ public partial class SAV_PokedexORAS : Form CLB_FormsSeen.Items.Clear(); CLB_FormDisplayed.Items.Clear(); - int fc = pi.FormCount; + var fc = pi.FormCount; int f = DexFormUtil.GetDexFormIndexORAS(species, fc); if (f < 0) return; @@ -170,7 +170,7 @@ public partial class SAV_PokedexORAS : Form ushort count = (ushort) Math.Min(0xFFFF, Util.ToUInt32(MT_Count.Text)); Zukan.SetEncounterCount(species - 1, count); - int fc = SAV.Personal[species].FormCount; + var fc = SAV.Personal[species].FormCount; int f = DexFormUtil.GetDexFormIndexORAS(species, fc); if (f < 0) return; @@ -218,7 +218,7 @@ public partial class SAV_PokedexORAS : Form CHK_P1.Checked = ModifierKeys != Keys.Control; } int index = LB_Species.SelectedIndex+1; - int gt = SAV.Personal[index].Gender; + byte gt = SAV.Personal[index].Gender; bool canBeMale = gt != PersonalInfo.RatioMagicFemale; bool canBeFemale = gt is not (PersonalInfo.RatioMagicMale or PersonalInfo.RatioMagicGenderless); @@ -280,7 +280,7 @@ public partial class SAV_PokedexORAS : Form if (mnuSeenNone != sender) { // if seen ensure at least one Displayed - int gt = SAV.Personal[i + 1].Gender; + byte gt = SAV.Personal[i + 1].Gender; if (!(CHK_P6.Checked || CHK_P7.Checked || CHK_P8.Checked || CHK_P9.Checked)) (gt != PersonalInfo.RatioMagicFemale ? CHK_P6 : CHK_P7).Checked = true; } @@ -302,7 +302,7 @@ public partial class SAV_PokedexORAS : Form { for (int i = 0; i < LB_Species.Items.Count; i++) { - int gt = SAV.Personal[i + 1].Gender; + byte gt = SAV.Personal[i + 1].Gender; LB_Species.SelectedIndex = i; foreach (CheckBox t in new[] { CHK_P1 }) t.Checked = mnuCaughtNone != sender; diff --git a/PKHeX.WinForms/Subforms/Save Editors/Gen6/SAV_PokedexXY.cs b/PKHeX.WinForms/Subforms/Save Editors/Gen6/SAV_PokedexXY.cs index f0dcc5cc6..92da48cdd 100644 --- a/PKHeX.WinForms/Subforms/Save Editors/Gen6/SAV_PokedexXY.cs +++ b/PKHeX.WinForms/Subforms/Save Editors/Gen6/SAV_PokedexXY.cs @@ -142,7 +142,7 @@ public partial class SAV_PokedexXY : Form CLB_FormsSeen.Items.Clear(); CLB_FormDisplayed.Items.Clear(); - int fc = pi.FormCount; + var fc = pi.FormCount; int f = DexFormUtil.GetDexFormIndexXY(species, fc); if (f < 0) return; @@ -179,7 +179,7 @@ public partial class SAV_PokedexXY : Form if (CHK_F1.Enabled) // species < 650 // (1-649) Zukan.SetForeignFlag(species - 1, CHK_F1.Checked); - int fc = SAV.Personal[species].FormCount; + var fc = SAV.Personal[species].FormCount; int f = DexFormUtil.GetDexFormIndexORAS(species, fc); if (f < 0) return; @@ -231,7 +231,7 @@ public partial class SAV_PokedexXY : Form CHK_F1.Checked = ModifierKeys != Keys.Control; } int index = LB_Species.SelectedIndex+1; - int gt = SAV.Personal[index].Gender; + byte gt = SAV.Personal[index].Gender; bool canBeMale = gt != PersonalInfo.RatioMagicFemale; bool canBeFemale = gt is not (PersonalInfo.RatioMagicMale or PersonalInfo.RatioMagicGenderless); @@ -265,7 +265,7 @@ public partial class SAV_PokedexXY : Form { for (int i = 0; i < LB_Species.Items.Count; i++) { - int gt = SAV.Personal[i + 1].Gender; + byte gt = SAV.Personal[i + 1].Gender; LB_Species.SelectedIndex = i; foreach (CheckBox t in new[] { CHK_P2, CHK_P3, CHK_P4, CHK_P5 }) t.Checked = mnuSeenNone != sender && t.Enabled; @@ -289,12 +289,12 @@ public partial class SAV_PokedexXY : Form } } } - + if (sender == mnuCaughtNone || sender == mnuCaughtAll || sender == mnuComplete) { for (int i = 0; i < CB_Species.Items.Count; i++) { - int gt = SAV.Personal[i + 1].Gender; + byte gt = SAV.Personal[i + 1].Gender; LB_Species.SelectedIndex = i; foreach (CheckBox t in new[] { CHK_P1, CHK_F1 }) t.Checked = mnuCaughtNone != sender; diff --git a/PKHeX.WinForms/Subforms/Save Editors/Gen6/SAV_Trainer.Designer.cs b/PKHeX.WinForms/Subforms/Save Editors/Gen6/SAV_Trainer.Designer.cs index d52df9c0c..7190809ba 100644 --- a/PKHeX.WinForms/Subforms/Save Editors/Gen6/SAV_Trainer.Designer.cs +++ b/PKHeX.WinForms/Subforms/Save Editors/Gen6/SAV_Trainer.Designer.cs @@ -240,7 +240,7 @@ namespace PKHeX.WinForms this.L_TID.Name = "L_TID"; this.L_TID.Size = new System.Drawing.Size(38, 13); this.L_TID.TabIndex = 6; - this.L_TID.Text = "TID:"; + this.L_TID.Text = "TID16:"; this.L_TID.TextAlign = System.Drawing.ContentAlignment.MiddleRight; // // L_SID @@ -249,7 +249,7 @@ namespace PKHeX.WinForms this.L_SID.Name = "L_SID"; this.L_SID.Size = new System.Drawing.Size(38, 13); this.L_SID.TabIndex = 7; - this.L_SID.Text = "SID:"; + this.L_SID.Text = "SID16:"; this.L_SID.TextAlign = System.Drawing.ContentAlignment.MiddleRight; // // MT_TID diff --git a/PKHeX.WinForms/Subforms/Save Editors/Gen6/SAV_Trainer.cs b/PKHeX.WinForms/Subforms/Save Editors/Gen6/SAV_Trainer.cs index d34aeafae..3db507dab 100644 --- a/PKHeX.WinForms/Subforms/Save Editors/Gen6/SAV_Trainer.cs +++ b/PKHeX.WinForms/Subforms/Save Editors/Gen6/SAV_Trainer.cs @@ -28,7 +28,7 @@ public partial class SAV_Trainer : Form CB_Gender.Items.Clear(); CB_Gender.Items.AddRange(Main.GenderSymbols.Take(2).ToArray()); // m/f depending on unicode selection - TrainerStats.LoadRecords(SAV, Records.RecordList_6); + TrainerStats.LoadRecords(SAV, RecordLists.RecordList_6); TrainerStats.GetToolTipText = UpdateTip; MaisonRecords = new[] @@ -111,8 +111,8 @@ public partial class SAV_Trainer : Form // Display Data TB_OTName.Text = OT_NAME; - MT_TID.Text = SAV.TID.ToString("00000"); - MT_SID.Text = SAV.SID.ToString("00000"); + MT_TID.Text = SAV.TID16.ToString("00000"); + MT_SID.Text = SAV.SID16.ToString("00000"); MT_Money.Text = SAV.Money.ToString(); var status = SAV.Status; @@ -201,8 +201,8 @@ public partial class SAV_Trainer : Form SAV.Game = (byte)(CB_Game.SelectedIndex + 0x18); SAV.Gender = (byte)CB_Gender.SelectedIndex; - SAV.TID = (ushort)Util.ToUInt32(MT_TID.Text); - SAV.SID = (ushort)Util.ToUInt32(MT_SID.Text); + SAV.TID16 = (ushort)Util.ToUInt32(MT_TID.Text); + SAV.SID16 = (ushort)Util.ToUInt32(MT_SID.Text); SAV.Money = Util.ToUInt32(MT_Money.Text); SAV.Region = (byte)WinFormsUtil.GetIndex(CB_Region); SAV.Country = (byte)WinFormsUtil.GetIndex(CB_Country); @@ -292,9 +292,9 @@ public partial class SAV_Trainer : Form private void ShowTSV(object sender, EventArgs e) { - uint TID = Util.ToUInt32(MT_TID.Text); - uint SID = Util.ToUInt32(MT_SID.Text); - uint tsv = (TID ^ SID) >> 4; + uint TID16 = Util.ToUInt32(MT_TID.Text); + uint SID16 = Util.ToUInt32(MT_SID.Text); + uint tsv = (TID16 ^ SID16) >> 4; Tip1.SetToolTip(MT_TID, $"TSV: {tsv:0000}"); Tip2.SetToolTip(MT_SID, $"TSV: {tsv:0000}"); } diff --git a/PKHeX.WinForms/Subforms/Save Editors/Gen7/SAV_Capture7GG.cs b/PKHeX.WinForms/Subforms/Save Editors/Gen7/SAV_Capture7GG.cs index 4ef899356..22bfee5f5 100644 --- a/PKHeX.WinForms/Subforms/Save Editors/Gen7/SAV_Capture7GG.cs +++ b/PKHeX.WinForms/Subforms/Save Editors/Gen7/SAV_Capture7GG.cs @@ -13,7 +13,7 @@ public partial class SAV_Capture7GG : Form private readonly Zukan7b Dex; private readonly CaptureRecords Captured; - private ushort Index = ushort.MaxValue; + private ushort Index; private bool Loading; public SAV_Capture7GG(SaveFile sav) @@ -58,7 +58,8 @@ public partial class SAV_Capture7GG : Form return; SetEntry(); - Index = CaptureRecords.GetSpeciesIndex((ushort)CB_Species.SelectedValue); + var species = (ushort)WinFormsUtil.GetIndex(CB_Species); + Index = CaptureRecords.GetSpeciesIndex(species); Loading = true; LB_Species.SelectedIndex = Index; LB_Species.TopIndex = LB_Species.SelectedIndex; diff --git a/PKHeX.WinForms/Subforms/Save Editors/Gen7/SAV_PokedexGG.cs b/PKHeX.WinForms/Subforms/Save Editors/Gen7/SAV_PokedexGG.cs index 11efd3a01..80b439eec 100644 --- a/PKHeX.WinForms/Subforms/Save Editors/Gen7/SAV_PokedexGG.cs +++ b/PKHeX.WinForms/Subforms/Save Editors/Gen7/SAV_PokedexGG.cs @@ -163,7 +163,7 @@ public partial class SAV_PokedexGG : Form } else { - int fc = SAV.Personal[bspecies].FormCount; + var fc = SAV.Personal[bspecies].FormCount; if (fc <= 1) return true; @@ -221,7 +221,7 @@ public partial class SAV_PokedexGG : Form CHK_P1.Enabled = currentSpecies <= SAV.MaxSpeciesID; CHK_P1.Checked = CHK_P1.Enabled && Dex.GetCaught(currentSpecies); - int gt = Dex.GetBaseSpeciesGenderValue(LB_Species.SelectedIndex); + var gt = Dex.GetBaseSpeciesGenderValue(LB_Species.SelectedIndex); bool canBeMale = gt != PersonalInfo.RatioMagicFemale; bool canBeFemale = gt is not (PersonalInfo.RatioMagicMale or PersonalInfo.RatioMagicGenderless); @@ -280,7 +280,7 @@ public partial class SAV_PokedexGG : Form void set(DexSizeType type, NumericUpDown nudH, NumericUpDown nudW, CheckBox ck) { - nudH.Enabled = nudW.Enabled = ck.Checked = Dex.GetSizeData(type, index, out int h, out int w); + nudH.Enabled = nudW.Enabled = ck.Checked = Dex.GetSizeData(type, index, out byte h, out byte w); nudH.Value = h; nudW.Value = w; } @@ -296,7 +296,7 @@ public partial class SAV_PokedexGG : Form if (!hasRecord) return; - static int get(NumericUpDown nud, CheckBox ck) => !ck.Checked ? Zukan7b.DefaultEntryValue : (int) Math.Max(0, Math.Min(255, nud.Value)); + static byte get(NumericUpDown nud, CheckBox ck) => !ck.Checked ? Zukan7b.DefaultEntryValue : (byte)nud.Value; Dex.SetSizeData(DexSizeType.MinHeight, index, get(NUD_RHeightMin, CHK_RMinHeight), get(NUD_RHeightMinWeight, CHK_RMinHeight)); Dex.SetSizeData(DexSizeType.MaxHeight, index, get(NUD_RHeightMax, CHK_RMaxHeight), get(NUD_RHeightMaxWeight, CHK_RMaxHeight)); @@ -347,7 +347,7 @@ public partial class SAV_PokedexGG : Form { CHK_P1.Checked = ModifierKeys != Keys.Control; } - int gt = Dex.GetBaseSpeciesGenderValue(LB_Species.SelectedIndex); + byte gt = Dex.GetBaseSpeciesGenderValue(LB_Species.SelectedIndex); bool canBeMale = gt != PersonalInfo.RatioMagicFemale; bool canBeFemale = gt is not (PersonalInfo.RatioMagicMale or PersonalInfo.RatioMagicGenderless); @@ -463,7 +463,7 @@ public partial class SAV_PokedexGG : Form yield return 809; } - private void SetCaught(object sender, int gt, int lang, bool isForm) + private void SetCaught(object sender, byte gt, int lang, bool isForm) { CHK_P1.Checked = mnuCaughtNone != sender; for (int j = 0; j < CL.Length; j++) @@ -502,7 +502,7 @@ public partial class SAV_PokedexGG : Form (gt != PersonalInfo.RatioMagicFemale ? CHK_P6 : CHK_P7).Checked = CHK_P1.Enabled; } - private void SetSeen(object sender, int gt, bool isForm) + private void SetSeen(object sender, byte gt, bool isForm) { foreach (CheckBox t in new[] { CHK_P2, CHK_P3, CHK_P4, CHK_P5 }) t.Checked = mnuSeenNone != sender && t.Enabled; diff --git a/PKHeX.WinForms/Subforms/Save Editors/Gen7/SAV_PokedexSM.cs b/PKHeX.WinForms/Subforms/Save Editors/Gen7/SAV_PokedexSM.cs index e35304ee7..efb598b92 100644 --- a/PKHeX.WinForms/Subforms/Save Editors/Gen7/SAV_PokedexSM.cs +++ b/PKHeX.WinForms/Subforms/Save Editors/Gen7/SAV_PokedexSM.cs @@ -88,7 +88,7 @@ public partial class SAV_PokedexSM : Form int form = LB_Forms.SelectedIndex; if (form > 0) { - int fc = SAV.Personal[bspecies].FormCount; + var fc = SAV.Personal[bspecies].FormCount; if (fc > 1) // actually has forms { int f = Dex.GetDexFormIndex(bspecies, fc, form); @@ -144,7 +144,7 @@ public partial class SAV_PokedexSM : Form } else { - int fc = SAV.Personal[bspecies].FormCount; + var fc = SAV.Personal[bspecies].FormCount; if (fc <= 1) return true; @@ -203,7 +203,7 @@ public partial class SAV_PokedexSM : Form CHK_P1.Enabled = currentSpecies <= SAV.MaxSpeciesID; CHK_P1.Checked = CHK_P1.Enabled && Dex.GetCaught(currentSpecies); - int gt = Dex.GetBaseSpeciesGenderValue(LB_Species.SelectedIndex); + byte gt = Dex.GetBaseSpeciesGenderValue(LB_Species.SelectedIndex); bool canBeMale = gt != PersonalInfo.RatioMagicFemale; bool canBeFemale = gt is not (PersonalInfo.RatioMagicMale or PersonalInfo.RatioMagicGenderless); @@ -276,7 +276,7 @@ public partial class SAV_PokedexSM : Form { CHK_P1.Checked = ModifierKeys != Keys.Control; } - int gt = Dex.GetBaseSpeciesGenderValue(LB_Species.SelectedIndex); + byte gt = Dex.GetBaseSpeciesGenderValue(LB_Species.SelectedIndex); bool canBeMale = gt != PersonalInfo.RatioMagicFemale; bool canBeFemale = gt is not (PersonalInfo.RatioMagicMale or PersonalInfo.RatioMagicGenderless); @@ -362,7 +362,7 @@ public partial class SAV_PokedexSM : Form } } - private void SetCaught(object sender, int gt, int lang, bool isForm) + private void SetCaught(object sender, byte gt, int lang, bool isForm) { CHK_P1.Checked = mnuCaughtNone != sender; for (int j = 0; j < CL.Length; j++) @@ -401,7 +401,7 @@ public partial class SAV_PokedexSM : Form (gt != PersonalInfo.RatioMagicFemale ? CHK_P6 : CHK_P7).Checked = CHK_P1.Enabled; } - private void SetSeen(object sender, int gt, bool isForm) + private void SetSeen(object sender, byte gt, bool isForm) { foreach (CheckBox t in new[] {CHK_P2, CHK_P3, CHK_P4, CHK_P5}) t.Checked = mnuSeenNone != sender && t.Enabled; diff --git a/PKHeX.WinForms/Subforms/Save Editors/Gen7/SAV_Trainer7.cs b/PKHeX.WinForms/Subforms/Save Editors/Gen7/SAV_Trainer7.cs index 2febf20f5..3874f3b03 100644 --- a/PKHeX.WinForms/Subforms/Save Editors/Gen7/SAV_Trainer7.cs +++ b/PKHeX.WinForms/Subforms/Save Editors/Gen7/SAV_Trainer7.cs @@ -30,7 +30,7 @@ public partial class SAV_Trainer7 : Form GetComboBoxes(); GetTextBoxes(); - TrainerStats.LoadRecords(SAV, Records.RecordList_7); + TrainerStats.LoadRecords(SAV, RecordLists.RecordList_7); TrainerStats.GetToolTipText = UpdateTip; CB_Fashion.SelectedIndex = 1; @@ -103,7 +103,7 @@ public partial class SAV_Trainer7 : Form // Display Data TB_OTName.Text = SAV.OT; - trainerID1.LoadIDValues(SAV); + trainerID1.LoadIDValues(SAV, SAV.Generation); MT_Money.Text = SAV.Money.ToString(); CB_Country.SelectedValue = (int)SAV.Country; @@ -468,7 +468,7 @@ public partial class SAV_Trainer7 : Form for (int i = 0; i < listbox.Items.Count; i++) { if (listbox.GetSelected(i)) - bits |= (uint)(1 << i); + bits |= 1u << i; } return bits; } diff --git a/PKHeX.WinForms/Subforms/Save Editors/Gen7/SAV_Trainer7GG.cs b/PKHeX.WinForms/Subforms/Save Editors/Gen7/SAV_Trainer7GG.cs index 4e248eaff..1ba02d125 100644 --- a/PKHeX.WinForms/Subforms/Save Editors/Gen7/SAV_Trainer7GG.cs +++ b/PKHeX.WinForms/Subforms/Save Editors/Gen7/SAV_Trainer7GG.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using System.IO; using System.Linq; @@ -71,7 +71,7 @@ public partial class SAV_Trainer7GG : Form CB_Game.SelectedValue = SAV.Game; CB_Gender.SelectedIndex = SAV.Gender; - trainerID1.LoadIDValues(SAV); + trainerID1.LoadIDValues(SAV, SAV.Generation); // Load Play Time MT_Hours.Text = SAV.PlayedHours.ToString(); @@ -183,7 +183,8 @@ public partial class SAV_Trainer7GG : Form private void ImportGP1From(string path) { int index = (int)NUD_GoIndex.Value; - index = Math.Min(GoParkStorage.Count - 1, Math.Max(0, index)); + const int max = GoParkStorage.Count - 1; + index = Math.Clamp(index, 0, max); ImportGP1From(path, index); } @@ -206,7 +207,8 @@ public partial class SAV_Trainer7GG : Form private void B_Export_Click(object sender, EventArgs e) { int index = (int)NUD_GoIndex.Value; - index = Math.Min(GoParkStorage.Count - 1, Math.Max(0, index)); + const int max = GoParkStorage.Count - 1; + index = Math.Clamp(index, 0, max); var data = Park[index]; using var sfd = new SaveFileDialog @@ -256,7 +258,8 @@ public partial class SAV_Trainer7GG : Form private void UpdateGoSummary(int index) { - index = Math.Min(GoParkStorage.Count - 1, Math.Max(0, index)); + const int max = GoParkStorage.Count - 1; + index = Math.Clamp(index, 0, max); int area = index / GoParkStorage.SlotsPerArea; int slot = index % GoParkStorage.SlotsPerArea; @@ -279,7 +282,8 @@ public partial class SAV_Trainer7GG : Form private void B_DeleteGo_Click(object sender, EventArgs e) { int index = (int)NUD_GoIndex.Value; - index = Math.Min(GoParkStorage.Count - 1, Math.Max(0, index)); + const int max = GoParkStorage.Count - 1; + index = Math.Clamp(index, 0, max); Park[index] = new GP1(); UpdateGoSummary((int)NUD_GoIndex.Value); System.Media.SystemSounds.Asterisk.Play(); diff --git a/PKHeX.WinForms/Subforms/Save Editors/Gen8/PokedexResearchTask8aPanel.Designer.cs b/PKHeX.WinForms/Subforms/Save Editors/Gen8/PokedexResearchTask8aPanel.Designer.cs index 16bac85a6..ffdf0c279 100644 --- a/PKHeX.WinForms/Subforms/Save Editors/Gen8/PokedexResearchTask8aPanel.Designer.cs +++ b/PKHeX.WinForms/Subforms/Save Editors/Gen8/PokedexResearchTask8aPanel.Designer.cs @@ -50,9 +50,11 @@ this.LB_Species.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) | System.Windows.Forms.AnchorStyles.Left))); this.LB_Species.FormattingEnabled = true; - this.LB_Species.Location = new System.Drawing.Point(-265, -101); + this.LB_Species.ItemHeight = 15; + this.LB_Species.Location = new System.Drawing.Point(-309, -117); + this.LB_Species.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3); this.LB_Species.Name = "LB_Species"; - this.LB_Species.Size = new System.Drawing.Size(125, 238); + this.LB_Species.Size = new System.Drawing.Size(145, 274); this.LB_Species.TabIndex = 125; // // FLP_T1 @@ -64,27 +66,27 @@ this.FLP_T1.Location = new System.Drawing.Point(0, 0); this.FLP_T1.Margin = new System.Windows.Forms.Padding(0); this.FLP_T1.Name = "FLP_T1"; - this.FLP_T1.Size = new System.Drawing.Size(646, 22); + this.FLP_T1.Size = new System.Drawing.Size(757, 25); this.FLP_T1.TabIndex = 127; // // PB_Bonus // this.PB_Bonus.Image = global::PKHeX.WinForms.Properties.Resources.research_bonus_points; this.PB_Bonus.InitialImage = null; - this.PB_Bonus.Location = new System.Drawing.Point(3, 0); - this.PB_Bonus.Margin = new System.Windows.Forms.Padding(3, 0, 3, 0); + this.PB_Bonus.Location = new System.Drawing.Point(4, 0); + this.PB_Bonus.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); this.PB_Bonus.Name = "PB_Bonus"; - this.PB_Bonus.Size = new System.Drawing.Size(20, 20); + this.PB_Bonus.Size = new System.Drawing.Size(23, 23); this.PB_Bonus.SizeMode = System.Windows.Forms.PictureBoxSizeMode.CenterImage; this.PB_Bonus.TabIndex = 43; this.PB_Bonus.TabStop = false; // // Label_Task // - this.Label_Task.Location = new System.Drawing.Point(26, 0); + this.Label_Task.Location = new System.Drawing.Point(31, 0); this.Label_Task.Margin = new System.Windows.Forms.Padding(0); this.Label_Task.Name = "Label_Task"; - this.Label_Task.Size = new System.Drawing.Size(316, 20); + this.Label_Task.Size = new System.Drawing.Size(369, 23); this.Label_Task.TabIndex = 19; this.Label_Task.Text = "Task Description:"; this.Label_Task.TextAlign = System.Drawing.ContentAlignment.MiddleLeft; @@ -92,15 +94,15 @@ // NUP_CurrentValue // this.NUP_CurrentValue.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); - this.NUP_CurrentValue.Location = new System.Drawing.Point(345, 0); - this.NUP_CurrentValue.Margin = new System.Windows.Forms.Padding(3, 0, 3, 0); + this.NUP_CurrentValue.Location = new System.Drawing.Point(404, 0); + this.NUP_CurrentValue.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); this.NUP_CurrentValue.Maximum = new decimal(new int[] { 60000, 0, 0, 0}); this.NUP_CurrentValue.Name = "NUP_CurrentValue"; - this.NUP_CurrentValue.Size = new System.Drawing.Size(72, 20); + this.NUP_CurrentValue.Size = new System.Drawing.Size(84, 23); this.NUP_CurrentValue.TabIndex = 51; this.NUP_CurrentValue.TextAlign = System.Windows.Forms.HorizontalAlignment.Right; this.NUP_CurrentValue.ValueChanged += new System.EventHandler(this.NUP_CurrentValue_Changed); @@ -114,22 +116,22 @@ this.FLP_T1Right.Controls.Add(this.MTB_Threshold2); this.FLP_T1Right.Controls.Add(this.MTB_Threshold1); this.FLP_T1Right.FlowDirection = System.Windows.Forms.FlowDirection.RightToLeft; - this.FLP_T1Right.Location = new System.Drawing.Point(420, 0); + this.FLP_T1Right.Location = new System.Drawing.Point(492, 0); this.FLP_T1Right.Margin = new System.Windows.Forms.Padding(0); this.FLP_T1Right.Name = "FLP_T1Right"; - this.FLP_T1Right.Size = new System.Drawing.Size(226, 21); + this.FLP_T1Right.Size = new System.Drawing.Size(264, 24); this.FLP_T1Right.TabIndex = 121; // // MTB_Threshold5 // this.MTB_Threshold5.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; this.MTB_Threshold5.Enabled = false; - this.MTB_Threshold5.Location = new System.Drawing.Point(183, 0); - this.MTB_Threshold5.Margin = new System.Windows.Forms.Padding(2, 0, 3, 0); + this.MTB_Threshold5.Location = new System.Drawing.Point(214, 0); + this.MTB_Threshold5.Margin = new System.Windows.Forms.Padding(2, 0, 4, 0); this.MTB_Threshold5.Mask = "999"; this.MTB_Threshold5.Name = "MTB_Threshold5"; this.MTB_Threshold5.PromptChar = ' '; - this.MTB_Threshold5.Size = new System.Drawing.Size(40, 20); + this.MTB_Threshold5.Size = new System.Drawing.Size(46, 23); this.MTB_Threshold5.TabIndex = 45; this.MTB_Threshold5.Text = "100"; this.MTB_Threshold5.TextAlign = System.Windows.Forms.HorizontalAlignment.Right; @@ -138,12 +140,12 @@ // this.MTB_Threshold4.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; this.MTB_Threshold4.Enabled = false; - this.MTB_Threshold4.Location = new System.Drawing.Point(138, 0); - this.MTB_Threshold4.Margin = new System.Windows.Forms.Padding(2, 0, 3, 0); + this.MTB_Threshold4.Location = new System.Drawing.Point(162, 0); + this.MTB_Threshold4.Margin = new System.Windows.Forms.Padding(2, 0, 4, 0); this.MTB_Threshold4.Mask = "999"; this.MTB_Threshold4.Name = "MTB_Threshold4"; this.MTB_Threshold4.PromptChar = ' '; - this.MTB_Threshold4.Size = new System.Drawing.Size(40, 20); + this.MTB_Threshold4.Size = new System.Drawing.Size(46, 23); this.MTB_Threshold4.TabIndex = 47; this.MTB_Threshold4.Text = "50"; this.MTB_Threshold4.TextAlign = System.Windows.Forms.HorizontalAlignment.Right; @@ -152,12 +154,12 @@ // this.MTB_Threshold3.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; this.MTB_Threshold3.Enabled = false; - this.MTB_Threshold3.Location = new System.Drawing.Point(93, 0); - this.MTB_Threshold3.Margin = new System.Windows.Forms.Padding(2, 0, 3, 0); + this.MTB_Threshold3.Location = new System.Drawing.Point(110, 0); + this.MTB_Threshold3.Margin = new System.Windows.Forms.Padding(2, 0, 4, 0); this.MTB_Threshold3.Mask = "999"; this.MTB_Threshold3.Name = "MTB_Threshold3"; this.MTB_Threshold3.PromptChar = ' '; - this.MTB_Threshold3.Size = new System.Drawing.Size(40, 20); + this.MTB_Threshold3.Size = new System.Drawing.Size(46, 23); this.MTB_Threshold3.TabIndex = 48; this.MTB_Threshold3.Text = "10"; this.MTB_Threshold3.TextAlign = System.Windows.Forms.HorizontalAlignment.Right; @@ -166,12 +168,12 @@ // this.MTB_Threshold2.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; this.MTB_Threshold2.Enabled = false; - this.MTB_Threshold2.Location = new System.Drawing.Point(48, 0); - this.MTB_Threshold2.Margin = new System.Windows.Forms.Padding(2, 0, 3, 0); + this.MTB_Threshold2.Location = new System.Drawing.Point(58, 0); + this.MTB_Threshold2.Margin = new System.Windows.Forms.Padding(2, 0, 4, 0); this.MTB_Threshold2.Mask = "999"; this.MTB_Threshold2.Name = "MTB_Threshold2"; this.MTB_Threshold2.PromptChar = ' '; - this.MTB_Threshold2.Size = new System.Drawing.Size(40, 20); + this.MTB_Threshold2.Size = new System.Drawing.Size(46, 23); this.MTB_Threshold2.TabIndex = 49; this.MTB_Threshold2.Text = "5"; this.MTB_Threshold2.TextAlign = System.Windows.Forms.HorizontalAlignment.Right; @@ -180,24 +182,25 @@ // this.MTB_Threshold1.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; this.MTB_Threshold1.Enabled = false; - this.MTB_Threshold1.Location = new System.Drawing.Point(3, 0); - this.MTB_Threshold1.Margin = new System.Windows.Forms.Padding(2, 0, 3, 0); + this.MTB_Threshold1.Location = new System.Drawing.Point(6, 0); + this.MTB_Threshold1.Margin = new System.Windows.Forms.Padding(2, 0, 4, 0); this.MTB_Threshold1.Mask = "999"; this.MTB_Threshold1.Name = "MTB_Threshold1"; this.MTB_Threshold1.PromptChar = ' '; - this.MTB_Threshold1.Size = new System.Drawing.Size(40, 20); + this.MTB_Threshold1.Size = new System.Drawing.Size(46, 23); this.MTB_Threshold1.TabIndex = 50; this.MTB_Threshold1.Text = "1"; this.MTB_Threshold1.TextAlign = System.Windows.Forms.HorizontalAlignment.Right; // // PokedexResearchTask8aPanel // - this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); + this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 15F); this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; this.Controls.Add(this.FLP_T1); this.Controls.Add(this.LB_Species); + this.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3); this.Name = "PokedexResearchTask8aPanel"; - this.Size = new System.Drawing.Size(646, 22); + this.Size = new System.Drawing.Size(756, 25); this.FLP_T1.ResumeLayout(false); ((System.ComponentModel.ISupportInitialize)(this.PB_Bonus)).EndInit(); ((System.ComponentModel.ISupportInitialize)(this.NUP_CurrentValue)).EndInit(); diff --git a/PKHeX.WinForms/Subforms/Save Editors/Gen8/SAV_PokedexSWSH.resx b/PKHeX.WinForms/Subforms/Save Editors/Gen8/SAV_PokedexSWSH.resx index d185e9e84..0ec7bc7ed 100644 --- a/PKHeX.WinForms/Subforms/Save Editors/Gen8/SAV_PokedexSWSH.resx +++ b/PKHeX.WinForms/Subforms/Save Editors/Gen8/SAV_PokedexSWSH.resx @@ -1,64 +1,4 @@ - - - + diff --git a/PKHeX.WinForms/Subforms/Save Editors/Gen8/SAV_Trainer8.cs b/PKHeX.WinForms/Subforms/Save Editors/Gen8/SAV_Trainer8.cs index cb5234970..2d2598c9b 100644 --- a/PKHeX.WinForms/Subforms/Save Editors/Gen8/SAV_Trainer8.cs +++ b/PKHeX.WinForms/Subforms/Save Editors/Gen8/SAV_Trainer8.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Linq; using System.Windows.Forms; using PKHeX.Core; @@ -27,7 +27,7 @@ public partial class SAV_Trainer8 : Form CB_Gender.Items.Clear(); CB_Gender.Items.AddRange(Main.GenderSymbols.Take(2).ToArray()); // m/f depending on unicode selection - TrainerStats.LoadRecords(SAV, Records.RecordList_8); + TrainerStats.LoadRecords(SAV, RecordLists.RecordList_8); NUD_BP.Value = Math.Min(SAV.Misc.BP, 9999); GetComboBoxes(); @@ -66,7 +66,7 @@ public partial class SAV_Trainer8 : Form TB_TrainerCardNumber.Text = SAV.Blocks.TrainerCard.Number; MT_TrainerCardID.Text = SAV.Blocks.TrainerCard.TrainerID.ToString("000000"); MT_RotoRally.Text = SAV.Blocks.TrainerCard.RotoRallyScore.ToString(); - trainerID1.LoadIDValues(SAV); + trainerID1.LoadIDValues(SAV, SAV.Generation); MT_Money.Text = SAV.Money.ToString(); MT_Watt.Text = SAV.MyStatus.Watt.ToString(); CB_Language.SelectedValue = SAV.Language; @@ -125,8 +125,8 @@ public partial class SAV_Trainer8 : Form SAV.SetValue(SaveBlockAccessor8SWSH.KBattleTowerSinglesStreak, (ushort)Math.Min(300, Util.ToUInt32(MT_BattleTowerSinglesStreak.Text))); SAV.SetValue(SaveBlockAccessor8SWSH.KBattleTowerDoublesStreak, (ushort)Math.Min(300, Util.ToUInt32(MT_BattleTowerDoublesStreak.Text))); - SAV.SetRecord(Records.G8BattleTowerSingleWin, (int)singles); - SAV.SetRecord(Records.G8BattleTowerDoubleWin, (int)doubles); + SAV.SetRecord(RecordLists.G8BattleTowerSingleWin, (int)singles); + SAV.SetRecord(RecordLists.G8BattleTowerDoubleWin, (int)doubles); } private void Save() diff --git a/PKHeX.WinForms/Subforms/Save Editors/Gen8/SAV_Trainer8a.cs b/PKHeX.WinForms/Subforms/Save Editors/Gen8/SAV_Trainer8a.cs index 755f14a0b..0edaa84ec 100644 --- a/PKHeX.WinForms/Subforms/Save Editors/Gen8/SAV_Trainer8a.cs +++ b/PKHeX.WinForms/Subforms/Save Editors/Gen8/SAV_Trainer8a.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Linq; using System.Windows.Forms; using PKHeX.Core; @@ -40,7 +40,7 @@ public partial class SAV_Trainer8a : Form // Display Data TB_OTName.Text = SAV.OT; - trainerID1.LoadIDValues(SAV); + trainerID1.LoadIDValues(SAV, SAV.Generation); MT_Money.Text = SAV.Money.ToString(); CB_Language.SelectedValue = SAV.Language; diff --git a/PKHeX.WinForms/Subforms/Save Editors/Gen8/SAV_Trainer8b.cs b/PKHeX.WinForms/Subforms/Save Editors/Gen8/SAV_Trainer8b.cs index 62384842e..898bdaca5 100644 --- a/PKHeX.WinForms/Subforms/Save Editors/Gen8/SAV_Trainer8b.cs +++ b/PKHeX.WinForms/Subforms/Save Editors/Gen8/SAV_Trainer8b.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Linq; using System.Windows.Forms; using PKHeX.Core; @@ -32,7 +32,7 @@ public partial class SAV_Trainer8b : Form GetComboBoxes(); GetTextBoxes(); - TrainerStats.LoadRecords(SAV, Records.RecordList_8b); + TrainerStats.LoadRecords(SAV, Record8b.RecordList_8b); Loading = false; } @@ -46,14 +46,14 @@ public partial class SAV_Trainer8b : Form private void GetTextBoxes() { // Get Data - CB_Game.SelectedIndex = Math.Max(0, Math.Min(1, SAV.Game - (int)GameVersion.BD)); + CB_Game.SelectedIndex = Math.Clamp(SAV.Game - (int)GameVersion.BD, 0, 1); CB_Gender.SelectedIndex = SAV.Gender; NUD_BP.Value = SAV.BattleTower.BP; // Display Data TB_OTName.Text = SAV.OT; - trainerID1.LoadIDValues(SAV); + trainerID1.LoadIDValues(SAV, SAV.Generation); MT_Money.Text = SAV.Money.ToString(); CB_Language.SelectedValue = SAV.Language; TB_Rival.Text = SAV.Rival; @@ -93,11 +93,11 @@ public partial class SAV_Trainer8b : Form private void Save() { SaveTrainerInfo(); - if (SAV.TID == 0 && SAV.SID == 0) - SAV.SID = 1; // Cannot have an all-zero ID. + if (SAV is { TID16: 0, SID16: 0 }) + SAV.SID16 = 1; // Cannot have an all-zero ID. // Trickle down the changes to the extra record block. - if (SAV.HasFirstSaveFileExpansion && (SAV.OT != Origin.OT || SAV.TID != Origin.TID || SAV.SID != Origin.SID)) + if (SAV.HasFirstSaveFileExpansion && (SAV.OT != Origin.OT || SAV.TID16 != Origin.TID16 || SAV.SID16 != Origin.SID16)) SAV.RecordAdd.ReplaceOT(Origin, SAV); } diff --git a/PKHeX.WinForms/Subforms/Save Editors/Gen9/SAV_PokedexSV.cs b/PKHeX.WinForms/Subforms/Save Editors/Gen9/SAV_PokedexSV.cs index 0d24fbfb7..b05b37157 100644 --- a/PKHeX.WinForms/Subforms/Save Editors/Gen9/SAV_PokedexSV.cs +++ b/PKHeX.WinForms/Subforms/Save Editors/Gen9/SAV_PokedexSV.cs @@ -12,7 +12,7 @@ public partial class SAV_PokedexSV : Form private readonly SAV9SV SAV; private readonly Zukan9 Dex; - private int lastIndex = -1; + private int lastIndex; private readonly bool CanSave; private readonly bool Loading; @@ -69,14 +69,14 @@ public partial class SAV_PokedexSV : Form DexIndex = GetDexIndex(Species); } - private static int GetDexIndex(int species) + private static int GetDexIndex(ushort species) { - var entry = PersonalTable.SV.GetFormEntry((ushort)species, 0); + var entry = PersonalTable.SV.GetFormEntry(species, 0); if (entry.DexIndex != 0) return entry.DexIndex; for (byte i = 1; i < entry.FormCount; i++) { - entry = PersonalTable.SV.GetFormEntry((ushort)species, i); + entry = PersonalTable.SV.GetFormEntry(species, i); if (entry.DexIndex != 0) return entry.DexIndex; } @@ -87,7 +87,7 @@ public partial class SAV_PokedexSV : Form private DexMap[] ListBoxToSpecies { get; } private ushort GetSpecies(int listBoxIndex) => Array.Find(ListBoxToSpecies, z => z.ListIndex == listBoxIndex)?.Species ?? 0; - private int GetIndex(int species) => Array.Find(ListBoxToSpecies, z => z.Species == species)?.ListIndex ?? 0; + private int GetIndex(ushort species) => Array.Find(ListBoxToSpecies, z => z.Species == species)?.ListIndex ?? 0; private void ChangeCBSpecies(object sender, EventArgs e) { diff --git a/PKHeX.WinForms/Subforms/Save Editors/Gen9/SAV_RaidSevenStar9.cs b/PKHeX.WinForms/Subforms/Save Editors/Gen9/SAV_RaidSevenStar9.cs index 82470d34f..eb513288d 100644 --- a/PKHeX.WinForms/Subforms/Save Editors/Gen9/SAV_RaidSevenStar9.cs +++ b/PKHeX.WinForms/Subforms/Save Editors/Gen9/SAV_RaidSevenStar9.cs @@ -2,7 +2,6 @@ using System; using System.Linq; using System.Windows.Forms; using PKHeX.Core; -using static PKHeX.Core.MessageStrings; namespace PKHeX.WinForms; diff --git a/PKHeX.WinForms/Subforms/Save Editors/Gen9/SAV_Trainer9.Designer.cs b/PKHeX.WinForms/Subforms/Save Editors/Gen9/SAV_Trainer9.Designer.cs index 780f6514a..544e653ba 100644 --- a/PKHeX.WinForms/Subforms/Save Editors/Gen9/SAV_Trainer9.Designer.cs +++ b/PKHeX.WinForms/Subforms/Save Editors/Gen9/SAV_Trainer9.Designer.cs @@ -94,7 +94,9 @@ namespace PKHeX.WinForms this.MT_LP = new System.Windows.Forms.MaskedTextBox(); this.B_MaxLP = new System.Windows.Forms.Button(); this.L_LP = new System.Windows.Forms.Label(); + this.trainerID1 = new PKHeX.WinForms.Controls.TrainerID(); this.Tab_MiscValues = new System.Windows.Forms.TabPage(); + this.B_UnlockBikeUpgrades = new System.Windows.Forms.Button(); this.B_UnlockTMRecipes = new System.Windows.Forms.Button(); this.B_CollectAllStakes = new System.Windows.Forms.Button(); this.B_UnlockFlyLocations = new System.Windows.Forms.Button(); @@ -105,8 +107,6 @@ namespace PKHeX.WinForms this.L_Y = new System.Windows.Forms.Label(); this.L_Z = new System.Windows.Forms.Label(); this.L_X = new System.Windows.Forms.Label(); - this.trainerID1 = new PKHeX.WinForms.Controls.TrainerID(); - this.B_UnlockBikeUpgrades = new System.Windows.Forms.Button(); this.TC_Editor.SuspendLayout(); this.Tab_Overview.SuspendLayout(); this.Tab_MiscValues.SuspendLayout(); @@ -119,9 +119,10 @@ namespace PKHeX.WinForms // B_Cancel // this.B_Cancel.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right))); - this.B_Cancel.Location = new System.Drawing.Point(294, 331); + this.B_Cancel.Location = new System.Drawing.Point(277, 300); + this.B_Cancel.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3); this.B_Cancel.Name = "B_Cancel"; - this.B_Cancel.Size = new System.Drawing.Size(75, 23); + this.B_Cancel.Size = new System.Drawing.Size(88, 27); this.B_Cancel.TabIndex = 0; this.B_Cancel.Text = "Cancel"; this.B_Cancel.UseVisualStyleBackColor = true; @@ -130,9 +131,10 @@ namespace PKHeX.WinForms // B_Save // this.B_Save.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right))); - this.B_Save.Location = new System.Drawing.Point(375, 331); + this.B_Save.Location = new System.Drawing.Point(372, 300); + this.B_Save.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3); this.B_Save.Name = "B_Save"; - this.B_Save.Size = new System.Drawing.Size(75, 23); + this.B_Save.Size = new System.Drawing.Size(88, 27); this.B_Save.TabIndex = 1; this.B_Save.Text = "Save"; this.B_Save.UseVisualStyleBackColor = true; @@ -140,11 +142,12 @@ namespace PKHeX.WinForms // // TB_OTName // - this.TB_OTName.Font = new System.Drawing.Font("Courier New", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); - this.TB_OTName.Location = new System.Drawing.Point(99, 7); + this.TB_OTName.Font = new System.Drawing.Font("Courier New", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); + this.TB_OTName.Location = new System.Drawing.Point(112, 10); + this.TB_OTName.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3); this.TB_OTName.MaxLength = 12; this.TB_OTName.Name = "TB_OTName"; - this.TB_OTName.Size = new System.Drawing.Size(93, 20); + this.TB_OTName.Size = new System.Drawing.Size(108, 20); this.TB_OTName.TabIndex = 2; this.TB_OTName.Text = "WWWWWWWWWWWW"; this.TB_OTName.TextAlign = System.Windows.Forms.HorizontalAlignment.Center; @@ -152,28 +155,32 @@ namespace PKHeX.WinForms // // L_TrainerName // - this.L_TrainerName.Location = new System.Drawing.Point(7, 9); + this.L_TrainerName.Location = new System.Drawing.Point(8, 8); + this.L_TrainerName.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); this.L_TrainerName.Name = "L_TrainerName"; - this.L_TrainerName.Size = new System.Drawing.Size(87, 16); + this.L_TrainerName.Size = new System.Drawing.Size(104, 24); this.L_TrainerName.TabIndex = 3; this.L_TrainerName.Text = "Trainer Name:"; this.L_TrainerName.TextAlign = System.Drawing.ContentAlignment.MiddleRight; // // MT_Money // - this.MT_Money.Location = new System.Drawing.Point(119, 29); + this.MT_Money.Location = new System.Drawing.Point(112, 64); + this.MT_Money.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3); this.MT_Money.Mask = "0000000"; this.MT_Money.Name = "MT_Money"; - this.MT_Money.Size = new System.Drawing.Size(52, 20); + this.MT_Money.Size = new System.Drawing.Size(56, 23); this.MT_Money.TabIndex = 4; + this.MT_Money.Text = "1234567"; this.MT_Money.TextAlign = System.Windows.Forms.HorizontalAlignment.Center; // // L_Money // this.L_Money.AutoSize = true; - this.L_Money.Location = new System.Drawing.Point(102, 32); + this.L_Money.Location = new System.Drawing.Point(92, 70); + this.L_Money.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); this.L_Money.Name = "L_Money"; - this.L_Money.Size = new System.Drawing.Size(16, 13); + this.L_Money.Size = new System.Drawing.Size(16, 15); this.L_Money.TabIndex = 5; this.L_Money.Text = "$:"; // @@ -216,107 +223,115 @@ namespace PKHeX.WinForms // this.TB_Saying5.Location = new System.Drawing.Point(0, 0); this.TB_Saying5.Name = "TB_Saying5"; - this.TB_Saying5.Size = new System.Drawing.Size(100, 20); + this.TB_Saying5.Size = new System.Drawing.Size(100, 23); this.TB_Saying5.TabIndex = 0; // // TB_Saying4 // this.TB_Saying4.Location = new System.Drawing.Point(0, 0); this.TB_Saying4.Name = "TB_Saying4"; - this.TB_Saying4.Size = new System.Drawing.Size(100, 20); + this.TB_Saying4.Size = new System.Drawing.Size(100, 23); this.TB_Saying4.TabIndex = 0; // // TB_Saying3 // this.TB_Saying3.Location = new System.Drawing.Point(0, 0); this.TB_Saying3.Name = "TB_Saying3"; - this.TB_Saying3.Size = new System.Drawing.Size(100, 20); + this.TB_Saying3.Size = new System.Drawing.Size(100, 23); this.TB_Saying3.TabIndex = 0; // // TB_Saying2 // this.TB_Saying2.Location = new System.Drawing.Point(0, 0); this.TB_Saying2.Name = "TB_Saying2"; - this.TB_Saying2.Size = new System.Drawing.Size(100, 20); + this.TB_Saying2.Size = new System.Drawing.Size(100, 23); this.TB_Saying2.TabIndex = 0; // // TB_Saying1 // this.TB_Saying1.Location = new System.Drawing.Point(0, 0); this.TB_Saying1.Name = "TB_Saying1"; - this.TB_Saying1.Size = new System.Drawing.Size(100, 20); + this.TB_Saying1.Size = new System.Drawing.Size(100, 23); this.TB_Saying1.TabIndex = 0; // // L_Seconds // - this.L_Seconds.AutoSize = true; - this.L_Seconds.Location = new System.Drawing.Point(147, 141); + this.L_Seconds.Location = new System.Drawing.Point(233, 172); + this.L_Seconds.Margin = new System.Windows.Forms.Padding(0); this.L_Seconds.Name = "L_Seconds"; - this.L_Seconds.Size = new System.Drawing.Size(29, 13); + this.L_Seconds.Size = new System.Drawing.Size(40, 24); this.L_Seconds.TabIndex = 30; this.L_Seconds.Text = "Sec:"; + this.L_Seconds.TextAlign = System.Drawing.ContentAlignment.MiddleRight; // // L_Minutes // - this.L_Minutes.AutoSize = true; - this.L_Minutes.Location = new System.Drawing.Point(95, 141); + this.L_Minutes.Location = new System.Drawing.Point(161, 172); + this.L_Minutes.Margin = new System.Windows.Forms.Padding(0); this.L_Minutes.Name = "L_Minutes"; - this.L_Minutes.Size = new System.Drawing.Size(27, 13); + this.L_Minutes.Size = new System.Drawing.Size(40, 24); this.L_Minutes.TabIndex = 29; this.L_Minutes.Text = "Min:"; + this.L_Minutes.TextAlign = System.Drawing.ContentAlignment.MiddleRight; // // MT_Seconds // - this.MT_Seconds.Location = new System.Drawing.Point(177, 138); + this.MT_Seconds.Location = new System.Drawing.Point(273, 172); + this.MT_Seconds.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3); this.MT_Seconds.Mask = "00"; this.MT_Seconds.Name = "MT_Seconds"; - this.MT_Seconds.Size = new System.Drawing.Size(22, 20); + this.MT_Seconds.Size = new System.Drawing.Size(25, 23); this.MT_Seconds.TabIndex = 28; this.MT_Seconds.TextAlign = System.Windows.Forms.HorizontalAlignment.Center; this.MT_Seconds.TextChanged += new System.EventHandler(this.Change255); // // MT_Minutes // - this.MT_Minutes.Location = new System.Drawing.Point(122, 138); + this.MT_Minutes.Location = new System.Drawing.Point(201, 172); + this.MT_Minutes.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3); this.MT_Minutes.Mask = "00"; this.MT_Minutes.Name = "MT_Minutes"; - this.MT_Minutes.Size = new System.Drawing.Size(22, 20); + this.MT_Minutes.Size = new System.Drawing.Size(25, 23); this.MT_Minutes.TabIndex = 27; this.MT_Minutes.TextAlign = System.Windows.Forms.HorizontalAlignment.Center; this.MT_Minutes.TextChanged += new System.EventHandler(this.Change255); // // L_Hours // - this.L_Hours.AutoSize = true; - this.L_Hours.Location = new System.Drawing.Point(23, 141); + this.L_Hours.Location = new System.Drawing.Point(72, 172); + this.L_Hours.Margin = new System.Windows.Forms.Padding(0); this.L_Hours.Name = "L_Hours"; - this.L_Hours.Size = new System.Drawing.Size(26, 13); + this.L_Hours.Size = new System.Drawing.Size(40, 24); this.L_Hours.TabIndex = 26; this.L_Hours.Text = "Hrs:"; + this.L_Hours.TextAlign = System.Drawing.ContentAlignment.MiddleRight; // // MT_Hours // - this.MT_Hours.Location = new System.Drawing.Point(55, 138); + this.MT_Hours.Location = new System.Drawing.Point(112, 172); + this.MT_Hours.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3); this.MT_Hours.Mask = "00000"; this.MT_Hours.Name = "MT_Hours"; - this.MT_Hours.Size = new System.Drawing.Size(38, 20); + this.MT_Hours.Size = new System.Drawing.Size(44, 23); this.MT_Hours.TabIndex = 25; this.MT_Hours.TextAlign = System.Windows.Forms.HorizontalAlignment.Center; // // L_Language // - this.L_Language.Location = new System.Drawing.Point(-7, 107); + this.L_Language.Location = new System.Drawing.Point(8, 144); + this.L_Language.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); this.L_Language.Name = "L_Language"; - this.L_Language.Size = new System.Drawing.Size(100, 13); + this.L_Language.Size = new System.Drawing.Size(104, 24); this.L_Language.TabIndex = 21; this.L_Language.Text = "Language:"; this.L_Language.TextAlign = System.Drawing.ContentAlignment.MiddleRight; // // B_MaxCash // - this.B_MaxCash.Location = new System.Drawing.Point(172, 29); + this.B_MaxCash.Location = new System.Drawing.Point(172, 64); + this.B_MaxCash.Margin = new System.Windows.Forms.Padding(0); this.B_MaxCash.Name = "B_MaxCash"; - this.B_MaxCash.Size = new System.Drawing.Size(20, 20); + this.B_MaxCash.Size = new System.Drawing.Size(23, 23); this.B_MaxCash.TabIndex = 16; this.B_MaxCash.Text = "+"; this.B_MaxCash.UseVisualStyleBackColor = true; @@ -325,9 +340,10 @@ namespace PKHeX.WinForms // this.CB_Language.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; this.CB_Language.FormattingEnabled = true; - this.CB_Language.Location = new System.Drawing.Point(99, 104); + this.CB_Language.Location = new System.Drawing.Point(112, 144); + this.CB_Language.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3); this.CB_Language.Name = "CB_Language"; - this.CB_Language.Size = new System.Drawing.Size(93, 21); + this.CB_Language.Size = new System.Drawing.Size(108, 23); this.CB_Language.TabIndex = 15; // // CB_Game @@ -337,9 +353,10 @@ namespace PKHeX.WinForms this.CB_Game.Items.AddRange(new object[] { "Scarlet", "Violet"}); - this.CB_Game.Location = new System.Drawing.Point(141, 77); + this.CB_Game.Location = new System.Drawing.Point(161, 120); + this.CB_Game.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3); this.CB_Game.Name = "CB_Game"; - this.CB_Game.Size = new System.Drawing.Size(89, 21); + this.CB_Game.Size = new System.Drawing.Size(103, 23); this.CB_Game.TabIndex = 24; // // CB_Gender @@ -349,79 +366,80 @@ namespace PKHeX.WinForms this.CB_Gender.Items.AddRange(new object[] { "♂", "♀"}); - this.CB_Gender.Location = new System.Drawing.Point(99, 77); + this.CB_Gender.Location = new System.Drawing.Point(112, 120); + this.CB_Gender.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3); this.CB_Gender.Name = "CB_Gender"; - this.CB_Gender.Size = new System.Drawing.Size(40, 21); + this.CB_Gender.Size = new System.Drawing.Size(46, 23); this.CB_Gender.TabIndex = 22; // // TB_MBMS // this.TB_MBMS.Location = new System.Drawing.Point(0, 0); this.TB_MBMS.Name = "TB_MBMS"; - this.TB_MBMS.Size = new System.Drawing.Size(100, 20); + this.TB_MBMS.Size = new System.Drawing.Size(100, 23); this.TB_MBMS.TabIndex = 0; // // TB_MBMN // this.TB_MBMN.Location = new System.Drawing.Point(0, 0); this.TB_MBMN.Name = "TB_MBMN"; - this.TB_MBMN.Size = new System.Drawing.Size(100, 20); + this.TB_MBMN.Size = new System.Drawing.Size(100, 23); this.TB_MBMN.TabIndex = 0; // // TB_MBRS // this.TB_MBRS.Location = new System.Drawing.Point(0, 0); this.TB_MBRS.Name = "TB_MBRS"; - this.TB_MBRS.Size = new System.Drawing.Size(100, 20); + this.TB_MBRS.Size = new System.Drawing.Size(100, 23); this.TB_MBRS.TabIndex = 0; // // TB_MBRN // this.TB_MBRN.Location = new System.Drawing.Point(0, 0); this.TB_MBRN.Name = "TB_MBRN"; - this.TB_MBRN.Size = new System.Drawing.Size(100, 20); + this.TB_MBRN.Size = new System.Drawing.Size(100, 23); this.TB_MBRN.TabIndex = 0; // // TB_MBTS // this.TB_MBTS.Location = new System.Drawing.Point(0, 0); this.TB_MBTS.Name = "TB_MBTS"; - this.TB_MBTS.Size = new System.Drawing.Size(100, 20); + this.TB_MBTS.Size = new System.Drawing.Size(100, 23); this.TB_MBTS.TabIndex = 0; // // TB_MBTN // this.TB_MBTN.Location = new System.Drawing.Point(0, 0); this.TB_MBTN.Name = "TB_MBTN"; - this.TB_MBTN.Size = new System.Drawing.Size(100, 20); + this.TB_MBTN.Size = new System.Drawing.Size(100, 23); this.TB_MBTN.TabIndex = 0; // // TB_MBDS // this.TB_MBDS.Location = new System.Drawing.Point(0, 0); this.TB_MBDS.Name = "TB_MBDS"; - this.TB_MBDS.Size = new System.Drawing.Size(100, 20); + this.TB_MBDS.Size = new System.Drawing.Size(100, 23); this.TB_MBDS.TabIndex = 0; // // TB_MBDN // this.TB_MBDN.Location = new System.Drawing.Point(0, 0); this.TB_MBDN.Name = "TB_MBDN"; - this.TB_MBDN.Size = new System.Drawing.Size(100, 20); + this.TB_MBDN.Size = new System.Drawing.Size(100, 23); this.TB_MBDN.TabIndex = 0; // // TB_MBSS // this.TB_MBSS.Location = new System.Drawing.Point(0, 0); this.TB_MBSS.Name = "TB_MBSS"; - this.TB_MBSS.Size = new System.Drawing.Size(100, 20); + this.TB_MBSS.Size = new System.Drawing.Size(100, 23); this.TB_MBSS.TabIndex = 0; // // TB_MBSN // this.TB_MBSN.Location = new System.Drawing.Point(0, 0); this.TB_MBSN.Name = "TB_MBSN"; - this.TB_MBSN.Size = new System.Drawing.Size(100, 20); + this.TB_MBSN.Size = new System.Drawing.Size(100, 23); this.TB_MBSN.TabIndex = 0; // // L_SuperB @@ -477,70 +495,70 @@ namespace PKHeX.WinForms // this.TB_MCMS.Location = new System.Drawing.Point(0, 0); this.TB_MCMS.Name = "TB_MCMS"; - this.TB_MCMS.Size = new System.Drawing.Size(100, 20); + this.TB_MCMS.Size = new System.Drawing.Size(100, 23); this.TB_MCMS.TabIndex = 0; // // TB_MCMN // this.TB_MCMN.Location = new System.Drawing.Point(0, 0); this.TB_MCMN.Name = "TB_MCMN"; - this.TB_MCMN.Size = new System.Drawing.Size(100, 20); + this.TB_MCMN.Size = new System.Drawing.Size(100, 23); this.TB_MCMN.TabIndex = 0; // // TB_MCRS // this.TB_MCRS.Location = new System.Drawing.Point(0, 0); this.TB_MCRS.Name = "TB_MCRS"; - this.TB_MCRS.Size = new System.Drawing.Size(100, 20); + this.TB_MCRS.Size = new System.Drawing.Size(100, 23); this.TB_MCRS.TabIndex = 0; // // TB_MCRN // this.TB_MCRN.Location = new System.Drawing.Point(0, 0); this.TB_MCRN.Name = "TB_MCRN"; - this.TB_MCRN.Size = new System.Drawing.Size(100, 20); + this.TB_MCRN.Size = new System.Drawing.Size(100, 23); this.TB_MCRN.TabIndex = 0; // // TB_MCTS // this.TB_MCTS.Location = new System.Drawing.Point(0, 0); this.TB_MCTS.Name = "TB_MCTS"; - this.TB_MCTS.Size = new System.Drawing.Size(100, 20); + this.TB_MCTS.Size = new System.Drawing.Size(100, 23); this.TB_MCTS.TabIndex = 0; // // TB_MCTN // this.TB_MCTN.Location = new System.Drawing.Point(0, 0); this.TB_MCTN.Name = "TB_MCTN"; - this.TB_MCTN.Size = new System.Drawing.Size(100, 20); + this.TB_MCTN.Size = new System.Drawing.Size(100, 23); this.TB_MCTN.TabIndex = 0; // // TB_MCDS // this.TB_MCDS.Location = new System.Drawing.Point(0, 0); this.TB_MCDS.Name = "TB_MCDS"; - this.TB_MCDS.Size = new System.Drawing.Size(100, 20); + this.TB_MCDS.Size = new System.Drawing.Size(100, 23); this.TB_MCDS.TabIndex = 0; // // TB_MCDN // this.TB_MCDN.Location = new System.Drawing.Point(0, 0); this.TB_MCDN.Name = "TB_MCDN"; - this.TB_MCDN.Size = new System.Drawing.Size(100, 20); + this.TB_MCDN.Size = new System.Drawing.Size(100, 23); this.TB_MCDN.TabIndex = 0; // // TB_MCSS // this.TB_MCSS.Location = new System.Drawing.Point(0, 0); this.TB_MCSS.Name = "TB_MCSS"; - this.TB_MCSS.Size = new System.Drawing.Size(100, 20); + this.TB_MCSS.Size = new System.Drawing.Size(100, 23); this.TB_MCSS.TabIndex = 0; // // TB_MCSN // this.TB_MCSN.Location = new System.Drawing.Point(0, 0); this.TB_MCSN.Name = "TB_MCSN"; - this.TB_MCSN.Size = new System.Drawing.Size(100, 20); + this.TB_MCSN.Size = new System.Drawing.Size(100, 23); this.TB_MCSN.TabIndex = 0; // // L_SuperC @@ -599,10 +617,11 @@ namespace PKHeX.WinForms | System.Windows.Forms.AnchorStyles.Right))); this.TC_Editor.Controls.Add(this.Tab_Overview); this.TC_Editor.Controls.Add(this.Tab_MiscValues); - this.TC_Editor.Location = new System.Drawing.Point(12, 12); + this.TC_Editor.Location = new System.Drawing.Point(14, 14); + this.TC_Editor.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3); this.TC_Editor.Name = "TC_Editor"; this.TC_Editor.SelectedIndex = 0; - this.TC_Editor.Size = new System.Drawing.Size(438, 313); + this.TC_Editor.Size = new System.Drawing.Size(445, 279); this.TC_Editor.TabIndex = 54; // // Tab_Overview @@ -626,41 +645,53 @@ namespace PKHeX.WinForms this.Tab_Overview.Controls.Add(this.L_Language); this.Tab_Overview.Controls.Add(this.CB_Language); this.Tab_Overview.Controls.Add(this.B_MaxCash); - this.Tab_Overview.Location = new System.Drawing.Point(4, 22); + this.Tab_Overview.Location = new System.Drawing.Point(4, 24); + this.Tab_Overview.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3); this.Tab_Overview.Name = "Tab_Overview"; - this.Tab_Overview.Padding = new System.Windows.Forms.Padding(3); - this.Tab_Overview.Size = new System.Drawing.Size(430, 287); + this.Tab_Overview.Padding = new System.Windows.Forms.Padding(4, 3, 4, 3); + this.Tab_Overview.Size = new System.Drawing.Size(437, 251); this.Tab_Overview.TabIndex = 0; this.Tab_Overview.Text = "Overview"; this.Tab_Overview.UseVisualStyleBackColor = true; // // MT_LP // - this.MT_LP.Location = new System.Drawing.Point(119, 51); + this.MT_LP.Location = new System.Drawing.Point(112, 92); + this.MT_LP.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3); this.MT_LP.Mask = "0000000"; this.MT_LP.Name = "MT_LP"; - this.MT_LP.Size = new System.Drawing.Size(52, 20); + this.MT_LP.Size = new System.Drawing.Size(56, 23); this.MT_LP.TabIndex = 70; this.MT_LP.TextAlign = System.Windows.Forms.HorizontalAlignment.Center; // // B_MaxLP // - this.B_MaxLP.Location = new System.Drawing.Point(172, 51); + this.B_MaxLP.Location = new System.Drawing.Point(172, 92); + this.B_MaxLP.Margin = new System.Windows.Forms.Padding(0); this.B_MaxLP.Name = "B_MaxLP"; - this.B_MaxLP.Size = new System.Drawing.Size(20, 20); + this.B_MaxLP.Size = new System.Drawing.Size(23, 23); this.B_MaxLP.TabIndex = 71; this.B_MaxLP.Text = "+"; this.B_MaxLP.UseVisualStyleBackColor = true; // // L_LP // - this.L_LP.Location = new System.Drawing.Point(82, 50); + this.L_LP.Location = new System.Drawing.Point(69, 91); + this.L_LP.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); this.L_LP.Name = "L_LP"; - this.L_LP.Size = new System.Drawing.Size(32, 20); + this.L_LP.Size = new System.Drawing.Size(37, 23); this.L_LP.TabIndex = 68; this.L_LP.Text = "LP:"; this.L_LP.TextAlign = System.Drawing.ContentAlignment.MiddleRight; // + // trainerID1 + // + this.trainerID1.Location = new System.Drawing.Point(32, 32); + this.trainerID1.Margin = new System.Windows.Forms.Padding(0); + this.trainerID1.Name = "trainerID1"; + this.trainerID1.Size = new System.Drawing.Size(246, 23); + this.trainerID1.TabIndex = 66; + // // Tab_MiscValues // this.Tab_MiscValues.Controls.Add(this.B_UnlockBikeUpgrades); @@ -668,19 +699,32 @@ namespace PKHeX.WinForms this.Tab_MiscValues.Controls.Add(this.B_CollectAllStakes); this.Tab_MiscValues.Controls.Add(this.B_UnlockFlyLocations); this.Tab_MiscValues.Controls.Add(this.GB_Map); - this.Tab_MiscValues.Location = new System.Drawing.Point(4, 22); + this.Tab_MiscValues.Location = new System.Drawing.Point(4, 24); + this.Tab_MiscValues.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3); this.Tab_MiscValues.Name = "Tab_MiscValues"; - this.Tab_MiscValues.Padding = new System.Windows.Forms.Padding(3); - this.Tab_MiscValues.Size = new System.Drawing.Size(430, 287); + this.Tab_MiscValues.Padding = new System.Windows.Forms.Padding(4, 3, 4, 3); + this.Tab_MiscValues.Size = new System.Drawing.Size(437, 251); this.Tab_MiscValues.TabIndex = 4; this.Tab_MiscValues.Text = "Misc"; this.Tab_MiscValues.UseVisualStyleBackColor = true; // + // B_UnlockBikeUpgrades + // + this.B_UnlockBikeUpgrades.Location = new System.Drawing.Point(264, 192); + this.B_UnlockBikeUpgrades.Margin = new System.Windows.Forms.Padding(0); + this.B_UnlockBikeUpgrades.Name = "B_UnlockBikeUpgrades"; + this.B_UnlockBikeUpgrades.Size = new System.Drawing.Size(160, 48); + this.B_UnlockBikeUpgrades.TabIndex = 63; + this.B_UnlockBikeUpgrades.Text = "Unlock All Bike Upgrades"; + this.B_UnlockBikeUpgrades.UseVisualStyleBackColor = true; + this.B_UnlockBikeUpgrades.Click += new System.EventHandler(this.B_UnlockBikeUpgrades_Click); + // // B_UnlockTMRecipes // - this.B_UnlockTMRecipes.Location = new System.Drawing.Point(248, 116); + this.B_UnlockTMRecipes.Location = new System.Drawing.Point(264, 136); + this.B_UnlockTMRecipes.Margin = new System.Windows.Forms.Padding(0); this.B_UnlockTMRecipes.Name = "B_UnlockTMRecipes"; - this.B_UnlockTMRecipes.Size = new System.Drawing.Size(120, 42); + this.B_UnlockTMRecipes.Size = new System.Drawing.Size(160, 48); this.B_UnlockTMRecipes.TabIndex = 62; this.B_UnlockTMRecipes.Text = "Unlock All TM Recipes"; this.B_UnlockTMRecipes.UseVisualStyleBackColor = true; @@ -688,9 +732,10 @@ namespace PKHeX.WinForms // // B_CollectAllStakes // - this.B_CollectAllStakes.Location = new System.Drawing.Point(248, 68); + this.B_CollectAllStakes.Location = new System.Drawing.Point(264, 80); + this.B_CollectAllStakes.Margin = new System.Windows.Forms.Padding(0); this.B_CollectAllStakes.Name = "B_CollectAllStakes"; - this.B_CollectAllStakes.Size = new System.Drawing.Size(120, 42); + this.B_CollectAllStakes.Size = new System.Drawing.Size(160, 48); this.B_CollectAllStakes.TabIndex = 61; this.B_CollectAllStakes.Text = "Collect All Stakes"; this.B_CollectAllStakes.UseVisualStyleBackColor = true; @@ -698,9 +743,10 @@ namespace PKHeX.WinForms // // B_UnlockFlyLocations // - this.B_UnlockFlyLocations.Location = new System.Drawing.Point(248, 20); + this.B_UnlockFlyLocations.Location = new System.Drawing.Point(264, 24); + this.B_UnlockFlyLocations.Margin = new System.Windows.Forms.Padding(0); this.B_UnlockFlyLocations.Name = "B_UnlockFlyLocations"; - this.B_UnlockFlyLocations.Size = new System.Drawing.Size(120, 42); + this.B_UnlockFlyLocations.Size = new System.Drawing.Size(160, 48); this.B_UnlockFlyLocations.TabIndex = 60; this.B_UnlockFlyLocations.Text = "Unlock All Fly Locations"; this.B_UnlockFlyLocations.UseVisualStyleBackColor = true; @@ -714,9 +760,11 @@ namespace PKHeX.WinForms this.GB_Map.Controls.Add(this.L_Y); this.GB_Map.Controls.Add(this.L_Z); this.GB_Map.Controls.Add(this.L_X); - this.GB_Map.Location = new System.Drawing.Point(6, 6); + this.GB_Map.Location = new System.Drawing.Point(7, 7); + this.GB_Map.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3); this.GB_Map.Name = "GB_Map"; - this.GB_Map.Size = new System.Drawing.Size(203, 156); + this.GB_Map.Padding = new System.Windows.Forms.Padding(4, 3, 4, 3); + this.GB_Map.Size = new System.Drawing.Size(232, 96); this.GB_Map.TabIndex = 59; this.GB_Map.TabStop = false; this.GB_Map.Text = "Map Position"; @@ -726,7 +774,8 @@ namespace PKHeX.WinForms this.NUD_Z.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) | System.Windows.Forms.AnchorStyles.Right))); this.NUD_Z.DecimalPlaces = 5; - this.NUD_Z.Location = new System.Drawing.Point(93, 68); + this.NUD_Z.Location = new System.Drawing.Point(108, 40); + this.NUD_Z.Margin = new System.Windows.Forms.Padding(0); this.NUD_Z.Maximum = new decimal(new int[] { 99999999, 0, @@ -738,7 +787,7 @@ namespace PKHeX.WinForms 0, -2147483648}); this.NUD_Z.Name = "NUD_Z"; - this.NUD_Z.Size = new System.Drawing.Size(96, 20); + this.NUD_Z.Size = new System.Drawing.Size(112, 23); this.NUD_Z.TabIndex = 53; this.NUD_Z.ValueChanged += new System.EventHandler(this.ChangeMapValue); // @@ -747,7 +796,8 @@ namespace PKHeX.WinForms this.NUD_Y.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) | System.Windows.Forms.AnchorStyles.Right))); this.NUD_Y.DecimalPlaces = 5; - this.NUD_Y.Location = new System.Drawing.Point(93, 94); + this.NUD_Y.Location = new System.Drawing.Point(108, 64); + this.NUD_Y.Margin = new System.Windows.Forms.Padding(0); this.NUD_Y.Maximum = new decimal(new int[] { 99999999, 0, @@ -759,7 +809,7 @@ namespace PKHeX.WinForms 0, -2147483648}); this.NUD_Y.Name = "NUD_Y"; - this.NUD_Y.Size = new System.Drawing.Size(96, 20); + this.NUD_Y.Size = new System.Drawing.Size(112, 23); this.NUD_Y.TabIndex = 51; this.NUD_Y.ValueChanged += new System.EventHandler(this.ChangeMapValue); // @@ -768,7 +818,8 @@ namespace PKHeX.WinForms this.NUD_X.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) | System.Windows.Forms.AnchorStyles.Right))); this.NUD_X.DecimalPlaces = 5; - this.NUD_X.Location = new System.Drawing.Point(93, 42); + this.NUD_X.Location = new System.Drawing.Point(108, 16); + this.NUD_X.Margin = new System.Windows.Forms.Padding(0); this.NUD_X.Maximum = new decimal(new int[] { 99999999, 0, @@ -780,64 +831,51 @@ namespace PKHeX.WinForms 0, -2147483648}); this.NUD_X.Name = "NUD_X"; - this.NUD_X.Size = new System.Drawing.Size(96, 20); + this.NUD_X.Size = new System.Drawing.Size(112, 23); this.NUD_X.TabIndex = 50; this.NUD_X.ValueChanged += new System.EventHandler(this.ChangeMapValue); // // L_Y // - this.L_Y.Location = new System.Drawing.Point(6, 94); + this.L_Y.Location = new System.Drawing.Point(8, 64); + this.L_Y.Margin = new System.Windows.Forms.Padding(0); this.L_Y.Name = "L_Y"; - this.L_Y.Size = new System.Drawing.Size(80, 20); + this.L_Y.Size = new System.Drawing.Size(96, 23); this.L_Y.TabIndex = 49; this.L_Y.Text = "Y Coordinate:"; this.L_Y.TextAlign = System.Drawing.ContentAlignment.MiddleRight; // // L_Z // - this.L_Z.Location = new System.Drawing.Point(6, 68); + this.L_Z.Location = new System.Drawing.Point(8, 40); + this.L_Z.Margin = new System.Windows.Forms.Padding(0); this.L_Z.Name = "L_Z"; - this.L_Z.Size = new System.Drawing.Size(80, 20); + this.L_Z.Size = new System.Drawing.Size(96, 23); this.L_Z.TabIndex = 48; this.L_Z.Text = "Z Coordinate:"; this.L_Z.TextAlign = System.Drawing.ContentAlignment.MiddleRight; // // L_X // - this.L_X.Location = new System.Drawing.Point(6, 42); + this.L_X.Location = new System.Drawing.Point(8, 16); + this.L_X.Margin = new System.Windows.Forms.Padding(0); this.L_X.Name = "L_X"; - this.L_X.Size = new System.Drawing.Size(80, 20); + this.L_X.Size = new System.Drawing.Size(96, 23); this.L_X.TabIndex = 47; this.L_X.Text = "X Coordinate:"; this.L_X.TextAlign = System.Drawing.ContentAlignment.MiddleRight; // - // trainerID1 - // - this.trainerID1.Location = new System.Drawing.Point(6, 26); - this.trainerID1.Name = "trainerID1"; - this.trainerID1.Size = new System.Drawing.Size(90, 74); - this.trainerID1.TabIndex = 66; - // - // B_UnlockBikeUpgrades - // - this.B_UnlockBikeUpgrades.Location = new System.Drawing.Point(248, 164); - this.B_UnlockBikeUpgrades.Name = "B_UnlockBikeUpgrades"; - this.B_UnlockBikeUpgrades.Size = new System.Drawing.Size(120, 42); - this.B_UnlockBikeUpgrades.TabIndex = 63; - this.B_UnlockBikeUpgrades.Text = "Unlock All Bike Upgrades"; - this.B_UnlockBikeUpgrades.UseVisualStyleBackColor = true; - this.B_UnlockBikeUpgrades.Click += new System.EventHandler(this.B_UnlockBikeUpgrades_Click); - // // SAV_Trainer9 // - this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); + this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 15F); this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; - this.ClientSize = new System.Drawing.Size(458, 363); + this.ClientSize = new System.Drawing.Size(468, 337); this.Controls.Add(this.TC_Editor); this.Controls.Add(this.B_Save); this.Controls.Add(this.B_Cancel); this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle; this.Icon = global::PKHeX.WinForms.Properties.Resources.Icon; + this.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3); this.MaximizeBox = false; this.MinimizeBox = false; this.Name = "SAV_Trainer9"; diff --git a/PKHeX.WinForms/Subforms/Save Editors/Gen9/SAV_Trainer9.cs b/PKHeX.WinForms/Subforms/Save Editors/Gen9/SAV_Trainer9.cs index 3f954dc53..0698771c2 100644 --- a/PKHeX.WinForms/Subforms/Save Editors/Gen9/SAV_Trainer9.cs +++ b/PKHeX.WinForms/Subforms/Save Editors/Gen9/SAV_Trainer9.cs @@ -70,7 +70,7 @@ public partial class SAV_Trainer9 : Form // Display Data TB_OTName.Text = SAV.OT; - trainerID1.LoadIDValues(SAV); + trainerID1.LoadIDValues(SAV, SAV.Generation); MT_Money.Text = SAV.Money.ToString(); MT_LP.Text = SAV.LeaguePoints.ToString(); CB_Language.SelectedValue = SAV.Language; diff --git a/PKHeX.WinForms/Subforms/Save Editors/SAV_EventFlags.cs b/PKHeX.WinForms/Subforms/Save Editors/SAV_EventFlags.cs index 81ae77341..77702fa59 100644 --- a/PKHeX.WinForms/Subforms/Save Editors/SAV_EventFlags.cs +++ b/PKHeX.WinForms/Subforms/Save Editors/SAV_EventFlags.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using System.Drawing; using System.Linq; @@ -180,8 +180,9 @@ public sealed partial class SAV_EventFlags : Form Width = 150, DropDownStyle = ComboBoxStyle.DropDownList, BindingContext = BindingContext, - DropDownWidth = Width + 100, }; + var font = cb.Font; + cb.DropDownWidth = entry.PredefinedValues.Max(z => TextRenderer.MeasureText(z.Name, font).Width); cb.InitializeBinding(); cb.DataSource = map; diff --git a/PKHeX.WinForms/Subforms/Save Editors/SAV_MailBox.cs b/PKHeX.WinForms/Subforms/Save Editors/SAV_MailBox.cs index 79a37f60c..ebe8e2884 100644 --- a/PKHeX.WinForms/Subforms/Save Editors/SAV_MailBox.cs +++ b/PKHeX.WinForms/Subforms/Save Editors/SAV_MailBox.cs @@ -288,7 +288,7 @@ public partial class SAV_MailBox : Form } if (Gen == 3) { - mail.AppearPKM = SpeciesConverter.GetG3Species(species); + mail.AppearPKM = SpeciesConverter.GetInternal3(species); return; } @@ -529,7 +529,7 @@ public partial class SAV_MailBox : Form } if (Gen == 3) { - AppearPKMs[0].SelectedValue = (int)SpeciesConverter.GetG4Species(species); + AppearPKMs[0].SelectedValue = (int)SpeciesConverter.GetNational3(species); editing = false; return; } diff --git a/PKHeX.WinForms/Subforms/Save Editors/SAV_SimpleTrainer.Designer.cs b/PKHeX.WinForms/Subforms/Save Editors/SAV_SimpleTrainer.Designer.cs index dfe74a9de..b8651ba0d 100644 --- a/PKHeX.WinForms/Subforms/Save Editors/SAV_SimpleTrainer.Designer.cs +++ b/PKHeX.WinForms/Subforms/Save Editors/SAV_SimpleTrainer.Designer.cs @@ -329,7 +329,7 @@ this.L_TID.Name = "L_TID"; this.L_TID.Size = new System.Drawing.Size(38, 13); this.L_TID.TabIndex = 61; - this.L_TID.Text = "TID:"; + this.L_TID.Text = "TID16:"; this.L_TID.TextAlign = System.Drawing.ContentAlignment.MiddleRight; // // MT_Money @@ -347,7 +347,7 @@ this.L_SID.Name = "L_SID"; this.L_SID.Size = new System.Drawing.Size(38, 13); this.L_SID.TabIndex = 62; - this.L_SID.Text = "SID:"; + this.L_SID.Text = "SID16:"; this.L_SID.TextAlign = System.Drawing.ContentAlignment.MiddleRight; // // L_Money diff --git a/PKHeX.WinForms/Subforms/Save Editors/SAV_SimpleTrainer.cs b/PKHeX.WinForms/Subforms/Save Editors/SAV_SimpleTrainer.cs index 496ce1303..24862c9a5 100644 --- a/PKHeX.WinForms/Subforms/Save Editors/SAV_SimpleTrainer.cs +++ b/PKHeX.WinForms/Subforms/Save Editors/SAV_SimpleTrainer.cs @@ -35,8 +35,8 @@ public partial class SAV_SimpleTrainer : Form TB_OTName.Text = SAV.OT; CB_Gender.SelectedIndex = SAV.Gender; - MT_TID.Text = SAV.TID.ToString("00000"); - MT_SID.Text = SAV.SID.ToString("00000"); + MT_TID.Text = SAV.TID16.ToString("00000"); + MT_SID.Text = SAV.SID16.ToString("00000"); MT_Money.Text = SAV.Money.ToString(); MT_Hours.Text = SAV.PlayedHours.ToString(); MT_Minutes.Text = SAV.PlayedMinutes.ToString(); @@ -188,8 +188,8 @@ public partial class SAV_SimpleTrainer : Form SAV.OT = TB_OTName.Text; SAV.Gender = (byte)CB_Gender.SelectedIndex; - SAV.TID = (ushort)Util.ToUInt32(MT_TID.Text); - SAV.SID = (ushort)Util.ToUInt32(MT_SID.Text); + SAV.TID16 = (ushort)Util.ToUInt32(MT_TID.Text); + SAV.SID16 = (ushort)Util.ToUInt32(MT_SID.Text); SAV.Money = Util.ToUInt32(MT_Money.Text); SAV.PlayedHours = ushort.Parse(MT_Hours.Text); diff --git a/PKHeX.WinForms/Util/DevUtil.cs b/PKHeX.WinForms/Util/DevUtil.cs index 67e197a02..7143e814c 100644 --- a/PKHeX.WinForms/Util/DevUtil.cs +++ b/PKHeX.WinForms/Util/DevUtil.cs @@ -76,9 +76,7 @@ namespace PKHeX.WinForms var loc = Path.Combine(dir, fn); if (File.Exists(loc)) File.Delete(loc); - File.Move(f, loc); - // if net framework support is ever removed, use the new overload instead of the stuff above: - // File.Move(f, loc, true); + File.Move(f, loc, true); } Application.Exit(); diff --git a/PKHeX.WinForms/Util/WinFormsTranslator.cs b/PKHeX.WinForms/Util/WinFormsTranslator.cs index e29b937c0..45749af74 100644 --- a/PKHeX.WinForms/Util/WinFormsTranslator.cs +++ b/PKHeX.WinForms/Util/WinFormsTranslator.cs @@ -1,3 +1,4 @@ +using System; using System.Collections.Generic; using System.IO; using System.Linq; @@ -76,7 +77,7 @@ public static class WinFormsTranslator } } - private static IEnumerable GetTranslationFile(string lang) + private static ReadOnlySpan GetTranslationFile(string lang) { var file = GetTranslationFileNameInternal(lang); // Check to see if a the translation file exists in the same folder as the executable @@ -173,17 +174,16 @@ public static class WinFormsTranslator public static void DumpAll(params string[] banlist) { - foreach (var c in Context) + foreach (var (lang, value) in Context) { - var lang = c.Key; var fn = GetTranslationFileNameExternal(lang); - var lines = c.Value.Write(); + var lines = value.Write(); var result = lines.Where(z => !banlist.Any(z.Contains)); File.WriteAllLines(fn, result); } } - public static void LoadAllForms(IEnumerable types, params string[] banlist) + public static void LoadAllForms(IEnumerable types, params string[] banlist) { types = types.Where(t => t.BaseType == typeof(Form) && !banlist.Contains(t.Name)); foreach (var t in types) @@ -194,7 +194,7 @@ public static class WinFormsTranslator var argCount = constructors[0].GetParameters().Length; try { - var _ = (Form?)System.Activator.CreateInstance(t, new object[argCount]); + var _ = (Form?)Activator.CreateInstance(t, new object[argCount]); } // This is a debug utility method, will always be logging. Shouldn't ever fail. catch @@ -266,11 +266,20 @@ public sealed class TranslationContext private readonly Dictionary Translation = new(); public IReadOnlyDictionary Lookup => Translation; - public TranslationContext(IEnumerable content, char separator = Separator) + public TranslationContext(ReadOnlySpan content, char separator = Separator) { - var entries = content.Select(z => z.Split(separator)).Where(z => z.Length == 2); - foreach (var kvp in entries.Where(z => !Translation.ContainsKey(z[0]))) - Translation.Add(kvp[0], kvp[1]); + foreach (var line in content) + LoadLine(line, separator); + } + + private void LoadLine(ReadOnlySpan line, char separator = Separator) + { + var split = line.IndexOf(separator); + if (split < 0) + return; // ignore + var key = line[..split].ToString(); + var value = line[(split + 1)..].ToString(); + Translation.TryAdd(key, value); } public string? GetTranslatedText(string val, string? fallback) diff --git a/PKHeX.WinForms/Util/WinFormsUtil.cs b/PKHeX.WinForms/Util/WinFormsUtil.cs index f8f388e7e..ecc3a63d2 100644 --- a/PKHeX.WinForms/Util/WinFormsUtil.cs +++ b/PKHeX.WinForms/Util/WinFormsUtil.cs @@ -4,7 +4,6 @@ using System.Collections.Generic; using System.Drawing; using System.IO; using System.Linq; -using System.Reflection; using System.Runtime.InteropServices; using System.Windows.Forms; @@ -64,11 +63,11 @@ public static class WinFormsUtil { case T p: return p; - case ToolStripItem t: - sender = t.Owner; + case ToolStripItem { Owner: { } o}: + sender = o; continue; - case ContextMenuStrip c: - sender = c.SourceControl; + case ContextMenuStrip { SourceControl: { } s }: + sender = s; continue; default: return default; @@ -177,15 +176,6 @@ public static class WinFormsUtil static int Clamp(int value, ScrollProperties prop) => Math.Max(prop.Minimum, Math.Min(prop.Maximum, value)); } - public static void DoubleBuffered(this DataGridView dgv, bool setting) - { - Type dgvType = dgv.GetType(); - var pi = dgvType.GetProperty("DoubleBuffered", BindingFlags.Instance | BindingFlags.NonPublic); - if (pi == null) - throw new Exception(nameof(dgv)); - pi.SetValue(dgv, setting, null); - } - /// /// Initializes the to be bound to a provided list. /// diff --git a/PKHeX.sln b/PKHeX.sln index 74f7a5f18..3512dbc5e 100644 --- a/PKHeX.sln +++ b/PKHeX.sln @@ -27,59 +27,33 @@ EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU - Debug|x86 = Debug|x86 Release|Any CPU = Release|Any CPU - Release|x86 = Release|x86 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution {D1B91861-A448-4762-A313-C7BC179F4415}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {D1B91861-A448-4762-A313-C7BC179F4415}.Debug|Any CPU.Build.0 = Debug|Any CPU - {D1B91861-A448-4762-A313-C7BC179F4415}.Debug|x86.ActiveCfg = Debug|Any CPU - {D1B91861-A448-4762-A313-C7BC179F4415}.Debug|x86.Build.0 = Debug|Any CPU {D1B91861-A448-4762-A313-C7BC179F4415}.Release|Any CPU.ActiveCfg = Release|Any CPU {D1B91861-A448-4762-A313-C7BC179F4415}.Release|Any CPU.Build.0 = Release|Any CPU - {D1B91861-A448-4762-A313-C7BC179F4415}.Release|x86.ActiveCfg = Release|Any CPU - {D1B91861-A448-4762-A313-C7BC179F4415}.Release|x86.Build.0 = Release|Any CPU {279E59F2-50EA-475D-8BA4-FA69F0578C0D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {279E59F2-50EA-475D-8BA4-FA69F0578C0D}.Debug|Any CPU.Build.0 = Debug|Any CPU - {279E59F2-50EA-475D-8BA4-FA69F0578C0D}.Debug|x86.ActiveCfg = Debug|Any CPU - {279E59F2-50EA-475D-8BA4-FA69F0578C0D}.Debug|x86.Build.0 = Debug|Any CPU {279E59F2-50EA-475D-8BA4-FA69F0578C0D}.Release|Any CPU.ActiveCfg = Release|Any CPU {279E59F2-50EA-475D-8BA4-FA69F0578C0D}.Release|Any CPU.Build.0 = Release|Any CPU - {279E59F2-50EA-475D-8BA4-FA69F0578C0D}.Release|x86.ActiveCfg = Release|Any CPU - {279E59F2-50EA-475D-8BA4-FA69F0578C0D}.Release|x86.Build.0 = Release|Any CPU {C3B5B74F-ACE8-4FB2-A917-0DEDBFD5703B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {C3B5B74F-ACE8-4FB2-A917-0DEDBFD5703B}.Debug|Any CPU.Build.0 = Debug|Any CPU - {C3B5B74F-ACE8-4FB2-A917-0DEDBFD5703B}.Debug|x86.ActiveCfg = Debug|Any CPU - {C3B5B74F-ACE8-4FB2-A917-0DEDBFD5703B}.Debug|x86.Build.0 = Debug|Any CPU {C3B5B74F-ACE8-4FB2-A917-0DEDBFD5703B}.Release|Any CPU.ActiveCfg = Release|Any CPU {C3B5B74F-ACE8-4FB2-A917-0DEDBFD5703B}.Release|Any CPU.Build.0 = Release|Any CPU - {C3B5B74F-ACE8-4FB2-A917-0DEDBFD5703B}.Release|x86.ActiveCfg = Release|Any CPU - {C3B5B74F-ACE8-4FB2-A917-0DEDBFD5703B}.Release|x86.Build.0 = Release|Any CPU {87976C6C-3E91-42DE-B098-1E97E42C9588}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {87976C6C-3E91-42DE-B098-1E97E42C9588}.Debug|Any CPU.Build.0 = Debug|Any CPU - {87976C6C-3E91-42DE-B098-1E97E42C9588}.Debug|x86.ActiveCfg = Debug|Any CPU - {87976C6C-3E91-42DE-B098-1E97E42C9588}.Debug|x86.Build.0 = Debug|Any CPU {87976C6C-3E91-42DE-B098-1E97E42C9588}.Release|Any CPU.ActiveCfg = Release|Any CPU {87976C6C-3E91-42DE-B098-1E97E42C9588}.Release|Any CPU.Build.0 = Release|Any CPU - {87976C6C-3E91-42DE-B098-1E97E42C9588}.Release|x86.ActiveCfg = Release|Any CPU - {87976C6C-3E91-42DE-B098-1E97E42C9588}.Release|x86.Build.0 = Release|Any CPU {990D2FB5-5F3B-44CA-8D13-A2EC99756941}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {990D2FB5-5F3B-44CA-8D13-A2EC99756941}.Debug|Any CPU.Build.0 = Debug|Any CPU - {990D2FB5-5F3B-44CA-8D13-A2EC99756941}.Debug|x86.ActiveCfg = Debug|Any CPU - {990D2FB5-5F3B-44CA-8D13-A2EC99756941}.Debug|x86.Build.0 = Debug|Any CPU {990D2FB5-5F3B-44CA-8D13-A2EC99756941}.Release|Any CPU.ActiveCfg = Release|Any CPU {990D2FB5-5F3B-44CA-8D13-A2EC99756941}.Release|Any CPU.Build.0 = Release|Any CPU - {990D2FB5-5F3B-44CA-8D13-A2EC99756941}.Release|x86.ActiveCfg = Release|Any CPU - {990D2FB5-5F3B-44CA-8D13-A2EC99756941}.Release|x86.Build.0 = Release|Any CPU {BBBCAF7F-1487-46C5-8BD7-1E276AA1891E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {BBBCAF7F-1487-46C5-8BD7-1E276AA1891E}.Debug|Any CPU.Build.0 = Debug|Any CPU - {BBBCAF7F-1487-46C5-8BD7-1E276AA1891E}.Debug|x86.ActiveCfg = Debug|Any CPU - {BBBCAF7F-1487-46C5-8BD7-1E276AA1891E}.Debug|x86.Build.0 = Debug|Any CPU {BBBCAF7F-1487-46C5-8BD7-1E276AA1891E}.Release|Any CPU.ActiveCfg = Release|Any CPU {BBBCAF7F-1487-46C5-8BD7-1E276AA1891E}.Release|Any CPU.Build.0 = Release|Any CPU - {BBBCAF7F-1487-46C5-8BD7-1E276AA1891E}.Release|x86.ActiveCfg = Release|Any CPU - {BBBCAF7F-1487-46C5-8BD7-1E276AA1891E}.Release|x86.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/README.md b/README.md index 6e22c2d36..cdda6a162 100644 --- a/README.md +++ b/README.md @@ -32,9 +32,9 @@ PKHeX expects save files that are not encrypted with console-specific keys. Use ## Building -PKHeX is a Windows Forms application which requires [.NET Framework v4.6](https://www.microsoft.com/en-us/download/details.aspx?id=48137), with experimental support for [.NET 6.0](https://dotnet.microsoft.com/download/dotnet/6.0). +PKHeX is a Windows Forms application which requires [.NET 7.0](https://dotnet.microsoft.com/download/dotnet/7.0). -The executable can be built with any compiler that supports C# 10. +The executable can be built with any compiler that supports C# 11. ### Build Configurations @@ -51,7 +51,3 @@ PKHeX's Pokémon Legends: Arceus sprite collection is taken from the [National P ### IDE PKHeX can be opened with IDEs such as [Visual Studio](https://visualstudio.microsoft.com/downloads/) by opening the .sln or .csproj file. - -### GNU/Linux - -GNU/Linux is not the main Operating System of developers of this program so there may be bugs; some may come from non GNU/Linux specific code of Mono/Wine, so other users may not be able to reproduce the error you are experiencing. diff --git a/Tests/PKHeX.Core.Tests/General/GeneralTests.cs b/Tests/PKHeX.Core.Tests/General/GeneralTests.cs index d5465ed18..fcee8dcd1 100644 --- a/Tests/PKHeX.Core.Tests/General/GeneralTests.cs +++ b/Tests/PKHeX.Core.Tests/General/GeneralTests.cs @@ -1,8 +1,7 @@ using FluentAssertions; -using PKHeX.Core; using Xunit; -namespace PKHeX.Tests.General; +namespace PKHeX.Core.Tests.General; public class GeneralTests { diff --git a/Tests/PKHeX.Core.Tests/General/MarshalTests.cs b/Tests/PKHeX.Core.Tests/General/MarshalTests.cs index bf3b90dda..3b620169a 100644 --- a/Tests/PKHeX.Core.Tests/General/MarshalTests.cs +++ b/Tests/PKHeX.Core.Tests/General/MarshalTests.cs @@ -1,21 +1,23 @@ +using System; using System.Runtime.InteropServices; using FluentAssertions; -using PKHeX.Core; using Xunit; -namespace PKHeX.Tests.General; +namespace PKHeX.Core.Tests.General; public class MarshalTests { - [Fact] - public void MarshalSize() - { - Marshal.SizeOf(typeof(NPCLock)).Should().Be(8); - Marshal.SizeOf(typeof(PIDIV)).Should().Be(8); - Marshal.SizeOf(typeof(MoveResult)).Should().Be(8); - Marshal.SizeOf(typeof(EvolutionMethod)).Should().Be(8); - Marshal.SizeOf(typeof(Moveset)).Should().Be(8); - Marshal.SizeOf(typeof(IndividualValueSet)).Should().BeLessOrEqualTo(8); - Marshal.SizeOf(typeof(GenerateParam9)).Should().BeLessOrEqualTo(16); - } + [Theory] + [InlineData(8, typeof(PIDIV))] + [InlineData(8, typeof(MoveResult))] + [InlineData(8, typeof(EvolutionMethod))] + [InlineData(8, typeof(Moveset))] + public void MarshalSizeExact(int expect, Type t) => Marshal.SizeOf(t).Should().Be(expect); + + [Theory] + [InlineData( 8, typeof(NPCLock))] + [InlineData( 8, typeof(IndividualValueSet))] + [InlineData(16, typeof(GenerateParam9))] + [InlineData(16, typeof(DreamWorldEntry))] + public void MarshalSizeLessThanEqual(int expect, Type t) => Marshal.SizeOf(t).Should().BeLessOrEqualTo(expect); } diff --git a/Tests/PKHeX.Core.Tests/General/XorShiftTests.cs b/Tests/PKHeX.Core.Tests/General/XorShiftTests.cs index 272e05ce1..47a50ffd0 100644 --- a/Tests/PKHeX.Core.Tests/General/XorShiftTests.cs +++ b/Tests/PKHeX.Core.Tests/General/XorShiftTests.cs @@ -1,8 +1,7 @@ -using FluentAssertions; -using PKHeX.Core; +using FluentAssertions; using Xunit; -namespace PKHeX.Tests; +namespace PKHeX.Core.Tests; public static class XorShiftTests { diff --git a/Tests/PKHeX.Core.Tests/General/Xoroshiro128Tests.cs b/Tests/PKHeX.Core.Tests/General/Xoroshiro128Tests.cs index a58192c7e..81fd546bd 100644 --- a/Tests/PKHeX.Core.Tests/General/Xoroshiro128Tests.cs +++ b/Tests/PKHeX.Core.Tests/General/Xoroshiro128Tests.cs @@ -1,8 +1,8 @@ -using FluentAssertions; -using PKHeX.Core; +using System; +using FluentAssertions; using Xunit; -namespace PKHeX.Tests; +namespace PKHeX.Core.Tests; public static class Xoroshiro128Tests { @@ -36,11 +36,12 @@ public static class Xoroshiro128Tests private static int GetFramesForward(ulong s0, ulong s1, ulong n0, ulong n1, int loop) { + var state = new UInt128(n1, n0); var rand = new Xoroshiro128Plus(s0, s1); for (int i = 0; i < loop; i++) { _ = rand.Next(); - if (rand.GetState() == (n0, n1)) + if (rand.FullState() == state) return i; } return -1; diff --git a/Tests/PKHeX.Core.Tests/General/Xoroshiro128bTests.cs b/Tests/PKHeX.Core.Tests/General/Xoroshiro128bTests.cs index 24fa8aeda..b3dd5cd79 100644 --- a/Tests/PKHeX.Core.Tests/General/Xoroshiro128bTests.cs +++ b/Tests/PKHeX.Core.Tests/General/Xoroshiro128bTests.cs @@ -1,8 +1,7 @@ -using FluentAssertions; -using PKHeX.Core; +using FluentAssertions; using Xunit; -namespace PKHeX.Tests; +namespace PKHeX.Core.Tests; public static class Xoroshiro128bTests { diff --git a/Tests/PKHeX.Core.Tests/Legality/BreedTests.cs b/Tests/PKHeX.Core.Tests/Legality/BreedTests.cs index 00946c06c..c4a76f29c 100644 --- a/Tests/PKHeX.Core.Tests/Legality/BreedTests.cs +++ b/Tests/PKHeX.Core.Tests/Legality/BreedTests.cs @@ -1,13 +1,12 @@ using System; using System.Linq; using FluentAssertions; -using PKHeX.Core; using Xunit; using static PKHeX.Core.Move; using static PKHeX.Core.Species; using static PKHeX.Core.GameVersion; -namespace PKHeX.Tests.Legality; +namespace PKHeX.Core.Tests.Legality; public class BreedTests { diff --git a/Tests/PKHeX.Core.Tests/Legality/LearnabilityTests.cs b/Tests/PKHeX.Core.Tests/Legality/LearnabilityTests.cs index 6cf5bd950..56ae41794 100644 --- a/Tests/PKHeX.Core.Tests/Legality/LearnabilityTests.cs +++ b/Tests/PKHeX.Core.Tests/Legality/LearnabilityTests.cs @@ -1,9 +1,8 @@ using System.Linq; using FluentAssertions; -using PKHeX.Core; using Xunit; -namespace PKHeX.Tests.Legality; +namespace PKHeX.Core.Tests.Legality; public static class LearnabilityTests { diff --git a/Tests/PKHeX.Core.Tests/Legality/LegalityData.cs b/Tests/PKHeX.Core.Tests/Legality/LegalityData.cs index c05ea341d..72b217f02 100644 --- a/Tests/PKHeX.Core.Tests/Legality/LegalityData.cs +++ b/Tests/PKHeX.Core.Tests/Legality/LegalityData.cs @@ -3,10 +3,9 @@ using System.Collections.Generic; using System.Linq; using System.Reflection; using FluentAssertions; -using PKHeX.Core; using Xunit; -namespace PKHeX.Tests.Legality; +namespace PKHeX.Core.Tests.Legality; public class LegalityData { diff --git a/Tests/PKHeX.Core.Tests/Legality/LegalityRules.cs b/Tests/PKHeX.Core.Tests/Legality/LegalityRules.cs index f4482d973..9f9214374 100644 --- a/Tests/PKHeX.Core.Tests/Legality/LegalityRules.cs +++ b/Tests/PKHeX.Core.Tests/Legality/LegalityRules.cs @@ -1,8 +1,7 @@ -using FluentAssertions; -using PKHeX.Core; +using FluentAssertions; using Xunit; -namespace PKHeX.Tests.Legality; +namespace PKHeX.Core.Tests.Legality; public class LegalityRules { diff --git a/Tests/PKHeX.Core.Tests/Legality/LegalityTests.cs b/Tests/PKHeX.Core.Tests/Legality/LegalityTests.cs index adddd3c97..4b103a159 100644 --- a/Tests/PKHeX.Core.Tests/Legality/LegalityTests.cs +++ b/Tests/PKHeX.Core.Tests/Legality/LegalityTests.cs @@ -1,12 +1,11 @@ using System; using System.Collections.Generic; using FluentAssertions; -using PKHeX.Core; using System.IO; using System.Linq; using Xunit; -namespace PKHeX.Tests.Legality; +namespace PKHeX.Core.Tests.Legality; public class LegalityTest { @@ -34,9 +33,10 @@ public class LegalityTest [InlineData("censor")] [InlineData("buttnugget")] [InlineData("18넘")] - public void CensorsBadWords(string badword) + [InlineData("inoffensive", false)] + public void CensorsBadWords(string badword, bool value = true) { - WordFilter.IsFiltered(badword, out _).Should().BeTrue("the word should have been identified as a bad word"); + WordFilter.TryMatch(badword, out _).Should().Be(value, "the word should have been identified as a bad word"); } [Theory] diff --git a/Tests/PKHeX.Core.Tests/Legality/RaidTests.cs b/Tests/PKHeX.Core.Tests/Legality/RaidTests.cs index b755cb0e5..54ac94f69 100644 --- a/Tests/PKHeX.Core.Tests/Legality/RaidTests.cs +++ b/Tests/PKHeX.Core.Tests/Legality/RaidTests.cs @@ -1,9 +1,8 @@ -using System; +using System; using FluentAssertions; -using PKHeX.Core; using Xunit; -namespace PKHeX.Tests.Legality; +namespace PKHeX.Core.Tests.Legality; public class RaidTests { diff --git a/Tests/PKHeX.Core.Tests/Legality/ShadowTests.cs b/Tests/PKHeX.Core.Tests/Legality/ShadowTests.cs index 5d3b0d428..d0da851cd 100644 --- a/Tests/PKHeX.Core.Tests/Legality/ShadowTests.cs +++ b/Tests/PKHeX.Core.Tests/Legality/ShadowTests.cs @@ -1,12 +1,11 @@ using System; using System.Collections.Generic; using FluentAssertions; -using PKHeX.Core; using Xunit; using static PKHeX.Core.Encounters3XDTeams; using static PKHeX.Core.Encounters3ColoTeams; -namespace PKHeX.Tests.Legality.Shadow; +namespace PKHeX.Core.Tests.Legality.Shadow; public static class ValidityTests { @@ -179,7 +178,7 @@ public static class PIDTests } } - public static readonly uint[] MawileTeamPIDs = + private static readonly uint[] MawileTeamPIDs = { 0x4C3005E8, // Loudred 0xD28DE40E, // Girafarig (re - rolled 64 times to next viable match) @@ -192,13 +191,13 @@ public static class PIDTests VerifyResultsAntiShiny(MawileTeamPIDs, Mawile, 12345, 51882, stackalloc[] {31, 30, 29, 31, 23, 27}); } - private static void VerifyResultsAntiShiny(ReadOnlySpan resultPIDs, TeamLock[] team, int tid, int sid, ReadOnlySpan ivs) + private static void VerifyResultsAntiShiny(ReadOnlySpan resultPIDs, TeamLock[] team, ushort tid, ushort sid, ReadOnlySpan ivs) { var pk3 = new PK3 { PID = resultPIDs[^1], - TID = tid, - SID = sid, + TID16 = tid, + SID16 = sid, }; pk3.SetIVs(ivs); diff --git a/Tests/PKHeX.Core.Tests/Legality/Wild8aRNGTests.cs b/Tests/PKHeX.Core.Tests/Legality/Wild8aRNGTests.cs index 9e5bf8454..6fe491247 100644 --- a/Tests/PKHeX.Core.Tests/Legality/Wild8aRNGTests.cs +++ b/Tests/PKHeX.Core.Tests/Legality/Wild8aRNGTests.cs @@ -1,4 +1,4 @@ -using FluentAssertions; +using FluentAssertions; using Xunit; namespace PKHeX.Core.Tests.Legality; diff --git a/Tests/PKHeX.Core.Tests/Legality/Wild8bRNGTests.cs b/Tests/PKHeX.Core.Tests/Legality/Wild8bRNGTests.cs index fce592024..c83fa7bbe 100644 --- a/Tests/PKHeX.Core.Tests/Legality/Wild8bRNGTests.cs +++ b/Tests/PKHeX.Core.Tests/Legality/Wild8bRNGTests.cs @@ -1,4 +1,4 @@ -using FluentAssertions; +using FluentAssertions; using Xunit; namespace PKHeX.Core.Tests.Legality; diff --git a/Tests/PKHeX.Core.Tests/PKHeX.Core.Tests.csproj b/Tests/PKHeX.Core.Tests/PKHeX.Core.Tests.csproj index 40c102f4d..e8f3b6e61 100644 --- a/Tests/PKHeX.Core.Tests/PKHeX.Core.Tests.csproj +++ b/Tests/PKHeX.Core.Tests/PKHeX.Core.Tests.csproj @@ -1,16 +1,13 @@ - + - net6.0 - 10 - enable - + net7.0 false - + all diff --git a/Tests/PKHeX.Core.Tests/PKM/AbilityPermissionTests.cs b/Tests/PKHeX.Core.Tests/PKM/AbilityPermissionTests.cs index 193afa6c5..795808d85 100644 --- a/Tests/PKHeX.Core.Tests/PKM/AbilityPermissionTests.cs +++ b/Tests/PKHeX.Core.Tests/PKM/AbilityPermissionTests.cs @@ -1,8 +1,7 @@ -using FluentAssertions; -using PKHeX.Core; +using FluentAssertions; using Xunit; -namespace PKHeX.Tests.PKM; +namespace PKHeX.Core.Tests.PKM; public static class AbilityPermissionTests { diff --git a/Tests/PKHeX.Core.Tests/PKM/BatchInstructionTests.cs b/Tests/PKHeX.Core.Tests/PKM/BatchInstructionTests.cs new file mode 100644 index 000000000..bf785f908 --- /dev/null +++ b/Tests/PKHeX.Core.Tests/PKM/BatchInstructionTests.cs @@ -0,0 +1,37 @@ +using FluentAssertions; +using Xunit; +namespace PKHeX.Core.Tests; + +public class BatchInstructionTests +{ + private const string TestInstructions = """ + =Species=4 + .Form=0 + .Nickname=Hello + """; + + [Theory] + [InlineData(TestInstructions)] + public void ParseCount(string lines) + { + var len = StringInstructionSet.GetInstructionSetLength(lines); + len.Should().Be(lines.Length); + lines += "\n;\n.Species=0"; + var extra = StringInstructionSet.GetInstructionSetLength(lines); + (len + 1).Should().Be(extra); + } + + [Theory] + [InlineData('=')] + [InlineData('!')] + [InlineData('>')] + [InlineData('<')] + [InlineData('≥')] + [InlineData('≤')] + [InlineData('f', false)] + public void ParseComparer(char c, bool expect = true) + { + var comparer = StringInstruction.GetComparer(c); + comparer.IsSupportedComparer().Should().Be(expect); + } +} diff --git a/Tests/PKHeX.Core.Tests/PKM/HiddenPowerTests.cs b/Tests/PKHeX.Core.Tests/PKM/HiddenPowerTests.cs index bc1945b20..36f259b6f 100644 --- a/Tests/PKHeX.Core.Tests/PKM/HiddenPowerTests.cs +++ b/Tests/PKHeX.Core.Tests/PKM/HiddenPowerTests.cs @@ -1,9 +1,8 @@ -using System; +using System; using FluentAssertions; -using PKHeX.Core; using Xunit; -namespace PKHeX.Tests.PKM; +namespace PKHeX.Core.Tests.PKM; public class HiddenPowerTests { diff --git a/Tests/PKHeX.Core.Tests/PKM/PIDIVTests.cs b/Tests/PKHeX.Core.Tests/PKM/PIDIVTests.cs index c3ab16040..69d3d3762 100644 --- a/Tests/PKHeX.Core.Tests/PKM/PIDIVTests.cs +++ b/Tests/PKHeX.Core.Tests/PKM/PIDIVTests.cs @@ -1,10 +1,9 @@ using System; using System.Linq; using FluentAssertions; -using PKHeX.Core; using Xunit; -namespace PKHeX.Tests.PKM; +namespace PKHeX.Core.Tests.PKM; public class PIDIVTest { @@ -71,7 +70,7 @@ public class PIDIVTest public void PIDIVMatchingTest3MiscChannel() { // Channel Jirachi - var pkC = new PK3 {PID = 0x264750D9, IVs = new[] {06, 31, 14, 27, 05, 27}, SID = 45819, OT_Gender = 1, Version = (int)GameVersion.R}; + var pkC = new PK3 {PID = 0x264750D9, IVs = new[] {06, 31, 14, 27, 05, 27}, SID16 = 45819, OT_Gender = 1, Version = (int)GameVersion.R}; var (type, seed) = MethodFinder.Analyze(pkC); Assert.Equal(PIDType.Channel,type); @@ -84,35 +83,35 @@ public class PIDIVTest [Fact] public void PIDIVMatchingTest3Event() { - // Restricted: TID/SID are zero. + // Restricted: TID16/SID16 are zero. var pkR = new PK3 {PID = 0x0000E97E, IVs = new[] {17, 19, 20, 16, 13, 12}}; Assert.Equal(PIDType.BACD_R, MethodFinder.Analyze(pkR).Type); // Restricted Antishiny: PID is incremented 2 times to lose shininess. - var pkRA = new PK3 {PID = 0x0000E980, IVs = new[] {17, 19, 20, 16, 13, 12}, TID = 01337, SID = 60486}; + var pkRA = new PK3 {PID = 0x0000E980, IVs = new[] {17, 19, 20, 16, 13, 12}, TID16 = 01337, SID16 = 60486}; Assert.Equal(PIDType.BACD_R_A, MethodFinder.Analyze(pkRA).Type); - // Unrestricted: TID/SID are zero. + // Unrestricted: TID16/SID16 are zero. var pkU = new PK3 {PID = 0x67DBFC33, IVs = new[] {12, 25, 27, 30, 02, 31}}; Assert.Equal(PIDType.BACD_U, MethodFinder.Analyze(pkU).Type); // Unrestricted Antishiny: PID is incremented 5 times to lose shininess. - var pkUA = new PK3 {PID = 0x67DBFC38, IVs = new[] {12, 25, 27, 30, 02, 31}, TID = 01337, SID = 40657}; + var pkUA = new PK3 {PID = 0x67DBFC38, IVs = new[] {12, 25, 27, 30, 02, 31}, TID16 = 01337, SID16 = 40657}; Assert.Equal(PIDType.BACD_U_A, MethodFinder.Analyze(pkUA).Type); // berry fix zigzagoon: seed 0x0020 - var pkRS = new PK3 {PID = 0x38CA4EA0, IVs = new[] {00, 20, 28, 11, 19, 00}, TID = 30317, SID = 00000}; + var pkRS = new PK3 {PID = 0x38CA4EA0, IVs = new[] {00, 20, 28, 11, 19, 00}, TID16 = 30317, SID16 = 00000}; var a_pkRS = MethodFinder.Analyze(pkRS); Assert.Equal(PIDType.BACD_R_S, a_pkRS.Type); Assert.True(a_pkRS.OriginSeed == 0x0020, "Unable to match PID to BACD-R shiny spread origin seed"); - var gkRS = new PK3 { TID = 30317, SID = 00000 }; + var gkRS = new PK3 { TID16 = 30317, SID16 = 00000 }; PIDGenerator.SetValuesFromSeed(gkRS, PIDType.BACD_R_S, a_pkRS.OriginSeed); Assert.Equal(pkRS.PID, gkRS.PID); Assert.True(pkRS.IVs.SequenceEqual(gkRS.IVs), "Unable to match generated IVs to BACD-R shiny spread"); // Unrestricted Antishiny nyx - var nyxUA = new PK3 {PID = 0xBD3DF676, IVs = new[] {00, 15, 05, 04, 21, 05}, TID = 80, SID = 0}; + var nyxUA = new PK3 {PID = 0xBD3DF676, IVs = new[] {00, 15, 05, 04, 21, 05}, TID16 = 80, SID16 = 0}; var nyx_pkUA = MethodFinder.Analyze(nyxUA); Assert.Equal(PIDType.BACD_U_AX, nyx_pkUA.Type); } @@ -124,11 +123,11 @@ public class PIDIVTest var pkCC = new PK4 {PID = 0x00000037, IVs = new[] {16, 13, 12, 02, 18, 03}, Species = 1, Gender = 0}; Assert.Equal(PIDType.CuteCharm, MethodFinder.Analyze(pkCC).Type); - // Antishiny Mystery Gift: TID/SID are zero. Original PID of 0x5271E97E is rerolled. + // Antishiny Mystery Gift: TID16/SID16 are zero. Original PID of 0x5271E97E is rerolled. var pkASR = new PK4 {PID = 0x07578CB7, IVs = new[] {16, 13, 12, 02, 18, 03}}; Assert.Equal(PIDType.G4MGAntiShiny, MethodFinder.Analyze(pkASR).Type); - // Chain Shiny: TID/SID are zero. + // Chain Shiny: TID16/SID16 are zero. var pkCS = new PK4 {PID = 0xA9C1A9C6, IVs = new[] {22, 14, 23, 24, 11, 04}}; Assert.Equal(PIDType.ChainShiny, MethodFinder.Analyze(pkCS).Type); } @@ -137,7 +136,7 @@ public class PIDIVTest public void PIDIVMatchingTest5() { // Shiny Mystery Gift PGF; IVs are unrelated. - var pkS5 = new PK5 {PID = 0xBEEF0037, TID = 01337, SID = 48097}; + var pkS5 = new PK5 {PID = 0xBEEF0037, TID16 = 01337, SID16 = 48097}; Assert.Equal(PIDType.G5MGShiny, MethodFinder.Analyze(pkS5).Type); } @@ -158,16 +157,16 @@ public class PIDIVTest { var pkPW = new[] { - new PK4 { Species = 025, PID = 0x34000089, TID = 20790, SID = 39664, Gender = 0}, // Pikachu - new PK4 { Species = 025, PID = 0x7DFFFF60, TID = 30859, SID = 63760, Gender = 1}, // Pikachu - new PK4 { Species = 025, PID = 0x7DFFFF65, TID = 30859, SID = 63760, Gender = 1}, // Pikachu - new PK4 { Species = 025, PID = 0x7E000003, TID = 30859, SID = 63760, Gender = 1}, // Pikachu + new PK4 { Species = 025, PID = 0x34000089, TID16 = 20790, SID16 = 39664, Gender = 0}, // Pikachu + new PK4 { Species = 025, PID = 0x7DFFFF60, TID16 = 30859, SID16 = 63760, Gender = 1}, // Pikachu + new PK4 { Species = 025, PID = 0x7DFFFF65, TID16 = 30859, SID16 = 63760, Gender = 1}, // Pikachu + new PK4 { Species = 025, PID = 0x7E000003, TID16 = 30859, SID16 = 63760, Gender = 1}, // Pikachu - new PK4 { Species = 025, PID = 0x2100008F, TID = 31526, SID = 42406, Gender = 0}, // Pikachu - new PK4 { Species = 025, PID = 0x71FFFF5A, TID = 49017, SID = 12807, Gender = 1}, // Pikachu - new PK4 { Species = 025, PID = 0xC0000001, TID = 17398, SID = 31936, Gender = 1}, // Pikachu - new PK4 { Species = 025, PID = 0x2FFFFF5E, TID = 27008, SID = 42726, Gender = 1}, // Pikachu - new PK4 { Species = 025, PID = 0x59FFFFFE, TID = 51223, SID = 28044, Gender = 0}, // Pikachu + new PK4 { Species = 025, PID = 0x2100008F, TID16 = 31526, SID16 = 42406, Gender = 0}, // Pikachu + new PK4 { Species = 025, PID = 0x71FFFF5A, TID16 = 49017, SID16 = 12807, Gender = 1}, // Pikachu + new PK4 { Species = 025, PID = 0xC0000001, TID16 = 17398, SID16 = 31936, Gender = 1}, // Pikachu + new PK4 { Species = 025, PID = 0x2FFFFF5E, TID16 = 27008, SID16 = 42726, Gender = 1}, // Pikachu + new PK4 { Species = 025, PID = 0x59FFFFFE, TID16 = 51223, SID16 = 28044, Gender = 0}, // Pikachu }; foreach (var pk in pkPW) Assert.Equal(PIDType.Pokewalker, MethodFinder.Analyze(pk).Type); diff --git a/Tests/PKHeX.Core.Tests/PKM/PKMTests.cs b/Tests/PKHeX.Core.Tests/PKM/PKMTests.cs index b03d46bd1..3e018b4ff 100644 --- a/Tests/PKHeX.Core.Tests/PKM/PKMTests.cs +++ b/Tests/PKHeX.Core.Tests/PKM/PKMTests.cs @@ -1,9 +1,8 @@ -using System; +using System; using FluentAssertions; -using PKHeX.Core; using Xunit; -namespace PKHeX.Tests.PKM; +namespace PKHeX.Core.Tests.PKM; public class MetDateTests { @@ -30,7 +29,7 @@ public class MetDateTests Met_Year = 16, }; - pk.MetDate.GetValueOrDefault().Should().Be(new DateTime(2016, 8, 10).Date); + pk.MetDate.GetValueOrDefault().Should().Be(new DateOnly(2016, 8, 10)); } [Fact] @@ -43,7 +42,7 @@ public class MetDateTests Met_Year = 0, }; - pk.MetDate.GetValueOrDefault().Date.Year.Should().Be(2000); + pk.MetDate.GetValueOrDefault().Year.Should().Be(2000); } [Fact] @@ -81,7 +80,7 @@ public class MetDateTests pk.Met_Month.Should().Be(12); pk.Met_Year.Should().Be(12); - pk.MetDate = new DateTime(2005, 5, 5); + pk.MetDate = new DateOnly(2005, 5, 5); pk.Met_Day.Should().Be(5); pk.Met_Month.Should().Be(5); @@ -114,7 +113,7 @@ public class EggMetDateTests Egg_Year = 16, }; - pk.EggMetDate.GetValueOrDefault().Should().Be(new DateTime(2016, 8, 10).Date); + pk.EggMetDate.GetValueOrDefault().Should().Be(new DateOnly(2016, 8, 10)); } [Fact] @@ -127,7 +126,7 @@ public class EggMetDateTests Egg_Year = 0, }; - pk.EggMetDate.GetValueOrDefault().Date.Year.Should().Be(2000); + pk.EggMetDate.GetValueOrDefault().Year.Should().Be(2000); } [Fact] @@ -165,7 +164,7 @@ public class EggMetDateTests pk.Egg_Month.Should().Be(12); pk.Egg_Year.Should().Be(12); - pk.EggMetDate = new DateTime(2005, 5, 5); + pk.EggMetDate = new DateOnly(2005, 5, 5); pk.Egg_Day.Should().Be(5); pk.Egg_Month.Should().Be(5); diff --git a/Tests/PKHeX.Core.Tests/PKM/SpeciesConverterTests.cs b/Tests/PKHeX.Core.Tests/PKM/SpeciesConverterTests.cs new file mode 100644 index 000000000..95ad32fa6 --- /dev/null +++ b/Tests/PKHeX.Core.Tests/PKM/SpeciesConverterTests.cs @@ -0,0 +1,50 @@ +using FluentAssertions; +using Xunit; +using static PKHeX.Core.Species; + +namespace PKHeX.Core.Tests; + +public class SpeciesConverterTests +{ + [Theory] + [InlineData(0)] + [InlineData(1, Rhydon)] + [InlineData(14, Gengar)] + [InlineData(176, Charmander)] + public void GetNational1(byte raw, Species national = 0) => ((Species)SpeciesConverter.GetNational1(raw)).Should().Be(national); + + [Theory] + [InlineData(0)] + [InlineData(1, Rhydon)] + [InlineData(14, Gengar)] + [InlineData(176, Charmander)] + public void GetInternal1(byte raw, Species national = 0) => SpeciesConverter.GetInternal1((byte)national).Should().Be(raw); + + [Theory] + [InlineData(0)] + [InlineData(411, Chimecho)] + [InlineData(407, Latias)] + [InlineData(355, Mawile)] + public void GetNational3(ushort raw, Species national = 0) => ((Species)SpeciesConverter.GetNational3(raw)).Should().Be(national); + + [Theory] + [InlineData(0)] + [InlineData(411, Chimecho)] + [InlineData(407, Latias)] + [InlineData(355, Mawile)] + public void GetInternal3(ushort raw, Species national = 0) => SpeciesConverter.GetInternal3((ushort)national).Should().Be(raw); + + [Theory] + [InlineData(0)] + [InlineData(934, Palafin)] + [InlineData(980, _980)] + [InlineData(987, _987)] + public void GetNational9(ushort raw, Species national = 0) => ((Species)SpeciesConverter.GetNational9(raw)).Should().Be(national); + + [Theory] + [InlineData(0)] + [InlineData(934, Palafin)] + [InlineData(980, _980)] + [InlineData(987, _987)] + public void GetInternal9(ushort raw, Species national = 0) => SpeciesConverter.GetInternal9((ushort)national).Should().Be(raw); +} diff --git a/Tests/PKHeX.Core.Tests/PKM/StatTest.cs b/Tests/PKHeX.Core.Tests/PKM/StatTest.cs index f19d2d790..db3085ffb 100644 --- a/Tests/PKHeX.Core.Tests/PKM/StatTest.cs +++ b/Tests/PKHeX.Core.Tests/PKM/StatTest.cs @@ -1,8 +1,7 @@ using FluentAssertions; -using PKHeX.Core; using Xunit; -namespace PKHeX.Tests.PKM; +namespace PKHeX.Core.Tests.PKM; public class StatTest { diff --git a/Tests/PKHeX.Core.Tests/PKM/StringTests.cs b/Tests/PKHeX.Core.Tests/PKM/StringTests.cs index d39faac30..6c7e2875d 100644 --- a/Tests/PKHeX.Core.Tests/PKM/StringTests.cs +++ b/Tests/PKHeX.Core.Tests/PKM/StringTests.cs @@ -1,9 +1,8 @@ using System; using FluentAssertions; -using PKHeX.Core; using Xunit; -namespace PKHeX.Tests.PKM; +namespace PKHeX.Core.Tests.PKM; public class StringTests { diff --git a/Tests/PKHeX.Core.Tests/Saves/HomeTests.cs b/Tests/PKHeX.Core.Tests/Saves/HomeTests.cs index 019952a08..3bb742e39 100644 --- a/Tests/PKHeX.Core.Tests/Saves/HomeTests.cs +++ b/Tests/PKHeX.Core.Tests/Saves/HomeTests.cs @@ -1,12 +1,11 @@ -using System; +using System; using System.Collections.Generic; using System.IO; using FluentAssertions; -using PKHeX.Core; using Xunit; using static System.Buffers.Binary.BinaryPrimitives; -namespace PKHeX.Tests.Saves; +namespace PKHeX.Core.Tests.Saves; public static class HomeTests { diff --git a/Tests/PKHeX.Core.Tests/Saves/MemeCrypto/MemeCryptoTests.cs b/Tests/PKHeX.Core.Tests/Saves/MemeCrypto/MemeCryptoTests.cs index b37892a35..596ee739d 100644 --- a/Tests/PKHeX.Core.Tests/Saves/MemeCrypto/MemeCryptoTests.cs +++ b/Tests/PKHeX.Core.Tests/Saves/MemeCrypto/MemeCryptoTests.cs @@ -1,9 +1,8 @@ -using System.Collections.Generic; +using System.Collections.Generic; using FluentAssertions; -using PKHeX.Core; using Xunit; -namespace PKHeX.Tests.Saves; +namespace PKHeX.Core.Tests.Saves; public class MemeCryptoTests { @@ -105,6 +104,6 @@ public class MemeCryptoTests [MemberData(nameof(KnownKeys))] public void TestVerifyKnownKeys(MemeKeyIndex keyIndex, byte[] key) { - MemeCrypto.VerifyMemeData(key, out _, keyIndex).Should().BeTrue("because they key should be valid"); + MemeCrypto.VerifyMemeData(key, out _, keyIndex).Should().BeTrue("because the key should be valid"); } } diff --git a/Tests/PKHeX.Core.Tests/Saves/MemeCrypto/SwishCryptoTests.cs b/Tests/PKHeX.Core.Tests/Saves/MemeCrypto/SwishCryptoTests.cs index 79139ddb3..842abbf84 100644 --- a/Tests/PKHeX.Core.Tests/Saves/MemeCrypto/SwishCryptoTests.cs +++ b/Tests/PKHeX.Core.Tests/Saves/MemeCrypto/SwishCryptoTests.cs @@ -1,8 +1,7 @@ -using FluentAssertions; -using PKHeX.Core; +using FluentAssertions; using Xunit; -namespace PKHeX.Tests.Saves; +namespace PKHeX.Core.Tests.Saves; public class SwishCryptoTests { diff --git a/Tests/PKHeX.Core.Tests/Saves/PokeDex.cs b/Tests/PKHeX.Core.Tests/Saves/PokeDex.cs index ac435b076..c18d3318e 100644 --- a/Tests/PKHeX.Core.Tests/Saves/PokeDex.cs +++ b/Tests/PKHeX.Core.Tests/Saves/PokeDex.cs @@ -1,9 +1,8 @@ using System; using Xunit; using FluentAssertions; -using PKHeX.Core; -namespace PKHeX.Tests.Saves; +namespace PKHeX.Core.Tests.Saves; public static class PokeDex { @@ -28,7 +27,7 @@ public static class PokeDex private static void SetDexSpecies(SaveFile sav, ushort species, int regionSize) { - var pk5 = new PK5 {Species = species, TID = 1337}; // non-shiny + var pk5 = new PK5 {Species = species, TID16 = 1337}; // non-shiny pk5.Gender = pk5.GetSaneGender(); sav.SetBoxSlotAtIndex(pk5, 0); @@ -57,7 +56,7 @@ public static class PokeDex var dex = sav.PokeDex; var data = sav.Data; - int fc = sav.Personal[species].FormCount; + var fc = sav.Personal[species].FormCount; var bit = ((SAV5)sav).Zukan.DexFormIndexFetcher(species, fc); if (bit < 0) return; diff --git a/Tests/PKHeX.Core.Tests/Saves/SMTests.cs b/Tests/PKHeX.Core.Tests/Saves/SMTests.cs index 7ccd6a9f5..fe4792978 100644 --- a/Tests/PKHeX.Core.Tests/Saves/SMTests.cs +++ b/Tests/PKHeX.Core.Tests/Saves/SMTests.cs @@ -1,9 +1,8 @@ -using FluentAssertions; -using PKHeX.Core; +using FluentAssertions; using System.IO; using Xunit; -namespace PKHeX.Tests.Saves; +namespace PKHeX.Core.Tests.Saves; public static class SMTests { diff --git a/Tests/PKHeX.Core.Tests/Simulator/GeneratorTests.cs b/Tests/PKHeX.Core.Tests/Simulator/GeneratorTests.cs index 4da669264..a6813c4be 100644 --- a/Tests/PKHeX.Core.Tests/Simulator/GeneratorTests.cs +++ b/Tests/PKHeX.Core.Tests/Simulator/GeneratorTests.cs @@ -1,10 +1,9 @@ using System.Collections.Generic; using System.Linq; using FluentAssertions; -using PKHeX.Core; using Xunit; -namespace PKHeX.Tests.Simulator; +namespace PKHeX.Core.Tests.Simulator; public class GeneratorTests { @@ -52,8 +51,8 @@ public class GeneratorTests var criteria = EncounterCriteria.Unrestricted; var tr = new SimpleTrainerInfo(GameVersion.B2) { - TID = 57600, - SID = 62446, + TID16 = 57600, + SID16 = 62446, }; for (var nature = Nature.Hardy; nature <= Nature.Quirky; nature++) @@ -62,8 +61,8 @@ public class GeneratorTests var pk = ez.ConvertToPKM(tr, criteria); pk.Nature.Should().Be((int)nature, "not nature locked"); pk.IsShiny.Should().BeTrue("encounter is shiny locked"); - pk.TID.Should().Be(tr.TID); - pk.SID.Should().Be(tr.SID); + pk.TID16.Should().Be(tr.TID16); + pk.SID16.Should().Be(tr.SID16); } } } diff --git a/Tests/PKHeX.Core.Tests/Simulator/ShowdownSetTests.cs b/Tests/PKHeX.Core.Tests/Simulator/ShowdownSetTests.cs index e50313a32..1ad6c93a9 100644 --- a/Tests/PKHeX.Core.Tests/Simulator/ShowdownSetTests.cs +++ b/Tests/PKHeX.Core.Tests/Simulator/ShowdownSetTests.cs @@ -1,10 +1,8 @@ -using System; using System.Linq; using FluentAssertions; -using PKHeX.Core; using Xunit; -namespace PKHeX.Tests.Simulator; +namespace PKHeX.Core.Tests.Simulator; public class ShowdownSetTests { @@ -21,7 +19,7 @@ public class ShowdownSetTests { var set = new ShowdownSet(setstr).Text; var lines = set.Split('\n').Select(z => z.Trim()); - Assert.True(lines.All(z => setstr.Contains(z)), setstr); + Assert.True(lines.All(setstr.Contains), setstr); } } @@ -37,7 +35,7 @@ public class ShowdownSetTests var first = encounters.FirstOrDefault(); Assert.NotNull(first); - var egg = (EncounterEgg)first!; + var egg = (EncounterEgg)first; var info = new SimpleTrainerInfo(GameVersion.SN); var pk = egg.ConvertToPKM(info); Assert.True(pk.Species != set.Species); @@ -46,11 +44,12 @@ public class ShowdownSetTests Assert.True(la.Valid); var test = EncounterMovesetGenerator.GenerateEncounters(pk7, info, pk7.Moves).ToList(); - foreach (var t in test) + for (var i = 0; i < test.Count; i++) { + var t = test[i]; var convert = t.ConvertToPKM(info); var la2 = new LegalityAnalysis(convert); - Assert.True(la2.Valid); + la2.Valid.Should().BeTrue($"Encounter {i} should have generated legally: {t}"); } } @@ -65,7 +64,7 @@ public class ShowdownSetTests var first = encs.FirstOrDefault(); Assert.NotNull(first); - var wc3 = (WC3)first!; + var wc3 = (WC3)first; var info = new SimpleTrainerInfo(GameVersion.R); var pk = wc3.ConvertToPKM(info); @@ -84,9 +83,8 @@ public class ShowdownSetTests var first = encs.FirstOrDefault(); Assert.NotNull(first); - var enc = first!; var info = new SimpleTrainerInfo(GameVersion.SN); - var pk = enc.ConvertToPKM(info); + var pk = first.ConvertToPKM(info); var la = new LegalityAnalysis(pk); Assert.True(la.Valid); @@ -136,9 +134,8 @@ public class ShowdownSetTests var first = encs.FirstOrDefault(); Assert.NotNull(first); - var enc = first!; var info = new SimpleTrainerInfo(GameVersion.SN); - var pk = enc.ConvertToPKM(info); + var pk = first.ConvertToPKM(info); var la = new LegalityAnalysis(pk); Assert.True(la.Valid); @@ -148,11 +145,10 @@ public class ShowdownSetTests public void SimulatorParseMultiple() { var text = string.Join("\r\n\r\n", Sets); - var lines = text.Split(new[] {"\r\n", "\n"}, StringSplitOptions.None); - var sets = ShowdownParsing.GetShowdownSets(lines); + var sets = ShowdownParsing.GetShowdownSets(text); Assert.True(sets.Count() == Sets.Length); - sets = ShowdownParsing.GetShowdownSets(Enumerable.Empty()); + sets = ShowdownParsing.GetShowdownSets(string.Empty); Assert.True(!sets.Any()); sets = ShowdownParsing.GetShowdownSets(new [] {"", " ", " "}); diff --git a/Tests/PKHeX.Core.Tests/Util/ConvertUtilTests.cs b/Tests/PKHeX.Core.Tests/Util/ConvertUtilTests.cs index 1315a8845..223d6e7a8 100644 --- a/Tests/PKHeX.Core.Tests/Util/ConvertUtilTests.cs +++ b/Tests/PKHeX.Core.Tests/Util/ConvertUtilTests.cs @@ -1,10 +1,9 @@ using System; using FluentAssertions; -using PKHeX.Core; using Xunit; using static System.Buffers.Binary.BinaryPrimitives; -namespace PKHeX.Tests.Util; +namespace PKHeX.Core.Tests.Util; public class ConvertUtilTests { diff --git a/Tests/PKHeX.Core.Tests/Util/DataUtilTests.cs b/Tests/PKHeX.Core.Tests/Util/DataUtilTests.cs index 7b484701d..2d7f3cf8c 100644 --- a/Tests/PKHeX.Core.Tests/Util/DataUtilTests.cs +++ b/Tests/PKHeX.Core.Tests/Util/DataUtilTests.cs @@ -1,8 +1,7 @@ -using FluentAssertions; -using PKHeX.Core; +using FluentAssertions; using Xunit; -namespace PKHeX.Tests.Util; +namespace PKHeX.Core.Tests.Util; public class DataUtilTests { diff --git a/Tests/PKHeX.Core.Tests/Util/DateUtilTests.cs b/Tests/PKHeX.Core.Tests/Util/DateUtilTests.cs index 4eea50e05..4f7d5a5a7 100644 --- a/Tests/PKHeX.Core.Tests/Util/DateUtilTests.cs +++ b/Tests/PKHeX.Core.Tests/Util/DateUtilTests.cs @@ -1,9 +1,8 @@ -using System; +using System; using FluentAssertions; -using PKHeX.Core; using Xunit; -namespace PKHeX.Tests.Util; +namespace PKHeX.Core.Tests.Util; public class DateUtilTests { @@ -62,8 +61,8 @@ public class DateUtilTests [InlineData(2000, 12, 1, 2000, 12, 31, 12)] // rand->+30 public void CheckRandomDate(int y1, int m1, int d1, int y2, int m2, int d2, int seed) { - var start = new DateTime(y1, m1, d1); - var end = new DateTime(y2, m2, d2); + var start = new DateOnly(y1, m1, d1); + var end = new DateOnly(y2, m2, d2); (start <= end).Should().BeTrue(); var r = new Random(seed); diff --git a/Tests/PKHeX.Core.Tests/Util/FlagUtilTests.cs b/Tests/PKHeX.Core.Tests/Util/FlagUtilTests.cs index 0a99a352b..4dd043bed 100644 --- a/Tests/PKHeX.Core.Tests/Util/FlagUtilTests.cs +++ b/Tests/PKHeX.Core.Tests/Util/FlagUtilTests.cs @@ -1,10 +1,9 @@ -using System; +using System; using FluentAssertions; -using PKHeX.Core; using Xunit; using static System.Buffers.Binary.BinaryPrimitives; -namespace PKHeX.Tests.Util; +namespace PKHeX.Core.Tests.Util; public class FlagUtilTests { diff --git a/Tests/PKHeX.Core.Tests/Util/GeoLocationTests.cs b/Tests/PKHeX.Core.Tests/Util/GeoLocationTests.cs index 78d79fa01..35b41e77b 100644 --- a/Tests/PKHeX.Core.Tests/Util/GeoLocationTests.cs +++ b/Tests/PKHeX.Core.Tests/Util/GeoLocationTests.cs @@ -1,35 +1,34 @@ -using FluentAssertions; -using PKHeX.Core; +using FluentAssertions; using Xunit; -namespace PKHeX.Tests.Util; +namespace PKHeX.Core.Tests.Util; public class GeoLocationTests { [Theory] [InlineData("en", 1, "Japan")] - public void ReturnsCorrectCountryNameByString(string language, int country, string expectedName) + public void ReturnsCorrectCountryNameByString(string language, byte country, string expectedName) { GeoLocation.GetCountryName(language, country).Should().Be(expectedName); } [Theory] [InlineData(LanguageID.English, 10, "Argentina")] - public void ReturnsCorrectCountryNameByLanguageId(LanguageID languageId, int country, string expectedName) + public void ReturnsCorrectCountryNameByLanguageId(LanguageID languageId, byte country, string expectedName) { GeoLocation.GetCountryName(languageId, country).Should().Be(expectedName); } [Theory] [InlineData("en", 1, 2, "Tokyo")] - public void ReturnsCorrectRegionNameByString(string language, int country, int region, string expectedName) + public void ReturnsCorrectRegionNameByString(string language, byte country, byte region, string expectedName) { GeoLocation.GetRegionName(language, country, region).Should().Be(expectedName); } [Theory] [InlineData(LanguageID.Korean, 186, 1, "버뮤다")] - public void ReturnsCorrectRegionNameByLanguageId(LanguageID languageId, int country, int region, string expectedName) + public void ReturnsCorrectRegionNameByLanguageId(LanguageID languageId, byte country, byte region, string expectedName) { GeoLocation.GetRegionName(languageId, country, region).Should().Be(expectedName); } diff --git a/Tests/PKHeX.Core.Tests/Util/StringQualityTests.cs b/Tests/PKHeX.Core.Tests/Util/StringQualityTests.cs index 3f02ae637..a73e78a16 100644 --- a/Tests/PKHeX.Core.Tests/Util/StringQualityTests.cs +++ b/Tests/PKHeX.Core.Tests/Util/StringQualityTests.cs @@ -1,10 +1,9 @@ using System.Collections.Generic; using System.Linq; using FluentAssertions; -using PKHeX.Core; using Xunit; -namespace PKHeX.Tests.Util; +namespace PKHeX.Core.Tests.Util; public class StringQualityTests { diff --git a/Tests/PKHeX.Core.Tests/Util/TestUtil.cs b/Tests/PKHeX.Core.Tests/Util/TestUtil.cs index 4141f117e..45544976f 100644 --- a/Tests/PKHeX.Core.Tests/Util/TestUtil.cs +++ b/Tests/PKHeX.Core.Tests/Util/TestUtil.cs @@ -1,7 +1,7 @@ using System; using System.IO; -namespace PKHeX.Tests; +namespace PKHeX.Core.Tests; internal static class TestUtil {