Mercurial > wow > skeletonkey
view SkeletonKey/ActionTemplates.lua @ 49:9a9d7f2a7c07
- handle mouse input with string.upper
- process input for the whole bindings frame region when a slot is activated
- fix various errors arising from handler inconsistencies
author | Nenue |
---|---|
date | Thu, 18 Aug 2016 01:34:22 -0400 |
parents | daff39af0c6d |
children | 1aba8a6fd4a9 |
line wrap: on
line source
-- SkeletonKey -- ActionTemplates.lua -- Created: 7/29/2016 9:14 PM -- %file-revision% -- Code dealing with the implementation of action hotkeys local tostring, tonumber, pairs, ipairs = tostring, tonumber, pairs, ipairs local unpack, SetBinding = unpack, SetBinding local tinsert, tContains, select, wipe = tinsert, tContains, select, table.wipe local GetSpellBookItemInfo, GetSpellBookItemName, GetSpellInfo = GetSpellBookItemInfo, GetSpellBookItemName, GetSpellInfo local GetSpecialization, GetSpecializationInfo, IsPassiveSpell, IsTalentSpell = GetSpecialization, GetSpecializationInfo, IsPassiveSpell, IsTalentSpell local PetHasSpellbook, PetHasActionBar, GetPetActionInfo, HasPetSpells = PetHasSpellbook, PetHasActionBar, GetPetActionInfo, HasPetSpells local GetProfessions, GetProfessionInfo, GetTalentInfo = GetProfessions, GetProfessionInfo, GetTalentInfo local GetNumBindings, GetBinding = GetNumBindings, GetBinding local kb, print, wrap = LibStub('LibKraken').register(KeyBinder, 'Info') local cprint = (DEVIAN_PNAME == 'SkeletonKey') and function(...) _G.print('Cfg', ...) end or function() end local CLICK_KEYBINDER_MACRO = "CLICK KeyBinderMacro:" local CLICK_KEYBINDER_KEY = "CLICK KeyBinderKey:" local PET_BASIC_SUBTEXT = 'Basic Attack' local PET_SPECIAL_SUBTEXT = 'Special Ability' local PETACTION_SCRIPT = { [PET_ACTION_MOVE_TO] = {'pet_move_to', SLASH_PET_MOVE_TO1}, [PET_ACTION_ATTACK] = {'pet_attack', SLASH_PET_ATTACK1}, [PET_ACTION_FOLLOW] = {'pet_follow', SLASH_PET_FOLLOW1}, [PET_ACTION_WAIT] = {'pet_stay', SLASH_PET_STAY1 }, [PET_MODE_AGGRESSIVE] = {'pet_aggressive', SLASH_PET_AGGRESSIVE1 }, [PET_MODE_DEFENSIVE] = { 'pet_defensive', SLASH_PET_DEFENSIVE1}, [PET_MODE_PASSIVE] = { 'pet_passive', SLASH_PET_PASSIVE1}, [PET_MODE_ASSIST] = {'pet_assist', SLASH_PET_ASSIST1}, } local SECONDARY_PROFESSIONS = { [5] = 3, [7] = 4, [9] = 5, [10] = 6 } local SUMMON_RANDOM_FAVORITE_MOUNT_SPELL = 150544 --kb.ChangedBindings = {} --kb.ActionTypes = {} local atype = kb.ActionTypes --- Caps Lock atype['mount'] = function(id, name) if id == SUMMON_RANDOM_FAVORITE_MOUNT_SPELL then return CLICK_KEYBINDER_MACRO, 'mount_random', "/script C_MountJournal.SummonByID(0)" else return CLICK_KEYBINDER_MACRO, 'mount_'..id, "/script C_MountJournal.SummonByID("..id..")" 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 attributeName, attributeValue = unpack(PETACTION_SCRIPT[name]) elseif kb.PetCache.special[name] then attributeName = "petaction_"..kb.PetCache.special[name][3].."_" .. tonumber(kb.PetCache.special[name][6]) 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 attributeName ~= baseName then print(' * Creating|cFF00FF00', attributeName) else print(' * Re-using|cFF00FF00', attributeName) 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 () 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 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) end kb.UpdateTalentInfo = function() if kb.talentsPushed then return end 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() wipe(kb.ProfessionCache) local profs = {GetProfessions() } print(GetProfessions()) local primaryNum = 0 for i = 1, 6 do if profs[i] then local index = profs[i] local profName, texture, _, _, 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 print(i, profNum) kb.ProfessionCache[profNum] = kb.ProfessionCache[profNum] 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 } kb.SecureAttribute(KeyBinderKey, "*type-profession_"..i .. '_' ..j, "spell") kb.SecureAttribute(KeyBinderKey, "*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 end kb.UpdateDynamicButtons('profession') end kb.UpdatePetInfo = function() local hasPetSpells, petType = HasPetSpells() --kb.PetCache.specNum = GetSpecialization(nil, true) --kb.PetCache.specID, kb.PetCache.specName = GetSpecializationInfo(petSpec, nil, true) if PetHasSpellbook() then print('PET SPELLBOOK') local i = 1 local specialNum = {} repeat local spellType, spellID = GetSpellBookItemInfo(i, BOOKTYPE_PET) local spellName, subText = GetSpellBookItemName(i, BOOKTYPE_PET) local texture = GetSpellBookItemTexture(i, BOOKTYPE_PET) local isPassive = IsPassiveSpell(i, BOOKTYPE_PET) if not isPassive then if spellName then kb.PetCache.spellslot[spellName] = {i, spellName, subText, spellID, texture} print('|cFF00FF88spellslot['..spellName..']|r', '=>', i, subText) if subText then -- make sure that pet specialization subtext maps correctly --if match(subText, kb.PetCache.specName) then -- subText = 'specialization' --end kb.PetCache.subtext[subText] = kb.PetCache.subtext[subText] or {} specialNum[subText] = (specialNum[subText] or 0) + 1 local entry = {i, spellName, subText, spellID, texture, specialNum[subText]} kb.PetCache.special[spellName] = entry kb.PetCache.subtext[subText][specialNum[subText]] = entry kb.SecureAttribute(KeyBinderMacro, "*macrotext-petaction_"..subText.."_"..specialNum[subText], "/cast "..spellName) print('|cFF00FFFFspecial['..spellName..']|r', '\n','|cFF00FFFFsubtext['..subText..']['..specialNum[subText]..']|r', '=>', i, spellName, subText, spellID, texture, specialNum[subText]) 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') wipe(kb.PetCache.spell) 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') wipe(kb.PetCache.action) end kb.UpdateDynamicButtons('petaction') end kb.UpdateSystemBinds = function() wipe(kb.SystemBindings) local n = GetNumBindings() for i=1, n do local command, key1, key2 = GetBinding(i) if not command:match('ACTION.*%d+') then if key1 then kb.SystemBindings[key1] = command end if key2 then kb.SystemBindings[key2] = command end else print('ignoring action button binding', 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 kb.pendingAttributes = {} kb.SecureAttribute = function(target, name, value) if InCombatLockdown() then if #kb.pendingAttributes == 0 then kb:print(kb.L('Key bindings will be applied when you exit combat.')) end tinsert(kb.pendingAttributes, {target, name, value}) kb:RegisterEvent('PLAYER_REGEN_ENABLED') else print(target:GetName(), 'attribute', '"'.. tostring(name)..'" = "'..tostring(value)..'"') target:SetAttribute(name, value) end end kb.PLAYER_REGEN_ENABLED = function() if #kb.pendingAttributes >= 1 then local args = tremove(kb.pendingAttributes) while args do local target, name, value = unpack(args) print(target:GetName(), 'attribute', '"'.. tostring(name)..'" = "'..tostring(value)..'"') target:SetAttribute(name, value) args = tremove(kb.pendingAttributes) end end if #kb.pendingCalls >= 1 then local func = tremove(kb.pendingCalls) while func do func() end end end kb.UpdateBindingsCache = function(actionType, actionID, bindings) kb.bindings[actionType] = kb.bindings[actionType] or {} kb.bindings[actionType][actionID] = bindings print('|cFF00FF00'..actionType..'-'..actionID..'|r = {', table.concat(bindings,', '), '}') tinsert(kb.ChangedBindings, {actionType, actionID}) end