From 12c6c5b90b2d03597c79c5ac6379940f29444241 Mon Sep 17 00:00:00 2001 From: avitasia Date: Sat, 13 Dec 2025 08:04:19 -0800 Subject: [PATCH] avoid race condition with casting a spell before queue pops --- nampower/castqueue.h | 18 ++++++++++++++++++ nampower/spellcast.cpp | 10 +++------- 2 files changed, 21 insertions(+), 7 deletions(-) diff --git a/nampower/castqueue.h b/nampower/castqueue.h index 8df945f..7fa5b04 100644 --- a/nampower/castqueue.h +++ b/nampower/castqueue.h @@ -105,6 +105,24 @@ namespace Nampower { return nullptr; } + bool removeSpellId(uint32_t spellId) { + for (int i = 0; i < size; i++) { + int index = (front + i) % maxSize; + if (queue[index].spellId == spellId) { + // Shift all elements after this one forward + for (int j = i; j < size - 1; j++) { + int currentIndex = (front + j) % maxSize; + int nextIndex = (front + j + 1) % maxSize; + queue[currentIndex] = queue[nextIndex]; + } + rear = (rear - 1 + maxSize) % maxSize; + size--; + return true; + } + } + return false; + } + CastSpellParams *findOldestWaitingForServerSpellId(uint32_t spellId) { for (int i = size - 1; i >= 0; i--) { int index = (front + i) % maxSize; diff --git a/nampower/spellcast.cpp b/nampower/spellcast.cpp index abd17e3..d0e0d8d 100644 --- a/nampower/spellcast.cpp +++ b/nampower/spellcast.cpp @@ -448,6 +448,9 @@ namespace Nampower { // save the detour to allow quickly calling this hook castSpellDetour = detour; + // it is possible when spamming to attempt to cast before queues are processed + processQueues(); + if (item == nullptr && casterUnit != game::GetObjectPtr(game::ClntObjMgrGetActivePlayerGuid())) { DEBUG_LOG("Ignoring non active player cast of spell " << game::GetSpellName(spellId) << " " << spellId); // just call original function if caster is not the active player @@ -496,13 +499,6 @@ namespace Nampower { } } - if (gCastData.nonGcdSpellQueued && spellOnGcd) { - // it is possible when spamming to attempt to cast before non gcd spells are processed, process queue first - if (processQueues()) { - return false; - } - } - gLastCastData.attemptTimeMs = currentTime; gLastCastData.attemptSpellId = spellId;