From 8c85a03d78f9376d5e7644ca00c9bd43688d193e Mon Sep 17 00:00:00 2001 From: Kurt Date: Thu, 19 Jun 2025 23:36:59 -0500 Subject: [PATCH] simplify mysterygift clone move declaration to derived class, can return specific type now don't use AbilityType directly, use the ability permission computed property for legality checks. probably can remove this explicit MG method in the future. --- .../Encounters/Information/EncounterText.cs | 2 +- .../Verifiers/Ability/AbilityVerifier.cs | 12 +++++------ PKHeX.Core/MysteryGifts/DataMysteryGift.cs | 18 ++++++----------- PKHeX.Core/MysteryGifts/MysteryGift.cs | 20 ++++--------------- PKHeX.Core/MysteryGifts/PCD.cs | 1 + PKHeX.Core/MysteryGifts/PGF.cs | 3 ++- PKHeX.Core/MysteryGifts/PGT.cs | 1 + PKHeX.Core/MysteryGifts/WA8.cs | 3 ++- PKHeX.Core/MysteryGifts/WB7.cs | 3 ++- PKHeX.Core/MysteryGifts/WB8.cs | 3 ++- PKHeX.Core/MysteryGifts/WC6.cs | 3 ++- PKHeX.Core/MysteryGifts/WC7.cs | 3 ++- PKHeX.Core/MysteryGifts/WC8.cs | 3 ++- PKHeX.Core/MysteryGifts/WC9.cs | 3 ++- PKHeX.Core/MysteryGifts/WR7.cs | 3 +++ .../Subforms/Save Editors/SAV_Wondercard.cs | 4 ++-- 16 files changed, 40 insertions(+), 45 deletions(-) diff --git a/PKHeX.Core/Legality/Encounters/Information/EncounterText.cs b/PKHeX.Core/Legality/Encounters/Information/EncounterText.cs index 8f0695d93..0e532cf27 100644 --- a/PKHeX.Core/Legality/Encounters/Information/EncounterText.cs +++ b/PKHeX.Core/Legality/Encounters/Information/EncounterText.cs @@ -46,7 +46,7 @@ public static IReadOnlyList GetTextLines(this IEncounterInfo enc, GameSt return lines; // Record types! Can get a nice summary. - // Won't work neatly for Mystery Gift types since those aren't record types. + // Won't work neatly for Mystery Gift types since those aren't record types, plus they have way too many properties. if (enc is not MysteryGift) { // ReSharper disable once ConstantNullCoalescingCondition diff --git a/PKHeX.Core/Legality/Verifiers/Ability/AbilityVerifier.cs b/PKHeX.Core/Legality/Verifiers/Ability/AbilityVerifier.cs index 324d09b35..f92f358a7 100644 --- a/PKHeX.Core/Legality/Verifiers/Ability/AbilityVerifier.cs +++ b/PKHeX.Core/Legality/Verifiers/Ability/AbilityVerifier.cs @@ -262,21 +262,21 @@ private CheckResult VerifyAbilityMG(LegalityAnalysis data, MysteryGift g, IPerso if (g is PGT) // Ranger Manaphy return (pk.Format >= 6 ? (pk.AbilityNumber == 1) : (pk.AbilityNumber < 4)) ? VALID : GetInvalid(LAbilityMismatchGift); - var cardType = g.AbilityType; - if (cardType == 4) // 1/2/H + var permit = g.Ability; + if (permit == AbilityPermission.Any12H) return VALID; int abilNumber = pk.AbilityNumber; - if (cardType == 3) // 1/2 + if (permit == AbilityPermission.Any12) return abilNumber == 4 ? GetInvalid(LAbilityMismatchGift) : VALID; // Only remaining matches are fixed index abilities - int cardAbilIndex = 1 << cardType; + int cardAbilIndex = (int)permit; if (abilNumber == cardAbilIndex) return VALID; // Can still match if the ability was changed via ability capsule... // However, it can't change to/from Hidden Abilities. - if (abilNumber == 4 || cardType == 2) + if (abilNumber == 4 || permit == AbilityPermission.OnlyHidden) return GetInvalid(LAbilityHiddenFail); // Ability can be flipped 0/1 if Ability Capsule is available, is not Hidden Ability, and Abilities are different. @@ -319,7 +319,7 @@ private CheckResult VerifyAbility5(LegalityAnalysis data, IEncounterTemplate enc { var pk = data.Entity; - // Eggs and Encounter Slots are not yet checked for Hidden Ability potential. + // Eggs and Encounter Slots have not yet checked for Hidden Ability potential. return enc switch { EncounterEgg5 egg when pk.AbilityNumber == 4 && !egg.Ability.CanBeHidden() => GetInvalid(LAbilityHiddenUnavailable), diff --git a/PKHeX.Core/MysteryGifts/DataMysteryGift.cs b/PKHeX.Core/MysteryGifts/DataMysteryGift.cs index 6ff9c50dc..6de5e42b5 100644 --- a/PKHeX.Core/MysteryGifts/DataMysteryGift.cs +++ b/PKHeX.Core/MysteryGifts/DataMysteryGift.cs @@ -14,7 +14,7 @@ public abstract class DataMysteryGift(Memory Raw) : MysteryGift /// public virtual ReadOnlySpan Write() => Data; - public override int GetHashCode() + public sealed override int GetHashCode() { int hash = 17; foreach (var b in Data) @@ -22,18 +22,12 @@ public override int GetHashCode() return hash; } + public sealed override bool IsEmpty => !Data.ContainsAnyExcept(0); + + public void Clear() => Data.Clear(); + /// /// Creates a deep copy of the object data. /// - public override MysteryGift Clone() - { - var data = Data.ToArray(); - var result = GetMysteryGift(data); - ArgumentNullException.ThrowIfNull(result); - return result; - } - - public sealed override bool Empty => !Data.ContainsAnyExcept(0); - - public void Clear() => Data.Clear(); + public abstract DataMysteryGift Clone(); } diff --git a/PKHeX.Core/MysteryGifts/MysteryGift.cs b/PKHeX.Core/MysteryGifts/MysteryGift.cs index 42aa7fd56..4cbf54cfa 100644 --- a/PKHeX.Core/MysteryGifts/MysteryGift.cs +++ b/PKHeX.Core/MysteryGifts/MysteryGift.cs @@ -100,11 +100,6 @@ public EncounterMatchRating GetMatchRating(PKM pk) return EncounterMatchRating.Match; } - /// - /// Creates a deep copy of the object data. - /// - public abstract MysteryGift Clone(); - /// /// Gets a friendly name for the underlying type. /// @@ -134,23 +129,16 @@ public EncounterMatchRating GetMatchRating(PKM pk) public virtual int Quantity { get => 1; set { } } public virtual bool IsEmpty => false; - public virtual string CardHeader => (CardID > 0 ? $"Card #: {CardID:0000}" : "N/A") + $" - {CardTitle.Replace('\u3000',' ').Trim()}"; + public string CardHeader => (CardID > 0 ? $"Card #: {CardID:0000}" : "N/A") + $" - {CardTitle.Replace('\u3000',' ').Trim()}"; // Search Properties public virtual Moveset Moves { get => default; set { } } public virtual bool HasFixedIVs => true; public virtual void GetIVs(Span value) { } public virtual bool IsShiny => false; - - public virtual Shiny Shiny - { - get => Shiny.Never; - init => throw new InvalidOperationException(); - } - - public virtual bool IsEgg { get => false; set { } } - public virtual int HeldItem { get => -1; set { } } - public virtual int AbilityType { get => -1; set { } } + public abstract Shiny Shiny { get; } + public abstract bool IsEgg { get; set; } + public abstract int HeldItem { get; set; } public abstract byte Gender { get; set; } public abstract byte Form { get; set; } public abstract uint ID32 { get; set; } diff --git a/PKHeX.Core/MysteryGifts/PCD.cs b/PKHeX.Core/MysteryGifts/PCD.cs index 9e282e30b..84475225b 100644 --- a/PKHeX.Core/MysteryGifts/PCD.cs +++ b/PKHeX.Core/MysteryGifts/PCD.cs @@ -17,6 +17,7 @@ public sealed class PCD(Memory raw) { public PCD() : this(new byte[Size]) { } private readonly Memory _raw = raw; + public override PCD Clone() => new(Data.ToArray()); public const int Size = 0x358; // 856 public override byte Generation => 4; diff --git a/PKHeX.Core/MysteryGifts/PGF.cs b/PKHeX.Core/MysteryGifts/PGF.cs index 738fa78fd..dcc0b0374 100644 --- a/PKHeX.Core/MysteryGifts/PGF.cs +++ b/PKHeX.Core/MysteryGifts/PGF.cs @@ -11,6 +11,7 @@ public sealed class PGF : DataMysteryGift, IRibbonSetEvent3, IRibbonSetEvent4, I { public PGF() : this(new byte[Size]) { } public PGF(Memory raw) : base(raw) { } + public override PGF Clone() => new(Data.ToArray()); public int RestrictLanguage { get; set; } // None public byte RestrictVersion { get; set; } // Permit All @@ -75,7 +76,7 @@ public string Nickname public Nature Nature { get => (Nature)Data[0x34]; set => Data[0x34] = (byte)value; } public override byte Gender { get => Data[0x35]; set => Data[0x35] = value; } - public override int AbilityType { get => Data[0x36]; set => Data[0x36] = (byte)value; } + public int AbilityType { get => Data[0x36]; set => Data[0x36] = (byte)value; } public int PIDType { get => Data[0x37]; set => Data[0x37] = (byte)value; } public override ushort EggLocation { get => ReadUInt16LittleEndian(Data[0x38..]); set => WriteUInt16LittleEndian(Data[0x38..], value); } public override ushort Location { get => ReadUInt16LittleEndian(Data[0x3A..]); set => WriteUInt16LittleEndian(Data[0x3A..], value); } diff --git a/PKHeX.Core/MysteryGifts/PGT.cs b/PKHeX.Core/MysteryGifts/PGT.cs index 68dd158fb..973dffe91 100644 --- a/PKHeX.Core/MysteryGifts/PGT.cs +++ b/PKHeX.Core/MysteryGifts/PGT.cs @@ -12,6 +12,7 @@ public sealed class PGT : DataMysteryGift, IRibbonSetEvent3, IRibbonSetEvent4, I { public PGT() : this(new byte[Size]) { } public PGT(Memory raw) : base(raw) { } + public override PGT Clone() => new(Data.ToArray()); public const int Size = 0x104; // 260 public override byte Generation => 4; diff --git a/PKHeX.Core/MysteryGifts/WA8.cs b/PKHeX.Core/MysteryGifts/WA8.cs index dc085ec81..aad3ffba3 100644 --- a/PKHeX.Core/MysteryGifts/WA8.cs +++ b/PKHeX.Core/MysteryGifts/WA8.cs @@ -15,6 +15,7 @@ public sealed class WA8 : DataMysteryGift, ILangNick, INature, IGigantamax, IDyn { public WA8() : this(new byte[Size]) { } public WA8(Memory raw) : base(raw) { } + public override WA8 Clone() => new(Data.ToArray()); public const int Size = 0x2C8; @@ -176,7 +177,7 @@ public override int HeldItem public override byte Level { get => Data[0x23C]; set => Data[0x23C] = value; } public override bool IsEgg { get => Data[0x23D] == 1; set => Data[0x23D] = value ? (byte)1 : (byte)0; } public Nature Nature { get => (Nature)Data[0x23E]; set => Data[0x23E] = (byte)value; } - public override int AbilityType { get => Data[0x23F]; set => Data[0x23F] = (byte)value; } + public int AbilityType { get => Data[0x23F]; set => Data[0x23F] = (byte)value; } private byte PIDTypeValue => Data[0x240]; diff --git a/PKHeX.Core/MysteryGifts/WB7.cs b/PKHeX.Core/MysteryGifts/WB7.cs index 013748873..f637ab19c 100644 --- a/PKHeX.Core/MysteryGifts/WB7.cs +++ b/PKHeX.Core/MysteryGifts/WB7.cs @@ -11,6 +11,7 @@ public sealed class WB7 : DataMysteryGift, ILangNick, IAwakened, IRelearn, IEnco { public WB7() : this(new byte[Size]) { } public WB7(Memory raw) : base(raw) { } + public override WB7 Clone() => new(Data.ToArray()); public const int Size = 0x310; private const int CardStart = 0x208; @@ -183,7 +184,7 @@ private uint GetShinyXor() public Nature Nature { get => (Nature)Card[0xA0]; set => Card[0xA0] = (byte)value; } public override byte Gender { get => Card[0xA1]; set => Card[0xA1] = value; } - public override int AbilityType { get => IsHOMEGift ? Card[0xA2] : 3; set => Card[0xA2] = (byte)value; } // no references, always ability 0/1 + public int AbilityType { get => IsHOMEGift ? Card[0xA2] : 3; set => Card[0xA2] = (byte)value; } // no references, always ability 0/1 public ShinyType6 PIDType { get => (ShinyType6)Card[0xA3]; set => Card[0xA3] = (byte)value; } public override ushort EggLocation { get => ReadUInt16LittleEndian(Card[0xA4..]); set => WriteUInt16LittleEndian(Card[0xA4..], value); } public override ushort Location { get => ReadUInt16LittleEndian(Card[0xA6..]); set => WriteUInt16LittleEndian(Card[0xA6..], value); } diff --git a/PKHeX.Core/MysteryGifts/WB8.cs b/PKHeX.Core/MysteryGifts/WB8.cs index fc49dda49..d8b4eac24 100644 --- a/PKHeX.Core/MysteryGifts/WB8.cs +++ b/PKHeX.Core/MysteryGifts/WB8.cs @@ -15,6 +15,7 @@ public sealed class WB8 : DataMysteryGift, { public WB8() : this(new byte[Size]) { } public WB8(Memory raw) : base(raw) { } + public override WB8 Clone() => new(Data.ToArray()); public const int Size = 0x2DC; public const int CardStart = 0x0; @@ -187,7 +188,7 @@ public override int HeldItem public override byte Level { get => Data[CardStart + 0x28C]; set => Data[CardStart + 0x28C] = value; } public override bool IsEgg { get => Data[CardStart + 0x28D] == 1; set => Data[CardStart + 0x28D] = value ? (byte)1 : (byte)0; } public Nature Nature { get => (Nature)Data[CardStart + 0x28E]; set => Data[CardStart + 0x28E] = (byte)value; } - public override int AbilityType { get => Data[CardStart + 0x28F]; set => Data[CardStart + 0x28F] = (byte)value; } + public int AbilityType { get => Data[CardStart + 0x28F]; set => Data[CardStart + 0x28F] = (byte)value; } private byte PIDTypeValue => Data[CardStart + 0x290]; diff --git a/PKHeX.Core/MysteryGifts/WC6.cs b/PKHeX.Core/MysteryGifts/WC6.cs index 15847e507..d267d92dc 100644 --- a/PKHeX.Core/MysteryGifts/WC6.cs +++ b/PKHeX.Core/MysteryGifts/WC6.cs @@ -11,6 +11,7 @@ public sealed class WC6 : DataMysteryGift, IRibbonSetEvent3, IRibbonSetEvent4, { public WC6() : this(new byte[Size]) { } public WC6(Memory raw) : base(raw) { } + public override WC6 Clone() => new(Data.ToArray()); public const int Size = 0x108; public const uint EonTicketConst = 0x225D73C2; @@ -176,7 +177,7 @@ public string Nickname public Nature Nature { get => (Nature)Data[0xA0]; set => Data[0xA0] = (byte)value; } public override byte Gender { get => Data[0xA1]; set => Data[0xA1] = value; } - public override int AbilityType { get => Data[0xA2]; set => Data[0xA2] = (byte)value; } + public int AbilityType { get => Data[0xA2]; set => Data[0xA2] = (byte)value; } public ShinyType6 PIDType { get => (ShinyType6)Data[0xA3]; set => Data[0xA3] = (byte)value; } public override ushort EggLocation { get => ReadUInt16LittleEndian(Data[0xA4..]); set => WriteUInt16LittleEndian(Data[0xA4..], value); } public override ushort Location { get => ReadUInt16LittleEndian(Data[0xA6..]); set => WriteUInt16LittleEndian(Data[0xA6..], value); } diff --git a/PKHeX.Core/MysteryGifts/WC7.cs b/PKHeX.Core/MysteryGifts/WC7.cs index 5e33c4b18..a914d4344 100644 --- a/PKHeX.Core/MysteryGifts/WC7.cs +++ b/PKHeX.Core/MysteryGifts/WC7.cs @@ -11,6 +11,7 @@ public sealed class WC7 : DataMysteryGift, IRibbonSetEvent3, IRibbonSetEvent4, I { public WC7() : this(new byte[Size]) { } public WC7(Memory raw) : base(raw) { } + public override WC7 Clone() => new(Data.ToArray()); public const int Size = 0x108; public override byte Generation => 7; @@ -223,7 +224,7 @@ public string Nickname public Nature Nature { get => (Nature)Data[0xA0]; set => Data[0xA0] = (byte)value; } public override byte Gender { get => Data[0xA1]; set => Data[0xA1] = value; } - public override int AbilityType { get => Data[0xA2]; set => Data[0xA2] = (byte)value; } + public int AbilityType { get => Data[0xA2]; set => Data[0xA2] = (byte)value; } public ShinyType6 PIDType { get => (ShinyType6)Data[0xA3]; set => Data[0xA3] = (byte)value; } public override ushort EggLocation { get => ReadUInt16LittleEndian(Data[0xA4..]); set => WriteUInt16LittleEndian(Data[0xA4..], value); } public override ushort Location { get => ReadUInt16LittleEndian(Data[0xA6..]); set => WriteUInt16LittleEndian(Data[0xA6..], value); } diff --git a/PKHeX.Core/MysteryGifts/WC8.cs b/PKHeX.Core/MysteryGifts/WC8.cs index fe896fc68..89884bb43 100644 --- a/PKHeX.Core/MysteryGifts/WC8.cs +++ b/PKHeX.Core/MysteryGifts/WC8.cs @@ -13,6 +13,7 @@ public sealed class WC8 : DataMysteryGift, ILangNick, INature, IGigantamax, IDyn { public WC8() : this(new byte[Size]) { } public WC8(Memory raw) : base(raw) { } + public override WC8 Clone() => new(Data.ToArray()); public const int Size = 0x2D0; public const int CardStart = 0x0; @@ -184,7 +185,7 @@ public override int HeldItem public override byte Level { get => Data[CardStart + 0x244]; set => Data[CardStart + 0x244] = value; } public override bool IsEgg { get => Data[CardStart + 0x245] == 1; set => Data[CardStart + 0x245] = value ? (byte)1 : (byte)0; } public Nature Nature { get => (Nature)Data[CardStart + 0x246]; set => Data[CardStart + 0x246] = (byte)value; } - public override int AbilityType { get => Data[CardStart + 0x247]; set => Data[CardStart + 0x247] = (byte)value; } + public int AbilityType { get => Data[CardStart + 0x247]; set => Data[CardStart + 0x247] = (byte)value; } public ShinyType8 PIDType { get => (ShinyType8)Data[CardStart + 0x248]; set => Data[CardStart + 0x248] = (byte)value; } diff --git a/PKHeX.Core/MysteryGifts/WC9.cs b/PKHeX.Core/MysteryGifts/WC9.cs index eef35b158..ca690345f 100644 --- a/PKHeX.Core/MysteryGifts/WC9.cs +++ b/PKHeX.Core/MysteryGifts/WC9.cs @@ -14,6 +14,7 @@ public sealed class WC9 : DataMysteryGift, ILangNick, INature, ITeraType, IRibbo { public WC9() : this(new byte[Size]) { } public WC9(Memory raw) : base(raw) { } + public override WC9 Clone() => new(Data.ToArray()); public const int Size = 0x2C8; public const int CardStart = 0x0; @@ -199,7 +200,7 @@ public override int HeldItem public override byte Level { get => Data[CardStart + 0x23C]; set => Data[CardStart + 0x23C] = value; } public override bool IsEgg { get => Data[CardStart + 0x23D] == 1; set => Data[CardStart + 0x23D] = value ? (byte)1 : (byte)0; } public Nature Nature { get => (Nature)Data[CardStart + 0x23E]; set => Data[CardStart + 0x23E] = (byte)value; } - public override int AbilityType { get => Data[CardStart + 0x23F]; set => Data[CardStart + 0x23F] = (byte)value; } + public int AbilityType { get => Data[CardStart + 0x23F]; set => Data[CardStart + 0x23F] = (byte)value; } public ShinyType8 PIDType { get => (ShinyType8)Data[CardStart + 0x240]; set => Data[CardStart + 0x240] = (byte)value; } diff --git a/PKHeX.Core/MysteryGifts/WR7.cs b/PKHeX.Core/MysteryGifts/WR7.cs index 41339dc96..257802676 100644 --- a/PKHeX.Core/MysteryGifts/WR7.cs +++ b/PKHeX.Core/MysteryGifts/WR7.cs @@ -14,6 +14,7 @@ public sealed class WR7 : DataMysteryGift { public WR7() : this(new byte[Size]) { } public WR7(Memory raw) : base(raw) { } + public override WR7 Clone() => new(Data.ToArray()); public const int Size = 0x140; public override byte Generation => 7; @@ -90,6 +91,8 @@ public override ushort Species public override uint ID32 { get; set; } public override ushort TID16 { get; set; } public override ushort SID16 { get; set; } + public override bool IsEgg { get => false; set { } } + public override int HeldItem { get => -1; set { } } public override string OriginalTrainerName { diff --git a/PKHeX.WinForms/Subforms/Save Editors/SAV_Wondercard.cs b/PKHeX.WinForms/Subforms/Save Editors/SAV_Wondercard.cs index 4af2d8e2c..cfa291207 100644 --- a/PKHeX.WinForms/Subforms/Save Editors/SAV_Wondercard.cs +++ b/PKHeX.WinForms/Subforms/Save Editors/SAV_Wondercard.cs @@ -257,7 +257,7 @@ private void ClickSet(object sender, EventArgs e) WinFormsUtil.Alert(MsgMysteryGiftSlotFail, $"{GameInfo.Strings.Item[533]} slot not valid."); return; } - gifts[index] = (DataMysteryGift)gift.Clone(); + gifts[index] = gift.Clone(); SetBackground(index, Drawing.PokeSprite.Properties.Resources.slotSet); SetGiftBoxes(); SetCardID(gift.CardID); @@ -556,7 +556,7 @@ private void BoxSlot_DragDrop(object? sender, DragEventArgs? e) return; } SetBackground(index, Drawing.PokeSprite.Properties.Resources.slotSet); - dest = (DataMysteryGift)gift.Clone(); + dest = gift.Clone(); SetCardID(dest.CardID); ViewGiftData(dest);