/Tukui/modules/unitframes/plugins/oUF_AuraWatch/oUF_AuraWatch.lua

http://github.com/Asphyxia/Tukui · Lua · 330 lines · 194 code · 29 blank · 107 comment · 65 complexity · c3b5caf40925c17c29daa8b93d600007 MD5 · raw file

  1. local T, C, L = unpack(select(2, ...)) -- Import: T - functions, constants, variables; C - config; L - locales
  2. if C.unitframes.enable ~= true or C.unitframes.raidunitdebuffwatch ~= true then return end
  3. local _, ns = ...
  4. local oUF = ns.oUF or oUF
  5. if not oUF then return end
  6. --[[------------------------------------------------------------------------------------------------------
  7. oUF_AuraWatch by Astromech
  8. Please leave comments, suggestions, and bug reports on this addon's WoWInterface page
  9. To setup, create a table named AuraWatch in your unit frame. There are several options
  10. you can specify, as explained below.
  11. icons
  12. Mandatory!
  13. A table of frames to be used as icons. oUF_Aurawatch does not position
  14. these frames, so you must do so yourself. Each icon needs a spellID entry,
  15. which is the spell ID of the aura to watch. Table should be set up
  16. such that values are icon frames, but the keys can be anything.
  17. Note each icon can have several options set as well. See below.
  18. strictMatching
  19. Default: false
  20. If true, AuraWatch will only show an icon if the specific aura
  21. with the specified spell id is on the unit. If false, AuraWatch
  22. will show the icon if any aura with the same name and icon texture
  23. is on the unit. Strict matching can be undesireable because most
  24. ranks of an aura have different spell ids.
  25. missingAlpha
  26. Default 0.75
  27. The alpha value for icons of auras which have faded from the unit.
  28. presentAlpha
  29. Default 1
  30. The alpha value for icons or auras present on the unit.
  31. onlyShowMissing
  32. Default false
  33. If this is true, oUF_AW will hide icons if they are present on the unit.
  34. onlyShowPresent
  35. Default false
  36. If this is true, oUF_AW will hide icons if they have expired from the unit.
  37. hideCooldown
  38. Default false
  39. If this is true, oUF_AW will not create a cooldown frame
  40. hideCount
  41. Default false
  42. If this is true, oUF_AW will not create a count fontstring
  43. fromUnits
  44. Default {["player"] = true, ["pet"] = true, ["vehicle"] = true}
  45. A table of units from which auras can originate. Have the units be the keys
  46. and "true" be the values.
  47. anyUnit
  48. Default false
  49. Set to true for oUF_AW to to show an aura no matter what unit it
  50. originates from. This will override any fromUnits setting.
  51. PostCreateIcon
  52. Default nil
  53. A function to call when an icon is created to modify it, such as adding
  54. a border or repositioning the count fontstring. Leave as nil to ignore.
  55. The arguements are: AuraWatch table, icon, auraSpellID, auraName, unitFrame
  56. Below are options set on a per icon basis. Set these as fields in the icon frames.
  57. The following settings can be overridden from the AuraWatch table on a per-aura basis:
  58. onlyShowMissing
  59. onlyShowPresent
  60. hideCooldown
  61. hideCount
  62. fromUnits
  63. anyUnit
  64. The following settings are unique to icons:
  65. spellID
  66. Mandatory!
  67. The spell id of the aura, as explained above.
  68. icon
  69. Default aura texture
  70. A texture value for this icon.
  71. overlay
  72. Default Blizzard aura overlay
  73. An overlay for the icon. This is not created if a custom icon texture is created.
  74. count
  75. Default A fontstring
  76. An fontstring to show the stack count of an aura.
  77. Here is an example of how to set oUF_AW up:
  78. local createAuraWatch = function(self, unit)
  79. local auras = {}
  80. -- A table of spellIDs to create icons for
  81. -- To find spellIDs, look up a spell on www.wowhead.com and look at the URL
  82. -- http://www.wowhead.com/?spell=SPELL_ID
  83. local spellIDs = { ... }
  84. auras.presentAlpha = 1
  85. auras.missingAlpha = .7
  86. auras.PostCreateIcon = myCustomIconSkinnerFunction
  87. -- Set any other AuraWatch settings
  88. auras.icons = {}
  89. for i, sid in pairs(spellIDs) do
  90. local icon = CreateFrame("Frame", nil, auras)
  91. icon.spellID = sid
  92. -- set the dimensions and positions
  93. icon:SetWidth(24)
  94. icon:SetHeight(24)
  95. icon:SetPoint("BOTTOM", self, "BOTTOM", 0, 28 * i)
  96. auras.icons[sid] = icon
  97. -- Set any other AuraWatch icon settings
  98. end
  99. self.AuraWatch = auras
  100. end
  101. -----------------------------------------------------------------------------------------------------------]]
  102. local _, ns = ...
  103. local oUF = ns.oUF or _G.oUF
  104. assert(oUF, "oUF_AuraWatch cannot find an instance of oUF. If your oUF is embedded into a layout, it may not be embedded properly.")
  105. local UnitBuff, UnitDebuff, UnitGUID = UnitBuff, UnitDebuff, UnitGUID
  106. local GUIDs = {}
  107. local PLAYER_UNITS = {
  108. player = true,
  109. vehicle = true,
  110. pet = true,
  111. }
  112. local setupGUID
  113. do
  114. local cache = setmetatable({}, {__type = "k"})
  115. local frame = CreateFrame"Frame"
  116. frame:SetScript("OnEvent", function(self, event)
  117. for k,t in pairs(GUIDs) do
  118. GUIDs[k] = nil
  119. for a in pairs(t) do
  120. t[a] = nil
  121. end
  122. cache[t] = true
  123. end
  124. end)
  125. frame:RegisterEvent"PLAYER_REGEN_ENABLED"
  126. frame:RegisterEvent"PLAYER_ENTERING_WORLD"
  127. function setupGUID(guid)
  128. local t = next(cache)
  129. if t then
  130. cache[t] = nil
  131. else
  132. t = {}
  133. end
  134. GUIDs[guid] = t
  135. end
  136. end
  137. local function resetIcon(icon, frame, count, duration, remaining)
  138. if icon.onlyShowMissing then
  139. icon:Hide()
  140. else
  141. icon:Show()
  142. if icon.cd then
  143. if duration and duration > 0 then
  144. icon.cd:SetCooldown(remaining - duration, duration)
  145. icon.cd:Show()
  146. else
  147. icon.cd:Hide()
  148. end
  149. end
  150. if icon.count then
  151. icon.count:SetText((count > 1 and count))
  152. end
  153. if icon.overlay then
  154. icon.overlay:Hide()
  155. end
  156. icon:SetAlpha(frame.presentAlpha)
  157. end
  158. end
  159. local function expireIcon(icon, frame)
  160. if icon.onlyShowPresent then
  161. icon:Hide()
  162. else
  163. if (icon.cd) then icon.cd:Hide() end
  164. if (icon.count) then icon.count:SetText() end
  165. icon:SetAlpha(frame.missingAlpha)
  166. if icon.overlay then
  167. icon.overlay:Show()
  168. end
  169. icon:Show()
  170. end
  171. end
  172. local found = {}
  173. local function Update(frame, event, unit)
  174. if frame.unit ~= unit then return end
  175. local watch = frame.AuraWatch
  176. local index, icons = 1, watch.watched
  177. local _, name, texture, count, duration, remaining, caster, key, icon, spellid
  178. local filter = "HELPFUL"
  179. local guid = UnitGUID(unit)
  180. if not guid then return end
  181. if not GUIDs[guid] then setupGUID(guid) end
  182. for key, icon in pairs(icons) do
  183. icon:Hide()
  184. end
  185. while true do
  186. name, _, texture, count, _, duration, remaining, caster, _, _, spellid = UnitAura(unit, index, filter)
  187. if not name then
  188. if filter == "HELPFUL" then
  189. filter = "HARMFUL"
  190. index = 1
  191. else
  192. break
  193. end
  194. else
  195. if watch.strictMatching then
  196. key = spellID
  197. else
  198. key = name..texture
  199. end
  200. icon = icons[key]
  201. if icon and (icon.anyUnit or (caster and icon.fromUnits[caster])) then
  202. resetIcon(icon, watch, count, duration, remaining)
  203. GUIDs[guid][key] = true
  204. found[key] = true
  205. end
  206. index = index + 1
  207. end
  208. end
  209. for key in pairs(GUIDs[guid]) do
  210. if icons[key] and not found[key] then
  211. expireIcon(icons[key], watch)
  212. end
  213. end
  214. for k in pairs(found) do
  215. found[k] = nil
  216. end
  217. end
  218. local function setupIcons(self)
  219. local watch = self.AuraWatch
  220. local icons = watch.icons
  221. watch.watched = {}
  222. if not watch.missingAlpha then watch.missingAlpha = 0.75 end
  223. if not watch.presentAlpha then watch.presentAlpha = 1 end
  224. for _,icon in pairs(icons) do
  225. local name, _, image = GetSpellInfo(icon.spellID)
  226. if not name then error("oUF_AuraWatch error: no spell with "..tostring(icon.spellID).." spell ID exists") end
  227. icon.name = name
  228. if not icon.cd and not (watch.hideCooldown or icon.hideCooldown) then
  229. local cd = CreateFrame("Cooldown", nil, icon)
  230. cd:SetAllPoints(icon)
  231. icon.cd = cd
  232. end
  233. if not icon.icon then
  234. local tex = icon:CreateTexture(nil, "BACKGROUND")
  235. tex:SetAllPoints(icon)
  236. tex:SetTexture(image)
  237. icon.icon = tex
  238. if not icon.overlay then
  239. local overlay = icon:CreateTexture(nil, "OVERLAY")
  240. overlay:SetTexture"Interface\\Buttons\\UI-Debuff-Overlays"
  241. overlay:SetAllPoints(icon)
  242. overlay:SetTexCoord(.296875, .5703125, 0, .515625)
  243. overlay:SetVertexColor(1, 0, 0)
  244. icon.overlay = overlay
  245. end
  246. end
  247. if not icon.count and not (watch.hideCount or icon.hideCount) then
  248. local count = icon:CreateFontString(nil, "OVERLAY")
  249. count:SetFontObject(NumberFontNormal)
  250. count:SetPoint("BOTTOMRIGHT", icon, "BOTTOMRIGHT", -1, 0)
  251. icon.count = count
  252. end
  253. if icon.onlyShowMissing == nil then
  254. icon.onlyShowMissing = watch.onlyShowMissing
  255. end
  256. if icon.onlyShowPresent == nil then
  257. icon.onlyShowPresent = watch.onlyShowPresent
  258. end
  259. if icon.fromUnits == nil then
  260. icon.fromUnits = watch.fromUnits or PLAYER_UNITS
  261. end
  262. if icon.anyUnit == nil then
  263. icon.anyUnit = watch.anyUnit
  264. end
  265. if watch.strictMatching then
  266. watch.watched[icon.spellID] = icon
  267. else
  268. watch.watched[name..image] = icon
  269. end
  270. if watch.PostCreateIcon then watch:PostCreateIcon(icon, icon.spellID, name, self) end
  271. end
  272. end
  273. local function Enable(self)
  274. if self.AuraWatch then
  275. self:RegisterEvent("UNIT_AURA", Update)
  276. setupIcons(self)
  277. return true
  278. else
  279. return false
  280. end
  281. end
  282. local function Disable(self)
  283. if self.AuraWatch then
  284. self:UnregisterEvent("UNIT_AURA", Update)
  285. for _,icon in pairs(self.AuraWatch.icons) do
  286. icon:Hide()
  287. end
  288. end
  289. end
  290. oUF:AddElement("AuraWatch", Update, Enable, Disable)