diff options
author | Treeston <treeston.mmoc@gmail.com> | 2019-07-08 11:33:09 +0200 |
---|---|---|
committer | Shauren <shauren.trinity@gmail.com> | 2021-12-14 22:42:22 +0100 |
commit | 2532de6acb7d73957a8fca44e7fc26160f47cc47 (patch) | |
tree | 7e5377ad36d395a52e2d91d45396760c3c60916f /src/server | |
parent | 8be3d33eae02e327ba6ae7c7cee87f9def9c7207 (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.
(cherry picked from commit 84b7b2e08ea55575cbe62d795383d4a5341ffd4d)
Diffstat (limited to 'src/server')
-rw-r--r-- | src/server/game/Entities/Creature/Creature.cpp | 58 | ||||
-rw-r--r-- | src/server/game/Entities/Creature/Creature.h | 2 | ||||
-rw-r--r-- | src/server/game/Entities/GameObject/GameObject.cpp | 48 | ||||
-rw-r--r-- | src/server/game/Entities/GameObject/GameObject.h | 2 | ||||
-rw-r--r-- | src/server/game/Entities/Pet/Pet.h | 4 | ||||
-rw-r--r-- | src/server/game/Maps/Map.cpp | 8 | ||||
-rw-r--r-- | src/server/game/Maps/Map.h | 9 | ||||
-rw-r--r-- | src/server/game/OutdoorPvP/OutdoorPvP.cpp | 44 | ||||
-rw-r--r-- | src/server/scripts/Commands/cs_gobject.cpp | 62 | ||||
-rw-r--r-- | src/server/scripts/Commands/cs_misc.cpp | 2 | ||||
-rw-r--r-- | src/server/scripts/Commands/cs_npc.cpp | 57 | ||||
-rw-r--r-- | src/server/scripts/Commands/cs_wp.cpp | 67 |
12 files changed, 163 insertions, 200 deletions
diff --git a/src/server/game/Entities/Creature/Creature.cpp b/src/server/game/Entities/Creature/Creature.cpp index 81c4791e2a5..ce5222b5195 100644 --- a/src/server/game/Entities/Creature/Creature.cpp +++ b/src/server/game/Entities/Creature/Creature.cpp @@ -35,6 +35,7 @@ #include "InstanceScript.h" #include "Log.h" #include "LootMgr.h" +#include "MapManager.h" #include "MiscPackets.h" #include "MotionMaster.h" #include "ObjectAccessor.h" @@ -1888,70 +1889,79 @@ 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 %s!", GetGUID().ToString().c_str()); - return; - } + CreatureData const* data = sObjectMgr->GetCreatureData(spawnId); + if (!data) + return false; + + CharacterDatabaseTransaction charTrans = CharacterDatabase.BeginTransaction(); + + sMapMgr->DoForAllMapsWithMapId(data->spawnPoint.GetMapId(), + [spawnId, charTrans](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, charTrans); + } + ); - // remove any scheduled respawns - GetMap()->RemoveRespawnTime(SPAWN_TYPE_CREATURE, m_spawnId); + // delete data from memory ... + sObjectMgr->DeleteCreatureData(spawnId); - // delete data from memory - sObjectMgr->DeleteCreatureData(m_spawnId); + CharacterDatabase.CommitTransaction(charTrans); - // delete data and all its associations from DB WorldDatabaseTransaction trans = WorldDatabase.BeginTransaction(); + // ... and the database WorldDatabasePreparedStatement* stmt = WorldDatabase.GetPreparedStatement(WORLD_DEL_CREATURE); - stmt->setUInt64(0, m_spawnId); + stmt->setUInt64(0, spawnId); trans->Append(stmt); stmt = WorldDatabase.GetPreparedStatement(WORLD_DEL_SPAWNGROUP_MEMBER); stmt->setUInt8(0, uint8(SPAWN_TYPE_CREATURE)); - stmt->setUInt64(1, m_spawnId); + stmt->setUInt64(1, spawnId); trans->Append(stmt); stmt = WorldDatabase.GetPreparedStatement(WORLD_DEL_CREATURE_ADDON); - stmt->setUInt64(0, m_spawnId); + stmt->setUInt64(0, spawnId); trans->Append(stmt); stmt = WorldDatabase.GetPreparedStatement(WORLD_DEL_GAME_EVENT_CREATURE); - stmt->setUInt64(0, m_spawnId); + stmt->setUInt64(0, spawnId); trans->Append(stmt); stmt = WorldDatabase.GetPreparedStatement(WORLD_DEL_GAME_EVENT_MODEL_EQUIP); - stmt->setUInt64(0, m_spawnId); + stmt->setUInt64(0, spawnId); trans->Append(stmt); stmt = WorldDatabase.GetPreparedStatement(WORLD_DEL_LINKED_RESPAWN); - stmt->setUInt64(0, m_spawnId); + stmt->setUInt64(0, spawnId); stmt->setUInt32(1, LINKED_RESPAWN_CREATURE_TO_CREATURE); trans->Append(stmt); stmt = WorldDatabase.GetPreparedStatement(WORLD_DEL_LINKED_RESPAWN); - stmt->setUInt64(0, m_spawnId); + stmt->setUInt64(0, spawnId); stmt->setUInt32(1, LINKED_RESPAWN_CREATURE_TO_GO); trans->Append(stmt); stmt = WorldDatabase.GetPreparedStatement(WORLD_DEL_LINKED_RESPAWN_MASTER); - stmt->setUInt64(0, m_spawnId); + stmt->setUInt64(0, spawnId); stmt->setUInt32(1, LINKED_RESPAWN_CREATURE_TO_CREATURE); trans->Append(stmt); stmt = WorldDatabase.GetPreparedStatement(WORLD_DEL_LINKED_RESPAWN_MASTER); - stmt->setUInt64(0, m_spawnId); + stmt->setUInt64(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 b4d2228bb2e..a108630811c 100644 --- a/src/server/game/Entities/Creature/Creature.h +++ b/src/server/game/Entities/Creature/Creature.h @@ -214,7 +214,7 @@ class TC_GAME_API Creature : public Unit, public GridObject<Creature>, public Ma void SaveToDB(); // overriden in Pet virtual void SaveToDB(uint32 mapid, std::vector<Difficulty> const& spawnDifficulties); - 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 e36ec3016ba..0d20d360d55 100644 --- a/src/server/game/Entities/GameObject/GameObject.cpp +++ b/src/server/game/Entities/GameObject/GameObject.cpp @@ -34,6 +34,8 @@ #include "Item.h" #include "Log.h" #include "LootMgr.h" +#include "Map.h" +#include "MapManager.h" #include "MiscPackets.h" #include "ObjectAccessor.h" #include "ObjectMgr.h" @@ -1261,51 +1263,75 @@ 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; + + CharacterDatabaseTransaction charTrans = CharacterDatabase.BeginTransaction(); + + sMapMgr->DoForAllMapsWithMapId(data->spawnPoint.GetMapId(), + [spawnId, charTrans](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, charTrans); + } + ); + + // delete data from memory + sObjectMgr->DeleteGameObjectData(spawnId); + + CharacterDatabase.CommitTransaction(charTrans); WorldDatabaseTransaction trans = WorldDatabase.BeginTransaction(); + // ... and the database WorldDatabasePreparedStatement* stmt = WorldDatabase.GetPreparedStatement(WORLD_DEL_GAMEOBJECT); - stmt->setUInt64(0, m_spawnId); + stmt->setUInt64(0, spawnId); trans->Append(stmt); stmt = WorldDatabase.GetPreparedStatement(WORLD_DEL_SPAWNGROUP_MEMBER); stmt->setUInt8(0, uint8(SPAWN_TYPE_GAMEOBJECT)); - stmt->setUInt64(1, m_spawnId); + stmt->setUInt64(1, spawnId); trans->Append(stmt); stmt = WorldDatabase.GetPreparedStatement(WORLD_DEL_EVENT_GAMEOBJECT); - stmt->setUInt64(0, m_spawnId); + stmt->setUInt64(0, spawnId); trans->Append(stmt); stmt = WorldDatabase.GetPreparedStatement(WORLD_DEL_LINKED_RESPAWN); - stmt->setUInt64(0, m_spawnId); + stmt->setUInt64(0, spawnId); stmt->setUInt32(1, LINKED_RESPAWN_GO_TO_GO); trans->Append(stmt); stmt = WorldDatabase.GetPreparedStatement(WORLD_DEL_LINKED_RESPAWN); - stmt->setUInt64(0, m_spawnId); + stmt->setUInt64(0, spawnId); stmt->setUInt32(1, LINKED_RESPAWN_GO_TO_CREATURE); trans->Append(stmt); stmt = WorldDatabase.GetPreparedStatement(WORLD_DEL_LINKED_RESPAWN_MASTER); - stmt->setUInt64(0, m_spawnId); + stmt->setUInt64(0, spawnId); stmt->setUInt32(1, LINKED_RESPAWN_GO_TO_GO); trans->Append(stmt); stmt = WorldDatabase.GetPreparedStatement(WORLD_DEL_LINKED_RESPAWN_MASTER); - stmt->setUInt64(0, m_spawnId); + stmt->setUInt64(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->setUInt64(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 16af03dcfb7..72f466aa327 100644 --- a/src/server/game/Entities/GameObject/GameObject.h +++ b/src/server/game/Entities/GameObject/GameObject.h @@ -131,7 +131,7 @@ class TC_GAME_API GameObject : public WorldObject, public GridObject<GameObject> void SaveToDB(); void SaveToDB(uint32 mapid, std::vector<Difficulty> const& spawnDifficulties); 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 047df2581ae..8a6f6571105 100644 --- a/src/server/game/Entities/Pet/Pet.h +++ b/src/server/game/Entities/Pet/Pet.h @@ -166,9 +166,5 @@ class TC_GAME_API Pet : public Guardian { ABORT(); } - void DeleteFromDB() override // override of Creature::DeleteFromDB - must not be called - { - ABORT(); - } }; #endif diff --git a/src/server/game/Maps/Map.cpp b/src/server/game/Maps/Map.cpp index 8d8a6f2d4bd..dbc3ba69480 100644 --- a/src/server/game/Maps/Map.cpp +++ b/src/server/game/Maps/Map.cpp @@ -3218,9 +3218,9 @@ void Map::DoRespawn(SpawnObjectType type, ObjectGuid::LowType spawnId, uint32 gr } } -void Map::Respawn(RespawnInfo* info, bool force, CharacterDatabaseTransaction dbTrans) +void Map::Respawn(RespawnInfo* info, CharacterDatabaseTransaction dbTrans) { - if (!force && !CheckRespawn(info)) + if (!CheckRespawn(info)) { if (info->respawnTime) SaveRespawnTime(info->type, info->spawnId, info->entry, info->respawnTime, info->zoneId, info->gridId, true, true, dbTrans); @@ -3237,11 +3237,11 @@ void Map::Respawn(RespawnInfo* info, bool force, CharacterDatabaseTransaction db DoRespawn(type, spawnId, gridId); } -void Map::Respawn(std::vector<RespawnInfo*>& respawnData, bool force, CharacterDatabaseTransaction dbTrans) +void Map::Respawn(std::vector<RespawnInfo*>& respawnData, CharacterDatabaseTransaction dbTrans) { CharacterDatabaseTransaction trans = dbTrans ? dbTrans : CharacterDatabase.BeginTransaction(); for (RespawnInfo* info : respawnData) - Respawn(info, force, trans); + Respawn(info, trans); if (!dbTrans) CharacterDatabase.CommitTransaction(trans); } diff --git a/src/server/game/Maps/Map.h b/src/server/game/Maps/Map.h index cf273e36c00..b678a82ff71 100644 --- a/src/server/game/Maps/Map.h +++ b/src/server/game/Maps/Map.h @@ -720,8 +720,8 @@ class TC_GAME_API Map : public GridRefManager<NGridType> // if return value is false and info->respawnTime is nonzero, it is guaranteed to be greater than time(NULL) bool CheckRespawn(RespawnInfo* info); void DoRespawn(SpawnObjectType type, ObjectGuid::LowType spawnId, uint32 gridId); - void Respawn(RespawnInfo* info, bool force = false, CharacterDatabaseTransaction dbTrans = nullptr); - void Respawn(std::vector<RespawnInfo*>& respawnData, bool force = false, CharacterDatabaseTransaction dbTrans = nullptr); + void Respawn(RespawnInfo* info, CharacterDatabaseTransaction dbTrans = nullptr); + void Respawn(std::vector<RespawnInfo*>& respawnData, CharacterDatabaseTransaction dbTrans = nullptr); void AddRespawnInfo(RespawnInfo& info, bool replace = false); void DeleteRespawnInfo(); void DeleteRespawnInfo(RespawnInfo* info); @@ -747,11 +747,6 @@ class TC_GAME_API Map : public GridRefManager<NGridType> public: void GetRespawnInfo(std::vector<RespawnInfo*>& respawnData, SpawnObjectTypeMask types, uint32 zoneId = 0) const; RespawnInfo* GetRespawnInfo(SpawnObjectType type, ObjectGuid::LowType spawnId) const; - void ForceRespawn(SpawnObjectType type, ObjectGuid::LowType spawnId) - { - if (RespawnInfo* info = GetRespawnInfo(type, spawnId)) - Respawn(info, true); - } void RemoveRespawnTime(RespawnInfo* info, bool doRespawn = false, CharacterDatabaseTransaction dbTrans = nullptr); void RemoveRespawnTime(std::vector<RespawnInfo*>& respawnData, bool doRespawn = false, CharacterDatabaseTransaction dbTrans = nullptr); void RemoveRespawnTime(SpawnObjectTypeMask types = SPAWN_TYPEMASK_ALL, uint32 zoneId = 0, bool doRespawn = false, CharacterDatabaseTransaction dbTrans = nullptr) diff --git a/src/server/game/OutdoorPvP/OutdoorPvP.cpp b/src/server/game/OutdoorPvP/OutdoorPvP.cpp index 5fc95c3740f..ccb7311c30f 100644 --- a/src/server/game/OutdoorPvP/OutdoorPvP.cpp +++ b/src/server/game/OutdoorPvP/OutdoorPvP.cpp @@ -165,56 +165,24 @@ bool OPvPCapturePoint::DelCreature(uint32 type) TC_LOG_DEBUG("outdoorpvp", "opvp creature type %u was already deleted", type); return false; } - - auto bounds = m_PvP->GetMap()->GetCreatureBySpawnIdStore().equal_range(spawnId); - for (auto itr = bounds.first; itr != bounds.second;) - { - Creature* c = itr->second; - ++itr; - // Don't save respawn time - c->SetRespawnTime(0); - c->DespawnOrUnsummon(); - c->AddObjectToRemoveList(); - } - TC_LOG_DEBUG("outdoorpvp", "deleting opvp creature type %u", type); - // explicit removal from map - // beats me why this is needed, but with the recent removal "cleanup" some creatures stay in the map if "properly" deleted - // so this is a big fat workaround, if AddObjectToRemoveList and DoDelayedMovesAndRemoves worked correctly, this wouldn't be needed - //if (Map* map = sMapMgr->FindMap(cr->GetMapId())) - // map->Remove(cr, false); - // delete respawn time for this creature - CharacterDatabasePreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_CREATURE_RESPAWN); - stmt->setUInt64(0, spawnId); - stmt->setUInt16(1, m_PvP->GetMap()->GetId()); - stmt->setUInt32(2, 0); // instance id, always 0 for world maps - CharacterDatabase.Execute(stmt); - - sObjectMgr->DeleteCreatureData(spawnId); m_CreatureTypes[m_Creatures[type]] = 0; m_Creatures[type] = 0; - return true; + + return Creature::DeleteFromDB(spawnId); } bool OPvPCapturePoint::DelObject(uint32 type) { - if (!m_Objects[type]) + uint32 spawnId = m_Objects[type]; + if (!spawnId) return false; - ObjectGuid::LowType spawnId = m_Objects[type]; - auto bounds = m_PvP->GetMap()->GetGameObjectBySpawnIdStore().equal_range(spawnId); - for (auto itr = bounds.first; itr != bounds.second;) - { - GameObject* go = itr->second; - ++itr; - // Don't save respawn time - go->SetRespawnTime(0); - go->Delete(); - } sObjectMgr->DeleteGameObjectData(spawnId); m_ObjectTypes[m_Objects[type]] = 0; m_Objects[type] = 0; - return true; + + return GameObject::DeleteFromDB(spawnId); } bool OPvPCapturePoint::DelCapturePoint() diff --git a/src/server/scripts/Commands/cs_gobject.cpp b/src/server/scripts/Commands/cs_gobject.cpp index 324d6ede64c..0647eb8e3c9 100644 --- a/src/server/scripts/Commands/cs_gobject.cpp +++ b/src/server/scripts/Commands/cs_gobject.cpp @@ -49,6 +49,7 @@ EndScriptData */ bool HandleNpcSpawnGroup(ChatHandler* handler, char const* args); bool HandleNpcDespawnGroup(ChatHandler* handler, char const* args); +using namespace Trinity::ChatCommands; class gobject_commandscript : public CommandScript { public: @@ -340,49 +341,36 @@ public: } //delete object by selection or guid - static bool HandleGameObjectDeleteCommand(ChatHandler* handler, char const* args) + static bool HandleGameObjectDeleteCommand(ChatHandler* handler, Variant<Hyperlink<gameobject>, ObjectGuid::LowType> spawnId) { - // number or [name] Shift-click form |color|Hgameobject:go_guid|h[name]|h|r - char* id = handler->extractKeyFromLink((char*)args, "Hgameobject"); - if (!id) - return false; - - ObjectGuid::LowType guidLow = atoull(id); - if (!guidLow) - return false; - - Player const* const player = handler->GetSession()->GetPlayer(); - // force respawn to make sure we find something - player->GetMap()->ForceRespawn(SPAWN_TYPE_GAMEOBJECT, guidLow); - GameObject* object = handler->GetObjectFromPlayerMapByDbGuid(guidLow); - if (!object) + if (GameObject* object = handler->GetObjectFromPlayerMapByDbGuid(spawnId)) { - handler->PSendSysMessage(LANG_COMMAND_OBJNOTFOUND, std::to_string(guidLow).c_str()); - handler->SetSentErrorMessage(true); - return false; - } - - ObjectGuid ownerGuid = object->GetOwnerGUID(); - if (!ownerGuid.IsEmpty()) - { - Unit* owner = ObjectAccessor::GetUnit(*player, ownerGuid); - if (!owner || !ownerGuid.IsPlayer()) + Player const* const player = handler->GetSession()->GetPlayer(); + ObjectGuid ownerGuid = object->GetOwnerGUID(); + if (!ownerGuid.IsEmpty()) { - handler->PSendSysMessage(LANG_COMMAND_DELOBJREFERCREATURE, ownerGuid.ToString().c_str(), object->GetGUID().ToString().c_str()); - handler->SetSentErrorMessage(true); - return false; + Unit* owner = ObjectAccessor::GetUnit(*player, ownerGuid); + if (!owner || !ownerGuid.IsPlayer()) + { + handler->PSendSysMessage(LANG_COMMAND_DELOBJREFERCREATURE, ownerGuid.GetCounter(), spawnId); + handler->SetSentErrorMessage(true); + return false; + } + owner->RemoveGameObject(object, false); } - - owner->RemoveGameObject(object, false); } - object->SetRespawnTime(0); // not save respawn time - object->Delete(); - object->DeleteFromDB(); - - handler->PSendSysMessage(LANG_COMMAND_DELOBJMESSAGE, std::to_string(guidLow).c_str()); - - return true; + if (GameObject::DeleteFromDB(spawnId)) + { + handler->PSendSysMessage(LANG_COMMAND_DELOBJMESSAGE, std::to_string(spawnId)); + return true; + } + else + { + handler->PSendSysMessage(LANG_COMMAND_OBJNOTFOUND, std::to_string(spawnId)); + handler->SetSentErrorMessage(true); + return false; + } } //turn selected object diff --git a/src/server/scripts/Commands/cs_misc.cpp b/src/server/scripts/Commands/cs_misc.cpp index b487a319a22..793b4f02838 100644 --- a/src/server/scripts/Commands/cs_misc.cpp +++ b/src/server/scripts/Commands/cs_misc.cpp @@ -1983,7 +1983,7 @@ public: uint32 const gridId = Trinity::ComputeGridCoord(player->GetPositionX(), player->GetPositionY()).GetId(); for (RespawnInfo* info : data) if (info->gridId == gridId) - player->GetMap()->ForceRespawn(info->type, info->spawnId); + player->GetMap()->RemoveRespawnTime(info, true); } return true; diff --git a/src/server/scripts/Commands/cs_npc.cpp b/src/server/scripts/Commands/cs_npc.cpp index 64330b8aa64..6530652fe71 100644 --- a/src/server/scripts/Commands/cs_npc.cpp +++ b/src/server/scripts/Commands/cs_npc.cpp @@ -128,6 +128,7 @@ bool HandleNpcDespawnGroup(ChatHandler* handler, char const* args) return true; } +using namespace Trinity::ChatCommands; class npc_commandscript : public CommandScript { public: @@ -429,48 +430,40 @@ public: return true; } - static bool HandleNpcDeleteCommand(ChatHandler* handler, char const* args) + static bool HandleNpcDeleteCommand(ChatHandler* handler, Optional<Variant<Hyperlink<creature>, ObjectGuid::LowType>> spawnIdArg) { - Creature* creature = nullptr; - - if (*args) + ObjectGuid::LowType spawnId; + if (spawnIdArg) + spawnId = *spawnIdArg; + else { - // number or [name] Shift-click form |color|Hcreature:creature_guid|h[name]|h|r - char* cId = handler->extractKeyFromLink((char*)args, "Hcreature"); - if (!cId) - return false; - - ObjectGuid::LowType lowguid = atoull(cId); - if (!lowguid) + Creature* creature = handler->getSelectedCreature(); + if (!creature || creature->IsPet() || creature->IsTotem()) + { + handler->SendSysMessage(LANG_SELECT_CREATURE); + handler->SetSentErrorMessage(true); return false; - // force respawn to make sure we find something - handler->GetSession()->GetPlayer()->GetMap()->ForceRespawn(SPAWN_TYPE_CREATURE, lowguid); - // then try to find it - creature = handler->GetCreatureFromPlayerMapByDbGuid(lowguid); + } + if (TempSummon* summon = creature->ToTempSummon()) + { + summon->UnSummon(); + handler->SendSysMessage(LANG_COMMAND_DELCREATMESSAGE); + return true; + } + spawnId = creature->GetSpawnId(); } - else - creature = handler->getSelectedCreature(); - if (!creature || creature->IsPet() || creature->IsTotem()) + if (Creature::DeleteFromDB(spawnId)) { - handler->SendSysMessage(LANG_SELECT_CREATURE); - handler->SetSentErrorMessage(true); - return false; + handler->SendSysMessage(LANG_COMMAND_DELCREATMESSAGE); + return true; } - - if (TempSummon* summon = creature->ToTempSummon()) - summon->UnSummon(); else { - // Delete the creature - creature->CombatStop(); - creature->DeleteFromDB(); - creature->AddObjectToRemoveList(); + handler->PSendSysMessage(LANG_COMMAND_CREATGUIDNOTFOUND, std::to_string(spawnId)); + handler->SetSentErrorMessage(true); + return false; } - - handler->SendSysMessage(LANG_COMMAND_DELCREATMESSAGE); - - return true; } //del item from vendor list diff --git a/src/server/scripts/Commands/cs_wp.cpp b/src/server/scripts/Commands/cs_wp.cpp index ad3ccf37669..949061302e6 100644 --- a/src/server/scripts/Commands/cs_wp.cpp +++ b/src/server/scripts/Commands/cs_wp.cpp @@ -637,21 +637,27 @@ public: { handler->PSendSysMessage("|cff00ff00DEBUG: wp modify del, PathID: |r|cff00ffff%u|r", pathid); - target->DeleteFromDB(); - target->AddObjectToRemoveList(); - - stmt = WorldDatabase.GetPreparedStatement(WORLD_DEL_WAYPOINT_DATA); - stmt->setUInt32(0, pathid); - stmt->setUInt32(1, point); - WorldDatabase.Execute(stmt); + if (Creature::DeleteFromDB(target->GetSpawnId())) + { + stmt = WorldDatabase.GetPreparedStatement(WORLD_DEL_WAYPOINT_DATA); + stmt->setUInt32(0, pathid); + stmt->setUInt32(1, point); + WorldDatabase.Execute(stmt); - stmt = WorldDatabase.GetPreparedStatement(WORLD_UPD_WAYPOINT_DATA_POINT); - stmt->setUInt32(0, pathid); - stmt->setUInt32(1, point); - WorldDatabase.Execute(stmt); + stmt = WorldDatabase.GetPreparedStatement(WORLD_UPD_WAYPOINT_DATA_POINT); + stmt->setUInt32(0, pathid); + stmt->setUInt32(1, point); + WorldDatabase.Execute(stmt); - handler->PSendSysMessage(LANG_WAYPOINT_REMOVED); - return true; + handler->SendSysMessage(LANG_WAYPOINT_REMOVED); + return true; + } + else + { + handler->SendSysMessage(LANG_WAYPOINT_NOTREMOVED); + handler->SetSentErrorMessage(true); + return false; + } } // del if (show == "move") @@ -663,8 +669,12 @@ public: // What to do: // Move the visual spawnpoint // Respawn the owner of the waypoints - target->DeleteFromDB(); - target->AddObjectToRemoveList(); + if (!Creature::DeleteFromDB(target->GetSpawnId())) + { + handler->PSendSysMessage(LANG_WAYPOINT_VP_NOTCREATED, VISUAL_WAYPOINT); + handler->SetSentErrorMessage(true); + return false; + } // re-create Creature* wpCreature = Creature::CreateCreature(VISUAL_WAYPOINT, map, chr->GetPosition()); @@ -842,22 +852,10 @@ public: { Field* fields = result2->Fetch(); ObjectGuid::LowType wpguid = fields[0].GetUInt64(); - Creature* creature = handler->GetCreatureFromPlayerMapByDbGuid(wpguid); - - if (!creature) + if (!Creature::DeleteFromDB(wpguid)) { handler->PSendSysMessage(LANG_WAYPOINT_NOTREMOVED, std::to_string(wpguid).c_str()); hasError = true; - - stmt = WorldDatabase.GetPreparedStatement(WORLD_DEL_CREATURE); - stmt->setUInt64(0, wpguid); - WorldDatabase.Execute(stmt); - } - else - { - creature->CombatStop(); - creature->DeleteFromDB(); - creature->AddObjectToRemoveList(); } } @@ -1061,21 +1059,10 @@ public: Field* fields = result->Fetch(); ObjectGuid::LowType lowguid = fields[0].GetUInt64(); - Creature* creature = handler->GetCreatureFromPlayerMapByDbGuid(lowguid); - if (!creature) + if (!Creature::DeleteFromDB(lowguid)) { handler->PSendSysMessage(LANG_WAYPOINT_NOTREMOVED, std::to_string(lowguid).c_str()); hasError = true; - - stmt = WorldDatabase.GetPreparedStatement(WORLD_DEL_CREATURE); - stmt->setUInt64(0, lowguid); - WorldDatabase.Execute(stmt); - } - else - { - creature->CombatStop(); - creature->DeleteFromDB(); - creature->AddObjectToRemoveList(); } } while (result->NextRow()); |