PageRenderTime 21ms CodeModel.GetById 12ms app.highlight 5ms RepoModel.GetById 2ms app.codeStats 0ms

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

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