PKHeX/Legality/Data.cs
Kaphotics 4e9ea707f9 Fix untraded Glalie/Steelix link gift history chk
Has an OT, HT=player but doesn't get a geolocation, behaves like a wc6
gift.
2016-05-08 18:11:31 -07:00

400 lines
13 KiB
C#

using System;
using System.IO;
using System.Linq;
namespace PKHeX
{
public class Learnset
{
public readonly int Count;
public readonly int[] Moves, Levels;
public Learnset(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 Learnset(entries[i]);
return data;
}
public int[] getMoves(int level)
{
for (int i = 0; i < Levels.Length; i++)
if (Levels[i] > level)
return Moves.Take(i).ToArray();
return Moves;
}
}
public class EggMoves
{
public readonly int Count;
public readonly int[] Moves;
public EggMoves(byte[] data)
{
if (data.Length < 2 || data.Length % 2 != 0)
{ Count = 0; Moves = new int[0]; return; }
using (BinaryReader br = new BinaryReader(new MemoryStream(data)))
{
Moves = new int[Count = br.ReadUInt16()];
for (int i = 0; i < Count; i++)
Moves[i] = br.ReadUInt16();
}
}
public static EggMoves[] getArray(byte[][] entries)
{
EggMoves[] data = new EggMoves[entries.Length];
for (int i = 0; i < data.Length; i++)
data[i] = new EggMoves(entries[i]);
return data;
}
}
public class Evolutions
{
public readonly DexLevel[] Evos = new DexLevel[0];
public Evolutions(byte[] data)
{
int Count = data.Length / 4;
if (data.Length < 4 || data.Length % 4 != 0) return;
Evos = new DexLevel[Count];
for (int i = 0; i < data.Length; i += 4)
{
Evos[i/4] = new DexLevel
{
Species = BitConverter.ToUInt16(data, i),
Level = BitConverter.ToUInt16(data, i + 2)
};
}
}
public static Evolutions[] getArray(byte[][] entries)
{
Evolutions[] data = new Evolutions[entries.Length];
for (int i = 0; i < data.Length; i++)
data[i] = new Evolutions(entries[i]);
return data;
}
}
public class DexLevel
{
public int Species;
public int Level;
}
public class EncounterArea
{
public int Location;
public EncounterSlot[] Slots;
public EncounterArea() { }
public EncounterArea(byte[] data)
{
Location = BitConverter.ToUInt16(data, 0);
Slots = new EncounterSlot[(data.Length-2)/4];
for (int i = 0; i < Slots.Length; i++)
{
ushort SpecForm = BitConverter.ToUInt16(data, 2 + i*4);
Slots[i] = new EncounterSlot
{
Species = SpecForm & 0x7FF,
Form = SpecForm >> 11,
LevelMin = data[4 + i*4],
LevelMax = data[5 + i*4],
};
}
}
public static EncounterArea[] getArray(byte[][] entries)
{
EncounterArea[] data = new EncounterArea[entries.Length];
for (int i = 0; i < data.Length; i++)
data[i] = new EncounterArea(entries[i]);
return data;
}
}
public class EncounterSlot
{
public int Species;
public int Form;
public int LevelMin;
public int LevelMax;
public SlotType Type = SlotType.Any;
public bool AllowDexNav;
public bool Pressure;
public bool DexNav;
public bool WhiteFlute;
public bool BlackFlute;
public bool Normal => !(WhiteFlute || BlackFlute || DexNav);
public EncounterSlot() { }
public EncounterSlot(EncounterSlot template)
{
Species = template.Species;
AllowDexNav = template.AllowDexNav;
LevelMax = template.LevelMax;
LevelMin = template.LevelMin;
Type = template.Type;
Pressure = template.Pressure;
}
}
public enum SlotType
{
Any,
Grass,
Rough_Terrain,
Yellow_Flowers,
Purple_Flowers,
Red_Flowers,
Surf,
Old_Rod,
Good_Rod,
Super_Rod,
Rock_Smash,
Horde,
FriendSafari,
Special,
}
public class EncounterStatic
{
public int Species;
public int Level;
public int Location = 0;
public int Ability = 0;
public int Form = 0;
public bool? Shiny = null; // false = never, true = always, null = possible
public int[] Relearn = new int[4];
public int Gender = -1;
public int EggLocation = 0;
public Nature Nature = Nature.Random;
public bool Gift = false;
public int Ball = 4; // Gift Only
public GameVersion Version = GameVersion.Any;
public int[] IVs = {-1, -1, -1, -1, -1, -1};
public bool IV3;
public int[] Contest = {0, 0, 0, 0, 0, 0};
}
public class EncounterTrade
{
public int Species;
public int Level;
public int Location = 30001;
public int Ability = 0;
public Nature Nature = Nature.Random;
public int TID;
public int SID = 0;
public int[] IVs = { -1, -1, -1, -1, -1, -1 };
public int[] Moves;
public int Form = 0;
public bool Shiny = false;
public int Gender = -1;
}
public class EncounterLink
{
public int Species;
public int Level;
public int Location = 30011;
public int Ability = 4;
public int Ball = 4; // Pokéball
public Nature Nature = Nature.Random;
public int[] IVs = { -1, -1, -1, -1, -1, -1 };
public int FlawlessIVs = 0;
public bool Classic = true;
public bool Fateful = false;
public int[] RelearnMoves = new int[4];
public bool XY = true;
public bool ORAS = true;
public bool? Shiny = false;
public bool OT = false;
}
public enum Nature
{
Random = -1,
Hardy, Lonely, Brave, Adamant, Naughty, Bold,
Docile, Relaxed, Impish, Lax, Timid, Hasty,
Serious, Jolly, Naive, Modest, Mild, Quiet,
Bashful, Rash, Calm, Gentle, Sassy, Careful,
Quirky,
}
public class PersonalInfo
{
internal static int SizeAO = 0x50;
internal static int SizeXY = 0x40;
public byte HP, ATK, DEF, SPE, SPA, SPD;
public int BST;
public int EV_HP, EV_ATK, EV_DEF, EV_SPE, EV_SPA, EV_SPD;
public byte[] Types = new byte[2];
public byte CatchRate, EvoStage;
public ushort[] Items = new ushort[3];
public byte Gender, HatchCycles, BaseFriendship, EXPGrowth;
public byte[] EggGroups = new byte[2];
public byte[] Abilities = new byte[3];
public ushort FormStats, FormeSprite, BaseEXP;
public byte FormeCount, Color;
public float Height, Weight;
public bool[] TMHM;
public bool[] Tutors;
public bool[][] ORASTutors = new bool[4][];
public byte EscapeRate;
public PersonalInfo(byte[] data)
{
using (BinaryReader br = new BinaryReader(new MemoryStream(data)))
{
HP = br.ReadByte(); ATK = br.ReadByte(); DEF = br.ReadByte();
SPE = br.ReadByte(); SPA = br.ReadByte(); SPD = br.ReadByte();
BST = HP + ATK + DEF + SPE + SPA + SPD;
Types = new[] { br.ReadByte(), br.ReadByte() };
CatchRate = br.ReadByte();
EvoStage = br.ReadByte();
ushort EVs = br.ReadUInt16();
EV_HP = EVs >> 0 & 0x3;
EV_ATK = EVs >> 2 & 0x3;
EV_DEF = EVs >> 4 & 0x3;
EV_SPE = EVs >> 6 & 0x3;
EV_SPA = EVs >> 8 & 0x3;
EV_SPD = EVs >> 10 & 0x3;
Items = new[] { br.ReadUInt16(), br.ReadUInt16(), br.ReadUInt16() };
Gender = br.ReadByte();
HatchCycles = br.ReadByte();
BaseFriendship = br.ReadByte();
EXPGrowth = br.ReadByte();
EggGroups = new[] { br.ReadByte(), br.ReadByte() };
Abilities = new[] { br.ReadByte(), br.ReadByte(), br.ReadByte() };
EscapeRate = br.ReadByte();
FormStats = br.ReadUInt16();
FormeSprite = br.ReadUInt16();
FormeCount = br.ReadByte();
Color = br.ReadByte();
BaseEXP = br.ReadUInt16();
Height = br.ReadUInt16();
Weight = br.ReadUInt16();
byte[] TMHMData = br.ReadBytes(0x10);
TMHM = new bool[8 * TMHMData.Length];
for (int j = 0; j < TMHM.Length; j++)
TMHM[j] = (TMHMData[j / 8] >> (j % 8) & 0x1) == 1; //Bitflags for TMHM
byte[] TutorData = br.ReadBytes(8);
Tutors = new bool[8 * TutorData.Length];
for (int j = 0; j < Tutors.Length; j++)
Tutors[j] = (TutorData[j / 8] >> (j % 8) & 0x1) == 1; //Bitflags for Tutors
if (br.BaseStream.Length - br.BaseStream.Position == 0x10) // ORAS
{
byte[][] ORASTutorData =
{
br.ReadBytes(4), // 15
br.ReadBytes(4), // 17
br.ReadBytes(4), // 16
br.ReadBytes(4), // 15
};
for (int i = 0; i < 4; i++)
{
ORASTutors[i] = new bool[8 * ORASTutorData[i].Length];
for (int b = 0; b < 8 * ORASTutorData[i].Length; b++)
ORASTutors[i][b] = (ORASTutorData[i][b / 8] >> b % 8 & 0x1) == 1;
}
}
}
}
// Data Manipulation
public int FormeIndex(int species, int forme)
{
return forme == 0 || FormStats == 0 ? species : FormStats + forme - 1;
}
public int RandomGender
{
get
{
switch (Gender)
{
case 255: // Genderless
return 2;
case 254: // Female
return 1;
case 0: // Male
return 0;
default:
return (int)(Util.rnd32() % 2);
}
}
}
public bool HasFormes => FormeCount > 1;
internal static PersonalInfo[] getArray(byte[] data, int size)
{
PersonalInfo[] d = new PersonalInfo[data.Length / size];
for (int i = 0; i < d.Length; i++)
d[i] = new PersonalInfo(data.Skip(i * size).Take(size).ToArray());
return d;
}
}
internal static class Data
{
internal static byte[][] unpackMini(byte[] fileData, string identifier)
{
using (var s = new MemoryStream(fileData))
using (var br = new BinaryReader(s))
{
if (identifier != new string(br.ReadChars(2)))
return null;
ushort count = br.ReadUInt16();
byte[][] returnData = new byte[count][];
uint[] offsets = new uint[count + 1];
for (int i = 0; i < count; i++)
offsets[i] = br.ReadUInt32();
uint length = br.ReadUInt32();
offsets[offsets.Length - 1] = length;
for (int i = 0; i < count; i++)
{
br.BaseStream.Seek(offsets[i], SeekOrigin.Begin);
using (MemoryStream dataout = new MemoryStream())
{
byte[] data = new byte[0];
s.CopyTo(dataout, (int)offsets[i]);
int len = (int)offsets[i + 1] - (int)offsets[i];
if (len != 0)
{
data = dataout.ToArray();
Array.Resize(ref data, len);
}
returnData[i] = data;
}
}
return returnData;
}
}
}
}