mirror of
https://github.com/brues-code/SuperCleveRoidMacros.git
synced 2026-09-16 03:38:00 +00:00
use pfui swingtimer if SP not available, fix vanish regeant count
This commit is contained in:
+72
-75
@@ -2111,33 +2111,66 @@ function CleveRoids.ValidateComboPoints(operator, amount)
|
||||
return false
|
||||
end
|
||||
|
||||
-- Validates swing timer percentage for SP_SwingTimer addon integration
|
||||
-- Returns percent of swing elapsed (0-100) from best available source, or nil
|
||||
-- Priority: 1) SP_SwingTimer, 2) pfUI swing timer module
|
||||
function CleveRoids.GetSwingPercentElapsed()
|
||||
-- Priority 1: SP_SwingTimer
|
||||
if st_timer ~= nil then
|
||||
local attackSpeed = st_timerMax or UnitAttackSpeed("player")
|
||||
if attackSpeed and attackSpeed > 0 then
|
||||
return ((attackSpeed - st_timer) / attackSpeed) * 100
|
||||
end
|
||||
end
|
||||
|
||||
-- Priority 2: pfUI swing timer
|
||||
if pfUI and pfUI.swingtimer and pfUI.swingtimer.mainhand
|
||||
and pfUI.swingtimer.mainhand:IsShown() then
|
||||
return pfUI.swingtimer.mainhand:GetValue() * 100
|
||||
end
|
||||
|
||||
return nil
|
||||
end
|
||||
|
||||
-- Returns timeRemaining, swingSpeed from best available source, or nil, nil
|
||||
-- Priority: 1) SP_SwingTimer, 2) pfUI swing timer + GetUnitField
|
||||
function CleveRoids.GetSwingTimerRaw()
|
||||
-- Priority 1: SP_SwingTimer
|
||||
if st_timer ~= nil and st_timerMax ~= nil then
|
||||
return st_timer, st_timerMax
|
||||
end
|
||||
|
||||
-- Priority 2: pfUI swing timer + GetUnitField
|
||||
if pfUI and pfUI.swingtimer and pfUI.swingtimer.mainhand
|
||||
and pfUI.swingtimer.mainhand:IsShown() and GetUnitField then
|
||||
local mhSpeed = GetUnitField("player", "baseAttackTime")
|
||||
if mhSpeed and mhSpeed > 0 then
|
||||
local swingSpeed = mhSpeed / 1000
|
||||
local progress = pfUI.swingtimer.mainhand:GetValue()
|
||||
local timeRemaining = (1 - progress) * swingSpeed
|
||||
return timeRemaining, swingSpeed
|
||||
end
|
||||
end
|
||||
|
||||
return nil, nil
|
||||
end
|
||||
|
||||
-- Validates swing timer percentage for SP_SwingTimer / pfUI integration
|
||||
-- operator: Comparison operator (>, <, =, >=, <=, ~=)
|
||||
-- amount: Percentage of swing time elapsed (e.g., 20 means 20% of swing has elapsed)
|
||||
-- returns: True if percentElapsed [operator] amount
|
||||
function CleveRoids.ValidateSwingTimer(operator, amount)
|
||||
if not operator or not amount then return false end
|
||||
|
||||
-- Check if SP_SwingTimer is loaded by checking for st_timer global
|
||||
if st_timer == nil then
|
||||
local percentElapsed = CleveRoids.GetSwingPercentElapsed()
|
||||
if percentElapsed == nil then
|
||||
-- Only show error once per session
|
||||
if not CleveRoids._swingTimerErrorShown then
|
||||
DEFAULT_CHAT_FRAME:AddMessage("|cffff0000[SuperCleveRoidMacros]|r The [swingtimer] conditional requires the SP_SwingTimer addon. Get it at: https://github.com/jrc13245/SP_SwingTimer", 1, 0.5, 0.5)
|
||||
DEFAULT_CHAT_FRAME:AddMessage("|cffff0000[SuperCleveRoidMacros]|r The [swingtimer] conditional requires SP_SwingTimer or pfUI (swing timer module). Get SP_SwingTimer at: https://github.com/jrc13245/SP_SwingTimer", 1, 0.5, 0.5)
|
||||
CleveRoids._swingTimerErrorShown = true
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
-- Get player's attack speed (main hand)
|
||||
local attackSpeed = UnitAttackSpeed("player")
|
||||
if not attackSpeed or attackSpeed <= 0 then return false end
|
||||
|
||||
-- Calculate percentage of swing elapsed
|
||||
-- st_timer counts down from attackSpeed to 0 (time remaining)
|
||||
-- So: timeElapsed = attackSpeed - st_timer
|
||||
local timeElapsed = attackSpeed - st_timer
|
||||
local percentElapsed = (timeElapsed / attackSpeed) * 100
|
||||
|
||||
-- Compare percent elapsed against threshold
|
||||
if CleveRoids.operators[operator] then
|
||||
return CleveRoids.comparators[operator](percentElapsed, amount)
|
||||
@@ -2261,9 +2294,10 @@ end
|
||||
-- IMPORTANT: Uses st_timerMax (SP_SwingTimer's adjusted swing timer) not UnitAttackSpeed
|
||||
-- because Flurry and other buffs modify st_timerMax but not UnitAttackSpeed
|
||||
function CleveRoids.GetSlamWindowPercent()
|
||||
-- Use st_timerMax from SP_SwingTimer (accounts for Flurry)
|
||||
-- Fall back to UnitAttackSpeed if st_timerMax not available
|
||||
local attackSpeed = st_timerMax or UnitAttackSpeed("player")
|
||||
-- Use swing speed from best available source (SP_SwingTimer or pfUI)
|
||||
-- Fall back to UnitAttackSpeed if neither available
|
||||
local _, swingSpeed = CleveRoids.GetSwingTimerRaw()
|
||||
local attackSpeed = swingSpeed or UnitAttackSpeed("player")
|
||||
if not attackSpeed or attackSpeed <= 0 then return 0 end
|
||||
|
||||
local slamCastTime = CleveRoids.GetSlamCastTime()
|
||||
@@ -2278,8 +2312,9 @@ end
|
||||
-- Scenario: No Slam this swing, cast instant, then Slam next swing without clipping
|
||||
-- Formula: MaxInstantPercent = (2 * SwingTimer - SlamCastTime - GCD) / SwingTimer * 100
|
||||
function CleveRoids.GetInstantWindowPercent()
|
||||
-- Use st_timerMax from SP_SwingTimer (accounts for Flurry)
|
||||
local attackSpeed = st_timerMax or UnitAttackSpeed("player")
|
||||
-- Use swing speed from best available source (SP_SwingTimer or pfUI)
|
||||
local _, swingSpeed = CleveRoids.GetSwingTimerRaw()
|
||||
local attackSpeed = swingSpeed or UnitAttackSpeed("player")
|
||||
if not attackSpeed or attackSpeed <= 0 then return 0 end
|
||||
|
||||
local slamCastTime = CleveRoids.GetSlamCastTime()
|
||||
@@ -2293,46 +2328,32 @@ end
|
||||
-- Validate if current swing timer is within the Slam window (no clip)
|
||||
-- Returns true if casting Slam NOW will NOT clip the auto-attack
|
||||
function CleveRoids.ValidateNoSlamClip()
|
||||
-- Check if SP_SwingTimer is loaded (st_timer and st_timerMax are global)
|
||||
if st_timer == nil or st_timerMax == nil then
|
||||
local percentElapsed = CleveRoids.GetSwingPercentElapsed()
|
||||
if percentElapsed == nil then
|
||||
if not CleveRoids._slamClipErrorShown then
|
||||
DEFAULT_CHAT_FRAME:AddMessage("|cffff0000[SuperCleveRoidMacros]|r The [noslamclip] conditional requires the SP_SwingTimer addon. Get it at: https://github.com/jrc13245/SP_SwingTimer", 1, 0.5, 0.5)
|
||||
DEFAULT_CHAT_FRAME:AddMessage("|cffff0000[SuperCleveRoidMacros]|r The [noslamclip] conditional requires SP_SwingTimer or pfUI (swing timer module). Get SP_SwingTimer at: https://github.com/jrc13245/SP_SwingTimer", 1, 0.5, 0.5)
|
||||
CleveRoids._slamClipErrorShown = true
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
-- Use st_timerMax (Flurry-adjusted) not UnitAttackSpeed (base speed)
|
||||
local attackSpeed = st_timerMax
|
||||
if not attackSpeed or attackSpeed <= 0 then return false end
|
||||
|
||||
local timeElapsed = attackSpeed - st_timer
|
||||
local percentElapsed = (timeElapsed / attackSpeed) * 100
|
||||
local maxPercent = CleveRoids.GetSlamWindowPercent()
|
||||
|
||||
return percentElapsed <= maxPercent
|
||||
end
|
||||
|
||||
-- Validate if current swing timer is within the instant window for next Slam
|
||||
-- Returns true if casting an instant NOW will NOT cause the NEXT Slam to clip
|
||||
function CleveRoids.ValidateNoNextSlamClip()
|
||||
-- Check if SP_SwingTimer is loaded (st_timer and st_timerMax are global)
|
||||
if st_timer == nil or st_timerMax == nil then
|
||||
local percentElapsed = CleveRoids.GetSwingPercentElapsed()
|
||||
if percentElapsed == nil then
|
||||
if not CleveRoids._slamClipErrorShown then
|
||||
DEFAULT_CHAT_FRAME:AddMessage("|cffff0000[SuperCleveRoidMacros]|r The [nonextslamclip] conditional requires the SP_SwingTimer addon. Get it at: https://github.com/jrc13245/SP_SwingTimer", 1, 0.5, 0.5)
|
||||
DEFAULT_CHAT_FRAME:AddMessage("|cffff0000[SuperCleveRoidMacros]|r The [nonextslamclip] conditional requires SP_SwingTimer or pfUI (swing timer module). Get SP_SwingTimer at: https://github.com/jrc13245/SP_SwingTimer", 1, 0.5, 0.5)
|
||||
CleveRoids._slamClipErrorShown = true
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
-- Use st_timerMax (Flurry-adjusted) not UnitAttackSpeed (base speed)
|
||||
local attackSpeed = st_timerMax
|
||||
if not attackSpeed or attackSpeed <= 0 then return false end
|
||||
|
||||
local timeElapsed = attackSpeed - st_timer
|
||||
local percentElapsed = (timeElapsed / attackSpeed) * 100
|
||||
local maxPercent = CleveRoids.GetInstantWindowPercent()
|
||||
|
||||
return percentElapsed <= maxPercent
|
||||
end
|
||||
|
||||
@@ -6950,21 +6971,15 @@ CleveRoids.Keywords = {
|
||||
|
||||
-- Handle multi-comparison (e.g., >50&<80)
|
||||
if args.comparisons and type(args.comparisons) == "table" then
|
||||
-- Check if SP_SwingTimer is loaded
|
||||
if st_timer == nil then
|
||||
local percentElapsed = CleveRoids.GetSwingPercentElapsed()
|
||||
if percentElapsed == nil then
|
||||
if not CleveRoids._swingTimerErrorShown then
|
||||
DEFAULT_CHAT_FRAME:AddMessage("|cffff0000[SuperCleveRoidMacros]|r The [swingtimer] conditional requires the SP_SwingTimer addon. Get it at: https://github.com/jrc13245/SP_SwingTimer", 1, 0.5, 0.5)
|
||||
DEFAULT_CHAT_FRAME:AddMessage("|cffff0000[SuperCleveRoidMacros]|r The [swingtimer] conditional requires SP_SwingTimer or pfUI (swing timer module). Get SP_SwingTimer at: https://github.com/jrc13245/SP_SwingTimer", 1, 0.5, 0.5)
|
||||
CleveRoids._swingTimerErrorShown = true
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
local attackSpeed = UnitAttackSpeed("player")
|
||||
if not attackSpeed or attackSpeed <= 0 then return false end
|
||||
|
||||
local timeElapsed = attackSpeed - st_timer
|
||||
local percentElapsed = (timeElapsed / attackSpeed) * 100
|
||||
|
||||
-- ALL comparisons must pass (AND logic)
|
||||
for _, comp in ipairs(args.comparisons) do
|
||||
if not CleveRoids.operators[comp.operator] then
|
||||
@@ -6988,21 +7003,15 @@ CleveRoids.Keywords = {
|
||||
|
||||
-- Handle multi-comparison (e.g., >50&<80)
|
||||
if args.comparisons and type(args.comparisons) == "table" then
|
||||
-- Check if SP_SwingTimer is loaded
|
||||
if st_timer == nil then
|
||||
local percentElapsed = CleveRoids.GetSwingPercentElapsed()
|
||||
if percentElapsed == nil then
|
||||
if not CleveRoids._swingTimerErrorShown then
|
||||
DEFAULT_CHAT_FRAME:AddMessage("|cffff0000[SuperCleveRoidMacros]|r The [swingtimer] conditional requires the SP_SwingTimer addon. Get it at: https://github.com/jrc13245/SP_SwingTimer", 1, 0.5, 0.5)
|
||||
DEFAULT_CHAT_FRAME:AddMessage("|cffff0000[SuperCleveRoidMacros]|r The [swingtimer] conditional requires SP_SwingTimer or pfUI (swing timer module). Get SP_SwingTimer at: https://github.com/jrc13245/SP_SwingTimer", 1, 0.5, 0.5)
|
||||
CleveRoids._swingTimerErrorShown = true
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
local attackSpeed = UnitAttackSpeed("player")
|
||||
if not attackSpeed or attackSpeed <= 0 then return false end
|
||||
|
||||
local timeElapsed = attackSpeed - st_timer
|
||||
local percentElapsed = (timeElapsed / attackSpeed) * 100
|
||||
|
||||
-- ALL comparisons must pass (AND logic)
|
||||
for _, comp in ipairs(args.comparisons) do
|
||||
if not CleveRoids.operators[comp.operator] then
|
||||
@@ -7026,21 +7035,15 @@ CleveRoids.Keywords = {
|
||||
|
||||
-- Handle multi-comparison by checking positive and negating
|
||||
if args.comparisons and type(args.comparisons) == "table" then
|
||||
-- Check if SP_SwingTimer is loaded
|
||||
if st_timer == nil then
|
||||
local percentElapsed = CleveRoids.GetSwingPercentElapsed()
|
||||
if percentElapsed == nil then
|
||||
if not CleveRoids._swingTimerErrorShown then
|
||||
DEFAULT_CHAT_FRAME:AddMessage("|cffff0000[SuperCleveRoidMacros]|r The [swingtimer] conditional requires the SP_SwingTimer addon. Get it at: https://github.com/jrc13245/SP_SwingTimer", 1, 0.5, 0.5)
|
||||
DEFAULT_CHAT_FRAME:AddMessage("|cffff0000[SuperCleveRoidMacros]|r The [swingtimer] conditional requires SP_SwingTimer or pfUI (swing timer module). Get SP_SwingTimer at: https://github.com/jrc13245/SP_SwingTimer", 1, 0.5, 0.5)
|
||||
CleveRoids._swingTimerErrorShown = true
|
||||
end
|
||||
return true
|
||||
end
|
||||
|
||||
local attackSpeed = UnitAttackSpeed("player")
|
||||
if not attackSpeed or attackSpeed <= 0 then return true end
|
||||
|
||||
local timeElapsed = attackSpeed - st_timer
|
||||
local percentElapsed = (timeElapsed / attackSpeed) * 100
|
||||
|
||||
-- Check if ALL comparisons pass
|
||||
for _, comp in ipairs(args.comparisons) do
|
||||
if not CleveRoids.operators[comp.operator] then
|
||||
@@ -7064,21 +7067,15 @@ CleveRoids.Keywords = {
|
||||
|
||||
-- Handle multi-comparison by checking positive and negating
|
||||
if args.comparisons and type(args.comparisons) == "table" then
|
||||
-- Check if SP_SwingTimer is loaded
|
||||
if st_timer == nil then
|
||||
local percentElapsed = CleveRoids.GetSwingPercentElapsed()
|
||||
if percentElapsed == nil then
|
||||
if not CleveRoids._swingTimerErrorShown then
|
||||
DEFAULT_CHAT_FRAME:AddMessage("|cffff0000[SuperCleveRoidMacros]|r The [swingtimer] conditional requires the SP_SwingTimer addon. Get it at: https://github.com/jrc13245/SP_SwingTimer", 1, 0.5, 0.5)
|
||||
DEFAULT_CHAT_FRAME:AddMessage("|cffff0000[SuperCleveRoidMacros]|r The [swingtimer] conditional requires SP_SwingTimer or pfUI (swing timer module). Get SP_SwingTimer at: https://github.com/jrc13245/SP_SwingTimer", 1, 0.5, 0.5)
|
||||
CleveRoids._swingTimerErrorShown = true
|
||||
end
|
||||
return true
|
||||
end
|
||||
|
||||
local attackSpeed = UnitAttackSpeed("player")
|
||||
if not attackSpeed or attackSpeed <= 0 then return true end
|
||||
|
||||
local timeElapsed = attackSpeed - st_timer
|
||||
local percentElapsed = (timeElapsed / attackSpeed) * 100
|
||||
|
||||
-- Check if ALL comparisons pass
|
||||
for _, comp in ipairs(args.comparisons) do
|
||||
if not CleveRoids.operators[comp.operator] then
|
||||
|
||||
@@ -645,6 +645,7 @@ function CleveRoids.GetSpellCost(spellSlot, bookType)
|
||||
_, _, reagent = string.find(reagentText, "^Reagents?%s*:%s*(.*)")
|
||||
end
|
||||
reagent = _StripColor(reagent)
|
||||
if reagent == "" then reagent = nil end
|
||||
|
||||
-- Fallback: scan all lines on a named tooltip (handles Vanish layout)
|
||||
if not reagent or not cost then
|
||||
@@ -685,6 +686,7 @@ function CleveRoids.GetSpellCost(spellSlot, bookType)
|
||||
elseif string.find(rt, "^[Rr]eagents?%s*:") then
|
||||
reagent = _StripColor((lt ~= "" and lt) or (string.gsub(rt, "^[Rr]eagents?%s*:%s*", "")))
|
||||
end
|
||||
if reagent == "" then reagent = nil end
|
||||
end
|
||||
|
||||
if not cost and rt ~= "" then
|
||||
@@ -696,7 +698,8 @@ function CleveRoids.GetSpellCost(spellSlot, bookType)
|
||||
end
|
||||
end
|
||||
|
||||
if not reagent then
|
||||
if not reagent or reagent == "" then
|
||||
reagent = nil
|
||||
local name = GetSpellName(spellSlot, bookType)
|
||||
if name then
|
||||
name = string.gsub(name, "%s*%(%s*Rank%s+%d+%s*%)%s*$", "") -- strip "(Rank X)" only
|
||||
@@ -704,7 +707,7 @@ function CleveRoids.GetSpellCost(spellSlot, bookType)
|
||||
end
|
||||
end
|
||||
|
||||
return (cost and tonumber(cost) or 0), (reagent and tostring(reagent) or nil)
|
||||
return (cost and tonumber(cost) or 0), (reagent and reagent ~= "" and tostring(reagent) or nil)
|
||||
end
|
||||
|
||||
function CleveRoids.GetProxyActionSlot(slot)
|
||||
@@ -4741,7 +4744,8 @@ function GetActionCount(slot)
|
||||
|
||||
elseif actionToCheck.spell then
|
||||
local reagent = actionToCheck.spell.reagent
|
||||
if not reagent then
|
||||
if not reagent or reagent == "" then
|
||||
reagent = nil
|
||||
local ss, bt = actionToCheck.spell.spellSlot, actionToCheck.spell.bookType
|
||||
if ss and bt then
|
||||
local _, r = CleveRoids.GetSpellCost(ss, bt)
|
||||
@@ -4752,7 +4756,7 @@ function GetActionCount(slot)
|
||||
end
|
||||
actionToCheck.spell.reagent = reagent -- cache it so we don't re-scan every frame
|
||||
end
|
||||
if reagent then
|
||||
if reagent and reagent ~= "" then
|
||||
count = CleveRoids.GetReagentCount(reagent) -- id-first bag scan, falls back to name/tooltip
|
||||
end
|
||||
end
|
||||
@@ -4791,8 +4795,17 @@ function IsConsumableAction(slot)
|
||||
end
|
||||
|
||||
|
||||
if actionToCheck.spell and actionToCheck.spell.reagent then
|
||||
return 1
|
||||
if actionToCheck.spell then
|
||||
local reagent = actionToCheck.spell.reagent
|
||||
if (not reagent or reagent == "") and actionToCheck.spell.name then
|
||||
reagent = _ReagentBySpell[actionToCheck.spell.name]
|
||||
if reagent then
|
||||
actionToCheck.spell.reagent = reagent
|
||||
end
|
||||
end
|
||||
if reagent and reagent ~= "" then
|
||||
return 1
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@@ -250,12 +250,17 @@ local function GetTargetOverflowBuffs()
|
||||
local trackingData = CleveRoids.AllCasterAuraTracking
|
||||
if not trackingData or not trackingData[targetGuid] then return results end
|
||||
|
||||
-- Build set of visible buff textures on target
|
||||
local visibleBuffs = {}
|
||||
-- Build set of visible aura textures on target (buffs + debuffs)
|
||||
local visibleAuras = {}
|
||||
for i = 1, 32 do
|
||||
local texture = UnitBuff("target", i)
|
||||
if not texture then break end
|
||||
visibleBuffs[texture] = true
|
||||
visibleAuras[texture] = true
|
||||
end
|
||||
for i = 1, 16 do
|
||||
local texture = UnitDebuff("target", i)
|
||||
if not texture then break end
|
||||
visibleAuras[texture] = true
|
||||
end
|
||||
|
||||
local now = GetTime()
|
||||
@@ -268,7 +273,7 @@ local function GetTargetOverflowBuffs()
|
||||
local isVisible = false
|
||||
if not auraData._testEntry then
|
||||
local spellIcon = lib and lib:GetCachedIcon(spellId)
|
||||
isVisible = spellIcon and visibleBuffs[spellIcon]
|
||||
isVisible = spellIcon and visibleAuras[spellIcon]
|
||||
end
|
||||
if not isVisible then
|
||||
table.insert(results, {
|
||||
|
||||
@@ -58,7 +58,7 @@ function CleveRoids.IndexSpells()
|
||||
else
|
||||
local cost, reagent = CleveRoids.GetSpellCost(i, bookType)
|
||||
-- Fallback for known reagent spells if tooltip scan failed
|
||||
if not reagent and CleveRoids.ReagentBySpell then
|
||||
if (not reagent or reagent == "") and CleveRoids.ReagentBySpell then
|
||||
reagent = CleveRoids.ReagentBySpell[spellName]
|
||||
end
|
||||
local texture = GetSpellTexture(i, bookType)
|
||||
@@ -84,6 +84,10 @@ function CleveRoids.IndexSpells()
|
||||
}
|
||||
spells[bookType][spellName].highest = spells[bookType][spellName][spellRank]
|
||||
end
|
||||
-- For spells with no rank string, the base entry is the highest
|
||||
if not spellRank and not spells[bookType][spellName].highest then
|
||||
spells[bookType][spellName].highest = spells[bookType][spellName]
|
||||
end
|
||||
|
||||
if reagent then
|
||||
CleveRoids.countedItemTypes[reagent] = true
|
||||
@@ -458,7 +462,12 @@ function CleveRoids.GetSpell(text)
|
||||
|
||||
for book, spells in CleveRoids.Spells do
|
||||
if spells and spells[name] then
|
||||
return spells[name][rank or "highest"]
|
||||
local entry = spells[name][rank or "highest"]
|
||||
if entry then return entry end
|
||||
-- Fallback: for spells with no rank, return base entry
|
||||
if not rank and spells[name].spellSlot then
|
||||
return spells[name]
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
Reference in New Issue
Block a user