diff --git a/PKHeX.Core/Saves/Substructures/Gen6/SuperTrainBlock.cs b/PKHeX.Core/Saves/Substructures/Gen6/SuperTrainBlock.cs index 491396bcf..2e9530761 100644 --- a/PKHeX.Core/Saves/Substructures/Gen6/SuperTrainBlock.cs +++ b/PKHeX.Core/Saves/Substructures/Gen6/SuperTrainBlock.cs @@ -8,29 +8,80 @@ public class SuperTrainBlock : SaveBlock public SuperTrainBlock(SAV6AO sav, int offset) : base(sav) => Offset = offset; // Structure: - // 8 bytes ??? (flags?) + // 6 bytes stage unlock flags + // 1 byte distribution stage unlock flags + // 1 byte counter (max value = 10) // float[48] recordScore1; // 0x08, 4byte/entry // float[48] recordScore2; // 0xC8, 4byte/entry // SS-F-G[48] recordHolder1; // 0x188, 4byte/entry // SS-F-G[48] recordHolder2; // 0x248, 4byte/entry - // byte[12] bags? // 0x308 - // u32 ??? // 0x314 + // byte[12] bags // 0x308 + // u32 tutorial tracker (max value = 6) // 0x314 // 0x318 total size // SS-F-G = u16 species, u8 form, u8 gender private const int MAX = 48; + private const int MAX_RELEASED = 32; + private const int MAX_DIST = 6; + private const int MAX_BAG = 12; - public byte[] Bytes8 + /// + /// Checks if a Regimen is unlocked. + /// + /// Index of regimen. + /// Is Unlocked + public bool GetIsRegimenUnlocked(int index) { - get => Data.Slice(Offset + 0, 8); - set - { - if (value.Length != 8) - throw new ArgumentException(nameof(value)); - value.CopyTo(Data, Offset + 0); - } + if ((uint)index >= MAX) + throw new ArgumentException(nameof(index)); + return SAV.GetFlag(Offset, index); + } + + /// + /// Sets a Regimen to the desired unlocked state. + /// + /// Index of regimen. + /// Is Unlocked + public void SetIsRegimenUnlocked(int index, bool value) + { + if ((uint)index >= MAX) + throw new ArgumentException(nameof(index)); + SAV.SetFlag(Offset, index, value); + } + + /// + /// Checks if a Distribution Regimen is unlocked. + /// + /// Index of regimen. + /// Is Unlocked + public bool GetIsDistributionUnlocked(int index) + { + if ((uint)index >= MAX_DIST) + throw new ArgumentException(nameof(index)); + return SAV.GetFlag(Offset + 6, index); + } + + /// + /// Sets a Distribution Regimen to the desired unlocked state. + /// + /// Index of regimen. + /// Is Unlocked + public void SetIsDistributionUnlocked(int index, bool value) + { + if ((uint)index >= MAX_DIST) + throw new ArgumentException(nameof(index)); + SAV.SetFlag(Offset + 6, index, value); + } + + /// + /// Counts something up to 10 (overall stages unlocked?) + /// + public byte Counter + { + get => Data[Offset + 7]; + set => Data[Offset + 7] = Math.Min((byte)10, value); } /// @@ -109,34 +160,75 @@ public SuperTrainingSpeciesRecord GetHolder2(int index) return new SuperTrainingSpeciesRecord(Data, Offset + 0x248 + (4 * index)); } - public byte[] Bags - { - get => Data.Slice(Offset + 0x308, 12); - set - { - if (value.Length != 12) - throw new ArgumentException(nameof(value)); - value.CopyTo(Data, Offset + 0x308); - } - } - + /// + /// Gets the bag from the desired . + /// + /// Bag index public byte GetBag(int index) { - if ((uint)index >= 12) + if ((uint)index >= MAX_BAG) throw new ArgumentException(nameof(index)); return Data[Offset + 0x308 + index]; } + /// + /// Sets a bag to the desired . + /// + /// Bag index + /// Bag ID public void SetBag(int index, byte value) { - if ((uint)index >= 12) + if ((uint)index >= MAX_BAG) throw new ArgumentException(nameof(index)); Data[Offset + 0x308 + index] = value; } - public void ClearBag(int index) => SetBag(index, 0); + /// + /// Gets the next open bag index. + /// + /// Bag index that is empty + public int GetOpenBagIndex() + { + for (int i = 0; i < MAX_BAG; i++) + { + if (GetBag(i) != 0) + return i; + } - public uint EndValue + return -1; + } + + /// + /// Adds a bag to the list of bags. + /// + /// Bag type + /// Bag was added or not + public bool AddBag(byte bag) + { + int index = GetOpenBagIndex(); + if (index < 0) + return false; + SetBag(index, bag); + return true; + } + + /// + /// Removes a bag from the list of bags. + /// + /// Bag index + public void RemoveBag(int index) + { + if ((uint)index >= MAX_BAG) + throw new ArgumentException(nameof(index)); + for (int i = index; i < MAX_BAG - 1; i++) + { + var next = GetBag(i + 1); + SetBag(i, next); + } + SetBag(MAX_BAG - 1, 0); + } + + public uint TutorialIndex { get => BitConverter.ToUInt32(Data, Offset + 0x314); set => BitConverter.GetBytes(value).CopyTo(Data, Offset + 0x314); @@ -167,6 +259,27 @@ public void ClearRecord2(int index) SetTime2(index, 0f); GetHolder2(index).Clear(); } + + /// + /// Unlocks all stages. + /// + /// Unlock all Distribution stages too. + public void UnlockAllStages(bool dist) + { + for (int i = 0; i < MAX_RELEASED; i++) + SetIsRegimenUnlocked(i, true); + + if (!dist) + return; + + for (int i = 0; i < MAX_DIST; i++) + SetIsDistributionUnlocked(i, true); + } + + /// + /// Clears all data in the block. + /// + public void ClearBlock() => Array.Clear(Data, Offset, 0x318); } public class SuperTrainingSpeciesRecord @@ -212,5 +325,16 @@ public byte Gender /// Wipes the record holder's pkm-related data. /// public void Clear() => Species = AltForm = Gender = 0; + + /// + /// Sets the data to match what is in the provided reference. + /// + /// Reference to load from. + public void LoadFrom(PKM pkm) + { + Species = (ushort)pkm.Species; + AltForm = (byte)pkm.AltForm; + Gender = (byte)pkm.Gender; + } } } \ No newline at end of file