Mercurial > wow > skeletonkey
diff SkeletonKey.lua @ 70:131d9190db6b
Curseforge migration
author | Nenue |
---|---|
date | Wed, 28 Dec 2016 16:31:15 -0500 |
parents | |
children | c48913c5924c |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/SkeletonKey.lua Wed Dec 28 16:31:15 2016 -0500 @@ -0,0 +1,409 @@ +-------------------------------------------- +-- SkeletonKey +-- Krakyn-Mal'Ganis +-- @project-revision@ @project-hash@ +-- @file-revision@ @file-hash@ +-- Created: 6/16/2016 3:47 AM +-------------------------------------------- +-- Header script + +local addonName, kb = ... +local print = DEVIAN_WORKSPACE and function(...) print('SK',...) end or nop +SkeletonKeyMixin = { + scrollCache = {}, + tabButtons = {}, + keyButtons = {}, + panelButtons = {}, + numTabs = 0, +} +kb.L = setmetatable({}, { + __call = function(t, k, ...) return format(t[k] or k, ...) end +}) +local L = kb.L + +--- Caps Lock literals +L.UNSELECTED_TALENT_ASSIGNED = '|cFF00FF00%s|r added for |cFFFFFF00%s|r (%s).' +L.BINDING_ASSIGNED = '|cFF00FF00%s|r assigned to |cFFFFFF00%s|r (%s).' +L.BINDING_REMOVED = '|cFFFFFF00%s|r (|cFF00FFFF%s|r) unbound.' +L.BINDING_FAILED_PROTECTED = '|cFFFF4400Cannot use |r|cFF00FF00%s|r|cFFFF4400 (currently |cFFFFFF00%s|r|cFFFF4400). Uncheck "Safety" to ignore this restraint.|r' + + +local BINDING_TYPE_SPECIALIZATION = 3 +local BINDING_TYPE_CHARACTER = 2 +local BINDING_TYPE_GLOBAL = 1 +kb.configTitle = { + [BINDING_TYPE_GLOBAL] = L('Global Binds'), + [BINDING_TYPE_CHARACTER] = L('%%s'), + [BINDING_TYPE_SPECIALIZATION] = L('%%s') +} +kb.configDescription = { + [BINDING_TYPE_GLOBAL] = L('The bindings are applied globally.'), + [BINDING_TYPE_CHARACTER] = L('Applied when you log onto this character.'), + [BINDING_TYPE_SPECIALIZATION] = L('Applied when you select this specialization.'), +} + + +kb.ChangedBindings = {} +kb.SystemBindings = {} +kb.ActionTypes = {} +kb.TalentBindings = {} +kb.PetCache = { + spell = {}, + spellslot = {}, + action = {}, + special = {}, + subtext = {} +} +kb.DynamicSpells = { + profession = {}, + petaction = {}, + talent = {}, +} +kb.TalentCache = {} +kb.ProfessionCache = {} +kb.pendingCalls = {} +kb.pendingAttributes = {} + +kb.configHeaders = {} +kb.loadedProfiles = {} +kb.orderedProfiles = {} +kb.buttons = {} +kb.macros = {} +kb.bindings = {} +kb.petFrames = {} -- pet data is slightly delayed, their buttons are indexed here so they can be refreshed +kb.talentFrames = {} +kb.professionFrames = {} + +-- these are sent to plugin + + +local db +local _G = _G +local UnitName, SelectedRealmName, InCombatLockdown, UnitClass = UnitName, SelectedRealmName, InCombatLockdown, UnitClass +local tostring, select, tinsert, pairs = tostring, select, tinsert, pairs +local concat, wipe = table.concat, table.wipe +local classHeader, className, classID = '', '', 0 + + +local CloseButton_OnClick = function() + + kb.db.showUI = false + print(kb.db.showUI) + SkeletonKey:SetShown(kb.db.showUI) +end + +--- Returns conflicting assignment and binding profiles for use in displaying confirmations +kb.IsCommandBound = function(self, command) + local isAssigned, assignedBy = false, kb.db.bindMode + local isBound, boundBy = false, kb.db.bindMode + command = command or self.command + for i = 1, #kb.orderedProfiles do + local profile = kb.orderedProfiles[i] + if i ~= kb.db.bindMode then + + if profile.commands[command] then + print(' command: ', i , kb.configHeaders[i], profile.commands[command]) + isAssigned = true + assignedBy = i + end + if profile.bound[command] then + print(' bound: ', i , kb.configHeaders[i], profile.bound[command]) + isBound = true + boundBy = i + end + + + + + if isAssigned and isBound then + print(' hit: ', i , kb.configHeaders[i], profile.commands[command], profile.bound[command]) + break + end + end + + end + + print('|cFFFFFF00IsCommandBound:|r', command,'|r [profile:', kb.db.bindMode .. ']', isAssigned, isBound, assignedBy, boundBy) + return isAssigned, isBound, assignedBy, boundBy +end + +local talentSpellHardCodes = { + [109248] = 'Binding Shot', +} + +--- Returns a value for use with Texture:SetDesaturated() +kb.BindingIsLocked = function(key) + local success = false + for i = 1, db.bindMode-1 do + local tier = kb.orderedProfiles[i] + if tier.bindings[key] then + success = true + break + end + end + return success +end + +--- Translates GetBindingKey() results into a printable string. +kb.BindingString = function(...) + local stack = {} + for i = 1, select('#', ...) do + local key = select(i, ...) + if type(key) == 'string' then + stack[i] = key:gsub('SHIFT', 's'):gsub('ALT', 'a'):gsub('CTRL', 'c'):gsub('SPACE', 'Sp'):gsub('BUTTON', 'M '):gsub('NUMPAD', '# ') + end + end + + if #stack >= 1 then + return concat(stack, ',') + else + return nil + end +end + + +function kb:print(...) + + local msg = '|cFF0088FFSkeletonKey|r:' + for i = 1, select('#', ...) do + msg = msg .. ' ' .. tostring(select(i, ...)) + end + DEFAULT_CHAT_FRAME:AddMessage(msg) +end + + +kb.Command = function(args, editor) + if args:match("import") then + kb.ImportCommmit(args) + return + elseif args:match("scan") then + kb.ImportScan(args) + SkeletonKey:Update() + return + elseif args:match("load") then + kb:ApplyAllBindings() + return + end + + if db.showUI then + db.showUI = false + else + db.showUI = true + if not InCombatLockdown() then + kb:print(L('Config frame opened.')) + else + kb:print(L('Config frame will open upon exiting combat.')) + end + end + SkeletonKey:SetShown(db.showUI) + SkeletonKey:Update(true) +end + +kb.InitProfile = function(profile, prototype) + print('|cFF00FFFFkb.InitProfile()', profile, prototype) + if not profile then + profile = {} + end + if prototype then + for k,v in pairs(prototype) do + if not profile[k] then + profile[k] = v + end + end + end + + profile.bound = profile.bound or {} + profile.buttons = profile.buttons or {} + profile.commands = profile.commands or {} + profile.bindings = profile.bindings or {} + profile.macros = profile.macros or {} + profile.talents = profile.talents or {} + return profile +end + +kb.ResetProfile = function(profile, prototype) + if profile == kb.currentProfile then + for i, button in pairs(kb.buttons) do + kb.ReleaseSlot(button) + end + end + wipe(profile) + kb.InitProfile(profile, prototype) +end + + + +--- Handles constructing spec profiles as they are selected + + +--- Obtains profile data or creates the necessary tables +kb.SelectProfileSet = function(name) + + local defaultMode + --- General info + classHeader, className, classID = UnitClass('player') + print('|cFF00FF00profile:|r', name) + print('|cFF00FF00class:|r', UnitClass('player')) + + defaultMode = BINDING_TYPE_GLOBAL + if db[name] then + defaultMode = BINDING_TYPE_CHARACTER + if db[name][kb.specInfo.id] then + defaultMode = BINDING_TYPE_SPECIALIZATION + end + end + + db[name] = kb.InitProfile(db[name], + { + classHeader = classHeader, + className = className, + classID = classID + }) + db[name][kb.specInfo.id] = kb.InitProfile(db[name][kb.specInfo.id], + { + specID = kb.specInfo.id, + specName = kb.specInfo.name + }) + + kb.loadedProfiles[BINDING_TYPE_GLOBAL] = db + kb.loadedProfiles[BINDING_TYPE_CHARACTER] = db[name] + kb.loadedProfiles[BINDING_TYPE_SPECIALIZATION] = db[name][kb.specInfo.id] + kb.orderedProfiles = {db, db[name], db[name][kb.specInfo.id]} + + if (not db.bindMode) or (not kb.configTitle[db.bindMode]) then + print('fixing bad bindMode value, was', db.bindMode) + db.bindMode = defaultMode + end + + + print(BINDING_TYPE_GLOBAL) + kb.configHeaders[BINDING_TYPE_GLOBAL] = kb.configTitle[BINDING_TYPE_GLOBAL] + kb.configHeaders[BINDING_TYPE_CHARACTER] = kb.configTitle[BINDING_TYPE_CHARACTER]:format(UnitName('player', true)) + kb.configHeaders[BINDING_TYPE_SPECIALIZATION] = kb.configTitle[BINDING_TYPE_SPECIALIZATION]:format(kb.specInfo.name or '') + + + setmetatable(kb.loadedProfiles[BINDING_TYPE_GLOBAL], {__tostring =function() return kb.configHeaders[BINDING_TYPE_GLOBAL] end}) + setmetatable(kb.loadedProfiles[BINDING_TYPE_CHARACTER], {__tostring =function() return kb.configHeaders[BINDING_TYPE_CHARACTER] end}) + setmetatable(kb.loadedProfiles[BINDING_TYPE_SPECIALIZATION], {__tostring =function() return kb.configHeaders[BINDING_TYPE_SPECIALIZATION] end}) + + print('|cFF00FF00bindMode:|r', db.bindMode) + kb.currentProfile = kb.loadedProfiles[db.bindMode] + kb.currentHeader = kb.configHeaders[db.bindMode] +end + + +function SkeletonKeyMixin:SetTab (id) + self.scrollCache[db.bindMode] = kb.scrollOffset + db.bindMode =id + kb.currentProfile = kb.loadedProfiles[id] + kb.currentHeader = kb.configHeaders[db.bindMode] + kb.scrollOffset = self.scrollCache[db.bindMode] or 0 + self:Update(true) +end + +kb.ConfirmBindings = function() + kb.ApplyAllBindings() + if #kb.pendingAttributes == 0 then + kb:print(L("Manual bindings update finished.")) + else + kb:print(L("Manual update will complete upon exiting combat.")) + end + SkeletonKey:Update() +end + +function SkeletonKeyMixin:OnLoad() + kb.frame = self + print('|cFF0088FF'..self:GetName()..':OnLoad()') + + self.CloseButton:SetScript('OnClick', CloseButton_OnClick) + self:RegisterEvent('PLAYER_ENTERING_WORLD') + self:RegisterEvent('ADDON_LOADED') + self:EnableKeyboard(false) + + self.zoomScale = self:GetScale() + self.backdrop = self:GetBackdrop() + self.backdropColor = {self:GetBackdropColor() } + self.backdropBorder = {self:GetBackdropBorderColor() } + +end + +function SkeletonKeyMixin:OnEvent(event, arg) + if event == 'ADDON_LOADED' then + + print('|cFF00FFFF'..event ..'|r', arg or '', IsLoggedIn()) + if IsLoggedIn() and not self.initialized then + self:Setup() + self.initialized = true + self:Update() + end + + + elseif kb[event] then + if self.initialized then + print('|cFF0088FF'..event ..'|r', arg or '') + kb[event](self, event, arg) + else + + print('|cFF004488'..event ..'|r', arg or '') + end + end +end + + +--- post ADDON_LOADED +function SkeletonKeyMixin:Setup () + print('|cFF00FFFF'..self:GetName()..':Setup()') + SkeletonKeyDB = kb.InitProfile(SkeletonKeyDB, {}) + kb.db = _G.SkeletonKeyDB + kb.playerName = UnitName('player') + kb.playerRealm = SelectedRealmName() + kb.profileName = kb.playerRealm .. '_' .. kb.playerName + db = kb.db + + kb.UpdateSpecInfo() + kb.UpdateTalentInfo() + kb.SelectProfileSet(kb.profileName) + -- todo: redo import checking + + kb.UpdateSystemBinds() + kb.ApplyAllBindings() + + if not InCombatLockdown() then + kb.CreateHooks() + else + kb:print('Some functionality will not load until breaking combat.') + tinsert(kb.pendingCalls, kb.CreateHooks) + end + SLASH_SKB1 = "/skb" + SLASH_SKB2 = "/skeletonkey" + SlashCmdList.SKB = kb.Command + + self:SetShown(kb.db.showUI) + self:Update(true) + + self:RegisterEvent('UPDATE_MACROS') + self:RegisterEvent('UPDATE_BINDINGS') + self:RegisterUnitEvent('UNIT_PORTRAIT_UPDATE', 'player', 'pet') + self:RegisterUnitEvent('PLAYER_SPECIALIZATION_CHANGED', 'player', 'pet') + self:RegisterUnitEvent('SPELLS_CHANGED') + self:RegisterUnitEvent('TALENT_UPDATE', 'player', 'pet') + self:RegisterEvent('PLAYER_REGEN_DISABLED') + self:RegisterEvent('PLAYER_REGEN_ENABLED') + + self:RegisterForDrag('LeftButton') + self:SetMovable(true) + for index, frame in ipairs(self.Plugins) do + frame:Setup() + end +end + + +-- Volatiles Access +kb.FormatActionID = function(actionType, actionID) return tostring(actionType) .. '_' .. tostring(actionID) end +kb.GetBindings = function() return kb.bindings end +kb.GetButtons = function() return kb.buttons end +kb.GetCharacterProfile = function () return kb.loadedProfiles[BINDING_TYPE_CHARACTER] end +kb.GetGlobalProfile = function () return kb.loadedProfiles[BINDING_TYPE_GLOBAL] end +kb.GetSpecProfile = function () return kb.loadedProfiles[BINDING_TYPE_SPECIALIZATION] end + +