Mercurial > wow > skeletonkey
comparison SkeletonKey.lua @ 70:131d9190db6b
Curseforge migration
author | Nenue |
---|---|
date | Wed, 28 Dec 2016 16:31:15 -0500 |
parents | |
children | c48913c5924c |
comparison
equal
deleted
inserted
replaced
69:b14d0611c8d9 | 70:131d9190db6b |
---|---|
1 -------------------------------------------- | |
2 -- SkeletonKey | |
3 -- Krakyn-Mal'Ganis | |
4 -- @project-revision@ @project-hash@ | |
5 -- @file-revision@ @file-hash@ | |
6 -- Created: 6/16/2016 3:47 AM | |
7 -------------------------------------------- | |
8 -- Header script | |
9 | |
10 local addonName, kb = ... | |
11 local print = DEVIAN_WORKSPACE and function(...) print('SK',...) end or nop | |
12 SkeletonKeyMixin = { | |
13 scrollCache = {}, | |
14 tabButtons = {}, | |
15 keyButtons = {}, | |
16 panelButtons = {}, | |
17 numTabs = 0, | |
18 } | |
19 kb.L = setmetatable({}, { | |
20 __call = function(t, k, ...) return format(t[k] or k, ...) end | |
21 }) | |
22 local L = kb.L | |
23 | |
24 --- Caps Lock literals | |
25 L.UNSELECTED_TALENT_ASSIGNED = '|cFF00FF00%s|r added for |cFFFFFF00%s|r (%s).' | |
26 L.BINDING_ASSIGNED = '|cFF00FF00%s|r assigned to |cFFFFFF00%s|r (%s).' | |
27 L.BINDING_REMOVED = '|cFFFFFF00%s|r (|cFF00FFFF%s|r) unbound.' | |
28 L.BINDING_FAILED_PROTECTED = '|cFFFF4400Cannot use |r|cFF00FF00%s|r|cFFFF4400 (currently |cFFFFFF00%s|r|cFFFF4400). Uncheck "Safety" to ignore this restraint.|r' | |
29 | |
30 | |
31 local BINDING_TYPE_SPECIALIZATION = 3 | |
32 local BINDING_TYPE_CHARACTER = 2 | |
33 local BINDING_TYPE_GLOBAL = 1 | |
34 kb.configTitle = { | |
35 [BINDING_TYPE_GLOBAL] = L('Global Binds'), | |
36 [BINDING_TYPE_CHARACTER] = L('%%s'), | |
37 [BINDING_TYPE_SPECIALIZATION] = L('%%s') | |
38 } | |
39 kb.configDescription = { | |
40 [BINDING_TYPE_GLOBAL] = L('The bindings are applied globally.'), | |
41 [BINDING_TYPE_CHARACTER] = L('Applied when you log onto this character.'), | |
42 [BINDING_TYPE_SPECIALIZATION] = L('Applied when you select this specialization.'), | |
43 } | |
44 | |
45 | |
46 kb.ChangedBindings = {} | |
47 kb.SystemBindings = {} | |
48 kb.ActionTypes = {} | |
49 kb.TalentBindings = {} | |
50 kb.PetCache = { | |
51 spell = {}, | |
52 spellslot = {}, | |
53 action = {}, | |
54 special = {}, | |
55 subtext = {} | |
56 } | |
57 kb.DynamicSpells = { | |
58 profession = {}, | |
59 petaction = {}, | |
60 talent = {}, | |
61 } | |
62 kb.TalentCache = {} | |
63 kb.ProfessionCache = {} | |
64 kb.pendingCalls = {} | |
65 kb.pendingAttributes = {} | |
66 | |
67 kb.configHeaders = {} | |
68 kb.loadedProfiles = {} | |
69 kb.orderedProfiles = {} | |
70 kb.buttons = {} | |
71 kb.macros = {} | |
72 kb.bindings = {} | |
73 kb.petFrames = {} -- pet data is slightly delayed, their buttons are indexed here so they can be refreshed | |
74 kb.talentFrames = {} | |
75 kb.professionFrames = {} | |
76 | |
77 -- these are sent to plugin | |
78 | |
79 | |
80 local db | |
81 local _G = _G | |
82 local UnitName, SelectedRealmName, InCombatLockdown, UnitClass = UnitName, SelectedRealmName, InCombatLockdown, UnitClass | |
83 local tostring, select, tinsert, pairs = tostring, select, tinsert, pairs | |
84 local concat, wipe = table.concat, table.wipe | |
85 local classHeader, className, classID = '', '', 0 | |
86 | |
87 | |
88 local CloseButton_OnClick = function() | |
89 | |
90 kb.db.showUI = false | |
91 print(kb.db.showUI) | |
92 SkeletonKey:SetShown(kb.db.showUI) | |
93 end | |
94 | |
95 --- Returns conflicting assignment and binding profiles for use in displaying confirmations | |
96 kb.IsCommandBound = function(self, command) | |
97 local isAssigned, assignedBy = false, kb.db.bindMode | |
98 local isBound, boundBy = false, kb.db.bindMode | |
99 command = command or self.command | |
100 for i = 1, #kb.orderedProfiles do | |
101 local profile = kb.orderedProfiles[i] | |
102 if i ~= kb.db.bindMode then | |
103 | |
104 if profile.commands[command] then | |
105 print(' command: ', i , kb.configHeaders[i], profile.commands[command]) | |
106 isAssigned = true | |
107 assignedBy = i | |
108 end | |
109 if profile.bound[command] then | |
110 print(' bound: ', i , kb.configHeaders[i], profile.bound[command]) | |
111 isBound = true | |
112 boundBy = i | |
113 end | |
114 | |
115 | |
116 | |
117 | |
118 if isAssigned and isBound then | |
119 print(' hit: ', i , kb.configHeaders[i], profile.commands[command], profile.bound[command]) | |
120 break | |
121 end | |
122 end | |
123 | |
124 end | |
125 | |
126 print('|cFFFFFF00IsCommandBound:|r', command,'|r [profile:', kb.db.bindMode .. ']', isAssigned, isBound, assignedBy, boundBy) | |
127 return isAssigned, isBound, assignedBy, boundBy | |
128 end | |
129 | |
130 local talentSpellHardCodes = { | |
131 [109248] = 'Binding Shot', | |
132 } | |
133 | |
134 --- Returns a value for use with Texture:SetDesaturated() | |
135 kb.BindingIsLocked = function(key) | |
136 local success = false | |
137 for i = 1, db.bindMode-1 do | |
138 local tier = kb.orderedProfiles[i] | |
139 if tier.bindings[key] then | |
140 success = true | |
141 break | |
142 end | |
143 end | |
144 return success | |
145 end | |
146 | |
147 --- Translates GetBindingKey() results into a printable string. | |
148 kb.BindingString = function(...) | |
149 local stack = {} | |
150 for i = 1, select('#', ...) do | |
151 local key = select(i, ...) | |
152 if type(key) == 'string' then | |
153 stack[i] = key:gsub('SHIFT', 's'):gsub('ALT', 'a'):gsub('CTRL', 'c'):gsub('SPACE', 'Sp'):gsub('BUTTON', 'M '):gsub('NUMPAD', '# ') | |
154 end | |
155 end | |
156 | |
157 if #stack >= 1 then | |
158 return concat(stack, ',') | |
159 else | |
160 return nil | |
161 end | |
162 end | |
163 | |
164 | |
165 function kb:print(...) | |
166 | |
167 local msg = '|cFF0088FFSkeletonKey|r:' | |
168 for i = 1, select('#', ...) do | |
169 msg = msg .. ' ' .. tostring(select(i, ...)) | |
170 end | |
171 DEFAULT_CHAT_FRAME:AddMessage(msg) | |
172 end | |
173 | |
174 | |
175 kb.Command = function(args, editor) | |
176 if args:match("import") then | |
177 kb.ImportCommmit(args) | |
178 return | |
179 elseif args:match("scan") then | |
180 kb.ImportScan(args) | |
181 SkeletonKey:Update() | |
182 return | |
183 elseif args:match("load") then | |
184 kb:ApplyAllBindings() | |
185 return | |
186 end | |
187 | |
188 if db.showUI then | |
189 db.showUI = false | |
190 else | |
191 db.showUI = true | |
192 if not InCombatLockdown() then | |
193 kb:print(L('Config frame opened.')) | |
194 else | |
195 kb:print(L('Config frame will open upon exiting combat.')) | |
196 end | |
197 end | |
198 SkeletonKey:SetShown(db.showUI) | |
199 SkeletonKey:Update(true) | |
200 end | |
201 | |
202 kb.InitProfile = function(profile, prototype) | |
203 print('|cFF00FFFFkb.InitProfile()', profile, prototype) | |
204 if not profile then | |
205 profile = {} | |
206 end | |
207 if prototype then | |
208 for k,v in pairs(prototype) do | |
209 if not profile[k] then | |
210 profile[k] = v | |
211 end | |
212 end | |
213 end | |
214 | |
215 profile.bound = profile.bound or {} | |
216 profile.buttons = profile.buttons or {} | |
217 profile.commands = profile.commands or {} | |
218 profile.bindings = profile.bindings or {} | |
219 profile.macros = profile.macros or {} | |
220 profile.talents = profile.talents or {} | |
221 return profile | |
222 end | |
223 | |
224 kb.ResetProfile = function(profile, prototype) | |
225 if profile == kb.currentProfile then | |
226 for i, button in pairs(kb.buttons) do | |
227 kb.ReleaseSlot(button) | |
228 end | |
229 end | |
230 wipe(profile) | |
231 kb.InitProfile(profile, prototype) | |
232 end | |
233 | |
234 | |
235 | |
236 --- Handles constructing spec profiles as they are selected | |
237 | |
238 | |
239 --- Obtains profile data or creates the necessary tables | |
240 kb.SelectProfileSet = function(name) | |
241 | |
242 local defaultMode | |
243 --- General info | |
244 classHeader, className, classID = UnitClass('player') | |
245 print('|cFF00FF00profile:|r', name) | |
246 print('|cFF00FF00class:|r', UnitClass('player')) | |
247 | |
248 defaultMode = BINDING_TYPE_GLOBAL | |
249 if db[name] then | |
250 defaultMode = BINDING_TYPE_CHARACTER | |
251 if db[name][kb.specInfo.id] then | |
252 defaultMode = BINDING_TYPE_SPECIALIZATION | |
253 end | |
254 end | |
255 | |
256 db[name] = kb.InitProfile(db[name], | |
257 { | |
258 classHeader = classHeader, | |
259 className = className, | |
260 classID = classID | |
261 }) | |
262 db[name][kb.specInfo.id] = kb.InitProfile(db[name][kb.specInfo.id], | |
263 { | |
264 specID = kb.specInfo.id, | |
265 specName = kb.specInfo.name | |
266 }) | |
267 | |
268 kb.loadedProfiles[BINDING_TYPE_GLOBAL] = db | |
269 kb.loadedProfiles[BINDING_TYPE_CHARACTER] = db[name] | |
270 kb.loadedProfiles[BINDING_TYPE_SPECIALIZATION] = db[name][kb.specInfo.id] | |
271 kb.orderedProfiles = {db, db[name], db[name][kb.specInfo.id]} | |
272 | |
273 if (not db.bindMode) or (not kb.configTitle[db.bindMode]) then | |
274 print('fixing bad bindMode value, was', db.bindMode) | |
275 db.bindMode = defaultMode | |
276 end | |
277 | |
278 | |
279 print(BINDING_TYPE_GLOBAL) | |
280 kb.configHeaders[BINDING_TYPE_GLOBAL] = kb.configTitle[BINDING_TYPE_GLOBAL] | |
281 kb.configHeaders[BINDING_TYPE_CHARACTER] = kb.configTitle[BINDING_TYPE_CHARACTER]:format(UnitName('player', true)) | |
282 kb.configHeaders[BINDING_TYPE_SPECIALIZATION] = kb.configTitle[BINDING_TYPE_SPECIALIZATION]:format(kb.specInfo.name or '') | |
283 | |
284 | |
285 setmetatable(kb.loadedProfiles[BINDING_TYPE_GLOBAL], {__tostring =function() return kb.configHeaders[BINDING_TYPE_GLOBAL] end}) | |
286 setmetatable(kb.loadedProfiles[BINDING_TYPE_CHARACTER], {__tostring =function() return kb.configHeaders[BINDING_TYPE_CHARACTER] end}) | |
287 setmetatable(kb.loadedProfiles[BINDING_TYPE_SPECIALIZATION], {__tostring =function() return kb.configHeaders[BINDING_TYPE_SPECIALIZATION] end}) | |
288 | |
289 print('|cFF00FF00bindMode:|r', db.bindMode) | |
290 kb.currentProfile = kb.loadedProfiles[db.bindMode] | |
291 kb.currentHeader = kb.configHeaders[db.bindMode] | |
292 end | |
293 | |
294 | |
295 function SkeletonKeyMixin:SetTab (id) | |
296 self.scrollCache[db.bindMode] = kb.scrollOffset | |
297 db.bindMode =id | |
298 kb.currentProfile = kb.loadedProfiles[id] | |
299 kb.currentHeader = kb.configHeaders[db.bindMode] | |
300 kb.scrollOffset = self.scrollCache[db.bindMode] or 0 | |
301 self:Update(true) | |
302 end | |
303 | |
304 kb.ConfirmBindings = function() | |
305 kb.ApplyAllBindings() | |
306 if #kb.pendingAttributes == 0 then | |
307 kb:print(L("Manual bindings update finished.")) | |
308 else | |
309 kb:print(L("Manual update will complete upon exiting combat.")) | |
310 end | |
311 SkeletonKey:Update() | |
312 end | |
313 | |
314 function SkeletonKeyMixin:OnLoad() | |
315 kb.frame = self | |
316 print('|cFF0088FF'..self:GetName()..':OnLoad()') | |
317 | |
318 self.CloseButton:SetScript('OnClick', CloseButton_OnClick) | |
319 self:RegisterEvent('PLAYER_ENTERING_WORLD') | |
320 self:RegisterEvent('ADDON_LOADED') | |
321 self:EnableKeyboard(false) | |
322 | |
323 self.zoomScale = self:GetScale() | |
324 self.backdrop = self:GetBackdrop() | |
325 self.backdropColor = {self:GetBackdropColor() } | |
326 self.backdropBorder = {self:GetBackdropBorderColor() } | |
327 | |
328 end | |
329 | |
330 function SkeletonKeyMixin:OnEvent(event, arg) | |
331 if event == 'ADDON_LOADED' then | |
332 | |
333 print('|cFF00FFFF'..event ..'|r', arg or '', IsLoggedIn()) | |
334 if IsLoggedIn() and not self.initialized then | |
335 self:Setup() | |
336 self.initialized = true | |
337 self:Update() | |
338 end | |
339 | |
340 | |
341 elseif kb[event] then | |
342 if self.initialized then | |
343 print('|cFF0088FF'..event ..'|r', arg or '') | |
344 kb[event](self, event, arg) | |
345 else | |
346 | |
347 print('|cFF004488'..event ..'|r', arg or '') | |
348 end | |
349 end | |
350 end | |
351 | |
352 | |
353 --- post ADDON_LOADED | |
354 function SkeletonKeyMixin:Setup () | |
355 print('|cFF00FFFF'..self:GetName()..':Setup()') | |
356 SkeletonKeyDB = kb.InitProfile(SkeletonKeyDB, {}) | |
357 kb.db = _G.SkeletonKeyDB | |
358 kb.playerName = UnitName('player') | |
359 kb.playerRealm = SelectedRealmName() | |
360 kb.profileName = kb.playerRealm .. '_' .. kb.playerName | |
361 db = kb.db | |
362 | |
363 kb.UpdateSpecInfo() | |
364 kb.UpdateTalentInfo() | |
365 kb.SelectProfileSet(kb.profileName) | |
366 -- todo: redo import checking | |
367 | |
368 kb.UpdateSystemBinds() | |
369 kb.ApplyAllBindings() | |
370 | |
371 if not InCombatLockdown() then | |
372 kb.CreateHooks() | |
373 else | |
374 kb:print('Some functionality will not load until breaking combat.') | |
375 tinsert(kb.pendingCalls, kb.CreateHooks) | |
376 end | |
377 SLASH_SKB1 = "/skb" | |
378 SLASH_SKB2 = "/skeletonkey" | |
379 SlashCmdList.SKB = kb.Command | |
380 | |
381 self:SetShown(kb.db.showUI) | |
382 self:Update(true) | |
383 | |
384 self:RegisterEvent('UPDATE_MACROS') | |
385 self:RegisterEvent('UPDATE_BINDINGS') | |
386 self:RegisterUnitEvent('UNIT_PORTRAIT_UPDATE', 'player', 'pet') | |
387 self:RegisterUnitEvent('PLAYER_SPECIALIZATION_CHANGED', 'player', 'pet') | |
388 self:RegisterUnitEvent('SPELLS_CHANGED') | |
389 self:RegisterUnitEvent('TALENT_UPDATE', 'player', 'pet') | |
390 self:RegisterEvent('PLAYER_REGEN_DISABLED') | |
391 self:RegisterEvent('PLAYER_REGEN_ENABLED') | |
392 | |
393 self:RegisterForDrag('LeftButton') | |
394 self:SetMovable(true) | |
395 for index, frame in ipairs(self.Plugins) do | |
396 frame:Setup() | |
397 end | |
398 end | |
399 | |
400 | |
401 -- Volatiles Access | |
402 kb.FormatActionID = function(actionType, actionID) return tostring(actionType) .. '_' .. tostring(actionID) end | |
403 kb.GetBindings = function() return kb.bindings end | |
404 kb.GetButtons = function() return kb.buttons end | |
405 kb.GetCharacterProfile = function () return kb.loadedProfiles[BINDING_TYPE_CHARACTER] end | |
406 kb.GetGlobalProfile = function () return kb.loadedProfiles[BINDING_TYPE_GLOBAL] end | |
407 kb.GetSpecProfile = function () return kb.loadedProfiles[BINDING_TYPE_SPECIALIZATION] end | |
408 | |
409 |