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 =
{