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
+
+