fix(Core/Creature): Make Respawn() respect conditions and linked respawns (#17597)

This commit is contained in:
KJack
2023-11-26 06:48:58 -05:00
committed by GitHub
parent 2a7b507dd1
commit b7f7a7c731
2 changed files with 106 additions and 101 deletions
+40 -35
View File
@@ -622,40 +622,7 @@ void Creature::Update(uint32 diff)
time_t now = GameTime::GetGameTime().count(); time_t now = GameTime::GetGameTime().count();
if (m_respawnTime <= now) if (m_respawnTime <= now)
{ {
ConditionList conditions = sConditionMgr->GetConditionsForNotGroupedEntry(CONDITION_SOURCE_TYPE_CREATURE_RESPAWN, GetEntry());
if (!sConditionMgr->IsObjectMeetToConditions(this, conditions))
{
// Creature should not respawn, reset respawn timer. Conditions will be checked again the next time it tries to respawn.
m_respawnTime = GameTime::GetGameTime().count() + m_respawnDelay;
break;
}
bool allowed = !IsAIEnabled || AI()->CanRespawn(); // First check if there are any scripts that prevent us respawning
if (!allowed) // Will be rechecked on next Update call
break;
ObjectGuid dbtableHighGuid = ObjectGuid::Create<HighGuid::Unit>(m_creatureData ? m_creatureData->id1 : GetEntry(), m_spawnId);
time_t linkedRespawntime = GetMap()->GetLinkedRespawnTime(dbtableHighGuid);
CreatureTemplate const* cInfo = sObjectMgr->GetCreatureTemplate(GetEntry());
if (!linkedRespawntime || (cInfo && cInfo->HasFlagsExtra(CREATURE_FLAG_EXTRA_HARD_RESET))) // Can respawn
Respawn(); Respawn();
else // the master is dead
{
ObjectGuid targetGuid = sObjectMgr->GetLinkedRespawnGuid(dbtableHighGuid);
if (targetGuid == dbtableHighGuid) // if linking self, never respawn (check delayed to next day)
{
SetRespawnTime(DAY);
}
else
{
m_respawnTime = (now > linkedRespawntime ? now : linkedRespawntime) + urand(5, MINUTE); // else copy time from master and add a little
}
SaveRespawnTime(); // also save to DB immediately
}
} }
break; break;
} }
@@ -2006,16 +1973,38 @@ void Creature::setDeathState(DeathState s, bool despawn)
void Creature::Respawn(bool force) void Creature::Respawn(bool force)
{ {
//DestroyForNearbyPlayers(); // pussywizard: not needed
if (force) if (force)
{ {
if (IsAlive()) if (IsAlive())
{
setDeathState(DeathState::JustDied); setDeathState(DeathState::JustDied);
}
else if (getDeathState() != DeathState::Corpse) else if (getDeathState() != DeathState::Corpse)
{
setDeathState(DeathState::Corpse); setDeathState(DeathState::Corpse);
} }
}
ConditionList conditions = sConditionMgr->GetConditionsForNotGroupedEntry(CONDITION_SOURCE_TYPE_CREATURE_RESPAWN, GetEntry());
if (!sConditionMgr->IsObjectMeetToConditions(this, conditions) && !force)
{
// Creature should not respawn, reset respawn timer. Conditions will be checked again the next time it tries to respawn.
m_respawnTime = GameTime::GetGameTime().count() + m_respawnDelay;
return;
}
bool allowed = !IsAIEnabled || AI()->CanRespawn(); // First check if there are any scripts that prevent us respawning
if (!allowed && !force) // Will be rechecked on next Update call
return;
ObjectGuid dbtableHighGuid = ObjectGuid::Create<HighGuid::Unit>(m_creatureData ? m_creatureData->id1 : GetEntry(), m_spawnId);
time_t linkedRespawntime = GetMap()->GetLinkedRespawnTime(dbtableHighGuid);
CreatureTemplate const* cInfo = sObjectMgr->GetCreatureTemplate(GetEntry());
if (!linkedRespawntime || (cInfo && cInfo->HasFlagsExtra(CREATURE_FLAG_EXTRA_HARD_RESET)) || force) // Should respawn
{
RemoveCorpse(false, false); RemoveCorpse(false, false);
if (getDeathState() == DeathState::Dead) if (getDeathState() == DeathState::Dead)
@@ -2083,6 +2072,22 @@ void Creature::Respawn(bool force)
// xinef: relocate notifier, fixes npc appearing in corpse position after forced respawn (instead of spawn) // xinef: relocate notifier, fixes npc appearing in corpse position after forced respawn (instead of spawn)
m_last_notify_position.Relocate(-5000.0f, -5000.0f, -5000.0f, 0.0f); m_last_notify_position.Relocate(-5000.0f, -5000.0f, -5000.0f, 0.0f);
UpdateObjectVisibility(false); UpdateObjectVisibility(false);
}
else // the master is dead
{
ObjectGuid targetGuid = sObjectMgr->GetLinkedRespawnGuid(dbtableHighGuid);
if (targetGuid == dbtableHighGuid) // if linking self, never respawn (check delayed to next day)
{
SetRespawnTime(DAY);
}
else
{
time_t now = GameTime::GetGameTime().count();
m_respawnTime = (now > linkedRespawntime ? now : linkedRespawntime) + urand(5, MINUTE); // else copy time from master and add a little
}
SaveRespawnTime(); // also save to DB immediately
}
} }
void Creature::ForcedDespawn(uint32 timeMSToDespawn, Seconds forceRespawnTimer) void Creature::ForcedDespawn(uint32 timeMSToDespawn, Seconds forceRespawnTimer)
+1 -1
View File
@@ -2391,7 +2391,7 @@ public:
if (target->isDead()) if (target->isDead())
{ {
target->ToCreature()->Respawn(); target->ToCreature()->Respawn(true);
} }
return true; return true;
} }