diff --git a/PKHeX/Legality/Checks.cs b/PKHeX/Legality/Checks.cs index b3c1025f5..41f188d04 100644 --- a/PKHeX/Legality/Checks.cs +++ b/PKHeX/Legality/Checks.cs @@ -1125,69 +1125,47 @@ private void verifyRibbons() } // Check Event Ribbons - var RibbonData = ReflectUtil.getPropertiesStartWithPrefix(pkm.GetType(), "Ribbon"); - MysteryGift MatchedGift = EncounterMatch as MysteryGift; - string[] EventRib = + var encounterContent = (EncounterMatch as MysteryGift)?.Content ?? EncounterMatch; + var set1 = pkm as IRibbonSet1; + if (set1 != null) { - nameof(PK6.RibbonCountry), nameof(PK6.RibbonNational), nameof(PK6.RibbonEarth), nameof(PK6.RibbonWorld), nameof(PK6.RibbonClassic), - nameof(PK6.RibbonPremier), nameof(PK6.RibbonEvent), nameof(PK6.RibbonBirthday), nameof(PK6.RibbonSpecial), nameof(PK6.RibbonSouvenir), - nameof(PK6.RibbonWishing), nameof(PK6.RibbonChampionBattle), nameof(PK6.RibbonChampionRegional), nameof(PK6.RibbonChampionNational), nameof(PK6.RibbonChampionWorld) - }; - if (MatchedGift != null) // Wonder Card - { - var mgRibbons = MatchedGift.Format == 4 ? EventRib : ReflectUtil.getPropertiesStartWithPrefix(MatchedGift.Content.GetType(), "Ribbon"); - var commonRibbons = mgRibbons.Intersect(RibbonData).ToArray(); + var sb = RibbonSetHelper.getRibbonBits(set1); + var enc1 = encounterContent as IRibbonSet1; + var eb = RibbonSetHelper.getRibbonBits(enc1); - foreach (string r in commonRibbons) + if (pkm.Gen3) + eb[0] = sb[0]; // permit Earth Ribbon + if (pkm.Version == 15) + eb[1] = true; // require National Ribbon TODO: shadow pkm only + + for (int i = 0; i < sb.Length; i++) { - bool? pk = ReflectUtil.getBooleanState(pkm, r); - bool? mg = ReflectUtil.getBooleanState(MatchedGift.Content, r); - if (pk != mg) // Mismatch - { - if (pk ?? false) - missingRibbons.Add(r); - else - invalidRibbons.Add(r); - } - } - } - else if (EncounterType == typeof(EncounterLink)) - { - // No Event Ribbons except Classic (unless otherwise specified, ie not for Demo) - for (int i = 0; i < EventRib.Length; i++) - { - if (i == 4) + if (sb[i] == eb[i]) // valid continue; - - if (ReflectUtil.getBooleanState(pkm, EventRib[i]) == true) - invalidRibbons.Add(EventRibName[i]); + var list = eb[i] ? missingRibbons : invalidRibbons; + list.Add(RibbonSetHelper.getRibbonNames(set1, i)); } - - bool classic = ReflectUtil.getBooleanState(pkm, EventRib[4]) == true; - if (classic ^ ((EncounterLink)EncounterMatch).Classic) - (classic ? invalidRibbons : missingRibbons).Add(EventRibName[4]); } - else if (EncounterType == typeof(EncounterStatic)) + + var set2 = pkm as IRibbonSet2; + if (set2 != null) { - // No Event Ribbons except Wishing (which is only for Magearna) - for (int i = 0; i < EventRib.Length; i++) + var sb = RibbonSetHelper.getRibbonBits(set2); + var enc2 = encounterContent as IRibbonSet2; + var eb = RibbonSetHelper.getRibbonBits(enc2); + + if (EncounterMatch is EncounterLink) + eb[0] = true; // require Classic Ribbon + if ((EncounterMatch as EncounterStatic)?.RibbonWishing ?? false) + eb[1] = true; // require Wishing Ribbon + + for (int i = 0; i < sb.Length; i++) { - if (i == 10) + if (sb[i] == eb[i]) // valid continue; - - if (ReflectUtil.getBooleanState(pkm, EventRib[i]) == true) - invalidRibbons.Add(EventRibName[i]); + var list = eb[i] ? missingRibbons : invalidRibbons; + list.Add(RibbonSetHelper.getRibbonNames(set2, i)); } - - bool wishing = ReflectUtil.getBooleanState(pkm, EventRib[10]) == true; - if (wishing ^ ((EncounterStatic)EncounterMatch).RibbonWishing) - (wishing ? invalidRibbons : missingRibbons).Add(EventRibName[10]); - } - else // No ribbons - { - for (int i = 0; i < EventRib.Length; i++) - if (ReflectUtil.getBooleanState(pkm, EventRib[i]) == true) - invalidRibbons.Add(EventRibName[i]); } // Unobtainable ribbons for Gen Origin @@ -1197,8 +1175,6 @@ private void verifyRibbons() invalidRibbons.Add(V96); // RSE HoF if (ReflectUtil.getBooleanState(pkm, nameof(PK3.RibbonArtist)) == true) invalidRibbons.Add(V97); // RSE Master Rank Portrait - if (ReflectUtil.getBooleanState(pkm, nameof(PK3.RibbonNational)) == true && pkm.Version != (int)GameVersion.CXD) - invalidRibbons.Add(V98); // RSE HoF } if (pkm.GenNumber > 4) { @@ -1225,9 +1201,9 @@ private void verifyRibbons() string[] result = new string[2]; if (missingRibbons.Count > 0) - result[0] = string.Format(V101, string.Join(", ", missingRibbons)); + result[0] = string.Format(V101, string.Join(", ", missingRibbons.Select(z => z.Replace("Ribbon", "")))); if (invalidRibbons.Count > 0) - result[1] = string.Format(V102, string.Join(", ", invalidRibbons)); + result[1] = string.Format(V102, string.Join(", ", invalidRibbons.Select(z => z.Replace("Ribbon", "")))); AddLine(Severity.Invalid, string.Join(Environment.NewLine, result.Where(s => !string.IsNullOrEmpty(s))), CheckIdentifier.Ribbon); } private void verifyAbility() diff --git a/PKHeX/Legality/Structures/IRibbonSet.cs b/PKHeX/Legality/Structures/IRibbonSet.cs new file mode 100644 index 000000000..b93d0f1d8 --- /dev/null +++ b/PKHeX/Legality/Structures/IRibbonSet.cs @@ -0,0 +1,73 @@ +namespace PKHeX.Core +{ + internal interface IRibbonSet1 // Gen3+ + { + bool RibbonEarth { get; set; } + bool RibbonNational { get; set; } + bool RibbonCountry { get; set; } + bool RibbonChampionBattle { get; set; } + bool RibbonChampionRegional { get; set; } + bool RibbonChampionNational { get; set; } + } + internal interface IRibbonSet2 // Gen4+ + { + bool RibbonClassic { get; set; } + bool RibbonWishing { get; set; } + bool RibbonPremier { get; set; } + bool RibbonEvent { get; set; } + bool RibbonBirthday { get; set; } + bool RibbonSpecial { get; set; } + bool RibbonWorld { get; set; } + bool RibbonChampionWorld { get; set; } + bool RibbonSouvenir { get; set; } + } + + internal static class RibbonSetHelper + { + public static readonly string[] RibbonNames1 = + { + nameof(IRibbonSet1.RibbonEarth), nameof(IRibbonSet1.RibbonNational), nameof(IRibbonSet1.RibbonCountry), + nameof(IRibbonSet1.RibbonChampionBattle), nameof(IRibbonSet1.RibbonChampionRegional), nameof(IRibbonSet1.RibbonChampionNational) + }; + public static bool[] getRibbonBits(IRibbonSet1 set) + { + if (set == null) + return new bool[6]; + return new[] + { + set.RibbonEarth, + set.RibbonNational, + set.RibbonCountry, + set.RibbonChampionBattle, + set.RibbonChampionRegional, + set.RibbonChampionNational, + }; + } + public static readonly string[] RibbonNames2 = + { + nameof(IRibbonSet2.RibbonClassic), nameof(IRibbonSet2.RibbonWishing), nameof(IRibbonSet2.RibbonPremier), + nameof(IRibbonSet2.RibbonEvent), nameof(IRibbonSet2.RibbonBirthday), nameof(IRibbonSet2.RibbonSpecial), + nameof(IRibbonSet2.RibbonWorld), nameof(IRibbonSet2.RibbonChampionWorld), nameof(IRibbonSet2.RibbonSouvenir) + }; + public static bool[] getRibbonBits(IRibbonSet2 set) + { + if (set == null) + return new bool[9]; + return new[] + { + set.RibbonClassic, + set.RibbonWishing, + set.RibbonPremier, + set.RibbonEvent, + set.RibbonBirthday, + set.RibbonSpecial, + set.RibbonWorld, + set.RibbonChampionWorld, + set.RibbonSouvenir, + }; + } + + public static string getRibbonNames(IRibbonSet1 set, int index) => RibbonNames1[index]; + public static string getRibbonNames(IRibbonSet2 set, int index) => RibbonNames2[index]; + } +} diff --git a/PKHeX/MysteryGifts/PGF.cs b/PKHeX/MysteryGifts/PGF.cs index 32c21a441..f6d03ce81 100644 --- a/PKHeX/MysteryGifts/PGF.cs +++ b/PKHeX/MysteryGifts/PGF.cs @@ -3,7 +3,7 @@ namespace PKHeX.Core { - public sealed class PGF : MysteryGift + public sealed class PGF : MysteryGift, IRibbonSet1, IRibbonSet2 { public const int Size = 0xCC; public override int Format => 5; diff --git a/PKHeX/MysteryGifts/WC6.cs b/PKHeX/MysteryGifts/WC6.cs index 82d0ef872..94814f625 100644 --- a/PKHeX/MysteryGifts/WC6.cs +++ b/PKHeX/MysteryGifts/WC6.cs @@ -4,7 +4,7 @@ namespace PKHeX.Core { - public sealed class WC6 : MysteryGift + public sealed class WC6 : MysteryGift, IRibbonSet1, IRibbonSet2 { public const int Size = 0x108; public const int SizeFull = 0x310; diff --git a/PKHeX/MysteryGifts/WC7.cs b/PKHeX/MysteryGifts/WC7.cs index 8144b3313..5abf43580 100644 --- a/PKHeX/MysteryGifts/WC7.cs +++ b/PKHeX/MysteryGifts/WC7.cs @@ -4,7 +4,7 @@ namespace PKHeX.Core { - public sealed class WC7 : MysteryGift + public sealed class WC7 : MysteryGift, IRibbonSet1, IRibbonSet2 { public const int Size = 0x108; public const int SizeFull = 0x310; diff --git a/PKHeX/PKHeX.Core.csproj b/PKHeX/PKHeX.Core.csproj index cccb4872e..ef18c538c 100644 --- a/PKHeX/PKHeX.Core.csproj +++ b/PKHeX/PKHeX.Core.csproj @@ -167,6 +167,7 @@ + diff --git a/PKHeX/PKM/PK3.cs b/PKHeX/PKM/PK3.cs index 4f87fb3f3..11a242921 100644 --- a/PKHeX/PKM/PK3.cs +++ b/PKHeX/PKM/PK3.cs @@ -3,7 +3,7 @@ namespace PKHeX.Core { - public class PK3 : PKM // 3rd Generation PKM File + public class PK3 : PKM, IRibbonSet1 { public static readonly byte[] ExtraBytes = { diff --git a/PKHeX/PKM/PK4.cs b/PKHeX/PKM/PK4.cs index 79fe0a4da..aedc9d216 100644 --- a/PKHeX/PKM/PK4.cs +++ b/PKHeX/PKM/PK4.cs @@ -3,7 +3,7 @@ namespace PKHeX.Core { - public class PK4 : PKM // 4th Generation PKM File + public class PK4 : PKM, IRibbonSet1, IRibbonSet2 { public static readonly byte[] ExtraBytes = { diff --git a/PKHeX/PKM/PK5.cs b/PKHeX/PKM/PK5.cs index 8e2a8f998..37f2c5fc1 100644 --- a/PKHeX/PKM/PK5.cs +++ b/PKHeX/PKM/PK5.cs @@ -3,7 +3,7 @@ namespace PKHeX.Core { - public class PK5 : PKM // 5th Generation PKM File + public class PK5 : PKM, IRibbonSet1, IRibbonSet2 { public static readonly byte[] ExtraBytes = { diff --git a/PKHeX/PKM/PK6.cs b/PKHeX/PKM/PK6.cs index f7fd002eb..8aacfae17 100644 --- a/PKHeX/PKM/PK6.cs +++ b/PKHeX/PKM/PK6.cs @@ -3,7 +3,7 @@ namespace PKHeX.Core { - public class PK6 : PKM + public class PK6 : PKM, IRibbonSet1, IRibbonSet2 { public static readonly byte[] ExtraBytes = { diff --git a/PKHeX/PKM/PK7.cs b/PKHeX/PKM/PK7.cs index 13df5dccf..27a0c6acc 100644 --- a/PKHeX/PKM/PK7.cs +++ b/PKHeX/PKM/PK7.cs @@ -3,7 +3,7 @@ namespace PKHeX.Core { - public class PK7 : PKM + public class PK7 : PKM, IRibbonSet1, IRibbonSet2 { public static readonly byte[] ExtraBytes = {