Repository navigation
Expand file tree
/
Copy pathAutoSeal.lua
More file actions
156 lines (138 loc) · 5.58 KB
/
Copy pathAutoSeal.lua
File metadata and controls
156 lines (138 loc) · 5.58 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
-- AutoSeal.lua (Vanilla/Turtle-safe, tooltip fallback + secure queue)
local AutoSealFrame = CreateFrame("Frame")
local AutoSealButton = CreateFrame("Button", "AutoSealButton", UIParent, "SecureActionButtonTemplate")
AutoSealButton:SetAttribute("type", "spell")
AutoSealButton:Hide()
-- small hidden tooltip used for reading buff names (classic trick)
local tip = CreateFrame("GameTooltip", "AutoSealTooltip", nil, "GameTooltipTemplate")
tip:SetOwner(UIParent, "ANCHOR_NONE")
-- CONFIG
local SEAL_NAME = "Seal of the Crusader"
local AutoSealSettings = {
enabled = true,
combat_only = true,
announce = true,
check_interval = 1.0,
}
local function SealPrint(msg)
DEFAULT_CHAT_FRAME:AddMessage("|cff00ff00[AutoSeal]|r " .. msg)
end
local DEBUG = false
local function debug(msg)
if DEBUG then DEFAULT_CHAT_FRAME:AddMessage("|cff00ffff[AutoSeal Debug]|r "..msg) end
end
-- Robust check for whether a buff with `sealName` is active on player.
local function IsSealActive(sealName)
if not sealName then return false end
-- 1) Try UnitBuff by name (works if UnitBuff accepts name on this client)
if UnitBuff then
local ok = UnitBuff("player", sealName)
if ok then
debug("UnitBuff by name matched: "..tostring(ok))
return true
end
-- 2) Some clients return the buff name when iterating by index; try that.
for i = 1, 40 do
local v = UnitBuff("player", i)
if not v then break end
if type(v) == "string" and string.find(v, sealName) then
debug("UnitBuff(index) matched: slot "..i.." -> "..v)
return true
end
end
end
-- 3) Tooltip fallback (works in Classic/Vanilla): iterate buff slots and read tooltip text
if tip and tip.SetPlayerBuff then
for i = 1, 32 do
tip:ClearLines()
-- SetPlayerBuff expects the buff slot index (1..)
tip:SetPlayerBuff(i)
local left1 = _G["AutoSealTooltipTextLeft1"]
if left1 then
local text = left1:GetText()
if text and string.find(text, sealName) then
tip:Hide()
debug("Tooltip matched: slot "..i.." -> "..tostring(text))
return true
end
end
end
tip:Hide()
end
return false
end
-- Queue the seal on the secure button (legal way to make the client cast it when the player next acts)
local lastQueued = 0
local function QueueSeal()
if not AutoSealSettings.enabled then return end
if UnitIsDeadOrGhost("player") then return end
if AutoSealSettings.combat_only and not UnitAffectingCombat("player") then return end
if IsSealActive(SEAL_NAME) then
debug("Seal already active; not queueing.")
return
end
local now = GetTime()
if (now - lastQueued) < 1.0 then return end
lastQueued = now
AutoSealButton:SetAttribute("spell", SEAL_NAME)
if AutoSealSettings.announce then
SealPrint("Queued " .. SEAL_NAME .. " — will cast on next valid action.")
else
debug("Queued "..SEAL_NAME)
end
end
-- Convenience: immediate attempt to cast (will be blocked by protected context if used from code)
-- Keep it around for manual use/testing only.
local function TryCastDirect()
if not IsSealActive(SEAL_NAME) and not (CastingInfo() or ChannelInfo()) then
CastSpellByName(SEAL_NAME) -- may be blocked by client when running from events
SealPrint("Tried CastSpellByName (may be blocked by client).")
end
end
-- Events to queue the seal on: enter combat, aura change, and combat hits
AutoSealFrame:RegisterEvent("PLAYER_ENTERING_WORLD")
AutoSealFrame:RegisterEvent("PLAYER_REGEN_DISABLED") -- enter combat
AutoSealFrame:RegisterEvent("UNIT_AURA") -- buff changes
AutoSealFrame:RegisterEvent("UNIT_COMBAT") -- swings / attacks / Crusader Strike
AutoSealFrame:SetScript("OnEvent", function(self, event, arg1, ...)
if not AutoSealSettings.enabled then return end
if event == "PLAYER_ENTERING_WORLD" then
SealPrint("AutoSeal loaded. Watching for "..SEAL_NAME..". Use /autoseal to toggle.")
elseif event == "PLAYER_REGEN_DISABLED" then
QueueSeal()
elseif event == "UNIT_AURA" and arg1 == "player" then
QueueSeal()
elseif event == "UNIT_COMBAT" and arg1 == "player" then
-- any swing / damage / Crusader Strike should queue the seal
QueueSeal()
end
end)
-- Safe OnUpdate (handles nil elapsed in some 1.12 clients)
local lastCheck = 0
AutoSealFrame:SetScript("OnUpdate", function(_, elapsed)
if not elapsed or type(elapsed) ~= "number" then elapsed = 0.1 end
lastCheck = lastCheck + elapsed
if lastCheck >= AutoSealSettings.check_interval then
QueueSeal()
lastCheck = 0
end
end)
-- Slash command for simple debugging and toggles
SLASH_AUTOSEAL1 = "/autoseal"
SlashCmdList["AUTOSEAL"] = function(msg)
local cmd, rest = string.match(msg, "(%S+)%s*(.*)")
cmd = string.lower(cmd or "")
if cmd == "on" then
AutoSealSettings.enabled = true; SealPrint("Enabled")
elseif cmd == "off" then
AutoSealSettings.enabled = false; SealPrint("Disabled")
elseif cmd == "announce" then
AutoSealSettings.announce = not AutoSealSettings.announce; SealPrint("Announce "..(AutoSealSettings.announce and "ON" or "OFF"))
elseif cmd == "debug" then
DEBUG = not DEBUG; SealPrint("Debug "..tostring(DEBUG))
elseif cmd == "try" then
TryCastDirect()
else
SealPrint("/autoseal on | off | announce | debug | try")
end
end