aboutsummaryrefslogtreecommitdiff
path: root/src/server/game/Entities
diff options
context:
space:
mode:
authorTreeston <treeston.mmoc@gmail.com>2019-07-08 11:33:09 +0200
committerTreeston <treeston.mmoc@gmail.com>2019-07-08 11:56:41 +0200
commit84b7b2e08ea55575cbe62d795383d4a5341ffd4d (patch)
treed0ce35d87614d0a45bc7747631e84949bf68d6c5 /src/server/game/Entities
parentec1a77bca20487f86765620485db9b13bb03aee8 (diff)
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.
Diffstat (limited to 'src/server/game/Entities')
-rw-r--r--src/server/game/Entities/Creature/Creature.cpp56
-rw-r--r--src/server/game/Entities/Creature/Creature.h2
-rw-r--r--src/server/game/Entities/GameObject/GameObject.cpp44
-rw-r--r--src/server/game/Entities/GameObject/GameObject.h2
-rw-r--r--src/server/game/Entities/Pet/Pet.h4
5 files changed, 66 insertions, 42 deletions
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<Creature*> 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<Creature>, 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();
diff --git a/src/server/game/Entities/GameObject/GameObject.cpp b/src/server/game/Entities/GameObject/GameObject.cpp
index 2212267b179..40a56400e19 100644
--- a/src/server/game/Entities/GameObject/GameObject.cpp
+++ b/src/server/game/Entities/GameObject/GameObject.cpp
@@ -30,6 +30,8 @@
#include "GroupMgr.h"
#include "Log.h"
#include "LootMgr.h"
+#include "Map.h"
+#include "MapManager.h"
#include "ObjectAccessor.h"
#include "ObjectMgr.h"
#include "OutdoorPvPMgr.h"
@@ -1111,51 +1113,71 @@ bool GameObject::LoadFromDB(ObjectGuid::LowType spawnId, Map* map, bool addToMap
return true;
}
-void GameObject::DeleteFromDB()
+/*static*/ bool GameObject::DeleteFromDB(ObjectGuid::LowType spawnId)
{
- GetMap()->RemoveRespawnTime(SPAWN_TYPE_GAMEOBJECT, m_spawnId);
- sObjectMgr->DeleteGameObjectData(m_spawnId);
+ GameObjectData const* data = sObjectMgr->GetGameObjectData(spawnId);
+ if (!data)
+ return false;
SQLTransaction trans = WorldDatabase.BeginTransaction();
+ sMapMgr->DoForAllMapsWithMapId(data->spawnPoint.GetMapId(),
+ [spawnId, trans](Map* map) -> void
+ {
+ // despawn all active objects, and remove their respawns
+ std::vector<GameObject*> toUnload;
+ for (auto const& pair : Trinity::Containers::MapEqualRange(map->GetGameObjectBySpawnIdStore(), spawnId))
+ toUnload.push_back(pair.second);
+ for (GameObject* obj : toUnload)
+ map->AddObjectToRemoveList(obj);
+ map->RemoveRespawnTime(SPAWN_TYPE_GAMEOBJECT, spawnId, false, trans);
+ }
+ );
+
+ // delete data from memory
+ sObjectMgr->DeleteGameObjectData(spawnId);
+
+ // ... and the database
PreparedStatement* stmt = WorldDatabase.GetPreparedStatement(WORLD_DEL_GAMEOBJECT);
- 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_GAMEOBJECT));
- stmt->setUInt32(1, m_spawnId);
+ stmt->setUInt32(1, spawnId);
trans->Append(stmt);
stmt = WorldDatabase.GetPreparedStatement(WORLD_DEL_EVENT_GAMEOBJECT);
- 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_GO_TO_GO);
trans->Append(stmt);
stmt = WorldDatabase.GetPreparedStatement(WORLD_DEL_LINKED_RESPAWN);
- stmt->setUInt32(0, m_spawnId);
+ stmt->setUInt32(0, spawnId);
stmt->setUInt32(1, LINKED_RESPAWN_GO_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_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_GO);
trans->Append(stmt);
stmt = WorldDatabase.GetPreparedStatement(WORLD_DEL_GAMEOBJECT_ADDON);
- stmt->setUInt32(0, m_spawnId);
+ stmt->setUInt32(0, spawnId);
trans->Append(stmt);
WorldDatabase.CommitTransaction(trans);
+
+ return true;
}
/*********************************************************/
diff --git a/src/server/game/Entities/GameObject/GameObject.h b/src/server/game/Entities/GameObject/GameObject.h
index f47611cee9f..7abf6223cf5 100644
--- a/src/server/game/Entities/GameObject/GameObject.h
+++ b/src/server/game/Entities/GameObject/GameObject.h
@@ -118,7 +118,7 @@ class TC_GAME_API GameObject : public WorldObject, public GridObject<GameObject>
void SaveToDB();
void SaveToDB(uint32 mapid, uint8 spawnMask, uint32 phaseMask);
bool LoadFromDB(ObjectGuid::LowType spawnId, Map* map, bool addToMap, bool = true); // arg4 is unused, only present to match the signature on Creature
- void DeleteFromDB();
+ static bool DeleteFromDB(ObjectGuid::LowType spawnId);
void SetOwnerGUID(ObjectGuid owner)
{
diff --git a/src/server/game/Entities/Pet/Pet.h b/src/server/game/Entities/Pet/Pet.h
index 5de4723e9e7..dbbcc1979fd 100644
--- a/src/server/game/Entities/Pet/Pet.h
+++ b/src/server/game/Entities/Pet/Pet.h
@@ -164,9 +164,5 @@ class TC_GAME_API Pet : public Guardian
{
ABORT();
}
- void DeleteFromDB() override // override of Creature::DeleteFromDB - must not be called
- {
- ABORT();
- }
};
#endif