diff --git a/PKHeX.Core/Saves/Access/ISaveBlock9Main.cs b/PKHeX.Core/Saves/Access/ISaveBlock9Main.cs index c703866a3..313353805 100644 --- a/PKHeX.Core/Saves/Access/ISaveBlock9Main.cs +++ b/PKHeX.Core/Saves/Access/ISaveBlock9Main.cs @@ -17,5 +17,6 @@ public interface ISaveBlock9Main Epoch1970Value LastSaved { get; } PlayerFashion9 PlayerFashion { get; } PlayerAppearance9 PlayerAppearance { get; } - RaidSpawnList9 Raid { get; } + RaidSpawnList9 RaidPaldea { get; } + RaidSpawnList9 RaidKitakami { get; } } diff --git a/PKHeX.Core/Saves/Access/SaveBlockAccessor9SV.cs b/PKHeX.Core/Saves/Access/SaveBlockAccessor9SV.cs index 754c4e52c..45b883c4e 100644 --- a/PKHeX.Core/Saves/Access/SaveBlockAccessor9SV.cs +++ b/PKHeX.Core/Saves/Access/SaveBlockAccessor9SV.cs @@ -23,7 +23,8 @@ public sealed class SaveBlockAccessor9SV : SCBlockAccessor, ISaveBlock9Main public Epoch1970Value LastSaved { get; } public PlayerFashion9 PlayerFashion { get; } public PlayerAppearance9 PlayerAppearance { get; } - public RaidSpawnList9 Raid { get; } + public RaidSpawnList9 RaidPaldea { get; } + public RaidSpawnList9 RaidKitakami { get; } public RaidSevenStar9 RaidSevenStar { get; } public Epoch1900Value EnrollmentDate { get; } @@ -36,13 +37,14 @@ public sealed class SaveBlockAccessor9SV : SCBlockAccessor, ISaveBlock9Main BoxLayout = new BoxLayout9(sav, GetBlock(KBoxLayout)); MyStatus = new MyStatus9(sav, GetBlock(KMyStatus)); Played = new PlayTime9(sav, GetBlock(KPlayTime)); - Zukan = new Zukan9(sav, GetBlock(KZukan)); + Zukan = new Zukan9(sav, GetBlock(KZukan), GetBlockSafe(KZukanT1)); Config = new ConfigSave9(sav, GetBlock(KConfig)); TeamIndexes = new TeamIndexes9(sav, GetBlock(KTeamIndexes)); LastSaved = new Epoch1970Value(GetBlock(KLastSaved)); PlayerFashion = new PlayerFashion9(sav, GetBlock(KCurrentClothing)); PlayerAppearance = new PlayerAppearance9(sav, GetBlock(KCurrentAppearance)); - Raid = new RaidSpawnList9(sav, GetBlock(KTeraRaids)); + RaidPaldea = new RaidSpawnList9(sav, GetBlock(KTeraRaidPaldea), RaidSpawnList9.RaidCountLegal_T0, true); + RaidKitakami = new RaidSpawnList9(sav, GetBlockSafe(KTeraRaidKitakami), RaidSpawnList9.RaidCountLegal_T1, false); RaidSevenStar = new RaidSevenStar9(sav, GetBlock(KSevenStarRaids)); EnrollmentDate = new Epoch1900Value(GetBlock(KEnrollmentDate)); } @@ -65,11 +67,12 @@ public sealed class SaveBlockAccessor9SV : SCBlockAccessor, ISaveBlock9Main private const uint KSessionLength = 0x1522C79C; // Milliseconds(?) elapsed private const uint KOverworld = 0x173304D8; // [0x158+7C][20] overworld pokemon private const uint KGimmighoul = 0x53DC955C; // ulong seed x2 (today and tomorrow); Gimmighoul struct (0x20): bool is_active, u64 hash, u64 seed, bool ??, bool first_time - private const uint KTeraRaids = 0xCAAC8800; + private const uint KTeraRaidPaldea = 0xCAAC8800; + private const uint KTeraRaidKitakami = 0x100B93DA; public const uint KBoxesUnlocked = 0x71825204; public const uint KFusedCalyrex = 0x916BCA9E; // Calyrex private const uint KZukan = 0x0DEAAEBD; - private const uint KZukanT1 = 0x8; // TODO TEAL MASK + private const uint KZukanT1 = 0xF5D7C0E2; private const uint KMysteryGift = 0x99E1625E; private const uint KDLCGifts = 0xA4B7A814; // Unix timestamp, 1 byte type of gift (0 = Pokémon, 1 = Item, 2 = Apparel) private const uint KLastSaved = 0x7495969E; // u64 time_t diff --git a/PKHeX.Core/Saves/SAV9SV.cs b/PKHeX.Core/Saves/SAV9SV.cs index acf6555f3..a352ec299 100644 --- a/PKHeX.Core/Saves/SAV9SV.cs +++ b/PKHeX.Core/Saves/SAV9SV.cs @@ -18,7 +18,7 @@ public sealed class SAV9SV : SaveFile, ISaveBlock9Main, ISCBlockArray, ISaveFile { AllBlocks = blocks; Blocks = new SaveBlockAccessor9SV(this); - SaveRevision = GetRevision(); + SaveRevision = Zukan.GetRevision(); Initialize(); } @@ -26,18 +26,11 @@ public sealed class SAV9SV : SaveFile, ISaveBlock9Main, ISCBlockArray, ISaveFile { AllBlocks = Meta9.GetBlankDataSV(); Blocks = new SaveBlockAccessor9SV(this); - SaveRevision = GetRevision(); + SaveRevision = Zukan.GetRevision(); Initialize(); ClearBoxes(); } - private int GetRevision() - { - if (!Blocks.HasBlock(0x08E1CF45)) - return 0; - return 1; - } - public override void CopyChangesFrom(SaveFile sav) { // Absorb changes from all blocks @@ -85,7 +78,8 @@ public sealed class SAV9SV : SaveFile, ISaveBlock9Main, ISCBlockArray, ISaveFile public Epoch1970Value LastSaved => Blocks.LastSaved; public PlayerFashion9 PlayerFashion => Blocks.PlayerFashion; public PlayerAppearance9 PlayerAppearance => Blocks.PlayerAppearance; - public RaidSpawnList9 Raid => Blocks.Raid; + public RaidSpawnList9 RaidPaldea => Blocks.RaidPaldea; + public RaidSpawnList9 RaidKitakami => Blocks.RaidKitakami; public RaidSevenStar9 RaidSevenStar => Blocks.RaidSevenStar; public Epoch1900Value EnrollmentDate => Blocks.EnrollmentDate; #endregion diff --git a/PKHeX.Core/Saves/Substructures/Gen9/RaidSpawnList9.cs b/PKHeX.Core/Saves/Substructures/Gen9/RaidSpawnList9.cs index 108d631a1..fba85be2f 100644 --- a/PKHeX.Core/Saves/Substructures/Gen9/RaidSpawnList9.cs +++ b/PKHeX.Core/Saves/Substructures/Gen9/RaidSpawnList9.cs @@ -9,16 +9,23 @@ public sealed class RaidSpawnList9 : SaveBlock { public readonly int CountAll; public readonly int CountUsed; + public const int RaidCountLegal_T0 = 72; + public const int RaidCountLegal_T1 = 100; + public readonly bool HasSeeds; + private readonly int OffsetRaidStart; - public RaidSpawnList9(SAV9SV sav, SCBlock block) : base(sav, block.Data) + public RaidSpawnList9(SAV9SV sav, SCBlock block, int countUsed, bool hasSeeds) : base(sav, block.Data) { - CountAll = block.Data.Length / TeraRaidDetail.SIZE; - CountUsed = RaidCountLegal_A0; + var length = block.Data.Length; + HasSeeds = hasSeeds; + OffsetRaidStart = hasSeeds ? 0x10 : 0; + CountAll = length == 0 ? 0 : (length - OffsetRaidStart) / TeraRaidDetail.SIZE; + CountUsed = countUsed; } - public const int RaidCountLegal_A0 = 72; + public TeraRaidDetail GetRaid(int entry) => new(Data.AsMemory(GetOffset(entry), TeraRaidDetail.SIZE)); - public TeraRaidDetail GetRaid(int entry) => new(Data, 0x10 + (entry * TeraRaidDetail.SIZE)); + private int GetOffset(int entry) => OffsetRaidStart + (entry * TeraRaidDetail.SIZE); public TeraRaidDetail[] GetAllRaids() { @@ -30,14 +37,14 @@ public sealed class RaidSpawnList9 : SaveBlock public ulong CurrentSeed { - get => ReadUInt64LittleEndian(Data.AsSpan(0x00)); - set => WriteUInt64LittleEndian(Data.AsSpan(0x00), value); + get => HasSeeds ? ReadUInt64LittleEndian(Data.AsSpan(0x00)) : 0; + set { if (HasSeeds) WriteUInt64LittleEndian(Data.AsSpan(0x00), value); } } public ulong TomorrowSeed { - get => ReadUInt64LittleEndian(Data.AsSpan(0x08)); - set => WriteUInt64LittleEndian(Data.AsSpan(0x08), value); + get => HasSeeds ? ReadUInt64LittleEndian(Data.AsSpan(0x08)) : 0; + set { if (HasSeeds) WriteUInt64LittleEndian(Data.AsSpan(0x08), value); } } /// @@ -66,14 +73,10 @@ public sealed class TeraRaidDetail { public const int SIZE = 0x20; - private readonly byte[] Data; - private readonly int Offset; + private readonly Memory Data; + private Span Span => Data.Span; - public TeraRaidDetail(byte[] data, int ofs) - { - Data = data; - Offset = ofs; - } + public TeraRaidDetail(Memory data) => Data = data; private const string General = nameof(General); private const string Misc = nameof(Misc); @@ -81,57 +84,57 @@ public sealed class TeraRaidDetail [Category(General), Description("Indicates if this entry has an active raid crystal.")] public bool IsEnabled { - get => ReadUInt32LittleEndian(Data.AsSpan(Offset + 0x00)) != 0; - set => WriteUInt32LittleEndian(Data.AsSpan(Offset + 0x00), value ? 1u : 0); + get => ReadUInt32LittleEndian(Span) != 0; + set => WriteUInt32LittleEndian(Span, value ? 1u : 0); } [Category(General), Description("Zone the raid crystal is located in.")] public uint AreaID { - get => ReadUInt32LittleEndian(Data.AsSpan(Offset + 0x04)); - set => WriteUInt32LittleEndian(Data.AsSpan(Offset + 0x04), value); + get => ReadUInt32LittleEndian(Span[0x04..]); + set => WriteUInt32LittleEndian(Span[0x04..], value); } [Category(Misc), Description("Indicates how the crystal is shown on the player's YMAP.")] public TeraRaidDisplayType DisplayType { - get => (TeraRaidDisplayType)ReadUInt32LittleEndian(Data.AsSpan(Offset + 0x08)); - set => WriteUInt32LittleEndian(Data.AsSpan(Offset + 0x08), (uint)value); + get => (TeraRaidDisplayType)ReadUInt32LittleEndian(Span[0x08..]); + set => WriteUInt32LittleEndian(Span[0x08..], (uint)value); } [Category(General), Description("Zone-specific overworld spawn point for the raid crystal.")] public uint SpawnPointID { - get => ReadUInt32LittleEndian(Data.AsSpan(Offset + 0x0C)); - set => WriteUInt32LittleEndian(Data.AsSpan(Offset + 0x0C), value); + get => ReadUInt32LittleEndian(Span[0x0C..]); + set => WriteUInt32LittleEndian(Span[0x0C..], value); } [Category(General), Description("RNG Seed (32bit) for fetching the raid data table and generating the raid."), TypeConverter(typeof(TypeConverterU32))] public uint Seed { - get => ReadUInt32LittleEndian(Data.AsSpan(Offset + 0x10)); - set => WriteUInt32LittleEndian(Data.AsSpan(Offset + 0x10), value); + get => ReadUInt32LittleEndian(Span[0x10..]); + set => WriteUInt32LittleEndian(Span[0x10..], value); } [Category(Misc), Description("Always zero.")] public uint Unused { - get => ReadUInt32LittleEndian(Data.AsSpan(Offset + 0x14)); - set => WriteUInt32LittleEndian(Data.AsSpan(Offset + 0x14), value); + get => ReadUInt32LittleEndian(Span[0x14..]); + set => WriteUInt32LittleEndian(Span[0x14..], value); } [Category(General), Description("Indicates the source of the raid encounter data and rewards.")] public TeraRaidContentType Content { - get => (TeraRaidContentType)ReadUInt32LittleEndian(Data.AsSpan(Offset + 0x18)); - set => WriteUInt32LittleEndian(Data.AsSpan(Offset + 0x18), (uint)value); + get => (TeraRaidContentType)ReadUInt32LittleEndian(Span[0x18..]); + set => WriteUInt32LittleEndian(Span[0x18..], (uint)value); } [Category(Misc), Description("Has player already collected the League Points for this raid?")] public bool IsClaimedLeaguePoints { - get => ReadUInt32LittleEndian(Data.AsSpan(Offset + 0x1C)) != 0; - set => WriteUInt32LittleEndian(Data.AsSpan(Offset + 0x1C), value ? 1u : 0); + get => ReadUInt32LittleEndian(Span[0x1C..]) != 0; + set => WriteUInt32LittleEndian(Span[0x1C..], value ? 1u : 0); } } diff --git a/PKHeX.Core/Saves/Substructures/PokeDex/Gen9/DexBlockMode9.cs b/PKHeX.Core/Saves/Substructures/PokeDex/Gen9/DexBlockMode9.cs new file mode 100644 index 000000000..1e1a4d000 --- /dev/null +++ b/PKHeX.Core/Saves/Substructures/PokeDex/Gen9/DexBlockMode9.cs @@ -0,0 +1,7 @@ +namespace PKHeX.Core; + +public enum DexBlockMode9 +{ + Paldea, + Kitakami, +} diff --git a/PKHeX.Core/Saves/Substructures/PokeDex/Gen9/PokeDexEntry9Kitakami.cs b/PKHeX.Core/Saves/Substructures/PokeDex/Gen9/PokeDexEntry9Kitakami.cs new file mode 100644 index 000000000..722445efa --- /dev/null +++ b/PKHeX.Core/Saves/Substructures/PokeDex/Gen9/PokeDexEntry9Kitakami.cs @@ -0,0 +1,229 @@ +using System; +using static System.Buffers.Binary.BinaryPrimitives; + +namespace PKHeX.Core; + +public readonly ref struct PokeDexEntry9Kitakami +{ + public const int SIZE = 0x20; + + private readonly Span Data; + public PokeDexEntry9Kitakami(Span data) => Data = data; + + /* Structure: 0x20 bytes + 0x00 u32 bitflags for forms obtained + 0x04 u32 bitflags for forms seen + 0x08 u32 bitflags for forms heard of (book visible but empty for adjacent mons) + + 0x0C u32 bitflags for previous forms seen, new if different from 0x4 and copies 0x8 + 0x10 u16 language bitflags + + 0x12 u8 flags for genders seen, can be on mons you don't have + 01 = male seen + 02 = female seen + 04 = genderless seen + 0x13 u8 bitflags for shiny seen, default always has bit 1 + 01 = regular model available + 02 = shiny model available (seen) + + 0x14 u8 form displayed (Paldea dex) + 0x15 u8 gender displayed (0 = male, 1 = female, 2 = genderless) (Paldea dex) + 0x16 u8 bool for shiny displayed (Paldea dex) + 0x17 alignment + + 0x18 u8 form displayed (Kitakami dex) + 0x19 u8 gender displayed (0 = male, 1 = female, 2 = genderless) (Kitakami dex) + 0x1A u8 bool for shiny displayed (Kitakami dex) + 0x1B alignment + + 0x1C u8 form displayed (Blueberry dex) + 0x1D u8 gender displayed (0 = male, 1 = female, 2 = genderless) (Blueberry dex) + 0x1E u8 bool for shiny displayed (Blueberry dex) + 0x1F alignment + */ + + private uint FlagsFormObtained { get => ReadUInt32LittleEndian(Data); set => WriteUInt32LittleEndian(Data, value); } + private uint FlagsFormSeen { get => ReadUInt32LittleEndian(Data[0x04..]); set => WriteUInt32LittleEndian(Data[0x04..], value); } + private uint FlagsFormHeard { get => ReadUInt32LittleEndian(Data[0x08..]); set => WriteUInt32LittleEndian(Data[0x08..], value); } + private uint FlagsFormChecked { get => ReadUInt32LittleEndian(Data[0x0C..]); set => WriteUInt32LittleEndian(Data[0x0C..], value); } + + private ushort FlagsLanguage { get => ReadUInt16LittleEndian(Data[0x10..]); set => WriteUInt16LittleEndian(Data[0x10..], value); } + public ref byte FlagsGenderSeen => ref Data[0x12]; + public ref byte FlagsShinySeen => ref Data[0x13]; // bit0 = regular, bit1 = shiny + + public ref byte DisplayedPaldeaForm => ref Data[0x14]; + public ref byte DisplayedPaldeaGender => ref Data[0x15]; + public ref byte DisplayedPaldeaShiny => ref Data[0x16]; + + public ref byte DisplayedKitakamiForm => ref Data[0x18]; + public ref byte DisplayedKitakamiGender => ref Data[0x19]; + public ref byte DisplayedKitakamiShiny => ref Data[0x1A]; + + public ref byte DisplayedBlueberryForm => ref Data[0x1C]; + public ref byte DisplayedBlueberryGender => ref Data[0x1D]; + public ref byte DisplayedBlueberryShiny => ref Data[0x1E]; + + public bool IsSeen => FlagsFormSeen != 0; + public bool IsCaught => FlagsFormObtained != 0; + public bool IsKnown => FlagsFormHeard != 0; + + private static bool GetFlag(ref byte flags, int bit) => (flags & (1 << bit)) != 0; + + private static void SetFlag(ref byte flags, int bit, bool value) + { + if (value) + flags |= (byte)(1 << bit); + else + flags &= (byte)~(1 << bit); + } + + public bool GetObtainedForm(byte form) => (FlagsFormObtained & (1u << form)) != 0; + + public void SetObtainedForm(byte form, bool value) + { + if (value) + FlagsFormObtained |= 1u << form; + else + FlagsFormObtained &= ~(1u << form); + } + + public bool GetSeenForm(byte form) => (FlagsFormSeen & (1u << form)) != 0; + + public void SetSeenForm(byte form, bool value) + { + if (value) + FlagsFormSeen |= 1u << form; + else + FlagsFormSeen &= ~(1u << form); + } + + public bool GetHeardForm(byte form) => (FlagsFormHeard & (1u << form)) != 0; + + public void SetHeardForm(byte form, bool value) + { + if (value) + FlagsFormHeard |= 1u << form; + else + FlagsFormHeard &= ~(1u << form); + } + + public bool GetCheckedForm(byte form) => (FlagsFormChecked & (1u << form)) != 0; + + public void SetCheckedForm(byte form, bool value) + { + if (value) + FlagsFormChecked |= 1u << form; + else + FlagsFormChecked &= ~(1u << form); + } + + public bool GetIsAnyFormNotViewedShowNew() => FlagsFormChecked != FlagsFormHeard; + + public static int GetDexLangFlag(int lang) => lang switch + { + > 10 or 6 or <= 0 => 0, // invalid language + // skip over langID 0 (unused) => [0-8] + // skip over langID 6 (unused) + >= 7 => lang - 2, + _ => lang - 1, + }; + + private static int GetLanguageBitMask(int langIndex) => 1 << GetDexLangFlag(langIndex); + + public bool GetLanguageFlag(int langIndex) => (FlagsLanguage & GetLanguageBitMask(langIndex)) != 0; + + public void SetLanguageFlag(int langIndex, bool value) + { + var mask = GetLanguageBitMask(langIndex); + if (value) + FlagsLanguage |= (ushort)mask; + else + FlagsLanguage &= (ushort)~mask; + } + + public bool GetIsGenderSeen(int gender) => GetFlag(ref FlagsGenderSeen, gender); + public void SetIsGenderSeen(int gender, bool value) => SetFlag(ref FlagsGenderSeen, gender, value); + + public bool GetIsModelSeen(bool shiny) => GetFlag(ref FlagsShinySeen, shiny ? 1 : 0); + public void SetIsModelSeen(bool shiny, bool value) => SetFlag(ref FlagsShinySeen, shiny ? 1 : 0, value); + + public void Clear() + { + Data.Clear(); + this.FlagsShinySeen = 1; + } + + public void SetAllLanguageFlags(ushort value = 0b11_1111_1111) => FlagsLanguage = value; // 10 languages + + public void ClearCaught() + { + FlagsFormObtained = 0; + FlagsLanguage = 0; + ClearLocalPaldea(); + ClearLocalKitakami(); + ClearLocalBlueberry(); + } + + private void ClearLocalPaldea() => SetLocalPaldea(0, 0, 0); + private void ClearLocalKitakami() => SetLocalKitakami(0, 0, 0); + private void ClearLocalBlueberry() => SetLocalBlueberry(0, 0, 0); + + public void RegisterFormFlags(byte form, bool value = true, bool hasChecked = false) + { + SetObtainedForm(form, value); + SetSeenForm(form, value); + SetHeardForm(form, value); + SetCheckedForm(form, value && hasChecked); + } + + public void SetLocalStates(PersonalInfo9SV pi, byte form, byte gender, bool shiny) + { + if (this.DisplayedPaldeaForm == 0 && pi.DexPaldea != 0) + SetLocalPaldea(form, gender, shiny ? (byte)1 : (byte)0); + if (this.DisplayedKitakamiForm == 0 && pi.DexKitakami != 0) + SetLocalKitakami(form, gender, shiny ? (byte)1 : (byte)0); + if (this.DisplayedBlueberryForm == 0 && pi.DexBlueberry != 0) + SetLocalBlueberry(form, gender, shiny ? (byte)1 : (byte)0); + } + + public void SetLocalPaldea(byte form, byte gender, byte sv) + { + this.DisplayedPaldeaForm = form; + this.DisplayedPaldeaGender = gender; + this.DisplayedPaldeaShiny = sv; + } + + public void SetLocalKitakami(byte form, byte gender, byte sv) + { + this.DisplayedKitakamiForm = form; + this.DisplayedKitakamiGender = gender; + this.DisplayedKitakamiShiny = sv; + } + + public void SetLocalBlueberry(byte form, byte gender, byte sv) + { + this.DisplayedBlueberryForm = form; + this.DisplayedBlueberryGender = gender; + this.DisplayedBlueberryShiny = sv; + } + + public void ClearSeen(byte form) + { + SetSeenForm(form, false); + if (FlagsFormSeen == 0) + { + // Shouldn't have anything if no forms are seen + Clear(); + return; + } + SetObtainedForm(form, false); + SetHeardForm(form, false); + SetCheckedForm(form, false); + if (DisplayedPaldeaForm == form) + ClearLocalPaldea(); + if (DisplayedKitakamiForm == form) + ClearLocalKitakami(); + if (DisplayedBlueberryForm == form) + ClearLocalBlueberry(); + } +} diff --git a/PKHeX.Core/Saves/Substructures/PokeDex/PokeDexEntry9SV.cs b/PKHeX.Core/Saves/Substructures/PokeDex/Gen9/PokeDexEntry9Paldea.cs similarity index 80% rename from PKHeX.Core/Saves/Substructures/PokeDex/PokeDexEntry9SV.cs rename to PKHeX.Core/Saves/Substructures/PokeDex/Gen9/PokeDexEntry9Paldea.cs index b1400404a..aa777d374 100644 --- a/PKHeX.Core/Saves/Substructures/PokeDex/PokeDexEntry9SV.cs +++ b/PKHeX.Core/Saves/Substructures/PokeDex/Gen9/PokeDexEntry9Paldea.cs @@ -1,14 +1,14 @@ using System; -using System.Buffers.Binary; +using static System.Buffers.Binary.BinaryPrimitives; namespace PKHeX.Core; -public readonly ref struct PokeDexEntry9SV +public readonly ref struct PokeDexEntry9Paldea { public const int SIZE = 0x18; private readonly Span Data; - public PokeDexEntry9SV(Span data) => Data = data; + public PokeDexEntry9Paldea(Span data) => Data = data; public void Clear() => Data.Clear(); /* Structure: 0x18 bytes @@ -30,22 +30,22 @@ public readonly ref struct PokeDexEntry9SV 0x17 u8 - unused alignment */ - public uint GetState() => BinaryPrimitives.ReadUInt32LittleEndian(Data); - private uint FlagsFormSeen { get => BinaryPrimitives.ReadUInt32LittleEndian(Data[0x04..]); set => BinaryPrimitives.WriteUInt32LittleEndian(Data[0x04..], value); } - private ushort FlagsGenderSeen { get => BinaryPrimitives.ReadUInt16LittleEndian(Data[0x08..]); set => BinaryPrimitives.WriteUInt16LittleEndian(Data[0x08..], value); } - private ushort FlagsLanguage { get => BinaryPrimitives.ReadUInt16LittleEndian(Data[0x0A..]); set => BinaryPrimitives.WriteUInt16LittleEndian(Data[0x0A..], value); } + public uint GetState() => ReadUInt32LittleEndian(Data); + private uint FlagsFormSeen { get => ReadUInt32LittleEndian(Data[0x04..]); set => WriteUInt32LittleEndian(Data[0x04..], value); } + private ushort FlagsGenderSeen { get => ReadUInt16LittleEndian(Data[0x08..]); set => WriteUInt16LittleEndian(Data[0x08..], value); } + private ushort FlagsLanguage { get => ReadUInt16LittleEndian(Data[0x0A..]); set => WriteUInt16LittleEndian(Data[0x0A..], value); } public bool GetSeenIsShiny() => Data[0x0C] != 0; public bool GetDisplayIsNew() => Data[0x0D] != 0; public byte GetUnused0E() => Data[0x0E]; public byte GetUnused0F() => Data[0x0F]; - private uint DisplayFormIndex { get => BinaryPrimitives.ReadUInt32LittleEndian(Data[0x10..]); set => BinaryPrimitives.WriteUInt32LittleEndian(Data[0x10..], value); } + private uint DisplayFormIndex { get => ReadUInt32LittleEndian(Data[0x10..]); set => WriteUInt32LittleEndian(Data[0x10..], value); } private byte DisplayGender { get => Data[0x14]; set => Data[0x14] = value; } public bool GetDisplayIsShiny() => Data[0x15] != 0; public bool GetDisplayGenderIsDifferent() => Data[0x16] != 0; public byte GetUnused17() => Data[0x17]; - public void SetState(uint value) => BinaryPrimitives.WriteUInt32LittleEndian(Data, value); + public void SetState(uint value) => WriteUInt32LittleEndian(Data, value); public void SetSeenIsShiny(bool value = true) => Data[0x0C] = value ? (byte)1 : (byte)0; public void SetDisplayIsNew(bool value = true) => Data[0x0D] = value ? (byte)1 : (byte)0; public void SetUnused0E(byte value) => Data[0x0E] = value; diff --git a/PKHeX.Core/Saves/Substructures/PokeDex/Gen9/Zukan9.cs b/PKHeX.Core/Saves/Substructures/PokeDex/Gen9/Zukan9.cs new file mode 100644 index 000000000..b1085f4a6 --- /dev/null +++ b/PKHeX.Core/Saves/Substructures/PokeDex/Gen9/Zukan9.cs @@ -0,0 +1,196 @@ +using System; +using static PKHeX.Core.DexBlockMode9; + +namespace PKHeX.Core; + +/// +/// Pokédex structure used for . +/// > +public sealed class Zukan9 : ZukanBase +{ + public readonly Zukan9Paldea DexPaldea; + public readonly Zukan9Kitakami DexKitakami; + private readonly DexBlockMode9 Mode; + + public Zukan9(SAV9SV sav, SCBlock paldea, SCBlock kitakami) : base(sav, 0) + { + DexPaldea = new(sav, paldea); + DexKitakami = new(sav, kitakami); + + // Starting in 2.0.1, the developers have dummied out the old Paldea Pokédex block and exclusively use the new Kitakami block. + if (kitakami.Data.Length != 0) + Mode = Kitakami; + else + Mode = Paldea; + } + + /// + /// Checks how much DLC patches have been installed by detecting if DLC blocks are present. + /// + public int GetRevision() => (int)Mode; + + public override bool GetSeen(ushort species) => Mode switch + { + Paldea => DexPaldea.GetSeen(species), + Kitakami => DexKitakami.GetSeen(species), + _ => false, + }; + + public override bool GetCaught(ushort species) => Mode switch + { + Paldea => DexPaldea.GetCaught(species), + Kitakami => DexKitakami.GetCaught(species), + _ => false, + }; + + #region Inherited + public override void SetDex(PKM pk) + { + if (pk.IsEgg) // do not add + return; + var species = pk.Species; + var form = pk.Form; + var pt = SAV.Personal; + if (!pt.IsPresentInGame(species, form)) + return; + + // Don't register bad species-form data for DLC-less saves. + var pi = pt.GetFormEntry(species, form); + if (SAV.SaveRevision == 0 && pi.DexGroup > 1) + return; + if (SAV.SaveRevision == 1 && pi.DexGroup > 2) + return; + + Register(pk, species, form, Mode); + } + + private void Register(PKM pk, ushort species, byte form, DexBlockMode9 dex) + { + if (dex == Paldea) + DexPaldea.Register(pk, species, form); + else if (dex == Kitakami) + DexKitakami.Register(pk, species, form); + else + throw new ArgumentOutOfRangeException(nameof(dex), dex, null); + } + + public (byte Group, ushort Index) GetDexIndex(ushort species) + { + var pt = SAV.Personal; + // For each form including form 0, check the dex index. + var pi = pt.GetFormEntry(species, 0); + for (byte f = 0; f <= pi.FormCount; f++) + { + pi = pt.GetFormEntry(species, f); + if (pi.DexPaldea != 0) + return (1, pi.DexPaldea); + if (pi.DexKitakami != 0) + return (2, pi.DexKitakami); + if (pi.DexBlueberry != 0) + return (3, pi.DexBlueberry); + } + return default; + } + + public override void SeenNone() + { + DexPaldea.SeenNone(); + DexKitakami.SeenNone(); + } + + public override void CaughtNone() + { + DexPaldea.CaughtNone(); + DexKitakami.CaughtNone(); + } + + public override void SeenAll(bool shinyToo = false) + { + SetAllSeen(true, shinyToo); + } + + private void SeenAll(ushort species, byte formCount, bool value = true, bool shinyToo = false) + { + var dex = Mode; + if (dex == Paldea) + DexPaldea.SeenAll(species, formCount, value, shinyToo); + else if (dex == Kitakami) + DexKitakami.SeenAll(species, formCount, value, shinyToo); + else + throw new ArgumentOutOfRangeException(nameof(dex), dex, null); + } + + public override void CompleteDex(bool shinyToo = false) + { + for (ushort species = 0; species <= SAV.MaxSpeciesID; species++) + { + if (!SAV.Personal.IsSpeciesInGame(species)) + continue; + if (GetDexIndex(species).Index == 0) + continue; + SetDexEntryAll(species, shinyToo); + } + } + + public override void CaughtAll(bool shinyToo = false) + { + SeenAll(shinyToo); + for (ushort species = 0; species <= SAV.MaxSpeciesID; species++) + { + if (!SAV.Personal.IsSpeciesInGame(species)) + continue; + if (GetDexIndex(species).Index == 0) + continue; + SetAllCaught(species, true, shinyToo); + } + } + + private void SetAllCaught(ushort species, bool value = true, bool shinyToo = false) + { + var dex = Mode; + if (dex == Paldea) + DexPaldea.SetAllCaught(species, value, shinyToo); + else if (dex == Kitakami) + DexKitakami.SetAllCaught(species, value, shinyToo); + else + throw new ArgumentOutOfRangeException(nameof(dex), dex, null); + } + + public override void SetAllSeen(bool value = true, bool shinyToo = false) + { + var pt = SAV.Personal; + for (ushort species = 0; species < SAV.MaxSpeciesID; species++) + { + if (value && GetDexIndex(species).Index == 0) + continue; + var pi = pt[species]; + SeenAll(species, pi.FormCount, value, shinyToo); + } + } + + private void SetAllSeen(ushort species, bool value = true, bool shinyToo = false) + { + var pi = SAV.Personal[species]; + var fc = pi.FormCount; + SeenAll(species, fc, value, shinyToo); + } + + public override void SetDexEntryAll(ushort species, bool shinyToo = false) + { + SetAllSeen(species, true, shinyToo); + SetAllCaught(species, true, shinyToo); + } + + public override void ClearDexEntryAll(ushort species) + { + var dex = Mode; + if (dex == Paldea) + DexPaldea.ClearDexEntryAll(species); + else if (dex == Kitakami) + DexKitakami.ClearDexEntryAll(species); + else + throw new ArgumentOutOfRangeException(nameof(dex), dex, null); + } + + #endregion +} diff --git a/PKHeX.Core/Saves/Substructures/PokeDex/Gen9/Zukan9Kitakami.cs b/PKHeX.Core/Saves/Substructures/PokeDex/Gen9/Zukan9Kitakami.cs new file mode 100644 index 000000000..fe6721da9 --- /dev/null +++ b/PKHeX.Core/Saves/Substructures/PokeDex/Gen9/Zukan9Kitakami.cs @@ -0,0 +1,261 @@ +using System; + +namespace PKHeX.Core; + +/// +/// Pokédex structure used for . +/// > +public sealed class Zukan9Kitakami : ZukanBase +{ + private readonly SCBlock Block; + + public Zukan9Kitakami(SAV9SV sav, SCBlock block) : base(sav, 0) => Block = block; + + public PokeDexEntry9Kitakami Get(ushort species) + { + if (species > SAV.MaxSpeciesID) + throw new ArgumentOutOfRangeException(nameof(species), species, null); + + const int size = PokeDexEntry9Kitakami.SIZE; + var internalSpecies = SpeciesConverter.GetInternal9(species); + var span = Block.Data.AsSpan(internalSpecies * size, size); + return new PokeDexEntry9Kitakami(span); + } + + public override bool GetSeen(ushort species) => Get(species).IsSeen; + public override bool GetCaught(ushort species) => Get(species).IsCaught; + + #region Inherited + public override void SetDex(PKM pk) + { + if (pk.IsEgg) // do not add + return; + var species = pk.Species; + var form = pk.Form; + var pt = SAV.Personal; + if (!pt.IsPresentInGame(species, form)) + return; + + // Don't register bad species-form data for DLC-less saves. + var pi = pt.GetFormEntry(species, form); + if (SAV.SaveRevision == 0 && pi.DexGroup > 1) + return; + if (SAV.SaveRevision == 1 && pi.DexGroup > 2) + return; + + Register(pk, species, form); + } + + public void UpdateAdjacent(ushort species) + { + var (group, index) = GetDexIndex(species); + if (index == 0) + return; + + MarkAsKnown1(group, index - 1); + MarkAsKnown1(group, index + 1); + } + + private void MarkAsKnown1(byte group, int index, byte form = 0) + { + if (group == 1 && index <= 9) // Don't set adjacent for starters. Hide their evolutions! + return; + + var species = GetSpecies(group, index); + if (species == 0) + return; + var entry = Get(species); + if (!entry.IsKnown) + entry.SetHeardForm(form, true); + } + + private ushort GetSpecies(byte group, int index) + { + for (ushort species = 0; species <= SAV.MaxSpeciesID; species++) + { + var (g, i) = GetDexIndex(species); + if (g == group && i == index) + return species; + } + return 0; + } + + public (byte Group, ushort Index) GetDexIndex(ushort species) + { + var pt = SAV.Personal; + // For each form including form 0, check the dex index. + var pi = pt.GetFormEntry(species, 0); + for (byte f = 0; f <= pi.FormCount; f++) + { + pi = pt.GetFormEntry(species, f); + if (pi.DexPaldea != 0) + return (1, pi.DexPaldea); + if (pi.DexKitakami != 0) + return (2, pi.DexKitakami); + if (pi.DexBlueberry != 0) + return (3, pi.DexBlueberry); + } + return (0, 0); + } + + public override void SeenNone() + { + Array.Clear(Block.Data, 0, Block.Data.Length); + } + + public override void CaughtNone() + { + for (ushort i = 0; i <= SAV.MaxSpeciesID; i++) + { + var entry = Get(i); + entry.ClearCaught(); + } + } + + public override void SeenAll(bool shinyToo = false) + { + SetAllSeen(true, shinyToo); + } + + public void SeenAll(ushort species, byte formCount, bool value = true, bool shinyToo = false) + { + // Wipe existing gender flags. + var entry = Get(species); + entry.FlagsGenderSeen = 0; + entry.FlagsShinySeen = (byte)(value ? shinyToo ? 3 : 1 : 0); + + var pt = SAV.Personal; + for (byte form = 0; form < formCount; form++) + { + var pi = pt.GetFormEntry(species, form); + bool actual = value && pi.IsPresentInGame; + SetSeen(entry, pi, form, actual, shinyToo && value); + } + } + + private static void SetSeen(PokeDexEntry9Kitakami entry, PersonalInfo9SV pi, byte form, bool seen, bool shinyToo) + { + if (!seen) + { + entry.ClearSeen(form); + return; + } + + entry.SetSeenForm(form, true); + entry.SetHeardForm(form, true); + + if (pi.IsDualGender) + { + entry.FlagsGenderSeen = 3; + } + else + { + var displayGender = (byte)pi.FixedGender(); + entry.SetIsGenderSeen(displayGender, true); + } + + if (shinyToo) + entry.SetIsModelSeen(true, true); + } + + public override void CompleteDex(bool shinyToo = false) + { + for (ushort species = 0; species <= SAV.MaxSpeciesID; species++) + { + if (!SAV.Personal.IsSpeciesInGame(species)) + continue; + if (GetDexIndex(species).Index == 0) + continue; + SetDexEntryAll(species, shinyToo); + } + } + + public override void CaughtAll(bool shinyToo = false) + { + SeenAll(shinyToo); + for (ushort species = 0; species <= SAV.MaxSpeciesID; species++) + { + if (!SAV.Personal.IsSpeciesInGame(species)) + continue; + if (GetDexIndex(species).Index == 0) + continue; + SetAllCaught(species, true, shinyToo); + } + } + + public void SetAllCaught(ushort species, bool value = true, bool shinyToo = false) + { + var entry = Get(species); + if (value) + { + var pi = SAV.Personal[species]; + if (shinyToo) + entry.SetIsModelSeen(true, true); + + for (byte form = 0; form < pi.FormCount; form++) + { + if (!SAV.Personal.IsPresentInGame(species, form)) + continue; + SetSeen(entry, pi, form, true, shinyToo); + entry.SetObtainedForm(form, true); + entry.SetLocalStates(pi, form, (byte)pi.RandomGender(), shinyToo); + } + entry.SetAllLanguageFlags(); + } + else + { + entry.SetAllLanguageFlags(0); + } + } + + public override void SetAllSeen(bool value = true, bool shinyToo = false) + { + var pt = SAV.Personal; + for (ushort species = 0; species < SAV.MaxSpeciesID; species++) + { + if (value && GetDexIndex(species).Index == 0) + continue; + var pi = pt[species]; + SeenAll(species, pi.FormCount, value, shinyToo); + } + } + + private void SetAllSeen(ushort species, bool value = true, bool shinyToo = false) + { + var pi = SAV.Personal[species]; + var fc = pi.FormCount; + SeenAll(species, fc, value, shinyToo); + } + + public override void SetDexEntryAll(ushort species, bool shinyToo = false) + { + SetAllSeen(species, true, shinyToo); + SetAllCaught(species, true, shinyToo); + } + + public override void ClearDexEntryAll(ushort species) => Get(species).Clear(); + + #endregion + + public void Register(PKM pk, ushort species, byte form) + { + var pi = SAV.Personal.GetFormEntry(species, form); + if (!pi.IsPresentInGame) + return; + + var entry = Get(species); + bool isShiny = pk.IsShiny; + + SetSeen(entry, pi, form, true, isShiny); + entry.SetObtainedForm(form, true); + entry.SetLocalStates(pi, form, (byte)pi.RandomGender(), isShiny); + if (isShiny) + entry.SetIsModelSeen(true, true); + entry.SetLanguageFlag(pk.Language, true); + if (SAV.Language != pk.Language) + entry.SetLanguageFlag(SAV.Language, true); + + // Update adjacent entries if not seen. + UpdateAdjacent(species); + } +} diff --git a/PKHeX.Core/Saves/Substructures/PokeDex/Zukan9.cs b/PKHeX.Core/Saves/Substructures/PokeDex/Gen9/Zukan9Paldea.cs similarity index 87% rename from PKHeX.Core/Saves/Substructures/PokeDex/Zukan9.cs rename to PKHeX.Core/Saves/Substructures/PokeDex/Gen9/Zukan9Paldea.cs index 3c51bc74b..4587e5e32 100644 --- a/PKHeX.Core/Saves/Substructures/PokeDex/Zukan9.cs +++ b/PKHeX.Core/Saves/Substructures/PokeDex/Gen9/Zukan9Paldea.cs @@ -5,25 +5,21 @@ namespace PKHeX.Core; /// /// Pokédex structure used for . /// > -public sealed class Zukan9 : ZukanBase +public sealed class Zukan9Paldea : ZukanBase { - private readonly SCBlock Paldea; + private readonly SCBlock Block; - public Zukan9(SAV9SV sav, SCBlock paldea) : base(sav, 0) - { - Paldea = paldea; - } + public Zukan9Paldea(SAV9SV sav, SCBlock block) : base(sav, 0) => Block = block; - private const int EntrySize = PokeDexEntry9SV.SIZE; - - public PokeDexEntry9SV Get(ushort species) + public PokeDexEntry9Paldea Get(ushort species) { if (species > SAV.MaxSpeciesID) throw new ArgumentOutOfRangeException(nameof(species), species, null); + const int size = PokeDexEntry9Paldea.SIZE; var internalSpecies = SpeciesConverter.GetInternal9(species); - var span = Paldea.Data.AsSpan(internalSpecies * EntrySize, EntrySize); - return new PokeDexEntry9SV(span); + var span = Block.Data.AsSpan(internalSpecies * size, size); + return new PokeDexEntry9Paldea(span); } public override bool GetSeen(ushort species) => Get(species).IsSeen; @@ -34,7 +30,7 @@ public sealed class Zukan9 : ZukanBase public bool GetIsLanguageObtained(ushort species, int language) { - int langIndex = PokeDexEntry9SV.GetDexLangFlag(language); + int langIndex = PokeDexEntry9Paldea.GetDexLangFlag(language); if (langIndex < 0) return false; @@ -43,7 +39,7 @@ public sealed class Zukan9 : ZukanBase public void SetIsLanguageObtained(ushort species, int language, bool value = true) { - int langIndex = PokeDexEntry9SV.GetDexLangFlag(language); + int langIndex = PokeDexEntry9Paldea.GetDexLangFlag(language); if (langIndex < 0) return; @@ -76,26 +72,7 @@ public sealed class Zukan9 : ZukanBase if (SAV.SaveRevision == 1 && pi.DexGroup > 2) return; - var entry = Get(species); - if (!entry.IsKnown) - entry.SetDisplayIsNew(); - - entry.SetCaught(true); - entry.SetIsGenderSeen(pk.Gender, true); - entry.SetIsFormSeen(form, true); - entry.SetDisplayForm(form); - entry.SetDisplayGender(pk.Gender); - if (pk.IsShiny) - { - entry.SetDisplayIsShiny(); - entry.SetSeenIsShiny(); - } - entry.SetLanguageFlag(pk.Language, true); - if (SAV.Language != pk.Language) - entry.SetLanguageFlag(SAV.Language, true); - - // Update adjacent entries if not seen. - UpdateAdjacent(species); + Register(pk, species, form); } public void UpdateAdjacent(ushort species) @@ -142,17 +119,13 @@ public sealed class Zukan9 : ZukanBase pi = pt.GetFormEntry(species, f); if (pi.DexPaldea != 0) return (1, pi.DexPaldea); - if (pi.DexKitakami != 0) - return (2, pi.DexKitakami); - if (pi.DexBlueberry != 0) - return (3, pi.DexBlueberry); } - return (0, 0); + return default; } public override void SeenNone() { - Array.Clear(Paldea.Data, 0, Paldea.Data.Length); + Array.Clear(Block.Data, 0, Block.Data.Length); } public override void CaughtNone() @@ -169,7 +142,7 @@ public sealed class Zukan9 : ZukanBase SetAllSeen(true, shinyToo); } - private void SeenAll(ushort species, byte formCount, bool value = true, bool shinyToo = false) + public void SeenAll(ushort species, byte formCount, bool value = true, bool shinyToo = false) { // Wipe existing gender flags. var entry = Get(species); @@ -189,14 +162,14 @@ public sealed class Zukan9 : ZukanBase } } - private static void SetIsFormSeen(PokeDexEntry9SV entry, IGenderDetail pi, byte form, bool seenForm) + private static void SetIsFormSeen(PokeDexEntry9Paldea entry, IGenderDetail pi, byte form, bool seenForm) { entry.SetIsFormSeen(form, seenForm); if (seenForm) SetIsFormSeenGender(entry, pi); } - private static void SetIsFormSeenGender(PokeDexEntry9SV entry, IGenderDetail pi) + private static void SetIsFormSeenGender(PokeDexEntry9Paldea entry, IGenderDetail pi) { if (pi.IsDualGender) { @@ -235,7 +208,7 @@ public sealed class Zukan9 : ZukanBase } } - private void SetAllCaught(ushort species, bool value = true, bool shinyToo = false) + public void SetAllCaught(ushort species, bool value = true, bool shinyToo = false) { SetCaught(species, value); for (int i = 1; i <= (int)LanguageID.ChineseT; i++) @@ -284,4 +257,28 @@ public sealed class Zukan9 : ZukanBase public override void ClearDexEntryAll(ushort species) => Get(species).Clear(); #endregion + + public void Register(PKM pk, ushort species, byte form) + { + var entry = Get(species); + if (!entry.IsKnown) + entry.SetDisplayIsNew(); + + entry.SetCaught(true); + entry.SetIsGenderSeen(pk.Gender, true); + entry.SetIsFormSeen(form, true); + entry.SetDisplayForm(form); + entry.SetDisplayGender(pk.Gender); + if (pk.IsShiny) + { + entry.SetDisplayIsShiny(); + entry.SetSeenIsShiny(); + } + entry.SetLanguageFlag(pk.Language, true); + if (SAV.Language != pk.Language) + entry.SetLanguageFlag(SAV.Language, true); + + // Update adjacent entries if not seen. + UpdateAdjacent(species); + } } diff --git a/PKHeX.WinForms/Controls/SAV Editor/SAVEditor.Designer.cs b/PKHeX.WinForms/Controls/SAV Editor/SAVEditor.Designer.cs index c6a5bb4b3..b22aff15f 100644 --- a/PKHeX.WinForms/Controls/SAV Editor/SAVEditor.Designer.cs +++ b/PKHeX.WinForms/Controls/SAV Editor/SAVEditor.Designer.cs @@ -86,6 +86,7 @@ namespace PKHeX.WinForms.Controls B_Raids = new System.Windows.Forms.Button(); B_RaidArmor = new System.Windows.Forms.Button(); B_RaidCrown = new System.Windows.Forms.Button(); + B_RaidKitakami = new System.Windows.Forms.Button(); B_Blocks = new System.Windows.Forms.Button(); B_OtherSlots = new System.Windows.Forms.Button(); B_OpenSealStickers = new System.Windows.Forms.Button(); @@ -394,6 +395,7 @@ namespace PKHeX.WinForms.Controls FLP_SAVtools.Controls.Add(B_Raids); FLP_SAVtools.Controls.Add(B_RaidArmor); FLP_SAVtools.Controls.Add(B_RaidCrown); + FLP_SAVtools.Controls.Add(B_RaidKitakami); FLP_SAVtools.Controls.Add(B_Blocks); FLP_SAVtools.Controls.Add(B_OtherSlots); FLP_SAVtools.Controls.Add(B_OpenSealStickers); @@ -761,6 +763,16 @@ namespace PKHeX.WinForms.Controls B_RaidCrown.UseVisualStyleBackColor = true; B_RaidCrown.Click += B_OpenRaids_Click; // + // B_RaidKitakami + // + B_RaidKitakami.Margin = new System.Windows.Forms.Padding(4); + B_RaidKitakami.Name = "B_RaidKitakami"; + B_RaidKitakami.Size = new System.Drawing.Size(96, 32); + B_RaidKitakami.TabIndex = 4; + B_RaidKitakami.Text = "Raids (DLC 1)"; + B_RaidKitakami.UseVisualStyleBackColor = true; + B_RaidKitakami.Click += B_OpenRaids_Click; + // // B_Blocks // B_Blocks.Location = new System.Drawing.Point(212, 284); @@ -1062,6 +1074,7 @@ namespace PKHeX.WinForms.Controls private System.Windows.Forms.Button B_RaidArmor; private System.Windows.Forms.Button B_OtherSlots; private System.Windows.Forms.Button B_RaidCrown; + private System.Windows.Forms.Button B_RaidKitakami; private System.Windows.Forms.Button Menu_ExportBAK; private System.Windows.Forms.FlowLayoutPanel FLP_SAVToolsMisc; private System.Windows.Forms.Button B_OpenSealStickers; diff --git a/PKHeX.WinForms/Controls/SAV Editor/SAVEditor.cs b/PKHeX.WinForms/Controls/SAV Editor/SAVEditor.cs index 39d88cc04..f6e457b30 100644 --- a/PKHeX.WinForms/Controls/SAV Editor/SAVEditor.cs +++ b/PKHeX.WinForms/Controls/SAV Editor/SAVEditor.cs @@ -558,7 +558,9 @@ public partial class SAVEditor : UserControl, ISlotViewer, ISaveFile if (SAV is SAV9SV sv) { if (sender == B_Raids) - OpenDialog(new SAV_Raid9(sv, sv.Raid)); + OpenDialog(new SAV_Raid9(sv, sv.RaidPaldea)); + else if (sender == B_RaidKitakami) + OpenDialog(new SAV_Raid9(sv, sv.RaidKitakami)); else if (sender == B_RaidsSevenStar) OpenDialog(new SAV_RaidSevenStar9(sv, sv.RaidSevenStar)); } @@ -653,7 +655,7 @@ public partial class SAVEditor : UserControl, ISlotViewer, ISaveFile SAV8SWSH swsh => new SAV_PokedexSWSH(swsh), SAV8BS bs => new SAV_PokedexBDSP(bs), SAV8LA la => new SAV_PokedexLA(la), - SAV9SV swsh => new SAV_PokedexSV(swsh), + SAV9SV sv => sv.SaveRevision == 0 ? new SAV_PokedexSV(sv) : new SAV_PokedexSVKitakami(sv), _ => (Form?)null, }; form?.ShowDialog(); @@ -1139,6 +1141,7 @@ public partial class SAVEditor : UserControl, ISlotViewer, ISaveFile B_RaidsSevenStar.Visible = sav is SAV9SV; B_RaidArmor.Visible = sav is SAV8SWSH { SaveRevision: >= 1 }; B_RaidCrown.Visible = sav is SAV8SWSH { SaveRevision: >= 2 }; + B_RaidKitakami.Visible = sav is SAV9SV { SaveRevision: >= 1 }; FLP_SAVtools.Visible = B_Blocks.Visible = true; var list = FLP_SAVtools.Controls.OfType().OrderBy(z => z.Text).ToArray(); diff --git a/PKHeX.WinForms/Subforms/Save Editors/Gen9/SAV_PokedexSV.cs b/PKHeX.WinForms/Subforms/Save Editors/Gen9/SAV_PokedexSV.cs index 6d1132b4c..c29718a19 100644 --- a/PKHeX.WinForms/Subforms/Save Editors/Gen9/SAV_PokedexSV.cs +++ b/PKHeX.WinForms/Subforms/Save Editors/Gen9/SAV_PokedexSV.cs @@ -138,7 +138,7 @@ public partial class SAV_PokedexSV : Form private void GetEntry(ushort species) { - var entry = SAV.Zukan.Get(species); + var entry = SAV.Zukan.DexPaldea.Get(species); var forms = GetFormList(species); if (forms[0].Length == 0) forms[0] = GameInfo.Strings.Types[0]; @@ -191,7 +191,7 @@ public partial class SAV_PokedexSV : Form private void SetEntry(ushort species) { - var entry = SAV.Zukan.Get(species); + var entry = SAV.Zukan.DexPaldea.Get(species); entry.SetState((uint)CB_State.SelectedIndex); entry.SetDisplayIsNew(CHK_IsNew.Checked); diff --git a/PKHeX.WinForms/Subforms/Save Editors/Gen9/SAV_PokedexSVKitakami.Designer.cs b/PKHeX.WinForms/Subforms/Save Editors/Gen9/SAV_PokedexSVKitakami.Designer.cs new file mode 100644 index 000000000..3e33a6715 --- /dev/null +++ b/PKHeX.WinForms/Subforms/Save Editors/Gen9/SAV_PokedexSVKitakami.Designer.cs @@ -0,0 +1,725 @@ +namespace PKHeX.WinForms +{ + partial class SAV_PokedexSVKitakami + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + components = new System.ComponentModel.Container(); + B_Cancel = new System.Windows.Forms.Button(); + LB_Species = new System.Windows.Forms.ListBox(); + L_goto = new System.Windows.Forms.Label(); + CB_Species = new System.Windows.Forms.ComboBox(); + B_GiveAll = new System.Windows.Forms.Button(); + B_Save = new System.Windows.Forms.Button(); + B_Modify = new System.Windows.Forms.Button(); + modifyMenu = new System.Windows.Forms.ContextMenuStrip(components); + mnuSeenNone = new System.Windows.Forms.ToolStripMenuItem(); + mnuSeenAll = new System.Windows.Forms.ToolStripMenuItem(); + mnuCaughtNone = new System.Windows.Forms.ToolStripMenuItem(); + mnuCaughtAll = new System.Windows.Forms.ToolStripMenuItem(); + mnuComplete = new System.Windows.Forms.ToolStripMenuItem(); + mnuFormNone = new System.Windows.Forms.ToolStripMenuItem(); + mnuForm1 = new System.Windows.Forms.ToolStripMenuItem(); + mnuFormAll = new System.Windows.Forms.ToolStripMenuItem(); + CB_PaldeaForm = new System.Windows.Forms.ComboBox(); + GB_Paldea = new System.Windows.Forms.GroupBox(); + CB_PaldeaGender = new System.Windows.Forms.ComboBox(); + CHK_PaldeaShiny = new System.Windows.Forms.CheckBox(); + GB_Language = new System.Windows.Forms.GroupBox(); + CHK_LangCHT = new System.Windows.Forms.CheckBox(); + CHK_LangCHS = new System.Windows.Forms.CheckBox(); + CHK_LangKOR = new System.Windows.Forms.CheckBox(); + CHK_LangSPA = new System.Windows.Forms.CheckBox(); + CHK_LangGER = new System.Windows.Forms.CheckBox(); + CHK_LangITA = new System.Windows.Forms.CheckBox(); + CHK_LangFRE = new System.Windows.Forms.CheckBox(); + CHK_LangENG = new System.Windows.Forms.CheckBox(); + CHK_LangJPN = new System.Windows.Forms.CheckBox(); + CLB_FormSeen = new System.Windows.Forms.CheckedListBox(); + CHK_SeenShiny = new System.Windows.Forms.CheckBox(); + GB_SeenFlags = new System.Windows.Forms.GroupBox(); + CHK_SeenGenderless = new System.Windows.Forms.CheckBox(); + CHK_SeenFemale = new System.Windows.Forms.CheckBox(); + CHK_SeenMale = new System.Windows.Forms.CheckBox(); + GB_Kitakami = new System.Windows.Forms.GroupBox(); + CB_KitakamiGender = new System.Windows.Forms.ComboBox(); + CB_KitakamiForm = new System.Windows.Forms.ComboBox(); + CHK_KitakamiShiny = new System.Windows.Forms.CheckBox(); + GB_Blueberry = new System.Windows.Forms.GroupBox(); + CB_BlueberryGender = new System.Windows.Forms.ComboBox(); + CB_BlueberryForm = new System.Windows.Forms.ComboBox(); + CHK_BlueberryShiny = new System.Windows.Forms.CheckBox(); + CLB_FormObtained = new System.Windows.Forms.CheckedListBox(); + CLB_FormHeard = new System.Windows.Forms.CheckedListBox(); + CLB_FormViewed = new System.Windows.Forms.CheckedListBox(); + L_Seen = new System.Windows.Forms.Label(); + L_Obtained = new System.Windows.Forms.Label(); + L_HeardOf = new System.Windows.Forms.Label(); + L_Viewed = new System.Windows.Forms.Label(); + modifyMenu.SuspendLayout(); + GB_Paldea.SuspendLayout(); + GB_Language.SuspendLayout(); + GB_SeenFlags.SuspendLayout(); + GB_Kitakami.SuspendLayout(); + GB_Blueberry.SuspendLayout(); + SuspendLayout(); + // + // B_Cancel + // + B_Cancel.Anchor = System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right; + B_Cancel.Location = new System.Drawing.Point(712, 361); + B_Cancel.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3); + B_Cancel.Name = "B_Cancel"; + B_Cancel.Size = new System.Drawing.Size(93, 27); + B_Cancel.TabIndex = 0; + B_Cancel.Text = "Cancel"; + B_Cancel.UseVisualStyleBackColor = true; + B_Cancel.Click += B_Cancel_Click; + // + // LB_Species + // + LB_Species.FormattingEnabled = true; + LB_Species.ItemHeight = 15; + LB_Species.Location = new System.Drawing.Point(16, 54); + LB_Species.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3); + LB_Species.Name = "LB_Species"; + LB_Species.Size = new System.Drawing.Size(160, 334); + LB_Species.TabIndex = 2; + LB_Species.SelectedIndexChanged += ChangeLBSpecies; + // + // L_goto + // + L_goto.AutoSize = true; + L_goto.Location = new System.Drawing.Point(14, 18); + L_goto.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); + L_goto.Name = "L_goto"; + L_goto.Size = new System.Drawing.Size(35, 15); + L_goto.TabIndex = 20; + L_goto.Text = "goto:"; + // + // CB_Species + // + CB_Species.AutoCompleteMode = System.Windows.Forms.AutoCompleteMode.Suggest; + CB_Species.AutoCompleteSource = System.Windows.Forms.AutoCompleteSource.ListItems; + CB_Species.DropDownWidth = 95; + CB_Species.FormattingEnabled = true; + CB_Species.Items.AddRange(new object[] { "0" }); + CB_Species.Location = new System.Drawing.Point(58, 15); + CB_Species.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3); + CB_Species.Name = "CB_Species"; + CB_Species.Size = new System.Drawing.Size(118, 23); + CB_Species.TabIndex = 21; + CB_Species.SelectedIndexChanged += ChangeCBSpecies; + CB_Species.SelectedValueChanged += ChangeCBSpecies; + // + // B_GiveAll + // + B_GiveAll.Location = new System.Drawing.Point(558, 6); + B_GiveAll.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3); + B_GiveAll.Name = "B_GiveAll"; + B_GiveAll.Size = new System.Drawing.Size(104, 27); + B_GiveAll.TabIndex = 23; + B_GiveAll.Text = "Check All"; + B_GiveAll.UseVisualStyleBackColor = true; + B_GiveAll.Click += B_GiveAll_Click; + // + // B_Save + // + B_Save.Anchor = System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right; + B_Save.Location = new System.Drawing.Point(712, 328); + B_Save.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3); + B_Save.Name = "B_Save"; + B_Save.Size = new System.Drawing.Size(93, 27); + B_Save.TabIndex = 24; + B_Save.Text = "Save"; + B_Save.UseVisualStyleBackColor = true; + B_Save.Click += B_Save_Click; + // + // B_Modify + // + B_Modify.Location = new System.Drawing.Point(701, 6); + B_Modify.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3); + B_Modify.Name = "B_Modify"; + B_Modify.Size = new System.Drawing.Size(104, 27); + B_Modify.TabIndex = 25; + B_Modify.Text = "Modify All..."; + B_Modify.UseVisualStyleBackColor = true; + B_Modify.Click += B_Modify_Click; + // + // modifyMenu + // + modifyMenu.ImageScalingSize = new System.Drawing.Size(20, 20); + modifyMenu.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { mnuSeenNone, mnuSeenAll, mnuCaughtNone, mnuCaughtAll, mnuComplete }); + modifyMenu.Name = "modifyMenu"; + modifyMenu.Size = new System.Drawing.Size(150, 114); + // + // mnuSeenNone + // + mnuSeenNone.Name = "mnuSeenNone"; + mnuSeenNone.Size = new System.Drawing.Size(149, 22); + mnuSeenNone.Text = "Seen none"; + mnuSeenNone.Click += SeenNone; + // + // mnuSeenAll + // + mnuSeenAll.Name = "mnuSeenAll"; + mnuSeenAll.Size = new System.Drawing.Size(149, 22); + mnuSeenAll.Text = "Seen all"; + mnuSeenAll.Click += SeenAll; + // + // mnuCaughtNone + // + mnuCaughtNone.Name = "mnuCaughtNone"; + mnuCaughtNone.Size = new System.Drawing.Size(149, 22); + mnuCaughtNone.Text = "Caught none"; + mnuCaughtNone.Click += CaughtNone; + // + // mnuCaughtAll + // + mnuCaughtAll.Name = "mnuCaughtAll"; + mnuCaughtAll.Size = new System.Drawing.Size(149, 22); + mnuCaughtAll.Text = "Caught all"; + mnuCaughtAll.Click += CaughtAll; + // + // mnuComplete + // + mnuComplete.Name = "mnuComplete"; + mnuComplete.Size = new System.Drawing.Size(149, 22); + mnuComplete.Text = "Complete Dex"; + mnuComplete.Click += CompleteDex; + // + // mnuFormNone + // + mnuFormNone.Name = "mnuFormNone"; + mnuFormNone.Size = new System.Drawing.Size(32, 19); + // + // mnuForm1 + // + mnuForm1.Name = "mnuForm1"; + mnuForm1.Size = new System.Drawing.Size(32, 19); + // + // mnuFormAll + // + mnuFormAll.Name = "mnuFormAll"; + mnuFormAll.Size = new System.Drawing.Size(32, 19); + // + // CB_PaldeaForm + // + CB_PaldeaForm.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; + CB_PaldeaForm.FormattingEnabled = true; + CB_PaldeaForm.Items.AddRange(new object[] { "♂", "♀", "-" }); + CB_PaldeaForm.Location = new System.Drawing.Point(9, 44); + CB_PaldeaForm.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3); + CB_PaldeaForm.Name = "CB_PaldeaForm"; + CB_PaldeaForm.Size = new System.Drawing.Size(120, 23); + CB_PaldeaForm.TabIndex = 45; + // + // GB_Paldea + // + GB_Paldea.Controls.Add(CB_PaldeaGender); + GB_Paldea.Controls.Add(CB_PaldeaForm); + GB_Paldea.Controls.Add(CHK_PaldeaShiny); + GB_Paldea.Location = new System.Drawing.Point(184, 319); + GB_Paldea.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3); + GB_Paldea.Name = "GB_Paldea"; + GB_Paldea.Padding = new System.Windows.Forms.Padding(4, 3, 4, 3); + GB_Paldea.Size = new System.Drawing.Size(138, 72); + GB_Paldea.TabIndex = 44; + GB_Paldea.TabStop = false; + GB_Paldea.Text = "Display: Paldea"; + // + // CB_PaldeaGender + // + CB_PaldeaGender.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; + CB_PaldeaGender.FormattingEnabled = true; + CB_PaldeaGender.Items.AddRange(new object[] { "♂", "♀", "-" }); + CB_PaldeaGender.Location = new System.Drawing.Point(8, 16); + CB_PaldeaGender.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3); + CB_PaldeaGender.Name = "CB_PaldeaGender"; + CB_PaldeaGender.Size = new System.Drawing.Size(46, 23); + CB_PaldeaGender.TabIndex = 24; + // + // CHK_PaldeaShiny + // + CHK_PaldeaShiny.AutoSize = true; + CHK_PaldeaShiny.Location = new System.Drawing.Point(64, 18); + CHK_PaldeaShiny.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3); + CHK_PaldeaShiny.Name = "CHK_PaldeaShiny"; + CHK_PaldeaShiny.Size = new System.Drawing.Size(55, 19); + CHK_PaldeaShiny.TabIndex = 9; + CHK_PaldeaShiny.Text = "Shiny"; + CHK_PaldeaShiny.UseVisualStyleBackColor = true; + // + // GB_Language + // + GB_Language.Controls.Add(CHK_LangCHT); + GB_Language.Controls.Add(CHK_LangCHS); + GB_Language.Controls.Add(CHK_LangKOR); + GB_Language.Controls.Add(CHK_LangSPA); + GB_Language.Controls.Add(CHK_LangGER); + GB_Language.Controls.Add(CHK_LangITA); + GB_Language.Controls.Add(CHK_LangFRE); + GB_Language.Controls.Add(CHK_LangENG); + GB_Language.Controls.Add(CHK_LangJPN); + GB_Language.Location = new System.Drawing.Point(670, 148); + GB_Language.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3); + GB_Language.Name = "GB_Language"; + GB_Language.Padding = new System.Windows.Forms.Padding(4, 3, 4, 3); + GB_Language.Size = new System.Drawing.Size(134, 167); + GB_Language.TabIndex = 47; + GB_Language.TabStop = false; + GB_Language.Text = "Languages"; + // + // CHK_LangCHT + // + CHK_LangCHT.AutoSize = true; + CHK_LangCHT.Location = new System.Drawing.Point(7, 145); + CHK_LangCHT.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3); + CHK_LangCHT.Name = "CHK_LangCHT"; + CHK_LangCHT.Size = new System.Drawing.Size(74, 19); + CHK_LangCHT.TabIndex = 21; + CHK_LangCHT.Text = "ChineseT"; + CHK_LangCHT.UseVisualStyleBackColor = true; + // + // CHK_LangCHS + // + CHK_LangCHS.AutoSize = true; + CHK_LangCHS.Location = new System.Drawing.Point(7, 129); + CHK_LangCHS.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3); + CHK_LangCHS.Name = "CHK_LangCHS"; + CHK_LangCHS.Size = new System.Drawing.Size(74, 19); + CHK_LangCHS.TabIndex = 20; + CHK_LangCHS.Text = "ChineseS"; + CHK_LangCHS.UseVisualStyleBackColor = true; + // + // CHK_LangKOR + // + CHK_LangKOR.AutoSize = true; + CHK_LangKOR.Location = new System.Drawing.Point(7, 113); + CHK_LangKOR.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3); + CHK_LangKOR.Name = "CHK_LangKOR"; + CHK_LangKOR.Size = new System.Drawing.Size(63, 19); + CHK_LangKOR.TabIndex = 19; + CHK_LangKOR.Text = "Korean"; + CHK_LangKOR.UseVisualStyleBackColor = true; + // + // CHK_LangSPA + // + CHK_LangSPA.AutoSize = true; + CHK_LangSPA.Location = new System.Drawing.Point(7, 97); + CHK_LangSPA.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3); + CHK_LangSPA.Name = "CHK_LangSPA"; + CHK_LangSPA.Size = new System.Drawing.Size(67, 19); + CHK_LangSPA.TabIndex = 18; + CHK_LangSPA.Text = "Spanish"; + CHK_LangSPA.UseVisualStyleBackColor = true; + // + // CHK_LangGER + // + CHK_LangGER.AutoSize = true; + CHK_LangGER.Location = new System.Drawing.Point(7, 81); + CHK_LangGER.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3); + CHK_LangGER.Name = "CHK_LangGER"; + CHK_LangGER.Size = new System.Drawing.Size(68, 19); + CHK_LangGER.TabIndex = 17; + CHK_LangGER.Text = "German"; + CHK_LangGER.UseVisualStyleBackColor = true; + // + // CHK_LangITA + // + CHK_LangITA.AutoSize = true; + CHK_LangITA.Location = new System.Drawing.Point(7, 65); + CHK_LangITA.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3); + CHK_LangITA.Name = "CHK_LangITA"; + CHK_LangITA.Size = new System.Drawing.Size(58, 19); + CHK_LangITA.TabIndex = 16; + CHK_LangITA.Text = "Italian"; + CHK_LangITA.UseVisualStyleBackColor = true; + // + // CHK_LangFRE + // + CHK_LangFRE.AutoSize = true; + CHK_LangFRE.Location = new System.Drawing.Point(7, 48); + CHK_LangFRE.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3); + CHK_LangFRE.Name = "CHK_LangFRE"; + CHK_LangFRE.Size = new System.Drawing.Size(62, 19); + CHK_LangFRE.TabIndex = 15; + CHK_LangFRE.Text = "French"; + CHK_LangFRE.UseVisualStyleBackColor = true; + // + // CHK_LangENG + // + CHK_LangENG.AutoSize = true; + CHK_LangENG.Location = new System.Drawing.Point(7, 32); + CHK_LangENG.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3); + CHK_LangENG.Name = "CHK_LangENG"; + CHK_LangENG.Size = new System.Drawing.Size(64, 19); + CHK_LangENG.TabIndex = 14; + CHK_LangENG.Text = "English"; + CHK_LangENG.UseVisualStyleBackColor = true; + // + // CHK_LangJPN + // + CHK_LangJPN.AutoSize = true; + CHK_LangJPN.Location = new System.Drawing.Point(7, 16); + CHK_LangJPN.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3); + CHK_LangJPN.Name = "CHK_LangJPN"; + CHK_LangJPN.Size = new System.Drawing.Size(73, 19); + CHK_LangJPN.TabIndex = 13; + CHK_LangJPN.Text = "Japanese"; + CHK_LangJPN.UseVisualStyleBackColor = true; + // + // CLB_FormSeen + // + CLB_FormSeen.FormattingEnabled = true; + CLB_FormSeen.Location = new System.Drawing.Point(184, 57); + CLB_FormSeen.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3); + CLB_FormSeen.Name = "CLB_FormSeen"; + CLB_FormSeen.Size = new System.Drawing.Size(112, 256); + CLB_FormSeen.TabIndex = 48; + // + // CHK_SeenShiny + // + CHK_SeenShiny.AutoSize = true; + CHK_SeenShiny.Location = new System.Drawing.Point(6, 69); + CHK_SeenShiny.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3); + CHK_SeenShiny.Name = "CHK_SeenShiny"; + CHK_SeenShiny.Size = new System.Drawing.Size(55, 19); + CHK_SeenShiny.TabIndex = 25; + CHK_SeenShiny.Text = "Shiny"; + CHK_SeenShiny.UseVisualStyleBackColor = true; + // + // GB_SeenFlags + // + GB_SeenFlags.Controls.Add(CHK_SeenGenderless); + GB_SeenFlags.Controls.Add(CHK_SeenShiny); + GB_SeenFlags.Controls.Add(CHK_SeenFemale); + GB_SeenFlags.Controls.Add(CHK_SeenMale); + GB_SeenFlags.Location = new System.Drawing.Point(670, 54); + GB_SeenFlags.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3); + GB_SeenFlags.Name = "GB_SeenFlags"; + GB_SeenFlags.Padding = new System.Windows.Forms.Padding(4, 3, 4, 3); + GB_SeenFlags.Size = new System.Drawing.Size(134, 92); + GB_SeenFlags.TabIndex = 49; + GB_SeenFlags.TabStop = false; + GB_SeenFlags.Text = "Seen"; + // + // CHK_SeenGenderless + // + CHK_SeenGenderless.AutoSize = true; + CHK_SeenGenderless.Location = new System.Drawing.Point(6, 48); + CHK_SeenGenderless.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3); + CHK_SeenGenderless.Name = "CHK_SeenGenderless"; + CHK_SeenGenderless.Size = new System.Drawing.Size(83, 19); + CHK_SeenGenderless.TabIndex = 12; + CHK_SeenGenderless.Text = "Genderless"; + CHK_SeenGenderless.UseVisualStyleBackColor = true; + // + // CHK_SeenFemale + // + CHK_SeenFemale.AutoSize = true; + CHK_SeenFemale.Location = new System.Drawing.Point(6, 32); + CHK_SeenFemale.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3); + CHK_SeenFemale.Name = "CHK_SeenFemale"; + CHK_SeenFemale.Size = new System.Drawing.Size(64, 19); + CHK_SeenFemale.TabIndex = 9; + CHK_SeenFemale.Text = "Female"; + CHK_SeenFemale.UseVisualStyleBackColor = true; + // + // CHK_SeenMale + // + CHK_SeenMale.AutoSize = true; + CHK_SeenMale.Location = new System.Drawing.Point(6, 16); + CHK_SeenMale.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3); + CHK_SeenMale.Name = "CHK_SeenMale"; + CHK_SeenMale.Size = new System.Drawing.Size(52, 19); + CHK_SeenMale.TabIndex = 11; + CHK_SeenMale.Text = "Male"; + CHK_SeenMale.UseVisualStyleBackColor = true; + // + // GB_Kitakami + // + GB_Kitakami.Controls.Add(CB_KitakamiGender); + GB_Kitakami.Controls.Add(CB_KitakamiForm); + GB_Kitakami.Controls.Add(CHK_KitakamiShiny); + GB_Kitakami.Location = new System.Drawing.Point(328, 319); + GB_Kitakami.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3); + GB_Kitakami.Name = "GB_Kitakami"; + GB_Kitakami.Padding = new System.Windows.Forms.Padding(4, 3, 4, 3); + GB_Kitakami.Size = new System.Drawing.Size(138, 72); + GB_Kitakami.TabIndex = 46; + GB_Kitakami.TabStop = false; + GB_Kitakami.Text = "Display: Kitakami"; + // + // CB_KitakamiGender + // + CB_KitakamiGender.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; + CB_KitakamiGender.FormattingEnabled = true; + CB_KitakamiGender.Items.AddRange(new object[] { "♂", "♀", "-" }); + CB_KitakamiGender.Location = new System.Drawing.Point(8, 16); + CB_KitakamiGender.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3); + CB_KitakamiGender.Name = "CB_KitakamiGender"; + CB_KitakamiGender.Size = new System.Drawing.Size(46, 23); + CB_KitakamiGender.TabIndex = 24; + // + // CB_KitakamiForm + // + CB_KitakamiForm.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; + CB_KitakamiForm.FormattingEnabled = true; + CB_KitakamiForm.Items.AddRange(new object[] { "♂", "♀", "-" }); + CB_KitakamiForm.Location = new System.Drawing.Point(9, 44); + CB_KitakamiForm.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3); + CB_KitakamiForm.Name = "CB_KitakamiForm"; + CB_KitakamiForm.Size = new System.Drawing.Size(120, 23); + CB_KitakamiForm.TabIndex = 45; + // + // CHK_KitakamiShiny + // + CHK_KitakamiShiny.AutoSize = true; + CHK_KitakamiShiny.Location = new System.Drawing.Point(64, 18); + CHK_KitakamiShiny.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3); + CHK_KitakamiShiny.Name = "CHK_KitakamiShiny"; + CHK_KitakamiShiny.Size = new System.Drawing.Size(55, 19); + CHK_KitakamiShiny.TabIndex = 9; + CHK_KitakamiShiny.Text = "Shiny"; + CHK_KitakamiShiny.UseVisualStyleBackColor = true; + // + // GB_Blueberry + // + GB_Blueberry.Controls.Add(CB_BlueberryGender); + GB_Blueberry.Controls.Add(CB_BlueberryForm); + GB_Blueberry.Controls.Add(CHK_BlueberryShiny); + GB_Blueberry.Location = new System.Drawing.Point(472, 319); + GB_Blueberry.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3); + GB_Blueberry.Name = "GB_Blueberry"; + GB_Blueberry.Padding = new System.Windows.Forms.Padding(4, 3, 4, 3); + GB_Blueberry.Size = new System.Drawing.Size(138, 72); + GB_Blueberry.TabIndex = 47; + GB_Blueberry.TabStop = false; + GB_Blueberry.Text = "Display: Blueberry"; + // + // CB_BlueberryGender + // + CB_BlueberryGender.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; + CB_BlueberryGender.FormattingEnabled = true; + CB_BlueberryGender.Items.AddRange(new object[] { "♂", "♀", "-" }); + CB_BlueberryGender.Location = new System.Drawing.Point(8, 16); + CB_BlueberryGender.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3); + CB_BlueberryGender.Name = "CB_BlueberryGender"; + CB_BlueberryGender.Size = new System.Drawing.Size(46, 23); + CB_BlueberryGender.TabIndex = 24; + // + // CB_BlueberryForm + // + CB_BlueberryForm.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; + CB_BlueberryForm.FormattingEnabled = true; + CB_BlueberryForm.Items.AddRange(new object[] { "♂", "♀", "-" }); + CB_BlueberryForm.Location = new System.Drawing.Point(9, 44); + CB_BlueberryForm.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3); + CB_BlueberryForm.Name = "CB_BlueberryForm"; + CB_BlueberryForm.Size = new System.Drawing.Size(120, 23); + CB_BlueberryForm.TabIndex = 45; + // + // CHK_BlueberryShiny + // + CHK_BlueberryShiny.AutoSize = true; + CHK_BlueberryShiny.Location = new System.Drawing.Point(64, 18); + CHK_BlueberryShiny.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3); + CHK_BlueberryShiny.Name = "CHK_BlueberryShiny"; + CHK_BlueberryShiny.Size = new System.Drawing.Size(55, 19); + CHK_BlueberryShiny.TabIndex = 9; + CHK_BlueberryShiny.Text = "Shiny"; + CHK_BlueberryShiny.UseVisualStyleBackColor = true; + // + // CLB_FormObtained + // + CLB_FormObtained.FormattingEnabled = true; + CLB_FormObtained.Location = new System.Drawing.Point(306, 57); + CLB_FormObtained.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3); + CLB_FormObtained.Name = "CLB_FormObtained"; + CLB_FormObtained.Size = new System.Drawing.Size(112, 256); + CLB_FormObtained.TabIndex = 50; + // + // CLB_FormHeard + // + CLB_FormHeard.FormattingEnabled = true; + CLB_FormHeard.Location = new System.Drawing.Point(428, 57); + CLB_FormHeard.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3); + CLB_FormHeard.Name = "CLB_FormHeard"; + CLB_FormHeard.Size = new System.Drawing.Size(112, 256); + CLB_FormHeard.TabIndex = 51; + // + // CLB_FormViewed + // + CLB_FormViewed.FormattingEnabled = true; + CLB_FormViewed.Location = new System.Drawing.Point(550, 57); + CLB_FormViewed.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3); + CLB_FormViewed.Name = "CLB_FormViewed"; + CLB_FormViewed.Size = new System.Drawing.Size(112, 256); + CLB_FormViewed.TabIndex = 52; + // + // L_Seen + // + L_Seen.AutoSize = true; + L_Seen.Location = new System.Drawing.Point(184, 41); + L_Seen.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); + L_Seen.Name = "L_Seen"; + L_Seen.Size = new System.Drawing.Size(35, 15); + L_Seen.TabIndex = 53; + L_Seen.Text = "Seen:"; + // + // L_Obtained + // + L_Obtained.AutoSize = true; + L_Obtained.Location = new System.Drawing.Point(306, 39); + L_Obtained.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); + L_Obtained.Name = "L_Obtained"; + L_Obtained.Size = new System.Drawing.Size(59, 15); + L_Obtained.TabIndex = 54; + L_Obtained.Text = "Obtained:"; + // + // L_HeardOf + // + L_HeardOf.AutoSize = true; + L_HeardOf.Location = new System.Drawing.Point(428, 39); + L_HeardOf.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); + L_HeardOf.Name = "L_HeardOf"; + L_HeardOf.Size = new System.Drawing.Size(58, 15); + L_HeardOf.TabIndex = 55; + L_HeardOf.Text = "Heard Of:"; + // + // L_Viewed + // + L_Viewed.AutoSize = true; + L_Viewed.Location = new System.Drawing.Point(550, 39); + L_Viewed.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); + L_Viewed.Name = "L_Viewed"; + L_Viewed.Size = new System.Drawing.Size(48, 15); + L_Viewed.TabIndex = 56; + L_Viewed.Text = "Viewed:"; + // + // SAV_PokedexSVKitakami + // + AutoScaleMode = System.Windows.Forms.AutoScaleMode.Inherit; + ClientSize = new System.Drawing.Size(820, 399); + Controls.Add(L_Viewed); + Controls.Add(L_HeardOf); + Controls.Add(L_Obtained); + Controls.Add(L_Seen); + Controls.Add(CLB_FormViewed); + Controls.Add(CLB_FormHeard); + Controls.Add(CLB_FormObtained); + Controls.Add(GB_Blueberry); + Controls.Add(GB_Kitakami); + Controls.Add(GB_SeenFlags); + Controls.Add(CLB_FormSeen); + Controls.Add(GB_Language); + Controls.Add(GB_Paldea); + Controls.Add(B_Modify); + Controls.Add(B_Save); + Controls.Add(B_GiveAll); + Controls.Add(CB_Species); + Controls.Add(L_goto); + Controls.Add(LB_Species); + Controls.Add(B_Cancel); + Icon = Properties.Resources.Icon; + Margin = new System.Windows.Forms.Padding(4, 3, 4, 3); + MaximizeBox = false; + MinimizeBox = false; + Name = "SAV_PokedexSVKitakami"; + StartPosition = System.Windows.Forms.FormStartPosition.CenterParent; + Text = "Pokédex Editor"; + modifyMenu.ResumeLayout(false); + GB_Paldea.ResumeLayout(false); + GB_Paldea.PerformLayout(); + GB_Language.ResumeLayout(false); + GB_Language.PerformLayout(); + GB_SeenFlags.ResumeLayout(false); + GB_SeenFlags.PerformLayout(); + GB_Kitakami.ResumeLayout(false); + GB_Kitakami.PerformLayout(); + GB_Blueberry.ResumeLayout(false); + GB_Blueberry.PerformLayout(); + ResumeLayout(false); + PerformLayout(); + } + + #endregion + + private System.Windows.Forms.Button B_Cancel; + private System.Windows.Forms.ListBox LB_Species; + private System.Windows.Forms.Label L_goto; + private System.Windows.Forms.ComboBox CB_Species; + private System.Windows.Forms.Button B_GiveAll; + private System.Windows.Forms.Button B_Save; + private System.Windows.Forms.Button B_Modify; + private System.Windows.Forms.ContextMenuStrip modifyMenu; + private System.Windows.Forms.ToolStripMenuItem mnuSeenNone; + private System.Windows.Forms.ToolStripMenuItem mnuSeenAll; + private System.Windows.Forms.ToolStripMenuItem mnuCaughtNone; + private System.Windows.Forms.ToolStripMenuItem mnuCaughtAll; + private System.Windows.Forms.ToolStripMenuItem mnuComplete; + private System.Windows.Forms.ToolStripMenuItem mnuFormNone; + private System.Windows.Forms.ToolStripMenuItem mnuForm1; + private System.Windows.Forms.ToolStripMenuItem mnuFormAll; + private System.Windows.Forms.ComboBox CB_PaldeaForm; + private System.Windows.Forms.GroupBox GB_Paldea; + private System.Windows.Forms.CheckBox CHK_PaldeaShiny; + private System.Windows.Forms.ComboBox CB_PaldeaGender; + private System.Windows.Forms.GroupBox GB_Language; + private System.Windows.Forms.CheckBox CHK_LangCHT; + private System.Windows.Forms.CheckBox CHK_LangCHS; + private System.Windows.Forms.CheckBox CHK_LangKOR; + private System.Windows.Forms.CheckBox CHK_LangSPA; + private System.Windows.Forms.CheckBox CHK_LangGER; + private System.Windows.Forms.CheckBox CHK_LangITA; + private System.Windows.Forms.CheckBox CHK_LangFRE; + private System.Windows.Forms.CheckBox CHK_LangENG; + private System.Windows.Forms.CheckBox CHK_LangJPN; + private System.Windows.Forms.CheckedListBox CLB_FormSeen; + private System.Windows.Forms.CheckBox CHK_SeenShiny; + private System.Windows.Forms.GroupBox GB_SeenFlags; + private System.Windows.Forms.CheckBox CHK_SeenGenderless; + private System.Windows.Forms.CheckBox CHK_SeenFemale; + private System.Windows.Forms.CheckBox CHK_SeenMale; + private System.Windows.Forms.GroupBox GB_Kitakami; + private System.Windows.Forms.ComboBox CB_KitakamiGender; + private System.Windows.Forms.ComboBox CB_KitakamiForm; + private System.Windows.Forms.CheckBox CHK_KitakamiShiny; + private System.Windows.Forms.GroupBox GB_Blueberry; + private System.Windows.Forms.ComboBox CB_BlueberryGender; + private System.Windows.Forms.ComboBox CB_BlueberryForm; + private System.Windows.Forms.CheckBox CHK_BlueberryShiny; + private System.Windows.Forms.CheckedListBox CLB_FormObtained; + private System.Windows.Forms.CheckedListBox CLB_FormHeard; + private System.Windows.Forms.CheckedListBox CLB_FormViewed; + private System.Windows.Forms.Label L_Seen; + private System.Windows.Forms.Label L_Obtained; + private System.Windows.Forms.Label L_HeardOf; + private System.Windows.Forms.Label L_Viewed; + } +} diff --git a/PKHeX.WinForms/Subforms/Save Editors/Gen9/SAV_PokedexSVKitakami.cs b/PKHeX.WinForms/Subforms/Save Editors/Gen9/SAV_PokedexSVKitakami.cs new file mode 100644 index 000000000..b4bfff334 --- /dev/null +++ b/PKHeX.WinForms/Subforms/Save Editors/Gen9/SAV_PokedexSVKitakami.cs @@ -0,0 +1,364 @@ +using System; +using System.Drawing; +using System.Linq; +using System.Windows.Forms; +using PKHeX.Core; + +namespace PKHeX.WinForms; + +public partial class SAV_PokedexSVKitakami : Form +{ + private readonly SAV9SV Origin; + private readonly SAV9SV SAV; + private readonly Zukan9 Dex; + + private int lastIndex; + private readonly bool CanSave; + private readonly bool Loading; + + public SAV_PokedexSVKitakami(SAV9SV sav) + { + InitializeComponent(); + WinFormsUtil.TranslateInterface(this, Main.CurrentLanguage); + SAV = (SAV9SV)(Origin = sav).Clone(); + Dex = SAV.Blocks.Zukan; + + Loading = true; + // Clear Listbox and ComboBox + LB_Species.Items.Clear(); + CB_Species.Items.Clear(); + + var empty = new string[32]; + foreach (ref var x in empty.AsSpan()) + x = string.Empty; + CLB_FormSeen.Items.AddRange(empty); + CLB_FormObtained.Items.AddRange(empty); + CLB_FormHeard.Items.AddRange(empty); + CLB_FormViewed.Items.AddRange(empty); + + // Fill List + CB_Species.InitializeBinding(); + var species = GameInfo.SpeciesDataSource.Where(z => SAV.Personal.IsSpeciesInGame((ushort)z.Value)).ToArray(); + CB_Species.DataSource = new BindingSource(species, null); + + var list = species + .Select(z => new DexMap(z)) + .OrderByDescending(z => z.IsInAnyDex) + .ThenBy(z => z.Dex).ToArray(); + + var lbi = LB_Species.Items; + for (var i = 0; i < list.Length; i++) + { + var n = list[i]; + var display = n.GetDexString(); + lbi.Add($"{display} - {n.Name}"); + n.ListIndex = i; + } + + ListBoxToSpecies = list; + LB_Species.SelectedIndex = 0; + CB_Species.KeyDown += WinFormsUtil.RemoveDropCB; + Loading = false; + CanSave = true; + lastIndex = 0; + GetEntry(0); + } + + private record DexMap + { + public ushort Species { get; } + public bool IsInAnyDex => Dex != default; + public (int Group, int Index) Dex { get; } + public string Name { get; } + public int ListIndex { get; set; } + + public DexMap(ComboItem c) + { + Species = (ushort)c.Value; + Name = c.Text; + Dex = GetDexIndex(Species); + } + + private static (int Group, int Index) GetDexIndex(ushort species) + { + var entry = PersonalTable.SV.GetFormEntry(species, 0); + for (byte i = 0; i < entry.FormCount; i++) + { + entry = PersonalTable.SV.GetFormEntry(species, i); + if (entry.DexPaldea != 0) + return (1, entry.DexPaldea); + if (entry.DexKitakami != 0) + return (2, entry.DexKitakami); + if (entry.DexBlueberry != 0) + return (3, entry.DexBlueberry); + } + return default; + } + + public string GetDexString() + { + if (!IsInAnyDex) + return "***"; + var prefix = Dex.Group switch + { + 1 => "P", + 2 => "K", + 3 => "B", + _ => "?", + }; + return $"{prefix}-{Dex.Index:000}"; + } + } + + private DexMap[] ListBoxToSpecies { get; } + + private ushort GetSpecies(int listBoxIndex) => Array.Find(ListBoxToSpecies, z => z.ListIndex == listBoxIndex)?.Species ?? 0; + private int GetIndex(ushort species) => Array.Find(ListBoxToSpecies, z => z.Species == species)?.ListIndex ?? 0; + + private bool IgnoreChangeEvent; + + private void ChangeCBSpecies(object sender, EventArgs e) + { + if (Loading || IgnoreChangeEvent) + return; + + var species = (ushort)WinFormsUtil.GetIndex(CB_Species); + var index = GetIndex(species); + if (LB_Species.SelectedIndex != index) + LB_Species.SelectedIndex = index; // trigger event + } + + private void ChangeLBSpecies(object sender, EventArgs e) + { + if (Loading || LB_Species.SelectedIndex < 0 || IgnoreChangeEvent) + return; + + SetEntry(lastIndex); + lastIndex = LB_Species.SelectedIndex; + GetEntry(lastIndex); + + IgnoreChangeEvent = true; + CB_Species.SelectedValue = (int)GetSpecies(lastIndex); + IgnoreChangeEvent = false; + } + + private void GetEntry(int index) + { + if (!CanSave || Loading || index < 0) + return; + var species = GetSpecies(index); + GetEntry(species); + } + + private void GetEntry(ushort species) + { + var entry = SAV.Zukan.DexKitakami.Get(species); + var forms = GetFormList(species); + if (forms[0].Length == 0) + forms[0] = GameInfo.Strings.Types[0]; + + this.SuspendLayout(); + // Clear all CheckedListBoxes + var seen = CLB_FormSeen.Items; + var obtained = CLB_FormObtained.Items; + var heard = CLB_FormHeard.Items; + var viewed = CLB_FormViewed.Items; + var p = CB_PaldeaForm.Items; + var k = CB_KitakamiForm.Items; + var b = CB_BlueberryForm.Items; + p.Clear(); + k.Clear(); + b.Clear(); + p.AddRange(forms); + k.AddRange(forms); + b.AddRange(forms); + + // Fill CheckedListBoxes + for (byte i = 0; i < sizeof(uint) * 8; i++) + { + var name = i < forms.Length ? forms[i] : $"--{i:00}--"; + seen[i] = obtained[i] = heard[i] = viewed[i] = name; + CLB_FormSeen.SetItemChecked(i, entry.GetSeenForm(i)); + CLB_FormObtained.SetItemChecked(i, entry.GetObtainedForm(i)); + CLB_FormHeard.SetItemChecked(i, entry.GetHeardForm(i)); + CLB_FormViewed.SetItemChecked(i, entry.GetCheckedForm(i)); + } + + // Fill Checkboxes + CHK_SeenMale.Checked = entry.GetIsGenderSeen(0); + CHK_SeenFemale.Checked = entry.GetIsGenderSeen(1); + CHK_SeenGenderless.Checked = entry.GetIsGenderSeen(2); + CHK_SeenShiny.Checked = entry.GetIsModelSeen(true); + + // Fill Languages + CHK_LangJPN.Checked = entry.GetLanguageFlag((int)LanguageID.Japanese); + CHK_LangENG.Checked = entry.GetLanguageFlag((int)LanguageID.English); + CHK_LangFRE.Checked = entry.GetLanguageFlag((int)LanguageID.French); + CHK_LangITA.Checked = entry.GetLanguageFlag((int)LanguageID.Italian); + CHK_LangGER.Checked = entry.GetLanguageFlag((int)LanguageID.German); + CHK_LangSPA.Checked = entry.GetLanguageFlag((int)LanguageID.Spanish); + CHK_LangKOR.Checked = entry.GetLanguageFlag((int)LanguageID.Korean); + CHK_LangCHS.Checked = entry.GetLanguageFlag((int)LanguageID.ChineseS); + CHK_LangCHT.Checked = entry.GetLanguageFlag((int)LanguageID.ChineseT); + + // Fill Paldea + CB_PaldeaForm.SelectedIndex = entry.DisplayedPaldeaForm; + CB_PaldeaGender.SelectedIndex = entry.DisplayedPaldeaGender; + CHK_PaldeaShiny.Checked = entry.DisplayedPaldeaShiny != 0; + + // Fill Kitakami + CB_KitakamiForm.SelectedIndex = entry.DisplayedKitakamiForm; + CB_KitakamiGender.SelectedIndex = entry.DisplayedKitakamiGender; + CHK_KitakamiShiny.Checked = entry.DisplayedKitakamiShiny != 0; + + // Fill Blueberry + CB_BlueberryForm.SelectedIndex = entry.DisplayedBlueberryForm; + CB_BlueberryGender.SelectedIndex = entry.DisplayedBlueberryGender; + CHK_BlueberryShiny.Checked = entry.DisplayedBlueberryShiny != 0; + + var pi = SAV.Personal[species]; + var fc = pi.FormCount; + bool paldea = false, kitakami = false, blueberry = false; + for (byte i = 0; i < fc; i++) + { + pi = SAV.Personal.GetFormEntry(species, i); + if (pi.DexPaldea != 0) + paldea = true; + if (pi.DexKitakami != 0) + kitakami = true; + if (pi.DexBlueberry != 0) + blueberry = true; + } + GB_Paldea.Enabled = paldea; + GB_Kitakami.Enabled = kitakami; + GB_Blueberry.Enabled = blueberry; + } + + private static string[] GetFormList(in ushort species) + { + var s = GameInfo.Strings; + if (species == (int)Species.Alcremie) + return FormConverter.GetAlcremieFormList(s.forms); + return FormConverter.GetFormList(species, s.Types, s.forms, GameInfo.GenderSymbolASCII, EntityContext.Gen9).ToArray(); + } + + private void SetEntry(int index) + { + if (!CanSave || Loading || index < 0) + return; + var species = GetSpecies(index); + SetEntry(species); + } + + private void SetEntry(ushort species) + { + var entry = SAV.Zukan.DexKitakami.Get(species); + + // Set Form Flags + for (byte i = 0; i < sizeof(uint) * 8; i++) + { + entry.SetSeenForm(i, CLB_FormSeen.GetItemChecked(i)); + entry.SetObtainedForm(i, CLB_FormObtained.GetItemChecked(i)); + entry.SetHeardForm(i, CLB_FormHeard.GetItemChecked(i)); + entry.SetCheckedForm(i, CLB_FormViewed.GetItemChecked(i)); + } + + // Set Flags + entry.SetIsGenderSeen(0, CHK_SeenMale.Checked); + entry.SetIsGenderSeen(1, CHK_SeenFemale.Checked); + entry.SetIsGenderSeen(2, CHK_SeenGenderless.Checked); + entry.SetIsModelSeen(true, CHK_SeenShiny.Checked); + + // Set Languages + entry.SetLanguageFlag((int)LanguageID.Japanese, CHK_LangJPN.Checked); + entry.SetLanguageFlag((int)LanguageID.English, CHK_LangENG.Checked); + entry.SetLanguageFlag((int)LanguageID.French, CHK_LangFRE.Checked); + entry.SetLanguageFlag((int)LanguageID.Italian, CHK_LangITA.Checked); + entry.SetLanguageFlag((int)LanguageID.German, CHK_LangGER.Checked); + entry.SetLanguageFlag((int)LanguageID.Spanish, CHK_LangSPA.Checked); + entry.SetLanguageFlag((int)LanguageID.Korean, CHK_LangKOR.Checked); + entry.SetLanguageFlag((int)LanguageID.ChineseS, CHK_LangCHS.Checked); + entry.SetLanguageFlag((int)LanguageID.ChineseT, CHK_LangCHT.Checked); + + // Set Local Dexes + entry.SetLocalPaldea((byte)CB_PaldeaForm.SelectedIndex, (byte)CB_PaldeaGender.SelectedIndex, CHK_PaldeaShiny.Checked ? (byte)1 : (byte)0); + entry.SetLocalKitakami((byte)CB_KitakamiForm.SelectedIndex, (byte)CB_KitakamiGender.SelectedIndex, CHK_KitakamiShiny.Checked ? (byte)1 : (byte)0); + entry.SetLocalBlueberry((byte)CB_BlueberryForm.SelectedIndex, (byte)CB_BlueberryGender.SelectedIndex, CHK_BlueberryShiny.Checked ? (byte)1 : (byte)0); + } + + private void B_Cancel_Click(object sender, EventArgs e) + { + Close(); + } + + private void B_Save_Click(object sender, EventArgs e) + { + SetEntry(lastIndex); + Origin.CopyChangesFrom(SAV); + Close(); + } + + private void B_GiveAll_Click(object sender, EventArgs e) + { + SetEntry(lastIndex); + bool shiny = ModifierKeys == Keys.Shift; + var species = GetSpecies(lastIndex); + Dex.SetDexEntryAll(species, shiny); + System.Media.SystemSounds.Asterisk.Play(); + GetEntry(species); + } + + private void B_Modify_Click(object sender, EventArgs e) + { + Button btn = (Button)sender; + modifyMenu.Show(btn.PointToScreen(new Point(0, btn.Height))); + } + + private void SeenNone(object sender, EventArgs e) + { + var species = GetSpecies(lastIndex); + SetEntry(species); + Dex.SeenNone(); + System.Media.SystemSounds.Asterisk.Play(); + GetEntry(species); + } + + private void SeenAll(object sender, EventArgs e) + { + var species = GetSpecies(lastIndex); + SetEntry(species); + bool shiny = ModifierKeys == Keys.Shift; + Dex.SeenAll(shiny); + System.Media.SystemSounds.Asterisk.Play(); + GetEntry(species); + } + + private void CaughtNone(object sender, EventArgs e) + { + var species = GetSpecies(lastIndex); + SetEntry(species); + Dex.CaughtNone(); + System.Media.SystemSounds.Asterisk.Play(); + GetEntry(species); + } + + private void CaughtAll(object sender, EventArgs e) + { + var species = GetSpecies(lastIndex); + SetEntry(species); + bool shiny = ModifierKeys == Keys.Shift; + Dex.CaughtAll(shiny); + System.Media.SystemSounds.Asterisk.Play(); + GetEntry(species); + } + + private void CompleteDex(object sender, EventArgs e) + { + var species = GetSpecies(lastIndex); + SetEntry(species); + bool shiny = ModifierKeys == Keys.Shift; + Dex.CompleteDex(shiny); + System.Media.SystemSounds.Asterisk.Play(); + GetEntry(species); + } +} diff --git a/PKHeX.WinForms/Subforms/Save Editors/Gen9/SAV_Raid9.cs b/PKHeX.WinForms/Subforms/Save Editors/Gen9/SAV_Raid9.cs index b5b72b9cc..855a4e972 100644 --- a/PKHeX.WinForms/Subforms/Save Editors/Gen9/SAV_Raid9.cs +++ b/PKHeX.WinForms/Subforms/Save Editors/Gen9/SAV_Raid9.cs @@ -20,12 +20,26 @@ public partial class SAV_Raid9 : Form Raids = raid; CB_Raid.Items.AddRange(Enumerable.Range(1, raid.CountUsed).Select(z => (object)$"Raid {z:000}").ToArray()); CB_Raid.SelectedIndex = 0; + LoadSeeds(raid); + } - TB_SeedToday.Text = Raids.CurrentSeed.ToString("X16"); - TB_SeedTomorrow.Text = Raids.TomorrowSeed.ToString("X16"); + private void LoadSeeds(RaidSpawnList9 raid) + { + if (raid.HasSeeds) + { + TB_SeedToday.Text = Raids.CurrentSeed.ToString("X16"); + TB_SeedTomorrow.Text = Raids.TomorrowSeed.ToString("X16"); - TB_SeedToday.Validated += UpdateStringSeed; - TB_SeedTomorrow.Validated += UpdateStringSeed; + TB_SeedToday.Validated += UpdateStringSeed; + TB_SeedTomorrow.Validated += UpdateStringSeed; + } + else + { + L_SeedCurrent.Visible = false; + L_SeedTomorrow.Visible = false; + TB_SeedToday.Visible = false; + TB_SeedTomorrow.Visible = false; + } } private void LoadRaid(int index) => PG_Raid.SelectedObject = Raids.GetRaid(index);