vanilla-wow-addons – Blame information for rev 1
?pathlinks?
Rev | Author | Line No. | Line |
---|---|---|---|
1 | office | 1 | -------------------------------------------------------- |
2 | -- Ralak's Needy List |
||
3 | -- a UI modification by Ralak of Kel'Thuzad |
||
4 | -- German Localization by Nitram from DE-Azshara |
||
5 | -- French Localization by Olivier Bockstal |
||
6 | -------------------------------------------------------- |
||
7 | NL_CURRENT_VERSION = 2.05; |
||
8 | |||
9 | NL_DEBUG_MODE = false; |
||
10 | |||
11 | NL_MAX_TOOLTIP_BUFFS = 16; |
||
12 | NL_MAX_TOOLTIP_DEBUFFS = 16; |
||
13 | NL_MAX_NEEDS = 12; |
||
14 | NL_BLACK_LIST = {}; |
||
15 | NL_MINIMIZED = false; |
||
16 | NL_SLOTS = {}; |
||
17 | NL_NUM_NEEDY_UNITS = 0; |
||
18 | |||
19 | NL_PLAYERCLASS = ""; |
||
20 | NL_ITERATOR = 1; |
||
21 | |||
22 | NeedyListDetails = { |
||
23 | name = 'Ralak\'s Needy List', |
||
24 | description = 'Monitor needy units in your party or raid group.', |
||
25 | version = NL_CURRENT_VERSION, |
||
26 | releaseDate = 'June 25, 2006', |
||
27 | author = 'Carson Knittig', |
||
28 | email = 'needylist@gmail.com', |
||
29 | category = MYADDONS_CATEGORY_RAID, |
||
30 | frame = 'NLMainFrame', |
||
31 | optionsframe = 'NLConfigFrame' |
||
32 | }; |
||
33 | |||
34 | NL_CLASS_COLORS = {}; |
||
35 | NL_CLASS_COLORS[NL_PRIEST_NAME] = {r = 1.0, g = 1.0, b = 1.0}; |
||
36 | NL_CLASS_COLORS[NL_DRUID_NAME] = {r = 0.0, g = 1.0, b = 0.0}; |
||
37 | NL_CLASS_COLORS[NL_MAGE_NAME] = {r = 0.0, g = 0.0, b = 1.0}; |
||
38 | NL_CLASS_COLORS[NL_PALADIN_NAME] = {r = 1.0, g = 1.0, b = 0.0}; |
||
39 | NL_CLASS_COLORS[NL_WARLOCK_NAME] = {r = 0.5, g = 0.25, b = 0.6}; |
||
40 | NL_CLASS_COLORS[NL_ROGUE_NAME] = {r = 0.5, g = 0.5, b = 0.5}; |
||
41 | NL_CLASS_COLORS[NL_SHAMAN_NAME] = {r = 1.0, g = 1.0, b = 0.0}; |
||
42 | NL_CLASS_COLORS[NL_WARRIOR_NAME] = {r = 1.0, g = 0.0, b = 0.0}; |
||
43 | NL_CLASS_COLORS[NL_BEAST_NAME] = {r = 0.5, g = 0.4, b = 0.25}; |
||
44 | NL_CLASS_COLORS[NL_DEMON_NAME] = {r = 1.0, g = 0.6, b = 0.25}; |
||
45 | NL_CLASS_COLORS["Default"] = {r = 0.25, g = 0.25, b = 0.25}; |
||
46 | |||
47 | NL_WEAKENED_SOUL = "Interface\\Icons\\Spell_Holy_AshesToAshes"; |
||
48 | NL_BANISH = "Interface\\Icons\\Spell_Shadow_Cripple"; |
||
49 | NL_PHASE_SHIFT = "Interface\\Icons\\Spell_Shadow_ImpPhaseShift"; |
||
50 | NL_MINDCONTROL = "Interface\\Icons\\Spell_Shadow_ShadowWordDominate"; |
||
51 | NL_MINDCONTROLCAP = "Interface\\Icons\\Spell_Magic_MageArmor"; |
||
52 | NL_FEIGNDEATH = "Interface\\Icons\\Ability_Rogue_FeignDeath"; |
||
53 | |||
54 | NL_CLICK_INDICES = {LeftButton = 1, RightButton = 2, MiddleButton = 3, Button4 = 4, Button5 = 5}; |
||
55 | |||
56 | NL_ICON_LOCATION = "Interface\\Icons\\"; |
||
57 | |||
58 | NLAnchors = { { |
||
59 | AnchorPoint = "TOPLEFT", |
||
60 | ReferenceAnchorPoint = "BOTTOMLEFT", |
||
61 | Offset = -1, |
||
62 | }, |
||
63 | { |
||
64 | AnchorPoint = "BOTTOMLEFT", |
||
65 | ReferenceAnchorPoint = "TOPLEFT", |
||
66 | Offset = 1, |
||
67 | } |
||
68 | }; |
||
69 | |||
70 | function NL_Msg(msg) |
||
71 | DEFAULT_CHAT_FRAME:AddMessage(msg); |
||
72 | end |
||
73 | |||
74 | function NL_DebugMsg(msg) |
||
75 | if( NL_DEBUG_MODE ) then |
||
76 | DEFAULT_CHAT_FRAME:AddMessage(msg); |
||
77 | end |
||
78 | end |
||
79 | |||
80 | function NL_PrintTable() |
||
81 | local test1, test2, test3, test4 = NLMemberplayer:GetPoint("TOPLEFT"); |
||
82 | table.foreach( test2, NL_Msg ); |
||
83 | NL_Msg( test3 .. test4 ); |
||
84 | end |
||
85 | |||
86 | function NL_OnLoad() |
||
87 | -- Register Events |
||
88 | NLMainFrame:RegisterEvent("UNIT_NAME_UPDATE"); |
||
89 | NLMainFrame:RegisterEvent("PLAYER_ENTERING_WORLD"); |
||
90 | NLMainFrame:RegisterEvent("UNIT_HEALTH"); |
||
91 | NLMainFrame:RegisterEvent("UNIT_MANA"); |
||
92 | NLMainFrame:RegisterEvent("UNIT_RAGE"); |
||
93 | NLMainFrame:RegisterEvent("UNIT_FOCUS"); |
||
94 | NLMainFrame:RegisterEvent("UNIT_ENERGY"); |
||
95 | NLMainFrame:RegisterEvent("UNIT_AURA"); |
||
96 | NLMainFrame:RegisterEvent("PARTY_MEMBERS_CHANGED"); |
||
97 | NLMainFrame:RegisterEvent("RAID_ROSTER_UPDATE"); |
||
98 | NLMainFrame:RegisterEvent("UNIT_PET"); |
||
99 | NLMainFrame:RegisterEvent("VARIABLES_LOADED"); |
||
100 | NLMainFrame:RegisterEvent("PLAYER_TARGET_CHANGED"); |
||
101 | |||
102 | -- Add Slash Commands |
||
103 | SlashCmdList["NLCONFIG"] = NL_Configure; |
||
104 | SLASH_NLCONFIG1 = "/nlconfig"; |
||
105 | |||
106 | -- get this player's class so we know which buffs and debuffs to notify him/her of |
||
107 | NL_PLAYERCLASS = UnitClass("player"); |
||
108 | |||
109 | if( DEFAULT_CHAT_FRAME ) then |
||
110 | DEFAULT_CHAT_FRAME:AddMessage(NL_STR_INTRO_PREFIX..NL_CURRENT_VERSION..NL_STR_INTRO_SUFFIX); |
||
111 | DEFAULT_CHAT_FRAME:AddMessage(NL_STR_INTRO_DESC); |
||
112 | end |
||
113 | |||
114 | -- set the units on each frame so they never have to be set again |
||
115 | NLMemberplayer.Unit = "player"; |
||
116 | NLMemberpet.Unit = "pet"; |
||
117 | NLMembertarget.Unit = "target"; |
||
118 | for NL_ITERATOR=1, 4 do |
||
119 | getglobal("NLMemberparty"..NL_ITERATOR).Unit = "party"..NL_ITERATOR; |
||
120 | getglobal("NLMemberpartypet"..NL_ITERATOR).Unit = "partypet"..NL_ITERATOR; |
||
121 | end |
||
122 | for NL_ITERATOR=1, 40 do |
||
123 | getglobal("NLMemberraid"..NL_ITERATOR).Unit = "raid"..NL_ITERATOR; |
||
124 | getglobal("NLMemberraidpet"..NL_ITERATOR).Unit = "raidpet"..NL_ITERATOR; |
||
125 | end |
||
126 | end |
||
127 | |||
128 | function NL_CheckIfEnabled() |
||
129 | local bRaid = GetNumRaidMembers() > 0; |
||
130 | local bParty = UnitExists("party1") and not bRaid; |
||
131 | local bSolo = not ( bParty or bRaid ); |
||
132 | |||
133 | if( ( bRaid and NLConfig.UseInRaid == 1 ) or ( bParty and NLConfig.UseInParty == 1 ) or ( bSolo and NLConfig.UseWhenSolo == 1 ) ) then |
||
134 | NL_Enable(); |
||
135 | else |
||
136 | NL_Disable(); |
||
137 | end |
||
138 | end |
||
139 | |||
140 | function NL_Disable() |
||
141 | NL_ENABLED = false; |
||
142 | |||
143 | NLHeader:Hide(); |
||
144 | |||
145 | getglobal("NLMemberplayer"):Hide(); |
||
146 | getglobal("NLMemberpet"):Hide(); |
||
147 | for NL_ITERATOR=1, 4 do |
||
148 | getglobal("NLMemberparty"..NL_ITERATOR):Hide(); |
||
149 | getglobal("NLMemberpartypet"..NL_ITERATOR):Hide(); |
||
150 | end |
||
151 | for NL_ITERATOR=1, 40 do |
||
152 | getglobal("NLMemberraid"..NL_ITERATOR):Hide(); |
||
153 | getglobal("NLMemberraidpet"..NL_ITERATOR):Hide(); |
||
154 | end |
||
155 | end |
||
156 | |||
157 | function NL_Enable() |
||
158 | NL_ENABLED = true; |
||
159 | |||
160 | NLHeader:Show(); |
||
161 | |||
162 | NLMember_CheckAllUnits(); |
||
163 | end |
||
164 | |||
165 | function NL_Configure() |
||
166 | NLConfigFrame:Show(); |
||
167 | end |
||
168 | |||
169 | function NL_OnEvent(event, arg1) |
||
170 | |||
171 | --Player loaded completely |
||
172 | if ( event == "UNIT_NAME_UPDATE" and arg1 == "player" ) or (event=="PLAYER_ENTERING_WORLD") then |
||
173 | -- get the configs for this player |
||
174 | NLConfig = NL_GetConfigForCurrentPlayer( false ); |
||
175 | |||
176 | NL_CheckIfEnabled(); |
||
177 | if( not NL_ENABLED ) then |
||
178 | return; |
||
179 | end |
||
180 | |||
181 | NLHeader:Show(); |
||
182 | |||
183 | NLMember_CheckAllUnits(); |
||
184 | |||
185 | return; |
||
186 | end |
||
187 | |||
188 | if( NLConfig == nil ) then |
||
189 | return; |
||
190 | end |
||
191 | |||
192 | -- this check is only for enabling the needy list based on party status |
||
193 | if( event == "PARTY_MEMBERS_CHANGED" or event == "RAID_ROSTER_UPDATE" ) then |
||
194 | NL_CheckIfEnabled(); |
||
195 | end |
||
196 | |||
197 | if( not NL_ENABLED ) then |
||
198 | return; |
||
199 | end |
||
200 | |||
201 | if( event == "PLAYER_TARGET_CHANGED" ) then |
||
202 | NL_CheckTarget(); |
||
203 | return; |
||
204 | end |
||
205 | |||
206 | -- if this is a stat or buff change on a unit |
||
207 | if ( event == "UNIT_HEALTH" or event == "UNIT_MANA" or event == "UNIT_RAGE" or event == "UNIT_FOCUS" or event == "UNIT_ENERGY" or event == "UNIT_AURA" ) then |
||
208 | -- if the unit is blacklisted or never shown, just return |
||
209 | if( arg1 ~= "target" ) then |
||
210 | for NL_ITERATOR = 1, table.getn(NL_BLACK_LIST) do |
||
211 | if( NL_BLACK_LIST[NL_ITERATOR].Unit == arg1 ) then |
||
212 | return; |
||
213 | end |
||
214 | end |
||
215 | end |
||
216 | |||
217 | -- if I'm in a raid group, only use units with raid in their name |
||
218 | local criteria; |
||
219 | if( GetNumRaidMembers() > 0 ) then |
||
220 | criteria = string.find( arg1, "raid" ) ~= nil; |
||
221 | elseif( GetNumPartyMembers() > 0 ) then |
||
222 | criteria = string.find( arg1, "party" ) ~= nil or arg1 == "player" or arg1 == "pet"; |
||
223 | else |
||
224 | criteria = arg1 == "player" or arg1 == "pet"; |
||
225 | end |
||
226 | |||
227 | -- if this player is in the raid or party, or is the default player |
||
228 | if( criteria or (arg1 == "target" and UnitIsFriend("target", "player") and NLConfig.ShowTargetFrame == 1)) then |
||
229 | if( getglobal("NLMember"..arg1).TopNeed and getglobal("NLMember"..arg1).TopNeed == 0 ) then |
||
230 | return; |
||
231 | end |
||
232 | |||
233 | if( not NL_CheckForResurrectionNeed( arg1 ) ) then |
||
234 | if( NLConfig.ResurrectionNeedIndex ) then |
||
235 | if( getglobal("NLMember"..arg1).Needs[NLConfig.ResurrectionNeedIndex] ) then |
||
236 | getglobal("NLMember"..arg1).Needs[NLConfig.ResurrectionNeedIndex] = false; |
||
237 | NL_CheckAllNeeds(arg1); |
||
238 | return; |
||
239 | end |
||
240 | end |
||
241 | |||
242 | if( event == "UNIT_HEALTH" ) then |
||
243 | if( NL_CheckHealth( arg1 ) ) then |
||
244 | NL_AddToList( arg1 ); |
||
245 | else |
||
246 | NL_RemoveFromList( arg1 ); |
||
247 | end |
||
248 | elseif( event == "UNIT_AURA" ) then |
||
249 | if( NL_CheckAura( arg1 ) ) then |
||
250 | NL_AddToList( arg1 ); |
||
251 | if( getglobal("NLMember"..arg1):IsShown() ) then |
||
252 | NL_UpdateAura( arg1 ); |
||
253 | end |
||
254 | else |
||
255 | NL_RemoveFromList( arg1 ); |
||
256 | end |
||
257 | else |
||
258 | if( NL_CheckMana( arg1 ) ) then |
||
259 | NL_AddToList( arg1 ); |
||
260 | else |
||
261 | NL_RemoveFromList( arg1 ); |
||
262 | end |
||
263 | end |
||
264 | if( getglobal("NLMember"..arg1):IsShown() ) then |
||
265 | NL_UpdateUnit( arg1 ); |
||
266 | end |
||
267 | end |
||
268 | end |
||
269 | |||
270 | return; |
||
271 | end |
||
272 | |||
273 | if( event == "UNIT_PET" ) then |
||
274 | local criteria; |
||
275 | local prefix; |
||
276 | local suffix; |
||
277 | if( GetNumRaidMembers() > 0 ) then |
||
278 | criteria = string.find( arg1, "raid" ) ~= nil; |
||
279 | prefix = "raid"; |
||
280 | suffix = string.sub( arg1, 5 ); |
||
281 | else |
||
282 | -- the reason we only check the player here is because in a raid, the player is treated as a raid member as well as the player |
||
283 | -- no sense updating twice! |
||
284 | if( arg1 == "player" ) then |
||
285 | NL_CheckAllNeeds( "pet" ); |
||
286 | return; |
||
287 | else |
||
288 | criteria = string.find( arg1, "party" ) ~= nil; |
||
289 | prefix = "party"; |
||
290 | suffix = string.sub( arg1, 6 ); |
||
291 | end |
||
292 | end |
||
293 | |||
294 | -- if we're in a raid, check raid members |
||
295 | -- if not, check party members, or do nothing if we already found the player |
||
296 | if( criteria ) then |
||
297 | local petUnit = prefix .. "pet" .. suffix; |
||
298 | NL_DebugMsg( "pet event for "..petUnit .. " was caught"); |
||
299 | NL_CheckAllNeeds( petUnit ); |
||
300 | end |
||
301 | return; |
||
302 | end |
||
303 | |||
304 | if( event == "PARTY_MEMBERS_CHANGED" or event == "RAID_ROSTER_UPDATE" ) then |
||
305 | NLMember_CheckAllUnits(); |
||
306 | return; |
||
307 | end |
||
308 | |||
309 | if( event == "VARIABLES_LOADED" ) then |
||
310 | -- Register the addon in myAddOns |
||
311 | if(myAddOnsFrame_Register) then |
||
312 | myAddOnsFrame_Register(NeedyListDetails); |
||
313 | end |
||
314 | |||
315 | return; |
||
316 | end |
||
317 | end |
||
318 | |||
319 | function NL_UnitPassesFilter( unit, filter ) |
||
320 | if( filter == nil or filter.Type == "Everyone" ) then |
||
321 | return true; |
||
322 | end |
||
323 | |||
324 | if( filter.Type == "Units" ) then |
||
325 | if( string.find( filter.Names, UnitName( unit ) ) ) then |
||
326 | local foundName = string.sub( filter.Names, string.find( filter.Names, UnitName( unit ) ) ); |
||
327 | if( string.find( foundName, "," ) ) then |
||
328 | foundName = string.sub( foundName, string.find( foundName, "," ) - 1 ); |
||
329 | end |
||
330 | if( foundName == UnitName( unit ) ) then |
||
331 | return true; |
||
332 | end |
||
333 | end |
||
334 | end |
||
335 | |||
336 | -- if the filter is by party, use the unit name to determine which party and check if that party is being monitored |
||
337 | -- party filter is only valid in raids, so if you're not in a raid, pretend filter is everyone |
||
338 | if( filter.Type == "Multi" ) then |
||
339 | local bPassedPartyCheck = false; |
||
340 | if( unit == "target" ) then |
||
341 | bPassedPartyCheck = true; |
||
342 | else |
||
343 | if( ( UnitInParty(unit) or string.find( unit, "partypet" ) or unit == "pet" ) and filter.Names["My Party"] ) then |
||
344 | bPassedPartyCheck = true; |
||
345 | elseif( string.find( unit, "raid" ) ~= nil ) then |
||
346 | local raidIndex; |
||
347 | if( string.find( unit, "raidpet" ) ~= nil ) then |
||
348 | raidIndex = string.sub( unit, 8 ); |
||
349 | else |
||
350 | raidIndex = string.sub( unit, 5 ); |
||
351 | end |
||
352 | |||
353 | local name, rank, subgroup = GetRaidRosterInfo(raidIndex); |
||
354 | |||
355 | if( filter.Names["Party " .. subgroup] ) then |
||
356 | bPassedPartyCheck = true; |
||
357 | end |
||
358 | end |
||
359 | end |
||
360 | |||
361 | if( bPassedPartyCheck ) then |
||
362 | if( string.find( unit, "pet" ) ~= nil ) then |
||
363 | if( filter.Names[UnitCreatureType( unit )] ) then |
||
364 | return true; |
||
365 | end |
||
366 | else |
||
367 | if( filter.Names[UnitClass( unit )] ) then |
||
368 | return true; |
||
369 | end |
||
370 | end |
||
371 | end |
||
372 | end |
||
373 | |||
374 | return false; |
||
375 | end |
||
376 | |||
377 | function NL_ClearNeedDetails(member) |
||
378 | -- clear the need buttons in the needdetails frame |
||
379 | local frameName = "NLMember" .. member; |
||
380 | for NL_ITERATOR=1, NL_MAX_NEEDS do |
||
381 | getglobal(frameName .. "NeedsDetailsNeed" .. NL_ITERATOR):Hide(); |
||
382 | end |
||
383 | getglobal(frameName .. "NeedsDetails"):Hide(); |
||
384 | end |
||
385 | |||
386 | function NL_GetUnitBuffsAndDebuffs( member ) |
||
387 | local buffList = {}; |
||
388 | local debuffList = {}; |
||
389 | local debuffTypeList = {}; |
||
390 | |||
391 | NL_ITERATOR = 1; |
||
392 | local buff = UnitBuff(member, NL_ITERATOR); |
||
393 | while( buff ~= nil ) do |
||
394 | buffList[buff] = true; |
||
395 | NL_ITERATOR = NL_ITERATOR + 1; |
||
396 | buff = UnitBuff(member, NL_ITERATOR); |
||
397 | end |
||
398 | |||
399 | NL_ITERATOR = 1; |
||
400 | local debuff = UnitDebuff(member, NL_ITERATOR); |
||
401 | |||
402 | while( debuff ~= nil ) do |
||
403 | -- do not add the ignored debuffs to the debuff lists |
||
404 | if( debuff ~= NL_ICON_LOCATION.."Spell_Holy_MindVision" ) then |
||
405 | debuffList[debuff] = true; |
||
406 | |||
407 | NL_BuffTooltipTextRight1:SetText(nil); |
||
408 | NL_BuffTooltip:SetUnitDebuff( member, NL_ITERATOR ); |
||
409 | local debuffType = NL_BuffTooltipTextRight1:GetText(); |
||
410 | |||
411 | if( debuffType ) then |
||
412 | debuffTypeList[debuffType] = true; |
||
413 | end |
||
414 | end |
||
415 | |||
416 | NL_ITERATOR = NL_ITERATOR + 1; |
||
417 | debuff = UnitDebuff(member, NL_ITERATOR); |
||
418 | end |
||
419 | |||
420 | if( string.find( member, "pet" ) and ((buffList and buffList[NL_PHASE_SHIFT]) or (debuffList and debuffList[NL_BANISH] )) ) then |
||
421 | NL_RemoveFromList( member ); |
||
422 | return nil; |
||
423 | end |
||
424 | if( debuffList and (debuffList[NL_MINDCONTROL] or debuffList[NL_MINDCONTROLCAP]) and UnitIsFriend("player", member) ) then |
||
425 | NL_RemoveFromList( member ); |
||
426 | return nil; |
||
427 | end |
||
428 | |||
429 | return buffList, debuffList, debuffTypeList; |
||
430 | end |
||
431 | |||
432 | function NL_CheckAura( member ) |
||
433 | local buffList, debuffList, debuffTypeList = NL_GetUnitBuffsAndDebuffs( member ); |
||
434 | |||
435 | if( buffList == nil ) then |
||
436 | return false; |
||
437 | end |
||
438 | |||
439 | local foundNewTopNeed = false; |
||
440 | |||
441 | local unitFrame = getglobal("NLMember"..member); |
||
442 | |||
443 | -- 0 and 1 are never show and sticky, so don't need to go thru them here |
||
444 | for NL_ITERATOR = 2, NLConfig.NumNeeds - 1 do |
||
445 | local CurrentNeed = NLConfig.Needs[NL_ITERATOR]; |
||
446 | if( CurrentNeed.Toggle == 1 and NL_UnitPassesFilter( member, CurrentNeed.Filter ) ) then |
||
447 | local FoundNeed = false; |
||
448 | if( CurrentNeed.Name == "WellFed" ) then |
||
449 | if( not buffList[NL_ICON_LOCATION .. NL_OTHER.WellFed.Icon] ) then |
||
450 | FoundNeed = true; |
||
451 | end |
||
452 | elseif( CurrentNeed.Type == "BUFF" and debuffList ) then |
||
453 | if( not NL_FindInBuffList( CurrentNeed.Name, buffList ) ) then |
||
454 | -- if the buff is power word shield, need to look for the weakened soul debuff before finding need |
||
455 | if( CurrentNeed.Name == "PWShield" ) then |
||
456 | if( not debuffList[NL_WEAKENED_SOUL] ) then |
||
457 | FoundNeed = true; |
||
458 | end |
||
459 | else |
||
460 | -- didn't find buff on unit, need it |
||
461 | FoundNeed = true; |
||
462 | end |
||
463 | end |
||
464 | elseif( CurrentNeed.Type == "ENCHANT" ) then |
||
465 | local hasMainHandEnchant, mainHandExpiration, mainHandCharges, |
||
466 | hasOffHandEnchant, offHandExpiration, offHandCharges = GetWeaponEnchantInfo() |
||
467 | if( NL_PLAYERCLASS == NL_SHAMAN_NAME ) then |
||
468 | if( hasMainHandEnchant ~= 1 ) then |
||
469 | FoundNeed = true; |
||
470 | end |
||
471 | elseif( NL_PLAYERCLASS == NL_ROGUE_NAME ) then |
||
472 | if( ( CurrentNeed.Name == "MainhandPoison" and hasMainHandEnchant ~= 1 ) or |
||
473 | ( CurrentNeed.Name == "OffhandPoison" and hasOffHandEnchant ~= 1 ) ) then |
||
474 | FoundNeed = true; |
||
475 | end |
||
476 | end |
||
477 | elseif( CurrentNeed.Type == "DEBUFF" and debuffTypeList ) then |
||
478 | if( debuffTypeList[CurrentNeed.Name] ) then |
||
479 | -- found debuff on unit, this is the highest priority need |
||
480 | FoundNeed = true; |
||
481 | end |
||
482 | end |
||
483 | |||
484 | if( FoundNeed ) then |
||
485 | unitFrame.Needs[NL_ITERATOR] = true; |
||
486 | if( not foundNewTopNeed ) then |
||
487 | NL_SetNewTopNeed( unitFrame, NL_ITERATOR ); |
||
488 | foundNewTopNeed = true; |
||
489 | end |
||
490 | elseif( NL_ITERATOR ~= NLConfig.HealthNeedIndex and NL_ITERATOR ~= NLConfig.ManaNeedIndex and NL_ITERATOR ~= NLConfig.ResurrectionNeedIndex ) then |
||
491 | unitFrame.Needs[NL_ITERATOR] = false; |
||
492 | if( unitFrame.TopNeed == NL_ITERATOR ) then |
||
493 | NL_SetNewTopNeed( unitFrame, NL_ITERATOR ); |
||
494 | end |
||
495 | end |
||
496 | end |
||
497 | end |
||
498 | |||
499 | if( unitFrame.TopNeed and unitFrame.TopNeed > 0 ) then |
||
500 | return true; |
||
501 | end |
||
502 | |||
503 | return false; |
||
504 | end |
||
505 | |||
506 | function NL_CheckHealth( member ) |
||
507 | if( not NL_GetUnitBuffsAndDebuffs( member ) ) then |
||
508 | return false; |
||
509 | end |
||
510 | |||
511 | local unitFrame = getglobal("NLMember"..member); |
||
512 | unitFrame.CurrentHealth = UnitHealth( member ) / UnitHealthMax( member ) * 100; |
||
513 | |||
514 | if( not NLConfig.HealthNeedIndex ) then |
||
515 | if( unitFrame.TopNeed and unitFrame.TopNeed > 0 ) then |
||
516 | return true; |
||
517 | end |
||
518 | return false; |
||
519 | end |
||
520 | |||
521 | local HealthNeed = NLConfig.Needs[NLConfig.HealthNeedIndex]; |
||
522 | if( HealthNeed.Toggle == 1 and NL_UnitPassesFilter( member, HealthNeed.Filter ) ) then |
||
523 | if(unitFrame.CurrentHealth < HealthNeed.Threshold or |
||
524 | (unitFrame.CurrentHealth < min(HealthNeed.Threshold + 5,99) and unitFrame.SlotIndex and |
||
525 | unitFrame.TopNeed == NLConfig.HealthNeedIndex ) ) then |
||
526 | -- needs health |
||
527 | unitFrame.Needs[NLConfig.HealthNeedIndex] = true; |
||
528 | else |
||
529 | unitFrame.Needs[NLConfig.HealthNeedIndex] = false; |
||
530 | end |
||
531 | else |
||
532 | unitFrame.Needs[NLConfig.HealthNeedIndex] = false; |
||
533 | end |
||
534 | |||
535 | return NL_SetNewTopNeed( unitFrame, NLConfig.HealthNeedIndex ); |
||
536 | end |
||
537 | |||
538 | function NL_CheckMana( member ) |
||
539 | if( not NL_GetUnitBuffsAndDebuffs( member ) ) then |
||
540 | return false; |
||
541 | end |
||
542 | |||
543 | local unitFrame = getglobal("NLMember"..member); |
||
544 | unitFrame.CurrentMana = UnitMana( member ) / UnitManaMax( member ) * 100; |
||
545 | |||
546 | if( not NLConfig.ManaNeedIndex ) then |
||
547 | if( unitFrame.TopNeed and unitFrame.TopNeed > 0 ) then |
||
548 | return true; |
||
549 | end |
||
550 | return false; |
||
551 | end |
||
552 | |||
553 | local ManaNeed = NLConfig.Needs[NLConfig.ManaNeedIndex]; |
||
554 | if( ManaNeed.Toggle == 1 and NL_UnitPassesFilter( member, ManaNeed.Filter ) ) then |
||
555 | if( UnitPowerType(member) == 0 and (unitFrame.CurrentMana < ManaNeed.Threshold or |
||
556 | (unitFrame.CurrentMana < min(ManaNeed.Threshold + 5,99) and unitFrame:IsShown() and |
||
557 | NLConfig.ManaNeedIndex and unitFrame.TopNeed == NLConfig.ManaNeedIndex ) ) ) then |
||
558 | -- needs mana |
||
559 | unitFrame.Needs[NLConfig.ManaNeedIndex] = true; |
||
560 | else |
||
561 | unitFrame.Needs[NLConfig.ManaNeedIndex] = false; |
||
562 | end |
||
563 | else |
||
564 | unitFrame.Needs[NLConfig.ManaNeedIndex] = false; |
||
565 | end |
||
566 | |||
567 | return NL_SetNewTopNeed( unitFrame, NLConfig.ManaNeedIndex ); |
||
568 | end |
||
569 | |||
570 | function NL_SetNewTopNeed( unitFrame, index ) |
||
571 | if( unitFrame.Needs[index] == true and (not unitFrame.TopNeed or unitFrame.TopNeed > index) ) then |
||
572 | unitFrame.TopNeed = index; |
||
573 | elseif( unitFrame.Needs[index] == false and unitFrame.TopNeed == index ) then |
||
574 | -- the next need is the new top need because health is no longer a need |
||
575 | -- find the first true need in the unit's needs |
||
576 | for NL_ITERATOR = 1, NLConfig.NumNeeds - 1 do |
||
577 | if( unitFrame.Needs[NL_ITERATOR] ) then |
||
578 | unitFrame.TopNeed = NL_ITERATOR; |
||
579 | return true; |
||
580 | end |
||
581 | end |
||
582 | |||
583 | -- if we got here, there is no longer a top need, so this unit can be removed |
||
584 | unitFrame.TopNeed = nil; |
||
585 | return false; |
||
586 | end |
||
587 | |||
588 | return true; |
||
589 | end |
||
590 | |||
591 | function NL_CheckAllNeeds( member ) |
||
592 | -- first, make sure the unit exists |
||
593 | if( not UnitExists( member ) or UnitName( member ) == "" or UnitName( member ) == nil or not UnitIsConnected( member ) ) then |
||
594 | NL_RemoveFromList( member ); |
||
595 | return; |
||
596 | end |
||
597 | |||
598 | -- check if never show |
||
599 | if( NLConfig.Needs[0].Toggle == 1 and NL_UnitPassesFilter( getglobal("NLMember"..member).Unit, NLConfig.Needs[0].Filter ) ) then |
||
600 | getglobal("NLMember"..member).TopNeed = 0; |
||
601 | return; |
||
602 | end |
||
603 | |||
604 | -- check if stickied |
||
605 | if( NLConfig.Needs[1].Toggle == 1 and NL_UnitPassesFilter( getglobal("NLMember"..member).Unit, NLConfig.Needs[1].Filter ) ) then |
||
606 | getglobal("NLMember"..member).TopNeed = 1; |
||
607 | getglobal("NLMember"..member).Needs[1] = true; |
||
608 | end |
||
609 | |||
610 | if( NL_CheckForResurrectionNeed( member ) ) then |
||
611 | return; |
||
612 | end |
||
613 | |||
614 | -- make sure to set the resurrection need to false if we got here |
||
615 | if( NLConfig.ResurrectionNeedIndex ) then |
||
616 | if( getglobal("NLMember"..member).TopNeed == NLConfig.ResurrectionNeedIndex ) then |
||
617 | getglobal("NLMember"..member).TopNeed = nil; |
||
618 | end |
||
619 | getglobal("NLMember"..member).Needs[NLConfig.ResurrectionNeedIndex] = false; |
||
620 | end |
||
621 | |||
622 | NL_CheckHealth( member ); |
||
623 | NL_CheckMana( member ); |
||
624 | NL_CheckAura( member ); |
||
625 | if( getglobal("NLMember"..member).TopNeed and getglobal("NLMember"..member).TopNeed > 0 ) then |
||
626 | NL_AddToList( member ); |
||
627 | else |
||
628 | NL_RemoveFromList( member ); |
||
629 | end |
||
630 | end |
||
631 | |||
632 | function NL_CheckForResurrectionNeed( member ) |
||
633 | -- if the unit is dead or a ghost, they either have |
||
634 | if( UnitIsDead(member) or UnitIsGhost(member) or UnitHealth(member) <= 0 ) then |
||
635 | if( UnitClass(member) == "Hunter" ) then |
||
636 | local buffList = NL_GetUnitBuffsAndDebuffs( member ); |
||
637 | |||
638 | if( buffList and buffList[NL_FEIGNDEATH] ) then |
||
639 | return false; |
||
640 | end |
||
641 | end |
||
642 | -- if unit is the player, then do not monitor resurrection need, because a) can't rez yourself b) it's obvious when you need a rez |
||
643 | if( NLConfig.ResurrectionNeedIndex and NLConfig.Needs[NLConfig.ResurrectionNeedIndex].Toggle == 1 ) then |
||
644 | if( not UnitIsUnit( member, "player" ) ) then |
||
645 | if( getglobal("NLMember"..member).TopNeed ~= 1 ) then |
||
646 | getglobal("NLMember"..member).TopNeed = NLConfig.ResurrectionNeedIndex; |
||
647 | end |
||
648 | getglobal("NLMember"..member).Needs[NLConfig.ResurrectionNeedIndex] = true; |
||
649 | NL_AddToList( member ); |
||
650 | if( getglobal("NLMember"..member):IsShown() ) then |
||
651 | NL_UpdateAura( member ); |
||
652 | NL_UpdateUnit( member ); |
||
653 | end |
||
654 | return true; |
||
655 | end |
||
656 | end |
||
657 | if( getglobal("NLMember"..member).TopNeed ~= 1 ) then |
||
658 | NL_RemoveFromList( member ); |
||
659 | end |
||
660 | return true; |
||
661 | end |
||
662 | |||
663 | return false; |
||
664 | end |
||
665 | |||
666 | function NL_GetMaxRankPlayerCanCast( spellName ) |
||
667 | NL_ITERATOR = 1; |
||
668 | local foundSpellName, foundSpellRank; |
||
669 | local highestMatch = nil; |
||
670 | |||
671 | repeat |
||
672 | foundSpellName, foundSpellRank = GetSpellName(NL_ITERATOR, BOOKTYPE_SPELL); |
||
673 | if( spellName == foundSpellName ) then |
||
674 | if( foundSpellRank == nil ) then |
||
675 | return nil; |
||
676 | end |
||
677 | highestMatch = tonumber(string.sub( foundSpellRank, 6 )); |
||
678 | end |
||
679 | NL_ITERATOR = NL_ITERATOR + 1; |
||
680 | until not foundSpellName |
||
681 | |||
682 | return highestMatch; |
||
683 | end |
||
684 | |||
685 | function NL_GetMaxRankUnitCanReceive( spellRanks, unitLevel ) |
||
686 | NL_ITERATOR = 1; |
||
687 | while spellRanks[NL_ITERATOR] and unitLevel + 10 >= spellRanks[NL_ITERATOR] do |
||
688 | NL_ITERATOR = NL_ITERATOR + 1; |
||
689 | end |
||
690 | |||
691 | return NL_ITERATOR - 1; |
||
692 | end |
||
693 | |||
694 | function NL_CureNeedOnUnit( needName, unit, mousebutton ) |
||
695 | -- once in a while the interface can miss an event, leaving you with a unit whose needs have already been fixed |
||
696 | -- do a check needs before casting, to make sure this is still a need on this unit |
||
697 | NL_CheckAllNeeds(unit); |
||
698 | NL_ITERATOR = 1; |
||
699 | local needFrame = getglobal("NLMember".. unit .. "NeedsDetailsNeed"..NL_ITERATOR); |
||
700 | while( needFrame and needFrame.NeedName and needFrame.NeedName ~= needName ) do |
||
701 | NL_ITERATOR = NL_ITERATOR + 1; |
||
702 | needFrame = getglobal("NLMember".. unit .. "NeedsDetailsNeed"..NL_ITERATOR); |
||
703 | end |
||
704 | |||
705 | -- if it wasn't found as a need, it's been cured, so just return |
||
706 | if( not needFrame or needFrame.NeedName == nil ) then |
||
707 | return; |
||
708 | end |
||
709 | |||
710 | local spellName = nil; |
||
711 | local spellRanks = nil; |
||
712 | local spellCanTargetEnemy = false; |
||
713 | local spellNeedsNoTarget = false; |
||
714 | local isBuff = false; |
||
715 | |||
716 | local clickIndex = NL_CLICK_INDICES[mousebutton]; |
||
717 | |||
718 | -- find a cure spell that I can cast for this problem based on the player's level |
||
719 | if( NL_BUFF_SPELLS[NL_PLAYERCLASS] and NL_BUFF_SPELLS[NL_PLAYERCLASS][needName] ) then |
||
720 | spellName = NL_BUFF_SPELLS[NL_PLAYERCLASS][needName][clickIndex]; |
||
721 | spellRanks = NL_BUFF_SPELLS[NL_PLAYERCLASS][needName].Ranks; |
||
722 | spellCanTargetEnemy = NL_BUFF_SPELLS[NL_PLAYERCLASS][needName].CanTargetEnemy; |
||
723 | spellNeedsNoTarget = NL_BUFF_SPELLS[NL_PLAYERCLASS][needName].NoTarget; |
||
724 | isBuff = true; |
||
725 | elseif( NL_CURE_SPELLS[NL_PLAYERCLASS] and NL_CURE_SPELLS[NL_PLAYERCLASS][needName] ) then |
||
726 | -- it's a debuff, find the cure spell for it |
||
727 | spellName = NL_CURE_SPELLS[NL_PLAYERCLASS][needName][clickIndex]; |
||
728 | spellRanks = NL_CURE_SPELLS[NL_PLAYERCLASS][needName].Ranks; |
||
729 | spellCanTargetEnemy = NL_CURE_SPELLS[NL_PLAYERCLASS][needName].CanTargetEnemy; |
||
730 | elseif( NL_ENCHANT_SPELLS[NL_PLAYERCLASS] and NL_ENCHANT_SPELLS[NL_PLAYERCLASS][needName] ) then |
||
731 | if( NL_PLAYERCLASS == "Rogue" ) then |
||
732 | return; |
||
733 | end |
||
734 | |||
735 | spellName = NL_ENCHANT_SPELLS[NL_PLAYERCLASS][needName][clickIndex]; |
||
736 | spellRanks = NL_ENCHANT_SPELLS[NL_PLAYERCLASS][needName].Ranks; |
||
737 | spellCanTargetEnemy = NL_ENCHANT_SPELLS[NL_PLAYERCLASS][needName].CanTargetEnemy; |
||
738 | elseif( needName == "Health" ) then |
||
739 | if( NLConfig.HealSpells ) then |
||
740 | spellName = NLConfig.HealSpells[clickIndex]; |
||
741 | end |
||
742 | elseif( needName == "Mana" ) then |
||
743 | spellName = "Innervate"; |
||
744 | end |
||
745 | |||
746 | if( spellName ) then |
||
747 | local hadTarget = false; |
||
748 | |||
749 | -- cast pet spells here |
||
750 | -- fire shield seems unique in that it requires your target to actually change |
||
751 | -- most other spells don't require a target to start casting |
||
752 | -- therefore Fire Shield is the only spell that will not add units to the blacklist |
||
753 | if( spellName == "Fire Shield" ) then |
||
754 | local switchedTarget = false; |
||
755 | local targetWasEnemy = false; |
||
756 | local friendlyTargetName = ""; |
||
757 | if( UnitExists( "target" ) ) then |
||
758 | hadTarget = true; |
||
759 | end |
||
760 | |||
761 | if( UnitIsEnemy( "player", "target" ) ) then |
||
762 | targetWasEnemy = true; |
||
763 | else |
||
764 | friendlyTargetName = UnitName("target"); |
||
765 | end |
||
766 | TargetUnit( unit ); |
||
767 | switchedTarget = true; |
||
768 | -- find the action on the pet bar that matches this spell name |
||
769 | NL_ITERATOR = 1; |
||
770 | while( spellName ~= GetPetActionInfo(NL_ITERATOR) and NL_ITERATOR < 12 ) do |
||
771 | NL_ITERATOR = NL_ITERATOR + 1; |
||
772 | end |
||
773 | |||
774 | if( spellName == GetPetActionInfo(NL_ITERATOR) ) then |
||
775 | CastPetAction(NL_ITERATOR); |
||
776 | end |
||
777 | |||
778 | if( hadTarget == false ) then |
||
779 | ClearTarget(); |
||
780 | elseif( switchedTarget ) then |
||
781 | if( targetWasEnemy ) then |
||
782 | TargetLastEnemy(); |
||
783 | else |
||
784 | TargetByName(friendlyTargetName); |
||
785 | end |
||
786 | end |
||
787 | -- cast the highest ranked spell based on player level |
||
788 | elseif( string.sub( spellName, 0, 1 ) ~= "[" ) then |
||
789 | -- if the unit is not already the target |
||
790 | -- AND |
||
791 | -- if the spell needs a target |
||
792 | -- and the player has a target |
||
793 | -- and |
||
794 | -- the spell can target enemies OR (the spell can't target the enemy AND the target is friendly) |
||
795 | -- Clear the target |
||
796 | if( unit ~= "target" and (not spellNeedsNoTarget and UnitExists( "target" ) and (spellCanTargetEnemy or (not spellCanTargetEnemy and UnitIsFriend("player","target"))))) then |
||
797 | hadTarget = true; |
||
798 | ClearTarget(); |
||
799 | end |
||
800 | |||
801 | -- figure out the rank of the spell to cast based on level |
||
802 | if( not spellNeedsNoTarget ) then |
||
803 | if( spellRanks ) then |
||
804 | local validRank = NL_GetMaxRankPlayerCanCast( spellName ); |
||
805 | if( validRank ) then |
||
806 | local allowedRank = validRank; |
||
807 | if( isBuff ) then |
||
808 | allowedRank = NL_GetMaxRankUnitCanReceive( spellRanks, UnitLevel(unit) ); |
||
809 | end |
||
810 | if( validRank > 0 and allowedRank > 0 ) then |
||
811 | -- cast the maximum rank of this spell |
||
812 | CastSpellByName( spellName .. "("..NL_LANG_RANK.." " .. min(validRank,allowedRank) .. ")" ); |
||
813 | end |
||
814 | else |
||
815 | CastSpellByName( spellName ); |
||
816 | end |
||
817 | else |
||
818 | CastSpellByName( spellName ); |
||
819 | end |
||
820 | else |
||
821 | -- the spell needs no target, so just cast it. The game will find the correct rank to cast. |
||
822 | CastSpellByName( spellName ); |
||
823 | end |
||
824 | else |
||
825 | if( unit ~= "target" and UnitExists( "target" ) and UnitIsFriend("player","target")) then |
||
826 | hadTarget = true; |
||
827 | ClearTarget(); |
||
828 | end |
||
829 | |||
830 | local bagNum, slotNum; |
||
831 | local done = false; |
||
832 | for bagNum = 0, NUM_BAG_FRAMES do |
||
833 | local numSlots = GetContainerNumSlots(bagNum); |
||
834 | for slotNum = 1, numSlots do |
||
835 | local itemLink = GetContainerItemLink(bagNum, slotNum); |
||
836 | local itemName = string.sub(spellName, 2, string.len(spellName) - 1); |
||
837 | if( itemLink and string.find(itemLink, itemName) ) then |
||
838 | UseContainerItem(bagNum, slotNum); |
||
839 | done = true; |
||
840 | break; |
||
841 | end |
||
842 | end |
||
843 | if( done ) then |
||
844 | break; |
||
845 | end |
||
846 | end |
||
847 | end |
||
848 | |||
849 | if( not spellNeedsNoTarget ) then |
||
850 | if ( SpellIsTargeting() ) then |
||
851 | if( SpellCanTargetUnit(unit) ) then |
||
852 | -- message the person we're casting on, if notifications are enabled |
||
853 | if( NLConfig.SpellNotify == 1 ) then |
||
854 | SendChatMessage( "I'm casting "..spellName.." on you.", "WHISPER", this.language, UnitName(unit) ); |
||
855 | end |
||
856 | SpellTargetUnit(unit); |
||
857 | else |
||
858 | -- blacklist the unit, so they drop to the end of the list for however long the 'out of range' timer is set for |
||
859 | -- for now, remove them from the list and set a timer on them |
||
860 | SpellStopTargeting(); |
||
861 | -- ONLY if the unit isn't stickied and the blacklist delay is above 0 |
||
862 | if( getglobal("NLMember"..unit).TopNeed ~= 1 and NLConfig.BlackListDelay > 0 ) then |
||
863 | NLBlacklistUnit( unit ); |
||
864 | end |
||
865 | end |
||
866 | end |
||
867 | |||
868 | if( hadTarget == true ) then |
||
869 | TargetLastTarget(); |
||
870 | end |
||
871 | end |
||
872 | end |
||
873 | end |
||
874 | |||
875 | function NL_PulloutIfInvisible( unit ) |
||
876 | -- previous frame won't be nil on a frame that has been removed already but not pulled out |
||
877 | if( getglobal( "NLMember"..unit ).PendingRemoval ) then |
||
878 | NL_RemoveFromList( unit ); |
||
879 | getglobal( "NLMember"..unit ).PendingRemoval = false; |
||
880 | end |
||
881 | end |
||
882 | |||
883 | function NL_PulloutAllInvisibleFrames() |
||
884 | if( GetNumRaidMembers() > 0 ) then |
||
885 | -- iterate through all frames |
||
886 | for NL_ITERATOR = 1, 40 do |
||
887 | NL_PulloutIfInvisible( "raid" .. NL_ITERATOR ); |
||
888 | NL_PulloutIfInvisible( "raidpet" .. NL_ITERATOR ); |
||
889 | end |
||
890 | else |
||
891 | -- iterate through all frames |
||
892 | NL_PulloutIfInvisible( "player" ); |
||
893 | NL_PulloutIfInvisible( "pet" ); |
||
894 | |||
895 | for NL_ITERATOR = 1, 4 do |
||
896 | NL_PulloutIfInvisible( "party" .. NL_ITERATOR ); |
||
897 | NL_PulloutIfInvisible( "partypet" .. NL_ITERATOR ); |
||
898 | end |
||
899 | end |
||
900 | end |
||
901 | |||
902 | function NL_ResortSingleUnit( unit ) |
||
903 | if( not UnitExists(unit) ) then |
||
904 | return; |
||
905 | end |
||
906 | |||
907 | -- if the frame has a slot index it has a need |
||
908 | if( getglobal("NLMember"..unit).SlotIndex ) then |
||
909 | getglobal("NLMember"..unit).SlotIndex = nil; |
||
910 | if( getglobal("NLMember"..unit).TopNeed ) then |
||
911 | NL_AddToList(unit); |
||
912 | end |
||
913 | end |
||
914 | end |
||
915 | |||
916 | function NL_SortAllVisibleFrames() |
||
917 | NL_NUM_NEEDY_UNITS = 0; |
||
918 | NL_SLOTS = {}; |
||
919 | |||
920 | if( GetNumRaidMembers() > 0 ) then |
||
921 | -- iterate through all frames |
||
922 | for NL_ITERATOR = 1, 40 do |
||
923 | NL_ResortSingleUnit( "raid" .. NL_ITERATOR ); |
||
924 | NL_ResortSingleUnit( "raidpet" .. NL_ITERATOR ); |
||
925 | end |
||
926 | else |
||
927 | -- iterate through all frames |
||
928 | NL_ResortSingleUnit( "player" ); |
||
929 | NL_ResortSingleUnit( "pet" ); |
||
930 | |||
931 | for NL_ITERATOR = 1, 4 do |
||
932 | NL_ResortSingleUnit( "party" .. NL_ITERATOR ); |
||
933 | NL_ResortSingleUnit( "partypet" .. NL_ITERATOR ); |
||
934 | end |
||
935 | end |
||
936 | end |
||
937 | |||
938 | function NL_OnUpdate( elapsed ) |
||
939 | if( not NL_MOUSE_IN_FRAME and not NL_LIST_IS_SORTED ) then |
||
940 | -- do a generic sort of all visible units |
||
941 | if( NLConfig.AutoSort == 1 ) then |
||
942 | NL_PulloutAllInvisibleFrames(); |
||
943 | NL_SortAllVisibleFrames(); |
||
944 | else |
||
945 | NL_PulloutAllInvisibleFrames(); |
||
946 | end |
||
947 | |||
948 | NL_LIST_IS_SORTED = true; |
||
949 | end |
||
950 | |||
951 | NL_ITERATOR = 1; |
||
952 | while( NL_BLACK_LIST[NL_ITERATOR] ) do |
||
953 | NL_BLACK_LIST[NL_ITERATOR].Time = NL_BLACK_LIST[NL_ITERATOR].Time - elapsed; |
||
954 | |||
955 | if( NL_BLACK_LIST[NL_ITERATOR].Time <= 0 ) then |
||
956 | -- check needs and remove this unit from the blacklist |
||
957 | local member = NL_BLACK_LIST[NL_ITERATOR].Unit; |
||
958 | table.remove(NL_BLACK_LIST, NL_ITERATOR); |
||
959 | NL_CheckAllNeeds( member ); |
||
960 | else |
||
961 | NL_ITERATOR = NL_ITERATOR + 1; |
||
962 | end |
||
963 | end |
||
964 | end |
||
965 | |||
966 | function NL_FindInBuffList( needName, buffList ) |
||
967 | if( NL_BUFF_SPELLS[ NL_PLAYERCLASS ] ) then |
||
968 | if( NL_BUFF_SPELLS[ NL_PLAYERCLASS ][needName] ) then |
||
969 | if( NL_BUFF_SPELLS[ NL_PLAYERCLASS ][needName].Icons[1] and buffList[NL_ICON_LOCATION..NL_BUFF_SPELLS[ NL_PLAYERCLASS ][needName].Icons[1]] ) then |
||
970 | return true; |
||
971 | elseif( NL_BUFF_SPELLS[ NL_PLAYERCLASS ][needName].Icons[2] and buffList[NL_ICON_LOCATION..NL_BUFF_SPELLS[ NL_PLAYERCLASS ][needName].Icons[2]] ) then |
||
972 | return true; |
||
973 | end |
||
974 | end |
||
975 | end |
||
976 | |||
977 | return false; |
||
978 | end |
||
979 | |||
980 | function NL_AddToList(member) |
||
981 | if( not UnitExists(member) or UnitName(member) == nil or UnitName(member) == "" or UnitName(member) == "Unknown Entity" ) then |
||
982 | NL_RemoveFromList(member); |
||
983 | return nil; |
||
984 | end |
||
985 | |||
986 | getglobal("NLMember"..member.."Name"):SetText( string.sub(UnitName(member),1,NLConfig.FrameWidth/8) ); |
||
987 | local frame = getglobal("NLMember"..member); |
||
988 | |||
989 | if( frame.TopNeed == nil ) then |
||
990 | return; |
||
991 | end |
||
992 | |||
993 | if( frame.PendingRemoval ) then |
||
994 | frame.PendingRemoval = false; |
||
995 | frame:Show(); |
||
996 | end |
||
997 | |||
998 | if( NLConfig.ColorByClass == 1 ) then |
||
999 | local class = ""; |
||
1000 | if( string.find( member, "pet" ) ~= nil ) then |
||
1001 | class = UnitCreatureType(member); |
||
1002 | else |
||
1003 | class = UnitClass(member); |
||
1004 | end |
||
1005 | |||
1006 | if( NL_CLASS_COLORS[class] ) then |
||
1007 | frame:SetBackdropColor(NL_CLASS_COLORS[class].r, NL_CLASS_COLORS[class].g, NL_CLASS_COLORS[class].b, 1); |
||
1008 | else |
||
1009 | frame:SetBackdropColor(NL_CLASS_COLORS["Default"].r, NL_CLASS_COLORS["Default"].g, NL_CLASS_COLORS["Default"].b, 1); |
||
1010 | end |
||
1011 | elseif( NLConfig.Needs[frame.TopNeed] ~= nil ) then |
||
1012 | frame:SetBackdropColor(NLConfig.Needs[frame.TopNeed].BGColor.r, NLConfig.Needs[frame.TopNeed].BGColor.g, NLConfig.Needs[frame.TopNeed].BGColor.b, 0.8); |
||
1013 | end |
||
1014 | |||
1015 | -- target has special treatment, as it should not be in the list |
||
1016 | if( member == "target" ) then |
||
1017 | frame:Show(); |
||
1018 | return frame; |
||
1019 | end |
||
1020 | |||
1021 | if( not frame.SlotIndex ) then |
||
1022 | frame.SlotIndex = NL_NUM_NEEDY_UNITS; |
||
1023 | NL_SLOTS[NL_NUM_NEEDY_UNITS] = frame; |
||
1024 | NL_NUM_NEEDY_UNITS = NL_NUM_NEEDY_UNITS + 1; |
||
1025 | NLAnchorFrame( frame ); |
||
1026 | end |
||
1027 | |||
1028 | if( NLConfig.AutoSort == 1 and not NL_MOUSE_IN_FRAME ) then |
||
1029 | NLSortFrameIntoList(frame); |
||
1030 | end |
||
1031 | |||
1032 | if( NL_MINIMIZED ) then |
||
1033 | NLHeaderMinimized:Show(); |
||
1034 | else |
||
1035 | NLHeader:Show(); |
||
1036 | end |
||
1037 | |||
1038 | return frame; |
||
1039 | end |
||
1040 | |||
1041 | function NLAnchorFrame( frame ) |
||
1042 | if( frame ~= NL_SLOTS[frame.SlotIndex] ) then |
||
1043 | NLBlacklistUnit(frame.Unit); |
||
1044 | end |
||
1045 | |||
1046 | if( frame.SlotIndex < NLConfig.MaxUnits ) then |
||
1047 | if( not frame:IsShown() ) then |
||
1048 | -- draw the details of the frame, because it's now being made visible |
||
1049 | frame:Show(); |
||
1050 | end |
||
1051 | frame:ClearAllPoints(); |
||
1052 | frame:SetPoint( NLAnchors[NLConfig.InvertList+1].AnchorPoint, NLHeader, NLAnchors[NLConfig.InvertList+1].ReferenceAnchorPoint, 0, NLAnchors[NLConfig.InvertList+1].Offset * (frame:GetHeight() - 5) * frame.SlotIndex - (5 * NLAnchors[NLConfig.InvertList+1].Offset) ); |
||
1053 | else |
||
1054 | frame:Hide(); |
||
1055 | end |
||
1056 | end |
||
1057 | |||
1058 | function NLBlacklistUnit( unit ) |
||
1059 | NL_RemoveFromList(unit); |
||
1060 | local newBlackListItem = {}; |
||
1061 | newBlackListItem.Unit = unit; |
||
1062 | newBlackListItem.Time = NLConfig.BlackListDelay; |
||
1063 | table.insert(NL_BLACK_LIST, newBlackListItem); |
||
1064 | end |
||
1065 | |||
1066 | function NLSortFrameDown( frame ) |
||
1067 | local nextFrame = nil; |
||
1068 | while( frame.SlotIndex < NL_NUM_NEEDY_UNITS - 1 and NL_SLOTS[frame.SlotIndex+1] and NL_SLOTS[frame.SlotIndex+1].Unit and not NL_SLOTS[frame.SlotIndex+1].TopNeed ) do |
||
1069 | NL_DebugMsg("Removing " .. NL_SLOTS[frame.SlotIndex+1].Unit .. " from list because its TopNeed is nil"); |
||
1070 | NL_RemoveFromList(NL_SLOTS[frame.SlotIndex+1].Unit); |
||
1071 | -- at this point, the removed frame should shift the rest up, and this frame can still be sorted downward |
||
1072 | end |
||
1073 | while( frame.SlotIndex < NL_NUM_NEEDY_UNITS - 1 and ( NL_SLOTS[frame.SlotIndex].TopNeed > NL_SLOTS[frame.SlotIndex+1].TopNeed |
||
1074 | or (NL_SLOTS[frame.SlotIndex].TopNeed == NL_SLOTS[frame.SlotIndex+1].TopNeed and |
||
1075 | ( ( NL_SLOTS[frame.SlotIndex].TopNeed == NLConfig.HealthNeedIndex and NL_SLOTS[frame.SlotIndex].CurrentHealth > NL_SLOTS[frame.SlotIndex+1].CurrentHealth ) or |
||
1076 | ( ( NLConfig.ManaNeedIndex and NL_SLOTS[frame.SlotIndex].TopNeed == NLConfig.ManaNeedIndex and NL_SLOTS[frame.SlotIndex].CurrentMana > NL_SLOTS[frame.SlotIndex+1].CurrentMana ) ) ) ) ) ) do |
||
1077 | nextFrame = NL_SLOTS[frame.SlotIndex+1]; |
||
1078 | nextFrame.SlotIndex = frame.SlotIndex; |
||
1079 | frame.SlotIndex = frame.SlotIndex + 1; |
||
1080 | NL_SLOTS[frame.SlotIndex] = frame; |
||
1081 | NL_SLOTS[nextFrame.SlotIndex] = nextFrame; |
||
1082 | |||
1083 | NLAnchorFrame( frame ); |
||
1084 | NLAnchorFrame( nextFrame ); |
||
1085 | |||
1086 | if( frame.SlotIndex < NL_NUM_NEEDY_UNITS - 1 and NL_SLOTS[frame.SlotIndex+1] and NL_SLOTS[frame.SlotIndex+1].Unit and not NL_SLOTS[frame.SlotIndex+1].TopNeed ) then |
||
1087 | NL_DebugMsg("Removing " .. NL_SLOTS[frame.SlotIndex+1].Unit .. " from list because its TopNeed is nil"); |
||
1088 | NL_RemoveFromList(NL_SLOTS[frame.SlotIndex+1].Unit); |
||
1089 | -- at this point, the removed frame should shift the rest up, and this frame can still be sorted downward |
||
1090 | end |
||
1091 | end |
||
1092 | end |
||
1093 | |||
1094 | function NLSortFrameUp( frame ) |
||
1095 | local previousFrame = nil; |
||
1096 | while( frame.SlotIndex > 0 and NL_SLOTS[frame.SlotIndex-1] and NL_SLOTS[frame.SlotIndex-1].Unit and not NL_SLOTS[frame.SlotIndex-1].TopNeed ) do |
||
1097 | NL_DebugMsg("Removing " .. NL_SLOTS[frame.SlotIndex-1].Unit .. " from list because its TopNeed is nil"); |
||
1098 | NL_RemoveFromList(NL_SLOTS[frame.SlotIndex-1].Unit); |
||
1099 | -- at this point, the removed frame should shift the rest up, and this frame can still be sorted upward |
||
1100 | end |
||
1101 | while( frame.SlotIndex > 0 and ( NL_SLOTS[frame.SlotIndex].TopNeed < NL_SLOTS[frame.SlotIndex-1].TopNeed |
||
1102 | or (NL_SLOTS[frame.SlotIndex].TopNeed == NL_SLOTS[frame.SlotIndex-1].TopNeed and |
||
1103 | ( ( NL_SLOTS[frame.SlotIndex].TopNeed == NLConfig.HealthNeedIndex and NL_SLOTS[frame.SlotIndex].CurrentHealth < NL_SLOTS[frame.SlotIndex-1].CurrentHealth ) or |
||
1104 | ( NLConfig.ManaNeedIndex and NL_SLOTS[frame.SlotIndex].TopNeed == NLConfig.ManaNeedIndex and NL_SLOTS[frame.SlotIndex].CurrentMana < NL_SLOTS[frame.SlotIndex-1].CurrentMana ) ) ) ) ) do |
||
1105 | previousFrame = NL_SLOTS[frame.SlotIndex-1]; |
||
1106 | previousFrame.SlotIndex = frame.SlotIndex; |
||
1107 | frame.SlotIndex = frame.SlotIndex - 1; |
||
1108 | NL_SLOTS[frame.SlotIndex] = frame; |
||
1109 | NL_SLOTS[previousFrame.SlotIndex] = previousFrame; |
||
1110 | |||
1111 | NLAnchorFrame( frame ); |
||
1112 | NLAnchorFrame( previousFrame ); |
||
1113 | |||
1114 | if( frame.SlotIndex > 0 and NL_SLOTS[frame.SlotIndex-1] and NL_SLOTS[frame.SlotIndex-1].Unit and not NL_SLOTS[frame.SlotIndex-1].TopNeed ) then |
||
1115 | NL_DebugMsg("Removing " .. NL_SLOTS[frame.SlotIndex-1].Unit .. " from list because its TopNeed is nil"); |
||
1116 | NL_RemoveFromList(NL_SLOTS[frame.SlotIndex-1].Unit); |
||
1117 | -- at this point, the removed frame should shift the rest up, and this frame can still be sorted upward |
||
1118 | end |
||
1119 | end |
||
1120 | end |
||
1121 | |||
1122 | function NLSortFrameIntoList(frame) |
||
1123 | NLSortFrameUp( frame ); |
||
1124 | NLSortFrameDown( frame ); |
||
1125 | end |
||
1126 | |||
1127 | function NLShiftRemainingUp( index ) |
||
1128 | while( index < NL_NUM_NEEDY_UNITS - 1 ) do |
||
1129 | NL_SLOTS[index] = NL_SLOTS[index+1]; |
||
1130 | NL_SLOTS[index].SlotIndex = index; |
||
1131 | |||
1132 | NLAnchorFrame( NL_SLOTS[index] ); |
||
1133 | |||
1134 | index = index + 1; |
||
1135 | end |
||
1136 | end |
||
1137 | |||
1138 | function NL_RemoveFromList(member) |
||
1139 | -- sort to bottom of list (so all other units shift up) |
||
1140 | if( not member ) then |
||
1141 | return; |
||
1142 | end |
||
1143 | |||
1144 | local frame = getglobal("NLMember"..member); |
||
1145 | |||
1146 | -- target has special treatment, as it should not be in the list |
||
1147 | if( member == "target" ) then |
||
1148 | frame:Hide(); |
||
1149 | return; |
||
1150 | end |
||
1151 | |||
1152 | if( NL_MOUSE_IN_FRAME ) then |
||
1153 | frame.PendingRemoval = true; |
||
1154 | frame:Hide(); |
||
1155 | return; |
||
1156 | end |
||
1157 | |||
1158 | if( frame.SlotIndex ) then |
||
1159 | NL_SLOTS[frame.SlotIndex] = nil; |
||
1160 | frame:Hide(); |
||
1161 | NLShiftRemainingUp( frame.SlotIndex ); |
||
1162 | NL_NUM_NEEDY_UNITS = NL_NUM_NEEDY_UNITS - 1; |
||
1163 | frame.SlotIndex = nil; |
||
1164 | frame.TopNeed = nil; |
||
1165 | end |
||
1166 | |||
1167 | if( NLConfig.HideHeader == 1 and NL_NUM_NEEDY_UNITS == 0 ) then |
||
1168 | NLHeader:Hide(); |
||
1169 | NLHeaderMinimized:Hide(); |
||
1170 | end |
||
1171 | end |
||
1172 | |||
1173 | function NL_MouseEnteredFrame() |
||
1174 | NL_MOUSE_IN_FRAME = true; |
||
1175 | NL_LIST_IS_SORTED = false; |
||
1176 | end |
||
1177 | |||
1178 | function NL_MouseLeftFrame() |
||
1179 | NL_MOUSE_IN_FRAME = false; |
||
1180 | end |
||
1181 | |||
1182 | function NL_UpdateUnit(id) |
||
1183 | NL_UpdateNeeds( id ); |
||
1184 | local frame = "NLMember" .. id; |
||
1185 | if( NLConfig.ShowHealthNum == 1 ) then |
||
1186 | if( NLConfig.ShowHealthLost == 1 ) then |
||
1187 | getglobal(frame .. "HealthNum"):SetText(UnitHealth(id)-UnitHealthMax(id)); |
||
1188 | else |
||
1189 | getglobal(frame .. "HealthNum"):SetText(UnitHealth(id) .. "/" .. UnitHealthMax(id)); |
||
1190 | end |
||
1191 | getglobal(frame .. "HealthNum"):Show(); |
||
1192 | elseif( getglobal(frame .. "HealthNum"):IsShown() ) then |
||
1193 | getglobal(frame .. "HealthNum"):Hide(); |
||
1194 | end |
||
1195 | |||
1196 | if( UnitIsDead(id) or UnitIsGhost(id) or UnitHealth(id) == 0 ) then |
||
1197 | getglobal(frame .. "HPBar"):Hide(); |
||
1198 | getglobal(frame .. "MPBar"):Hide(); |
||
1199 | if( NLConfig.ShowHealth == 1 or NLConfig.ShowMana == 1 ) then |
||
1200 | if( UnitIsGhost(id) ) then |
||
1201 | getglobal(frame .. "Status"):SetText("Ghost"); |
||
1202 | elseif( UnitIsDead(id) or UnitHealth(id) == 0 ) then |
||
1203 | getglobal(frame .. "Status"):SetText("Dead"); |
||
1204 | end |
||
1205 | getglobal(frame .. "Status"):Show(); |
||
1206 | end |
||
1207 | return; |
||
1208 | else |
||
1209 | getglobal(frame .. "Status"):Hide(); |
||
1210 | if( NLConfig.ShowHealth == 1 ) then |
||
1211 | getglobal(frame .. "HPBar"):Show(); |
||
1212 | else |
||
1213 | getglobal(frame .. "HPBar"):Hide(); |
||
1214 | end |
||
1215 | -- determine the color for the power bar |
||
1216 | local info = ManaBarColor[UnitPowerType(id)]; |
||
1217 | getglobal(frame .. "MPBar"):SetStatusBarColor(info.r, info.g, info.b); |
||
1218 | if( NLConfig.ShowMana == 1 ) then |
||
1219 | getglobal(frame .. "MPBar"):Show(); |
||
1220 | else |
||
1221 | getglobal(frame .. "MPBar"):Hide(); |
||
1222 | end |
||
1223 | end |
||
1224 | |||
1225 | -- set the name in the frame |
||
1226 | if( getglobal(frame).CurrentHealth ) then |
||
1227 | local percent = floor(getglobal(frame).CurrentHealth); |
||
1228 | if ( percent and percent > 0 ) then |
||
1229 | if ( percent > 100 ) then |
||
1230 | percent = 100; |
||
1231 | end |
||
1232 | getglobal(frame .. "HPBar"):SetValue(percent); |
||
1233 | local hppercent = percent/100; |
||
1234 | local r, g; |
||
1235 | if ( hppercent > 0.5 and hppercent <= 1) then |
||
1236 | g = 1; |
||
1237 | r = (1.0 - hppercent) * 2; |
||
1238 | elseif ( hppercent >= 0 and hppercent <= 0.5 ) then |
||
1239 | r = 1.0; |
||
1240 | g = hppercent * 2; |
||
1241 | else |
||
1242 | r = 0; |
||
1243 | g = 1; |
||
1244 | end |
||
1245 | getglobal(frame .. "HPBar"):SetStatusBarColor(r, g, 0); |
||
1246 | end |
||
1247 | end |
||
1248 | |||
1249 | -- get the class of the player and update the mana bar appropriately |
||
1250 | if( UnitManaMax(id) == 0 ) then |
||
1251 | getglobal(frame .. "MPBar"):SetValue(0); |
||
1252 | else |
||
1253 | if( getglobal(frame).CurrentMana ) then |
||
1254 | local percent = floor(getglobal(frame).CurrentMana); |
||
1255 | getglobal(frame .. "MPBar"):SetValue(percent); |
||
1256 | end |
||
1257 | end |
||
1258 | end |
||
1259 | |||
1260 | function NL_UpdateAura( unit ) |
||
1261 | if( not UnitExists(unit) ) then |
||
1262 | return; |
||
1263 | end |
||
1264 | |||
1265 | local frame = "NLMember" .. unit; |
||
1266 | |||
1267 | if( NLConfig.ShowBuffs == 0 and NLConfig.ShowHealBuffs == 0 ) then |
||
1268 | getglobal(frame .. "BuffsDetails"):SetWidth( 5 ); |
||
1269 | getglobal(frame .. "BuffsDetails"):Hide(); |
||
1270 | else |
||
1271 | local buff; |
||
1272 | local numBuffs = 0; |
||
1273 | local index = 1; |
||
1274 | for NL_ITERATOR=1, NL_MAX_TOOLTIP_BUFFS do |
||
1275 | buff = UnitBuff(unit, NL_ITERATOR); |
||
1276 | if ( buff and (NLConfig.ShowBuffs == 1 or (NLConfig.ShowHealBuffs == 1 and |
||
1277 | (buff == NL_ICON_LOCATION .. "Spell_Nature_Rejuvenation" or |
||
1278 | buff == NL_ICON_LOCATION .. "Spell_Nature_ResistNature" or |
||
1279 | buff == NL_ICON_LOCATION .. "Spell_Holy_Renew" ) |
||
1280 | ) ) ) then |
||
1281 | getglobal(frame .. "BuffsDetailsBuff"..index):SetNormalTexture(buff); |
||
1282 | getglobal(frame .. "BuffsDetailsBuff"..index):Show(); |
||
1283 | getglobal(frame .. "BuffsDetailsBuff"..index):SetID(index); |
||
1284 | if( getglobal(frame .. "BuffsDetailsBuff"..index) == NL_MOUSE_OVER_FRAME ) then |
||
1285 | GameTooltip:SetUnitBuff( getglobal(frame).Unit, NL_ITERATOR ); |
||
1286 | end |
||
1287 | index = index + 1; |
||
1288 | numBuffs = numBuffs + 1; |
||
1289 | end |
||
1290 | end |
||
1291 | for NL_ITERATOR=index, NL_MAX_TOOLTIP_BUFFS do |
||
1292 | getglobal(frame .. "BuffsDetailsBuff"..NL_ITERATOR):Hide(); |
||
1293 | end |
||
1294 | |||
1295 | getglobal(frame .. "BuffsDetailsBuff1"):ClearAllPoints(); |
||
1296 | getglobal(frame .. "BuffsDetailsBuff1"):SetPoint( "TOPLEFT", frame .. "BuffsDetails", "TOPLEFT", 5, -5 ); |
||
1297 | getglobal(frame .. "BuffsDetails"):SetHeight( 26 ); |
||
1298 | -- Size the tooltip |
||
1299 | if ( numBuffs > 0 ) then |
||
1300 | getglobal(frame .. "BuffsDetails"):SetWidth( (numBuffs * 17) + 9 ); |
||
1301 | getglobal(frame .. "BuffsDetails"):Show(); |
||
1302 | else |
||
1303 | getglobal(frame .. "BuffsDetails"):SetWidth( 5 ); |
||
1304 | getglobal(frame .. "BuffsDetails"):Hide(); |
||
1305 | end |
||
1306 | end |
||
1307 | |||
1308 | if( NLConfig.ShowDebuffs == 0 ) then |
||
1309 | getglobal(frame .. "DebuffsDetails"):SetWidth( 5 ); |
||
1310 | getglobal(frame .. "DebuffsDetails"):Hide(); |
||
1311 | else |
||
1312 | local buff; |
||
1313 | local numDebuffs = 0; |
||
1314 | local index = 1; |
||
1315 | for NL_ITERATOR=1, NL_MAX_TOOLTIP_DEBUFFS do |
||
1316 | buff = UnitDebuff(unit, NL_ITERATOR); |
||
1317 | |||
1318 | if ( buff ) then |
||
1319 | getglobal(frame .. "DebuffsDetailsDebuff"..index):SetNormalTexture(buff); |
||
1320 | getglobal(frame .. "DebuffsDetailsDebuff"..index):Show(); |
||
1321 | getglobal(frame .. "DebuffsDetailsDebuff"..index):SetID(index); |
||
1322 | if( getglobal(frame .. "DebuffsDetailsDebuff"..index) == NL_MOUSE_OVER_FRAME ) then |
||
1323 | GameTooltip:SetUnitDebuff( getglobal(frame).Unit, NL_ITERATOR ); |
||
1324 | end |
||
1325 | index = index + 1; |
||
1326 | numDebuffs = numDebuffs + 1; |
||
1327 | end |
||
1328 | end |
||
1329 | for NL_ITERATOR=index, NL_MAX_TOOLTIP_DEBUFFS do |
||
1330 | getglobal(frame .. "DebuffsDetailsDebuff"..NL_ITERATOR):Hide(); |
||
1331 | end |
||
1332 | |||
1333 | getglobal(frame .. "DebuffsDetailsDebuff1"):ClearAllPoints(); |
||
1334 | getglobal(frame .. "DebuffsDetailsDebuff1"):SetPoint( "TOPLEFT", frame .. "DebuffsDetails", "TOPLEFT", 5, -5 ); |
||
1335 | getglobal(frame .. "DebuffsDetails"):SetHeight( 26 ); |
||
1336 | -- Size the tooltip |
||
1337 | if ( numDebuffs > 0 ) then |
||
1338 | getglobal(frame .. "DebuffsDetails"):SetWidth( (numDebuffs * 17) + 9 ); |
||
1339 | getglobal(frame .. "DebuffsDetails"):Show(); |
||
1340 | else |
||
1341 | getglobal(frame .. "DebuffsDetails"):SetWidth( 5 ); |
||
1342 | getglobal(frame .. "DebuffsDetails"):Hide(); |
||
1343 | end |
||
1344 | end |
||
1345 | end |
||
1346 | |||
1347 | function NL_UpdateNeeds( member ) |
||
1348 | local frame = getglobal( "NLMember"..member ); |
||
1349 | if( not frame or not frame.TopNeed or frame.TopNeed < 1 or NLConfig.ShowNeeds == 0 ) then |
||
1350 | NL_ClearNeedDetails( member ); |
||
1351 | return; |
||
1352 | end |
||
1353 | |||
1354 | local needFrameIndex = 1; |
||
1355 | |||
1356 | -- if resurrection is a need of this unit |
||
1357 | if( frame.Needs[NLConfig.ResurrectionNeedIndex] ) then |
||
1358 | if( NL_CURE_SPELLS[NL_PLAYERCLASS] and NL_CURE_SPELLS[NL_PLAYERCLASS].Resurrection ) then |
||
1359 | iconName = NL_CURE_SPELLS[NL_PLAYERCLASS].Resurrection.Icon; |
||
1360 | if( iconName ~= "" ) then |
||
1361 | local needFrame = getglobal(frame:GetName() .. "NeedsDetailsNeed"..needFrameIndex); |
||
1362 | if( NLConfig.LargeNeedIcons == 1 ) then |
||
1363 | getglobal(frame:GetName() .. "NeedsDetailsNeed"..needFrameIndex):SetWidth( 22 ); |
||
1364 | getglobal(frame:GetName() .. "NeedsDetailsNeed"..needFrameIndex):SetHeight( 22 ); |
||
1365 | else |
||
1366 | getglobal(frame:GetName() .. "NeedsDetailsNeed"..needFrameIndex):SetWidth( 16 ); |
||
1367 | getglobal(frame:GetName() .. "NeedsDetailsNeed"..needFrameIndex):SetHeight( 16 ); |
||
1368 | end |
||
1369 | needFrame:SetNormalTexture(NL_ICON_LOCATION .. iconName); |
||
1370 | needFrame.NeedName = "Resurrection"; |
||
1371 | needFrame:Show(); |
||
1372 | if( needFrame == NL_MOUSE_OVER_FRAME ) then |
||
1373 | NL_MouseOverNeedButton(needFrame); |
||
1374 | end |
||
1375 | needFrameIndex = needFrameIndex + 1; |
||
1376 | end |
||
1377 | end |
||
1378 | else |
||
1379 | for NL_ITERATOR=2, NLConfig.NumNeeds - 1 do |
||
1380 | local iconName = ""; |
||
1381 | if( frame.Needs[NL_ITERATOR] ) then |
||
1382 | if( NL_BUFF_SPELLS[NL_PLAYERCLASS] and NL_BUFF_SPELLS[NL_PLAYERCLASS][NLConfig.Needs[NL_ITERATOR].Name] ) then |
||
1383 | iconName = NL_BUFF_SPELLS[NL_PLAYERCLASS][NLConfig.Needs[NL_ITERATOR].Name].Icons[1]; |
||
1384 | elseif( NL_CURE_SPELLS[NL_PLAYERCLASS] and NL_CURE_SPELLS[NL_PLAYERCLASS][NLConfig.Needs[NL_ITERATOR].Name] ) then |
||
1385 | iconName = NL_CURE_SPELLS[NL_PLAYERCLASS][NLConfig.Needs[NL_ITERATOR].Name].Icon; |
||
1386 | elseif( NL_ENCHANT_SPELLS[NL_PLAYERCLASS] and NL_ENCHANT_SPELLS[NL_PLAYERCLASS][NLConfig.Needs[NL_ITERATOR].Name] ) then |
||
1387 | iconName = NL_ENCHANT_SPELLS[NL_PLAYERCLASS][NLConfig.Needs[NL_ITERATOR].Name].Icon; |
||
1388 | elseif( NL_OTHER[NLConfig.Needs[NL_ITERATOR].Name] ) then |
||
1389 | iconName = NL_OTHER[NLConfig.Needs[NL_ITERATOR].Name].Icon; |
||
1390 | end |
||
1391 | |||
1392 | if( iconName ~= "" ) then |
||
1393 | local needFrame = getglobal(frame:GetName() .. "NeedsDetailsNeed"..needFrameIndex); |
||
1394 | if( NLConfig.LargeNeedIcons == 1 ) then |
||
1395 | getglobal(frame:GetName() .. "NeedsDetailsNeed"..needFrameIndex):SetWidth( 22 ); |
||
1396 | getglobal(frame:GetName() .. "NeedsDetailsNeed"..needFrameIndex):SetHeight( 22 ); |
||
1397 | else |
||
1398 | getglobal(frame:GetName() .. "NeedsDetailsNeed"..needFrameIndex):SetWidth( 16 ); |
||
1399 | getglobal(frame:GetName() .. "NeedsDetailsNeed"..needFrameIndex):SetHeight( 16 ); |
||
1400 | end |
||
1401 | needFrame:SetNormalTexture(NL_ICON_LOCATION .. iconName); |
||
1402 | needFrame.NeedName = NLConfig.Needs[NL_ITERATOR].Name; |
||
1403 | needFrame:Show(); |
||
1404 | if( needFrame == NL_MOUSE_OVER_FRAME ) then |
||
1405 | NL_MouseOverNeedButton(needFrame); |
||
1406 | end |
||
1407 | needFrameIndex = needFrameIndex + 1; |
||
1408 | if( needFrameIndex > NL_MAX_NEEDS ) then |
||
1409 | -- this is a break condition, we don't need to see more needs |
||
1410 | NL_ITERATOR = NLConfig.NumNeeds; |
||
1411 | end |
||
1412 | end |
||
1413 | end |
||
1414 | end |
||
1415 | end |
||
1416 | |||
1417 | local needCount = needFrameIndex - 1; |
||
1418 | |||
1419 | for NL_ITERATOR=needFrameIndex, NL_MAX_NEEDS - 1 do |
||
1420 | getglobal(frame:GetName() .. "NeedsDetailsNeed"..NL_ITERATOR):Hide(); |
||
1421 | end |
||
1422 | |||
1423 | if( NLConfig.LargeNeedIcons == 1 ) then |
||
1424 | getglobal(frame:GetName() .. "NeedsDetails"):SetWidth( needCount * 23 + 9 ); |
||
1425 | getglobal(frame:GetName() .. "NeedsDetails"):SetHeight( 32 ); |
||
1426 | else |
||
1427 | getglobal(frame:GetName() .. "NeedsDetails"):SetWidth( needCount * 17 + 9 ); |
||
1428 | getglobal(frame:GetName() .. "NeedsDetails"):SetHeight( 26 ); |
||
1429 | end |
||
1430 | getglobal(frame:GetName() .. "NeedsDetailsNeed1"):ClearAllPoints(); |
||
1431 | getglobal(frame:GetName() .. "NeedsDetailsNeed1"):SetPoint( "TOPLEFT", frame:GetName() .. "NeedsDetails", "TOPLEFT", 5, -5 ); |
||
1432 | if( needCount > 0 ) then |
||
1433 | getglobal(frame:GetName() .. "NeedsDetails"):Show(); |
||
1434 | else |
||
1435 | getglobal(frame:GetName() .. "NeedsDetails"):Hide(); |
||
1436 | end |
||
1437 | end |
||
1438 | |||
1439 | function NL_SetTooltipOwner( frame, anchor ) |
||
1440 | if( NLConfig.ShowTooltips == 1 ) then |
||
1441 | GameTooltip:SetOwner(frame, anchor); |
||
1442 | else |
||
1443 | GameTooltip:Hide(); |
||
1444 | end |
||
1445 | end |
||
1446 | |||
1447 | function NLMember_OnEnter(frame) |
||
1448 | NL_SetTooltipOwner( frame, "ANCHOR_TOPLEFT" ); |
||
1449 | GameTooltip:SetUnit( frame.Unit ); |
||
1450 | end |
||
1451 | |||
1452 | function NLMember_OnLeave(frame) |
||
1453 | GameTooltip:Hide(); |
||
1454 | end |
||
1455 | |||
1456 | function NLMember_OnClick(button, frame) |
||
1457 | if( NLConfig.UseCastParty == 1 and CastParty_OnClickByUnit ~= nil ) then |
||
1458 | CastParty_OnClickByUnit( button, frame.Unit ); |
||
1459 | else |
||
1460 | if ( button == "LeftButton" ) then |
||
1461 | -- determine which unit was clicked |
||
1462 | if ( SpellIsTargeting() ) then |
||
1463 | SpellTargetUnit(frame.Unit); |
||
1464 | elseif ( CursorHasItem() ) then |
||
1465 | DropItemOnUnit(frame.Unit); |
||
1466 | else |
||
1467 | TargetUnit(frame.Unit); |
||
1468 | end |
||
1469 | else |
||
1470 | if( SpellIsTargeting() ) then |
||
1471 | SpellStopTargeting(); |
||
1472 | return; |
||
1473 | end |
||
1474 | end |
||
1475 | end |
||
1476 | end |
||
1477 | |||
1478 | function NLMember_CheckAllUnits() |
||
1479 | NL_NUM_NEEDY_UNITS = 0; |
||
1480 | if( NLConfig.HideHeader == 1 ) then |
||
1481 | NLHeader:Hide(); |
||
1482 | end |
||
1483 | |||
1484 | NL_SLOTS = {}; |
||
1485 | |||
1486 | -- hide all frames |
||
1487 | NLMemberplayer:Hide(); |
||
1488 | NLMemberplayer.SlotIndex = nil; |
||
1489 | NLMemberplayer.TopNeed = nil; |
||
1490 | NLMemberplayer.Needs = {}; |
||
1491 | NLMemberpet:Hide(); |
||
1492 | NLMemberpet.SlotIndex = nil; |
||
1493 | NLMemberpet.TopNeed = nil; |
||
1494 | NLMemberpet.Needs = {}; |
||
1495 | |||
1496 | for NL_ITERATOR = 1, 4 do |
||
1497 | getglobal("NLMemberparty"..NL_ITERATOR):Hide(); |
||
1498 | getglobal("NLMemberparty"..NL_ITERATOR).SlotIndex = nil; |
||
1499 | getglobal("NLMemberparty"..NL_ITERATOR).TopNeed = nil; |
||
1500 | getglobal("NLMemberparty"..NL_ITERATOR).Needs = {}; |
||
1501 | getglobal("NLMemberpartypet"..NL_ITERATOR):Hide(); |
||
1502 | getglobal("NLMemberpartypet"..NL_ITERATOR).SlotIndex = nil; |
||
1503 | getglobal("NLMemberpartypet"..NL_ITERATOR).TopNeed = nil; |
||
1504 | getglobal("NLMemberpartypet"..NL_ITERATOR).Needs = {}; |
||
1505 | end |
||
1506 | for NL_ITERATOR = 1, 40 do |
||
1507 | getglobal("NLMemberraid"..NL_ITERATOR):Hide(); |
||
1508 | getglobal("NLMemberraid"..NL_ITERATOR).SlotIndex = nil; |
||
1509 | getglobal("NLMemberraid"..NL_ITERATOR).TopNeed = nil; |
||
1510 | getglobal("NLMemberraid"..NL_ITERATOR).Needs = {}; |
||
1511 | getglobal("NLMemberraidpet"..NL_ITERATOR):Hide(); |
||
1512 | getglobal("NLMemberraidpet"..NL_ITERATOR).SlotIndex = nil; |
||
1513 | getglobal("NLMemberraidpet"..NL_ITERATOR).TopNeed = nil; |
||
1514 | getglobal("NLMemberraidpet"..NL_ITERATOR).Needs = {}; |
||
1515 | end |
||
1516 | |||
1517 | -- if player in a raid, check all 40 units, otherwise just check player and party |
||
1518 | if( GetNumRaidMembers() > 0 ) then |
||
1519 | for NL_ITERATOR = 1, 40 do |
||
1520 | if( UnitExists( "raid" .. NL_ITERATOR ) ) then |
||
1521 | NL_CheckAllNeeds( "raid" .. NL_ITERATOR ); |
||
1522 | if( UnitExists( "raidpet" .. NL_ITERATOR ) ) then |
||
1523 | NL_CheckAllNeeds( "raidpet" .. NL_ITERATOR ); |
||
1524 | end |
||
1525 | end |
||
1526 | end |
||
1527 | else |
||
1528 | if( UnitExists( "player" ) ) then |
||
1529 | NL_CheckAllNeeds( "player" ); |
||
1530 | if( UnitExists( "pet" ) ) then |
||
1531 | NL_CheckAllNeeds( "pet" ); |
||
1532 | end |
||
1533 | end |
||
1534 | |||
1535 | for NL_ITERATOR = 1, 4 do |
||
1536 | if( UnitExists( "party" .. NL_ITERATOR ) ) then |
||
1537 | NL_CheckAllNeeds( "party" .. NL_ITERATOR ); |
||
1538 | if( UnitExists( "partypet" .. NL_ITERATOR ) ) then |
||
1539 | NL_CheckAllNeeds( "partypet" .. NL_ITERATOR ); |
||
1540 | end |
||
1541 | end |
||
1542 | end |
||
1543 | end |
||
1544 | |||
1545 | NL_CheckTarget(); |
||
1546 | end |
||
1547 | |||
1548 | function NL_CheckTarget() |
||
1549 | NLMembertarget.Needs = {}; |
||
1550 | NLMembertarget.TopNeed = nil; |
||
1551 | NLMembertarget:Hide(); |
||
1552 | |||
1553 | if( NLConfig.ShowTargetFrame == 1 ) then |
||
1554 | if( UnitExists( "target" ) and UnitIsFriend( "target", "player" ) ) then |
||
1555 | NL_CheckAllNeeds( "target" ); |
||
1556 | else |
||
1557 | NLMembertarget:Hide(); |
||
1558 | end |
||
1559 | end |
||
1560 | end |
||
1561 | |||
1562 | function NL_MouseOverNeedButton(frame) |
||
1563 | NL_SetTooltipOwner(frame:GetParent():GetParent(), "ANCHOR_TOPLEFT"); |
||
1564 | local tooltipText = ""; |
||
1565 | if( NL_BUFF_SPELLS[NL_PLAYERCLASS] and NL_BUFF_SPELLS[NL_PLAYERCLASS][frame.NeedName] and NL_BUFF_SPELLS[NL_PLAYERCLASS][frame.NeedName][1] ) then |
||
1566 | if( NL_BUFF_SPELLS[NL_PLAYERCLASS] and NL_BUFF_SPELLS[NL_PLAYERCLASS][frame.NeedName] ) then |
||
1567 | if( NL_BUFF_SPELLS[NL_PLAYERCLASS][frame.NeedName][1] ) then |
||
1568 | tooltipText = "Left-click to cast " .. NL_BUFF_SPELLS[NL_PLAYERCLASS][frame.NeedName][1] .. "."; |
||
1569 | end |
||
1570 | if( NL_BUFF_SPELLS[NL_PLAYERCLASS][frame.NeedName][2] ) then |
||
1571 | tooltipText = tooltipText .. "\nRight-click to cast " .. NL_BUFF_SPELLS[NL_PLAYERCLASS][frame.NeedName][2] .. "."; |
||
1572 | end |
||
1573 | end |
||
1574 | elseif( NL_ENCHANT_SPELLS[NL_PLAYERCLASS] and NL_ENCHANT_SPELLS[NL_PLAYERCLASS][frame.NeedName] and NL_ENCHANT_SPELLS[NL_PLAYERCLASS][frame.NeedName][1] ) then |
||
1575 | if( NL_PLAYERCLASS == "Rogue" ) then |
||
1576 | tooltipText = "Needs " .. NL_ENCHANT_SPELLS[NL_PLAYERCLASS][frame.NeedName][1] .. "."; |
||
1577 | else |
||
1578 | tooltipText = "Needs " .. NL_ENCHANT_SPELLS[NL_PLAYERCLASS][frame.NeedName][1] .. ".\nClick here to fix."; |
||
1579 | end |
||
1580 | elseif( frame.NeedName == "Resurrection" ) then |
||
1581 | if( NL_CURE_SPELLS[NL_PLAYERCLASS] and NL_CURE_SPELLS[NL_PLAYERCLASS].Resurrection ) then |
||
1582 | tooltipText = "Left-click to cast " .. NL_CURE_SPELLS[NL_PLAYERCLASS].Resurrection[1] .. "."; |
||
1583 | end |
||
1584 | elseif( frame.NeedName == "WellFed" ) then |
||
1585 | tooltipText = "Needs to be well fed."; |
||
1586 | elseif( frame.NeedName == "Health" ) then |
||
1587 | tooltipText = "Needs healing."; |
||
1588 | if( NLConfig.HealSpells ) then |
||
1589 | if( NLConfig.HealSpells[1] ) then |
||
1590 | tooltipText = tooltipText .. "\nLeft-click to cast " .. NLConfig.HealSpells[1] .. "."; |
||
1591 | end |
||
1592 | if( NLConfig.HealSpells[2] ) then |
||
1593 | tooltipText = tooltipText .. "\nRight-click to cast " .. NLConfig.HealSpells[2] .. "."; |
||
1594 | end |
||
1595 | if( NLConfig.HealSpells[3] ) then |
||
1596 | tooltipText = tooltipText .. "\nMiddle-click to cast " .. NLConfig.HealSpells[3] .. "."; |
||
1597 | end |
||
1598 | if( NLConfig.HealSpells[4] ) then |
||
1599 | tooltipText = tooltipText .. "\nClick button 4 to cast " .. NLConfig.HealSpells[4] .. "."; |
||
1600 | end |
||
1601 | if( NLConfig.HealSpells[5] ) then |
||
1602 | tooltipText = tooltipText .. "\nClick button 5 to cast " .. NLConfig.HealSpells[5] .. "."; |
||
1603 | end |
||
1604 | end |
||
1605 | if( tooltipText == "Needs healing." ) then |
||
1606 | tooltipText = tooltipText .. "\nUse 'Configure Spells' from the configuration window to add heal spells."; |
||
1607 | end |
||
1608 | elseif( frame.NeedName == "Mana" ) then |
||
1609 | tooltipText = "Needs mana.\nLeft-click to cast Innervate."; |
||
1610 | else |
||
1611 | tooltipText = "Needs cure for " .. frame.NeedName .. "."; |
||
1612 | if( NL_CURE_SPELLS[NL_PLAYERCLASS] and NL_CURE_SPELLS[NL_PLAYERCLASS][frame.NeedName] ) then |
||
1613 | if( NL_CURE_SPELLS[NL_PLAYERCLASS][frame.NeedName][1] ) then |
||
1614 | tooltipText = tooltipText .. "\nLeft-click to cast " .. NL_CURE_SPELLS[NL_PLAYERCLASS][frame.NeedName][1] .. "."; |
||
1615 | end |
||
1616 | if( NL_CURE_SPELLS[NL_PLAYERCLASS][frame.NeedName][2] ) then |
||
1617 | tooltipText = tooltipText .. "\nRight-click to cast " .. NL_CURE_SPELLS[NL_PLAYERCLASS][frame.NeedName][2] .. "."; |
||
1618 | end |
||
1619 | end |
||
1620 | end |
||
1621 | GameTooltip:SetText( tooltipText ); |
||
1622 | end |
||
1623 | |||
1624 | function NL_CureTopNeed(button) |
||
1625 | for NL_ITERATOR = 0, NL_NUM_NEEDY_UNITS - 1 do |
||
1626 | if( NL_SLOTS[NL_ITERATOR] and NL_SLOTS[NL_ITERATOR].TopNeed and NL_SLOTS[NL_ITERATOR].TopNeed > 1 and NL_SLOTS[NL_ITERATOR].Unit ) then |
||
1627 | NL_CureNeedOnUnit( NLConfig.Needs[NL_SLOTS[NL_ITERATOR].TopNeed].Name, NL_SLOTS[NL_ITERATOR].Unit, button ); |
||
1628 | return; |
||
1629 | end |
||
1630 | end |
||
1631 | end |
||
1632 | |||
1633 | function NL_SortList() |
||
1634 | if( NL_MOUSE_IN_FRAME ) then |
||
1635 | NL_MOUSE_IN_FRAME = false; |
||
1636 | NL_SortAllVisibleFrames(); |
||
1637 | NL_MOUSE_IN_FRAME = true; |
||
1638 | else |
||
1639 | NL_SortAllVisibleFrames(); |
||
1640 | end |
||
1641 | end |