Core/Spawns: merged Dynamic Spawning

This commit is contained in:
Ovahlord committed 2018-07-21 20:44:41 +02:00
1 parent 21795a5ae5
commit b976bc1187
87 files changed
+3200 -1007

No files matched your search

+162 -83
View File
@@ -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;
}