diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/server/game/Entities/Creature/Creature.cpp | 26 | ||||
-rw-r--r-- | src/server/game/Grids/ObjectGridLoader.cpp | 8 | ||||
-rw-r--r-- | src/server/game/Instances/InstanceScript.cpp | 2 | ||||
-rw-r--r-- | src/server/game/Maps/Map.cpp | 32 | ||||
-rw-r--r-- | src/server/game/Maps/Map.h | 15 | ||||
-rw-r--r-- | src/server/game/Scripting/ScriptMgr.cpp | 30 | ||||
-rw-r--r-- | src/server/game/Scripting/ScriptMgr.h | 4 |
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 */ |