diff --git a/Core.lua b/Core.lua index 0ebecaa..524aca2 100644 --- a/Core.lua +++ b/Core.lua @@ -4673,6 +4673,7 @@ SlashCmdList["CLEVEROID"] = function(msg) DEFAULT_CHAT_FRAME:AddMessage('/cleveroid channeldebug - Toggle [channeltime] conditional debug output') DEFAULT_CHAT_FRAME:AddMessage("|cffffaa00Action Slot Debug:|r") DEFAULT_CHAT_FRAME:AddMessage('/cleveroid slotdebug - Debug action slot state (tooltip/range/mana)') + DEFAULT_CHAT_FRAME:AddMessage('/cleveroid rangedebug - Debug spell range checking (channeled spells)') DEFAULT_CHAT_FRAME:AddMessage("|cffffaa00Slam Rotation (Warrior):|r") DEFAULT_CHAT_FRAME:AddMessage('/cleveroid slamdebug - Show Slam cast time and clip window calculations') DEFAULT_CHAT_FRAME:AddMessage("|cffffaa00Debuff Tracking Debug:|r") @@ -4922,6 +4923,94 @@ SlashCmdList["CLEVEROID"] = function(msg) return end + -- rangedebug - Debug range checking for a spell + if cmd == "rangedebug" or cmd == "testrange" then + -- Combine val and val2 for multi-word spell names + local spellName = val + if val2 and val2 ~= "" then + spellName = val .. " " .. val2 + end + if not spellName or spellName == "" then + CleveRoids.Print("Usage: /cleveroid rangedebug ") + CleveRoids.Print("Example: /cleveroid rangedebug Arcane Missiles") + return + end + + CleveRoids.Print("|cff00ff00=== Range Debug: " .. spellName .. " ===|r") + + -- Get spell ID + local spellId = nil + if GetSpellIdForName then + spellId = GetSpellIdForName(spellName) + CleveRoids.Print("Spell ID: " .. (spellId and tostring(spellId) or "|cffff0000NOT FOUND|r")) + else + CleveRoids.Print("GetSpellIdForName: |cffff0000NOT AVAILABLE|r") + end + + if spellId and spellId > 0 then + -- Check native IsSpellInRange + if IsSpellInRange then + local target = UnitExists("target") and "target" or nil + if target then + local result = IsSpellInRange(spellId, target) + CleveRoids.Print("Native IsSpellInRange: " .. tostring(result)) + if result == -1 then + CleveRoids.Print(" |cffffff00(-1 means non-unit-targeted spell, using fallback)|r") + elseif result == nil then + CleveRoids.Print(" |cffffff00(nil means error or unknown spell)|r") + end + else + CleveRoids.Print("Native IsSpellInRange: |cffffff00No target selected|r") + end + end + + -- Check GetSpellRec fields + local API = CleveRoids.NampowerAPI + if API then + -- Try rangeMax (may not exist) + local rangeMax = API.GetSpellField(spellId, "rangeMax") + CleveRoids.Print("rangeMax field: " .. (rangeMax and tostring(rangeMax) or "|cffffff00nil|r")) + + -- Try rangeIndex + local rangeIndex = API.GetSpellField(spellId, "rangeIndex") + CleveRoids.Print("rangeIndex field: " .. (rangeIndex and tostring(rangeIndex) or "|cffffff00nil|r")) + + if rangeIndex and API.SpellRangeTable then + local lookupRange = API.SpellRangeTable[rangeIndex] + CleveRoids.Print("SpellRangeTable[" .. rangeIndex .. "]: " .. (lookupRange and (tostring(lookupRange) .. " yards") or "|cffffff00not found|r")) + end + + -- Final GetSpellRange result + local finalRange = API.GetSpellRange(spellId) + CleveRoids.Print("API.GetSpellRange: " .. (finalRange and (tostring(finalRange) .. " yards") or "|cffff0000nil|r")) + + -- UnitXP distance check + if CleveRoids.hasUnitXP and UnitExists("target") then + local distance = UnitXP("distanceBetween", "player", "target") + CleveRoids.Print("Distance to target: " .. (distance and (string.format("%.1f", distance) .. " yards") or "|cffffff00nil|r")) + + if finalRange and distance then + local inRange = distance <= finalRange + CleveRoids.Print("In range (distance <= spellRange): " .. (inRange and "|cff00ff00YES|r" or "|cffff0000NO|r")) + end + elseif not CleveRoids.hasUnitXP then + CleveRoids.Print("UnitXP: |cffff0000NOT INSTALLED (required for fallback)|r") + else + CleveRoids.Print("Distance check: |cffffff00No target selected|r") + end + + -- Final API.IsSpellInRange result + if UnitExists("target") then + local finalResult = API.IsSpellInRange(spellId, "target") + CleveRoids.Print("API.IsSpellInRange: " .. tostring(finalResult)) + end + end + end + + CleveRoids.Print("|cff00ff00=== End Range Debug ===|r") + return + end + -- testcasting (debug casting state detection) if cmd == "testcasting" or cmd == "casttest" then CleveRoids.Print("|cff00ff00=== Casting State Test ===|r") diff --git a/NampowerAPI.lua b/NampowerAPI.lua index b9f5f9c..85d445b 100644 --- a/NampowerAPI.lua +++ b/NampowerAPI.lua @@ -333,12 +333,71 @@ function API.GetSpellManaCost(spellId) return API.GetSpellField(spellId, "manaCost") end +-- SpellRange.dbc lookup table: rangeIndex -> maxRange (in yards) +-- From vanilla 1.12.1 client data (corrected based on actual spell ranges) +API.SpellRangeTable = { + [0] = 0, -- Self Only + [1] = 5, -- Combat Range (Melee) + [2] = 30, -- 30 yard range (Frostbolt, etc.) + [3] = 35, -- 35 yard range + [4] = 30, -- 30 yard range (Arcane Missiles, etc.) + [5] = 40, -- 40 yard range + [6] = 45, -- 45 yard range + [7] = 100, -- Vision Range + [8] = 20, -- 20 yard range + [9] = 10, -- 10 yard range + [10] = 8, -- 8 yard range + [11] = 15, -- 15 yard range (Charge) + [12] = 25, -- 25 yard range + [13] = 100, -- Anywhere/Unlimited + [14] = 0, -- Self Only (alternate) + [15] = 80, -- 80 yard range (hunters) + [16] = 18, -- 18 yard range + [17] = 60, -- 60 yard range + [18] = 5, -- Melee (alternate) + [19] = 25, -- 25 yard range (alternate) + [20] = 30, -- 30 yard range (alternate) + [21] = 35, -- 35 yard range (alternate) + [22] = 40, -- 40 yard range (alternate) + [23] = 0, -- Touch + [24] = 41, -- 41 yard range + [25] = 10, -- 10 yard range (alternate) + [26] = 50, -- 50 yard range + [27] = 55, -- 55 yard range + [28] = 65, -- 65 yard range + [29] = 70, -- 70 yard range + [30] = 50000, -- Unlimited + [31] = 8, -- 8 yard range (alternate) + [32] = 7, -- 7 yard range + [33] = 11, -- 11 yard range + [34] = 12, -- 12 yard range + [35] = 28, -- 28 yard range + [36] = 6, -- 6 yard range + [37] = 13, -- 13 yard range + [38] = 15, -- 15 yard range (alternate) + [39] = 100, -- 100 yard range (alternate) + [40] = 150, -- 150 yard range +} + -- Get spell range (max range in yards) function API.GetSpellRange(spellId) + if not spellId or spellId == 0 then return nil end + + -- First try rangeMax (Nampower may provide this as a resolved field) local rangeMax = API.GetSpellField(spellId, "rangeMax") - if rangeMax then + if rangeMax and rangeMax > 0 then return rangeMax / 10 -- Convert from game units to yards end + + -- Fallback: lookup rangeIndex in SpellRange table + local rangeIndex = API.GetSpellField(spellId, "rangeIndex") + if rangeIndex then + local range = API.SpellRangeTable[rangeIndex] + if range then + return range + end + end + return nil end @@ -1483,13 +1542,16 @@ function API.IsSpellInRange(spellIdentifier, unit) -- Try native IsSpellInRange first if IsSpellInRange then local result = IsSpellInRange(checkValue, unit) - if result ~= nil then + -- result == 1 (in range), 0 (out of range), -1 (invalid/non-unit-targeted), nil (error) + -- Only use native result for definitive answers (0 or 1) + -- Fall through to UnitXP fallback for -1 (ground-targeted spells like Blizzard) + if result == 0 or result == 1 then return result end end -- Fallback: Use spell range from record + UnitXP distance check - -- This handles channeled spells where IsSpellInRange returns nil + -- This handles channeled spells where IsSpellInRange returns nil or -1 if spellId and spellId > 0 and CleveRoids.hasUnitXP and UnitExists(unit) then local spellRange = API.GetSpellRange(spellId) if spellRange and spellRange > 0 then