mirror of
https://github.com/brues-code/SuperCleveRoidMacros.git
synced 2026-09-16 03:38:00 +00:00
clean debug and add movingand nomoving conditionals that use monkeyspeed
This commit is contained in:
@@ -2023,6 +2023,100 @@ function CleveRoids.ValidateTTE(operator, amount)
|
||||
return false
|
||||
end
|
||||
|
||||
-- ============================================================================
|
||||
-- MONKEYSPEED ADDON INTEGRATION
|
||||
-- ============================================================================
|
||||
-- Integrates with MonkeySpeed addon for accurate movement speed detection
|
||||
-- MonkeySpeed uses SuperWoW's UnitPosition to calculate actual movement speed
|
||||
|
||||
--- Check if MonkeySpeed addon is available and loaded
|
||||
--- @return boolean True if MonkeySpeed is available with speed data
|
||||
function CleveRoids.HasMonkeySpeed()
|
||||
return type(MonkeySpeed) == "table" and
|
||||
MonkeySpeed.m_bLoaded == true and
|
||||
MonkeySpeed.m_fSpeed ~= nil
|
||||
end
|
||||
|
||||
--- Require MonkeySpeed for a feature, warn once if missing
|
||||
--- @param feature string Feature name for warning message
|
||||
--- @return boolean True if MonkeySpeed is available
|
||||
function CleveRoids.RequireMonkeySpeed(feature)
|
||||
if CleveRoids.HasMonkeySpeed() then
|
||||
return true
|
||||
end
|
||||
if not CleveRoids._monkeySpeedErrorShown then
|
||||
DEFAULT_CHAT_FRAME:AddMessage("|cffff0000[SuperCleveRoidMacros]|r The [moving] speed conditional requires the MonkeySpeed addon.", 1, 0.5, 0.5)
|
||||
CleveRoids._monkeySpeedErrorShown = true
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
--- Get current player movement speed as percentage (100 = normal run speed)
|
||||
--- @return number|nil Speed percentage, or nil if MonkeySpeed not available
|
||||
function CleveRoids.GetPlayerSpeed()
|
||||
if not CleveRoids.HasMonkeySpeed() then
|
||||
return nil
|
||||
end
|
||||
return MonkeySpeed.m_fSpeed or 0
|
||||
end
|
||||
|
||||
--- Check if player is currently moving (speed > 0)
|
||||
--- Falls back to basic position checking if MonkeySpeed isn't available
|
||||
--- @return boolean True if player is moving
|
||||
function CleveRoids.IsPlayerMoving()
|
||||
-- If MonkeySpeed is available, use it for accurate detection
|
||||
if CleveRoids.HasMonkeySpeed() then
|
||||
return (MonkeySpeed.m_fSpeed or 0) > 0
|
||||
end
|
||||
|
||||
-- Fallback: use SuperWoW's UnitPosition for basic moving detection
|
||||
-- We store last position and compare
|
||||
if UnitPosition then
|
||||
local x, y = UnitPosition("player")
|
||||
if x and y then
|
||||
if CleveRoids._lastPlayerPos then
|
||||
local dx = x - CleveRoids._lastPlayerPos.x
|
||||
local dy = y - CleveRoids._lastPlayerPos.y
|
||||
local dist = math.sqrt(dx * dx + dy * dy)
|
||||
CleveRoids._lastPlayerPos = { x = x, y = y, time = GetTime() }
|
||||
-- Moving if distance > small threshold (account for floating point)
|
||||
return dist > 0.001
|
||||
else
|
||||
CleveRoids._lastPlayerPos = { x = x, y = y, time = GetTime() }
|
||||
return false -- Can't determine on first call
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return false
|
||||
end
|
||||
|
||||
--- Validates a movement speed conditional.
|
||||
--- Usage: [moving:>100] [moving:<50] [moving:=0]
|
||||
--- operator: Comparison operator (>, <, =, >=, <=, ~=)
|
||||
--- amount: Speed percentage (100 = normal run speed)
|
||||
--- returns: True if speed [operator] amount
|
||||
function CleveRoids.ValidateMovingSpeed(operator, amount)
|
||||
if not operator or not amount then return false end
|
||||
|
||||
-- Check if MonkeySpeed is available for speed comparisons
|
||||
if not CleveRoids.RequireMonkeySpeed("moving speed comparison") then
|
||||
return false
|
||||
end
|
||||
|
||||
local speed = CleveRoids.GetPlayerSpeed()
|
||||
if speed == nil then
|
||||
return false
|
||||
end
|
||||
|
||||
-- Compare speed against threshold
|
||||
if CleveRoids.operators[operator] then
|
||||
return CleveRoids.comparators[operator](speed, amount)
|
||||
end
|
||||
|
||||
return false
|
||||
end
|
||||
|
||||
-- ============================================================================
|
||||
-- CURSIVE ADDON INTEGRATION
|
||||
-- ============================================================================
|
||||
@@ -6268,6 +6362,81 @@ CleveRoids.Keywords = {
|
||||
nobuffcapped = function(conditionals)
|
||||
local target = conditionals.target or "target"
|
||||
return not CleveRoids.IsTargetBuffCapped(target)
|
||||
end,
|
||||
|
||||
-- =========================================================================
|
||||
-- MOVEMENT SPEED CONDITIONALS (MonkeySpeed integration)
|
||||
-- =========================================================================
|
||||
-- [moving] - Player is moving (speed > 0)
|
||||
-- [moving:>100] - Player speed is above 100% (faster than normal run)
|
||||
-- [moving:<50] - Player speed is below 50% (slower than half speed)
|
||||
-- Requires MonkeySpeed addon for speed comparisons (basic moving check uses fallback)
|
||||
moving = function(conditionals)
|
||||
-- Boolean form [moving] - just check if moving at all
|
||||
if conditionals.moving == true then
|
||||
return CleveRoids.IsPlayerMoving()
|
||||
end
|
||||
|
||||
-- Operator form [moving:>100] - check speed percentage
|
||||
return Multi(conditionals.moving, function(args)
|
||||
if type(args) ~= "table" then return false end
|
||||
|
||||
-- Handle multi-comparison (e.g., >50&<150)
|
||||
if args.comparisons and type(args.comparisons) == "table" then
|
||||
local speed = CleveRoids.GetPlayerSpeed()
|
||||
if speed == nil then
|
||||
CleveRoids.RequireMonkeySpeed("moving speed comparison")
|
||||
return false
|
||||
end
|
||||
|
||||
-- ALL comparisons must pass (AND logic)
|
||||
for _, comp in ipairs(args.comparisons) do
|
||||
if not CleveRoids.operators[comp.operator] then
|
||||
return false
|
||||
end
|
||||
if not CleveRoids.comparators[comp.operator](speed, comp.amount) then
|
||||
return false
|
||||
end
|
||||
end
|
||||
return true
|
||||
end
|
||||
|
||||
return CleveRoids.ValidateMovingSpeed(args.operator, args.amount)
|
||||
end, conditionals, "moving")
|
||||
end,
|
||||
|
||||
-- [nomoving] - Player is NOT moving (speed == 0)
|
||||
-- [nomoving:>100] - Player speed is NOT above 100% (at or below normal run)
|
||||
nomoving = function(conditionals)
|
||||
-- Boolean form [nomoving] - check if NOT moving
|
||||
if conditionals.nomoving == true then
|
||||
return not CleveRoids.IsPlayerMoving()
|
||||
end
|
||||
|
||||
-- Operator form [nomoving:>100] - negate speed comparison
|
||||
return NegatedMulti(conditionals.nomoving, function(args)
|
||||
if type(args) ~= "table" then return false end
|
||||
|
||||
if args.comparisons and type(args.comparisons) == "table" then
|
||||
local speed = CleveRoids.GetPlayerSpeed()
|
||||
if speed == nil then
|
||||
-- If MonkeySpeed not available, negated returns true (fail-safe)
|
||||
return true
|
||||
end
|
||||
|
||||
for _, comp in ipairs(args.comparisons) do
|
||||
if not CleveRoids.operators[comp.operator] then
|
||||
return true
|
||||
end
|
||||
if not CleveRoids.comparators[comp.operator](speed, comp.amount) then
|
||||
return true
|
||||
end
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
return not CleveRoids.ValidateMovingSpeed(args.operator, args.amount)
|
||||
end, conditionals, "nomoving")
|
||||
end
|
||||
}
|
||||
|
||||
|
||||
@@ -96,6 +96,8 @@ local BOOLEAN_CONDITIONALS = {
|
||||
noohimbue = true,
|
||||
group = true,
|
||||
nogroup = true,
|
||||
moving = true,
|
||||
nomoving = true,
|
||||
}
|
||||
|
||||
local requirementCheckFrame = CreateFrame("Frame")
|
||||
@@ -5285,11 +5287,7 @@ SlashCmdList["CLEVEROID"] = function(msg)
|
||||
DEFAULT_CHAT_FRAME:AddMessage("/cleveroid forget <spellID|all> - Forget learned duration(s)")
|
||||
DEFAULT_CHAT_FRAME:AddMessage("/cleveroid debug [0|1] - Toggle learning debug messages")
|
||||
end
|
||||
DEFAULT_CHAT_FRAME:AddMessage("/cleveroid macrodebug - Toggle macro length warning debug")
|
||||
DEFAULT_CHAT_FRAME:AddMessage("/cleveroid macrorefdebug - Toggle macro reference {Name} execution debug")
|
||||
DEFAULT_CHAT_FRAME:AddMessage("/cleveroid macrostatus - Check macro length warning status")
|
||||
DEFAULT_CHAT_FRAME:AddMessage("|cffffaa00Spell School Detection:|r")
|
||||
DEFAULT_CHAT_FRAME:AddMessage('/cleveroid schooltest <spellID or name> - Test spell school detection')
|
||||
DEFAULT_CHAT_FRAME:AddMessage("|cffffaa00Spell Schools:|r")
|
||||
DEFAULT_CHAT_FRAME:AddMessage('/cleveroid listschools - List all learned spell schools')
|
||||
DEFAULT_CHAT_FRAME:AddMessage('/cleveroid clearschools - Clear learned spell school data')
|
||||
DEFAULT_CHAT_FRAME:AddMessage("|cffffaa00Immunity Tracking:|r")
|
||||
@@ -5312,24 +5310,6 @@ SlashCmdList["CLEVEROID"] = function(msg)
|
||||
DEFAULT_CHAT_FRAME:AddMessage('/cleveroid listtab <tab> - List all talents in a tab with their IDs')
|
||||
DEFAULT_CHAT_FRAME:AddMessage('/cleveroid talents - Show current talent ranks')
|
||||
DEFAULT_CHAT_FRAME:AddMessage('/cleveroid testtalent <spellID> - Test talent modifier for a spell')
|
||||
DEFAULT_CHAT_FRAME:AddMessage('/cleveroid diagnosetalent <spellID> - Diagnose talent modifier issues')
|
||||
DEFAULT_CHAT_FRAME:AddMessage("|cffffaa00Equipment Modifiers:|r")
|
||||
DEFAULT_CHAT_FRAME:AddMessage('/cleveroid testequip <spellID> - Test equipment modifier for a spell')
|
||||
DEFAULT_CHAT_FRAME:AddMessage('/cleveroid equipdebug <item name> - Debug item lookup for /equip')
|
||||
DEFAULT_CHAT_FRAME:AddMessage('/cleveroid equiplog - Toggle real-time equip command logging')
|
||||
DEFAULT_CHAT_FRAME:AddMessage("|cffffaa00Reactive Proc Tracking:|r")
|
||||
DEFAULT_CHAT_FRAME:AddMessage('/cleveroid listprocs - Show active reactive ability procs')
|
||||
DEFAULT_CHAT_FRAME:AddMessage('/cleveroid setproc <spell> [duration] - Manually set proc (testing)')
|
||||
DEFAULT_CHAT_FRAME:AddMessage('/cleveroid clearproc [spell|all] - Clear reactive proc(s)')
|
||||
DEFAULT_CHAT_FRAME:AddMessage("|cffffaa00Casting Detection:|r")
|
||||
DEFAULT_CHAT_FRAME:AddMessage('/cleveroid testcasting - Test [selfcasting]/[noselfcasting] conditionals')
|
||||
DEFAULT_CHAT_FRAME:AddMessage('/cleveroid testchannel - Test [channeltime] conditional tracking')
|
||||
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 <slot> - Debug action slot state (tooltip/range/mana)')
|
||||
DEFAULT_CHAT_FRAME:AddMessage('/cleveroid rangedebug <spell> - 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")
|
||||
DEFAULT_CHAT_FRAME:AddMessage('/cleveroid debuffdebug [spell] - Debug debuff tracking on target')
|
||||
return
|
||||
@@ -5422,342 +5402,6 @@ SlashCmdList["CLEVEROID"] = function(msg)
|
||||
return
|
||||
end
|
||||
|
||||
-- macrodebug (toggle macro length warning debug messages)
|
||||
if cmd == "macrodebug" then
|
||||
CleveRoids.MacroLengthDebug = not CleveRoids.MacroLengthDebug
|
||||
CleveRoids.Print("Macro length warning debug " .. (CleveRoids.MacroLengthDebug and "enabled" or "disabled"))
|
||||
return
|
||||
end
|
||||
|
||||
-- macrorefdebug (toggle macro reference execution debug messages)
|
||||
if cmd == "macrorefdebug" or cmd == "refdebug" then
|
||||
CleveRoids.macroRefDebug = not CleveRoids.macroRefDebug
|
||||
CleveRoids.Print("Macro reference debug " .. (CleveRoids.macroRefDebug and "enabled" or "disabled"))
|
||||
CleveRoids.Print("Use /cast [cond] {MacroName} and watch for [MacroRef] messages")
|
||||
return
|
||||
end
|
||||
|
||||
-- cooldowndebug (toggle cooldown update debug messages)
|
||||
if cmd == "cooldowndebug" or cmd == "cddebug" then
|
||||
CleveRoids.cooldownDebug = not CleveRoids.cooldownDebug
|
||||
-- Clear the logged cache when enabling to get fresh output
|
||||
if CleveRoids.cooldownDebug then
|
||||
CleveRoids.cooldownDebugLogged = {}
|
||||
end
|
||||
CleveRoids.Print("Cooldown debug " .. (CleveRoids.cooldownDebug and "enabled" or "disabled"))
|
||||
if CleveRoids.cooldownDebug then
|
||||
CleveRoids.Print("Cast spells with broken cooldowns - issues will be logged once per slot.")
|
||||
CleveRoids.Print("Use /cleveroid slotdebug <slot> for detailed slot info.")
|
||||
local handlerCount = CleveRoids.actionEventHandlers and table.getn(CleveRoids.actionEventHandlers) or 0
|
||||
CleveRoids.Print("Action event handlers: " .. handlerCount .. " (0 = Blizzard UI only)")
|
||||
end
|
||||
return
|
||||
end
|
||||
|
||||
-- slotdebug <slot> - Debug action slot state for tooltip/range/mana issues
|
||||
if cmd == "slotdebug" then
|
||||
local slot = tonumber(val)
|
||||
if not slot then
|
||||
CleveRoids.Print("Usage: /cleveroid slotdebug <slot> - Debug action slot (1-120)")
|
||||
return
|
||||
end
|
||||
local actions = CleveRoids.GetAction(slot)
|
||||
CleveRoids.Print("|cff00ff00=== Slot " .. slot .. " Debug ===|r")
|
||||
if not actions then
|
||||
CleveRoids.Print("No actions data for slot " .. slot)
|
||||
CleveRoids.Print("GetActionText: " .. tostring(GetActionText(slot)))
|
||||
return
|
||||
end
|
||||
CleveRoids.Print("actions.tooltip: " .. tostring(actions.tooltip ~= nil))
|
||||
CleveRoids.Print("actions.explicitTooltip: " .. tostring(actions.explicitTooltip))
|
||||
CleveRoids.Print("actions.list count: " .. tostring(actions.list and table.getn(actions.list) or 0))
|
||||
if actions.active then
|
||||
CleveRoids.Print("|cff00ffffActive action:|r")
|
||||
CleveRoids.Print(" .action: " .. tostring(actions.active.action))
|
||||
CleveRoids.Print(" .type: " .. tostring(actions.active.type))
|
||||
CleveRoids.Print(" .spell: " .. tostring(actions.active.spell ~= nil))
|
||||
if actions.active.spell then
|
||||
CleveRoids.Print(" .spell.name: " .. tostring(actions.active.spell.name))
|
||||
CleveRoids.Print(" .spell.cost: " .. tostring(actions.active.spell.cost))
|
||||
end
|
||||
CleveRoids.Print(" .usable: " .. tostring(actions.active.usable))
|
||||
CleveRoids.Print(" .oom: " .. tostring(actions.active.oom))
|
||||
CleveRoids.Print(" .inRange: " .. tostring(actions.active.inRange))
|
||||
CleveRoids.Print(" .conditionals: " .. tostring(actions.active.conditionals ~= nil))
|
||||
if actions.active.conditionals then
|
||||
CleveRoids.Print(" .target: " .. tostring(actions.active.conditionals.target))
|
||||
end
|
||||
else
|
||||
CleveRoids.Print("|cffff0000No active action|r")
|
||||
end
|
||||
CleveRoids.Print("|cffaaaa00Hook conditions:|r")
|
||||
local hasTooltip = actions.tooltip ~= nil
|
||||
local hasActive = actions.active ~= nil
|
||||
local typeIsSpell = actions.active and actions.active.type == "spell"
|
||||
CleveRoids.Print(" actions.tooltip: " .. tostring(hasTooltip))
|
||||
CleveRoids.Print(" actions.active: " .. tostring(hasActive))
|
||||
CleveRoids.Print(" .type == 'spell': " .. tostring(typeIsSpell))
|
||||
CleveRoids.Print(" Range hook would: " .. (hasTooltip and hasActive and typeIsSpell and "USE CUSTOM" or "FALLBACK"))
|
||||
return
|
||||
end
|
||||
|
||||
-- macrostatus (check macro length warning status)
|
||||
if cmd == "macrostatus" then
|
||||
CleveRoids.Print("|cff00ff00=== MacroLengthWarn Status ===|r")
|
||||
|
||||
-- Check if file loaded
|
||||
if CleveRoids.MacroLengthWarnLoaded then
|
||||
CleveRoids.Print("File: |cff00ff00LOADED|r")
|
||||
else
|
||||
CleveRoids.Print("File: |cffff0000NOT LOADED|r - Check for Lua errors!")
|
||||
end
|
||||
|
||||
-- Check if extension is registered
|
||||
local ext = CleveRoids.Extensions and CleveRoids.Extensions["MacroLengthWarn"]
|
||||
if ext then
|
||||
CleveRoids.Print("Extension: |cff00ff00REGISTERED|r")
|
||||
|
||||
-- Check if OnLoad was called
|
||||
if ext.ShowMessages then
|
||||
CleveRoids.Print("OnLoad: |cff00ff00CALLED|r")
|
||||
|
||||
-- Call the status function
|
||||
ext.ShowMessages()
|
||||
else
|
||||
CleveRoids.Print("OnLoad: |cffff0000NOT CALLED|r")
|
||||
end
|
||||
else
|
||||
CleveRoids.Print("Extension: |cffff0000NOT REGISTERED|r")
|
||||
CleveRoids.Print("The MacroLengthWarn extension failed to register!")
|
||||
end
|
||||
|
||||
-- Check key functions
|
||||
CleveRoids.Print(" ")
|
||||
CleveRoids.Print("Function Status:")
|
||||
CleveRoids.Print(" EditMacro: " .. (EditMacro and "|cff00ff00EXISTS|r" or "|cffff0000MISSING|r"))
|
||||
CleveRoids.Print(" MacroFrame_SaveMacro: " .. (MacroFrame_SaveMacro and "|cff00ff00EXISTS|r" or "|cffffff00NOT LOADED YET|r"))
|
||||
|
||||
return
|
||||
end
|
||||
|
||||
-- channeldebug (toggle channeltime conditional debug)
|
||||
if cmd == "channeldebug" then
|
||||
CleveRoids.ChannelTimeDebug = not CleveRoids.ChannelTimeDebug
|
||||
CleveRoids.Print("Channel time debug " .. (CleveRoids.ChannelTimeDebug and "enabled" or "disabled"))
|
||||
if CleveRoids.ChannelTimeDebug then
|
||||
CleveRoids.Print("You will see messages every time [channeltime] is evaluated")
|
||||
CleveRoids.Print("This shows if your macro is re-evaluating during the channel")
|
||||
end
|
||||
return
|
||||
end
|
||||
|
||||
-- testchannel (debug channel time detection)
|
||||
if cmd == "testchannel" or cmd == "channeltest" then
|
||||
CleveRoids.Print("|cff00ff00=== Channel Time Test ===|r")
|
||||
|
||||
-- Check spell tracking
|
||||
local playerCast = CleveRoids.spell_tracking[CleveRoids.playerGuid]
|
||||
if not playerCast then
|
||||
CleveRoids.Print("|cffffff00No spell tracking data for player|r")
|
||||
CleveRoids.Print("You must be casting or channeling a spell for this to show data")
|
||||
else
|
||||
CleveRoids.Print("Spell tracking found:")
|
||||
CleveRoids.Print(" Type: " .. tostring(playerCast.type))
|
||||
CleveRoids.Print(" Spell ID: " .. tostring(playerCast.spell_id))
|
||||
if playerCast.spell_id and SpellInfo then
|
||||
local spellName = SpellInfo(playerCast.spell_id)
|
||||
CleveRoids.Print(" Spell Name: " .. tostring(spellName))
|
||||
end
|
||||
if playerCast.expires then
|
||||
local timeLeft = playerCast.expires - GetTime()
|
||||
CleveRoids.Print(" Expires at: " .. tostring(playerCast.expires))
|
||||
CleveRoids.Print(" Time left: " .. string.format("%.2f", timeLeft) .. "s")
|
||||
|
||||
-- Test conditionals
|
||||
CleveRoids.Print(" ")
|
||||
CleveRoids.Print("Conditional tests:")
|
||||
CleveRoids.Print(" [channeltime:<0.5]: " .. (timeLeft < 0.5 and "|cff00ff00TRUE|r" or "|cffff0000FALSE|r"))
|
||||
CleveRoids.Print(" [channeltime:<1.0]: " .. (timeLeft < 1.0 and "|cff00ff00TRUE|r" or "|cffff0000FALSE|r"))
|
||||
CleveRoids.Print(" [channeltime:>2.0]: " .. (timeLeft > 2.0 and "|cff00ff00TRUE|r" or "|cffff0000FALSE|r"))
|
||||
else
|
||||
CleveRoids.Print(" Expires: NOT SET")
|
||||
end
|
||||
end
|
||||
|
||||
CleveRoids.Print(" ")
|
||||
CleveRoids.Print("|cff00ffffInstructions:|r")
|
||||
CleveRoids.Print("1. Start channeling Arcane Missiles")
|
||||
CleveRoids.Print("2. Run /cleveroid testchannel while channeling")
|
||||
CleveRoids.Print("3. Check if spell tracking is working")
|
||||
|
||||
CleveRoids.Print("|cff00ff00=== End Test ===|r")
|
||||
return
|
||||
end
|
||||
|
||||
-- rangedebug <spell> - 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 <spell name>")
|
||||
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))
|
||||
else
|
||||
-- Test without target
|
||||
local finalResult = API.IsSpellInRange(spellId, "player")
|
||||
CleveRoids.Print("API.IsSpellInRange (no target, using player): " .. tostring(finalResult))
|
||||
end
|
||||
|
||||
-- Target type detection
|
||||
local targetA = API.GetSpellField(spellId, "effectImplicitTargetA")
|
||||
local targetB = API.GetSpellField(spellId, "effectImplicitTargetB")
|
||||
|
||||
-- Format target data (handle tables)
|
||||
local function formatTarget(t)
|
||||
if not t then return "|cffffff00nil|r" end
|
||||
if type(t) == "table" then
|
||||
local parts = {}
|
||||
for i = 1, 3 do
|
||||
table.insert(parts, tostring(t[i] or 0))
|
||||
end
|
||||
return "{" .. table.concat(parts, ", ") .. "}"
|
||||
end
|
||||
return tostring(t)
|
||||
end
|
||||
|
||||
CleveRoids.Print("effectImplicitTargetA: " .. formatTarget(targetA))
|
||||
CleveRoids.Print("effectImplicitTargetB: " .. formatTarget(targetB))
|
||||
|
||||
local isUnitTargeted = API.IsUnitTargetedSpell(spellId)
|
||||
CleveRoids.Print("Is unit-targeted spell: " .. (isUnitTargeted == true and "|cff00ff00YES|r" or isUnitTargeted == false and "|cffff0000NO|r" or "|cffffff00UNKNOWN|r"))
|
||||
|
||||
-- Self-cast/ground-targeted detection summary
|
||||
local isSelfCast = (isUnitTargeted == false)
|
||||
CleveRoids.Print("Detected as self/ground-targeted: " .. (isSelfCast and "|cff00ff00YES|r" or "|cffff0000NO|r"))
|
||||
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")
|
||||
|
||||
-- Check GetCurrentCastingInfo availability
|
||||
if not GetCurrentCastingInfo then
|
||||
CleveRoids.Print("|cffff0000ERROR: GetCurrentCastingInfo not available!|r")
|
||||
CleveRoids.Print("This requires Nampower to be installed.")
|
||||
return
|
||||
end
|
||||
|
||||
-- Get current casting info
|
||||
local castId, visId, autoId, casting, channeling, onswing, autoattack = GetCurrentCastingInfo()
|
||||
|
||||
CleveRoids.Print("GetCurrentCastingInfo() values:")
|
||||
CleveRoids.Print(" castId: " .. tostring(castId))
|
||||
CleveRoids.Print(" visId: " .. tostring(visId))
|
||||
CleveRoids.Print(" autoId: " .. tostring(autoId))
|
||||
CleveRoids.Print(" casting: " .. tostring(casting))
|
||||
CleveRoids.Print(" channeling: " .. tostring(channeling))
|
||||
CleveRoids.Print(" onswing: " .. tostring(onswing))
|
||||
CleveRoids.Print(" autoattack: " .. tostring(autoattack))
|
||||
|
||||
-- Test conditionals
|
||||
local isCasting = (casting and casting == 1) or false
|
||||
local isChanneling = (channeling and channeling == 1) or false
|
||||
|
||||
CleveRoids.Print(" ")
|
||||
CleveRoids.Print("Conditional results:")
|
||||
CleveRoids.Print(" [selfcasting]: " .. tostring(isCasting or isChanneling))
|
||||
CleveRoids.Print(" [noselfcasting]: " .. tostring(not isCasting and not isChanneling))
|
||||
|
||||
CleveRoids.Print(" ")
|
||||
if isCasting then
|
||||
CleveRoids.Print("|cffff00ffYou ARE currently CASTING|r")
|
||||
elseif isChanneling then
|
||||
CleveRoids.Print("|cffff00ffYou ARE currently CHANNELING|r")
|
||||
else
|
||||
CleveRoids.Print("|cff00ff00You are NOT casting or channeling|r")
|
||||
end
|
||||
|
||||
CleveRoids.Print("|cff00ff00=== End Test ===|r")
|
||||
return
|
||||
end
|
||||
|
||||
-- listimmune (list immunity data)
|
||||
if cmd == "listimmune" or cmd == "immunelist" then
|
||||
CleveRoids.ListImmunities(val ~= "" and val or nil)
|
||||
@@ -5880,43 +5524,6 @@ SlashCmdList["CLEVEROID"] = function(msg)
|
||||
return
|
||||
end
|
||||
|
||||
-- schooltest (test spell school detection)
|
||||
if cmd == "schooltest" or cmd == "testschool" then
|
||||
local input = val
|
||||
if input == "" then
|
||||
CleveRoids.Print("Usage: /cleveroid schooltest <spellID or name>")
|
||||
CleveRoids.Print("Example: /cleveroid schooltest 133")
|
||||
CleveRoids.Print("Example: /cleveroid schooltest Fireball")
|
||||
return
|
||||
end
|
||||
|
||||
local spellID = tonumber(input)
|
||||
local spellName = nil
|
||||
local school = nil
|
||||
|
||||
if spellID then
|
||||
-- Input is a spell ID
|
||||
spellName = SpellInfo and SpellInfo(spellID)
|
||||
school = CleveRoids.GetSpellSchoolByID(spellID)
|
||||
else
|
||||
-- Input is a spell name
|
||||
spellName = input
|
||||
spellID = CleveRoids.GetSpellIdForName and CleveRoids.GetSpellIdForName(spellName)
|
||||
school = CleveRoids.GetSpellSchool(spellName, spellID)
|
||||
end
|
||||
|
||||
CleveRoids.Print("|cff88ff88=== Spell School Test ===|r")
|
||||
CleveRoids.Print("Spell: " .. (spellName or "Unknown") .. " (ID:" .. (spellID or "Unknown") .. ")")
|
||||
CleveRoids.Print("School: " .. (school or "|cffff0000Unknown|r"))
|
||||
|
||||
if spellID and CleveRoids_SpellSchools[spellID] then
|
||||
CleveRoids.Print("|cff00ff00Source:|r Learned from Nampower damage events")
|
||||
elseif school then
|
||||
CleveRoids.Print("|cffffaa00Source:|r Tooltip/pattern matching")
|
||||
end
|
||||
return
|
||||
end
|
||||
|
||||
-- listschools (show learned spell schools)
|
||||
if cmd == "listschools" or cmd == "schools" then
|
||||
CleveRoids.Print("|cff88ff88=== Learned Spell Schools ===|r")
|
||||
@@ -6069,74 +5676,6 @@ SlashCmdList["CLEVEROID"] = function(msg)
|
||||
return
|
||||
end
|
||||
|
||||
-- diagnosetalent (comprehensive diagnostic for talent modifier)
|
||||
if cmd == "diagnosetalent" or cmd == "diagtalent" then
|
||||
local spellID = tonumber(val)
|
||||
if not spellID then
|
||||
CleveRoids.Print("Usage: /cleveroid diagnosetalent <spellID>")
|
||||
CleveRoids.Print("Example: /cleveroid diagnosetalent 1943 (Rupture Rank 1)")
|
||||
return
|
||||
end
|
||||
|
||||
-- Inline diagnostic
|
||||
local baseDuration = 10
|
||||
DEFAULT_CHAT_FRAME:AddMessage("|cff00ff00=== Talent Modifier Diagnostic ===|r")
|
||||
|
||||
local spellName = SpellInfo(spellID)
|
||||
if not spellName then
|
||||
DEFAULT_CHAT_FRAME:AddMessage("|cffff0000ERROR: Invalid spell ID " .. tostring(spellID) .. "|r")
|
||||
return
|
||||
end
|
||||
DEFAULT_CHAT_FRAME:AddMessage("Spell: " .. spellName .. " (ID: " .. spellID .. ")")
|
||||
|
||||
local modifier = CleveRoids.talentModifiers and CleveRoids.talentModifiers[spellID]
|
||||
if not modifier then
|
||||
DEFAULT_CHAT_FRAME:AddMessage("|cffff0000No talent modifier registered for this spell|r")
|
||||
return
|
||||
end
|
||||
|
||||
local talentDesc = modifier.talent or ("Tab " .. tostring(modifier.tab) .. " ID " .. tostring(modifier.id))
|
||||
DEFAULT_CHAT_FRAME:AddMessage("Modifier registered: " .. talentDesc)
|
||||
|
||||
-- Test position-based lookup
|
||||
local talentRank = 0
|
||||
local lookupMethod = "none"
|
||||
|
||||
if modifier.tab and modifier.id then
|
||||
local _, name, _, _, rank = GetTalentInfo(modifier.tab, modifier.id)
|
||||
talentRank = tonumber(rank) or 0
|
||||
lookupMethod = "position"
|
||||
DEFAULT_CHAT_FRAME:AddMessage("|cff00ff00Position lookup (Tab " .. modifier.tab .. ", ID " .. modifier.id .. "):|r")
|
||||
DEFAULT_CHAT_FRAME:AddMessage(" Talent name: " .. tostring(name))
|
||||
DEFAULT_CHAT_FRAME:AddMessage(" Rank: " .. talentRank)
|
||||
end
|
||||
|
||||
if modifier.talent and CleveRoids.GetTalentRank then
|
||||
local nameRank = CleveRoids.GetTalentRank(modifier.talent)
|
||||
DEFAULT_CHAT_FRAME:AddMessage("|cffaaaa00Name lookup (" .. modifier.talent .. "):|r")
|
||||
DEFAULT_CHAT_FRAME:AddMessage(" Rank: " .. nameRank)
|
||||
if talentRank == 0 and nameRank > 0 then
|
||||
talentRank = nameRank
|
||||
lookupMethod = "name"
|
||||
end
|
||||
end
|
||||
|
||||
DEFAULT_CHAT_FRAME:AddMessage("Final rank: " .. talentRank .. " (via " .. lookupMethod .. ")")
|
||||
|
||||
if talentRank > 0 then
|
||||
local modifiedDuration = modifier.modifier(baseDuration, talentRank)
|
||||
DEFAULT_CHAT_FRAME:AddMessage("|cff00ff00Test calculation:|r")
|
||||
DEFAULT_CHAT_FRAME:AddMessage(" Base: " .. baseDuration .. "s")
|
||||
DEFAULT_CHAT_FRAME:AddMessage(" Modified: " .. modifiedDuration .. "s")
|
||||
DEFAULT_CHAT_FRAME:AddMessage(" Bonus: +" .. (modifiedDuration - baseDuration) .. "s")
|
||||
else
|
||||
DEFAULT_CHAT_FRAME:AddMessage("|cffff0000You don't have " .. talentDesc .. "!|r")
|
||||
end
|
||||
|
||||
DEFAULT_CHAT_FRAME:AddMessage("|cff00ff00=== End Diagnostic ===|r")
|
||||
return
|
||||
end
|
||||
|
||||
-- testtalent (test talent modifier for a spell)
|
||||
if cmd == "testtalent" or cmd == "talenttest" then
|
||||
local spellID = tonumber(val)
|
||||
@@ -6190,349 +5729,6 @@ SlashCmdList["CLEVEROID"] = function(msg)
|
||||
return
|
||||
end
|
||||
|
||||
-- testequip (test equipment modifier for a spell)
|
||||
if cmd == "testequip" or cmd == "equiptest" then
|
||||
local spellID = tonumber(val)
|
||||
if not spellID then
|
||||
CleveRoids.Print("Usage: /cleveroid testequip <spellID>")
|
||||
CleveRoids.Print("Example: /cleveroid testequip 1079 (Rip Rank 1)")
|
||||
return
|
||||
end
|
||||
|
||||
local spellName = SpellInfo(spellID) or ("Spell " .. spellID)
|
||||
local modifier = CleveRoids.equipmentModifiers and CleveRoids.equipmentModifiers[spellID]
|
||||
|
||||
if not modifier then
|
||||
CleveRoids.Print(spellName .. " (ID:" .. spellID .. ") has no equipment modifier configured")
|
||||
return
|
||||
end
|
||||
|
||||
local itemID = CleveRoids.GetEquippedItemID and CleveRoids.GetEquippedItemID(modifier.slot)
|
||||
local itemName = "None"
|
||||
if itemID then
|
||||
local itemLink = GetInventoryItemLink("player", modifier.slot)
|
||||
if itemLink then
|
||||
itemName = string.match(itemLink, "%[(.-)%]") or ("Item " .. itemID)
|
||||
end
|
||||
end
|
||||
|
||||
CleveRoids.Print("=== Equipment Modifier Test ===")
|
||||
CleveRoids.Print("Spell: " .. spellName .. " (ID:" .. spellID .. ")")
|
||||
CleveRoids.Print("Slot: " .. modifier.slot .. " (Ranged/Relic)")
|
||||
CleveRoids.Print("Equipped: " .. itemName .. (itemID and (" [" .. itemID .. "]") or ""))
|
||||
|
||||
if not itemID then
|
||||
CleveRoids.Print("|cffff0000No item equipped in this slot!|r")
|
||||
else
|
||||
-- Test with a base duration (use 10s as example)
|
||||
local baseDur = 10
|
||||
local modDur = modifier.modifier(baseDur, itemID)
|
||||
if modDur ~= baseDur then
|
||||
CleveRoids.Print("Example: 10s base -> " .. modDur .. "s modified")
|
||||
if modDur < baseDur then
|
||||
CleveRoids.Print("|cffff0000Duration reduced by " .. (baseDur - modDur) .. "s|r")
|
||||
else
|
||||
CleveRoids.Print("|cff00ff00Duration increased by " .. (modDur - baseDur) .. "s|r")
|
||||
end
|
||||
else
|
||||
CleveRoids.Print("|cffffaa00This item has no effect on this spell|r")
|
||||
end
|
||||
end
|
||||
return
|
||||
end
|
||||
|
||||
-- equiplog (toggle real-time equip logging)
|
||||
if cmd == "equiplog" then
|
||||
CleveRoids.equipDebugLog = not CleveRoids.equipDebugLog
|
||||
CleveRoids.Print("Equip command logging " .. (CleveRoids.equipDebugLog and "|cff00ff00ENABLED|r" or "|cffff0000DISABLED|r"))
|
||||
if CleveRoids.equipDebugLog then
|
||||
CleveRoids.Print("Use /equip commands to see detailed lookup info")
|
||||
end
|
||||
return
|
||||
end
|
||||
|
||||
-- equipdebug (debug item lookup for /equip command)
|
||||
if cmd == "equipdebug" then
|
||||
local itemName = val
|
||||
if val2 and val2 ~= "" then
|
||||
itemName = val .. " " .. val2
|
||||
end
|
||||
if not itemName or itemName == "" then
|
||||
CleveRoids.Print("Usage: /cleveroid equipdebug <item name>")
|
||||
CleveRoids.Print('Example: /cleveroid equipdebug Idol of Ferocity')
|
||||
return
|
||||
end
|
||||
-- Strip quotes if present
|
||||
itemName = string.gsub(itemName, '"', "")
|
||||
itemName = string.gsub(itemName, "_", " ")
|
||||
|
||||
CleveRoids.Print("|cff00ff00=== Equipment Debug: " .. itemName .. " ===|r")
|
||||
|
||||
-- Check equipped slot 18 (relic/idol)
|
||||
local slot18Link = GetInventoryItemLink("player", 18)
|
||||
if slot18Link then
|
||||
local _, _, slot18Name = string.find(slot18Link, "|h%[(.-)%]|h")
|
||||
CleveRoids.Print("Slot 18 equipped: " .. (slot18Name or "unknown"))
|
||||
else
|
||||
CleveRoids.Print("Slot 18 equipped: (empty)")
|
||||
end
|
||||
|
||||
-- Check cache
|
||||
local Items = CleveRoids.Items or {}
|
||||
local cached = Items[itemName]
|
||||
CleveRoids.Print("|cffffaa00Cache lookup:|r")
|
||||
if cached then
|
||||
if type(cached) == "table" then
|
||||
if cached.inventoryID then
|
||||
CleveRoids.Print(" Found in cache: EQUIPPED (inventoryID=" .. cached.inventoryID .. ")")
|
||||
elseif cached.bagID then
|
||||
CleveRoids.Print(" Found in cache: BAG (bag=" .. cached.bagID .. ", slot=" .. cached.slot .. ")")
|
||||
else
|
||||
CleveRoids.Print(" Found in cache: (type unknown)")
|
||||
end
|
||||
elseif type(cached) == "string" then
|
||||
CleveRoids.Print(" Found in cache: -> " .. cached .. " (canonical name)")
|
||||
end
|
||||
else
|
||||
CleveRoids.Print(" Not in cache")
|
||||
end
|
||||
|
||||
-- Try GetItemFast
|
||||
CleveRoids.Print("|cffffaa00GetItemFast:|r")
|
||||
local fastItem = CleveRoids.GetItemFast and CleveRoids.GetItemFast(itemName)
|
||||
if fastItem then
|
||||
if fastItem.inventoryID then
|
||||
CleveRoids.Print(" Returns: EQUIPPED (inventoryID=" .. fastItem.inventoryID .. ")")
|
||||
elseif fastItem.bagID then
|
||||
CleveRoids.Print(" Returns: BAG (bag=" .. fastItem.bagID .. ", slot=" .. fastItem.slot .. ")")
|
||||
end
|
||||
else
|
||||
CleveRoids.Print(" Returns: nil")
|
||||
end
|
||||
|
||||
-- Try FindItemQuick
|
||||
CleveRoids.Print("|cffffaa00FindItemQuick (scans equipped then bags):|r")
|
||||
local quickItem = CleveRoids.FindItemQuick and CleveRoids.FindItemQuick(itemName)
|
||||
if quickItem then
|
||||
if quickItem.inventoryID then
|
||||
CleveRoids.Print(" Returns: EQUIPPED (inventoryID=" .. quickItem.inventoryID .. ")")
|
||||
elseif quickItem.bagID then
|
||||
CleveRoids.Print(" Returns: BAG (bag=" .. quickItem.bagID .. ", slot=" .. quickItem.slot .. ")")
|
||||
end
|
||||
else
|
||||
CleveRoids.Print(" Returns: nil (item not found)")
|
||||
end
|
||||
|
||||
-- Check HasGearEquipped (used by [equipped] conditional)
|
||||
CleveRoids.Print("|cffffaa00HasGearEquipped (conditional check):|r")
|
||||
local hasEquipped = CleveRoids.HasGearEquipped and CleveRoids.HasGearEquipped(itemName)
|
||||
CleveRoids.Print(" [equipped:" .. itemName .. "] = " .. (hasEquipped and "|cff00ff00TRUE|r" or "|cffff0000FALSE|r"))
|
||||
|
||||
-- Combat state
|
||||
CleveRoids.Print("|cffffaa00Combat state:|r")
|
||||
CleveRoids.Print(" UnitAffectingCombat: " .. (UnitAffectingCombat("player") and "IN COMBAT" or "not in combat"))
|
||||
CleveRoids.Print(" playerClass: " .. (CleveRoids.playerClass or "unknown"))
|
||||
|
||||
return
|
||||
end
|
||||
|
||||
-- listprocs (show active reactive procs)
|
||||
if cmd == "listprocs" or cmd == "procs" or cmd == "reactive" then
|
||||
CleveRoids.Print("=== Active Reactive Procs ===")
|
||||
local found = false
|
||||
local now = GetTime()
|
||||
local _, currentTargetGUID = UnitExists("target")
|
||||
|
||||
if CleveRoids.reactiveProcs then
|
||||
for spellName, procData in pairs(CleveRoids.reactiveProcs) do
|
||||
if procData and procData.expiry and procData.expiry > now then
|
||||
local remaining = procData.expiry - now
|
||||
local guidInfo = ""
|
||||
|
||||
if procData.targetGUID then
|
||||
local matches = currentTargetGUID and (currentTargetGUID == procData.targetGUID)
|
||||
if matches then
|
||||
guidInfo = " |cff00ff00[Current Target]|r"
|
||||
else
|
||||
local targetName = UnitName("target")
|
||||
if targetName then
|
||||
guidInfo = " |cffff0000[Wrong Target: " .. targetName .. "]|r"
|
||||
else
|
||||
guidInfo = " |cffff0000[No Target]|r"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
CleveRoids.Print(spellName .. ": " .. string.format("%.1fs", remaining) .. " remaining" .. guidInfo)
|
||||
found = true
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if not found then
|
||||
CleveRoids.Print("|cffffaa00No active reactive procs|r")
|
||||
end
|
||||
return
|
||||
end
|
||||
|
||||
-- setproc (manually set a reactive proc for testing)
|
||||
if cmd == "setproc" or cmd == "procset" then
|
||||
if val == "" then
|
||||
CleveRoids.Print("Usage: /cleveroid setproc <spell> [duration]")
|
||||
CleveRoids.Print("Example: /cleveroid setproc Overpower 5")
|
||||
CleveRoids.Print("Note: Uses current target's GUID for target-specific procs")
|
||||
return
|
||||
end
|
||||
|
||||
local duration = tonumber(val2) or 5.0
|
||||
local _, targetGUID = UnitExists("target")
|
||||
|
||||
if CleveRoids.SetReactiveProc then
|
||||
CleveRoids.SetReactiveProc(val, duration, targetGUID)
|
||||
local guidMsg = targetGUID and (" for target [" .. (UnitName("target") or "Unknown") .. "]") or ""
|
||||
CleveRoids.Print("Set " .. val .. " proc for " .. duration .. " seconds" .. guidMsg)
|
||||
else
|
||||
CleveRoids.Print("|cffff0000Reactive proc system not loaded!|r")
|
||||
end
|
||||
return
|
||||
end
|
||||
|
||||
-- clearproc (clear a reactive proc)
|
||||
if cmd == "clearproc" or cmd == "procclear" then
|
||||
if val == "" or val == "all" then
|
||||
CleveRoids.reactiveProcs = {}
|
||||
CleveRoids.Print("Cleared all reactive procs")
|
||||
else
|
||||
if CleveRoids.ClearReactiveProc then
|
||||
CleveRoids.ClearReactiveProc(val)
|
||||
CleveRoids.Print("Cleared " .. val .. " proc")
|
||||
else
|
||||
CleveRoids.Print("|cffff0000Reactive proc system not loaded!|r")
|
||||
end
|
||||
end
|
||||
CleveRoids.QueueActionUpdate()
|
||||
return
|
||||
end
|
||||
|
||||
-- slamdebug (show Slam cast time and window calculations for Warrior rotation)
|
||||
if cmd == "slamdebug" or cmd == "slam" or cmd == "slamtime" then
|
||||
CleveRoids.Print("|cff88ff88=== Slam Clip Window Debug ===|r")
|
||||
|
||||
-- Get swing timer info
|
||||
local attackSpeed = UnitAttackSpeed("player")
|
||||
if not attackSpeed or attackSpeed <= 0 then
|
||||
CleveRoids.Print("|cffff0000No attack speed available!|r")
|
||||
CleveRoids.Print("You need to be in combat or have a weapon equipped.")
|
||||
return
|
||||
end
|
||||
|
||||
-- Check SP_SwingTimer
|
||||
if st_timer == nil then
|
||||
CleveRoids.Print("|cffff0000SP_SwingTimer not detected!|r")
|
||||
CleveRoids.Print("The [noslamclip] conditionals require SP_SwingTimer addon.")
|
||||
CleveRoids.Print("Get it at: https://github.com/jrc13245/SP_SwingTimer")
|
||||
else
|
||||
local timeElapsed = attackSpeed - st_timer
|
||||
local percentElapsed = (timeElapsed / attackSpeed) * 100
|
||||
CleveRoids.Print("|cffffaa00SP_SwingTimer:|r st_timer=" .. string.format("%.3f", st_timer) .. "s")
|
||||
CleveRoids.Print("Swing elapsed: " .. string.format("%.2f", percentElapsed) .. "%")
|
||||
end
|
||||
|
||||
CleveRoids.Print(" ")
|
||||
CleveRoids.Print("|cffffaa00Swing Timer:|r " .. string.format("%.3f", attackSpeed) .. "s")
|
||||
|
||||
-- Get Slam cast time from tooltip scanning
|
||||
local slamCastTime = CleveRoids.GetSlamCastTime()
|
||||
local isDefault = (slamCastTime == 1.5)
|
||||
|
||||
CleveRoids.Print("|cffffaa00Slam Cast Time:|r " .. string.format("%.3f", slamCastTime) .. "s" .. (isDefault and " (default)" or " (from tooltip)"))
|
||||
|
||||
-- Show tooltip scanning diagnostic info
|
||||
if CleveRoids.GetSlamSpellSlot then
|
||||
local slot = CleveRoids.GetSlamSpellSlot()
|
||||
if slot then
|
||||
CleveRoids.Print(" Slam found in spellbook slot: " .. slot)
|
||||
else
|
||||
CleveRoids.Print(" |cffff0000Slam not found in spellbook!|r Are you a Warrior?")
|
||||
end
|
||||
end
|
||||
|
||||
if isDefault then
|
||||
CleveRoids.Print(" Note: Could not read from tooltip, using default 1.5s")
|
||||
end
|
||||
|
||||
-- Calculate windows
|
||||
CleveRoids.Print(" ")
|
||||
local slamWindowTime = attackSpeed - slamCastTime
|
||||
local slamWindow = 0
|
||||
if slamWindowTime > 0 then
|
||||
slamWindow = (slamWindowTime / attackSpeed) * 100
|
||||
end
|
||||
|
||||
local instantWindowTime = (2 * attackSpeed) - slamCastTime - 1.5
|
||||
local instantWindow = 0
|
||||
if instantWindowTime > 0 then
|
||||
instantWindow = (instantWindowTime / attackSpeed) * 100
|
||||
end
|
||||
|
||||
CleveRoids.Print("|cff00ff00=== Window Calculations ===|r")
|
||||
CleveRoids.Print("|cffffaa00Slam Window:|r " .. string.format("%.2f", slamWindow) .. "%")
|
||||
CleveRoids.Print(" Formula: (SwingTimer - SlamCast) / SwingTimer")
|
||||
CleveRoids.Print(" (" .. string.format("%.3f", attackSpeed) .. " - " .. string.format("%.3f", slamCastTime) .. ") / " .. string.format("%.3f", attackSpeed) .. " = " .. string.format("%.2f", slamWindow) .. "%")
|
||||
CleveRoids.Print(" Max time to cast Slam: " .. string.format("%.3f", slamWindowTime) .. "s into swing")
|
||||
|
||||
CleveRoids.Print(" ")
|
||||
CleveRoids.Print("|cffffaa00Instant Window:|r " .. string.format("%.2f", instantWindow) .. "%")
|
||||
CleveRoids.Print(" Formula: (2×SwingTimer - SlamCast - GCD) / SwingTimer")
|
||||
CleveRoids.Print(" (2×" .. string.format("%.3f", attackSpeed) .. " - " .. string.format("%.3f", slamCastTime) .. " - 1.5) / " .. string.format("%.3f", attackSpeed) .. " = " .. string.format("%.2f", instantWindow) .. "%")
|
||||
CleveRoids.Print(" Max time to cast instant: " .. string.format("%.3f", instantWindowTime) .. "s into swing")
|
||||
|
||||
-- Show current status
|
||||
if st_timer ~= nil then
|
||||
CleveRoids.Print(" ")
|
||||
CleveRoids.Print("|cff00ff00=== Current Status ===|r")
|
||||
local timeElapsed = attackSpeed - st_timer
|
||||
local percentElapsed = (timeElapsed / attackSpeed) * 100
|
||||
local inSlamWindow = percentElapsed <= slamWindow
|
||||
local inInstantWindow = percentElapsed <= instantWindow
|
||||
CleveRoids.Print("[noslamclip]: " .. (inSlamWindow and "|cff00ff00TRUE|r (safe to Slam)" or "|cffff0000FALSE|r (would clip)"))
|
||||
CleveRoids.Print("[nonextslamclip]: " .. (inInstantWindow and "|cff00ff00TRUE|r (safe to instant)" or "|cffff0000FALSE|r (would clip next Slam)"))
|
||||
end
|
||||
|
||||
return
|
||||
end
|
||||
|
||||
-- formdebug (debug shapeshift form detection)
|
||||
if cmd == "formdebug" or cmd == "form" or cmd == "shapeshiftdebug" then
|
||||
CleveRoids.Print("|cff88ff88=== Shapeshift Form Debug ===|r")
|
||||
CleveRoids.Print("Player class: " .. tostring(CleveRoids.playerClass))
|
||||
|
||||
local numForms = GetNumShapeshiftForms()
|
||||
CleveRoids.Print("Number of forms: " .. tostring(numForms))
|
||||
|
||||
local currentIndex = CleveRoids.GetCurrentShapeshiftIndex()
|
||||
CleveRoids.Print("Current form index: " .. tostring(currentIndex))
|
||||
|
||||
CleveRoids.Print(" ")
|
||||
CleveRoids.Print("|cff00ff00=== Form Details ===|r")
|
||||
for i = 1, numForms do
|
||||
local icon, name, isActive, isCastable = GetShapeshiftFormInfo(i)
|
||||
local activeStr = isActive and "|cff00ff00ACTIVE|r" or "|cff888888inactive|r"
|
||||
local castableStr = isCastable and "castable" or "not castable"
|
||||
CleveRoids.Print(string.format("Form %d: %s - %s (%s)", i, tostring(name), activeStr, castableStr))
|
||||
end
|
||||
|
||||
CleveRoids.Print(" ")
|
||||
CleveRoids.Print("|cff00ff00=== ValidatePlayerBuff Tests ===|r")
|
||||
local testForms = {"Cat Form", "Bear Form", "Dire Bear Form", "Travel Form", "Aquatic Form", "Moonkin Form"}
|
||||
for _, formName in ipairs(testForms) do
|
||||
local result = CleveRoids.ValidatePlayerBuff(formName)
|
||||
local resultStr = result and "|cff00ff00true|r" or "|cffff0000false|r"
|
||||
CleveRoids.Print(" ValidatePlayerBuff('" .. formName .. "') = " .. resultStr)
|
||||
end
|
||||
return
|
||||
end
|
||||
|
||||
-- debuffdebug (debug debuff tracking on target)
|
||||
if cmd == "debuffdebug" or cmd == "debuff" or cmd == "trackdebug" then
|
||||
local searchName = val
|
||||
@@ -6687,85 +5883,6 @@ SlashCmdList["CLEVEROID"] = function(msg)
|
||||
return
|
||||
end
|
||||
|
||||
-- tooltipdebug (debug spell tooltip scanning)
|
||||
if cmd == "tooltipdebug" or cmd == "ttdebug" or cmd == "spelltooltip" then
|
||||
local spellName = val
|
||||
if val2 and val2 ~= "" then
|
||||
spellName = val .. " " .. val2
|
||||
end
|
||||
if not spellName or spellName == "" then
|
||||
spellName = "Arcane Missiles" -- Default to Arcane Missiles
|
||||
end
|
||||
-- Strip underscores
|
||||
spellName = string.gsub(spellName, "_", " ")
|
||||
|
||||
CleveRoids.Print("|cff88ff88=== Tooltip Scan Debug: " .. spellName .. " ===|r")
|
||||
|
||||
-- Find highest rank spell in spellbook (same logic as GetSpellSlotByName)
|
||||
local slot, bookType = nil, nil
|
||||
local foundRank = nil
|
||||
local i = 1
|
||||
while true do
|
||||
local name, rank = GetSpellName(i, BOOKTYPE_SPELL)
|
||||
if not name then break end
|
||||
if name == spellName then
|
||||
-- Keep updating to find the last (highest) rank
|
||||
slot = i
|
||||
bookType = BOOKTYPE_SPELL
|
||||
foundRank = rank
|
||||
end
|
||||
i = i + 1
|
||||
end
|
||||
|
||||
if not slot then
|
||||
CleveRoids.Print("|cffff0000Spell not found in spellbook!|r")
|
||||
return
|
||||
end
|
||||
|
||||
CleveRoids.Print("Found in spellbook slot: " .. slot .. " (rank: " .. (foundRank or "none") .. ")")
|
||||
|
||||
-- Create tooltip if needed
|
||||
if not CleveRoidsDebugTooltip then
|
||||
CreateFrame("GameTooltip", "CleveRoidsDebugTooltip", nil, "GameTooltipTemplate")
|
||||
CleveRoidsDebugTooltip:SetOwner(WorldFrame, "ANCHOR_NONE")
|
||||
end
|
||||
|
||||
CleveRoidsDebugTooltip:ClearLines()
|
||||
CleveRoidsDebugTooltip:SetSpell(slot, bookType)
|
||||
|
||||
CleveRoids.Print("Tooltip lines (" .. CleveRoidsDebugTooltip:NumLines() .. "):")
|
||||
for lineNum = 1, CleveRoidsDebugTooltip:NumLines() do
|
||||
local leftText = getglobal("CleveRoidsDebugTooltipTextLeft" .. lineNum)
|
||||
local rightText = getglobal("CleveRoidsDebugTooltipTextRight" .. lineNum)
|
||||
|
||||
local leftStr = leftText and leftText:GetText() or ""
|
||||
local rightStr = rightText and rightText:GetText() or ""
|
||||
|
||||
if leftStr and leftStr ~= "" then
|
||||
CleveRoids.Print(" L" .. lineNum .. ": " .. leftStr)
|
||||
-- Check for duration pattern
|
||||
local duration = string.match(leftStr, "for (%d+%.?%d*) sec")
|
||||
if duration then
|
||||
CleveRoids.Print(" |cff00ff00^ Found 'for X sec': " .. duration .. "s|r")
|
||||
end
|
||||
local duration2 = string.match(leftStr, "over (%d+%.?%d*) sec")
|
||||
if duration2 then
|
||||
CleveRoids.Print(" |cff00ff00^ Found 'over X sec': " .. duration2 .. "s|r")
|
||||
end
|
||||
end
|
||||
if rightStr and rightStr ~= "" then
|
||||
CleveRoids.Print(" R" .. lineNum .. ": " .. rightStr)
|
||||
end
|
||||
end
|
||||
|
||||
-- Show what GetSpellDurationFromTooltip returns
|
||||
local cachedDuration = CleveRoids.GetSpellDurationFromTooltip and CleveRoids.GetSpellDurationFromTooltip(spellName)
|
||||
CleveRoids.Print(" ")
|
||||
CleveRoids.Print("GetSpellDurationFromTooltip result: " .. (cachedDuration and (cachedDuration .. "s") or "|cffff0000nil|r"))
|
||||
|
||||
return
|
||||
end
|
||||
|
||||
-- Unknown command fallback
|
||||
CleveRoids.Print("Usage:")
|
||||
DEFAULT_CHAT_FRAME:AddMessage("/cleveroid - Show current settings")
|
||||
|
||||
@@ -68,6 +68,7 @@ All conditionals support negation with `no` prefix (e.g., `[nocombat]`, `[nobuff
|
||||
| `group` | `[group]` `[group:party/raid]` | Player in group type |
|
||||
| `resting` | `[resting]` | In rest area |
|
||||
| `swimming` | `[swimming]` | Can use aquatic form |
|
||||
| `moving` | `[moving]` `[moving:>100]` | Moving / speed % (MonkeySpeed) |
|
||||
| `zone` | `[zone:"Ironforge"]` | Current zone name |
|
||||
|
||||
### Resources
|
||||
@@ -200,6 +201,7 @@ All conditionals support negation with `no` prefix (e.g., `[nocombat]`, `[nobuff
|
||||
| `ttk` | TimeToKill | `[ttk:<10]` | Time to kill (seconds) |
|
||||
| `tte` | TimeToKill | `[tte:<5]` | Time to execute (20% HP) |
|
||||
| `cursive` | Cursive | `[cursive:Rake>3]` | GUID debuff tracking |
|
||||
| `moving` | MonkeySpeed | `[moving:>100]` | Speed % (100=normal run) |
|
||||
|
||||
### Warrior Slam Conditionals
|
||||
For optimizing Slam rotations without clipping auto-attacks:
|
||||
@@ -552,6 +554,39 @@ The addon checks debuffs on the target:
|
||||
- Works at debuff cap
|
||||
- More accurate timing
|
||||
|
||||
### MonkeySpeed Integration (`[moving]`)
|
||||
|
||||
[MonkeySpeed](https://github.com/jrc13245/MonkeySpeed) provides accurate movement speed detection via SuperWoW's `UnitPosition` API:
|
||||
|
||||
```lua
|
||||
-- Only cast if standing still
|
||||
/cast [nomoving] Aimed Shot
|
||||
|
||||
-- Cast instant ability while moving
|
||||
/cast [moving] Arcane Shot
|
||||
|
||||
-- Check speed percentage (100 = normal run speed)
|
||||
/cast [moving:>100] Sprint -- Already faster than normal
|
||||
/cast [moving:<50] Escape Artist -- Currently slowed
|
||||
|
||||
-- Combined with other conditionals
|
||||
/cast [nomoving, harm] Aimed Shot
|
||||
/cast [moving, harm] Arcane Shot
|
||||
```
|
||||
|
||||
**Speed Reference:**
|
||||
| Speed | Description |
|
||||
|-------|-------------|
|
||||
| `0` | Standing still |
|
||||
| `100` | Normal run speed |
|
||||
| `160` | Level 40 mount |
|
||||
| `200` | Epic mount |
|
||||
|
||||
**Notes:**
|
||||
- Basic `[moving]`/`[nomoving]` works without MonkeySpeed (position fallback)
|
||||
- Speed comparisons (`[moving:>100]`) require MonkeySpeed addon
|
||||
- Speed values vary with buffs/debuffs affecting movement
|
||||
|
||||
### Recommended DoT Macro Patterns
|
||||
|
||||
**Druid Feral (with Cursive):**
|
||||
@@ -612,7 +647,7 @@ The addon checks debuffs on the target:
|
||||
|
||||
**Action Bars:** Blizzard, [pfUI](https://github.com/jrc13245/pfUI), Bongos, Discord Action Bars
|
||||
|
||||
**Integrations:** SP_SwingTimer, TWThreat, TimeToKill, QuickHeal, Cursive (with mouseover support for DoT timer bars), ClassicFocus, SuperMacro
|
||||
**Integrations:** SP_SwingTimer, TWThreat, TimeToKill, QuickHeal, Cursive (with mouseover support for DoT timer bars), ClassicFocus, SuperMacro, MonkeySpeed
|
||||
|
||||
> **Note:** For pfUI users, the [jrc13245/pfUI fork](https://github.com/jrc13245/pfUI) includes native SuperCleveRoidMacros integration for proper cooldown, icon, and tooltip display on conditional macros.
|
||||
|
||||
|
||||
Reference in New Issue
Block a user