Core/Spawns: merged Dynamic Spawning
This commit is contained in:
1 parent
21795a5ae5
commit
b976bc1187
87 files changed
+3200
-1007
No files matched your search
@@ -181,6 +181,86 @@ EnumName<CreatureFlagsExtra> const flagsExtra[] =
|
||||
|
||||
uint32 const FLAGS_EXTRA_COUNT = std::extent<decltype(flagsExtra)>::value;
|
||||
|
||||
bool HandleNpcSpawnGroup(ChatHandler* handler, char const* args)
|
||||
{
|
||||
if (!*args)
|
||||
return false;
|
||||
|
||||
bool ignoreRespawn = false;
|
||||
bool force = false;
|
||||
uint32 groupId = 0;
|
||||
|
||||
// Decode arguments
|
||||
char* arg = strtok((char*)args, " ");
|
||||
while (arg)
|
||||
{
|
||||
std::string thisArg = arg;
|
||||
std::transform(thisArg.begin(), thisArg.end(), thisArg.begin(), ::tolower);
|
||||
if (thisArg == "ignorerespawn")
|
||||
ignoreRespawn = true;
|
||||
else if (thisArg == "force")
|
||||
force = true;
|
||||
else if (thisArg.empty() || !(std::count_if(thisArg.begin(), thisArg.end(), ::isdigit) == (int)thisArg.size()))
|
||||
return false;
|
||||
else
|
||||
groupId = atoi(thisArg.c_str());
|
||||
|
||||
arg = strtok(NULL, " ");
|
||||
}
|
||||
|
||||
Player* player = handler->GetSession()->GetPlayer();
|
||||
|
||||
std::vector <WorldObject*> creatureList;
|
||||
if (!player->GetMap()->SpawnGroupSpawn(groupId, ignoreRespawn, force, &creatureList))
|
||||
{
|
||||
handler->PSendSysMessage(LANG_SPAWNGROUP_BADGROUP, groupId);
|
||||
handler->SetSentErrorMessage(true);
|
||||
return false;
|
||||
}
|
||||
|
||||
handler->PSendSysMessage(LANG_SPAWNGROUP_SPAWNCOUNT, creatureList.size());
|
||||
for (WorldObject* obj : creatureList)
|
||||
handler->PSendSysMessage("%s (%s)", obj->GetName(), obj->GetGUID().ToString().c_str());
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool HandleNpcDespawnGroup(ChatHandler* handler, char const* args)
|
||||
{
|
||||
if (!*args)
|
||||
return false;
|
||||
|
||||
bool deleteRespawnTimes = false;
|
||||
uint32 groupId = 0;
|
||||
|
||||
// Decode arguments
|
||||
char* arg = strtok((char*)args, " ");
|
||||
while (arg)
|
||||
{
|
||||
std::string thisArg = arg;
|
||||
std::transform(thisArg.begin(), thisArg.end(), thisArg.begin(), ::tolower);
|
||||
if (thisArg == "removerespawntime")
|
||||
deleteRespawnTimes = true;
|
||||
else if (thisArg.empty() || !(std::count_if(thisArg.begin(), thisArg.end(), ::isdigit) == (int)thisArg.size()))
|
||||
return false;
|
||||
else
|
||||
groupId = atoi(thisArg.c_str());
|
||||
|
||||
arg = strtok(nullptr, " ");
|
||||
}
|
||||
|
||||
Player* player = handler->GetSession()->GetPlayer();
|
||||
|
||||
if (!player->GetMap()->SpawnGroupDespawn(groupId, deleteRespawnTimes))
|
||||
{
|
||||
handler->PSendSysMessage(LANG_SPAWNGROUP_BADGROUP, groupId);
|
||||
handler->SetSentErrorMessage(true);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
class npc_commandscript : public CommandScript
|
||||
{
|
||||
public:
|
||||
@@ -225,21 +305,23 @@ public:
|
||||
};
|
||||
static std::vector<ChatCommand> npcCommandTable =
|
||||
{
|
||||
{ "info", rbac::RBAC_PERM_COMMAND_NPC_INFO, false, &HandleNpcInfoCommand, "" },
|
||||
{ "near", rbac::RBAC_PERM_COMMAND_NPC_NEAR, false, &HandleNpcNearCommand, "" },
|
||||
{ "move", rbac::RBAC_PERM_COMMAND_NPC_MOVE, false, &HandleNpcMoveCommand, "" },
|
||||
{ "playemote", rbac::RBAC_PERM_COMMAND_NPC_PLAYEMOTE, false, &HandleNpcPlayEmoteCommand, "" },
|
||||
{ "say", rbac::RBAC_PERM_COMMAND_NPC_SAY, false, &HandleNpcSayCommand, "" },
|
||||
{ "textemote", rbac::RBAC_PERM_COMMAND_NPC_TEXTEMOTE, false, &HandleNpcTextEmoteCommand, "" },
|
||||
{ "whisper", rbac::RBAC_PERM_COMMAND_NPC_WHISPER, false, &HandleNpcWhisperCommand, "" },
|
||||
{ "yell", rbac::RBAC_PERM_COMMAND_NPC_YELL, false, &HandleNpcYellCommand, "" },
|
||||
{ "tame", rbac::RBAC_PERM_COMMAND_NPC_TAME, false, &HandleNpcTameCommand, "" },
|
||||
{ "add", rbac::RBAC_PERM_COMMAND_NPC_ADD, false, nullptr, "", npcAddCommandTable },
|
||||
{ "delete", rbac::RBAC_PERM_COMMAND_NPC_DELETE, false, nullptr, "", npcDeleteCommandTable },
|
||||
{ "follow", rbac::RBAC_PERM_COMMAND_NPC_FOLLOW, false, nullptr, "", npcFollowCommandTable },
|
||||
{ "set", rbac::RBAC_PERM_COMMAND_NPC_SET, false, nullptr, "", npcSetCommandTable },
|
||||
{ "evade", rbac::RBAC_PERM_COMMAND_NPC_EVADE, false, &HandleNpcEvadeCommand, "" },
|
||||
{ "showloot", rbac::RBAC_PERM_COMMAND_NPC_SHOWLOOT, false, &HandleNpcShowLootCommand, "" },
|
||||
{ "info", rbac::RBAC_PERM_COMMAND_NPC_INFO, false, &HandleNpcInfoCommand, "" },
|
||||
{ "near", rbac::RBAC_PERM_COMMAND_NPC_NEAR, false, &HandleNpcNearCommand, "" },
|
||||
{ "move", rbac::RBAC_PERM_COMMAND_NPC_MOVE, false, &HandleNpcMoveCommand, "" },
|
||||
{ "playemote", rbac::RBAC_PERM_COMMAND_NPC_PLAYEMOTE, false, &HandleNpcPlayEmoteCommand, "" },
|
||||
{ "say", rbac::RBAC_PERM_COMMAND_NPC_SAY, false, &HandleNpcSayCommand, "" },
|
||||
{ "textemote", rbac::RBAC_PERM_COMMAND_NPC_TEXTEMOTE, false, &HandleNpcTextEmoteCommand, "" },
|
||||
{ "whisper", rbac::RBAC_PERM_COMMAND_NPC_WHISPER, false, &HandleNpcWhisperCommand, "" },
|
||||
{ "yell", rbac::RBAC_PERM_COMMAND_NPC_YELL, false, &HandleNpcYellCommand, "" },
|
||||
{ "tame", rbac::RBAC_PERM_COMMAND_NPC_TAME, false, &HandleNpcTameCommand, "" },
|
||||
{ "spawngroup", rbac::RBAC_PERM_COMMAND_NPC_SPAWNGROUP, false, &HandleNpcSpawnGroup, "" },
|
||||
{ "despawngroup", rbac::RBAC_PERM_COMMAND_NPC_DESPAWNGROUP, false, &HandleNpcDespawnGroup, "" },
|
||||
{ "add", rbac::RBAC_PERM_COMMAND_NPC_ADD, false, nullptr, "", npcAddCommandTable },
|
||||
{ "delete", rbac::RBAC_PERM_COMMAND_NPC_DELETE, false, nullptr, "", npcDeleteCommandTable },
|
||||
{ "follow", rbac::RBAC_PERM_COMMAND_NPC_FOLLOW, false, nullptr, "", npcFollowCommandTable },
|
||||
{ "set", rbac::RBAC_PERM_COMMAND_NPC_SET, false, nullptr, "", npcSetCommandTable },
|
||||
{ "evade", rbac::RBAC_PERM_COMMAND_NPC_EVADE, false, &HandleNpcEvadeCommand, "" },
|
||||
{ "showloot", rbac::RBAC_PERM_COMMAND_NPC_SHOWLOOT, false, &HandleNpcShowLootCommand, "" },
|
||||
};
|
||||
static std::vector<ChatCommand> commandTable =
|
||||
{
|
||||
@@ -263,22 +345,16 @@ public:
|
||||
return false;
|
||||
|
||||
Player* chr = handler->GetSession()->GetPlayer();
|
||||
float x = chr->GetPositionX();
|
||||
float y = chr->GetPositionY();
|
||||
float z = chr->GetPositionZ();
|
||||
float o = chr->GetOrientation();
|
||||
Map* map = chr->GetMap();
|
||||
|
||||
if (Transport* trans = chr->GetTransport())
|
||||
{
|
||||
ObjectGuid::LowType guid = map->GenerateLowGuid<HighGuid::Unit>();
|
||||
CreatureData& data = sObjectMgr->NewOrExistCreatureData(guid);
|
||||
data.spawnId = guid;
|
||||
data.id = id;
|
||||
data.phaseMask = chr->GetPhaseMask();
|
||||
data.posX = chr->GetTransOffsetX();
|
||||
data.posY = chr->GetTransOffsetY();
|
||||
data.posZ = chr->GetTransOffsetZ();
|
||||
data.orientation = chr->GetTransOffsetO();
|
||||
data.spawnPoint.Relocate(chr->GetTransOffsetX(), chr->GetTransOffsetY(), chr->GetTransOffsetZ(), chr->GetTransOffsetO());
|
||||
|
||||
Creature* creature = trans->CreateNPCPassenger(guid, &data);
|
||||
|
||||
@@ -291,7 +367,7 @@ public:
|
||||
}
|
||||
|
||||
Creature* creature = new Creature();
|
||||
if (!creature->Create(map->GenerateLowGuid<HighGuid::Unit>(), map, chr->GetPhaseMask(), id, x, y, z, o))
|
||||
if (!creature->Create(map->GenerateLowGuid<HighGuid::Unit>(), map, chr->GetPhaseMask(), id, *chr))
|
||||
{
|
||||
delete creature;
|
||||
return false;
|
||||
@@ -307,7 +383,7 @@ public:
|
||||
creature->CleanupsBeforeDelete();
|
||||
delete creature;
|
||||
creature = new Creature();
|
||||
if (!creature->LoadCreatureFromDB(db_guid, map))
|
||||
if (!creature->LoadFromDB(db_guid, map, true, true))
|
||||
{
|
||||
delete creature;
|
||||
return false;
|
||||
@@ -484,7 +560,7 @@ public:
|
||||
|
||||
static bool HandleNpcDeleteCommand(ChatHandler* handler, char const* args)
|
||||
{
|
||||
Creature* unit = nullptr;
|
||||
Creature* creature = nullptr;
|
||||
|
||||
if (*args)
|
||||
{
|
||||
@@ -496,22 +572,30 @@ public:
|
||||
ObjectGuid::LowType lowguid = atoul(cId);
|
||||
if (!lowguid)
|
||||
return false;
|
||||
unit = handler->GetCreatureFromPlayerMapByDbGuid(lowguid);
|
||||
// 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);
|
||||
}
|
||||
else
|
||||
unit = handler->getSelectedCreature();
|
||||
creature = handler->getSelectedCreature();
|
||||
|
||||
if (!unit || unit->IsPet() || unit->IsTotem())
|
||||
if (!creature || creature->IsPet() || creature->IsTotem())
|
||||
{
|
||||
handler->SendSysMessage(LANG_SELECT_CREATURE);
|
||||
handler->SetSentErrorMessage(true);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Delete the creature
|
||||
unit->CombatStop();
|
||||
unit->DeleteFromDB();
|
||||
unit->AddObjectToRemoveList();
|
||||
if (TempSummon* summon = creature->ToTempSummon())
|
||||
summon->UnSummon();
|
||||
else
|
||||
{
|
||||
// Delete the creature
|
||||
creature->CombatStop();
|
||||
creature->DeleteFromDB();
|
||||
creature->AddObjectToRemoveList();
|
||||
}
|
||||
|
||||
handler->SendSysMessage(LANG_COMMAND_DELCREATMESSAGE);
|
||||
|
||||
@@ -701,15 +785,22 @@ public:
|
||||
uint32 mechanicImmuneMask = cInfo->MechanicImmuneMask;
|
||||
uint32 displayid = target->GetDisplayId();
|
||||
uint32 nativeid = target->GetNativeDisplayId();
|
||||
uint32 Entry = target->GetEntry();
|
||||
uint32 entry = target->GetEntry();
|
||||
|
||||
int64 curRespawnDelay = target->GetRespawnCompatibilityMode() ? target->GetRespawnTimeEx() - time(nullptr) : target->GetMap()->GetCreatureRespawnTime(target->GetSpawnId()) - time(nullptr);
|
||||
|
||||
int64 curRespawnDelay = target->GetRespawnTimeEx()-time(nullptr);
|
||||
if (curRespawnDelay < 0)
|
||||
curRespawnDelay = 0;
|
||||
std::string curRespawnDelayStr = secsToTimeString(uint64(curRespawnDelay), true);
|
||||
std::string defRespawnDelayStr = secsToTimeString(target->GetRespawnDelay(), true);
|
||||
|
||||
handler->PSendSysMessage(LANG_NPCINFO_CHAR, target->GetSpawnId(), target->GetGUID().GetCounter(), faction, npcflags, Entry, displayid, nativeid);
|
||||
handler->PSendSysMessage(LANG_NPCINFO_CHAR, target->GetName().c_str(), target->GetSpawnId(), target->GetGUID().GetCounter(), entry, faction, npcflags, displayid, nativeid);
|
||||
if (target->GetCreatureData() && target->GetCreatureData()->spawnGroupData->groupId)
|
||||
{
|
||||
SpawnGroupTemplateData const* const groupData = target->GetCreatureData()->spawnGroupData;
|
||||
handler->PSendSysMessage(LANG_SPAWNINFO_GROUP_ID, groupData->name.c_str(), groupData->groupId, groupData->flags, target->GetMap()->IsSpawnGroupActive(groupData->groupId));
|
||||
}
|
||||
handler->PSendSysMessage(LANG_SPAWNINFO_COMPATIBILITY_MODE, target->GetRespawnCompatibilityMode());
|
||||
handler->PSendSysMessage(LANG_NPCINFO_LEVEL, target->getLevel());
|
||||
handler->PSendSysMessage(LANG_NPCINFO_EQUIPMENT, target->GetCurrentEquipmentId(), target->GetOriginalEquipmentId());
|
||||
handler->PSendSysMessage(LANG_NPCINFO_HEALTH, target->GetCreateHealth(), target->GetMaxHealth(), target->GetHealth());
|
||||
@@ -785,7 +876,7 @@ public:
|
||||
if (!creatureTemplate)
|
||||
continue;
|
||||
|
||||
handler->PSendSysMessage(LANG_CREATURE_LIST_CHAT, guid, guid, creatureTemplate->Name.c_str(), x, y, z, mapId);
|
||||
handler->PSendSysMessage(LANG_CREATURE_LIST_CHAT, guid, guid, creatureTemplate->Name.c_str(), x, y, z, mapId, "", "");
|
||||
|
||||
++count;
|
||||
}
|
||||
@@ -803,8 +894,13 @@ public:
|
||||
ObjectGuid::LowType lowguid = 0;
|
||||
|
||||
Creature* creature = handler->getSelectedCreature();
|
||||
Player const* player = handler->GetSession()->GetPlayer();
|
||||
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");
|
||||
@@ -812,63 +908,46 @@ 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;
|
||||
}
|
||||
|
||||
uint32 map_id = data->mapid;
|
||||
|
||||
if (handler->GetSession()->GetPlayer()->GetMapId() != map_id)
|
||||
{
|
||||
handler->PSendSysMessage(LANG_COMMAND_CREATUREATSAMEMAP, lowguid);
|
||||
handler->SetSentErrorMessage(true);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
|
||||
// Attempting creature load from DB data
|
||||
CreatureData const* data = sObjectMgr->GetCreatureData(lowguid);
|
||||
if (!data)
|
||||
{
|
||||
lowguid = creature->GetSpawnId();
|
||||
handler->PSendSysMessage(LANG_COMMAND_CREATGUIDNOTFOUND, lowguid);
|
||||
handler->SetSentErrorMessage(true);
|
||||
return false;
|
||||
}
|
||||
|
||||
float x = handler->GetSession()->GetPlayer()->GetPositionX();
|
||||
float y = handler->GetSession()->GetPlayer()->GetPositionY();
|
||||
float z = handler->GetSession()->GetPlayer()->GetPositionZ();
|
||||
float o = handler->GetSession()->GetPlayer()->GetOrientation();
|
||||
|
||||
if (creature)
|
||||
if (player->GetMapId() != data->spawnPoint.GetMapId())
|
||||
{
|
||||
if (CreatureData const* data = sObjectMgr->GetCreatureData(creature->GetSpawnId()))
|
||||
{
|
||||
const_cast<CreatureData*>(data)->posX = x;
|
||||
const_cast<CreatureData*>(data)->posY = y;
|
||||
const_cast<CreatureData*>(data)->posZ = z;
|
||||
const_cast<CreatureData*>(data)->orientation = o;
|
||||
}
|
||||
creature->SetPosition(x, y, z, o);
|
||||
creature->GetMotionMaster()->Initialize();
|
||||
if (creature->IsAlive()) // dead creature will reset movement generator at respawn
|
||||
{
|
||||
creature->setDeathState(JUST_DIED);
|
||||
creature->Respawn();
|
||||
}
|
||||
handler->PSendSysMessage(LANG_COMMAND_CREATUREATSAMEMAP, lowguid);
|
||||
handler->SetSentErrorMessage(true);
|
||||
return false;
|
||||
}
|
||||
|
||||
// update position in memory
|
||||
const_cast<CreatureData*>(data)->spawnPoint.Relocate(*player);
|
||||
|
||||
PreparedStatement* stmt = WorldDatabase.GetPreparedStatement(WORLD_UPD_CREATURE_POSITION);
|
||||
|
||||
stmt->setFloat(0, x);
|
||||
stmt->setFloat(1, y);
|
||||
stmt->setFloat(2, z);
|
||||
stmt->setFloat(3, o);
|
||||
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;
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user