Initial Commit

This commit is contained in:
Jrc13245
2025-08-18 16:15:25 -04:00
commit fb359993b2
27 changed files with 6583 additions and 0 deletions
+34
View File
@@ -0,0 +1,34 @@
## Interface: 11200
## Author: DWG, _brain, Torio, yani9o
## Title: [Super]CleveRoidMacros
## Notes: /cleveroid for settings
## Version: 1.2
## OptionalDeps: ClassicFocus, FocusFrame, pfUI, SuperMacro, Bongos_ActionBar
## SavedVariables: CleveRoidMacros
Localization.lua
Init.lua
Utility.lua
Core.lua
Conditionals.lua
Console.lua
ExtensionsManager.lua
Compatibility\SuperMacro.lua
Compatibility\pfUI.lua
Compatibility\Bongos.lua
Extensions\MacroLengthWarn.lua
Extensions\Mouseover\GameTooltip.lua
Extensions\Mouseover\Blizzard.lua
Extensions\Mouseover\CT_RaidAssist.lua
Extensions\Mouseover\CT_UnitFrames.lua
Extensions\Mouseover\DiscordUnitFrames.lua
Extensions\Mouseover\FocusFrame.lua
Extensions\Mouseover\Grid.lua
Extensions\Mouseover\NotGrid.lua
Extensions\Mouseover\PerfectRaid.lua
Extensions\Mouseover\pfUI.lua
Extensions\Mouseover\sRaidFrames.lua
Extensions\Mouseover\ag_UnitFrames.lua
Extensions\Tooltip\Generic.lua
+8
View File
@@ -0,0 +1,8 @@
CleveRoids.RegisterActionEventHandler(function(slot, event)
if not slot or not BActionButton or not BActionBar then return end
local button = getglobal("BActionButton" .. slot)
if button then
BActionButton.Update(button)
end
end)
+21
View File
@@ -0,0 +1,21 @@
local _G = _G or getfenv(0)
local CleveRoids = _G.CleveRoids or {}
local Extension = CleveRoids.RegisterExtension("Compatibility_SuperMacro")
Extension.RegisterEvent("ADDON_LOADED", "OnLoad")
function Extension.RunMacro(name)
CleveRoids.ExecuteMacroByName(name)
end
function Extension.OnLoad()
if not SuperMacroFrame then
return
end
Extension.Hook("RunMacro", "RunMacro", true)
Extension.UnregisterEvent("ADDON_LOADED", "Onload")
end
_G["CleveRoids"] = CleveRoids
+37
View File
@@ -0,0 +1,37 @@
local _G = _G or getfenv(0)
local CleveRoids = _G.CleveRoids or {}
local Extension = CleveRoids.RegisterExtension("Compatibility_pfUI")
Extension.RegisterEvent("ADDON_LOADED", "OnLoad")
Extension.Debug = false
function Extension.RunMacro(name)
CleveRoids.ExecuteMacroByName(name)
end
function Extension.DLOG(msg)
if Extension.Debug then
DEFAULT_CHAT_FRAME:AddMessage("|cffcccc33[R]: |cffffff55" .. ( msg ))
end
end
function Extension.FocusNameHook()
local hook = Extension.internal.memberHooks[CleveRoids]["GetFocusName"]
local target = hook.original()
if pfUI and pfUI.uf and pfUI.uf.focus and pfUI.uf.focus.unitname then
target = pfUI.uf.focus.unitname
end
--Extension.DLOG(target)
return target
end
function Extension.OnLoad()
Extension.DLOG("Extension pfUI Loaded.")
Extension.HookMethod(CleveRoids, "GetFocusName", "FocusNameHook", true)
Extension.UnregisterEvent("ADDON_LOADED", "Onload")
end
_G["CleveRoids"] = CleveRoids
+1321
View File
File diff suppressed because it is too large Load Diff
+204
View File
@@ -0,0 +1,204 @@
--[[
Author: Dennis Werner Garske (DWG) / brian / Mewtiny
License: MIT License
]]
local _G = _G or getfenv(0)
local CleveRoids = _G.CleveRoids or {}
SLASH_PETATTACK1 = "/petattack"
SlashCmdList.PETATTACK = function(msg) CleveRoids.DoPetAction(PetAttack, msg); end
SLASH_PETFOLLOW1 = "/petfollow"
SlashCmdList.PETFOLLOW = function(msg) CleveRoids.DoPetAction(PetFollow, msg); end
SLASH_PETWAIT1 = "/petwait"
SlashCmdList.PETWAIT = function(msg) CleveRoids.DoPetAction(PetWait, msg); end
SLASH_PETPASSIVE1 = "/petpassive"
SlashCmdList.PETPASSIVE = function(msg) CleveRoids.DoPetAction(PetPassiveMode, msg); end
SLASH_PETAGGRESSIVE1 = "/petaggressive"
SlashCmdList.PETAGGRESSIVE = function(msg) CleveRoids.DoPetAction(PetAggressiveMode, msg); end
SLASH_PETDEFENSIVE1 = "/petdefensive"
SlashCmdList.PETDEFENSIVE = function(msg) CleveRoids.DoPetAction(PetDefensiveMode, msg); end
SLASH_RELOAD1 = "/rl"
SlashCmdList.RELOAD = function() ReloadUI(); end
SLASH_USE1 = "/use"
SlashCmdList.USE = CleveRoids.DoUse
SLASH_EQUIP1 = "/equip"
SlashCmdList.EQUIP = CleveRoids.DoUse
-- take back supermacro and pfUI /equip
SlashCmdList.SMEQUIP = CleveRoids.DoUse
SlashCmdList.PFEQUIP = CleveRoids.DoUse
SLASH_EQUIPMH1 = "/equipmh"
SlashCmdList.EQUIPMH = CleveRoids.DoEquipMainhand
SLASH_EQUIPOH1 = "/equipoh"
SlashCmdList.EQUIPOH = CleveRoids.DoEquipOffhand
SLASH_UNSHIFT1 = "/unshift"
SlashCmdList.UNSHIFT = CleveRoids.DoUnshift
SLASH_UNQUEUE1 = "/unqueue"
SlashCmdList.UNQUEUE = SpellStopCasting
-- TODO make this conditional too
SLASH_CANCELAURA1 = "/cancelaura"
SLASH_CANCELAURA2 = "/unbuff"
SlashCmdList.CANCELAURA = CleveRoids.DoConditionalCancelAura
-- Define original implementations before hooking them.
-- This ensures we have a fallback for non-conditional use.
local StartAttack = function(msg)
if not UnitExists("target") or UnitIsDead("target") then TargetNearestEnemy() end
if not CleveRoids.CurrentSpell.autoAttack and not CleveRoids.CurrentSpell.autoAttackLock and UnitExists("target") and UnitCanAttack("player","target") then
CleveRoids.CurrentSpell.autoAttackLock = true
CleveRoids.autoAttackLockElapsed = GetTime()
AttackTarget()
end
end
local StopAttack = function(msg)
if CleveRoids.CurrentSpell.autoAttack and UnitExists("target") then
AttackTarget()
CleveRoids.CurrentSpell.autoAttack = false
end
end
-- Register slash commands and assign original handlers.
-- These will be hooked immediately after.
SLASH_STARTATTACK1 = "/startattack"
SlashCmdList.STARTATTACK = StartAttack
SLASH_STOPATTACK1 = "/stopattack"
SlashCmdList.STOPATTACK = StopAttack
SLASH_STOPCASTING1 = "/stopcasting"
SlashCmdList.STOPCASTING = SpellStopCasting
----------------------------------
-- HOOK DEFINITIONS START
----------------------------------
-- /startattack hook
CleveRoids.Hooks.STARTATTACK_SlashCmd = SlashCmdList.STARTATTACK
SlashCmdList.STARTATTACK = function(msg)
msg = msg or ""
if string.find(msg, "%[") then
CleveRoids.DoConditionalStartAttack(msg)
else
CleveRoids.Hooks.STARTATTACK_SlashCmd(msg)
end
end
-- /stopattack hook
CleveRoids.Hooks.STOPATTACK_SlashCmd = SlashCmdList.STOPATTACK
SlashCmdList.STOPATTACK = function(msg)
msg = msg or ""
if string.find(msg, "%[") then
-- If conditionals are present, let the function handle it.
-- It will only stop the attack if the conditions are met.
CleveRoids.DoConditionalStopAttack(msg)
else
-- If no conditionals, run the original command.
CleveRoids.Hooks.STOPATTACK_SlashCmd(msg)
end
end
-- /stopcasting hook
CleveRoids.Hooks.STOPCASTING_SlashCmd = SlashCmdList.STOPCASTING
SlashCmdList.STOPCASTING = function(msg)
msg = msg or ""
if string.find(msg, "%[") then
-- If conditionals are present, let the function handle it.
-- It will only stop the cast if the conditions are met.
CleveRoids.DoConditionalStopCasting(msg)
else
-- If no conditionals, run the original command.
CleveRoids.Hooks.STOPCASTING_SlashCmd()
end
end
CleveRoids.Hooks.UNQUEUE_SlashCmd = SlashCmdList.UNQUEUE
SlashCmdList.UNQUEUE = function(msg)
msg = msg or ""
if string.find(msg, "%[") then
-- If conditionals are present, let the function handle it.
CleveRoids.DoConditionalStopCasting(msg)
else
-- If no conditionals, run the original command.
CleveRoids.Hooks.UNQUEUE_SlashCmd()
end
end
-- /cast hook
CleveRoids.Hooks.CAST_SlashCmd = SlashCmdList.CAST
SlashCmdList.CAST = function(msg)
if msg and string.find(msg, "[%[%?!~{]") then
CleveRoids.DoCast(msg)
else
CleveRoids.Hooks.CAST_SlashCmd(msg)
end
end
CleveRoids.Hooks.TARGET_SlashCmd = SlashCmdList.TARGET
CleveRoids.TARGET_SlashCmd = function(msg)
tmsg = CleveRoids.Trim(msg)
if tmsg ~= "" and not string.find(tmsg, "%[") and not string.find(tmsg, "@") then
CleveRoids.Hooks.TARGET_SlashCmd(tmsg)
return
end
if CleveRoids.DoTarget(tmsg) then
if UnitExists("target") then
return
end
end
CleveRoids.Hooks.TARGET_SlashCmd(msg)
end
SlashCmdList.TARGET = CleveRoids.TARGET_SlashCmd
SLASH_CASTSEQUENCE1 = "/castsequence"
SlashCmdList.CASTSEQUENCE = function(msg)
msg = CleveRoids.Trim(msg)
local sequence = CleveRoids.GetSequence(msg)
if not sequence then return end
-- if not sequence.active then return end
CleveRoids.DoCastSequence(sequence)
end
SLASH_RUNMACRO1 = "/runmacro"
SlashCmdList.RUNMACRO = function(msg)
return CleveRoids.ExecuteMacroByName(CleveRoids.Trim(msg))
end
SLASH_RETARGET1 = "/retarget"
SlashCmdList.RETARGET = function(msg)
CleveRoids.DoRetarget()
end
SLASH_STOPMACRO1 = "/stopmacro"
SlashCmdList.STOPMACRO = function(msg)
CleveRoids.DoStopMacro(msg)
end
+2146
View File
File diff suppressed because it is too large Load Diff
+41
View File
@@ -0,0 +1,41 @@
--[[
Author: Dennis Werner Garske (DWG) / brian / Mewtiny
License: MIT License
]]
local _G = _G or getfenv(0)
local CleveRoids = _G.CleveRoids or {}
-- CleveRoids.mouseoverUnit = CleveRoids.mouseoverUnit or nil
local Extension = CleveRoids.RegisterExtension("MacroLengthWarn")
local edit_orig = EditMacro
function Extension.SafeEditMacro(macro_id, x, y, body)
if SuperMacroFrame ~= nil and x and y and body == nil then
-- super will handle macro
edit_orig(macro_id, x, y, body)
return
end
if not body then -- can't be too long without a body
edit_orig(macro_id, x, y, body)
return
end
for line in string.gfind(body, "([^\n]+)") do
if string.len(line) > 261 then
DEFAULT_CHAT_FRAME:AddMessage("ERROR: A line in the macro < |cffffffff"..GetMacroInfo(macro_id).."|r > is too long and will |cffff0000CRASH|r the client and may |cffff0000DELETE|r all macros on exit! Max line length: |cffffffff261|r",1,1,0)
return
end
end
edit_orig(macro_id, x, y, body)
end
function Extension.OnLoad()
-- how do I use this with a global function?
-- CleveRoids.RegisterMethodHook("MacroLengthWarn", _G, "EditMacro", "SafeEditMacro", true)
EditMacro = Extension.SafeEditMacro
end
_G["CleveRoids"] = CleveRoids
+77
View File
@@ -0,0 +1,77 @@
--[[
Author: Fondlez
This extension adds improved support for mouseover macros in Roid-Macros
for the default Blizzard frames.
]]
local _G = _G or getfenv(0)
local CleveRoids = _G.CleveRoids or {}
CleveRoids.mouseoverUnit = CleveRoids.mouseoverUnit or nil
local Extension = CleveRoids.RegisterExtension("Blizzard")
function Extension.RegisterMouseoverForFrame(frame, unit)
if not frame then return end
local onenter = frame:GetScript("OnEnter")
local onleave = frame:GetScript("OnLeave")
frame:SetScript("OnEnter", function()
CleveRoids.mouseoverUnit = unit
if onenter then
onenter()
end
end)
frame:SetScript("OnLeave", function()
CleveRoids.mouseoverUnit = nil
if onleave then
onleave()
end
end)
end
do
local frames = {
["PlayerFrame"] = "player",
["PetFrame"] = "pet",
["TargetFrame"] = "target",
["PartyMemberFrame1"] = "party1",
["PartyMemberFrame2"] = "party2",
["PartyMemberFrame3"] = "party3",
["PartyMemberFrame4"] = "party4",
["PartyMemberFrame1PetFrame"] = "party1",
["PartyMemberFrame2PetFrame"] = "party2",
["PartyMemberFrame3PetFrame"] = "party3",
["PartyMemberFrame4PetFrame"] = "party4",
}
local bars = {
"HealthBar",
"ManaBar",
}
local allFrames = {}
for name, unit in pairs(frames) do
allFrames[name] = unit
for i, bar in ipairs(bars) do
allFrames[name .. bar] = unit
end
end
-- Inconsisent naming for TargetofTarget required
allFrames["TargetofTargetFrame"] = "targettarget"
allFrames["TargetofTargetHealthBar"] = "targettarget"
allFrames["TargetofTargetManaBar"] = "targettarget"
function Extension.OnLoad()
local frame
for name, unit in pairs(allFrames) do
frame = _G[name]
if frame then
Extension.RegisterMouseoverForFrame(frame, unit)
end
end
end
end
+62
View File
@@ -0,0 +1,62 @@
--[[
Author: Dennis Werner Garske (DWG) / brian / Mewtiny
License: MIT License
]]
local _G = _G or getfenv(0)
local CleveRoids = _G.CleveRoids or {}
CleveRoids.mouseoverUnit = CleveRoids.mouseoverUnit or nil
local Extension = CleveRoids.RegisterExtension("CT_RaidAssist")
Extension.RegisterEvent("ADDON_LOADED", "OnLoad")
function Extension.OnEnter()
local tempOptions = CT_RAMenu_Options["temp"]
if ( SpellIsTargeting() ) then
SetCursor("CAST_CURSOR")
end
local parent = this.frameParent
local id = parent.id
if ( strsub(parent.name, 1, 12) == "CT_RAMTGroup" ) then
local name
if ( CT_RA_MainTanks[id] ) then
name = CT_RA_MainTanks[id]
end
for i = 1, GetNumRaidMembers(), 1 do
local memberName = GetRaidRosterInfo(i)
if ( name == memberName ) then
id = i
break
end
end
elseif ( strsub(parent.name, 1, 12) == "CT_RAPTGroup" ) then
local name
if ( CT_RA_PTargets[id] ) then
name = CT_RA_PTargets[id]
end
for i = 1, GetNumRaidMembers(), 1 do
local memberName = GetRaidRosterInfo(i)
if ( name == memberName ) then
id = i
break
end
end
end
CleveRoids.mouseoverUnit = "raid"..id
end
function Extension.OnLeave()
CleveRoids.mouseoverUnit = nil
end
function Extension.OnLoad()
if arg1 ~= "CT_RaidAssist" then
return
end
Extension.Hook("CT_RA_MemberFrame_OnEnter", "OnEnter")
Extension.HookMethod(_G["GameTooltip"], "Hide", "OnLeave")
Extension.HookMethod(_G["GameTooltip"], "FadeOut", "OnLeave")
end
_G["CleveRoids"] = CleveRoids
+39
View File
@@ -0,0 +1,39 @@
--[[
Author: Dennis Werner Garske (DWG) / brian / Mewtiny
License: MIT License
]]
local _G = _G or getfenv(0)
local CleveRoids = _G.CleveRoids or {}
CleveRoids.mouseoverUnit = CleveRoids.mouseoverUnit or nil
local Extension = CleveRoids.RegisterExtension("CT_UnitFrames")
Extension.RegisterEvent("ADDON_LOADED", "OnLoad")
function Extension.SetHook(widget)
local hookedOnEnter = widget:GetScript("OnEnter")
local hookedOnLeave = widget:GetScript("OnLeave")
widget:SetScript("OnEnter", function()
hookedOnEnter()
CleveRoids.mouseoverUnit = "targettarget"
end)
widget:SetScript("OnLeave", function()
hookedOnLeave()
CleveRoids.mouseoverUnit = nil
end)
end
function Extension.OnLoad()
if arg1 ~= "CT_UnitFrames" or not CT_AssistFrame then
return
end
CleveRoids.Print("CT_UnitFrames module loaded.")
Extension.SetHook(CT_AssistFrame)
Extension.SetHook(CT_AssistFrameHealthBar)
Extension.SetHook(CT_AssistFrameManaBar)
Extension.SetHook(CT_AssistFrame_Drag)
end
_G["CleveRoids"] = CleveRoids
@@ -0,0 +1,41 @@
--[[
Author: Dennis Werner Garske (DWG) / brian / Mewtiny
License: MIT License
]]
local _G = _G or getfenv(0)
local CleveRoids = _G.CleveRoids or {}
CleveRoids.mouseoverUnit = CleveRoids.mouseoverUnit or nil
local Extension = CleveRoids.RegisterExtension("DiscordUnitFrames")
Extension.RegisterEvent("ADDON_LOADED", "OnLoad")
function Extension.OnEnterFrame()
CleveRoids.mouseoverUnit = this.unit
end
function Extension.OnLeaveFrame()
CleveRoids.mouseoverUnit = nil
end
function Extension.OnEnterElement()
CleveRoids.mouseoverUnit = this:GetParent().unit
end
function Extension.OnLeaveElement()
CleveRoids.mouseoverUnit = nil
end
function Extension.OnLoad()
if arg1 ~= "DiscordUnitFrames" then
return
end
CleveRoids.ClearHooks()
Extension.Hook("DUF_UnitFrame_OnEnter", "OnEnterFrame")
Extension.Hook("DUF_UnitFrame_OnLeave", "OnLeaveFrame")
Extension.Hook("DUF_Element_OnEnter", "OnEnterElement")
Extension.Hook("DUF_Element_OnLeave", "OnLeaveElement")
end
_G["CleveRoids"] = CleveRoids
+42
View File
@@ -0,0 +1,42 @@
--[[
Author: Dennis Werner Garske (DWG) / brian / Mewtiny
License: MIT License
]]
local _G = _G or getfenv(0)
local CleveRoids = _G.CleveRoids or {}
CleveRoids.mouseoverUnit = CleveRoids.mouseoverUnit or nil
local Extension = CleveRoids.RegisterExtension("FocusFrame")
function Extension.RegisterMouseoverForFrame(frame)
local onenter = frame:GetScript("OnEnter")
local onleave = frame:GetScript("OnLeave")
frame:SetScript("OnEnter", function()
CleveRoids.mouseoverUnit = "focus"
if onenter then
onenter()
end
end)
frame:SetScript("OnLeave", function()
CleveRoids.mouseoverUnit = nil
if onleave then
onleave()
end
end)
end
function Extension.OnLoad()
if not FocusFrameHealthBar
or not FocusFrameManaBar
or not FocusFrameTextureFrame
or not FocusFrame then
return
end
Extension.RegisterMouseoverForFrame(FocusFrameHealthBar)
Extension.RegisterMouseoverForFrame(FocusFrameManaBar)
Extension.RegisterMouseoverForFrame(FocusFrameTextureFrame)
Extension.RegisterMouseoverForFrame(FocusFrame)
end
+29
View File
@@ -0,0 +1,29 @@
--[[
Author: Dennis Werner Garske (DWG) / brian / Mewtiny
License: MIT License
]]
local _G = _G or getfenv(0)
local CleveRoids = _G.CleveRoids or {}
local Extension = CleveRoids.RegisterExtension("GameTooltipMouseover")
local lastUnit, setByTooltip = nil, false
function Extension.SetUnit(_, unit)
if unit and unit ~= "" then
CleveRoids.SetMouseoverFrom("tooltip", unit)
end
end
function Extension.OnClose()
CleveRoids.ClearMouseoverFrom("tooltip")
end
function Extension.OnLoad()
Extension.HookMethod(_G["GameTooltip"], "SetUnit", "SetUnit")
Extension.HookMethod(_G["GameTooltip"], "Hide", "OnClose")
Extension.HookMethod(_G["GameTooltip"], "FadeOut", "OnClose")
end
_G["CleveRoids"] = CleveRoids
+114
View File
@@ -0,0 +1,114 @@
--[[
Author: Dennis Werner Garske (DWG) / brian / Mewtiny
License: MIT License
]]
local _G = _G or getfenv(0)
local CleveRoids = _G.CleveRoids or {}
CleveRoids.Hooks = CleveRoids.Hooks or {}
CleveRoids.mouseoverUnit = CleveRoids.mouseoverUnit or nil
local Extension = CleveRoids.RegisterExtension("Grid")
Extension.RegisterEvent("ADDON_LOADED", "OnLoad")
function Extension.OnEnter(unit)
CleveRoids.mouseoverUnit = unit
end
function Extension.OnLeave()
CleveRoids.mouseoverUnit = nil
end
function Extension.OnLoad()
if arg1 ~= "Grid" then
return
end
CleveRoids.Hooks.Grid = { CreateFrames = GridFrame.frameClass.prototype.CreateFrames}
GridFrame.frameClass.prototype.CreateFrames = CleveRoids.GrdCreateFrames
end
-- Taken from GridFrame.lua and added OnEnter and OnLeave scripts
function CleveRoids:GrdCreateFrames()
-- create frame
--self.frame = CreateFrame("Button", nil, UIParent)
local f = self.frame
f:SetScript("OnEnter", function()
Extension.OnEnter(self.unit)
end)
f:SetScript("OnLeave", function()
Extension.OnLeave()
end)
-- f:Hide()
f:EnableMouse(true)
f:RegisterForClicks("LeftButtonUp", "RightButtonUp", "MiddleButtonUp", "Button4Up", "Button5Up")
f:SetWidth(GridFrame:GetFrameSize())
f:SetHeight(GridFrame:GetFrameSize())
-- only use SetScript pre-TBC
if Grid.isTBC then
f:SetAttribute("type1", "target")
else
f:SetScript("OnClick", function () GridFrame_OnClick(f, arg1) end)
f:SetScript("OnAttributeChanged", GridFrame_OnAttributeChanged)
end
-- create border
f:SetBackdrop({
bgFile = "Interface\\Addons\\Grid\\white16x16", tile = true, tileSize = 16,
edgeFile = "Interface\\Addons\\Grid\\white16x16", edgeSize = 1,
insets = {left = 1, right = 1, top = 1, bottom = 1},
})
f:SetBackdropBorderColor(0,0,0,0)
f:SetBackdropColor(0,0,0,1)
-- create bar BG (which users will think is the real bar, as it is the one that has a shiny color)
-- this is necessary as there's no other way to implement status bars that grow in the other direction than normal
f.BarBG = f:CreateTexture()
f.BarBG:SetTexture("Interface\\Addons\\Grid\\gradient32x32")
f.BarBG:SetPoint("CENTER", f, "CENTER")
f.BarBG:SetWidth(GridFrame:GetFrameSize()-4)
f.BarBG:SetHeight(GridFrame:GetFrameSize()-4)
-- create bar
f.Bar = CreateFrame("StatusBar", nil, f)
f.Bar:SetStatusBarTexture("Interface\\Addons\\Grid\\gradient32x32")
f.Bar:SetOrientation("VERTICAL")
f.Bar:SetMinMaxValues(0,100)
f.Bar:SetValue(100)
f.Bar:SetStatusBarColor(0,0,0,0.8)
f.Bar:SetPoint("CENTER", f, "CENTER")
f.Bar:SetFrameLevel(4)
f.Bar:SetWidth(GridFrame:GetFrameSize()-4)
f.Bar:SetHeight(GridFrame:GetFrameSize()-4)
-- create center text
f.Text = f.Bar:CreateFontString(nil, "ARTWORK")
f.Text:SetFontObject(GameFontHighlightSmall)
f.Text:SetFont(STANDARD_TEXT_FONT,8)
f.Text:SetJustifyH("CENTER")
f.Text:SetJustifyV("CENTER")
f.Text:SetPoint("CENTER", f, "CENTER")
-- create icon
f.Icon = f.Bar:CreateTexture("Icon", "OVERLAY")
f.Icon:SetWidth(16)
f.Icon:SetHeight(16)
f.Icon:SetPoint("CENTER", f, "CENTER")
f.Icon:SetTexCoord(0.05, 0.95, 0.05, 0.95)
f.Icon:SetTexture(1,1,1,0) --"Interface\\Icons\\INV_Misc_Orb_02"
-- set texture
f:SetNormalTexture(1,1,1,0)
f:SetHighlightTexture("Interface\\QuestFrame\\UI-QuestTitleHighlight")
self.frame = f
-- set up click casting
ClickCastFrames = ClickCastFrames or {}
ClickCastFrames[self.frame] = true
end
_G["CleveRoids"] = CleveRoids
+54
View File
@@ -0,0 +1,54 @@
--[[
Author: Dennis Werner Garske (DWG) / brian / Mewtiny
License: MIT License
]]
local _G = _G or getfenv(0)
local CleveRoids = _G.CleveRoids or {}
local CreateFrames = nil
CleveRoids.mouseoverUnit = CleveRoids.mouseoverUnit or nil
local Extension = CleveRoids.RegisterExtension("NotGrid")
Extension.RegisterEvent("ADDON_LOADED", "OnLoad")
function Extension.OnEnter()
CleveRoids.mouseoverUnit = this.unit
end
function Extension.OnLeave()
CleveRoids.mouseoverUnit = nil
end
function CleveRoids:NotGrid_CreateFrames()
CreateFrames(NotGrid); -- call the original
-- NotGrid stores all of it's frames in the NotGrid.UnitFrames table.
for k, frame in pairs(NotGrid.UnitFrames) do
local enter = frame:GetScript("OnEnter")
local leave = frame:GetScript("OnLeave")
frame:SetScript("OnEnter", function()
enter()
Extension.OnEnter()
end)
frame:SetScript("OnLeave", function()
leave()
Extension.OnLeave()
end)
end
end
function Extension.OnLoad()
-- NotGrid loads before CleveRoids, so if NotGrid is enabled, then it's global will exist.
if not NotGrid then
return
end
-- Hooking manually as we need a post hook.
CreateFrames = NotGrid.CreateFrames
NotGrid.CreateFrames = CleveRoids.NotGrid_CreateFrames
Extension.UnregisterEvent("ADDON_LOADED", "Onload")
end
_G["CleveRoids"] = CleveRoids
+137
View File
@@ -0,0 +1,137 @@
--[[
Author: Dennis Werner Garske (DWG) / brian / Mewtiny
License: MIT License
]]
local _G = _G or getfenv(0)
local CleveRoids = _G.CleveRoids or {}
CleveRoids.Hooks = CleveRoids.Hooks or {}
CleveRoids.mouseoverUnit = CleveRoids.mouseoverUnit or nil
local Extension = CleveRoids.RegisterExtension("PerfectRaid")
Extension.RegisterEvent("ADDON_LOADED", "OnLoad")
function Extension.OnEnter(unit)
CleveRoids.mouseoverUnit = unit
end
function Extension.OnLeave()
CleveRoids.mouseoverUnit = nil
end
function Extension.OnLoad()
if arg1 ~= "PerfectRaid" then
return
end
CleveRoids.Hooks.PerfectRaid = { CreateFrame = PerfectRaid.CreateFrame }
PerfectRaid.CreateFrame = CleveRoids.PerfectRaidCreateFrame
end
function CleveRoids.PerfectRaidCreateFrame(self, num)
-- We need to allocate up to num frames
if self.poolsize >= num then return end
--[[
local mem,thr = gcinfo()
self:Msg("Memory Usage Before: %s [%s].", mem, thr)
--]]
local side = self.opt.Align
local justify,point,relative,offset
if side == "left" then
justify = "RIGHT"
point = "LEFT"
relative = "RIGHT"
offset = 5
elseif side == "right" then
justify = "LEFT"
point = "RIGHT"
relative = "LEFT"
offset = -5
end
for i=(self.poolsize + 1),num do
local frame = CreateFrame("Button", nil, PerfectRaidFrame)
frame:EnableMouse(true)
frame.unit = "raid"..i
frame.id = i
frame:SetWidth(225)
frame:SetHeight(13)
frame:SetMovable(true)
frame:RegisterForDrag("LeftButton")
frame:SetScript("OnDragStart", function() self["master"]:StartMoving() end)
frame:SetScript("OnDragStop", function() self["master"]:StopMovingOrSizing() self:SavePosition() end)
frame:RegisterForClicks("LeftButtonUp", "RightButtonUp", "MiddleButtonUp", "Button4Up", "Button5Up")
frame:SetScript("OnClick", self.OnClick)
frame:SetScript("OnEnter", function()
Extension.OnEnter(this.unit)
end)
frame:SetScript("OnLeave", function()
Extension.OnLeave()
end)
frame:SetParent(self.master)
local font = frame:CreateFontString(nil, "ARTWORK")
font:SetFontObject(GameFontHighlightSmall)
font:SetText("WW")
font:SetJustifyH("CENTER")
font:SetWidth(font:GetStringWidth())
font:SetHeight(14)
font:Show()
font:ClearAllPoints()
font:SetPoint(point, frame, relative,0, 0)
-- Add this font string to the frame
frame.Prefix = font
font = frame:CreateFontString(nil, "ARTWORK")
font:SetFontObject(GameFontHighlightSmall)
font:SetText()
font:SetJustifyH(justify)
font:SetWidth(55)
font:SetHeight(12)
font:Show()
font:ClearAllPoints()
font:SetPoint(point, frame.Prefix, relative, offset, 0)
-- Add this font string to the frame
frame.Name = font
local bar = CreateFrame("StatusBar", nil, frame)
bar:SetStatusBarTexture("Interface\\TargetingFrame\\UI-StatusBar")
bar:SetMinMaxValues(0,100)
bar:ClearAllPoints()
bar:SetPoint(point, frame.Name, relative, offset, 0)
bar:SetWidth(60)
bar:SetHeight(7)
bar:Show()
-- Add this status bar to the frame
frame.Bar = bar
font = frame:CreateFontString(nil, "ARTWORK")
font:SetFontObject(GameFontHighlightSmall)
font:SetText("")
font:SetJustifyH(justify)
font:SetWidth(font:GetStringWidth())
font:SetHeight(12)
font:Show()
font:ClearAllPoints()
font:SetPoint(point, frame.Bar, relative, offset, 0)
-- Add this font string to the frame
frame.Status = font
-- Lets set the frame in the indexed array
self.frames[i] = frame
self.frames["raid"..i] = frame
self.poolsize = i
end
mem2,thr2 = gcinfo()
--[[
self:Msg("Memory Usage After: %s [%s].", mem2, thr2)
self:Msg("Frame creation change: %s [%s].", mem2 - mem, thr2 - thr)
--]]
end
_G["CleveRoids"] = CleveRoids
+44
View File
@@ -0,0 +1,44 @@
local _G = _G or getfenv(0)
local CleveRoids = _G.CleveRoids or {}
CleveRoids.Hooks = CleveRoids.Hooks or {}
CleveRoids.mouseoverUnit = CleveRoids.mouseoverUnit or nil
local Extension = CleveRoids.RegisterExtension("ag_UnitFrames")
Extension.RegisterEvent("ADDON_LOADED", "OnLoad")
function Extension.OnEnter(unit)
CleveRoids.mouseoverUnit = unit
end
function Extension.OnLeave()
CleveRoids.mouseoverUnit = nil
end
-- Because AddOns are loaded in alphabetical order, this callback will never see the aUF loaded message, had to do a workaround...
function Extension.OnLoad()
if not aUF then
return
end
CleveRoids.Hooks.ag_UnitFrames = { OnEnter = aUF.classes.aUFunit.prototype.OnEnter, OnLeave = aUF.classes.aUFunit.prototype.OnLeave}
aUF.classes.aUFunit.prototype.OnEnter = CleveRoids.aUFOnEnter
aUF.classes.aUFunit.prototype.OnLeave = CleveRoids.aUFOnLeave
Extension.UnregisterEvent("ADDON_LOADED", "Onload")
end
-- Taken from ag_UnitClass.lua
function CleveRoids:aUFOnEnter()
Extension.OnEnter(self.unit)
self.frame.unit = self.unit
self:UpdateHighlight(true)
UnitFrame_OnEnter()
end
function CleveRoids:aUFOnLeave()
Extension.OnLeave()
self:UpdateHighlight()
UnitFrame_OnLeave()
end
_G["CleveRoids"] = CleveRoids
+299
View File
@@ -0,0 +1,299 @@
--[[
Author: Dennis Werner Garske (DWG) / brian / Mewtiny
License: MIT License
Fixes pfUI mouseover issues by:
- Using a unique source key per pfUI frame (e.g., "pfui:party3", "pfui:raid7")
- Pairing Set/Clear with the same per-frame key
- Resolving a real UnitID when .unit isn't set
- Properly hooking party group[0] (your own party slot) with a safe closure and defaulting to "player"
]]
local _G = _G or getfenv(0)
local CleveRoids = _G.CleveRoids or {}
CleveRoids.mouseoverUnit = CleveRoids.mouseoverUnit or nil
local Extension = CleveRoids.RegisterExtension("pfUI")
Extension.RegisterEvent("PLAYER_ENTERING_WORLD", "PLAYER_ENTERING_WORLD")
function Extension.OnLoad()
end
-- Resolve a pfUI unitframe (focus / focustarget and fallback for party/raid)
local function ResolvePfUnit(frame, fallbackName)
if not frame then return nil end
if frame.label and frame.id then
return frame.label .. frame.id
end
local name = fallbackName or frame.unitname
if not name or name == "" then return nil end
name = strlower(name)
local candidates = { "target", "targettarget", "player", "pet" }
local i
for i = 1, 4 do
table.insert(candidates, "party"..i)
table.insert(candidates, "partypet"..i)
end
for i = 1, 40 do
table.insert(candidates, "raid"..i)
table.insert(candidates, "raidpet"..i)
end
for _,u in ipairs(candidates) do
if UnitExists(u) and strlower(UnitName(u) or "") == name then
return u
end
end
return nil
end
-- Unique key per pfUI frame so leave events can't clear another frame's hover
local function PfSourceKey(frame)
if not frame then return "pfui:unknown" end
if frame.label and frame.id then
return "pfui:" .. frame.label .. frame.id
end
if frame.unit and frame.unit ~= "" then
return "pfui:" .. frame.unit
end
return "pfui:" .. tostring(frame) -- stable per-frame string in 1.12
end
-- Resolve a *real* UnitID for a pfUI frame
local function PfResolveUnit(frame, defaultUnit)
if frame and frame.unit and frame.unit ~= "" then
return frame.unit
end
if frame and frame.label and frame.id then
return frame.label .. frame.id
end
return ResolvePfUnit(frame) or defaultUnit
end
-- Helper to set with per-frame key
local function PfSet(frame, defaultUnit)
local key = PfSourceKey(frame)
local unit = PfResolveUnit(frame, defaultUnit)
if unit then
frame.__cr_src = key
CleveRoids.SetMouseoverFrom(key, unit)
end
end
-- Helper to clear with the same per-frame key
local function PfClear(frame)
if frame and frame.__cr_src then
CleveRoids.ClearMouseoverFrom(frame.__cr_src)
frame.__cr_src = nil
end
end
-- PLAYER
function Extension.RegisterPlayerScripts()
if not pfUI or not pfUI.uf or not pfUI.uf.player then return end
local frame = pfUI.uf.player
local onEnterFunc = frame:GetScript("OnEnter")
local onLeaveFunc = frame:GetScript("OnLeave")
frame:SetScript("OnEnter", function()
PfSet(this, "player")
if onEnterFunc then onEnterFunc(this) end
end)
frame:SetScript("OnLeave", function()
PfClear(this)
if onLeaveFunc then onLeaveFunc(this) end
end)
end
-- TARGET
function Extension.RegisterTargetScripts()
if not pfUI or not pfUI.uf or not pfUI.uf.target then return end
local frame = pfUI.uf.target
local onEnterFunc = frame:GetScript("OnEnter")
local onLeaveFunc = frame:GetScript("OnLeave")
frame:SetScript("OnEnter", function()
PfSet(this, "target")
if onEnterFunc then onEnterFunc(this) end
end)
frame:SetScript("OnLeave", function()
PfClear(this)
if onLeaveFunc then onLeaveFunc(this) end
end)
end
-- TARGETTARGET
function Extension.RegisterTargetTargetScripts()
if not pfUI or not pfUI.uf or not pfUI.uf.targettarget then return end
local frame = pfUI.uf.targettarget
local onEnterFunc = frame:GetScript("OnEnter")
local onLeaveFunc = frame:GetScript("OnLeave")
frame:SetScript("OnEnter", function()
PfSet(this, "targettarget")
if onEnterFunc then onEnterFunc(this) end
end)
frame:SetScript("OnLeave", function()
PfClear(this)
if onLeaveFunc then onLeaveFunc(this) end
end)
end
-- PARTY (pfUI.uf.group[0..4]) -- include 0 to cover your own party slot
function Extension.RegisterPartyScripts()
if not pfUI or not pfUI.uf or not pfUI.uf.group then return end
local i
for i = 0, 4 do
local frame = pfUI.uf.group[i]
if frame then
-- bind loop index for closures (Vanilla-safe)
local idx = i
local onEnterFunc = frame:GetScript("OnEnter")
local onLeaveFunc = frame:GetScript("OnLeave")
frame:SetScript("OnEnter", function()
-- For group[0] (your own party frame), default to "player"
local defaultUnit = (idx == 0) and "player" or nil
PfSet(this, defaultUnit)
if onEnterFunc then onEnterFunc(this) end
end)
frame:SetScript("OnLeave", function()
PfClear(this)
if onLeaveFunc then onLeaveFunc(this) end
end)
end
end
end
-- RAID (pfUI.uf.raid[1..40])
function Extension.RegisterRaidScripts()
if not pfUI or not pfUI.uf or not pfUI.uf.raid then return end
local i
for i = 1, 40 do
local frame = pfUI.uf.raid[i]
if frame then
local onEnterFunc = frame:GetScript("OnEnter")
local onLeaveFunc = frame:GetScript("OnLeave")
frame:SetScript("OnEnter", function()
PfSet(this)
if onEnterFunc then onEnterFunc(this) end
end)
frame:SetScript("OnLeave", function()
PfClear(this)
if onLeaveFunc then onLeaveFunc(this) end
end)
end
end
end
-- FOCUS
function Extension.RegisterFocusScripts()
if not pfUI or not pfUI.uf or not pfUI.uf.focus then return end
local frame = pfUI.uf.focus
local onEnterFunc = frame:GetScript("OnEnter")
local onLeaveFunc = frame:GetScript("OnLeave")
frame:SetScript("OnEnter", function()
PfSet(this) -- ResolvePfUnit handles focus emulation
if onEnterFunc then onEnterFunc(this) end
end)
frame:SetScript("OnLeave", function()
PfClear(this)
if onLeaveFunc then onLeaveFunc(this) end
end)
end
-- FOCUSTARGET (if your pfUI build provides it)
function Extension.RegisterFocusTargetScripts()
if not pfUI or not pfUI.uf or not pfUI.uf.focustarget then return end
local frame = pfUI.uf.focustarget
local onEnterFunc = frame:GetScript("OnEnter")
local onLeaveFunc = frame:GetScript("OnLeave")
frame:SetScript("OnEnter", function()
PfSet(this)
if onEnterFunc then onEnterFunc(this) end
end)
frame:SetScript("OnLeave", function()
PfClear(this)
if onLeaveFunc then onLeaveFunc(this) end
end)
end
-- PARTYTARGET (party1target..party4target, plus player's target)
function Extension.RegisterPartyTargetScripts()
if not pfUI or not pfUI.uf then return end
-- This helper function is used to hook any given frame.
local function hookFrame(frame, defaultUnit)
if not frame then return end
local onEnterFunc = frame:GetScript("OnEnter")
local onLeaveFunc = frame:GetScript("OnLeave")
frame:SetScript("OnEnter", function()
PfSet(this, defaultUnit)
-- We remove the call to the original onEnterFunc to prevent overwritten tooltips.
end)
frame:SetScript("OnLeave", function()
PfClear(this)
if onLeaveFunc then onLeaveFunc(this) end
end)
end
-- This helper function is specifically for party member targets (1-4)
local function hookPartyMemberTarget(i, frame)
if not frame then return end
local defaultUnit = "party" .. i .. "target"
hookFrame(frame, defaultUnit)
end
-- Case A: Hook dedicated arrays for party members 1-4
if pfUI.uf.grouptarget then
for i = 1, 4 do hookPartyMemberTarget(i, pfUI.uf.grouptarget[i]) end
end
if pfUI.uf.partytarget then
for i = 1, 4 do hookPartyMemberTarget(i, pfUI.uf.partytarget[i]) end
end
-- Case B: Hook child target frames for party members 1-4
if pfUI.uf.group then
for i = 1, 4 do
local g = pfUI.uf.group[i]
if g and g.target then hookPartyMemberTarget(i, g.target) end
end
end
--- START OF FIX to include party0target ---
-- Case C: Specifically find and hook the player's own target frame (group[0].target)
if pfUI.uf.group and pfUI.uf.group[0] and pfUI.uf.group[0].target then
-- The player's target UnitID is always "target", not "party0target".
hookFrame(pfUI.uf.group[0].target, "target")
end
--- END OF FIX ---
end
function Extension.PLAYER_ENTERING_WORLD()
if not pfUI or not pfUI.uf then return end
Extension.RegisterPlayerScripts()
Extension.RegisterTargetScripts()
Extension.RegisterTargetTargetScripts()
Extension.RegisterPartyScripts()
Extension.RegisterPartyTargetScripts()
Extension.RegisterRaidScripts()
Extension.RegisterFocusScripts()
Extension.RegisterFocusTargetScripts()
end
+24
View File
@@ -0,0 +1,24 @@
--[[
Author: Dennis Werner Garske (DWG) / brian / Mewtiny
License: MIT License
]]
local _G = _G or getfenv(0)
local CleveRoids = _G.CleveRoids or {}
CleveRoids.mouseoverUnit = CleveRoids.mouseoverUnit or nil
local Extension = CleveRoids.RegisterExtension("sRaidFrames")
Extension.RegisterEvent("ADDON_LOADED", "OnLoad")
function Extension:OnEnter(frame)
CleveRoids.mouseoverUnit = frame.unit
end
function Extension.OnLoad()
if arg1 ~= "sRaidFrames" then
return
end
Extension.HookMethod(sRaidFrames, "UnitTooltip", "OnEnter")
end
_G["CleveRoids"] = CleveRoids
+259
View File
@@ -0,0 +1,259 @@
--[[
Author: Dennis Werner Garske (DWG) / brian / Mewtiny
License: MIT License
]]
local _G = _G or getfenv(0)
local CleveRoids = _G.CleveRoids or {}
-- Indexes all spells the current player and pet knows
function CleveRoids.IndexSpells()
local spells = {}
local i = 0
local book = 1
local bookType = CleveRoids.bookTypes[book]
local maxBooks = table.getn(CleveRoids.bookTypes)
spells[bookType] = {}
while true do
i = i + 1
local spellName, spellRank = GetSpellName(i, bookType)
if not spellName then
i = 0
book = book + 1
if book > maxBooks then
break
end
bookType = CleveRoids.bookTypes[book]
spells[bookType] = {}
else
local cost, reagent = CleveRoids.GetSpellCost(i, bookType)
local texture = GetSpellTexture(i, bookType)
if not spells[bookType][spellName] then
spells[bookType][spellName] = {
spellSlot = i,
name = spellName,
bookType = bookType,
texture = texture,
cost = cost,
reagent = reagent,
}
end
if spellRank and not spells[bookType][spellName][spellRank] then
spells[bookType][spellName][spellRank] = {
spellSlot = i,
name = spellName,
rank = spellRank,
bookType = bookType,
texture = texture,
cost = cost,
reagent = reagent
}
spells[bookType][spellName].highest = spells[bookType][spellName][spellRank]
end
if reagent then
CleveRoids.countedItemTypes[reagent] = true
end
end
end
CleveRoids.Spells = spells
end
function CleveRoids.IndexTalents()
local talents = {[1] = true}
for tab = 1, GetNumTalentTabs() do
for i = 1, GetNumTalents(tab) do
local name, _, _, _, rank = GetTalentInfo(tab, i)
talents[name] = tonumber(rank)
end
end
CleveRoids.Talents = talents
end
function CleveRoids.IndexItems()
local items = {}
for bagID = 0, NUM_BAG_SLOTS do
for slot = GetContainerNumSlots(bagID), 1, -1 do
local link = GetContainerItemLink(bagID, slot)
if link then
local _, _, itemID = string.find(link, "item:(%d+)")
local name, link, _, _, itemType, itemSubType, _, _, texture = GetItemInfo(itemID)
if name then
local _, count = GetContainerItemInfo(bagID, slot)
if not items[name] then
items[name] = {
bagID = bagID,
slot = slot,
id = itemID,
name = name,
type = itemType,
count = count,
texture = texture,
link = link,
bagSlots = {{bagID, slot}},
slotsIndex = 1,
}
items[itemID] = name
else
items[name].count = (items[name].count or 0) + (count or 0)
table.insert(items[name].bagSlots, {bagID, slot})
end
end
end
end
end
for inventoryID = 0, 19 do
local link = GetInventoryItemLink("player", inventoryID)
if link then
local _, _, itemID = string.find(link, "item:(%d+)")
local name, link, _, _, itemType, itemSubType, _, _, texture = GetItemInfo(itemID)
if name then
local count = GetInventoryItemCount("player", inventoryID)
if not items[name] then
items[name] = {
inventoryID = inventoryID,
id = itemID,
name = name,
count = count,
texture = texture,
link = link,
}
items[itemID] = name
else
items[name].inventoryID = inventoryID
items[name].count = (items[name].count or 0) + (count or 0)
end
end
end
end
CleveRoids.lastGetItem = nil
CleveRoids.Items = items
-- relink an item action to the item if it wasn't in inventory/bags before
for slot, actions in CleveRoids.Actions do
for i, action in actions.list do
if action.item then
action.item = CleveRoids.GetItem(action.action)
end
end
end
end
function CleveRoids.ClearSlot(slots, slot)
if slots[slot] then
slots[slots[slot]] = nil
end
slots[slot] = nil
end
function CleveRoids.IndexActionSlot(slot)
if not HasAction(slot) then
CleveRoids.Actions[slot] = nil
CleveRoids.ClearSlot(CleveRoids.reactiveSlots, slot)
CleveRoids.ClearSlot(CleveRoids.actionSlots, slot)
else
local actionType, _, name, rank = CleveRoids.GetActionButtonInfo(slot)
if name then
local reactiveName = CleveRoids.reactiveSpells[name] and name
local actionSlotName = name..(rank and ("("..rank..")") or "")
if reactiveName then
if not CleveRoids.reactiveSlots[reactiveName] then
CleveRoids.reactiveSlots[reactiveName] = slot
CleveRoids.reactiveSlots[slot] = reactiveName
end
elseif not reactiveName then
CleveRoids.ClearSlot(CleveRoids.reactiveSlots, slot)
end
if actionType == "SPELL" or actionType == "ITEM" then
if not CleveRoids.actionSlots[actionSlotName] then
CleveRoids.actionSlots[actionSlotName] = slot
CleveRoids.actionSlots[slot] = actionSlotName
end
end
end
end
CleveRoids.TestForActiveAction(CleveRoids.GetAction(slot))
CleveRoids.SendEventForAction(slot, "ACTIONBAR_SLOT_CHANGED", slot)
end
function CleveRoids.IndexActionBars()
for i = 1, 120 do
CleveRoids.IndexActionSlot(i)
end
end
function CleveRoids.GetSpell(text)
text = CleveRoids.Trim(text)
local rs, _, rank = string.find(text, "[^%s]%((Rank %d+)%)$")
local name = rank and string.sub(text, 1, rs) or text
for book, spells in CleveRoids.Spells do
if spells and spells[name] then
return spells[name][rank or "highest"]
end
end
end
function CleveRoids.GetTalent(text)
text = CleveRoids.Trim(text)
return CleveRoids.Talents[text]
end
function CleveRoids.GetItem(text)
local item = CleveRoids.Items[text] or CleveRoids.Items[tostring(text)]
if item then
-- Items are stored as [name]->{item} and [id]->name
if type(item) == "table" then return item end
return CleveRoids.Items[tostring(item)]
else
local name, link, _, _, itemType, _, _, _, texture = GetItemInfo(text)
if not name then
return
end
local item = {
id = text,
name = name,
link = link,
texture = texture,
}
CleveRoids.Items[name] = item
return item
end
end
function CleveRoids.GetNextBagSlotForUse(item, text)
if not item then return end
if CleveRoids.lastGetItem == CleveRoids.GetItem(text) then
if table.getn(item.bagSlots) > item.slotsIndex then
item.slotsIndex = item.slotsIndex + 1
item.bagID, item.slot = unpack(item.bagSlots[item.slotsIndex])
end
end
CleveRoids.lastGetItem = item
return item
end
local Extension = CleveRoids.RegisterExtension("Generic_show")
Extension.RegisterEvent("SPELLS_CHANGED", "SPELLS_CHANGED")
function Extension.OnLoad()
end
function Extension.SPELLS_CHANGED()
end
+220
View File
@@ -0,0 +1,220 @@
--[[
Author: Dennis Werner Garske (DWG) / brian / Mewtiny
License: MIT License
]]
local _G = _G or getfenv(0)
local CleveRoids = _G.CleveRoids or {}
-- A list of all registered extensions
CleveRoids.Extensions = CleveRoids.Extensions or {}
-- Calls the "OnLoad" function of every extension
function CleveRoids.InitializeExtensions()
for k, v in pairs(CleveRoids.Extensions) do
local func = v["OnLoad"]
if not func then
CleveRoids.Print("CleveRoids.InitializeExtensions - Couldn't find 'OnLoad' function for extension "..k)
else
func()
end
end
end
-- Removes the given hook
-- hook: The hook to remove
function CleveRoids.RemoveHook(hook)
_G[hook.name] = hook.original
end
-- Removes the given hook from the given object
-- object: The object to remove the hook from
-- hook: The hook to remove
function CleveRoids.RemoveMethodHook(object, hook)
object[hook.name] = hook.original
end
-- Clears all previously declared hooks
function CleveRoids.ClearHooks()
for k, v in pairs(CleveRoids.Extensions) do
for k2, v2 in pairs(v.internal.memberHooks) do
for k3, v3 in pairs(v2) do
CleveRoids.RemoveMethodHook(k2, v3)
end
end
for k2, v2 in pairs(v.internal.hooks) do
CleveRoids.RemoveHook(v2)
end
end
end
-- Creates a new extension with the given name
-- name: the name of the extension
function CleveRoids.RegisterExtension(name)
local extension = {
internal =
{
frame = CreateFrame("FRAME"),
eventHandlers = {},
hooks = {},
memberHooks = {},
},
}
extension.RegisterEvent = function(eventName, callbackName)
CleveRoids.RegisterEvent(name, eventName, callbackName)
end
extension.Hook = function(functionName, callbackName, dontCallOriginal)
CleveRoids.RegisterHook(name, functionName, callbackName, dontCallOriginal)
end
extension.HookMethod = function(object, functionName, callbackName, dontCallOriginal)
CleveRoids.RegisterMethodHook(name, object, functionName, callbackName, dontCallOriginal)
end
extension.UnregisterEvent = function(eventName, callbackName)
CleveRoids.UnregisterEvent(name, eventName, callbackName)
end
extension.internal.OnEvent = function()
local callbackName = extension.internal.eventHandlers[event]
if callbackName then
extension[callbackName]()
end
end
-- This is a function wrapper that we swap with the function that we want to hook
-- @return Value of Callback() or Origininal() if dontCallOriginal is false
extension.internal.OnHook = function(object, functionName, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10)
local hook
if object then
hook = extension.internal.memberHooks[object][functionName]
else
hook = extension.internal.hooks[functionName]
end
local retval = hook.callback(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10)
if not hook.dontCallOriginal then
retval = hook.original(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10)
end
return retval
end
extension.internal.frame:SetScript("OnEvent", extension.internal.OnEvent)
CleveRoids.Extensions[name] = extension
return extension
end
-- Registers a callback function for a given event name
-- extensionName: The name of the extension trying to register the callback
-- eventName: The event's name we'd like to register a callback for
-- callbackName: The name of the callback that get's called when the event fires
function CleveRoids.RegisterEvent(extensionName, eventName, callbackName)
local extension = CleveRoids.Extensions[extensionName]
extension.internal.eventHandlers[eventName] = callbackName
extension.internal.frame:RegisterEvent(eventName)
end
-- Hooks the given function by it's name
-- extensionName: The name of the extension trying to register the callback
-- functionName: The name of the function that'll be hooked
-- callbackName: The name of the callback that get's called when the hooked function is called
-- dontCallOriginal: Set to true when the original function should not be called
function CleveRoids.RegisterHook(extensionName, functionName, callbackName, dontCallOriginal)
local orig = _G[functionName]
local extension = CleveRoids.Extensions[extensionName]
if not orig then
CleveRoids.Print("CleveRoids.RegisterHook - Invalid function to hook: "..functionName)
end
if not extension then
CleveRoids.Print("CleveRoids.RegisterHook - Invalid extension: "..extension)
return
end
if not extension[callbackName] then
CleveRoids.Print("CleveRoids.RegisterHook - Couldn't find callback: "..callbackName)
return
end
extension.internal.hooks[functionName] = {
original = orig,
callback = extension[callbackName],
name = functionName,
dontCallOriginal = dontCallOriginal
}
_G[functionName] = function(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10)
return extension.internal.OnHook(nil, functionName, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10)
end
end
-- Hooks the given object's function
-- object: The object you want to hook
-- extensionName: The name of the extension trying to register the callback
-- functionName: The name of the function that'll be hooked
-- callbackName: The name of the callback that get's called when the hooked function is called
function CleveRoids.RegisterMethodHook(extensionName, object, functionName, callbackName, dontCallOriginal)
if not object then
CleveRoids.Print("CleveRoids.RegisterMethodHook - The object could not be found!")
return
end
if type(object) ~= "table" then
CleveRoids.Print("CleveRoids.RegisterMethodHook - The object needs to be a table!")
return
end
local orig = object[functionName]
if not orig then
CleveRoids.Print("CleveRoids.RegisterMethodHook - The object doesn't have a function named "..functionName)
return
end
local extension = CleveRoids.Extensions[extensionName]
if not extension then
CleveRoids.Print("CleveRoids.RegisterMethodHook - Invalid extension: "..extension)
return
end
if not extension[callbackName] then
CleveRoids.Print("CleveRoids.RegisterMethodHook - Couldn't find callback: "..callbackName)
return
end
if not extension.internal.memberHooks[object] then
extension.internal.memberHooks[object] = {}
end
extension.internal.memberHooks[object][functionName] = {
original = orig,
callback = extension[callbackName],
name = functionName,
dontCallOriginal = dontCallOriginal
}
object[functionName] = function(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10)
return extension.internal.OnHook(object, functionName, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10)
end
end
function CleveRoids.UnregisterEvent(extensionName, eventName, callbackName)
local extension = CleveRoids.Extensions[extensionName]
if extension.internal.eventHandlers[eventName] then
extension.internal.eventHandlers[eventName] = nil
extension.internal.frame:UnregisterEvent(eventName)
end
end
_G["CleveRoids"] = CleveRoids
+135
View File
@@ -0,0 +1,135 @@
local _G = _G or getfenv(0)
local CleveRoids = _G.CleveRoids or {}
_G.CleveRoids = CleveRoids
CleveRoids.ready = false
CleveRoids.Hooks = CleveRoids.Hooks or {}
CleveRoids.Hooks.GameTooltip = {}
CleveRoids.Extensions = CleveRoids.Extensions or {}
CleveRoids.actionEventHandlers = {}
CleveRoids.mouseOverResolvers = {}
CleveRoids.mouseoverUnit = CleveRoids.mouseoverUnit or nil
CleveRoids.mouseOverUnit = nil
-- Environment flags
CleveRoids.hasSuperwow = SetAutoloot and true or false
CleveRoids.hasTurtle = (type(_G.TURTLE_WOW_VERSION) ~= "nil")
CleveRoids.supported = (CleveRoids.hasSuperwow or CleveRoids.hasTurtle)
CleveRoids.ParsedMsg = {}
CleveRoids.Items = {}
CleveRoids.Spells = {}
CleveRoids.Talents = {}
CleveRoids.Cooldowns = {}
CleveRoids.Macros = {}
CleveRoids.Actions = {}
CleveRoids.Sequences = {}
CleveRoids.lastUpdate = 0
CleveRoids.lastGetItem = nil
CleveRoids.currentSequence = nil
CleveRoids.bookTypes = {BOOKTYPE_SPELL, BOOKTYPE_PET}
CleveRoids.unknownTexture = "Interface\\Icons\\INV_Misc_QuestionMark"
CleveRoids.spell_tracking = {}
-- Holds information about the currently cast spell
CleveRoids.CurrentSpell = {
-- "channeled" or "cast"
type = "",
-- the name of the spell
spellName = "",
-- is the Attack ability enabled
autoAttack = false,
-- is the Auto Shot ability enabled
autoShot = false,
-- is the Shoot ability (wands) enabled
wand = false,
}
CleveRoids.dynamicCmds = {
["/cast"] = true,
["/castsequence"] = true,
["/use"] = true,
["/equip"] = true,
["/equipmh"] = true,
["/equipoh"] = true,
}
CleveRoids.ignoreKeywords = {
action = true,
ignoretooltip = true,
cancelaura = true,
}
-- TODO: Localize?
CleveRoids.countedItemTypes = {
["Consumable"] = true,
["Reagent"] = true,
["Projectile"] = true,
["Trade Goods"] = true,
}
-- TODO: Localize?
CleveRoids.actionSlots = {}
CleveRoids.reactiveSlots = {}
CleveRoids.reactiveSpells = {
["Revenge"] = true,
["Overpower"] = true,
["Riposte"] = true,
["Surprise Attack"] = true,
["Mongoose Bite"] = true,
["Counterattack"] = true,
["Arcane Surge"] = true,
}
CleveRoids.spamConditions = {
[CleveRoids.Localized.Attack] = "checkchanneled",
[CleveRoids.Localized.AutoShot] = "checkchanneled",
[CleveRoids.Localized.Shoot] = "checkchanneled",
}
CleveRoids.auraTextures = {
[CleveRoids.Localized.Spells["Stealth"]] = "Interface\\Icons\\Ability_Stealth",
[CleveRoids.Localized.Spells["Prowl"]] = "Interface\\Icons\\Ability_Ambush",
[CleveRoids.Localized.Spells["Shadowform"]] = "Interface\\Icons\\Spell_Shadow_Shadowform",
["Seal of Wisdom"] = "Interface\\Icons\\Spell_Holy_RighteousnessAura",
["Seal of the Crusader"] = "Interface\\Icons\\Spell_Holy_HolySmite",
["Seal of Light"] = "Interface\\Icons\\Spell_Holy_HealingAura",
["Seal of the Justice"] = "Interface\\Icons\\Spell_Holy_SealOfWrath",
["Seal of Righteousness"] = "Interface\\Icons\\Ability_ThunderBolt",
["Seal of Command"] = "Interface\\Icons\\Ability_Warrior_InnerRage",
}
-- I need to make a 2h modifier
-- Maps easy to use weapon type names (e.g. Axes, Shields) to their inventory slot name and their localized tooltip name
CleveRoids.WeaponTypeNames = {
Daggers = { slot = "MainHandSlot", name = CleveRoids.Localized.Dagger },
Fists = { slot = "MainHandSlot", name = CleveRoids.Localized.FistWeapon },
Axes = { slot = "MainHandSlot", name = CleveRoids.Localized.Axe },
Swords = { slot = "MainHandSlot", name = CleveRoids.Localized.Sword },
Staves = { slot = "MainHandSlot", name = CleveRoids.Localized.Staff },
Maces = { slot = "MainHandSlot", name = CleveRoids.Localized.Mace },
Polearms = { slot = "MainHandSlot", name = CleveRoids.Localized.Polearm },
-- OH
Daggers2 = { slot = "SecondaryHandSlot", name = CleveRoids.Localized.Dagger },
Fists2 = { slot = "SecondaryHandSlot", name = CleveRoids.Localized.FistWeapon },
Axes2 = { slot = "SecondaryHandSlot", name = CleveRoids.Localized.Axe },
Swords2 = { slot = "SecondaryHandSlot", name = CleveRoids.Localized.Sword },
Maces2 = { slot = "SecondaryHandSlot", name = CleveRoids.Localized.Mace },
Shields = { slot = "SecondaryHandSlot", name = CleveRoids.Localized.Shield },
-- ranged
Guns = { slot = "RangedSlot", name = CleveRoids.Localized.Gun },
Crossbows = { slot = "RangedSlot", name = CleveRoids.Localized.Crossbow },
Bows = { slot = "RangedSlot", name = CleveRoids.Localized.Bow },
Thrown = { slot = "RangedSlot", name = CleveRoids.Localized.Thrown },
Wands = { slot = "RangedSlot", name = CleveRoids.Localized.Wand },
}
_G["CleveRoids"] = CleveRoids
+21
View File
@@ -0,0 +1,21 @@
MIT License
Copyright (c) 2016 Dennis Werner Garske (DWG)
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
+444
View File
@@ -0,0 +1,444 @@
--[[
Author : Dennis Werner Garske (DWG) / brian / Mewtiny
License : MIT License
]]
local _G = _G or getfenv(0)
local CleveRoids = _G.CleveRoids or {}
CleveRoids.Locale = GetLocale()
CleveRoids.Localized = {}
if CleveRoids.Locale == "enUS" or CleveRoids.Locale == "enGB" then
-- place item in backpack slot 1 and run:
-- /script local l=GetContainerItemLink(0,1);local _,_,id=string.find(l,"item:(%d+)");local n,_,_,_,t,st=GetItemInfo(id);DEFAULT_CHAT_FRAME:AddMessage("\n\nID: ["..id.."]\nName: ["..n.."]\nType: ["..t.."]\nSub Type: ["..st.."]\n\n");
CleveRoids.Localized.Shield = "Shields"
CleveRoids.Localized.Bow = "Bows"
CleveRoids.Localized.Crossbow = "Crossbows"
CleveRoids.Localized.Gun = "Guns"
CleveRoids.Localized.Thrown = "Thrown"
CleveRoids.Localized.Wand = "Wands"
CleveRoids.Localized.Sword = "Swords"
CleveRoids.Localized.Staff = "Staves"
CleveRoids.Localized.Polearm = "Polearms"
CleveRoids.Localized.Mace = "Maces"
CleveRoids.Localized.FistWeapon = "Fist Weapons"
CleveRoids.Localized.Dagger = "Daggers"
CleveRoids.Localized.Axe = "Axes"
CleveRoids.Localized.Attack = "Attack"
CleveRoids.Localized.AutoShot = "Auto Shot"
CleveRoids.Localized.Shoot = "Shoot"
CleveRoids.Localized.SpellRank = "%(Rank %d+%)"
-- target creature and run:
-- /script local ct, uc = UnitCreatureType("target"),UnitClassification("target"); DEFAULT_CHAT_FRAME:AddMessage("\n\nUnitCreatureType: ["..ct.."]\nUnitClassificationType: ["..uc.."]\n\n");
CleveRoids.Localized.CreatureTypes = {
["Beast"] = "Beast",
["Critter"] = "Critter",
["Demon"] = "Demon",
["Dragonkin"] = "Dragonkin",
["Elemental"] = "Elemental",
["Giant"] = "Giant",
["Humanoid"] = "Humanoid",
["Mechanical"] = "Mechanical",
["Not specified"] = "Not Specified",
["Totem"] = "Totem",
["Undead"] = "Undead",
}
CleveRoids.Localized.Spells = {
["Shadowform"] = "Shadowform",
["Stealth"] = "Stealth",
["Prowl"] = "Prowl",
["Revenge"] = "Revenge",
["Overpower"] = "Overpower",
["Riposte"] = "Riposte",
["Surprise Attack"] = "Surprise Attack",
["Mongoose Bite"] = "Mongoose Bite",
["Counterattack"] = "Counterattack",
["Arcane Surge"] = "Arcane Surge",
}
-- place item in backpack slot 1 and run:
-- /script local l=GetContainerItemLink(0,1);local _,_,id=string.find(l,"item:(%d+)");local n,_,_,_,t,st=GetItemInfo(id);DEFAULT_CHAT_FRAME:AddMessage("\n\nID: ["..id.."]\nName: ["..n.."]\nType: ["..t.."]\nSub Type: ["..st.."]\n\n");
CleveRoids.Localized.ItemTypes = {
["Consumable"] = "Consumable",
["Reagent"] = "Reagent",
["Projectile"] = "Projectile",
["Trade Goods"] = "Trade Goods",
}
elseif CleveRoids.Locale == "deDE" then
CleveRoids.Localized.Shield = "Schilde"
CleveRoids.Localized.Bow = "Bögen"
CleveRoids.Localized.Crossbow = "Armbrüste"
CleveRoids.Localized.Gun = "Waffen"
CleveRoids.Localized.Thrown = "Geworfen"
CleveRoids.Localized.Wand = "Zauberstäbe"
CleveRoids.Localized.Sword = "Schwerter"
CleveRoids.Localized.Staff = "Dauben"
CleveRoids.Localized.Polearm = "Stangenwaffen"
CleveRoids.Localized.Mace = "Streitkolben"
CleveRoids.Localized.FistWeapon = "Faustwaffen"
CleveRoids.Localized.Dagger = "Dolche"
CleveRoids.Localized.Axe = "Äxte"
CleveRoids.Localized.Attack = "Angriff"
CleveRoids.Localized.AutoShot = "Automatischer Schuss"
CleveRoids.Localized.Shoot = "Schießen"
CleveRoids.Localized.SpellRank = "%(Rank %d+%)"
CleveRoids.Localized.CreatureTypes = {
["Wildtier"] = "Beast",
["Kleintier"] = "Critter",
["Dämon"] = "Demon",
["Drachkin"] = "Dragonkin",
["Elementar"] = "Elemental",
["Riese"] = "Giant",
["Humanoid"] = "Humanoid",
["Mechanisch"] = "Mechanical",
["Nicht spezifiziert"] = "Not Specified",
["Totem"] = "Totem",
["Untoter"] = "Undead",
}
CleveRoids.Localized.Spells = {
["Shadowform"] = "Schattengestalt",
["Stealth"] = "Verstohlenheit",
["Prowl"] = "Schleichen",
["Revenge"] = "Rache",
["Overpower"] = "Überwältigen",
["Riposte"] = "Riposte",
["Surprise Attack"] = "Überraschungsangriff",
["Mongoose Bite"] = "Mungobiss",
["Counterattack"] = "Gegenangriff",
["Arcane Surge"] = "Arkane Woge",
}
CleveRoids.Localized.ItemTypes = {
["Consumable"] = "Verbrauchsmaterial",
["Reagent"] = "Reagens",
["Projectile"] = "Projektil",
["Trade Goods"] = "Handwerkswaren",
}
elseif CleveRoids.Locale == "frFR" then
CleveRoids.Localized.Shield = "Boucliers"
CleveRoids.Localized.Bow = "Arcs"
CleveRoids.Localized.Crossbow = "Arbalètes"
CleveRoids.Localized.Gun = "Armes à feu"
CleveRoids.Localized.Thrown = "Thrown"
CleveRoids.Localized.Wand = "Wands"
CleveRoids.Localized.Sword = "Swords"
CleveRoids.Localized.Staff = "Staves"
CleveRoids.Localized.Polearm = "Polearms"
CleveRoids.Localized.Mace = "Maces"
CleveRoids.Localized.FistWeapon = "Fist Weapons"
CleveRoids.Localized.Dagger = "Daggers"
CleveRoids.Localized.Axe = "Axes"
CleveRoids.Localized.Attack = "Attack"
CleveRoids.Localized.AutoShot = "Auto Shot"
CleveRoids.Localized.Shoot = "Shoot"
CleveRoids.Localized.SpellRank = "%(Rank %d+%)"
CleveRoids.Localized.CreatureTypes = {
["Bête"] = "Beast",
["Bestiole"] = "Critter",
["Démon"] = "Demon",
["Draconien"] = "Dragonkin",
["Elémentaire"] = "Elemental",
["Géant"] = "Giant",
["Humanoïde"] = "Humanoid",
["Machine"] = "Mechanical",
["Non spécifié"] = "Not Specified",
["Totem"] = "Totem",
["Mort-vivant"] = "Undead",
}
CleveRoids.Localized.Spells = {
["Shadowform"] = "Forme d'Ombre",
["Stealth"] = "Camouflage",
["Prowl"] = "Rôder",
["Revenge"] = "Vengeance",
["Overpower"] = "Fulgurance",
["Riposte"] = "Riposte",
["Surprise Attack"] = "Attaque surprise",
["Mongoose Bite"] = "Morsure de la mangouste",
["Counterattack"] = "Contre-attaque",
["Arcane Surge"] = "Éruption darcanes",
}
CleveRoids.Localized.ItemTypes = {
["Consumable"] = "Consommable",
["Reagent"] = "Reagent",
["Projectile"] = "Projectile",
["Trade Goods"] = "Artisanat",
}
elseif CleveRoids.Locale == "koKR" then
CleveRoids.Localized.Shield = "Shields"
CleveRoids.Localized.Bow = "Bows"
CleveRoids.Localized.Crossbow = "Crossbows"
CleveRoids.Localized.Gun = "Guns"
CleveRoids.Localized.Thrown = "Thrown"
CleveRoids.Localized.Wand = "Wands"
CleveRoids.Localized.Sword = "Swords"
CleveRoids.Localized.Staff = "Staves"
CleveRoids.Localized.Polearm = "Polearms"
CleveRoids.Localized.Mace = "Maces"
CleveRoids.Localized.FistWeapon = "Fist Weapons"
CleveRoids.Localized.Dagger = "Daggers"
CleveRoids.Localized.Axe = "Axes"
CleveRoids.Localized.Attack = "Attack"
CleveRoids.Localized.AutoShot = "Auto Shot"
CleveRoids.Localized.Shoot = "Shoot"
CleveRoids.Localized.SpellRank = "%(Rank %d+%)"
CleveRoids.Localized.CreatureTypes = {
["야수"] = "Beast",
["동물"] = "Critter",
["악마"] = "Demon",
["용족"] = "Dragonkin",
["정령"] = "Elemental",
["거인"] = "Giant",
["인간형"] = "Humanoid",
["기계"] = "Mechanical",
["기타"] = "Not Specified",
["토템"] = "Totem",
["언데드"] = "Undead",
}
CleveRoids.Localized.Spells = {
["Shadowform"] = "어둠의 형상",
["Stealth"] = "은신",
["Prowl"] = "숨기",
["Revenge"] = "복수",
["Overpower"] = "제압",
["Riposte"] = "반격",
["Surprise Attack"] = "기습",
["Mongoose Bite"] = "살쾡이의 이빨",
["Counterattack"] = "역습",
["Arcane Surge"] = "비전 쇄도",
}
CleveRoids.Localized.ItemTypes = {
["Consumable"] = "소모품",
["Reagent"] = "Reagent",
["Projectile"] = "Projectile",
["Trade Goods"] = "거래 용품",
}
elseif CleveRoids.Locale == "zhCN" then
CleveRoids.Localized.Shield = "Shields"
CleveRoids.Localized.Bow = "Bows"
CleveRoids.Localized.Crossbow = "Crossbows"
CleveRoids.Localized.Gun = "Guns"
CleveRoids.Localized.Thrown = "Thrown"
CleveRoids.Localized.Wand = "Wands"
CleveRoids.Localized.Sword = "Swords"
CleveRoids.Localized.Staff = "Staves"
CleveRoids.Localized.Polearm = "Polearms"
CleveRoids.Localized.Mace = "Maces"
CleveRoids.Localized.FistWeapon = "Fist Weapons"
CleveRoids.Localized.Dagger = "Daggers"
CleveRoids.Localized.Axe = "Axes"
CleveRoids.Localized.Attack = "Attack"
CleveRoids.Localized.AutoShot = "Auto Shot"
CleveRoids.Localized.Shoot = "Shoot"
CleveRoids.Localized.SpellRank = "%(Rank %d+%)"
CleveRoids.Localized.CreatureTypes = {
["野兽"] = "Beast",
["小动物"] = "Critter",
["恶魔"] = "Demon",
["龙类"] = "Dragonkin",
["元素生物"] = "Elemental",
["巨人"] = "Giant",
["人型生物"] = "Humanoid",
["机械"] = "Mechanical",
["未指定"] = "Not Specified",
["图腾"] = "Totem",
["亡灵"] = "Undead",
}
CleveRoids.Localized.Spells = {
["Shadowform"] = "暗影形态",
["Stealth"] = "潜行",
["Prowl"] = "潜行",
["Revenge"] = "复仇",
["Overpower"] = "压制",
["Riposte"] = "还击",
["Surprise Attack"] = "偷袭",
["Mongoose Bite"] = "猫鼬撕咬",
["Counterattack"] = "反击",
["Arcane Surge"] = "奥术涌动",
}
CleveRoids.Localized.ItemTypes = {
["Consumable"] = "消耗品",
["Reagent"] = "Reagent",
["Projectile"] = "Projectile",
["Trade Goods"] = "贸易品",
}
elseif CleveRoids.Locale == "zhTW" then
CleveRoids.Localized.Shield = "Shields"
CleveRoids.Localized.Bow = "Bows"
CleveRoids.Localized.Crossbow = "Crossbows"
CleveRoids.Localized.Gun = "Guns"
CleveRoids.Localized.Thrown = "Thrown"
CleveRoids.Localized.Wand = "Wands"
CleveRoids.Localized.Sword = "Swords"
CleveRoids.Localized.Staff = "Staves"
CleveRoids.Localized.Polearm = "Polearms"
CleveRoids.Localized.Mace = "Maces"
CleveRoids.Localized.FistWeapon = "Fist Weapons"
CleveRoids.Localized.Dagger = "Daggers"
CleveRoids.Localized.Axe = "Axes"
CleveRoids.Localized.Attack = "Attack"
CleveRoids.Localized.AutoShot = "Auto Shot"
CleveRoids.Localized.Shoot = "Shoot"
CleveRoids.Localized.SpellRank = "%(Rank %d+%)"
CleveRoids.Localized.CreatureTypes = {
["野獸"] = "Beast",
["小動物"] = "Critter",
["惡魔"] = "Demon",
["龍類"] = "Dragonkin",
["元素生物"] = "Elemental",
["巨人"] = "Giant",
["人型生物"] = "Humanoid",
["機械"] = "Mechanical",
["不明"] = "Not Specified",
["圖騰"] = "Totem",
["不死族"] = "Undead",
}
CleveRoids.Localized.Spells = {
["Shadowform"] = "暗影形態",
["Stealth"] = "隱形",
["Prowl"] = "徘徊",
["Revenge"] = "復仇",
["Overpower"] = "壓倒",
["Riposte"] = "還擊",
["Surprise Attack"] = "偷襲",
["Mongoose Bite"] = "貓鼬咬傷",
["Counterattack"] = "反擊",
["Arcane Surge"] = "奧術湧動",
}
CleveRoids.Localized.ItemTypes = {
["Consumable"] = "消耗品",
["Reagent"] = "Reagent",
["Projectile"] = "Projectile",
["Trade Goods"] = "貿易貨物",
}
elseif CleveRoids.Locale == "ruRU" then
CleveRoids.Localized.Shield = "Shields"
CleveRoids.Localized.Bow = "Bows"
CleveRoids.Localized.Crossbow = "Crossbows"
CleveRoids.Localized.Gun = "Guns"
CleveRoids.Localized.Thrown = "Thrown"
CleveRoids.Localized.Wand = "Wands"
CleveRoids.Localized.Sword = "Swords"
CleveRoids.Localized.Staff = "Staves"
CleveRoids.Localized.Polearm = "Polearms"
CleveRoids.Localized.Mace = "Maces"
CleveRoids.Localized.FistWeapon = "Fist Weapons"
CleveRoids.Localized.Dagger = "Daggers"
CleveRoids.Localized.Axe = "Axes"
CleveRoids.Localized.Attack = "Attack"
CleveRoids.Localized.AutoShot = "Auto Shot"
CleveRoids.Localized.Shoot = "Shoot"
CleveRoids.Localized.SpellRank = "%(Rank %d+%)"
CleveRoids.Localized.CreatureTypes = {
["Животное"] = "Beast",
["Существо"] = "Critter",
["Демон"] = "Demon",
["Дракон"] = "Dragonkin",
["Элементаль"] = "Elemental",
["Великан"] = "Giant",
["Гуманоид"] = "Humanoid",
["Механизм"] = "Mechanical",
["Не указано"] = "Not Specified",
["Тотем"] = "Totem",
["Нежить"] = "Undead",
}
CleveRoids.Localized.Spells = {
["Shadowform"] = "Облик Тени",
["Stealth"] = "Незаметность",
["Prowl"] = "Крадущийся зверь",
["Revenge"] = "Реванш",
["Overpower"] = "Превосходство",
["Riposte"] = "Ответный удар",
["Surprise Attack"] = "Внезапная атака",
["Mongoose Bite"] = "Укус мангуста",
["Counterattack"] = "Контратака",
["Arcane Surge"] = "Чародейский выброс",
}
CleveRoids.Localized.ItemTypes = {
["Consumable"] = "Расходный материал",
["Reagent"] = "Reagent",
["Projectile"] = "Projectile",
["Trade Goods"] = "Хозяйственные товары",
}
elseif CleveRoids.Locale == "esES" then
CleveRoids.Localized.Shield = "Shields"
CleveRoids.Localized.Bow = "Bows"
CleveRoids.Localized.Crossbow = "Crossbows"
CleveRoids.Localized.Gun = "Guns"
CleveRoids.Localized.Thrown = "Thrown"
CleveRoids.Localized.Wand = "Wands"
CleveRoids.Localized.Sword = "Swords"
CleveRoids.Localized.Staff = "Staves"
CleveRoids.Localized.Polearm = "Polearms"
CleveRoids.Localized.Mace = "Maces"
CleveRoids.Localized.FistWeapon = "Fist Weapons"
CleveRoids.Localized.Dagger = "Daggers"
CleveRoids.Localized.Axe = "Axes"
CleveRoids.Localized.Attack = "Attack"
CleveRoids.Localized.AutoShot = "Auto Shot"
CleveRoids.Localized.Shoot = "Shoot"
CleveRoids.Localized.SpellRank = "%(Rank %d+%)"
CleveRoids.Localized.CreatureTypes = {
["Bestia"] = "Beast",
["Alma"] = "Critter",
["Demonio"] = "Demon",
["Dragon"] = "Dragonkin",
["Elemental"] = "Elemental",
["Gigante"] = "Giant",
["Humanoide"] = "Humanoid",
["Mecánico"] = "Mechanical",
["No especificado"] = "Not Specified",
["Tótem"] = "Totem",
["No-muerto"] = "Undead",
}
CleveRoids.Localized.Spells = {
["Shadowform"] = "Forma de las Sombras",
["Stealth"] = "Sigilo",
["Prowl"] = "Acechar",
["Revenge"] = "Revancha",
["Overpower"] = "Abrumar",
["Riposte"] = "Estocada",
["Surprise Attack"] = "Ataque sorpresa",
["Mongoose Bite"] = "Mordedura de mangosta",
["Counterattack"] = "Contraataque",
["Arcane Surge"] = "Oleada Arcana",
}
CleveRoids.Localized.ItemTypes = {
["Consumable"] = "Consumible",
["Reagent"] = "Reagent",
["Projectile"] = "Projectile",
["Trade Goods"] = "Objetos comerciables",
}
end
_G["CleveRoids"] = CleveRoids
+465
View File
@@ -0,0 +1,465 @@
# SuperCleveRoid Macros
This was originally an effort to bring the dynamic tooltip and cast sequence functionality of [CleverMacro](https://github.com/DanielAdolfsson/CleverMacro) into [Roid-Macros](https://github.com/MarcelineVQ/Roid-Macros). It has since expanded after some additional changes I wanted along with feedback from others. The majority of credit goes to the [original addon authors](#original-addons--authors). Still a work in progress.
Both [SuperWoW](https://github.com/balakethelock/SuperWoW) and [Nampower](https://github.com/pepopo978/nampower) are REQUIRED.
Check slash command and all conditional lists for new usages!
---
## Installation
### Manual
1. Download a zip from the green Code button or by clicking [here](https://github.com/jrc13245/SuperCleveRoidMacros/archive/refs/heads/main.zip)
2. Unzip the file and place the folder into your `Interface/Addons` folder.
3. Rename the `SuperCleveRoidMacros-main` folder to `SuperCleveRoidMacros`
4. Check that it is enabled in your addon list in-game.
5. Make sure you don't have other macro addons that may interfere. SuperMacro should be compatible.
6. SUPERWOW and NAMPOWER are REQUIRED!
* [SuperWoW](https://github.com/balakethelock/SuperWoW) dll mod is required
* [Nampower](https://github.com/pepopo978/nampower) dll mod is required
### Turtle WoW Launcher / GitAddonsManager
1. Open either application
2. Click the Add button
3. Paste the url `https://github.com/jrc13245/SuperCleveRoidMacros`
4. Download and keep up to date
### SuperCleveRoidMacros Settings
* /cleveroid - view settings
* /cleveroid realtime 0 or 1 - Force realtime updates rather than event based updates (Default: 0. 1 = on, increases CPU load.)
* /cleveroid refresh X - Set refresh rate. (1 to 10 updates per second. Default: 5)
---
## Known Issues
* By default, conditional checks to update icons are event based with realtime set to 0. This means icons using some conditionals that arent triggered by events are slow to change. example: @unitid mod etc. Enable realtime setting, but beware increase in cpu usage and lag.
* ALL macros must be given unique names, no blank names or muliple of the same name or using spell names.
* If any of your macros have syntax errors, it will affect all macros when it comes to errors.
* Spells with parenthesis ie: Faerie Fire (Feral) or Barkskin (Feral) MUST be written using ranks, becomming `Faerie Fire (Feral)(Rank X)`
* Minor: If you improperly create a macro, in some certain cases it can cause strange UI issues including not displaying any icons, other macros not working or lua errors. Fix the macro or remove it from your actionbar and it should go back to normal automatically. Depending on the cause, you may need to reload your UI (/rl). If you find one of these and can reproduce the issue, let me know.
* Minor: HealComm support. See [below](#healcomm-support)
* I have not tested all possible combinations of conditionals or ways to break things. Find me on Discord or open an issue if you find any bugs or have feedback.
---
# What's Different
## Commands and Conditionals
### ***Important! Spells, Items, conditionals, etc are case sensitive. Barring a bug, if there is an issue, it's almost always because something is typed incorrectly.***
* New Alias for stopcasting 'unqueue'
* New update settings to swap between realtime or event based. Event based is the default and saves cpu and memory usage.
* New Conditional class/noclass.
* Conditional exists is now noable.
* Added alive/dead alias' nodead/noalive.
* Conditional combat can now take unitids.
* Renamed `attacking`/`noattacking` contitionals to `targeting`/`notargeting` for better clarity of what they do.
* All conditionals that should have an implied target of @target now do
* Conditionals can be separated by comma or space
* Conditional arguments with spaces that would need to be replaced with underscores (`_`) can instead be enclosed in quotes.
* Updated syntax for conditionals with stack/time checking
* You can use `>, <, =, ~=, >=, <=` as valid operators. Include a `#` sign to designate you're checking the stack's, not time
* Operators should be placed after the colon, either by itself (if applicable) or after the argument
`[power:>20]`, `[debuff:"Sunder Armor<#5"]`, `[buff:Thorns<30]`
* Omitting an operator or amount will just check that the buff/debuff exists
* When stack checking, omitting an operator assumes equals (=)
`[debuff:"Sunder Armor#3]` is the same as `[debuff:"Sunder Armor=#3]`
* Omitting the argument entirely will assume you want to use the action in the condition check
`[nobuff] Power Word: Fortitude` is the same as `[nobuff:"Power Word: Fortitude"] Power Word: Fortitude`
* Updated most conditionals (that make sense) to allow for multiple arguments. Use a / to separate them.
* Added `plain` [mod] and [nomod] to conditionals
* Added `alive` conditional
* Added `member` conditional
* Added `form` conditional (an alias of stance)
* Added Priest Shadowform to `stance`/`form` conditionals. Use `[stance:1]` or `[form:1]`
* Added Rogue Stealth to `stance`/`form` conditionals. Use `[stance:1]` or `[form:1]`
* Added `combo` conditional
* Added `known` conditional
* Added `resting` conditional
* Changed `cooldown` conditional to ignore the GCD (will show usable if the cooldown is exactly 1.5 seconds) -- It felt better but not 100% on keeping this, send feedback.
* Added `cdgcd` conditional that works the same as `cooldown` that will trigger for any length of cooldown
* Added `inrange` conditional ([Nampower](https://github.com/pepopo978/nampower) required)
* Added changes to make usable/mana/range updating show properly in pfUI.
* Added Bongos action bars compatibility support
* Added /runmacro command. Same as /cast {macroname} but always ignores icon/tooltip
* Added /retarget command. Clears your target if it doesn't exist, has 0 hp or if you can't attack it and then targets the nearest enemy
* Added /equipmh command. Equips the weapon into your mainhand slot.
* Added ? flag to prevent an action from affecting the icon/tooltips. It must be the first character.
```lua
#showtooltip
/use ?Some Item
/cast [reactive] Overpower; Heroic Strike
```
* Updated ! flag as a shortcut easily make spammable spells.
* Added ~ flag to either cast or cancel the buff/aura if possible. (Toggles the spell on/off)
* Added /stopmacro command.
* Added conditional use to /startattack /stopattack /stopcasting.
* Added stat conditional. ex: '/cast [hp:<=20 stat:AP>=2000]Bloodthirst'
## Dynamic Icons and Tooltips
* The icon and tooltip for a macro will automatically update to the first true condition's action. Left to right, top to bottom.
* Consumables and certain other item types will now show a count on the action bar.
* Spells with reagent costs will now show a count of how many uses you have.
* Full `#showtooltip` support with dynamic icons and tooltips
* A macro must start with `#showtooltip` or `#showtooltip spell/item/itemid`. The icons and tooltips will update on your bars as the conditions are met.
```lua
#showtooltip
/cast [mod:alt] Frostbolt; [mod:ctrl] Fire Blast; [mod:shift] {MyMacro}; Blink
```
```lua
#showtooltip
/cast [stance:1/3, nocooldown, notargeting:player] Mocking Blow
/cast [stance:2/3, nocooldown, notargeting:player] Taunt
/cast Shield Slam
```
One line or separate lines are valid, sometimes one is better than the other
```
#showtooltip
/cast [zone:Ahn'Qiraj] Yellow Qiraji Battle Tank;[nozone:Orgrimmar/Undercity/"Thunder Bluff" nomybuff:"Water Walking"] Red Goblin Shredder;Plainsrunning
```
Is the same as
```
#showtooltip
/cast [zone:Ahn'Qiraj] Yellow Qiraji Battle Tank
/cast [nozone:Orgrimmar/Undercity/"Thunder Bluff" nomybuff:"Water Walking"] Red Goblin Shredder
/cast Plainsrunning
```
* Updated `/castsequence` support. See [below](#cast-sequence)
* Added support for updating to the icon/tooltip of the {macro} named in a another macro
* Macro 1 calls Macro 2 and will update the icon when out of combat with Arcane Missiles from Macro2's `#showtooltip`
***Note: This will only use the icon/tooltip of either the referenced `#showtooltip <spell/item/itemid>` or the icon you set for the macro.***
Macro 1:
```lua
#showtooltip
/cast [nocombat] {Macro2}; Fireball
```
Macro 2
```lua
#showtooltip Arcane Missiles
/cast [mod] Conjure Food
/use 2288
```
* Added support for itemid lookup instead of the item's name. Using this will show the icon/tooltip even if you don't have the item cached or in your inventory so you don't see ? icons. e.g. No Mage food/water on login
```lua
#showtooltip
/use [nomod] 5350
/cast [mod] Conjure Water
```
*Added support of using equipped items by slot number
```lua
#showtooltip
/use 16
```
---
# Usage
## Slash Commands
| Command | Conditionals Supported | Purpose |
|-----------------------| :-: |---------|
| /cleveroid | | show update settings. /cleveroid realtime 0/1 : /cleveroid refresh 1-10 |
| /target | | takes limited conditionals. will target by name first and then if conditionals are not valid will target your last target or clear target. help/harm check in a 40 yd cone in front of you. this is due to client limitations. available conditionals: (help,harm,alive,dead,exists,isplayer,isnpc,type,(no)inrange,(no(de))buff,(raw)hp,(raw)power,(no)casting) |
| /retarget | | Clears your target if it doesn't exist, has 0 hp or if you can't attack it and then targets the nearest enemy. |
| /startattack | * | Starts auto-attacking. |
| /stopattack | * | Stops auto-attacking. |
| /stopcasting | * | Stops casting. |
| /unqueue | * | Stops casting. |
| /petattack | * | Command pet to Attack. |
| /petfollow | * | Command pet to Follow. |
| /petwait | * | Command pet to Wait (Stay). |
| /petaggressive | * | Set pet mode to Aggressive. |
| /petdefensive | * | Set pet mode to Defensive. |
| /petpassive | * | Set pet mode to Passive. |
| /castsequence | * | Performs a cast sequence. See [below](#cast-sequence) for more infomation. |
| /equip | * | Equips an item by name or itemid. |
| /equipmh | * | Equips an item by name or itemid into your mainhand slot. |
| /equipoh | * | Equips an item by name or itemid into your offhand slot. |
| /unshift | * | Cancels your current shapeshift form. |
| /cancelaura, /unbuff | | Cancels a valid buff/aura. |
| /runmacro | | Runs a macro. Use /runmacro {macroname} |
| /use | * | Uses an item by name or id |
| /cast | * | Casts a spell by name |
| /stopmacro | * | prevent any lines under /stopmacro from being run unless conditionals are met |
## Cast Sequence
```lua
#showtooltip
/castsequence reset=3 Fireball, Frostbolt, Arcane Explosion, Fire Blast
```
* Dynamic icons and tooltips on each sequence with range/mana/usable checks
* Supports reset=#/mod/target/combat
* Supports conditionals for the entire sequence, not individual actions within the sequence.
```lua
#showtooltip
/castsequence [group:party/raid] reset=3/target Sweaty Spell 1, Sweaty Spell 2, Sweaty Spell 3
/castsequence reset=target/combat Casual Spell 1, Casual Spell 2, Casual Spell 3
```
## Conditionals
* Conditionals are basically if/then/else statements which are evaluated left to right, top to bottom.
* The first set of conditions that are all true will be the action that happens so the order you put things in is very important.
* Multiple conditionals can be used, separated with a space or comma.
* Spells and items with spaces in the name need to use underscores (`_`) instead of spaces or be enclosed in quotations.
* Each action can be written on one line or on separate. Both are effectively the same however WoW executes every line of a macro so it is technically better to use one line where possible. I usually prefer separate lines because it's easier to read and troubleshoot at a quick glance. You do you.
**startattack, stopattack, stopacasting:**
```
#showtooltip
/startattack [harm alive]
#showtooltip
/stopattack [form:0/1/2/3]
#showtooltip
/stopcasting [hp:<=20]
```
**Item Slots 1-19 supports /use only right now:**
```
#showtooltip
/use [combat,hp:<=20]13
```
**Separate Lines:**
```
#showtooltip
/use [@mouseover alive help hp:<70 nodebuff:"Recently Bandaged"] Runecloth Bandage
/use [@target, alive, help, hp:<70, nodebuff:Recently_Bandaged] Runecloth Bandage
/use [@player] Runecloth Bandage
```
**One Line:**
```
#showtooltip
/use [@mouseover alive help hp:<70 nodebuff:"Recently Bandaged"] Runecloth Bandage; [@target, alive, help, hp:<70, nodebuff:Recently_Bandaged] Runecloth Bandage; [@player] Runecloth Bandage
```
**Note: Classic/Retail macros allow for cascading conditional blocks like below. This is NOT supported.**
```
#showtooltip
/use [@mouseover alive help hp:<70][@target alive help hp:<70][@player][] Runecloth Bandage
```
* If a conditional on the table is marked as **Multi** you can provide multiple values in the same condition. *Only one needs to be true.*
`[targeting:party1/party2/party3/party4]` -- targeting one of your party members
`[zone:Stormwind/Ironforge]` -- in Stormwind OR Ironforge
* If a conditional is marked as **Noable** you can prefix the condition with "no" to test the opposite condition. *All need to be true*
`[notargeting:player]` -- not targeting the player
`[nozone:Stormwind/Ironforge]` -- not in Stormwind AND not in Ironforge
* You can specifiy a target unit for the macro by adding in a valid @unitid
`/cast [@party1 combat] Intervene` -- casts Intervene on party member 1 if you (player) are in combat
* @focus / focus can be used as an @unitid / conditional unitid however Vanilla does not support focus targets, a compatible addon is required to make this function.
* If the conditional allows for a numerical comparison, the format is `condition:>X` or `condition:"Some Value">X`. If you want to compare stacks/rank (where applicable) and not remaining time, use `>#X`.
* **Only the player's buffs/debufs can be checked for remaining time**
* Valid operators are =, ~=, >, >=, <, <=
* You can omit the value of a conditional if you want to check the same spell/item that you are using in the action.
`[debuff:"Sunder Armor"<#5] Sunder Armor` == `[debuff:<#5] Sunder Armor`
`[nobuff:"Mark of the Wild"] Mark of the Wild` == `[nobuff] Mark of the Wild`
* [SuperWoW](https://github.com/balakethelock/SuperWoW) dll mod is required for some conditionals
* [Nampower](https://github.com/pepopo978/nampower) dll mod required for some conditionals
### Special Characters
| Character | Syntax Examples | Description |
| :-: |---------------|-------------|
| ! | !Attack<br/>!Cat Form<br/>!Spell Name | Prefix on spell name.<br/>Will only use the spell if it's not already active.<br/>Can also be used with other spells as shorthand for `nomybuff` |
| ? | /use ?[equipped:Swords]</br>/cast ?Presence of Mind | Prevents the icon and tooltip from showing.<br/>Must be the first character. |
| ~ | ~Slow Fall | Prefix on spell name. Acts as a toggle ability.<br/>Will cast or cancel the buff/aura if possible. |
### Key Modifiers
| Conditional | Syntax Examples | Multi | Noable | Tests For |
|----------------|---------------| :-: | :-: |-----------|
| mod | [mod]<br/>[mod:ctrl/alt/shift] | * | * | If any mod key is pressed.</br>If one of the listed modifier keys are pressed. |
### Player Only
| Conditional | Syntax Examples | Multi | Noable | Tests For |
|----------------|---------------| :-: | :-: |-----------|
| cdgcd | [cdgcd]<br/>[cdgcd:"Name"]<br/>[cdgcd:"Name">X] | * | * | If the Spell or Item is on cooldown and optionally if the amount of time left is >= or <= than X seconds. **GCD NOT IGNORED** |
| channeled | [channeled] | | | If the player is currently channeling a spell. |
| combo | [combo:>#3]<br/>[combo:#2]</br>[combo:<#5] | | * | If the player has the specified number of combo points. |
| cooldown | [cooldown]<br/>[cooldown:"Name"]<br/>[cooldown:"Name"<X] | * | * | If the Spell or Item name is on cooldown and optionally if the amount of time left is >= or <= than X seconds. **GCD (if exatly 1.5 sec) IGNORED** |
| equipped | [equipped:"Name"]<br/>[equipped:Shields]<br/>[equipped:Daggers2] | * | * | If the player has an item name/id or item type equipped. See [below](#weapon-types) for a list of valid Weapon Types. |
| form | [form:0/1/2/3/4/5] | * | | Alias of `stance` |
| group | [group]<br/>[group:party/raid] | * | * | If the player is in any group or specific group type. |
| known | [known]<br/>[known:"Name"]</br>[known:"Name">#2] | * | * | If the player knows a spell or talent. Can optionally check the rank. |
| mybuff | [mybuff]<br/>[mybuff:"Name"]<br/>[mybuff:"Name">#X]<br/>[mybuff:<X] | * | | If the player has a buff of the given name.</br>Optionally compared to X number of stacks.<br/>Optionally compared to X time remaining. |
| mydebuff | [mydebuff]<br/>[mydebuff:"Name"]<br/>[mydebuff:"Name">#X]<br/>[mydebuff:<X] | * | | If the player has a debuff of the given name.<br/>Optionally compared to X number of stacks.<br/>Optionally compared to X time remaining. |
| myhp | [myhp:<=X]<br/>[myhp:>=X/<=Y] | * | | The player's health **PERCENT** compared to X. |
| myhplost | [myhplost:>=X]<br/>[myhplost:>=X/<=Y] | * | | The player's lost health compared to X. |
| mypower | [mypower:>=X]<br/>[mypower:>=X/<=Y] | * | | The player's power (mana/rage/energy) **PERCENT** compared to X. |
| mypowerlost | [mypowerlost:>=X]<br/>[mypowerlost:>=X/<=Y] | * | | The player's lost power (mana/rage/energy) compared to X. |
| myrawhp | [myrawhp:>=X]<br/>[myrawhp:>=X/<=Y] | * | | The player's health compared to X. |
| myrawpower | [myrawpower:>=X]<br/>[myrawpower:>=X/<=Y] | * | | The player's power (mana/rage/energy) compared to X. |
| reactive | [reactive]<br/>[reactive:Overpower] | * | | If the player has the reactive ability (Revenge, Overpower, Riposte, etc.) available to use.<br/><br/>**NOTE: Currently requires the reactive ability to be somewhere on your actionbars in addition to any macros you're using it in. A planned future update will remove this requirement if using [Nampower](https://github.com/pepopo978/nampower).** |
| resting | [resting] | | * | If the player is resting (in an inn/capital city/etc.) |
| stance | [stance:0/1/2/3/4/5] | * | | If the player is in stance #.<br/>Supports Shadowform and Stealth as stance 1.|
| stealth | [stealth] | | * | If the player is in Stealth or Prowl. |
| zone | [zone:"Zone"]<br/>[zone:"Zone"/"Another Zone"] | * | * | If the player is in one or more zones of the given name. |
| checkchanneled | [checkchanneled] | * | | Prevents a spell from being cast if you are already channeling it. |
| stat | [stat:stat>=x] | | | Check if one of the players statistics is greater or less than a specific number. Available Stats: str/strength, agi/agility, stam/stamina, int/intellect, spi/spirit, ap/attackpower, rap/rangedattackpower, healing/healingpower, arcane_power, fire_power, frost_power, nature_power, shadow_power, armor, defense, arcane_res, fire_res, frost_res, nature_res, shadow_res. |
### Unit Based
### The default @unitid is usually @target if you don't specify one
### The only conditionals that take conditional:unitid are combat/nocombat and targeting/notargeting
| Conditional | Syntax | Multi | Noable | Tests For |
|----------------|---------------| :-: | :-: |-----------|
| alive | [alive] | | * | If the @unitid is NOT dead or a ghost. |
| buff | [buff]<br/>[buff:"Name"]<br/>[buff:"Name">#X]<br/>[buff:"Name"<X] | | * | If the @unitid has a buff of the given name and optionally if it has >= or <= than X number of stacks. |
| casting | [casting]<br/>[casting:"Spell Name"] | * | * | If the @unitid is casting any or one or more specific spells. |
| combat | [combat]<br/>[combat:target] | | * | If the unitid (default is player) is in combat. |
| dead | [dead] | | * | If the @unitid is dead or a ghost. |
| debuff | [debuff]<br/>[debuff:"Name"]<br/>[debuff:"Name">#X]<br/>[debuff:<X] | | * | If the @unitid has a debuff of the given name and optionally if it has >= or <= than X number of stacks. |
| harm | [harm] | | | If the @unitid is an enemy. |
| help | [help] | | | If the @unitid is friendly. |
| hp | [hp:>=X]<br/>[hp:>=X/<=Y] | | | The @unitid health **PERCENT** compared to X. |
| hplost | [hplost:>=X]<br/>[hplost:>=X/<=Y] | | | The @unitid health lost compared to X. |
| inrange | [inrange]<br/>[inrange:"Name"] | * | * | If the specified @unitid is in range of the spell. |
| isnpc | [isnpc] | * | | If the @unitid is an npc.<br/>See this [article](https://wowpedia.fandom.com/wiki/UnitId) for a list of unitids.<br/>Not all units are valid in vanilla. |
| isplayer | [isplayer] | * | | If the @unitid is a player.<br/>See this [article](https://wowpedia.fandom.com/wiki/UnitId) for a list of unitids.<br/>Not all units are valid in vanilla. |
| member | [member] | | * | If the @unitid is in your party OR raid. |
| party | [party] | | * | If the @unitid is in your party. |
| power | [power:>=X]<br/>[power:>=X/<=Y] | | | The @unitid power (mana/rage/energy) **PERCENT** compared to X. |
| powerlost | [powerlost:>=X]<br/>[powerlost:>=X/<=Y] | | | The @unitid power (mana/rage/energy) lost compared to X. |
| raid | [raid] | | * | If the @unitid is in your raid. |
| rawphp | [rawhp:>=X]<br/>[rawhp:>=X/<=Y] | | | The @unitid health compared to X. |
| rawpower | [rawpower:>=X]<br/>[rawpower:>=X/<=Y] | | | The @unitid power (mana/rage/energy) compared to X. |
| type | [type:"Creature Type"] | * | * | If the @unitid is the specified creature type. See [below](#creature-types) for a list of valid Creature Types. |
| targeting | [targeting:unitid] | * | * | If the @unitid is targeting the specified unitid.<br/>See this [article](https://wowpedia.fandom.com/wiki/UnitId) for a list of unitids.<br/>Not all units are valid in vanilla. |
| exists | [exists] | | * | If the @unitid exists. |
| @unitid | [@mouseover] | | | The @unitid is a valid target. |
| class | [class:classname1/classname2]<br/>[class:Warrior/Priest] | * | * | The target is a player of the specified class/classes. |
### Unitids
| Name (N=party/raid slot number) |
|------|
| player |
| target |
| pet |
| mouseover |
| partyN |
| partypetN |
| raidN |
| raidpetN |
| targettarget |
| playertarget |
| pettarget |
| partyNtarget |
| raidNtarget |
| targettargettarget |
| focus (requires pfui or another addon) |
### Classes
| Class |
|------|
| Warrior |
| Paladin |
| Hunter |
| Shaman |
| Druid |
| Rogue |
| Mage |
| Warlock |
| Priest |
### Weapon Types
| Name | Slot |
|------|------|
| Axes, Axes2 | Main Hand, Off Hand |
| Bows | Ranged |
| Daggers, Daggers2 | Main Hand, Off Hand |
| Crossbows | Ranged |
| Fists, Fists2 | Main Hand, Off Hand |
| Guns | Ranged |
| Maces, Maces2 | Main Hand, Off Hand |
| Polearms | Main Hand |
| Shields | Off Hand |
| Staves | Main Hand |
| Swords, Swords2 | Main Hand, Off Hand |
| Thrown | Ranged |
| Wands | Ranged |
### Creature Types
| Name |
|------|
| Boss |
| Worldboss |
| Beast |
| Dragonkin |
| Demon |
| Elemental |
| Giant |
| Undead |
| Humanoid |
| Critter |
| Mechanical |
| Not specified |
| Totem |
| Non-combat Pet |
| Gas Cloud |
### Reactive Spells (twow)
| Name |
|---------------|
| Revenge |
| Overpower |
| Riposte |
| Mongoose Bite |
| Counterattack |
| Arcane Surge |
### UnitFrames
* agUnitFrames
* Blizzard's UnitFrames
* CT_RaidAssist
* CT_UnitFrames
* DiscordUnitFrames
* FocusFrame
* Grid
* LunaUnitFrames
* NotGrid
* PerfectRaid
* pfUI
* sRaidFrames
* UnitFramesImproved_Vanilla
* XPerl
### Action Bars
* Blizzard's Action Bars
* Bongos
* Discord Action Bars
* pfUI
### Supported Addons
* ClassicFocus / FocusFrame
* SuperMacro
* ShaguTweaks
### HealComm Support
This addon uses [SuperWoW](https://github.com/balakethelock/SuperWoW)'s CastSpellByName which is not compatible with the standard HealComm-1.0 library. MarcelineVQ has an updated version of [LunaUnitFrames](https://github.com/MarcelineVQ/LunaUnitFrames) where they added [SuperWoW](https://github.com/balakethelock/SuperWoW) support to the HealComm-1.0 library. If you use [SuperWoW](https://github.com/balakethelock/SuperWoW) and want proper HealComm support with your macros, you need to do one or both of the following:
* Contact the author of whichever addon and ask that they update their HealComm to support [SuperWoW](https://github.com/balakethelock/SuperWoW) and link them to MarcelineVQ's updated [LunaUnitFrames](https://github.com/MarcelineVQ/LunaUnitFrames).
* Manually update any addon that is using the `HealComm-1.0` library by deleting the `HealComm-1.0` folder and replacing it with the `libs/HealComm-1.0` folder from MarcelineVQ's version of LunaUnitFrames.
Example for the standalone HealComm addon:
1. Exit WoW completely.
2. Download a copy of the updated [LunaUnitFrames](https://github.com/MarcelineVQ/LunaUnitFrames).
3. Delete the `/Interface/AddOns/HealComm/libs/HealComm-1.0` folder.
4. From the [LunaUnitFrames](https://github.com/MarcelineVQ/LunaUnitFrames) download, copy the `/libs/HealComm-1.0` folder into your `/Interface/AddOns/HealComm/libs/` folder.
----
### Original Addons & Authors
* [Roid-Macros by DennisWG (DWG)](https://github.com/DennisWG/Roid-Macros)
* [CleverMacro by DanielAdolfsson (_brain)](https://github.com/DanielAdolfsson/CleverMacro)
----
License
----
MIT
+265
View File
@@ -0,0 +1,265 @@
--[[
Author: Dennis Werner Garske (DWG) / brian / Mewtiny
License: MIT License
]]
local _G = _G or getfenv(0)
local CleveRoids = _G.CleveRoids or {} -- redundant since we're loading first but peace of mind if another file is added top of chain
function CleveRoids.Seq(_, i)
return (i or 0) + 1
end
-- Trims any leading or trailing white space characters from the given string
-- str: The string to trim
-- returns: The trimmed string
function CleveRoids.Trim(str)
if not str then
return nil
end
return string.gsub(str,"^%s*(.-)%s*$", "%1")
end
do
local _G = _G or getfenv(0)
local CleveRoids = _G.CleveRoids or {}
_G.CleveRoids = CleveRoids
CleveRoids.__mo = CleveRoids.__mo or { sources = {}, current = nil }
local PRIORITY = {
pfui = 3, -- unitframe hovers should win
blizz = 3, -- same level as pfui
tooltip = 1, -- lowest; dont stomp frames
}
local function getBest()
local bestSource, bestUnit, bestP = nil, nil, -1
for source, unit in CleveRoids.__mo.sources do
if unit and unit ~= "" then
local p = PRIORITY[source] or 0
if p > bestP then
bestP, bestSource, bestUnit = p, source, unit
end
end
end
return bestSource, bestUnit
end
local function apply(unit)
-- SuperWoW path if available; otherwise internal fallback
if CleveRoids.hasSuperwow and _G.SetMouseoverUnit then
_G.SetMouseoverUnit(unit) -- nil clears
else
CleveRoids.mouseoverUnit = unit
end
if CleveRoids.QueueActionUpdate then CleveRoids.QueueActionUpdate() end
end
function CleveRoids.SetMouseoverFrom(source, unit)
-- set/refresh a sources unit
if not source then return end
CleveRoids.__mo.sources[source] = unit
local _, bestUnit = getBest()
if bestUnit ~= CleveRoids.__mo.current then
CleveRoids.__mo.current = bestUnit
apply(bestUnit)
end
end
function CleveRoids.ClearMouseoverFrom(source, unitIfMatch)
if not source then return end
if unitIfMatch and CleveRoids.__mo.sources[source] ~= unitIfMatch then
return -- dont clear if it was replaced meanwhile
end
CleveRoids.__mo.sources[source] = nil
local _, bestUnit = getBest()
if bestUnit ~= CleveRoids.__mo.current then
CleveRoids.__mo.current = bestUnit
apply(bestUnit)
end
end
end
-- TODO: Get rid of one Split function. CleveRoids.splitString is ~10% slower
function CleveRoids.Split(s, p, trim)
local r, o = {}, 1
if not p or p == "" then
if trim then
s = CleveRoids.Trim(s)
end
for i = 1, string.len(s) do
table.insert(r, string.sub(s, i, 1))
end
return r
end
repeat
local b, e = string.find(s, p, o)
if b == nil then
local sub = string.sub(s, o)
table.insert(r, trim and CleveRoids.Trim(sub) or sub)
return r
end
if b > 1 then
local sub = string.sub(s, o, b - 1)
table.insert(r, trim and CleveRoids.Trim(sub) or sub)
else
table.insert(r, "")
end
o = e + 1
until false
end
-- Splits the given string into a list of sub-strings
-- str: The string to split
-- seperatorPattern: The seperator between sub-string. May contain patterns
-- returns: A list of sub-strings
function CleveRoids.splitString(str, seperatorPattern)
local tbl = {}
if not str then
return tbl
end
local pattern = "(.-)" .. seperatorPattern
local lastEnd = 1
local s, e, cap = string.find(str, pattern, 1)
while s do
if s ~= 1 or cap ~= "" then
table.insert(tbl,cap)
end
lastEnd = e + 1
s, e, cap = string.find(str, pattern, lastEnd)
end
if lastEnd <= string.len(str) then
cap = string.sub(str, lastEnd)
table.insert(tbl, cap)
end
return tbl
end
function CleveRoids.splitStringIgnoringQuotes(str, separator)
local result = {}
local temp = ""
local insideQuotes = false
local separators = {}
if type(separator) == "table" then
for _, s in separator do
separators[s] = s
end
else
separators[separator or ";"] = separator or ";"
end
for i = 1, string.len(str) do
local char = string.sub(str, i, i)
if char == "\"" then
insideQuotes = not insideQuotes
temp = temp .. char
elseif char == separators[char] and not insideQuotes then
temp = CleveRoids.Trim(temp)
if temp ~= "" then table.insert(result, temp) end
temp = ""
else
temp = temp .. char
end
end
-- Add the last segment if it exists
if temp ~= "" then
temp = CleveRoids.Trim(temp)
table.insert(result, temp)
end
-- if nothing was found, return the empty string
return (next(result) and result or {""})
end
-- Prints all the given arguments into WoW's default chat frame
function CleveRoids.Print(...)
local c = "|cFF4477FFCleveR|r|cFFFFFFFFoid :: |r"
local out = ""
for i=1, arg.n, 1 do
out = out..tostring(arg[i]).." "
end
if WowLuaFrameOutput then
WowLuaFrameOutput:AddMessage(out)
else
if not DEFAULT_CHAT_FRAME:IsVisible() then
FCF_SelectDockFrame(DEFAULT_CHAT_FRAME)
end
DEFAULT_CHAT_FRAME:AddMessage(c..out)
end
end
function CleveRoids.PrintI(msg, depth)
depth = depth or 0
msg = string.rep(" ", depth) .. tostring(msg)
CleveRoids.Print(msg)
end
function CleveRoids.PrintT(t, depth)
depth = depth or 0
local cs = "|cffc8c864"
local ce = "|r"
if t == nil or type(t) ~= "table" then
CleveRoids.PrintI(t, depth)
else
for k, v in pairs(t) do
if type(v) == "table" then
CleveRoids.PrintI(cs..tostring(k)..":"..ce.." <TABLE>", depth)
CleveRoids.PrintT(v, depth + 1)
else
CleveRoids.PrintI(cs..tostring(k)..ce..": "..tostring(v), depth)
end
end
end
end
CleveRoids.kmods = {
ctrl = IsControlKeyDown,
alt = IsAltKeyDown,
shift = IsShiftKeyDown,
mod = function() return (IsControlKeyDown() or IsAltKeyDown() or IsShiftKeyDown()) end,
nomod = function() return (not IsControlKeyDown() and not IsAltKeyDown() and not IsShiftKeyDown()) end,
}
CleveRoids.operators = {
["<"] = "lt",
["lt"] = "<",
[">"] = "gt",
["gt"] = ">",
["="] = "eq",
["eq"] = "=",
["<="] = "lte",
["lte"] = "<=",
[">="] = "gte",
["gte"] = ">=",
["~="] = "ne",
["ne"] = "~=",
}
CleveRoids.comparators = {
lt = function(a, b) return (a < b) end,
gt = function(a, b) return (a > b) end,
eq = function(a, b) return (a == b) end,
lte = function(a, b) return (a <= b) end,
gte = function(a, b) return (a >= b) end,
ne = function(a, b) return (a ~= b) end,
}
CleveRoids.comparators["<"] = CleveRoids.comparators.lt
CleveRoids.comparators[">"] = CleveRoids.comparators.gt
CleveRoids.comparators["="] = CleveRoids.comparators.eq
CleveRoids.comparators["<="] = CleveRoids.comparators.lte
CleveRoids.comparators[">="] = CleveRoids.comparators.gte
CleveRoids.comparators["~="] = CleveRoids.comparators.ne
_G["CleveRoids"] = CleveRoids