mirror of
https://github.com/araxiaonline/TrinityCore.git
synced 2026-06-19 22:49:39 -04:00
Dynamic Creature/Go spawning:
- True blizzlike creature spawn/respawn behavior - new creature = new object - Toggleable spawn groups (with C++/SAI/command options to use them) - Custom feature: dynamic spawn rate scaling. Accelerates respawn rate based on players in the zone. - Backward compatibility mode (set via group and for summons) to support creatures/gos that currently don't work well with this (this should be removed once the exceptions are fixed) Fixes and closes #2858 Tags #8661 as fixable. Fixes and closes #13787 Fixes #15222.
This commit is contained in:
@@ -38,6 +38,10 @@ EndScriptData */
|
||||
#include "RBAC.h"
|
||||
#include "WorldSession.h"
|
||||
|
||||
// definitions are over in cs_npc.cpp
|
||||
bool HandleNpcSpawnGroup(ChatHandler* handler, char const* args);
|
||||
bool HandleNpcDespawnGroup(ChatHandler* handler, char const* args);
|
||||
|
||||
class gobject_commandscript : public CommandScript
|
||||
{
|
||||
public:
|
||||
@@ -57,15 +61,17 @@ public:
|
||||
};
|
||||
static std::vector<ChatCommand> gobjectCommandTable =
|
||||
{
|
||||
{ "activate", rbac::RBAC_PERM_COMMAND_GOBJECT_ACTIVATE, false, &HandleGameObjectActivateCommand, "" },
|
||||
{ "delete", rbac::RBAC_PERM_COMMAND_GOBJECT_DELETE, false, &HandleGameObjectDeleteCommand, "" },
|
||||
{ "info", rbac::RBAC_PERM_COMMAND_GOBJECT_INFO, false, &HandleGameObjectInfoCommand, "" },
|
||||
{ "move", rbac::RBAC_PERM_COMMAND_GOBJECT_MOVE, false, &HandleGameObjectMoveCommand, "" },
|
||||
{ "near", rbac::RBAC_PERM_COMMAND_GOBJECT_NEAR, false, &HandleGameObjectNearCommand, "" },
|
||||
{ "target", rbac::RBAC_PERM_COMMAND_GOBJECT_TARGET, false, &HandleGameObjectTargetCommand, "" },
|
||||
{ "turn", rbac::RBAC_PERM_COMMAND_GOBJECT_TURN, false, &HandleGameObjectTurnCommand, "" },
|
||||
{ "add", rbac::RBAC_PERM_COMMAND_GOBJECT_ADD, false, nullptr, "", gobjectAddCommandTable },
|
||||
{ "set", rbac::RBAC_PERM_COMMAND_GOBJECT_SET, false, nullptr, "", gobjectSetCommandTable },
|
||||
{ "activate", rbac::RBAC_PERM_COMMAND_GOBJECT_ACTIVATE, false, &HandleGameObjectActivateCommand, "" },
|
||||
{ "delete", rbac::RBAC_PERM_COMMAND_GOBJECT_DELETE, false, &HandleGameObjectDeleteCommand, "" },
|
||||
{ "info", rbac::RBAC_PERM_COMMAND_GOBJECT_INFO, false, &HandleGameObjectInfoCommand, "" },
|
||||
{ "move", rbac::RBAC_PERM_COMMAND_GOBJECT_MOVE, false, &HandleGameObjectMoveCommand, "" },
|
||||
{ "near", rbac::RBAC_PERM_COMMAND_GOBJECT_NEAR, false, &HandleGameObjectNearCommand, "" },
|
||||
{ "target", rbac::RBAC_PERM_COMMAND_GOBJECT_TARGET, false, &HandleGameObjectTargetCommand, "" },
|
||||
{ "turn", rbac::RBAC_PERM_COMMAND_GOBJECT_TURN, false, &HandleGameObjectTurnCommand, "" },
|
||||
{ "spawngroup", rbac::RBAC_PERM_COMMAND_GOBJECT_SPAWNGROUP, false, &HandleNpcSpawnGroup, "" },
|
||||
{ "despawngroup", rbac::RBAC_PERM_COMMAND_GOBJECT_DESPAWNGROUP, false, &HandleNpcDespawnGroup,""},
|
||||
{ "add", rbac::RBAC_PERM_COMMAND_GOBJECT_ADD, false, nullptr, "", gobjectAddCommandTable },
|
||||
{ "set", rbac::RBAC_PERM_COMMAND_GOBJECT_SET, false, nullptr, "", gobjectSetCommandTable },
|
||||
};
|
||||
static std::vector<ChatCommand> commandTable =
|
||||
{
|
||||
@@ -169,14 +175,14 @@ public:
|
||||
|
||||
object = new GameObject();
|
||||
// this will generate a new guid if the object is in an instance
|
||||
if (!object->LoadGameObjectFromDB(guidLow, map))
|
||||
if (!object->LoadFromDB(guidLow, map, true))
|
||||
{
|
||||
delete object;
|
||||
return false;
|
||||
}
|
||||
|
||||
/// @todo is it really necessary to add both the real and DB table guid here ?
|
||||
sObjectMgr->AddGameobjectToGrid(guidLow, sObjectMgr->GetGOData(guidLow));
|
||||
sObjectMgr->AddGameobjectToGrid(guidLow, sObjectMgr->GetGameObjectData(guidLow));
|
||||
|
||||
handler->PSendSysMessage(LANG_GAMEOBJECT_ADD, objectId, objectInfo->name.c_str(), guidLow, player->GetPositionX(), player->GetPositionY(), player->GetPositionZ());
|
||||
return true;
|
||||
@@ -430,7 +436,7 @@ public:
|
||||
object->Delete();
|
||||
|
||||
object = new GameObject();
|
||||
if (!object->LoadGameObjectFromDB(guidLow, map))
|
||||
if (!object->LoadFromDB(guidLow, map, true))
|
||||
{
|
||||
delete object;
|
||||
return false;
|
||||
@@ -499,7 +505,7 @@ public:
|
||||
object->Delete();
|
||||
|
||||
object = new GameObject();
|
||||
if (!object->LoadGameObjectFromDB(guidLow, map))
|
||||
if (!object->LoadFromDB(guidLow, map, true))
|
||||
{
|
||||
delete object;
|
||||
return false;
|
||||
@@ -578,7 +584,7 @@ public:
|
||||
if (!gameObjectInfo)
|
||||
continue;
|
||||
|
||||
handler->PSendSysMessage(LANG_GO_LIST_CHAT, guid, entry, guid, gameObjectInfo->name.c_str(), x, y, z, mapId);
|
||||
handler->PSendSysMessage(LANG_GO_LIST_CHAT, guid, entry, guid, gameObjectInfo->name.c_str(), x, y, z, mapId, "", "");
|
||||
|
||||
++count;
|
||||
} while (result->NextRow());
|
||||
@@ -611,7 +617,7 @@ public:
|
||||
if (!cValue)
|
||||
return false;
|
||||
ObjectGuid::LowType guidLow = atoul(cValue);
|
||||
GameObjectData const* data = sObjectMgr->GetGOData(guidLow);
|
||||
GameObjectData const* data = sObjectMgr->GetGameObjectData(guidLow);
|
||||
if (!data)
|
||||
return false;
|
||||
entry = data->id;
|
||||
@@ -623,9 +629,16 @@ public:
|
||||
|
||||
GameObjectTemplate const* gameObjectInfo = sObjectMgr->GetGameObjectTemplate(entry);
|
||||
|
||||
GameObject* thisGO = nullptr;
|
||||
|
||||
if (!gameObjectInfo)
|
||||
return false;
|
||||
|
||||
if (*args && handler->GetSession()->GetPlayer())
|
||||
thisGO = handler->GetSession()->GetPlayer()->FindNearestGameObject(entry, 30);
|
||||
else if (handler->getSelectedObject() && handler->getSelectedObject()->GetTypeId() == TYPEID_GAMEOBJECT)
|
||||
thisGO = handler->getSelectedObject()->ToGameObject();
|
||||
|
||||
type = gameObjectInfo->type;
|
||||
displayId = gameObjectInfo->displayId;
|
||||
name = gameObjectInfo->name;
|
||||
@@ -634,10 +647,32 @@ public:
|
||||
else if (type == GAMEOBJECT_TYPE_FISHINGHOLE)
|
||||
lootId = gameObjectInfo->fishinghole.lootId;
|
||||
|
||||
// If we have a real object, send some info about it
|
||||
if (thisGO)
|
||||
{
|
||||
handler->PSendSysMessage(LANG_SPAWNINFO_GUIDINFO, thisGO->GetGUID().ToString().c_str());
|
||||
handler->PSendSysMessage(LANG_SPAWNINFO_SPAWNID_LOCATION, thisGO->GetSpawnId(), thisGO->GetPositionX(), thisGO->GetPositionY(), thisGO->GetPositionZ());
|
||||
if (Player* player = handler->GetSession()->GetPlayer())
|
||||
{
|
||||
Position playerPos = player->GetPosition();
|
||||
float dist = thisGO->GetExactDist(&playerPos);
|
||||
handler->PSendSysMessage(LANG_SPAWNINFO_DISTANCEFROMPLAYER, dist);
|
||||
}
|
||||
}
|
||||
handler->PSendSysMessage(LANG_GOINFO_ENTRY, entry);
|
||||
handler->PSendSysMessage(LANG_GOINFO_TYPE, type);
|
||||
handler->PSendSysMessage(LANG_GOINFO_LOOTID, lootId);
|
||||
handler->PSendSysMessage(LANG_GOINFO_DISPLAYID, displayId);
|
||||
if (WorldObject* object = handler->getSelectedObject())
|
||||
{
|
||||
if (object->ToGameObject() && object->ToGameObject()->GetGameObjectData() && object->ToGameObject()->GetGameObjectData()->spawnGroupData->groupId)
|
||||
{
|
||||
SpawnGroupTemplateData const* groupData = object->ToGameObject()->GetGameObjectData()->spawnGroupData;
|
||||
handler->PSendSysMessage(LANG_SPAWNINFO_GROUP_ID, groupData->name.c_str(), groupData->groupId, groupData->flags, groupData->isActive);
|
||||
}
|
||||
if (object->ToGameObject())
|
||||
handler->PSendSysMessage(LANG_SPAWNINFO_COMPATIBILITY_MODE, object->ToGameObject()->GetRespawnCompatibilityMode());
|
||||
}
|
||||
handler->PSendSysMessage(LANG_GOINFO_NAME, name.c_str());
|
||||
handler->PSendSysMessage(LANG_GOINFO_SIZE, gameObjectInfo->size);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user