DS-Pokemon-Rom-Editor/DS_Map/ROMFiles/PokemonPersonalData.cs
2023-10-08 23:28:24 +02:00

266 lines
8.6 KiB
C#

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using static DSPRE.RomInfo;
namespace DSPRE.ROMFiles {
public enum PokemonGender {
Male = 0,
Female = 254,
Unknown = 255
}
public enum PokemonType {
Normal = 0,
Fighting,
Flying,
Poison,
Ground,
Rock,
Bug,
Ghost,
Steel,
Unknown,
Fire,
Water,
Grass,
Electric,
Psychic,
Ice,
Dragon,
Dark
}
public enum PokemonGrowthCurve {
Erratic = 0,
Fast,
MediumFast,
MediumSlow,
Slow,
Fluctuating,
}
public enum PokemonEggGroup {
Unassigned = 0,
Monster,
Water1,
Bug,
Flying,
Field,
Fairy,
Grass,
Humanoid,
Water3,
Mineral,
Amorphous,
Water2,
Ditto,
Dragon,
NoBreed,
};
public enum PokemonDexColor {
Red = 0,
Blue,
Yellow,
Green,
Black,
Brown,
Purple,
Gray,
White,
Pink,
Unspecified
}
public class PokemonPersonalData : RomFile {
public static readonly int tmsCount = 92;
public static readonly int hmsCount = 8;
public byte baseHP;
public byte baseAtk;
public byte baseDef;
public byte baseSpeed;
public byte baseSpAtk;
public byte baseSpDef;
public PokemonType type1;
public PokemonType type2;
public byte catchRate;
public byte givenExp;
//Part of a u16 bitfield, 2 bits each.
public byte evHP;
public byte evAtk;
public byte evDef;
public byte evSpeed;
public byte evSpAtk;
public byte evSpDef;
public ushort item1; // First item that the mon may hold when caught
public ushort item2; // Second item that the mon may hold when caught
public byte genderVec;
public byte eggSteps;
public byte baseFriendship;
public PokemonGrowthCurve growthCurve;
public byte eggGroup1;
public byte eggGroup2;
public byte firstAbility;
public byte secondAbility;
public byte escapeRate;
public PokemonDexColor color;// : 7; // Color (used in Pokedex)
public bool flip;// : 1; // Flip Flag
public SortedSet<byte> machines;
public PokemonPersonalData(Stream stream) {
using (BinaryReader reader = new BinaryReader(stream)) {
// Deserialize the object from binary
baseHP = reader.ReadByte();
baseAtk = reader.ReadByte();
baseDef = reader.ReadByte();
baseSpeed = reader.ReadByte();
baseSpAtk = reader.ReadByte();
baseSpDef = reader.ReadByte();
type1 = (PokemonType)reader.ReadByte();
type2 = (PokemonType)reader.ReadByte();
catchRate = reader.ReadByte();
givenExp = reader.ReadByte();
ushort evData = reader.ReadUInt16();
evHP = (byte)(evData & 0b11);
evAtk = (byte)((evData >> 2) & 0b11);
evDef = (byte)((evData >> 4) & 0b11);
evSpeed = (byte)((evData >> 6) & 0b11);
evSpAtk = (byte)((evData >> 8) & 0b11);
evSpDef = (byte)((evData >> 10) & 0b11);
item1 = reader.ReadUInt16();
item2 = reader.ReadUInt16();
genderVec = reader.ReadByte();
eggSteps = reader.ReadByte();
baseFriendship = reader.ReadByte();
growthCurve = (PokemonGrowthCurve)reader.ReadByte();
eggGroup1 = reader.ReadByte();
eggGroup2 = reader.ReadByte();
firstAbility = reader.ReadByte();
secondAbility = reader.ReadByte();
escapeRate = reader.ReadByte();
byte colorAndFlip = reader.ReadByte();
color = (PokemonDexColor)(colorAndFlip & 0b01111111);
flip = ((colorAndFlip >> 7) & 0b00000001) == 1;
reader.BaseStream.Position += 2; //Alignment
uint tm1 = reader.ReadUInt32();
uint tm2 = reader.ReadUInt32();
uint tm3 = reader.ReadUInt32();
uint tm4 = reader.ReadUInt32();
machines = BitFieldToSet(new uint[4] { tm1, tm2, tm3, tm4 });
}
}
public PokemonPersonalData(int ID) : this(new FileStream(RomInfo.gameDirs[DirNames.personalPokeData].unpackedDir + "\\" + ID.ToString("D4"), FileMode.Open)) { }
public override byte[] ToByteArray() {
using (MemoryStream stream = new MemoryStream()) {
using (BinaryWriter writer = new BinaryWriter(stream)) {
// Serialize the object to binary
writer.Write(baseHP);
writer.Write(baseAtk);
writer.Write(baseDef);
writer.Write(baseSpeed);
writer.Write(baseSpAtk);
writer.Write(baseSpDef);
writer.Write((byte)type1);
writer.Write((byte)type2);
writer.Write(catchRate);
writer.Write(givenExp);
ushort evData = (ushort)((evHP & 0b11) |
((evAtk & 0b11) << 2) |
((evDef & 0b11) << 4) |
((evSpeed & 0b11) << 6) |
((evSpAtk & 0b11) << 8) |
((evSpDef & 0b11) << 10));
writer.Write(evData);
writer.Write(item1);
writer.Write(item2);
writer.Write(genderVec);
writer.Write(eggSteps);
writer.Write(baseFriendship);
writer.Write((byte)growthCurve);
writer.Write(eggGroup1);
writer.Write(eggGroup2);
writer.Write(firstAbility);
writer.Write(secondAbility);
writer.Write(escapeRate);
byte colorAndFlipflag = (byte)(((byte)color & 0b01111111) |
(((flip ? 1 : 0) & 0b00000001) << 7));
writer.Write(colorAndFlipflag);
writer.BaseStream.Position += 2; //Alignment
uint[] bfs = SetToBitField(machines);
int l = Math.Min(bfs.Length, 4);
int i;
for (i = 0; i < l; i++) {
writer.Write(bfs[i]);
}
while (i < 4) {
writer.Write((uint)0);
i++;
}
}
return stream.ToArray();
}
}
public SortedSet<byte> BitFieldToSet(uint[] bitfield) {
var result = new SortedSet<byte>();
for (uint i = 0; i < bitfield.Length; i++) {
uint currentBitfield = bitfield[i];
for (int j = 0; j < 32; j++) {
if ((currentBitfield & (1 << j)) != 0) {
result.Add((byte)(i * 32 + j));
}
}
}
return result;
}
public uint[] SetToBitField(SortedSet<byte> set) {
if (set == null) {
return null;
}
if (set.Count == 0) {
return new uint[0];
}
int maxBit = set.Max();
uint[] bitfield = new uint[(maxBit / 32) + 1];
foreach (byte bit in set) {
int index = bit / 32;
int offset = bit % 32;
bitfield[index] |= (uint)(1 << offset);
}
return bitfield;
}
public void SaveToFileDefaultDir(int IDtoReplace, bool showSuccessMessage = true) {
SaveToFileDefaultDir(DirNames.personalPokeData, IDtoReplace, showSuccessMessage);
}
public void SaveToFileExplorePath(string suggestedFileName, bool showSuccessMessage = true) {
SaveToFileExplorePath("Gen IV Personal Pokémon data", "bin", suggestedFileName, showSuccessMessage);
}
}
}