/Tukui/modules/actionbars/Range.lua

http://github.com/Asphyxia/Tukui · Lua · 322 lines · 245 code · 51 blank · 26 comment · 52 complexity · cd2cb360f66368f6c71a6c7b6a07a07c MD5 · raw file

  1. local T, C, L = unpack(select(2, ...)) -- Import: T - functions, constants, variables; C - config; L - locales
  2. --[[
  3. Thx to Tulla
  4. Adds out of range coloring to action buttons
  5. Derived from RedRange and TullaRange
  6. --]]
  7. if not C["actionbar"].enable == true then return end
  8. --locals and speed
  9. local _G = _G
  10. local UPDATE_DELAY = 0.15
  11. local ATTACK_BUTTON_FLASH_TIME = ATTACK_BUTTON_FLASH_TIME
  12. local SPELL_POWER_HOLY_POWER = SPELL_POWER_HOLY_POWER
  13. local ActionButton_GetPagedID = ActionButton_GetPagedID
  14. local ActionButton_IsFlashing = ActionButton_IsFlashing
  15. local ActionHasRange = ActionHasRange
  16. local IsActionInRange = IsActionInRange
  17. local IsUsableAction = IsUsableAction
  18. local HasAction = HasAction
  19. --code for handling defaults
  20. local function removeDefaults(tbl, defaults)
  21. for k, v in pairs(defaults) do
  22. if type(tbl[k]) == 'table' and type(v) == 'table' then
  23. removeDefaults(tbl[k], v)
  24. if next(tbl[k]) == nil then
  25. tbl[k] = nil
  26. end
  27. elseif tbl[k] == v then
  28. tbl[k] = nil
  29. end
  30. end
  31. return tbl
  32. end
  33. local function copyDefaults(tbl, defaults)
  34. for k, v in pairs(defaults) do
  35. if type(v) == 'table' then
  36. tbl[k] = copyDefaults(tbl[k] or {}, v)
  37. elseif tbl[k] == nil then
  38. tbl[k] = v
  39. end
  40. end
  41. return tbl
  42. end
  43. local function timer_Create(parent, interval)
  44. local updater = parent:CreateAnimationGroup()
  45. updater:SetLooping('NONE')
  46. updater:SetScript('OnFinished', function(self)
  47. if parent:Update() then
  48. parent:Start(interval)
  49. end
  50. end)
  51. local a = updater:CreateAnimation('Animation'); a:SetOrder(1)
  52. parent.Start = function(self)
  53. self:Stop()
  54. a:SetDuration(interval)
  55. updater:Play()
  56. return self
  57. end
  58. parent.Stop = function(self)
  59. if updater:IsPlaying() then
  60. updater:Stop()
  61. end
  62. return self
  63. end
  64. parent.Active = function(self)
  65. return updater:IsPlaying()
  66. end
  67. return parent
  68. end
  69. --stuff for holy power detection
  70. local PLAYER_IS_PALADIN = select(2, UnitClass('player')) == 'PALADIN'
  71. local HAND_OF_LIGHT = GetSpellInfo(90174)
  72. local isHolyPowerAbility
  73. do
  74. local HOLY_POWER_SPELLS = {
  75. [85256] = GetSpellInfo(85256), --Templar's Verdict
  76. [53600] = GetSpellInfo(53600), --Shield of the Righteous
  77. -- [84963] = GetSpellInfo(84963), --Inquisition
  78. -- [85673] = GetSpellInfo(85673), --Word of Glory
  79. -- [85222] = GetSpellInfo(85222), --Light of Dawn
  80. }
  81. isHolyPowerAbility = function(actionId)
  82. local actionType, id = GetActionInfo(actionId)
  83. if actionType == 'macro' then
  84. local macroSpell = GetMacroSpell(id)
  85. if macroSpell then
  86. for spellId, spellName in pairs(HOLY_POWER_SPELLS) do
  87. if macroSpell == spellName then
  88. return true
  89. end
  90. end
  91. end
  92. else
  93. return HOLY_POWER_SPELLS[id]
  94. end
  95. return false
  96. end
  97. end
  98. --[[ The main thing ]]--
  99. local TukuiRange = timer_Create(CreateFrame('Frame', 'TukuiRange'), UPDATE_DELAY)
  100. function TukuiRange:Load()
  101. self:SetScript('OnEvent', self.OnEvent)
  102. self:RegisterEvent('PLAYER_LOGIN')
  103. self:RegisterEvent('PLAYER_LOGOUT')
  104. end
  105. --[[ Frame Events ]]--
  106. function TukuiRange:OnEvent(event, ...)
  107. local action = self[event]
  108. if action then
  109. action(self, event, ...)
  110. end
  111. end
  112. --[[ Game Events ]]--
  113. function TukuiRange:PLAYER_LOGIN()
  114. if not TukuiRange_COLORS then
  115. TukuiRange_COLORS = {}
  116. end
  117. self.colors = copyDefaults(TukuiRange_COLORS, self:GetDefaults())
  118. --add options loader
  119. local f = CreateFrame('Frame', nil, InterfaceOptionsFrame)
  120. f:SetScript('OnShow', function(self)
  121. self:SetScript('OnShow', nil)
  122. LoadAddOn('TukuiRange_Config')
  123. end)
  124. self.buttonsToUpdate = {}
  125. hooksecurefunc('ActionButton_OnUpdate', self.RegisterButton)
  126. hooksecurefunc('ActionButton_UpdateUsable', self.OnUpdateButtonUsable)
  127. hooksecurefunc('ActionButton_Update', self.OnButtonUpdate)
  128. end
  129. function TukuiRange:PLAYER_LOGOUT()
  130. removeDefaults(TukuiRange_COLORS, self:GetDefaults())
  131. end
  132. --[[ Actions ]]--
  133. function TukuiRange:Update()
  134. return self:UpdateButtons(UPDATE_DELAY)
  135. end
  136. function TukuiRange:ForceColorUpdate()
  137. for button in pairs(self.buttonsToUpdate) do
  138. TukuiRange.OnUpdateButtonUsable(button)
  139. end
  140. end
  141. function TukuiRange:UpdateActive()
  142. if next(self.buttonsToUpdate) then
  143. if not self:Active() then
  144. self:Start()
  145. end
  146. else
  147. self:Stop()
  148. end
  149. end
  150. function TukuiRange:UpdateButtons(elapsed)
  151. if next(self.buttonsToUpdate) then
  152. for button in pairs(self.buttonsToUpdate) do
  153. self:UpdateButton(button, elapsed)
  154. end
  155. return true
  156. end
  157. return false
  158. end
  159. function TukuiRange:UpdateButton(button, elapsed)
  160. TukuiRange.UpdateButtonUsable(button)
  161. TukuiRange.UpdateFlash(button, elapsed)
  162. end
  163. function TukuiRange:UpdateButtonStatus(button)
  164. local action = ActionButton_GetPagedID(button)
  165. if button:IsVisible() and action and HasAction(action) and ActionHasRange(action) then
  166. self.buttonsToUpdate[button] = true
  167. else
  168. self.buttonsToUpdate[button] = nil
  169. end
  170. self:UpdateActive()
  171. end
  172. --[[ Button Hooking ]]--
  173. function TukuiRange.RegisterButton(button)
  174. button:HookScript('OnShow', TukuiRange.OnButtonShow)
  175. button:HookScript('OnHide', TukuiRange.OnButtonHide)
  176. button:SetScript('OnUpdate', nil)
  177. TukuiRange:UpdateButtonStatus(button)
  178. end
  179. function TukuiRange.OnButtonShow(button)
  180. TukuiRange:UpdateButtonStatus(button)
  181. end
  182. function TukuiRange.OnButtonHide(button)
  183. TukuiRange:UpdateButtonStatus(button)
  184. end
  185. function TukuiRange.OnUpdateButtonUsable(button)
  186. button.TukuiRangeColor = nil
  187. TukuiRange.UpdateButtonUsable(button)
  188. end
  189. function TukuiRange.OnButtonUpdate(button)
  190. TukuiRange:UpdateButtonStatus(button)
  191. end
  192. --[[ Range Coloring ]]--
  193. function TukuiRange.UpdateButtonUsable(button)
  194. local action = ActionButton_GetPagedID(button)
  195. local isUsable, notEnoughMana = IsUsableAction(action)
  196. --usable
  197. if isUsable then
  198. --but out of range
  199. if IsActionInRange(action) == 0 then
  200. TukuiRange.SetButtonColor(button, 'oor')
  201. --a holy power abilty, and we're less than 3 Holy Power
  202. elseif PLAYER_IS_PALADIN and isHolyPowerAbility(action) and not(UnitPower('player', SPELL_POWER_HOLY_POWER) == 3 or UnitBuff('player', HAND_OF_LIGHT)) then
  203. TukuiRange.SetButtonColor(button, 'ooh')
  204. --in range
  205. else
  206. TukuiRange.SetButtonColor(button, 'normal')
  207. end
  208. --out of mana
  209. elseif notEnoughMana then
  210. TukuiRange.SetButtonColor(button, 'oom')
  211. --unusable
  212. else
  213. button.TukuiRangeColor = 'unusuable'
  214. end
  215. end
  216. function TukuiRange.SetButtonColor(button, colorType)
  217. if button.TukuiRangeColor ~= colorType then
  218. button.TukuiRangeColor = colorType
  219. local r, g, b = TukuiRange:GetColor(colorType)
  220. local icon = _G[button:GetName() .. 'Icon']
  221. icon:SetVertexColor(r, g, b)
  222. local nt = button:GetNormalTexture()
  223. nt:SetVertexColor(r, g, b)
  224. end
  225. end
  226. function TukuiRange.UpdateFlash(button, elapsed)
  227. if ActionButton_IsFlashing(button) then
  228. local flashtime = button.flashtime - elapsed
  229. if flashtime <= 0 then
  230. local overtime = -flashtime
  231. if overtime >= ATTACK_BUTTON_FLASH_TIME then
  232. overtime = 0
  233. end
  234. flashtime = ATTACK_BUTTON_FLASH_TIME - overtime
  235. local flashTexture = _G[button:GetName() .. 'Flash']
  236. if flashTexture:IsShown() then
  237. flashTexture:Hide()
  238. else
  239. flashTexture:Show()
  240. end
  241. end
  242. button.flashtime = flashtime
  243. end
  244. end
  245. --[[ Configuration ]]--
  246. function TukuiRange:GetDefaults()
  247. return {
  248. normal = {1, 1, 1},
  249. oor = {1, 0.1, 0.1},
  250. oom = {0.1, 0.3, 1},
  251. ooh = {0.45, 0.45, 1},
  252. }
  253. end
  254. function TukuiRange:Reset()
  255. TukuiRange_COLORS = {}
  256. self.colors = copyDefaults(TukuiRange_COLORS, self:GetDefaults())
  257. self:ForceColorUpdate()
  258. end
  259. function TukuiRange:SetColor(index, r, g, b)
  260. local color = self.colors[index]
  261. color[1] = r
  262. color[2] = g
  263. color[3] = b
  264. self:ForceColorUpdate()
  265. end
  266. function TukuiRange:GetColor(index)
  267. local color = self.colors[index]
  268. return color[1], color[2], color[3]
  269. end
  270. --[[ Load The Thing ]]--
  271. TukuiRange:Load()