view SkeletonKey/ActionTypes.lua @ 19:67db6b712bf3

- option checkbutton literals are stored by enclosure - detect and save any old keybindings when a slot is assigned (anything that begins with 'CLICK KeyBinder*' is ours) - mouseover mode key input will stay active after leaving a button - button border flashes when a non-modifier key is pressed
author Nenue
date Sat, 30 Jul 2016 19:08:11 -0400
parents 500f9b2bd9ac
children 564015ef0317
line wrap: on
line source
-- SkeletonKey
-- ActionTypes.lua
-- Created: 7/29/2016 9:14 PM
-- %file-revision%
--
local kb, print, wrap = LibStub('LibKraken').register(KeyBinder)
local cprint = DEVIAN_WORKSPACE and function(...) _G.print('Cfg', ...) end or function() end

local SUMMON_RANDOM_FAVORITE_MOUNT_SPELL = 150544
local CLICK_KEYBINDER_MACRO = "CLICK KeyBinderMacro:"
local CLICK_KEYBINDER_KEY = "CLICK KeyBinderKey:"

local PETACTION_SCRIPT = {
  [PET_ACTION_MOVE_TO] = {SLASH_PET_MOVE_TO1, 'pet_move_to'},
  [PET_ACTION_ATTACK] = {SLASH_PET_ATTACK1, 'pet_attack'},
  [PET_ACTION_FOLLOW] = {SLASH_PET_FOLLOW1, 'pet_follow'},
  [PET_ACTION_WAIT] = {SLASH_PET_STAY1, 'pet_stay'},
  [PET_MODE_AGGRESSIVE] = {SLASH_PET_AGGRESSIVE1, 'pet_aggressive'},
  [PET_MODE_DEFENSIVE] = {SLASH_PET_DEFENSIVE1, 'pet_defensive'},
  [PET_MODE_PASSIVE] = {SLASH_PET_PASSIVE1, 'pet_passive'},
  [PET_MODE_ASSIST] = {SLASH_PET_ASSIST1, 'pet_assist'},
}

kb.ActionTypes = {}
kb.PetCache = {}
kb.TalentCache = {}
kb.ProfessionCache = {}

local atype = kb.ActionTypes

--- Caps Lock
atype['mount'] = function(id, name)
  if id == SUMMON_RANDOM_FAVORITE_MOUNT_SPELL then
    return 'mount_random', "/script C_MountJournal.SummonByID(0)", CLICK_KEYBINDER_MACRO
  else
    return 'mount_'..id, "/script C_MountJournal.SummonByID("..id..")", CLICK_KEYBINDER_MACRO
  end
end

atype['macro'] = function(id, name)
  return CLICK_KEYBINDER_MACRO, 'macro_' .. tostring(name), id
end

atype['equipset'] = function(id, name)
    return CLICK_KEYBINDER_MACRO, 'equipset_'..tostring(name), "/script UseEquipmentSet("..tostring(id)..")"
end

atype['spell'] = function(id, name)
  local attributeName = name
  if kb.ProfessionCache[id] then
    attributeName = "profession_".. kb.ProfessionCache[id].profOffset .. '_' .. kb.ProfessionCache[id].spellNum
  end
  return CLICK_KEYBINDER_KEY, attributeName, name
end

atype['petaction'] = function(_, name)
  -- ID doesn't exist for basic commands, even though they can be picked up
  local attributeName, attributeValue = "petaction_" .. tostring(name), "/cast "..tostring(name)
  if PETACTION_SCRIPT[name] then
    attributeValue, attributeName = unpack(PETACTION_SCRIPT[name])
  elseif kb.PetCache.special[name] then
    attributeName = "petaction_special" .. tonumber(kb.PetCache.special[name][2])
  end
  return CLICK_KEYBINDER_MACRO, attributeName, attributeValue
end

atype['battlepet'] = function(id, name)
  return CLICK_KEYBINDER_MACRO, 'battlepet_' .. tostring(name), SLASH_SUMMON_BATTLE_PET1 .. " " .. tostring(name)
end

atype['item'] = function(id, name)
  return CLICK_KEYBINDER_KEY, 'item_' .. tostring(name), id
end


--- Resolves the SecureActionButton attribute names used for the given action
kb.RegisterAction = function(actionType, id, name)

  assert(atype[actionType], 'Missing actionType handler for `'..tostring(actionType)..'`')
  local target, attributeName, attributeValue  = atype[actionType](id, name)

  local command = target .. attributeName
  local baseName, iterative = attributeName, 1
  while (kb.macros[attributeName] and kb.macros[attributeName][1] ~= attributeValue) do
    print(' * cannot use|cFF00FF00', attributeName, '|r"'.. tostring(kb.macros[attributeName][1]) .. '"')
    attributeName = baseName .. '_' .. iterative
    iterative = iterative + 1
  end
  if macroName ~= baseName then
    print(' * Creating|cFF00FF00', macroName)
  else
    print(' * Re-using|cFF00FF00', macroName)
  end
  kb.macros[attributeName] = {attributeValue, command}


  print('RegisterAction', actionType, id, '->', attributeName, attributeValue, target .. attributeName)
  return attributeName, attributeValue, command
end




kb.ApplyTalentBinding = function(talentInfo, cache)
  for i = 5, #talentInfo do
    local command = CLICK_KEYBINDER_KEY.. talentInfo[2]
    SetBinding(talentInfo[i], command)
    cprint(' **', talentInfo[i], '->', command)
    tinsert(cache, talentInfo[i])
  end
end
kb.CacheTalentBinding = function(talentInfo, cache)

  local spellID = talentInfo[4]
  cache[spellID] = cache[spellID] or {}
  cache[spellID] = {select(5,unpack(talentInfo)) }
  --cprint(spellID, unpack(kb.TalentBindings[spellID]))
end

do
  local bindings = kb.bindings
  local key, macro = KeyBinderKey, KeyBinderMacro
  kb.LoadBinding = function(command, name, icon, actionType, actionID, macroName, macroText )

    if actionType == 'spell' then
      key:SetAttribute("*type-"..name, actionType)
      key:SetAttribute("*"..actionType.."-"..name, name)
    elseif actionType == 'item' then
      key:SetAttribute("*type-"..name, actionType)
      key:SetAttribute("*"..actionType.."-"..name, name)
    elseif actionType == 'macro' then
      macro:SetAttribute("*macro-"..macroName, actionID)
    else
      macro:SetAttribute("*macrotext-"..macroName, macroText)
    end

    cprint('Loading binding', actionType, actionID)
    bindings[actionType] = bindings[actionType] or {}
    bindings[actionType][actionID] = bindings[actionType][actionID] or {}
    bindings[command] = bindings[actionType][actionID]
    return bindings[actionType], actionID
  end

  kb.ApplyBindings = function (profile)
    cprint('binding profile', profile)
    for slot, data in pairs(profile.buttons) do
      kb.LoadBinding(unpack(data))
    end

    for key, command in pairs(profile.bindings) do

      cprint(' *', key, '->', command)

      --_G.print('HotKey','loading', key, command)
      SetBinding(key, command)
      if bindings[command] and not tContains(bindings[command], key) then
        tinsert(bindings[command], key)
      end
    end

    for spellName, talentInfo in pairs(profile.talents) do
      local dummy = GetSpellInfo(spellName)
      local func = kb.CacheTalentBinding
      local dest = kb.TalentBindings
      if dummy then
        cprint('|cFFBBFF00Active:|r', dummy)
        local macroName, spellName, actionType, actionID = unpack(talentInfo)
        bindings[actionType] = bindings[actionType] or {}
        bindings[actionType][actionID] = {}
        func = kb.ApplyTalentBinding
        dest = kb.bindings[actionType][actionID]
      else

        cprint('|cFFFF4400Inactive:|r', talentInfo[2])
      end
      func(talentInfo, dest)
    end

  end

  kb.ApplyAllBindings =function ()
    table.wipe(kb.TalentBindings)


    -- reflect action key settings
    if GetCVarBool("ActionButtonUseKeyDown") then
      KeyBinderMacro:RegisterForClicks("AnyDown")
      KeyBinderKey:RegisterForClicks("AnyDown")
    else
      KeyBinderMacro:RegisterForClicks("AnyUp")
      KeyBinderKey:RegisterForClicks("AnyUp")
    end

    for i, profile in ipairs(kb.orderedProfiles) do
      kb.ApplyBindings(profile)
    end
    -- do this after to ensure that profession binds are properly overridden
    kb.UpdateProfessionInfo()


    SaveBindings(GetCurrentBindingSet())
  end
end


local PET_SPECIAL_SUBTEXT = 'Special Ability'
local SECONDARY_PROFESSIONS = {
  [5] = 3,
  [7] = 4,
  [9] = 5,
  [10] = 6
}

kb.TalentCache = {}
kb.ProfessionCache = {}
kb.PetCache = {}
kb.specInfo = {}
kb.UpdateSpecInfo = function()
  kb.specInfo.id = GetSpecialization()
  kb.specInfo.globalID, kb.specInfo.name, kb.specInfo.desc, kb.specInfo.texture = GetSpecializationInfo(kb.specInfo.id)
  print('|cFF00FF00current spec:|r', kb.specInfo.id, 'of', GetNumSpecializations())
end

kb.UpdateTalentInfo = function()
  if kb.talentsPushed then
    return
  end
  table.wipe(kb.TalentCache)
  for row =1, MAX_TALENT_TIERS do
    for col = 1, NUM_TALENT_COLUMNS do
      local talentID, talentName, icon, selected, available, spellID = GetTalentInfo(row, col, 1)
      local talentInfo = kb.TalentCache[spellID] or {}
      talentInfo.row = 1
      talentInfo.col = col
      talentInfo.name = talentName
      talentInfo.talentID = talentID
      talentInfo.selected = selected
      talentInfo.available = available
      talentInfo.spellID = spellID
      kb.TalentCache[spellID] = talentInfo
      kb.TalentCache[talentName] = talentInfo
      print('Talent ', row, col, spellID, talentName)
    end
  end
  kb.talentsPushed = true

  kb.UpdateDynamicButtons('talent')
end

kb.UpdateProfessionInfo = function()
  table.wipe(kb.ProfessionCache)
  local profs = {GetProfessions() }
  local primaryNum = 0
  for i, index in ipairs(profs) do
    local profName, texture, rank, maxRank, numSpells, spellOffset = GetProfessionInfo(index)
    print(i, index, profName, numSpells, spellOffset)
    if not SECONDARY_PROFESSIONS[index] then
      primaryNum = primaryNum + 1
    end
    local profNum = SECONDARY_PROFESSIONS[index] or primaryNum


    kb.ProfessionCache[profNum] = kb.ProfessionCache[i] or {}

    for j = 1, numSpells do
      local spellName, _, icon, _, _, _, spellID = GetSpellInfo(spellOffset+j, BOOKTYPE_PROFESSION)

      local profInfo = {
        spellName = spellName,
        spellID = spellID,
        icon = icon,
        profOffset = i,
        profIndex = index,
        spellOffset = (spellOffset+j),
        spellNum = j
      }
      KeyBinderKey:SetAttribute("*type-profession_"..i .. '_' ..j, "spell")
      KeyBinderKey:SetAttribute("*spell-profession_"..i .. '_' ..j, spellName)

      kb.ProfessionCache[i .. '_' .. j] = profInfo
      kb.ProfessionCache[spellName] = profInfo
      kb.ProfessionCache[spellID] = profInfo
      print('  |cFF0088FF['..i..']|r|cFFFF44BB['..spellOffset+i..']|r', spellName, "profession_"..i .. '_' ..j)
    end

  end

  kb.UpdateDynamicButtons('profession')
end



kb.UpdatePetInfo = function()
  kb.PetCache.spell = kb.PetCache.spell or {}
  kb.PetCache.spellslot = kb.PetCache.spellslot or {}
  kb.PetCache.action = kb.PetCache.action or {}
  kb.PetCache.special = kb.PetCache.action or {}
  local hasPetSpells, petType = HasPetSpells()
  if PetHasSpellbook() then
    print('PET SPELLBOOK')
    local i = 1
    local specialNum = 0
    repeat

      local spellType, spellID = GetSpellBookItemInfo(i, BOOKTYPE_PET)
      local spellName, subText = GetSpellBookItemName(i, BOOKTYPE_PET)
      local isPassive = IsPassiveSpell(i, BOOKTYPE_PET)
      if not isPassive then
        if spellName then
          kb.PetCache.spellslot[spellName] = {i, spellName, subText}
          print('|cFF00FF88spellslot['..spellName..']|r', '=>', i, subText)

          if subText == PET_SPECIAL_SUBTEXT then
            specialNum = specialNum + 1
            kb.PetCache.special[spellName] = {i, specialNum, spellID, subText }
            print('|cFF00FFFFspecial['..spellName..']|r', '=>', i, specialNum, spellID, subText)
            KeyBinderMacro:SetAttribute("*macrotext-pet_special_"..specialNum, "/cast "..spellName)
          end

          if spellID then
            kb.PetCache.spell[i] = {spellID, spellName, subText}
            print('|cFF0088FFspell['..i..']|r', '=>', spellID, spellName, subText)
          end
        end


      end

      i = i + 1
    until spellType == nil
  else
    print('NO PET SPELLBOOK')
    table.wipe(kb.PetCache.spell)
    table.wipe(kb.PetCache.spellslot)
  end

  if PetHasActionBar() then
    print('PET ACTION BAR')
    for i = 1, 10 do


      local name, subtext, texture, isToken, isActive = GetPetActionInfo(i)
      if name then
        kb.PetCache.action[i] = {name, subtext, texture, isToken, isActive }


      end
      print('|cFFFFFF00action['..i..']|r', name, subtext, texture)
    end
  else
    print('NO PET ACTION BAR')
    table.wipe(kb.PetCache.action)
  end

  kb.UpdateDynamicButtons('petaction')

end

kb.UpdateSystemBinds = function()
  table.wipe(kb.SystemBindings)
  local n = GetNumBindings()
  for i=1, n do
    local command, key1, key2 = GetBinding(i)
    if key1 then
      kb.SystemBindings[key1] = command
    end
    if key2 then
      kb.SystemBindings[key2] = command
    end
  end
end

kb.UpdateDynamicButtons = function(dynamicType)
  for i, button in ipairs(kb.buttons) do
    if button.isDynamic == dynamicType then
      kb.UpdateSlot(button, true)
    end
  end
end