Populate moveset interfaces on Battle Tower Pokémon.

This commit is contained in:
Greg Edwards
2021-11-22 01:24:24 -05:00
parent 28ea0df638
commit 296fec2bd7
10 changed files with 178 additions and 111 deletions

View File

@@ -741,15 +741,15 @@ namespace PkmnFoundations.Data
List<MySqlParameter> result = new List<MySqlParameter>(15);
result.Add(new MySqlParameter("@species", pokemon.SpeciesID));
result.Add(new MySqlParameter("@held_item", pokemon.HeldItemID));
result.Add(new MySqlParameter("@move1", pokemon.Moveset[0]));
result.Add(new MySqlParameter("@move2", pokemon.Moveset[1]));
result.Add(new MySqlParameter("@move3", pokemon.Moveset[2]));
result.Add(new MySqlParameter("@move4", pokemon.Moveset[3]));
result.Add(new MySqlParameter("@move1", (ushort)pokemon.Moves[0].MoveID));
result.Add(new MySqlParameter("@move2", (ushort)pokemon.Moves[1].MoveID));
result.Add(new MySqlParameter("@move3", (ushort)pokemon.Moves[2].MoveID));
result.Add(new MySqlParameter("@move4", (ushort)pokemon.Moves[3].MoveID));
result.Add(new MySqlParameter("@trainer_id", pokemon.TrainerID));
result.Add(new MySqlParameter("@personality", pokemon.Personality));
result.Add(new MySqlParameter("@ivs", pokemon.IVs.ToInt32() | (int)pokemon.IvFlags));
result.Add(new MySqlParameter("@evs", pokemon.EVs.ToArray()));
result.Add(new MySqlParameter("@unknown1", pokemon.Unknown1));
result.Add(new MySqlParameter("@unknown1", pokemon.GetPpUps()));
result.Add(new MySqlParameter("@language", (byte)pokemon.Language));
result.Add(new MySqlParameter("@ability", pokemon.AbilityID));
result.Add(new MySqlParameter("@happiness", pokemon.Happiness));
@@ -926,26 +926,23 @@ namespace PkmnFoundations.Data
private BattleTowerPokemon4 BattleTowerPokemon4FromReader(MySqlDataReader reader, Pokedex.Pokedex pokedex)
{
BattleTowerPokemon4 result = new BattleTowerPokemon4(pokedex);
result.SpeciesID = reader.GetUInt16(2);
result.HeldItemID = reader.GetUInt16(3);
result.Moveset = new ushort[4];
result.Moveset[0] = reader.GetUInt16(4);
result.Moveset[1] = reader.GetUInt16(5);
result.Moveset[2] = reader.GetUInt16(6);
result.Moveset[3] = reader.GetUInt16(7);
result.TrainerID = reader.GetUInt32(8);
result.Personality = reader.GetUInt32(9);
result.IVs = new IvStatValues((int)(reader.GetUInt32(10) & 0x3fffffff));
result.IvFlags = reader.GetUInt32(10) & 0xc0000000u;
result.EVs = new ByteStatValues(reader.GetByteArray(11, 6));
result.Unknown1 = reader.GetByte(12);
result.Language = (Languages)reader.GetByte(13);
result.AbilityID = reader.GetByte(14);
result.Happiness = reader.GetByte(15);
result.NicknameEncoded = new EncodedString4(reader.GetByteArray(16, 22));
return result;
return new BattleTowerPokemon4(pokedex,
Database.Cast<ushort>(reader["Species"]),
Database.Cast<ushort>(reader["HeldItem"]),
Database.Cast<ushort>(reader["Move1"]),
Database.Cast<ushort>(reader["Move2"]),
Database.Cast<ushort>(reader["Move3"]),
Database.Cast<ushort>(reader["Move4"]),
Database.Cast<uint>(reader["TrainerID"]),
Database.Cast<uint>(reader["Personality"]),
Database.Cast<uint>(reader["IVs"]),
Database.Cast<byte[]>(reader["EVs"]),
Database.Cast<byte>(reader["Unknown1"]),
(Languages)Database.Cast<byte>(reader["Language"]),
Database.Cast<byte>(reader["Ability"]),
Database.Cast<byte>(reader["Happiness"]),
new EncodedString4(Database.Cast<byte[]>(reader["Nickname"]), 0, 22)
);
}
public BattleTowerProfile4[] BattleTowerGetLeaders4(MySqlTransaction tran, Pokedex.Pokedex pokedex, byte rank, byte roomNum)
@@ -1745,15 +1742,15 @@ namespace PkmnFoundations.Data
List<MySqlParameter> result = new List<MySqlParameter>(15);
result.Add(new MySqlParameter("@species", pokemon.SpeciesID));
result.Add(new MySqlParameter("@held_item", pokemon.HeldItemID));
result.Add(new MySqlParameter("@move1", pokemon.Moveset[0]));
result.Add(new MySqlParameter("@move2", pokemon.Moveset[1]));
result.Add(new MySqlParameter("@move3", pokemon.Moveset[2]));
result.Add(new MySqlParameter("@move4", pokemon.Moveset[3]));
result.Add(new MySqlParameter("@move1", pokemon.Moves[0].MoveID));
result.Add(new MySqlParameter("@move2", pokemon.Moves[1].MoveID));
result.Add(new MySqlParameter("@move3", pokemon.Moves[2].MoveID));
result.Add(new MySqlParameter("@move4", pokemon.Moves[3].MoveID));
result.Add(new MySqlParameter("@trainer_id", pokemon.TrainerID));
result.Add(new MySqlParameter("@personality", pokemon.Personality));
result.Add(new MySqlParameter("@ivs", pokemon.IVs.ToInt32() | (int)pokemon.IvFlags));
result.Add(new MySqlParameter("@evs", pokemon.EVs.ToArray()));
result.Add(new MySqlParameter("@unknown1", pokemon.Unknown1));
result.Add(new MySqlParameter("@unknown1", pokemon.GetPpUps()));
result.Add(new MySqlParameter("@language", (byte)pokemon.Language));
result.Add(new MySqlParameter("@ability", pokemon.AbilityID));
result.Add(new MySqlParameter("@happiness", pokemon.Happiness));
@@ -1933,28 +1930,24 @@ namespace PkmnFoundations.Data
private BattleSubwayPokemon5 BattleSubwayPokemon5FromReader(MySqlDataReader reader, Pokedex.Pokedex pokedex)
{
// xxx: Don't use ordinals
BattleSubwayPokemon5 result = new BattleSubwayPokemon5(pokedex);
result.SpeciesID = reader.GetUInt16(2);
result.HeldItemID = reader.GetUInt16(3);
result.Moveset = new ushort[4];
result.Moveset[0] = reader.GetUInt16(4);
result.Moveset[1] = reader.GetUInt16(5);
result.Moveset[2] = reader.GetUInt16(6);
result.Moveset[3] = reader.GetUInt16(7);
result.TrainerID = reader.GetUInt32(8);
result.Personality = reader.GetUInt32(9);
result.IVs = new IvStatValues((int)(reader.GetUInt32(10) & 0x3fffffff));
result.IvFlags = reader.GetUInt32(10) & 0xc0000000u;
result.EVs = new ByteStatValues(reader.GetByteArray(11, 6));
result.Unknown1 = reader.GetByte(12);
result.Language = (Languages)reader.GetByte(13);
result.AbilityID = reader.GetByte(14);
result.Happiness = reader.GetByte(15);
result.NicknameEncoded = new EncodedString5(reader.GetByteArray(16, 22));
result.Unknown2 = reader.GetUInt32(17);
return result;
return new BattleSubwayPokemon5(pokedex,
Database.Cast<ushort>(reader["Species"]),
Database.Cast<ushort>(reader["HeldItem"]),
Database.Cast<ushort>(reader["Move1"]),
Database.Cast<ushort>(reader["Move2"]),
Database.Cast<ushort>(reader["Move3"]),
Database.Cast<ushort>(reader["Move4"]),
Database.Cast<uint>(reader["TrainerID"]),
Database.Cast<uint>(reader["Personality"]),
Database.Cast<uint>(reader["IVs"]),
Database.Cast<byte[]>(reader["EVs"]),
Database.Cast<byte>(reader["Unknown1"]),
(Languages)Database.Cast<byte>(reader["Language"]),
Database.Cast<byte>(reader["Ability"]),
Database.Cast<byte>(reader["Happiness"]),
new EncodedString5(Database.Cast<byte[]>(reader["Nickname"]), 0, 22),
Database.Cast<uint>(reader["Unknown2"])
);
}
public override BattleSubwayProfile5[] BattleSubwayGetLeaders5(Pokedex.Pokedex pokedex, byte rank, byte roomNum)

View File

@@ -58,6 +58,11 @@ namespace PkmnFoundations.Data
#endregion
#region Utility
public static T Cast<T>(object value)
{
if (value is DBNull) value = null;
return (T)value; // Allow InvalidCastException to escape.
}
#endregion
#region GTS 4

View File

@@ -14,7 +14,7 @@ namespace PkmnFoundations.Structures
}
public BattleSubwayPokemon5(Pokedex.Pokedex pokedex, ushort species, ushort held_item, ushort[] moveset,
uint ot, uint personality, uint ivs, byte[] evs, byte unknown1,
uint ot, uint personality, uint ivs, byte[] evs, byte pp_ups,
Languages language, byte ability, byte happiness, EncodedString5 nickname, uint unknown2) : base(pokedex)
{
if (moveset == null) throw new ArgumentNullException("moveset");
@@ -26,13 +26,12 @@ namespace PkmnFoundations.Structures
SpeciesID = species;
HeldItemID = held_item;
Moveset = moveset.ToArray();
GetMovesFromArray(Moves, pokedex, moveset, pp_ups);
TrainerID = ot;
Personality = personality;
IVs = new IvStatValues((int)ivs & 0x3fffffff);
IvFlags = ivs & 0xc0000000u;
EVs = new ByteStatValues(evs);
Unknown1 = unknown1;
Language = language;
AbilityID = ability;
Happiness = happiness;
@@ -40,6 +39,15 @@ namespace PkmnFoundations.Structures
Unknown2 = unknown2;
}
public BattleSubwayPokemon5(Pokedex.Pokedex pokedex, ushort species, ushort held_item,
ushort move1, ushort move2, ushort move3, ushort move4, uint ot, uint personality,
uint ivs, byte[] evs, byte pp_ups, Languages language, byte ability, byte happiness,
EncodedString5 nickname, uint unknown2) :
this(pokedex, species, held_item, new ushort[] { move1, move2, move3, move4 },
ot, personality, ivs, evs, pp_ups, language, ability, happiness, nickname, unknown2)
{
}
public BattleSubwayPokemon5(Pokedex.Pokedex pokedex, BinaryReader data) : base(pokedex)
{
Load(data);
@@ -73,25 +81,22 @@ namespace PkmnFoundations.Structures
}
}
[Obsolete("Use IVs[] indexer.")]
public byte IV(Stats stat)
{
return IVs[stat];
}
protected override void Save(BinaryWriter writer)
{
writer.Write((ushort)SpeciesID);
writer.Write((ushort)HeldItemID);
for (int x = 0; x < 4; x++)
ushort[] moveset = GetArrayFromMoves(Moves);
for (int i = 0; i < 4; i++)
{
writer.Write(Moveset[x]);
writer.Write(moveset[i]);
}
writer.Write(TrainerID);
writer.Write(Personality);
writer.Write(IVs.ToInt32() | (int)IvFlags);
writer.Write(EVs.ToArray(), 0, 6);
writer.Write(Unknown1);
writer.Write(GetPpUpsFromMoves(Moves));
writer.Write((byte)Language);
writer.Write((byte)AbilityID);
writer.Write(Happiness);
@@ -105,11 +110,13 @@ namespace PkmnFoundations.Structures
{
SpeciesID = reader.ReadUInt16();
HeldItemID = reader.ReadUInt16();
Moveset = new ushort[4];
for (int x = 0; x < 4; x++)
ushort[] moveset = new ushort[4];
for (int i = 0; i < 4; i++)
{
Moveset[x] = reader.ReadUInt16();
moveset[i] = reader.ReadUInt16();
}
TrainerID = reader.ReadUInt32();
Personality = reader.ReadUInt32();
uint ivs = reader.ReadUInt32();
@@ -117,7 +124,9 @@ namespace PkmnFoundations.Structures
IvFlags = ivs & 0xc0000000u;
EVs = new ByteStatValues(reader.ReadBytes(6));
Unknown1 = reader.ReadByte();
byte ppUps = reader.ReadByte();
GetMovesFromArray(Moves, m_pokedex, moveset, ppUps);
Language = (Languages)reader.ReadByte();
AbilityID = reader.ReadByte();
Happiness = reader.ReadByte();
@@ -128,9 +137,12 @@ namespace PkmnFoundations.Structures
public BattleSubwayPokemon5 Clone()
{
uint ivsField = (uint)(IVs.ToInt32() & 0x3fffffffu) | (IvFlags & 0xc0000000u);
ushort[] moveset = GetArrayFromMoves(Moves);
byte ppUps = GetPpUpsFromMoves(Moves);
BattleSubwayPokemon5 result = new BattleSubwayPokemon5(m_pokedex,
(ushort)SpeciesID, (ushort)HeldItemID, Moveset.ToArray(),
TrainerID, Personality, ivsField, EVs.ToArray(), Unknown1,
(ushort)SpeciesID, (ushort)HeldItemID, moveset,
TrainerID, Personality, ivsField, EVs.ToArray(), ppUps,
Language, (byte)AbilityID, Happiness, NicknameEncoded, Unknown2);
return result;

View File

@@ -52,7 +52,7 @@ namespace PkmnFoundations.Structures
public TrendyPhrase5 PhraseLeader;
// Different from GTS, 0 = male, 2 = female, 1 = Plato????
public byte Gender;
public byte Unknown;
public byte Unknown; // Probably trainer class.
public byte[] Save()
{

View File

@@ -39,8 +39,8 @@ namespace PkmnFoundations.Structures
public byte Rank;
public byte RoomNum;
public byte BattlesWon;
public byte[] Unknown4; // 5 bytes
public ulong Unknown5;
public byte[] Unknown4; // 5 bytes, appears to always be 00 00 00 00 00?
public ulong Unknown5; // Appears to be zero on AdmiralCurtiss's scraped data, but is very big ints on data being uploaded.
public int PID;
public byte[] Save()

View File

@@ -14,7 +14,7 @@ namespace PkmnFoundations.Structures
}
public BattleTowerPokemon4(Pokedex.Pokedex pokedex, ushort species, ushort held_item, ushort[] moveset,
uint ot, uint personality, uint ivs, byte[] evs, byte unknown1,
uint ot, uint personality, uint ivs, byte[] evs, byte pp_ups,
Languages language, byte ability, byte happiness, EncodedString4 nickname) : base(pokedex)
{
if (moveset == null) throw new ArgumentNullException("moveset");
@@ -26,19 +26,27 @@ namespace PkmnFoundations.Structures
SpeciesID = species;
HeldItemID = held_item;
Moveset = moveset.ToArray();
GetMovesFromArray(Moves, pokedex, moveset, pp_ups);
TrainerID = ot;
Personality = personality;
IVs = new IvStatValues((int)ivs & 0x3fffffff);
IvFlags = ivs & 0xc0000000u;
EVs = new ByteStatValues(evs);
Unknown1 = unknown1;
Language = language;
AbilityID = ability;
Happiness = happiness;
NicknameEncoded = nickname; // todo: clone
}
public BattleTowerPokemon4(Pokedex.Pokedex pokedex, ushort species, ushort held_item,
ushort move1, ushort move2, ushort move3, ushort move4, uint ot, uint personality,
uint ivs, byte[] evs, byte pp_ups, Languages language, byte ability, byte happiness,
EncodedString4 nickname) :
this(pokedex, species, held_item, new ushort[] { move1, move2, move3, move4 },
ot, personality, ivs, evs, pp_ups, language, ability, happiness, nickname)
{
}
public BattleTowerPokemon4(Pokedex.Pokedex pokedex, BinaryReader data) : base(pokedex)
{
Load(data);
@@ -70,25 +78,22 @@ namespace PkmnFoundations.Structures
}
}
[Obsolete("Use IVs[] indexer.")]
public byte IV(Stats stat)
{
return IVs[stat];
}
protected override void Save(BinaryWriter writer)
{
writer.Write((ushort)SpeciesID);
writer.Write((ushort)HeldItemID);
for (int x = 0; x < 4; x++)
ushort[] moveset = GetArrayFromMoves(Moves);
for (int i = 0; i < 4; i++)
{
writer.Write(Moveset[x]);
writer.Write(moveset[i]);
}
writer.Write(TrainerID);
writer.Write(Personality);
writer.Write(IVs.ToInt32() | (int)IvFlags);
writer.Write(EVs.ToArray(), 0, 6);
writer.Write(Unknown1);
writer.Write(GetPpUpsFromMoves(Moves));
writer.Write((byte)Language);
writer.Write((byte)AbilityID);
writer.Write(Happiness);
@@ -101,11 +106,13 @@ namespace PkmnFoundations.Structures
{
SpeciesID = reader.ReadUInt16();
HeldItemID = reader.ReadUInt16();
Moveset = new ushort[4];
for (int x = 0; x < 4; x++)
ushort[] moveset = new ushort[4];
for (int i = 0; i < 4; i++)
{
Moveset[x] = reader.ReadUInt16();
moveset[i] = reader.ReadUInt16();
}
TrainerID = reader.ReadUInt32();
Personality = reader.ReadUInt32();
uint ivs = reader.ReadUInt32();
@@ -113,7 +120,9 @@ namespace PkmnFoundations.Structures
IvFlags = ivs & 0xc0000000u;
EVs = new ByteStatValues(reader.ReadBytes(6));
Unknown1 = reader.ReadByte();
byte ppUps = reader.ReadByte();
GetMovesFromArray(Moves, m_pokedex, moveset, ppUps);
Language = (Languages)reader.ReadByte();
AbilityID = reader.ReadByte();
Happiness = reader.ReadByte();
@@ -123,9 +132,12 @@ namespace PkmnFoundations.Structures
public BattleTowerPokemon4 Clone()
{
uint ivsField = (uint)(IVs.ToInt32() & 0x3fffffffu) | (IvFlags & 0xc0000000u);
ushort[] moveset = GetArrayFromMoves(Moves);
byte ppUps = GetPpUpsFromMoves(Moves);
BattleTowerPokemon4 result = new BattleTowerPokemon4(m_pokedex,
(ushort)SpeciesID, (ushort)HeldItemID, Moveset.ToArray(),
TrainerID, Personality, ivsField, EVs.ToArray(), Unknown1,
(ushort)SpeciesID, (ushort)HeldItemID, moveset,
TrainerID, Personality, ivsField, EVs.ToArray(), ppUps,
Language, (byte)AbilityID, Happiness, NicknameEncoded);
return result;
@@ -146,19 +158,5 @@ namespace PkmnFoundations.Structures
return 56;
}
}
// todo: move me to the actual pokemon class once it's made.
[Obsolete("Use IvStatValues.UnpackIV or IvStatValues indexer, depending on context.")]
public static byte UnpackIV(uint ivs, Stats stat)
{
return IvStatValues.UnpackIV(ivs, stat);
}
[Obsolete("Use IvStatValues.PackIVs")]
// todo: Move to IVs class
public static uint PackIVs(byte HP, byte Attack, byte Defense, byte Speed, byte SpAttack, byte SpDefense)
{
return IvStatValues.PackIVs(HP, Attack, Defense, Speed, SpAttack, SpDefense);
}
}
}

View File

@@ -15,8 +15,6 @@ namespace PkmnFoundations.Structures
}
public ushort[] Moveset;
public byte Unknown1; // probably a bitmask of applied PP ups
// In the main PKM structure, the remaining 2 bits on the IVs field
// represents whether it's nicknamed and if it's an egg. Clearly, eggs
// shouldn't be brought into Battle Tower.
@@ -35,5 +33,59 @@ namespace PkmnFoundations.Structures
throw new NotSupportedException();
}
}
internal static void GetMovesFromArray(IList<MoveSlot> result, Pokedex.Pokedex pokedex, ushort[] moves, byte ppUps)
{
if (moves.Length != 4) throw new ArgumentException("moves");
if (result.Count != 4) throw new ArgumentException("movesOut");
for (int i = 0; i < 4; i++)
{
result[i] = MoveFromValues(pokedex, moves[i], (byte)(ppUps & 0x03));
ppUps >>= 2;
}
}
internal static MoveSlot MoveFromValues(Pokedex.Pokedex pokedex, ushort move, byte ppUps)
{
MoveSlot result = new MoveSlot(pokedex, move, ppUps, 0);
result.RemainingPP = (byte)result.PP;
return result;
}
internal static ushort[] GetArrayFromMoves(IList<MoveSlot> moves)
{
if (moves.Count != 4) throw new ArgumentException("moves");
ushort[] result = new ushort[4];
for (int i = 0; i < 4; i++)
{
result[i] = (ushort)moves[i].MoveID;
}
return result;
}
internal static byte GetPpUpsFromMoves(IList<MoveSlot> moves)
{
// The first move uses the least significant bits, moving up from there.
// [1, 3, 0, 0] -> 0x0d
byte ppUps = 0;
for (int i = 0; i < 4; i++)
{
ppUps |= (byte)(moves[i].PPUps << (i * 2));
}
return ppUps;
}
public ushort[] GetMoveIds()
{
return GetArrayFromMoves(Moves);
}
public byte GetPpUps()
{
return GetPpUpsFromMoves(Moves);
}
}
}

View File

@@ -50,7 +50,7 @@ namespace PkmnFoundations.Structures
public uint OT;
public TrendyPhrase4 PhraseLeader;
// Different from GTS, 0 = male, 2 = female, 1 = Plato????
public byte Gender;
public byte Gender; // Probably trainer class.
// 3: Lass
// 6: Bug Catcher

View File

@@ -34,12 +34,12 @@ namespace PkmnFoundations.Structures
public TrendyPhrase4 PhraseChallenged;
public TrendyPhrase4 PhraseWon;
public TrendyPhrase4 PhraseLost;
public ushort Unknown3;
public ushort Unknown3; // Seems to be some sort of Elo rating. Goes up to about 8000.
public byte Rank;
public byte RoomNum;
public byte BattlesWon;
public ulong Unknown5;
public ulong Unknown5; // Appears to be zero on AdmiralCurtiss's scraped data, but is very big ints on data being uploaded.
public int PID;
public byte[] Save()

View File

@@ -40,6 +40,13 @@ namespace PkmnFoundations.Structures
public byte PPUps { get; set; } // todo: validate range
public byte RemainingPP { get; set; } // todo: validate range (against pokedex data and pp ups)
public int PP { get { return Move.PP * (5 + PPUps) / 5; } }
public int PP
{
get
{
return Move == null ? 0 : Move.PP * (5 + PPUps) / 5;
}
}
}
}