diff --git a/library/Data/DataAbstract.cs b/library/Data/DataAbstract.cs index 9956d967..7109460e 100644 --- a/library/Data/DataAbstract.cs +++ b/library/Data/DataAbstract.cs @@ -64,6 +64,13 @@ namespace PkmnFoundations.Data public abstract void GtsLogTrade4(GtsRecord4 record, DateTime ? timeWithdrawn); #endregion + #region Battle Tower 4 + public abstract ulong BattleTowerUpdateRecord4(BattleTowerRecord4 record); + public abstract ulong BattleTowerAddLeader4(BattleTowerProfile4 profile); + public abstract BattleTowerRecord4[] BattleTowerGetOpponents4(byte rank, byte roomNum); + public abstract BattleTowerProfile4[] BattleTowerGetLeaders4(byte rank, byte roomNum); + #endregion + #region Other Gamestats 4 public abstract bool GamestatsSetProfile4(TrainerProfile4 profile); #endregion @@ -90,6 +97,9 @@ namespace PkmnFoundations.Data public abstract bool GamestatsSetProfile5(TrainerProfile5 profile); #endregion + #region Battle Subway 5 + #endregion + #region Global Terminal 4 public const int DRESSUP_VERSION_4 = 1; public const int BOX_VERSION_4 = 1; diff --git a/library/Data/DataMysql.cs b/library/Data/DataMysql.cs index e8be4dfe..96f90a52 100644 --- a/library/Data/DataMysql.cs +++ b/library/Data/DataMysql.cs @@ -408,6 +408,188 @@ namespace PkmnFoundations.Data } #endregion + #region Battle Tower 4 + public override ulong BattleTowerUpdateRecord4(BattleTowerRecord4 record) + { + using (MySqlConnection db = CreateConnection()) + { + db.Open(); + using (MySqlTransaction tran = db.BeginTransaction()) + { + ulong result = BattleTowerUpdateRecord4(tran, record); + tran.Commit(); + return result; + } + } + } + + private ulong BattleTowerUpdateRecord4(MySqlTransaction tran, BattleTowerRecord4 record) + { + if (record.BattlesWon > 7) throw new ArgumentException("Battles won can not be greater than 7."); + + // Does this player already have a record in this room? + // Also get primary key if it does. (We need it for updating party) + object objPkey = tran.ExecuteScalar("SELECT id FROM GtsBattleTower4 " + + "WHERE pid = @pid AND RoomNum = @room", + new MySqlParameter("@pid", record.PID), + new MySqlParameter("@room", record.RoomNum)); + ulong pkey = (ulong)(objPkey ?? 0); + + if (objPkey != null) + { + // If the player already has a record, move everyone below it up one position + // (effectively removing this record from the ordering) + tran.ExecuteNonQuery("SELECT @old_rank = Rank, @old_position = Position " + + "FROM GtsBattleTower4 WHERE pid = @pid AND RoomNum = @room); " + + "UPDATE GtsBattleTower4 SET Position = Position - 1 " + + "WHERE RoomNum = @room AND Rank = @old_rank AND Position > @old_position", + new MySqlParameter("@pid", record.PID), + new MySqlParameter("@room", record.RoomNum)); + } + + // Shift down all the players in the player's new rank by one. + tran.ExecuteNonQuery("UPDATE GtsBattleTower4 SET Position = Position + 1 " + + "WHERE RoomNum = @room AND Rank = @rank AND Position <= @position", + new MySqlParameter("@room", record.RoomNum), + new MySqlParameter("@rank", record.Rank), + new MySqlParameter("@position", 7 - record.BattlesWon)); + + // Update the actual record + if (objPkey != null) + { + tran.ExecuteNonQuery("UPDATE GtsBattleTower4 SET Name = @name, " + + "Version = @version, Language = @language, Country = @country, " + + "Region = @region, TrainerID = @trainer_id, Unknown1 = @unknown1, " + + "TrendyPhrase = @trendy_phrase, Unknown2 = @unknown2, Unknown3 = @unknown3, " + + "Unknown4 = @unknown4, ParseVersion = 1, Rank = @rank, " + + "BattlesWon = @battles_won, Position = @position, " + + "TimeUpdated = UTC_TIMESTAMP() WHERE id = @id", + new MySqlParameter("@name", record.Profile.Name.RawData), + new MySqlParameter("@version", (byte)record.Profile.Version), + new MySqlParameter("@language", (byte)record.Profile.Language), + new MySqlParameter("@country", record.Profile.Country), + new MySqlParameter("@region", record.Profile.Region), + new MySqlParameter("@trainer_id", record.Profile.OT), + new MySqlParameter("@unknown1", record.Profile.Unknown1), + new MySqlParameter("@trendy_phrase", record.Profile.TrendyPhrase), + new MySqlParameter("@unknown2", record.Profile.Unknown2), + new MySqlParameter("@unknown3", record.Unknown3), + new MySqlParameter("@unknown4", record.Unknown4), + new MySqlParameter("@rank", record.Rank), + new MySqlParameter("@battles_won", record.BattlesWon), + new MySqlParameter("@position", 7 - record.BattlesWon), + new MySqlParameter("@id", pkey)); + + UpdateBattleTowerPokemon(tran, record.Party[0], pkey, 0); + UpdateBattleTowerPokemon(tran, record.Party[1], pkey, 1); + UpdateBattleTowerPokemon(tran, record.Party[2], pkey, 2); + } + else + { + pkey = Convert.ToUInt64(tran.ExecuteNonQuery("INSERT INTO GtsBattleTower4 " + + "(pid, Name, Version, Language, Country, Region, TrainerID, " + + "Unknown1, TrendyPhrase, Unknown2, Unknown3, Unknown4, ParseVersion, " + + "RoomNum, Rank, BattlesWon, Position, TimeAdded, TimeUpdated) VALUES " + + "(@pid, @name, @version, @language, @country, @region, @trainer_id, " + + "@unknown1, @trendy_phrase, @unknown2, @unknown3, @unknown4, 1, " + + "@room, @rank, @battles_won, @position, UTC_TIMESTAMP(), UTC_TIMESTAMP()); " + + "SELECT LAST_INSERT_ID()", + new MySqlParameter("@pid", record.PID), + new MySqlParameter("@name", record.Profile.Name.RawData), + new MySqlParameter("@version", (byte)record.Profile.Version), + new MySqlParameter("@language", (byte)record.Profile.Language), + new MySqlParameter("@country", record.Profile.Country), + new MySqlParameter("@region", record.Profile.Region), + new MySqlParameter("@trainer_id", record.Profile.OT), + new MySqlParameter("@unknown1", record.Profile.Unknown1), + new MySqlParameter("@trendy_phrase", record.Profile.TrendyPhrase), + new MySqlParameter("@unknown2", record.Profile.Unknown2), + new MySqlParameter("@unknown3", record.Unknown3), + new MySqlParameter("@unknown4", record.Unknown4), + new MySqlParameter("@room", record.RoomNum), + new MySqlParameter("@rank", record.Rank), + new MySqlParameter("@battles_won", record.BattlesWon), + new MySqlParameter("@position", 7 - record.BattlesWon) + )); + + InsertBattleTowerPokemon(tran, record.Party[0], pkey, 0); + InsertBattleTowerPokemon(tran, record.Party[1], pkey, 1); + InsertBattleTowerPokemon(tran, record.Party[2], pkey, 2); + } + + return pkey; + } + + private void InsertBattleTowerPokemon(MySqlTransaction tran, BattleTowerPokemon4 pokemon, ulong partyId, byte slot) + { + MySqlParameter[] _params1 = ParamsFromBattleTowerPokemon4(pokemon); + MySqlParameter[] _params2 = new MySqlParameter[_params1.Length + 2]; + Array.Copy(_params1, 0, _params2, 2, _params1.Length); + _params2[0] = new MySqlParameter("@id", partyId); + _params2[1] = new MySqlParameter("@slot", slot); + + tran.ExecuteNonQuery("INSERT INTO GtsBattleTowerPokemon4 " + + "(party_id, Slot, Species, HeldItem, Move1, Move2, Move3, Move4, TrainerID, " + + "Personality, IVs, EVs, Unknown1, Language, Ability, Happiness, Nickname) VALUES " + + "(@id, @slot, @species, @held_item, @move1, @move2, @move3, @move4, @trainer_id, " + + "@personality, @ivs, @evs, @unknown1, @language, @ability, @happiness, @nickname)", + _params2); + } + + private void UpdateBattleTowerPokemon(MySqlTransaction tran, BattleTowerPokemon4 pokemon, ulong partyId, byte slot) + { + MySqlParameter[] _params1 = ParamsFromBattleTowerPokemon4(pokemon); + MySqlParameter[] _params2 = new MySqlParameter[_params1.Length + 2]; + Array.Copy(_params1, 0, _params2, 2, _params1.Length); + _params2[0] = new MySqlParameter("@id", partyId); + _params2[1] = new MySqlParameter("@slot", slot); + + tran.ExecuteNonQuery("UPDATE GtsBattleTowerPokemon4 SET Species = @species, " + + "HeldItem = @held_item, Move1 = @move1, Move2 = @move2, Move3 = @move3, " + + "Move4 = @move4, TrainerID = @trainer_id, Personality = @personality, " + + "IVs = @ivs, EVs = @evs, Unknown1 = @unknown1, Language = @language, " + + "Ability = @ability, Happiness = @happiness, Nickname = @nickname " + + "WHERE party_id = @id AND Slot = @slot", + _params2); + } + + private MySqlParameter[] ParamsFromBattleTowerPokemon4(BattleTowerPokemon4 pokemon) + { + MySqlParameter[] result = new MySqlParameter[15]; + result[0] = new MySqlParameter("@species", pokemon.Species); + result[1] = new MySqlParameter("@held_item", pokemon.HeldItem); + result[2] = new MySqlParameter("@move1", pokemon.Moveset[0]); + result[3] = new MySqlParameter("@move2", pokemon.Moveset[1]); + result[4] = new MySqlParameter("@move3", pokemon.Moveset[2]); + result[5] = new MySqlParameter("@move4", pokemon.Moveset[3]); + result[6] = new MySqlParameter("@trainer_id", pokemon.OT); + result[7] = new MySqlParameter("@personality", pokemon.Personality); + result[8] = new MySqlParameter("@ivs", pokemon.IVs); + result[9] = new MySqlParameter("@evs", pokemon.EVs); + result[10] = new MySqlParameter("@unknown1", pokemon.Unknown1); + result[11] = new MySqlParameter("@language", (byte)pokemon.Language); + result[12] = new MySqlParameter("@ability", pokemon.Ability); + result[13] = new MySqlParameter("@happiness", pokemon.Happiness); + result[14] = new MySqlParameter("@nickname", pokemon.Nickname.RawData); + return result; + } + + public override void BattleTowerAddLeader4(BattleTowerProfile4 profile) + { + throw new NotImplementedException(); + } + + public override BattleTowerRecord4[] BattleTowerGetOpponents4(byte rank, byte roomNum) + { + throw new NotImplementedException(); + } + + public override BattleTowerProfile4[] BattleTowerGetLeaders4(byte rank, byte roomNum) + { + throw new NotImplementedException(); + } + #endregion + #region Other Gamestats 4 public override bool GamestatsSetProfile4(TrainerProfile4 profile) { diff --git a/library/Library.csproj b/library/Library.csproj index 52563717..1f2eefbc 100644 --- a/library/Library.csproj +++ b/library/Library.csproj @@ -53,6 +53,9 @@ + + + diff --git a/library/Structures/BattleTowerPokemon4.cs b/library/Structures/BattleTowerPokemon4.cs new file mode 100644 index 00000000..8e341400 --- /dev/null +++ b/library/Structures/BattleTowerPokemon4.cs @@ -0,0 +1,129 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using PkmnFoundations.Support; + +namespace PkmnFoundations.Structures +{ + public class BattleTowerPokemon4 + { + public BattleTowerPokemon4() + { + } + + public BattleTowerPokemon4(byte[] data) + { + Load(data, 0); + } + + public BattleTowerPokemon4(byte[] data, int start) + { + Load(data, start); + } + + public ushort Species; + public ushort HeldItem; + public ushort[] Moveset; + public uint OT; + public uint Personality; + public uint IVs; + public byte[] EVs; + public byte Unknown1; + public Languages Language; + public byte Ability; + public byte Happiness; + public EncodedString4 Nickname; + + // todo: add IVs class with indexer? + // byte myHp = myPokemon.IVs[Stats.HP]; + public byte IV(Stats stat) + { + return UnpackIV(IVs, stat); + } + + public byte[] Save() + { + byte[] data = new byte[0x38]; + MemoryStream ms = new MemoryStream(); + BinaryWriter writer = new BinaryWriter(ms); + + writer.Write(Species); + writer.Write(HeldItem); + for (int x = 0; x < 4; x++) + { + writer.Write(Moveset[x]); + } + writer.Write(OT); + writer.Write(Personality); + writer.Write(IVs); + for (int x = 0; x < 6; x++) + { + writer.Write(EVs[x]); + } + writer.Write(Unknown1); + writer.Write((byte)Language); + writer.Write(Ability); + writer.Write(Happiness); + writer.Write(Nickname.RawData); + + writer.Flush(); + ms.Flush(); + return data; + } + + public void Load(byte[] data, int start) + { + if (start + 0x38 > data.Length) throw new ArgumentOutOfRangeException("start"); + + Species = BitConverter.ToUInt16(data, 0x00); + HeldItem = BitConverter.ToUInt16(data, 0x02); + Moveset = new ushort[4]; + for (int x = 0; x < 4; x++) + { + Moveset[x] = BitConverter.ToUInt16(data, 0x04 + x * 2); + } + OT = BitConverter.ToUInt32(data, 0x0c); + Personality = BitConverter.ToUInt32(data, 0x10); + IVs = BitConverter.ToUInt32(data, 0x14); + + EVs = new byte[6]; + for (int x = 0; x < 6; x++) + { + EVs[x] = data[0x18 + x]; + } + Unknown1 = data[0x1e]; + Language = (Languages)data[0x1f]; + Ability = data[0x20]; + Happiness = data[0x21]; + Nickname = new EncodedString4(data, 0x22, 0x16); + } + + public BattleTowerPokemon4 Clone() + { + BattleTowerPokemon4 result = new BattleTowerPokemon4(); + result.Species = Species; + result.HeldItem = HeldItem; + result.Moveset = Moveset.ToArray(); + result.OT = OT; + result.Personality = Personality; + result.IVs = IVs; + result.EVs = EVs.ToArray(); + result.Unknown1 = Unknown1; + result.Language = Language; + result.Ability = Ability; + result.Happiness = Happiness; + result.Nickname = new EncodedString4(Nickname.RawData.ToArray()); + + return result; + } + + // todo: move me to the actual pokemon class once it's made. + public static byte UnpackIV(uint ivs, Stats stat) + { + int shift = (int)stat * 5 - 5; + return (byte)(ivs << shift & 0x1f); + } + } +} diff --git a/library/Structures/BattleTowerProfile4.cs b/library/Structures/BattleTowerProfile4.cs new file mode 100644 index 00000000..36f3970d --- /dev/null +++ b/library/Structures/BattleTowerProfile4.cs @@ -0,0 +1,81 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using PkmnFoundations.Support; + +namespace PkmnFoundations.Structures +{ + public class BattleTowerProfile4 + { + public BattleTowerProfile4() + { + + } + + public BattleTowerProfile4(byte[] data) + { + Load(data, 0); + } + + public BattleTowerProfile4(byte[] data, int start) + { + Load(data, 0); + } + + public EncodedString4 Name; + public Versions Version; + public Languages Language; + public byte Country; + public byte Region; + public uint OT; + public ushort Unknown1; + // todo: TrendyPhrase4 class + public ushort[] TrendyPhrase; + public ushort Unknown2; + + public byte[] Save() + { + byte[] data = new byte[0x22]; + MemoryStream ms = new MemoryStream(data); + BinaryWriter writer = new BinaryWriter(ms); + + writer.Write(Name.RawData); + writer.Write((byte)Version); + writer.Write((byte)Language); + writer.Write(Country); + writer.Write(Region); + writer.Write(OT); + writer.Write(Unknown1); + for (int x = 0; x < 3; x++) + { + writer.Write(TrendyPhrase[x]); + } + writer.Write(Unknown2); + + writer.Flush(); + ms.Flush(); + return data; + } + + public void Load(byte[] data, int start) + { + if (start + 0x22 > data.Length) throw new ArgumentOutOfRangeException("start"); + + Name = new EncodedString4(data, 0, 0x10); + Version = (Versions)data[0x10]; + Language = (Languages)data[0x11]; + Country = data[0x12]; + Region = data[0x13]; + OT = BitConverter.ToUInt32(data, 0x14); + Unknown1 = BitConverter.ToUInt16(data, 0x18); + TrendyPhrase = new ushort[3]; + for (int x = 0; x < 3; x++) + { + TrendyPhrase[x] = BitConverter.ToUInt16(data, 0x1a + x * 2); + } + Unknown2 = BitConverter.ToUInt16(data, 0x20); + } + } +} diff --git a/library/Structures/BattleTowerRecord4.cs b/library/Structures/BattleTowerRecord4.cs new file mode 100644 index 00000000..2327a422 --- /dev/null +++ b/library/Structures/BattleTowerRecord4.cs @@ -0,0 +1,68 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; + +namespace PkmnFoundations.Structures +{ + public class BattleTowerRecord4 + { + public BattleTowerRecord4() + { + + } + + public BattleTowerRecord4(byte[] data) + { + Load(data, 0); + } + + public BattleTowerRecord4(byte[] data, int start) + { + Load(data, start); + } + + public BattleTowerPokemon4[] Party; + public BattleTowerProfile4 Profile; + public byte[] Unknown3; + + public byte Rank; + public byte RoomNum; + public byte BattlesWon; + public ulong Unknown4; + public int PID; + + public byte[] Save() + { + byte[] data = new byte[0xe4]; + MemoryStream ms = new MemoryStream(data); + BinaryWriter writer = new BinaryWriter(ms); + + for (int x = 0; x < 3; x++) + { + writer.Write(Party[x].Save()); + } + writer.Write(Profile.Save()); + writer.Write(Unknown3); + + writer.Flush(); + ms.Flush(); + return data; + } + + public void Load(byte[] data, int start) + { + if (start + 0xe4 > data.Length) throw new ArgumentOutOfRangeException("start"); + + Party = new BattleTowerPokemon4[3]; + for (int x = 0; x < 3; x++) + { + Party[x] = new BattleTowerPokemon4(data, start + x * 0x38); + } + Profile = new BattleTowerProfile4(data, 0xa8); + Unknown3 = new byte[0x1a]; + Array.Copy(data, start + 0xca, Unknown3, 0, 0x1a); + } + } +} diff --git a/library/Structures/Enums.cs b/library/Structures/Enums.cs index 8d7eab03..06dd558e 100644 --- a/library/Structures/Enums.cs +++ b/library/Structures/Enums.cs @@ -26,7 +26,7 @@ namespace PkmnFoundations.Structures Generation6 = 32 } - public enum Versions + public enum Versions : byte { // todo: fact check that these GenIII values // are retained as-is through pal park. diff --git a/library/Support/EncodedString4.cs b/library/Support/EncodedString4.cs index ea58ee66..147a98bb 100644 --- a/library/Support/EncodedString4.cs +++ b/library/Support/EncodedString4.cs @@ -8,11 +8,21 @@ namespace PkmnFoundations.Support { public class EncodedString4 { + /// + /// Instances an EncodedString4 from its binary representation. + /// + /// This buffer is NOT copied. public EncodedString4(byte[] data) { RawData = data; } + /// + /// Instances an EncodedString4 from its binary representation. + /// + /// Buffer to copy from + /// Offset in buffer + /// Number of bytes (not chars) to copy public EncodedString4(byte[] data, int start, int count) { if (data.Length < start + count) throw new ArgumentOutOfRangeException("count"); diff --git a/library/database.sql b/library/database.sql index b1777a18..16c6a473 100644 --- a/library/database.sql +++ b/library/database.sql @@ -7,7 +7,7 @@ # # Host: 127.0.0.1 (MySQL 5.5.27) # Database: gts -# Generation Time: 2014-07-22 15:58:36 +0000 +# Generation Time: 2014-07-27 05:56:06 +0000 # ************************************************************ @@ -209,6 +209,93 @@ CREATE TABLE `FoundationsTypes` ( +# Dump of table GtsBattleTower4 +# ------------------------------------------------------------ + +DROP TABLE IF EXISTS `GtsBattleTower4`; + +CREATE TABLE `GtsBattleTower4` ( + `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT, + `pid` int(11) NOT NULL, + `Name` binary(16) DEFAULT '\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0', + `Version` tinyint(3) unsigned DEFAULT NULL, + `Language` tinyint(3) unsigned DEFAULT NULL, + `Country` tinyint(3) unsigned DEFAULT NULL, + `Region` tinyint(3) unsigned DEFAULT NULL, + `TrainerID` int(10) unsigned DEFAULT NULL, + `Unknown1` smallint(5) unsigned DEFAULT NULL, + `TrendyPhrase` binary(6) DEFAULT NULL, + `Unknown2` smallint(5) unsigned DEFAULT NULL, + `Unknown3` blob, + `Unknown4` bigint(20) DEFAULT NULL, + `ParseVersion` int(10) unsigned DEFAULT NULL, + `Rank` tinyint(3) unsigned DEFAULT NULL, + `RoomNum` tinyint(3) unsigned NOT NULL DEFAULT '0', + `BattlesWon` tinyint(3) unsigned DEFAULT NULL, + `Position` int(10) unsigned DEFAULT NULL, + `TimeAdded` datetime DEFAULT NULL, + `TimeUpdated` datetime DEFAULT NULL, + PRIMARY KEY (`id`), + KEY `RoomNum` (`RoomNum`,`Rank`,`Position`), + KEY `pid` (`pid`,`RoomNum`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + + + +# Dump of table GtsBattleTowerLeaders4 +# ------------------------------------------------------------ + +DROP TABLE IF EXISTS `GtsBattleTowerLeaders4`; + +CREATE TABLE `GtsBattleTowerLeaders4` ( + `pid` int(11) NOT NULL DEFAULT '0', + `Name` binary(16) DEFAULT NULL, + `Version` tinyint(3) unsigned DEFAULT NULL, + `Language` tinyint(3) unsigned DEFAULT NULL, + `Country` tinyint(3) unsigned DEFAULT NULL, + `Region` tinyint(3) unsigned DEFAULT NULL, + `TrainerID` int(10) unsigned DEFAULT NULL, + `Unknown1` smallint(5) unsigned DEFAULT NULL, + `TrendyPhrase` binary(6) DEFAULT NULL, + `Unknown2` smallint(5) unsigned DEFAULT NULL, + `ParseVersion` int(10) unsigned DEFAULT NULL, + `Rank` tinyint(3) unsigned DEFAULT NULL, + `RoomNum` tinyint(3) unsigned NOT NULL DEFAULT '0', + `TimeAdded` datetime DEFAULT NULL, + PRIMARY KEY (`pid`,`RoomNum`), + KEY `RoomNum` (`RoomNum`,`Rank`,`TimeAdded`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + + + +# Dump of table GtsBattleTowerPokemon4 +# ------------------------------------------------------------ + +DROP TABLE IF EXISTS `GtsBattleTowerPokemon4`; + +CREATE TABLE `GtsBattleTowerPokemon4` ( + `party_id` bigint(20) unsigned NOT NULL, + `Slot` tinyint(3) unsigned NOT NULL, + `Species` smallint(5) unsigned DEFAULT NULL, + `HeldItem` smallint(5) unsigned DEFAULT NULL, + `Move1` smallint(5) unsigned DEFAULT NULL, + `Move2` smallint(5) unsigned DEFAULT NULL, + `Move3` smallint(5) unsigned DEFAULT NULL, + `Move4` smallint(5) unsigned DEFAULT NULL, + `TrainerID` int(10) unsigned DEFAULT NULL, + `Personality` int(10) unsigned DEFAULT NULL, + `IVs` int(10) unsigned DEFAULT NULL, + `EVs` binary(6) DEFAULT NULL, + `Unknown1` tinyint(3) unsigned DEFAULT NULL, + `Language` tinyint(3) unsigned DEFAULT NULL, + `Ability` tinyint(3) unsigned DEFAULT NULL, + `Happiness` tinyint(3) unsigned DEFAULT NULL, + `Nickname` binary(22) DEFAULT NULL, + PRIMARY KEY (`party_id`,`Slot`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + + + # Dump of table GtsHistory4 # ------------------------------------------------------------