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