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