annotate 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
rev   line source
Nenue@16 1 -- SkeletonKey
Nenue@16 2 -- ActionTypes.lua
Nenue@16 3 -- Created: 7/29/2016 9:14 PM
Nenue@16 4 -- %file-revision%
Nenue@16 5 --
Nenue@16 6 local kb, print, wrap = LibStub('LibKraken').register(KeyBinder)
Nenue@17 7 local cprint = DEVIAN_WORKSPACE and function(...) _G.print('Cfg', ...) end or function() end
Nenue@16 8
Nenue@16 9 local SUMMON_RANDOM_FAVORITE_MOUNT_SPELL = 150544
Nenue@17 10 local CLICK_KEYBINDER_MACRO = "CLICK KeyBinderMacro:"
Nenue@17 11 local CLICK_KEYBINDER_KEY = "CLICK KeyBinderKey:"
Nenue@16 12
Nenue@16 13 local PETACTION_SCRIPT = {
Nenue@16 14 [PET_ACTION_MOVE_TO] = {SLASH_PET_MOVE_TO1, 'pet_move_to'},
Nenue@16 15 [PET_ACTION_ATTACK] = {SLASH_PET_ATTACK1, 'pet_attack'},
Nenue@16 16 [PET_ACTION_FOLLOW] = {SLASH_PET_FOLLOW1, 'pet_follow'},
Nenue@16 17 [PET_ACTION_WAIT] = {SLASH_PET_STAY1, 'pet_stay'},
Nenue@16 18 [PET_MODE_AGGRESSIVE] = {SLASH_PET_AGGRESSIVE1, 'pet_aggressive'},
Nenue@16 19 [PET_MODE_DEFENSIVE] = {SLASH_PET_DEFENSIVE1, 'pet_defensive'},
Nenue@16 20 [PET_MODE_PASSIVE] = {SLASH_PET_PASSIVE1, 'pet_passive'},
Nenue@16 21 [PET_MODE_ASSIST] = {SLASH_PET_ASSIST1, 'pet_assist'},
Nenue@16 22 }
Nenue@16 23
Nenue@19 24 kb.ActionTypes = {}
Nenue@19 25 kb.PetCache = {}
Nenue@19 26 kb.TalentCache = {}
Nenue@19 27 kb.ProfessionCache = {}
Nenue@19 28
Nenue@19 29 local atype = kb.ActionTypes
Nenue@19 30
Nenue@17 31 --- Caps Lock
Nenue@19 32 atype['mount'] = function(id, name)
Nenue@17 33 if id == SUMMON_RANDOM_FAVORITE_MOUNT_SPELL then
Nenue@17 34 return 'mount_random', "/script C_MountJournal.SummonByID(0)", CLICK_KEYBINDER_MACRO
Nenue@17 35 else
Nenue@17 36 return 'mount_'..id, "/script C_MountJournal.SummonByID("..id..")", CLICK_KEYBINDER_MACRO
Nenue@17 37 end
Nenue@16 38 end
Nenue@19 39
Nenue@19 40 atype['macro'] = function(id, name)
Nenue@17 41 return CLICK_KEYBINDER_MACRO, 'macro_' .. tostring(name), id
Nenue@17 42 end
Nenue@19 43
Nenue@19 44 atype['equipset'] = function(id, name)
Nenue@17 45 return CLICK_KEYBINDER_MACRO, 'equipset_'..tostring(name), "/script UseEquipmentSet("..tostring(id)..")"
Nenue@17 46 end
Nenue@19 47
Nenue@19 48 atype['spell'] = function(id, name)
Nenue@17 49 local attributeName = name
Nenue@17 50 if kb.ProfessionCache[id] then
Nenue@17 51 attributeName = "profession_".. kb.ProfessionCache[id].profOffset .. '_' .. kb.ProfessionCache[id].spellNum
Nenue@17 52 end
Nenue@17 53 return CLICK_KEYBINDER_KEY, attributeName, name
Nenue@17 54 end
Nenue@19 55
Nenue@19 56 atype['petaction'] = function(_, name)
Nenue@17 57 -- ID doesn't exist for basic commands, even though they can be picked up
Nenue@17 58 local attributeName, attributeValue = "petaction_" .. tostring(name), "/cast "..tostring(name)
Nenue@17 59 if PETACTION_SCRIPT[name] then
Nenue@17 60 attributeValue, attributeName = unpack(PETACTION_SCRIPT[name])
Nenue@19 61 elseif kb.PetCache.special[name] then
Nenue@19 62 attributeName = "petaction_special" .. tonumber(kb.PetCache.special[name][2])
Nenue@17 63 end
Nenue@17 64 return CLICK_KEYBINDER_MACRO, attributeName, attributeValue
Nenue@16 65 end
Nenue@16 66
Nenue@19 67 atype['battlepet'] = function(id, name)
Nenue@17 68 return CLICK_KEYBINDER_MACRO, 'battlepet_' .. tostring(name), SLASH_SUMMON_BATTLE_PET1 .. " " .. tostring(name)
Nenue@17 69 end
Nenue@19 70
Nenue@19 71 atype['item'] = function(id, name)
Nenue@17 72 return CLICK_KEYBINDER_KEY, 'item_' .. tostring(name), id
Nenue@17 73 end
Nenue@16 74
Nenue@16 75
Nenue@17 76 --- Resolves the SecureActionButton attribute names used for the given action
Nenue@16 77 kb.RegisterAction = function(actionType, id, name)
Nenue@16 78
Nenue@19 79 assert(atype[actionType], 'Missing actionType handler for `'..tostring(actionType)..'`')
Nenue@19 80 local target, attributeName, attributeValue = atype[actionType](id, name)
Nenue@17 81
Nenue@17 82 local command = target .. attributeName
Nenue@17 83 local baseName, iterative = attributeName, 1
Nenue@17 84 while (kb.macros[attributeName] and kb.macros[attributeName][1] ~= attributeValue) do
Nenue@17 85 print(' * cannot use|cFF00FF00', attributeName, '|r"'.. tostring(kb.macros[attributeName][1]) .. '"')
Nenue@17 86 attributeName = baseName .. '_' .. iterative
Nenue@17 87 iterative = iterative + 1
Nenue@17 88 end
Nenue@17 89 if macroName ~= baseName then
Nenue@17 90 print(' * Creating|cFF00FF00', macroName)
Nenue@17 91 else
Nenue@17 92 print(' * Re-using|cFF00FF00', macroName)
Nenue@17 93 end
Nenue@17 94 kb.macros[attributeName] = {attributeValue, command}
Nenue@17 95
Nenue@17 96
Nenue@17 97 print('RegisterAction', actionType, id, '->', attributeName, attributeValue, target .. attributeName)
Nenue@17 98 return attributeName, attributeValue, command
Nenue@17 99 end
Nenue@17 100
Nenue@17 101
Nenue@17 102
Nenue@17 103
Nenue@17 104 kb.ApplyTalentBinding = function(talentInfo, cache)
Nenue@17 105 for i = 5, #talentInfo do
Nenue@17 106 local command = CLICK_KEYBINDER_KEY.. talentInfo[2]
Nenue@17 107 SetBinding(talentInfo[i], command)
Nenue@17 108 cprint(' **', talentInfo[i], '->', command)
Nenue@17 109 tinsert(cache, talentInfo[i])
Nenue@17 110 end
Nenue@17 111 end
Nenue@17 112 kb.CacheTalentBinding = function(talentInfo, cache)
Nenue@17 113
Nenue@17 114 local spellID = talentInfo[4]
Nenue@19 115 cache[spellID] = cache[spellID] or {}
Nenue@19 116 cache[spellID] = {select(5,unpack(talentInfo)) }
Nenue@19 117 --cprint(spellID, unpack(kb.TalentBindings[spellID]))
Nenue@17 118 end
Nenue@17 119
Nenue@17 120 do
Nenue@17 121 local bindings = kb.bindings
Nenue@17 122 local key, macro = KeyBinderKey, KeyBinderMacro
Nenue@17 123 kb.LoadBinding = function(command, name, icon, actionType, actionID, macroName, macroText )
Nenue@17 124
Nenue@17 125 if actionType == 'spell' then
Nenue@17 126 key:SetAttribute("*type-"..name, actionType)
Nenue@17 127 key:SetAttribute("*"..actionType.."-"..name, name)
Nenue@17 128 elseif actionType == 'item' then
Nenue@17 129 key:SetAttribute("*type-"..name, actionType)
Nenue@17 130 key:SetAttribute("*"..actionType.."-"..name, name)
Nenue@17 131 elseif actionType == 'macro' then
Nenue@17 132 macro:SetAttribute("*macro-"..macroName, actionID)
Nenue@16 133 else
Nenue@17 134 macro:SetAttribute("*macrotext-"..macroName, macroText)
Nenue@16 135 end
Nenue@16 136
Nenue@17 137 cprint('Loading binding', actionType, actionID)
Nenue@17 138 bindings[actionType] = bindings[actionType] or {}
Nenue@17 139 bindings[actionType][actionID] = bindings[actionType][actionID] or {}
Nenue@17 140 bindings[command] = bindings[actionType][actionID]
Nenue@17 141 return bindings[actionType], actionID
Nenue@16 142 end
Nenue@16 143
Nenue@17 144 kb.ApplyBindings = function (profile)
Nenue@17 145 cprint('binding profile', profile)
Nenue@17 146 for slot, data in pairs(profile.buttons) do
Nenue@17 147 kb.LoadBinding(unpack(data))
Nenue@17 148 end
Nenue@17 149
Nenue@17 150 for key, command in pairs(profile.bindings) do
Nenue@17 151
Nenue@17 152 cprint(' *', key, '->', command)
Nenue@17 153
Nenue@17 154 --_G.print('HotKey','loading', key, command)
Nenue@17 155 SetBinding(key, command)
Nenue@17 156 if bindings[command] and not tContains(bindings[command], key) then
Nenue@17 157 tinsert(bindings[command], key)
Nenue@17 158 end
Nenue@17 159 end
Nenue@17 160
Nenue@17 161 for spellName, talentInfo in pairs(profile.talents) do
Nenue@17 162 local dummy = GetSpellInfo(spellName)
Nenue@17 163 local func = kb.CacheTalentBinding
Nenue@19 164 local dest = kb.TalentBindings
Nenue@17 165 if dummy then
Nenue@17 166 cprint('|cFFBBFF00Active:|r', dummy)
Nenue@17 167 local macroName, spellName, actionType, actionID = unpack(talentInfo)
Nenue@17 168 bindings[actionType] = bindings[actionType] or {}
Nenue@17 169 bindings[actionType][actionID] = {}
Nenue@17 170 func = kb.ApplyTalentBinding
Nenue@17 171 dest = kb.bindings[actionType][actionID]
Nenue@17 172 else
Nenue@17 173
Nenue@17 174 cprint('|cFFFF4400Inactive:|r', talentInfo[2])
Nenue@17 175 end
Nenue@17 176 func(talentInfo, dest)
Nenue@17 177 end
Nenue@17 178
Nenue@17 179 end
Nenue@17 180
Nenue@17 181 kb.ApplyAllBindings =function ()
Nenue@19 182 table.wipe(kb.TalentBindings)
Nenue@17 183
Nenue@17 184
Nenue@17 185 -- reflect action key settings
Nenue@17 186 if GetCVarBool("ActionButtonUseKeyDown") then
Nenue@17 187 KeyBinderMacro:RegisterForClicks("AnyDown")
Nenue@17 188 KeyBinderKey:RegisterForClicks("AnyDown")
Nenue@17 189 else
Nenue@17 190 KeyBinderMacro:RegisterForClicks("AnyUp")
Nenue@17 191 KeyBinderKey:RegisterForClicks("AnyUp")
Nenue@17 192 end
Nenue@17 193
Nenue@17 194 for i, profile in ipairs(kb.orderedProfiles) do
Nenue@17 195 kb.ApplyBindings(profile)
Nenue@17 196 end
Nenue@17 197 -- do this after to ensure that profession binds are properly overridden
Nenue@17 198 kb.UpdateProfessionInfo()
Nenue@17 199
Nenue@17 200
Nenue@17 201 SaveBindings(GetCurrentBindingSet())
Nenue@17 202 end
Nenue@19 203 end
Nenue@19 204
Nenue@19 205
Nenue@19 206 local PET_SPECIAL_SUBTEXT = 'Special Ability'
Nenue@19 207 local SECONDARY_PROFESSIONS = {
Nenue@19 208 [5] = 3,
Nenue@19 209 [7] = 4,
Nenue@19 210 [9] = 5,
Nenue@19 211 [10] = 6
Nenue@19 212 }
Nenue@19 213
Nenue@19 214 kb.TalentCache = {}
Nenue@19 215 kb.ProfessionCache = {}
Nenue@19 216 kb.PetCache = {}
Nenue@19 217 kb.specInfo = {}
Nenue@19 218 kb.UpdateSpecInfo = function()
Nenue@19 219 kb.specInfo.id = GetSpecialization()
Nenue@19 220 kb.specInfo.globalID, kb.specInfo.name, kb.specInfo.desc, kb.specInfo.texture = GetSpecializationInfo(kb.specInfo.id)
Nenue@19 221 print('|cFF00FF00current spec:|r', kb.specInfo.id, 'of', GetNumSpecializations())
Nenue@19 222 end
Nenue@19 223
Nenue@19 224 kb.UpdateTalentInfo = function()
Nenue@19 225 if kb.talentsPushed then
Nenue@19 226 return
Nenue@19 227 end
Nenue@19 228 table.wipe(kb.TalentCache)
Nenue@19 229 for row =1, MAX_TALENT_TIERS do
Nenue@19 230 for col = 1, NUM_TALENT_COLUMNS do
Nenue@19 231 local talentID, talentName, icon, selected, available, spellID = GetTalentInfo(row, col, 1)
Nenue@19 232 local talentInfo = kb.TalentCache[spellID] or {}
Nenue@19 233 talentInfo.row = 1
Nenue@19 234 talentInfo.col = col
Nenue@19 235 talentInfo.name = talentName
Nenue@19 236 talentInfo.talentID = talentID
Nenue@19 237 talentInfo.selected = selected
Nenue@19 238 talentInfo.available = available
Nenue@19 239 talentInfo.spellID = spellID
Nenue@19 240 kb.TalentCache[spellID] = talentInfo
Nenue@19 241 kb.TalentCache[talentName] = talentInfo
Nenue@19 242 print('Talent ', row, col, spellID, talentName)
Nenue@19 243 end
Nenue@19 244 end
Nenue@19 245 kb.talentsPushed = true
Nenue@19 246
Nenue@19 247 kb.UpdateDynamicButtons('talent')
Nenue@19 248 end
Nenue@19 249
Nenue@19 250 kb.UpdateProfessionInfo = function()
Nenue@19 251 table.wipe(kb.ProfessionCache)
Nenue@19 252 local profs = {GetProfessions() }
Nenue@19 253 local primaryNum = 0
Nenue@19 254 for i, index in ipairs(profs) do
Nenue@19 255 local profName, texture, rank, maxRank, numSpells, spellOffset = GetProfessionInfo(index)
Nenue@19 256 print(i, index, profName, numSpells, spellOffset)
Nenue@19 257 if not SECONDARY_PROFESSIONS[index] then
Nenue@19 258 primaryNum = primaryNum + 1
Nenue@19 259 end
Nenue@19 260 local profNum = SECONDARY_PROFESSIONS[index] or primaryNum
Nenue@19 261
Nenue@19 262
Nenue@19 263 kb.ProfessionCache[profNum] = kb.ProfessionCache[i] or {}
Nenue@19 264
Nenue@19 265 for j = 1, numSpells do
Nenue@19 266 local spellName, _, icon, _, _, _, spellID = GetSpellInfo(spellOffset+j, BOOKTYPE_PROFESSION)
Nenue@19 267
Nenue@19 268 local profInfo = {
Nenue@19 269 spellName = spellName,
Nenue@19 270 spellID = spellID,
Nenue@19 271 icon = icon,
Nenue@19 272 profOffset = i,
Nenue@19 273 profIndex = index,
Nenue@19 274 spellOffset = (spellOffset+j),
Nenue@19 275 spellNum = j
Nenue@19 276 }
Nenue@19 277 KeyBinderKey:SetAttribute("*type-profession_"..i .. '_' ..j, "spell")
Nenue@19 278 KeyBinderKey:SetAttribute("*spell-profession_"..i .. '_' ..j, spellName)
Nenue@19 279
Nenue@19 280 kb.ProfessionCache[i .. '_' .. j] = profInfo
Nenue@19 281 kb.ProfessionCache[spellName] = profInfo
Nenue@19 282 kb.ProfessionCache[spellID] = profInfo
Nenue@19 283 print(' |cFF0088FF['..i..']|r|cFFFF44BB['..spellOffset+i..']|r', spellName, "profession_"..i .. '_' ..j)
Nenue@19 284 end
Nenue@19 285
Nenue@19 286 end
Nenue@19 287
Nenue@19 288 kb.UpdateDynamicButtons('profession')
Nenue@19 289 end
Nenue@19 290
Nenue@19 291
Nenue@19 292
Nenue@19 293 kb.UpdatePetInfo = function()
Nenue@19 294 kb.PetCache.spell = kb.PetCache.spell or {}
Nenue@19 295 kb.PetCache.spellslot = kb.PetCache.spellslot or {}
Nenue@19 296 kb.PetCache.action = kb.PetCache.action or {}
Nenue@19 297 kb.PetCache.special = kb.PetCache.action or {}
Nenue@19 298 local hasPetSpells, petType = HasPetSpells()
Nenue@19 299 if PetHasSpellbook() then
Nenue@19 300 print('PET SPELLBOOK')
Nenue@19 301 local i = 1
Nenue@19 302 local specialNum = 0
Nenue@19 303 repeat
Nenue@19 304
Nenue@19 305 local spellType, spellID = GetSpellBookItemInfo(i, BOOKTYPE_PET)
Nenue@19 306 local spellName, subText = GetSpellBookItemName(i, BOOKTYPE_PET)
Nenue@19 307 local isPassive = IsPassiveSpell(i, BOOKTYPE_PET)
Nenue@19 308 if not isPassive then
Nenue@19 309 if spellName then
Nenue@19 310 kb.PetCache.spellslot[spellName] = {i, spellName, subText}
Nenue@19 311 print('|cFF00FF88spellslot['..spellName..']|r', '=>', i, subText)
Nenue@19 312
Nenue@19 313 if subText == PET_SPECIAL_SUBTEXT then
Nenue@19 314 specialNum = specialNum + 1
Nenue@19 315 kb.PetCache.special[spellName] = {i, specialNum, spellID, subText }
Nenue@19 316 print('|cFF00FFFFspecial['..spellName..']|r', '=>', i, specialNum, spellID, subText)
Nenue@19 317 KeyBinderMacro:SetAttribute("*macrotext-pet_special_"..specialNum, "/cast "..spellName)
Nenue@19 318 end
Nenue@19 319
Nenue@19 320 if spellID then
Nenue@19 321 kb.PetCache.spell[i] = {spellID, spellName, subText}
Nenue@19 322 print('|cFF0088FFspell['..i..']|r', '=>', spellID, spellName, subText)
Nenue@19 323 end
Nenue@19 324 end
Nenue@19 325
Nenue@19 326
Nenue@19 327 end
Nenue@19 328
Nenue@19 329 i = i + 1
Nenue@19 330 until spellType == nil
Nenue@19 331 else
Nenue@19 332 print('NO PET SPELLBOOK')
Nenue@19 333 table.wipe(kb.PetCache.spell)
Nenue@19 334 table.wipe(kb.PetCache.spellslot)
Nenue@19 335 end
Nenue@19 336
Nenue@19 337 if PetHasActionBar() then
Nenue@19 338 print('PET ACTION BAR')
Nenue@19 339 for i = 1, 10 do
Nenue@19 340
Nenue@19 341
Nenue@19 342 local name, subtext, texture, isToken, isActive = GetPetActionInfo(i)
Nenue@19 343 if name then
Nenue@19 344 kb.PetCache.action[i] = {name, subtext, texture, isToken, isActive }
Nenue@19 345
Nenue@19 346
Nenue@19 347 end
Nenue@19 348 print('|cFFFFFF00action['..i..']|r', name, subtext, texture)
Nenue@19 349 end
Nenue@19 350 else
Nenue@19 351 print('NO PET ACTION BAR')
Nenue@19 352 table.wipe(kb.PetCache.action)
Nenue@19 353 end
Nenue@19 354
Nenue@19 355 kb.UpdateDynamicButtons('petaction')
Nenue@19 356
Nenue@19 357 end
Nenue@19 358
Nenue@19 359 kb.UpdateSystemBinds = function()
Nenue@19 360 table.wipe(kb.SystemBindings)
Nenue@19 361 local n = GetNumBindings()
Nenue@19 362 for i=1, n do
Nenue@19 363 local command, key1, key2 = GetBinding(i)
Nenue@19 364 if key1 then
Nenue@19 365 kb.SystemBindings[key1] = command
Nenue@19 366 end
Nenue@19 367 if key2 then
Nenue@19 368 kb.SystemBindings[key2] = command
Nenue@19 369 end
Nenue@19 370 end
Nenue@19 371 end
Nenue@19 372
Nenue@19 373 kb.UpdateDynamicButtons = function(dynamicType)
Nenue@19 374 for i, button in ipairs(kb.buttons) do
Nenue@19 375 if button.isDynamic == dynamicType then
Nenue@19 376 kb.UpdateSlot(button, true)
Nenue@19 377 end
Nenue@19 378 end
Nenue@16 379 end