diff --git a/Legality/Analysis.cs b/Legality/Analysis.cs index 69e9e7556..7586db419 100644 --- a/Legality/Analysis.cs +++ b/Legality/Analysis.cs @@ -3,27 +3,6 @@ namespace PKHeX { - public enum Severity - { - Indeterminate = -2, - Invalid = -1, - Fishy = 0, - Valid = 1, - NotImplemented = 2, - } - public class LegalityCheck - { - public Severity Judgement = Severity.Invalid; - public string Comment; - public bool Valid => Judgement >= Severity.Fishy; - - public LegalityCheck() { } - public LegalityCheck(Severity s, string c) - { - Judgement = s; - Comment = c; - } - } public class LegalityAnalysis { private readonly PK6 pk6; @@ -131,6 +110,11 @@ public bool[] getRelearnValidity(int[] Moves) public string Report => getLegalityReport(); private string getLegalityReport() { + EC = LegalityCheck.verifyECPID(pk6); + Nickname = LegalityCheck.verifyNickname(pk6); + PID = LegalityCheck.verifyECPID(pk6); + IVs = LegalityCheck.verifyIVs(pk6); + EVs = LegalityCheck.verifyEVs(pk6); return null; } } diff --git a/Legality/Checks.cs b/Legality/Checks.cs new file mode 100644 index 000000000..c3d7f2189 --- /dev/null +++ b/Legality/Checks.cs @@ -0,0 +1,101 @@ +using System.Linq; + +namespace PKHeX +{ + public enum Severity + { + Indeterminate = -2, + Invalid = -1, + Fishy = 0, + Valid = 1, + NotImplemented = 2, + } + public class LegalityCheck + { + public Severity Judgement = Severity.Invalid; + public string Comment; + public bool Valid => Judgement >= Severity.Fishy; + + public LegalityCheck() { } + public LegalityCheck(Severity s, string c) + { + Judgement = s; + Comment = c; + } + public static LegalityCheck verifyECPID(PK6 pk) + { + // Secondary Checks + if (pk.EncryptionConstant == 0) + return new LegalityCheck(Severity.Fishy, "Encryption Constant is not set."); + + if (pk.PID == 0) + return new LegalityCheck(Severity.Fishy, "PID is not set."); + + if (pk.Gen6) + return new LegalityCheck(); + + // When transferred to Generation 6, the Encryption Constant is copied from the PID. + // The PID is then checked to see if it becomes shiny with the new Shiny rules (>>4 instead of >>3) + // If the PID is nonshiny->shiny, the top bit is flipped. + + // Check to see if the PID and EC are properly configured. + bool xorPID = ((pk.TID ^ pk.SID ^ (int)(pk.PID & 0xFFFF) ^ (int)(pk.PID >> 16)) & 0x7) == 8; + bool valid = xorPID + ? pk.EncryptionConstant == (pk.PID ^ 0x8000000) + : pk.EncryptionConstant == pk.PID; + + if (!valid) + if (xorPID) + return new LegalityCheck(Severity.Invalid, "PID should be equal to EC [with top bit flipped]!"); + else + return new LegalityCheck(Severity.Invalid, "PID should be equal to EC!"); + + return new LegalityCheck(); + } + public static LegalityCheck verifyNickname(PK6 pk) + { + LegalityCheck r = new LegalityCheck { Judgement = Severity.NotImplemented }; + // If the Pokémon is not nicknamed, it should match one of the language strings. + if (pk.Nickname.Length == 0) + { + r.Judgement = Severity.Indeterminate; + r.Comment = "Pokémon nickname is empty."; + } + return r; + } + public static LegalityCheck verifyEVs(PK6 pk) + { + var EVs = pk.EVs; + if (EVs.Sum() == 0 && pk.Met_Level != pk.Stat_Level && pk.Stat_Level > 1) + return new LegalityCheck(Severity.Fishy, "All EVs are zero, but leveled above Met Level"); + if (EVs.Sum() == 508) + return new LegalityCheck(Severity.Fishy, "2 EVs remaining."); + if (EVs.Sum() > 510) + return new LegalityCheck(Severity.Invalid, "EV total cannot be above 510."); + if (EVs.Any(ev => ev > 252)) + return new LegalityCheck(Severity.Invalid, "EVs cannot go above 252."); + if (EVs.All(ev => pk.EVs[0] == ev) && EVs[0] != 0) + return new LegalityCheck(Severity.Fishy, "EVs are all equal."); + + return new LegalityCheck(); + } + public static LegalityCheck verifyIVs(PK6 pk) + { + if (pk.IVs.Sum() == 0) + return new LegalityCheck(Severity.Fishy, "All IVs are zero."); + if (pk.IVs[0] < 30 && pk.IVs.All(iv => pk.IVs[0] == iv)) + return new LegalityCheck(Severity.Fishy, "All IVs are equal."); + return new LegalityCheck(); + } + public static LegalityCheck verifyID(PK6 pk) + { + if (pk.TID == 0 && pk.SID == 0) + return new LegalityCheck(Severity.Fishy, "TID and SID are zero."); + if (pk.TID == 0) + return new LegalityCheck(Severity.Fishy, "TID is zero."); + if (pk.SID == 0) + return new LegalityCheck(Severity.Fishy, "SID is zero."); + return new LegalityCheck(); + } + } +} diff --git a/PKHeX.csproj b/PKHeX.csproj index 428738bd5..9e07eba6d 100644 --- a/PKHeX.csproj +++ b/PKHeX.csproj @@ -69,6 +69,7 @@ +