diff --git a/PKHeX.Core/Game/GameInfo.cs b/PKHeX.Core/Game/GameInfo.cs index 5910d2f92..dcfcbdf92 100644 --- a/PKHeX.Core/Game/GameInfo.cs +++ b/PKHeX.Core/Game/GameInfo.cs @@ -185,7 +185,7 @@ namespace PKHeX.Core itemlist[842] += " (SM)"; // Fishing Rod // Append Z-Crystal flagging - foreach (var i in Legal.Pouch_ZCrystal_SM) + foreach (var i in Legal.Pouch_ZCrystal_USUM) itemlist[i] += " [Z]"; } private void SanitizeMetLocations() diff --git a/PKHeX.Core/Legality/Core.cs b/PKHeX.Core/Legality/Core.cs index fa0614db4..06bdaf495 100644 --- a/PKHeX.Core/Legality/Core.cs +++ b/PKHeX.Core/Legality/Core.cs @@ -2178,33 +2178,31 @@ namespace PKHeX.Core info = PersonalTable.B2W2[species]; moves.AddRange(TypeTutor6.Where((t, i) => info.TypeTutors[i])); if (pkm.InhabitedGeneration(5) && specialTutors) - { - PersonalInfo pi = PersonalTable.B2W2.GetFormeEntry(species, form); - for (int i = 0; i < Tutors_B2W2.Length; i++) - for (int b = 0; b < Tutors_B2W2[i].Length; b++) - if (pi.SpecialTutors[i][b]) - moves.Add(Tutors_B2W2[i][b]); - } + moves.AddRange(GetTutors(PersonalTable.B2W2, Tutors_B2W2)); break; case 6: info = PersonalTable.AO[species]; moves.AddRange(TypeTutor6.Where((t, i) => info.TypeTutors[i])); if (pkm.InhabitedGeneration(6) && specialTutors && (pkm.AO || !pkm.IsUntraded)) - { - PersonalInfo pi = PersonalTable.AO.GetFormeEntry(species, form); - for (int i = 0; i < Tutors_AO.Length; i++) - for (int b = 0; b < Tutors_AO[i].Length; b++) - if (pi.SpecialTutors[i][b]) - moves.Add(Tutors_AO[i][b]); - } + moves.AddRange(GetTutors(PersonalTable.AO, Tutors_AO)); break; case 7: info = PersonalTable.USUM.GetFormeEntry(species, form); moves.AddRange(TypeTutor6.Where((t, i) => info.TypeTutors[i])); - // No special tutors in G7 + if (pkm.InhabitedGeneration(7) && specialTutors && (pkm.USUM || !pkm.IsUntraded)) + moves.AddRange(GetTutors(PersonalTable.USUM, Tutors_USUM)); break; } return moves.Distinct(); + + IEnumerable GetTutors(PersonalTable t, IReadOnlyList tutors) + { + var pi = t.GetFormeEntry(species, form); + for (int i = 0; i < tutors.Count; i++) + for (int b = 0; b < tutors[i].Length; b++) + if (pi.SpecialTutors[i][b]) + yield return tutors[i][b]; + } } internal static bool IsTradedKadabraG1(PKM pkm) { diff --git a/PKHeX.Core/Legality/Structures/EncounterStatic.cs b/PKHeX.Core/Legality/Structures/EncounterStatic.cs index cfcae608c..290b86787 100644 --- a/PKHeX.Core/Legality/Structures/EncounterStatic.cs +++ b/PKHeX.Core/Legality/Structures/EncounterStatic.cs @@ -1,4 +1,6 @@ -namespace PKHeX.Core +using System.Collections.Generic; + +namespace PKHeX.Core { /// /// Static Encounter Data @@ -78,15 +80,13 @@ }; } - public EncounterStatic[] DreamRadarClone() + public IEnumerable DreamRadarClone() { - EncounterStatic[] Encounters = new EncounterStatic[8]; for (int i = 0; i < 8; i++) - Encounters[i] = DreamRadarClone(5 * i + 5); //Level from 5->40 depends on the number of badage - return Encounters; + yield return DreamRadarClone(5 * i + 5); //Level from 5->40 depends on the number of badges } - public EncounterStatic DreamRadarClone(int level) + private EncounterStatic DreamRadarClone(int level) { return new EncounterStatic { diff --git a/PKHeX.Core/Legality/Tables7.cs b/PKHeX.Core/Legality/Tables7.cs index ee1544d72..08379a5f9 100644 --- a/PKHeX.Core/Legality/Tables7.cs +++ b/PKHeX.Core/Legality/Tables7.cs @@ -50,6 +50,13 @@ namespace PKHeX.Core #endregion + internal static readonly int[][] Tutors_USUM = + { + new int[0], // todo + new int[0], // todo + new int[0], // todo + new int[0], // todo + }; internal static readonly ushort[] Pouch_Regular_SM = // 00 { 068, 069, 070, 071, 072, 073, 074, 075, 076, 077, 078, 079, 080, 081, 082, 083, 084, 085, 086, 087, @@ -83,6 +90,9 @@ namespace PKHeX.Core 705, 706, 765, 773, 797, 841, 842, 843, 845, 847, 850, 857, 858, 860, }; + internal static readonly ushort[] Pouch_Key_USUM = { + // todo + }; internal static readonly ushort[] Pouch_TMHM_SM = { // 02 328, 329, 330, 331, 332, 333, 334, 335, 336, 337, 338, 339, 340, 341, 342, 343, 344, 345, 346, 347, 348, 349, 350, 351, 352, 353, 354, 355, 356, 357, 358, 359, 360, 361, 362, 363, @@ -106,8 +116,14 @@ namespace PKHeX.Core internal static readonly ushort[] Pouch_ZCrystalHeld_SM = { // Piece 776, 777, 778, 779, 780, 781, 782, 783, 784, 785, 786, 787, 788, 789, 790, 791, 792, 793, 794, 798, 799, 800, 801, 802, 803, 804, 805, 806, 836 }; - public static readonly Dictionary ZCrystalDictionary = Pouch_ZCrystal_SM - .Zip(Pouch_ZCrystalHeld_SM, (k, v) => new { Key = (int)k, Value = (int)v }) + internal static readonly ushort[] Pouch_ZCrystal_USUM = Pouch_ZCrystal_SM.Concat(new ushort[] { // Bead + // todo + }).ToArray(); + internal static readonly ushort[] Pouch_ZCrystalHeld_USUM = Pouch_ZCrystalHeld_SM.Concat(new ushort[] { // Piece + // todo + }).ToArray(); + public static readonly Dictionary ZCrystalDictionary = Pouch_ZCrystal_USUM + .Zip(Pouch_ZCrystalHeld_USUM, (k, v) => new { Key = (int)k, Value = (int)v }) .ToDictionary(x => x.Key, x => x.Value); internal static readonly ushort[] HeldItems_SM = new ushort[1].Concat(Pouch_Items_SM).Concat(Pouch_Berries_SM).Concat(Pouch_Medicine_SM).Concat(Pouch_ZCrystalHeld_SM).ToArray(); internal static readonly ushort[] HeldItems_USUM = HeldItems_SM; // todo diff --git a/PKHeX.Core/PKM/PK7.cs b/PKHeX.Core/PKM/PK7.cs index fc8be2deb..5a34a1c7a 100644 --- a/PKHeX.Core/PKM/PK7.cs +++ b/PKHeX.Core/PKM/PK7.cs @@ -8,7 +8,7 @@ namespace PKHeX.Core { public static readonly byte[] ExtraBytes = { - 0x2A, // Old Marking Value + 0x2A, // Old Marking Value (PelagoEventStatus) // 0x36, 0x37, // Unused Ribbons 0x58, 0x59, 0x73, 0x90, 0x91, 0x9E, 0x9F, 0xA0, 0xA1, 0xA7, 0xAA, 0xAB, 0xAC, 0xAD, 0xC8, 0xC9, 0xD7, 0xE4, 0xE5, 0xE6, 0xE7 }; diff --git a/PKHeX.Core/Saves/SAV1.cs b/PKHeX.Core/Saves/SAV1.cs index 13764e349..b89740235 100644 --- a/PKHeX.Core/Saves/SAV1.cs +++ b/PKHeX.Core/Saves/SAV1.cs @@ -21,7 +21,7 @@ namespace PKHeX.Core { Data = data == null ? new byte[SaveUtil.SIZE_G1RAW] : (byte[])data.Clone(); BAK = (byte[])Data.Clone(); - Exportable = !Data.SequenceEqual(new byte[Data.Length]); + Exportable = !Data.All(z => z == 0); if (data == null) Version = GameVersion.RBY; diff --git a/PKHeX.Core/Saves/SAV2.cs b/PKHeX.Core/Saves/SAV2.cs index 4aa2d7548..503312446 100644 --- a/PKHeX.Core/Saves/SAV2.cs +++ b/PKHeX.Core/Saves/SAV2.cs @@ -23,7 +23,7 @@ namespace PKHeX.Core { Data = data == null ? new byte[SaveUtil.SIZE_G2RAW_U] : (byte[])data.Clone(); BAK = (byte[])Data.Clone(); - Exportable = !Data.SequenceEqual(new byte[Data.Length]); + Exportable = !Data.All(z => z == 0); if (data == null) Version = GameVersion.C; diff --git a/PKHeX.Core/Saves/SAV3.cs b/PKHeX.Core/Saves/SAV3.cs index 219e2ebbe..c76b6f1ea 100644 --- a/PKHeX.Core/Saves/SAV3.cs +++ b/PKHeX.Core/Saves/SAV3.cs @@ -44,7 +44,7 @@ namespace PKHeX.Core { Data = data == null ? new byte[SaveUtil.SIZE_G3RAW] : (byte[])data.Clone(); BAK = (byte[])Data.Clone(); - Exportable = !Data.SequenceEqual(new byte[Data.Length]); + Exportable = !Data.All(z => z == 0); if (data == null) Version = GameVersion.FRLG; diff --git a/PKHeX.Core/Saves/SAV3Colosseum.cs b/PKHeX.Core/Saves/SAV3Colosseum.cs index 9c4ba2bf3..fe56f6372 100644 --- a/PKHeX.Core/Saves/SAV3Colosseum.cs +++ b/PKHeX.Core/Saves/SAV3Colosseum.cs @@ -48,7 +48,7 @@ namespace PKHeX.Core { Data = data == null ? new byte[SaveUtil.SIZE_G3COLO] : (byte[])data.Clone(); BAK = (byte[])Data.Clone(); - Exportable = !Data.SequenceEqual(new byte[Data.Length]); + Exportable = !Data.All(z => z == 0); if (SaveUtil.GetIsG3COLOSAV(Data) != GameVersion.COLO) return; diff --git a/PKHeX.Core/Saves/SAV3RSBox.cs b/PKHeX.Core/Saves/SAV3RSBox.cs index 0eb77b727..68cd3db67 100644 --- a/PKHeX.Core/Saves/SAV3RSBox.cs +++ b/PKHeX.Core/Saves/SAV3RSBox.cs @@ -26,8 +26,8 @@ namespace PKHeX.Core { Data = data == null ? new byte[SaveUtil.SIZE_G3BOX] : (byte[])data.Clone(); BAK = (byte[])Data.Clone(); - Exportable = !Data.SequenceEqual(new byte[Data.Length]); - + Exportable = !Data.All(z => z == 0); + if (SaveUtil.GetIsG3BOXSAV(Data) != GameVersion.RSBOX) return; diff --git a/PKHeX.Core/Saves/SAV3XD.cs b/PKHeX.Core/Saves/SAV3XD.cs index a3217ee44..5988244a7 100644 --- a/PKHeX.Core/Saves/SAV3XD.cs +++ b/PKHeX.Core/Saves/SAV3XD.cs @@ -40,7 +40,7 @@ namespace PKHeX.Core { Data = data == null ? new byte[SaveUtil.SIZE_G3XD] : (byte[])data.Clone(); BAK = (byte[])Data.Clone(); - Exportable = !Data.SequenceEqual(new byte[Data.Length]); + Exportable = !Data.All(z => z == 0); if (SaveUtil.GetIsG3XDSAV(Data) != GameVersion.XD) return; diff --git a/PKHeX.Core/Saves/SAV4.cs b/PKHeX.Core/Saves/SAV4.cs index 3824e8dc7..950f2bfb6 100644 --- a/PKHeX.Core/Saves/SAV4.cs +++ b/PKHeX.Core/Saves/SAV4.cs @@ -16,7 +16,7 @@ namespace PKHeX.Core { Data = data == null ? new byte[SaveUtil.SIZE_G4RAW] : (byte[])data.Clone(); BAK = (byte[])Data.Clone(); - Exportable = !Data.SequenceEqual(new byte[Data.Length]); + Exportable = !Data.All(z => z == 0); // Get Version if (data == null) diff --git a/PKHeX.Core/Saves/SAV5.cs b/PKHeX.Core/Saves/SAV5.cs index 901582bcb..594d526a7 100644 --- a/PKHeX.Core/Saves/SAV5.cs +++ b/PKHeX.Core/Saves/SAV5.cs @@ -19,7 +19,7 @@ namespace PKHeX.Core { Data = data == null ? new byte[SaveUtil.SIZE_G5RAW] : (byte[])data.Clone(); BAK = (byte[])Data.Clone(); - Exportable = !Data.SequenceEqual(new byte[Data.Length]); + Exportable = !Data.All(z => z == 0); // Get Version if (data == null) diff --git a/PKHeX.Core/Saves/SAV6.cs b/PKHeX.Core/Saves/SAV6.cs index 61d4b9129..3040a1330 100644 --- a/PKHeX.Core/Saves/SAV6.cs +++ b/PKHeX.Core/Saves/SAV6.cs @@ -19,7 +19,7 @@ namespace PKHeX.Core { Data = data == null ? new byte[SaveUtil.SIZE_G6ORAS] : (byte[])data.Clone(); BAK = (byte[])Data.Clone(); - Exportable = !Data.SequenceEqual(new byte[Data.Length]); + Exportable = !Data.All(z => z == 0); // Load Info GetBlockInfo(); diff --git a/PKHeX.Core/Saves/SAV7.cs b/PKHeX.Core/Saves/SAV7.cs index 22a615b46..1f2c55d77 100644 --- a/PKHeX.Core/Saves/SAV7.cs +++ b/PKHeX.Core/Saves/SAV7.cs @@ -24,18 +24,18 @@ namespace PKHeX.Core { Data = data == null ? new byte[SaveUtil.SIZE_G7SM] : (byte[])data.Clone(); BAK = (byte[])Data.Clone(); - Exportable = !Data.SequenceEqual(new byte[Data.Length]); + Exportable = !Data.All(z => z == 0); // Load Info GetBlockInfo(); GetSAVOffsets(); - HeldItems = Legal.HeldItems_SM; + HeldItems = USUM ? Legal.HeldItems_USUM : Legal.HeldItems_SM; Personal = USUM ? PersonalTable.USUM : PersonalTable.SM; if (!Exportable) ClearBoxes(); - var demo = new byte[0x4C4].SequenceEqual(Data.Skip(PCLayout).Take(0x4C4)); // up to Battle Box values + var demo = !USUM && Data.Skip(PCLayout).Take(0x4C4).All(z => z == 0); // up to Battle Box values if (demo || !Exportable) { PokeDex = -1; // Disabled @@ -44,28 +44,10 @@ namespace PKHeX.Core } else // Valid slot locking info present { - int lockedCount = 0, teamCount = 0; - for (int i = 0; i < TeamCount; i++) - { - bool locked = Data[PCBackgrounds - TeamCount - i] == 1; - for (int j = 0; j < 6; j++) - { - short val = BitConverter.ToInt16(Data, BattleBoxFlags + (i*6 + j) * 2); - if (val < 0) - continue; - - var slotVal = (BoxSlotCount*(val >> 8) + (val & 0xFF)) & 0xFFFF; - - if (locked) - LockedSlots[lockedCount++] = slotVal; - else TeamSlots[teamCount++] = slotVal; - } - } - Array.Resize(ref LockedSlots, lockedCount); - Array.Resize(ref TeamSlots, teamCount); + LoadLockedSlots(); } } - + // Configuration public override SaveFile Clone() { return new SAV7(Data); } @@ -822,8 +804,8 @@ namespace PKHeX.Core new InventoryPouch(InventoryType.Items, Legal.Pouch_Items_SM, 999, OFS_PouchHeldItem), new InventoryPouch(InventoryType.TMHMs, Legal.Pouch_TMHM_SM, 1, OFS_PouchTMHM), new InventoryPouch(InventoryType.Berries, Legal.Pouch_Berries_SM, 999, OFS_PouchBerry), - new InventoryPouch(InventoryType.KeyItems, Legal.Pouch_Key_SM, 1, OFS_PouchKeyItem), - new InventoryPouch(InventoryType.ZCrystals, Legal.Pouch_ZCrystal_SM, 1, OFS_PouchZCrystals), + new InventoryPouch(InventoryType.KeyItems, USUM ? Legal.Pouch_Key_USUM : Legal.Pouch_Key_SM, 1, OFS_PouchKeyItem), + new InventoryPouch(InventoryType.ZCrystals, USUM ? Legal.Pouch_ZCrystal_USUM : Legal.Pouch_ZCrystal_SM, 1, OFS_PouchZCrystals), }; foreach (var p in pouch) p.GetPouch7(ref Data); @@ -1178,6 +1160,28 @@ namespace PKHeX.Core int slotIndex = slot + BoxSlotCount * box; return TeamSlots.Any(s => s == slotIndex); } + private void LoadLockedSlots() + { + int lockedCount = 0, teamCount = 0; + for (int i = 0; i < TeamCount; i++) + { + bool locked = Data[PCBackgrounds - TeamCount - i] == 1; + for (int j = 0; j < 6; j++) + { + short val = BitConverter.ToInt16(Data, BattleBoxFlags + (i * 6 + j) * 2); + if (val < 0) + continue; + + var slotVal = (BoxSlotCount * (val >> 8) + (val & 0xFF)) & 0xFFFF; + + if (locked) + LockedSlots[lockedCount++] = slotVal; + else TeamSlots[teamCount++] = slotVal; + } + } + Array.Resize(ref LockedSlots, lockedCount); + Array.Resize(ref TeamSlots, teamCount); + } public override int DaycareSeedSize => 32; // 128 bits public override int GetDaycareSlotOffset(int loc, int slot) diff --git a/PKHeX.Core/Saves/SaveFile.cs b/PKHeX.Core/Saves/SaveFile.cs index 27b8dd772..b6ab17433 100644 --- a/PKHeX.Core/Saves/SaveFile.cs +++ b/PKHeX.Core/Saves/SaveFile.cs @@ -659,8 +659,10 @@ namespace PKHeX.Core public virtual void SetSeen(int species, bool seen) { } public virtual bool GetCaught(int species) => false; public virtual void SetCaught(int species, bool caught) { } - public int SeenCount => HasPokeDex ? new bool[MaxSpeciesID].Where((b, i) => GetSeen(i+1)).Count() : 0; - public int CaughtCount => HasPokeDex ? new bool[MaxSpeciesID].Where((b, i) => GetCaught(i+1)).Count() : 0; + public int SeenCount => HasPokeDex ? Enumerable.Range(1, MaxSpeciesID).Count(GetSeen) : 0; + public int CaughtCount => HasPokeDex ? Enumerable.Range(1, MaxSpeciesID).Count(GetCaught) : 0; + public decimal PercentSeen => (decimal) SeenCount / MaxSpeciesID; + public decimal PercentCaught => (decimal)CaughtCount / MaxSpeciesID; public byte[] GetData(int Offset, int Length) {