All pastes #1469152 Raw Copy code Copy link Edit

Zeug

public diff v1 · immutable
#1469152 ·published 2009-06-21 20:32 UTC
rendered paste body
diff --git a/sql/characters.sql b/sql/characters.sqlindex 2783b8e..33809fd 100644--- a/sql/characters.sql+++ b/sql/characters.sql@@ -197,6 +197,13 @@ CREATE TABLE `characters` (   `name` varchar(12) NOT NULL default '',   `race` tinyint(3) unsigned NOT NULL default '0',   `class` tinyint(3) unsigned NOT NULL default '0',+  `gender` TINYINT UNSIGNED NOT NULL,+  `level` TINYINT UNSIGNED NOT NULL,+  `xp` INT UNSIGNED NOT NULL,+  `money` INT UNSIGNED NOT NULL,+  `playerBytes` INT UNSIGNED NOT NULL,+  `playerBytes2` INT UNSIGNED NOT NULL,+  `playerFlags` INT UNSIGNED NOT NULL,   `position_x` float NOT NULL default '0',   `position_y` float NOT NULL default '0',   `position_z` float NOT NULL default '0',diff --git a/sql/updates/9999_01_characters_characters.sql b/sql/updates/9999_01_characters_characters.sqlnew file mode 100644index 0000000..026b403--- /dev/null+++ b/sql/updates/9999_01_characters_characters.sql@@ -0,0 +1,17 @@+ALTER TABLE characters+ADD gender TINYINT UNSIGNED NOT NULL AFTER class,+ADD level TINYINT UNSIGNED NOT NULL AFTER gender,+ADD xp INT UNSIGNED NOT NULL AFTER level,+ADD money INT UNSIGNED NOT NULL AFTER xp,+ADD playerBytes INT UNSIGNED NOT NULL AFTER money,+ADD playerBytes2 INT UNSIGNED NOT NULL AFTER playerBytes,+ADD playerFlags INT UNSIGNED NOT NULL AFTER playerBytes2;++UPDATE characters SET+gender = (CAST(SUBSTRING_INDEX(SUBSTRING_INDEX(data, ' ', 23), ' ', -1) AS UNSIGNED) & 0xFF0000) >> 16,+level = CAST(SUBSTRING_INDEX(SUBSTRING_INDEX(data, ' ', 54), ' ', -1) AS UNSIGNED),+xp = CAST(SUBSTRING_INDEX(SUBSTRING_INDEX(data, ' ', 609), ' ', -1) AS UNSIGNED),+money = CAST(SUBSTRING_INDEX(SUBSTRING_INDEX(data, ' ', 1145), ' ', -1) AS UNSIGNED),+playerBytes = CAST(SUBSTRING_INDEX(SUBSTRING_INDEX(data, ' ', 154), ' ', -1) AS UNSIGNED),+playerBytes2 = CAST(SUBSTRING_INDEX(SUBSTRING_INDEX(data, ' ', 155), ' ', -1) AS UNSIGNED),+playerFlags = CAST(SUBSTRING_INDEX(SUBSTRING_INDEX(data, ' ', 151), ' ', -1) AS UNSIGNED);diff --git a/src/game/CharacterHandler.cpp b/src/game/CharacterHandler.cppindex dcd61ea..7f5f010 100644--- a/src/game/CharacterHandler.cpp+++ b/src/game/CharacterHandler.cpp@@ -59,7 +59,7 @@ bool LoginQueryHolder::Initialize()      // NOTE: all fields in `characters` must be read to prevent lost character data at next save in case wrong DB structure.     // !!! NOTE: including unused `zone`,`online`-    res &= SetPQuery(PLAYER_LOGIN_QUERY_LOADFROM,            "SELECT guid, account, data, name, race, class, position_x, position_y, position_z, map, orientation, taximask, cinematic, totaltime, leveltime, rest_bonus, logout_time, is_logout_resting, resettalents_cost, resettalents_time, trans_x, trans_y, trans_z, trans_o, transguid, extra_flags, stable_slots, at_login, zone, online, death_expire_time, taxi_path, dungeon_difficulty, arena_pending_points,bgid,bgteam,bgmap,bgx,bgy,bgz,bgo FROM characters WHERE guid = '%u'", GUID_LOPART(m_guid));+    res &= SetPQuery(PLAYER_LOGIN_QUERY_LOADFROM,            "SELECT guid, account, data, name, race, class, gender, level, xp, money, playerBytes, playerBytes2, playerFlags, position_x, position_y, position_z, map, orientation, taximask, cinematic, totaltime, leveltime, rest_bonus, logout_time, is_logout_resting, resettalents_cost, resettalents_time, trans_x, trans_y, trans_z, trans_o, transguid, extra_flags, stable_slots, at_login, zone, online, death_expire_time, taxi_path, dungeon_difficulty, arena_pending_points,bgid,bgteam,bgmap,bgx,bgy,bgz,bgo FROM characters WHERE guid = '%u'", GUID_LOPART(m_guid));     res &= SetPQuery(PLAYER_LOGIN_QUERY_LOADGROUP,           "SELECT leaderGuid FROM group_member WHERE memberGuid ='%u'", GUID_LOPART(m_guid));     res &= SetPQuery(PLAYER_LOGIN_QUERY_LOADBOUNDINSTANCES,  "SELECT id, permanent, map, difficulty, resettime FROM character_instance LEFT JOIN instance ON instance = id WHERE guid = '%u'", GUID_LOPART(m_guid));     res &= SetPQuery(PLAYER_LOGIN_QUERY_LOADAURAS,           "SELECT caster_guid,spell,effect_index,stackcount,amount,maxduration,remaintime,remaincharges FROM character_aura WHERE guid = '%u'", GUID_LOPART(m_guid));@@ -133,12 +133,8 @@ void WorldSession::HandleCharEnum(QueryResult * result)         {             uint32 guidlow = (*result)[0].GetUInt32();             sLog.outDetail("Loading char guid %u from account %u.",guidlow,GetAccountId());--            if(plr->MinimalLoadFromDB( result, guidlow ))-            {-                plr->BuildEnumData( result, &data );-                ++num;-            }+            Player::BuildEnumData(result, &data);+            ++num;         }         while( result->NextRow() ); @@ -157,19 +153,23 @@ void WorldSession::HandleCharEnumOpcode( WorldPacket & /*recv_data*/ )     CharacterDatabase.AsyncPQuery(&chrHandler, &CharacterHandler::HandleCharEnumCallback, GetAccountId(),          !sWorld.getConfig(CONFIG_DECLINED_NAMES_USED) ?     //   ------- Query Without Declined Names ---------    //          0                1                2                3                      4                      5               6                     7                     8-        "SELECT characters.guid, characters.data, characters.name, characters.position_x, characters.position_y, characters.position_z, characters.map, characters.totaltime, characters.leveltime, "-    //   9                     10              11                   12                     13                   14-        "characters.at_login, characters.zone, character_pet.entry, character_pet.modelid, character_pet.level, guild_member.guildid "+    //           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+        "characters.at_login, character_pet.entry, character_pet.modelid, character_pet.level, characters.data "         "FROM characters LEFT JOIN character_pet ON characters.guid=character_pet.owner AND character_pet.slot='%u' "         "LEFT JOIN guild_member ON characters.guid = guild_member.guid "         "WHERE characters.account = '%u' ORDER BY characters.guid"         :     //   --------- Query With Declined Names ----------    //          0                1                2                3                      4                      5               6                     7                     8-        "SELECT characters.guid, characters.data, characters.name, characters.position_x, characters.position_y, characters.position_z, characters.map, characters.totaltime, characters.leveltime, "-    //   9                    10               11                   12                     13                   14                 15-        "characters.at_login, characters.zone, character_pet.entry, character_pet.modelid, character_pet.level, guild_member.guildid, character_declinedname.genitive "+    //           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+        "characters.at_login, character_pet.entry, character_pet.modelid, character_pet.level, characters.data, character_declinedname.genitive "         "FROM characters LEFT JOIN character_pet ON characters.guid = character_pet.owner AND character_pet.slot='%u' "         "LEFT JOIN character_declinedname ON characters.guid = character_declinedname.guid "         "LEFT JOIN guild_member ON characters.guid = guild_member.guid "@@ -335,7 +335,7 @@ void WorldSession::HandleCharCreateOpcode( WorldPacket & recv_data )      if(!AllowTwoSideAccounts || skipCinematics == 1 || class_ == CLASS_DEATH_KNIGHT)     {-        QueryResult *result2 = CharacterDatabase.PQuery("SELECT guid,race,class FROM characters WHERE account = '%u' %s",+        QueryResult *result2 = CharacterDatabase.PQuery("SELECT level,race,class FROM characters WHERE account = '%u' %s",             GetAccountId(), (skipCinematics == 1 || class_ == CLASS_DEATH_KNIGHT) ? "" : "LIMIT 1");         if(result2)         {@@ -362,8 +362,7 @@ void WorldSession::HandleCharCreateOpcode( WorldPacket & recv_data )                  if(!have_req_level_for_heroic)                 {-                    uint32 acc_guid = field[0].GetUInt32();-                    uint32 acc_level = Player::GetUInt32ValueFromDB(UNIT_FIELD_LEVEL,acc_guid);+                    uint32 acc_level = field[0].GetUInt32();                     if(acc_level >= req_level_for_heroic)                         have_req_level_for_heroic = true;                 }@@ -417,8 +416,7 @@ void WorldSession::HandleCharCreateOpcode( WorldPacket & recv_data )                      if(!have_req_level_for_heroic)                     {-                        uint32 acc_guid = field[0].GetUInt32();-                        uint32 acc_level = Player::GetUInt32ValueFromDB(UNIT_FIELD_LEVEL,acc_guid);+                        uint32 acc_level = field[0].GetUInt32();                         if(acc_level >= req_level_for_heroic)                             have_req_level_for_heroic = true;                     }diff --git a/src/game/Guild.cpp b/src/game/Guild.cppindex a4c4a26..ee6c164 100644--- a/src/game/Guild.cpp+++ b/src/game/Guild.cpp@@ -352,17 +352,14 @@ bool Guild::FillPlayerData(uint64 guid, MemberSlot* memslot)     }     else     {-        QueryResult *result = CharacterDatabase.PQuery("SELECT name,data,zone,class FROM characters WHERE guid = '%u'", GUID_LOPART(guid));+        QueryResult *result = CharacterDatabase.PQuery("SELECT name,level,zone,class FROM characters WHERE guid = '%u'", GUID_LOPART(guid));         if(!result)             return false;                                   // player doesn't exist          Field *fields = result->Fetch();          plName = fields[0].GetCppString();--        Tokens data = StrSplit(fields[1].GetCppString(), " ");-        plLevel = Player::GetUInt32ValueFromArray(data,UNIT_FIELD_LEVEL);-+        plLevel = fields[1].GetUInt32();         plZone = fields[2].GetUInt32();         plClass = fields[3].GetUInt32();         delete result;diff --git a/src/game/GuildHandler.cpp b/src/game/GuildHandler.cppindex 9b5dba2..649f57b 100644--- a/src/game/GuildHandler.cpp+++ b/src/game/GuildHandler.cpp@@ -976,7 +976,7 @@ void WorldSession::HandleGuildBankDepositMoney( WorldPacket & recv_data )      pGuild->SetBankMoney(pGuild->GetGuildBankMoney()+money);     GetPlayer()->ModifyMoney(-int(money));-    GetPlayer()->SaveDataFieldToDB();                       //contains money+    GetPlayer()->SaveGoldToDB();      CharacterDatabase.CommitTransaction(); @@ -1032,7 +1032,7 @@ void WorldSession::HandleGuildBankWithdrawMoney( WorldPacket & recv_data )     }      GetPlayer()->ModifyMoney(money);-    GetPlayer()->SaveDataFieldToDB();                       // contains money+    GetPlayer()->SaveGoldToDB();      CharacterDatabase.CommitTransaction(); diff --git a/src/game/Level2.cpp b/src/game/Level2.cppindex 6a3b6fa..65d63cc 100644--- a/src/game/Level2.cpp+++ b/src/game/Level2.cpp@@ -2133,21 +2133,17 @@ bool ChatHandler::HandlePInfoCommand(const char* args)         if (HasLowerSecurity(NULL, target_guid))             return false; -        //                                                     0-        QueryResult *result = CharacterDatabase.PQuery("SELECT totaltime FROM characters WHERE guid = '%u'", GUID_LOPART(target_guid));+        //                                                     0          1      2+        QueryResult *result = CharacterDatabase.PQuery("SELECT totaltime, level, money FROM characters WHERE guid = '%u'", GUID_LOPART(target_guid));         if (!result)             return false;          Field *fields = result->Fetch();         total_player_time = fields[0].GetUInt32();+        level = fields[1].GetUInt32();+        money = fields[2].GetUInt32();         delete result; -        Tokens data;-        if (!Player::LoadValuesArrayFromDB(data,target_guid))-            return false;--        money = Player::GetUInt32ValueFromArray(data, PLAYER_FIELD_COINAGE);-        level = Player::GetUInt32ValueFromArray(data, UNIT_FIELD_LEVEL);         accId = objmgr.GetPlayerAccountIdByGUID(target_guid);     } diff --git a/src/game/Level3.cpp b/src/game/Level3.cppindex bebba74..1a3021e 100644--- a/src/game/Level3.cpp+++ b/src/game/Level3.cpp@@ -3931,11 +3931,7 @@ void ChatHandler::HandleCharacterLevel(Player* player, uint64 player_guid, uint3     else     {         // update level and XP at level, all other will be updated at loading-        Tokens values;-        Player::LoadValuesArrayFromDB(values,player_guid);-        Player::SetUInt32ValueInArray(values,UNIT_FIELD_LEVEL,newlevel);-        Player::SetUInt32ValueInArray(values,PLAYER_XP,0);-        Player::SaveValuesArrayInDB(values,player_guid);+        CharacterDatabase.PExecute("UPDATA characters SET level = '%u', xp = 0 WHERE guid = '%u'", newlevel, GUID_LOPART(player_guid));     } } @@ -3960,7 +3956,7 @@ bool ChatHandler::HandleCharacterLevelCommand(const char* args)     if(!extractPlayerTarget(nameStr,&target,&target_guid,&target_name))         return false; -    int32 oldlevel = target ? target->getLevel() : Player::GetUInt32ValueFromDB(UNIT_FIELD_LEVEL,target_guid);+    int32 oldlevel = target ? target->getLevel() : Player::GetLevelFromDB(target_guid);     int32 newlevel = levelStr ? atoi(levelStr) : oldlevel;      if(newlevel < 1)@@ -3999,7 +3995,7 @@ bool ChatHandler::HandleLevelUpCommand(const char* args)     if(!extractPlayerTarget(nameStr,&target,&target_guid,&target_name))         return false; -    int32 oldlevel = target ? target->getLevel() : Player::GetUInt32ValueFromDB(UNIT_FIELD_LEVEL,target_guid);+    int32 oldlevel = target ? target->getLevel() : Player::GetLevelFromDB(target_guid);     int32 addlevel = levelStr ? atoi(levelStr) : 1;     int32 newlevel = oldlevel + addlevel; diff --git a/src/game/Mail.cpp b/src/game/Mail.cppindex 0d90792..2453f19 100644--- a/src/game/Mail.cpp+++ b/src/game/Mail.cpp@@ -557,7 +557,7 @@ void WorldSession::HandleMailTakeMoney(WorldPacket & recv_data )      // save money and mail to prevent cheating     CharacterDatabase.BeginTransaction();-    pl->SaveDataFieldToDB();                                // contains money+    pl->SaveGoldToDB();     pl->_SaveMail();     CharacterDatabase.CommitTransaction(); }diff --git a/src/game/Player.cpp b/src/game/Player.cppindex 41a8701..977dc1c 100644--- a/src/game/Player.cpp+++ b/src/game/Player.cpp@@ -538,9 +538,6 @@ bool Player::Create( uint32 guidlow, const std::string& name, uint8 race, uint8     for (int i = 0; i < PLAYER_SLOTS_COUNT; ++i)         m_items[i] = NULL; -    m_race = race;-    m_class = class_;-     SetMapId(info->mapId);     Relocate(info->positionX,info->positionY,info->positionZ); @@ -572,7 +569,7 @@ bool Player::Create( uint32 guidlow, const std::string& name, uint8 race, uint8             break;     } -    setFactionForRace(m_race);+    setFactionForRace(race);      uint32 RaceClassGender = ( race ) | ( class_ << 8 ) | ( gender << 16 ); @@ -1402,51 +1399,57 @@ void Player::setDeathState(DeathState s)  void Player::BuildEnumData( QueryResult * result, WorldPacket * p_data ) {+    //             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+    //    "characters.at_login, character_pet.entry, character_pet.modelid, character_pet.level, characters.data, character_declinedname.genitive "+     Field *fields = result->Fetch(); -    *p_data << uint64(GetGUID());-    *p_data << m_name;+    uint32 guid = fields[0].GetUInt32();+    *p_data << uint64(MAKE_NEW_GUID(guid, 0, HIGHGUID_PLAYER));+    *p_data << fields[1].GetString();                       // name -    *p_data << uint8(getRace());-    uint8 pClass = getClass();-    *p_data << uint8(pClass);-    *p_data << uint8(getGender());+    *p_data << uint8(fields[2].GetUInt8());                 // race+    uint8 pClass = fields[3].GetUInt8();+    *p_data << uint8(pClass);                               // class+    *p_data << uint8(fields[4].GetUInt8());                 // gender -    uint32 bytes = GetUInt32Value(PLAYER_BYTES);-    *p_data << uint8(bytes);-    *p_data << uint8(bytes >> 8);-    *p_data << uint8(bytes >> 16);-    *p_data << uint8(bytes >> 24);+    uint32 playerBytes = fields[5].GetUInt32();+    *p_data << uint8(playerBytes);                          // skin+    *p_data << uint8(playerBytes >> 8);                     // face+    *p_data << uint8(playerBytes >> 16);                    // hair style+    *p_data << uint8(playerBytes >> 24);                    // hair color -    bytes = GetUInt32Value(PLAYER_BYTES_2);-    *p_data << uint8(bytes);+    uint32 playerBytes2 = fields[6].GetUInt32();+    *p_data << uint8(playerBytes2 & 0xFF);                  // facial hair -    *p_data << uint8(getLevel());                           // player level-    // do not use GetMap! it will spawn a new instance since the bound instances are not loaded-    uint32 zoneId = fields[10].GetUInt32();-    sLog.outDebug("Player::BuildEnumData: map:%u, x:%f, y:%f, z:%f zone:%u", GetMapId(), GetPositionX(), GetPositionY(), GetPositionZ(), zoneId);-    *p_data << uint32(zoneId);-    *p_data << uint32(GetMapId());+    *p_data << uint8(fields[7].GetUInt8());                 // level+    *p_data << uint32(fields[8].GetUInt32());               // zone+    *p_data << uint32(fields[9].GetUInt32());               // map -    *p_data << GetPositionX();-    *p_data << GetPositionY();-    *p_data << GetPositionZ();+    *p_data << fields[10].GetFloat();                       // x+    *p_data << fields[11].GetFloat();                       // y+    *p_data << fields[12].GetFloat();                       // z -    // guild id-    *p_data << uint32(fields[14].GetUInt32());+    *p_data << uint32(fields[13].GetUInt32());              // guild id      uint32 char_flags = 0;-    if(HasFlag(PLAYER_FLAGS, PLAYER_FLAGS_HIDE_HELM))+    uint32 playerFlags = fields[14].GetUInt32();+    uint32 atLoginFlags = fields[15].GetUInt32();+    if(playerFlags & PLAYER_FLAGS_HIDE_HELM)         char_flags |= CHARACTER_FLAG_HIDE_HELM;-    if(HasFlag(PLAYER_FLAGS, PLAYER_FLAGS_HIDE_CLOAK))+    if(playerFlags & PLAYER_FLAGS_HIDE_CLOAK)         char_flags |= CHARACTER_FLAG_HIDE_CLOAK;-    if(HasFlag(PLAYER_FLAGS, PLAYER_FLAGS_GHOST))+    if(playerFlags & PLAYER_FLAGS_GHOST)         char_flags |= CHARACTER_FLAG_GHOST;-    if(HasAtLoginFlag(AT_LOGIN_RENAME))+    if(atLoginFlags & AT_LOGIN_RENAME)         char_flags |= CHARACTER_FLAG_RENAME;     if(sWorld.getConfig(CONFIG_DECLINED_NAMES_USED))     {-        if(!fields[15].GetCppString().empty())+        if(!fields[20].GetCppString().empty())             char_flags |= CHARACTER_FLAG_DECLINED;     }     else@@ -1454,7 +1457,7 @@ void Player::BuildEnumData( QueryResult * result, WorldPacket * p_data )      *p_data << uint32(char_flags);                          // character flags     // character customize (flags?)-    *p_data << uint32(HasAtLoginFlag(AT_LOGIN_CUSTOMIZE) ? 1 : 0);+    *p_data << uint32(atLoginFlags & AT_LOGIN_CUSTOMIZE ? 1 : 0);     *p_data << uint8(1);                                    // unknown      // Pets info@@ -1463,15 +1466,15 @@ void Player::BuildEnumData( QueryResult * result, WorldPacket * p_data )         uint32 petLevel   = 0;         uint32 petFamily  = 0; -        // show pet at selection character in character list  only for non-ghost character-        if (result && isAlive() && (pClass == CLASS_WARLOCK || pClass == CLASS_HUNTER || pClass == CLASS_DEATH_KNIGHT))+        // show pet at selection character in character list only for non-ghost character+        if (result && !(playerFlags & PLAYER_FLAGS_GHOST) && (pClass == CLASS_WARLOCK || pClass == CLASS_HUNTER || pClass == CLASS_DEATH_KNIGHT))         {-            uint32 entry = fields[11].GetUInt32();+            uint32 entry = fields[16].GetUInt32();             CreatureInfo const* cInfo = sCreatureStorage.LookupEntry<CreatureInfo>(entry);             if(cInfo)             {-                petDisplayId = fields[12].GetUInt32();-                petLevel     = fields[13].GetUInt32();+                petDisplayId = fields[17].GetUInt32();+                petLevel     = fields[18].GetUInt32();                 petFamily    = cInfo->family;             }         }@@ -1481,32 +1484,34 @@ void Player::BuildEnumData( QueryResult * result, WorldPacket * p_data )         *p_data << uint32(petFamily);     } +    // TODO: do not access data field here+    Tokens data = StrSplit(fields[19].GetCppString(), " ");+     for (uint8 slot = 0; slot < EQUIPMENT_SLOT_END; slot++)     {         uint32 visualbase = PLAYER_VISIBLE_ITEM_1_ENTRYID + (slot * 2);-        uint32 item_id = GetUInt32Value(visualbase);+        uint32 item_id = GetUInt32ValueFromArray(data, visualbase);         const ItemPrototype * proto = objmgr.GetItemPrototype(item_id);+        if(!proto)+        {+            *p_data << uint32(0);+            *p_data << uint8(0);+            *p_data << uint32(0);                           // enchant?+            continue;+        }+         SpellItemEnchantmentEntry const *enchant = NULL; +        uint32 enchants = GetUInt32ValueFromArray(data, visualbase + 1);         for(uint8 enchantSlot = PERM_ENCHANTMENT_SLOT; enchantSlot <= TEMP_ENCHANTMENT_SLOT; ++enchantSlot)         {-            uint32 enchantId = GetUInt16Value(visualbase + 1, enchantSlot);-            if(enchant = sSpellItemEnchantmentStore.LookupEntry(enchantId))+            if(enchant = sSpellItemEnchantmentStore.LookupEntry(enchantSlot >> enchantSlot*16))                 break;         } -        if (proto != NULL)-        {-            *p_data << uint32(proto->DisplayInfoID);-            *p_data << uint8(proto->InventoryType);-            *p_data << uint32(enchant ? enchant->aura_id : 0);-        }-        else-        {-            *p_data << uint32(0);-            *p_data << uint8(0);-            *p_data << uint32(0);                           // enchant?-        }+        *p_data << uint32(proto->DisplayInfoID);+        *p_data << uint8(proto->InventoryType);+        *p_data << uint32(enchant ? enchant->aura_id : 0);     }     *p_data << uint32(0);                                   // first bag display id     *p_data << uint8(0);                                    // first bag inventory type@@ -6061,6 +6066,19 @@ uint32 Player::GetZoneIdFromDB(uint64 guid)     return zone; } +uint32 Player::GetLevelFromDB(uint64 guid)+{+    QueryResult *result = CharacterDatabase.PQuery( "SELECT level FROM characters WHERE guid='%u'", GUID_LOPART(guid) );+    if (!result)+        return 0;++    Field* fields = result->Fetch();+    uint32 level = fields[0].GetUInt32();+    delete result;++    return level;+}+ void Player::UpdateArea(uint32 newArea) {     // FFA_PVP flags are area and not zone id dependent@@ -13667,8 +13685,8 @@ bool Player::MinimalLoadFromDB( QueryResult *result, uint32 guid )     bool delete_result = true;     if (!result)     {-        //                                          0     1     2     3           4           5           6    7          8          9         10-        result = CharacterDatabase.PQuery("SELECT guid, data, name, position_x, position_y, position_z, map, totaltime, leveltime, at_login, zone FROM characters WHERE guid = '%u'",guid);+        //                                        0     1     2     3           4           5           6    7          8          9         10    11+        result = CharacterDatabase.PQuery("SELECT guid, data, name, position_x, position_y, position_z, map, totaltime, leveltime, at_login, zone, level FROM characters WHERE guid = '%u'",guid);         if (!result)             return false;     }@@ -13870,8 +13888,8 @@ float Player::GetFloatValueFromDB(uint16 index, uint64 guid)  bool Player::LoadFromDB( uint32 guid, SqlQueryHolder *holder ) {-    ////                                                     0     1        2     3     4     5      6           7           8           9    10           11        12         13         14         15          16           17                 18                 19                 20       21       22       23       24         25           26            27        [28]  [29]    30                 31         32                         33            34   35     36    37  38  39  40-    //QueryResult *result = CharacterDatabase.PQuery("SELECT guid, account, data, name, race, class, position_x, position_y, position_z, map, orientation, taximask, cinematic, totaltime, leveltime, rest_bonus, logout_time, is_logout_resting, resettalents_cost, resettalents_time, trans_x, trans_y, trans_z, trans_o, transguid, extra_flags, stable_slots, at_login, zone, online, death_expire_time, taxi_path, dungeon_difficulty, arena_pending_points,bgid,bgteam,bgmap,bgx,bgy,bgz,bgo FROM characters WHERE guid = '%u'", guid);+    ////                                                     0     1        2     3     4     5      6       7      8   9      10           11            12           13          14          15          16   17           18        19         20         21         22          23           24                 25                 26                 27       28       29       30       31         32           33            34        35    36      37                 38         39                  40                   41   42     43    44  45  46  47+    //QueryResult *result = CharacterDatabase.PQuery("SELECT guid, account, data, name, race, class, gender, level, xp, money, playerBytes, playerBytes2, playerFlags, position_x, position_y, position_z, map, orientation, taximask, cinematic, totaltime, leveltime, rest_bonus, logout_time, is_logout_resting, resettalents_cost, resettalents_time, trans_x, trans_y, trans_z, trans_o, transguid, extra_flags, stable_slots, at_login, zone, online, death_expire_time, taxi_path, dungeon_difficulty, arena_pending_points,bgid,bgteam,bgmap,bgx,bgy,bgz,bgo FROM characters WHERE guid = '%u'", guid);     QueryResult *result = holder->GetResult(PLAYER_LOGIN_QUERY_LOADFROM);      if(!result)@@ -13915,6 +13933,19 @@ bool Player::LoadFromDB( uint32 guid, SqlQueryHolder *holder )     // overwrite possible wrong/corrupted guid     SetUInt64Value(OBJECT_FIELD_GUID, MAKE_NEW_GUID(guid, 0, HIGHGUID_PLAYER)); +    // overwrite some data fields+    uint32 bytes0 = GetUInt32Value(UNIT_FIELD_BYTES_0) & 0xFF000000;+    bytes0 |= fields[4].GetUInt8();+    bytes0 |= fields[5].GetUInt8() << 8;+    bytes0 |= fields[6].GetUInt8() << 16;+    SetUInt32Value(UNIT_FIELD_LEVEL, fields[7].GetUInt8());+    SetUInt32Value(PLAYER_XP, fields[8].GetUInt32());+    SetUInt32Value(PLAYER_FIELD_COINAGE, fields[9].GetUInt32());+    SetUInt32Value(PLAYER_BYTES, fields[10].GetUInt32());+    SetUInt32Value(PLAYER_BYTES_2, fields[11].GetUInt32());+    SetUInt32Value(PLAYER_BYTES_3, (GetUInt32Value(PLAYER_BYTES_3) & ~1) | fields[6].GetUInt8());+    SetUInt32Value(PLAYER_FLAGS, fields[12].GetUInt32());+     // cleanup inventory related item value fields (its will be filled correctly in _LoadInventory)     for(uint8 slot = EQUIPMENT_SLOT_START; slot < EQUIPMENT_SLOT_END; ++slot)     {@@ -13935,14 +13966,11 @@ bool Player::LoadFromDB( uint32 guid, SqlQueryHolder *holder )     sLog.outDebug("Load Basic value of player %s is: ", m_name.c_str());     outDebugValues(); -    m_race = fields[4].GetUInt8();-    //Need to call it to initialize m_team (m_team can be calculated from m_race)+    //Need to call it to initialize m_team (m_team can be calculated from race)     //Other way is to saves m_team into characters table.-    setFactionForRace(m_race);+    setFactionForRace(getRace());     SetCharm(NULL); -    m_class = fields[5].GetUInt8();-     // load home bind and check in same time class/race pair, it used later for restore broken positions     if(!_LoadHomeBind(holder->GetResult(PLAYER_LOGIN_QUERY_LOADHOMEBIND)))     {@@ -13953,16 +13981,16 @@ bool Player::LoadFromDB( uint32 guid, SqlQueryHolder *holder )     InitPrimaryProfessions();                               // to max set before any spell loaded      // init saved position, and fix it later if problematic-    uint32 transGUID = fields[24].GetUInt32();-    Relocate(fields[6].GetFloat(),fields[7].GetFloat(),fields[8].GetFloat(),fields[10].GetFloat());-    SetMapId(fields[9].GetUInt32());-    SetDifficulty(fields[32].GetUInt32());                  // may be changed in _LoadGroup+    uint32 transGUID = fields[31].GetUInt32();+    Relocate(fields[13].GetFloat(),fields[14].GetFloat(),fields[15].GetFloat(),fields[17].GetFloat());+    SetMapId(fields[16].GetUInt32());+    SetDifficulty(fields[39].GetUInt32());                  // may be changed in _LoadGroup      _LoadGroup(holder->GetResult(PLAYER_LOGIN_QUERY_LOADGROUP));      _LoadArenaTeamInfo(holder->GetResult(PLAYER_LOGIN_QUERY_LOADARENAINFO)); -    uint32 arena_currency = GetUInt32Value(PLAYER_FIELD_ARENA_CURRENCY) + fields[33].GetUInt32();+    uint32 arena_currency = GetUInt32Value(PLAYER_FIELD_ARENA_CURRENCY) + fields[40].GetUInt32();     if (arena_currency > sWorld.getConfig(CONFIG_MAX_ARENA_POINTS))         arena_currency = sWorld.getConfig(CONFIG_MAX_ARENA_POINTS); @@ -13999,12 +14027,12 @@ bool Player::LoadFromDB( uint32 guid, SqlQueryHolder *holder )         m_movementInfo.t_o = 0.0f;     } -    uint32 bgid = fields[34].GetUInt32();-    uint32 bgteam = fields[35].GetUInt32();+    uint32 bgid = fields[41].GetUInt32();+    uint32 bgteam = fields[42].GetUInt32();      if(bgid)                                                //saved in BattleGround     {-        SetBattleGroundEntryPoint(fields[36].GetUInt32(),fields[37].GetFloat(),fields[38].GetFloat(),fields[39].GetFloat(),fields[40].GetFloat());+        SetBattleGroundEntryPoint(fields[43].GetUInt32(),fields[44].GetFloat(),fields[45].GetFloat(),fields[46].GetFloat(),fields[47].GetFloat());          // check entry point and fix to homebind if need         MapEntry const* mapEntry = sMapStore.LookupEntry(m_bgEntryPoint.mapid);@@ -14043,8 +14071,8 @@ bool Player::LoadFromDB( uint32 guid, SqlQueryHolder *holder )         if(!mapEntry || mapEntry->IsBattleGroundOrArena())         {             // return to BG master-            SetMapId(fields[36].GetUInt32());-            Relocate(fields[37].GetFloat(),fields[38].GetFloat(),fields[39].GetFloat(),fields[40].GetFloat());+            SetMapId(fields[43].GetUInt32());+            Relocate(fields[44].GetFloat(),fields[45].GetFloat(),fields[46].GetFloat(),fields[47].GetFloat());              // check entry point and fix to homebind if need             mapEntry = sMapStore.LookupEntry(GetMapId());@@ -14055,10 +14083,10 @@ bool Player::LoadFromDB( uint32 guid, SqlQueryHolder *holder )      if (transGUID != 0)     {-        m_movementInfo.t_x = fields[20].GetFloat();-        m_movementInfo.t_y = fields[21].GetFloat();-        m_movementInfo.t_z = fields[22].GetFloat();-        m_movementInfo.t_o = fields[23].GetFloat();+        m_movementInfo.t_x = fields[27].GetFloat();+        m_movementInfo.t_y = fields[28].GetFloat();+        m_movementInfo.t_z = fields[29].GetFloat();+        m_movementInfo.t_o = fields[30].GetFloat();          if( !MaNGOS::IsValidMapCoord(             GetPositionX()+m_movementInfo.t_x,GetPositionY()+m_movementInfo.t_y,@@ -14149,7 +14177,7 @@ bool Player::LoadFromDB( uint32 guid, SqlQueryHolder *holder )     SaveRecallPosition();      time_t now = time(NULL);-    time_t logoutTime = time_t(fields[16].GetUInt64());+    time_t logoutTime = time_t(fields[23].GetUInt64());      // since last logout (in seconds)     uint64 time_diff = uint64(now - logoutTime);@@ -14164,27 +14192,27 @@ bool Player::LoadFromDB( uint32 guid, SqlQueryHolder *holder )     uint16 newDrunkenValue = uint16(soberFactor*(GetUInt32Value(PLAYER_BYTES_3) & 0xFFFE));     SetDrunkValue(newDrunkenValue); -    m_rest_bonus = fields[15].GetFloat();+    m_rest_bonus = fields[22].GetFloat();     //speed collect rest bonus in offline, in logout, far from tavern, city (section/in hour)     float bubble0 = 0.031;     //speed collect rest bonus in offline, in logout, in tavern, city (section/in hour)     float bubble1 = 0.125; -    if((int32)fields[16].GetUInt32() > 0)+    if((int32)fields[23].GetUInt32() > 0)     {-        float bubble = fields[17].GetUInt32() > 0+        float bubble = fields[24].GetUInt32() > 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);     } -    m_cinematic = fields[12].GetUInt32();-    m_Played_time[0]= fields[13].GetUInt32();-    m_Played_time[1]= fields[14].GetUInt32();+    m_cinematic = fields[19].GetUInt32();+    m_Played_time[0]= fields[20].GetUInt32();+    m_Played_time[1]= fields[21].GetUInt32(); -    m_resetTalentsCost = fields[18].GetUInt32();-    m_resetTalentsTime = time_t(fields[19].GetUInt64());+    m_resetTalentsCost = fields[25].GetUInt32();+    m_resetTalentsTime = time_t(fields[26].GetUInt64());      // reserve some flags     uint32 old_safe_flags = GetUInt32Value(PLAYER_FLAGS) & ( PLAYER_FLAGS_HIDE_CLOAK | PLAYER_FLAGS_HIDE_HELM );@@ -14192,29 +14220,29 @@ bool Player::LoadFromDB( uint32 guid, SqlQueryHolder *holder )     if( HasFlag(PLAYER_FLAGS, PLAYER_FLAGS_GM) )         SetUInt32Value(PLAYER_FLAGS, 0 | old_safe_flags); -    m_taxi.LoadTaxiMask( fields[11].GetString() );          // must be before InitTaxiNodesForLevel+    m_taxi.LoadTaxiMask( fields[18].GetString() );          // must be before InitTaxiNodesForLevel      uint32 extraflags = fields[25].GetUInt32(); -    m_stableSlots = fields[26].GetUInt32();+    m_stableSlots = fields[33].GetUInt32();     if(m_stableSlots > MAX_PET_STABLES)     {         sLog.outError("Player can have not more %u stable slots, but have in DB %u",MAX_PET_STABLES,uint32(m_stableSlots));         m_stableSlots = MAX_PET_STABLES;     } -    m_atLoginFlags = fields[27].GetUInt32();+    m_atLoginFlags = fields[34].GetUInt32();      // Honor system     // Update Honor kills data     m_lastHonorUpdateTime = logoutTime;     UpdateHonorFields(); -    m_deathExpireTime = (time_t)fields[30].GetUInt64();+    m_deathExpireTime = (time_t)fields[37].GetUInt64();     if(m_deathExpireTime > now+MAX_DEATH_COUNT*DEATH_EXPIRE_STEP)         m_deathExpireTime = now+MAX_DEATH_COUNT*DEATH_EXPIRE_STEP-1; -    std::string taxi_nodes = fields[31].GetCppString();+    std::string taxi_nodes = fields[38].GetCppString();      delete result; @@ -14551,7 +14579,7 @@ void Player::_LoadAuras(QueryResult *result, uint32 timediff)         delete result;     } -    if(m_class == CLASS_WARRIOR)+    if(getClass() == CLASS_WARRIOR)         CastSpell(this,SPELL_ID_PASSIVE_BATTLE_STANCE,true); } @@ -15373,7 +15401,7 @@ void Player::SaveToDB()     CharacterDatabase.escape_string(sql_name);      std::ostringstream ss;-    ss << "INSERT INTO characters (guid,account,name,race,class,"+    ss << "INSERT INTO characters (guid,account,name,race,class,gender,level,xp,money,playerBytes,playerBytes2,playerFlags,"         "map, dungeon_difficulty, position_x, position_y, position_z, orientation, data, "         "taximask, online, cinematic, "         "totaltime, leveltime, rest_bonus, logout_time, is_logout_resting, resettalents_cost, resettalents_time, "@@ -15382,8 +15410,15 @@ void Player::SaveToDB()         << GetGUIDLow() << ", "         << GetSession()->GetAccountId() << ", '"         << sql_name << "', "-        << m_race << ", "-        << m_class << ", ";+        << (uint32)getRace() << ", "+        << (uint32)getClass() << ", "+        << (uint32)getGender() << ", "+        << getLevel() << ", "+        << GetUInt32Value(PLAYER_XP) << ", "+        << GetMoney() << ", "+        << GetUInt32Value(PLAYER_BYTES) << ", "+        << GetUInt32Value(PLAYER_BYTES_2) << ", "+        << GetUInt32Value(PLAYER_FLAGS) << ", ";      if(!IsBeingTeleported())     {@@ -15514,8 +15549,12 @@ void Player::SaveToDB() void Player::SaveInventoryAndGoldToDB() {     _SaveInventory();-    //money is in data field-    SaveDataFieldToDB();+    SaveGoldToDB();+}++void Player::SaveGoldToDB()+{+    CharacterDatabase.PExecute("UPDATE money = '%u' WHERE guid = '%u'", GetMoney(), GetGUIDLow()); }  void Player::_SaveActions()@@ -15939,38 +15978,30 @@ void Player::SetFloatValueInDB(uint16 index, float value, uint64 guid)  void Player::Customize(uint64 guid, uint8 gender, uint8 skin, uint8 face, uint8 hairStyle, uint8 hairColor, uint8 facialHair) {-    Tokens tokens;-    if(!LoadValuesArrayFromDB(tokens, guid))+    //                                                     0     1     2      3            4+    QueryResult* result = CharacterDatabase.PQuery("SELECT data, race, class, playerBytes, playerBytes2 FROM characters WHERE guid = '%u'", GUID_LOPART(guid));+    if(!result)         return; -    uint32 unit_bytes0 = GetUInt32ValueFromArray(tokens, UNIT_FIELD_BYTES_0);-    uint8 race = unit_bytes0 & 0xFF;-    uint8 class_ = (unit_bytes0 >> 8) & 0xFF;+    Field* fields = result->Fetch(); -    PlayerInfo const* info = objmgr.GetPlayerInfo(race, class_);+    Tokens tokens = StrSplit(fields[0].GetString(), " ");++    PlayerInfo const* info = objmgr.GetPlayerInfo(fields[1].GetUInt8(), fields[2].GetUInt8());     if(!info)         return; -    unit_bytes0 &= ~(0xFF << 16);-    unit_bytes0 |= (gender << 16);-    SetUInt32ValueInArray(tokens, UNIT_FIELD_BYTES_0, unit_bytes0);-     SetUInt32ValueInArray(tokens, UNIT_FIELD_DISPLAYID, gender ? info->displayId_f : info->displayId_m);     SetUInt32ValueInArray(tokens, UNIT_FIELD_NATIVEDISPLAYID, gender ? info->displayId_f : info->displayId_m); -    SetUInt32ValueInArray(tokens, PLAYER_BYTES, (skin | (face << 8) | (hairStyle << 16) | (hairColor << 24)));--    uint32 player_bytes2 = GetUInt32ValueFromArray(tokens, PLAYER_BYTES_2);+    uint32 player_bytes2 = fields[4].GetUInt32();     player_bytes2 &= ~0xFF;     player_bytes2 |= facialHair;-    SetUInt32ValueInArray(tokens, PLAYER_BYTES_2, player_bytes2);--    uint32 player_bytes3 = GetUInt32ValueFromArray(tokens, PLAYER_BYTES_3);-    player_bytes3 &= ~0xFF;-    player_bytes3 |= gender;-    SetUInt32ValueInArray(tokens, PLAYER_BYTES_3, player_bytes3);      SaveValuesArrayInDB(tokens, guid);+    CharacterDatabase.PExecute("UPDATE characters SET gender = '%u', playerBytes = '%u', playerBytes2 = '%u' WHERE guid = '%u'", gender, skin | (face << 8) | (hairStyle << 16) | (hairColor << 24), player_bytes2, GUID_LOPART(guid));++    delete result; }  void Player::SendAttackSwingDeadTarget()diff --git a/src/game/Player.h b/src/game/Player.hindex 02d8f30..d70fd78 100644--- a/src/game/Player.h+++ b/src/game/Player.h@@ -902,7 +902,7 @@ class MANGOS_DLL_SPEC Player : public Unit          void Update( uint32 time ); -        void BuildEnumData( QueryResult * result,  WorldPacket * p_data );+        static void BuildEnumData( QueryResult * result,  WorldPacket * p_data );          void SetInWater(bool apply); @@ -1261,6 +1261,7 @@ class MANGOS_DLL_SPEC Player : public Unit         static uint32 GetUInt32ValueFromDB(uint16 index, uint64 guid);         static float  GetFloatValueFromDB(uint16 index, uint64 guid);         static uint32 GetZoneIdFromDB(uint64 guid);+        static uint32 GetLevelFromDB(uint64 guid);         static bool   LoadPositionFromDB(uint32& mapid, float& x,float& y,float& z,float& o, bool& in_flight, uint64 guid);          /*********************************************************/@@ -1269,6 +1270,7 @@ class MANGOS_DLL_SPEC Player : public Unit          void SaveToDB();         void SaveInventoryAndGoldToDB();                    // fast save function for item/money cheating preventing+        void SaveGoldToDB();         void SaveDataFieldToDB();         static bool SaveValuesArrayInDB(Tokens const& data,uint64 guid);         static void SetUInt32ValueInArray(Tokens& data,uint16 index, uint32 value);@@ -2187,8 +2189,6 @@ class MANGOS_DLL_SPEC Player : public Unit         void outDebugValues() const;         uint64 m_lootGuid; -        uint32 m_race;-        uint32 m_class;         uint32 m_team;         uint32 m_nextSave;         time_t m_speakTime;