diff options
author | Treeston <treeston.mmoc@gmail.com> | 2018-02-22 20:31:42 +0100 |
---|---|---|
committer | funjoker <funjoker109@gmail.com> | 2021-08-08 21:21:34 +0200 |
commit | 5c80f5073493a3d31fd4b463891727beb6fe7eb1 (patch) | |
tree | 53318cf5dbff62024ade4dd33ae46d660a9e4558 /src | |
parent | 5e7a11f88d9762fc75983ea2bbe65c598c4e51ba (diff) |
Core/Spawning: Actually check spawn group state before processing a respawn. It feels like that is something that should've been noticed at some point.
Also remove CreatureScript::CanSpawn since nobody uses it, and spawn groups do the same thing.
(cherry picked from commit 94b5d9bfa1195ad7c32cf51a665b55514dac0938)
Diffstat (limited to 'src')
-rw-r--r-- | src/server/game/Entities/Creature/Creature.cpp | 25 | ||||
-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 | 38 | ||||
-rw-r--r-- | src/server/game/Scripting/ScriptMgr.h | 4 |
7 files changed, 44 insertions, 80 deletions
diff --git a/src/server/game/Entities/Creature/Creature.cpp b/src/server/game/Entities/Creature/Creature.cpp index 9dfff1fad98..3c98d58eba2 100644 --- a/src/server/game/Entities/Creature/Creature.cpp +++ b/src/server/game/Entities/Creature/Creature.cpp @@ -698,11 +698,16 @@ void Creature::Update(uint32 diff) break; case DEAD: { + if (!m_respawnCompatibilityMode) + { + TC_LOG_ERROR("entities.unit", "Creature (GUID: " UI64FMTD " 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 @@ -1749,7 +1754,7 @@ bool Creature::LoadFromDB(ObjectGuid::LowType spawnId, Map* map, bool addToMap, CreatureData const* data = sObjectMgr->GetCreatureData(spawnId); if (!data) { - TC_LOG_ERROR("sql.sql", "Creature (GUID: " UI64FMTD ") not found in table `creature`, can't load. ", spawnId); + TC_LOG_ERROR("sql.sql", "Creature (SpawnID " UI64FMTD ") not found in table `creature`, can't load. ", spawnId); return false; } @@ -1760,13 +1765,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::Creature>(), map, data->id, data->spawnPoint, data, 0U , !m_respawnCompatibilityMode)) return false; @@ -1778,8 +1776,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 " UI64FMTD ") 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 aafe9b65d58..39f3bf9dc47 100644 --- a/src/server/game/Grids/ObjectGridLoader.cpp +++ b/src/server/game/Grids/ObjectGridLoader.cpp @@ -145,14 +145,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(PhasingHandler::GetEmptyPhaseShift(), 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 32317dff54a..0df55ede4ab 100644 --- a/src/server/game/Instances/InstanceScript.cpp +++ b/src/server/game/Instances/InstanceScript.cpp @@ -271,7 +271,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 856b5a4185c..8c1d6aae417 100644 --- a/src/server/game/Maps/Map.cpp +++ b/src/server/game/Maps/Map.cpp @@ -3062,10 +3062,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 " UI64FMTD " 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) { @@ -3075,11 +3089,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) @@ -3143,15 +3153,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 fbd2478adb7..419073adf19 100644 --- a/src/server/game/Maps/Map.h +++ b/src/server/game/Maps/Map.h @@ -760,10 +760,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 @@ -799,6 +808,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 de42459a367..8df91f40ff5 100644 --- a/src/server/game/Scripting/ScriptMgr.cpp +++ b/src/server/game/Scripting/ScriptMgr.cpp @@ -1599,44 +1599,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 = nullptr; - DifficultyEntry const* difficultyEntry = sDifficultyStore.LookupEntry(map->GetDifficultyID()); - while (!actTemplate && difficultyEntry) - { - int32 idx = CreatureTemplate::DifficultyIDToDifficultyEntryIndex(difficultyEntry->ID); - if (idx == -1) - break; - - if (baseTemplate->DifficultyEntry[idx]) - { - actTemplate = sObjectMgr->GetCreatureTemplate(baseTemplate->DifficultyEntry[idx]); - break; - } - - if (!difficultyEntry->FallbackDifficultyID) - break; - - difficultyEntry = sDifficultyStore.LookupEntry(difficultyEntry->FallbackDifficultyID); - } - - if (!actTemplate) - actTemplate = baseTemplate; - - 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 cf02fcad7a8..bd3e383572c 100644 --- a/src/server/game/Scripting/ScriptMgr.h +++ b/src/server/game/Scripting/ScriptMgr.h @@ -420,9 +420,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; }; @@ -989,7 +986,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 */ |