diff --git a/PKHeX.Core/Saves/SAV8BS.cs b/PKHeX.Core/Saves/SAV8BS.cs index 2e7871bcf..43e53c96a 100644 --- a/PKHeX.Core/Saves/SAV8BS.cs +++ b/PKHeX.Core/Saves/SAV8BS.cs @@ -33,7 +33,7 @@ namespace PKHeX.Core Contest = new Contest8b(this, 0x79C08); // size: 0x720 Zukan = new Zukan8b(this, 0x7A328); // size: 0x30B8 - // 0x7D3E0 - Trainer Battle Data (bool,bool)[707] + BattleTrainer = new BattleTrainerStatus8b(this, 0x7D3E0); // size: 0x1618 // 0x7E9F8 - Menu selections (TopMenuItemTypeInt32, bool IsNew)[8], TopMenuItemTypeInt32 LastSelected // 0x7EA3C - _FIELDOBJ_SAVE Objects[1000] (sizeof (0x44, 17 int fields), total size 0x109A0 Records = new Record8b(this, 0x8F3DC); // size: 0x78 @@ -53,8 +53,8 @@ namespace PKHeX.Core // BoukenNote // TV_DATA // UgSaveData - // GMS_DATA - // PLAYER_NETWORK_DATA + // 0x9D03C - GMS_DATA // size: 0x31304 + // 0xCE340 - PLAYER_NETWORK_DATA // UnionSaveData // CON_PHOTO_LANG_DATA -- contest photo language data // ZUKAN_PERSONAL_RND_DATA @@ -188,6 +188,7 @@ namespace PKHeX.Core public Contest8b Contest { get; } // public Misc8 Misc { get; } public Zukan8b Zukan { get; } + public BattleTrainerStatus8b BattleTrainer { get; } public Record8b Records { get; } public BerryTreeGrowSave8b BerryTrees { get; } public PoffinSaveData8b Poffins { get; } diff --git a/PKHeX.Core/Saves/Substructures/Gen8/BS/BattleTrainerStatus8b.cs b/PKHeX.Core/Saves/Substructures/Gen8/BS/BattleTrainerStatus8b.cs new file mode 100644 index 000000000..59f06d9b7 --- /dev/null +++ b/PKHeX.Core/Saves/Substructures/Gen8/BS/BattleTrainerStatus8b.cs @@ -0,0 +1,54 @@ +using System; + +namespace PKHeX.Core +{ + /// + /// Defeated Status for all trainers (Dpr.Trainer.TrainerID) + /// + /// size: 0x1618 + public sealed class BattleTrainerStatus8b : SaveBlock + { + public BattleTrainerStatus8b(SAV8BS sav, int offset) : base(sav) => Offset = offset; + + // Structure: + // (bool IsWin, bool IsBattleSearcher)[707]; + private const int COUNT_TRAINER = 707; + private const int SIZE_TRAINER = 8; // bool,bool + + /// + /// Don't use this unless you've finished the post-game. + /// + public void DefeatAll() + { + for (int i = 0; i < COUNT_TRAINER; i++) + { + SetIsWin(i, true); + SetIsBattleSearcher(i, false); + } + } + + /// + /// Don't use this unless you've finished the post-game. + /// + public void RebattleAll() + { + for (int i = 0; i < COUNT_TRAINER; i++) + { + SetIsWin(i, true); + SetIsBattleSearcher(i, true); + } + } + + private int GetTrainerOffset(int trainer) + { + if ((uint)trainer >= COUNT_TRAINER) + throw new ArgumentOutOfRangeException(nameof(trainer)); + return Offset + (trainer * SIZE_TRAINER); + } + + public bool GetIsWin(int trainer) => BitConverter.ToUInt32(Data, GetTrainerOffset(trainer)) == 1; + public bool GetIsBattleSearcher(int trainer) => BitConverter.ToUInt32(Data, GetTrainerOffset(trainer) + 4) == 1; + public void SetIsWin(int trainer, bool value) => BitConverter.GetBytes(value ? 1u : 0u).CopyTo(Data, GetTrainerOffset(trainer)); + public void SetIsBattleSearcher(int trainer, bool value) => BitConverter.GetBytes(value ? 1u : 0u).CopyTo(Data, GetTrainerOffset(trainer) + 4); + } +}