annotate SkeletonKey/KeySlot.lua @ 14:82170735e67c

- move co-routine handler to general lib - slightly better handling of pet actions
author Nenue
date Thu, 28 Jul 2016 23:58:53 -0400
parents
children 32d64e42ec9b
rev   line source
Nenue@14 1 -- SkeletonKey
Nenue@14 2 -- KeySlot.lua
Nenue@14 3 -- Created: 7/28/2016 11:26 PM
Nenue@14 4 -- %file-revision%
Nenue@14 5 -- All the internal slot logic is kept here
Nenue@14 6
Nenue@14 7 local kb, print = LibStub('LibKraken').register(KeyBinder, 'Slot')
Nenue@14 8 local CURSOR_SPELLSLOT, CURSOR_BOOKTYPE, CURSOR_PETACTION
Nenue@14 9 local SUMMON_RANDOM_FAVORITE_MOUNT_SPELL = 150544
Nenue@14 10 local BORDER_UNASSIGNED = {0.2,0.2,0.2,1 }
Nenue@14 11 local BORDER_ASSIGNED = {0.5,0.5,0.5,1 }
Nenue@14 12 local BORDER_DYNAMIC = {1,1,0,1}
Nenue@14 13 local BORDER_PENDING = {1,0.5,0,1 }
Nenue@14 14
Nenue@14 15 local BUTTON_HEADERS = {
Nenue@14 16 ['spell'] = SPELLS,
Nenue@14 17 ['macro'] = MACRO,
Nenue@14 18 ['petaction'] = PET,
Nenue@14 19 ['mount'] = MOUNT,
Nenue@14 20 ['battlepet'] = BATTLEPET,
Nenue@14 21
Nenue@14 22
Nenue@14 23 [5] = PROFESSIONS_FIRST_AID,
Nenue@14 24 [7] = PROFESSIONS_COOKING,
Nenue@14 25 [9] = PROFESSIONS_FISHING,
Nenue@14 26 [10] = PROFESSIONS_ARCHAEOLOGY,
Nenue@14 27
Nenue@14 28 }
Nenue@14 29
Nenue@14 30 -- This is needed to identify a spells that aren't reflected by GetCursorInfo()
Nenue@14 31 hooksecurefunc("PickupSpellBookItem", function(slot, bookType)
Nenue@14 32 print('|cFFFF4400PickupSpellBookItem(..', tostring(slot),', '..tostring(bookType)..')')
Nenue@14 33 CURSOR_SPELLSLOT = slot
Nenue@14 34 CURSOR_BOOKTYPE = bookType
Nenue@14 35 end)
Nenue@14 36
Nenue@14 37 do
Nenue@14 38 -- Pet actions
Nenue@14 39 local isPickup
Nenue@14 40 hooksecurefunc("PickupPetAction", function(slot, ...)
Nenue@14 41 isPickup = GetCursorInfo()
Nenue@14 42
Nenue@14 43 CURSOR_PETACTION = isPickup and slot
Nenue@14 44 print('|cFFFF4400PickupPetAction|r', isPickup, CURSOR_PETACTION)
Nenue@14 45 end)
Nenue@14 46 end
Nenue@14 47
Nenue@14 48
Nenue@14 49 kb.DropToSlot = function(self)
Nenue@14 50 print(self:GetName(),'|cFF0088FFreceived|r')
Nenue@14 51 local actionType, actionID, subType, subData = GetCursorInfo()
Nenue@14 52 print('GetCursorInfo', GetCursorInfo())
Nenue@14 53 if actionType then
Nenue@14 54
Nenue@14 55 if actionType == 'flyout' then
Nenue@14 56 ClearCursor()
Nenue@14 57 ResetCursor()
Nenue@14 58 return
Nenue@14 59 end
Nenue@14 60
Nenue@14 61
Nenue@14 62 local macroName, macroText
Nenue@14 63 local command, name, icon, _
Nenue@14 64 local pickupID, pickupBook
Nenue@14 65
Nenue@14 66 if actionType == 'spell' then
Nenue@14 67 actionID = subData
Nenue@14 68 name, _, icon = GetSpellInfo(actionID)
Nenue@14 69
Nenue@14 70 elseif actionType == 'macro' then
Nenue@14 71 name, icon = GetMacroInfo(actionID)
Nenue@14 72 elseif actionType == 'petaction' then
Nenue@14 73 if not (CURSOR_SPELLSLOT and CURSOR_BOOKTYPE) then
Nenue@14 74
Nenue@14 75 ClearCursor()
Nenue@14 76 ResetCursor()
Nenue@14 77 end
Nenue@14 78
Nenue@14 79 local bookType, spellID = GetSpellBookItemInfo(CURSOR_SPELLSLOT, CURSOR_BOOKTYPE)
Nenue@14 80 actionID = spellID
Nenue@14 81 pickupID = CURSOR_SPELLSLOT
Nenue@14 82 pickupBook = CURSOR_BOOKTYPE
Nenue@14 83 name, _, icon = GetSpellInfo(spellID)
Nenue@14 84 elseif actionType == 'mount' then
Nenue@14 85 if subType == 0 then
Nenue@14 86 name, _, icon = GetSpellInfo(SUMMON_RANDOM_FAVORITE_MOUNT_SPELL)
Nenue@14 87 actionID = 0
Nenue@14 88 else
Nenue@14 89 name, _, icon = C_MountJournal.GetMountInfoByID(actionID)
Nenue@14 90 end
Nenue@14 91 elseif actionType == 'item' then
Nenue@14 92 name = GetItemInfo(actionID)
Nenue@14 93 icon = GetItemIcon(actionID)
Nenue@14 94 actionID = name
Nenue@14 95 elseif actionType == 'battlepet' then
Nenue@14 96
Nenue@14 97 local speciesID, customName, level, xp, maxXp, displayID, isFavorite, petName, petIcon, petType, creatureID = C_PetJournal.GetPetInfoByPetID(detail);
Nenue@14 98 name = customName or petName
Nenue@14 99 icon = petIcon
Nenue@14 100
Nenue@14 101 end
Nenue@14 102 macroName, macroText, command = kb.RegisterAction(actionType, actionID, name)
Nenue@14 103
Nenue@14 104
Nenue@14 105 local isAssigned, isBound, assignedBy, boundBy = kb.IsCommandBound(self, command)
Nenue@14 106 if isAssigned then
Nenue@14 107 local popup = StaticPopupDialogs["SKELETONKEY_CONFIRM_ASSIGN_SLOT"]
Nenue@14 108 popup.slot = self
Nenue@14 109 popup.text = "Currently assigned in |cFFFFFF00"..tostring(kb.configHeaders[assignedBy]).."|r. Are you sure?"
Nenue@14 110 popup.oldProfile = assignedBy
Nenue@14 111 popup.args = {command, name, icon, actionType, actionID, macroName, macroText, pickupID, pickupBook }
Nenue@14 112 kb:SetScript('OnMouseWheel', nil) -- disable scrolling
Nenue@14 113 StaticPopup_Show('SKELETONKEY_CONFIRM_ASSIGN_SLOT')
Nenue@14 114 else
Nenue@14 115 kb.SetSlot(self, command, name, icon, actionType, actionID, macroName, macroText, pickupID, pickupBook)
Nenue@14 116 kb.UpdateSlot(self)
Nenue@14 117 self.active = nil
Nenue@14 118 ClearCursor()
Nenue@14 119 ResetCursor()
Nenue@14 120 end
Nenue@14 121 end
Nenue@14 122 end
Nenue@14 123
Nenue@14 124
Nenue@14 125 do
Nenue@14 126 local PickupAction = {
Nenue@14 127 spell = _G.PickupSpell,
Nenue@14 128 petaction = _G.PickupSpellBookItem,
Nenue@14 129 macro = _G.PickupMacro,
Nenue@14 130 item = _G.PickupItem,
Nenue@14 131 mount = _G.C_MountJournal.Pickup
Nenue@14 132 }
Nenue@14 133 local GetPickupValue = {
Nenue@14 134 spell = function(self) return select(7, GetSpellInfo(self.actionID)) end,
Nenue@14 135 petaction = function(self) return self.pickupSlot, self.pickupBook end,
Nenue@14 136 }
Nenue@14 137 kb.PickupSlot = function(self)
Nenue@14 138 if not self.command then
Nenue@14 139 return
Nenue@14 140 end
Nenue@14 141 print(self.actionType)
Nenue@14 142 if self.actionType == 'spell' then
Nenue@14 143 -- It can't be picked up if SpellInfo(name) returns void
Nenue@14 144 local dummy = GetSpellInfo(self.actionName)
Nenue@14 145 if not dummy then
Nenue@14 146 return
Nenue@14 147 end
Nenue@14 148 end
Nenue@14 149 if PickupAction[self.actionType] then
Nenue@14 150 if GetPickupValue[self.actionType] then
Nenue@14 151 PickupAction[self.actionType](GetPickupValue[self.actionType](self))
Nenue@14 152 else
Nenue@14 153 PickupAction[self.actionType](self.actionID)
Nenue@14 154 end
Nenue@14 155 kb.ReleaseSlot(self)
Nenue@14 156 kb.UpdateSlot(self)
Nenue@14 157 end
Nenue@14 158 end
Nenue@14 159 end
Nenue@14 160
Nenue@14 161
Nenue@14 162
Nenue@14 163 --- Updates profile assignment and button contents
Nenue@14 164 kb.UpdateSlot = function(self, force)
Nenue@14 165 local slot = self:GetID()
Nenue@14 166
Nenue@14 167 if force then
Nenue@14 168 if kb.currentProfile.buttons[slot] then
Nenue@14 169 kb.SetSlot(self, unpack(kb.currentProfile.buttons[slot]))
Nenue@14 170 else
Nenue@14 171 kb.ReleaseSlot(self)
Nenue@14 172 end
Nenue@14 173 end
Nenue@14 174
Nenue@14 175 if self.command then
Nenue@14 176 print('['..slot..'] =', self.command, GetBindingKey(self.command))
Nenue@14 177
Nenue@14 178 if self.pending then
Nenue@14 179 self.border:SetColorTexture(unpack(BORDER_PENDING))
Nenue@14 180 elseif self.isDynamic then
Nenue@14 181 self.border:SetColorTexture(unpack(BORDER_DYNAMIC))
Nenue@14 182 else
Nenue@14 183 self.border:SetColorTexture(unpack(BORDER_ASSIGNED))
Nenue@14 184 end
Nenue@14 185
Nenue@14 186 if self.actionType == 'macro' then
Nenue@14 187 self.macro:Show()
Nenue@14 188 else
Nenue@14 189 self.macro:Hide()
Nenue@14 190 if self.actionType == 'spell' then
Nenue@14 191 local dummy = GetSpellInfo(self.actionName)
Nenue@14 192 if not dummy then
Nenue@14 193 self.icon:SetDesaturated(true)
Nenue@14 194 else
Nenue@14 195 self.icon:SetDesaturated(false)
Nenue@14 196 end
Nenue@14 197
Nenue@14 198 end
Nenue@14 199 end
Nenue@14 200
Nenue@14 201 if self.isDynamic then
Nenue@14 202 print('|cFFFFBB00UpdateSlot|r: ', self.isDynamic, self.isAvailable, self.actionID)
Nenue@14 203 end
Nenue@14 204
Nenue@14 205 if self.isDynamic == 'profession' then
Nenue@14 206 local profText = (self.spellNum == 1) and TRADE_SKILLS or (BUTTON_HEADERS[self.profIndex] or GetProfessionInfo(self.profIndex))
Nenue@14 207 if self.isAvailable then
Nenue@14 208 print(self.profIndex, 'spnum', type(self.spellNum), (self.spellNum == 1))
Nenue@14 209
Nenue@14 210 self.statusText = '|cFFFFFF00'..profText..'|r'
Nenue@14 211 self.bindingText = kb.BindingString(GetBindingKey(self.command))
Nenue@14 212 else
Nenue@14 213 self.statusText = '|cFFFF4400'..profText..'|r'
Nenue@14 214 self.actionName = '(need to train profession #'..self.profNum..')'
Nenue@14 215 self.bindingText ='?'
Nenue@14 216 end
Nenue@14 217 elseif self.isDynamic == 'talent' then
Nenue@14 218
Nenue@14 219 self.statusText = '|cFF00FFFF'.. TALENT .. '|r'
Nenue@14 220 if self.isAvailable then
Nenue@14 221 self.bindingText = kb.BindingString(GetBindingKey(self.command))
Nenue@14 222 else
Nenue@14 223 if kb.inactiveTalentBindings[self.actionID] then
Nenue@14 224 print(self.actionID, #kb.inactiveTalentBindings[self.actionID])
Nenue@14 225 self.bindingText= kb.BindingString(unpack(kb.inactiveTalentBindings[self.actionID]))
Nenue@14 226 end
Nenue@14 227
Nenue@14 228 end
Nenue@14 229 else
Nenue@14 230 self.statusText = '|cFF00FF00'.. (BUTTON_HEADERS[self.actionType] and BUTTON_HEADERS[self.actionType] or self.actionType) .. '|r'
Nenue@14 231 self.bindingText = kb.BindingString(GetBindingKey(self.command))
Nenue@14 232 end
Nenue@14 233
Nenue@14 234 local locked, layer = kb.IsCommandBound(self)
Nenue@14 235 if locked then
Nenue@14 236 self.icon:SetAlpha(0.5)
Nenue@14 237 else
Nenue@14 238 self.icon:SetAlpha(1)
Nenue@14 239 end
Nenue@14 240
Nenue@14 241 if self.actionType == 'spell' then
Nenue@14 242 self.icon:SetTexture(GetSpellTexture(self.actionID))
Nenue@14 243 end
Nenue@14 244 end
Nenue@14 245
Nenue@14 246 if not self.isAvailable then
Nenue@14 247 self.bind:SetTextColor(0.7,0.7,0.7,1)
Nenue@14 248 else
Nenue@14 249 self.bind:SetTextColor(1,1,1,1)
Nenue@14 250 end
Nenue@14 251
Nenue@14 252 self.header:SetText(self.statusText)
Nenue@14 253 self.bind:SetText(self.bindingText)
Nenue@14 254 self.details:SetText(self.actionName)
Nenue@14 255 end
Nenue@14 256
Nenue@14 257 --- Resets button command
Nenue@14 258 kb.ReleaseSlot = function(self)
Nenue@14 259 local slot = self:GetID()
Nenue@14 260
Nenue@14 261
Nenue@14 262 if kb.currentProfile.buttons[slot] then
Nenue@14 263 kb.currentProfile.buttons[slot] = nil
Nenue@14 264 end
Nenue@14 265 if self.command then
Nenue@14 266 kb.currentProfile.commands[self.command] = nil
Nenue@14 267 end
Nenue@14 268 if self.actionType == 'spell' and IsTalentSpell(self.actionName) then
Nenue@14 269 if kb.currentProfile.talents[self.actionID] then
Nenue@14 270 kb.currentProfile.talents[self.actionID] = nil
Nenue@14 271 end
Nenue@14 272 end
Nenue@14 273 local droppedKeys = {}
Nenue@14 274
Nenue@14 275 -- doing removal in second loop to avoid possible iterator shenanigans
Nenue@14 276 for k,v in pairs(kb.currentProfile.bindings) do
Nenue@14 277 if v == self.command then
Nenue@14 278 tinsert(droppedKeys, k)
Nenue@14 279 end
Nenue@14 280 end
Nenue@14 281 if #droppedKeys >=1 then
Nenue@14 282 for i, k in ipairs(droppedKeys) do
Nenue@14 283 kb.currentProfile.bindings[k] = nil
Nenue@14 284 end
Nenue@14 285 end
Nenue@14 286
Nenue@14 287 self.isAvailable = nil
Nenue@14 288 self.isDynamic = nil
Nenue@14 289 self.bindingText = nil
Nenue@14 290 self.statusText = nil
Nenue@14 291 self.command = nil
Nenue@14 292 self.actionType = nil
Nenue@14 293 self.actionID = nil
Nenue@14 294 self.actionName = nil
Nenue@14 295 self.pickupSlot = nil
Nenue@14 296 self.pickupBook = nil
Nenue@14 297 self.macroName = nil
Nenue@14 298 self.profile = nil
Nenue@14 299 self.icon:SetTexture(nil)
Nenue@14 300 self.border:SetColorTexture(unpack(BORDER_UNASSIGNED))
Nenue@14 301 self:EnableKeyboard(false)
Nenue@14 302 self:SetScript('OnKeyDown', nil)
Nenue@14 303 end
Nenue@14 304
Nenue@14 305 kb.SetSlot = function(self, command, name, icon, actionType, actionID, macroName, macroText, pickupSlot, pickupBook)
Nenue@14 306 local slot = self:GetID()
Nenue@14 307 local isDynamic, isAvailable
Nenue@14 308
Nenue@14 309 print('|cFFFFFF00SetSlot|r:', self:GetID())
Nenue@14 310 if command then
Nenue@14 311
Nenue@14 312 if actionType == 'spell' then
Nenue@14 313 local professionNum, spellNum = command:match("profession_(%d)_(%d)")
Nenue@14 314
Nenue@14 315 if (professionNum and spellNum) then
Nenue@14 316 isDynamic = 'profession'
Nenue@14 317 local cacheInfo = kb.ProfessionCache[professionNum..'_'..spellNum]
Nenue@14 318 if cacheInfo then
Nenue@14 319 isAvailable = true
Nenue@14 320 name = cacheInfo.spellName
Nenue@14 321 icon = cacheInfo.icon
Nenue@14 322 actionID = cacheInfo.spellID
Nenue@14 323 self.profIndex = cacheInfo.profIndex
Nenue@14 324 self.spellOffset = cacheInfo.spellOffset
Nenue@14 325 end
Nenue@14 326 print(' Special slot: |cFF00FFFFProfession|r', professionNum, spellNum, isDynamic, isAvailable)
Nenue@14 327
Nenue@14 328 self.professionNum = tonumber(professionNum)
Nenue@14 329 self.spellNum = tonumber(spellNum)
Nenue@14 330
Nenue@14 331 else
Nenue@14 332 if kb.TalentCache[actionID] then
Nenue@14 333 isDynamic = 'talent'
Nenue@14 334 print(' Special slot: |cFFBBFF00talent|r', name, isAvailable)
Nenue@14 335 end
Nenue@14 336
Nenue@14 337 isAvailable = GetSpellInfo(name)
Nenue@14 338 end
Nenue@14 339 elseif actionType == 'macro' then
Nenue@14 340 if not actionID then
Nenue@14 341 actionID = GetMacroIndexByName(name)
Nenue@14 342 end
Nenue@14 343 isAvailable = true
Nenue@14 344 else
Nenue@14 345 --- Journal selections
Nenue@14 346 -- todo: consider using the deep end of blizzard action bar instead
Nenue@14 347 if not actionID then
Nenue@14 348 actionID = command:match("^KeyBinderMacro:(.+)")
Nenue@14 349 end
Nenue@14 350 isAvailable = true
Nenue@14 351 end
Nenue@14 352
Nenue@14 353 if isAvailable then
Nenue@14 354 local oldCommand = command
Nenue@14 355 macroName, macroText, command = kb.RegisterAction(actionType, actionID, name)
Nenue@14 356 if oldCommand ~= command then
Nenue@14 357 print('|cFFFF4400fixing command string', actionType, actionID, name)
Nenue@14 358 kb.currentProfile.bound[oldCommand] = nil
Nenue@14 359 kb.currentProfile.bound[command] = slot
Nenue@14 360 for k,v in pairs(kb.currentProfile.bindings) do
Nenue@14 361 if v == oldCommand then
Nenue@14 362 kb.currentProfile.bindings[k] = command
Nenue@14 363 end
Nenue@14 364 end
Nenue@14 365 end
Nenue@14 366 kb.LoadBinding(command, name, icon, actionType, actionID, macroName, macroText)
Nenue@14 367 end
Nenue@14 368
Nenue@14 369 if actionType == 'petaction' then
Nenue@14 370 self.pickupSlot = pickupSlot
Nenue@14 371 self.pickupBook = pickupBook
Nenue@14 372 else
Nenue@14 373 self.pickupSlot = nil
Nenue@14 374 self.pickupBook = nil
Nenue@14 375 end
Nenue@14 376
Nenue@14 377 actionID = actionID or 0
Nenue@14 378 self:EnableKeyboard(true)
Nenue@14 379 print(' |cFF00FF00kb.currentProfile.buttons['..slot..'] |cFF00FFFF=|r |cFF00FFFF"'.. command.. '"|r |cFF00FF00"'.. name, '"|r |cFFFFFF00icon:'.. icon .. '|r |cFFFF8800"'.. actionType, '"|r |cFFFF0088id:'.. actionID ..'|r |cFF00FF00"'.. macroName .. '"|r')
Nenue@14 380 kb.currentProfile.buttons[slot] = {command, name, icon, actionType, actionID, macroName, macroText, pickupSlot, pickupBook}
Nenue@14 381
Nenue@14 382 -- Clean up conflicting entries for loaded button
Nenue@14 383 local previous = kb.currentProfile.commands[command]
Nenue@14 384 if previous ~= slot and kb.buttons[previous] then
Nenue@14 385 kb.ReleaseSlot(kb.buttons[previous])
Nenue@14 386 end
Nenue@14 387 kb.currentProfile.commands[command] = slot
Nenue@14 388 end
Nenue@14 389
Nenue@14 390 self.isAvailable = isAvailable
Nenue@14 391 self.isDynamic = isDynamic
Nenue@14 392
Nenue@14 393 self.macroText = macroText
Nenue@14 394 self.macroName = macroName
Nenue@14 395 self.actionType = actionType
Nenue@14 396 self.actionID = actionID
Nenue@14 397 self.actionName = name
Nenue@14 398 self.command = command
Nenue@14 399 self.icon:SetTexture(icon)
Nenue@14 400 self.profile = kb.db.bindMode
Nenue@14 401 self:RegisterForDrag('LeftButton')
Nenue@14 402 end
Nenue@14 403
Nenue@14 404
Nenue@14 405
Nenue@14 406 --- Add to blizzard interfaces
Nenue@14 407 StaticPopupDialogs["SKELETONKEY_CONFIRM_ASSIGN_SLOT"] = {
Nenue@14 408 text = "Confirm moving an assigned command.",
Nenue@14 409 button1 = OKAY,
Nenue@14 410 button2 = CANCEL,
Nenue@14 411 timeout = 0,
Nenue@14 412 whileDead = 1,
Nenue@14 413 showAlert = 1,
Nenue@14 414 OnAccept = kb.AcceptAssignment,
Nenue@14 415 OnCancel = function() kb:SetScript('OnMouseWheel', KeyBinder_OnMouseWheel) end
Nenue@14 416 }