using System; using System.Collections.Generic; using System.IO; namespace PKHeX.Core { public abstract class Learnset { protected int Count; protected int[] Moves; protected int[] Levels; /// /// Returns the moves a Pokémon can learn between the specified level range. /// /// Maximum level /// Minimum level /// Array of Move IDs public int[] GetMoves(int maxLevel, int minLevel = 0) { if (minLevel <= 1 && maxLevel >= 100) return Moves; if (minLevel > maxLevel) return new int[0]; int start = Array.FindIndex(Levels, z => z >= minLevel); if (start < 0) return new int[0]; int end = Array.FindLastIndex(Levels, z => z <= maxLevel); if (end < 0) return new int[0]; int[] result = new int[end - start + 1]; Array.Copy(Moves, start, result, 0, result.Length); return result; } /// Returns the moves a Pokémon would have if it were encountered at the specified level. /// In Generation 1, it is not possible to learn any moves lower than these encounter moves. /// The level the Pokémon was encountered at. /// The amount of move slots to return. /// Array of Move IDs public int[] GetEncounterMoves(int level, int count = 4) { if (count == 0 || Moves.Length == 0) return new int[0]; int end = Array.FindLastIndex(Levels, z => z <= level); if (end < 0) return new int[0]; // Moves can be duplicated in the learnset. // When generating the encounter, loop backwards until all moves are filled or no moves are left. // Insert moves in reverse so that the first move is from the earliest position in the learnset. int[] result = new int[count]; var list = new List{Moves[end]}; while (end-- > 0) { int move = Moves[end]; if (list.Contains(move)) continue; list.Insert(0, move); if (list.Count == count) break; } list.CopyTo(result); return result; } /// Returns the index of the lowest level move if the Pokémon were encountered at the specified level. /// Helps determine the minimum level an encounter can be at. /// The level the Pokémon was encountered at. /// Array of Move IDs public int GetMinMoveLevel(int level) { if (Levels.Length == 0) return 1; int end = Array.FindLastIndex(Levels, z => z <= level); return Math.Max(end - 4, 1); } /// Returns the level that a Pokémon can learn the specified move. /// Move ID /// Level the move is learned at. If the result is below 0, it cannot be learned by levelup. public int GetLevelLearnMove(int move) { int index = Array.IndexOf(Moves, move); return index < 0 ? 0 : Levels[index]; } } public class Learnset1 : Learnset { private Learnset1(byte[] data, ref int offset) { var moves = new List(); var levels = new List(); while (data[offset] != 0) { levels.Add(data[offset++]); moves.Add(data[offset++]); } ++offset; Moves = moves.ToArray(); Levels = levels.ToArray(); Count = Moves.Length; } public static Learnset[] GetArray(byte[] input, int maxSpecies) { var data = new Learnset[maxSpecies + 1]; int offset = 0; for (int s = 0; s < data.Length; s++) data[s] = new Learnset1(input, ref offset); return data; } } public class Learnset6 : Learnset { private Learnset6(byte[] data) { if (data.Length < 4 || data.Length % 4 != 0) { Count = 0; Levels = new int[0]; Moves = new int[0]; return; } Count = data.Length / 4 - 1; Moves = new int[Count]; Levels = new int[Count]; using (BinaryReader br = new BinaryReader(new MemoryStream(data))) for (int i = 0; i < Count; i++) { Moves[i] = br.ReadInt16(); Levels[i] = br.ReadInt16(); } } public static Learnset[] GetArray(byte[][] entries) { Learnset[] data = new Learnset[entries.Length]; for (int i = 0; i < data.Length; i++) data[i] = new Learnset6(entries[i]); return data; } } public class Learnset7 : Learnset { private Learnset7(byte[] data) { if (data.Length < 4 || data.Length % 4 != 0) { Count = 0; Levels = new int[0]; Moves = new int[0]; return; } Count = data.Length / 4 - 1; Moves = new int[Count]; Levels = new int[Count]; using (BinaryReader br = new BinaryReader(new MemoryStream(data))) for (int i = 0; i < Count; i++) { Moves[i] = br.ReadInt16(); Levels[i] = br.ReadInt16(); } } public static Learnset[] GetArray(byte[][] entries) { Learnset[] data = new Learnset[entries.Length]; for (int i = 0; i < data.Length; i++) data[i] = new Learnset7(entries[i]); return data; } } }