fix(Core/Map): Dynamic respawns: preserve original respawn timer and skip rares (#21440)
This commit is contained in:
@@ -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())
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user