feat: show out-of-range red tint on macro action bar buttons

The out-of-range indicator (red tint) only applied to SPELL-type action
bar slots. Macro buttons like /cast Frostbolt never turned red even when
the target was out of range. Now resolves the macro's primary spell via
the cached lookup and checks its max range against the target distance,
giving the same visual feedback as regular spell buttons.
This commit is contained in:
Kelsi 2026-03-20 08:27:10 -07:00
parent 3b20485c79
commit 1d53c35ed7

View file

@ -8746,13 +8746,18 @@ void GameScreen::renderActionBar(game::GameHandler& gameHandler) {
const bool onGCD = gameHandler.isGCDActive() && !onCooldown && !slot.isEmpty();
// Out-of-range check: red tint when a targeted spell cannot reach the current target.
// Only applies to SPELL slots with a known max range (>5 yd) and an active target.
// Applies to SPELL and MACRO slots with a known max range (>5 yd) and an active target.
// Item range is checked below after barItemDef is populated.
bool outOfRange = false;
if (!slot.isEmpty() && slot.type == game::ActionBarSlot::SPELL && slot.id != 0
&& !onCooldown && gameHandler.hasTarget()) {
uint32_t maxRange = spellbookScreen.getSpellMaxRange(slot.id, assetMgr);
if (maxRange > 5) { // >5 yd = not melee/self
{
uint32_t rangeCheckSpellId = 0;
if (slot.type == game::ActionBarSlot::SPELL && slot.id != 0)
rangeCheckSpellId = slot.id;
else if (slot.type == game::ActionBarSlot::MACRO && slot.id != 0)
rangeCheckSpellId = resolveMacroPrimarySpellId(slot.id, gameHandler);
if (rangeCheckSpellId != 0 && !onCooldown && gameHandler.hasTarget()) {
uint32_t maxRange = spellbookScreen.getSpellMaxRange(rangeCheckSpellId, assetMgr);
if (maxRange > 5) {
auto& em = gameHandler.getEntityManager();
auto playerEnt = em.getEntity(gameHandler.getPlayerGuid());
auto targetEnt = em.getEntity(gameHandler.getTargetGuid());
@ -8760,12 +8765,12 @@ void GameScreen::renderActionBar(game::GameHandler& gameHandler) {
float dx = playerEnt->getX() - targetEnt->getX();
float dy = playerEnt->getY() - targetEnt->getY();
float dz = playerEnt->getZ() - targetEnt->getZ();
float dist = std::sqrt(dx * dx + dy * dy + dz * dz);
if (dist > static_cast<float>(maxRange))
if (std::sqrt(dx*dx + dy*dy + dz*dz) > static_cast<float>(maxRange))
outOfRange = true;
}
}
}
}
// Insufficient-power check: orange tint when player doesn't have enough power to cast.
// Only applies to SPELL slots with a known power cost and when not already on cooldown.