diff --git a/PKHeX.Core/Game/ComboItem.cs b/PKHeX.Core/Game/ComboItem.cs index 04f6db77f..de744e91b 100644 --- a/PKHeX.Core/Game/ComboItem.cs +++ b/PKHeX.Core/Game/ComboItem.cs @@ -1,5 +1,8 @@ namespace PKHeX.Core { + /// + /// Key Value pair for a displayed and underlying value. + /// public struct ComboItem { public string Text { get; set; } diff --git a/PKHeX.Core/Game/GameInfo.cs b/PKHeX.Core/Game/GameInfo.cs index 5910d2f92..dcfcbdf92 100644 --- a/PKHeX.Core/Game/GameInfo.cs +++ b/PKHeX.Core/Game/GameInfo.cs @@ -185,7 +185,7 @@ private void SanitizeItemNames() itemlist[842] += " (SM)"; // Fishing Rod // Append Z-Crystal flagging - foreach (var i in Legal.Pouch_ZCrystal_SM) + foreach (var i in Legal.Pouch_ZCrystal_USUM) itemlist[i] += " [Z]"; } private void SanitizeMetLocations() diff --git a/PKHeX.Core/Game/GameUtil.cs b/PKHeX.Core/Game/GameUtil.cs index 537bd9346..3e048d946 100644 --- a/PKHeX.Core/Game/GameUtil.cs +++ b/PKHeX.Core/Game/GameUtil.cs @@ -1,5 +1,8 @@ namespace PKHeX.Core { + /// + /// Utility class for logic. + /// public static class GameUtil { /// Determines the Version Grouping of an input Version ID diff --git a/PKHeX.Core/Game/GameVersion.cs b/PKHeX.Core/Game/GameVersion.cs index 4427c7805..110e44510 100644 --- a/PKHeX.Core/Game/GameVersion.cs +++ b/PKHeX.Core/Game/GameVersion.cs @@ -1,5 +1,8 @@ namespace PKHeX.Core { + /// + /// Game Version ID enum shared between actual Version IDs and lumped version groupings. + /// public enum GameVersion { // Indicators diff --git a/PKHeX.Core/Legality/Analysis.cs b/PKHeX.Core/Legality/Analysis.cs index fb2134986..60d994f4f 100644 --- a/PKHeX.Core/Legality/Analysis.cs +++ b/PKHeX.Core/Legality/Analysis.cs @@ -8,6 +8,9 @@ namespace PKHeX.Core { + /// + /// Legality Check object containing the data and overview values from the parse. + /// public partial class LegalityAnalysis { private PKM pkm; @@ -53,6 +56,10 @@ private IEnumerable AllSuggestedRelearnMoves private int[] _allSuggestedMoves, _allSuggestedRelearnMoves; public int[] AllSuggestedMovesAndRelearn => AllSuggestedMoves.Concat(AllSuggestedRelearnMoves).ToArray(); + /// + /// Checks the input data for legality. + /// + /// Input data to check public LegalityAnalysis(PKM pk) { #if SUPPRESS diff --git a/PKHeX.Core/Legality/Checks.cs b/PKHeX.Core/Legality/Checks.cs index 4d2d2bb3c..a223f3c11 100644 --- a/PKHeX.Core/Legality/Checks.cs +++ b/PKHeX.Core/Legality/Checks.cs @@ -320,74 +320,114 @@ private void VerifyNicknameEgg() } private void VerifyNicknameTrade() { - string[] validOT = new string[0]; - int index = -1; - if (pkm.XY) + switch (Info.Generation) { - validOT = Encounters6.TradeXY[pkm.Language]; - index = Array.IndexOf(Encounters6.TradeGift_XY, EncounterMatch); + case 1: + case 2: VerifyTrade12(); return; + case 3: VerifyTrade3(); return; // todo + case 4: VerifyTrade4(); return; + case 5: VerifyTrade5(); return; // todo + case 6: VerifyTrade6(); return; + case 7: VerifyTrade7(); return; } - else if (pkm.AO) - { - validOT = Encounters6.TradeAO[pkm.Language]; - index = Array.IndexOf(Encounters6.TradeGift_AO, EncounterMatch); - } - else if (pkm.SM) - { - // TODO - AddLine(Severity.Valid, V194, CheckIdentifier.Nickname); - return; - } - else if (pkm.USUM) - { - // TODO - AddLine(Severity.Valid, V194, CheckIdentifier.Nickname); - return; - } - else if (pkm.Gen4) - { - if (pkm.TID != 1000) - return; // only care about Ranch atm + } + private void VerifyTrade12() + { + var et = (EncounterOriginalGB ?? EncounterMatch) as EncounterTrade; + if (et?.TID != 0) // Gen2 Trade + return; // already checked all relevant properties when fetching with getValidEncounterTradeVC2 - string[] OTs = { null, "ユカリ", "Hayley", "EULALIE", "GIULIA", "EUKALIA", "Eulalia" }; - int lang = pkm.Language; - if (OTs.Length <= lang) - { - AddLine(Severity.Valid, V8, CheckIdentifier.Trainer); - return; - } - if (pkm.IsNicknamed) - AddLine(Severity.Invalid, V9, CheckIdentifier.Nickname); - else if (OTs[lang] != pkm.OT_Name) - AddLine(Severity.Invalid, V10, CheckIdentifier.Trainer); + if (!EncounterGenerator.IsEncounterTrade1Valid(pkm)) + AddLine(Severity.Invalid, V10, CheckIdentifier.Trainer); + } + private void VerifyTrade3() + { + if (pkm.FRLG) + VerifyTradeTable(Encounters3.TradeFRLG, Encounters3.TradeGift_FRLG); + else + VerifyTradeTable(Encounters3.TradeRSE, Encounters3.TradeGift_RSE); + } + private void VerifyTrade4() + { + if (pkm.TID == 1000) + { + VerifyTrade4Ranch(); + return; + } + if (pkm.HGSS) + VerifyTradeTable(Encounters4.TradeHGSS, Encounters4.TradeGift_HGSS); + else + { + if (EncounterMatch.Species == 129) // Magikarp + VerifyTradeTable(Encounters4.TradeDPPt, Encounters4.TradeGift_DPPt, pkm.Nickname); else - AddLine(Severity.Valid, V11, CheckIdentifier.Nickname); - return; + VerifyTradeTable(Encounters4.TradeDPPt, Encounters4.TradeGift_DPPt); } - else if (pkm.Format <= 2 || pkm.VC) + } + private void VerifyTrade5() + { + // Trades for JPN games have language ID of 0, not 1. + if (pkm.BW) { - var et = (EncounterOriginalGB ?? EncounterMatch) as EncounterTrade; - if (et?.TID == 0) // Gen1 Trade - { - if (!EncounterGenerator.IsEncounterTrade1Valid(pkm)) - AddLine(Severity.Invalid, V10, CheckIdentifier.Trainer); - } - else // Gen2 - { - return; // already checked all relevant properties when fetching with getValidEncounterTradeVC2 - } - return; - } - else if (3 <= Info.Generation && Info.Generation <= 5) - { - // Trades for JPN games have language ID of 0, not 1. - if (pkm.BW && pkm.Format == 5 && pkm.Language == (int)LanguageID.Japanese) + int lang = pkm.Language; + if (pkm.Format == 5 && lang == (int)LanguageID.Japanese) AddLine(Severity.Invalid, string.Format(V5, 0, (int)LanguageID.Japanese), CheckIdentifier.Language); - // Suppressing temporarily - return; + lang = Math.Max(lang, 1); + VerifyTradeTable(Encounters5.TradeBW, Encounters5.TradeGift_BW, lang); } + else // B2W2 + { + if (Encounters5.TradeGift_B2W2_YancyCurtis.Contains(EncounterMatch)) + VerifyTradeOTOnly(pkm.OT_Gender == 0 ? Encounters5.TradeOT_B2W2_M : Encounters5.TradeOT_B2W2_F); + else + VerifyTradeTable(Encounters5.TradeB2W2, Encounters5.TradeGift_B2W2); + } + } + private void VerifyTrade6() + { + if (pkm.XY) + VerifyTradeTable(Encounters6.TradeXY, Encounters6.TradeGift_XY, pkm.Language); + else if (pkm.AO) + VerifyTradeTable(Encounters6.TradeAO, Encounters6.TradeGift_AO, pkm.Language); + } + private void VerifyTrade7() + { + if (pkm.SM) + VerifyTradeTable(Encounters7.TradeSM, Encounters7.TradeGift_SM, pkm.Language); + else if (pkm.USUM) + VerifyTradeTable(Encounters7.TradeUSUM, Encounters7.TradeGift_USUM, pkm.Language); + } + private void VerifyTrade4Ranch() => VerifyTradeOTOnly(Encounters4.RanchOTNames); + private void VerifyTradeTable(string[][] ots, EncounterTrade[] table) => VerifyTradeTable(ots, table, pkm.Language); + private void VerifyTradeTable(string[][] ots, EncounterTrade[] table, int language) + { + var validOT = language >= ots.Length ? ots[0] : ots[pkm.Language]; + var index = Array.IndexOf(table, EncounterMatch); + VerifyTradeOTNick(validOT, index); + } + private void VerifyTradeTable(string[][] ots, EncounterTrade[] table, string nickname) + { + // edge case method for Foppa (DPPt Magikarp Trade) + var index = Array.IndexOf(table, EncounterMatch); + var validOT = ots.FirstOrDefault(z => index < z.Length && z[index] == nickname); + VerifyTradeOTNick(validOT, index); + } + private void VerifyTradeOTOnly(string[] validOT) + { + if (pkm.IsNicknamed) + AddLine(Severity.Invalid, V9, CheckIdentifier.Nickname); + int lang = pkm.Language; + if (validOT.Length >= lang) + AddLine(Severity.Invalid, V8, CheckIdentifier.Trainer); + else if (validOT[lang] != pkm.OT_Name) + AddLine(Severity.Invalid, V10, CheckIdentifier.Trainer); + else + AddLine(Severity.Valid, V11, CheckIdentifier.Nickname); + } + private void VerifyTradeOTNick(string[] validOT, int index) + { if (validOT.Length == 0) { AddLine(Severity.Indeterminate, V7, CheckIdentifier.Trainer); @@ -403,11 +443,12 @@ private void VerifyNicknameTrade() string OT = validOT[validOT.Length / 2 + index]; if (nick != pkm.Nickname) - AddLine(Severity.Fishy, V9, CheckIdentifier.Nickname); - else if (OT != pkm.OT_Name) - AddLine(Severity.Invalid, V10, CheckIdentifier.Trainer); + AddLine(Severity.Invalid, V9, CheckIdentifier.Nickname); else AddLine(Severity.Valid, V11, CheckIdentifier.Nickname); + + if (OT != pkm.OT_Name) + AddLine(Severity.Invalid, V10, CheckIdentifier.Trainer); } #endregion private void VerifyEVs() @@ -548,7 +589,7 @@ private void VerifyG1OT() string tr = pkm.OT_Name; VerifyG1OTWithinBounds(tr); - if ((EncounterMatch as EncounterStatic)?.Version == GameVersion.Stadium) + if (EncounterMatch is EncounterStatic s && (s.Version == GameVersion.Stadium || s.Version == GameVersion.Stadium2)) VerifyG1OTStadium(tr); if (pkm.Species == 151) @@ -601,7 +642,7 @@ private void VerifyG1NicknameWithinBounds(string str) } private void VerifyG1OTStadium(string tr) { - bool jp = (pkm as PK1)?.Japanese ?? (pkm as PK2)?.Japanese ?? pkm.Language != (int)LanguageID.English; + bool jp = pkm.Japanese; bool valid = GetIsStadiumOTIDValid(jp, tr); if (!valid) AddLine(Severity.Invalid, V402, CheckIdentifier.Trainer); @@ -612,7 +653,7 @@ private bool GetIsStadiumOTIDValid(bool jp, string tr) { if (jp) return tr == "スタジアム" && pkm.TID == 1999; - return tr == "STADIUM" && pkm.TID == 2000; + return tr == (Info.Generation == 1 ? "STADIUM" : "Stadium") && pkm.TID == 2000; } #endregion private void VerifyHyperTraining() diff --git a/PKHeX.Core/Legality/Core.cs b/PKHeX.Core/Legality/Core.cs index f7793013c..06bdaf495 100644 --- a/PKHeX.Core/Legality/Core.cs +++ b/PKHeX.Core/Legality/Core.cs @@ -649,7 +649,7 @@ internal static IEnumerable GetInitialMovesGBEncounter(int species, int lvl var LevelTable = ver == GameVersion.YW ? LevelUpY : LevelUpRB; int index = PersonalTable.RB.GetFormeIndex(species, 0); if (index == 0) - return new int[0]; + return Enumerable.Empty(); LevelUpMoves = LevelTable[species].GetEncounterMoves(lvl); diff = 4 - LevelUpMoves.Count(z => z != 0); if (diff == 0) @@ -668,7 +668,7 @@ internal static IEnumerable GetInitialMovesGBEncounter(int species, int lvl var LevelTable = ver == GameVersion.C ? LevelUpC : LevelUpGS; int index = PersonalTable.C.GetFormeIndex(species, 0); if (index == 0) - return new int[0]; + return Enumerable.Empty(); LevelUpMoves = LevelTable[species].GetEncounterMoves(lvl); diff = 4 - LevelUpMoves.Count(z => z != 0); if (diff == 0) @@ -678,7 +678,7 @@ internal static IEnumerable GetInitialMovesGBEncounter(int species, int lvl break; } default: - return new int[0]; + return Enumerable.Empty(); } // Initial Moves could be duplicated in the level up table // level up table moves have preference @@ -1100,7 +1100,7 @@ internal static IEnumerable GetFutureGenEvolutions(int generation) case 3: return FutureEvolutionsGen3; case 4: return FutureEvolutionsGen4; case 5: return FutureEvolutionsGen5; - default: return new int[0]; + default: return Enumerable.Empty(); } } @@ -1603,7 +1603,7 @@ private static IEnumerable GetRelearnLVLMoves(PKM pkm, int species, int lvl case GameVersion.US: case GameVersion.UM: return getMoves(LevelUpUSUM, PersonalTable.USUM); } - return new int[0]; + return Enumerable.Empty(); int[] getMoves(Learnset[] moves, PersonalTable table) => moves[table.GetFormeIndex(species, formnum)].GetMoves(lvl); } @@ -2178,33 +2178,31 @@ internal static IEnumerable GetTutorMoves(PKM pkm, int species, int form, b info = PersonalTable.B2W2[species]; moves.AddRange(TypeTutor6.Where((t, i) => info.TypeTutors[i])); if (pkm.InhabitedGeneration(5) && specialTutors) - { - PersonalInfo pi = PersonalTable.B2W2.GetFormeEntry(species, form); - for (int i = 0; i < Tutors_B2W2.Length; i++) - for (int b = 0; b < Tutors_B2W2[i].Length; b++) - if (pi.SpecialTutors[i][b]) - moves.Add(Tutors_B2W2[i][b]); - } + moves.AddRange(GetTutors(PersonalTable.B2W2, Tutors_B2W2)); break; case 6: info = PersonalTable.AO[species]; moves.AddRange(TypeTutor6.Where((t, i) => info.TypeTutors[i])); if (pkm.InhabitedGeneration(6) && specialTutors && (pkm.AO || !pkm.IsUntraded)) - { - PersonalInfo pi = PersonalTable.AO.GetFormeEntry(species, form); - for (int i = 0; i < Tutors_AO.Length; i++) - for (int b = 0; b < Tutors_AO[i].Length; b++) - if (pi.SpecialTutors[i][b]) - moves.Add(Tutors_AO[i][b]); - } + moves.AddRange(GetTutors(PersonalTable.AO, Tutors_AO)); break; case 7: info = PersonalTable.USUM.GetFormeEntry(species, form); moves.AddRange(TypeTutor6.Where((t, i) => info.TypeTutors[i])); - // No special tutors in G7 + if (pkm.InhabitedGeneration(7) && specialTutors && (pkm.USUM || !pkm.IsUntraded)) + moves.AddRange(GetTutors(PersonalTable.USUM, Tutors_USUM)); break; } return moves.Distinct(); + + IEnumerable GetTutors(PersonalTable t, IReadOnlyList tutors) + { + var pi = t.GetFormeEntry(species, form); + for (int i = 0; i < tutors.Count; i++) + for (int b = 0; b < tutors[i].Length; b++) + if (pi.SpecialTutors[i][b]) + yield return tutors[i][b]; + } } internal static bool IsTradedKadabraG1(PKM pkm) { diff --git a/PKHeX.Core/Legality/Encounters/Data/Encounters1.cs b/PKHeX.Core/Legality/Encounters/Data/Encounters1.cs index 74ac36437..8059e06c4 100644 --- a/PKHeX.Core/Legality/Encounters/Data/Encounters1.cs +++ b/PKHeX.Core/Legality/Encounters/Data/Encounters1.cs @@ -4,6 +4,9 @@ namespace PKHeX.Core { + /// + /// Generation 1 Encounters + /// internal static class Encounters1 { internal static readonly EncounterArea[] SlotsRBY; diff --git a/PKHeX.Core/Legality/Encounters/Data/Encounters2.cs b/PKHeX.Core/Legality/Encounters/Data/Encounters2.cs index a89e97ef4..0d2d598ab 100644 --- a/PKHeX.Core/Legality/Encounters/Data/Encounters2.cs +++ b/PKHeX.Core/Legality/Encounters/Data/Encounters2.cs @@ -3,6 +3,9 @@ namespace PKHeX.Core { + /// + /// Generation 2 Encounters + /// internal static class Encounters2 { internal static readonly EncounterArea[] SlotsGSC, SlotsGS, SlotsC; diff --git a/PKHeX.Core/Legality/Encounters/Data/Encounters3.cs b/PKHeX.Core/Legality/Encounters/Data/Encounters3.cs index d333f6eec..f680af810 100644 --- a/PKHeX.Core/Legality/Encounters/Data/Encounters3.cs +++ b/PKHeX.Core/Legality/Encounters/Data/Encounters3.cs @@ -3,6 +3,9 @@ namespace PKHeX.Core { + /// + /// Generation 3 Encounters + /// internal static class Encounters3 { internal static readonly EncounterArea[] SlotsR, SlotsS, SlotsE; @@ -218,30 +221,52 @@ private static void MarkG3SlotsSafariZones(ref EncounterArea[] Areas, int locati private static readonly int[] TradeContest_Tough = { 05, 05, 05, 05, 30, 10 }; internal static readonly EncounterTrade[] TradeGift_RSE = { - new EncounterTrade { Species = 296, Ability = 2, TID = 49562, SID = 00000, OTGender = 0, Gender = 0, IVs = new[] {5,5,4,4,4,4}, Level = 05, Nature = Nature.Hardy, Contest = TradeContest_Tough, Version = GameVersion.RS, }, // Slakoth (Level 5 Breeding) -> Makuhita - new EncounterTrade { Species = 300, Ability = 1, TID = 02259, SID = 00000, OTGender = 1, Gender = 1, IVs = new[] {5,4,4,5,4,4}, Level = 03, Nature = Nature.Timid, Contest = TradeContest_Cute, Version = GameVersion.RS, }, // Pikachu (Level 3 Viridiam Forest) -> Skitty - new EncounterTrade { Species = 222, Ability = 2, TID = 50183, SID = 00000, OTGender = 1, Gender = 1, IVs = new[] {4,4,5,4,4,5}, Level = 21, Nature = Nature.Calm, Contest = TradeContest_Beauty, Version = GameVersion.RS, }, // Bellossom (Level 21 Odish -> Gloom -> Bellossom) -> Corsola - new EncounterTrade { Species = 273, Ability = 2, TID = 38726, SID = 00000, OTGender = 0, Gender = 0, IVs = new[] {5,4,5,4,4,4}, Level = 04, Nature = Nature.Relaxed, Contest = TradeContest_Cool, Version = GameVersion.E, }, // Ralts (Level 4 Route 102) -> Seedot - new EncounterTrade { Species = 311, Ability = 1, TID = 08460, SID = 00001, OTGender = 0, Gender = 1, IVs = new[] {4,4,4,5,5,4}, Level = 05, Nature = Nature.Hasty, Contest = TradeContest_Cute, Version = GameVersion.E, }, // Volbeat (Level 5 Breeding) -> Plusle - new EncounterTrade { Species = 116, Ability = 1, TID = 46285, SID = 00000, OTGender = 0, Gender = 0, IVs = new[] {5,4,4,4,5,4}, Level = 05, Nature = Nature.Brave, Contest = TradeContest_Tough, Version = GameVersion.E, }, // Bagon Bagon (Level 5 Breeding) -> Horsea* - new EncounterTrade { Species = 052, Ability = 1, TID = 25945, SID = 00001, OTGender = 1, Gender = 0, IVs = new[] {4,5,4,5,4,4}, Level = 03, Nature = Nature.Naive, Contest = TradeContest_Clever, Version = GameVersion.E, }, // Skitty (Level 3 Trade)-> Meowth* + new EncounterTradePID { Species = 296, Ability = 2, TID = 49562, SID = 00000, OTGender = 0, Gender = 0, IVs = new[] {5,5,4,4,4,4}, Level = 05, PID = 0x00009C40, Contest = TradeContest_Tough, Version = GameVersion.RS, }, // Slakoth (Level 5 Breeding) -> Makuhita + new EncounterTradePID { Species = 300, Ability = 1, TID = 02259, SID = 00000, OTGender = 1, Gender = 1, IVs = new[] {5,4,4,5,4,4}, Level = 03, PID = 0x498A2E17, Contest = TradeContest_Cute, Version = GameVersion.RS, }, // Pikachu (Level 3 Viridiam Forest) -> Skitty + new EncounterTradePID { Species = 222, Ability = 2, TID = 50183, SID = 00000, OTGender = 1, Gender = 1, IVs = new[] {4,4,5,4,4,5}, Level = 21, PID = 0x4C970B7F, Contest = TradeContest_Beauty, Version = GameVersion.RS, }, // Bellossom (Level 21 Odish -> Gloom -> Bellossom) -> Corsola + new EncounterTradePID { Species = 273, Ability = 2, TID = 38726, SID = 00000, OTGender = 0, Gender = 0, IVs = new[] {5,4,5,4,4,4}, Level = 04, PID = 0x00000084, Contest = TradeContest_Cool, Version = GameVersion.E, }, // Ralts (Level 4 Route 102) -> Seedot + new EncounterTradePID { Species = 311, Ability = 1, TID = 08460, SID = 00001, OTGender = 0, Gender = 1, IVs = new[] {4,4,4,5,5,4}, Level = 05, PID = 0x0000006F, Contest = TradeContest_Cute, Version = GameVersion.E, }, // Volbeat (Level 5 Breeding) -> Plusle + new EncounterTradePID { Species = 116, Ability = 1, TID = 46285, SID = 00000, OTGender = 0, Gender = 0, IVs = new[] {5,4,4,4,5,4}, Level = 05, PID = 0x0000007F, Contest = TradeContest_Tough, Version = GameVersion.E, }, // Bagon (Level 5 Breeding) -> Horsea* + new EncounterTradePID { Species = 052, Ability = 1, TID = 25945, SID = 00001, OTGender = 1, Gender = 0, IVs = new[] {4,5,4,5,4,4}, Level = 03, PID = 0x0000008B, Contest = TradeContest_Clever, Version = GameVersion.E, }, // 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. }; internal static readonly EncounterTrade[] TradeGift_FRLG = { - new EncounterTrade { Species = 122, Ability = 1, TID = 01985, SID = 00000, OTGender = 0, Gender = 0, IVs = new[] {20,15,17,24,23,22}, Nature = Nature.Timid, Contest = TradeContest_Clever,}, // Mr. Mime - new EncounterTrade { Species = 029, Ability = 1, TID = 63184, SID = 00000, OTGender = 1, Gender = 1, IVs = new[] {22,18,25,19,15,22}, Nature = Nature.Bold, Contest = TradeContest_Tough, Version = GameVersion.FR, }, // Nidoran♀ - new EncounterTrade { Species = 032, Ability = 1, TID = 63184, SID = 00000, OTGender = 1, Gender = 0, IVs = new[] {19,25,18,22,22,15}, Nature = Nature.Lonely, Contest = TradeContest_Cool, Version = GameVersion.LG, }, // Nidoran♂ * - new EncounterTrade { Species = 030, Ability = 1, TID = 13637, SID = 00000, OTGender = 0, Gender = 1, IVs = new[] {22,25,18,19,22,15}, Nature = Nature.Lonely, Contest = TradeContest_Cute, Version = GameVersion.FR,}, // Nidorina * - new EncounterTrade { Species = 033, Ability = 1, TID = 13637, SID = 00000, OTGender = 0, Gender = 0, IVs = new[] {19,18,25,22,15,22}, Nature = Nature.Bold, Contest = TradeContest_Tough, Version = GameVersion.LG,}, // Nidorino * - new EncounterTrade { Species = 108, Ability = 1, TID = 01239, SID = 00000, OTGender = 0, Gender = 0, IVs = new[] {24,19,21,15,23,21}, Nature = Nature.Relaxed, Contest = TradeContest_Tough, }, // Lickitung * - new EncounterTrade { Species = 124, Ability = 1, TID = 36728, SID = 00000, OTGender = 0, Gender = 1, IVs = new[] {18,17,18,22,25,21}, Nature = Nature.Mild, Contest = TradeContest_Beauty, }, // Jynx - new EncounterTrade { Species = 083, Ability = 1, TID = 08810, SID = 00000, OTGender = 0, Gender = 0, IVs = new[] {20,25,21,24,15,20}, Nature = Nature.Adamant, Contest = TradeContest_Cool, }, // Farfetch'd - new EncounterTrade { Species = 101, Ability = 2, TID = 50298, SID = 00000, OTGender = 0, Gender = 2, IVs = new[] {19,16,18,25,25,19}, Nature = Nature.Hasty, Contest = TradeContest_Cool, }, // Electrode - new EncounterTrade { Species = 114, Ability = 1, TID = 60042, SID = 00000, OTGender = 1, Gender = 0, IVs = new[] {22,17,25,16,23,20}, Nature = Nature.Sassy, Contest = TradeContest_Cute, }, // Tangela - new EncounterTrade { Species = 086, Ability = 1, TID = 09853, SID = 00000, OTGender = 0, Gender = 0, IVs = new[] {24,15,22,16,23,22}, Nature = Nature.Bold, Contest = TradeContest_Tough, }, // Seel * + new EncounterTradePID { Species = 122, Ability = 1, TID = 01985, SID = 00000, OTGender = 0, Gender = 0, IVs = new[] {20,15,17,24,23,22}, PID = 0x00009CAE, Contest = TradeContest_Clever, }, // Mr. Mime + new EncounterTradePID { Species = 029, Ability = 1, TID = 63184, SID = 00000, OTGender = 1, Gender = 1, IVs = new[] {22,18,25,19,15,22}, PID = 0x4C970B89, Contest = TradeContest_Tough, Version = GameVersion.FR, }, // Nidoran♀ + new EncounterTradePID { Species = 032, Ability = 1, TID = 63184, SID = 00000, OTGender = 1, Gender = 0, IVs = new[] {19,25,18,22,22,15}, PID = 0x4C970B9E, Contest = TradeContest_Cool, Version = GameVersion.LG, }, // Nidoran♂ * + new EncounterTradePID { Species = 030, Ability = 1, TID = 13637, SID = 00000, OTGender = 0, Gender = 1, IVs = new[] {22,25,18,19,22,15}, PID = 0x00EECA15, Contest = TradeContest_Cute, Version = GameVersion.FR,}, // Nidorina * + new EncounterTradePID { Species = 033, Ability = 1, TID = 13637, SID = 00000, OTGender = 0, Gender = 0, IVs = new[] {19,18,25,22,15,22}, PID = 0x00EECA19, Contest = TradeContest_Tough, Version = GameVersion.LG,}, // Nidorino * + new EncounterTradePID { Species = 108, Ability = 1, TID = 01239, SID = 00000, OTGender = 0, Gender = 0, IVs = new[] {24,19,21,15,23,21}, PID = 0x451308AB, Contest = TradeContest_Tough, }, // Lickitung * + new EncounterTradePID { Species = 124, Ability = 1, TID = 36728, SID = 00000, OTGender = 0, Gender = 1, IVs = new[] {18,17,18,22,25,21}, PID = 0x498A2E1D, Contest = TradeContest_Beauty, }, // Jynx + new EncounterTradePID { Species = 083, Ability = 1, TID = 08810, SID = 00000, OTGender = 0, Gender = 0, IVs = new[] {20,25,21,24,15,20}, PID = 0x151943D7, Contest = TradeContest_Cool, }, // Farfetch'd + new EncounterTradePID { Species = 101, Ability = 2, TID = 50298, SID = 00000, OTGender = 0, Gender = 2, IVs = new[] {19,16,18,25,25,19}, PID = 0x06341016, Contest = TradeContest_Cool, }, // Electrode + new EncounterTradePID { Species = 114, Ability = 1, TID = 60042, SID = 00000, OTGender = 1, Gender = 0, IVs = new[] {22,17,25,16,23,20}, PID = 0x5C77ECFA, Contest = TradeContest_Cute, }, // Tangela + new EncounterTradePID { Species = 086, Ability = 1, TID = 09853, SID = 00000, OTGender = 0, Gender = 0, IVs = new[] {24,15,22,16,23,22}, PID = 0x482CAC89, Contest = TradeContest_Tough, }, // Seel * // If Pokémon with * is evolved in a Generation IV or V game, its Ability will become its second Ability. }; + internal static readonly string[][] TradeRSE = + { + new string[0], // 0 - None + Util.GetStringList("traderse", "ja"), // 1 + Util.GetStringList("traderse", "en"), // 2 + Util.GetStringList("traderse", "fr"), // 3 + Util.GetStringList("traderse", "it"), // 4 + Util.GetStringList("traderse", "de"), // 5 + new string[0], // 6 - None + Util.GetStringList("traderse", "es"), // 7 + }; + internal static readonly string[][] TradeFRLG = + { + new string[0], // 0 - None + Util.GetStringList("tradefrlg", "ja"), // 1 + Util.GetStringList("tradefrlg", "en"), // 2 + Util.GetStringList("tradefrlg", "fr"), // 3 + Util.GetStringList("tradefrlg", "it"), // 4 + Util.GetStringList("tradefrlg", "de"), // 5 + new string[0], // 6 - None + Util.GetStringList("tradefrlg", "es"), // 7 + }; #region AltSlots private static readonly int[] SafariZoneLocation_3 = @@ -403,7 +428,8 @@ private static void MarkG3SlotsSafariZones(ref EncounterArea[] Areas, int locati new EncounterStaticShadow { Species = 206, Level = 33, Gauge = 05000, Moves = new[] {180,137,281,036}, Location = 029 }, // Dunsparce: Rider Sosh @ Pyrite Cave new EncounterStaticShadow { Species = 333, Level = 33, Gauge = 05000, Moves = new[] {119,047,219,019}, Location = 032 }, // Swablu: Hunter Zalo @ Pyrite Cave - new EncounterStaticShadow { Species = 185, Level = 35, Gauge = 10000, Moves = new[] {175,335,067,157}, Location = 125 }, // Sudowoodo: Cipher Admin Miror B. @ Deep Colosseum -- (Realgam Tower missing) + new EncounterStaticShadow { Species = 185, Level = 35, Gauge = 10000, Moves = new[] {175,335,067,157}, Location = 104 }, // Sudowoodo: Cipher Admin Miror B. @ Realgam Tower + new EncounterStaticShadow { Species = 185, Level = 35, Gauge = 10000, Moves = new[] {175,335,067,157}, Location = 125 }, // Sudowoodo: Cipher Admin Miror B. @ Deep Colosseum new EncounterStaticShadow { Species = 185, Level = 35, Gauge = 10000, Moves = new[] {175,335,067,157}, Location = 030 }, // Sudowoodo: Cipher Admin Miror B. @ Pyrite Cave // missing locs: Shadow PKMN Lab @@ -413,14 +439,16 @@ private static void MarkG3SlotsSafariZones(ref EncounterArea[] Areas, int locati new EncounterStaticShadow { Species = 166, Level = 40, Gauge = 06000, Moves = new[] {226,219,048,004}, Location = 047 }, // Ledian: Cipher Peon Kloak @ The Under new EncounterStaticShadow { Species = 166, Level = 40, Gauge = 06000, Moves = new[] {226,219,048,004}, Location = 132 }, // Ledian: Cipher Peon Kloak @ Snagem Hideout - // missing locs: Realgam Tower/Deep Colosseum + new EncounterStaticShadow { Species = 244, Level = 40, Gauge = 13000, Moves = new[] {241,043,044,126}, Location = 104 }, // Entei: Cipher Admin Dakim @ Realgam Tower + new EncounterStaticShadow { Species = 244, Level = 40, Gauge = 13000, Moves = new[] {241,043,044,126}, Location = 125 }, // Entei: Cipher Admin Dakim @ Deep Colosseum new EncounterStaticShadow { Species = 244, Level = 40, Gauge = 13000, Moves = new[] {241,043,044,126}, Location = 076 }, // Entei: Cipher Admin Dakim @ Mt. Battle - // missing loc: Realgam Tower + new EncounterStaticShadow { Species = 245, Level = 40, Gauge = 13000, Moves = new[] {240,043,016,057}, Location = 104 }, // Suicune (Surf): Cipher Admin Venus @ Realgam Tower + new EncounterStaticShadow { Species = 245, Level = 40, Gauge = 13000, Moves = new[] {240,043,016,056}, Location = 125 }, // Suicune (Hydro Pump): Cipher Admin Venus @ Deep Colosseum new EncounterStaticShadow { Species = 245, Level = 40, Gauge = 13000, Moves = new[] {240,043,016,057}, Location = 055 }, // Suicune (Surf): Cipher Admin Venus @ The Under - new EncounterStaticShadow { Species = 245, Level = 40, Gauge = 13000, Moves = new[] {240,043,016,056}, Location = 000 }, // Suicune (Hydro Pump): Cipher Admin Venus @ Deep Colosseum - // missing locs: Realgam Tower/Deep Colosseum + new EncounterStaticShadow { Species = 243, Level = 40, Gauge = 13000, Moves = new[] {240,043,098,087}, Location = 104 }, // Raikou: Cipher Admin Ein @ Realgam Tower + new EncounterStaticShadow { Species = 243, Level = 40, Gauge = 13000, Moves = new[] {240,043,098,087}, Location = 125 }, // Raikou: Cipher Admin Ein @ Deep Colosseum new EncounterStaticShadow { Species = 243, Level = 40, Gauge = 13000, Moves = new[] {240,043,098,087}, Location = 069 }, // Raikou: Cipher Admin Ein @ Shadow PKMN Lab new EncounterStaticShadow { Species = 207, Level = 43, Gauge = 06000, Moves = new[] {185,028,040,163}, Location = 058 }, // Gligar: Hunter Frena @ The Under Subway diff --git a/PKHeX.Core/Legality/Encounters/Data/Encounters4.cs b/PKHeX.Core/Legality/Encounters/Data/Encounters4.cs index 00b46b707..0f85328c7 100644 --- a/PKHeX.Core/Legality/Encounters/Data/Encounters4.cs +++ b/PKHeX.Core/Legality/Encounters/Data/Encounters4.cs @@ -5,6 +5,9 @@ namespace PKHeX.Core { + /// + /// Generation 4 Encounters + /// internal static class Encounters4 { internal static readonly EncounterArea[] SlotsD, SlotsP, SlotsPt, SlotsHG, SlotsSS; @@ -126,11 +129,11 @@ private static void MarkEncounterTypeData(ref EncounterArea[] D_Slots, ref Encou MarkDPPtEncounterTypeSlots_MultipleTypes(ref P_Slots, MtCoronet, DPPt_MtCoronetExteriorEncounters, EncounterType.Cave_HallOfOrigin); MarkDPPtEncounterTypeSlots_MultipleTypes(ref Pt_Slots, MtCoronet, DPPt_MtCoronetExteriorEncounters, EncounterType.Cave_HallOfOrigin); const int RuinsOfAlph = 209; - MarkHGSSEncounterTypeSlots_MultipleTypes(ref HG_Slots, RuinsOfAlph, 1, EncounterType.Cave_HallOfOrigin); - MarkHGSSEncounterTypeSlots_MultipleTypes(ref SS_Slots, RuinsOfAlph, 1, EncounterType.Cave_HallOfOrigin); + MarkHGSSEncounterTypeSlots_MultipleTypes(ref HG_Slots, RuinsOfAlph, EncounterType.Cave_HallOfOrigin, 1); + MarkHGSSEncounterTypeSlots_MultipleTypes(ref SS_Slots, RuinsOfAlph, EncounterType.Cave_HallOfOrigin, 1); const int MtSilver = 219; - MarkHGSSEncounterTypeSlots_MultipleTypes(ref HG_Slots, MtSilver, HGSS_MtSilverCaveExteriorEncounters, EncounterType.Cave_HallOfOrigin); - MarkHGSSEncounterTypeSlots_MultipleTypes(ref SS_Slots, MtSilver, HGSS_MtSilverCaveExteriorEncounters, EncounterType.Cave_HallOfOrigin); + MarkHGSSEncounterTypeSlots_MultipleTypes(ref HG_Slots, MtSilver, EncounterType.Cave_HallOfOrigin, HGSS_MtSilverCaveExteriorEncounters); + MarkHGSSEncounterTypeSlots_MultipleTypes(ref SS_Slots, MtSilver, EncounterType.Cave_HallOfOrigin, HGSS_MtSilverCaveExteriorEncounters); } private static void MarkG4PokeWalker(EncounterStatic[] t) @@ -210,6 +213,7 @@ private static EncounterType GetEncounterTypeBySlotHGSS(SlotType Type, Encounter case SlotType.Grass: case SlotType.Grass_Safari: case SlotType.BugContest: return GrassType; + case SlotType.Surf: case SlotType.Old_Rod: case SlotType.Good_Rod: @@ -218,10 +222,17 @@ private static EncounterType GetEncounterTypeBySlotHGSS(SlotType Type, Encounter case SlotType.Old_Rod_Safari: case SlotType.Good_Rod_Safari: case SlotType.Super_Rod_Safari: return EncounterType.Surfing_Fishing; + case SlotType.Rock_Smash: - case SlotType.Rock_Smash_Safari: return EncounterType.RockSmash; - case SlotType.Headbutt: return HeadbuttType; - case SlotType.Headbutt_Special: return EncounterType.None; + if (HeadbuttType == EncounterType.Building_EnigmaStone) + return HeadbuttType; + if (GrassType == EncounterType.Cave_HallOfOrigin) + return GrassType; + return EncounterType.None; + + case SlotType.Headbutt_Special: + case SlotType.Headbutt: return HeadbuttType | EncounterType.None; + // not sure on if "None" should always be allowed, but this is so uncommon it shouldn't matter (gen7 doesn't keep this value anyway). } return EncounterType.None; } @@ -253,7 +264,7 @@ private static void MarkDPPtEncounterTypeSlots_MultipleTypes(ref EncounterArea[] } } } - private static void MarkHGSSEncounterTypeSlots_MultipleTypes(ref EncounterArea[] Areas, int Location, int SpecialEncounterFile, EncounterType NormalEncounterType) + private static void MarkHGSSEncounterTypeSlots_MultipleTypes(ref EncounterArea[] Areas, int Location, EncounterType NormalEncounterType, params int[] SpecialEncounterFile) { // Area with two different encounter type for grass encounters // SpecialEncounterFile is taall grass encounter type, the other files have the normal encounter type for this location @@ -262,21 +273,7 @@ private static void MarkHGSSEncounterTypeSlots_MultipleTypes(ref EncounterArea[] foreach (EncounterArea Area in Areas.Where(x => x.Location == Location)) { numfile++; - var GrassType = numfile == SpecialEncounterFile ? EncounterType.TallGrass : NormalEncounterType; - foreach (EncounterSlot Slot in Area.Slots) - { - Slot.TypeEncounter = GetEncounterTypeBySlotHGSS(Slot.Type, GrassType, HeadbuttType); - } - } - } - private static void MarkHGSSEncounterTypeSlots_MultipleTypes(ref EncounterArea[] Areas, int Location, ICollection SpecialEncounterFiles, EncounterType NormalEncounterType) - { - var HeadbuttType = GetHeadbuttEncounterType(Location); - var numfile = 0; - foreach (EncounterArea Area in Areas.Where(x => x.Location == Location)) - { - numfile++; - var GrassType = SpecialEncounterFiles.Contains(numfile) ? EncounterType.TallGrass : NormalEncounterType; + var GrassType = SpecialEncounterFile.Contains(numfile) ? EncounterType.TallGrass : NormalEncounterType; foreach (EncounterSlot Slot in Area.Slots) { Slot.TypeEncounter = GetEncounterTypeBySlotHGSS(Slot.Type, GrassType, HeadbuttType); @@ -304,18 +301,26 @@ private static EncounterType GetHeadbuttEncounterType(int Location) var allowsurf = HGSS_SurfingHeadbutt_Locations.Contains(Location); // Cities if (HGSS_CityLocations.Contains(Location)) - return allowsurf ? EncounterType.Headbutt_CitySurf : EncounterType.Building_EnigmaStone; + return allowsurf + ? EncounterType.Building_EnigmaStone | EncounterType.Surfing_Fishing + : EncounterType.Building_EnigmaStone; // Caves with no exterior zones if (!HGSS_MixInteriorExteriorLocations.Contains(Location) && HGSS_CaveLocations.Contains(Location)) - return allowsurf ? EncounterType.Headbutt_CaveSurf : EncounterType.Cave_HallOfOrigin; + return allowsurf + ? EncounterType.Cave_HallOfOrigin | EncounterType.Surfing_Fishing + : EncounterType.Cave_HallOfOrigin; // Routes and exterior areas // Routes with trees adjacent to grass tiles var allowgrass = HGSS_GrassHeadbutt_Locations.Contains(Location); - return allowgrass && allowsurf ? EncounterType.Headbutt_GrassSurf : - allowgrass ? EncounterType.Headbutt_Grass : - allowsurf ? EncounterType.Headbutt_Surf : - EncounterType.None; + if (allowgrass) + return allowsurf + ? EncounterType.TallGrass | EncounterType.Surfing_Fishing + : EncounterType.TallGrass; + + return allowsurf + ? EncounterType.Surfing_Fishing + : EncounterType.None; } private static void MarkHGSSEncounterTypeSlots(ref EncounterArea[] Areas) @@ -489,11 +494,11 @@ private static void MarkHGSSEncounterTypeSlots(ref EncounterArea[] Areas) 219, // Mt. Silver Cave 224, // Viridian Forest }; - private static readonly HashSet HGSS_MtSilverCaveExteriorEncounters = new HashSet + private static readonly int[] HGSS_MtSilverCaveExteriorEncounters = { 2, 3 }; - private static readonly HashSet HGSS_MixInteriorExteriorLocations = new HashSet + private static readonly int[] HGSS_MixInteriorExteriorLocations = { 209, // Ruins of Alph 219, // Mt. Silver Cave @@ -909,6 +914,7 @@ private static void MarkHGSSEncounterTypeSlots(ref EncounterArea[] Areas) Encounter_HGSS_Regular).ToArray(); #endregion #region Trade Tables + internal static readonly string[] RanchOTNames = { null, "ユカリ", "Hayley", "EULALIE", "GIULIA", "EUKALIA", "Eulalia" }; private static readonly EncounterTrade[] RanchGifts = { new EncounterTradePID { Species = 025, Level = 18, Moves = new[] {447,085,148,104}, TID = 1000, SID = 19840, OTGender = 1, Version = GameVersion.D, Location = 0068, Gender = 0, PID = 323975838, CurrentLevel = 20, }, // Pikachu @@ -936,26 +942,50 @@ private static void MarkHGSSEncounterTypeSlots(ref EncounterArea[] Areas) }; internal static readonly EncounterTrade[] TradeGift_DPPt = new[] { - new EncounterTrade { Species = 063, Ability = 1, TID = 25643, SID = 00000, OTGender = 1, Gender = 0, IVs = new[] {15,15,15,20,25,25}, Nature = Nature.Quiet,}, // Abra - new EncounterTrade { Species = 441, Ability = 2, TID = 44142, SID = 00000, OTGender = 0, Gender = 1, IVs = new[] {15,20,15,25,25,15}, Nature = Nature.Lonely, Contest = new[] {20,20,20,20,20,0} }, // Chatot - new EncounterTrade { Species = 093, Ability = 1, TID = 19248, SID = 00000, OTGender = 1, Gender = 0, IVs = new[] {20,25,15,25,15,15}, Nature = Nature.Hasty,}, // Haunter - new EncounterTrade { Species = 129, Ability = 1, TID = 53277, SID = 00000, OTGender = 0, Gender = 1, IVs = new[] {15,25,15,20,25,15}, Nature = Nature.Mild}, // Magikarp + new EncounterTradePID { Species = 063, Ability = 1, TID = 25643, SID = 00000, OTGender = 1, Gender = 0, IVs = new[] {15,15,15,20,25,25}, PID = 0x0000008E }, // Abra + new EncounterTradePID { Species = 441, Ability = 2, TID = 44142, SID = 00000, OTGender = 0, Gender = 1, IVs = new[] {15,20,15,25,25,15}, PID = 0x00000867, Contest = new[] {20,20,20,20,20,0} }, // Chatot + new EncounterTradePID { Species = 093, Ability = 1, TID = 19248, SID = 00000, OTGender = 1, Gender = 0, IVs = new[] {20,25,15,25,15,15}, PID = 0x00000088 }, // Haunter + new EncounterTradePID { Species = 129, Ability = 1, TID = 53277, SID = 00000, OTGender = 0, Gender = 1, IVs = new[] {15,25,15,20,25,15}, PID = 0x0000045C }, // Magikarp }.Concat(RanchGifts).ToArray(); internal static readonly EncounterTrade[] TradeGift_HGSS = { - new EncounterTrade { Species = 095, Ability = 2, TID = 48926, SID = 00000, OTGender = 0, Gender = 0, IVs = new[] {25,20,25,15,15,15}, Nature = Nature.Hasty,}, // Onix - new EncounterTrade { Species = 066, Ability = 1, TID = 37460, SID = 00000, OTGender = 0, Gender = 1, IVs = new[] {15,25,20,20,15,15}, Nature = Nature.Lonely,}, // Machop - new EncounterTrade { Species = 100, Ability = 2, TID = 29189, SID = 00000, OTGender = 0, Gender = 2, IVs = new[] {15,20,15,25,25,15}, Nature = Nature.Hardy,}, // Voltorb - new EncounterTrade { Species = 085, Ability = 1, TID = 00283, SID = 00000, OTGender = 1, Gender = 1, IVs = new[] {20,20,20,15,15,15}, Nature = Nature.Impish,}, // Dodrio - new EncounterTrade { Species = 082, Ability = 1, TID = 50082, SID = 00000, OTGender = 0, Gender = 2, IVs = new[] {15,20,15,20,20,20}, Nature = Nature.Impish,}, // Magneton - new EncounterTrade { Species = 178, Ability = 1, TID = 15616, SID = 00000, OTGender = 0, Gender = 0, IVs = new[] {15,20,15,20,20,20}, Nature = Nature.Modest,}, // Xatu - new EncounterTrade { Species = 025, Ability = 1, TID = 33038, SID = 00000, OTGender = 0, Gender = 1, IVs = new[] {20,25,18,31,25,13}, Nature = Nature.Jolly,}, // Pikachu - new EncounterTrade { Species = 374, Ability = 1, TID = 23478, SID = 00000, OTGender = 0, Gender = 2, IVs = new[] {28,29,24,23,24,25}, Nature = Nature.Brave,}, // Beldum - new EncounterTrade { Species = 111, Ability = 1, TID = 06845, SID = 00000, OTGender = 0, Gender = 1, IVs = new[] {22,31,13,00,22,09}, Nature = Nature.Relaxed, Moves= new[]{422} }, // Rhyhorn - new EncounterTrade { Species = 208, Ability = 1, TID = 26491, SID = 00000, OTGender = 1, Gender = 0, IVs = new[] {08,30,28,06,18,20}, Nature = Nature.Brave,}, // Steelix + new EncounterTradePID { Species = 095, Ability = 2, TID = 48926, SID = 00000, OTGender = 0, Gender = 0, IVs = new[] {25,20,25,15,15,15}, PID = 0x000025EF }, // Onix + new EncounterTradePID { Species = 066, Ability = 1, TID = 37460, SID = 00000, OTGender = 0, Gender = 1, IVs = new[] {15,25,20,20,15,15}, PID = 0x00002310 }, // Machop + new EncounterTradePID { Species = 100, Ability = 2, TID = 29189, SID = 00000, OTGender = 0, Gender = 2, IVs = new[] {15,20,15,25,25,15}, PID = 0x000001DB }, // Voltorb + new EncounterTradePID { Species = 085, Ability = 1, TID = 00283, SID = 00000, OTGender = 1, Gender = 1, IVs = new[] {20,20,20,15,15,15}, PID = 0x0001FC0A }, // Dodrio + new EncounterTradePID { Species = 082, Ability = 1, TID = 50082, SID = 00000, OTGender = 0, Gender = 2, IVs = new[] {15,20,15,20,20,20}, PID = 0x0000D136 }, // Magneton + new EncounterTradePID { Species = 178, Ability = 1, TID = 15616, SID = 00000, OTGender = 0, Gender = 0, IVs = new[] {15,20,15,20,20,20}, PID = 0x000034E4 }, // Xatu + new EncounterTradePID { Species = 025, Ability = 1, TID = 33038, SID = 00000, OTGender = 0, Gender = 1, IVs = new[] {20,25,18,31,25,13}, PID = 0x00485876 }, // Pikachu + new EncounterTradePID { Species = 374, Ability = 1, TID = 23478, SID = 00000, OTGender = 0, Gender = 2, IVs = new[] {28,29,24,23,24,25}, PID = 0x0012B6D4 }, // Beldum + new EncounterTradePID { Species = 111, Ability = 1, TID = 06845, SID = 00000, OTGender = 0, Gender = 1, IVs = new[] {22,31,13,00,22,09}, PID = 0x0012971C, Moves = new[]{422} }, // Rhyhorn + new EncounterTradePID { Species = 208, Ability = 1, TID = 26491, SID = 00000, OTGender = 1, Gender = 0, IVs = new[] {08,30,28,06,18,20}, PID = 0x00101596}, // Steelix //Gift - new EncounterTrade { Species = 021, Ability = 1, TID = 01001, SID = 00000, OTGender = 0, Gender = 1, Nature = Nature.Hasty, Level = 20, Location = 183, Moves= new[]{043,031,228,332}},//Webster's Spearow - new EncounterTrade { Species = 213, Ability = 2, TID = 04336, SID = 00001, OTGender = 0, Gender = 0, Nature = Nature.Relaxed, Level = 20, Location = 130, Moves= new[]{132,117,227,219}},//Kirk's Shuckle + new EncounterTradePID { Species = 021, Ability = 1, TID = 01001, SID = 00000, OTGender = 0, Gender = 1, IVs = new[] {15,20,15,20,20,20}, PID = 0x00006B5E, Level = 20, Location = 183, Moves = new[]{043,031,228,332} },// Webster's Spearow + new EncounterTradePID { Species = 213, Ability = 2, TID = 04336, SID = 00001, OTGender = 0, Gender = 0, IVs = new[] {15,20,15,20,20,20}, PID = 0x000214D7, Level = 20, Location = 130, Moves = new[]{132,117,227,219} },// Kirk's Shuckle + }; + internal static readonly string[][] TradeDPPt = + { + new string[0], // 0 - None + Util.GetStringList("tradedppt", "ja"), // 1 + Util.GetStringList("tradedppt", "en"), // 2 + Util.GetStringList("tradedppt", "fr"), // 3 + Util.GetStringList("tradedppt", "it"), // 4 + Util.GetStringList("tradedppt", "de"), // 5 + new string[0], // 6 - None + Util.GetStringList("tradedppt", "es"), // 7 + Util.GetStringList("tradedppt", "ko"), // 8 + }; + internal static readonly string[][] TradeHGSS = + { + new string[0], // 0 - None + Util.GetStringList("tradehgss", "ja"), // 1 + Util.GetStringList("tradehgss", "en"), // 2 + Util.GetStringList("tradehgss", "fr"), // 3 + Util.GetStringList("tradehgss", "it"), // 4 + Util.GetStringList("tradehgss", "de"), // 5 + new string[0], // 6 - None + Util.GetStringList("tradehgss", "es"), // 7 + Util.GetStringList("tradehgss", "ko"), // 8 }; #endregion diff --git a/PKHeX.Core/Legality/Encounters/Data/Encounters5.cs b/PKHeX.Core/Legality/Encounters/Data/Encounters5.cs index 8059dcf18..d49646f41 100644 --- a/PKHeX.Core/Legality/Encounters/Data/Encounters5.cs +++ b/PKHeX.Core/Legality/Encounters/Data/Encounters5.cs @@ -4,6 +4,9 @@ namespace PKHeX.Core { + /// + /// Generation 5 Encounters + /// internal static class Encounters5 { internal static readonly EncounterArea[] SlotsB, SlotsW, SlotsB2, SlotsW2; @@ -629,16 +632,16 @@ private static void MarkG5Slots(ref EncounterArea[] Areas) internal static readonly EncounterTrade[] TradeGift_BW = { - new EncounterTrade { Species = 548, Level = 15, Ability = 1, TID = 39922, SID = 00000, OTGender = 1, Gender = 1, IVs = new[] {20,20,20,20,31,20}, Nature = Nature.Modest, Version = GameVersion.B, }, // Petilil - new EncounterTrade { Species = 546, Level = 15, Ability = 1, TID = 39922, SID = 00000, OTGender = 1, Gender = 1, IVs = new[] {20,20,20,20,31,20}, Nature = Nature.Modest, Version = GameVersion.W, }, // Cottonee - new EncounterTrade { Species = 550, Level = 25, Ability = 1, TID = 27646, SID = 00000, OTGender = 0, Gender = 0, IVs = new[] {20,31,20,20,20,20}, Nature = Nature.Adamant, Version = GameVersion.B, Form = 0, }, // Basculin-Red - new EncounterTrade { Species = 550, Level = 25, Ability = 1, TID = 27646, SID = 00000, OTGender = 0, Gender = 0, IVs = new[] {20,31,20,20,20,20}, Nature = Nature.Adamant, Version = GameVersion.W, Form = 1, }, // Basculin-Blue - new EncounterTrade { Species = 587, Level = 30, Ability = 1, TID = 11195, SID = 00000, OTGender = 0, Gender = 0, IVs = new[] {20,20,31,20,20,20}, Nature = Nature.Lax, }, // Emolga - new EncounterTrade { Species = 479, Level = 60, Ability = 1, TID = 54673, SID = 00000, OTGender = 1, Gender = 2, IVs = new[] {20,20,20,20,20,31}, Nature = Nature.Gentle, }, // Rotom - new EncounterTrade { Species = 446, Level = 60, Ability = 2, TID = 40217, SID = 00000, OTGender = 0, Gender = 0, IVs = new[] {31,20,20,20,20,20}, Nature = Nature.Serious, }, // Munchlax + new EncounterTradePID { Species = 548, Level = 15, Ability = 1, TID = 39922, SID = 00000, OTGender = 1, Gender = 1, IVs = new[] {20,20,20,20,31,20}, PID = 0x64000000, Version = GameVersion.B, }, // Petilil + new EncounterTradePID { Species = 546, Level = 15, Ability = 1, TID = 39922, SID = 00000, OTGender = 1, Gender = 1, IVs = new[] {20,20,20,20,31,20}, PID = 0x6400007E, Version = GameVersion.W, }, // Cottonee + new EncounterTradePID { Species = 550, Level = 25, Ability = 1, TID = 27646, SID = 00000, OTGender = 0, Gender = 0, IVs = new[] {20,31,20,20,20,20}, PID = 0x9400007F, Version = GameVersion.B, Form = 0, }, // Basculin-Red + new EncounterTradePID { Species = 550, Level = 25, Ability = 1, TID = 27646, SID = 00000, OTGender = 0, Gender = 0, IVs = new[] {20,31,20,20,20,20}, PID = 0x9400007F, Version = GameVersion.W, Form = 1, }, // Basculin-Blue + new EncounterTradePID { Species = 587, Level = 30, Ability = 1, TID = 11195, SID = 00000, OTGender = 0, Gender = 0, IVs = new[] {20,20,31,20,20,20}, PID = 0xD400007F, }, // Emolga + new EncounterTradePID { Species = 479, Level = 60, Ability = 1, TID = 54673, SID = 00000, OTGender = 1, Gender = 2, IVs = new[] {20,20,20,20,20,31}, PID = 0x2A000000, }, // Rotom + new EncounterTradePID { Species = 446, Level = 60, Ability = 2, TID = 40217, SID = 00000, OTGender = 0, Gender = 0, IVs = new[] {31,20,20,20,20,20}, PID = 0x6200001F, }, // Munchlax }; - internal static readonly EncounterTrade[] TradeGift_B2W2 = + internal static readonly EncounterTrade[] TradeGift_B2W2_Regular = { new EncounterTrade { Species = 548, Level = 20, Ability = 2, TID = 65217, SID = 00000, OTGender = 1, Gender = 1, IVs = new[] {20,20,20,20,31,20}, Nature = Nature.Timid, Version = GameVersion.B2, }, // Petilil new EncounterTrade { Species = 546, Level = 20, Ability = 1, TID = 05720, SID = 00001, OTGender = 0, Gender = 0, IVs = new[] {20,20,20,20,31,20}, Nature = Nature.Modest, Version = GameVersion.W2, }, // Cottonee @@ -647,6 +650,9 @@ private static void MarkG5Slots(ref EncounterArea[] Areas) new EncounterTrade { Species = 479, Level = 60, Ability = 1, TID = 54673, SID = 00000, OTGender = 1, Gender = 2, IVs = new[] {20,20,20,20,20,31}, Nature = Nature.Calm, }, // Rotom new EncounterTrade { Species = 424, Level = 40, Ability = 2, TID = 17074, SID = 00001, OTGender = 1, Gender = 0, IVs = new[] {20,20,20,31,20,20}, Nature = Nature.Jolly, }, // Ambipom new EncounterTrade { Species = 065, Level = 40, Ability = 1, TID = 17074, SID = 00001, OTGender = 1, Gender = 0, IVs = new[] {20,20,20,31,20,20}, Nature = Nature.Timid, }, // Alakazam + }; + internal static readonly EncounterTrade[] TradeGift_B2W2_YancyCurtis = + { // player is male new EncounterTrade { Species = 052, Level = 50, Ability = 4, TID = 10303, SID = 00000, OTGender = 1,}, new EncounterTrade { Species = 202, Level = 50, Ability = 4, TID = 10303, SID = 00000, OTGender = 1,}, @@ -674,6 +680,33 @@ private static void MarkG5Slots(ref EncounterArea[] Areas) new EncounterTrade { Species = 327, Level = 50, Ability = 4, TID = 54118, SID = 00000, OTGender = 0,}, new EncounterTrade { Species = 175, Level = 50, Ability = 4, TID = 54118, SID = 00000, OTGender = 0,}, }; + internal static readonly string[] TradeOT_B2W2_F = {null, "ルリ", "Yancy", "Brenda", "Sabine", "Lilì", null, "Belinda", "루리"}; + internal static readonly string[] TradeOT_B2W2_M = {null, "テツ", "Curtis", "Julien", "Markus", "Dadi", null, "Julián", "철권"}; + internal static readonly string[][] TradeBW = + { + new string[0], // 0 - None + Util.GetStringList("tradebw", "ja"), // 1 + Util.GetStringList("tradebw", "en"), // 2 + Util.GetStringList("tradebw", "fr"), // 3 + Util.GetStringList("tradebw", "it"), // 4 + Util.GetStringList("tradebw", "de"), // 5 + new string[0], // 6 - None + Util.GetStringList("tradebw", "es"), // 7 + Util.GetStringList("tradebw", "ko"), // 8 + }; + internal static readonly string[][] TradeB2W2 = + { + new string[0], // 0 - None + Util.GetStringList("tradeb2w2", "ja"), // 1 + Util.GetStringList("tradeb2w2", "en"), // 2 + Util.GetStringList("tradeb2w2", "fr"), // 3 + Util.GetStringList("tradeb2w2", "it"), // 4 + Util.GetStringList("tradeb2w2", "de"), // 5 + new string[0], // 6 - None + Util.GetStringList("tradeb2w2", "es"), // 7 + Util.GetStringList("tradeb2w2", "ko"), // 8 + }; + internal static readonly EncounterTrade[] TradeGift_B2W2 = TradeGift_B2W2_Regular.Concat(TradeGift_B2W2_YancyCurtis).ToArray(); #endregion #region Alt Slots diff --git a/PKHeX.Core/Legality/Encounters/Data/Encounters6.cs b/PKHeX.Core/Legality/Encounters/Data/Encounters6.cs index 7c4042f82..72e0db6c3 100644 --- a/PKHeX.Core/Legality/Encounters/Data/Encounters6.cs +++ b/PKHeX.Core/Legality/Encounters/Data/Encounters6.cs @@ -2,6 +2,9 @@ namespace PKHeX.Core { + /// + /// Generation 6 Encounters + /// internal static class Encounters6 { internal static readonly EncounterArea[] SlotsX, SlotsY, SlotsA, SlotsO; diff --git a/PKHeX.Core/Legality/Encounters/Data/Encounters7.cs b/PKHeX.Core/Legality/Encounters/Data/Encounters7.cs index 2a94afa13..1cfbc7f6c 100644 --- a/PKHeX.Core/Legality/Encounters/Data/Encounters7.cs +++ b/PKHeX.Core/Legality/Encounters/Data/Encounters7.cs @@ -3,6 +3,9 @@ namespace PKHeX.Core { + /// + /// Generation 7 Encounters + /// internal static class Encounters7 { internal static readonly EncounterArea[] SlotsSN, SlotsMN, SlotsUS, SlotsUM; @@ -167,6 +170,24 @@ private static void MarkG7SMSlots(ref EncounterArea[] Areas) { }; + internal static readonly string[][] TradeSM = + { + new string[0], // 0 - None + Util.GetStringList("tradesm", "ja"), // 1 + Util.GetStringList("tradesm", "en"), // 2 + Util.GetStringList("tradesm", "fr"), // 3 + Util.GetStringList("tradesm", "it"), // 4 + Util.GetStringList("tradesm", "de"), // 5 + new string[0], // 6 - None + Util.GetStringList("tradesm", "es"), // 7 + Util.GetStringList("tradesm", "ko"), // 8 + Util.GetStringList("tradesm", "zh"), // 9 + Util.GetStringList("tradesm", "zh"), // 10 + }; + internal static readonly string[][] TradeUSUM = + { + // todo + }; private static readonly EncounterArea[] Encounter_Pelago_SM = { diff --git a/PKHeX.Core/Legality/Encounters/Data/EncountersWC3.cs b/PKHeX.Core/Legality/Encounters/Data/EncountersWC3.cs index a1c22de86..d13fecb09 100644 --- a/PKHeX.Core/Legality/Encounters/Data/EncountersWC3.cs +++ b/PKHeX.Core/Legality/Encounters/Data/EncountersWC3.cs @@ -1,10 +1,18 @@ -using System.Linq; +using System.Collections.Generic; +using System.Linq; namespace PKHeX.Core { + /// + /// Generation 3 Gifts + /// + /// + /// Generation 3 has a wide range of PIDIV types and other restrictions, and was never consistently stored in raw bytes. + /// Normally we'd just load the data from a binary, but without raw data... hard-code everything by hand. + /// internal static class EncountersWC3 { - internal static readonly MysteryGift[] Encounter_Event3 = + internal static readonly MysteryGift[] Encounter_Event3_Special = { new WC3 { Species = 251, Level = 10, TID = 31121, OT_Gender = 1, OT_Name = "アゲト", CardTitle = "Agate Celebi", Method = PIDType.CXD, Shiny = false, Language = (int)LanguageID.Japanese }, new WC3 { Species = 025, Level = 10, TID = 31121, OT_Gender = 0, OT_Name = "コロシアム", CardTitle = "Colosseum Pikachu", Method = PIDType.CXD, Shiny = false, Language = (int)LanguageID.Japanese }, @@ -12,27 +20,30 @@ internal static class EncountersWC3 new WC3 { Species = 385, Level = 05, TID = 20043, OT_Gender = 0, OT_Name = "WISHMKR", CardTitle = "Wishmaker Jirachi", Method = PIDType.BACD_R, Language = (int)LanguageID.English }, new WC3 { Species = 251, Level = 10, TID = 31121, OT_Gender = 1, OT_Name = "AGATE", CardTitle = "Agate Celebi", Method = PIDType.CXD, Shiny = false, Language = (int)LanguageID.English, NotDistributed = true }, new WC3 { Species = 025, Level = 10, TID = 31121, OT_Gender = 0, OT_Name = "COLOS", CardTitle = "Colosseum Pikachu", Method = PIDType.CXD, Shiny = false, Language = (int)LanguageID.English, NotDistributed = true }, - - new WC3 { Species = 250, Level = 70, TID = 10048, OT_Gender = 0, OT_Name = "バトルやま", CardTitle = "Mt. Battle Ho-oh", Method = PIDType.CXD, Shiny = false, Language = (int)LanguageID.Japanese }, // JPN - new WC3 { Species = 250, Level = 70, TID = 10048, OT_Gender = 0, OT_Name = "MATTLE", CardTitle = "Mt. Battle Ho-oh", Method = PIDType.CXD, Shiny = false, Language = (int)LanguageID.English }, // ENG - new WC3 { Species = 250, Level = 70, TID = 10048, OT_Gender = 0, OT_Name = "MT BATA", CardTitle = "Mt. Battle Ho-oh", Method = PIDType.CXD, Shiny = false, Language = (int)LanguageID.French }, // FRE - new WC3 { Species = 250, Level = 70, TID = 10048, OT_Gender = 0, OT_Name = "DUELLBE", CardTitle = "Mt. Battle Ho-oh", Method = PIDType.CXD, Shiny = false, Language = (int)LanguageID.German }, // GER - new WC3 { Species = 250, Level = 70, TID = 10048, OT_Gender = 0, OT_Name = "MONTE L", CardTitle = "Mt. Battle Ho-oh", Method = PIDType.CXD, Shiny = false, Language = (int)LanguageID.Italian }, // ITA - new WC3 { Species = 250, Level = 70, TID = 10048, OT_Gender = 0, OT_Name = "ERNESTO", CardTitle = "Mt. Battle Ho-oh", Method = PIDType.CXD, Shiny = false, Language = (int)LanguageID.Spanish }, // SPA - - // CXD - new WC3 { Species = 239, Level = 20, Language = (int)LanguageID.English, Fateful = true, Met_Location = 164, TID = 41400, SID = -1, OT_Gender = 0, OT_Name = "HORDEL", CardTitle = "Trade Togepi", Method = PIDType.CXD, Moves = new[] {8,7,9,238} }, // Elekid @ Snagem Hideout - new WC3 { Species = 307, Level = 20, Language = (int)LanguageID.English, Fateful = true, Met_Location = 116, TID = 37149, SID = -1, OT_Gender = 0, OT_Name = "DUKING", CardTitle = "Trade Trapinch", Method = PIDType.CXD, Moves = new[] {223,93,247,197} }, // Meditite @ Pyrite Town - new WC3 { Species = 213, Level = 20, Language = (int)LanguageID.English, Fateful = true, Met_Location = 116, TID = 37149, SID = -1, OT_Gender = 0, OT_Name = "DUKING", CardTitle = "Trade Surskit", Method = PIDType.CXD, Moves = new[] {92,164,188,277} }, // Shuckle @ Pyrite Town - new WC3 { Species = 246, Level = 20, Language = (int)LanguageID.English, Fateful = true, Met_Location = 116, TID = 37149, SID = -1, OT_Gender = 0, OT_Name = "DUKING", CardTitle = "Trade Wooper", Method = PIDType.CXD, Moves = new[] {201,349,44,200} }, // Larvitar @ Pyrite Town - new WC3 { Species = 311, Level = 13, Language = (int)LanguageID.English, Fateful = false, Met_Location = 254, TID = 37149, OT_Gender = 0, OT_Name = "DUKING", CardTitle = "Gift", Method = PIDType.CXD }, // Plusle @ Ingame Trade - - new WC3 { Species = 239, Level = 20, Language = (int)LanguageID.Japanese, Fateful = true, Met_Location = 164, TID = 41400, SID = -1, OT_Gender = 0, OT_Name = "ダニー", CardTitle = "Trade Togepi", Method = PIDType.CXD, Moves = new[] {8,7,9,238} }, // Elekid @ Snagem Hideout - new WC3 { Species = 307, Level = 20, Language = (int)LanguageID.Japanese, Fateful = true, Met_Location = 116, TID = 37149, SID = -1, OT_Gender = 0, OT_Name = "ギンザル", CardTitle = "Trade Trapinch", Method = PIDType.CXD, Moves = new[] {223,93,247,197} }, // Meditite @ Pyrite Town - new WC3 { Species = 213, Level = 20, Language = (int)LanguageID.Japanese, Fateful = true, Met_Location = 116, TID = 37149, SID = -1, OT_Gender = 0, OT_Name = "ギンザル", CardTitle = "Trade Surskit", Method = PIDType.CXD, Moves = new[] {92,164,188,277} }, // Shuckle @ Pyrite Town - new WC3 { Species = 246, Level = 20, Language = (int)LanguageID.Japanese, Fateful = true, Met_Location = 116, TID = 37149, SID = -1, OT_Gender = 0, OT_Name = "ギンザル", CardTitle = "Trade Wooper", Method = PIDType.CXD, Moves = new[] {201,349,44,200} }, // Larvitar @ Pyrite Town - new WC3 { Species = 311, Level = 13, Language = (int)LanguageID.Japanese, Fateful = false, Met_Location = 254, TID = 37149, OT_Gender = 0, OT_Name = "ギンザル", CardTitle = "Gift", Method = PIDType.CXD }, // Plusle @ Ingame Trade }; + private static IEnumerable GetIngameCXDData() + { + var langs = new[]{LanguageID.Japanese, LanguageID.English, LanguageID.French, LanguageID.Italian, LanguageID.German, LanguageID.Spanish}; + var h = new[] {null, "ダニー", "HORDEL", "VOLKER", "ODINO", "HORAZ", null, "HORDEL"}; + var d = new[] {null, "ギンザル", "DUKING", "DOKING", "RODRIGO", "GRAND", null, "GERMÁN"}; + var m = new[] {null, "バトルやま", "MATTLE", "MT BATA", "MONTE L", "DUELLBE", null, "ERNESTO"}; + + return langs.SelectMany(l => GetIngame((int)l)); + IEnumerable GetIngame(int l) + { + var id = (LanguageID) l; + return new[] + { + new WC3 { Species = 239, Level = 20, Language = l, Fateful = true, Met_Location = 164, TID = 41400, SID = -1, OT_Gender = 0, OT_Name = h[l], CardTitle = $"Trade Togepi ({id})", Method = PIDType.CXD, Moves = new[] { 008, 007, 009, 238 } }, // Elekid @ Snagem Hideout + new WC3 { Species = 307, Level = 20, Language = l, Fateful = true, Met_Location = 116, TID = 37149, SID = -1, OT_Gender = 0, OT_Name = d[l], CardTitle = $"Trade Trapinch ({id})", Method = PIDType.CXD, Moves = new[] { 223, 093, 247, 197 } }, // Meditite @ Pyrite Town + new WC3 { Species = 213, Level = 20, Language = l, Fateful = true, Met_Location = 116, TID = 37149, SID = -1, OT_Gender = 0, OT_Name = d[l], CardTitle = $"Trade Surskit ({id})", Method = PIDType.CXD, Moves = new[] { 092, 164, 188, 277 } }, // Shuckle @ Pyrite Town + new WC3 { Species = 246, Level = 20, Language = l, Fateful = true, Met_Location = 116, TID = 37149, SID = -1, OT_Gender = 0, OT_Name = d[l], CardTitle = $"Trade Wooper ({id})", Method = PIDType.CXD, Moves = new[] { 201, 349, 044, 200 } }, // Larvitar @ Pyrite Town + new WC3 { Species = 311, Level = 13, Language = l, Fateful = false, Met_Location = 254, TID = 37149, SID = 0, OT_Gender = 0, OT_Name = d[l], CardTitle = $"Special Gift ({id})", Method = PIDType.CXD }, // Plusle @ Ingame Trade + new WC3 { Species = 250, Level = 70, Language = l, Fateful = false, /*loc already set*/ TID = 10048, SID = 0, OT_Gender = 0, OT_Name = m[l], CardTitle = $"Mt. Battle Ho-oh ({id})", Method = PIDType.CXD, Shiny = false } // Ho-oh @ Mt. Battle + }; + } + } + internal static readonly MysteryGift[] Encounter_Event3 = Encounter_Event3_Special.Concat(GetIngameCXDData()).ToArray(); internal static readonly MysteryGift[] Encounter_Event3_FRLG = { @@ -243,6 +254,5 @@ internal static class EncountersWC3 }; internal static readonly MysteryGift[] Encounter_WC3 = Encounter_Event3.Concat(Encounter_Event3_RS).Concat(Encounter_Event3_FRLG.Concat(Encounter_Event3_Common)).ToArray(); - } } diff --git a/PKHeX.Core/Legality/Encounters/EncounterEgg.cs b/PKHeX.Core/Legality/Encounters/EncounterEgg.cs index 755bfc174..a2f53bb53 100644 --- a/PKHeX.Core/Legality/Encounters/EncounterEgg.cs +++ b/PKHeX.Core/Legality/Encounters/EncounterEgg.cs @@ -1,5 +1,8 @@ namespace PKHeX.Core { + /// + /// Egg Encounter Data + /// public class EncounterEgg : IEncounterable { public int Species { get; set; } diff --git a/PKHeX.Core/Legality/Encounters/EncounterGenerator.cs b/PKHeX.Core/Legality/Encounters/EncounterGenerator.cs index f2bdff7fe..9ae6dd36f 100644 --- a/PKHeX.Core/Legality/Encounters/EncounterGenerator.cs +++ b/PKHeX.Core/Legality/Encounters/EncounterGenerator.cs @@ -139,8 +139,7 @@ private static IEnumerable GenerateRawEncounters12(PKM pkm, Gam if (s.Version == GameVersion.EventsGBGen2 && s.Species != 251) { // no Gen2 events outside of Japan besides Celebi - var jp = (pkm as PK2)?.Japanese ?? (pkm as PK1)?.Japanese; - if (jp == true) + if (pkm.Japanese) deferred.Add(s); continue; } @@ -266,10 +265,10 @@ private static IEnumerable GenerateRawEncounters(PKM pkm) } private static IEnumerable GenerateRawEncounters4(PKM pkm) { - int ctr = 0; bool wasEvent = pkm.WasEvent || pkm.WasEventEgg; // egg events? if (wasEvent) { + int ctr = 0; foreach (var z in GetValidGifts(pkm)) { yield return z; ++ctr; } if (ctr != 0) yield break; @@ -277,7 +276,7 @@ private static IEnumerable GenerateRawEncounters4(PKM pkm) if (pkm.WasEgg) { foreach (var z in GenerateEggs(pkm)) - { yield return z; ++ctr; } + yield return z; } var deferred = new List(); @@ -288,17 +287,12 @@ private static IEnumerable GenerateRawEncounters4(PKM pkm) if (z.Gift && pkm.Ball != 4) deferred.Add(z); else - { - yield return z; ++ctr; - } + yield return z; } - // if (ctr != 0) yield break; - foreach (var z in GetValidWildEncounters(pkm)) - { yield return z; ++ctr; } - if (ctr != 0 && pkm.HasOriginalMetLocation && pkm.TID != 1000) yield break; // EncounterTrade abra/gengar will match wild slots foreach (var z in GetValidEncounterTrades(pkm)) - { yield return z; ++ctr; } - if (ctr != 0) yield break; + yield return z; + foreach (var z in GetValidWildEncounters(pkm)) + yield return z; // do static encounters if they were deferred to end, spit out any possible encounters for invalid pkm if (safariSport) @@ -327,17 +321,14 @@ private static IEnumerable GenerateRawEncounters3(PKM pkm) foreach (var z in GetValidEncounterTrades(pkm)) yield return z; + if (pkm.Version != 15) // no eggs in C/XD + foreach (var z in GenerateEggs(pkm)) + yield return z; + // do static encounters if they were deferred to end, spit out any possible encounters for invalid pkm if (safari) foreach (var z in GetValidStaticEncounter(pkm)) yield return z; - - if (pkm.Version == 15) - yield break; // no eggs in C/XD - - foreach (var z in GenerateEggs(pkm)) - yield return z; - foreach (var z in deferred) yield return z; } @@ -779,7 +770,7 @@ private static IEnumerable GetValidLinkGifts(PKM pkm) case 6: return Encounters6.LinkGifts6.Where(g => g.Species == pkm.Species && g.Level == pkm.Met_Level); default: - return new EncounterLink[0]; + return Enumerable.Empty(); } } @@ -976,7 +967,7 @@ private static IEnumerable GetValidGifts(PKM pkm) case 7: return GetMatchingWC7(pkm, MGDB_G7); default: - return new List(); + return Enumerable.Empty(); } } private static IEnumerable GetMatchingWC3(PKM pkm, IEnumerable DB) diff --git a/PKHeX.Core/Legality/Encounters/EncounterInvalid.cs b/PKHeX.Core/Legality/Encounters/EncounterInvalid.cs index 841397fc8..4ca7466aa 100644 --- a/PKHeX.Core/Legality/Encounters/EncounterInvalid.cs +++ b/PKHeX.Core/Legality/Encounters/EncounterInvalid.cs @@ -1,5 +1,8 @@ namespace PKHeX.Core { + /// + /// Invalid Encounter Data + /// public class EncounterInvalid : IEncounterable { public int Species { get; } diff --git a/PKHeX.Core/Legality/Encounters/EncounterRejected.cs b/PKHeX.Core/Legality/Encounters/EncounterRejected.cs index 4bfebf328..c39bb2777 100644 --- a/PKHeX.Core/Legality/Encounters/EncounterRejected.cs +++ b/PKHeX.Core/Legality/Encounters/EncounterRejected.cs @@ -1,5 +1,8 @@ namespace PKHeX.Core { + /// + /// Rejected Encounter Data containing a reason why the encounter was rejected (not compatible). + /// public class EncounterRejected : IEncounterable { public readonly IEncounterable Encounter; diff --git a/PKHeX.Core/Legality/Encounters/EncounterSuggestion.cs b/PKHeX.Core/Legality/Encounters/EncounterSuggestion.cs index c1cb99223..a05525a6e 100644 --- a/PKHeX.Core/Legality/Encounters/EncounterSuggestion.cs +++ b/PKHeX.Core/Legality/Encounters/EncounterSuggestion.cs @@ -2,6 +2,9 @@ namespace PKHeX.Core { + /// + /// Logic for providing suggested property values with respect to the input data. + /// internal static class EncounterSuggestion { public static EncounterStatic GetSuggestedMetInfo(PKM pkm) @@ -95,6 +98,8 @@ public static int GetSuggestedEggMetLocation(PKM pkm) case GameVersion.B: case GameVersion.W: + case GameVersion.B2: + case GameVersion.W2: return 16; // Route 3 case GameVersion.X: diff --git a/PKHeX.Core/Legality/Encounters/LegalInfo.cs b/PKHeX.Core/Legality/Encounters/LegalInfo.cs index 72cbddbc1..2e80afb54 100644 --- a/PKHeX.Core/Legality/Encounters/LegalInfo.cs +++ b/PKHeX.Core/Legality/Encounters/LegalInfo.cs @@ -3,6 +3,9 @@ namespace PKHeX.Core { + /// + /// Calculated Information storage with properties useful for parsing the legality of the input . + /// public class LegalInfo { /// The object used for comparisons. diff --git a/PKHeX.Core/Legality/Encounters/PeekEnumerator.cs b/PKHeX.Core/Legality/Encounters/PeekEnumerator.cs index a82318b91..da06736bc 100644 --- a/PKHeX.Core/Legality/Encounters/PeekEnumerator.cs +++ b/PKHeX.Core/Legality/Encounters/PeekEnumerator.cs @@ -4,6 +4,10 @@ namespace PKHeX.Core { + /// + /// Iterates a generic collection with the ability to peek into the collection to see if the next element exists. + /// + /// Generic Collection Element Type public class PeekEnumerator : IEnumerator { private readonly IEnumerator Enumerator; @@ -12,6 +16,10 @@ public class PeekEnumerator : IEnumerator #region IEnumerator Implementation + /// + /// Advances the enumerator to the next element in the collection. + /// + /// Indication if there are more elements in the collection. public bool MoveNext() { if (!didPeek) @@ -19,6 +27,9 @@ public bool MoveNext() didPeek = false; return true; } + /// + /// Sets the enumerator to its initial position, which is before the first element in the collection. + /// public void Reset() { Enumerator.Reset(); diff --git a/PKHeX.Core/Legality/Encounters/VerifyCurrentMoves.cs b/PKHeX.Core/Legality/Encounters/VerifyCurrentMoves.cs index 354231a91..5c645751e 100644 --- a/PKHeX.Core/Legality/Encounters/VerifyCurrentMoves.cs +++ b/PKHeX.Core/Legality/Encounters/VerifyCurrentMoves.cs @@ -6,6 +6,9 @@ namespace PKHeX.Core { + /// + /// Logic to verify the current . + /// public static class VerifyCurrentMoves { public static CheckMoveResult[] VerifyMoves(PKM pkm, LegalInfo info, GameVersion game = GameVersion.Any) diff --git a/PKHeX.Core/Legality/Encounters/VerifyRelearnMoves.cs b/PKHeX.Core/Legality/Encounters/VerifyRelearnMoves.cs index 8c0d186c6..af5a2be6d 100644 --- a/PKHeX.Core/Legality/Encounters/VerifyRelearnMoves.cs +++ b/PKHeX.Core/Legality/Encounters/VerifyRelearnMoves.cs @@ -6,6 +6,9 @@ namespace PKHeX.Core { + /// + /// Logic to verify the current . + /// public static class VerifyRelearnMoves { public static CheckResult[] VerifyRelearn(PKM pkm, LegalInfo info) diff --git a/PKHeX.Core/Legality/LegalityCheckStrings.cs b/PKHeX.Core/Legality/LegalityCheckStrings.cs index cac381bd3..f767ce5c2 100644 --- a/PKHeX.Core/Legality/LegalityCheckStrings.cs +++ b/PKHeX.Core/Legality/LegalityCheckStrings.cs @@ -3,6 +3,9 @@ namespace PKHeX.Core { + /// + /// Legality Check Message Strings to indicate why certain values are flagged. + /// public static class LegalityCheckStrings { diff --git a/PKHeX.Core/Legality/Structures/CheckMoveResult.cs b/PKHeX.Core/Legality/Structures/CheckMoveResult.cs index e3ce6ca86..7ef93d69b 100644 --- a/PKHeX.Core/Legality/Structures/CheckMoveResult.cs +++ b/PKHeX.Core/Legality/Structures/CheckMoveResult.cs @@ -1,5 +1,8 @@ namespace PKHeX.Core { + /// + /// Source the Move was learned from + /// public enum MoveSource { Unknown, @@ -17,6 +20,9 @@ public enum MoveSource Sketch, } + /// + /// Move specific to contain in which Generation it was learned & source. + /// public class CheckMoveResult : CheckResult { public readonly MoveSource Source; diff --git a/PKHeX.Core/Legality/Structures/CheckResult.cs b/PKHeX.Core/Legality/Structures/CheckResult.cs index e84ea823a..36bd07cc1 100644 --- a/PKHeX.Core/Legality/Structures/CheckResult.cs +++ b/PKHeX.Core/Legality/Structures/CheckResult.cs @@ -1,5 +1,8 @@ namespace PKHeX.Core { + /// + /// Result of a Legality Check + /// public class CheckResult { internal readonly Severity Judgement = Severity.Valid; diff --git a/PKHeX.Core/Legality/Structures/EncounterArea.cs b/PKHeX.Core/Legality/Structures/EncounterArea.cs index 6acdd7c53..3423045b1 100644 --- a/PKHeX.Core/Legality/Structures/EncounterArea.cs +++ b/PKHeX.Core/Legality/Structures/EncounterArea.cs @@ -4,12 +4,26 @@ namespace PKHeX.Core { + /// + /// Represents an Area where can be encountered, which contains a Location ID and data. + /// public class EncounterArea { public int Location; public EncounterSlot[] Slots; + + /// + /// Creates an empty encounter area ready for initialization. + /// public EncounterArea() { } + /// + /// Creates an array of encounter data with a specified location ID. + /// + /// Encounter data + /// + /// Encounter Data is stored in the following format: (u16 Location, n*[u16 Species/Form, u8 Min, u8 Max]) + /// private EncounterArea(byte[] data) { Location = BitConverter.ToUInt16(data, 0); @@ -49,10 +63,10 @@ public EncounterArea[] Clone(int[] locations) return Areas; } - private static EncounterSlot1[] GetSlots1_GW(byte[] data, ref int ofs, SlotType t) + private static IEnumerable GetSlots1_GW(byte[] data, ref int ofs, SlotType t) { int rate = data[ofs++]; - return rate == 0 ? new EncounterSlot1[0] : ReadSlots(data, ref ofs, 10, t, rate); + return rate == 0 ? Enumerable.Empty() : ReadSlots(data, ref ofs, 10, t, rate); } private static EncounterSlot1[] GetSlots1_F(byte[] data, ref int ofs) { @@ -85,7 +99,7 @@ private static EncounterSlot1[] GetSlots2_GW(byte[] data, ref int ofs, SlotType return slots; } - private static EncounterSlot1[] GetSlots2_F(byte[] data, ref int ofs, SlotType t) + private static List GetSlots2_F(byte[] data, ref int ofs, SlotType t) { // slot set ends in 0xFF 0x** 0x** var slots = new List(); @@ -109,7 +123,7 @@ private static EncounterSlot1[] GetSlots2_F(byte[] data, ref int ofs, SlotType t if (rate == 0xFF) break; } - return slots.ToArray(); + return slots; } private static EncounterSlot1[] GetSlots2_H(byte[] data, ref int ofs, SlotType t) { @@ -916,6 +930,11 @@ public static EncounterArea[] GetSimpleEncounterArea(IEnumerable species, i return new[] { new EncounterArea { Location = location, Slots = l.ToArray() } }; } + /// + /// Gets an array of areas from an array of raw area data + /// + /// Simplified raw format of an Area + /// Array of areas public static EncounterArea[] GetArray(byte[][] entries) { if (entries == null) diff --git a/PKHeX.Core/Legality/Structures/EncounterLink.cs b/PKHeX.Core/Legality/Structures/EncounterLink.cs index 90beb3b56..20482a790 100644 --- a/PKHeX.Core/Legality/Structures/EncounterLink.cs +++ b/PKHeX.Core/Legality/Structures/EncounterLink.cs @@ -1,5 +1,8 @@ namespace PKHeX.Core { + /// + /// Pokémon Link Encounter Data + /// public class EncounterLink : IEncounterable, IRibbonSetEvent4, IMoveset { public int Species { get; set; } diff --git a/PKHeX.Core/Legality/Structures/EncounterLock.cs b/PKHeX.Core/Legality/Structures/EncounterLock.cs index 815cdf383..eff652907 100644 --- a/PKHeX.Core/Legality/Structures/EncounterLock.cs +++ b/PKHeX.Core/Legality/Structures/EncounterLock.cs @@ -1,6 +1,9 @@ namespace PKHeX.Core { - // Gender Locking + /// + /// Encounter lock values restricting certain properties to a fixed value. + /// + /// Used in Colosseum/XD to ensure that non-shadow are of a certain Nature/etc. public class EncounterLock { public int Species { get; set; } diff --git a/PKHeX.Core/Legality/Structures/EncounterSlot.cs b/PKHeX.Core/Legality/Structures/EncounterSlot.cs index 4f2c733f6..cca8a1216 100644 --- a/PKHeX.Core/Legality/Structures/EncounterSlot.cs +++ b/PKHeX.Core/Legality/Structures/EncounterSlot.cs @@ -14,6 +14,9 @@ public class EncounterSlotPermissions public bool IsNormalLead => !(WhiteFlute || BlackFlute || DexNav); public bool IsDexNav => AllowDexNav && DexNav; } + /// + /// Wild Encounter Slot data + /// public class EncounterSlot : IEncounterable, IGeneration { public int Location { get; set; } = -1; @@ -53,10 +56,18 @@ public string Name } } } + + /// + /// Generation 1 Wild Encounter Slot data + /// + /// + /// Contains Time data which is present in origin data. + /// Contains identification, as this Version value is not stored in or formats. + /// public class EncounterSlot1 : EncounterSlot { public int Rate; - public EncounterTime Time = EncounterTime.Any; + internal EncounterTime Time = EncounterTime.Any; public GameVersion Version = GameVersion.Any; public override EncounterSlot Clone() { diff --git a/PKHeX.Core/Legality/Structures/EncounterStatic.cs b/PKHeX.Core/Legality/Structures/EncounterStatic.cs index 5cc14b8ab..290b86787 100644 --- a/PKHeX.Core/Legality/Structures/EncounterStatic.cs +++ b/PKHeX.Core/Legality/Structures/EncounterStatic.cs @@ -1,5 +1,13 @@ -namespace PKHeX.Core +using System.Collections.Generic; + +namespace PKHeX.Core { + /// + /// Static Encounter Data + /// + /// + /// Static Encounters are fixed position encounters with properties that are not subject to Wild Encounter conditions. + /// public class EncounterStatic : IEncounterable, IMoveset, IGeneration { public int Species { get; set; } @@ -72,15 +80,13 @@ public virtual EncounterStatic Clone(int location) }; } - public EncounterStatic[] DreamRadarClone() + public IEnumerable DreamRadarClone() { - EncounterStatic[] Encounters = new EncounterStatic[8]; for (int i = 0; i < 8; i++) - Encounters[i] = DreamRadarClone(5 * i + 5); //Level from 5->40 depends on the number of badage - return Encounters; + yield return DreamRadarClone(5 * i + 5); //Level from 5->40 depends on the number of badges } - public EncounterStatic DreamRadarClone(int level) + private EncounterStatic DreamRadarClone(int level) { return new EncounterStatic { diff --git a/PKHeX.Core/Legality/Structures/EncounterTime.cs b/PKHeX.Core/Legality/Structures/EncounterTime.cs index 050bf7b6f..45a56219f 100644 --- a/PKHeX.Core/Legality/Structures/EncounterTime.cs +++ b/PKHeX.Core/Legality/Structures/EncounterTime.cs @@ -1,6 +1,9 @@ namespace PKHeX.Core { - public enum EncounterTime + /// + /// Generation 2 Time of Encounter enum + /// + internal enum EncounterTime { Any = -1, MorningDay = -2, @@ -9,9 +12,9 @@ public enum EncounterTime Night = 3 } - public static class EncounterTimeExtension + internal static class EncounterTimeExtension { - public static bool Contains(this EncounterTime t1, int t2) => t1.Contains((EncounterTime)t2); + internal static bool Contains(this EncounterTime t1, int t2) => t1.Contains((EncounterTime)t2); private static bool Contains(this EncounterTime t1, EncounterTime t2) { if (t1 == t2 || t1 == EncounterTime.Any || t2 == EncounterTime.Any) diff --git a/PKHeX.Core/Legality/Structures/EncounterTrade.cs b/PKHeX.Core/Legality/Structures/EncounterTrade.cs index 48f4e4ccf..4c3d8a910 100644 --- a/PKHeX.Core/Legality/Structures/EncounterTrade.cs +++ b/PKHeX.Core/Legality/Structures/EncounterTrade.cs @@ -1,5 +1,11 @@ namespace PKHeX.Core { + /// + /// Trade Encounter data + /// + /// + /// Trade data is fixed level in all cases except for the first few generations of games. + /// public class EncounterTrade : IEncounterable, IMoveset, IGeneration { public int Species { get; set; } @@ -36,11 +42,20 @@ public class EncounterTrade : IEncounterable, IMoveset, IGeneration }; } + /// + /// Trade Encounter data with a fixed PID. + /// public class EncounterTradePID : EncounterTrade { public uint PID; } + /// + /// Trade Encounter data with a fixed Catch Rate + /// + /// + /// Generation 1 specific value used in detecting unmodified/untraded Generation 1 Trade Encounter data. + /// public class EncounterTradeCatchRate : EncounterTrade { public uint Catch_Rate; diff --git a/PKHeX.Core/Legality/Structures/EncounterType.cs b/PKHeX.Core/Legality/Structures/EncounterType.cs index a2c329cb2..53a4c4964 100644 --- a/PKHeX.Core/Legality/Structures/EncounterType.cs +++ b/PKHeX.Core/Legality/Structures/EncounterType.cs @@ -1,48 +1,36 @@ -namespace PKHeX.Core +using System; + +namespace PKHeX.Core { + /// + /// Tile type the was encountered from. + /// + /// + /// 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. + /// Some locations have multiple tile types, requiring multiple values possible. + /// + [Flags] public enum EncounterType { - Headbutt_Grass = -1, // None or TallGrass - Headbutt_Surf = -2, // None or Surfing_Fishing - Headbutt_GrassSurf = -3, // None, TallGrass or Surfing_Fishing - Headbutt_CitySurf = -4, // Building_EnigmaStone or Surfing_Fishing - Headbutt_CaveSurf = -5, // Cave_HallOfOrigin or Surfing_Fishing - None = 0, - RockSmash = 1, - TallGrass = 2, - DialgaPalkia = 4, - Cave_HallOfOrigin = 5, - Surfing_Fishing = 7, - Building_EnigmaStone = 9, - MarshSafari = 10, - Starter_Fossil_Gift_DP = 12, - DistortionWorld_Pt = 23, - Starter_Fossil_Gift_Pt_DPTrio = 24, + None = 1 << 00, + RockSmash = 1 << 01, + TallGrass = 1 << 02, + DialgaPalkia = 1 << 04, + Cave_HallOfOrigin = 1 << 05, + Surfing_Fishing = 1 << 07, + Building_EnigmaStone = 1 << 09, + MarshSafari = 1 << 10, + Starter_Fossil_Gift_DP = 1 << 12, + DistortionWorld_Pt = 1 << 23, + Starter_Fossil_Gift_Pt_DPTrio = 1 << 24, } public static class EncounterTypeExtension { public static bool Contains(this EncounterType g1, int g2) { - return g1.Contains((EncounterType)g2); - } - private static bool Contains(this EncounterType g1, EncounterType g2) - { - switch (g1) - { - case EncounterType.Headbutt_Grass: - return g2 == EncounterType.None || g2 == EncounterType.TallGrass; - case EncounterType.Headbutt_Surf: - return g2 == EncounterType.None || g2 == EncounterType.Surfing_Fishing; - case EncounterType.Headbutt_GrassSurf: - return EncounterType.Headbutt_Grass.Contains(g2) || g2 == EncounterType.Surfing_Fishing; - case EncounterType.Headbutt_CitySurf: - return g2 == EncounterType.Building_EnigmaStone || g2 == EncounterType.Surfing_Fishing; - case EncounterType.Headbutt_CaveSurf: - return g2 == EncounterType.Cave_HallOfOrigin || g2 == EncounterType.Surfing_Fishing; - } - - return g1 == g2; + var type = (EncounterType)(1 << g2); + return (g1 & type) != 0; } } } diff --git a/PKHeX.Core/Legality/Structures/EvolutionTree.cs b/PKHeX.Core/Legality/Structures/EvolutionTree.cs index 659d74e0f..38c2d84e1 100644 --- a/PKHeX.Core/Legality/Structures/EvolutionTree.cs +++ b/PKHeX.Core/Legality/Structures/EvolutionTree.cs @@ -4,6 +4,12 @@ namespace PKHeX.Core { + /// + /// Generation specific Evolution Tree data. + /// + /// + /// Used to determine if a can evolve from prior steps in its evolution branch. + /// public class EvolutionTree { private static readonly EvolutionTree Evolves1; @@ -207,10 +213,16 @@ public IEnumerable GetValidPreEvolutions(PKM pkm, int maxLevel, int ma } } + /// + /// Table of Evolution Branch Entries + /// public abstract class EvolutionSet { public EvolutionMethod[] PossibleEvolutions; } + /// + /// Generation 1 Evolution Branch Entries + /// public class EvolutionSet1 : EvolutionSet { private static EvolutionMethod GetMethod(byte[] data, ref int offset) @@ -263,6 +275,9 @@ public static List GetArray(byte[] data, int maxSpecies) return evos; } } + /// + /// Generation 2 Evolution Branch Entries + /// public class EvolutionSet2 : EvolutionSet { private static EvolutionMethod GetMethod(byte[] data, ref int offset) @@ -299,6 +314,9 @@ public static List GetArray(byte[] data, int maxSpecies) return evos; } } + /// + /// Generation 3 Evolution Branch Entries + /// public class EvolutionSet3 : EvolutionSet { private static EvolutionMethod GetMethod(byte[] data, int offset) @@ -358,6 +376,9 @@ public static List GetArray(byte[] data) return evos.ToList(); } } + /// + /// Generation 4 Evolution Branch Entries + /// public class EvolutionSet4 : EvolutionSet { private static EvolutionMethod GetMethod(byte[] data, int offset) @@ -410,6 +431,9 @@ public static List GetArray(byte[] data) return evos; } } + /// + /// Generation 5 Evolution Branch Entries + /// public class EvolutionSet5 : EvolutionSet { private static EvolutionMethod GetMethod(byte[] data, int offset) @@ -457,6 +481,9 @@ public static List GetArray(byte[] data) return evos; } } + /// + /// Generation 6 Evolution Branch Entries + /// public class EvolutionSet6 : EvolutionSet { private static readonly HashSet argEvos = new HashSet {6, 8, 16, 17, 18, 19, 20, 21, 22, 29, 30, 32, 33, 34}; @@ -484,6 +511,9 @@ public EvolutionSet6(byte[] data) } } } + /// + /// Generation 7 Evolution Branch Entries + /// public class EvolutionSet7 : EvolutionSet { private const int SIZE = 8; @@ -503,6 +533,10 @@ public EvolutionSet7(byte[] data) } } } + + /// + /// Criteria for evolving to this branch in the + /// public class EvolutionMethod { public int Method; @@ -624,7 +658,9 @@ public EvolutionMethod Copy(int species = -1) } } - // Informatics + /// + /// Informatics pertaining to a 's evolution lineage. + /// public class EvolutionLineage { public readonly List Chain = new List(); @@ -720,6 +756,9 @@ private static void UpdateMinValues(IReadOnlyCollection dl, EvolutionM last.RequiresLvlUp = evo.RequiresLevelUp; } } + /// + /// Evolution Stage Entries + /// public struct EvolutionStage { public List StageEntryMethods; diff --git a/PKHeX.Core/Legality/Structures/GBEncounterData.cs b/PKHeX.Core/Legality/Structures/GBEncounterData.cs index 7adb07b15..29ae9cfb7 100644 --- a/PKHeX.Core/Legality/Structures/GBEncounterData.cs +++ b/PKHeX.Core/Legality/Structures/GBEncounterData.cs @@ -2,7 +2,10 @@ namespace PKHeX.Core { - public enum GBEncounterType + /// + /// Generation 1/2 Encounter Data type, which serves as a 'best match' priority rating when returning from a list. + /// + internal enum GBEncounterType { EggEncounter, WildEncounter, @@ -12,12 +15,15 @@ public enum GBEncounterType TradeEncounterG2, } + /// + /// Generation 1/2 Encounter Data wrapper for storing supplemental information about the encounter. + /// public class GBEncounterData : IEncounterable { - public readonly int Level; + private readonly int Level; public readonly GameVersion Game; public readonly int Generation; - public readonly GBEncounterType Type; + internal readonly GBEncounterType Type; public readonly IEncounterable Encounter; public int Species => Encounter.Species; diff --git a/PKHeX.Core/Legality/Structures/IEncounterable.cs b/PKHeX.Core/Legality/Structures/IEncounterable.cs index 42cf68b51..2156bb3f2 100644 --- a/PKHeX.Core/Legality/Structures/IEncounterable.cs +++ b/PKHeX.Core/Legality/Structures/IEncounterable.cs @@ -1,5 +1,8 @@ namespace PKHeX.Core { + /// + /// Common Encounter Properties base interface. + /// public interface IEncounterable { int Species { get; } @@ -17,15 +20,13 @@ private static bool IsWithinRange(this IEncounterable encounter, int lvl) } public static bool IsWithinRange(this IEncounterable encounter, PKM pkm) { - if (pkm.HasOriginalMetLocation) - { - if (encounter.EggEncounter) - return pkm.CurrentLevel == Legal.GetEggHatchLevel(pkm); - if (encounter is MysteryGift g) - return pkm.CurrentLevel == g.Level; - return pkm.CurrentLevel == pkm.Met_Level; - } - return encounter.IsWithinRange(pkm.CurrentLevel); + if (!pkm.HasOriginalMetLocation) + return encounter.IsWithinRange(pkm.CurrentLevel); + if (encounter.EggEncounter) + return pkm.CurrentLevel == Legal.GetEggHatchLevel(pkm); + if (encounter is MysteryGift g) + return pkm.CurrentLevel == g.Level; + return pkm.CurrentLevel == pkm.Met_Level; } internal static string GetEncounterTypeName(this IEncounterable Encounter) => Encounter?.Name ?? "Unknown"; } diff --git a/PKHeX.Core/Legality/Structures/IGeneration.cs b/PKHeX.Core/Legality/Structures/IGeneration.cs index e49264c0a..911c982d1 100644 --- a/PKHeX.Core/Legality/Structures/IGeneration.cs +++ b/PKHeX.Core/Legality/Structures/IGeneration.cs @@ -1,5 +1,8 @@ namespace PKHeX.Core { + /// + /// Interface that exposes a Generation value for the object. + /// internal interface IGeneration { int Generation { get; } diff --git a/PKHeX.Core/Legality/Structures/IMoveset.cs b/PKHeX.Core/Legality/Structures/IMoveset.cs index 423cd4d37..63f53badc 100644 --- a/PKHeX.Core/Legality/Structures/IMoveset.cs +++ b/PKHeX.Core/Legality/Structures/IMoveset.cs @@ -1,5 +1,8 @@ namespace PKHeX.Core { + /// + /// Interface that exposes a Moveset for the object. + /// internal interface IMoveset { int[] Moves { get; set; } diff --git a/PKHeX.Core/Legality/Structures/Nature.cs b/PKHeX.Core/Legality/Structures/Nature.cs index c737b4806..73ce7038e 100644 --- a/PKHeX.Core/Legality/Structures/Nature.cs +++ b/PKHeX.Core/Legality/Structures/Nature.cs @@ -1,5 +1,8 @@ namespace PKHeX.Core { + /// + /// Nature ID values for the corresponding English nature name. + /// public enum Nature { Random = -1, diff --git a/PKHeX.Core/Legality/Structures/SlotType.cs b/PKHeX.Core/Legality/Structures/SlotType.cs index 7e6741735..d82226df7 100644 --- a/PKHeX.Core/Legality/Structures/SlotType.cs +++ b/PKHeX.Core/Legality/Structures/SlotType.cs @@ -1,5 +1,10 @@ namespace PKHeX.Core { + /// + /// Wild Encounter data Type + /// + /// + /// Different from , this corresponds to the method that the may be encountered. public enum SlotType { Any, diff --git a/PKHeX.Core/Legality/Structures/TradebackType.cs b/PKHeX.Core/Legality/Structures/TradebackType.cs index 02d28c12f..83bc9eb92 100644 --- a/PKHeX.Core/Legality/Structures/TradebackType.cs +++ b/PKHeX.Core/Legality/Structures/TradebackType.cs @@ -1,5 +1,9 @@ namespace PKHeX.Core { + /// + /// Indicates if the is required to be traded between Generation 1/2 saves. + /// + /// Used for only Generation 1/2 data. public enum TradebackType { Any, diff --git a/PKHeX.Core/Legality/Structures/ValidEncounterMoves.cs b/PKHeX.Core/Legality/Structures/ValidEncounterMoves.cs index 99082e965..154c0414e 100644 --- a/PKHeX.Core/Legality/Structures/ValidEncounterMoves.cs +++ b/PKHeX.Core/Legality/Structures/ValidEncounterMoves.cs @@ -3,6 +3,9 @@ namespace PKHeX.Core { + /// + /// Object which stores information useful for analyzing a moveset relative to the encounter data. + /// public class ValidEncounterMoves { public int EncounterSpecies { get; } diff --git a/PKHeX.Core/Legality/Tables7.cs b/PKHeX.Core/Legality/Tables7.cs index ee1544d72..08379a5f9 100644 --- a/PKHeX.Core/Legality/Tables7.cs +++ b/PKHeX.Core/Legality/Tables7.cs @@ -50,6 +50,13 @@ public static partial class Legal #endregion + internal static readonly int[][] Tutors_USUM = + { + new int[0], // todo + new int[0], // todo + new int[0], // todo + new int[0], // todo + }; internal static readonly ushort[] Pouch_Regular_SM = // 00 { 068, 069, 070, 071, 072, 073, 074, 075, 076, 077, 078, 079, 080, 081, 082, 083, 084, 085, 086, 087, @@ -83,6 +90,9 @@ public static partial class Legal 705, 706, 765, 773, 797, 841, 842, 843, 845, 847, 850, 857, 858, 860, }; + internal static readonly ushort[] Pouch_Key_USUM = { + // todo + }; internal static readonly ushort[] Pouch_TMHM_SM = { // 02 328, 329, 330, 331, 332, 333, 334, 335, 336, 337, 338, 339, 340, 341, 342, 343, 344, 345, 346, 347, 348, 349, 350, 351, 352, 353, 354, 355, 356, 357, 358, 359, 360, 361, 362, 363, @@ -106,8 +116,14 @@ public static partial class Legal internal static readonly ushort[] Pouch_ZCrystalHeld_SM = { // Piece 776, 777, 778, 779, 780, 781, 782, 783, 784, 785, 786, 787, 788, 789, 790, 791, 792, 793, 794, 798, 799, 800, 801, 802, 803, 804, 805, 806, 836 }; - public static readonly Dictionary ZCrystalDictionary = Pouch_ZCrystal_SM - .Zip(Pouch_ZCrystalHeld_SM, (k, v) => new { Key = (int)k, Value = (int)v }) + internal static readonly ushort[] Pouch_ZCrystal_USUM = Pouch_ZCrystal_SM.Concat(new ushort[] { // Bead + // todo + }).ToArray(); + internal static readonly ushort[] Pouch_ZCrystalHeld_USUM = Pouch_ZCrystalHeld_SM.Concat(new ushort[] { // Piece + // todo + }).ToArray(); + public static readonly Dictionary ZCrystalDictionary = Pouch_ZCrystal_USUM + .Zip(Pouch_ZCrystalHeld_USUM, (k, v) => new { Key = (int)k, Value = (int)v }) .ToDictionary(x => x.Key, x => x.Value); internal static readonly ushort[] HeldItems_SM = new ushort[1].Concat(Pouch_Items_SM).Concat(Pouch_Berries_SM).Concat(Pouch_Medicine_SM).Concat(Pouch_ZCrystalHeld_SM).ToArray(); internal static readonly ushort[] HeldItems_USUM = HeldItems_SM; // todo diff --git a/PKHeX.Core/Legality/VivillonTables.cs b/PKHeX.Core/Legality/VivillonTables.cs index e13cbb844..db3a5022f 100644 --- a/PKHeX.Core/Legality/VivillonTables.cs +++ b/PKHeX.Core/Legality/VivillonTables.cs @@ -242,18 +242,26 @@ private struct FormSubregionTable }, }; - public static bool CheckVivillonPattern(int form, int pkmcountry, int pkmregion) + /// + /// Compares the Vivillon pattern against its country and region to determine if the pattern is able to be obtained legally. + /// + /// Alternate Forme Pattern + /// Country ID + /// Console Region ID + /// + public static bool CheckVivillonPattern(int form, int country, int region) { - if (!VivillonCountryTable[form].Contains(pkmcountry)) + if (!VivillonCountryTable[form].Contains(country)) return false; // Country mismatch - if (RegionFormTable.All(c => c.countryID != pkmcountry)) + + CountryTable ct = RegionFormTable.Where(t => t.countryID == country).FirstOrDefault(); + if (ct.otherforms == null) // empty struct = no forms referenced return true; // No subregion table - CountryTable ct = RegionFormTable.Where(t => t.countryID == pkmcountry).ToArray()[0]; if (ct.mainform == form) - return !ct.otherforms.SelectMany(e => e.region).Contains(pkmregion); //true if Mainform not in other specific region + return !ct.otherforms.Any(e => e.region.Contains(region)); //true if Mainform not in other specific region - return ct.otherforms.Any(e => e.form == form && e.region.Contains(pkmregion)); + return ct.otherforms.Any(e => e.form == form && e.region.Contains(region)); } } } \ No newline at end of file diff --git a/PKHeX.Core/Legality/WordFilter.cs b/PKHeX.Core/Legality/WordFilter.cs index 116dee3b1..5710c8f46 100644 --- a/PKHeX.Core/Legality/WordFilter.cs +++ b/PKHeX.Core/Legality/WordFilter.cs @@ -3,6 +3,9 @@ namespace PKHeX.Core { + /// + /// Bad-word Filter class containing logic to check against unsavory regular expressions. + /// public static class WordFilter { /// diff --git a/PKHeX.Core/MysteryGifts/MysteryGift.cs b/PKHeX.Core/MysteryGifts/MysteryGift.cs index 58d664397..5059ff377 100644 --- a/PKHeX.Core/MysteryGifts/MysteryGift.cs +++ b/PKHeX.Core/MysteryGifts/MysteryGift.cs @@ -3,6 +3,9 @@ namespace PKHeX.Core { + /// + /// Mystery Gift Template File + /// public abstract class MysteryGift : IEncounterable, IMoveset { @@ -25,27 +28,25 @@ public static bool IsMysteryGift(long len) /// This overload differs from by checking the / combo for validity. If either is invalid, a null reference is returned. public static MysteryGift GetMysteryGift(byte[] data, string ext) { - // Generation 7 - if (data.Length == WC7.SizeFull && ext == ".wc7full") - return new WC7(data); - if (data.Length == WC7.Size && ext == ".wc7") - return new WC7(data); + if (ext == null) + return GetMysteryGift(data); - // Generation 6 - if (data.Length == WC6.SizeFull && ext == ".wc6full") - return new WC6(data); - if (data.Length == WC6.Size && ext == ".wc6") - return new WC6(data); + switch (data.Length) + { + case WC7.SizeFull when ext == ".wc7full": + case WC7.Size when ext == ".wc7": + return new WC7(data); + case WC6.SizeFull when ext == ".wc6full": + case WC6.Size when ext == ".wc6": + return new WC6(data); - // Generation 5 - if (data.Length == PGF.Size && ext == ".pgf") - return new PGF(data); - - // Generation 4 - if (data.Length == PGT.Size && ext == ".pgt") - return new PGT(data); - if (data.Length == PCD.Size && ext == ".pcd") - return new PCD(data); + case PGF.Size when ext == ".pgf": + return new PGF(data); + case PGT.Size when ext == ".pgt": + return new PGT(data); + case PCD.Size when ext == ".pcd": + return new PCD(data); + } return null; } @@ -69,14 +70,11 @@ public static MysteryGift GetMysteryGift(byte[] data) if (BitConverter.ToUInt32(data, 0x4C) / 10000 < 2000) return new WC7(data); return new WC6(data); - case PGF.Size: - return new PGF(data); - case PGT.Size: - return new PGT(data); - case PCD.Size: - return new PCD(data); - default: - return null; + + case PGF.Size: return new PGF(data); + case PGT.Size: return new PGT(data); + case PCD.Size: return new PCD(data); + default: return null; } } diff --git a/PKHeX.Core/MysteryGifts/PGF.cs b/PKHeX.Core/MysteryGifts/PGF.cs index 4b26e8380..09f314796 100644 --- a/PKHeX.Core/MysteryGifts/PGF.cs +++ b/PKHeX.Core/MysteryGifts/PGF.cs @@ -3,6 +3,9 @@ namespace PKHeX.Core { + /// + /// Generation 5 Mystery Gift Template File + /// public sealed class PGF : MysteryGift, IRibbonSetEvent3, IRibbonSetEvent4 { public const int Size = 0xCC; diff --git a/PKHeX.Core/MysteryGifts/PGT.cs b/PKHeX.Core/MysteryGifts/PGT.cs index 7bd836923..49db2c1f2 100644 --- a/PKHeX.Core/MysteryGifts/PGT.cs +++ b/PKHeX.Core/MysteryGifts/PGT.cs @@ -3,11 +3,15 @@ namespace PKHeX.Core { - /* Big thanks to Grovyle91's Pokémon Mystery Gift Editor, from which the structure was referenced. - * http://projectpokemon.org/forums/member.php?829-Grovyle91 - * http://projectpokemon.org/forums/showthread.php?6524 - * See also: http://tccphreak.shiny-clique.net/debugger/pcdfiles.htm - */ + /// + /// Generation 4 Mystery Gift Template File + /// + /// + /// Big thanks to Grovyle91's Pokémon Mystery Gift Editor, from which the structure was referenced. + /// http://projectpokemon.org/forums/member.php?829-Grovyle91 + /// http://projectpokemon.org/forums/showthread.php?6524 + /// See also: http://tccphreak.shiny-clique.net/debugger/pcdfiles.htm + /// public sealed class PCD : MysteryGift { public const int Size = 0x358; // 856 @@ -106,6 +110,10 @@ public override PKM ConvertToPKM(SaveFile SAV) public bool CanBeReceivedBy(int pkmVersion) => (CardCompatibility >> pkmVersion & 1) == 1; } + + /// + /// Generation 4 Mystery Gift Template File (Inner Gift Data, no card data) + /// public sealed class PGT : MysteryGift { public const int Size = 0x104; // 260 diff --git a/PKHeX.Core/MysteryGifts/PL6.cs b/PKHeX.Core/MysteryGifts/PL6.cs index 64aedeff1..7890a6041 100644 --- a/PKHeX.Core/MysteryGifts/PL6.cs +++ b/PKHeX.Core/MysteryGifts/PL6.cs @@ -4,7 +4,14 @@ namespace PKHeX.Core { - public class PL6 //: PokemonLink + /// + /// Pokemon Link Data Storage + /// + /// + /// This Template object is very similar to the structure in that it stores more data than just the gift. + /// This template object is only present in Generation 6 save files. + /// + public class PL6 { public const int Size = 0xA47; public const string Filter = "Pokémon Link Data|*.pl6|All Files (*.*)|*.*"; @@ -14,13 +21,17 @@ public PL6(byte[] data = null) { Data = (byte[])(data?.Clone() ?? new byte[Size]); } - // Pokémon Link Flag + /// + /// Pokémon Link Flag + /// public byte PL_Flag { get => Data[0x00]; set => Data[0x00] = value; } public bool PL_enabled { get => PL_Flag != 0; set => PL_Flag = (byte)(value ? 1 << 7 : 0); } - - //Name of data source + + /// + /// Name of data source + /// public string Origin_app { get => Util.TrimFromZero(Encoding.Unicode.GetString(Data, 0x01, 0x6E)); set => Encoding.Unicode.GetBytes(value.PadRight(54 + 1, '\0')).CopyTo(Data, 0x01); @@ -171,9 +182,15 @@ public int[] Quantities set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0x4A3); } } - public class PL6_PKM : IEncounterable + /// + /// Pokemon Link Gift Template + /// + /// + /// This Template object is very similar to the structure and similar objects, in that the structure offsets are ordered the same. + /// This template object is only present in Generation 6 save files. + /// + public class PL6_PKM : IEncounterable, IRibbonSetEvent3, IRibbonSetEvent4 { - internal const int Size = 0xA0; public readonly byte[] Data; @@ -289,22 +306,22 @@ public PL6_PKM(byte[] data = null) public int OT_Feeling { get => Data[0x7C]; set => Data[0x7C] = (byte)value; } private byte RIB0 { get => Data[0x0C]; set => Data[0x0C] = value; } - public bool RIB0_0 { get => (RIB0 & (1 << 0)) == 1 << 0; set => RIB0 = (byte)(RIB0 & ~(1 << 0) | (value ? 1 << 0 : 0)); } // Battle Champ Ribbon - public bool RIB0_1 { get => (RIB0 & (1 << 1)) == 1 << 1; set => RIB0 = (byte)(RIB0 & ~(1 << 1) | (value ? 1 << 1 : 0)); } // Regional Champ Ribbon - public bool RIB0_2 { get => (RIB0 & (1 << 2)) == 1 << 2; set => RIB0 = (byte)(RIB0 & ~(1 << 2) | (value ? 1 << 2 : 0)); } // National Champ Ribbon - public bool RIB0_3 { get => (RIB0 & (1 << 3)) == 1 << 3; set => RIB0 = (byte)(RIB0 & ~(1 << 3) | (value ? 1 << 3 : 0)); } // Country Ribbon - public bool RIB0_4 { get => (RIB0 & (1 << 4)) == 1 << 4; set => RIB0 = (byte)(RIB0 & ~(1 << 4) | (value ? 1 << 4 : 0)); } // National Ribbon - public bool RIB0_5 { get => (RIB0 & (1 << 5)) == 1 << 5; set => RIB0 = (byte)(RIB0 & ~(1 << 5) | (value ? 1 << 5 : 0)); } // Earth Ribbon - public bool RIB0_6 { get => (RIB0 & (1 << 6)) == 1 << 6; set => RIB0 = (byte)(RIB0 & ~(1 << 6) | (value ? 1 << 6 : 0)); } // World Ribbon - public bool RIB0_7 { get => (RIB0 & (1 << 7)) == 1 << 7; set => RIB0 = (byte)(RIB0 & ~(1 << 7) | (value ? 1 << 7 : 0)); } // Event Ribbon + public bool RibbonChampionBattle { get => (RIB0 & (1 << 0)) == 1 << 0; set => RIB0 = (byte)(RIB0 & ~(1 << 0) | (value ? 1 << 0 : 0)); } // Battle Champ Ribbon + public bool RibbonChampionRegional { get => (RIB0 & (1 << 1)) == 1 << 1; set => RIB0 = (byte)(RIB0 & ~(1 << 1) | (value ? 1 << 1 : 0)); } // Regional Champ Ribbon + public bool RibbonChampionNational { get => (RIB0 & (1 << 2)) == 1 << 2; set => RIB0 = (byte)(RIB0 & ~(1 << 2) | (value ? 1 << 2 : 0)); } // National Champ Ribbon + public bool RibbonCountry { get => (RIB0 & (1 << 3)) == 1 << 3; set => RIB0 = (byte)(RIB0 & ~(1 << 3) | (value ? 1 << 3 : 0)); } // Country Ribbon + public bool RibbonNational { get => (RIB0 & (1 << 4)) == 1 << 4; set => RIB0 = (byte)(RIB0 & ~(1 << 4) | (value ? 1 << 4 : 0)); } // National Ribbon + public bool RibbonEarth { get => (RIB0 & (1 << 5)) == 1 << 5; set => RIB0 = (byte)(RIB0 & ~(1 << 5) | (value ? 1 << 5 : 0)); } // Earth Ribbon + public bool RibbonWorld { get => (RIB0 & (1 << 6)) == 1 << 6; set => RIB0 = (byte)(RIB0 & ~(1 << 6) | (value ? 1 << 6 : 0)); } // World Ribbon + public bool RibbonEvent { get => (RIB0 & (1 << 7)) == 1 << 7; set => RIB0 = (byte)(RIB0 & ~(1 << 7) | (value ? 1 << 7 : 0)); } // Event Ribbon private byte RIB1 { get => Data[0x0D]; set => Data[0x0D] = value; } - public bool RIB1_0 { get => (RIB1 & (1 << 0)) == 1 << 0; set => RIB1 = (byte)(RIB1 & ~(1 << 0) | (value ? 1 << 0 : 0)); } // World Champ Ribbon - public bool RIB1_1 { get => (RIB1 & (1 << 1)) == 1 << 1; set => RIB1 = (byte)(RIB1 & ~(1 << 1) | (value ? 1 << 1 : 0)); } // Birthday Ribbon - public bool RIB1_2 { get => (RIB1 & (1 << 2)) == 1 << 2; set => RIB1 = (byte)(RIB1 & ~(1 << 2) | (value ? 1 << 2 : 0)); } // Special Ribbon - public bool RIB1_3 { get => (RIB1 & (1 << 3)) == 1 << 3; set => RIB1 = (byte)(RIB1 & ~(1 << 3) | (value ? 1 << 3 : 0)); } // Souvenir Ribbon - public bool RIB1_4 { get => (RIB1 & (1 << 4)) == 1 << 4; set => RIB1 = (byte)(RIB1 & ~(1 << 4) | (value ? 1 << 4 : 0)); } // Wishing Ribbon - public bool RIB1_5 { get => (RIB1 & (1 << 5)) == 1 << 5; set => RIB1 = (byte)(RIB1 & ~(1 << 5) | (value ? 1 << 5 : 0)); } // Classic Ribbon - public bool RIB1_6 { get => (RIB1 & (1 << 6)) == 1 << 6; set => RIB1 = (byte)(RIB1 & ~(1 << 6) | (value ? 1 << 6 : 0)); } // Premier Ribbon + public bool RibbonChampionWorld { get => (RIB1 & (1 << 0)) == 1 << 0; set => RIB1 = (byte)(RIB1 & ~(1 << 0) | (value ? 1 << 0 : 0)); } // World Champ Ribbon + public bool RibbonBirthday { get => (RIB1 & (1 << 1)) == 1 << 1; set => RIB1 = (byte)(RIB1 & ~(1 << 1) | (value ? 1 << 1 : 0)); } // Birthday Ribbon + public bool RibbonSpecial { get => (RIB1 & (1 << 2)) == 1 << 2; set => RIB1 = (byte)(RIB1 & ~(1 << 2) | (value ? 1 << 2 : 0)); } // Special Ribbon + public bool RibbonSouvenir { get => (RIB1 & (1 << 3)) == 1 << 3; set => RIB1 = (byte)(RIB1 & ~(1 << 3) | (value ? 1 << 3 : 0)); } // Souvenir Ribbon + public bool RibbonWishing { get => (RIB1 & (1 << 4)) == 1 << 4; set => RIB1 = (byte)(RIB1 & ~(1 << 4) | (value ? 1 << 4 : 0)); } // Wishing Ribbon + public bool RibbonClassic { get => (RIB1 & (1 << 5)) == 1 << 5; set => RIB1 = (byte)(RIB1 & ~(1 << 5) | (value ? 1 << 5 : 0)); } // Classic Ribbon + public bool RibbonPremier { get => (RIB1 & (1 << 6)) == 1 << 6; set => RIB1 = (byte)(RIB1 & ~(1 << 6) | (value ? 1 << 6 : 0)); } // Premier Ribbon public bool RIB1_7 { get => (RIB1 & (1 << 7)) == 1 << 7; set => RIB1 = (byte)(RIB1 & ~(1 << 7) | (value ? 1 << 7 : 0)); } // Empty public int[] Moves diff --git a/PKHeX.Core/MysteryGifts/WC3.cs b/PKHeX.Core/MysteryGifts/WC3.cs index 2577ec763..2bce68aef 100644 --- a/PKHeX.Core/MysteryGifts/WC3.cs +++ b/PKHeX.Core/MysteryGifts/WC3.cs @@ -2,6 +2,13 @@ namespace PKHeX.Core { + /// + /// Generation 3 Mystery Gift Template File + /// + /// + /// This is fabricated data built to emulate the future generation Mystery Gift objects. + /// Data here is not stored in any save file and cannot be naturally exported. + /// public class WC3 : MysteryGift, IRibbonSetEvent3 { // Template Properties diff --git a/PKHeX.Core/MysteryGifts/WC6.cs b/PKHeX.Core/MysteryGifts/WC6.cs index de74f6fe1..0eb5e50f9 100644 --- a/PKHeX.Core/MysteryGifts/WC6.cs +++ b/PKHeX.Core/MysteryGifts/WC6.cs @@ -4,6 +4,9 @@ namespace PKHeX.Core { + /// + /// Generation 6 Mystery Gift Template File + /// public sealed class WC6 : MysteryGift, IRibbonSetEvent3, IRibbonSetEvent4 { public const int Size = 0x108; diff --git a/PKHeX.Core/MysteryGifts/WC7.cs b/PKHeX.Core/MysteryGifts/WC7.cs index 71f0031e3..9c89afdc3 100644 --- a/PKHeX.Core/MysteryGifts/WC7.cs +++ b/PKHeX.Core/MysteryGifts/WC7.cs @@ -4,6 +4,9 @@ namespace PKHeX.Core { + /// + /// Generation 7 Mystery Gift Template File + /// public sealed class WC7 : MysteryGift, IRibbonSetEvent3, IRibbonSetEvent4 { public const int Size = 0x108; diff --git a/PKHeX.Core/PKM/BK4.cs b/PKHeX.Core/PKM/BK4.cs index c8cabda3b..c53a32769 100644 --- a/PKHeX.Core/PKM/BK4.cs +++ b/PKHeX.Core/PKM/BK4.cs @@ -3,7 +3,9 @@ namespace PKHeX.Core { - public class BK4 : PKM // Big Endian 4th Generation PKM File + /// Generation 4 format, exclusively for Pokémon Battle Revolution. + /// Values are stored in Big Endian format rather than Little Endian. Beware. + public class BK4 : PKM { public static readonly byte[] ExtraBytes = { diff --git a/PKHeX.Core/PKM/CK3.cs b/PKHeX.Core/PKM/CK3.cs index edf60997f..64f60a706 100644 --- a/PKHeX.Core/PKM/CK3.cs +++ b/PKHeX.Core/PKM/CK3.cs @@ -2,6 +2,7 @@ namespace PKHeX.Core { + /// Generation 3 format, exclusively for Pokémon Colosseum. public class CK3 : PKM, IRibbonSetEvent3, IRibbonSetCommon3, IRibbonSetUnique3, IRibbonSetOnly3, IShadowPKM { public static readonly byte[] ExtraBytes = diff --git a/PKHeX.Core/PKM/IShadowPKM.cs b/PKHeX.Core/PKM/IShadowPKM.cs index fdc0290ce..9b926f2a3 100644 --- a/PKHeX.Core/PKM/IShadowPKM.cs +++ b/PKHeX.Core/PKM/IShadowPKM.cs @@ -1,5 +1,9 @@ namespace PKHeX.Core { + /// + /// Interface that exposes Shadow details for the object. + /// + /// Used only for Colosseum/XD that were shadow encounters. public interface IShadowPKM { int ShadowID { get; set; } diff --git a/PKHeX.Core/PKM/ItemConverter.cs b/PKHeX.Core/PKM/ItemConverter.cs index 0c56d30ba..e9c1b7fae 100644 --- a/PKHeX.Core/PKM/ItemConverter.cs +++ b/PKHeX.Core/PKM/ItemConverter.cs @@ -1,5 +1,8 @@ namespace PKHeX.Core { + /// + /// Logic for converting Item IDs between the generation specific value sets. + /// internal static class ItemConverter { /// Unused item ID, placeholder for item/sprite finding diff --git a/PKHeX.Core/PKM/PK1.cs b/PKHeX.Core/PKM/PK1.cs index 170302f5f..c1e12d30a 100644 --- a/PKHeX.Core/PKM/PK1.cs +++ b/PKHeX.Core/PKM/PK1.cs @@ -5,6 +5,7 @@ namespace PKHeX.Core { + /// Generation 1 format. public class PK1 : PKM { // Internal use only diff --git a/PKHeX.Core/PKM/PK2.cs b/PKHeX.Core/PKM/PK2.cs index 772565e31..48ceed2b2 100644 --- a/PKHeX.Core/PKM/PK2.cs +++ b/PKHeX.Core/PKM/PK2.cs @@ -5,6 +5,7 @@ namespace PKHeX.Core { + /// Generation 2 format. public class PK2 : PKM { // Internal use only @@ -146,8 +147,10 @@ private IEnumerable GetNonNickname() { var name = PKX.GetSpeciesNameGeneration(Species, GuessedLanguage(), Format); var bytes = SetString(name, StringLength); - return bytes.Concat(Enumerable.Repeat((byte)0x50, nick.Length - bytes.Length)) - .Select(b => (byte)(b == 0xF2 ? 0xE8 : b)); // Decimal point<->period fix + var data = bytes.Concat(Enumerable.Repeat((byte) 0x50, nick.Length - bytes.Length)); + if (!Korean) + data = data.Select(b => (byte)(b == 0xF2 ? 0xE8 : b)); // Decimal point<->period fix + return data; } public bool IsNicknamedBank { @@ -164,7 +167,7 @@ public override int Language if (Japanese) return (int)LanguageID.Japanese; if (Korean) - return (int)LanguageID.English; + return (int)LanguageID.Korean; if (StringConverter.IsG12German(otname)) return (int)LanguageID.German; // german int lang = PKX.GetSpeciesNameLanguage(Species, Nickname, Format); diff --git a/PKHeX.Core/PKM/PK3.cs b/PKHeX.Core/PKM/PK3.cs index b828090b7..1d36c522e 100644 --- a/PKHeX.Core/PKM/PK3.cs +++ b/PKHeX.Core/PKM/PK3.cs @@ -2,6 +2,7 @@ namespace PKHeX.Core { + /// Generation 3 format. public class PK3 : PKM, IRibbonSetEvent3, IRibbonSetCommon3, IRibbonSetUnique3, IRibbonSetOnly3 { public static readonly byte[] ExtraBytes = diff --git a/PKHeX.Core/PKM/PK4.cs b/PKHeX.Core/PKM/PK4.cs index 6f81d86ac..a2056d7eb 100644 --- a/PKHeX.Core/PKM/PK4.cs +++ b/PKHeX.Core/PKM/PK4.cs @@ -3,6 +3,7 @@ namespace PKHeX.Core { + /// Generation 4 format. public class PK4 : PKM, IRibbonSetEvent3, IRibbonSetEvent4, IRibbonSetUnique3, IRibbonSetUnique4, IRibbonSetCommon3, IRibbonSetCommon4 { public static readonly byte[] ExtraBytes = diff --git a/PKHeX.Core/PKM/PK5.cs b/PKHeX.Core/PKM/PK5.cs index 49b99ef77..9e8d9766a 100644 --- a/PKHeX.Core/PKM/PK5.cs +++ b/PKHeX.Core/PKM/PK5.cs @@ -3,6 +3,7 @@ namespace PKHeX.Core { + /// Generation 5 format. public class PK5 : PKM, IRibbonSetEvent3, IRibbonSetEvent4, IRibbonSetUnique3, IRibbonSetUnique4, IRibbonSetCommon3, IRibbonSetCommon4 { public static readonly byte[] ExtraBytes = diff --git a/PKHeX.Core/PKM/PK6.cs b/PKHeX.Core/PKM/PK6.cs index 949cdc666..e03f7c4e3 100644 --- a/PKHeX.Core/PKM/PK6.cs +++ b/PKHeX.Core/PKM/PK6.cs @@ -3,6 +3,7 @@ namespace PKHeX.Core { + /// Generation 6 format. public class PK6 : PKM, IRibbonSetEvent3, IRibbonSetEvent4, IRibbonSetCommon3, IRibbonSetCommon4, IRibbonSetCommon6 { public static readonly byte[] ExtraBytes = diff --git a/PKHeX.Core/PKM/PK7.cs b/PKHeX.Core/PKM/PK7.cs index 1591ad939..5a34a1c7a 100644 --- a/PKHeX.Core/PKM/PK7.cs +++ b/PKHeX.Core/PKM/PK7.cs @@ -3,11 +3,12 @@ namespace PKHeX.Core { + /// Generation 7 format. public class PK7 : PKM, IRibbonSetEvent3, IRibbonSetEvent4, IRibbonSetCommon3, IRibbonSetCommon4, IRibbonSetCommon6, IRibbonSetCommon7 { public static readonly byte[] ExtraBytes = { - 0x2A, // Old Marking Value + 0x2A, // Old Marking Value (PelagoEventStatus) // 0x36, 0x37, // Unused Ribbons 0x58, 0x59, 0x73, 0x90, 0x91, 0x9E, 0x9F, 0xA0, 0xA1, 0xA7, 0xAA, 0xAB, 0xAC, 0xAD, 0xC8, 0xC9, 0xD7, 0xE4, 0xE5, 0xE6, 0xE7 }; diff --git a/PKHeX.Core/PKM/PKM.cs b/PKHeX.Core/PKM/PKM.cs index 406e4cd5f..866c3bd94 100644 --- a/PKHeX.Core/PKM/PKM.cs +++ b/PKHeX.Core/PKM/PKM.cs @@ -3,6 +3,9 @@ namespace PKHeX.Core { + /// + /// Object representing a 's data and derived properties. + /// public abstract class PKM { public static readonly string[] Extensions = PKX.GetPKMExtensions(); diff --git a/PKHeX.Core/PKM/PKMConverter.cs b/PKHeX.Core/PKM/PKMConverter.cs index 73431ac4e..ce581380d 100644 --- a/PKHeX.Core/PKM/PKMConverter.cs +++ b/PKHeX.Core/PKM/PKMConverter.cs @@ -5,6 +5,9 @@ namespace PKHeX.Core { + /// + /// Logic for converting a from one generation specific format to another. + /// public static class PKMConverter { public static int Country { get; private set; } = 49; @@ -197,7 +200,7 @@ public static bool IsConvertibleToFormat(PKM pk, int format) /// Converted PKM public static PKM ConvertToType(PKM pk, Type PKMType, out string comment) { - if (pk == null || pk.Species == 0) + if (pk == null) { comment = $"Bad {nameof(pk)} input. Aborting."; return null; @@ -239,7 +242,7 @@ public static PKM ConvertToType(PKM pk, Type PKMType, out string comment) { if (pk.Species > 151) { - comment = $"Cannot convert a {PKX.GetSpeciesName(pkm.Species, ((PK2)pkm).Japanese ? 1 : 2)} to {PKMType.Name}"; + comment = $"Cannot convert a {PKX.GetSpeciesName(pkm.Species, pkm.Japanese ? 1 : 2)} to {PKMType.Name}"; return null; } pkm = ((PK2)pk).ConvertToPK1(); @@ -389,6 +392,35 @@ public static void CheckEncrypted(ref byte[] pkm) } } + /// + /// Checks if the input is compatible with the target . + /// + /// Input to check -> update/sanitize + /// Target type PKM with misc properties accessible for checking. + /// Comment output + /// Output compatible PKM + /// Indication if the input is (now) compatible with the target. + public static bool TryMakePKMCompatible(PKM pk, PKM target, out string c, out PKM pkm) + { + if (!IsConvertibleToFormat(pk, target.Format)) + { + pkm = null; + c = $"Can't load {pk.GetType().Name}s to Gen{target.Format} saves."; + return false; + } + if (target.Format < 3 && pk.Japanese != target.Japanese) + { + pkm = null; + var strs = new[] { "International", "Japanese" }; + var val = target.Japanese ? 0 : 1; + c = $"Cannot load {strs[val]} {pk.GetType().Name}s to {strs[val ^ 1]} saves."; + return false; + } + pkm = ConvertToType(pk, target.GetType(), out c); + Debug.WriteLine(c); + return pkm != null; + } + /// /// Gets a Blank object of the specified type. /// diff --git a/PKHeX.Core/PKM/PKX.cs b/PKHeX.Core/PKM/PKX.cs index 0da14ce05..fc40499dc 100644 --- a/PKHeX.Core/PKM/PKX.cs +++ b/PKHeX.Core/PKM/PKX.cs @@ -196,6 +196,7 @@ public static bool IsPKM(long len) /// National Dex number of the Pokémon. Should be 0 if an egg. /// Language ID of the Pokémon /// The Species name if within expected range, else an empty string. + /// Should only be used externally for message displays; for accurate in-game names use . public static string GetSpeciesName(int species, int lang) { if (lang < 0 || SpeciesLang.Length <= lang) @@ -219,6 +220,8 @@ public static string GetSpeciesNameGeneration(int species, int lang, int generat return "タマゴ"; string nick = GetSpeciesName(species, lang); + if (generation == 2 && lang == (int)LanguageID.Korean) + return StringConverter.LocalizeKOR2(nick); if (generation < 5 && (generation != 4 || species != 0)) // All caps GenIV and previous, except GenIV eggs. { diff --git a/PKHeX.Core/PKM/ShowdownSet.cs b/PKHeX.Core/PKM/ShowdownSet.cs index e2f58100b..45fbea2a4 100644 --- a/PKHeX.Core/PKM/ShowdownSet.cs +++ b/PKHeX.Core/PKM/ShowdownSet.cs @@ -4,6 +4,9 @@ namespace PKHeX.Core { + /// + /// Logic for exporting and importing data in Pokémon Showdown's text format. + /// public class ShowdownSet { // String to Values @@ -285,7 +288,7 @@ private void ParseSpeciesNickname(ref string line) { n1 = line.Substring(0, index - 1); n2 = line.Substring(index).Trim(); - ReplaceAll(ref n2, "", "[", "]", "(", ")"); // Trim out excess data + n2 = ReplaceAll(n2, string.Empty, "[", "]", "(", ")"); // Trim out excess data } else // nickname first (manually created set, incorrect) { @@ -308,7 +311,7 @@ private string ParseLineMove(string line) if (moveString.Length > 13) { string type = moveString.Remove(0, 13); - ReplaceAll(ref type, "", "[", "]", "(", ")"); // Trim out excess data + type = ReplaceAll(type, string.Empty, "[", "]", "(", ")"); // Trim out excess data int hpVal = Array.IndexOf(hptypes, type); // Get HP Type if (hpVal >= 0) IVs = PKX.SetHPIVs(hpVal, IVs); // Get IVs @@ -418,9 +421,9 @@ private static string[] SplitLineStats(string line) .Replace("SDef", "SpD").Replace("Sp Def", "SpD") .Replace("Spd", "Spe").Replace("Speed", "Spe").Split(new[] { " / ", " " }, StringSplitOptions.None); } - private static void ReplaceAll(ref string rv, string o, params string[] i) + private static string ReplaceAll(string original, string to, params string[] toBeReplaced) { - rv = i.Aggregate(rv, (current, v) => current.Replace(v, o)); + return toBeReplaced.Aggregate(original, (current, v) => current.Replace(v, to)); } } } diff --git a/PKHeX.Core/PKM/SpeciesConverter.cs b/PKHeX.Core/PKM/SpeciesConverter.cs index 2b0415763..c146d56a0 100644 --- a/PKHeX.Core/PKM/SpeciesConverter.cs +++ b/PKHeX.Core/PKM/SpeciesConverter.cs @@ -3,6 +3,10 @@ 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. internal static class SpeciesConverter { /// diff --git a/PKHeX.Core/PKM/StringConverter.cs b/PKHeX.Core/PKM/StringConverter.cs index 85c8bf314..1a03344d3 100644 --- a/PKHeX.Core/PKM/StringConverter.cs +++ b/PKHeX.Core/PKM/StringConverter.cs @@ -5,6 +5,9 @@ namespace PKHeX.Core { + /// + /// Logic for converting a between the various generation specific encoding formats. + /// public static class StringConverter { /// @@ -1148,7 +1151,7 @@ private static byte SetG3Char(ushort chr, bool jp) {"ㅏ", 0x20}, {"ㅑ", 0x21}, {"ㅓ", 0x22}, {"ㅕ", 0x23}, {"ㅗ", 0x24}, {"ㅛ", 0x25}, {"ㅜ", 0x26}, {"ㅠ", 0x27}, {"ㅡ", 0x28}, {"ㅣ", 0x29}, {"ㅐ", 0x2A}, {"ㅒ", 0x2B}, {"ㅔ", 0x2C}, {"ㅖ", 0x2D}, {"ㅘ", 0x2E}, {"ㅙ", 0x2F}, {"ㅚ", 0x30}, {"ㅝ", 0x31}, {"ㅞ", 0x32}, {"ㅟ", 0x33}, {"ㅢ", 0x34}, {"_", 0x3E}, {"—", 0x3F}, {"「", 0x60}, {"」", 0x61}, {"『", 0x62}, {"』", 0x63}, {"(", 0x64}, {")", 0x65}, {"!", 0x66}, {"?", 0x67}, {"-", 0x68}, {"~", 0x69}, {"⋯", 0x6A}, {",", 0x6B}, {".", 0x6C}, - {"0", 0xF0}, {"1", 0xF1}, {"2", 0xF2}, {"3", 0xF3}, {"4", 0xF4}, {"5", 0xF5}, {"6", 0xF6}, {"7", 0xF7}, {"8", 0xF8}, {"9", 0xF9}, + {"0", 0xF0}, {"1", 0xF1}, {"2", 0xF2}, {"3", 0xF3}, {"4", 0xF4}, {"5", 0xF5}, {"6", 0xF6}, {"7", 0xF7}, {"8", 0xF8}, {"9", 0xF9}, }; private static readonly Dictionary U2GSC_KOR_1 = new Dictionary { {"가", 0x01}, {"각", 0x02}, {"간", 0x03}, {"갇", 0x04}, {"갈", 0x05}, {"갉", 0x06}, {"갊", 0x07}, {"감", 0x08}, {"갑", 0x09}, {"값", 0x0A}, {"갓", 0x0B}, {"갔", 0x0C}, {"강", 0x0D}, {"갖", 0x0E}, {"갗", 0x0F}, @@ -1320,21 +1323,15 @@ private static byte SetG3Char(ushort chr, bool jp) {"휸", 0xE0}, {"휼", 0xE1}, {"흄", 0xE2}, {"흇", 0xE3}, {"흉", 0xE4}, {"흐", 0xE5}, {"흑", 0xE6}, {"흔", 0xE7}, {"흖", 0xE8}, {"흗", 0xE9}, {"흘", 0xEA}, {"흙", 0xEB}, {"흠", 0xEC}, {"흡", 0xED}, {"흣", 0xEE}, {"흥", 0xEF}, {"흩", 0xF0}, {"희", 0xF1}, {"흰", 0xF2}, {"흴", 0xF3}, {"흼", 0xF4}, {"흽", 0xF5}, {"힁", 0xF6}, {"히", 0xF7}, {"힉", 0xF8}, {"힌", 0xF9}, {"힐", 0xFA}, {"힘", 0xFB}, {"힙", 0xFC}, {"힛", 0xFD}, {"힝", 0xFE}, }; - private static readonly Dictionary U2GSC_KOR_B = new Dictionary { - {"ㄱ", 0x00}, {"ㄴ", 0x01}, {"ㄷ", 0x02}, {"ㄹ", 0x03}, {"ㅁ", 0x04}, {"ㅂ", 0x05}, {"ㅅ", 0x06}, {"ㅇ", 0x07}, {"ㅈ", 0x08}, {"ㅊ", 0x09}, {"ㅋ", 0x0A}, {"ㅌ", 0x0B}, {"ㅍ", 0x0C}, {"ㅎ", 0x0D}, {"ㄲ", 0x0E}, {"ㄸ", 0x0F}, - {"ㅃ", 0x10}, {"ㅆ", 0x11}, {"ㅉ", 0x12}, - {"ㅏ", 0x20}, {"ㅑ", 0x21}, {"ㅓ", 0x22}, {"ㅕ", 0x23}, {"ㅗ", 0x24}, {"ㅛ", 0x25}, {"ㅜ", 0x26}, {"ㅠ", 0x27}, {"ㅡ", 0x28}, {"ㅣ", 0x29}, {"ㅐ", 0x2A}, {"ㅒ", 0x2B}, {"ㅔ", 0x2C}, {"ㅖ", 0x2D}, {"ㅘ", 0x2E}, {"ㅙ", 0x2F}, - {"ㅚ", 0x30}, {"ㅝ", 0x31}, {"ㅞ", 0x32}, {"ㅟ", 0x33}, {"ㅢ", 0x34}, {"_", 0x3E}, {"—", 0x3F}, - {"「", 0x60}, {"」", 0x61}, {"『", 0x62}, {"』", 0x63}, {"(", 0x64}, {")", 0x65}, {"!", 0x66}, {"?", 0x67}, {"-", 0x68}, {"~", 0x69}, {"⋯", 0x6A}, {",", 0x6B}, {".", 0x6C}, - {"0", 0xF0}, {"1", 0xF1}, {"2", 0xF2}, {"3", 0xF3}, {"4", 0xF4}, {"5", 0xF5}, {"6", 0xF6}, {"7", 0xF7}, {"8", 0xF8}, {"9", 0xF9}, - }; + private static readonly Dictionary U2GSC_KOR_B = U2GSC_KOR_0; + private static readonly Dictionary GSC2U_KOR_0 = new Dictionary { {0x00, "ㄱ"}, {0x01, "ㄴ"}, {0x02, "ㄷ"}, {0x03, "ㄹ"}, {0x04, "ㅁ"}, {0x05, "ㅂ"}, {0x06, "ㅅ"}, {0x07, "ㅇ"}, {0x08, "ㅈ"}, {0x09, "ㅊ"}, {0x0A, "ㅋ"}, {0x0B, "ㅌ"}, {0x0C, "ㅍ"}, {0x0D, "ㅎ"}, {0x0E, "ㄲ"}, {0x0F, "ㄸ"}, {0x10, "ㅃ"}, {0x11, "ㅆ"}, {0x12, "ㅉ"}, {0x20, "ㅏ"}, {0x21, "ㅑ"}, {0x22, "ㅓ"}, {0x23, "ㅕ"}, {0x24, "ㅗ"}, {0x25, "ㅛ"}, {0x26, "ㅜ"}, {0x27, "ㅠ"}, {0x28, "ㅡ"}, {0x29, "ㅣ"}, {0x2A, "ㅐ"}, {0x2B, "ㅒ"}, {0x2C, "ㅔ"}, {0x2D, "ㅖ"}, {0x2E, "ㅘ"}, {0x2F, "ㅙ"}, {0x30, "ㅚ"}, {0x31, "ㅝ"}, {0x32, "ㅞ"}, {0x33, "ㅟ"}, {0x34, "ㅢ"}, {0x3E, "_"}, {0x3F, "—"}, {0x60, "「"}, {0x61, "」"}, {0x62, "『"}, {0x63, "』"}, {0x64, "("}, {0x65, ")"}, {0x66, "!"}, {0x67, "?"}, {0x68, "-"}, {0x69, "~"}, {0x6A, "⋯"}, {0x6B, ","}, {0x6C, "."}, - {0xF0, "0"}, {0xF1, "1"}, {0xF2, "2"}, {0xF3, "3"}, {0xF4, "4"}, {0xF5, "5"}, {0xF6, "6"}, {0xF7, "7"}, {0xF8, "8"}, {0xF9, "9"}, + {0xF0, "0"}, {0xF1, "1"}, {0xF2, "2"}, {0xF3, "3"}, {0xF4, "4"}, {0xF5, "5"}, {0xF6, "6"}, {0xF7, "7"}, {0xF8, "8"}, {0xF9, "9"}, }; private static readonly Dictionary GSC2U_KOR_1 = new Dictionary { {0x01, "가"}, {0x02, "각"}, {0x03, "간"}, {0x04, "갇"}, {0x05, "갈"}, {0x06, "갉"}, {0x07, "갊"}, {0x08, "감"}, {0x09, "갑"}, {0x0A, "값"}, {0x0B, "갓"}, {0x0C, "갔"}, {0x0D, "강"}, {0x0E, "갖"}, {0x0F, "갗"}, @@ -1506,14 +1503,7 @@ private static byte SetG3Char(ushort chr, bool jp) {0xE0, "휸"}, {0xE1, "휼"}, {0xE2, "흄"}, {0xE3, "흇"}, {0xE4, "흉"}, {0xE5, "흐"}, {0xE6, "흑"}, {0xE7, "흔"}, {0xE8, "흖"}, {0xE9, "흗"}, {0xEA, "흘"}, {0xEB, "흙"}, {0xEC, "흠"}, {0xED, "흡"}, {0xEE, "흣"}, {0xEF, "흥"}, {0xF0, "흩"}, {0xF1, "희"}, {0xF2, "흰"}, {0xF3, "흴"}, {0xF4, "흼"}, {0xF5, "흽"}, {0xF6, "힁"}, {0xF7, "히"}, {0xF8, "힉"}, {0xF9, "힌"}, {0xFA, "힐"}, {0xFB, "힘"}, {0xFC, "힙"}, {0xFD, "힛"}, {0xFE, "힝"}, }; - private static readonly Dictionary GSC2U_KOR_B = new Dictionary { - {0x00, "ㄱ"}, {0x01, "ㄴ"}, {0x02, "ㄷ"}, {0x03, "ㄹ"}, {0x04, "ㅁ"}, {0x05, "ㅂ"}, {0x06, "ㅅ"}, {0x07, "ㅇ"}, {0x08, "ㅈ"}, {0x09, "ㅊ"}, {0x0A, "ㅋ"}, {0x0B, "ㅌ"}, {0x0C, "ㅍ"}, {0x0D, "ㅎ"}, {0x0E, "ㄲ"}, {0x0F, "ㄸ"}, - {0x10, "ㅃ"}, {0x11, "ㅆ"}, {0x12, "ㅉ"}, - {0x20, "ㅏ"}, {0x21, "ㅑ"}, {0x22, "ㅓ"}, {0x23, "ㅕ"}, {0x24, "ㅗ"}, {0x25, "ㅛ"}, {0x26, "ㅜ"}, {0x27, "ㅠ"}, {0x28, "ㅡ"}, {0x29, "ㅣ"}, {0x2A, "ㅐ"}, {0x2B, "ㅒ"}, {0x2C, "ㅔ"}, {0x2D, "ㅖ"}, {0x2E, "ㅘ"}, {0x2F, "ㅙ"}, - {0x30, "ㅚ"}, {0x31, "ㅝ"}, {0x32, "ㅞ"}, {0x33, "ㅟ"}, {0x34, "ㅢ"}, {0x3E, "_"}, {0x3F, "—"}, - {0x60, "「"}, {0x61, "」"}, {0x62, "『"}, {0x63, "』"}, {0x64, "("}, {0x65, ")"}, {0x66, "!"}, {0x67, "?"}, {0x68, "-"}, {0x69, "~"}, {0x6A, "⋯"}, {0x6B, ","}, {0x6C, "."}, - {0xF0, "0"}, {0xF1, "1"}, {0xF2, "2"}, {0xF3, "3"}, {0xF4, "4"}, {0xF5, "5"}, {0xF6, "6"}, {0xF7, "7"}, {0xF8, "8"}, {0xF9, "9"}, - }; + private static readonly Dictionary GSC2U_KOR_B = GSC2U_KOR_0; private static readonly Dictionary[] U2GSC_KOR = { @@ -2037,5 +2027,22 @@ public static string StripDiacriticsFR4(string input) { 'Ê', 'E' }, { 'Ï', 'I' }, }; + + /// + /// Localizes a Gen4+ Korean species name to the localization used in Generation 2 Gold/Silver + /// + /// Generation 4 Species Name + /// Localized Name for Generation 2 + public static string LocalizeKOR2(string nick) + { + if (KorG2Localized.TryGetValue(nick, out string localized)) + return localized; + return nick; + } + private static readonly Dictionary KorG2Localized = new Dictionary + { + { "덩쿠리", "덩구리" }, // Tangela + { "슈륙챙이", "수륙챙이" }, // Poliwhirl + }; } } diff --git a/PKHeX.Core/PKM/XK3.cs b/PKHeX.Core/PKM/XK3.cs index d76aa3939..67e352870 100644 --- a/PKHeX.Core/PKM/XK3.cs +++ b/PKHeX.Core/PKM/XK3.cs @@ -2,6 +2,7 @@ namespace PKHeX.Core { + /// Generation 3 format, exclusively for Pokémon XD. public class XK3 : PKM, IRibbonSetEvent3, IRibbonSetCommon3, IRibbonSetUnique3, IRibbonSetOnly3, IShadowPKM { public static readonly byte[] ExtraBytes = diff --git a/PKHeX.Core/PersonalInfo/PersonalInfo.cs b/PKHeX.Core/PersonalInfo/PersonalInfo.cs index a9a09753b..b0a3c949b 100644 --- a/PKHeX.Core/PersonalInfo/PersonalInfo.cs +++ b/PKHeX.Core/PersonalInfo/PersonalInfo.cs @@ -1,5 +1,8 @@ namespace PKHeX.Core { + /// + /// Stat/misc data for individual species or their associated alternate forme data. + /// public abstract class PersonalInfo { protected byte[] Data; @@ -59,8 +62,15 @@ protected static byte[] SetBits(bool[] bits) return data; } - public void AddTMHM(byte[] data) => TMHM = GetBits(data); - public void AddTypeTutors(byte[] data) => TypeTutors = GetBits(data); + /// + /// Injects supplementary TM/HM compatibility which is not present in the generation specific PersonalInfo format. + /// + /// + internal void AddTMHM(byte[] data) => TMHM = GetBits(data); + /// + /// Injects supplementary Type Tutor compatibility which is not present in the generation specific PersonalInfo format. + /// + internal void AddTypeTutors(byte[] data) => TypeTutors = GetBits(data); // Data Manipulation public int FormeIndex(int species, int forme) @@ -87,7 +97,7 @@ public int RandomGender case 0: // Male return 0; default: - return (int)(Util.Rand32() % 2); + return (int)(Util.Rand32() & 1); } } } diff --git a/PKHeX.Core/PersonalInfo/PersonalInfoB2W2.cs b/PKHeX.Core/PersonalInfo/PersonalInfoB2W2.cs index 8ada11418..804c988d6 100644 --- a/PKHeX.Core/PersonalInfo/PersonalInfoB2W2.cs +++ b/PKHeX.Core/PersonalInfo/PersonalInfoB2W2.cs @@ -2,6 +2,9 @@ namespace PKHeX.Core { + /// + /// class with values from the Black 2 & White 2 games. + /// public class PersonalInfoB2W2 : PersonalInfoBW { public new const int SIZE = 0x4C; diff --git a/PKHeX.Core/PersonalInfo/PersonalInfoBW.cs b/PKHeX.Core/PersonalInfo/PersonalInfoBW.cs index edc3b879d..97bfce025 100644 --- a/PKHeX.Core/PersonalInfo/PersonalInfoBW.cs +++ b/PKHeX.Core/PersonalInfo/PersonalInfoBW.cs @@ -3,6 +3,9 @@ namespace PKHeX.Core { + /// + /// class with values from the Black & White games. + /// public class PersonalInfoBW : PersonalInfo { protected PersonalInfoBW() { } diff --git a/PKHeX.Core/PersonalInfo/PersonalInfoG1.cs b/PKHeX.Core/PersonalInfo/PersonalInfoG1.cs index 3b45e3eea..181f04de8 100644 --- a/PKHeX.Core/PersonalInfo/PersonalInfoG1.cs +++ b/PKHeX.Core/PersonalInfo/PersonalInfoG1.cs @@ -2,6 +2,9 @@ namespace PKHeX.Core { + /// + /// class with values from Generation 1 games. + /// public class PersonalInfoG1 : PersonalInfo { protected PersonalInfoG1() { } diff --git a/PKHeX.Core/PersonalInfo/PersonalInfoG2.cs b/PKHeX.Core/PersonalInfo/PersonalInfoG2.cs index 46f2077e0..7225771f0 100644 --- a/PKHeX.Core/PersonalInfo/PersonalInfoG2.cs +++ b/PKHeX.Core/PersonalInfo/PersonalInfoG2.cs @@ -2,6 +2,9 @@ namespace PKHeX.Core { + /// + /// class with values from Generation 2 games. + /// public class PersonalInfoG2 : PersonalInfo { protected PersonalInfoG2() { } diff --git a/PKHeX.Core/PersonalInfo/PersonalInfoG3.cs b/PKHeX.Core/PersonalInfo/PersonalInfoG3.cs index f0236e345..660fcaab6 100644 --- a/PKHeX.Core/PersonalInfo/PersonalInfoG3.cs +++ b/PKHeX.Core/PersonalInfo/PersonalInfoG3.cs @@ -2,6 +2,9 @@ namespace PKHeX.Core { + /// + /// class with values from Generation 3 games. + /// public class PersonalInfoG3 : PersonalInfo { protected PersonalInfoG3() { } diff --git a/PKHeX.Core/PersonalInfo/PersonalInfoG4.cs b/PKHeX.Core/PersonalInfo/PersonalInfoG4.cs index 3765e6310..46c8c81e1 100644 --- a/PKHeX.Core/PersonalInfo/PersonalInfoG4.cs +++ b/PKHeX.Core/PersonalInfo/PersonalInfoG4.cs @@ -3,6 +3,9 @@ namespace PKHeX.Core { + /// + /// class with values from Generation 4 games. + /// public class PersonalInfoG4 : PersonalInfoG3 { public new const int SIZE = 0x2C; diff --git a/PKHeX.Core/PersonalInfo/PersonalInfoORAS.cs b/PKHeX.Core/PersonalInfo/PersonalInfoORAS.cs index 020805e93..91d237e1d 100644 --- a/PKHeX.Core/PersonalInfo/PersonalInfoORAS.cs +++ b/PKHeX.Core/PersonalInfo/PersonalInfoORAS.cs @@ -2,6 +2,9 @@ namespace PKHeX.Core { + /// + /// class with values from the OR & AS games. + /// public class PersonalInfoORAS : PersonalInfoXY { public new const int SIZE = 0x50; diff --git a/PKHeX.Core/PersonalInfo/PersonalInfoSM.cs b/PKHeX.Core/PersonalInfo/PersonalInfoSM.cs index fbe952584..ad74020ba 100644 --- a/PKHeX.Core/PersonalInfo/PersonalInfoSM.cs +++ b/PKHeX.Core/PersonalInfo/PersonalInfoSM.cs @@ -3,6 +3,9 @@ namespace PKHeX.Core { + /// + /// class with values from the Sun/Moon games. + /// public class PersonalInfoSM : PersonalInfoXY { public new const int SIZE = 0x54; @@ -14,9 +17,23 @@ public PersonalInfoSM(byte[] data) TMHM = GetBits(Data.Skip(0x28).Take(0x10).ToArray()); // 36-39 TypeTutors = GetBits(Data.Skip(0x38).Take(0x4).ToArray()); // 40 + + SpecialTutors = new[] + { + GetBits(Data.Skip(0x3C).Take(0x04).ToArray()), + GetBits(Data.Skip(0x40).Take(0x04).ToArray()), + GetBits(Data.Skip(0x44).Take(0x04).ToArray()), + GetBits(Data.Skip(0x48).Take(0x04).ToArray()), + }; } public override byte[] Write() { + SetBits(TMHM).CopyTo(Data, 0x28); + SetBits(TypeTutors).CopyTo(Data, 0x38); + SetBits(SpecialTutors[0]).CopyTo(Data, 0x3C); + SetBits(SpecialTutors[1]).CopyTo(Data, 0x40); + SetBits(SpecialTutors[2]).CopyTo(Data, 0x44); + SetBits(SpecialTutors[3]).CopyTo(Data, 0x48); return Data; } diff --git a/PKHeX.Core/PersonalInfo/PersonalInfoXY.cs b/PKHeX.Core/PersonalInfo/PersonalInfoXY.cs index 04203c75d..200dc50b0 100644 --- a/PKHeX.Core/PersonalInfo/PersonalInfoXY.cs +++ b/PKHeX.Core/PersonalInfo/PersonalInfoXY.cs @@ -2,6 +2,9 @@ namespace PKHeX.Core { + /// + /// class with values from the X & Y games. + /// public class PersonalInfoXY : PersonalInfoBW { protected PersonalInfoXY() { } // For ORAS diff --git a/PKHeX.Core/PersonalInfo/PersonalTable.cs b/PKHeX.Core/PersonalInfo/PersonalTable.cs index 1dd0fa5ff..681a7eb5c 100644 --- a/PKHeX.Core/PersonalInfo/PersonalTable.cs +++ b/PKHeX.Core/PersonalInfo/PersonalTable.cs @@ -4,6 +4,12 @@ namespace PKHeX.Core { + /// + /// table (array). + /// + /// + /// Serves as the main object that is accessed for stat data in a particular generation/game format. + /// public class PersonalTable { public static readonly PersonalTable USUM = GetTable("sm", GameVersion.USUM); @@ -151,14 +157,12 @@ private PersonalTable(byte[] data, GameVersion format) public int[] GetAbilities(int species, int forme) { - if (species >= Table.Length) - { species = 0; Debug.WriteLine("Requested out of bounds SpeciesID"); } - return this[GetFormeIndex(species, forme)].Abilities; + return GetFormeEntry(species, forme).Abilities; } public int GetFormeIndex(int species, int forme) { if (species >= Table.Length) - { species = 0; Debug.WriteLine("Requested out of bounds SpeciesID"); } + { species = 0; Debug.WriteLine($"Requested out of bounds {nameof(species)}: {species} (max={Table.Length-1}"); } return this[species].FormeIndex(species, forme); } public PersonalInfo GetFormeEntry(int species, int forme) diff --git a/PKHeX.Core/Resources/text/de/text_tradeb2w2_de.txt b/PKHeX.Core/Resources/text/de/text_tradeb2w2_de.txt new file mode 100644 index 000000000..4cf80de31 --- /dev/null +++ b/PKHeX.Core/Resources/text/de/text_tradeb2w2_de.txt @@ -0,0 +1,14 @@ +Lilpe +Wolli +Brockoloss +Fluffi +Zapp +Pompom +Schnäuzi +Yuriko +Shosuke +Hilbert +Maru +Lilo +Ursina +Ursina \ No newline at end of file diff --git a/PKHeX.Core/Resources/text/de/text_tradebw_de.txt b/PKHeX.Core/Resources/text/de/text_tradebw_de.txt new file mode 100644 index 000000000..786850ed0 --- /dev/null +++ b/PKHeX.Core/Resources/text/de/text_tradebw_de.txt @@ -0,0 +1,14 @@ +Lilili +Bauschi +Senilax +Grimli +Flumau +Rotoro +Papsat +Denise +Denise +Chester +Chester +Hilbert +Lilo +Hajo \ No newline at end of file diff --git a/PKHeX.Core/Resources/text/de/text_tradedppt_de.txt b/PKHeX.Core/Resources/text/de/text_tradedppt_de.txt new file mode 100644 index 000000000..ed5fa2c5a --- /dev/null +++ b/PKHeX.Core/Resources/text/de/text_tradedppt_de.txt @@ -0,0 +1,8 @@ +Salla +Plaupa +Pollo +Pador +Paula +Pierre +Marlène +Meister diff --git a/PKHeX.Core/Resources/text/de/text_tradefrlg_de.txt b/PKHeX.Core/Resources/text/de/text_tradefrlg_de.txt new file mode 100644 index 000000000..47532769f --- /dev/null +++ b/PKHeX.Core/Resources/text/de/text_tradefrlg_de.txt @@ -0,0 +1,22 @@ +MIMOSE +NIEDOMAN +NIEDOMAN +RIDONINO +RIDONINO +MARK +SCHMUSI +POLENTE +LECKIBAL +SPAJETTIE +EUROPE +RICHARD +WALTRAUD +WALTRAUD +THOMAS +THOMAS +HELMUTH +DANTE +ELISA +FRANZ +NORMA +GUSTAV \ No newline at end of file diff --git a/PKHeX.Core/Resources/text/de/text_tradehgss_de.txt b/PKHeX.Core/Resources/text/de/text_tradehgss_de.txt new file mode 100644 index 000000000..69e72a7c7 --- /dev/null +++ b/PKHeX.Core/Resources/text/de/text_tradehgss_de.txt @@ -0,0 +1,24 @@ +Aaron +Herakles +Kugo +Horlik +Ferro +Tecum +Volty +Tetsuo +Hornelchen +Beißer +Sirin +Nessie +Tobi +Chester +Cedric +Filipa +Waldo +Mondo +Maj.Bob +Troy +Rocko +Jasmin +Norman +Ronald \ No newline at end of file diff --git a/PKHeX.Core/Resources/text/de/text_traderse_de.txt b/PKHeX.Core/Resources/text/de/text_traderse_de.txt new file mode 100644 index 000000000..4f3a49fb4 --- /dev/null +++ b/PKHeX.Core/Resources/text/de/text_traderse_de.txt @@ -0,0 +1,14 @@ +MAKIT +CONEC +CORASO +MURZELLO +PLUSPO +SEEPOM +MIEZMIEZ +MAIK +MADINA +LIANA +FABIAN +RÜDIGER +TORSTEN +TABITHA \ No newline at end of file diff --git a/PKHeX.Core/Resources/text/de/text_tradesm_de.txt b/PKHeX.Core/Resources/text/de/text_tradesm_de.txt new file mode 100644 index 000000000..6c7b3518f --- /dev/null +++ b/PKHeX.Core/Resources/text/de/text_tradesm_de.txt @@ -0,0 +1,14 @@ +Machocho +Frubbi +Quaputzel +Wonni +Geoneo +Bailala +Fia +Hilahila +Kihe +Laule'a +Moemoe +Hepa +Kumu +Huhu \ No newline at end of file diff --git a/PKHeX.Core/Resources/text/en/text_tradeb2w2_en.txt b/PKHeX.Core/Resources/text/en/text_tradeb2w2_en.txt new file mode 100644 index 000000000..230db9d28 --- /dev/null +++ b/PKHeX.Core/Resources/text/en/text_tradeb2w2_en.txt @@ -0,0 +1,14 @@ +Petulia +Fluffee +Gigalith +Tangles +Bucky +Ambidexter +Beardy +Calla +Cotton +Manny +Slick +Lillian +Diana +Diana \ No newline at end of file diff --git a/PKHeX.Core/Resources/text/en/text_tradebw_en.txt b/PKHeX.Core/Resources/text/en/text_tradebw_en.txt new file mode 100644 index 000000000..312b1ad8c --- /dev/null +++ b/PKHeX.Core/Resources/text/en/text_tradebw_en.txt @@ -0,0 +1,14 @@ +Lillil +Fluffee +Redeye +Blueeye +Minipete +Eeks +Gorge +Dye +Dye +Kyle +Kyle +Manny +Lillian +Ander \ No newline at end of file diff --git a/PKHeX.Core/Resources/text/en/text_tradedppt_en.txt b/PKHeX.Core/Resources/text/en/text_tradedppt_en.txt new file mode 100644 index 000000000..1728a0aa0 --- /dev/null +++ b/PKHeX.Core/Resources/text/en/text_tradedppt_en.txt @@ -0,0 +1,8 @@ +Kazza +Charap +Gaspar +Foppa +Hasshi +Noburin +Minacchi +Meister diff --git a/PKHeX.Core/Resources/text/en/text_tradefrlg_en.txt b/PKHeX.Core/Resources/text/en/text_tradefrlg_en.txt new file mode 100644 index 000000000..974146bbd --- /dev/null +++ b/PKHeX.Core/Resources/text/en/text_tradefrlg_en.txt @@ -0,0 +1,22 @@ +MIMIEN +MS. NIDO +MR. NIDO +NINA +NINO +MARC +ZYNX +CH'DING +ESPHERE +TANGENY +SEELOR +REYLEY +SAIGE +SAIGE +TURNER +TURNER +HADEN +DONTAE +ELYSSA +CLIFTON +NORMA +GARETT \ No newline at end of file diff --git a/PKHeX.Core/Resources/text/en/text_tradehgss_en.txt b/PKHeX.Core/Resources/text/en/text_tradehgss_en.txt new file mode 100644 index 000000000..616de2d7a --- /dev/null +++ b/PKHeX.Core/Resources/text/en/text_tradehgss_en.txt @@ -0,0 +1,24 @@ +Rocky +Muscle +Billy +Doris +Maggie +Paul +Volty +Iron +Hornlette +Rusty +Kenya +Shuckie +Rudy +Jose +Richard +Ayana +Lorenzo +Mondo +Surge +Steven +Brock +Jasmine +Webster +Kirk \ No newline at end of file diff --git a/PKHeX.Core/Resources/text/en/text_traderse_en.txt b/PKHeX.Core/Resources/text/en/text_traderse_en.txt new file mode 100644 index 000000000..242555a0c --- /dev/null +++ b/PKHeX.Core/Resources/text/en/text_traderse_en.txt @@ -0,0 +1,14 @@ +MAKIT +SKITIT +COROSO +DOTS +PLUSES +SEASOR +MEOWOW +ELYSSA +DARRELL +LANE +KOBE +ROMAN +SKYLAR +ISIS \ No newline at end of file diff --git a/PKHeX.Core/Resources/text/en/text_tradesm_en.txt b/PKHeX.Core/Resources/text/en/text_tradesm_en.txt new file mode 100644 index 000000000..641af2a7a --- /dev/null +++ b/PKHeX.Core/Resources/text/en/text_tradesm_en.txt @@ -0,0 +1,14 @@ +Macho +Bouncee +Whirly +Happini +Veler +Stena +Talo +Hila +Kihei +Laule'a +Momoe +Sill +Kumu +Anga \ No newline at end of file diff --git a/PKHeX.Core/Resources/text/es/text_tradeb2w2_es.txt b/PKHeX.Core/Resources/text/es/text_tradeb2w2_es.txt new file mode 100644 index 000000000..f3b2f1457 --- /dev/null +++ b/PKHeX.Core/Resources/text/es/text_tradeb2w2_es.txt @@ -0,0 +1,14 @@ +Pettulip +Cotona +Gigalith +Tangles +Bucky +Ambidexter +Beardy +Lilly +Cotton +Manny +Slick +Lillian +Corina +Corina \ No newline at end of file diff --git a/PKHeX.Core/Resources/text/es/text_tradebw_es.txt b/PKHeX.Core/Resources/text/es/text_tradebw_es.txt new file mode 100644 index 000000000..bc90b77c8 --- /dev/null +++ b/PKHeX.Core/Resources/text/es/text_tradebw_es.txt @@ -0,0 +1,14 @@ +Florina +Cotona +Mordiscos +Colmi +Saltirón +Tecno +Tripón +Geles +Geles +Bertín +Bertín +Dani +Juno +Nico \ No newline at end of file diff --git a/PKHeX.Core/Resources/text/es/text_tradedppt_es.txt b/PKHeX.Core/Resources/text/es/text_tradedppt_es.txt new file mode 100644 index 000000000..20636bbf8 --- /dev/null +++ b/PKHeX.Core/Resources/text/es/text_tradedppt_es.txt @@ -0,0 +1,8 @@ +Kazza +Charap +Gaspar +Foppa +Hilary +Norton +Mindy +Maestro diff --git a/PKHeX.Core/Resources/text/es/text_tradefrlg_es.txt b/PKHeX.Core/Resources/text/es/text_tradefrlg_es.txt new file mode 100644 index 000000000..cffd71e98 --- /dev/null +++ b/PKHeX.Core/Resources/text/es/text_tradefrlg_es.txt @@ -0,0 +1,22 @@ +MIMI +NIDRANA +NIDRÁN +NIDRINA +NIDRINO +LICKITITO +ZYNX +FARFI +BOLICHI +TANGELITO +SEELÍN +RÚTEO +QUICA +QUICA +ONZANO +ONZANO +DIOCHO +CELESTO +CARMELA +CANEL +DULCE +GOYO \ No newline at end of file diff --git a/PKHeX.Core/Resources/text/es/text_tradehgss_es.txt b/PKHeX.Core/Resources/text/es/text_tradehgss_es.txt new file mode 100644 index 000000000..8cef4976f --- /dev/null +++ b/PKHeX.Core/Resources/text/es/text_tradehgss_es.txt @@ -0,0 +1,24 @@ +Temblores +Musculitos +Calamby +Trespicolo +Magni +Xaty +Volty +Brazy +Rinaldo +Pétreo +Alerón +Caparazz +Nero +Bertín +Rafael +Anahí +Lucio +Pavel +Surge +Máximo +Brock +Yasmina +Quintín +Klaus \ No newline at end of file diff --git a/PKHeX.Core/Resources/text/es/text_traderse_es.txt b/PKHeX.Core/Resources/text/es/text_traderse_es.txt new file mode 100644 index 000000000..d7ca76cfd --- /dev/null +++ b/PKHeX.Core/Resources/text/es/text_traderse_es.txt @@ -0,0 +1,14 @@ +MAKIT +SKITIT +COROSO +SITOT +PUSLE +HORSI +MEOWOW +EVELIO +DALILA +LAILA +QUICO +RENATO +SERGIO +ISA \ No newline at end of file diff --git a/PKHeX.Core/Resources/text/es/text_tradesm_es.txt b/PKHeX.Core/Resources/text/es/text_tradesm_es.txt new file mode 100644 index 000000000..726fb2df3 --- /dev/null +++ b/PKHeX.Core/Resources/text/es/text_tradesm_es.txt @@ -0,0 +1,14 @@ +Machote +Suiti +Tracia +Feli +Sr. Pómez +Tina +Gavi +Hila +Kike +Lau +Moe +Epi +Kumu +Tito \ No newline at end of file diff --git a/PKHeX.Core/Resources/text/fr/text_tradeb2w2_fr.txt b/PKHeX.Core/Resources/text/fr/text_tradeb2w2_fr.txt new file mode 100644 index 000000000..070fdd413 --- /dev/null +++ b/PKHeX.Core/Resources/text/fr/text_tradeb2w2_fr.txt @@ -0,0 +1,14 @@ +Tulipette +Jersey +Gigalithe +Toutouffe +GITS +Caudal +Stachemou +Yuriko +Shosuke +Hilbert +Maru +Lilo +Ursina +Ursina \ No newline at end of file diff --git a/PKHeX.Core/Resources/text/fr/text_tradebw_fr.txt b/PKHeX.Core/Resources/text/fr/text_tradebw_fr.txt new file mode 100644 index 000000000..34aaec5e8 --- /dev/null +++ b/PKHeX.Core/Resources/text/fr/text_tradebw_fr.txt @@ -0,0 +1,14 @@ +Bulbébé +Cotontige +Siaboua +Siaméto +Patacrêpe +Triphaset +Grobidon +Denise +Denise +Chester +Chester +Hilbert +Lilo +Hajo \ No newline at end of file diff --git a/PKHeX.Core/Resources/text/fr/text_tradedppt_fr.txt b/PKHeX.Core/Resources/text/fr/text_tradedppt_fr.txt new file mode 100644 index 000000000..205ea51a7 --- /dev/null +++ b/PKHeX.Core/Resources/text/fr/text_tradedppt_fr.txt @@ -0,0 +1,8 @@ +Kazou +Pijouk +Trumi +Bloupi +Hilary +Norton +Mindy +Meister diff --git a/PKHeX.Core/Resources/text/fr/text_tradefrlg_fr.txt b/PKHeX.Core/Resources/text/fr/text_tradefrlg_fr.txt new file mode 100644 index 000000000..f8f1dacee --- /dev/null +++ b/PKHeX.Core/Resources/text/fr/text_tradefrlg_fr.txt @@ -0,0 +1,22 @@ +MARCI +MS. NIDO +MR. NIDO +NINO +NINO +GLAVIOTE +LIPOUTI +PTICHO +RODY +TISSAC +OBAMI +NASSIM +FLORA +FLORA +ELIOTT +ELIOTT +ISMAEL +JOHAN +ADELINE +ALBAN +PERRINE +FELIX \ No newline at end of file diff --git a/PKHeX.Core/Resources/text/fr/text_tradehgss_fr.txt b/PKHeX.Core/Resources/text/fr/text_tradehgss_fr.txt new file mode 100644 index 000000000..d17d85cce --- /dev/null +++ b/PKHeX.Core/Resources/text/fr/text_tradehgss_fr.txt @@ -0,0 +1,24 @@ +Lombric +Gonflor +Voltounet +Triolo +Ovni +Quetzal +Electron +Pôlo +Cornu +Métallo +Piou Piou +Nessie +Gontran +Devon +Austin +Aglaé +Quantin +Médi +Mjr Bob +Rochard +Pierre +Jasmine +Vijay +Otto \ No newline at end of file diff --git a/PKHeX.Core/Resources/text/fr/text_traderse_fr.txt b/PKHeX.Core/Resources/text/fr/text_traderse_fr.txt new file mode 100644 index 000000000..8f7a7328b --- /dev/null +++ b/PKHeX.Core/Resources/text/fr/text_traderse_fr.txt @@ -0,0 +1,14 @@ +MAKIT +SKITIT +COCO +PIPIO +SIPO +HYPY +GNAGNAA +NELSON +ELYSA +LANA +KOBE +ALBAN +LUDOVIC +ISIS \ No newline at end of file diff --git a/PKHeX.Core/Resources/text/fr/text_tradesm_fr.txt b/PKHeX.Core/Resources/text/fr/text_tradesm_fr.txt new file mode 100644 index 000000000..0b1f59b8d --- /dev/null +++ b/PKHeX.Core/Resources/text/fr/text_tradesm_fr.txt @@ -0,0 +1,14 @@ +MasterSensei +Bella +Spiralia +Trocontent +Graboum +Miam-miam +Gérard +Hilahila +Kihe +Laule'a +Moemoe +Hepa +Kumu +Inaina \ No newline at end of file diff --git a/PKHeX.Core/Resources/text/it/text_tradeb2w2_it.txt b/PKHeX.Core/Resources/text/it/text_tradeb2w2_it.txt new file mode 100644 index 000000000..42272bc7a --- /dev/null +++ b/PKHeX.Core/Resources/text/it/text_tradeb2w2_it.txt @@ -0,0 +1,14 @@ +Petillin +Scoscò +Gigalith +Grogrò +Zapp +Pompom +Barbello +Tulippa +Scotty +Urano +Zucco +Rolly +Nenè +Nenè \ No newline at end of file diff --git a/PKHeX.Core/Resources/text/it/text_tradebw_it.txt b/PKHeX.Core/Resources/text/it/text_tradebw_it.txt new file mode 100644 index 000000000..a494cd621 --- /dev/null +++ b/PKHeX.Core/Resources/text/it/text_tradebw_it.txt @@ -0,0 +1,14 @@ +Flò +Fiocco +Rossino +Bluetto +Ufino +Cric +Satollo +Bettina +Bettina +Aldo +Aldo +Urano +Luna +Tiziano \ No newline at end of file diff --git a/PKHeX.Core/Resources/text/it/text_tradedppt_it.txt b/PKHeX.Core/Resources/text/it/text_tradedppt_it.txt new file mode 100644 index 000000000..c98ec89a6 --- /dev/null +++ b/PKHeX.Core/Resources/text/it/text_tradedppt_it.txt @@ -0,0 +1,8 @@ +Keikei +Charap +Gaspar +Mossy +Hilary +Norbert +Mara +Master diff --git a/PKHeX.Core/Resources/text/it/text_tradefrlg_it.txt b/PKHeX.Core/Resources/text/it/text_tradefrlg_it.txt new file mode 100644 index 000000000..fa81ae0a0 --- /dev/null +++ b/PKHeX.Core/Resources/text/it/text_tradefrlg_it.txt @@ -0,0 +1,22 @@ +MIMIEN +MS. NIDO +MR. NIDO +NINA +NINO +MARC +ZYNX +CH'DING +ESPHERE +TANGENY +SEELOR +REYLEY +SAIGE +SAIGE +TURNER +TURNER +HADEN +RINO +ELYSSA +CLIFTON +NORMA +GARETT \ No newline at end of file diff --git a/PKHeX.Core/Resources/text/it/text_tradehgss_it.txt b/PKHeX.Core/Resources/text/it/text_tradehgss_it.txt new file mode 100644 index 000000000..0091d930b --- /dev/null +++ b/PKHeX.Core/Resources/text/it/text_tradehgss_it.txt @@ -0,0 +1,24 @@ +Roccio +Muscol +Volt +Doddo +Calami +Totemix +Scossy +Ferrino +Rino +Acciarock +Sparvy +Caratroc +Quentin +Arnaldo +Maurice +Missy +Massimo +Monteo +Surge +Rocco +Brock +Jasmine +Mark +Cosimo \ No newline at end of file diff --git a/PKHeX.Core/Resources/text/it/text_traderse_it.txt b/PKHeX.Core/Resources/text/it/text_traderse_it.txt new file mode 100644 index 000000000..36e448be1 --- /dev/null +++ b/PKHeX.Core/Resources/text/it/text_traderse_it.txt @@ -0,0 +1,14 @@ +AGATA +SKITIT +COROSO +DOTS +PLUSES +SEASOR +MEOWOW +LEANDRO +LOLA +BETTA +KIKO +ROMAN +SERGINO +ISIS \ No newline at end of file diff --git a/PKHeX.Core/Resources/text/it/text_tradesm_it.txt b/PKHeX.Core/Resources/text/it/text_tradesm_it.txt new file mode 100644 index 000000000..1c519e1e4 --- /dev/null +++ b/PKHeX.Core/Resources/text/it/text_tradesm_it.txt @@ -0,0 +1,14 @@ +Chops +Par +Poli-Poli +Nippy +Gravus +Neenee +Flame +Hilahila +Kihe +Laule'a +Moemoe +Hepa +Kumu +Huhu \ No newline at end of file diff --git a/PKHeX.Core/Resources/text/ja/text_tradeb2w2_ja.txt b/PKHeX.Core/Resources/text/ja/text_tradeb2w2_ja.txt new file mode 100644 index 000000000..c0364ea2e --- /dev/null +++ b/PKHeX.Core/Resources/text/ja/text_tradeb2w2_ja.txt @@ -0,0 +1,14 @@ +チュりっぺ +メンメン +ギガイアス +フサフサ +バッキー +シッポ +おヒゲ +ユリコ +ショウスケ +ゲンゾウ +ツルマル +ユイ +ハツネ +ハツネ \ No newline at end of file diff --git a/PKHeX.Core/Resources/text/ja/text_tradebw_ja.txt b/PKHeX.Core/Resources/text/ja/text_tradebw_ja.txt new file mode 100644 index 000000000..a47ccfbda --- /dev/null +++ b/PKHeX.Core/Resources/text/ja/text_tradebw_ja.txt @@ -0,0 +1,14 @@ +チュりん +モンモン +アカメ +アオメ +トビマル +ドッキー +まんぷく +アヤ +アヤ +ナオキ +ナオキ +ゲンゾウ +ユイ +フトシ \ No newline at end of file diff --git a/PKHeX.Core/Resources/text/ja/text_tradedppt_ja.txt b/PKHeX.Core/Resources/text/ja/text_tradedppt_ja.txt new file mode 100644 index 000000000..755e137b8 --- /dev/null +++ b/PKHeX.Core/Resources/text/ja/text_tradedppt_ja.txt @@ -0,0 +1,8 @@ +ケーケー +ペッチャラ +ドロりん +ポッちゃん +ハッシー +ノブリン +ミナッチ +マイスター diff --git a/PKHeX.Core/Resources/text/ja/text_tradefrlg_ja.txt b/PKHeX.Core/Resources/text/ja/text_tradefrlg_ja.txt new file mode 100644 index 000000000..a13a0f717 --- /dev/null +++ b/PKHeX.Core/Resources/text/ja/text_tradefrlg_ja.txt @@ -0,0 +1,22 @@ +バリヤン +ニドちゃん +ニドくん +ニーナ +ニーノ +なめぞう +コリンダ +じんすけ +デンマル +じゃじゃお +ぱたろー +ひとまろ +めぐっぺ +めぐっぺ +とーたん +とーたん +みちはる +もりべー +みどりん +タナーカ +なっつん +よしもつ \ No newline at end of file diff --git a/PKHeX.Core/Resources/text/ja/text_tradehgss_ja.txt b/PKHeX.Core/Resources/text/ja/text_tradehgss_ja.txt new file mode 100644 index 000000000..3b6c618fe --- /dev/null +++ b/PKHeX.Core/Resources/text/ja/text_tradehgss_ja.txt @@ -0,0 +1,24 @@ +ブルブル +きんにく +ビリー +ドンドコ +さてつ +チーフ +VOLTY +こうてつ +つのこ +ネール +ひきゃく +ネッシー +コンタ +ナオキ +ジン +ミサコ +モリオ +モンド +マチス +ダイゴ +タケシ +ミカン +ユウジ +セイジ \ No newline at end of file diff --git a/PKHeX.Core/Resources/text/ja/text_traderse_ja.txt b/PKHeX.Core/Resources/text/ja/text_traderse_ja.txt new file mode 100644 index 000000000..59f0a6ff7 --- /dev/null +++ b/PKHeX.Core/Resources/text/ja/text_traderse_ja.txt @@ -0,0 +1,14 @@ +ポテマル +ベル +モモちゃん +セブン +プラプラ +ゴロー +チー +モーリン +ユキポン +サトチン +マッチャン +アッキー +ソガチン +マリッペ \ No newline at end of file diff --git a/PKHeX.Core/Resources/text/ja/text_tradesm_ja.txt b/PKHeX.Core/Resources/text/ja/text_tradesm_ja.txt new file mode 100644 index 000000000..b4b719de7 --- /dev/null +++ b/PKHeX.Core/Resources/text/ja/text_tradesm_ja.txt @@ -0,0 +1,14 @@ +シトサン +タリーヨ +ヤンヤン +うゆゆ +シヨッカ +ノッキリア +ツノリー +ヒラヒラ +キヘ +ラウレア +モエモエ +ヘパ +クム +フフー \ No newline at end of file diff --git a/PKHeX.Core/Resources/text/ko/text_tradeb2w2_ko.txt b/PKHeX.Core/Resources/text/ko/text_tradeb2w2_ko.txt new file mode 100644 index 000000000..6e79bb659 --- /dev/null +++ b/PKHeX.Core/Resources/text/ko/text_tradeb2w2_ko.txt @@ -0,0 +1,14 @@ +치릴뿌잉 +면면 +기가이어스 +북실북실 +바킹 +꼬리 +수여미 +율리크 +수천 +건상 +실마르 +유이 +초희 +초희 \ No newline at end of file diff --git a/PKHeX.Core/Resources/text/ko/text_tradebw_ko.txt b/PKHeX.Core/Resources/text/ko/text_tradebw_ko.txt new file mode 100644 index 000000000..ebd57d605 --- /dev/null +++ b/PKHeX.Core/Resources/text/ko/text_tradebw_ko.txt @@ -0,0 +1,14 @@ +추링 +솜솜 +빨강눈 +파랑눈 +날돌이 +독키 +배빵빵 +소영 +소영 +청수 +청수 +건상 +유이 +태사 \ No newline at end of file diff --git a/PKHeX.Core/Resources/text/ko/text_tradedppt_ko.txt b/PKHeX.Core/Resources/text/ko/text_tradedppt_ko.txt new file mode 100644 index 000000000..5dfd8f9b9 --- /dev/null +++ b/PKHeX.Core/Resources/text/ko/text_tradedppt_ko.txt @@ -0,0 +1,8 @@ +케이케이 +조자리 +고옹이 +킹킹이 +에이 +신달 +미나 +마이스터 diff --git a/PKHeX.Core/Resources/text/ko/text_tradehgss_ko.txt b/PKHeX.Core/Resources/text/ko/text_tradehgss_ko.txt new file mode 100644 index 000000000..797fcc311 --- /dev/null +++ b/PKHeX.Core/Resources/text/ko/text_tradehgss_ko.txt @@ -0,0 +1,24 @@ +덜덜이 +근육 +찌릭 +동동이 +사철이 +치프 +VOLTY +강철이 +각분이 +철톤 +파바리 +네시 +수빈 +청수 +진 +미사 +임남 +몬드 +마티스 +성호 +웅 +규리 +유랑 +태훈 \ No newline at end of file diff --git a/PKHeX.Core/Resources/text/ko/text_tradesm_ko.txt b/PKHeX.Core/Resources/text/ko/text_tradesm_ko.txt new file mode 100644 index 000000000..0559bd71e --- /dev/null +++ b/PKHeX.Core/Resources/text/ko/text_tradesm_ko.txt @@ -0,0 +1,14 @@ +튼삼 +몰리요 +얍얍 +우융융 +해보공 +노키리아 +뿌링뿌링 +히라히라 +키헤 +라우레아 +모에모에 +헤파 +쿠무 +후후 \ No newline at end of file diff --git a/PKHeX.Core/Resources/text/zh/text_tradesm_zh.txt b/PKHeX.Core/Resources/text/zh/text_tradesm_zh.txt new file mode 100644 index 000000000..743111c31 --- /dev/null +++ b/PKHeX.Core/Resources/text/zh/text_tradesm_zh.txt @@ -0,0 +1,14 @@ +POW・Li +Sweet +Spir◎l +Pinky +Gulu +Juicy +Arrow +Hila +Kihei +Laulea +Momoe +Hepa +Kumu +Huhu \ No newline at end of file diff --git a/PKHeX.Core/Saves/SAV1.cs b/PKHeX.Core/Saves/SAV1.cs index 0636c7331..b89740235 100644 --- a/PKHeX.Core/Saves/SAV1.cs +++ b/PKHeX.Core/Saves/SAV1.cs @@ -3,6 +3,9 @@ namespace PKHeX.Core { + /// + /// Generation 1 object. + /// public sealed class SAV1 : SaveFile { public override string BAKName => $"{FileName} [{OT} ({Version}) - {PlayTimeString}].bak"; @@ -18,7 +21,7 @@ public SAV1(byte[] data = null, GameVersion versionOverride = GameVersion.Any) { Data = data == null ? new byte[SaveUtil.SIZE_G1RAW] : (byte[])data.Clone(); BAK = (byte[])Data.Clone(); - Exportable = !Data.SequenceEqual(new byte[Data.Length]); + Exportable = !Data.All(z => z == 0); if (data == null) Version = GameVersion.RBY; diff --git a/PKHeX.Core/Saves/SAV2.cs b/PKHeX.Core/Saves/SAV2.cs index fabe51306..503312446 100644 --- a/PKHeX.Core/Saves/SAV2.cs +++ b/PKHeX.Core/Saves/SAV2.cs @@ -3,6 +3,9 @@ namespace PKHeX.Core { + /// + /// Generation 2 object. + /// public sealed class SAV2 : SaveFile { public override string BAKName => $"{FileName} [{OT} ({Version}) - {PlayTimeString}].bak"; @@ -20,7 +23,7 @@ public SAV2(byte[] data = null, GameVersion versionOverride = GameVersion.Any) { Data = data == null ? new byte[SaveUtil.SIZE_G2RAW_U] : (byte[])data.Clone(); BAK = (byte[])Data.Clone(); - Exportable = !Data.SequenceEqual(new byte[Data.Length]); + Exportable = !Data.All(z => z == 0); if (data == null) Version = GameVersion.C; @@ -222,8 +225,8 @@ protected override byte[] Write(bool DSV) public override int MaxIV => 15; public override int Generation => 2; protected override int GiftCountMax => 0; - public override int OTLength => Japanese ? 5 : 7; - public override int NickLength => Japanese ? 5 : 10; + public override int OTLength => Japanese || Korean ? 5 : 7; + public override int NickLength => Japanese || Korean ? 5 : 10; public override int BoxSlotCount => Japanese ? 30 : 20; public override bool HasParty => true; @@ -256,8 +259,8 @@ public override bool ChecksumsValid public override string OT { - get => GetString(Offsets.Trainer1 + 2, OTLength); - set => SetString(value, OTLength).CopyTo(Data, Offsets.Trainer1 + 2); + get => GetString(Offsets.Trainer1 + 2, (Korean ? 2 : 1) * OTLength); + set => SetString(value, (Korean ? 2 : 1) * OTLength).CopyTo(Data, Offsets.Trainer1 + 2); } public override int Gender { diff --git a/PKHeX.Core/Saves/SAV3.cs b/PKHeX.Core/Saves/SAV3.cs index 58ac3022b..c76b6f1ea 100644 --- a/PKHeX.Core/Saves/SAV3.cs +++ b/PKHeX.Core/Saves/SAV3.cs @@ -4,6 +4,9 @@ namespace PKHeX.Core { + /// + /// Generation 3 object. + /// public sealed class SAV3 : SaveFile { public override string BAKName => $"{FileName} [{OT} ({Version}) - {PlayTimeString}].bak"; @@ -41,7 +44,7 @@ public SAV3(byte[] data = null, GameVersion versionOverride = GameVersion.Any) { Data = data == null ? new byte[SaveUtil.SIZE_G3RAW] : (byte[])data.Clone(); BAK = (byte[])Data.Clone(); - Exportable = !Data.SequenceEqual(new byte[Data.Length]); + Exportable = !Data.All(z => z == 0); if (data == null) Version = GameVersion.FRLG; diff --git a/PKHeX.Core/Saves/SAV3Colosseum.cs b/PKHeX.Core/Saves/SAV3Colosseum.cs index 2c6557cd1..fe56f6372 100644 --- a/PKHeX.Core/Saves/SAV3Colosseum.cs +++ b/PKHeX.Core/Saves/SAV3Colosseum.cs @@ -4,6 +4,9 @@ namespace PKHeX.Core { + /// + /// Generation 3 object for Pokémon Colosseum saves. + /// public sealed class SAV3Colosseum : SaveFile, IDisposable { public override string BAKName => $"{FileName} [{OT} ({Version}) - {PlayTimeString}].bak"; @@ -45,7 +48,7 @@ public SAV3Colosseum(byte[] data = null) { Data = data == null ? new byte[SaveUtil.SIZE_G3COLO] : (byte[])data.Clone(); BAK = (byte[])Data.Clone(); - Exportable = !Data.SequenceEqual(new byte[Data.Length]); + Exportable = !Data.All(z => z == 0); if (SaveUtil.GetIsG3COLOSAV(Data) != GameVersion.COLO) return; diff --git a/PKHeX.Core/Saves/SAV3GCMemoryCard.cs b/PKHeX.Core/Saves/SAV3GCMemoryCard.cs index ea1a8b31e..e2c3c284e 100644 --- a/PKHeX.Core/Saves/SAV3GCMemoryCard.cs +++ b/PKHeX.Core/Saves/SAV3GCMemoryCard.cs @@ -8,6 +8,9 @@ namespace PKHeX.Core * https://github.com/dolphin-emu/dolphin/ */ + /// + /// Flags for indicating what data is present in the Memory Card + /// public enum GCMemoryCardState { Invalid, @@ -21,6 +24,9 @@ public enum GCMemoryCardState DuplicateRSBOX, } + /// + /// GameCube save container which may or may not contain Generation 3 objects. + /// public sealed class SAV3GCMemoryCard { private const int BLOCK_SIZE = 0x2000; diff --git a/PKHeX.Core/Saves/SAV3RSBox.cs b/PKHeX.Core/Saves/SAV3RSBox.cs index 0ce42cc85..68cd3db67 100644 --- a/PKHeX.Core/Saves/SAV3RSBox.cs +++ b/PKHeX.Core/Saves/SAV3RSBox.cs @@ -3,6 +3,9 @@ namespace PKHeX.Core { + /// + /// Generation 3 object for Pokémon Ruby Sapphire Box saves. + /// public sealed class SAV3RSBox : SaveFile { public override string BAKName => $"{FileName} [{Version} #{SaveCount:0000}].bak"; @@ -23,8 +26,8 @@ public SAV3RSBox(byte[] data = null) { Data = data == null ? new byte[SaveUtil.SIZE_G3BOX] : (byte[])data.Clone(); BAK = (byte[])Data.Clone(); - Exportable = !Data.SequenceEqual(new byte[Data.Length]); - + Exportable = !Data.All(z => z == 0); + if (SaveUtil.GetIsG3BOXSAV(Data) != GameVersion.RSBOX) return; diff --git a/PKHeX.Core/Saves/SAV3XD.cs b/PKHeX.Core/Saves/SAV3XD.cs index daa173e0b..5988244a7 100644 --- a/PKHeX.Core/Saves/SAV3XD.cs +++ b/PKHeX.Core/Saves/SAV3XD.cs @@ -3,6 +3,9 @@ namespace PKHeX.Core { + /// + /// Generation 3 object for Pokémon XD saves. + /// public sealed class SAV3XD : SaveFile { public override string BAKName => $"{FileName} [{OT} ({Version}) #{SaveCount:0000}].bak"; @@ -37,7 +40,7 @@ public SAV3XD(byte[] data = null) { Data = data == null ? new byte[SaveUtil.SIZE_G3XD] : (byte[])data.Clone(); BAK = (byte[])Data.Clone(); - Exportable = !Data.SequenceEqual(new byte[Data.Length]); + Exportable = !Data.All(z => z == 0); if (SaveUtil.GetIsG3XDSAV(Data) != GameVersion.XD) return; diff --git a/PKHeX.Core/Saves/SAV4.cs b/PKHeX.Core/Saves/SAV4.cs index 81da4543e..950f2bfb6 100644 --- a/PKHeX.Core/Saves/SAV4.cs +++ b/PKHeX.Core/Saves/SAV4.cs @@ -4,6 +4,9 @@ namespace PKHeX.Core { + /// + /// Generation 4 object. + /// public sealed class SAV4 : SaveFile { public override string BAKName => $"{FileName} [{OT} ({Version}) - {PlayTimeString}].bak"; @@ -13,7 +16,7 @@ public SAV4(byte[] data = null, GameVersion versionOverride = GameVersion.Any) { Data = data == null ? new byte[SaveUtil.SIZE_G4RAW] : (byte[])data.Clone(); BAK = (byte[])Data.Clone(); - Exportable = !Data.SequenceEqual(new byte[Data.Length]); + Exportable = !Data.All(z => z == 0); // Get Version if (data == null) diff --git a/PKHeX.Core/Saves/SAV4BR.cs b/PKHeX.Core/Saves/SAV4BR.cs index cb2f46e4a..f329b330b 100644 --- a/PKHeX.Core/Saves/SAV4BR.cs +++ b/PKHeX.Core/Saves/SAV4BR.cs @@ -5,6 +5,9 @@ namespace PKHeX.Core { + /// + /// Generation 4 object for Pokémon Battle Revolution saves. + /// public sealed class SAV4BR : SaveFile { public override string BAKName => $"{FileName} [{Version} #{SaveCount:0000}].bak"; diff --git a/PKHeX.Core/Saves/SAV5.cs b/PKHeX.Core/Saves/SAV5.cs index 954eab793..594d526a7 100644 --- a/PKHeX.Core/Saves/SAV5.cs +++ b/PKHeX.Core/Saves/SAV5.cs @@ -6,6 +6,9 @@ namespace PKHeX.Core { + /// + /// Generation 5 object. + /// public sealed class SAV5 : SaveFile { // Save Data Attributes @@ -16,7 +19,7 @@ public SAV5(byte[] data = null, GameVersion versionOverride = GameVersion.Any) { Data = data == null ? new byte[SaveUtil.SIZE_G5RAW] : (byte[])data.Clone(); BAK = (byte[])Data.Clone(); - Exportable = !Data.SequenceEqual(new byte[Data.Length]); + Exportable = !Data.All(z => z == 0); // Get Version if (data == null) diff --git a/PKHeX.Core/Saves/SAV6.cs b/PKHeX.Core/Saves/SAV6.cs index c4f234275..3040a1330 100644 --- a/PKHeX.Core/Saves/SAV6.cs +++ b/PKHeX.Core/Saves/SAV6.cs @@ -6,6 +6,9 @@ namespace PKHeX.Core { + /// + /// Generation 6 object. + /// public sealed class SAV6 : SaveFile { // Save Data Attributes @@ -16,7 +19,7 @@ public SAV6(byte[] data = null) { Data = data == null ? new byte[SaveUtil.SIZE_G6ORAS] : (byte[])data.Clone(); BAK = (byte[])Data.Clone(); - Exportable = !Data.SequenceEqual(new byte[Data.Length]); + Exportable = !Data.All(z => z == 0); // Load Info GetBlockInfo(); diff --git a/PKHeX.Core/Saves/SAV7.cs b/PKHeX.Core/Saves/SAV7.cs index 0e9b1d436..1f2c55d77 100644 --- a/PKHeX.Core/Saves/SAV7.cs +++ b/PKHeX.Core/Saves/SAV7.cs @@ -5,6 +5,9 @@ namespace PKHeX.Core { + /// + /// Generation 7 object. + /// public sealed class SAV7 : SaveFile { // Save Data Attributes @@ -21,18 +24,18 @@ public SAV7(byte[] data = null) { Data = data == null ? new byte[SaveUtil.SIZE_G7SM] : (byte[])data.Clone(); BAK = (byte[])Data.Clone(); - Exportable = !Data.SequenceEqual(new byte[Data.Length]); + Exportable = !Data.All(z => z == 0); // Load Info GetBlockInfo(); GetSAVOffsets(); - HeldItems = Legal.HeldItems_SM; + HeldItems = USUM ? Legal.HeldItems_USUM : Legal.HeldItems_SM; Personal = USUM ? PersonalTable.USUM : PersonalTable.SM; if (!Exportable) ClearBoxes(); - var demo = new byte[0x4C4].SequenceEqual(Data.Skip(PCLayout).Take(0x4C4)); // up to Battle Box values + var demo = !USUM && Data.Skip(PCLayout).Take(0x4C4).All(z => z == 0); // up to Battle Box values if (demo || !Exportable) { PokeDex = -1; // Disabled @@ -41,28 +44,10 @@ public SAV7(byte[] data = null) } else // Valid slot locking info present { - int lockedCount = 0, teamCount = 0; - for (int i = 0; i < TeamCount; i++) - { - bool locked = Data[PCBackgrounds - TeamCount - i] == 1; - for (int j = 0; j < 6; j++) - { - short val = BitConverter.ToInt16(Data, BattleBoxFlags + (i*6 + j) * 2); - if (val < 0) - continue; - - var slotVal = (BoxSlotCount*(val >> 8) + (val & 0xFF)) & 0xFFFF; - - if (locked) - LockedSlots[lockedCount++] = slotVal; - else TeamSlots[teamCount++] = slotVal; - } - } - Array.Resize(ref LockedSlots, lockedCount); - Array.Resize(ref TeamSlots, teamCount); + LoadLockedSlots(); } } - + // Configuration public override SaveFile Clone() { return new SAV7(Data); } @@ -819,8 +804,8 @@ public override InventoryPouch[] Inventory new InventoryPouch(InventoryType.Items, Legal.Pouch_Items_SM, 999, OFS_PouchHeldItem), new InventoryPouch(InventoryType.TMHMs, Legal.Pouch_TMHM_SM, 1, OFS_PouchTMHM), new InventoryPouch(InventoryType.Berries, Legal.Pouch_Berries_SM, 999, OFS_PouchBerry), - new InventoryPouch(InventoryType.KeyItems, Legal.Pouch_Key_SM, 1, OFS_PouchKeyItem), - new InventoryPouch(InventoryType.ZCrystals, Legal.Pouch_ZCrystal_SM, 1, OFS_PouchZCrystals), + new InventoryPouch(InventoryType.KeyItems, USUM ? Legal.Pouch_Key_USUM : Legal.Pouch_Key_SM, 1, OFS_PouchKeyItem), + new InventoryPouch(InventoryType.ZCrystals, USUM ? Legal.Pouch_ZCrystal_USUM : Legal.Pouch_ZCrystal_SM, 1, OFS_PouchZCrystals), }; foreach (var p in pouch) p.GetPouch7(ref Data); @@ -1175,6 +1160,28 @@ public override bool IsSlotInBattleTeam(int box, int slot) int slotIndex = slot + BoxSlotCount * box; return TeamSlots.Any(s => s == slotIndex); } + private void LoadLockedSlots() + { + int lockedCount = 0, teamCount = 0; + for (int i = 0; i < TeamCount; i++) + { + bool locked = Data[PCBackgrounds - TeamCount - i] == 1; + for (int j = 0; j < 6; j++) + { + short val = BitConverter.ToInt16(Data, BattleBoxFlags + (i * 6 + j) * 2); + if (val < 0) + continue; + + var slotVal = (BoxSlotCount * (val >> 8) + (val & 0xFF)) & 0xFFFF; + + if (locked) + LockedSlots[lockedCount++] = slotVal; + else TeamSlots[teamCount++] = slotVal; + } + } + Array.Resize(ref LockedSlots, lockedCount); + Array.Resize(ref TeamSlots, teamCount); + } public override int DaycareSeedSize => 32; // 128 bits public override int GetDaycareSlotOffset(int loc, int slot) diff --git a/PKHeX.Core/Saves/SaveFile.cs b/PKHeX.Core/Saves/SaveFile.cs index 8c384414c..b6ab17433 100644 --- a/PKHeX.Core/Saves/SaveFile.cs +++ b/PKHeX.Core/Saves/SaveFile.cs @@ -5,7 +5,9 @@ namespace PKHeX.Core { - // Base Class for Save Files + /// + /// Base Class for Save Files + /// public abstract class SaveFile { public static bool SetUpdateDex { protected get; set; } = true; @@ -198,9 +200,8 @@ public IList PartyData if (value[0].Species == 0) Debug.WriteLine($"Empty first slot, received {value.Count}."); - PKM[] newParty = value.Where(pk => pk.Species != 0).ToArray(); - - Array.Resize(ref newParty, 6); + PKM[] newParty = new PKM[6]; + value.Where(pk => pk.Species != 0).CopyTo(newParty); for (int i = PartyCount; i < newParty.Length; i++) newParty[i] = BlankPKM; @@ -658,8 +659,10 @@ public bool SetBoxBinary(byte[] data, int box) public virtual void SetSeen(int species, bool seen) { } public virtual bool GetCaught(int species) => false; public virtual void SetCaught(int species, bool caught) { } - public int SeenCount => HasPokeDex ? new bool[MaxSpeciesID].Where((b, i) => GetSeen(i+1)).Count() : 0; - public int CaughtCount => HasPokeDex ? new bool[MaxSpeciesID].Where((b, i) => GetCaught(i+1)).Count() : 0; + public int SeenCount => HasPokeDex ? Enumerable.Range(1, MaxSpeciesID).Count(GetSeen) : 0; + public int CaughtCount => HasPokeDex ? Enumerable.Range(1, MaxSpeciesID).Count(GetCaught) : 0; + public decimal PercentSeen => (decimal) SeenCount / MaxSpeciesID; + public decimal PercentCaught => (decimal)CaughtCount / MaxSpeciesID; public byte[] GetData(int Offset, int Length) { diff --git a/PKHeX.Core/Saves/SaveUtil.cs b/PKHeX.Core/Saves/SaveUtil.cs index a45c0dd91..06cf8be1c 100644 --- a/PKHeX.Core/Saves/SaveUtil.cs +++ b/PKHeX.Core/Saves/SaveUtil.cs @@ -6,6 +6,9 @@ namespace PKHeX.Core { + /// + /// Logic for data loading and manipulation. + /// public static class SaveUtil { public const int BEEF = 0x42454546; diff --git a/PKHeX.Core/Saves/Substructures/SaveObjects.cs b/PKHeX.Core/Saves/Substructures/SaveObjects.cs index 5e8a8b983..e74092043 100644 --- a/PKHeX.Core/Saves/Substructures/SaveObjects.cs +++ b/PKHeX.Core/Saves/Substructures/SaveObjects.cs @@ -13,6 +13,9 @@ public struct Daycare public ulong Seed; } + /// + /// Structure containing Mystery Gift Block Data + /// public struct MysteryGiftAlbum { public MysteryGift[] Gifts; diff --git a/PKHeX.WinForms/Controls/PKM Editor/EditPK3.cs b/PKHeX.WinForms/Controls/PKM Editor/EditPK3.cs index 946216b60..4097915c4 100644 --- a/PKHeX.WinForms/Controls/PKM Editor/EditPK3.cs +++ b/PKHeX.WinForms/Controls/PKM Editor/EditPK3.cs @@ -28,7 +28,7 @@ private void PopulateFieldsCK3() LoadMisc3(ck3); int abil = ck3.AbilityNumber >> 1; - CB_Ability.SelectedIndex = abil > CB_Ability.Items.Count ? 0 : abil; + CB_Ability.SelectedIndex = abil >= CB_Ability.Items.Count ? 0 : abil; LoadShadow3(ck3); LoadPartyStats(ck3); @@ -44,7 +44,7 @@ private void PopulateFieldsXK3() LoadMisc3(xk3); int abil = xk3.AbilityNumber >> 1; - CB_Ability.SelectedIndex = abil > CB_Ability.Items.Count ? 0 : abil; + CB_Ability.SelectedIndex = abil >= CB_Ability.Items.Count ? 0 : abil; LoadShadow3(xk3); LoadPartyStats(xk3); diff --git a/PKHeX.WinForms/Controls/PKM Editor/EditPK4.cs b/PKHeX.WinForms/Controls/PKM Editor/EditPK4.cs index 786ad8c22..727282e60 100644 --- a/PKHeX.WinForms/Controls/PKM Editor/EditPK4.cs +++ b/PKHeX.WinForms/Controls/PKM Editor/EditPK4.cs @@ -16,6 +16,7 @@ private void PopulateFieldsPK4() LoadMisc4(pk4); CB_EncounterType.SelectedValue = pk4.Gen4 ? pk4.EncounterType : 0; + CB_EncounterType.Visible = Label_EncounterType.Visible = pkm.Gen4; if (HaX) DEV_Ability.SelectedValue = pk4.Ability; diff --git a/PKHeX.WinForms/Controls/PKM Editor/EditPK5.cs b/PKHeX.WinForms/Controls/PKM Editor/EditPK5.cs index 46d76c8b4..208a447b5 100644 --- a/PKHeX.WinForms/Controls/PKM Editor/EditPK5.cs +++ b/PKHeX.WinForms/Controls/PKM Editor/EditPK5.cs @@ -14,6 +14,7 @@ private void PopulateFieldsPK5() LoadMisc3(pk5); LoadMisc4(pk5); CB_EncounterType.SelectedValue = pk5.Gen4 ? pk5.EncounterType : 0; + CB_EncounterType.Visible = Label_EncounterType.Visible = pkm.Gen4; CHK_NSparkle.Checked = pk5.NPokémon; if (HaX) diff --git a/PKHeX.WinForms/Controls/PKM Editor/EditPK6.cs b/PKHeX.WinForms/Controls/PKM Editor/EditPK6.cs index c4146982a..5c0e7377c 100644 --- a/PKHeX.WinForms/Controls/PKM Editor/EditPK6.cs +++ b/PKHeX.WinForms/Controls/PKM Editor/EditPK6.cs @@ -16,6 +16,7 @@ private void PopulateFieldsPK6() LoadMisc6(pk6); CB_EncounterType.SelectedValue = pk6.Gen4 ? pk6.EncounterType : 0; + CB_EncounterType.Visible = Label_EncounterType.Visible = pkm.Gen4; LoadPartyStats(pk6); UpdateStats(); diff --git a/PKHeX.WinForms/Controls/PKM Editor/LoadSave.cs b/PKHeX.WinForms/Controls/PKM Editor/LoadSave.cs index c60a4da0b..2fe7b261f 100644 --- a/PKHeX.WinForms/Controls/PKM Editor/LoadSave.cs +++ b/PKHeX.WinForms/Controls/PKM Editor/LoadSave.cs @@ -251,6 +251,9 @@ private void LoadMisc2(PKM pk) CB_HeldItem.SelectedValue = pk.HeldItem; CB_Form.SelectedIndex = CB_Form.Items.Count > pk.AltForm ? pk.AltForm : CB_Form.Items.Count - 1; TB_Friendship.Text = pk.CurrentFriendship.ToString(); + + Label_HatchCounter.Visible = CHK_IsEgg.Checked && pkm.Format > 1; + Label_Friendship.Visible = !CHK_IsEgg.Checked && pkm.Format > 1; } private void SaveMisc2(PKM pk) { diff --git a/PKHeX.WinForms/Controls/PKM Editor/PKMEditor.Designer.cs b/PKHeX.WinForms/Controls/PKM Editor/PKMEditor.Designer.cs index 5176757cd..897e67480 100644 --- a/PKHeX.WinForms/Controls/PKM Editor/PKMEditor.Designer.cs +++ b/PKHeX.WinForms/Controls/PKM Editor/PKMEditor.Designer.cs @@ -112,6 +112,7 @@ private void InitializeComponent() 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.Tab_Met = new System.Windows.Forms.TabPage(); this.CHK_AsEgg = new System.Windows.Forms.CheckBox(); this.GB_EggConditions = new System.Windows.Forms.GroupBox(); @@ -147,6 +148,7 @@ private void InitializeComponent() 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.Contest = new PKHeX.WinForms.Controls.ContestStat(); this.FLP_Stats = new System.Windows.Forms.FlowLayoutPanel(); this.FLP_StatHeader = new System.Windows.Forms.FlowLayoutPanel(); this.FLP_HackedStats = new System.Windows.Forms.FlowLayoutPanel(); @@ -272,8 +274,6 @@ private void InitializeComponent() this.Label_SID = new System.Windows.Forms.Label(); this.Label_TID = new System.Windows.Forms.Label(); this.Label_EncryptionConstant = new System.Windows.Forms.Label(); - this.ShinyLeaf = new PKHeX.WinForms.Controls.ShinyLeaf(); - this.Contest = new PKHeX.WinForms.Controls.ContestStat(); this.tabMain.SuspendLayout(); this.Tab_Main.SuspendLayout(); this.FLP_Main.SuspendLayout(); @@ -1354,6 +1354,11 @@ private void InitializeComponent() 0, 0, 0}); + this.NUD_Purification.Minimum = new decimal(new int[] { + 100, + 0, + 0, + -2147483648}); this.NUD_Purification.Name = "NUD_Purification"; this.NUD_Purification.Size = new System.Drawing.Size(51, 20); this.NUD_Purification.TabIndex = 103; @@ -1394,6 +1399,15 @@ private void InitializeComponent() 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(110, 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; + this.ShinyLeaf.Value = 0; + // // Tab_Met // this.Tab_Met.AllowDrop = true; @@ -1801,6 +1815,20 @@ private void InitializeComponent() this.Tab_Stats.Text = "Stats"; this.Tab_Stats.UseVisualStyleBackColor = true; // + // Contest + // + this.Contest.Beauty = 0; + this.Contest.Cool = 0; + this.Contest.Cute = 0; + this.Contest.Location = new System.Drawing.Point(21, 247); + this.Contest.Margin = new System.Windows.Forms.Padding(0); + this.Contest.Name = "Contest"; + this.Contest.Sheen = 0; + this.Contest.Size = new System.Drawing.Size(230, 50); + this.Contest.Smart = 0; + this.Contest.TabIndex = 117; + this.Contest.Tough = 0; + // // FLP_Stats // this.FLP_Stats.Controls.Add(this.FLP_StatHeader); @@ -3327,29 +3355,6 @@ private void InitializeComponent() this.Label_EncryptionConstant.Text = "Encryption Constant:"; this.Label_EncryptionConstant.TextAlign = System.Drawing.ContentAlignment.MiddleRight; // - // ShinyLeaf - // - this.ShinyLeaf.Location = new System.Drawing.Point(110, 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; - this.ShinyLeaf.Value = 0; - // - // Contest - // - this.Contest.Beauty = 0; - this.Contest.Cool = 0; - this.Contest.Cute = 0; - this.Contest.Location = new System.Drawing.Point(21, 247); - this.Contest.Margin = new System.Windows.Forms.Padding(0); - this.Contest.Name = "Contest"; - this.Contest.Sheen = 0; - this.Contest.Size = new System.Drawing.Size(230, 50); - this.Contest.Smart = 0; - this.Contest.TabIndex = 117; - this.Contest.Tough = 0; - // // PKMEditor // this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Inherit; diff --git a/PKHeX.WinForms/Controls/PKM Editor/PKMEditor.cs b/PKHeX.WinForms/Controls/PKM Editor/PKMEditor.cs index 1a63f4546..6e17e795a 100644 --- a/PKHeX.WinForms/Controls/PKM Editor/PKMEditor.cs +++ b/PKHeX.WinForms/Controls/PKM Editor/PKMEditor.cs @@ -62,10 +62,15 @@ public PKMEditor() public bool PKMIsUnsaved => fieldsInitialized && fieldsLoaded && LastData != null && LastData.Any(b => b != 0) && !LastData.SequenceEqual(PreparePKM().Data); public bool IsEmptyOrEgg => CHK_IsEgg.Checked || CB_Species.SelectedIndex == 0; + private bool forceValidation; public PKM PreparePKM(bool click = true) { if (click) + { + forceValidation = true; ValidateChildren(); + forceValidation = false; + } PKM pk = GetPKMfromFields(); return pk?.Clone(); } @@ -102,9 +107,6 @@ public void InitializeFields() { // Now that the ComboBoxes are ready, load the data. fieldsInitialized = true; - pkm.RefreshChecksum(); - - // Load Data PopulateFields(pkm); } @@ -170,37 +172,24 @@ public void SetPKMFormatMode(int Format) if (GB_ExtraBytes.Enabled) CB_ExtraBytes.SelectedIndex = 0; } - public void PopulateFields(PKM pk, bool focus = true) + public void PopulateFields(PKM pk, bool focus = true, bool skipConversionCheck = false) => LoadFieldsFromPKM(pk, focus, skipConversionCheck); + private void LoadFieldsFromPKM(PKM pk, bool focus = true, bool skipConversionCheck = true) { if (pk == null) { WinFormsUtil.Error("Attempted to load a null file."); return; } - - if (!PKMConverter.IsConvertibleToFormat(pk, pkm.Format)) - { WinFormsUtil.Alert($"Can't load Gen{pk.Format} to Gen{pkm.Format} games."); return; } - - bool oldInit = fieldsInitialized; - fieldsInitialized = fieldsLoaded = false; if (focus) Tab_Main.Focus(); - if (fieldsInitialized & !pkm.ChecksumValid) - WinFormsUtil.Alert("PKM File has an invalid checksum."); + if (!skipConversionCheck && !PKMConverter.TryMakePKMCompatible(pk, CurrentPKM, out string c, out pk)) + { WinFormsUtil.Alert(c); return; } - if (pk.Format != pkm.Format) // past gen format - { - pkm = PKMConverter.ConvertToType(pk.Clone(), pkm.GetType(), out string _); - if (pkm == null) - pkm = pk.Clone(); - else if (pk.Format != pkm.Format && focus) // converted - WinFormsUtil.Alert("Converted File."); - } - else - pkm = pk.Clone(); + bool oldInit = fieldsInitialized; + fieldsInitialized = fieldsLoaded = false; + + pkm = pk.Clone(); try { GetFieldsfromPKM(); } - catch { fieldsInitialized = oldInit; throw; } + finally { fieldsInitialized = oldInit; } - CB_EncounterType.Visible = Label_EncounterType.Visible = pkm.Gen4 && pkm.Format < 7; - fieldsInitialized = oldInit; UpdateIVs(null, null); UpdatePKRSInfected(null, null); UpdatePKRSCured(null, null); @@ -222,9 +211,6 @@ public void PopulateFields(PKM pk, bool focus = true) } fieldsLoaded = true; - Label_HatchCounter.Visible = CHK_IsEgg.Checked && pkm.Format > 1; - Label_Friendship.Visible = !CHK_IsEgg.Checked && pkm.Format > 1; - SetMarkings(); UpdateLegality(); UpdateSprite(); @@ -293,7 +279,7 @@ public void UpdateUnicode(string[] symbols) } private void UpdateSprite() { - if (fieldsLoaded && fieldsInitialized) + if (fieldsLoaded && fieldsInitialized && !forceValidation) UpdatePreviewSprite?.Invoke(this, null); } @@ -2070,22 +2056,22 @@ private void InitializeLanguage(SaveFile SAV) } private void PopulateFilteredDataSources(SaveFile SAV) { - GameInfo.SetItemDataSource(HaX, pkm.MaxItemID, SAV.HeldItems, pkm.Format, SAV.Version, GameInfo.Strings); - if (pkm.Format > 1) - CB_HeldItem.DataSource = new BindingSource(GameInfo.ItemDataSource.Where(i => i.Value <= pkm.MaxItemID).ToList(), null); + GameInfo.SetItemDataSource(HaX, SAV.MaxItemID, SAV.HeldItems, SAV.Generation, SAV.Version, GameInfo.Strings); + if (SAV.Generation > 1) + CB_HeldItem.DataSource = new BindingSource(GameInfo.ItemDataSource.Where(i => i.Value <= SAV.MaxItemID).ToList(), null); var languages = Util.GetUnsortedCBList("languages"); - if (pkm.Format < 7) + if (SAV.Generation < 7) languages = languages.Where(l => l.Value <= (int)LanguageID.Korean).ToList(); CB_Language.DataSource = languages; - CB_Ball.DataSource = new BindingSource(GameInfo.BallDataSource.Where(b => b.Value <= pkm.MaxBallID).ToList(), null); - CB_Species.DataSource = new BindingSource(GameInfo.SpeciesDataSource.Where(s => s.Value <= pkm.MaxSpeciesID).ToList(), null); - DEV_Ability.DataSource = new BindingSource(GameInfo.AbilityDataSource.Where(a => a.Value <= pkm.MaxAbilityID).ToList(), null); - CB_GameOrigin.DataSource = new BindingSource(GameInfo.VersionDataSource.Where(g => g.Value <= pkm.MaxGameID || pkm.Format >= 3 && g.Value == 15).ToList(), null); + CB_Ball.DataSource = new BindingSource(GameInfo.BallDataSource.Where(b => b.Value <= SAV.MaxBallID).ToList(), null); + CB_Species.DataSource = new BindingSource(GameInfo.SpeciesDataSource.Where(s => s.Value <= SAV.MaxSpeciesID).ToList(), null); + DEV_Ability.DataSource = new BindingSource(GameInfo.AbilityDataSource.Where(a => a.Value <= SAV.MaxAbilityID).ToList(), null); + CB_GameOrigin.DataSource = new BindingSource(GameInfo.VersionDataSource.Where(g => g.Value <= SAV.MaxGameID || SAV.Generation >= 3 && g.Value == 15).ToList(), null); // Set the Move ComboBoxes too.. - GameInfo.MoveDataSource = (HaX ? GameInfo.HaXMoveDataSource : GameInfo.LegalMoveDataSource).Where(m => m.Value <= pkm.MaxMoveID).ToList(); // Filter Z-Moves if appropriate + GameInfo.MoveDataSource = (HaX ? GameInfo.HaXMoveDataSource : GameInfo.LegalMoveDataSource).Where(m => m.Value <= SAV.MaxMoveID).ToList(); // Filter Z-Moves if appropriate foreach (ComboBox cb in new[] { CB_Move1, CB_Move2, CB_Move3, CB_Move4, CB_RelearnMove1, CB_RelearnMove2, CB_RelearnMove3, CB_RelearnMove4 }) { cb.DisplayMember = "Text"; cb.ValueMember = "Value"; diff --git a/PKHeX.WinForms/Controls/SAV Editor/ContextMenuSAV.cs b/PKHeX.WinForms/Controls/SAV Editor/ContextMenuSAV.cs index 87fb4b0b8..339885c03 100644 --- a/PKHeX.WinForms/Controls/SAV Editor/ContextMenuSAV.cs +++ b/PKHeX.WinForms/Controls/SAV Editor/ContextMenuSAV.cs @@ -33,7 +33,7 @@ private static void ClickView(object sender, EventArgs e) if ((sender as PictureBox)?.Image == null) { System.Media.SystemSounds.Asterisk.Play(); return; } - m.SE.PKME_Tabs.PopulateFields(m.GetPKM(info), false); + m.SE.PKME_Tabs.PopulateFields(m.GetPKM(info), false, true); m.SetColor(info.Box, info.Slot, Resources.slotView); } private static void ClickSet(object sender, EventArgs e) diff --git a/PKHeX.WinForms/MainWindow/Main.cs b/PKHeX.WinForms/MainWindow/Main.cs index 4b3944a5f..69836a043 100644 --- a/PKHeX.WinForms/MainWindow/Main.cs +++ b/PKHeX.WinForms/MainWindow/Main.cs @@ -99,9 +99,7 @@ private void FormLoadInitialSettings(string[] args, out bool showChangelog, out showChangelog = false; BAKprompt = false; - // Set up Language Selection - foreach (var cbItem in main_langlist) - CB_MainLanguage.Items.Add(cbItem); + CB_MainLanguage.Items.AddRange(main_langlist); C_SAV.HaX = PKME_Tabs.HaX = HaX = args.Any(x => string.Equals(x.Trim('-'), nameof(HaX), StringComparison.CurrentCultureIgnoreCase)); PB_Legal.Visible = !HaX; @@ -577,27 +575,11 @@ private bool TryLoadMemoryCard(byte[] input, string path) } private bool TryLoadPKM(byte[] input, string path, string ext, SaveFile SAV) { - var temp = PKMConverter.GetPKMfromBytes(input, prefer: ext.Length > 0 ? (ext.Last() - '0') & 0xF : C_SAV.SAV.Generation); - if (temp == null) - return false; - - var type = PKME_Tabs.CurrentPKM.GetType(); - PKM pk = PKMConverter.ConvertToType(temp, type, out string c); + var pk = PKMConverter.GetPKMfromBytes(input, prefer: ext.Length > 0 ? (ext.Last() - '0') & 0xF : C_SAV.SAV.Generation); if (pk == null) - { - WinFormsUtil.Alert("Conversion failed.", c); return false; - } - if (SAV.Generation < 3 && ((pk as PK1)?.Japanese ?? ((PK2)pk).Japanese) != SAV.Japanese) - { - var strs = new[] { "International", "Japanese" }; - var val = SAV.Japanese ? 0 : 1; - WinFormsUtil.Alert($"Cannot load {strs[val]} {pk.GetType().Name}s to {strs[val ^ 1]} saves."); - return false; - } PKME_Tabs.PopulateFields(pk); - Debug.WriteLine(c); return true; } private bool TryLoadPCBoxBin(byte[] input) @@ -607,7 +589,7 @@ private bool TryLoadPCBoxBin(byte[] input) if (!C_SAV.OpenPCBoxBin(input, out string c)) { WinFormsUtil.Alert("Binary is not compatible with save file.", c); - return false; + return true; } WinFormsUtil.Alert(c); @@ -989,28 +971,17 @@ private void ClickQR(object sender, EventArgs e) private void ImportQRToTabs(string url) { // Fetch data from QR code... - byte[] ekx = QR.GetQRData(url); - if (ekx == null) + byte[] input = QR.GetQRData(url); + if (input == null) return; - PKM pk = PKMConverter.GetPKMfromBytes(ekx, prefer: C_SAV.SAV.Generation); - if (pk == null) - { - WinFormsUtil.Alert("Decoded data not a valid PKM.", $"QR Data Size: {ekx.Length}"); + var sav = C_SAV.SAV; + if (TryLoadPKM(input, url, sav.Generation.ToString(), sav)) return; - } - if (!pk.Valid || pk.Species <= 0) - { - WinFormsUtil.Alert("Invalid data detected."); + if (TryLoadMysteryGift(input, url, null)) return; - } - PKM pkz = PKMConverter.ConvertToType(pk, C_SAV.SAV.PKMType, out string c); - if (pkz == null) - { - WinFormsUtil.Alert(c); - return; - } - PKME_Tabs.PopulateFields(pkz); + + WinFormsUtil.Alert("Decoded data not a valid PKM/Gift.", $"QR Data Size: {input.Length}"); } private void ExportQRFromTabs() { diff --git a/PKHeX.WinForms/Subforms/PKM Editors/BatchEditor.cs b/PKHeX.WinForms/Subforms/PKM Editors/BatchEditor.cs index 54391bab3..26bce0d32 100644 --- a/PKHeX.WinForms/Subforms/PKM Editors/BatchEditor.cs +++ b/PKHeX.WinForms/Subforms/PKM Editors/BatchEditor.cs @@ -623,7 +623,7 @@ private static void SetProperty(PKM PKM, StringInstruction cmd) else if (cmd.Random) ReflectFrameworkUtil.SetValue(PKM, cmd.PropertyName, cmd.RandomValue); else if (cmd.PropertyName == nameof(PKM.IsNicknamed) && cmd.PropertyValue.ToLower() == "false") - { PKM.IsNicknamed = false; PKM.Nickname = PKX.GetSpeciesName(PKM.Species, PKM.Language); } + { PKM.IsNicknamed = false; PKM.Nickname = PKX.GetSpeciesNameGeneration(PKM.Species, PKM.Language, PKM.Format); } else ReflectFrameworkUtil.SetValue(PKM, cmd.PropertyName, cmd.PropertyValue); }