diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/server/database/Database/Implementation/CharacterDatabase.cpp | 8 | ||||
-rw-r--r-- | src/server/game/Entities/Player/Player.cpp | 4 | ||||
-rw-r--r-- | src/server/game/Groups/GroupMgr.cpp | 6 | ||||
-rw-r--r-- | src/server/game/Handlers/MiscHandler.cpp | 22 | ||||
-rw-r--r-- | src/server/game/Instances/InstanceSaveMgr.cpp | 16 | ||||
-rw-r--r-- | src/server/game/Instances/InstanceSaveMgr.h | 8 | ||||
-rw-r--r-- | src/server/game/Instances/InstanceScript.cpp | 12 | ||||
-rw-r--r-- | src/server/game/Instances/InstanceScript.h | 11 | ||||
-rw-r--r-- | src/server/game/Maps/Map.cpp | 2 |
9 files changed, 71 insertions, 18 deletions
diff --git a/src/server/database/Database/Implementation/CharacterDatabase.cpp b/src/server/database/Database/Implementation/CharacterDatabase.cpp index 65e228a7c48..580243f0d51 100644 --- a/src/server/database/Database/Implementation/CharacterDatabase.cpp +++ b/src/server/database/Database/Implementation/CharacterDatabase.cpp @@ -83,7 +83,7 @@ void CharacterDatabaseConnection::DoPrepareStatements() "FROM characters WHERE guid = ?", CONNECTION_ASYNC); PrepareStatement(CHAR_SEL_GROUP_MEMBER, "SELECT guid FROM group_member WHERE memberGuid = ?", CONNECTION_BOTH); - PrepareStatement(CHAR_SEL_CHARACTER_INSTANCE, "SELECT id, permanent, map, difficulty, extendState, resettime FROM character_instance LEFT JOIN instance ON instance = id WHERE guid = ?", CONNECTION_ASYNC); + PrepareStatement(CHAR_SEL_CHARACTER_INSTANCE, "SELECT id, permanent, map, difficulty, extendState, resettime, entranceId FROM character_instance LEFT JOIN instance ON instance = id WHERE guid = ?", CONNECTION_ASYNC); PrepareStatement(CHAR_SEL_CHARACTER_AURAS, "SELECT casterGuid, itemGuid, spell, effectMask, recalculateMask, stackCount, maxDuration, remainTime, remainCharges, castItemLevel FROM character_aura WHERE guid = ?", CONNECTION_ASYNC); PrepareStatement(CHAR_SEL_CHARACTER_AURA_EFFECTS, "SELECT casterGuid, itemGuid, spell, effectMask, effectIndex, amount, baseAmount FROM character_aura_effect WHERE guid = ?", CONNECTION_ASYNC); PrepareStatement(CHAR_SEL_CHARACTER_SPELL, "SELECT spell, active, disabled FROM character_spell WHERE guid = ?", CONNECTION_ASYNC); @@ -290,8 +290,8 @@ void CharacterDatabaseConnection::DoPrepareStatements() PrepareStatement(CHAR_DEL_TUTORIALS, "DELETE FROM account_tutorial WHERE accountId = ?", CONNECTION_ASYNC); // Instance saves - PrepareStatement(CHAR_INS_INSTANCE_SAVE, "INSERT INTO instance (id, map, resettime, difficulty, completedEncounters, data) VALUES (?, ?, ?, ?, ?, ?)", CONNECTION_ASYNC); - PrepareStatement(CHAR_UPD_INSTANCE_DATA, "UPDATE instance SET completedEncounters=?, data=? WHERE id=?", CONNECTION_ASYNC); + PrepareStatement(CHAR_INS_INSTANCE_SAVE, "INSERT INTO instance (id, map, resettime, difficulty, completedEncounters, data, entranceId) VALUES (?, ?, ?, ?, ?, ?, ?)", CONNECTION_ASYNC); + PrepareStatement(CHAR_UPD_INSTANCE_DATA, "UPDATE instance SET completedEncounters=?, data=?, entranceId=? WHERE id=?", CONNECTION_ASYNC); // Game event saves PrepareStatement(CHAR_DEL_GAME_EVENT_SAVE, "DELETE FROM game_event_save WHERE eventEntry = ?", CONNECTION_ASYNC); @@ -467,7 +467,7 @@ void CharacterDatabaseConnection::DoPrepareStatements() 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 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_INSTANCE, "SELECT data, completedEncounters, entranceId FROM instance WHERE map = ? AND id = ?", CONNECTION_SYNCH); PrepareStatement(CHAR_SEL_PERM_BIND_BY_INSTANCE, "SELECT guid FROM character_instance WHERE instance = ? and permanent = 1", 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/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp index f308d22e359..8a4b23718ef 100644 --- a/src/server/game/Entities/Player/Player.cpp +++ b/src/server/game/Entities/Player/Player.cpp @@ -18135,6 +18135,8 @@ void Player::_LoadBoundInstances(PreparedQueryResult result) // so the value read from the DB may be wrong here but only if the InstanceSave is loaded // and in that case it is not used + uint32 entranceId = fields[6].GetUInt32(); + bool deleteInstance = false; MapEntry const* mapEntry = sMapStore.LookupEntry(mapId); @@ -18182,7 +18184,7 @@ void Player::_LoadBoundInstances(PreparedQueryResult result) } // since non permanent binds are always solo bind, they can always be reset - if (InstanceSave* save = sInstanceSaveMgr->AddInstanceSave(mapId, instanceId, Difficulty(difficulty), resetTime, !perm, true)) + if (InstanceSave* save = sInstanceSaveMgr->AddInstanceSave(mapId, instanceId, Difficulty(difficulty), resetTime, entranceId, !perm, true)) BindToInstance(save, perm, extendState, true); } while (result->NextRow()); diff --git a/src/server/game/Groups/GroupMgr.cpp b/src/server/game/Groups/GroupMgr.cpp index c6046c3a9aa..dce3102fe3e 100644 --- a/src/server/game/Groups/GroupMgr.cpp +++ b/src/server/game/Groups/GroupMgr.cpp @@ -201,8 +201,8 @@ void GroupMgr::LoadGroups() TC_LOG_INFO("server.loading", "Loading Group instance saves..."); { uint32 oldMSTime = getMSTime(); - // 0 1 2 3 4 5 6 - QueryResult result = CharacterDatabase.Query("SELECT gi.guid, i.map, gi.instance, gi.permanent, i.difficulty, i.resettime, COUNT(g.guid) " + // 0 1 2 3 4 5 6 7 + QueryResult result = CharacterDatabase.Query("SELECT gi.guid, i.map, gi.instance, gi.permanent, i.difficulty, i.resettime, i.entranceId, COUNT(g.guid) " "FROM group_instance gi INNER JOIN instance i ON gi.instance = i.id " "LEFT JOIN character_instance ci LEFT JOIN groups g ON g.leaderGuid = ci.guid ON ci.instance = gi.instance AND ci.permanent = 1 GROUP BY gi.instance ORDER BY gi.guid"); if (!result) @@ -230,7 +230,7 @@ void GroupMgr::LoadGroups() if (!difficultyEntry || difficultyEntry->InstanceType != mapEntry->InstanceType) continue; - InstanceSave* save = sInstanceSaveMgr->AddInstanceSave(mapEntry->ID, fields[2].GetUInt32(), Difficulty(diff), time_t(fields[5].GetUInt32()), fields[6].GetUInt64() != 0, true); + InstanceSave* save = sInstanceSaveMgr->AddInstanceSave(mapEntry->ID, fields[2].GetUInt32(), Difficulty(diff), time_t(fields[5].GetUInt32()), fields[6].GetUInt32(), fields[7].GetUInt64() != 0, true); group->BindToInstance(save, fields[3].GetBool(), true); ++count; } diff --git a/src/server/game/Handlers/MiscHandler.cpp b/src/server/game/Handlers/MiscHandler.cpp index 382b8d70f38..be271c2c73d 100644 --- a/src/server/game/Handlers/MiscHandler.cpp +++ b/src/server/game/Handlers/MiscHandler.cpp @@ -618,7 +618,27 @@ void WorldSession::HandleAreaTriggerOpcode(WorldPackets::Misc::AreaTrigger& pack } if (!teleported) - player->TeleportTo(at->target_mapId, at->target_X, at->target_Y, at->target_Z, at->target_Orientation, TELE_TO_NOT_LEAVE_TRANSPORT); + { + WorldSafeLocsEntry const* entranceLocation = nullptr; + InstanceSave* instanceSave = player->GetInstanceSave(at->target_mapId); + if (instanceSave) + { + // Check if we can contact the instancescript of the instance for an updated entrance location + if (Map* map = sMapMgr->FindMap(at->target_mapId, player->GetInstanceSave(at->target_mapId)->GetInstanceId())) + if (InstanceMap* instanceMap = map->ToInstanceMap()) + if (InstanceScript* instanceScript = instanceMap->GetInstanceScript()) + entranceLocation = sWorldSafeLocsStore.LookupEntry(instanceScript->GetEntranceLocation()); + + // Finally check with the instancesave for an entrance location if we did not get a valid one from the instancescript + if (!entranceLocation) + entranceLocation = sWorldSafeLocsStore.LookupEntry(instanceSave->GetEntranceLocation()); + } + + if (entranceLocation) + player->TeleportTo(entranceLocation->MapID, entranceLocation->Loc.X, entranceLocation->Loc.Y, entranceLocation->Loc.Z, entranceLocation->Facing * M_PI / 180, TELE_TO_NOT_LEAVE_TRANSPORT); + else + player->TeleportTo(at->target_mapId, at->target_X, at->target_Y, at->target_Z, at->target_Orientation, TELE_TO_NOT_LEAVE_TRANSPORT); + } } void WorldSession::HandleUpdateAccountData(WorldPackets::ClientConfig::UserClientUpdateAccountData& packet) diff --git a/src/server/game/Instances/InstanceSaveMgr.cpp b/src/server/game/Instances/InstanceSaveMgr.cpp index 4d979ecb9b3..9258977f7a8 100644 --- a/src/server/game/Instances/InstanceSaveMgr.cpp +++ b/src/server/game/Instances/InstanceSaveMgr.cpp @@ -71,7 +71,7 @@ void InstanceSaveManager::Unload() - adding instance into manager - called from InstanceMap::Add, _LoadBoundInstances, LoadGroups */ -InstanceSave* InstanceSaveManager::AddInstanceSave(uint32 mapId, uint32 instanceId, Difficulty difficulty, time_t resetTime, bool canReset, bool load) +InstanceSave* InstanceSaveManager::AddInstanceSave(uint32 mapId, uint32 instanceId, Difficulty difficulty, time_t resetTime, uint32 entranceId, bool canReset, bool load) { if (InstanceSave* old_save = GetInstanceSave(instanceId)) return old_save; @@ -96,6 +96,12 @@ InstanceSave* InstanceSaveManager::AddInstanceSave(uint32 mapId, uint32 instance return NULL; } + if (entranceId && !sWorldSafeLocsStore.LookupEntry(entranceId)) + { + TC_LOG_WARN("misc", "InstanceSaveManager::AddInstanceSave: invalid entranceId = %d defined for instance save with mapid = %d, instanceid = %d!", entranceId, mapId, instanceId); + entranceId = 0; + } + if (!resetTime) { // initialize reset time @@ -112,7 +118,7 @@ InstanceSave* InstanceSaveManager::AddInstanceSave(uint32 mapId, uint32 instance TC_LOG_DEBUG("maps", "InstanceSaveManager::AddInstanceSave: mapid = %d, instanceid = %d", mapId, instanceId); - InstanceSave* save = new InstanceSave(mapId, instanceId, difficulty, resetTime, canReset); + InstanceSave* save = new InstanceSave(mapId, instanceId, difficulty, entranceId, resetTime, canReset); if (!load) save->SaveToDB(); @@ -173,9 +179,9 @@ void InstanceSaveManager::UnloadInstanceSave(uint32 InstanceId) save->UnloadIfEmpty(); } -InstanceSave::InstanceSave(uint16 MapId, uint32 InstanceId, Difficulty difficulty, time_t resetTime, bool canReset) +InstanceSave::InstanceSave(uint16 MapId, uint32 InstanceId, Difficulty difficulty, uint32 entranceId, time_t resetTime, bool canReset) : m_resetTime(resetTime), m_instanceid(InstanceId), m_mapid(MapId), - m_difficulty(difficulty), m_canReset(canReset), m_toDelete(false) { } + m_difficulty(difficulty), m_entranceId(entranceId), m_canReset(canReset), m_toDelete(false) { } InstanceSave::~InstanceSave() { @@ -200,6 +206,7 @@ void InstanceSave::SaveToDB() { data = instanceScript->GetSaveData(); completedEncounters = instanceScript->GetCompletedEncounterMask(); + m_entranceId = instanceScript->GetEntranceLocation(); } } @@ -210,6 +217,7 @@ void InstanceSave::SaveToDB() stmt->setUInt8(3, uint8(GetDifficultyID())); stmt->setUInt32(4, completedEncounters); stmt->setString(5, data); + stmt->setUInt32(6, m_entranceId); CharacterDatabase.Execute(stmt); } diff --git a/src/server/game/Instances/InstanceSaveMgr.h b/src/server/game/Instances/InstanceSaveMgr.h index ff99736f2b7..6e0d34a88e6 100644 --- a/src/server/game/Instances/InstanceSaveMgr.h +++ b/src/server/game/Instances/InstanceSaveMgr.h @@ -49,7 +49,7 @@ class TC_GAME_API InstanceSave - any new instance is being generated - the first time a player bound to InstanceId logs in - when a group bound to the instance is loaded */ - InstanceSave(uint16 MapId, uint32 InstanceId, Difficulty difficulty, time_t resetTime, bool canReset); + InstanceSave(uint16 MapId, uint32 InstanceId, Difficulty difficulty, uint32 entranceId, time_t resetTime, bool canReset); /* Unloaded when m_playerList and m_groupList become empty or when the instance is reset */ @@ -75,6 +75,9 @@ class TC_GAME_API InstanceSave void SetResetTime(time_t resetTime) { m_resetTime = resetTime; } time_t GetResetTimeForDB(); + uint32 GetEntranceLocation() const { return m_entranceId; } + void SetEntranceLocation(uint32 entranceId) { m_entranceId = entranceId; } + InstanceTemplate const* GetTemplate(); MapEntry const* GetMapEntry(); @@ -139,6 +142,7 @@ class TC_GAME_API InstanceSave uint32 m_instanceid; uint32 m_mapid; Difficulty m_difficulty; + uint32 m_entranceId; bool m_canReset; bool m_toDelete; @@ -211,7 +215,7 @@ class TC_GAME_API InstanceSaveManager void Update(); - InstanceSave* AddInstanceSave(uint32 mapId, uint32 instanceId, Difficulty difficulty, time_t resetTime, + InstanceSave* AddInstanceSave(uint32 mapId, uint32 instanceId, Difficulty difficulty, time_t resetTime, uint32 entranceId, bool canReset, bool load = false); void RemoveInstanceSave(uint32 InstanceId); void UnloadInstanceSave(uint32 InstanceId); diff --git a/src/server/game/Instances/InstanceScript.cpp b/src/server/game/Instances/InstanceScript.cpp index 6ddef1ceeaa..2b415bf9a66 100644 --- a/src/server/game/Instances/InstanceScript.cpp +++ b/src/server/game/Instances/InstanceScript.cpp @@ -40,7 +40,7 @@ BossBoundaryData::~BossBoundaryData() } InstanceScript::InstanceScript(Map* map) : instance(map), completedEncounters(0), -_combatResurrectionTimer(0), _combatResurrectionCharges(0), _combatResurrectionTimerStarted(false) +_entranceId(0), _temporaryEntranceId(0), _combatResurrectionTimer(0), _combatResurrectionCharges(0), _combatResurrectionTimerStarted(false) { #ifdef TRINITY_API_USE_DYNAMIC_LINKING uint32 scriptId = sObjectMgr->GetInstanceTemplate(map->GetId())->ScriptId; @@ -61,7 +61,8 @@ void InstanceScript::SaveToDB() PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_UPD_INSTANCE_DATA); stmt->setUInt32(0, GetCompletedEncounterMask()); stmt->setString(1, data); - stmt->setUInt32(2, instance->GetInstanceId()); + stmt->setUInt32(2, _entranceId); + stmt->setUInt32(3, instance->GetInstanceId()); CharacterDatabase.Execute(stmt); } @@ -606,6 +607,13 @@ bool InstanceScript::CheckAchievementCriteriaMeet(uint32 criteria_id, Player con return false; } +void InstanceScript::SetEntranceLocation(uint32 worldSafeLocationId) +{ + _entranceId = worldSafeLocationId; + if (_temporaryEntranceId) + _temporaryEntranceId = 0; +} + void InstanceScript::SendEncounterUnit(uint32 type, Unit* unit /*= NULL*/, uint8 priority) { switch (type) diff --git a/src/server/game/Instances/InstanceScript.h b/src/server/game/Instances/InstanceScript.h index d858bb6b9c2..eb0579ef63e 100644 --- a/src/server/game/Instances/InstanceScript.h +++ b/src/server/game/Instances/InstanceScript.h @@ -246,6 +246,15 @@ class TC_GAME_API InstanceScript : public ZoneScript // Returns completed encounters mask for packets uint32 GetCompletedEncounterMask() const { return completedEncounters; } + // Sets the entrance location (WorldSafeLoc) id + void SetEntranceLocation(uint32 worldSafeLocationId); + + // Sets a temporary entrance that does not get saved to db + void SetTemporaryEntranceLocation(uint32 worldSafeLocationId) { _temporaryEntranceId = worldSafeLocationId; } + + // Get's the current entrance id + uint32 GetEntranceLocation() const { return _temporaryEntranceId ? _temporaryEntranceId : _entranceId; } + void SendEncounterUnit(uint32 type, Unit* unit = NULL, uint8 priority = 0); void SendEncounterStart(uint32 inCombatResCount = 0, uint32 maxInCombatResCount = 0, uint32 inCombatResChargeRecovery = 0, uint32 nextCombatResChargeTime = 0); void SendEncounterEnd(); @@ -309,6 +318,8 @@ class TC_GAME_API InstanceScript : public ZoneScript ObjectInfoMap _gameObjectInfo; ObjectGuidMap _objectGuids; uint32 completedEncounters; // completed encounter mask, bit indexes are DungeonEncounter.dbc boss numbers, used for packets + uint32 _entranceId; + uint32 _temporaryEntranceId; uint32 _combatResurrectionTimer; uint8 _combatResurrectionCharges; // the counter for available battle resurrections bool _combatResurrectionTimerStarted; diff --git a/src/server/game/Maps/Map.cpp b/src/server/game/Maps/Map.cpp index 81aa0fd174c..2e98dc59016 100644 --- a/src/server/game/Maps/Map.cpp +++ b/src/server/game/Maps/Map.cpp @@ -3135,7 +3135,7 @@ bool InstanceMap::AddPlayerToMap(Player* player, bool initPlayer /*= true*/) if (!mapSave) { TC_LOG_DEBUG("maps", "InstanceMap::Add: creating instance save for map %d spawnmode %d with instance id %d", GetId(), GetSpawnMode(), GetInstanceId()); - mapSave = sInstanceSaveMgr->AddInstanceSave(GetId(), GetInstanceId(), Difficulty(GetSpawnMode()), 0, true); + mapSave = sInstanceSaveMgr->AddInstanceSave(GetId(), GetInstanceId(), Difficulty(GetSpawnMode()), 0, 0, true); } ASSERT(mapSave); |