aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/server/game/Entities/Creature/Creature.cpp26
-rw-r--r--src/server/game/Grids/ObjectGridLoader.cpp8
-rw-r--r--src/server/game/Instances/InstanceScript.cpp2
-rw-r--r--src/server/game/Maps/Map.cpp32
-rw-r--r--src/server/game/Maps/Map.h15
-rw-r--r--src/server/game/Scripting/ScriptMgr.cpp30
-rw-r--r--src/server/game/Scripting/ScriptMgr.h4
7 files changed, 44 insertions, 73 deletions
diff --git a/src/server/game/Entities/Creature/Creature.cpp b/src/server/game/Entities/Creature/Creature.cpp
index c142fcf91f4..60bac60f45d 100644
--- a/src/server/game/Entities/Creature/Creature.cpp
+++ b/src/server/game/Entities/Creature/Creature.cpp
@@ -644,12 +644,16 @@ void Creature::Update(uint32 diff)
break;
case DEAD:
{
+ if (!m_respawnCompatibilityMode)
+ {
+ TC_LOG_ERROR("entities.unit", "Creature (GUID: %u Entry: %u) in wrong state: DEAD (3)", GetGUID().GetCounter(), GetEntry());
+ break;
+ }
time_t now = GameTime::GetGameTime();
if (m_respawnTime <= now)
{
-
- // First check if there are any scripts that object to us respawning
- if (!sScriptMgr->CanSpawn(GetSpawnId(), GetEntry(), GetCreatureData(), GetMap()))
+ // Delay respawn if spawn group is not active
+ if (m_creatureData && !GetMap()->IsSpawnGroupActive(m_creatureData->spawnGroupData->groupId))
{
m_respawnTime = now + urand(4,7);
break; // Will be rechecked on next Update call after delay expires
@@ -1608,7 +1612,7 @@ bool Creature::LoadFromDB(ObjectGuid::LowType spawnId, Map* map, bool addToMap,
if (!data)
{
- TC_LOG_ERROR("sql.sql", "Creature (GUID: %u) not found in table `creature`, can't load. ", spawnId);
+ TC_LOG_ERROR("sql.sql", "Creature (SpawnID %u) not found in table `creature`, can't load. ", spawnId);
return false;
}
@@ -1619,13 +1623,6 @@ bool Creature::LoadFromDB(ObjectGuid::LowType spawnId, Map* map, bool addToMap,
m_respawnradius = data->spawndist;
m_respawnDelay = data->spawntimesecs;
- // Is the creature script objecting to us spawning? If yes, delay by a little bit (then re-check in ::Update)
- if (!m_respawnCompatibilityMode && !m_respawnTime && !sScriptMgr->CanSpawn(spawnId, data->id, data, map))
- {
- SaveRespawnTime(urand(4,7));
- return false;
- }
-
if (!Create(map->GenerateLowGuid<HighGuid::Unit>(), map, data->phaseMask, data->id, data->spawnPoint, data, 0U , !m_respawnCompatibilityMode))
return false;
@@ -1637,8 +1634,11 @@ bool Creature::LoadFromDB(ObjectGuid::LowType spawnId, Map* map, bool addToMap,
m_respawnTime = GetMap()->GetCreatureRespawnTime(m_spawnId);
// Is the creature script objecting to us spawning? If yes, delay by a little bit (then re-check in ::Update)
- if (m_respawnCompatibilityMode && !m_respawnTime && !sScriptMgr->CanSpawn(spawnId, GetEntry(), GetCreatureData(), map))
- m_respawnTime = GameTime::GetGameTime() + urand(4,7);
+ if (!m_respawnTime && !map->IsSpawnGroupActive(data->spawnGroupData->groupId))
+ {
+ ASSERT(m_respawnCompatibilityMode, "Creature (SpawnID %u) trying to load in inactive spawn group %s.", spawnId, data->spawnGroupData->name.c_str());
+ m_respawnTime = GameTime::GetGameTime() + urand(4, 7);
+ }
if (m_respawnTime) // respawn on Update
{
diff --git a/src/server/game/Grids/ObjectGridLoader.cpp b/src/server/game/Grids/ObjectGridLoader.cpp
index ffa619e613e..4dfd7f679b1 100644
--- a/src/server/game/Grids/ObjectGridLoader.cpp
+++ b/src/server/game/Grids/ObjectGridLoader.cpp
@@ -140,14 +140,6 @@ void LoadHelper(CellGuidSet const& guid_set, CellCoord &cell, GridRefManager<T>
delete obj;
continue;
}
-
- // If script is blocking spawn, don't spawn but queue for a re-check in a little bit
- if (!(group->flags & SPAWNGROUP_FLAG_COMPATIBILITY_MODE) && !sScriptMgr->CanSpawn(guid, cdata->id, cdata, map))
- {
- map->SaveRespawnTime(SPAWN_TYPE_CREATURE, guid, cdata->id, GameTime::GetGameTime() + urand(4,7), map->GetZoneId(cdata->spawnPoint), Trinity::ComputeGridCoord(cdata->spawnPoint.GetPositionX(), cdata->spawnPoint.GetPositionY()).GetId(), false);
- delete obj;
- continue;
- }
}
else if (obj->GetTypeId() == TYPEID_GAMEOBJECT)
{
diff --git a/src/server/game/Instances/InstanceScript.cpp b/src/server/game/Instances/InstanceScript.cpp
index 540ea2b3c33..71fd330f0cf 100644
--- a/src/server/game/Instances/InstanceScript.cpp
+++ b/src/server/game/Instances/InstanceScript.cpp
@@ -265,7 +265,7 @@ void InstanceScript::UpdateSpawnGroups()
if (doSpawn)
instance->SpawnGroupSpawn(groupId);
else // otherwise, set it as inactive so it no longer respawns (but don't despawn it)
- instance->SetSpawnGroupActive(groupId, false);
+ instance->SetSpawnGroupInactive(groupId);
}
}
diff --git a/src/server/game/Maps/Map.cpp b/src/server/game/Maps/Map.cpp
index 8a55e13da77..84335b3fab4 100644
--- a/src/server/game/Maps/Map.cpp
+++ b/src/server/game/Maps/Map.cpp
@@ -2924,10 +2924,24 @@ void Map::SendObjectUpdates()
}
}
+// CheckRespawn MUST do one of the following:
+// -) return true
+// -) set info->respawnTime to zero, which indicates the respawn time should be deleted (and will never be processed again without outside intervention)
+// -) set info->respawnTime to a new respawn time, which must be strictly GREATER than the current time (GameTime::GetGameTime())
bool Map::CheckRespawn(RespawnInfo* info)
{
+ SpawnData const* data = sObjectMgr->GetSpawnData(info->type, info->spawnId);
+ ASSERT(data, "Invalid respawn info with type %u, spawnID %u in respawn queue.", info->type, info->spawnId);
+
+ // First, check if this creature's spawn group is inactive
+ if (!IsSpawnGroupActive(data->spawnGroupData->groupId))
+ {
+ info->respawnTime = 0;
+ return false;
+ }
+
uint32 poolId = info->spawnId ? sPoolMgr->IsPartOfAPool(info->type, info->spawnId) : 0;
- // First, check if there's already an instance of this object that would block the respawn
+ // Next, check if there's already an instance of this object that would block the respawn
// Only do this for unpooled spawns
if (!poolId)
{
@@ -2937,11 +2951,7 @@ bool Map::CheckRespawn(RespawnInfo* info)
case SPAWN_TYPE_CREATURE:
{
// escort check for creatures only (if the world config boolean is set)
- bool isEscort = false;
- if (sWorld->getBoolConfig(CONFIG_RESPAWN_DYNAMIC_ESCORTNPC) && info->type == SPAWN_TYPE_CREATURE)
- if (CreatureData const* cdata = sObjectMgr->GetCreatureData(info->spawnId))
- if (cdata->spawnGroupData->flags & SPAWNGROUP_FLAG_ESCORTQUESTNPC)
- isEscort = true;
+ bool const isEscort = (sWorld->getBoolConfig(CONFIG_RESPAWN_DYNAMIC_ESCORTNPC) && data->spawnGroupData->flags & SPAWNGROUP_FLAG_ESCORTQUESTNPC);
auto range = _creatureBySpawnIdStore.equal_range(info->spawnId);
for (auto it = range.first; it != range.second; ++it)
@@ -3003,15 +3013,7 @@ bool Map::CheckRespawn(RespawnInfo* info)
return false;
}
- // if we're a creature, see if the script objects to us spawning
- if (info->type == SPAWN_TYPE_CREATURE)
- {
- if (!sScriptMgr->CanSpawn(info->spawnId, info->entry, sObjectMgr->GetCreatureData(info->spawnId), this))
- { // if a script blocks our respawn, schedule next check in a little bit
- info->respawnTime = GameTime::GetGameTime() + urand(4, 7);
- return false;
- }
- }
+ // everything ok, let's spawn
return true;
}
diff --git a/src/server/game/Maps/Map.h b/src/server/game/Maps/Map.h
index 9c1f4748b06..4dada8f802e 100644
--- a/src/server/game/Maps/Map.h
+++ b/src/server/game/Maps/Map.h
@@ -838,10 +838,19 @@ class TC_GAME_API Map : public GridRefManager<NGridType>
}
SpawnGroupTemplateData const* GetSpawnGroupData(uint32 groupId) const;
+
+ bool IsSpawnGroupActive(uint32 groupId) const;
+
+ // Enable the spawn group, which causes all creatures in it to respawn (unless they have a respawn timer)
+ // The force flag can be used to force spawning additional copies even if old copies are still around from a previous spawn
bool SpawnGroupSpawn(uint32 groupId, bool ignoreRespawn = false, bool force = false, std::vector<WorldObject*>* spawnedObjects = nullptr);
+
+ // Despawn all creatures in the spawn group if spawned, optionally delete their respawn timer, and disable the group
bool SpawnGroupDespawn(uint32 groupId, bool deleteRespawnTimes = false, size_t* count = nullptr);
- void SetSpawnGroupActive(uint32 groupId, bool state);
- bool IsSpawnGroupActive(uint32 groupId) const;
+
+ // Disable the spawn group, which prevents any creatures in the group from respawning until re-enabled
+ // This will not affect any already-present creatures in the group
+ void SetSpawnGroupInactive(uint32 groupId) { SetSpawnGroupActive(groupId, false); }
private:
// Type specific code for add/remove to/from grid
@@ -877,6 +886,8 @@ class TC_GAME_API Map : public GridRefManager<NGridType>
RespawnInfoMap _gameObjectRespawnTimesBySpawnId;
RespawnInfoMap& GetRespawnMapForType(SpawnObjectType type) { return (type == SPAWN_TYPE_GAMEOBJECT) ? _gameObjectRespawnTimesBySpawnId : _creatureRespawnTimesBySpawnId; }
RespawnInfoMap const& GetRespawnMapForType(SpawnObjectType type) const { return (type == SPAWN_TYPE_GAMEOBJECT) ? _gameObjectRespawnTimesBySpawnId : _creatureRespawnTimesBySpawnId; }
+
+ void SetSpawnGroupActive(uint32 groupId, bool state);
std::unordered_set<uint32> _toggledSpawnGroupIds;
uint32 _respawnCheckTimer;
diff --git a/src/server/game/Scripting/ScriptMgr.cpp b/src/server/game/Scripting/ScriptMgr.cpp
index cbee458c9a0..16c6bc1a281 100644
--- a/src/server/game/Scripting/ScriptMgr.cpp
+++ b/src/server/game/Scripting/ScriptMgr.cpp
@@ -1565,36 +1565,6 @@ bool ScriptMgr::OnCastItemCombatSpell(Player* player, Unit* victim, SpellInfo co
return tmpscript->OnCastItemCombatSpell(player, victim, spellInfo, item);
}
-bool ScriptMgr::CanSpawn(ObjectGuid::LowType spawnId, uint32 entry, CreatureData const* cData, Map const* map)
-{
- ASSERT(map);
- CreatureTemplate const* baseTemplate = sObjectMgr->GetCreatureTemplate(entry);
- ASSERT(baseTemplate);
-
- // find out which template we'd be using
- CreatureTemplate const* actTemplate = baseTemplate;
- for (uint8 diff = uint8(map->GetSpawnMode()); diff > 0;)
- {
- if (uint32 diffEntry = baseTemplate->DifficultyEntry[diff - 1])
- if (CreatureTemplate const* diffTemplate = sObjectMgr->GetCreatureTemplate(diffEntry))
- {
- actTemplate = diffTemplate;
- break;
- }
- if (diff >= RAID_DIFFICULTY_10MAN_HEROIC && map->IsRaid())
- diff -= 2;
- else
- diff -= 1;
- }
-
- uint32 scriptId = baseTemplate->ScriptID;
- if (cData && cData->scriptId)
- scriptId = cData->scriptId;
-
- GET_SCRIPT_RET(CreatureScript, scriptId, tmpscript, true);
- return tmpscript->CanSpawn(spawnId, entry, baseTemplate, actTemplate, cData, map);
-}
-
CreatureAI* ScriptMgr::GetCreatureAI(Creature* creature)
{
ASSERT(creature);
diff --git a/src/server/game/Scripting/ScriptMgr.h b/src/server/game/Scripting/ScriptMgr.h
index bc7e75ca91b..39a51c3be6d 100644
--- a/src/server/game/Scripting/ScriptMgr.h
+++ b/src/server/game/Scripting/ScriptMgr.h
@@ -417,9 +417,6 @@ class TC_GAME_API CreatureScript : public UnitScript
public:
- // Called when the creature tries to spawn. Return false to block spawn and re-evaluate on next tick.
- virtual bool CanSpawn(ObjectGuid::LowType /*spawnId*/, uint32 /*entry*/, CreatureTemplate const* /*baseTemplate*/, CreatureTemplate const* /*actTemplate*/, CreatureData const* /*cData*/, Map const* /*map*/) const { return true; }
-
// Called when a CreatureAI object is needed for the creature.
virtual CreatureAI* GetAI(Creature* /*creature*/) const = 0;
};
@@ -920,7 +917,6 @@ class TC_GAME_API ScriptMgr
public: /* CreatureScript */
- bool CanSpawn(ObjectGuid::LowType spawnId, uint32 entry, CreatureData const* cData, Map const* map);
CreatureAI* GetCreatureAI(Creature* creature);
public: /* GameObjectScript */