mirror of
https://github.com/mod-playerbots/azerothcore-wotlk.git
synced 2026-01-18 03:15:41 +00:00
feat(Core/Player): implement Spell Queue (#20797)
This commit is contained in:
@@ -79,6 +79,7 @@ void Player::Update(uint32 p_time)
|
||||
|
||||
// used to implement delayed far teleports
|
||||
SetMustDelayTeleport(true);
|
||||
ProcessSpellQueue();
|
||||
Unit::Update(p_time);
|
||||
SetMustDelayTeleport(false);
|
||||
|
||||
@@ -2255,3 +2256,89 @@ void Player::ProcessTerrainStatusUpdate()
|
||||
else
|
||||
m_MirrorTimerFlags &= ~(UNDERWATER_INWATER | UNDERWATER_INLAVA | UNDERWATER_INSLIME | UNDERWATER_INDARKWATER);
|
||||
}
|
||||
|
||||
uint32 Player::GetSpellQueueWindow() const
|
||||
{
|
||||
return sWorld->getIntConfig(CONFIG_SPELL_QUEUE_WINDOW);
|
||||
}
|
||||
|
||||
bool Player::CanExecutePendingSpellCastRequest(SpellInfo const* spellInfo)
|
||||
{
|
||||
if (GetGlobalCooldownMgr().HasGlobalCooldown(spellInfo))
|
||||
return false;
|
||||
|
||||
if (GetSpellCooldownDelay(spellInfo->Id) > GetSpellQueueWindow())
|
||||
return false;
|
||||
|
||||
for (CurrentSpellTypes spellSlot : {CURRENT_MELEE_SPELL, CURRENT_GENERIC_SPELL})
|
||||
if (Spell* spell = GetCurrentSpell(spellSlot))
|
||||
{
|
||||
bool autoshot = spell->m_spellInfo->IsAutoRepeatRangedSpell();
|
||||
if (IsNonMeleeSpellCast(false, true, true, autoshot))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
const PendingSpellCastRequest* Player::GetCastRequest(uint32 category) const
|
||||
{
|
||||
for (const PendingSpellCastRequest& request : SpellQueue)
|
||||
if (request.category == category)
|
||||
return &request;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
bool Player::CanRequestSpellCast(SpellInfo const* spellInfo)
|
||||
{
|
||||
if (!sWorld->getBoolConfig(CONFIG_SPELL_QUEUE_ENABLED))
|
||||
return false;
|
||||
|
||||
// Check for existing cast request with the same category
|
||||
if (GetCastRequest(spellInfo->StartRecoveryCategory))
|
||||
return false;
|
||||
|
||||
if (GetGlobalCooldownMgr().GetGlobalCooldown(spellInfo) > GetSpellQueueWindow())
|
||||
return false;
|
||||
|
||||
if (GetSpellCooldownDelay(spellInfo->Id) > GetSpellQueueWindow())
|
||||
return false;
|
||||
|
||||
// If there is an existing cast that will last longer than the allowable
|
||||
// spell queue window, then we can't request a new spell cast
|
||||
for (CurrentSpellTypes spellSlot : { CURRENT_MELEE_SPELL, CURRENT_GENERIC_SPELL })
|
||||
if (Spell* spell = GetCurrentSpell(spellSlot))
|
||||
if (spell->GetCastTimeRemaining() > static_cast<int32>(GetSpellQueueWindow()))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void Player::ExecuteOrCancelSpellCastRequest(PendingSpellCastRequest* request, bool isCancel /* = false*/)
|
||||
{
|
||||
if (isCancel)
|
||||
request->cancelInProgress = true;
|
||||
|
||||
if (WorldSession* session = GetSession())
|
||||
{
|
||||
if (request->isItem)
|
||||
session->HandleUseItemOpcode(request->requestPacket);
|
||||
else
|
||||
session->HandleCastSpellOpcode(request->requestPacket);
|
||||
}
|
||||
}
|
||||
|
||||
void Player::ProcessSpellQueue()
|
||||
{
|
||||
while (!SpellQueue.empty())
|
||||
{
|
||||
PendingSpellCastRequest& request = SpellQueue.front(); // Peek at the first spell
|
||||
SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(request.spellId);
|
||||
if (CanExecutePendingSpellCastRequest(spellInfo))
|
||||
{
|
||||
ExecuteOrCancelSpellCastRequest(&request);
|
||||
SpellQueue.pop_front(); // Remove from the queue
|
||||
}
|
||||
else // If the first spell can't execute, stop processing
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user