fix(Core/Map): Dynamic respawns: preserve original respawn timer and skip rares (#21440)

This commit is contained in:
Andrew
2025-02-14 07:30:59 -03:00
committed by GitHub
parent db9b4cf0c6
commit 062f9c4341
4 changed files with 17 additions and 15 deletions
@@ -1975,8 +1975,8 @@ void Creature::setDeathState(DeathState state, bool despawn)
if (state == DeathState::JustDied) if (state == DeathState::JustDied)
{ {
m_corpseRemoveTime = GameTime::GetGameTime().count() + m_corpseDelay; m_corpseRemoveTime = GameTime::GetGameTime().count() + m_corpseDelay;
GetMap()->ApplyDynamicModeRespawnScaling(this, m_respawnDelay); uint32 dynamicRespawnDelay = GetMap()->ApplyDynamicModeRespawnScaling(this, m_respawnDelay);
m_respawnTime = GameTime::GetGameTime().count() + m_respawnDelay + m_corpseDelay; m_respawnTime = GameTime::GetGameTime().count() + dynamicRespawnDelay + m_corpseDelay;
// always save boss respawn time at death to prevent crash cheating // always save boss respawn time at death to prevent crash cheating
if (GetMap()->IsDungeon() || isWorldBoss() || GetCreatureTemplate()->rank >= CREATURE_ELITE_ELITE) if (GetMap()->IsDungeon() || isWorldBoss() || GetCreatureTemplate()->rank >= CREATURE_ELITE_ELITE)
@@ -897,8 +897,8 @@ void GameObject::Update(uint32 diff)
return; return;
} }
GetMap()->ApplyDynamicModeRespawnScaling(this, m_respawnDelayTime); uint32 dynamicRespawnDelay = GetMap()->ApplyDynamicModeRespawnScaling(this, m_respawnDelayTime);
m_respawnTime = GameTime::GetGameTime().count() + m_respawnDelayTime; m_respawnTime = GameTime::GetGameTime().count() + dynamicRespawnDelay;
// if option not set then object will be saved at grid unload // if option not set then object will be saved at grid unload
if (GetMap()->IsDungeon()) if (GetMap()->IsDungeon())
+12 -10
View File
@@ -2658,38 +2658,40 @@ void Map::SendObjectUpdates()
} }
} }
void Map::ApplyDynamicModeRespawnScaling(WorldObject const* obj, uint32& respawnDelay) const uint32 Map::ApplyDynamicModeRespawnScaling(WorldObject const* obj, uint32 respawnDelay) const
{ {
ASSERT(obj->GetMap() == this); ASSERT(obj->GetMap() == this);
float rate = sWorld->getFloatConfig(obj->IsGameObject() ? CONFIG_RESPAWN_DYNAMICRATE_GAMEOBJECT : CONFIG_RESPAWN_DYNAMICRATE_CREATURE); float rate = sWorld->getFloatConfig(obj->IsGameObject() ? CONFIG_RESPAWN_DYNAMICRATE_GAMEOBJECT : CONFIG_RESPAWN_DYNAMICRATE_CREATURE);
if (rate == 1.0f) if (rate == 1.0f)
return; return respawnDelay;
// No instanced maps (dungeons, battlegrounds, arenas etc.) // No instanced maps (dungeons, battlegrounds, arenas etc.)
if (obj->GetMap()->Instanceable()) if (obj->GetMap()->Instanceable())
return; return respawnDelay;
// No quest givers or world bosses // No quest givers or world bosses
if (Creature const* creature = obj->ToCreature()) if (Creature const* creature = obj->ToCreature())
if (creature->IsQuestGiver() || creature->isWorldBoss()) if (creature->IsQuestGiver() || creature->isWorldBoss()
return; || (creature->GetCreatureTemplate()->rank == CREATURE_ELITE_RARE)
|| (creature->GetCreatureTemplate()->rank == CREATURE_ELITE_RAREELITE))
return respawnDelay;
auto it = _zonePlayerCountMap.find(obj->GetZoneId()); auto it = _zonePlayerCountMap.find(obj->GetZoneId());
if (it == _zonePlayerCountMap.end()) if (it == _zonePlayerCountMap.end())
return; return respawnDelay;
uint32 const playerCount = it->second; uint32 const playerCount = it->second;
if (!playerCount) if (!playerCount)
return; return respawnDelay;
double const adjustFactor = rate / playerCount; double const adjustFactor = rate / playerCount;
if (adjustFactor >= 1.0) // nothing to do here if (adjustFactor >= 1.0) // nothing to do here
return; return respawnDelay;
uint32 const timeMinimum = sWorld->getIntConfig(obj->IsGameObject() ? CONFIG_RESPAWN_DYNAMICMINIMUM_GAMEOBJECT : CONFIG_RESPAWN_DYNAMICMINIMUM_CREATURE); uint32 const timeMinimum = sWorld->getIntConfig(obj->IsGameObject() ? CONFIG_RESPAWN_DYNAMICMINIMUM_GAMEOBJECT : CONFIG_RESPAWN_DYNAMICMINIMUM_CREATURE);
if (respawnDelay <= timeMinimum) if (respawnDelay <= timeMinimum)
return; return respawnDelay;
respawnDelay = std::max<uint32>(std::ceil(respawnDelay * adjustFactor), timeMinimum); return std::max<uint32>(std::ceil(respawnDelay * adjustFactor), timeMinimum);
} }
void Map::DelayedUpdate(const uint32 t_diff) void Map::DelayedUpdate(const uint32 t_diff)
+1 -1
View File
@@ -595,7 +595,7 @@ public:
[[nodiscard]] time_t GetInstanceResetPeriod() const { return _instanceResetPeriod; } [[nodiscard]] time_t GetInstanceResetPeriod() const { return _instanceResetPeriod; }
void UpdatePlayerZoneStats(uint32 oldZone, uint32 newZone); void UpdatePlayerZoneStats(uint32 oldZone, uint32 newZone);
void ApplyDynamicModeRespawnScaling(WorldObject const* obj, uint32& respawnDelay) const; [[nodiscard]] uint32 ApplyDynamicModeRespawnScaling(WorldObject const* obj, uint32 respawnDelay) const;
TaskScheduler _creatureRespawnScheduler; TaskScheduler _creatureRespawnScheduler;