using System; namespace PKHeX.Core { /// /// Pokédex structure used for Generation 5 games. /// public sealed class Zukan5 : Zukan { protected override int OFS_SEEN => OFS_CAUGHT + BitSeenSize; protected override int OFS_CAUGHT => 0x8; protected override int BitSeenSize => 0x54; protected override int DexLangFlagByteCount => 7; protected override int DexLangIDCount => 7; public Zukan5(SAV5B2W2 sav, int dex, int langflag) : base(sav, dex, langflag) { DexFormIndexFetcher = DexFormUtil.GetDexFormIndexB2W2; } public Zukan5(SAV5BW sav, int dex, int langflag) : base(sav, dex, langflag) { DexFormIndexFetcher = DexFormUtil.GetDexFormIndexBW; } public readonly Func DexFormIndexFetcher; protected override int GetDexLangFlag(int lang) { lang--; if (lang > 5) lang--; // 0-6 language vals if ((uint)lang > 5) return -1; return lang; } protected override bool GetSaneFormsToIterate(int species, out int formStart, out int formEnd, int formIn) { formStart = 0; formEnd = 0; return false; } protected override void SetSpindaDexData(PKM pkm, bool alreadySeen) { } protected override void SetAllDexFlagsLanguage(int bit, int lang, bool value = true) { lang = GetDexLangFlag(lang); if (lang < 0) return; // Set the Language int lbit = (bit * DexLangIDCount) + lang; if (bit < 493) // shifted by 1, Gen5 species do not have international language bits SetFlag(PokeDexLanguageFlags, lbit, value); } protected override void SetAllDexSeenFlags(int baseBit, int form, int gender, bool isShiny, bool value = true) { var shiny = isShiny ? 1 : 0; SetDexFlags(baseBit, baseBit, gender, shiny); SetFormFlags(baseBit + 1, form, shiny, value); } public override void SetDex(PKM pkm) { if (pkm.Species is 0 or > Legal.MaxSpeciesID_5) return; if (pkm.IsEgg) // do not add return; int bit = pkm.Species - 1; SetCaughtFlag(bit); // Set the [Species/Gender/Shiny] Seen Flag SetAllDexSeenFlags(bit, pkm.Form, pkm.Gender, pkm.IsShiny); SetAllDexFlagsLanguage(bit, pkm.Language); SetFormFlags(pkm); } private void SetCaughtFlag(int bit) => SetFlag(OFS_CAUGHT, bit); protected override void SetDisplayedFlag(int baseBit, int formBit, bool value, int shift) { if (!value) { SetDisplayed(baseBit, shift, false); return; } bool displayed = GetIsSpeciesAnyDisplayed(baseBit); if (displayed) return; // no need to set another bit SetDisplayed(baseBit, shift, true); } private bool GetIsSpeciesAnyDisplayed(int baseBit) { // Check Displayed Status for base form for (int i = 0; i < 4; i++) { if (GetDisplayed(baseBit, i)) return true; } return false; } private int FormLen => SAV is SAV5B2W2 ? 0xB : 0x9; private int FormDex => 0x8 + (BitSeenSize * 9); private void SetFormFlags(PKM pkm) { int species = pkm.Species; int form = pkm.Form; var shiny = pkm.IsShiny ? 1 : 0; SetFormFlags(species, form, shiny); } private void SetFormFlags(int species, int form, int shiny, bool value = true) { int fc = SAV.Personal[species].FormCount; int f = DexFormIndexFetcher(species, fc); if (f < 0) return; var bit = f + form; // Set Form Seen Flag SetFormFlag(bit, shiny, value); // Set Displayed Flag if necessary, check all flags if (!value || !GetIsFormDisplayed(f, fc)) SetFormFlag(bit, 2 + shiny, value); } public bool GetFormFlag(int formIndex, int flagRegion) => GetFlag(FormDex + (FormLen * flagRegion), formIndex); public void SetFormFlag(int formIndex, int flagRegion, bool value = true) => SetFlag(FormDex + (FormLen * flagRegion), formIndex, value); private bool GetIsFormDisplayed(int f, int fc) { for (int i = 0; i < fc; i++) { var index = f + i; if (GetFormFlag(index, 2)) // Nonshiny return true; // already set if (GetFormFlag(index, 3)) // Shiny return true; // already set } return false; } public bool[] GetLanguageBitflags(int species) { var result = new bool[DexLangIDCount]; int bit = species - 1; for (int i = 0; i < DexLangIDCount; i++) { int lbit = (bit * DexLangIDCount) + i; result[i] = GetFlag(PokeDexLanguageFlags, lbit); } return result; } public void SetLanguageBitflags(int species, bool[] value) { int bit = species - 1; for (int i = 0; i < DexLangIDCount; i++) { int lbit = (bit * DexLangIDCount) + i; SetFlag(PokeDexLanguageFlags, lbit, value[i]); } } public void ToggleLanguageFlagsAll(bool value) { var arr = GetBlankLanguageBits(value); for (int i = 1; i <= SAV.MaxSpeciesID; i++) SetLanguageBitflags(i, arr); } public void ToggleLanguageFlagsSingle(int species, bool value) { var arr = GetBlankLanguageBits(value); SetLanguageBitflags(species, arr); } private bool[] GetBlankLanguageBits(bool value) { var result = new bool[DexLangIDCount]; for (int i = 0; i < DexLangIDCount; i++) result[i] = value; return result; } } }