From 3027eadb8dc21ea2a6bdc8640075fe79fd4cbc7e Mon Sep 17 00:00:00 2001 From: Kurt Date: Tue, 21 Mar 2017 00:18:38 -0700 Subject: [PATCH] Refactory legality strings For future translation feature as per #959 3 helper methods provided to facilitate the localization (import / export / update) I decided to simplify some duplicate-function sections --- PKHeX.WinForms/MainWindow/Main.cs | 2 +- PKHeX/Legality/Analysis.cs | 53 +- PKHeX/Legality/CheckStrings.cs | 316 +++++++++++ PKHeX/Legality/Checks.cs | 836 ++++++++++++++---------------- PKHeX/Legality/Core.cs | 2 +- PKHeX/PKHeX.Core.csproj | 1 + 6 files changed, 739 insertions(+), 471 deletions(-) create mode 100644 PKHeX/Legality/CheckStrings.cs diff --git a/PKHeX.WinForms/MainWindow/Main.cs b/PKHeX.WinForms/MainWindow/Main.cs index 415a6678a..d2bcc4252 100644 --- a/PKHeX.WinForms/MainWindow/Main.cs +++ b/PKHeX.WinForms/MainWindow/Main.cs @@ -2978,7 +2978,7 @@ private void showLegality(PKM pk, bool tabs, bool verbose, bool skipMoveRepop = } if (tabs) updateLegality(la, skipMoveRepop); - WinFormsUtil.Alert(verbose ? la.VerboseReport : la.Report); + WinFormsUtil.Alert(la.Report(verbose)); } private void updateLegality(LegalityAnalysis la = null, bool skipMoveRepop = false) { diff --git a/PKHeX/Legality/Analysis.cs b/PKHeX/Legality/Analysis.cs index 0a6c235b0..bd6cbeb0d 100644 --- a/PKHeX/Legality/Analysis.cs +++ b/PKHeX/Legality/Analysis.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.Linq; +using static PKHeX.Core.CheckStrings; namespace PKHeX.Core { @@ -25,8 +26,7 @@ public partial class LegalityAnalysis public bool ParsedInvalid => Parsed && !Valid; public CheckResult[] vMoves = new CheckResult[4]; public CheckResult[] vRelearn = new CheckResult[4]; - public string Report => getLegalityReport(); - public string VerboseReport => getVerboseLegalityReport(); + public string Report(bool verbose = false) => verbose ? getVerboseLegalityReport() : getLegalityReport(); public readonly int[] AllSuggestedMoves; public readonly int[] AllSuggestedRelearnMoves; public readonly int[] AllSuggestedMovesAndRelearn; @@ -70,7 +70,7 @@ public LegalityAnalysis(PKM pk) Valid = false; if (pkm.FatefulEncounter && vRelearn.Any(chk => !chk.Valid) && EncounterMatch == null) - AddLine(Severity.Indeterminate, "Fateful Encounter with no matching Encounter. Has the Mystery Gift data been contributed?", CheckIdentifier.Fateful); + AddLine(Severity.Indeterminate, V188, CheckIdentifier.Fateful); } else return; @@ -94,7 +94,7 @@ private void parsePK1(PKM pk) { pkm = pk; if (!pkm.IsOriginValid) - { AddLine(Severity.Invalid, "Species does not exist in origin game.", CheckIdentifier.None); return; } + { AddLine(Severity.Invalid, V187, CheckIdentifier.None); return; } updateEncounterChain(); updateMoveLegality(); @@ -102,46 +102,49 @@ private void parsePK1(PKM pk) verifyNickname(); verifyDVs(); verifyG1OT(); - verifyEggMoves(); + AddLine(verifyEggMoves()); } private void parsePK3(PKM pk) { pkm = pk; if (!pkm.IsOriginValid) - { AddLine(Severity.Invalid, "Species does not exist in origin game.", CheckIdentifier.None); return; } + { AddLine(Severity.Invalid, V187, CheckIdentifier.None); return; } updateEncounterChain(); updateMoveLegality(); updateEncounterInfo(); updateChecks(); + AddLine(verifyEggMoves()); } private void parsePK4(PKM pk) { pkm = pk; if (!pkm.IsOriginValid) - { AddLine(Severity.Invalid, "Species does not exist in origin game.", CheckIdentifier.None); return; } + { AddLine(Severity.Invalid, V187, CheckIdentifier.None); return; } updateEncounterChain(); updateMoveLegality(); updateEncounterInfo(); updateChecks(); + AddLine(verifyEggMoves()); } private void parsePK5(PKM pk) { pkm = pk; if (!pkm.IsOriginValid) - { AddLine(Severity.Invalid, "Species does not exist in origin game.", CheckIdentifier.None); return; } + { AddLine(Severity.Invalid, V187, CheckIdentifier.None); return; } updateEncounterChain(); updateMoveLegality(); updateEncounterInfo(); updateChecks(); + AddLine(verifyEggMoves()); } private void parsePK6(PKM pk) { pkm = pk; if (!pkm.IsOriginValid) - { AddLine(Severity.Invalid, "Species does not exist in origin game.", CheckIdentifier.None); return; } + { AddLine(Severity.Invalid, V187, CheckIdentifier.None); return; } updateRelearnLegality(); updateEncounterChain(); @@ -153,7 +156,7 @@ private void parsePK7(PKM pk) { pkm = pk; if (!pkm.IsOriginValid) - { AddLine(Severity.Invalid, "Species does not exist in origin game.", CheckIdentifier.None); return; } + { AddLine(Severity.Invalid, V187, CheckIdentifier.None); return; } updateRelearnLegality(); updateEncounterChain(); @@ -165,13 +168,13 @@ private void parsePK7(PKM pk) private void updateRelearnLegality() { try { vRelearn = verifyRelearn(); } - catch { for (int i = 0; i < 4; i++) vRelearn[i] = new CheckResult(Severity.Invalid, "Internal error.", CheckIdentifier.RelearnMove); } + catch { for (int i = 0; i < 4; i++) vRelearn[i] = new CheckResult(Severity.Invalid, V190, CheckIdentifier.RelearnMove); } // SecondaryChecked = false; } private void updateMoveLegality() { try { vMoves = verifyMoves(); } - catch { for (int i = 0; i < 4; i++) vMoves[i] = new CheckResult(Severity.Invalid, "Internal error.", CheckIdentifier.Move); } + catch { for (int i = 0; i < 4; i++) vMoves[i] = new CheckResult(Severity.Invalid, V190, CheckIdentifier.Move); } // SecondaryChecked = false; } @@ -227,26 +230,27 @@ private void updateChecks() private string getLegalityReport() { if (!Parsed) - return "Analysis not available for this Pokémon."; + return V189; string r = ""; for (int i = 0; i < 4; i++) if (!vMoves[i].Valid) - r += $"{vMoves[i].Judgement} Move {i + 1}: {vMoves[i].Comment}" + Environment.NewLine; + r += string.Format(V191, vMoves[i].Judgement, i + 1, vMoves[i].Comment) + Environment.NewLine; if (pkm.Format >= 6) for (int i = 0; i < 4; i++) if (!vRelearn[i].Valid) - r += $"{vRelearn[i].Judgement} Relearn Move {i + 1}: {vRelearn[i].Comment}" + Environment.NewLine; + r += string.Format(V192, vRelearn[i].Judgement, i + 1, vRelearn[i].Comment) + Environment.NewLine; if (r.Length == 0 && Parse.All(chk => chk.Valid) && Valid) - return "Legal!"; + return V193; // Build result string... - r += Parse.Where(chk => !chk.Valid).Aggregate("", (current, chk) => current + $"{chk.Judgement}: {chk.Comment}{Environment.NewLine}"); + var outputLines = Parse.Where(chk => !chk.Valid); // Only invalid + r += string.Join(Environment.NewLine, outputLines.Select(chk => string.Format(V196, chk.Judgement, chk.Comment))); if (r.Length == 0) - r = "Internal Error."; + r = V190; return r.TrimEnd(); } @@ -260,21 +264,22 @@ private string getVerboseLegalityReport() for (int i = 0; i < 4; i++) if (vMoves[i].Valid) - r += $"{vMoves[i].Judgement} Move {i + 1}: {vMoves[i].Comment}" + Environment.NewLine; + r += string.Format(V191, vMoves[i].Judgement, i + 1, vMoves[i].Comment) + Environment.NewLine; if (pkm.Format >= 6) - for (int i = 0; i < 4; i++) + for (int i = 0; i < 4; i++) if (vRelearn[i].Valid) - r += $"{vRelearn[i].Judgement} Relearn Move {i + 1}: {vRelearn[i].Comment}" + Environment.NewLine; + r += string.Format(V192, vRelearn[i].Judgement, i + 1, vRelearn[i].Comment) + Environment.NewLine; if (rl != r.Length) // move info added, break for next section r += Environment.NewLine; - r += Parse.Where(chk => chk != null && chk.Valid && chk.Comment != "Valid").OrderBy(chk => chk.Judgement) // Fishy sorted to top - .Aggregate("", (current, chk) => current + $"{chk.Judgement}: {chk.Comment}{Environment.NewLine}"); + var outputLines = Parse.Where(chk => chk != null && chk.Valid && chk.Comment != V).OrderBy(chk => chk.Judgement); // Fishy sorted to top + r += string.Join(Environment.NewLine, outputLines.Select(chk => string.Format(V196, chk.Judgement, chk.Comment))); r += Environment.NewLine; - r += "Encounter Type: " + EncounterName; + r += "===" + Environment.NewLine + Environment.NewLine; + r += string.Format(V195, EncounterName); return r.TrimEnd(); } diff --git a/PKHeX/Legality/CheckStrings.cs b/PKHeX/Legality/CheckStrings.cs new file mode 100644 index 000000000..0e18bdd51 --- /dev/null +++ b/PKHeX/Legality/CheckStrings.cs @@ -0,0 +1,316 @@ +// ReSharper disable AutoPropertyCanBeMadeGetOnly.Local +// ReSharper disable AutoPropertyCanBeMadeGetOnly.Global + +using System; +using System.Collections.Generic; +using System.Linq; + +namespace PKHeX.Core +{ + public static class CheckStrings + { + public const string splitter = " = "; + public static void RefreshStrings(IEnumerable lines) + { + var t = typeof (CheckStrings); + foreach (var line in lines.Where(l => l != null)) + { + var index = line.IndexOf(splitter, StringComparison.Ordinal); + var prop = line.Substring(0, index); + var value = line.Substring(index + splitter.Length); + + try + { + ReflectUtil.SetValue(t, prop, value); + } + catch + { + Console.WriteLine($"Property not present: {prop} || Value written: {value}"); + } + } + } + public static IEnumerable DumpStrings() + { + var t = typeof (CheckStrings); + var props = ReflectUtil.getPropertiesStartWithPrefix(t, "V"); + return props.Select(p => $"{p}{splitter}{ReflectUtil.GetValue(t, p).ToString()}"); + } + public static string[] UpdateLocalization(string[] lines) + { + List list = new List(); + var current = DumpStrings(); + foreach (var line in current) + { + int index = line.IndexOf(splitter, StringComparison.Ordinal); + string prop = line.Substring(0, index); + string match = lines.FirstOrDefault(l => l.StartsWith(prop)); + list.Add(match ?? line); + } + return list.ToArray(); + } + + #region General Strings + + /// Default text for indicating validity. + public static string V {get; set;} = "Valid."; + /// Default text for indicating legality. + public static string V193 {get; set;} = "Legal!"; + /// Default text for indicating an error has occurred. + public static string V190 {get; set;} = "Internal error."; + /// Analysis not available for the + public static string V189 {get; set;} = "Analysis not available for this Pokémon."; + /// Format text for exporting a legality check result. + public static string V196 {get; set;} = "{0}: {1}"; + /// Format text for exporting a legality check result for an invalid Move. + public static string V191 {get; set;} = "{0} Move {1}: {2}"; + /// Format text for exporting a legality check result for an invalid Relearn Move. + public static string V192 {get; set;} = "{0} Relearn Move {1}: {2}"; + /// Format text for exporting the type of Encounter that was matched for the the + public static string V195 {get; set;} = "Encounter Type: {0}"; + + /// Original Trainer string used in various string formats such as Memories. + public static string V205 { get; set; } = "OT"; + /// Handling Trainer string used in various string formats such as Memories. + public static string V206 { get; set; } = "HT"; + + public static string V167 { get; set; } = "Empty Move."; + public static string V171 { get; set; } = "Egg Move."; + public static string V172 { get; set; } = "Relearnable Move."; + public static string V173 { get; set; } = "Learned by TM/HM."; + public static string V174 { get; set; } = "Learned by Move Tutor."; + public static string V175 { get; set; } = "Special Non-Relearn Move."; + public static string V177 { get; set; } = "Learned by Level-up."; + + #endregion + + #region Legality Check Result Strings + + public static string V203 {get; set;} = "Genderless Pokémon should not have a gender."; + public static string V201 {get; set;} = "Encryption Constant is not set."; + public static string V204 {get; set;} = "Held item is unreleased."; + + public static string V187 {get; set;} = "Species does not exist in origin game."; + public static string V188 {get; set;} = "Fateful Encounter with no matching Encounter. Has the Mystery Gift data been contributed?"; + public static string V194 { get; set;} = "Ingame Trade for Sun/Moon not implemented."; // Valid + + public static string V207 {get; set;} = "PID is not set."; + public static string V208 {get; set;} = "Encryption Constant matches PID."; + public static string V209 {get; set;} = "Static Encounter shiny mismatch."; + public static string V210 {get; set;} = "Wurmple evolution Encryption Constant mismatch."; + public static string V211 {get; set;} = "Encryption Constant matches shinyxored PID."; + public static string V212 {get; set;} = "Wurmple Evolution: {0}"; + public static string V213 {get; set;} = "Silcoon"; + public static string V214 {get; set;} = "Cascoon"; + public static string V215 {get; set;} = "PID should be equal to EC [with top bit flipped]!"; + public static string V216 {get; set;} = "PID should be equal to EC!"; + + public static string V14 {get; set;} = "Egg matches language Egg name."; // Valid + public static string V17 {get; set;} = "Nickname does not match another species name."; // Valid + public static string V18 {get; set;} = "Nickname matches species name."; // Valid + public static string V19 {get; set;} = "Nickname matches demo language name."; // Valid + public static string V11 {get; set;} = "Ingame Trade OT and Nickname have not been altered."; // Valid + public static string V1 {get; set;} = "Nickname too long."; // Invalid + public static string V2 {get; set;} = "Nickname is empty."; // Invalid + public static string V4 {get; set;} = "Language ID > 8."; // Invalid + public static string V5 {get; set;} = "Language ID > 10."; // Invalid + public static string V3 {get; set;} = "Species index invalid for Nickname comparison."; // Invalid + public static string V20 {get; set;} = "Nickname does not match species name."; // Invalid + public static string V13 {get; set;} = "Egg name does not match language Egg name."; // Invalid + public static string V12 {get; set;} = "Eggs must be nicknamed."; // Invalid + public static string V7 {get; set;} = "Ingame Trade invalid version?"; // Invalid + public static string V8 {get; set;} = "Ingame Trade invalid index?"; // Invalid + public static string V10 {get; set;} = "Ingame Trade OT has been altered."; // Invalid + public static string V9 {get; set;} = "Ingame Trade Nickname has been altered."; // Fishy + public static string V15 {get; set;} = "Nickname matches another species name (+language)."; // Fishy + public static string V16 {get; set;} = "Nickname flagged, matches species name."; // Fishy + + public static string V21 {get; set;} = "Matches: {0} {1}"; // Valid + + public static string V25 {get; set;} = "EV total cannot be above 510."; // Invalid + public static string V22 {get; set;} = "Eggs cannot receive EVs."; // Invalid + public static string V23 {get; set;} = "All EVs are zero, but leveled above Met Level."; // Fishy + public static string V24 {get; set;} = "2 EVs remaining."; // Fishy + public static string V26 {get; set;} = "EVs cannot go above 252."; // Invalid + public static string V27 {get; set;} = "EVs are all equal."; // Fishy + public static string V31 {get; set;} = "All IVs are 0."; // Fishy + public static string V32 {get; set;} = "All IVs are equal."; // Fishy + + public static string V28 {get; set;} = "Should have at least {0} IVs {get; set;} = 31."; // Invalid + public static string V29 {get; set;} = "Friend Safari captures should have at least 2 IVs {get; set;} = 31."; // Invalid + public static string V30 {get; set;} = "IVs do not match Mystery Gift Data."; // Invalid + + public static string V38 {get; set;} = "OT Name too long."; // Invalid + public static string V39 {get; set;} = "Incorrect RBY event OT Name."; // Invalid + public static string V34 {get; set;} = "SID should be 0."; // Invalid + public static string V33 {get; set;} = "TID and SID are 0."; // Fishy + public static string V35 {get; set;} = "TID and SID are equal."; // Fishy + public static string V36 {get; set;} = "TID is zero."; // Fishy + public static string V37 {get; set;} = "SID is zero."; // Fishy + + public static string V40 {get; set;} = "Can't Hyper Train a pokemon that isn't level 100."; // Invalid + public static string V41 {get; set;} = "Can't Hyper Train a pokemon with perfect IVs."; // Invalid + public static string V42 {get; set;} = "Can't Hyper Train a perfect IV."; // Invalid + + public static string V49 {get; set;} = "Valid Pokémon Link gift."; // Valid + public static string V47 {get; set;} = "Pokémon Link gift Shiny mismatch."; // Invalid + public static string V48 {get; set;} = "Pokémon Link gift should not be Fateful Encounter."; // Invalid + public static string V43 {get; set;} = "Can't find matching Pokémon Link gift."; // Invalid + public static string V44 {get; set;} = "Can't obtain this Pokémon Link gift in XY."; // Invalid + public static string V45 {get; set;} = "Can't obtain this Pokémon Link gift in ORAS."; // Invalid + public static string V46 {get; set;} = "Can't obtain this Pokémon Link gift in SM."; // Invalid + + public static string V63 {get; set;} = "Valid un-hatched egg."; // Valid + public static string V53 {get; set;} = "Able to hatch an egg at Met Location."; // Valid + public static string V56 {get; set;} = "Able to hatch a traded egg at Met Location."; + public static string V54 {get; set;} = "Can't hatch an egg at Met Location."; // Invalid + public static string V55 {get; set;} = "Can't obtain egg from Egg Location."; // Invalid + public static string V57 {get; set;} = "Can't transfer eggs between generations."; // Invalid + public static string V50 {get; set;} = "Can't obtain egg for this species."; // Invalid + public static string V51 {get; set;} = "Invalid Met Location for hatched egg."; // Invalid + public static string V52 {get; set;} = "Invalid Met Level, expected {0}."; // Invalid + public static string V58 {get; set;} = "Invalid Met Level for transfer."; // Invalid + public static string V59 {get; set;} = "Invalid Egg Location, expected none."; // Invalid + public static string V60 {get; set;} = "Invalid Met Location, expected Pal Park."; // Invalid + public static string V61 {get; set;} = "Invalid Met Location, expected Transporter."; // Invalid + public static string V62 {get; set;} = "Invalid Egg Location, shouldn't be 'traded' while an egg."; // Invalid + + public static string V66 {get; set;} = "Valid Friend Safari encounter."; // Valid + public static string V64 {get; set;} = "Friend Safari: Not valid color."; // Florges + public static string V6 {get; set;} = "Friend Safari: Not average sized."; // Pumpkaboo + public static string V65 {get; set;} = "Friend Safari: Not Spring form."; // Sawsbuck + + public static string V67 {get; set;} = "Valid Wild Encounter at location (Pressure/Hustle/Vital Spirit)."; + public static string V68 {get; set;} = "Valid Wild Encounter at location."; + public static string V69 {get; set;} = "Valid Wild Encounter at location (White Flute & Pressure/Hustle/Vital Spirit)."; + public static string V70 {get; set;} = "Valid Wild Encounter at location (White Flute)."; + public static string V71 {get; set;} = "Valid Wild Encounter at location (Black Flute & Pressure/Hustle/Vital Spirit)."; + public static string V72 {get; set;} = "Valid Wild Encounter at location (Black Flute)."; + public static string V73 {get; set;} = "Valid Wild Encounter at location (DexNav)."; + + public static string V76 {get; set;} = "Valid ingame trade."; + public static string V75 {get; set;} = "Valid gift/static encounter."; // Valid + public static string V74 {get; set;} = "Static encounter relearn move mismatch."; + + public static string V77 {get; set;} = "Can't obtain Species from Virtual Console games."; // Invalid + public static string V79 {get; set;} = "Can't obtain Special encounter in Virtual Console games."; // Invalid + public static string V78 {get; set;} = "Unable to match to a Mystery Gift in the database."; // Invalid + public static string V80 {get; set;} = "Unable to match an encounter from origin game."; // Invalid + public static string V81 {get; set;} = "Invalid Transfer Met Location."; // Invalid + public static string V82 {get; set;} = "Mewtwo cannot be transferred while knowing Pay Day."; // Invalid + + public static string V88 {get; set;} = "Current level is not below met level."; + public static string V83 {get; set;} = "Met Level does not match Mystery Gift level."; + public static string V84 {get; set;} = "Current Level below Mystery Gift level."; + public static string V85 {get; set;} = "Current level is below met level."; + public static string V86 {get; set;} = "Evolution not valid (or level/trade evolution unsatisfied)."; + public static string V87 {get; set;} = "Current experience matches level threshold."; // Fishy + + public static string V89 {get; set;} = "Can't Super Train an egg."; // Invalid + public static string V90 {get; set;} = "Super Training missions are not available in games visited."; + public static string V91 {get; set;} = "Can't have active Super Training unlocked flag for origins."; + public static string V92 {get; set;} = "Can't have active Super Training complete flag for origins."; + public static string V93 {get; set;} = "Super Training complete flag mismatch."; + public static string V94 {get; set;} = "Distribution Super Training missions are not released."; // Fishy + + public static string V95 {get; set;} = "Can't receive Ribbon(s) as an egg."; + public static string V96 {get; set;} = "GBA Champion Ribbon"; + public static string V97 {get; set;} = "Artist Ribbon"; + public static string V98 {get; set;} = "National Ribbon (Purified)"; + public static string V99 {get; set;} = "Sinnoh Champion Ribbon"; + public static string V100 {get; set;} = "Legend Ribbon"; + public static string V104 {get; set;} = "Record Ribbon"; + public static string V101 {get; set;} = "Missing Ribbons: {0}"; + public static string V102 {get; set;} = "Invalid Ribbons: {0}"; + public static string V103 {get; set;} = "All ribbons accounted for."; + public static string V105 {get; set;} = "Battle Memory Ribbon"; + public static string V106 {get; set;} = "Contest Memory Ribbon"; + + public static string V107 {get; set;} = "Ability is not valid for species/form."; + public static string V108 {get; set;} = "Hidden Ability mismatch for encounter type."; + public static string V109 {get; set;} = "Ability modified with Ability Capsule."; + public static string V110 {get; set;} = "Ability does not match Mystery Gift."; + public static string V111 {get; set;} = "Hidden Ability on non-SOS wild encounter."; + public static string V112 {get; set;} = "Hidden Ability not available."; + + public static string V115 {get; set;} = "Ability matches ability number."; // Valid + public static string V113 {get; set;} = "Ability does not match PID."; + public static string V114 {get; set;} = "Ability does not match ability number."; + + public static string V119 {get; set;} = "Correct ball for encounter type."; + public static string V118 {get; set;} = "Can't have ball for encounter type."; + public static string V116 {get; set;} = "Can't have Heavy Ball for light, low-catch rate species (Gen VII)."; + public static string V117 {get; set;} = "Can't have Master Ball for regular egg."; + public static string V120 {get; set;} = "Can't have Cherish Ball for regular egg."; + public static string V121 {get; set;} = "Can't obtain species in Ball."; + public static string V122 {get; set;} = "Can't obtain Hidden Ability with Ball."; + public static string V123 {get; set;} = "Ball possible for species."; + public static string V125 {get; set;} = "No check satisfied, assuming illegal."; + public static string V126 {get; set;} = "Ball unobtainable in origin generation."; + + public static string V145 {get; set;} = "History block is valid."; + public static string V155 {get; set;} = "{0} Memory is valid."; + + public static string V127 {get; set;} = "Skipped History check due to other check being invalid."; + public static string V128 {get; set;} = "No History Block to check."; + public static string V129 {get; set;} = "OT Affection should be 0."; + public static string V130 {get; set;} = "Can't have any OT Memory."; + public static string V124 {get; set;} = "Current handler cannot be past gen OT for transferred specimen."; + public static string V131 {get; set;} = "HT Gender invalid: {0}"; + public static string V132 {get; set;} = "Event OT Friendship does not match base friendship."; + public static string V133 {get; set;} = "Event OT Affection should be zero."; + public static string V134 {get; set;} = "Current handler should not be Event OT."; + public static string V138 {get; set;} = "Contest Stats should be 0."; + public static string V137 {get; set;} = "GeoLocation Memory: Memories should be present."; + public static string V135 {get; set;} = "GeoLocation Memory: Gap/Blank present."; + public static string V136 {get; set;} = "GeoLocation Memory: Region without Country."; + public static string V146 {get; set;} = "GeoLocation Memory: HT Name present but has no previous Country."; + public static string V147 {get; set;} = "GeoLocation Memory: Previous country of residence present with no Handling Trainer."; + public static string V139 {get; set;} = "Untraded: Current handler should not be the Handling Trainer."; + public static string V140 {get; set;} = "Untraded: Handling Trainer Friendship should be 0."; + public static string V141 {get; set;} = "Untraded: Handling Trainer Affection should be 0."; + public static string V142 {get; set;} = "Untraded: Requires a trade evolution."; + public static string V143 {get; set;} = "Untraded: Beauty is not high enough for Level-up Evolution."; + public static string V144 {get; set;} = "Untraded: Beauty is high enough but still Level 1."; + public static string V148 {get; set;} = "Memory: Handling Trainer Memory present with no Handling Trainer name."; + public static string V150 {get; set;} = "Memory: Handling Trainer Memory missing."; + public static string V152 {get; set;} = "Memory: Original Trainer Memory missing."; + public static string V149 {get; set;} = "Memory: Can't have Handling Trainer Memory as egg."; + public static string V151 {get; set;} = "Memory: Can't have Original Trainer Memory as egg."; + public static string V164 {get; set;} = "{0} Memory: Species can be captured in game."; + public static string V153 {get; set;} = "{0} Memory: Species can't learn this move."; + public static string V154 {get; set;} = "{0} Memory: Location doesn't have a Pokemon Center."; + public static string V160 {get; set;} = "{0} Memory: {0} did not hatch this."; + public static string V202 {get; set;} = "{0} Memory: {0} did not catch this."; + public static string V161 {get; set;} = "{0} Memory: Link Trade is not a valid first memory."; + public static string V162 {get; set;} = "{0} Memory: Can't obtain Location on {0} Version."; + public static string V163 {get; set;} = "{0} Memory: Can't obtain Memory on {0} Version."; + public static string V165 {get; set;} = "{0} Memory: Can't capture species in game."; + public static string V197 {get; set;} = "{0} Memory: Should be index {1}."; + public static string V198 {get; set;} = "{0} Memory: Intensity should be index {1}."; + public static string V199 {get; set;} = "{0} Memory: TextVar should be index {1}."; + public static string V200 {get; set;} = "{0} Memory: Feeling should be index {1}."; + + public static string V168 {get; set;} = "Duplicate Move."; + public static string V176 {get; set;} = "Invalid Move."; + public static string V166 {get; set;} = "Invalid Move (Sketch)."; + public static string V169 {get; set;} = "Keldeo Move/Form mismatch."; + public static string V181 {get; set;} = "Expected the following Relearn Moves: {0}"; + public static string V170 {get; set;} = "Relearn Moves missing: {0}"; + public static string V178 {get; set;} = "Expected: {0}."; + + public static string V179 {get; set;} = "Base egg move."; + public static string V180 {get; set;} = "Base egg move missing."; + public static string V182 {get; set;} = "Not an expected Relearnable move."; + public static string V183 {get; set;} = "Not an expected DexNav move."; + public static string V184 {get; set;} = "Expected no Relearn Move in slot."; + public static string V185 {get; set;} = "Egg Moves Source: {0}."; + public static string V186 {get; set;} = "Egg Move set check unimplemented."; + public static string V156 {get; set;} = "Should have a Link Trade HT Memory."; + public static string V157 {get; set;} = "Should have a HT Memory TextVar value (somewhere)."; + public static string V158 {get; set;} = "Should have a HT Memory Intensity value (1st)."; + public static string V159 {get; set;} = "Should have a HT Memory Feeling value 0-9."; + + #endregion + + } +} diff --git a/PKHeX/Legality/Checks.cs b/PKHeX/Legality/Checks.cs index a4a690c1c..92501bc8b 100644 --- a/PKHeX/Legality/Checks.cs +++ b/PKHeX/Legality/Checks.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.Linq; +using static PKHeX.Core.CheckStrings; namespace PKHeX.Core { @@ -46,7 +47,7 @@ internal enum CheckIdentifier public class CheckResult { internal readonly Severity Judgement = Severity.Valid; - internal string Comment = "Valid"; + internal string Comment = V; public bool Valid => Judgement >= Severity.Fishy; public bool Flag; internal readonly CheckIdentifier Identifier; @@ -65,34 +66,32 @@ private void verifyGender() { if (pkm.PersonalInfo.Gender == 255 && pkm.Gender != 2) { - AddLine(Severity.Invalid, "Genderless Pokémon should not have a gender.", CheckIdentifier.Gender); + AddLine(Severity.Invalid, V203, CheckIdentifier.Gender); // return; } } - private void verifyItem() { if (!Legal.getHeldItemAllowed(pkm.Format, pkm.HeldItem)) - AddLine(Severity.Invalid, "Held item is unreleased.", CheckIdentifier.Form); + AddLine(Severity.Invalid, V204, CheckIdentifier.Form); } - private void verifyECPID() { if (pkm.EncryptionConstant == 0) - AddLine(Severity.Fishy, "Encryption Constant is not set.", CheckIdentifier.EC); + AddLine(Severity.Fishy, V201, CheckIdentifier.EC); if (pkm.PID == 0) - AddLine(Severity.Fishy, "PID is not set.", CheckIdentifier.PID); + AddLine(Severity.Fishy, V207, CheckIdentifier.PID); if (pkm.GenNumber >= 6 && pkm.PID == pkm.EncryptionConstant) - AddLine(Severity.Fishy, "Encryption Constant matches PID.", CheckIdentifier.PID); + AddLine(Severity.Fishy, V208, CheckIdentifier.PID); if (EncounterType == typeof (EncounterStatic)) { var enc = (EncounterStatic) EncounterMatch; if (enc.Shiny != null && (bool) enc.Shiny ^ pkm.IsShiny) { - AddLine(Severity.Invalid, $"Encounter {(enc.Shiny == true ? "must be" : "cannot be")} shiny.", CheckIdentifier.Shiny); + AddLine(Severity.Invalid, V209, CheckIdentifier.Shiny); return; } } @@ -107,19 +106,19 @@ private void verifyECPID() if (pkm.WasEgg || (EncounterType == typeof(EncounterSlot[]) && (EncounterMatch as EncounterSlot[]).All(slot => slot.Species == 265))) if ((pkm.EncryptionConstant >> 16)%10/5 != wIndex/2) { - AddLine(Severity.Invalid, "Wurmple evolution Encryption Constant mismatch.", CheckIdentifier.EC); + AddLine(Severity.Invalid, V210, CheckIdentifier.EC); return; } } else if (pkm.Species == 265) { - AddLine(Severity.Valid, "Wurmple Evolution: " + ((pkm.EncryptionConstant >> 16)%10/5 == 0 ? "Silcoon" : "Cascoon"), CheckIdentifier.EC); + AddLine(Severity.Valid, string.Format(V212, (pkm.EncryptionConstant >> 16)%10/5 == 0 ? V213 : V214), CheckIdentifier.EC); } int xor = pkm.TSV ^ pkm.PSV; if (xor < 16 && xor >= 8 && (pkm.PID ^ 0x80000000) == pkm.EncryptionConstant) { - AddLine(Severity.Fishy, "Encryption Constant matches shinyxored PID.", CheckIdentifier.EC); + AddLine(Severity.Fishy, V211, CheckIdentifier.EC); return; } } @@ -142,8 +141,8 @@ private void verifyECPID() { AddLine(Severity.Invalid, xorPID - ? "PID should be equal to EC [with top bit flipped]!" - : "PID should be equal to EC!", CheckIdentifier.ECPID); + ? V215 + : V216, CheckIdentifier.ECPID); } } private void verifyNickname() @@ -151,12 +150,12 @@ private void verifyNickname() // If the Pokémon is not nicknamed, it should match one of the language strings. if (pkm.Nickname.Length == 0) { - AddLine(Severity.Invalid, "Nickname is empty.", CheckIdentifier.Nickname); + AddLine(Severity.Invalid, V2, CheckIdentifier.Nickname); return; } if (pkm.Species > PKX.SpeciesLang[0].Length) { - AddLine(Severity.Indeterminate, "Species index invalid for Nickname comparison.", CheckIdentifier.Nickname); + AddLine(Severity.Indeterminate, V3, CheckIdentifier.Nickname); return; } @@ -167,7 +166,7 @@ private void verifyNickname() int lang = Array.IndexOf(PKX.SpeciesLang, langset); if (pk.Length > (lang == 2 ? 10 : 5)) - AddLine(Severity.Invalid, "Nickname too long.", CheckIdentifier.Nickname); + AddLine(Severity.Invalid, V1, CheckIdentifier.Nickname); } if (!Encounter.Valid) @@ -175,12 +174,12 @@ private void verifyNickname() if (pkm.Format <= 6 && pkm.Language > 8) { - AddLine(Severity.Indeterminate, "Language ID > 8.", CheckIdentifier.Language); + AddLine(Severity.Indeterminate, V4, CheckIdentifier.Language); return; } if (pkm.Format <= 7 && pkm.Language > 10) { - AddLine(Severity.Indeterminate, "Language ID > 10.", CheckIdentifier.Language); + AddLine(Severity.Indeterminate, V5, CheckIdentifier.Language); return; } @@ -201,7 +200,7 @@ private void verifyNickname() else if (pkm.SM) { // TODO - AddLine(Severity.Valid, "Ingame Trade for Sun/Moon not implemented.", CheckIdentifier.Nickname); + AddLine(Severity.Valid, V194, CheckIdentifier.Nickname); return; } else if (pkm.Format <= 2 || pkm.VC) @@ -210,7 +209,7 @@ private void verifyNickname() if (et?.TID == 0) // Gen1 Trade { if (!Legal.getEncounterTrade1Valid(pkm)) - AddLine(Severity.Invalid, "Incorrect OT name for RBY in-game trade.", CheckIdentifier.Trainer); + AddLine(Severity.Invalid, V10, CheckIdentifier.Trainer); } else // Gen2 { @@ -221,12 +220,12 @@ private void verifyNickname() if (validOT.Length == 0) { - AddLine(Severity.Indeterminate, "Ingame Trade invalid version?", CheckIdentifier.Trainer); + AddLine(Severity.Indeterminate, V7, CheckIdentifier.Trainer); return; } if (index == -1 || validOT.Length < index*2) { - AddLine(Severity.Indeterminate, "Ingame Trade invalid lookup?", CheckIdentifier.Trainer); + AddLine(Severity.Indeterminate, V8, CheckIdentifier.Trainer); return; } @@ -234,11 +233,11 @@ private void verifyNickname() string OT = validOT[validOT.Length/2 + index]; if (nick != pkm.Nickname) - AddLine(Severity.Fishy, "Ingame Trade nickname has been altered.", CheckIdentifier.Nickname); + AddLine(Severity.Fishy, V9, CheckIdentifier.Nickname); else if (OT != pkm.OT_Name) - AddLine(Severity.Invalid, "Ingame Trade OT has been altered.", CheckIdentifier.Trainer); + AddLine(Severity.Invalid, V10, CheckIdentifier.Trainer); else - AddLine(Severity.Valid, "Ingame Trade OT/Nickname have not been altered.", CheckIdentifier.Nickname); + AddLine(Severity.Valid, V11, CheckIdentifier.Nickname); return; } @@ -246,11 +245,11 @@ private void verifyNickname() if (pkm.IsEgg) { if (!pkm.IsNicknamed && (pkm.Format != 7)) - AddLine(Severity.Invalid, "Eggs must be nicknamed.", CheckIdentifier.Egg); + AddLine(Severity.Invalid, V12, CheckIdentifier.Egg); else if (PKX.SpeciesLang[pkm.Language][0] != pkm.Nickname) - AddLine(Severity.Invalid, "Egg name does not match language Egg name.", CheckIdentifier.Egg); + AddLine(Severity.Invalid, V13, CheckIdentifier.Egg); else - AddLine(Severity.Valid, "Egg matches language Egg name.", CheckIdentifier.Egg); + AddLine(Severity.Valid, V14, CheckIdentifier.Egg); return; } @@ -266,16 +265,16 @@ private void verifyNickname() continue; AddLine(Severity.Fishy, index == pkm.Species && i != pkm.Language - ? "Nickname matches another species name (+language)." - : "Nickname flagged, matches species name.", CheckIdentifier.Nickname); + ? V15 + : V16, CheckIdentifier.Nickname); return; } - AddLine(Severity.Valid, "Nickname does not match another species name.", CheckIdentifier.Nickname); + AddLine(Severity.Valid, V17, CheckIdentifier.Nickname); } else if (pkm.Format < 3) { // pk1/pk2 IsNicknamed getter checks for match, logic should only reach here if matches. - AddLine(Severity.Valid, "Nickname matches species name.", CheckIdentifier.Nickname); + AddLine(Severity.Valid, V18, CheckIdentifier.Nickname); } else { @@ -286,12 +285,12 @@ private void verifyNickname() if (!match) { if ((EncounterMatch as MysteryGift)?.CardID == 2046 && (pkm.SID << 16 | pkm.TID) == 0x79F57B49) - AddLine(Severity.Valid, "Nickname matches demo language name.", CheckIdentifier.Nickname); + AddLine(Severity.Valid, V19, CheckIdentifier.Nickname); else - AddLine(Severity.Invalid, "Nickname does not match species name.", CheckIdentifier.Nickname); + AddLine(Severity.Invalid, V20, CheckIdentifier.Nickname); } else - AddLine(Severity.Valid, "Nickname matches species name.", CheckIdentifier.Nickname); + AddLine(Severity.Valid, V18, CheckIdentifier.Nickname); } } private void verifyEVs() @@ -299,17 +298,17 @@ private void verifyEVs() var evs = pkm.EVs; int sum = evs.Sum(); if (pkm.IsEgg && sum > 0) - AddLine(Severity.Invalid, "Eggs cannot receive EVs.", CheckIdentifier.EVs); + AddLine(Severity.Invalid, V22, CheckIdentifier.EVs); else if (sum == 0 && pkm.Stat_Level - pkm.Met_Level > 0) - AddLine(Severity.Fishy, "All EVs are zero, but leveled above Met Level.", CheckIdentifier.EVs); + AddLine(Severity.Fishy, V23, CheckIdentifier.EVs); else if (sum == 508) - AddLine(Severity.Fishy, "2 EVs remaining.", CheckIdentifier.EVs); + AddLine(Severity.Fishy, V24, CheckIdentifier.EVs); else if (sum > 510) - AddLine(Severity.Invalid, "EV total cannot be above 510.", CheckIdentifier.EVs); + AddLine(Severity.Invalid, V25, CheckIdentifier.EVs); else if (pkm.Format >= 6 && evs.Any(ev => ev > 252)) - AddLine(Severity.Invalid, "EVs cannot go above 252.", CheckIdentifier.EVs); + AddLine(Severity.Invalid, V26, CheckIdentifier.EVs); else if (evs.All(ev => pkm.EVs[0] == ev) && evs[0] != 0) - AddLine(Severity.Fishy, "EVs are all equal.", CheckIdentifier.EVs); + AddLine(Severity.Fishy, V27, CheckIdentifier.EVs); } private void verifyIVs() { @@ -321,7 +320,7 @@ private void verifyIVs() IVCount = 5; // VC Mew if (pkm.IVs.Count(iv => iv == 31) < IVCount) { - AddLine(Severity.Invalid, $"Should have at least {IVCount} IVs = 31.", CheckIdentifier.IVs); + AddLine(Severity.Invalid, string.Format(V28, IVCount), CheckIdentifier.IVs); return; } } @@ -329,7 +328,7 @@ private void verifyIVs() { if (pkm.IVs.Count(iv => iv == 31) < 2) { - AddLine(Severity.Invalid, "Friend Safari captures should have at least 2 IVs = 31.", CheckIdentifier.IVs); + AddLine(Severity.Invalid, V29, CheckIdentifier.IVs); return; } } @@ -352,13 +351,13 @@ private void verifyIVs() if (IVs[i] <= 31 && IVs[i] != pkIVs[i]) valid = false; if (!valid) - AddLine(Severity.Invalid, "IVs do not match Mystery Gift Data.", CheckIdentifier.IVs); + AddLine(Severity.Invalid, V30, CheckIdentifier.IVs); } } if (pkm.IVs.Sum() == 0) - AddLine(Severity.Fishy, "All IVs are zero.", CheckIdentifier.IVs); + AddLine(Severity.Fishy, V31, CheckIdentifier.IVs); else if (pkm.IVs[0] < 30 && pkm.IVs.All(iv => pkm.IVs[0] == iv)) - AddLine(Severity.Fishy, "All IVs are equal.", CheckIdentifier.IVs); + AddLine(Severity.Fishy, V32, CheckIdentifier.IVs); } private void verifyDVs() { @@ -370,18 +369,18 @@ private void verifyOT() return; // Already matches Encounter Trade information if (pkm.TID == 0 && pkm.SID == 0) - AddLine(Severity.Fishy, "TID and SID are zero.", CheckIdentifier.Trainer); + AddLine(Severity.Fishy, V33, CheckIdentifier.Trainer); else if (pkm.VC) { if (pkm.SID != 0) - AddLine(Severity.Invalid, "SID should be 0.", CheckIdentifier.Trainer); + AddLine(Severity.Invalid, V34, CheckIdentifier.Trainer); } else if (pkm.TID == pkm.SID) - AddLine(Severity.Fishy, "TID and SID are equal.", CheckIdentifier.Trainer); + AddLine(Severity.Fishy, V35, CheckIdentifier.Trainer); else if (pkm.TID == 0) - AddLine(Severity.Fishy, "TID is zero.", CheckIdentifier.Trainer); + AddLine(Severity.Fishy, V36, CheckIdentifier.Trainer); else if (pkm.SID == 0) - AddLine(Severity.Fishy, "SID is zero.", CheckIdentifier.Trainer); + AddLine(Severity.Fishy, V37, CheckIdentifier.Trainer); if (pkm.VC) verifyG1OT(); @@ -394,11 +393,11 @@ private void verifyG1OT() int lang = Array.IndexOf(PKX.SpeciesLang, langset); if (tr.Length > (lang == 2 ? 7 : 5)) - AddLine(Severity.Invalid, "OT Name too long.", CheckIdentifier.Trainer); + AddLine(Severity.Invalid, V38, CheckIdentifier.Trainer); if (pkm.Species == 151) { if (tr != "GF" && tr != "ゲーフリ") // if there are more events with special OTs, may be worth refactoring - AddLine(Severity.Invalid, "Incorrect event OT Name.", CheckIdentifier.Trainer); + AddLine(Severity.Invalid, V39, CheckIdentifier.Trainer); } } @@ -411,16 +410,16 @@ private void verifyHyperTraining() var HTs = new[] { pkm.HT_HP, pkm.HT_ATK, pkm.HT_DEF, pkm.HT_SPA, pkm.HT_SPD, pkm.HT_SPE }; if (HTs.Any(ht => ht) && pkm.CurrentLevel != 100) - AddLine(Severity.Invalid, "Can't Hyper Train a pokemon that isn't level 100.", CheckIdentifier.IVs); + AddLine(Severity.Invalid, V40, CheckIdentifier.IVs); if (IVs.All(iv => iv == 31) && HTs.Any(ht => ht)) - AddLine(Severity.Invalid, "Can't Hyper Train a pokemon with perfect IVs.", CheckIdentifier.IVs); + AddLine(Severity.Invalid, V41, CheckIdentifier.IVs); else { for (int i = 0; i < 6; i++) // Check individual IVs { if ((IVs[i] == 31) && HTs[i]) - AddLine(Severity.Invalid, "Can't Hyper Train a perfect IV.", CheckIdentifier.IVs); + AddLine(Severity.Invalid, V42, CheckIdentifier.IVs); } } } @@ -430,27 +429,27 @@ private CheckResult verifyEncounterLink() // Should NOT be Fateful, and should be in Database EncounterLink enc = EncounterMatch as EncounterLink; if (enc == null) - return new CheckResult(Severity.Invalid, "Invalid Link Gift: unable to find matching gift.", CheckIdentifier.Encounter); + return new CheckResult(Severity.Invalid, V43, CheckIdentifier.Encounter); if (pkm.XY && !enc.XY) - return new CheckResult(Severity.Invalid, "Invalid Link Gift: can't obtain in XY.", CheckIdentifier.Encounter); + return new CheckResult(Severity.Invalid, V44, CheckIdentifier.Encounter); if (pkm.AO && !enc.ORAS) - return new CheckResult(Severity.Invalid, "Invalid Link Gift: can't obtain in ORAS.", CheckIdentifier.Encounter); + return new CheckResult(Severity.Invalid, V45, CheckIdentifier.Encounter); if (pkm.SM && !enc.SM) - return new CheckResult(Severity.Invalid, "Invalid Link Gift: can't obtain in SM.", CheckIdentifier.Encounter); + return new CheckResult(Severity.Invalid, V46, CheckIdentifier.Encounter); if (enc.Shiny != null && (bool)enc.Shiny ^ pkm.IsShiny) - return new CheckResult(Severity.Invalid, "Shiny Link gift mismatch.", CheckIdentifier.Encounter); + return new CheckResult(Severity.Invalid, V47, CheckIdentifier.Encounter); return pkm.FatefulEncounter - ? new CheckResult(Severity.Invalid, "Invalid Link Gift: should not be Fateful Encounter.", CheckIdentifier.Encounter) - : new CheckResult(Severity.Valid, "Valid Link gift.", CheckIdentifier.Encounter); + ? new CheckResult(Severity.Invalid, V48, CheckIdentifier.Encounter) + : new CheckResult(Severity.Valid, V49, CheckIdentifier.Encounter); } private CheckResult verifyEncounterEvent() { MysteryGift MatchedGift = EncounterMatch as MysteryGift; if (MatchedGift != null) - return new CheckResult(Severity.Valid, $"Matches #{MatchedGift.CardID:0000} ({MatchedGift.CardTitle})", CheckIdentifier.Encounter); + return new CheckResult(Severity.Valid, string.Format(V21, MatchedGift.CardID.ToString("0000"), MatchedGift.CardTitle), CheckIdentifier.Encounter); return null; } @@ -458,7 +457,7 @@ private CheckResult verifyEncounterEgg() { // Check Species if (Legal.NoHatchFromEgg.Contains(pkm.Species)) - return new CheckResult(Severity.Invalid, "Species cannot be hatched from an egg.", CheckIdentifier.Encounter); + return new CheckResult(Severity.Invalid, V50, CheckIdentifier.Encounter); switch (pkm.GenNumber) { @@ -471,7 +470,7 @@ private CheckResult verifyEncounterEgg() case 7: return pkm.IsEgg ? verifyUnhatchedEgg(30002) : verifyEncounterEgg7(); default: // none of the above - return new CheckResult(Severity.Invalid, "Invalid location for hatched egg.", CheckIdentifier.Encounter); + return new CheckResult(Severity.Invalid, V51, CheckIdentifier.Encounter); } } private CheckResult verifyEncounterEgg3() @@ -479,51 +478,51 @@ private CheckResult verifyEncounterEgg3() if (pkm.Format == 3) { if (pkm.Met_Level != 0) - return new CheckResult(Severity.Invalid, "Invalid met level, expected 0.", CheckIdentifier.Encounter); + return new CheckResult(Severity.Invalid, string.Format(V52, 0), CheckIdentifier.Encounter); if (pkm.IsEgg) { var loc = pkm.FRLG ? 146 /* Four Island */ : 32; /* RSE: Route 117 */ if (pkm.Met_Location != loc) - return new CheckResult(Severity.Invalid, "Invalid unhatched egg met location.", CheckIdentifier.Encounter); + return new CheckResult(Severity.Invalid, V55, CheckIdentifier.Encounter); } else { var locs = pkm.FRLG ? Legal.ValidMet_FRLG : pkm.E ? Legal.ValidMet_E : Legal.ValidMet_RS; if (locs.Contains(pkm.Met_Location)) - return new CheckResult(Severity.Valid, "Valid hatch (met) location.", CheckIdentifier.Encounter); + return new CheckResult(Severity.Valid, V53, CheckIdentifier.Encounter); if (Legal.ValidMet_FRLG.Contains(pkm.Met_Location) || Legal.ValidMet_E.Contains(pkm.Met_Location) || Legal.ValidMet_RS.Contains(pkm.Met_Location)) - return new CheckResult(Severity.Valid, "Trade egg valid hatch (met) location.", CheckIdentifier.Encounter); - return new CheckResult(Severity.Invalid, "Invalid hatch (met) location.", CheckIdentifier.Encounter); + return new CheckResult(Severity.Valid, V56, CheckIdentifier.Encounter); + return new CheckResult(Severity.Invalid, V54, CheckIdentifier.Encounter); } } else { if (pkm.IsEgg) - return new CheckResult(Severity.Invalid, "Gen 3 unhatched egg can not be transfered via Pal Park.", CheckIdentifier.Encounter); + return new CheckResult(Severity.Invalid, V57, CheckIdentifier.Encounter); if (pkm.Met_Level < 5) - return new CheckResult(Severity.Invalid, "Invalid met level for transfer.", CheckIdentifier.Encounter); + return new CheckResult(Severity.Invalid, V58, CheckIdentifier.Encounter); if (pkm.Egg_Location != 0) - return new CheckResult(Severity.Invalid, "Invalid Egg location, expected none.", CheckIdentifier.Encounter); + return new CheckResult(Severity.Invalid, V59, CheckIdentifier.Encounter); if (pkm.Format == 4 && pkm.Met_Location != 0x37) // Pal Park - return new CheckResult(Severity.Invalid, "Invalid Met location, expected Pal Park.", CheckIdentifier.Encounter); + return new CheckResult(Severity.Invalid, V60, CheckIdentifier.Encounter); if (pkm.Format != 4 && pkm.Met_Location != 30001) - return new CheckResult(Severity.Invalid, "Invalid Met location, expected Transporter.", CheckIdentifier.Encounter); + return new CheckResult(Severity.Invalid, V61, CheckIdentifier.Encounter); } - return new CheckResult(CheckIdentifier.Encounter); + return new CheckResult(Severity.Valid, V53, CheckIdentifier.Encounter); } private CheckResult verifyEncounterEgg4() { if (pkm.Format == 4) return verifyEncounterEggLevelLoc(0, pkm.HGSS ? Legal.ValidMet_HGSS : pkm.Pt ? Legal.ValidMet_Pt : Legal.ValidMet_DP); - else if (pkm.IsEgg) - return new CheckResult(Severity.Invalid, "Gen 4 unhatched egg can not be transfered via Transporter", CheckIdentifier.Encounter); + if (pkm.IsEgg) + return new CheckResult(Severity.Invalid, V57, CheckIdentifier.Encounter); // transferred if (pkm.Met_Level < 1) - return new CheckResult(Severity.Invalid, "Invalid met level for transfer.", CheckIdentifier.Encounter); + return new CheckResult(Severity.Invalid, V58, CheckIdentifier.Encounter); if (pkm.Met_Location != 30001) - return new CheckResult(Severity.Invalid, "Invalid Met location, expected Transporter.", CheckIdentifier.Encounter); - return new CheckResult(CheckIdentifier.Encounter); + return new CheckResult(Severity.Invalid, V61, CheckIdentifier.Encounter); + return new CheckResult(Severity.Valid, V63, CheckIdentifier.Encounter); } private CheckResult verifyEncounterEgg5() { @@ -535,7 +534,7 @@ private CheckResult verifyEncounterEgg6() return verifyEncounterEggLevelLoc(1, Legal.ValidMet_AO); if (pkm.Egg_Location == 318) - return new CheckResult(Severity.Invalid, "Invalid X/Y egg location.", CheckIdentifier.Encounter); + return new CheckResult(Severity.Invalid, V55, CheckIdentifier.Encounter); return verifyEncounterEggLevelLoc(1, Legal.ValidMet_XY); } @@ -545,26 +544,26 @@ private CheckResult verifyEncounterEgg7() return verifyEncounterEggLevelLoc(1, Legal.ValidMet_SM); // no other games - return new CheckResult(Severity.Invalid, "Invalid location for hatched egg.", CheckIdentifier.Encounter); + return new CheckResult(Severity.Invalid, V51, CheckIdentifier.Encounter); } private CheckResult verifyEncounterEggLevelLoc(int eggLevel, int[] MetLocations) { if (pkm.Met_Level != eggLevel) - return new CheckResult(Severity.Invalid, $"Invalid met level, expected {eggLevel}.", CheckIdentifier.Encounter); + return new CheckResult(Severity.Invalid, string.Format(V52, eggLevel), CheckIdentifier.Encounter); return MetLocations.Contains(pkm.Met_Location) - ? new CheckResult(Severity.Valid, "Valid hatch (met) location.", CheckIdentifier.Encounter) - : new CheckResult(Severity.Invalid, "Invalid hatch (met) location.", CheckIdentifier.Encounter); + ? new CheckResult(Severity.Valid, V53, CheckIdentifier.Encounter) + : new CheckResult(Severity.Invalid, V54, CheckIdentifier.Encounter); } private CheckResult verifyUnhatchedEgg(int tradeLoc) { if (pkm.Egg_Location == tradeLoc) - return new CheckResult(Severity.Invalid, "Egg location shouldn't be 'traded' for an un-hatched egg.", CheckIdentifier.Encounter); + return new CheckResult(Severity.Invalid, V62, CheckIdentifier.Encounter); if (pkm.Met_Location == tradeLoc) - return new CheckResult(Severity.Valid, "Valid traded un-hatched egg.", CheckIdentifier.Encounter); + return new CheckResult(Severity.Valid, V56, CheckIdentifier.Encounter); return pkm.Met_Location == 0 - ? new CheckResult(Severity.Valid, "Valid un-hatched egg.", CheckIdentifier.Encounter) - : new CheckResult(Severity.Invalid, "Invalid location for un-hatched egg (expected no met location).", CheckIdentifier.Encounter); + ? new CheckResult(Severity.Valid, V63, CheckIdentifier.Encounter) + : new CheckResult(Severity.Invalid, V59, CheckIdentifier.Encounter); } private CheckResult verifyEncounterSafari() @@ -574,20 +573,20 @@ private CheckResult verifyEncounterSafari() case 670: // Floette case 671: // Florges if (!new[] {0, 1, 3}.Contains(pkm.AltForm)) // 0/1/3 - RBY - return new CheckResult(Severity.Invalid, "Friend Safari: Not valid color.", CheckIdentifier.Encounter); + return new CheckResult(Severity.Invalid, V64, CheckIdentifier.Encounter); break; case 710: // Pumpkaboo case 711: // Goregeist if (pkm.AltForm != 1) // Average - return new CheckResult(Severity.Invalid, "Friend Safari: Not average sized.", CheckIdentifier.Encounter); + return new CheckResult(Severity.Invalid, V6, CheckIdentifier.Encounter); break; case 586: // Sawsbuck if (pkm.AltForm != 0) - return new CheckResult(Severity.Invalid, "Friend Safari: Not Spring form.", CheckIdentifier.Encounter); + return new CheckResult(Severity.Invalid, V65, CheckIdentifier.Encounter); break; } - return new CheckResult(Severity.Valid, "Valid Friend Safari encounter.", CheckIdentifier.Encounter); + return new CheckResult(Severity.Valid, V66, CheckIdentifier.Encounter); } private CheckResult verifyEncounterWild() @@ -596,25 +595,25 @@ private CheckResult verifyEncounterWild() if (enc.Any(slot => slot.Normal)) return enc.All(slot => slot.Pressure) - ? new CheckResult(Severity.Valid, "Valid encounter at location (Pressure/Hustle/Vital Spirit).", CheckIdentifier.Encounter) - : new CheckResult(Severity.Valid, "Valid encounter at location.", CheckIdentifier.Encounter); + ? new CheckResult(Severity.Valid, V67, CheckIdentifier.Encounter) + : new CheckResult(Severity.Valid, V68, CheckIdentifier.Encounter); // Decreased Level Encounters if (enc.Any(slot => slot.WhiteFlute)) return enc.All(slot => slot.Pressure) - ? new CheckResult(Severity.Valid, "Valid encounter at location (White Flute & Pressure/Hustle/Vital Spirit).", CheckIdentifier.Encounter) - : new CheckResult(Severity.Valid, "Valid encounter at location (White Flute).", CheckIdentifier.Encounter); + ? new CheckResult(Severity.Valid, V69, CheckIdentifier.Encounter) + : new CheckResult(Severity.Valid, V70, CheckIdentifier.Encounter); // Increased Level Encounters if (enc.Any(slot => slot.BlackFlute)) return enc.All(slot => slot.Pressure) - ? new CheckResult(Severity.Valid, "Valid encounter at location (Black Flute & Pressure/Hustle/Vital Spirit).", CheckIdentifier.Encounter) - : new CheckResult(Severity.Valid, "Valid encounter at location (Black Flute).", CheckIdentifier.Encounter); + ? new CheckResult(Severity.Valid, V71, CheckIdentifier.Encounter) + : new CheckResult(Severity.Valid, V72, CheckIdentifier.Encounter); if (enc.Any(slot => slot.Pressure)) - return new CheckResult(Severity.Valid, "Valid encounter at location (Pressure/Hustle/Vital Spirit).", CheckIdentifier.Encounter); + return new CheckResult(Severity.Valid, V67, CheckIdentifier.Encounter); - return new CheckResult(Severity.Valid, "Valid encounter at location (DexNav).", CheckIdentifier.Encounter); + return new CheckResult(Severity.Valid, V73, CheckIdentifier.Encounter); } private CheckResult verifyEncounterStatic() { @@ -625,21 +624,21 @@ private CheckResult verifyEncounterStatic() { for (int i = 0; i < 4; i++) vRelearn[i] = pkm.RelearnMoves[i] != s.Relearn[i] - ? new CheckResult(Severity.Invalid, "Static encounter relearn move mismatch.", CheckIdentifier.RelearnMove) + ? new CheckResult(Severity.Invalid, V74, CheckIdentifier.RelearnMove) : new CheckResult(CheckIdentifier.RelearnMove); - return new CheckResult(Severity.Valid, "Valid gift/static encounter.", CheckIdentifier.Encounter); + return new CheckResult(Severity.Valid, V75, CheckIdentifier.Encounter); } return null; } private CheckResult verifyEncounterTrade() { - return new CheckResult(Severity.Valid, "Valid ingame trade.", CheckIdentifier.Encounter); + return new CheckResult(Severity.Valid, V76, CheckIdentifier.Encounter); } private CheckResult verifyEncounterG12() { var obj = Legal.getEncounter12(pkm, Legal.AllowGBCartEra && pkm.Format < 3); if (obj == null) - return new CheckResult(Severity.Invalid, "Unknown encounter.", CheckIdentifier.Encounter); + return new CheckResult(Severity.Invalid, V80, CheckIdentifier.Encounter); EncounterMatch = obj.Item1; if (EncounterMatch is bool) @@ -656,7 +655,7 @@ private CheckResult verifyEncounterG12() // shouldn't ever hit, above 3*invalid check should abort Console.WriteLine($"Gen1 encounter fallthrough: {pkm.FileName}"); - return new CheckResult(Severity.Invalid, "Unknown encounter.", CheckIdentifier.Encounter); + return new CheckResult(Severity.Invalid, V80, CheckIdentifier.Encounter); } private CheckResult verifyEncounter() { @@ -666,7 +665,7 @@ private CheckResult verifyEncounter() bool g1 = pkm.VC1 || pkm.Format == 1; if ((g1 && baseSpecies > Legal.MaxSpeciesID_1) || (baseSpecies > Legal.MaxSpeciesID_2)) - return new CheckResult(Severity.Invalid, "VC: Unobtainable species.", CheckIdentifier.Encounter); + return new CheckResult(Severity.Invalid, V77, CheckIdentifier.Encounter); // Get EncounterMatch prior to parsing transporter legality var result = verifyEncounterG12(); @@ -710,9 +709,9 @@ private CheckResult verifyEncounter() if (null != (EncounterMatch = Legal.getValidIngameTrade(pkm))) return verifyEncounterTrade(); - return wasEvent - ? new CheckResult(Severity.Invalid, "Unable to match to a Mystery Gift in the database.", CheckIdentifier.Encounter) - : new CheckResult(Severity.Invalid, "Unknown encounter.", CheckIdentifier.Encounter); + return wasEvent + ? new CheckResult(Severity.Invalid, V78, CheckIdentifier.Encounter) + : new CheckResult(Severity.Invalid, V80, CheckIdentifier.Encounter); } private CheckResult verifyVCEncounter(int baseSpecies) { @@ -724,7 +723,7 @@ private CheckResult verifyVCEncounter(int baseSpecies) // Check existing EncounterMatch if ((EncounterOriginal ?? EncounterMatch) == null) - return new CheckResult(Severity.Invalid, "Unable to match an encounter from origin game.", CheckIdentifier.Encounter); + return new CheckResult(Severity.Invalid, V80, CheckIdentifier.Encounter); var s = EncounterMatch as EncounterStatic; if (s != null && s.Version == GameVersion.SPECIAL) @@ -732,19 +731,19 @@ private CheckResult verifyVCEncounter(int baseSpecies) bool exceptions = false; exceptions |= baseSpecies == 151 && pkm.TID == 22796; if (!exceptions) - AddLine(new CheckResult(Severity.Invalid, "Special encounter is not available to Virtual Console games.", CheckIdentifier.Encounter)); + AddLine(new CheckResult(Severity.Invalid, V79, CheckIdentifier.Encounter)); } EncounterMatch = Legal.getRBYStaticTransfer(species); var ematch = (EncounterStatic) EncounterMatch; if (pkm.Met_Location != ematch.Location) - return new CheckResult(Severity.Invalid, "Invalid met location.", CheckIdentifier.Encounter); + return new CheckResult(Severity.Invalid, V81, CheckIdentifier.Encounter); if (pkm.Egg_Location != ematch.EggLocation) - return new CheckResult(Severity.Invalid, "Should not have an egg location.", CheckIdentifier.Encounter); + return new CheckResult(Severity.Invalid, V59, CheckIdentifier.Encounter); if (species == 150 && pkm.Moves.Contains(6)) - return new CheckResult(Severity.Invalid, "Mewtwo cannot be transferred while knowing Pay Day.", CheckIdentifier.Encounter); + return new CheckResult(Severity.Invalid, V82, CheckIdentifier.Encounter); return new CheckResult(CheckIdentifier.Encounter); } @@ -756,31 +755,31 @@ private void verifyLevel() { if (!(MatchedGift is WC7) || ((WC7) MatchedGift).MetLevel != pkm.Met_Level) { - AddLine(new CheckResult(Severity.Invalid, "Met Level does not match Wonder Card level.", CheckIdentifier.Level)); + AddLine(new CheckResult(Severity.Invalid, V83, CheckIdentifier.Level)); return; } } if (MatchedGift != null && MatchedGift.Level > pkm.CurrentLevel) { - AddLine(new CheckResult(Severity.Invalid, "Current Level below Wonder Card level.", CheckIdentifier.Level)); + AddLine(new CheckResult(Severity.Invalid, V84, CheckIdentifier.Level)); return; } int lvl = pkm.CurrentLevel; if (pkm.IsEgg) { - var eggValid = pkm.Format <= 3 ? lvl == 5 : lvl == 1; - if (!eggValid) - AddLine(Severity.Invalid, "Current level for an egg is invalid.", CheckIdentifier.Level); + int elvl = pkm.Format <= 3 ? 5 : 1; + if (elvl != lvl) + AddLine(Severity.Invalid, string.Format(V52, elvl), CheckIdentifier.Level); } else if (lvl < pkm.Met_Level) - AddLine(Severity.Invalid, "Current level is below met level.", CheckIdentifier.Level); + AddLine(Severity.Invalid, V85, CheckIdentifier.Level); else if ((pkm.WasEgg || EncounterMatch == null) && !Legal.getEvolutionValid(pkm) && pkm.Species != 350) - AddLine(Severity.Invalid, "Evolution not valid (or level/trade evolution unsatisfied).", CheckIdentifier.Level); + AddLine(Severity.Invalid, V86, CheckIdentifier.Level); else if (lvl > pkm.Met_Level && lvl > 1 && lvl != 100 && pkm.EXP == PKX.getEXP(pkm.Stat_Level, pkm.Species)) - AddLine(Severity.Fishy, "Current experience matches level threshold.", CheckIdentifier.Level); + AddLine(Severity.Fishy, V87, CheckIdentifier.Level); else - AddLine(Severity.Valid, "Current level is not below met level.", CheckIdentifier.Level); + AddLine(Severity.Valid, V88, CheckIdentifier.Level); } private void verifyMedals() { @@ -791,22 +790,22 @@ private void verifyMedals() var TrainNames = ReflectUtil.getPropertiesStartWithPrefix(pkm.GetType(), "SuperTrain").ToArray(); var TrainCount = TrainNames.Count(MissionName => ReflectUtil.GetValue(pkm, MissionName) as bool? == true); if (pkm.IsEgg && TrainCount > 0) - { AddLine(Severity.Invalid, "Super Training missions on Egg.", CheckIdentifier.Training); } - else if (TrainCount > 0 && pkm.GenNumber != 6) - { AddLine(Severity.Invalid, "Super Training missions are not available in game.", CheckIdentifier.Training); } + { AddLine(Severity.Invalid, V89, CheckIdentifier.Training); } + else if (TrainCount > 0 && pkm.GenNumber > 6) + { AddLine(Severity.Invalid, V90, CheckIdentifier.Training); } else { if (pkm.Format >= 7) { if (pkm.SecretSuperTrainingUnlocked) - { AddLine(Severity.Invalid, "Super Training unlocked flag invalid.", CheckIdentifier.Training); } + { AddLine(Severity.Invalid, V91, CheckIdentifier.Training); } if (pkm.SecretSuperTrainingComplete) - { AddLine(Severity.Invalid, "Super Training complete flag invalid.", CheckIdentifier.Training); } + { AddLine(Severity.Invalid, V92, CheckIdentifier.Training); } } else { if (TrainCount == 30 ^ pkm.SecretSuperTrainingComplete) - { AddLine(Severity.Invalid, "Super Training complete flag mismatch.", CheckIdentifier.Training); } + { AddLine(Severity.Invalid, V93, CheckIdentifier.Training); } } } @@ -814,11 +813,11 @@ private void verifyMedals() var DistNames = ReflectUtil.getPropertiesStartWithPrefix(pkm.GetType(), "DistSuperTrain"); var DistCount = DistNames.Count(MissionName => ReflectUtil.GetValue(pkm, MissionName) as bool? == true); if (pkm.IsEgg && DistCount > 0) - { AddLine(Severity.Invalid, "Distribution Super Training missions on Egg.", CheckIdentifier.Training); } - else if (DistCount > 0 && pkm.GenNumber != 6) - { AddLine(Severity.Invalid, "Distribution Super Training missions are not available in game.", CheckIdentifier.Training); } + { AddLine(Severity.Invalid, V89, CheckIdentifier.Training); } + else if (DistCount > 0 && pkm.GenNumber > 6) + { AddLine(Severity.Invalid, V90, CheckIdentifier.Training); } else if (DistCount > 0) - { AddLine(Severity.Fishy, "Distribution Super Training missions are not released.", CheckIdentifier.Training); } + { AddLine(Severity.Fishy, V94, CheckIdentifier.Training); } } private void verifyRibbons() { @@ -834,9 +833,9 @@ private void verifyRibbons() foreach (object RibbonValue in RibbonNames.Select(RibbonName => ReflectUtil.GetValue(pkm, RibbonName))) { if (RibbonValue as bool? == true) // Boolean - { AddLine(Severity.Invalid, "Eggs should not have ribbons.", CheckIdentifier.Ribbon); return; } + { AddLine(Severity.Invalid, V95, CheckIdentifier.Ribbon); return; } if ((RibbonValue as int?) > 0) // Count - { AddLine(Severity.Invalid, "Eggs should not have ribbons.", CheckIdentifier.Ribbon); return; } + { AddLine(Severity.Invalid, V95, CheckIdentifier.Ribbon); return; } } return; } @@ -911,40 +910,40 @@ private void verifyRibbons() if (pkm.GenNumber > 3) { if (ReflectUtil.getBooleanState(pkm, nameof(PK3.RibbonChampionG3Hoenn)) == true) - invalidRibbons.Add("GBA Champion"); // RSE HoF + invalidRibbons.Add(V96); // RSE HoF if (ReflectUtil.getBooleanState(pkm, nameof(PK3.RibbonArtist)) == true) - invalidRibbons.Add("Artist"); // RSE Master Rank Portrait + invalidRibbons.Add(V97); // RSE Master Rank Portrait if (ReflectUtil.getBooleanState(pkm, nameof(PK3.RibbonNational)) == true && pkm.Version != (int)GameVersion.CXD) - invalidRibbons.Add("National Ribbon (Purified)"); // RSE HoF + invalidRibbons.Add(V98); // RSE HoF } if (pkm.GenNumber > 4) { if (ReflectUtil.getBooleanState(pkm, nameof(PK4.RibbonChampionSinnoh)) == true) - invalidRibbons.Add("Sinnoh Champ"); // DPPt HoF + invalidRibbons.Add(V99); // DPPt HoF if (ReflectUtil.getBooleanState(pkm, nameof(PK4.RibbonLegend)) == true) - invalidRibbons.Add("Legend"); // HGSS Defeat Red @ Mt.Silver + invalidRibbons.Add(V100); // HGSS Defeat Red @ Mt.Silver } if (pkm.Format >= 6 && pkm.GenNumber >= 6) { if (ReflectUtil.getBooleanState(pkm, nameof(PK6.RibbonCountMemoryContest)) == true) - invalidRibbons.Add("Contest Memory"); // Gen3/4 Contest + invalidRibbons.Add(V106); // Gen3/4 Contest if (ReflectUtil.getBooleanState(pkm, nameof(PK6.RibbonCountMemoryBattle)) == true) - invalidRibbons.Add("Battle Memory"); // Gen3/4 Battle + invalidRibbons.Add(V105); // Gen3/4 Battle } if (ReflectUtil.getBooleanState(pkm, nameof(PK6.RibbonRecord)) == true) - invalidRibbons.Add("Record"); // Unobtainable + invalidRibbons.Add(V104); // Unobtainable if (missingRibbons.Count + invalidRibbons.Count == 0) { - AddLine(Severity.Valid, "All ribbons accounted for.", CheckIdentifier.Ribbon); + AddLine(Severity.Valid, V103, CheckIdentifier.Ribbon); return; } string[] result = new string[2]; if (missingRibbons.Count > 0) - result[0] = "Missing Ribbons: " + string.Join(", ", missingRibbons); + result[0] = string.Format(V101, string.Join(", ", missingRibbons)); if (invalidRibbons.Count > 0) - result[1] = "Invalid Ribbons: " + string.Join(", ", invalidRibbons); + result[1] = string.Format(V102, string.Join(", ", invalidRibbons)); AddLine(Severity.Invalid, string.Join(Environment.NewLine, result.Where(s => !string.IsNullOrEmpty(s))), CheckIdentifier.Ribbon); } private void verifyAbility() @@ -955,7 +954,7 @@ private void verifyAbility() int abilval = Array.IndexOf(abilities, pkm.Ability); if (abilval < 0) { - AddLine(Severity.Invalid, "Ability is not valid for species/form.", CheckIdentifier.Ability); + AddLine(Severity.Invalid, V107, CheckIdentifier.Ability); return; } @@ -964,24 +963,27 @@ private void verifyAbility() // Check Hidden Ability Mismatches if (pkm.GenNumber >= 5) { + bool valid = true; if (EncounterType == typeof(EncounterStatic)) + { if (pkm.AbilityNumber == 4 ^ ((EncounterStatic) EncounterMatch).Ability == 4) - { - AddLine(Severity.Invalid, "Hidden Ability mismatch for static encounter.", CheckIdentifier.Ability); - } - if (EncounterType == typeof(EncounterTrade)) + valid = false; + } + else if (EncounterType == typeof(EncounterTrade)) + { if (pkm.AbilityNumber == 4 ^ ((EncounterTrade) EncounterMatch).Ability == 4) - { - AddLine(Severity.Invalid, "Hidden Ability mismatch for ingame trade.", CheckIdentifier.Ability); - return; - } - if (EncounterType == typeof(EncounterLink)) + valid = false; + } + else if (EncounterType == typeof(EncounterLink)) + { if (pkm.AbilityNumber != ((EncounterLink)EncounterMatch).Ability) - { - AddLine(Severity.Invalid, "Ability mismatch for Link Gift.", CheckIdentifier.Ability); - return; - } - + valid = false; + } + if (!valid) + { + AddLine(Severity.Invalid, V108, CheckIdentifier.Ability); + return; + } } if (pkm.GenNumber == 6) { @@ -993,12 +995,12 @@ private void verifyAbility() if (type < 3 && abilNumber != 1 << type) // set number { if (type < 2 && abilNumber < 3 && abilities[0] != abilities[1]) // 0/1 required, not hidden, and ability can be changed - AddLine(Severity.Valid, "Ability modified with Ability Capsule.", CheckIdentifier.Ability); + AddLine(Severity.Valid, V109, CheckIdentifier.Ability); else - AddLine(Severity.Invalid, "Ability does not match Mystery Gift.", CheckIdentifier.Ability); + AddLine(Severity.Invalid, V110, CheckIdentifier.Ability); } else if (type == 3 && abilNumber == 4) // 1/2 only - AddLine(Severity.Invalid, "Ability does not match Mystery Gift.", CheckIdentifier.Ability); + AddLine(Severity.Invalid, V110, CheckIdentifier.Ability); } if (EncounterType == typeof(EncounterSlot[]) && pkm.AbilityNumber == 4) { @@ -1024,12 +1026,12 @@ private void verifyAbility() if (type < 3 && abilNumber != 1 << type) // set number { if (type < 2 && abilNumber < 3 && abilities[0] != abilities[1]) // 0/1 required, not hidden, and ability can be changed - AddLine(Severity.Valid, "Ability modified with Ability Capsule.", CheckIdentifier.Ability); + AddLine(Severity.Valid, V109, CheckIdentifier.Ability); else - AddLine(Severity.Invalid, "Ability does not match Mystery Gift.", CheckIdentifier.Ability); + AddLine(Severity.Invalid, V110, CheckIdentifier.Ability); } else if (type == 3 && abilNumber == 4) // 1/2 only - AddLine(Severity.Invalid, "Ability does not match Mystery Gift.", CheckIdentifier.Ability); + AddLine(Severity.Invalid, V110, CheckIdentifier.Ability); } if (EncounterType == typeof(EncounterSlot[]) && pkm.AbilityNumber == 4) { @@ -1038,13 +1040,13 @@ private void verifyAbility() if (!valid) { - AddLine(Severity.Invalid, "Hidden Ability on non-SOS wild encounter.", CheckIdentifier.Ability); + AddLine(Severity.Invalid, V111, CheckIdentifier.Ability); return; } } if (Legal.Ban_NoHidden7.Contains(pkm.Species) && pkm.AbilityNumber == 4) { - AddLine(Severity.Invalid, "Hidden Ability not available.", CheckIdentifier.Ability); + AddLine(Severity.Invalid, V112, CheckIdentifier.Ability); return; } @@ -1055,7 +1057,7 @@ private void verifyAbility() { if (pkm.Version != (int) GameVersion.CXD && abilities[0] != abilities[1] && pkm.PIDAbility != abilval) { - AddLine(Severity.Invalid, "Ability does not match PID.", CheckIdentifier.Ability); + AddLine(Severity.Invalid, V113, CheckIdentifier.Ability); return; } } @@ -1063,14 +1065,22 @@ private void verifyAbility() { if (abilities[pkm.AbilityNumber >> 1] != pkm.Ability) { - AddLine(Severity.Invalid, "Ability does not match ability number.", CheckIdentifier.Ability); + AddLine(Severity.Invalid, V114, CheckIdentifier.Ability); return; } } - AddLine(Severity.Valid, "Ability matches ability number.", CheckIdentifier.Ability); + AddLine(Severity.Valid, V115, CheckIdentifier.Ability); } + private void verifyBallEquals(params int[] balls) + { + int ball = pkm.Ball; + if (balls.Any(b => b == ball)) + AddLine(Severity.Valid, V119, CheckIdentifier.Ball); + else + AddLine(Severity.Invalid, V118, CheckIdentifier.Ball); + } private void verifyBall() { if (pkm.Format < 3) @@ -1083,29 +1093,17 @@ private void verifyBall() if (EncounterIsMysteryGift) { - if (pkm.Ball != ((MysteryGift) EncounterMatch).Ball) - AddLine(Severity.Invalid, "Ball does not match specified Mystery Gift Ball.", CheckIdentifier.Ball); - else - AddLine(Severity.Valid, "Ball matches Mystery Gift.", CheckIdentifier.Ball); - + verifyBallEquals(((MysteryGift)EncounterMatch).Ball); return; } if (EncounterType == typeof (EncounterLink)) { - if (((EncounterLink)EncounterMatch).Ball != pkm.Ball) - AddLine(Severity.Invalid, "Incorrect ball on Link gift.", CheckIdentifier.Ball); - else - AddLine(Severity.Valid, "Correct ball on Link gift.", CheckIdentifier.Ball); - + verifyBallEquals(((EncounterLink)EncounterMatch).Ball); return; } if (EncounterType == typeof (EncounterTrade)) { - if (pkm.Ball != 4) // Pokeball - AddLine(Severity.Invalid, "Incorrect ball on ingame trade encounter.", CheckIdentifier.Ball); - else - AddLine(Severity.Valid, "Correct ball on ingame trade encounter.", CheckIdentifier.Ball); - + verifyBallEquals(4); // Pokeball return; } @@ -1114,7 +1112,7 @@ private void verifyBall() var lineage = Legal.getLineage(pkm); if (lineage.Any(e => Legal.AlolanCaptureNoHeavyBall.Contains(e))) { - AddLine(Severity.Invalid, "Heavy ball not possible for light, low-catch rate species in Gen VII.", CheckIdentifier.Ball); + AddLine(Severity.Invalid, V116, CheckIdentifier.Ball); return; } } @@ -1123,37 +1121,17 @@ private void verifyBall() { EncounterStatic enc = EncounterMatch as EncounterStatic; if (enc?.Gift ?? false) - { - if (enc.Ball != pkm.Ball) // Pokéball by default - AddLine(Severity.Invalid, "Incorrect ball on ingame gift.", CheckIdentifier.Ball); - else - AddLine(Severity.Valid, "Correct ball on ingame gift.", CheckIdentifier.Ball); - - return; - } - - if (Legal.getWildBalls(pkm).Contains(pkm.Ball)) - AddLine(Severity.Valid, "Correct ball on ingame static encounter.", CheckIdentifier.Ball); + verifyBallEquals(enc.Ball); else - AddLine(Severity.Invalid, "Incorrect ball on ingame static encounter.", CheckIdentifier.Ball); - + verifyBallEquals(Legal.getWildBalls(pkm)); return; } if (EncounterType == typeof (EncounterSlot[])) { if (pkm.Met_Location == 30016 && pkm.Gen7) // Poké Pelago - { - if (pkm.Ball == 0x04) - AddLine(Severity.Valid, "Correct ball on Poké Pelago encounter.", CheckIdentifier.Ball); - else - AddLine(Severity.Invalid, "Incorrect ball on Poké Pelago encounter.", CheckIdentifier.Ball); - } - - if (Legal.getWildBalls(pkm).Contains(pkm.Ball)) - AddLine(Severity.Valid, "Correct ball on ingame encounter.", CheckIdentifier.Ball); + verifyBallEquals(4); // Pokeball else - AddLine(Severity.Invalid, "Incorrect ball on ingame encounter.", CheckIdentifier.Ball); - + verifyBallEquals(Legal.getWildBalls(pkm)); return; } @@ -1163,31 +1141,22 @@ private void verifyBall() return; } - if (pkm.Ball == 0x04) // Poké Ball - { - AddLine(Severity.Valid, "Standard Poké Ball.", CheckIdentifier.Ball); - return; - } - - AddLine(Severity.Invalid, "No ball check satisfied, assuming illegal.", CheckIdentifier.Ball); + verifyBallEquals(4); // Pokeball } private void verifyBallEgg() { if (pkm.GenNumber < 6) // No inheriting Balls { - if (pkm.Ball != 0x04) // Must be Pokéball -- no ball inheritance. - AddLine(Severity.Invalid, "Ball should be Pokéball.", CheckIdentifier.Ball); - else - AddLine(Severity.Valid, "Pokéball on egg.", CheckIdentifier.Ball); + verifyBallEquals(4); // Must be Pokéball -- no ball inheritance. return; } if (pkm.Ball == 0x01) // Master Ball - { AddLine(Severity.Invalid, "Master Ball on egg origin.", CheckIdentifier.Ball); return; } + { AddLine(Severity.Invalid, V117, CheckIdentifier.Ball); return; } if (pkm.Ball == 0x10) // Cherish Ball - { AddLine(Severity.Invalid, "Cherish Ball on non-event.", CheckIdentifier.Ball); return; } + { AddLine(Severity.Invalid, V120, CheckIdentifier.Ball); return; } if (pkm.Ball == 0x04) // Poké Ball - { AddLine(Severity.Valid, "Standard Poké Ball.", CheckIdentifier.Ball); return; } + { AddLine(Severity.Valid, V119, CheckIdentifier.Ball); return; } switch (pkm.GenNumber) { @@ -1203,183 +1172,174 @@ private void verifyBallEggGen6() { if (pkm.Gender == 2) // Genderless { - if (pkm.Ball != 0x04) // Must be Pokéball as ball can only pass via mother (not Ditto!) - AddLine(Severity.Invalid, "Non-Pokéball on genderless egg.", CheckIdentifier.Ball); - else - AddLine(Severity.Valid, "Pokéball on genderless egg.", CheckIdentifier.Ball); - + verifyBallEquals(4); // Must be Pokéball as ball can only pass via mother (not Ditto!) return; } if (Legal.BreedMaleOnly.Contains(pkm.Species)) { - if (pkm.Ball != 0x04) // Must be Pokéball as ball can only pass via mother (not Ditto!) - AddLine(Severity.Invalid, "Non-Pokéball on Male-Only egg.", CheckIdentifier.Ball); - else - AddLine(Severity.Valid, "Pokéball on Male-Only egg.", CheckIdentifier.Ball); - + verifyBallEquals(4); // Must be Pokéball as ball can only pass via mother (not Ditto!) return; } - if (pkm.Ball == 0x05) // Safari Ball + int ball = pkm.Ball; + + if (ball >= 26) + { + AddLine(Severity.Invalid, V126, CheckIdentifier.Ball); + return; + } + if (ball == 0x05) // Safari Ball { if (Legal.getLineage(pkm).All(e => !Legal.Inherit_Safari.Contains(e))) - AddLine(Severity.Invalid, "Safari Ball not possible for species.", CheckIdentifier.Ball); + AddLine(Severity.Invalid, V121, CheckIdentifier.Ball); else if (pkm.AbilityNumber == 4) - AddLine(Severity.Invalid, "Safari Ball with Hidden Ability.", CheckIdentifier.Ball); + AddLine(Severity.Invalid, V122, CheckIdentifier.Ball); else - AddLine(Severity.Valid, "Safari Ball possible for species.", CheckIdentifier.Ball); + AddLine(Severity.Valid, V123, CheckIdentifier.Ball); return; } - if (0x10 < pkm.Ball && pkm.Ball < 0x18) // Apricorn Ball + if (0x10 < ball && ball < 0x18) // Apricorn Ball { if (Legal.getLineage(pkm).All(e => !Legal.Inherit_Apricorn6.Contains(e))) - AddLine(Severity.Invalid, "Apricorn Ball not possible for species.", CheckIdentifier.Ball); + AddLine(Severity.Invalid, V121, CheckIdentifier.Ball); if (pkm.AbilityNumber == 4) - AddLine(Severity.Invalid, "Apricorn Ball with Hidden Ability.", CheckIdentifier.Ball); + AddLine(Severity.Invalid, V122, CheckIdentifier.Ball); else - AddLine(Severity.Valid, "Apricorn Ball possible for species.", CheckIdentifier.Ball); + AddLine(Severity.Valid, V123, CheckIdentifier.Ball); return; } - if (pkm.Ball == 0x18) // Sport Ball + if (ball == 0x18) // Sport Ball { if (Legal.getLineage(pkm).All(e => !Legal.Inherit_Sport.Contains(e))) - AddLine(Severity.Invalid, "Sport Ball not possible for species.", CheckIdentifier.Ball); + AddLine(Severity.Invalid, V121, CheckIdentifier.Ball); else if (pkm.AbilityNumber == 4) - AddLine(Severity.Invalid, "Sport Ball with Hidden Ability.", CheckIdentifier.Ball); + AddLine(Severity.Invalid, V122, CheckIdentifier.Ball); else - AddLine(Severity.Valid, "Sport Ball possible for species.", CheckIdentifier.Ball); + AddLine(Severity.Valid, V123, CheckIdentifier.Ball); return; } - if (pkm.Ball == 0x19) // Dream Ball + if (ball == 0x19) // Dream Ball { - if (Legal.getLineage(pkm).All(e => !Legal.Inherit_Dream.Contains(e))) - AddLine(Severity.Invalid, "Dream Ball not possible for species.", CheckIdentifier.Ball); + if (Legal.getLineage(pkm).Any(e => Legal.Inherit_Dream.Contains(e))) + AddLine(Severity.Valid, V123, CheckIdentifier.Ball); else - AddLine(Severity.Valid, "Dream Ball possible for species.", CheckIdentifier.Ball); + AddLine(Severity.Invalid, V121, CheckIdentifier.Ball); if (pkm.AbilityNumber == 4 && Legal.Ban_DreamHidden.Contains(pkm.Species)) - AddLine(Severity.Invalid, "Hidden Ability not obtainable from Dream World.", CheckIdentifier.Ball); + AddLine(Severity.Invalid, V122, CheckIdentifier.Ball); return; } - if (0x0D <= pkm.Ball && pkm.Ball <= 0x0F) + if (0x0D <= ball && ball <= 0x0F) { - if (Legal.Ban_Gen4Ball_6.Contains(pkm.Species)) - AddLine(Severity.Invalid, "Unobtainable capture for Gen4 Ball.", CheckIdentifier.Ball); + if (!Legal.Ban_Gen4Ball_6.Contains(pkm.Species)) + AddLine(Severity.Valid, V123, CheckIdentifier.Ball); else - AddLine(Severity.Valid, "Obtainable capture for Gen4 Ball.", CheckIdentifier.Ball); + AddLine(Severity.Invalid, V121, CheckIdentifier.Ball); return; } - if (0x02 <= pkm.Ball && pkm.Ball <= 0x0C) // Don't worry, Ball # 0x05 was already checked. + if (0x02 <= ball && ball <= 0x0C) // Don't worry, Ball # 0x05 was already checked. { if (Legal.Ban_Gen3Ball.Contains(pkm.Species)) - AddLine(Severity.Invalid, "Unobtainable capture for Gen3 Ball.", CheckIdentifier.Ball); + AddLine(Severity.Invalid, V121, CheckIdentifier.Ball); else if (pkm.AbilityNumber == 4 && 152 <= pkm.Species && pkm.Species <= 160) - AddLine(Severity.Invalid, "Ball not possible for species with hidden ability.", CheckIdentifier.Ball); + AddLine(Severity.Invalid, V122, CheckIdentifier.Ball); else - AddLine(Severity.Valid, "Obtainable capture for Gen3 Ball.", CheckIdentifier.Ball); + AddLine(Severity.Valid, V123, CheckIdentifier.Ball); return; } if (pkm.Species > 650 && pkm.Species != 700) // Sylveon { - if (!Legal.getWildBalls(pkm).Contains(pkm.Ball)) - AddLine(Severity.Invalid, "Unobtainable ball for Kalos origin.", CheckIdentifier.Ball); + if (Legal.getWildBalls(pkm).Contains(pkm.Ball)) + AddLine(Severity.Valid, V123, CheckIdentifier.Ball); else - AddLine(Severity.Valid, "Obtainable ball for Kalos origin.", CheckIdentifier.Ball); + AddLine(Severity.Invalid, V121, CheckIdentifier.Ball); return; } - AddLine(Severity.Invalid, pkm.Ball >= 26 - ? "Ball unobtainable in origin generation." - : "No ball check satisfied, assuming illegal.", CheckIdentifier.Ball); + AddLine(Severity.Invalid, V125, CheckIdentifier.Ball); } private void verifyBallEggGen7() { var Lineage = Legal.getLineage(pkm).ToArray(); if (722 <= pkm.Species && pkm.Species <= 730) // G7 Starters { - if (pkm.Ball == 4) - AddLine(Severity.Valid, "Ball possible.", CheckIdentifier.Ball); - else - AddLine(Severity.Invalid, "Only Poké Ball possible.", CheckIdentifier.Ball); + verifyBallEquals(4); return; } - if (pkm.Ball == 0x05) // Safari Ball + int ball = pkm.Ball; + if (ball == 0x05) // Safari Ball { - if (Lineage.Any(e => Legal.Inherit_Safari.Contains(e))) - AddLine(Severity.Valid, "Safari Ball possible from Female parent.", CheckIdentifier.Ball); - else if (Lineage.Any(e => Legal.Inherit_SafariMale.Contains(e))) - AddLine(Severity.Valid, "Safari Ball possible from Male parent.", CheckIdentifier.Ball); + if (Lineage.Any(e => Legal.Inherit_Safari.Contains(e) || Legal.Inherit_SafariMale.Contains(e))) + AddLine(Severity.Valid, V123, CheckIdentifier.Ball); else - AddLine(Severity.Invalid, "Safari Ball not possible for species.", CheckIdentifier.Ball); + AddLine(Severity.Invalid, V121, CheckIdentifier.Ball); return; } - if (0x10 < pkm.Ball && pkm.Ball < 0x18) // Apricorn Ball + if (0x10 < ball && ball < 0x18) // Apricorn Ball { if (Lineage.Any(e => Legal.Inherit_Apricorn7.Contains(e))) // past gen - AddLine(Severity.Valid, "Apricorn Ball possible for species.", CheckIdentifier.Ball); + AddLine(Severity.Valid, V123, CheckIdentifier.Ball); else - AddLine(Severity.Invalid, "Apricorn Ball not possible for species.", CheckIdentifier.Ball); + AddLine(Severity.Invalid, V121, CheckIdentifier.Ball); return; } - if (pkm.Ball == 0x18) // Sport Ball + if (ball == 0x18) // Sport Ball { - if (Lineage.All(e => !Legal.Inherit_Sport.Contains(e))) - AddLine(Severity.Invalid, "Sport Ball not possible for species.", CheckIdentifier.Ball); + if (Lineage.Any(e => Legal.Inherit_Sport.Contains(e))) + AddLine(Severity.Valid, V123, CheckIdentifier.Ball); else - AddLine(Severity.Valid, "Sport Ball possible for species.", CheckIdentifier.Ball); + AddLine(Severity.Invalid, V121, CheckIdentifier.Ball); return; } - if (pkm.Ball == 0x19) // Dream Ball + if (ball == 0x19) // Dream Ball { - if (Lineage.Any(e => Legal.Inherit_Dream.Contains(e))) - AddLine(Severity.Valid, "Dream Ball inheritance possible from Female species.", CheckIdentifier.Ball); - else if (Lineage.Any(e => Legal.Inherit_DreamMale.Contains(e))) - AddLine(Severity.Valid, "Dream Ball inheritance possible from Male/Genderless species.", CheckIdentifier.Ball); + if (Lineage.Any(e => Legal.Inherit_Dream.Contains(e) || Legal.Inherit_DreamMale.Contains(e))) + AddLine(Severity.Valid, V123, CheckIdentifier.Ball); else - AddLine(Severity.Invalid, "Dream Ball not possible for species.", CheckIdentifier.Ball); + AddLine(Severity.Invalid, V121, CheckIdentifier.Ball); return; } - if (0x0D <= pkm.Ball && pkm.Ball <= 0x0F) // Dusk Heal Quick + if (0x0D <= ball && ball <= 0x0F) // Dusk Heal Quick { - if (Legal.Ban_Gen4Ball_7.Contains(pkm.Species)) - AddLine(Severity.Invalid, "Unobtainable capture for Gen4 Ball.", CheckIdentifier.Ball); + if (!Legal.Ban_Gen4Ball_7.Contains(pkm.Species)) + AddLine(Severity.Valid, V123, CheckIdentifier.Ball); else - AddLine(Severity.Valid, "Obtainable capture for Gen4 Ball.", CheckIdentifier.Ball); + AddLine(Severity.Invalid, V121, CheckIdentifier.Ball); return; } - if (0x02 <= pkm.Ball && pkm.Ball <= 0x0C) // Don't worry, Ball # 0x05 was already checked. + if (0x02 <= ball && ball <= 0x0C) // Don't worry, Ball # 0x05 was already checked. { - if (Legal.Ban_Gen3Ball_7.Contains(pkm.Species)) - AddLine(Severity.Invalid, "Unobtainable capture for Gen3 Ball.", CheckIdentifier.Ball); + if (!Legal.Ban_Gen3Ball_7.Contains(pkm.Species)) + AddLine(Severity.Valid, V123, CheckIdentifier.Ball); else - AddLine(Severity.Valid, "Obtainable capture for Gen3 Ball.", CheckIdentifier.Ball); + AddLine(Severity.Invalid, V121, CheckIdentifier.Ball); return; } - if (pkm.Ball == 26) + if (ball == 26) { if ((pkm.Species > 731 && pkm.Species <= 785) || Lineage.Any(e => Legal.PastGenAlolanNatives.Contains(e))) { - AddLine(Severity.Valid, "Beast Ball possible for species.", CheckIdentifier.Ball); + AddLine(Severity.Valid, V123, CheckIdentifier.Ball); return; } if (Lineage.Any(e => Legal.PastGenAlolanScans.Contains(e))) { - AddLine(Severity.Valid, "Scanned Beast Ball possible for species.", CheckIdentifier.Ball); + AddLine(Severity.Valid, V123, CheckIdentifier.Ball); return; } // next statement catches all new alolans @@ -1387,39 +1347,40 @@ private void verifyBallEggGen7() if (pkm.Species > 721) { - if (!Legal.getWildBalls(pkm).Contains(pkm.Ball)) - AddLine(Severity.Invalid, "Unobtainable ball for Alola origin.", CheckIdentifier.Ball); - else - AddLine(Severity.Valid, "Obtainable ball for Alola origin.", CheckIdentifier.Ball); + verifyBallEquals(Legal.getWildBalls(pkm)); return; } - AddLine(Severity.Invalid, pkm.Ball > 26 - ? "Ball unobtainable in origin generation." - : "No ball check satisfied, assuming illegal.", CheckIdentifier.Ball); + + if (ball >= 27) + { + AddLine(Severity.Invalid, V126, CheckIdentifier.Ball); + return; + } + AddLine(Severity.Invalid, V125, CheckIdentifier.Ball); } private CheckResult verifyHistory() { if (!Encounter.Valid) - return new CheckResult(Severity.Valid, "Skipped History check due to other check being invalid.", CheckIdentifier.History); + return new CheckResult(Severity.Valid, V127, CheckIdentifier.History); if (pkm.GenNumber < 6) { if (pkm.Format < 6) - return new CheckResult(Severity.Valid, "No History Block to check.", CheckIdentifier.History); + return new CheckResult(Severity.Valid, V128, CheckIdentifier.History); if (pkm.OT_Affection > 0) - return new CheckResult(Severity.Invalid, "OT Affection should be zero.", CheckIdentifier.History); + return new CheckResult(Severity.Invalid, V129, CheckIdentifier.History); if (pkm.OT_Memory > 0 || pkm.OT_Feeling > 0 || pkm.OT_Intensity > 0 || pkm.OT_TextVar > 0) - return new CheckResult(Severity.Invalid, "Should not have OT memories.", CheckIdentifier.History); + return new CheckResult(Severity.Invalid, V130, CheckIdentifier.History); } if (pkm.Format >= 6 && pkm.GenNumber != pkm.Format && pkm.CurrentHandler != 1) - return new CheckResult(Severity.Invalid, "Current handler cannot be past gen OT for transferred specimen.", CheckIdentifier.History); + return new CheckResult(Severity.Invalid, V124, CheckIdentifier.History); if (pkm.HT_Gender > 1) - return new CheckResult(Severity.Invalid, $"HT Gender invalid {pkm.HT_Gender}.", CheckIdentifier.History); + return new CheckResult(Severity.Invalid, string.Format(V131, pkm.HT_Gender), CheckIdentifier.History); MysteryGift mg = EncounterMatch as MysteryGift; WC6 MatchedWC6 = EncounterMatch as WC6; @@ -1427,27 +1388,27 @@ private CheckResult verifyHistory() if (MatchedWC6?.OT.Length > 0) // Has Event OT -- null propagation yields false if MatchedWC6=null { if (pkm.OT_Friendship != PersonalTable.AO[MatchedWC6.Species].BaseFriendship) - return new CheckResult(Severity.Invalid, "Event OT Friendship does not match base friendship.", CheckIdentifier.History); + return new CheckResult(Severity.Invalid, V132, CheckIdentifier.History); if (pkm.OT_Affection != 0) - return new CheckResult(Severity.Invalid, "Event OT Affection should be zero.", CheckIdentifier.History); + return new CheckResult(Severity.Invalid, V133, CheckIdentifier.History); if (pkm.CurrentHandler != 1) - return new CheckResult(Severity.Invalid, "Current handler should not be Event OT.", CheckIdentifier.History); + return new CheckResult(Severity.Invalid, V134, CheckIdentifier.History); } else if (MatchedWC7?.OT.Length > 0) // Has Event OT -- null propagation yields false if MatchedWC7=null { if (pkm.OT_Friendship != PersonalTable.SM[MatchedWC7.Species].BaseFriendship) - return new CheckResult(Severity.Invalid, "Event OT Friendship does not match base friendship.", CheckIdentifier.History); + return new CheckResult(Severity.Invalid, V132, CheckIdentifier.History); if (pkm.OT_Affection != 0) - return new CheckResult(Severity.Invalid, "Event OT Affection should be zero.", CheckIdentifier.History); + return new CheckResult(Severity.Invalid, V133, CheckIdentifier.History); if (pkm.CurrentHandler != 1) - return new CheckResult(Severity.Invalid, "Current handler should not be Event OT.", CheckIdentifier.History); + return new CheckResult(Severity.Invalid, V134, CheckIdentifier.History); } else if (mg != null && mg.Format < 6 && pkm.Format >= 6) { if (pkm.OT_Affection != 0) - return new CheckResult(Severity.Invalid, "Event OT Affection should be zero.", CheckIdentifier.History); + return new CheckResult(Severity.Invalid, V133, CheckIdentifier.History); if (pkm.CurrentHandler != 1) - return new CheckResult(Severity.Invalid, "Current handler should not be Event OT.", CheckIdentifier.History); + return new CheckResult(Severity.Invalid, V134, CheckIdentifier.History); } // Geolocations @@ -1462,12 +1423,12 @@ private CheckResult verifyHistory() for (int i = 0; i < 5; i++) { if (geoEnd && geo[i] != 0) - return new CheckResult(Severity.Invalid, "Geolocation Memories invalid.", CheckIdentifier.History); + return new CheckResult(Severity.Invalid, V135, CheckIdentifier.History); if (geo[i] != 0) continue; if (geo[i + 5] != 0) - return new CheckResult(Severity.Invalid, "Geolocation Region without Country.", CheckIdentifier.History); + return new CheckResult(Severity.Invalid, V136, CheckIdentifier.History); geoEnd = true; } if (pkm.Format >= 7) @@ -1477,20 +1438,20 @@ private CheckResult verifyHistory() var hasGeo = geo.Any(d => d != 0); if (!hasGeo) - return new CheckResult(Severity.Invalid, "Geolocation Memories should be present.", CheckIdentifier.History); + return new CheckResult(Severity.Invalid, V137, CheckIdentifier.History); } if (pkm.GenNumber >= 7 && pkm.CNTs.Any(stat => stat > 0)) - return new CheckResult(Severity.Invalid, "Contest stats on SM origin should be zero.", CheckIdentifier.History); + return new CheckResult(Severity.Invalid, V138, CheckIdentifier.History); if (!pkm.WasEvent && pkm.HT_Name.Length == 0) // Is not Traded { if (pkm.CurrentHandler != 0) // Badly edited; PKHeX doesn't trip this. - return new CheckResult(Severity.Invalid, "Untraded -- Current handler should not be the Handling Trainer.", CheckIdentifier.History); + return new CheckResult(Severity.Invalid, V139, CheckIdentifier.History); if (pkm.HT_Friendship != 0) - return new CheckResult(Severity.Invalid, "Untraded -- Handling Trainer Friendship should be zero.", CheckIdentifier.History); + return new CheckResult(Severity.Invalid, V140, CheckIdentifier.History); if (pkm.HT_Affection != 0) - return new CheckResult(Severity.Invalid, "Untraded -- Handling Trainer Affection should be zero.", CheckIdentifier.History); + return new CheckResult(Severity.Invalid, V141, CheckIdentifier.History); // We know it is untraded (HT is empty), if it must be trade evolved flag it. if (Legal.getHasTradeEvolved(pkm) // if evo chain requires a trade @@ -1498,68 +1459,68 @@ private CheckResult verifyHistory() && (EncounterMatch as EncounterStatic)?.Species != pkm.Species) // Static Encounter { if (pkm.Species != 350) // Milotic - return new CheckResult(Severity.Invalid, "Untraded -- requires a trade evolution.", CheckIdentifier.History); + return new CheckResult(Severity.Invalid, V142, CheckIdentifier.History); if (pkm.CNT_Beauty < 170) // Beauty Contest Stat Requirement - return new CheckResult(Severity.Invalid, "Untraded -- Beauty is not high enough for Level-up Evolution.", CheckIdentifier.History); + return new CheckResult(Severity.Invalid, V143, CheckIdentifier.History); if (pkm.CurrentLevel == 1) - return new CheckResult(Severity.Invalid, "Untraded -- Beauty is high enough but still Level 1.", CheckIdentifier.History); + return new CheckResult(Severity.Invalid, V144, CheckIdentifier.History); } } - return new CheckResult(Severity.Valid, "S/M History Block is valid.", CheckIdentifier.History); + return new CheckResult(Severity.Valid, V145, CheckIdentifier.History); } if (!pkm.WasEvent && !(pkm.WasLink && (EncounterMatch as EncounterLink)?.OT == false) && (pkm.HT_Name.Length == 0 || pkm.Geo1_Country == 0)) // Is not Traded { if (pkm.HT_Name.Length != 0) - return new CheckResult(Severity.Invalid, "GeoLocation Memory -- HT Name present but has no previous Country.", CheckIdentifier.History); + return new CheckResult(Severity.Invalid, V146, CheckIdentifier.History); if (pkm.Geo1_Country != 0) - return new CheckResult(Severity.Invalid, "GeoLocation Memory -- Previous country of residence but no Handling Trainer.", CheckIdentifier.History); + return new CheckResult(Severity.Invalid, V147, CheckIdentifier.History); if (pkm.HT_Memory != 0) - return new CheckResult(Severity.Invalid, "Memory -- Handling Trainer memory present but no Handling Trainer.", CheckIdentifier.History); + return new CheckResult(Severity.Invalid, V148, CheckIdentifier.History); if (pkm.CurrentHandler != 0) // Badly edited; PKHeX doesn't trip this. - return new CheckResult(Severity.Invalid, "Untraded -- Current handler should not be the Handling Trainer.", CheckIdentifier.History); + return new CheckResult(Severity.Invalid, V139, CheckIdentifier.History); if (pkm.HT_Friendship != 0) - return new CheckResult(Severity.Invalid, "Untraded -- Handling Trainer Friendship should be zero.", CheckIdentifier.History); + return new CheckResult(Severity.Invalid, V140, CheckIdentifier.History); if (pkm.HT_Affection != 0) - return new CheckResult(Severity.Invalid, "Untraded -- Handling Trainer Affection should be zero.", CheckIdentifier.History); + return new CheckResult(Severity.Invalid, V141, CheckIdentifier.History); if (pkm.XY && pkm.CNTs.Any(stat => stat > 0)) - return new CheckResult(Severity.Invalid, "Untraded -- Contest stats on XY should be zero.", CheckIdentifier.History); + return new CheckResult(Severity.Invalid, V138, CheckIdentifier.History); // We know it is untraded (HT is empty), if it must be trade evolved flag it. if (Legal.getHasTradeEvolved(pkm) && (EncounterMatch as EncounterSlot[])?.Any(slot => slot.Species == pkm.Species) != true) { if (pkm.Species != 350) // Milotic - return new CheckResult(Severity.Invalid, "Untraded -- requires a trade evolution.", CheckIdentifier.History); + return new CheckResult(Severity.Invalid, V142, CheckIdentifier.History); if (pkm.CNT_Beauty < 170) // Beauty Contest Stat Requirement - return new CheckResult(Severity.Invalid, "Untraded -- Beauty is not high enough for Level-up Evolution.", CheckIdentifier.History); + return new CheckResult(Severity.Invalid, V143, CheckIdentifier.History); if (pkm.CurrentLevel == 1) - return new CheckResult(Severity.Invalid, "Untraded -- Beauty is high enough but still Level 1.", CheckIdentifier.History); + return new CheckResult(Severity.Invalid, V144, CheckIdentifier.History); } } else // Is Traded { if (pkm.Format == 6 && pkm.HT_Memory == 0) - return new CheckResult(Severity.Invalid, "Memory -- missing Handling Trainer Memory.", CheckIdentifier.History); + return new CheckResult(Severity.Invalid, V150, CheckIdentifier.History); } // Memory ChecksResult if (pkm.IsEgg) { if (pkm.HT_Memory != 0) - return new CheckResult(Severity.Invalid, "Memory -- has Handling Trainer Memory.", CheckIdentifier.History); + return new CheckResult(Severity.Invalid, V149, CheckIdentifier.History); if (pkm.OT_Memory != 0) - return new CheckResult(Severity.Invalid, "Memory -- has Original Trainer Memory.", CheckIdentifier.History); + return new CheckResult(Severity.Invalid, V151, CheckIdentifier.History); } else if (EncounterType != typeof(WC6)) { if (pkm.OT_Memory == 0 ^ !pkm.Gen6) - return new CheckResult(Severity.Invalid, "Memory -- missing Original Trainer Memory.", CheckIdentifier.History); + return new CheckResult(Severity.Invalid, V152, CheckIdentifier.History); if (pkm.GenNumber < 6 && pkm.OT_Affection != 0) - return new CheckResult(Severity.Invalid, "OT Affection should be zero.", CheckIdentifier.History); + return new CheckResult(Severity.Invalid, V129, CheckIdentifier.History); } // Unimplemented: Ingame Trade Memories - return new CheckResult(Severity.Valid, "History is valid.", CheckIdentifier.History); + return new CheckResult(Severity.Valid, V145, CheckIdentifier.History); } private CheckResult verifyCommonMemory(int handler) { @@ -1571,32 +1532,44 @@ private CheckResult verifyCommonMemory(int handler) case 0: m = pkm.OT_Memory; t = pkm.OT_TextVar; - resultPrefix = "OT "; + resultPrefix = V205; break; case 1: m = pkm.HT_Memory; t = pkm.HT_TextVar; - resultPrefix = "HT "; + resultPrefix = V206; break; } int matchingMoveMemory = Array.IndexOf(Legal.MoveSpecificMemories[0], m); if (matchingMoveMemory != -1 && pkm.Species != 235 && !Legal.getCanLearnMachineMove(pkm, Legal.MoveSpecificMemories[1][matchingMoveMemory], 6)) - return new CheckResult(Severity.Invalid, resultPrefix + "Memory: Species cannot learn this move.", CheckIdentifier.Memory); + return new CheckResult(Severity.Invalid, string.Format(V153, resultPrefix), CheckIdentifier.Memory); if (m == 6 && !Legal.LocationsWithPKCenter[0].Contains(t)) - return new CheckResult(Severity.Invalid, resultPrefix + "Memory: Location doesn't have a Pokemon Center.", CheckIdentifier.Memory); + return new CheckResult(Severity.Invalid, string.Format(V154, resultPrefix), CheckIdentifier.Memory); if (m == 21) // {0} saw {2} carrying {1} on its back. {4} that {3}. if (!Legal.getCanLearnMachineMove(new PK6 {Species = t, EXP = PKX.getEXP(100, t)}, 19, 6)) - return new CheckResult(Severity.Invalid, resultPrefix + "Memory: Argument Species cannot learn Fly.", CheckIdentifier.Memory); + return new CheckResult(Severity.Invalid, string.Format(V153, resultPrefix), CheckIdentifier.Memory); if ((m == 16 || m == 48) && (t == 0 || !Legal.getCanKnowMove(pkm, t, 6))) - return new CheckResult(Severity.Invalid, resultPrefix + "Memory: Species cannot know this move.", CheckIdentifier.Memory); + return new CheckResult(Severity.Invalid, string.Format(V153, resultPrefix), CheckIdentifier.Memory); if (m == 49 && (t == 0 || !Legal.getCanRelearnMove(pkm, t, 6))) // {0} was able to remember {2} at {1}'s instruction. {4} that {3}. - return new CheckResult(Severity.Invalid, resultPrefix + "Memory: Species cannot relearn this move.", CheckIdentifier.Memory); + return new CheckResult(Severity.Invalid, string.Format(V153, resultPrefix), CheckIdentifier.Memory); - return new CheckResult(Severity.Valid, resultPrefix + "Memory is valid.", CheckIdentifier.Memory); + return new CheckResult(Severity.Valid, string.Format(V155, resultPrefix), CheckIdentifier.Memory); + } + + private void verifyOTMemoryIs(int[] values) + { + if (pkm.OT_Memory != values[0]) + AddLine(Severity.Invalid, string.Format(V197, V205, values[0]), CheckIdentifier.Memory); + if (pkm.OT_Intensity != values[1]) + AddLine(Severity.Invalid, string.Format(V198, V205, values[1]), CheckIdentifier.Memory); + if (pkm.OT_TextVar != values[2]) + AddLine(Severity.Invalid, string.Format(V199, V205, values[2]), CheckIdentifier.Memory); + if (pkm.OT_Feeling != values[3]) + AddLine(Severity.Invalid, string.Format(V200, V205, values[3]), CheckIdentifier.Memory); } private void verifyOTMemory() { @@ -1608,57 +1581,30 @@ private void verifyOTMemory() if (pkm.GenNumber < 6) { - if (pkm.OT_Memory != 0) - AddLine(Severity.Invalid, "Should not have an OT Memory.", CheckIdentifier.Memory); - if (pkm.OT_Intensity != 0) - AddLine(Severity.Invalid, "Should not have an OT Memory Intensity value.", CheckIdentifier.Memory); - if (pkm.OT_TextVar != 0) - AddLine(Severity.Invalid, "Should not have an OT Memory TextVar value.", CheckIdentifier.Memory); - if (pkm.OT_Feeling != 0) - AddLine(Severity.Invalid, "Should not have an OT Memory Feeling value.", CheckIdentifier.Memory); + verifyOTMemoryIs(new [] {0,0,0,0}); // empty return; } if (EncounterType == typeof(EncounterTrade)) { // Undocumented, uncommon, and insignificant -- don't bother. - AddLine(Severity.Valid, "OT Memory (Ingame Trade) is valid.", CheckIdentifier.Memory); return; } if (EncounterType == typeof(WC6)) { - WC6 MatchedWC6 = EncounterMatch as WC6; - if (pkm.OT_Memory != MatchedWC6.OT_Memory) - AddLine(Severity.Invalid, "Event " + (MatchedWC6.OT_Memory == 0 ? "should not have an OT Memory" : "OT Memory should be index " + MatchedWC6.OT_Memory) + ".", CheckIdentifier.Memory); - if (pkm.OT_Intensity != MatchedWC6.OT_Intensity) - AddLine(Severity.Invalid, "Event " + (MatchedWC6.OT_Intensity == 0 ? "should not have an OT Memory Intensity value" : "OT Memory Intensity should be index " + MatchedWC6.OT_Intensity) + ".", CheckIdentifier.Memory); - if (pkm.OT_TextVar != MatchedWC6.OT_TextVar) - AddLine(Severity.Invalid, "Event " + (MatchedWC6.OT_TextVar == 0 ? "should not have an OT Memory TextVar value" : "OT Memory TextVar should be index " + MatchedWC6.OT_TextVar) + ".", CheckIdentifier.Memory); - if (pkm.OT_Feeling != MatchedWC6.OT_Feeling) - AddLine(Severity.Invalid, "Event " + (MatchedWC6.OT_Feeling == 0 ? "should not have an OT Memory Feeling value" : "OT Memory Feeling should be index " + MatchedWC6.OT_Feeling) + ".", CheckIdentifier.Memory); + WC6 g = EncounterMatch as WC6; + verifyOTMemoryIs(new[] {g.OT_Memory, g.OT_Intensity, g.OT_TextVar, g.OT_Feeling}); + return; } if (EncounterType == typeof(WC7)) { - WC7 MatchedWC7 = EncounterMatch as WC7; - if (pkm.OT_Memory != MatchedWC7.OT_Memory) - AddLine(Severity.Invalid, "Event " + (MatchedWC7.OT_Memory == 0 ? "should not have an OT Memory" : "OT Memory should be index " + MatchedWC7.OT_Memory) + ".", CheckIdentifier.Memory); - if (pkm.OT_Intensity != MatchedWC7.OT_Intensity) - AddLine(Severity.Invalid, "Event " + (MatchedWC7.OT_Intensity == 0 ? "should not have an OT Memory Intensity value" : "OT Memory Intensity should be index " + MatchedWC7.OT_Intensity) + ".", CheckIdentifier.Memory); - if (pkm.OT_TextVar != MatchedWC7.OT_TextVar) - AddLine(Severity.Invalid, "Event " + (MatchedWC7.OT_TextVar == 0 ? "should not have an OT Memory TextVar value" : "OT Memory TextVar should be index " + MatchedWC7.OT_TextVar) + ".", CheckIdentifier.Memory); - if (pkm.OT_Feeling != MatchedWC7.OT_Feeling) - AddLine(Severity.Invalid, "Event " + (MatchedWC7.OT_Feeling == 0 ? "should not have an OT Memory Feeling value" : "OT Memory Feeling should be index " + MatchedWC7.OT_Feeling) + ".", CheckIdentifier.Memory); + WC7 g = EncounterMatch as WC7; + verifyOTMemoryIs(new[] {g.OT_Memory, g.OT_Intensity, g.OT_TextVar, g.OT_Feeling}); + return; } - else if (pkm.GenNumber == 7) + if (pkm.GenNumber >= 7) { - if (pkm.OT_Memory != 0) - AddLine(Severity.Invalid, "Should not have an OT Memory.", CheckIdentifier.Memory); - if (pkm.OT_Intensity != 0) - AddLine(Severity.Invalid, "Should not have an OT Memory Intensity value.", CheckIdentifier.Memory); - if (pkm.OT_TextVar != 0) - AddLine(Severity.Invalid, "Should not have an OT Memory TextVar value.", CheckIdentifier.Memory); - if (pkm.OT_Feeling != 0) - AddLine(Severity.Invalid, "Should not have an OT Memory Feeling value.", CheckIdentifier.Memory); + verifyOTMemoryIs(new[] {0, 0, 0, 0}); // empty return; } @@ -1666,11 +1612,11 @@ private void verifyOTMemory() { case 2: // {0} hatched from an Egg and saw {1} for the first time at... {2}. {4} that {3}. if (!pkm.WasEgg && pkm.Egg_Location != 60004) - AddLine(Severity.Invalid, "OT Memory: OT did not hatch this.", CheckIdentifier.Memory); + AddLine(Severity.Invalid, string.Format(V160, V205), CheckIdentifier.Memory); break; case 4: // {0} became {1}’s friend when it arrived via Link Trade at... {2}. {4} that {3}. - AddLine(Severity.Invalid, "OT Memory: Link Trade is not a valid first memory.", CheckIdentifier.Memory); + AddLine(Severity.Invalid, string.Format(V161, V205), CheckIdentifier.Memory); return; case 6: // {0} went to the Pokémon Center in {2} with {1} and had its tired body healed there. {4} that {3}. @@ -1679,22 +1625,22 @@ private void verifyOTMemory() { int gameID = Legal.LocationsWithPKCenter[1][matchingOriginGame]; if (pkm.XY && gameID != 0 || pkm.AO && gameID != 1) - AddLine(Severity.Invalid, "OT Memory: Location doesn't exist on Origin Game region.", CheckIdentifier.Memory); + AddLine(Severity.Invalid, string.Format(V162, V205), CheckIdentifier.Memory); } AddLine(verifyCommonMemory(0)); return; case 14: if (!Legal.getCanBeCaptured(pkm.OT_TextVar, pkm.GenNumber, (GameVersion)pkm.Version)) - AddLine(Severity.Invalid, "OT Memory: Captured Species can not be captured in game.", CheckIdentifier.Memory); + AddLine(Severity.Invalid, string.Format(V165, V205), CheckIdentifier.Memory); else - AddLine(Severity.Valid, "OT Memory: Captured Species can be captured in game.", CheckIdentifier.Memory); + AddLine(Severity.Valid, string.Format(V164, V205), CheckIdentifier.Memory); return; } if (pkm.XY && Legal.Memory_NotXY.Contains(pkm.OT_Memory)) - AddLine(Severity.Invalid, "OT Memory: OR/AS exclusive memory on X/Y origin.", CheckIdentifier.Memory); + AddLine(Severity.Invalid, string.Format(V163, V205), CheckIdentifier.Memory); if (pkm.AO && Legal.Memory_NotAO.Contains(pkm.OT_Memory)) - AddLine(Severity.Invalid, "OT Memory: X/Y exclusive memory on OR/AS origin.", CheckIdentifier.Memory); + AddLine(Severity.Invalid, string.Format(V163, V205), CheckIdentifier.Memory); AddLine(verifyCommonMemory(0)); } @@ -1720,13 +1666,13 @@ private void verifyHTMemory() } if (pkm.HT_Memory != 4) - AddLine(Severity.Invalid, "Should have a Link Trade HT Memory.", CheckIdentifier.Memory); + AddLine(Severity.Invalid, V156, CheckIdentifier.Memory); if (pkm.HT_TextVar != 0) - AddLine(Severity.Invalid, "Should have a HT Memory TextVar value (somewhere).", CheckIdentifier.Memory); + AddLine(Severity.Invalid, V157, CheckIdentifier.Memory); if (pkm.HT_Intensity != 1) - AddLine(Severity.Invalid, "Should have a HT Memory Intensity value (1st).", CheckIdentifier.Memory); + AddLine(Severity.Invalid, V158, CheckIdentifier.Memory); if (pkm.HT_Feeling > 10) - AddLine(Severity.Invalid, "Should have a HT Memory Feeling value 0-9.", CheckIdentifier.Memory); + AddLine(Severity.Invalid, V159, CheckIdentifier.Memory); return; } @@ -1735,18 +1681,18 @@ private void verifyHTMemory() case 0: if (string.IsNullOrEmpty(pkm.HT_Name)) return; - AddLine(Severity.Invalid, "HT Memory is missing.", CheckIdentifier.Memory); return; + AddLine(Severity.Invalid, V150, CheckIdentifier.Memory); return; case 1: // {0} met {1} at... {2}. {1} threw a Poké Ball at it, and they started to travel together. {4} that {3}. - AddLine(Severity.Invalid, "HT Memory: Handling Trainer did not capture this.", CheckIdentifier.Memory); return; + AddLine(Severity.Invalid, string.Format(V202, V206), CheckIdentifier.Memory); return; case 2: // {0} hatched from an Egg and saw {1} for the first time at... {2}. {4} that {3}. - AddLine(Severity.Invalid, "HT Memory: Handling Trainer did not hatch this.", CheckIdentifier.Memory); return; + AddLine(Severity.Invalid, string.Format(V160, V206), CheckIdentifier.Memory); return; case 14: - if (!Legal.getCanBeCaptured(pkm.HT_TextVar, pkm.GenNumber)) - AddLine(Severity.Invalid, "HT Memory: Captured Species can not be captured in game.", CheckIdentifier.Memory); + if (Legal.getCanBeCaptured(pkm.HT_TextVar, pkm.GenNumber)) + AddLine(Severity.Valid, string.Format(V164, V206), CheckIdentifier.Memory); else - AddLine(Severity.Valid, "HT Memory: Captured Species can be captured in game.", CheckIdentifier.Memory); + AddLine(Severity.Invalid, string.Format(V165, V206), CheckIdentifier.Memory); return; } AddLine(verifyCommonMemory(1)); @@ -2061,7 +2007,7 @@ private CheckResult[] verifyMoves(GameVersion game = GameVersion.Any) { for (int i = 0; i < 4; i++) res[i] = Legal.InvalidSketch.Contains(Moves[i]) - ? new CheckResult(Severity.Invalid, "Invalid Sketch move.", CheckIdentifier.Move) + ? new CheckResult(Severity.Invalid, V166, CheckIdentifier.Move) : new CheckResult(CheckIdentifier.Move); } else if (EventGiftMatch?.Count > 1) // Multiple possible Mystery Gifts matched @@ -2093,19 +2039,19 @@ private CheckResult[] verifyMoves(GameVersion game = GameVersion.Any) if (pkm.GenNumber >= 6) for (int i = 0; i < 4; i++) if (res[i].Flag && !RelearnMoves.Contains(Moves[i])) - res[i] = new CheckResult(Severity.Invalid, "Relearn Moves missing " + res[i].Comment, res[i].Identifier); + res[i] = new CheckResult(Severity.Invalid, string.Format(V170, res[i].Comment), res[i].Identifier); } if (Moves[0] == 0) // None - res[0] = new CheckResult(Severity.Invalid, "Invalid Move.", CheckIdentifier.Move); + res[0] = new CheckResult(Severity.Invalid, V167, CheckIdentifier.Move); if (pkm.Species == 647) // Keldeo if (pkm.AltForm == 1 ^ pkm.Moves.Contains(548)) - res[Math.Max(Array.IndexOf(pkm.Moves, 548), 0)] = new CheckResult(Severity.Invalid, "Secret Sword / Resolute Keldeo Mismatch.", CheckIdentifier.Move); + res[Math.Max(Array.IndexOf(pkm.Moves, 548), 0)] = new CheckResult(Severity.Invalid, V169, CheckIdentifier.Move); // Duplicate Moves Check for (int i = 0; i < 4; i++) if (Moves.Count(m => m != 0 && m == Moves[i]) > 1) - res[i] = new CheckResult(Severity.Invalid, "Duplicate Move.", CheckIdentifier.Move); + res[i] = new CheckResult(Severity.Invalid, V168, CheckIdentifier.Move); return res; } @@ -2115,21 +2061,21 @@ private static CheckResult[] parseMoves(int[] moves, int[] learn, int[] relearn, for (int i = 0; i < 4; i++) { if (moves[i] == 0) - res[i] = new CheckResult(Severity.Valid, "Empty", CheckIdentifier.Move); + res[i] = new CheckResult(Severity.Valid, V167, CheckIdentifier.Move); else if (learn.Contains(moves[i])) - res[i] = new CheckResult(Severity.Valid, "Learned by Level-up.", CheckIdentifier.Move); + res[i] = new CheckResult(Severity.Valid, V177, CheckIdentifier.Move); else if (egg.Contains(moves[i])) - res[i] = new CheckResult(Severity.Valid, "Egg Move.", CheckIdentifier.Move) { Flag = true }; + res[i] = new CheckResult(Severity.Valid, V171, CheckIdentifier.Move) { Flag = true }; else if (relearn.Contains(moves[i])) - res[i] = new CheckResult(Severity.Valid, "Relearnable Move.", CheckIdentifier.Move) { Flag = true }; + res[i] = new CheckResult(Severity.Valid, V172, CheckIdentifier.Move) { Flag = true }; else if (tmhm.Contains(moves[i])) - res[i] = new CheckResult(Severity.Valid, "Learned by TM/HM.", CheckIdentifier.Move); + res[i] = new CheckResult(Severity.Valid, V173, CheckIdentifier.Move); else if (tutor.Contains(moves[i])) - res[i] = new CheckResult(Severity.Valid, "Learned by Move Tutor.", CheckIdentifier.Move); + res[i] = new CheckResult(Severity.Valid, V174, CheckIdentifier.Move); else if (special.Contains(moves[i])) - res[i] = new CheckResult(Severity.Valid, "Special Non-Relearn Move.", CheckIdentifier.Move); + res[i] = new CheckResult(Severity.Valid, V175, CheckIdentifier.Move); else - res[i] = new CheckResult(Severity.Invalid, "Invalid Move.", CheckIdentifier.Move); + res[i] = new CheckResult(Severity.Invalid, V176, CheckIdentifier.Move); } return res; } @@ -2157,7 +2103,7 @@ private CheckResult[] verifyRelearn() RelearnBase = moves; for (int i = 0; i < 4; i++) res[i] = moves[i] != Moves[i] - ? new CheckResult(Severity.Invalid, $"Expected: {movelist[moves[i]]}.", CheckIdentifier.RelearnMove) + ? new CheckResult(Severity.Invalid, string.Format(V178, movelist[moves[i]]), CheckIdentifier.RelearnMove) : new CheckResult(CheckIdentifier.RelearnMove); return res; } @@ -2170,7 +2116,7 @@ private CheckResult[] verifyRelearn() int[] moves = mg.RelearnMoves; for (int i = 0; i < 4; i++) res[i] = moves[i] != Moves[i] - ? new CheckResult(Severity.Invalid, $"Expected: {movelist[moves[i]]}.", CheckIdentifier.RelearnMove) + ? new CheckResult(Severity.Invalid, string.Format(V178, movelist[moves[i]]), CheckIdentifier.RelearnMove) : new CheckResult(CheckIdentifier.RelearnMove); if (res.Any(r => !r.Valid)) EventGiftMatch.Remove(mg); @@ -2213,7 +2159,7 @@ private CheckResult[] verifyRelearn() if (baseCt > 4) baseCt = 4; // Obtain Nonstandard moves - var relearnMoves = Legal.getValidRelearn(pkm, skipOption).ToArray(); + var relearnMoves = Legal.getValidRelearn(pkm, skipOption).ToList(); var relearn = pkm.RelearnMoves.Where(move => move != 0 && (!baseMoves.Contains(move) || relearnMoves.Contains(move)) ).ToArray(); @@ -2240,30 +2186,30 @@ private CheckResult[] verifyRelearn() // Movepool finalized! Check validity. int[] rl = pkm.RelearnMoves; - string em = string.Join(", ", baseMoves.Select(r => r >= movelist.Length ? "ERROR" : movelist[r])); + string em = string.Join(", ", baseMoves.Select(r => r >= movelist.Length ? V190 : movelist[r])); RelearnBase = baseMoves.ToArray(); // Base Egg Move for (int j = 0; j < reqBase; j++) { if (baseMoves.Contains(rl[j])) - res[j] = new CheckResult(Severity.Valid, "Base egg move.", CheckIdentifier.RelearnMove); + res[j] = new CheckResult(Severity.Valid, V179, CheckIdentifier.RelearnMove); else { - res[j] = new CheckResult(Severity.Invalid, "Base egg move missing.", CheckIdentifier.RelearnMove); + res[j] = new CheckResult(Severity.Invalid, V180, CheckIdentifier.RelearnMove); for (int f = j+1; f < reqBase; f++) - res[f] = new CheckResult(Severity.Invalid, "Base egg move missing.", CheckIdentifier.RelearnMove); - res[reqBase-1].Comment += $"{Environment.NewLine}Expected the following Relearn Moves: {em}."; + res[f] = new CheckResult(Severity.Invalid, V180, CheckIdentifier.RelearnMove); + res[reqBase-1].Comment += string.Format(Environment.NewLine + V181, em); break; } } // Non-Base if (Legal.LightBall.Contains(pkm.Species)) - relearnMoves = relearnMoves.Concat(new[] { 344 }).ToArray(); + relearnMoves.Add(344); for (int j = reqBase; j < 4; j++) res[j] = !relearnMoves.Contains(rl[j]) - ? new CheckResult(Severity.Invalid, "Not an expected relearn move.", CheckIdentifier.RelearnMove) - : new CheckResult(Severity.Valid, rl[j] == 0 ? "Empty" : "Relearn move.", CheckIdentifier.RelearnMove); + ? new CheckResult(Severity.Invalid, V182, CheckIdentifier.RelearnMove) + : new CheckResult(Severity.Valid, rl[j] == 0 ? V167 : V172, CheckIdentifier.RelearnMove); if (res.All(r => r.Valid)) break; @@ -2272,7 +2218,7 @@ private CheckResult[] verifyRelearn() // Duplicate Moves Check for (int i = 0; i < 4; i++) if (Moves.Count(m => m != 0 && m == Moves[i]) > 1) - res[i] = new CheckResult(Severity.Invalid, "Duplicate Relearn Move.", CheckIdentifier.RelearnMove); + res[i] = new CheckResult(Severity.Invalid, V168, CheckIdentifier.RelearnMove); return res; } @@ -2283,11 +2229,11 @@ private CheckResult[] verifyRelearn() goto noRelearn; res[0] = !Legal.getValidRelearn(pkm, 0).Contains(Moves[0]) - ? new CheckResult(Severity.Invalid, "Not an expected DexNav move.", CheckIdentifier.RelearnMove) + ? new CheckResult(Severity.Invalid, V183, CheckIdentifier.RelearnMove) : new CheckResult(CheckIdentifier.RelearnMove); for (int i = 1; i < 4; i++) res[i] = Moves[i] != 0 - ? new CheckResult(Severity.Invalid, "Expected no Relearn Move in slot.", CheckIdentifier.RelearnMove) + ? new CheckResult(Severity.Invalid, V184, CheckIdentifier.RelearnMove) : new CheckResult(CheckIdentifier.RelearnMove); if (res[0].Valid) @@ -2299,7 +2245,7 @@ private CheckResult[] verifyRelearn() noRelearn: for (int i = 0; i < 4; i++) res[i] = Moves[i] != 0 - ? new CheckResult(Severity.Invalid, "Expected no Relearn Moves.", CheckIdentifier.RelearnMove) + ? new CheckResult(Severity.Invalid, V184, CheckIdentifier.RelearnMove) : new CheckResult(CheckIdentifier.RelearnMove); return res; } @@ -2321,15 +2267,15 @@ private CheckResult verifyEggMoves() continue; // todo: check compatibility of parents (chain wise) - return new CheckResult(Severity.Valid, $"Egg Moves sourced from {game}.", CheckIdentifier.Egg); + return new CheckResult(Severity.Valid, string.Format(V185, game), CheckIdentifier.Egg); } break; case 3: - return new CheckResult(Severity.NotImplemented, "Egg Move set check unimplemented.", CheckIdentifier.Egg); + return new CheckResult(Severity.NotImplemented, V186, CheckIdentifier.Egg); case 4: - return new CheckResult(Severity.NotImplemented, "Egg Move set check unimplemented.", CheckIdentifier.Egg); + return new CheckResult(Severity.NotImplemented, V186, CheckIdentifier.Egg); } return new CheckResult(CheckIdentifier.Egg); } diff --git a/PKHeX/Legality/Core.cs b/PKHeX/Legality/Core.cs index f8a88b972..fb6a42376 100644 --- a/PKHeX/Legality/Core.cs +++ b/PKHeX/Legality/Core.cs @@ -1155,7 +1155,7 @@ internal static IEnumerable getLineage(PKM pkm) var lineage = table.getValidPreEvolutions(pkm, pkm.CurrentLevel); return lineage.Select(evolution => evolution.Species); } - internal static IEnumerable getWildBalls(PKM pkm) + internal static int[] getWildBalls(PKM pkm) { switch (pkm.GenNumber) { diff --git a/PKHeX/PKHeX.Core.csproj b/PKHeX/PKHeX.Core.csproj index 7d040fc2d..75bab202c 100644 --- a/PKHeX/PKHeX.Core.csproj +++ b/PKHeX/PKHeX.Core.csproj @@ -152,6 +152,7 @@ +