Scripts/Commands: Fix some quirkiness and potential crashes with live DB modification commands (npc move and npc delete), which are horrible and should be deleted anyway.

Fixes #20104.
This commit is contained in:
Treeston
2017-08-02 22:05:40 +02:00
parent c70b328eda
commit 759357049c
2 changed files with 39 additions and 31 deletions

View File

@@ -1612,9 +1612,13 @@ void Creature::DeleteFromDB()
return;
}
// remove any scheduled respawns
GetMap()->RemoveRespawnTime(SPAWN_TYPE_CREATURE, m_spawnId);
// delete data from memory
sObjectMgr->DeleteCreatureData(m_spawnId);
// delete data and all its associations from DB
SQLTransaction trans = WorldDatabase.BeginTransaction();
PreparedStatement* stmt = WorldDatabase.GetPreparedStatement(WORLD_DEL_CREATURE);
@@ -1639,6 +1643,11 @@ void Creature::DeleteFromDB()
trans->Append(stmt);
WorldDatabase.CommitTransaction(trans);
// then delete any active instances of the creature
auto const& range = GetMap()->GetCreatureBySpawnIdStore().equal_range(m_spawnId);
for (auto it = range.first; it != range.second; ++it)
it->second->AddObjectToRemoveList();
}
bool Creature::IsInvisibleDueToDespawn() const

View File

@@ -876,7 +876,9 @@ public:
if (!player)
return false;
if (!creature)
if (creature)
lowguid = creature->GetSpawnId();
else
{
// number or [name] Shift-click form |color|Hcreature:creature_guid|h[name]|h|r
char* cId = handler->extractKeyFromLink((char*)args, "Hcreature");
@@ -884,48 +886,45 @@ public:
return false;
lowguid = atoul(cId);
// Attempting creature load from DB data
CreatureData const* data = sObjectMgr->GetCreatureData(lowguid);
if (!data)
{
handler->PSendSysMessage(LANG_COMMAND_CREATGUIDNOTFOUND, lowguid);
handler->SetSentErrorMessage(true);
return false;
}
if (player->GetMapId() != data->spawnPoint.GetMapId())
{
handler->PSendSysMessage(LANG_COMMAND_CREATUREATSAMEMAP, lowguid);
handler->SetSentErrorMessage(true);
return false;
}
}
else
lowguid = creature->GetSpawnId();
if (creature)
// Attempting creature load from DB data
CreatureData const* data = sObjectMgr->GetCreatureData(lowguid);
if (!data)
{
sObjectMgr->NewOrExistCreatureData(creature->GetSpawnId()).spawnPoint.Relocate(*player);
creature->UpdatePosition(*player);
creature->GetMotionMaster()->Initialize();
if (creature->IsAlive()) // dead creature will reset movement generator at respawn
{
creature->setDeathState(JUST_DIED);
creature->Respawn();
}
handler->PSendSysMessage(LANG_COMMAND_CREATGUIDNOTFOUND, lowguid);
handler->SetSentErrorMessage(true);
return false;
}
PreparedStatement* stmt = WorldDatabase.GetPreparedStatement(WORLD_UPD_CREATURE_POSITION);
if (player->GetMapId() != data->spawnPoint.GetMapId())
{
handler->PSendSysMessage(LANG_COMMAND_CREATUREATSAMEMAP, lowguid);
handler->SetSentErrorMessage(true);
return false;
}
// update position in memory
const_cast<CreatureData*>(data)->spawnPoint.Relocate(*player);
// update position in DB
PreparedStatement* stmt = WorldDatabase.GetPreparedStatement(WORLD_UPD_CREATURE_POSITION);
stmt->setFloat(0, player->GetPositionX());
stmt->setFloat(1, player->GetPositionY());
stmt->setFloat(2, player->GetPositionZ());
stmt->setFloat(3, player->GetOrientation());
stmt->setUInt32(4, lowguid);
WorldDatabase.Execute(stmt);
// respawn selected creature at the new location
if (creature)
{
if (creature->IsAlive())
creature->setDeathState(JUST_DIED);
creature->Respawn(true);
if (!creature->GetRespawnCompatibilityMode())
creature->AddObjectToRemoveList();
}
handler->PSendSysMessage(LANG_COMMAND_CREATUREMOVED);
return true;
}