aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sql/base/characters_database.sql11
-rw-r--r--sql/updates/characters/2016_01_05_00_characters.sql19
-rw-r--r--src/server/database/Database/Implementation/CharacterDatabase.cpp22
-rw-r--r--src/server/database/Database/Implementation/CharacterDatabase.h2
-rw-r--r--src/server/game/Entities/Player/Player.cpp150
-rw-r--r--src/server/game/Handlers/CharacterHandler.cpp73
-rw-r--r--src/server/game/Server/Packets/CharacterPackets.cpp58
7 files changed, 173 insertions, 162 deletions
diff --git a/sql/base/characters_database.sql b/sql/base/characters_database.sql
index 5ad369a8f2e..d5d706a2e7c 100644
--- a/sql/base/characters_database.sql
+++ b/sql/base/characters_database.sql
@@ -1587,8 +1587,13 @@ CREATE TABLE `characters` (
`level` tinyint(3) unsigned NOT NULL DEFAULT '0',
`xp` int(10) unsigned NOT NULL DEFAULT '0',
`money` bigint(20) unsigned NOT NULL DEFAULT '0',
- `playerBytes` int(10) unsigned NOT NULL DEFAULT '0',
- `playerBytes2` int(10) unsigned NOT NULL DEFAULT '0',
+ `skin` tinyint(3) unsigned NOT NULL DEFAULT '0',
+ `face` tinyint(3) unsigned NOT NULL DEFAULT '0',
+ `hairStyle` tinyint(3) unsigned NOT NULL DEFAULT '0',
+ `hairColor` tinyint(3) unsigned NOT NULL DEFAULT '0',
+ `facialStyle` tinyint(3) unsigned NOT NULL DEFAULT '0',
+ `bankSlots` tinyint(3) unsigned NOT NULL DEFAULT '0',
+ `restState` tinyint(3) unsigned NOT NULL DEFAULT '0',
`playerFlags` int(10) unsigned NOT NULL DEFAULT '0',
`position_x` float NOT NULL DEFAULT '0',
`position_y` float NOT NULL DEFAULT '0',
@@ -3077,7 +3082,7 @@ CREATE TABLE `updates` (
LOCK TABLES `updates` WRITE;
/*!40000 ALTER TABLE `updates` DISABLE KEYS */;
-INSERT INTO `updates` VALUES ('2014_10_20_00_characters.sql','A5882DA0979CF4DAE33DA011EBAA006C24BE7230','ARCHIVED','2015-03-21 15:55:55',0),('2014_10_23_00_characters.sql','E2AC4758133EE19B7F08464A445802154D1261C8','ARCHIVED','2015-03-21 15:55:55',0),('2014_10_23_01_characters.sql','20029E6323D9773B32C34D84FFED1711CC60F09F','ARCHIVED','2015-03-21 15:55:55',0),('2014_10_23_02_characters.sql','8A7A16886EE71E7ACDDB3DDA6D0ECAC2FD2FDCA8','ARCHIVED','2015-03-21 15:55:55',0),('2014_10_24_00_characters.sql','D008FE81AE844FCA686439D6ECC5108FB0DD1EB9','ARCHIVED','2015-03-21 15:55:55',0),('2014_10_25_00_characters.sql','A39C7BE46686B54776BDAB9D7A882D91EDEC51A4','ARCHIVED','2015-03-21 15:55:55',0),('2014_10_26_00_characters.sql','C787954CC35FE34B4101FDE6527F14C027F4947C','ARCHIVED','2015-03-21 15:55:55',0),('2014_11_12_00_characters.sql','B160BB2313F1BD5F3B076A5A9279DC10D4796E34','ARCHIVED','2015-03-21 15:55:55',0),('2014_12_23_00_characters.sql','3D9D648B2387B357F4BD090B33F80682F7924882','ARCHIVED','2015-03-21 15:55:55',0),('2014_12_28_00_characters.sql','5362922FF4483A336311D73082A5727309CD9219','ARCHIVED','2015-03-21 15:55:55',0),('2014_12_31_00_characters.sql','498DDF2DD936CF156D74A8208DC93DCE9FCAB5AA','ARCHIVED','2015-03-21 15:55:55',0),('2015_01_02_00_characters.sql','E5940BE836F253982E07930120422E598D08BDE1','ARCHIVED','2015-03-21 15:55:55',0),('2015_01_10_00_characters.sql','30796056C8623699B2FE1BF626A19D38262E9284','ARCHIVED','2015-03-21 15:55:55',0),('2015_01_16_00_characters.sql','96642760A54C8D799AAFE438049A63AA521656F2','ARCHIVED','2015-03-21 15:55:55',0),('2015_01_27_00_characters.sql','EB710E3EB9F2CAFD84AB62CDC84E898403A80A4F','ARCHIVED','2015-03-21 15:55:55',0),('2015_02_13_00_characters.sql','405BEB4ED207DC6076442A37EE2AFB1F21E274A0','ARCHIVED','2015-03-21 15:55:55',0),('2015_02_13_01_characters.sql','35F582D4F33BF55D1685A1BA89273ED895FD09C5','ARCHIVED','2015-03-21 15:55:55',0),('2015_02_17_00_characters.sql','8D21FC5A55BF8B55D6DCDCE5F02CF2B640230E94','ARCHIVED','2015-03-21 15:55:55',0),('2015_03_10_00_characters.sql','E565B89B145C340067742DFF2DEF1B74F5F1BD4E','ARCHIVED','2015-03-21 15:55:55',0),('2015_03_20_00_characters.sql','B761760804EA73BD297F296C5C1919687DF7191C','ARCHIVED','2015-03-21 15:55:55',0),('2015_03_20_01_characters.sql','20BD68468C57FCF7E665B4DA185DCD52FACE8B3F','ARCHIVED','2015-03-21 15:55:55',0),('2015_03_20_02_characters.sql','0296995DCD3676BA9AE6024CA7C91C5F39D927A3','ARCHIVED','2015-03-21 15:56:46',0),('2015_03_29_00_characters.sql','95D6A46BB746A8BD3EE3FE2086DF1A07F7C33B92','ARCHIVED','2015-05-02 15:43:06',0),('2015_04_21_00_characters.sql','F2032B9BF4EDA7EDE5065554724ED392FD91657D','ARCHIVED','2015-05-02 15:43:06',0),('2015_04_28_00_characters.sql','949F62DB3A3461D420A1230ECF7A6A3ED6435703','ARCHIVED','2015-05-02 15:43:06',0),('2015_05_08_00_characters.sql','0F14B7821618D1C872625B6EDDAA9A667B211167','ARCHIVED','2015-07-10 19:32:17',0),('2015_05_22_00_characters.sql','65B82152413FAB23BE413656E59A486A74447FF7','ARCHIVED','2015-07-10 19:32:17',0),('2015_07_08_00_characters.sql','DAB25360ACB5244C8F8E6214CF6BD97160588A5B','ARCHIVED','2015-07-10 19:32:17',0),('2015_07_11_00_characters.sql','B421B6C0E57BD0FD587071358863D9DABF4BA849','ARCHIVED','2015-07-13 21:50:02',0),('2015_07_12_00_characters.sql','E98E7FD61EF6426E7EDE8ED9AD8C15D8D7132589','ARCHIVED','2015-07-13 21:50:02',0),('2015_07_28_00_characters.sql','0711BC3A658D189EF71B0CB68DCFF2E9B781C4A0','ARCHIVED','2015-07-29 16:23:56',0),('2015_08_08_00_characters.sql','EA12BB2DC24FAF2300A96D0888A45BBEA158D5DC','ARCHIVED','2015-08-08 16:34:07',0),('2015_08_12_00_characters.sql','4FD7F89FE5DA51D4E0C33E520719986AA3EBD31B','ARCHIVED','2015-08-12 12:35:20',0),('2015_09_05_00_characters.sql','4C22BB29365BE4B6B95E64DAD84B63CA002304EA','ARCHIVED','2015-09-05 12:35:20',0),('2015_09_09_00_characters.sql','AFC32E693BC17CFD9A17919FE5317B8FE337ACAD','ARCHIVED','2015-09-09 12:35:20',0),('2015_09_10_00_characters.sql','4555A7F35C107E54C13D74D20F141039ED42943E','ARCHIVED','2015-09-10 22:50:42',0),('2015_10_16_00_characters.sql','E3A3FFF0CB42F04A8DCF0CE4362143C16E2083AF','ARCHIVED','2015-10-15 21:54:11',0),('2015_11_06_00_characters_2015_10_12_00.sql','D6F9927BDED72AD0A81D6EC2C6500CBC34A39FA2','ARCHIVED','2015-11-06 23:43:27',0),('2015_11_08_00_characters.sql','0ACDD35EC9745231BCFA701B78056DEF94D0CC53','RELEASED','2015-11-08 00:51:45',15),('2015_11_23_00_characters.sql','9FC828E9E48E8E2E9B99A5A0073D6614C5BFC6B5','RELEASED','2015-11-22 23:27:34',0);
+INSERT INTO `updates` VALUES ('2014_10_20_00_characters.sql','A5882DA0979CF4DAE33DA011EBAA006C24BE7230','ARCHIVED','2015-03-21 15:55:55',0),('2014_10_23_00_characters.sql','E2AC4758133EE19B7F08464A445802154D1261C8','ARCHIVED','2015-03-21 15:55:55',0),('2014_10_23_01_characters.sql','20029E6323D9773B32C34D84FFED1711CC60F09F','ARCHIVED','2015-03-21 15:55:55',0),('2014_10_23_02_characters.sql','8A7A16886EE71E7ACDDB3DDA6D0ECAC2FD2FDCA8','ARCHIVED','2015-03-21 15:55:55',0),('2014_10_24_00_characters.sql','D008FE81AE844FCA686439D6ECC5108FB0DD1EB9','ARCHIVED','2015-03-21 15:55:55',0),('2014_10_25_00_characters.sql','A39C7BE46686B54776BDAB9D7A882D91EDEC51A4','ARCHIVED','2015-03-21 15:55:55',0),('2014_10_26_00_characters.sql','C787954CC35FE34B4101FDE6527F14C027F4947C','ARCHIVED','2015-03-21 15:55:55',0),('2014_11_12_00_characters.sql','B160BB2313F1BD5F3B076A5A9279DC10D4796E34','ARCHIVED','2015-03-21 15:55:55',0),('2014_12_23_00_characters.sql','3D9D648B2387B357F4BD090B33F80682F7924882','ARCHIVED','2015-03-21 15:55:55',0),('2014_12_28_00_characters.sql','5362922FF4483A336311D73082A5727309CD9219','ARCHIVED','2015-03-21 15:55:55',0),('2014_12_31_00_characters.sql','498DDF2DD936CF156D74A8208DC93DCE9FCAB5AA','ARCHIVED','2015-03-21 15:55:55',0),('2015_01_02_00_characters.sql','E5940BE836F253982E07930120422E598D08BDE1','ARCHIVED','2015-03-21 15:55:55',0),('2015_01_10_00_characters.sql','30796056C8623699B2FE1BF626A19D38262E9284','ARCHIVED','2015-03-21 15:55:55',0),('2015_01_16_00_characters.sql','96642760A54C8D799AAFE438049A63AA521656F2','ARCHIVED','2015-03-21 15:55:55',0),('2015_01_27_00_characters.sql','EB710E3EB9F2CAFD84AB62CDC84E898403A80A4F','ARCHIVED','2015-03-21 15:55:55',0),('2015_02_13_00_characters.sql','405BEB4ED207DC6076442A37EE2AFB1F21E274A0','ARCHIVED','2015-03-21 15:55:55',0),('2015_02_13_01_characters.sql','35F582D4F33BF55D1685A1BA89273ED895FD09C5','ARCHIVED','2015-03-21 15:55:55',0),('2015_02_17_00_characters.sql','8D21FC5A55BF8B55D6DCDCE5F02CF2B640230E94','ARCHIVED','2015-03-21 15:55:55',0),('2015_03_10_00_characters.sql','E565B89B145C340067742DFF2DEF1B74F5F1BD4E','ARCHIVED','2015-03-21 15:55:55',0),('2015_03_20_00_characters.sql','B761760804EA73BD297F296C5C1919687DF7191C','ARCHIVED','2015-03-21 15:55:55',0),('2015_03_20_01_characters.sql','20BD68468C57FCF7E665B4DA185DCD52FACE8B3F','ARCHIVED','2015-03-21 15:55:55',0),('2015_03_20_02_characters.sql','0296995DCD3676BA9AE6024CA7C91C5F39D927A3','ARCHIVED','2015-03-21 15:56:46',0),('2015_03_29_00_characters.sql','95D6A46BB746A8BD3EE3FE2086DF1A07F7C33B92','ARCHIVED','2015-05-02 15:43:06',0),('2015_04_21_00_characters.sql','F2032B9BF4EDA7EDE5065554724ED392FD91657D','ARCHIVED','2015-05-02 15:43:06',0),('2015_04_28_00_characters.sql','949F62DB3A3461D420A1230ECF7A6A3ED6435703','ARCHIVED','2015-05-02 15:43:06',0),('2015_05_08_00_characters.sql','0F14B7821618D1C872625B6EDDAA9A667B211167','ARCHIVED','2015-07-10 19:32:17',0),('2015_05_22_00_characters.sql','65B82152413FAB23BE413656E59A486A74447FF7','ARCHIVED','2015-07-10 19:32:17',0),('2015_07_08_00_characters.sql','DAB25360ACB5244C8F8E6214CF6BD97160588A5B','ARCHIVED','2015-07-10 19:32:17',0),('2015_07_11_00_characters.sql','B421B6C0E57BD0FD587071358863D9DABF4BA849','ARCHIVED','2015-07-13 21:50:02',0),('2015_07_12_00_characters.sql','E98E7FD61EF6426E7EDE8ED9AD8C15D8D7132589','ARCHIVED','2015-07-13 21:50:02',0),('2015_07_28_00_characters.sql','0711BC3A658D189EF71B0CB68DCFF2E9B781C4A0','ARCHIVED','2015-07-29 16:23:56',0),('2015_08_08_00_characters.sql','EA12BB2DC24FAF2300A96D0888A45BBEA158D5DC','ARCHIVED','2015-08-08 16:34:07',0),('2015_08_12_00_characters.sql','4FD7F89FE5DA51D4E0C33E520719986AA3EBD31B','ARCHIVED','2015-08-12 12:35:20',0),('2015_09_05_00_characters.sql','4C22BB29365BE4B6B95E64DAD84B63CA002304EA','ARCHIVED','2015-09-05 12:35:20',0),('2015_09_09_00_characters.sql','AFC32E693BC17CFD9A17919FE5317B8FE337ACAD','ARCHIVED','2015-09-09 12:35:20',0),('2015_09_10_00_characters.sql','4555A7F35C107E54C13D74D20F141039ED42943E','ARCHIVED','2015-09-10 22:50:42',0),('2015_10_16_00_characters.sql','E3A3FFF0CB42F04A8DCF0CE4362143C16E2083AF','ARCHIVED','2015-10-15 21:54:11',0),('2015_11_06_00_characters_2015_10_12_00.sql','D6F9927BDED72AD0A81D6EC2C6500CBC34A39FA2','ARCHIVED','2015-11-06 23:43:27',0),('2015_11_08_00_characters.sql','0ACDD35EC9745231BCFA701B78056DEF94D0CC53','RELEASED','2015-11-08 00:51:45',15),('2015_11_23_00_characters.sql','9FC828E9E48E8E2E9B99A5A0073D6614C5BFC6B5','RELEASED','2015-11-22 23:27:34',0),('2016_01_05_00_characters.sql','0EAD24977F40DE2476B4567DA2B477867CC0DA1A','RELEASED','2016-01-04 23:07:40',0);
/*!40000 ALTER TABLE `updates` ENABLE KEYS */;
UNLOCK TABLES;
diff --git a/sql/updates/characters/2016_01_05_00_characters.sql b/sql/updates/characters/2016_01_05_00_characters.sql
new file mode 100644
index 00000000000..11850067be9
--- /dev/null
+++ b/sql/updates/characters/2016_01_05_00_characters.sql
@@ -0,0 +1,19 @@
+ALTER TABLE `characters`
+ ADD `skin` tinyint(3) unsigned NOT NULL DEFAULT '0' AFTER `money`,
+ ADD `face` tinyint(3) unsigned NOT NULL DEFAULT '0' AFTER `skin`,
+ ADD `hairStyle` tinyint(3) unsigned NOT NULL DEFAULT '0' AFTER `face`,
+ ADD `hairColor` tinyint(3) unsigned NOT NULL DEFAULT '0' AFTER `hairStyle`,
+ ADD `facialStyle` tinyint(3) unsigned NOT NULL DEFAULT '0' AFTER `hairColor`,
+ ADD `bankSlots` tinyint(3) unsigned NOT NULL DEFAULT '0' AFTER `facialStyle`,
+ ADD `restState` tinyint(3) unsigned NOT NULL DEFAULT '0' AFTER `bankSlots`;
+
+UPDATE `characters` SET
+ `skin`=`playerBytes`&0xFF,
+ `face`=(`playerBytes`>>8)&0xFF,
+ `hairStyle`=(`playerBytes`>>16)&0xFF,
+ `hairColor`=(`playerBytes`>>24)&0xFF,
+ `facialStyle`=`playerBytes2`&0xFF,
+ `bankSlots`=(`playerBytes2`>>16)&0xFF,
+ `restState`=(`playerBytes2`>>24)&0xFF;
+
+ALTER TABLE `characters` DROP `playerBytes`, DROP `playerBytes2`;
diff --git a/src/server/database/Database/Implementation/CharacterDatabase.cpp b/src/server/database/Database/Implementation/CharacterDatabase.cpp
index 8459d6d4ae4..2b802a634e0 100644
--- a/src/server/database/Database/Implementation/CharacterDatabase.cpp
+++ b/src/server/database/Database/Implementation/CharacterDatabase.cpp
@@ -44,20 +44,20 @@ void CharacterDatabaseConnection::DoPrepareStatements()
PrepareStatement(CHAR_SEL_MAIL_LIST_INFO, "SELECT id, sender, (SELECT name FROM characters WHERE guid = sender) AS sendername, receiver, (SELECT name FROM characters WHERE guid = receiver) AS receivername, "
"subject, deliver_time, expire_time, money, has_items FROM mail WHERE receiver = ? ", CONNECTION_SYNCH);
PrepareStatement(CHAR_SEL_MAIL_LIST_ITEMS, "SELECT itemEntry,count FROM item_instance WHERE guid = ?", CONNECTION_SYNCH);
- PrepareStatement(CHAR_SEL_ENUM, "SELECT c.guid, c.name, c.race, c.class, c.gender, c.playerBytes, c.playerBytes2, c.level, c.zone, c.map, c.position_x, c.position_y, c.position_z, "
+ PrepareStatement(CHAR_SEL_ENUM, "SELECT c.guid, c.name, c.race, c.class, c.gender, c.skin, c.face, c.hairStyle, c.hairColor, c.facialStyle, c.level, c.zone, c.map, c.position_x, c.position_y, c.position_z, "
"gm.guildid, c.playerFlags, c.at_login, cp.entry, cp.modelid, cp.level, c.equipmentCache, cb.guid, c.slot "
"FROM characters AS c LEFT JOIN character_pet AS cp ON c.guid = cp.owner AND cp.slot = ? LEFT JOIN guild_member AS gm ON c.guid = gm.guid "
"LEFT JOIN character_banned AS cb ON c.guid = cb.guid AND cb.active = 1 WHERE c.account = ? AND c.deleteInfos_Name IS NULL", CONNECTION_ASYNC);
- PrepareStatement(CHAR_SEL_ENUM_DECLINED_NAME, "SELECT c.guid, c.name, c.race, c.class, c.gender, c.playerBytes, c.playerBytes2, c.level, c.zone, c.map, "
+ PrepareStatement(CHAR_SEL_ENUM_DECLINED_NAME, "SELECT c.guid, c.name, c.race, c.class, c.gender, c.skin, c.face, c.hairStyle, c.hairColor, c.facialStyle, c.level, c.zone, c.map, "
"c.position_x, c.position_y, c.position_z, gm.guildid, c.playerFlags, c.at_login, cp.entry, cp.modelid, cp.level, c.equipmentCache, "
"cb.guid, c.slot, cd.genitive FROM characters AS c LEFT JOIN character_pet AS cp ON c.guid = cp.owner AND cp.slot = ? "
"LEFT JOIN character_declinedname AS cd ON c.guid = cd.guid LEFT JOIN guild_member AS gm ON c.guid = gm.guid "
"LEFT JOIN character_banned AS cb ON c.guid = cb.guid AND cb.active = 1 WHERE c.account = ? AND c.deleteInfos_Name IS NULL", CONNECTION_ASYNC);
- PrepareStatement(CHAR_SEL_UNDELETE_ENUM, "SELECT c.guid, c.deleteInfos_Name, c.race, c.class, c.gender, c.playerBytes, c.playerBytes2, c.level, c.zone, c.map, c.position_x, c.position_y, c.position_z, "
+ PrepareStatement(CHAR_SEL_UNDELETE_ENUM, "SELECT c.guid, c.deleteInfos_Name, c.race, c.class, c.gender, c.skin, c.face, c.hairStyle, c.hairColor, c.facialStyle, c.level, c.zone, c.map, c.position_x, c.position_y, c.position_z, "
"gm.guildid, c.playerFlags, c.at_login, cp.entry, cp.modelid, cp.level, c.equipmentCache, cb.guid, c.slot "
"FROM characters AS c LEFT JOIN character_pet AS cp ON c.guid = cp.owner AND cp.slot = ? LEFT JOIN guild_member AS gm ON c.guid = gm.guid "
"LEFT JOIN character_banned AS cb ON c.guid = cb.guid AND cb.active = 1 WHERE c.deleteInfos_Account = ? AND c.deleteInfos_Name IS NOT NULL", CONNECTION_ASYNC);
- PrepareStatement(CHAR_SEL_UNDELETE_ENUM_DECLINED_NAME, "SELECT c.guid, c.deleteInfos_Name, c.race, c.class, c.gender, c.playerBytes, c.playerBytes2, c.level, c.zone, c.map, "
+ PrepareStatement(CHAR_SEL_UNDELETE_ENUM_DECLINED_NAME, "SELECT c.guid, c.deleteInfos_Name, c.race, c.class, c.gender, c.skin, c.face, c.hairStyle, c.hairColor, c.facialStyle, c.level, c.zone, c.map, "
"c.position_x, c.position_y, c.position_z, gm.guildid, c.playerFlags, c.at_login, cp.entry, cp.modelid, cp.level, c.equipmentCache, "
"cb.guid, c.slot, cd.genitive FROM characters AS c LEFT JOIN character_pet AS cp ON c.guid = cp.owner AND cp.slot = ? "
"LEFT JOIN character_declinedname AS cd ON c.guid = cd.guid LEFT JOIN guild_member AS gm ON c.guid = gm.guid "
@@ -75,7 +75,7 @@ void CharacterDatabaseConnection::DoPrepareStatements()
PrepareStatement(CHAR_DEL_BATTLEGROUND_RANDOM, "DELETE FROM character_battleground_random WHERE guid = ?", CONNECTION_ASYNC);
PrepareStatement(CHAR_INS_BATTLEGROUND_RANDOM, "INSERT INTO character_battleground_random (guid) VALUES (?)", CONNECTION_ASYNC);
- PrepareStatement(CHAR_SEL_CHARACTER, "SELECT guid, account, name, race, class, gender, level, xp, money, playerBytes, playerBytes2, playerFlags, "
+ PrepareStatement(CHAR_SEL_CHARACTER, "SELECT guid, account, name, race, class, gender, level, xp, money, skin, face, hairStyle, hairColor, facialStyle, bankSlots, restState, playerFlags, "
"position_x, position_y, position_z, map, orientation, taximask, cinematic, totaltime, leveltime, rest_bonus, logout_time, is_logout_resting, resettalents_cost, "
"resettalents_time, talentTree, trans_x, trans_y, trans_z, trans_o, transguid, extra_flags, stable_slots, at_login, zone, online, death_expire_time, taxi_path, dungeonDifficulty, "
"totalKills, todayKills, yesterdayKills, chosenTitle, watchedFaction, drunk, "
@@ -386,7 +386,7 @@ void CharacterDatabaseConnection::DoPrepareStatements()
PrepareStatement(CHAR_DEL_LFG_DATA, "DELETE FROM lfg_data WHERE guid = ?", CONNECTION_ASYNC);
// Player saving
- PrepareStatement(CHAR_INS_CHARACTER, "INSERT INTO characters (guid, account, name, race, class, gender, level, xp, money, playerBytes, playerBytes2, playerFlags, "
+ PrepareStatement(CHAR_INS_CHARACTER, "INSERT INTO characters (guid, account, name, race, class, gender, level, xp, money, skin, face, hairStyle, hairColor, facialStyle, bankSlots, restState, playerFlags, "
"map, instance_id, dungeonDifficulty, raidDifficulty, legacyRaidDifficulty, position_x, position_y, position_z, orientation, trans_x, trans_y, trans_z, trans_o, transguid, "
"taximask, cinematic, "
"totaltime, leveltime, rest_bonus, logout_time, is_logout_resting, resettalents_cost, resettalents_time, talentTree, "
@@ -394,8 +394,8 @@ void CharacterDatabaseConnection::DoPrepareStatements()
"death_expire_time, taxi_path, totalKills, "
"todayKills, yesterdayKills, chosenTitle, watchedFaction, drunk, health, power1, power2, power3, "
"power4, power5, power6, latency, talentGroupsCount, activeTalentGroup, lootSpecId, exploredZones, equipmentCache, knownTitles, actionBars, grantableLevels) VALUES "
- "(?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)", CONNECTION_ASYNC);
- PrepareStatement(CHAR_UPD_CHARACTER, "UPDATE characters SET name=?,race=?,class=?,gender=?,level=?,xp=?,money=?,playerBytes=?,playerBytes2=?,playerFlags=?,"
+ "(?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)", CONNECTION_ASYNC);
+ PrepareStatement(CHAR_UPD_CHARACTER, "UPDATE characters SET name=?,race=?,class=?,gender=?,level=?,xp=?,money=?,skin=?,face=?,hairStyle=?,hairColor=?,facialStyle=?,bankSlots=?,restState=?,playerFlags=?,"
"map=?,instance_id=?,dungeonDifficulty=?,raidDifficulty=?,legacyRaidDifficulty=?,position_x=?,position_y=?,position_z=?,orientation=?,trans_x=?,trans_y=?,trans_z=?,trans_o=?,transguid=?,taximask=?,cinematic=?,totaltime=?,leveltime=?,rest_bonus=?,"
"logout_time=?,is_logout_resting=?,resettalents_cost=?,resettalents_time=?,talentTree=?,extra_flags=?,stable_slots=?,at_login=?,zone=?,death_expire_time=?,taxi_path=?,"
"totalKills=?,todayKills=?,yesterdayKills=?,chosenTitle=?,"
@@ -443,7 +443,7 @@ void CharacterDatabaseConnection::DoPrepareStatements()
PrepareStatement(CHAR_DEL_CHAR_INSTANCE_BY_INSTANCE_GUID, "DELETE FROM character_instance WHERE guid = ? AND instance = ?", CONNECTION_ASYNC);
PrepareStatement(CHAR_UPD_CHAR_INSTANCE, "UPDATE character_instance SET instance = ?, permanent = ? WHERE guid = ? AND instance = ?", CONNECTION_ASYNC);
PrepareStatement(CHAR_INS_CHAR_INSTANCE, "INSERT INTO character_instance (guid, instance, permanent) VALUES (?, ?, ?)", CONNECTION_ASYNC);
- PrepareStatement(CHAR_UPD_GENDER_PLAYERBYTES, "UPDATE characters SET gender = ?, playerBytes = ?, playerBytes2 = ? WHERE guid = ?", CONNECTION_ASYNC);
+ PrepareStatement(CHAR_UPD_GENDER_AND_APPEARANCE, "UPDATE characters SET gender = ?, skin = ?, face = ?, hairStyle = ?, hairColor = ?, facialStyle = ? WHERE guid = ?", CONNECTION_ASYNC);
PrepareStatement(CHAR_DEL_CHARACTER_SKILL, "DELETE FROM character_skills WHERE guid = ? AND skill = ?", CONNECTION_ASYNC);
PrepareStatement(CHAR_UPD_CHARACTER_SOCIAL_FLAGS, "UPDATE character_social SET flags = ? WHERE guid = ? AND friend = ?", CONNECTION_ASYNC);
PrepareStatement(CHAR_INS_CHARACTER_SOCIAL, "INSERT INTO character_social (guid, friend, flags) VALUES (?, ?, ?)", CONNECTION_ASYNC);
@@ -465,8 +465,8 @@ void CharacterDatabaseConnection::DoPrepareStatements()
PrepareStatement(CHAR_SEL_CHAR_HOMEBIND, "SELECT mapId, zoneId, posX, posY, posZ FROM character_homebind WHERE guid = ?", CONNECTION_SYNCH);
PrepareStatement(CHAR_SEL_CHAR_GUID_NAME_BY_ACC, "SELECT guid, name FROM characters WHERE account = ?", CONNECTION_SYNCH);
PrepareStatement(CHAR_SEL_POOL_QUEST_SAVE, "SELECT quest_id FROM pool_quest_save WHERE pool_id = ?", CONNECTION_SYNCH);
- PrepareStatement(CHAR_SEL_CHAR_CUSTOMIZE_INFO, "SELECT name, race, class, gender, at_login, playerBytes2 FROM characters WHERE guid = ?", CONNECTION_ASYNC);
- PrepareStatement(CHAR_SEL_CHAR_RACE_OR_FACTION_CHANGE_INFOS, "SELECT at_login, knownTitles, playerBytes, playerBytes2 FROM characters WHERE guid = ?", CONNECTION_ASYNC);
+ PrepareStatement(CHAR_SEL_CHAR_CUSTOMIZE_INFO, "SELECT name, race, class, gender, at_login FROM characters WHERE guid = ?", CONNECTION_ASYNC);
+ PrepareStatement(CHAR_SEL_CHAR_RACE_OR_FACTION_CHANGE_INFOS, "SELECT at_login, knownTitles, skin, face, hairStyle, hairColor, facialStyle FROM characters WHERE guid = ?", CONNECTION_ASYNC);
PrepareStatement(CHAR_SEL_INSTANCE, "SELECT data, completedEncounters FROM instance WHERE map = ? AND id = ?", CONNECTION_SYNCH);
PrepareStatement(CHAR_SEL_CHAR_COD_ITEM_MAIL, "SELECT id, messageType, mailTemplateId, sender, subject, body, money, has_items FROM mail WHERE receiver = ? AND has_items <> 0 AND cod <> 0", CONNECTION_SYNCH);
PrepareStatement(CHAR_SEL_CHAR_SOCIAL, "SELECT DISTINCT guid FROM character_social WHERE friend = ?", CONNECTION_SYNCH);
diff --git a/src/server/database/Database/Implementation/CharacterDatabase.h b/src/server/database/Database/Implementation/CharacterDatabase.h
index d2e1fcd247b..ebc63f1cb6e 100644
--- a/src/server/database/Database/Implementation/CharacterDatabase.h
+++ b/src/server/database/Database/Implementation/CharacterDatabase.h
@@ -360,7 +360,7 @@ enum CharacterDatabaseStatements
CHAR_DEL_CHAR_INSTANCE_BY_INSTANCE_GUID,
CHAR_UPD_CHAR_INSTANCE,
CHAR_INS_CHAR_INSTANCE,
- CHAR_UPD_GENDER_PLAYERBYTES,
+ CHAR_UPD_GENDER_AND_APPEARANCE,
CHAR_DEL_CHARACTER_SKILL,
CHAR_UPD_CHARACTER_SOCIAL_FLAGS,
CHAR_INS_CHARACTER_SOCIAL,
diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp
index 7045b33bbdc..1de45429acc 100644
--- a/src/server/game/Entities/Player/Player.cpp
+++ b/src/server/game/Entities/Player/Player.cpp
@@ -16211,17 +16211,17 @@ bool Player::IsLoading() const
bool Player::LoadFromDB(ObjectGuid guid, SQLQueryHolder *holder)
{
- //// 0 1 2 3 4 5 6 7 8 9 10 11
- //QueryResult* result = CharacterDatabase.PQuery("SELECT guid, account, name, race, class, gender, level, xp, money, playerBytes, playerBytes2, playerFlags, "
- // 12 13 14 15 16 17 18 19 20 21 22 23 24
+ // 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
+ //"SELECT guid, account, name, race, class, gender, level, xp, money, skin, face, hairStyle, hairColor, facialStyle, bankSlots, restState, playerFlags, "
+ // 17 18 19 20 21 22 23 24 25 26 27 28 29
//"position_x, position_y, position_z, map, orientation, taximask, cinematic, totaltime, leveltime, rest_bonus, logout_time, is_logout_resting, resettalents_cost, "
- // 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39
+ // 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44
//"resettalents_time, talentTree, trans_x, trans_y, trans_z, trans_o, transguid, extra_flags, stable_slots, at_login, zone, online, death_expire_time, taxi_path, dungeonDifficulty, "
- // 40 41 42 43 44 45
+ // 45 46 47 48 49 50
//"totalKills, todayKills, yesterdayKills, chosenTitle, watchedFaction, drunk, "
- // 46 47 48 49 50 51 52 53 54 55 56 57 58
+ // 51 52 53 54 55 56 57 58 59 60 61 62 63
//"health, power1, power2, power3, power4, power5, power6, instance_id, speccount, activespec, lootSpecId, exploredZones, equipmentCache, "
- // 59 60 61 62 63
+ // 64 65 66 67 68
//"knownTitles, actionBars, grantableLevels, raidDifficulty, legacyRaidDifficulty FROM characters WHERE guid = '%u'", guid);
PreparedQueryResult result = holder->GetPreparedResult(PLAYER_LOGIN_QUERY_LOAD_FROM);
if (!result)
@@ -16256,8 +16256,7 @@ bool Player::LoadFromDB(ObjectGuid guid, SQLQueryHolder *holder)
// check name limitations
if (ObjectMgr::CheckPlayerName(m_name, GetSession()->GetSessionDbcLocale()) != CHAR_NAME_SUCCESS ||
- (!GetSession()->HasPermission(rbac::RBAC_PERM_SKIP_CHECK_CHARACTER_CREATION_RESERVEDNAME) &&
- sObjectMgr->IsReservedName(m_name)))
+ (!GetSession()->HasPermission(rbac::RBAC_PERM_SKIP_CHECK_CHARACTER_CREATION_RESERVEDNAME) && sObjectMgr->IsReservedName(m_name)))
{
PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_UPD_ADD_AT_LOGIN_FLAG);
stmt->setUInt16(0, uint16(AT_LOGIN_RENAME));
@@ -16291,8 +16290,8 @@ bool Player::LoadFromDB(ObjectGuid guid, SQLQueryHolder *holder)
SetUInt32Value(UNIT_FIELD_LEVEL, fields[6].GetUInt8());
SetUInt32Value(PLAYER_XP, fields[7].GetUInt32());
- _LoadIntoDataField(fields[57].GetCString(), PLAYER_EXPLORED_ZONES_1, PLAYER_EXPLORED_ZONES_SIZE);
- _LoadIntoDataField(fields[59].GetCString(), PLAYER__FIELD_KNOWN_TITLES, KNOWN_TITLES_SIZE*2);
+ _LoadIntoDataField(fields[62].GetCString(), PLAYER_EXPLORED_ZONES_1, PLAYER_EXPLORED_ZONES_SIZE);
+ _LoadIntoDataField(fields[64].GetCString(), PLAYER__FIELD_KNOWN_TITLES, KNOWN_TITLES_SIZE * 2);
SetObjectScale(1.0f);
SetFloatValue(UNIT_FIELD_HOVERHEIGHT, 1.0f);
@@ -16305,28 +16304,34 @@ bool Player::LoadFromDB(ObjectGuid guid, SQLQueryHolder *holder)
money = MAX_MONEY_AMOUNT;
SetMoney(money);
- SetUInt32Value(PLAYER_BYTES, fields[9].GetUInt32());
- SetUInt32Value(PLAYER_BYTES_2, fields[10].GetUInt32());
+ SetByteValue(PLAYER_BYTES, PLAYER_BYTES_OFFSET_SKIN_ID, fields[9].GetUInt8());
+ SetByteValue(PLAYER_BYTES, PLAYER_BYTES_OFFSET_FACE_ID, fields[10].GetUInt8());
+ SetByteValue(PLAYER_BYTES, PLAYER_BYTES_OFFSET_HAIR_STYLE_ID, fields[11].GetUInt8());
+ SetByteValue(PLAYER_BYTES, PLAYER_BYTES_OFFSET_HAIR_COLOR_ID, fields[12].GetUInt8());
+ SetByteValue(PLAYER_BYTES_2, PLAYER_BYTES_2_OFFSET_FACIAL_STYLE, fields[13].GetUInt8());
+ SetByteValue(PLAYER_BYTES_2, PLAYER_BYTES_2_OFFSET_BANK_BAG_SLOTS, fields[14].GetUInt8());
+ SetByteValue(PLAYER_BYTES_2, PLAYER_BYTES_2_OFFSET_REST_STATE, fields[15].GetUInt8());
SetByteValue(PLAYER_BYTES_3, PLAYER_BYTES_3_OFFSET_GENDER, gender);
- SetByteValue(PLAYER_BYTES_3, PLAYER_BYTES_3_OFFSET_INEBRIATION, fields[45].GetUInt8());
- SetUInt32Value(PLAYER_FLAGS, fields[11].GetUInt32());
- SetInt32Value(PLAYER_FIELD_WATCHED_FACTION_INDEX, fields[44].GetUInt32());
+ SetByteValue(PLAYER_BYTES_3, PLAYER_BYTES_3_OFFSET_INEBRIATION, fields[50].GetUInt8());
+ SetUInt32Value(PLAYER_FLAGS, fields[16].GetUInt32());
+ SetInt32Value(PLAYER_FIELD_WATCHED_FACTION_INDEX, fields[49].GetUInt32());
if (!ValidateAppearance(
fields[3].GetUInt8(), // race
fields[4].GetUInt8(), // class
- gender, GetByteValue(PLAYER_BYTES, 2), // hair type
- GetByteValue(PLAYER_BYTES, 3), //hair color
- uint8(fields[9].GetUInt32() >> 8), // face
- GetByteValue(PLAYER_BYTES_2, 0), // facial hair
- GetByteValue(PLAYER_BYTES, 0))) // skin color
+ gender,
+ GetByteValue(PLAYER_BYTES, PLAYER_BYTES_OFFSET_HAIR_STYLE_ID),
+ GetByteValue(PLAYER_BYTES, PLAYER_BYTES_OFFSET_HAIR_COLOR_ID),
+ GetByteValue(PLAYER_BYTES, PLAYER_BYTES_OFFSET_FACE_ID),
+ GetByteValue(PLAYER_BYTES_2, PLAYER_BYTES_2_OFFSET_FACIAL_STYLE),
+ GetByteValue(PLAYER_BYTES, PLAYER_BYTES_OFFSET_SKIN_ID)))
{
TC_LOG_ERROR("entities.player", "Player::LoadFromDB: Player (%s) has wrong Appearance values (Hair/Skin/Color), can't load.", guid.ToString().c_str());
return false;
}
// set which actionbars the client has active - DO NOT REMOVE EVER AGAIN (can be changed though, if it does change fieldwise)
- SetByteValue(PLAYER_FIELD_BYTES, PLAYER_FIELD_BYTES_OFFSET_ACTION_BAR_TOGGLES, fields[60].GetUInt8());
+ SetByteValue(PLAYER_FIELD_BYTES, PLAYER_FIELD_BYTES_OFFSET_ACTION_BAR_TOGGLES, fields[65].GetUInt8());
InitDisplayIds();
@@ -16354,18 +16359,18 @@ bool Player::LoadFromDB(ObjectGuid guid, SQLQueryHolder *holder)
InitPrimaryProfessions(); // to max set before any spell loaded
// init saved position, and fix it later if problematic
- ObjectGuid::LowType transLowGUID = fields[31].GetUInt64();
+ ObjectGuid::LowType transLowGUID = fields[36].GetUInt64();
- Relocate(fields[12].GetFloat(), fields[13].GetFloat(), fields[14].GetFloat(), fields[16].GetFloat());
+ Relocate(fields[17].GetFloat(), fields[18].GetFloat(), fields[19].GetFloat(), fields[21].GetFloat());
- uint32 mapId = fields[15].GetUInt16();
- uint32 instanceId = fields[53].GetUInt32();
+ uint32 mapId = fields[20].GetUInt16();
+ uint32 instanceId = fields[58].GetUInt32();
- SetDungeonDifficultyID(CheckLoadedDungeonDifficultyID(Difficulty(fields[39].GetUInt8())));
- SetRaidDifficultyID(CheckLoadedRaidDifficultyID(Difficulty(fields[62].GetUInt8())));
- SetLegacyRaidDifficultyID(CheckLoadedLegacyRaidDifficultyID(Difficulty(fields[63].GetUInt8())));
+ SetDungeonDifficultyID(CheckLoadedDungeonDifficultyID(Difficulty(fields[44].GetUInt8())));
+ SetRaidDifficultyID(CheckLoadedRaidDifficultyID(Difficulty(fields[67].GetUInt8())));
+ SetLegacyRaidDifficultyID(CheckLoadedLegacyRaidDifficultyID(Difficulty(fields[68].GetUInt8())));
- std::string taxi_nodes = fields[38].GetString();
+ std::string taxi_nodes = fields[43].GetString();
#define RelocateToHomebind(){ mapId = m_homebindMapId; instanceId = 0; Relocate(m_homebindX, m_homebindY, m_homebindZ); }
@@ -16390,9 +16395,9 @@ bool Player::LoadFromDB(ObjectGuid guid, SQLQueryHolder *holder)
}
_LoadCurrency(holder->GetPreparedResult(PLAYER_LOGIN_QUERY_LOAD_CURRENCY));
- SetUInt32Value(PLAYER_FIELD_LIFETIME_HONORABLE_KILLS, fields[40].GetUInt32());
- SetUInt16Value(PLAYER_FIELD_KILLS, PLAYER_FIELD_KILLS_OFFSET_TODAY_KILLS, fields[41].GetUInt16());
- SetUInt16Value(PLAYER_FIELD_KILLS, PLAYER_FIELD_KILLS_OFFSET_YESTERDAY_KILLS, fields[42].GetUInt16());
+ SetUInt32Value(PLAYER_FIELD_LIFETIME_HONORABLE_KILLS, fields[45].GetUInt32());
+ SetUInt16Value(PLAYER_FIELD_KILLS, PLAYER_FIELD_KILLS_OFFSET_TODAY_KILLS, fields[46].GetUInt16());
+ SetUInt16Value(PLAYER_FIELD_KILLS, PLAYER_FIELD_KILLS_OFFSET_YESTERDAY_KILLS, fields[47].GetUInt16());
_LoadBoundInstances(holder->GetPreparedResult(PLAYER_LOGIN_QUERY_LOAD_BOUND_INSTANCES));
_LoadInstanceTimeRestrictions(holder->GetPreparedResult(PLAYER_LOGIN_QUERY_LOAD_INSTANCE_LOCK_TIMES));
@@ -16465,7 +16470,7 @@ bool Player::LoadFromDB(ObjectGuid guid, SQLQueryHolder *holder)
if (transport)
{
- float x = fields[27].GetFloat(), y = fields[28].GetFloat(), z = fields[29].GetFloat(), o = fields[30].GetFloat();
+ float x = fields[32].GetFloat(), y = fields[33].GetFloat(), z = fields[34].GetFloat(), o = fields[35].GetFloat();
m_movementInfo.transport.pos.Relocate(x, y, z, o);
transport->CalculatePassengerPosition(x, y, z, &o);
@@ -16626,12 +16631,12 @@ bool Player::LoadFromDB(ObjectGuid guid, SQLQueryHolder *holder)
// randomize first save time in range [CONFIG_INTERVAL_SAVE] around [CONFIG_INTERVAL_SAVE]
// this must help in case next save after mass player load after server startup
- m_nextSave = urand(m_nextSave/2, m_nextSave*3/2);
+ m_nextSave = urand(m_nextSave / 2, m_nextSave * 3 / 2);
SaveRecallPosition();
time_t now = time(nullptr);
- time_t logoutTime = time_t(fields[22].GetUInt32());
+ time_t logoutTime = time_t(fields[27].GetUInt32());
// since last logout (in seconds)
uint32 time_diff = uint32(now - logoutTime); //uint64 is excessive for a time_diff in seconds.. uint32 allows for 136~ year difference.
@@ -16644,18 +16649,18 @@ bool Player::LoadFromDB(ObjectGuid guid, SQLQueryHolder *holder)
SetDrunkValue(newDrunkValue);
- m_cinematic = fields[18].GetUInt8();
- m_Played_time[PLAYED_TIME_TOTAL]= fields[19].GetUInt32();
- m_Played_time[PLAYED_TIME_LEVEL]= fields[20].GetUInt32();
+ m_cinematic = fields[23].GetUInt8();
+ m_Played_time[PLAYED_TIME_TOTAL] = fields[24].GetUInt32();
+ m_Played_time[PLAYED_TIME_LEVEL] = fields[25].GetUInt32();
- SetTalentResetCost(fields[24].GetUInt32());
- SetTalentResetTime(time_t(fields[25].GetUInt32()));
+ SetTalentResetCost(fields[29].GetUInt32());
+ SetTalentResetTime(time_t(fields[30].GetUInt32()));
- m_taxi.LoadTaxiMask(fields[17].GetString()); // must be before InitTaxiNodesForLevel
+ m_taxi.LoadTaxiMask(fields[22].GetString()); // must be before InitTaxiNodesForLevel
- uint32 extraflags = fields[32].GetUInt16();
+ uint32 extraflags = fields[37].GetUInt16();
- m_stableSlots = fields[33].GetUInt8();
+ m_stableSlots = fields[38].GetUInt8();
if (m_stableSlots > MAX_PET_STABLES)
{
TC_LOG_ERROR("entities.player", "Player::LoadFromDB: Player (%s) can't have more stable slots than %u, but has %u in DB",
@@ -16663,7 +16668,7 @@ bool Player::LoadFromDB(ObjectGuid guid, SQLQueryHolder *holder)
m_stableSlots = MAX_PET_STABLES;
}
- m_atLoginFlags = fields[34].GetUInt16();
+ m_atLoginFlags = fields[39].GetUInt16();
if (HasAtLoginFlag(AT_LOGIN_RENAME))
{
@@ -16676,7 +16681,7 @@ bool Player::LoadFromDB(ObjectGuid guid, SQLQueryHolder *holder)
m_lastHonorUpdateTime = logoutTime;
UpdateHonorFields();
- m_deathExpireTime = time_t(fields[37].GetUInt32());
+ m_deathExpireTime = time_t(fields[42].GetUInt32());
if (m_deathExpireTime > now + MAX_DEATH_COUNT * DEATH_EXPIRE_STEP)
m_deathExpireTime = now + MAX_DEATH_COUNT * DEATH_EXPIRE_STEP - 1;
@@ -16713,7 +16718,7 @@ bool Player::LoadFromDB(ObjectGuid guid, SQLQueryHolder *holder)
InitRunes();
// rest bonus can only be calculated after InitStatsForLevel()
- m_rest_bonus = fields[21].GetFloat();
+ m_rest_bonus = fields[26].GetFloat();
if (time_diff > 0)
{
@@ -16721,26 +16726,21 @@ bool Player::LoadFromDB(ObjectGuid guid, SQLQueryHolder *holder)
float bubble0 = 0.031f;
//speed collect rest bonus in offline, in logout, in tavern, city (section/in hour)
float bubble1 = 0.125f;
- float bubble = fields[23].GetUInt8() > 0
+ float bubble = fields[28].GetUInt8() > 0
? bubble1*sWorld->getRate(RATE_REST_OFFLINE_IN_TAVERN_OR_CITY)
: bubble0*sWorld->getRate(RATE_REST_OFFLINE_IN_WILDERNESS);
- SetRestBonus(GetRestBonus()+ time_diff*((float)GetUInt32Value(PLAYER_NEXT_LEVEL_XP)/72000)*bubble);
+ SetRestBonus(GetRestBonus() + time_diff*((float)GetUInt32Value(PLAYER_NEXT_LEVEL_XP) / 72000)*bubble);
}
// load skills after InitStatsForLevel because it triggering aura apply also
_LoadSkills(holder->GetPreparedResult(PLAYER_LOGIN_QUERY_LOAD_SKILLS));
UpdateSkillsForLevel(); //update skills after load, to make sure they are correctly update at player load
- // apply original stats mods before spell loading or item equipment that call before equip _RemoveStatsMods()
-
- //mails are loaded only when needed ;-) - when player in game click on mailbox.
- //_LoadMail();
-
- SetTalentGroupsCount(fields[54].GetUInt8());
- SetActiveTalentGroup(fields[55].GetUInt8());
+ SetTalentGroupsCount(fields[59].GetUInt8());
+ SetActiveTalentGroup(fields[60].GetUInt8());
- uint32 lootSpecId = fields[56].GetUInt32();
+ uint32 lootSpecId = fields[61].GetUInt32();
if (ChrSpecializationEntry const* chrSpec = sChrSpecializationStore.LookupEntry(lootSpecId))
{
if (chrSpec->ClassID == getClass())
@@ -16756,7 +16756,7 @@ bool Player::LoadFromDB(ObjectGuid guid, SQLQueryHolder *holder)
}
// Only load selected specializations, learning mastery spells requires this
- Tokenizer talentSpecs(fields[26].GetString(), ' ', MAX_TALENT_GROUPS);
+ Tokenizer talentSpecs(fields[31].GetString(), ' ', MAX_TALENT_GROUPS);
for (uint8 i = 0; i < MAX_TALENT_GROUPS; ++i)
{
if (i >= talentSpecs.size())
@@ -16823,7 +16823,7 @@ bool Player::LoadFromDB(ObjectGuid guid, SQLQueryHolder *holder)
// check PLAYER_CHOSEN_TITLE compatibility with PLAYER__FIELD_KNOWN_TITLES
// note: PLAYER__FIELD_KNOWN_TITLES updated at quest status loaded
- uint32 curTitle = fields[43].GetUInt32();
+ uint32 curTitle = fields[48].GetUInt32();
if (curTitle && !HasTitle(curTitle))
curTitle = 0;
@@ -16846,14 +16846,14 @@ bool Player::LoadFromDB(ObjectGuid guid, SQLQueryHolder *holder)
UpdateAllStats();
// restore remembered power/health values (but not more max values)
- uint32 savedHealth = fields[46].GetUInt32();
+ uint32 savedHealth = fields[51].GetUInt32();
SetHealth(savedHealth > GetMaxHealth() ? GetMaxHealth() : savedHealth);
uint32 loadedPowers = 0;
for (uint32 i = 0; i < MAX_POWERS; ++i)
{
if (GetPowerIndex(i) != MAX_POWERS)
{
- uint32 savedPower = fields[47+loadedPowers].GetUInt32();
+ uint32 savedPower = fields[52 + loadedPowers].GetUInt32();
uint32 maxPower = GetUInt32Value(UNIT_FIELD_MAXPOWER + loadedPowers);
SetPower(Powers(i), (savedPower > maxPower) ? maxPower : savedPower);
if (++loadedPowers >= MAX_POWERS_PER_CLASS)
@@ -16918,7 +16918,7 @@ bool Player::LoadFromDB(ObjectGuid guid, SQLQueryHolder *holder)
}
// RaF stuff.
- m_grantableLevels = fields[61].GetUInt8();
+ m_grantableLevels = fields[66].GetUInt8();
if (GetSession()->IsARecruiter() || (GetSession()->GetRecruiterId() != 0))
SetFlag(OBJECT_DYNAMIC_FLAGS, UNIT_DYNFLAG_REFER_A_FRIEND);
@@ -16933,10 +16933,10 @@ bool Player::LoadFromDB(ObjectGuid guid, SQLQueryHolder *holder)
std::unique_ptr<Garrison> garrison = Trinity::make_unique<Garrison>(this);
if (garrison->LoadFromDB(holder->GetPreparedResult(PLAYER_LOGIN_QUERY_LOAD_GARRISON),
- holder->GetPreparedResult(PLAYER_LOGIN_QUERY_LOAD_GARRISON_BLUEPRINTS),
- holder->GetPreparedResult(PLAYER_LOGIN_QUERY_LOAD_GARRISON_BUILDINGS),
- holder->GetPreparedResult(PLAYER_LOGIN_QUERY_LOAD_GARRISON_FOLLOWERS),
- holder->GetPreparedResult(PLAYER_LOGIN_QUERY_LOAD_GARRISON_FOLLOWER_ABILITIES)))
+ holder->GetPreparedResult(PLAYER_LOGIN_QUERY_LOAD_GARRISON_BLUEPRINTS),
+ holder->GetPreparedResult(PLAYER_LOGIN_QUERY_LOAD_GARRISON_BUILDINGS),
+ holder->GetPreparedResult(PLAYER_LOGIN_QUERY_LOAD_GARRISON_FOLLOWERS),
+ holder->GetPreparedResult(PLAYER_LOGIN_QUERY_LOAD_GARRISON_FOLLOWER_ABILITIES)))
_garrison = std::move(garrison);
m_achievementMgr->CheckAllAchievementCriteria(this);
@@ -18458,8 +18458,13 @@ void Player::SaveToDB(bool create /*=false*/)
stmt->setUInt8(index++, getLevel());
stmt->setUInt32(index++, GetUInt32Value(PLAYER_XP));
stmt->setUInt64(index++, GetMoney());
- stmt->setUInt32(index++, GetUInt32Value(PLAYER_BYTES));
- stmt->setUInt32(index++, GetUInt32Value(PLAYER_BYTES_2));
+ stmt->setUInt8(index++, GetByteValue(PLAYER_BYTES, PLAYER_BYTES_OFFSET_SKIN_ID));
+ stmt->setUInt8(index++, GetByteValue(PLAYER_BYTES, PLAYER_BYTES_OFFSET_FACE_ID));
+ stmt->setUInt8(index++, GetByteValue(PLAYER_BYTES, PLAYER_BYTES_OFFSET_HAIR_STYLE_ID));
+ stmt->setUInt8(index++, GetByteValue(PLAYER_BYTES, PLAYER_BYTES_OFFSET_HAIR_COLOR_ID));
+ stmt->setUInt8(index++, GetByteValue(PLAYER_BYTES_2, PLAYER_BYTES_2_OFFSET_FACIAL_STYLE));
+ stmt->setUInt8(index++, GetByteValue(PLAYER_BYTES_2, PLAYER_BYTES_2_OFFSET_BANK_BAG_SLOTS));
+ stmt->setUInt8(index++, GetByteValue(PLAYER_BYTES_2, PLAYER_BYTES_2_OFFSET_REST_STATE));
stmt->setUInt32(index++, GetUInt32Value(PLAYER_FLAGS));
stmt->setUInt16(index++, (uint16)GetMapId());
stmt->setUInt32(index++, (uint32)GetInstanceId());
@@ -18580,8 +18585,13 @@ void Player::SaveToDB(bool create /*=false*/)
stmt->setUInt8(index++, getLevel());
stmt->setUInt32(index++, GetUInt32Value(PLAYER_XP));
stmt->setUInt64(index++, GetMoney());
- stmt->setUInt32(index++, GetUInt32Value(PLAYER_BYTES));
- stmt->setUInt32(index++, GetUInt32Value(PLAYER_BYTES_2));
+ stmt->setUInt8(index++, GetByteValue(PLAYER_BYTES, PLAYER_BYTES_OFFSET_SKIN_ID));
+ stmt->setUInt8(index++, GetByteValue(PLAYER_BYTES, PLAYER_BYTES_OFFSET_FACE_ID));
+ stmt->setUInt8(index++, GetByteValue(PLAYER_BYTES, PLAYER_BYTES_OFFSET_HAIR_STYLE_ID));
+ stmt->setUInt8(index++, GetByteValue(PLAYER_BYTES, PLAYER_BYTES_OFFSET_HAIR_COLOR_ID));
+ stmt->setUInt8(index++, GetByteValue(PLAYER_BYTES_2, PLAYER_BYTES_2_OFFSET_FACIAL_STYLE));
+ stmt->setUInt8(index++, GetByteValue(PLAYER_BYTES_2, PLAYER_BYTES_2_OFFSET_BANK_BAG_SLOTS));
+ stmt->setUInt8(index++, GetByteValue(PLAYER_BYTES_2, PLAYER_BYTES_2_OFFSET_REST_STATE));
stmt->setUInt32(index++, GetUInt32Value(PLAYER_FLAGS));
if (!IsBeingTeleported())
diff --git a/src/server/game/Handlers/CharacterHandler.cpp b/src/server/game/Handlers/CharacterHandler.cpp
index 30ddd4ab201..ecccdc9525a 100644
--- a/src/server/game/Handlers/CharacterHandler.cpp
+++ b/src/server/game/Handlers/CharacterHandler.cpp
@@ -1550,7 +1550,6 @@ void WorldSession::HandleCharCustomizeCallback(PreparedQueryResult result, World
uint8 plrClass = fields[2].GetUInt8();
uint8 plrGender = fields[3].GetUInt8();
uint16 atLoginFlags = fields[4].GetUInt16();
- uint32 playerBytes2 = fields[5].GetUInt32();
if (!Player::ValidateAppearance(plrRace, plrClass, plrGender, customizeInfo->HairStyleID, customizeInfo->HairColorID, customizeInfo->FaceID, customizeInfo->FacialHairStyleID, customizeInfo->SkinID, true))
{
@@ -1606,15 +1605,15 @@ void WorldSession::HandleCharCustomizeCallback(PreparedQueryResult result, World
/// Customize
{
- playerBytes2 &= ~0xFF;
- playerBytes2 |= customizeInfo->FacialHairStyleID;
-
- stmt = CharacterDatabase.GetPreparedStatement(CHAR_UPD_GENDER_PLAYERBYTES);
+ stmt = CharacterDatabase.GetPreparedStatement(CHAR_UPD_GENDER_AND_APPEARANCE);
stmt->setUInt8(0, customizeInfo->SexID);
- stmt->setUInt32(1, customizeInfo->SkinID | (uint32(customizeInfo->FaceID) << 8) | (uint32(customizeInfo->HairStyleID) << 16) | (uint32(customizeInfo->HairColorID) << 24));
- stmt->setUInt32(2, playerBytes2);
- stmt->setUInt64(3, lowGuid);
+ stmt->setUInt8(1, customizeInfo->SkinID);
+ stmt->setUInt8(2, customizeInfo->FaceID);
+ stmt->setUInt8(3, customizeInfo->HairStyleID);
+ stmt->setUInt8(4, customizeInfo->HairColorID);
+ stmt->setUInt8(5, customizeInfo->FacialHairStyleID);
+ stmt->setUInt64(6, lowGuid);
trans->Append(stmt);
}
@@ -1777,8 +1776,6 @@ void WorldSession::HandleCharRaceOrFactionChangeCallback(PreparedQueryResult res
Field* fields = result->Fetch();
uint16 atLoginFlags = fields[0].GetUInt16();
std::string knownTitlesStr = fields[1].GetString();
- uint32 playerBytes = fields[2].GetUInt32();
- uint32 playerBytes2 = fields[3].GetUInt32();
uint16 usedLoginFlag = (factionChangeInfo->FactionChange ? AT_LOGIN_CHANGE_FACTION : AT_LOGIN_CHANGE_RACE);
if (!(atLoginFlags & usedLoginFlag))
@@ -1876,51 +1873,29 @@ void WorldSession::HandleCharRaceOrFactionChangeCallback(PreparedQueryResult res
// Customize
{
- if (factionChangeInfo->SkinID)
- {
- playerBytes &= ~uint32(0xFF);
- playerBytes |= *factionChangeInfo->SkinID;
- }
- else
- factionChangeInfo->SkinID = uint8(playerBytes & 0xFF);
+ if (!factionChangeInfo->SkinID)
+ factionChangeInfo->SkinID = fields[2].GetUInt8();
- if (factionChangeInfo->FaceID)
- {
- playerBytes &= ~(uint32(0xFF) << 8);
- playerBytes |= uint32(*factionChangeInfo->FaceID) << 8;
- }
- else
- factionChangeInfo->FaceID = uint8((playerBytes2 >> 8) & 0xFF);
+ if (!factionChangeInfo->FaceID)
+ factionChangeInfo->FaceID = fields[3].GetUInt8();
- if (factionChangeInfo->HairStyleID)
- {
- playerBytes &= ~(uint32(0xFF) << 16);
- playerBytes |= uint32(*factionChangeInfo->HairStyleID) << 16;
- }
- else
- factionChangeInfo->HairStyleID = uint8((playerBytes2 >> 16) & 0xFF);
+ if (!factionChangeInfo->HairStyleID)
+ factionChangeInfo->HairStyleID = fields[4].GetUInt8();
- if (factionChangeInfo->HairColorID)
- {
- playerBytes &= ~(uint32(0xFF) << 24);
- playerBytes |= uint32(*factionChangeInfo->HairColorID) << 24;
- }
- else
- factionChangeInfo->HairColorID = uint8((playerBytes2 >> 24) & 0xFF);
+ if (!factionChangeInfo->HairColorID)
+ factionChangeInfo->HairColorID = fields[5].GetUInt8();
- if (factionChangeInfo->FacialHairStyleID)
- {
- playerBytes2 &= ~0xFF;
- playerBytes2 |= *factionChangeInfo->FacialHairStyleID;
- }
- else
- factionChangeInfo->FacialHairStyleID = int8(playerBytes2 & 0xFF);
+ if (!factionChangeInfo->FacialHairStyleID)
+ factionChangeInfo->FacialHairStyleID = fields[6].GetUInt8();
- stmt = CharacterDatabase.GetPreparedStatement(CHAR_UPD_GENDER_PLAYERBYTES);
+ stmt = CharacterDatabase.GetPreparedStatement(CHAR_UPD_GENDER_AND_APPEARANCE);
stmt->setUInt8(0, factionChangeInfo->SexID);
- stmt->setUInt32(1, playerBytes);
- stmt->setUInt32(2, playerBytes2);
- stmt->setUInt64(3, lowGuid);
+ stmt->setUInt8(1, *factionChangeInfo->SkinID);
+ stmt->setUInt8(2, *factionChangeInfo->FaceID);
+ stmt->setUInt8(3, *factionChangeInfo->HairStyleID);
+ stmt->setUInt8(4, *factionChangeInfo->HairColorID);
+ stmt->setUInt8(5, *factionChangeInfo->FacialHairStyleID);
+ stmt->setUInt64(6, lowGuid);
trans->Append(stmt);
}
diff --git a/src/server/game/Server/Packets/CharacterPackets.cpp b/src/server/game/Server/Packets/CharacterPackets.cpp
index 7541bb8de70..ef41d16c2b2 100644
--- a/src/server/game/Server/Packets/CharacterPackets.cpp
+++ b/src/server/game/Server/Packets/CharacterPackets.cpp
@@ -22,35 +22,37 @@
WorldPackets::Character::EnumCharactersResult::CharacterInfo::CharacterInfo(Field* fields)
{
- // 0 1 2 3 4 5 6 7
- // "SELECT characters.guid, characters.name, characters.race, characters.class, characters.gender, characters.playerBytes, characters.playerBytes2, characters.level, "
- // 8 9 10 11 12 13 14
- // "characters.zone, characters.map, characters.position_x, characters.position_y, characters.position_z, guild_member.guildid, characters.playerFlags, "
- // 15 16 17 18 19 20 21 22
- // "characters.at_login, character_pet.entry, character_pet.modelid, character_pet.level, characters.data, character_banned.guid, characters.slot, character_declinedname.genitive"
+ // 0 1 2 3 4 5 6 7
+ // "SELECT characters.guid, characters.name, characters.race, characters.class, characters.gender, characters.skin, characters.face, characters.hairStyle, "
+ // 8 9 10 11 12 13 14 15
+ // "characters.hairColor, characters.facialStyle, characters.level, characters.zone, characters.map, characters.position_x, characters.position_y, characters.position_z, "
+ // 16 17 18 19 20 21 22
+ // "guild_member.guildid, characters.playerFlags, characters.at_login, character_pet.entry, character_pet.modelid, character_pet.level, characters.equipmentCache, "
+ // 23 24 25
+ // "character_banned.guid, characters.slot, character_declinedname.genitive"
Guid = ObjectGuid::Create<HighGuid::Player>(fields[0].GetUInt64());
Name = fields[1].GetString();
Race = fields[2].GetUInt8();
Class = fields[3].GetUInt8();
Sex = fields[4].GetUInt8();
- Skin = uint8(fields[5].GetUInt32() & 0xFF);
- Face = uint8((fields[5].GetUInt32() >> 8) & 0xFF);
- HairStyle = uint8((fields[5].GetUInt32() >> 16) & 0xFF);
- HairColor = uint8((fields[5].GetUInt32() >> 24) & 0xFF);
- FacialHair = uint8(fields[6].GetUInt32() & 0xFF);
- Level = fields[7].GetUInt8();
- ZoneId = int32(fields[8].GetUInt16());
- MapId = int32(fields[9].GetUInt16());
- PreLoadPosition.x = fields[10].GetFloat();
- PreLoadPosition.y = fields[11].GetFloat();
- PreLoadPosition.z = fields[12].GetFloat();
-
- if (ObjectGuid::LowType guildId = fields[13].GetUInt64())
+ Skin = fields[5].GetUInt8();
+ Face = fields[6].GetUInt8();
+ HairStyle = fields[7].GetUInt8();
+ HairColor = fields[8].GetUInt8();
+ FacialHair = fields[9].GetUInt8();
+ Level = fields[10].GetUInt8();
+ ZoneId = int32(fields[11].GetUInt16());
+ MapId = int32(fields[12].GetUInt16());
+ PreLoadPosition.x = fields[13].GetFloat();
+ PreLoadPosition.y = fields[14].GetFloat();
+ PreLoadPosition.z = fields[15].GetFloat();
+
+ if (ObjectGuid::LowType guildId = fields[16].GetUInt64())
GuildGuid = ObjectGuid::Create<HighGuid::Guild>(guildId);
- uint32 playerFlags = fields[14].GetUInt32();
- uint32 atLoginFlags = fields[15].GetUInt16();
+ uint32 playerFlags = fields[17].GetUInt32();
+ uint32 atLoginFlags = fields[18].GetUInt16();
if (atLoginFlags & AT_LOGIN_RESURRECT)
playerFlags &= ~PLAYER_FLAGS_GHOST;
@@ -67,10 +69,10 @@ WorldPackets::Character::EnumCharactersResult::CharacterInfo::CharacterInfo(Fiel
if (atLoginFlags & AT_LOGIN_RENAME)
Flags |= CHARACTER_FLAG_RENAME;
- if (fields[20].GetUInt32())
+ if (fields[23].GetUInt64())
Flags |= CHARACTER_FLAG_LOCKED_BY_BILLING;
- if (sWorld->getBoolConfig(CONFIG_DECLINED_NAMES_USED) && !fields[22].GetString().empty())
+ if (sWorld->getBoolConfig(CONFIG_DECLINED_NAMES_USED) && !fields[25].GetString().empty())
Flags |= CHARACTER_FLAG_DECLINED;
if (atLoginFlags & AT_LOGIN_CUSTOMIZE)
@@ -86,10 +88,10 @@ WorldPackets::Character::EnumCharactersResult::CharacterInfo::CharacterInfo(Fiel
// show pet at selection character in character list only for non-ghost character
if (!(playerFlags & PLAYER_FLAGS_GHOST) && (Class == CLASS_WARLOCK || Class == CLASS_HUNTER || Class == CLASS_DEATH_KNIGHT))
{
- if (CreatureTemplate const* creatureInfo = sObjectMgr->GetCreatureTemplate(fields[16].GetUInt32()))
+ if (CreatureTemplate const* creatureInfo = sObjectMgr->GetCreatureTemplate(fields[19].GetUInt32()))
{
- Pet.CreatureDisplayId = fields[17].GetUInt32();
- Pet.Level = fields[18].GetUInt16();
+ Pet.CreatureDisplayId = fields[20].GetUInt32();
+ Pet.Level = fields[21].GetUInt16();
Pet.CreatureFamily = creatureInfo->family;
}
}
@@ -98,8 +100,8 @@ WorldPackets::Character::EnumCharactersResult::CharacterInfo::CharacterInfo(Fiel
ProfessionIds[0] = 0;
ProfessionIds[1] = 0;
- Tokenizer equipment(fields[19].GetString(), ' ');
- ListPosition = fields[21].GetUInt8();
+ Tokenizer equipment(fields[22].GetString(), ' ');
+ ListPosition = fields[24].GetUInt8();
for (uint8 slot = 0; slot < INVENTORY_SLOT_BAG_END; ++slot)
{