vanilla-wow-addons – Blame information for rev 1

Subversion Repositories:
Rev:
Rev Author Line No. Line
1 office 1 --[[---------------------------------------------------------------------------------
2 Clique by Cladhaire <cladhaire@gmail.com>
3 GUI concept/code by Gello
4  
5 TODO:
6  
7 ----------------------------------------------------------------------------------]]
8  
9 --[[---------------------------------------------------------------------------------
10 Create the AddOn object and create a local binding for AceLocale
11 ----------------------------------------------------------------------------------]]
12  
13 Clique = AceLibrary("AceAddon-2.0"):new(
14 "AceHook-2.0",
15 "AceConsole-2.0",
16 "AceDB-2.0",
17 "AceEvent-2.0",
18 "AceModuleCore-2.0",
19 "AceDebug-2.0"
20 )
21  
22 Clique:RegisterDB("CliqueDB")
23 local L = AceLibrary:GetInstance("AceLocale-2.0"):new("Clique")
24  
25 -- Expoxe AceHook and AceEvent to our modules
26 Clique:SetModuleMixins("AceHook-2.0", "AceEvent-2.0", "AceDebug-2.0")
27  
28 --[[---------------------------------------------------------------------------------
29 This is the actual addon object
30 ----------------------------------------------------------------------------------]]
31  
32 function Clique:OnInitialize()
33 self:LevelDebug(2, "Clique:OnInitialize()")
34 self:CheckProfile()
35  
36 self:LevelDebug(3, "Setting all modules to inactive.")
37 for name,module in self:IterateModules() do
38 self:ToggleModuleActive(name, false)
39 end
40 end
41  
42 function Clique:OnEnable()
43 self:LevelDebug(2, "Clique:OnEnable()")
44 IndentationLib.addSmartCode(CliqueEditBox)
45  
46 if GetCVar("AutoSelfCast") == "1" then
47 StaticPopup_Show("CLIQUE_AUTO_SELF_CAST")
48 return
49 end
50  
51 -- Register for ADDON_LOADED so we can load plugins for LOD addons
52 self:RegisterEvent("ADDON_LOADED", "LoadModules")
53  
54 -- Build the action table, so we have precompiled functions
55 self:ScanSpellbook()
56 self:BuildActionTable()
57  
58 -- Enable tooltips in the GUI
59 self:EnableTooltips()
60 self:RegUtilFuncs()
61  
62 -- Create the hook tables
63 self._OnClick = {}
64  
65 -- Load any valid modules
66 self:LoadModules()
67  
68 -- Hook the SpellBookFrame so we can hide/show as needed
69 self:HookScript(SpellBookFrame, "OnShow", "SpellBookFrame_OnShow")
70 for i=1,12 do
71 local button = getglobal("SpellButton"..i)
72 button:RegisterForClicks("LeftButtonUp","RightButtonUp", "MiddleButtonUp", "Button4Up", "Button5Up");
73 self:HookScript(button, "OnClick", "SpellButton_OnClick")
74 end
75 end
76  
77 function Clique:LoadModules()
78 for name,module in self:IterateModules() do
79 if not self:IsModuleActive(name) and not module.disabled then
80 -- Try to enable the module
81  
82 local loadModule = nil
83  
84 if module.Test and type(module.Test) == "function" then
85 if module:Test() then
86 loadModule = true
87 end
88 else
89 loadModule = true
90 end
91  
92 if loadModule and not Clique:IsModuleActive(name) then
93 self:LevelDebug(1, "Enabling module \"%s\" for %s.", name, module.fullname)
94 Clique:ToggleModuleActive(name,true)
95  
96 if module._OnClick then
97 self:LevelDebug(2, "Grabbing _OnClick from %s", name)
98 self._OnClick[name] = module
99 end
100 end
101 end
102 end
103 end
104  
105 function Clique:CheckProfile()
106 self:LevelDebug(2, "Clique:CheckProfile()")
107  
108 local profile = self.db.char
109 profile[L"DEFAULT_FRIENDLY"] = profile[L"DEFAULT_FRIENDLY"] or {}
110 profile[L"DEFAULT_HOSTILE"] = profile[L"DEFAULT_HOSTILE"] or {}
111 end
112  
113 function Clique:BuildActionTable()
114 self:LevelDebug(2, "Clique:BuildActionTable()")
115  
116 local actions = self:ClearTable(self.Actions)
117 self.Actions = actions
118  
119 for k,v in pairs(self.db.char) do
120 actions[k] = {}
121  
122 for i,entry in ipairs(v) do
123 local a = bit.band(entry.modifiers, 1)
124 local c = bit.band(entry.modifiers, 2)
125 local s = bit.band(entry.modifiers, 4)
126  
127 -- Skip any non-bound entries
128 if entry.button ~= L"BINDING_NOT_DEFINED" then
129 local key = string.format("%s%d", entry.button, entry.modifiers)
130 local action = entry.action
131 if not action and not entry.custom then
132 local buff = self.spellbook[entry.name]
133 if buff then buff = tonumber(buff) end
134 if self:IsBuff(entry.name) and not entry.rank then
135 action = string.format("Clique:BestRank(\"%s\", Clique.unit)", entry.name)
136 elseif entry.rank then
137 action = string.format("Clique:CastSpell(\"%s(%s %d)\")", entry.name, L"RANK", entry.rank)
138 else
139 action = string.format("Clique:CastSpell(\"%s\")", entry.name)
140 end
141 end
142  
143 --self:Print(action)
144  
145 local func,errString = loadstring(action)
146 if func then
147 actions[k][key] = func
148 else
149 DEFAULT_CHAT_FRAME:AddMessage(string.format(L"ERROR_SCRIPT", errString))
150 end
151 end
152 end
153 end
154 end
155  
156 function Clique:OnClick(button, unit)
157 unit = unit or this.unit
158 button = button or arg1
159 local a,c,s = IsAltKeyDown() or 0, IsControlKeyDown() or 0, IsShiftKeyDown() or 0
160  
161 local targettarget = nil
162  
163 if not unit then
164 unit = this:GetParent().unit
165 if not unit then
166 error(string.format(L"NO_UNIT_FRAME", tostring(this:GetName())))
167 end
168 end
169  
170 if not UnitExists(unit) then
171 return
172 end
173  
174 Clique.unit = unit
175 -- DEFAULT_CHAT_FRAME:AddMessage("Clique:OnClick("..tostring(button)..", "..tostring(unit)..")")
176 if not UnitExists(unit) then return end
177  
178 -- If the casting hand is up on the screen, cast the waiting spell on
179 -- this unit
180 if SpellIsTargeting() then
181 if button == "LeftButton" then SpellTargetUnit(unit)
182 elseif button == "RightButton" then SpellStopTargeting() end
183 return true
184 end
185  
186 -- If the cursor has an item and we're clicking on another player,
187 -- attempt to trade with them (or feed your pet, etc). If we
188 -- LeftButton drop it on ourselves, then equip the item. If we click
189 -- anything else, then put the item back in the backpack
190 if CursorHasItem() then
191 if button == "LeftButton" then
192 if unit == "player" then AutoEquipCursorItem()
193 else DropItemOnUnit(unit) end
194 else PutItemInBackpack() end
195 return
196 end
197  
198 -- We need to determine which cast set we're coming from
199 local default = L"DEFAULT_FRIENDLY"
200 local restore = nil
201  
202 if UnitCanAttack("player", unit) then
203 default = L"DEFAULT_HOSTILE"
204 end
205  
206 Clique.set = default
207  
208 -- Iterate the hooks here
209 for name,module in pairs(Clique._OnClick) do
210 if module:_OnClick(button, Clique.unit) then
211 self:LevelDebug(3, "Module %s has changed the clique set.", name)
212 break
213 end
214 end
215  
216 if not Clique.set or not Clique.Actions[Clique.set] then
217 Clique.set = default
218 end
219  
220 local modifiers = 0
221 modifiers = bit.bor(modifiers, a * 1)
222 modifiers = bit.bor(modifiers, c * 2)
223 modifiers = bit.bor(modifiers, s * 4)
224  
225 local key = string.format("%s%d", button, modifiers)
226 local func = Clique.Actions[Clique.set][key]
227 local entry = Clique.db.char[Clique.set][key]
228  
229 self:LevelDebug(2, "Clique:OnClick("..button..", " .. modifiers..")")
230  
231 if not func then
232 self:LevelDebug(3, "Casting from the default set instead.")
233 func = Clique.Actions[default][key]
234 entry = Clique.db.char[default][key]
235 end
236  
237 if func then
238 func()
239  
240 -- In case spell failed to apply
241 if SpellIsTargeting() then SpellStopTargeting() end
242  
243 return true
244 else
245 --error("Could not find an action for key " .. key)
246 end
247 end
248  
249 function Clique:CastSpell(spell, unit)
250 local restore = nil
251 unit = unit or Clique.unit
252  
253 -- IMPORTANT: If the unit is targettarget or more, then we need to try
254 -- to convert it to a friendly unit (to make click-casting work
255 -- properly). If this isn't successful, set it up so we restore our
256 -- target
257  
258 self:LevelDebug(2, "Clique:CastSpell("..tostring(spell)..", "..tostring(unit) .. ")")
259  
260 if string.find(unit, "target") and string.len(unit) > 6 then
261 local friendly = Clique:GetFriendlyUnit(unit)
262  
263 if friendly then
264 unit = friendly
265 else
266 self:LevelDebug(2, "Setting targettarget flag.")
267 targettarget = true
268 end
269 end
270  
271 -- Lets resolve the targeting. If this is a hostile target and its
272 -- not currently our target, then we will need to target the unit
273 if UnitCanAttack("player", unit) then
274 if not UnitIsUnit(unit, "target") then
275 self:LevelDebug(2, "Changing to hostile target.")
276 TargetUnit(unit)
277 end
278  
279 -- If we're looking at someone else's target, we have to change targets since
280 -- ClearTarget() will get rid of the blahtarget unitID entirely. We only do
281 -- this if this is a friendly target (since they will consume the spell)
282 elseif targettarget and not UnitCanAttack("player", "target") then
283 self:LevelDebug(2, "Changing target due to friendly target.")
284 TargetUnit(unit)
285  
286 -- If the target is a friendly unit, and its not the unit we're casting on
287 elseif UnitExists("target") and not UnitCanAttack("player", "target") and not UnitIsUnit(unit, "target") then
288 self:LevelDebug(3, "Clearing the target")
289 ClearTarget()
290 restore = true
291  
292 elseif UnitExists("target") and self:IsDualSpell(spell) and not UnitIsUnit(unit, "target") then
293 self:LevelDebug(3, "Clearing target for this dual spell")
294 ClearTarget()
295 restore = true
296 end
297  
298 --self:Print("Clique:CastSpell(%s, %s)", spell, unit)
299 --self:Print("Dual Spell: %s, %s", spell, tostring(self:IsDualSpell(spell)))
300  
301 CastSpellByName(spell)
302  
303 if SpellIsTargeting() then
304 self:LevelDebug(3, "SpellTargetingUnit")
305 SpellTargetUnit(unit)
306 end
307  
308 if SpellIsTargeting() then SpellStopTargeting() end
309  
310 if restore then
311 self:LevelDebug(3, "Restoring with TargetLastTarget")
312 TargetLastTarget()
313 end
314 end