diff --git a/sql/characters.sql b/sql/characters.sql index 69800647075..b46e2d1ffaf 100644 --- a/sql/characters.sql +++ b/sql/characters.sql @@ -193,7 +193,6 @@ DROP TABLE IF EXISTS `characters`; CREATE TABLE `characters` ( `guid` int(11) unsigned NOT NULL default '0' COMMENT 'Global Unique Identifier', `account` int(11) unsigned NOT NULL default '0' COMMENT 'Account Identifier', - `data` longtext, `name` varchar(12) NOT NULL default '', `race` tinyint(3) unsigned NOT NULL default '0', `class` tinyint(3) unsigned NOT NULL default '0', @@ -252,6 +251,9 @@ CREATE TABLE `characters` ( `power7` int(10) UNSIGNED NOT NULL default '0', `specCount` tinyint(3) UNSIGNED NOT NULL default '1', `activeSpec` tinyint(3) UNSIGNED NOT NULL default '0', + `exploredZones` longtext, + `equipmentCache` longtext, + `ammoId` int(10) UNSIGNED NOT NULL default '0', PRIMARY KEY (`guid`), KEY `idx_account` (`account`), KEY `idx_online` (`online`), diff --git a/sql/updates/9999_01_characters_characters.sql b/sql/updates/9999_01_characters_characters.sql new file mode 100644 index 00000000000..a2529c46166 --- /dev/null +++ b/sql/updates/9999_01_characters_characters.sql @@ -0,0 +1,27 @@ +ALTER TABLE characters + ADD COLUMN `exploredZones` longtext AFTER activeSpec, + ADD COLUMN `equipmentCache` longtext AFTER exploredZones, + ADD COLUMN `ammoId` int(10) UNSIGNED NOT NULL default '0' AFTER equipmentCache; + +UPDATE characters SET +exploredZones = SUBSTRING(data, +length(SUBSTRING_INDEX(data, ' ', 1041))+2, +length(SUBSTRING_INDEX(data, ' ', 1168+1))- length(SUBSTRING_INDEX(data, ' ', 1041)) - 1), +equipmentCache = SUBSTRING(data, +length(SUBSTRING_INDEX(data, ' ', 283))+2, +length(SUBSTRING_INDEX(data, ' ', 320+1))- length(SUBSTRING_INDEX(data, ' ', 283)) - 1), +ammoId = SUBSTRING(data, +length(SUBSTRING_INDEX(data, ' ', 1198))+2, +length(SUBSTRING_INDEX(data, ' ', 1198+1))- length(SUBSTRING_INDEX(data, ' ', 1198)) - 1); + +CREATE TABLE `data_backup` ( + `guid` int(11) unsigned NOT NULL default '0' COMMENT 'Global Unique Identifier', + `data` longtext, + PRIMARY KEY (`guid`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + +INSERT INTO data_backup (guid, data) (SELECT guid, data FROM characters); + + +ALTER TABLE characters + DROP COLUMN data; diff --git a/src/game/CharacterHandler.cpp b/src/game/CharacterHandler.cpp index 822e1ee21ab..1854556c791 100644 --- a/src/game/CharacterHandler.cpp +++ b/src/game/CharacterHandler.cpp @@ -68,11 +68,11 @@ 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, gender, level, xp, money, playerBytes, playerBytes2, playerFlags," + res &= SetPQuery(PLAYER_LOGIN_QUERY_LOADFROM, "SELECT guid, account, 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," "arenaPoints, totalHonorPoints, todayHonorPoints, yesterdayHonorPoints, totalKills, todayKills, yesterdayKills, chosenTitle, knownCurrencies, watchedFaction, drunk," - "health, power1, power2, power3, power4, power5, power6, power7, specCount, activeSpec FROM characters WHERE guid = '%u'", GUID_LOPART(m_guid)); + "health, power1, power2, power3, power4, power5, power6, power7, specCount, activeSpec, exploredZones, equipmentCache, ammoId FROM characters WHERE guid = '%u'", GUID_LOPART(m_guid)); res &= SetPQuery(PLAYER_LOGIN_QUERY_LOADGROUP, "SELECT groupId 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)); @@ -145,7 +145,7 @@ void WorldSession::HandleCharEnum(QueryResult * result) do { uint32 guidlow = (*result)[0].GetUInt32(); - sLog.outDetail("Loading char guid %u from account %u.", guidlow, GetAccountId()); + sLog.outDetail("Build enum data for char guid %u from account %u.", guidlow, GetAccountId()); if(Player::BuildEnumData(result, &data)) ++num; } @@ -170,7 +170,7 @@ void WorldSession::HandleCharEnumOpcode( WorldPacket & /*recv_data*/ ) // 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 " + "characters.at_login, character_pet.entry, character_pet.modelid, character_pet.level, characters.equipmentCache " "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" @@ -180,8 +180,8 @@ void WorldSession::HandleCharEnumOpcode( WorldPacket & /*recv_data*/ ) "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 " + // 15 16 17 18 19 20 + "characters.at_login, character_pet.entry, character_pet.modelid, character_pet.level, characters.equipmentCache, 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 " diff --git a/src/game/Player.cpp b/src/game/Player.cpp index 4f6084618c8..d77831f9a81 100644 --- a/src/game/Player.cpp +++ b/src/game/Player.cpp @@ -1439,8 +1439,8 @@ bool Player::BuildEnumData( QueryResult * result, WorldPacket * p_data ) // "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 " + // 15 16 17 18 19 20 + // "characters.at_login, character_pet.entry, character_pet.modelid, character_pet.level, characters.equipmentCache, character_declinedname.genitive " Field *fields = result->Fetch(); @@ -1529,12 +1529,11 @@ bool Player::BuildEnumData( QueryResult * result, WorldPacket * p_data ) *p_data << uint32(petFamily); } - // TODO: do not access data field here - Tokens data = StrSplit(fields[19].GetCppString(), " "); + 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 visualbase = slot * 2; uint32 item_id = GetUInt32ValueFromArray(data, visualbase); const ItemPrototype * proto = ObjectMgr::GetItemPrototype(item_id); if(!proto) @@ -14635,21 +14634,6 @@ bool Player::LoadPositionFromDB(uint32& mapid, float& x,float& y,float& z,float& return true; } -bool Player::LoadValuesArrayFromDB(Tokens& data, uint64 guid) -{ - QueryResult *result = CharacterDatabase.PQuery("SELECT data FROM characters WHERE guid='%u'",GUID_LOPART(guid)); - if( !result ) - return false; - - Field *fields = result->Fetch(); - - data = StrSplit(fields[0].GetCppString(), " "); - - delete result; - - return true; -} - uint32 Player::GetUInt32ValueFromArray(Tokens const& data, uint16 index) { if(index >= data.size()) @@ -14667,36 +14651,36 @@ float Player::GetFloatValueFromArray(Tokens const& data, uint16 index) return result; } -uint32 Player::GetUInt32ValueFromDB(uint16 index, uint64 guid) +void Player::_LoadExploredZones(const char* data) { - Tokens data; - if(!LoadValuesArrayFromDB(data,guid)) - return 0; - - return GetUInt32ValueFromArray(data,index); -} + if(!data) + return; + + Tokens tokens = StrSplit(data, " "); -float Player::GetFloatValueFromDB(uint16 index, uint64 guid) -{ - float result; - uint32 temp = Player::GetUInt32ValueFromDB(index, guid); - memcpy(&result, &temp, sizeof(result)); + if(tokens.size() != 128) + return; - return result; + Tokens::iterator iter; + int index; + for (iter = tokens.begin(), index = 0; index < 128; ++iter, ++index) + { + m_uint32Values[PLAYER_EXPLORED_ZONES_1 + index] = atol((*iter).c_str()); + } } bool Player::LoadFromDB( uint32 guid, SqlQueryHolder *holder ) { - // 0 1 2 3 4 5 6 7 8 9 10 11 12 - //SELECT guid, account, data, name, race, class, gender, level, xp, money, playerBytes, playerBytes2, playerFlags," - // 13 14 15 16 17 18 19 20 21 22 23 24 25 + // 0 1 2 3 4 5 6 7 8 9 10 11 + //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 //"position_x, position_y, position_z, map, orientation, taximask, cinematic, totaltime, leveltime, rest_bonus, logout_time, is_logout_resting, resettalents_cost," - // 26 27 28 29 30 31 32 33 34 35 36 37 38 39 + // 25 26 27 28 29 30 31 32 33 34 35 36 37 38 //"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," - // 40 41 42 43 44 45 46 47 48 49 50 + // 39 40 41 42 43 44 45 46 47 48 49 //"arenaPoints, totalHonorPoints, todayHonorPoints, yesterdayHonorPoints, totalKills, todayKills, yesterdayKills, chosenTitle, knownCurrencies, watchedFaction, drunk," - // 51 52 53 54 55 56 57 58 59 60 - //"health, power1, power2, power3, power4, power5, power6, power7, specCount, activeSpec FROM characters WHERE guid = '%u'", GUID_LOPART(m_guid)); + // 50 51 52 53 54 55 56 57 58 59 60 61 62 + //"health, power1, power2, power3, power4, power5, power6, power7, specCount, activeSpec, exploredZones, equipmentCache, ammoId FROM characters WHERE guid = '%u'", GUID_LOPART(m_guid)); QueryResult *result = holder->GetResult(PLAYER_LOGIN_QUERY_LOADFROM); if(!result) @@ -14720,7 +14704,7 @@ bool Player::LoadFromDB( uint32 guid, SqlQueryHolder *holder ) Object::_Create( guid, 0, HIGHGUID_PLAYER ); - m_name = fields[3].GetCppString(); + m_name = fields[2].GetCppString(); // check name limitations if (ObjectMgr::CheckPlayerName(m_name) != CHAR_NAME_SUCCESS || @@ -14731,38 +14715,38 @@ bool Player::LoadFromDB( uint32 guid, SqlQueryHolder *holder ) return false; } - if(!LoadValues( fields[2].GetString())) - { - sLog.outError("Player #%d have broken data in `data` field. Can't be loaded.", GUID_LOPART(guid)); - delete result; - return false; - } - // 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(); // race - bytes0 |= fields[5].GetUInt8() << 8; // class - bytes0 |= fields[6].GetUInt8() << 16; // gender + uint32 bytes0 = 0; + bytes0 |= fields[3].GetUInt8(); // race + bytes0 |= fields[4].GetUInt8() << 8; // class + bytes0 |= fields[5].GetUInt8() << 16; // gender SetUInt32Value(UNIT_FIELD_BYTES_0, bytes0); - SetUInt32Value(UNIT_FIELD_LEVEL, fields[7].GetUInt8()); - SetUInt32Value(PLAYER_XP, fields[8].GetUInt32()); + SetUInt32Value(UNIT_FIELD_LEVEL, fields[6].GetUInt8()); + SetUInt32Value(PLAYER_XP, fields[7].GetUInt32()); + + _LoadExploredZones(fields[60].GetString()); + SetFloatValue(UNIT_FIELD_BOUNDINGRADIUS, DEFAULT_WORLD_OBJECT_SIZE); + SetFloatValue(UNIT_FIELD_COMBATREACH, 1.5f); + SetFloatValue(UNIT_FIELD_HOVERHEIGHT, 1.0f); - uint32 money = fields[9].GetUInt32(); + uint32 money = fields[8].GetUInt32(); if(money > MAX_MONEY_AMOUNT) money = MAX_MONEY_AMOUNT; SetMoney(money); - SetUInt32Value(PLAYER_BYTES, fields[10].GetUInt32()); - SetUInt32Value(PLAYER_BYTES_2, fields[11].GetUInt32()); - SetUInt32Value(PLAYER_BYTES_3, (fields[50].GetUInt16() & 0xFFFE) | fields[6].GetUInt8()); - SetUInt32Value(PLAYER_FLAGS, fields[12].GetUInt32()); - SetInt32Value(PLAYER_FIELD_WATCHED_FACTION_INDEX, fields[49].GetInt32()); + SetUInt32Value(PLAYER_BYTES, fields[9].GetUInt32()); + SetUInt32Value(PLAYER_BYTES_2, fields[10].GetUInt32()); + SetUInt32Value(PLAYER_BYTES_3, (fields[49].GetUInt16() & 0xFFFE) | fields[5].GetUInt8()); + SetUInt32Value(PLAYER_FLAGS, fields[11].GetUInt32()); + SetInt32Value(PLAYER_FIELD_WATCHED_FACTION_INDEX, fields[48].GetInt32()); + + SetUInt64Value(PLAYER_FIELD_KNOWN_CURRENCIES, fields[47].GetUInt64()); - SetUInt64Value(PLAYER_FIELD_KNOWN_CURRENCIES, fields[48].GetUInt64()); + SetUInt32Value(PLAYER_AMMO_ID, fields[62].GetUInt32()); InitDisplayIds(); @@ -14798,11 +14782,11 @@ 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[31].GetUInt32(); - Relocate(fields[13].GetFloat(),fields[14].GetFloat(),fields[15].GetFloat(),fields[17].GetFloat()); - SetLocationMapId(fields[16].GetUInt32()); + uint32 transGUID = fields[30].GetUInt32(); + Relocate(fields[12].GetFloat(),fields[13].GetFloat(),fields[14].GetFloat(),fields[16].GetFloat()); + SetLocationMapId(fields[15].GetUInt32()); - uint32 difficulty = fields[39].GetUInt32(); + uint32 difficulty = fields[38].GetUInt32(); if(difficulty >= MAX_DUNGEON_DIFFICULTY) difficulty = DUNGEON_DIFFICULTY_NORMAL; SetDungeonDifficulty(Difficulty(difficulty)); // may be changed in _LoadGroup @@ -14811,7 +14795,7 @@ bool Player::LoadFromDB( uint32 guid, SqlQueryHolder *holder ) _LoadArenaTeamInfo(holder->GetResult(PLAYER_LOGIN_QUERY_LOADARENAINFO)); - uint32 arena_currency = fields[40].GetUInt32(); + uint32 arena_currency = fields[39].GetUInt32(); if (arena_currency > sWorld.getConfig(CONFIG_UINT32_MAX_ARENA_POINTS)) arena_currency = sWorld.getConfig(CONFIG_UINT32_MAX_ARENA_POINTS); @@ -14833,12 +14817,12 @@ bool Player::LoadFromDB( uint32 guid, SqlQueryHolder *holder ) SetArenaTeamInfoField(arena_slot, ArenaTeamInfoType(j), 0); } - SetUInt32Value(PLAYER_FIELD_HONOR_CURRENCY, fields[41].GetUInt32()); - SetUInt32Value(PLAYER_FIELD_TODAY_CONTRIBUTION, fields[42].GetUInt32()); - SetUInt32Value(PLAYER_FIELD_YESTERDAY_CONTRIBUTION, fields[43].GetUInt32()); - SetUInt32Value(PLAYER_FIELD_LIFETIME_HONORBALE_KILLS, fields[44].GetUInt32()); - SetUInt16Value(PLAYER_FIELD_KILLS, 0, fields[45].GetUInt16()); - SetUInt16Value(PLAYER_FIELD_KILLS, 1, fields[46].GetUInt16()); + SetUInt32Value(PLAYER_FIELD_HONOR_CURRENCY, fields[40].GetUInt32()); + SetUInt32Value(PLAYER_FIELD_TODAY_CONTRIBUTION, fields[41].GetUInt32()); + SetUInt32Value(PLAYER_FIELD_YESTERDAY_CONTRIBUTION, fields[42].GetUInt32()); + SetUInt32Value(PLAYER_FIELD_LIFETIME_HONORBALE_KILLS, fields[43].GetUInt32()); + SetUInt16Value(PLAYER_FIELD_KILLS, 0, fields[44].GetUInt16()); + SetUInt16Value(PLAYER_FIELD_KILLS, 1, fields[45].GetUInt16()); _LoadBoundInstances(holder->GetResult(PLAYER_LOGIN_QUERY_LOADBOUNDINSTANCES)); @@ -14903,7 +14887,7 @@ bool Player::LoadFromDB( uint32 guid, SqlQueryHolder *holder ) if (transGUID != 0) { - m_movementInfo.SetTransportData(transGUID, fields[27].GetFloat(), fields[28].GetFloat(), fields[29].GetFloat(), fields[30].GetFloat(), 0, -1); + m_movementInfo.SetTransportData(transGUID, fields[26].GetFloat(), fields[27].GetFloat(), fields[28].GetFloat(), fields[29].GetFloat(), 0, -1); if( !MaNGOS::IsValidMapCoord( GetPositionX() + m_movementInfo.GetTransportPos()->x, GetPositionY() + m_movementInfo.GetTransportPos()->y, @@ -14984,7 +14968,7 @@ bool Player::LoadFromDB( uint32 guid, SqlQueryHolder *holder ) SaveRecallPosition(); time_t now = time(NULL); - time_t logoutTime = time_t(fields[23].GetUInt64()); + time_t logoutTime = time_t(fields[22].GetUInt64()); // since last logout (in seconds) uint32 time_diff = uint32(now - logoutTime); @@ -14999,27 +14983,12 @@ bool Player::LoadFromDB( uint32 guid, SqlQueryHolder *holder ) uint16 newDrunkenValue = uint16(soberFactor*(GetUInt32Value(PLAYER_BYTES_3) & 0xFFFE)); SetDrunkValue(newDrunkenValue); - m_rest_bonus = fields[22].GetFloat(); - //speed collect rest bonus in offline, in logout, far from tavern, city (section/in hour) - float bubble0 = 0.031f; - //speed collect rest bonus in offline, in logout, in tavern, city (section/in hour) - float bubble1 = 0.125f; + m_cinematic = fields[18].GetUInt32(); + m_Played_time[PLAYED_TIME_TOTAL]= fields[19].GetUInt32(); + m_Played_time[PLAYED_TIME_LEVEL]= fields[20].GetUInt32(); - if(time_diff > 0) - { - float bubble = fields[24].GetUInt32() > 0 - ? bubble1*sWorld.getConfig(CONFIG_FLOAT_RATE_REST_OFFLINE_IN_TAVERN_OR_CITY) - : bubble0*sWorld.getConfig(CONFIG_FLOAT_RATE_REST_OFFLINE_IN_WILDERNESS); - - SetRestBonus(GetRestBonus()+ time_diff*((float)GetUInt32Value(PLAYER_NEXT_LEVEL_XP)/72000)*bubble); - } - - m_cinematic = fields[19].GetUInt32(); - m_Played_time[PLAYED_TIME_TOTAL]= fields[20].GetUInt32(); - m_Played_time[PLAYED_TIME_LEVEL]= fields[21].GetUInt32(); - - m_resetTalentsCost = fields[25].GetUInt32(); - m_resetTalentsTime = time_t(fields[26].GetUInt64()); + m_resetTalentsCost = fields[24].GetUInt32(); + m_resetTalentsTime = time_t(fields[25].GetUInt64()); // reserve some flags uint32 old_safe_flags = GetUInt32Value(PLAYER_FLAGS) & ( PLAYER_FLAGS_HIDE_CLOAK | PLAYER_FLAGS_HIDE_HELM ); @@ -15027,29 +14996,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[18].GetString() ); // must be before InitTaxiNodesForLevel + m_taxi.LoadTaxiMask( fields[17].GetString() ); // must be before InitTaxiNodesForLevel - uint32 extraflags = fields[32].GetUInt32(); + uint32 extraflags = fields[31].GetUInt32(); - m_stableSlots = fields[33].GetUInt32(); + m_stableSlots = fields[32].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[34].GetUInt32(); + m_atLoginFlags = fields[33].GetUInt32(); // Honor system // Update Honor kills data m_lastHonorUpdateTime = logoutTime; UpdateHonorFields(); - m_deathExpireTime = (time_t)fields[37].GetUInt64(); + m_deathExpireTime = (time_t)fields[36].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[38].GetCppString(); + std::string taxi_nodes = fields[37].GetCppString(); // clear channel spell data (if saved at channel spell casting) SetChannelObjectGUID(0); @@ -15085,6 +15054,22 @@ bool Player::LoadFromDB( uint32 guid, SqlQueryHolder *holder ) InitTaxiNodesForLevel(); InitRunes(); + // rest bonus can only be calculated after InitStatsForLevel() + m_rest_bonus = fields[21].GetFloat(); + + if(time_diff > 0) + { + //speed collect rest bonus in offline, in logout, far from tavern, city (section/in hour) + 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].GetUInt32() > 0 + ? bubble1*sWorld.getConfig(CONFIG_FLOAT_RATE_REST_OFFLINE_IN_TAVERN_OR_CITY) + : bubble0*sWorld.getConfig(CONFIG_FLOAT_RATE_REST_OFFLINE_IN_WILDERNESS); + + SetRestBonus(GetRestBonus()+ time_diff*((float)GetUInt32Value(PLAYER_NEXT_LEVEL_XP)/72000)*bubble); + } + // load skills after InitStatsForLevel because it triggering aura apply also _LoadSkills(holder->GetResult(PLAYER_LOGIN_QUERY_LOADSKILLS)); @@ -15095,8 +15080,8 @@ bool Player::LoadFromDB( uint32 guid, SqlQueryHolder *holder ) _LoadMailedItems(holder->GetResult(PLAYER_LOGIN_QUERY_LOADMAILEDITEMS)); UpdateNextMailTimeAndUnreads(); - m_specsCount = fields[59].GetUInt8(); - m_activeSpec = fields[60].GetUInt8(); + m_specsCount = fields[58].GetUInt8(); + m_activeSpec = fields[59].GetUInt8(); _LoadGlyphs(holder->GetResult(PLAYER_LOGIN_QUERY_LOADGLYPHS)); @@ -15131,7 +15116,7 @@ bool Player::LoadFromDB( uint32 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[47].GetUInt32(); + uint32 curTitle = fields[46].GetUInt32(); if (curTitle && !HasTitle(curTitle)) curTitle = 0; @@ -15199,11 +15184,11 @@ bool Player::LoadFromDB( uint32 guid, SqlQueryHolder *holder ) UpdateAllStats(); // restore remembered power/health values (but not more max values) - uint32 savedhealth = fields[51].GetUInt32(); + uint32 savedhealth = fields[50].GetUInt32(); SetHealth(savedhealth > GetMaxHealth() ? GetMaxHealth() : savedhealth); for(uint32 i = 0; i < MAX_POWERS; ++i) { - uint32 savedpower = fields[52+i].GetUInt32(); + uint32 savedpower = fields[51+i].GetUInt32(); SetPower(Powers(i),savedpower > GetMaxPower(Powers(i)) ? GetMaxPower(Powers(i)) : savedpower); } @@ -16255,13 +16240,13 @@ void Player::SaveToDB() std::ostringstream ss; 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, " + "map, dungeon_difficulty, position_x, position_y, position_z, orientation, " "taximask, online, 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, " "death_expire_time, taxi_path, arenaPoints, totalHonorPoints, todayHonorPoints, yesterdayHonorPoints, totalKills, " "todayKills, yesterdayKills, chosenTitle, knownCurrencies, watchedFaction, drunk, health, power1, power2, power3, " - "power4, power5, power6, power7, specCount, activeSpec) VALUES (" + "power4, power5, power6, power7, specCount, activeSpec, exploredZones, equipmentCache, ammoId) VALUES (" << GetGUIDLow() << ", " << GetSession()->GetAccountId() << ", '" << sql_name << "', " @@ -16282,7 +16267,7 @@ void Player::SaveToDB() << finiteAlways(GetPositionX()) << ", " << finiteAlways(GetPositionY()) << ", " << finiteAlways(GetPositionZ()) << ", " - << finiteAlways(GetOrientation()) << ", '"; + << finiteAlways(GetOrientation()) << ", "; } else { @@ -16291,17 +16276,9 @@ void Player::SaveToDB() << finiteAlways(GetTeleportDest().coord_x) << ", " << finiteAlways(GetTeleportDest().coord_y) << ", " << finiteAlways(GetTeleportDest().coord_z) << ", " - << finiteAlways(GetTeleportDest().orientation) << ", '"; - } - - uint16 i; - for( i = 0; i < m_valuesCount; ++i ) - { - ss << GetUInt32Value(i) << " "; + << finiteAlways(GetTeleportDest().orientation) << ", "; } - ss << "', "; - ss << m_taxi << ", "; // string with TaxiMaskSize numbers ss << (IsInWorld() ? 1 : 0) << ", "; @@ -16371,8 +16348,20 @@ void Player::SaveToDB() ss << ", "; ss << uint32(m_specsCount) << ", "; - ss << uint32(m_activeSpec); + ss << uint32(m_activeSpec) << ", '"; + for(uint32 i = 0; i < 128; ++i ) + { + ss << GetUInt32Value(PLAYER_EXPLORED_ZONES_1 + i) << " "; + } + + ss << "', '"; + for(uint32 i = 0; i < EQUIPMENT_SLOT_END * 2; ++i ) + { + ss << GetUInt32Value(PLAYER_VISIBLE_ITEM_1_ENTRYID + i) << " "; + } + ss << "',"; + ss << GetUInt32Value(PLAYER_AMMO_ID); ss << ")"; CharacterDatabase.Execute( ss.str().c_str() ); @@ -16837,34 +16826,6 @@ void Player::SavePositionInDB(uint32 mapid, float x,float y,float z,float o,uint CharacterDatabase.Execute(ss.str().c_str()); } -void Player::SaveDataFieldToDB() -{ - std::ostringstream ss; - ss<<"UPDATE characters SET data='"; - - for(uint16 i = 0; i < m_valuesCount; ++i ) - { - ss << GetUInt32Value(i) << " "; - } - ss<<"' WHERE guid='"<< GUID_LOPART(GetGUIDLow()) <<"'"; - - CharacterDatabase.Execute(ss.str().c_str()); -} - -bool Player::SaveValuesArrayInDB(Tokens const& tokens, uint64 guid) -{ - std::ostringstream ss2; - ss2 << "UPDATE characters SET data='"; - int i = 0; - for (Tokens::const_iterator iter = tokens.begin(); iter != tokens.end(); ++iter, ++i) - { - ss2 << tokens[i] << " "; - } - ss2 << "' WHERE guid='" << GUID_LOPART(guid) << "'"; - - return CharacterDatabase.Execute(ss2.str().c_str()); -} - void Player::SetUInt32ValueInArray(Tokens& tokens,uint16 index, uint32 value) { char buf[11]; @@ -16876,29 +16837,6 @@ void Player::SetUInt32ValueInArray(Tokens& tokens,uint16 index, uint32 value) tokens[index] = buf; } -void Player::SetUInt32ValueInDB(uint16 index, uint32 value, uint64 guid) -{ - Tokens tokens; - if(!LoadValuesArrayFromDB(tokens,guid)) - return; - - if(index >= tokens.size()) - return; - - char buf[11]; - snprintf(buf,11,"%u",value); - tokens[index] = buf; - - SaveValuesArrayInDB(tokens,guid); -} - -void Player::SetFloatValueInDB(uint16 index, float value, uint64 guid) -{ - uint32 temp; - memcpy(&temp, &value, sizeof(value)); - Player::SetUInt32ValueInDB(index, temp, guid); -} - void Player::Customize(uint64 guid, uint8 gender, uint8 skin, uint8 face, uint8 hairStyle, uint8 hairColor, uint8 facialHair) { // 0 diff --git a/src/game/Player.h b/src/game/Player.h index 3062b8dbdad..1d356336d1b 100644 --- a/src/game/Player.h +++ b/src/game/Player.h @@ -1411,11 +1411,8 @@ class MANGOS_DLL_SPEC Player : public Unit bool LoadFromDB(uint32 guid, SqlQueryHolder *holder); - static bool LoadValuesArrayFromDB(Tokens& data,uint64 guid); static uint32 GetUInt32ValueFromArray(Tokens const& data, uint16 index); static float GetFloatValueFromArray(Tokens const& data, uint16 index); - 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); @@ -1427,12 +1424,8 @@ 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); static void SetFloatValueInArray(Tokens& data,uint16 index, float value); - static void SetUInt32ValueInDB(uint16 index, uint32 value, uint64 guid); - static void SetFloatValueInDB(uint16 index, float value, uint64 guid); static void Customize(uint64 guid, uint8 gender, uint8 skin, uint8 face, uint8 hairStyle, uint8 hairColor, uint8 facialHair); static void SavePositionInDB(uint32 mapid, float x,float y,float z,float o,uint32 zone,uint64 guid); @@ -2327,6 +2320,7 @@ class MANGOS_DLL_SPEC Player : public Unit void _LoadEquipmentSets(QueryResult *result); void _LoadBGData(QueryResult* result); void _LoadGlyphs(QueryResult *result); + void _LoadExploredZones(const char* data); /*********************************************************/ /*** SAVE SYSTEM ***/