From 84b7b2e08ea55575cbe62d795383d4a5341ffd4d Mon Sep 17 00:00:00 2001 From: Treeston Date: Mon, 8 Jul 2019 11:33:09 +0200 Subject: Entities/Unit: Nuke Map::ForceRespawn from orbit, with the following implications: - .npc respawn no longer causes stupid things to happen (Fixes #23014) - ::DeleteFromDB methods on Creature and GameObject rewritten to be as sensible as such a colossally stupid method can ever be. They're static now. - .npc delete and .gobj delete ported to new argument handling, and rewritten as per above. They can no longer crash the server when used in instances, too. Yay for that. - Adjusted various dusty cobwebbed hacks around the core (why does waypoint visualization use permanent spawns *shudder*) to still work too. --- src/server/game/Entities/Creature/Creature.cpp | 56 ++++++++++++++------------ src/server/game/Entities/Creature/Creature.h | 2 +- 2 files changed, 32 insertions(+), 26 deletions(-) (limited to 'src/server/game/Entities/Creature') diff --git a/src/server/game/Entities/Creature/Creature.cpp b/src/server/game/Entities/Creature/Creature.cpp index 0219731f64f..1661789062a 100644 --- a/src/server/game/Entities/Creature/Creature.cpp +++ b/src/server/game/Entities/Creature/Creature.cpp @@ -34,6 +34,7 @@ #include "InstanceScript.h" #include "Log.h" #include "LootMgr.h" +#include "MapManager.h" #include "MotionMaster.h" #include "MoveSpline.h" #include "ObjectAccessor.h" @@ -1725,70 +1726,75 @@ bool Creature::hasInvolvedQuest(uint32 quest_id) const return false; } -void Creature::DeleteFromDB() +/*static*/ bool Creature::DeleteFromDB(ObjectGuid::LowType spawnId) { - if (!m_spawnId) - { - TC_LOG_ERROR("entities.unit", "Trying to delete not saved creature! LowGUID: %u, Entry: %u", GetGUID().GetCounter(), GetEntry()); - return; - } + CreatureData const* data = sObjectMgr->GetCreatureData(spawnId); + if (!data) + return false; - // remove any scheduled respawns - GetMap()->RemoveRespawnTime(SPAWN_TYPE_CREATURE, m_spawnId); + SQLTransaction trans = WorldDatabase.BeginTransaction(); - // delete data from memory - sObjectMgr->DeleteCreatureData(m_spawnId); + sMapMgr->DoForAllMapsWithMapId(data->spawnPoint.GetMapId(), + [spawnId, trans](Map* map) -> void + { + // despawn all active creatures, and remove their respawns + std::vector toUnload; + for (auto const& pair : Trinity::Containers::MapEqualRange(map->GetCreatureBySpawnIdStore(), spawnId)) + toUnload.push_back(pair.second); + for (Creature* creature : toUnload) + map->AddObjectToRemoveList(creature); + map->RemoveRespawnTime(SPAWN_TYPE_CREATURE, spawnId, false, trans); + } + ); - // delete data and all its associations from DB - SQLTransaction trans = WorldDatabase.BeginTransaction(); + // delete data from memory ... + sObjectMgr->DeleteCreatureData(spawnId); + // ... and the database PreparedStatement* stmt = WorldDatabase.GetPreparedStatement(WORLD_DEL_CREATURE); - stmt->setUInt32(0, m_spawnId); + stmt->setUInt32(0, spawnId); trans->Append(stmt); stmt = WorldDatabase.GetPreparedStatement(WORLD_DEL_SPAWNGROUP_MEMBER); stmt->setUInt8(0, uint8(SPAWN_TYPE_CREATURE)); - stmt->setUInt32(1, m_spawnId); + stmt->setUInt32(1, spawnId); trans->Append(stmt); stmt = WorldDatabase.GetPreparedStatement(WORLD_DEL_CREATURE_ADDON); - stmt->setUInt32(0, m_spawnId); + stmt->setUInt32(0, spawnId); trans->Append(stmt); stmt = WorldDatabase.GetPreparedStatement(WORLD_DEL_GAME_EVENT_CREATURE); - stmt->setUInt32(0, m_spawnId); + stmt->setUInt32(0, spawnId); trans->Append(stmt); stmt = WorldDatabase.GetPreparedStatement(WORLD_DEL_GAME_EVENT_MODEL_EQUIP); - stmt->setUInt32(0, m_spawnId); + stmt->setUInt32(0, spawnId); trans->Append(stmt); stmt = WorldDatabase.GetPreparedStatement(WORLD_DEL_LINKED_RESPAWN); - stmt->setUInt32(0, m_spawnId); + stmt->setUInt32(0, spawnId); stmt->setUInt32(1, LINKED_RESPAWN_CREATURE_TO_CREATURE); trans->Append(stmt); stmt = WorldDatabase.GetPreparedStatement(WORLD_DEL_LINKED_RESPAWN); - stmt->setUInt32(0, m_spawnId); + stmt->setUInt32(0, spawnId); stmt->setUInt32(1, LINKED_RESPAWN_CREATURE_TO_GO); trans->Append(stmt); stmt = WorldDatabase.GetPreparedStatement(WORLD_DEL_LINKED_RESPAWN_MASTER); - stmt->setUInt32(0, m_spawnId); + stmt->setUInt32(0, spawnId); stmt->setUInt32(1, LINKED_RESPAWN_CREATURE_TO_CREATURE); trans->Append(stmt); stmt = WorldDatabase.GetPreparedStatement(WORLD_DEL_LINKED_RESPAWN_MASTER); - stmt->setUInt32(0, m_spawnId); + stmt->setUInt32(0, spawnId); stmt->setUInt32(1, LINKED_RESPAWN_GO_TO_CREATURE); trans->Append(stmt); WorldDatabase.CommitTransaction(trans); - // then delete any active instances of the creature - auto const& spawnMap = GetMap()->GetCreatureBySpawnIdStore(); - for (auto it = spawnMap.find(m_spawnId); it != spawnMap.end(); it = spawnMap.find(m_spawnId)) - it->second->AddObjectToRemoveList(); + return true; } bool Creature::IsInvisibleDueToDespawn() const diff --git a/src/server/game/Entities/Creature/Creature.h b/src/server/game/Entities/Creature/Creature.h index 83268df8303..92285145126 100644 --- a/src/server/game/Entities/Creature/Creature.h +++ b/src/server/game/Entities/Creature/Creature.h @@ -200,7 +200,7 @@ class TC_GAME_API Creature : public Unit, public GridObject, public Ma void SaveToDB(); // overriden in Pet virtual void SaveToDB(uint32 mapid, uint8 spawnMask, uint32 phaseMask); - virtual void DeleteFromDB(); // overriden in Pet + static bool DeleteFromDB(ObjectGuid::LowType spawnId); Loot loot; void StartPickPocketRefillTimer(); -- cgit v1.2.3