diff --git a/PKHeX.Core/Saves/SAV3.cs b/PKHeX.Core/Saves/SAV3.cs index b8e7289a0..4f8a5d2b9 100644 --- a/PKHeX.Core/Saves/SAV3.cs +++ b/PKHeX.Core/Saves/SAV3.cs @@ -594,5 +594,95 @@ public override void CopyChangesFrom(SaveFile sav) SetData(Large, s3.Large, 0); SetData(Storage, s3.Storage, 0); } + + #region External Connections + protected abstract int ExternalEventData { get; } + protected int ExternalEventFlags => ExternalEventData + 0x14; + + public uint ColosseumRaw1 + { + get => BitConverter.ToUInt32(Large, ExternalEventData + 7); + set => SetData(Large, BitConverter.GetBytes(value), ExternalEventData + 7); + } + + public uint ColosseumRaw2 + { + get => BitConverter.ToUInt32(Large, ExternalEventData + 11); + set => SetData(Large, BitConverter.GetBytes(value), ExternalEventData + 11); + } + + /// + /// PokéCoupons stored by Pokémon Colosseum and XD from Mt. Battle runs. Earned PokéCoupons are also added to . + /// + /// Colosseum/XD caps this at 9,999,999, but will read up to 16,777,215. + public uint ColosseumCoupons + { + get => ColosseumRaw1 >> 8; + set => ColosseumRaw1 = (value << 8) | (ColosseumRaw1 & 0xFF); + } + + /// Master Ball from JP Colosseum Bonus Disc; for reaching 30,000 + public bool ColosseumPokeCouponTitleGold + { + get => (ColosseumRaw2 & (1 << 0)) != 0; + set => ColosseumRaw2 = (ColosseumRaw2 & (1 << 0)) | ((value ? 1u : 0) << 0); + } + + /// Light Ball Pikachu from JP Colosseum Bonus Disc; for reaching 5000 + public bool ColosseumPokeCouponTitleSilver + { + get => (ColosseumRaw2 & (1 << 1)) != 0; + set => ColosseumRaw2 = (ColosseumRaw2 & (1 << 1)) | ((value ? 1u : 0) << 1); + } + + /// PP Max from JP Colosseum Bonus Disc; for reaching 2500 + public bool ColosseumPokeCouponTitleBronze + { + get => (ColosseumRaw2 & (1 << 2)) != 0; + set => ColosseumRaw2 = (ColosseumRaw2 & (1 << 2)) | ((value ? 1u : 0) << 2); + } + + /// Received Celebi Gift from JP Colosseum Bonus Disc + public bool ColosseumReceivedAgeto + { + get => (ColosseumRaw2 & (1 << 3)) != 0; + set => ColosseumRaw2 = (ColosseumRaw2 & (1 << 3)) | ((value ? 1u : 0) << 3); + } + + /// + /// Used by the JP Colosseum bonus disc. Determines PokéCoupon rank to distribute rewards. Unread in International games. + /// + /// + /// Colosseum/XD caps this at 9,999,999. + /// + public uint ColosseumCouponsTotal + { + get => ColosseumRaw2 >> 8; + set => ColosseumRaw2 = (value << 8) | (ColosseumRaw2 & 0xFF); + } + + /// Indicates if this save has connected to RSBOX and triggered the free False Swipe Swablu Egg giveaway. + public bool HasUsedRSBOX + { + get => GetFlag(ExternalEventFlags + 0, 0); + set => SetFlag(ExternalEventFlags + 0, 0, value); + } + + /// + /// 1 for ExtremeSpeed Zigzagoon (at 100 deposited), 2 for Pay Day Skitty (at 500 deposited), 3 for Surf Pichu (at 1499 deposited) + /// + public int RSBoxDepositEggsUnlocked + { + get => (Large[ExternalEventFlags] >> 1) & 3; + set => Large[ExternalEventFlags] = (byte)((Large[ExternalEventFlags] & ~(3 << 1)) | ((value & 3) << 1)); + } + + /// Received Jirachi Gift from Colosseum Bonus Disc + public bool HasReceivedWishmkrJirachi + { + get => GetFlag(ExternalEventFlags + 2, 0); + set => SetFlag(ExternalEventFlags + 2, 0, value); + } + #endregion } } diff --git a/PKHeX.Core/Saves/SAV3E.cs b/PKHeX.Core/Saves/SAV3E.cs index ca819516f..482d6d3c4 100644 --- a/PKHeX.Core/Saves/SAV3E.cs +++ b/PKHeX.Core/Saves/SAV3E.cs @@ -179,13 +179,7 @@ public int SwarmIndex public override string GetDaycareRNGSeed(int loc) => BitConverter.ToUInt32(Large, GetDaycareSlotOffset(0, 2)).ToString("X8"); // after the 2 slots, before the step counter public override void SetDaycareRNGSeed(int loc, string seed) => BitConverter.GetBytes(Util.GetHexValue(seed)).CopyTo(Large, GetDaycareEXPOffset(2)); - private const int ExternalEventFlags = 0x31C7; - - public bool HasReceivedWishmkrJirachi - { - get => GetFlag(ExternalEventFlags + 2, 0); - set => SetFlag(ExternalEventFlags + 2, 0, value); - } + protected override int ExternalEventData => 0x31B3; #region eBerry private const int OFFSET_EBERRY = 0x31F8; diff --git a/PKHeX.Core/Saves/SAV3FRLG.cs b/PKHeX.Core/Saves/SAV3FRLG.cs index 88aac3bec..d8eb558a7 100644 --- a/PKHeX.Core/Saves/SAV3FRLG.cs +++ b/PKHeX.Core/Saves/SAV3FRLG.cs @@ -137,6 +137,8 @@ protected override InventoryPouch3[] GetItems() public override string GetDaycareRNGSeed(int loc) => BitConverter.ToUInt16(Large, GetDaycareEXPOffset(2)).ToString("X4"); // after the 2nd slot EXP, before the step counter public override void SetDaycareRNGSeed(int loc, string seed) => BitConverter.GetBytes((ushort)Util.GetHexValue(seed)).CopyTo(Large, GetDaycareEXPOffset(2)); + protected override int ExternalEventData => 0x30A7; + #region eBerry private const int OFFSET_EBERRY = 0x30EC; private const int SIZE_EBERRY = 0x134; diff --git a/PKHeX.Core/Saves/SAV3RS.cs b/PKHeX.Core/Saves/SAV3RS.cs index 7bd3a7b50..5305eeb41 100644 --- a/PKHeX.Core/Saves/SAV3RS.cs +++ b/PKHeX.Core/Saves/SAV3RS.cs @@ -142,13 +142,7 @@ public int SwarmIndex public override string GetDaycareRNGSeed(int loc) => BitConverter.ToUInt16(Large, GetDaycareEXPOffset(2)).ToString("X4"); public override void SetDaycareRNGSeed(int loc, string seed) => BitConverter.GetBytes((ushort)Util.GetHexValue(seed)).CopyTo(Large, GetDaycareEXPOffset(2)); - private const int ExternalEventFlags = 0x312F; - - public bool HasReceivedWishmkrJirachi - { - get => GetFlag(ExternalEventFlags + 2, 0); - set => SetFlag(ExternalEventFlags + 2, 0, value); - } + protected override int ExternalEventData => 0x311B; #region eBerry private const int OFFSET_EBERRY = 0x3160; diff --git a/PKHeX.Core/Saves/Substructures/Gen3/IGen3Hoenn.cs b/PKHeX.Core/Saves/Substructures/Gen3/IGen3Hoenn.cs index d37924c81..103242742 100644 --- a/PKHeX.Core/Saves/Substructures/Gen3/IGen3Hoenn.cs +++ b/PKHeX.Core/Saves/Substructures/Gen3/IGen3Hoenn.cs @@ -12,7 +12,6 @@ public interface IGen3Hoenn PokeBlock3Case PokeBlocks { get; set; } DecorationInventory3 Decorations { get; set; } Swarm3 Swarm { get; set; } - bool HasReceivedWishmkrJirachi { get; set; } IReadOnlyList DefaultSwarms { get; } int SwarmIndex { get; set; }