vanilla-wow-addons – Blame information for rev 1
?pathlinks?
Rev | Author | Line No. | Line |
---|---|---|---|
1 | office | 1 | --[[--------------------------------------------------------------------------------- |
2 | This is a table of ranks, which rank of which buff spell has a required level |
||
3 | ----------------------------------------------------------------------------------]] |
||
4 | |||
5 | local L = AceLibrary:GetInstance("AceLocale-2.0"):new("Clique") |
||
6 | |||
7 | local buff_lookup = { |
||
8 | -- Buff lookups |
||
9 | [L"BUFF_PWF"] = {1,12,24,36,48,60}, |
||
10 | [L"BUFF_PWS"] = {6,12,18,24,30,36,42,48,54,60}, |
||
11 | [L"BUFF_SP"] = {30,42,56}, |
||
12 | [L"BUFF_DS"] = {30,40,50,60}, |
||
13 | [L"BUFF_RENEW"] = {8,14,20,26,32,38,44,50,56,60}, |
||
14 | [L"BUFF_MOTW"] = {1,10,20,30,40,50,60}, |
||
15 | [L"BUFF_THORNS"] = {6,14,24,34,44,54}, |
||
16 | [L"BUFF_REJUVENATION"] = {4,10,16,22,28,34,40,46,52,58,60}, |
||
17 | [L"BUFF_REGROWTH"] = {12,18,24,30,36,42,48,54,60}, |
||
18 | [L"BUFF_AI"] = {1,14,28,42,56}, |
||
19 | [L"BUFF_DM"] = {12,24,34,48,60}, |
||
20 | [L"BUFF_AM"] = {18,30,42,54}, |
||
21 | [L"BUFF_BOM"] = {4,12,22,32,42,52,60}, |
||
22 | [L"BUFF_BOP"] = {10,24,38}, |
||
23 | [L"BUFF_BOW"] = {14,24,34,44,54,60}, |
||
24 | [L"BUFF_BOS"] = {20,30,40,50,60}, |
||
25 | [L"BUFF_BOL"] = {40,50,60}, |
||
26 | [L"BUFF_BOSFC"] = {46,54}, |
||
27 | } |
||
28 | |||
29 | local cure_lookup = { |
||
30 | -- Cure lookups |
||
31 | [L"CURE_CURE_DISEASE"] = {"Disease"}, |
||
32 | [L"CURE_ABOLISH_DISEASE"] = {"Disease"}, |
||
33 | [L"CURE_PURIFY"] = {"Disease", "Poison"}, |
||
34 | [L"CURE_CLEANSE"] = {"Disease", "Poison", "Magic"}, |
||
35 | [L"CURE_DISPEL_MAGIC"] = {"Magic"}, |
||
36 | [L"CURE_CURE_POISON"] = {"Poison"}, |
||
37 | [L"CURE_ABOLISH_POISON"] = {"Poison"}, |
||
38 | [L"CURE_REMOVE_LESSER_CURSE"] = {"Curse"}, |
||
39 | [L"CURE_REMOVE_CURSE"] = {"Curse"}, |
||
40 | ["Disease"] = { |
||
41 | L"CURE_ABOLISH_DISEASE", |
||
42 | L"CURE_CURE_DISEASE", |
||
43 | L"CURE_CLEANSE", |
||
44 | L"CURE_PURIFY", |
||
45 | }, |
||
46 | ["Poison"] = { |
||
47 | L"CURE_ABOLISH_POISON", |
||
48 | L"CURE_CURE_POISON", |
||
49 | L"CURE_CLEANSE", |
||
50 | L"CURE_PURIFY", |
||
51 | }, |
||
52 | ["Magic"] = { |
||
53 | L"CURE_DISPEL_MAGIC", |
||
54 | L"CURE_CLEANSE", |
||
55 | }, |
||
56 | ["Curse"] = { |
||
57 | L"CURE_REMOVE_LESSER_CURSE", |
||
58 | L"CURE_REMOVE_CURSE", |
||
59 | }, |
||
60 | } |
||
61 | |||
62 | local dual_lookup = { |
||
63 | -- Any spell that can be cast on friendly or hostile units |
||
64 | [L"DUAL_HOLY_SHOCK"] = true, |
||
65 | [L"DUAL_MIND_VISION"] = true, |
||
66 | [L"CURE_DISPEL_MAGIC"] = true, |
||
67 | } |
||
68 | |||
69 | --[[--------------------------------------------------------------------------------- |
||
70 | Register all of our utility functions |
||
71 | ----------------------------------------------------------------------------------]] |
||
72 | |||
73 | function Clique:RegUtilFuncs() |
||
74 | self:RegisterCustomFunction("Clique:CastSpell(\"spell\")", "Clique:CastSpell(\"spell\")", "Casts a spell on Clique.unit without changing targets") |
||
75 | self:RegisterCustomFunction("Clique:IsBuffActive(\"buff\")", "Clique:IsBuffActive(\"buff\")", "Checks whether a buff or debuff is active on Clique.unit") |
||
76 | self:RegisterCustomFunction("Clique:UnitMenu()", "Clique:UnitMenu()", "Pops up the unit menu for Clique.unit") |
||
77 | self:RegisterCustomFunction("Clique:CureAny()", "Clique:CureAny()", "Attempts to cure any ailments on Clique.unit") |
||
78 | self:RegisterCustomFunction("Clique:NewSpell(\"spell\", \"buff\")", "Clique:NewSpell(\"spell\", \"buff\")", "Casts a spell if a given buff is NOT on a target") |
||
79 | self:RegisterCustomFunction("Clique:TargetUnit()", "Clique:TargetUnit()", "Targets the unit you clicked on.") |
||
80 | self:RegisterCustomFunction("Clique:AssistUnit()", "Clique:AssistUnit()", "Assists the unit you clicked on.") |
||
81 | end |
||
82 | |||
83 | --[[--------------------------------------------------------------------------------- |
||
84 | Scans the spellbook to determine which buffs/cures we know |
||
85 | ----------------------------------------------------------------------------------]] |
||
86 | |||
87 | function Clique:ScanSpellbook() |
||
88 | self:LevelDebug(2, "Clique:ScanSpellbok()") |
||
89 | |||
90 | local tabs = GetNumSpellTabs() |
||
91 | local name,texture,start,offset = GetSpellTabInfo(tabs) |
||
92 | local numspells = start + offset |
||
93 | |||
94 | self.spellbook = self:ClearTable(self.spellbook) |
||
95 | self.spellbook.buffs = buff_lookup |
||
96 | |||
97 | -- ace:print("Scanning " .. tabs .. " tabs for spells.") |
||
98 | for i=1,numspells do |
||
99 | local name,rank = GetSpellName(i, BOOKTYPE_SPELL) |
||
100 | -- ace:print("** Scanning spell id: " .. i .. " found " .. name .. ".") |
||
101 | local _,_,numrank = string.find(rank, L"RANK" .. " (%d+)") |
||
102 | numrank = tonumber(numrank) |
||
103 | |||
104 | if buff_lookup[name] or cure_lookup[name] then |
||
105 | if numrank then |
||
106 | self.spellbook[name] = numrank |
||
107 | else |
||
108 | self.spellbook[name] = true |
||
109 | end |
||
110 | end |
||
111 | |||
112 | if dual_lookup[name] and numrank then |
||
113 | local spell = string.format("%s(%s %d)", name, L"RANK", numrank) |
||
114 | dual_lookup[spell] = true |
||
115 | end |
||
116 | end |
||
117 | end |
||
118 | |||
119 | function Clique:IsDualSpell(spell) |
||
120 | return dual_lookup[spell] |
||
121 | end |
||
122 | |||
123 | --[[--------------------------------------------------------------------------------- |
||
124 | IsBuffActive() - Simple enough |
||
125 | ----------------------------------------------------------------------------------]] |
||
126 | |||
127 | function Clique:IsBuffActive(spell, unit) |
||
128 | if not unit then unit = Clique.unit end |
||
129 | if not UnitExists(unit) then return end |
||
130 | |||
131 | if string.find(spell, "Interface\\Icons\\") then |
||
132 | for i=1,32 do |
||
133 | local texture = UnitBuff(unit, i) |
||
134 | if texture == spell then return true end |
||
135 | end |
||
136 | |||
137 | for i=1,16 do |
||
138 | local texture = UnitDebuff(unit, i) |
||
139 | if texture == spell then return true end |
||
140 | end |
||
141 | |||
142 | return false |
||
143 | end |
||
144 | |||
145 | |||
146 | if not self.tooltip then |
||
147 | local tt = CreateFrame("GameTooltip", "CliqueTooltip", nil, "GameTooltipTemplate") |
||
148 | tt:SetOwner(tt, "ANCHOR_NONE") |
||
149 | tt.name = CliqueTooltipTextLeft1 |
||
150 | self.tooltip = tt |
||
151 | end |
||
152 | |||
153 | -- Check buffs |
||
154 | for i=1,32 do |
||
155 | if not UnitBuff(unit, i) then return nil end |
||
156 | |||
157 | self.tooltip:ClearLines() |
||
158 | self.tooltip:SetUnitBuff(unit, i) |
||
159 | if string.find(self.tooltip.name:GetText(), spell) then |
||
160 | return i |
||
161 | end |
||
162 | end |
||
163 | |||
164 | -- Check debuffs |
||
165 | for i=1,32 do |
||
166 | if not UnitDebuff(unit, i) then return nil end |
||
167 | |||
168 | self.tooltip:ClearLines() |
||
169 | self.tooltip:SetUnitDebuff(unit, i) |
||
170 | if string.find(self.tooltip.name:GetText(), spell) then |
||
171 | return i |
||
172 | end |
||
173 | end |
||
174 | return false |
||
175 | end |
||
176 | |||
177 | function Clique:IsBuff(name) |
||
178 | return buff_lookup[name] |
||
179 | end |
||
180 | |||
181 | function Clique:BuffTest(name, rank, unit) |
||
182 | if not self:IsBuff(name) then return end |
||
183 | |||
184 | local level = UnitLevel(unit) |
||
185 | return (buff_lookup[name][rank] - 10) <= level |
||
186 | end |
||
187 | |||
188 | --[[--------------------------------------------------------------------------------- |
||
189 | Handles the "smart buff" casting, determining which rank of a specified |
||
190 | spell to cast on the given unit (based on level restrictions) |
||
191 | ----------------------------------------------------------------------------------]] |
||
192 | |||
193 | function Clique:BestRank(name, unit) |
||
194 | -- If we don't know the spell |
||
195 | if not unit then unit = Clique.unit end |
||
196 | if not self.spellbook[name] or not buff_lookup[name] or not UnitExists(unit) then return end |
||
197 | |||
198 | local level = UnitLevel(unit) |
||
199 | local maxrank = self.spellbook[name] |
||
200 | local castrank = nil |
||
201 | |||
202 | -- Make sure we don't go beyond the rank we currently know |
||
203 | |||
204 | for i=1,maxrank do |
||
205 | if self:BuffTest(name, i, unit) then |
||
206 | castrank = i |
||
207 | end |
||
208 | end |
||
209 | |||
210 | if castrank then |
||
211 | self:LevelDebug(3, "Trying to cast: %s(%s %d)", name, L"RANK", castrank) |
||
212 | Clique:CastSpell(string.format("%s(%s %d)", name, L"RANK", castrank), unit) |
||
213 | return castrank |
||
214 | end |
||
215 | return true |
||
216 | end |
||
217 | |||
218 | --[[--------------------------------------------------------------------------------- |
||
219 | This is a small unitID cache on unit names which returns the friendly unitID |
||
220 | of a specified unit. This helps to convert raid2targettarget into the more |
||
221 | friendly (and usable) raid14 allowing us to click-cast without changing |
||
222 | targets. |
||
223 | ----------------------------------------------------------------------------------]] |
||
224 | |||
225 | local unitCache = {} |
||
226 | local RAID_IDS = {} |
||
227 | local PARTY_IDS = {} |
||
228 | for i=1,MAX_RAID_MEMBERS do RAID_IDS[i] = "raid"..i end |
||
229 | for i=1,MAX_PARTY_MEMBERS do PARTY_IDS[i] = "party"..i end |
||
230 | |||
231 | function Clique:GetFriendlyUnit(unit) |
||
232 | local name = UnitName(unit) |
||
233 | local cache = unitCache[name] |
||
234 | |||
235 | --ace:print("Unit: " .. unit .. " Cache: " .. tostring(cache)) |
||
236 | |||
237 | if cache then |
||
238 | if UnitName(cache) == name then |
||
239 | return cache |
||
240 | end |
||
241 | end |
||
242 | |||
243 | local unitID = nil |
||
244 | local num = GetNumRaidMembers() |
||
245 | |||
246 | local tbl |
||
247 | if not UnitIsUnit("player", unit) then |
||
248 | if num > 0 then |
||
249 | tbl = RAID_IDS |
||
250 | else |
||
251 | num = GetNumPartyMembers() |
||
252 | tbl = PARTY_IDS |
||
253 | end |
||
254 | |||
255 | for i=1,num do |
||
256 | local u = tbl[i] |
||
257 | if UnitIsUnit(u, unit) then |
||
258 | unitID = u |
||
259 | break |
||
260 | end |
||
261 | end |
||
262 | else |
||
263 | unitID = "player" |
||
264 | end |
||
265 | |||
266 | unitCache[name] = unitID |
||
267 | |||
268 | --ace:print("UnitID: " .. (tostring(unitID or unit))) |
||
269 | |||
270 | return unitID |
||
271 | end |
||
272 | |||
273 | --[[--------------------------------------------------------------------------------- |
||
274 | Simple table re-use function. Prevents memory churn |
||
275 | ----------------------------------------------------------------------------------]] |
||
276 | |||
277 | function Clique:ClearTable(tbl) |
||
278 | if not tbl then tbl = {} end |
||
279 | for k in pairs(tbl) do tbl[k] = nil end |
||
280 | table.setn(tbl, 0) |
||
281 | return tbl |
||
282 | end |
||
283 | |||
284 | --[[--------------------------------------------------------------------------------- |
||
285 | Sets the tooltip OnEnter |
||
286 | ----------------------------------------------------------------------------------]] |
||
287 | |||
288 | function Clique:SetTooltip(frame, text) |
||
289 | local func = function() |
||
290 | GameTooltip:SetOwner(frame, "ANCHOR_TOPLEFT") |
||
291 | GameTooltip:SetText(text) |
||
292 | GameTooltip:Show() |
||
293 | end |
||
294 | |||
295 | frame:SetScript("OnEnter", func) |
||
296 | frame:SetScript("OnLeave", function() GameTooltip:Hide() end) |
||
297 | end |
||
298 | |||
299 | --[[--------------------------------------------------------------------------------- |
||
300 | Pops up the user menu |
||
301 | ----------------------------------------------------------------------------------]] |
||
302 | |||
303 | function Clique:UnitMenu(unit) |
||
304 | local type,x = nil,nil |
||
305 | unit = unit or Clique.unit |
||
306 | |||
307 | if unit == "player" then |
||
308 | type = PlayerFrameDropDown |
||
309 | elseif unit == "target" then |
||
310 | type = TargetFrameDropDown |
||
311 | elseif unit == "pet" then |
||
312 | type = PetFrameDropDown |
||
313 | elseif string.find(unit, "party") then |
||
314 | _,_,x = string.find(unit, "(%d+)") |
||
315 | type = getglobal("PartyMemberFrame"..x.."DropDown") |
||
316 | elseif string.find(unit, "raid") then |
||
317 | _,_,x = string.find(unit, "(%d+)") |
||
318 | type = FriendsDropDown |
||
319 | this.unit = unit |
||
320 | this.name = UnitName(unit) |
||
321 | this.id = this:GetID() |
||
322 | FriendsDropDown.displayMode = "MENU" |
||
323 | FriendsDropDown.initialize = RaidFrameDropDown_Initialize |
||
324 | end |
||
325 | |||
326 | if x then this:SetID(x) end |
||
327 | |||
328 | if type then |
||
329 | type.unit = unit |
||
330 | type.name = UnitName(unit) |
||
331 | ToggleDropDownMenu(1, nil, type,"cursor") |
||
332 | return true |
||
333 | end |
||
334 | return true |
||
335 | end |
||
336 | |||
337 | --[[--------------------------------------------------------------------------------- |
||
338 | Dispels the unit of any ailments you can cure |
||
339 | ----------------------------------------------------------------------------------]] |
||
340 | |||
341 | function Clique:CureAny(unit) |
||
342 | unit = unit or Clique.unit |
||
343 | local ailments = Clique:ClearTable(self.work) |
||
344 | |||
345 | for i=1,16 do |
||
346 | local texture,stack,type = UnitDebuff(unit, i) |
||
347 | if not texture then break end |
||
348 | if type then |
||
349 | ailments[type] = true |
||
350 | end |
||
351 | end |
||
352 | if next(ailments) then |
||
353 | self:Debug("Checking ailments") |
||
354 | for type in pairs(ailments) do |
||
355 | self:Debug("Checking for type: " .. type) |
||
356 | for i,cure in pairs(cure_lookup[type]) do |
||
357 | self:Debug("Checking spell: " .. cure) |
||
358 | if self.spellbook[cure] then |
||
359 | self:Debug(cure) |
||
360 | Clique:CastSpell(cure, unit) |
||
361 | return cure |
||
362 | end |
||
363 | end |
||
364 | end |
||
365 | end |
||
366 | return true |
||
367 | end |
||
368 | |||
369 | function Clique:NewSpell(spell, buff) |
||
370 | if not Clique:IsBuffActive(buff or spell) then |
||
371 | if Clique:IsBuff(spell) then |
||
372 | Clique:BestRank(spell) |
||
373 | else |
||
374 | Clique:CastSpell(spell) |
||
375 | end |
||
376 | end |
||
377 | return true |
||
378 | end |
||
379 | |||
380 | function Clique:TargetUnit(unit) |
||
381 | if not unit then unit = Clique.unit end |
||
382 | TargetUnit(unit) |
||
383 | return true |
||
384 | end |
||
385 | |||
386 | function Clique:AssistUnit(unit) |
||
387 | if not unit then unit = Clique.unit end |
||
388 | AssistUnit(unit) |
||
389 | return true |
||
390 | end |