diff options
Diffstat (limited to 'src/game/Player.cpp')
-rw-r--r-- | src/game/Player.cpp | 279 |
1 files changed, 161 insertions, 118 deletions
diff --git a/src/game/Player.cpp b/src/game/Player.cpp index 55946030206..732acbd316e 100644 --- a/src/game/Player.cpp +++ b/src/game/Player.cpp @@ -539,9 +539,6 @@ bool Player::Create( uint32 guidlow, const std::string& name, uint8 race, uint8 for (uint8 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); @@ -573,7 +570,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 ); @@ -1452,53 +1449,67 @@ void Player::setDeathState(DeathState s) } } -void Player::BuildEnumData( QueryResult * result, WorldPacket * p_data ) +bool 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(); + uint8 pRace = fields[2].GetUInt8(); + uint8 pClass = fields[3].GetUInt8(); - *p_data << uint8(getRace()); - uint8 pClass = getClass(); - *p_data << uint8(pClass); - *p_data << uint8(getGender()); + PlayerInfo const *info = objmgr.GetPlayerInfo(pRace, pClass); + if(!info) + { + sLog.outError("Player %u have incorrect race/class pair. Don't build enum.", guid); + return false; + } - uint32 bytes = GetUInt32Value(PLAYER_BYTES); - *p_data << uint8(bytes); - *p_data << uint8(bytes >> 8); - *p_data << uint8(bytes >> 16); - *p_data << uint8(bytes >> 24); + *p_data << uint64(MAKE_NEW_GUID(guid, 0, HIGHGUID_PLAYER)); + *p_data << fields[1].GetString(); // name + *p_data << uint8(pRace); // race + *p_data << uint8(pClass); // class + *p_data << uint8(fields[4].GetUInt8()); // gender - bytes = GetUInt32Value(PLAYER_BYTES_2); - *p_data << uint8(bytes); + 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 - *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()); + uint32 playerBytes2 = fields[6].GetUInt32(); + *p_data << uint8(playerBytes2 & 0xFF); // facial hair - *p_data << GetPositionX(); - *p_data << GetPositionY(); - *p_data << GetPositionZ(); + *p_data << uint8(fields[7].GetUInt8()); // level + *p_data << uint32(fields[8].GetUInt32()); // zone + *p_data << uint32(fields[9].GetUInt32()); // map - // guild id - *p_data << uint32(fields[14].GetUInt32()); + *p_data << fields[10].GetFloat(); // x + *p_data << fields[11].GetFloat(); // y + *p_data << fields[12].GetFloat(); // z + + *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 @@ -1506,7 +1517,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 @@ -1515,15 +1526,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; } } @@ -1533,36 +1544,40 @@ 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); + 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 *p_data << uint32(0); // enchant? + + return true; } bool Player::ToggleAFK() @@ -6243,6 +6258,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 @@ -14073,8 +14101,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; } @@ -14307,8 +14335,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) @@ -14352,6 +14380,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) { @@ -14372,12 +14413,9 @@ 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); - - m_class = fields[5].GetUInt8(); + setFactionForRace(getRace()); // 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))) @@ -14389,17 +14427,18 @@ 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()); - SetInstanceId(fields[41].GetFloat()); - 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 + + SetInstanceId(fields[47].GetFloat()); _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); @@ -14436,12 +14475,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); @@ -14480,8 +14519,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()); @@ -14492,10 +14531,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( !Trinity::IsValidMapCoord( GetPositionX()+m_movementInfo.t_x,GetPositionY()+m_movementInfo.t_y, @@ -14627,7 +14666,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); @@ -14642,27 +14681,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 ); @@ -14670,29 +14709,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; @@ -15017,7 +15056,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); } @@ -15932,7 +15971,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, instance_id, 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, " @@ -15941,8 +15980,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()) { @@ -16078,8 +16124,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() @@ -16483,38 +16533,31 @@ 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); - + // TODO: do not access data field here 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() |