From 79ede6a212eca9eef419fbb4e53fdbccd6f53880 Mon Sep 17 00:00:00 2001 From: Kurt Date: Mon, 9 Oct 2017 21:00:36 -0700 Subject: [PATCH] Add gen3 roamer r/w --- PKHeX.Core/Saves/Substructures/Roamer3.cs | 87 +++++++++++++++++++++++ 1 file changed, 87 insertions(+) create mode 100644 PKHeX.Core/Saves/Substructures/Roamer3.cs diff --git a/PKHeX.Core/Saves/Substructures/Roamer3.cs b/PKHeX.Core/Saves/Substructures/Roamer3.cs new file mode 100644 index 000000000..cbb9df870 --- /dev/null +++ b/PKHeX.Core/Saves/Substructures/Roamer3.cs @@ -0,0 +1,87 @@ +using System; + +namespace PKHeX.Core +{ + public class Roamer3 + { + private readonly SaveFile SAV; + private readonly int Offset; + public bool IsGlitched { get; } + + public Roamer3(SAV3 sav) + { + Offset = sav.GetBlockOffset(4); + if (GameVersion.FRLG.Contains(SAV.Version)) + Offset += 0x250; // 0x250 - FRLG + else + Offset += 0x35C; // 0x35C - RSE + IsGlitched = SAV.Version != GameVersion.E; + + SAV = sav; + } + + private uint IV32 + { + get => BitConverter.ToUInt32(SAV.Data, Offset); + set => SAV.SetData(BitConverter.GetBytes(value), Offset); + } + public uint PID + { + get => BitConverter.ToUInt32(SAV.Data, Offset + 4); + set => SAV.SetData(BitConverter.GetBytes(value), Offset + 4); + } + public int Species + { + get => SpeciesConverter.GetG4Species(BitConverter.ToInt16(SAV.Data, Offset + 8)); + set => SAV.SetData(BitConverter.GetBytes((ushort)SpeciesConverter.GetG3Species(value)), Offset + 8); + } + + // Derived Properties + private int IV_HP { get => (int)(IV32 >> 00) & 0x1F; set => IV32 = (uint)((IV32 & ~(0x1F << 00)) | (uint)((value > 31 ? 31 : value) << 00)); } + private int IV_ATK { get => (int)(IV32 >> 05) & 0x1F; set => IV32 = (uint)((IV32 & ~(0x1F << 05)) | (uint)((value > 31 ? 31 : value) << 05)); } + private int IV_DEF { get => (int)(IV32 >> 10) & 0x1F; set => IV32 = (uint)((IV32 & ~(0x1F << 10)) | (uint)((value > 31 ? 31 : value) << 10)); } + private int IV_SPE { get => (int)(IV32 >> 15) & 0x1F; set => IV32 = (uint)((IV32 & ~(0x1F << 15)) | (uint)((value > 31 ? 31 : value) << 15)); } + private int IV_SPA { get => (int)(IV32 >> 20) & 0x1F; set => IV32 = (uint)((IV32 & ~(0x1F << 20)) | (uint)((value > 31 ? 31 : value) << 20)); } + private int IV_SPD { get => (int)(IV32 >> 25) & 0x1F; set => IV32 = (uint)((IV32 & ~(0x1F << 25)) | (uint)((value > 31 ? 31 : value) << 25)); } + + /// + /// Roamer's IVs. + /// + public int[] IVs + { + get => new[] { IV_HP, IV_ATK, IV_DEF, IV_SPE, IV_SPA, IV_SPD }; + set + { + if (value?.Length != 6) return; + IV_HP = value[0]; IV_ATK = value[1]; IV_DEF = value[2]; + IV_SPE = value[3]; IV_SPA = value[4]; IV_SPD = value[5]; + } + } + + /// + /// Indicates if the Roamer is shiny with the 's Trainer Details. + /// + /// PID to check for + /// Indication if the PID is shiny for the trainer. + public bool IsShiny(uint pid) + { + var val = (ushort)(SAV.SID ^ SAV.TID ^ (pid >> 16) ^ pid); + return val < 8; + } + + /// + /// Gets the glitched Roamer IVs, where only 1 byte of IV data is loaded when encountered. + /// + public int[] IVsGlitch + { + get + { + var ivs = IV32; // store for restoration later + IV32 &= 0xFF; // only 1 byte is loaded to the encounter + var glitch = IVs; // get glitched IVs + IV32 = ivs; // restore unglitched IVs + return glitch; + } + } + } +}