vanilla-wow-addons – Blame information for rev 1

Subversion Repositories:
Rev:
Rev Author Line No. Line
1 office 1 -- //////////////////////////////////////////////////////////////////////////////////////
2 -- //
3 -- // BuffWatch
4 -- // by Pup
5 -- //
6 -- // TODO: (possibly)
7 -- //
8 -- // Base resize on num players visible/buffs vis (store and count when scanning)
9 -- //
10 -- // Ignore dead / disconn in threshold count
11 -- // Window doesnt always properly resize
12 -- // Update ResizeWindow to run no more than once every 2 secs
13 -- // Option to split into columns (previous changes might suffice)
14 -- // Localisation for various bits of text
15 -- // Keybinding to scan list and recast any expired buffs
16 -- // Show poisons and weapon buffs for player
17 -- // Lower spell rank support
18 -- // Allow cleansing of debuffs
19 -- // UI Scaling
20 -- //
21 -- // CHANGES:
22 -- //
23 -- // Added option to restrict buff updates
24 -- // Fixed a couple of bugs as a result of 1.11
25 -- //
26 -- //////////////////////////////////////////////////////////////////////////////////////
27 -- //////////////////////////////////////////////////////////////////////////////////////
28 -- //
29 -- // Variables
30 -- //
31 -- //////////////////////////////////////////////////////////////////////////////////////
32  
33 BINDING_HEADER_BUFFWATCHHEADER = "BuffWatch"
34 BW_VERSION = "1.15"
35 BW_RELEASE_DATE = "June 25, 2006"
36 BW_SORTORDER_DROPDOWN_LIST = {
37 "Raid Order",
38 "Class",
39 "Name"
40 }
41  
42 BuffWatchConfig = { alpha, rightMouseSpell, show_on_startup, ShowPets,
43 ShowCastableBuffs, ShowDebuffs, ShowDispellableDebuffs, DebuffsAlwaysVisible,
44 AlignBuffs, ExpiredWarning, ExpiredSound, SortOrder, BuffThreshold, HighlightPvP,
45 PreventPvPBuff, UpdPerSec, ShowUpdPerSec }
46  
47 local lastspellcast
48 local lastgrouptype
49 local buttonalignposition = 0
50 local buttonalignid
51 local buffexpired
52 local minimized = false
53 local HideUnmonitored = false
54 local HideMonitored = false
55  
56 local Player_Info = { }
57 local Player_Left = { }
58 local UNIT_IDs = { }
59  
60 local GroupBuffs = { }
61  
62 local BuffUpdateTime
63 local LastBuffStatusUpdated
64 local BuffUpdatePending = false
65 local UpdPerSec = { }
66 local CurrSec = 0
67 local SAMPLE_SIZE = 10
68  
69 -- //////////////////////////////////////////////////////////////////////////////////////
70 -- //
71 -- // Events
72 -- //
73 -- //////////////////////////////////////////////////////////////////////////////////////
74  
75 function BW_OnLoad()
76  
77 this:RegisterEvent("PLAYER_LOGIN")
78 this:RegisterEvent("PARTY_MEMBERS_CHANGED")
79 this:RegisterEvent("RAID_ROSTER_UPDATE")
80 this:RegisterEvent("SPELLCAST_START")
81 this:RegisterEvent("UNIT_AURA")
82 this:RegisterEvent("UNIT_PET")
83 this:RegisterEvent("UNIT_PVP_UPDATE")
84 this:RegisterEvent("VARIABLES_LOADED")
85  
86 SlashCmdList["BUFFWATCH"] = BW_SlashHandler
87 SLASH_BUFFWATCH1 = "/buffwatch"
88 SLASH_BUFFWATCH2 = "/bw"
89  
90 end
91  
92  
93 function BW_OnEvent()
94  
95 if event == "VARIABLES_LOADED" then
96  
97 -----------------------
98 -- support for myAddons
99 -----------------------
100 if(myAddOnsFrame_Register) then
101 BuffWatchDetails = {
102 name = "BuffWatch",
103 description = "Keeps track of party/raid buffs",
104 version = BW_VERSION,
105 releaseDate = BW_RELEASE_DATE,
106 author = "Pup",
107 category = MYADDONS_CATEGORY_OTHERS,
108 frame = "BW",
109 optionsframe = "BW_Options"
110 }
111  
112 BuffWatchHelp = { " - BuffWatch Usage - v " .. BW_VERSION .. "-\n\n" ..
113 " Show/Hide the BuffWatch window:\n - Bind a keyboard button to show/hide the window\n" ..
114 " - You can also close it by right clicking the \"BuffWatch\" label (appears on mouseover)\n\n" ..
115 " Showing Buffs:\n - Left click the BuffWatch label\n - Also occurs automatically whenever your gain/lose a party or raid member\n\n" ..
116 " Locking a player's watched buffs:\n - If the checkbox to the left is unchecked, buffs will be added automatically whenever they gain a buff\n" ..
117 " - If checked, buffs will not be added\n\n",
118 " Rebuffing:\n - Left click an icon (will auto-target)\n\n" ..
119 " Right click spell:\n" ..
120 " - Cast any spell with a cast time (not instant).\n Then type \"/bw set\"\n - To cast it, right click any icon (will auto-target)\n\n" ..
121 " Deleting buffs:\n - Lock the player's buffs (check the box).\n Then [ CTRL + Right Click ] on the buff\n" ..
122 " - Optionally, [ ALT + Right Click ] to delete all but the selected one.\n\n",
123 " Slash Commands ( Use /buffwatch or /bw )\n" ..
124 " - /bw toggle : shows/hides the window\n" ..
125 " - /bw options : shows/hides the options window\n" ..
126 " - /bw : shows this help menu :)\n\n" ..
127 " Verbosity:\n" ..
128 " - Hold [ Shift ] while left or right-clicking a buff icon to send a cast message to your party\n"
129 }
130  
131 myAddOnsFrame_Register(BuffWatchDetails, BuffWatchHelp)
132 end
133  
134 ---------------------
135 -- support for Cosmos
136 ---------------------
137 if EarthFeature_AddButton then
138 EarthFeature_AddButton({
139 id = "BuffWatch";
140 name = "BuffWatch";
141 subtext = "Buff monitoring";
142 tooltip = "Monitor Party or Raid buffs";
143 icon = "Interface\\Icons\\INV_Misc_Spyglass_03";
144 callback = BW_OptionsToggle;
145 test = nil
146 })
147 elseif Cosmos_RegisterButton then
148 Cosmos_RegisterButton(
149 "BuffWatch",
150 "Buff monitoring",
151 "Monitor Party or Raid buffs",
152 "Interface\\Icons\\INV_Misc_Spyglass_03",
153 BW_OptionsToggle
154 )
155 end
156  
157 --------------------
158 -- support for CTMod
159 --------------------
160 if CT_RegisterMod then
161 CT_RegisterMod(
162 "BuffWatch",
163 "Buff monitoring",
164 5,
165 "Interface\\Icons\\INV_Misc_Spyglass_03",
166 "Monitor Party or Raid buffs",
167 "switch",
168 "",
169 BW_OptionsToggle
170 )
171 end
172  
173 BW_Print("BuffWatch loaded. Please type \"/buffwatch\" or \"/bw\" for usage. Use \"/bw toggle\" to show window.", 0.2, 0.9, 0.9 )
174  
175 BW_HeaderText:SetText("BuffWatch")
176 BW_HeaderText:SetTextColor(0.2, 0.9, 0.9)
177 BW_Background:SetBackdropBorderColor(0, 0, 0)
178  
179 if BuffWatchConfig.alpha == nil then
180 BuffWatchConfig.alpha = 0.5
181 end
182  
183 BW_Background:SetAlpha(BuffWatchConfig.alpha)
184  
185 if BuffWatchConfig.show_on_startup == nil then
186 BuffWatchConfig.show_on_startup = true
187 BW:Show()
188 elseif BuffWatchConfig.show_on_startup == true then
189 BW:Show()
190 elseif BuffWatchConfig.show_on_startup == false then
191 BW:Hide()
192 end
193  
194 if BuffWatchConfig.ShowPets == nil then
195 BuffWatchConfig.ShowPets = true
196 end
197  
198 if BuffWatchConfig.ShowCastableBuffs == nil then
199 BuffWatchConfig.ShowCastableBuffs = false
200 end
201  
202 if BuffWatchConfig.ShowDebuffs == nil then
203 BuffWatchConfig.ShowDebuffs = true
204 end
205  
206 if BuffWatchConfig.ShowDispellableDebuffs == nil then
207 BuffWatchConfig.ShowDispellableDebuffs = false
208 end
209  
210 if BuffWatchConfig.DebuffsAlwaysVisible == nil then
211 BuffWatchConfig.DebuffsAlwaysVisible = true
212 end
213  
214 if BuffWatchConfig.AlignBuffs == nil then
215 BuffWatchConfig.AlignBuffs = true
216 end
217  
218 if BuffWatchConfig.ExpiredWarning == nil then
219 BuffWatchConfig.ExpiredWarning = true
220 end
221  
222 if BuffWatchConfig.ExpiredSound == nil then
223 BuffWatchConfig.ExpiredSound = false
224 end
225  
226 if BuffWatchConfig.SortOrder == nil then
227 BuffWatchConfig.SortOrder = BW_SORTORDER_DROPDOWN_LIST[1]
228 end
229  
230 if BuffWatchConfig.BuffThreshold == nil then
231 BuffWatchConfig.BuffThreshold = 0
232 end
233  
234 if BuffWatchConfig.HighlightPvP == nil then
235 BuffWatchConfig.HighlightPvP = false
236 end
237  
238 if BuffWatchConfig.PreventPvPBuff == nil then
239 BuffWatchConfig.PreventPvPBuff = false
240 end
241  
242 if BuffWatchConfig.UpdPerSec == nil then
243 BuffWatchConfig.UpdPerSec = 0
244 end
245  
246 if BuffWatchConfig.ShowUpdPerSec == nil then
247 BuffWatchConfig.ShowUpdPerSec = false
248 end
249  
250 -- Mark of the Wild (Same icon as Gift of the Wild)
251 GroupBuffs["Interface\\Icons\\Spell_Nature_Regeneration"] = {
252 ["Greater"] = "Gift of the Wild",
253 ["Type"] = "SubGroup",
254 ["ByName"] = 1
255 }
256  
257 -- Power Word Fortitude
258 GroupBuffs["Interface\\Icons\\Spell_Holy_WordFortitude"] = {
259 ["Greater"] = "Interface\\Icons\\Spell_Holy_PrayerOfFortitude",
260 ["Type"] = "SubGroup"
261 }
262 -- Prayer of Fortitude
263 GroupBuffs["Interface\\Icons\\Spell_Holy_PrayerOfFortitude"] = {
264 ["Lesser"] = "Interface\\Icons\\Spell_Holy_WordFortitude",
265 ["Type"] = "SubGroup"
266 }
267 -- Divine Spirit
268 GroupBuffs["Interface\\Icons\\Spell_Holy_DivineSpirit"] = {
269 ["Greater"] = "Interface\\Icons\\Spell_Holy_PrayerofSpirit",
270 ["Type"] = "SubGroup"
271 }
272 -- Prayer of Spirit
273 GroupBuffs["Interface\\Icons\\Spell_Holy_PrayerofSpirit"] = {
274 ["Lesser"] = "Interface\\Icons\\Spell_Holy_DivineSpirit",
275 ["Type"] = "SubGroup"
276 }
277 -- Shadow Protection
278 GroupBuffs["Interface\\Icons\\Spell_Shadow_AntiShadow"] = {
279 ["Greater"] = "Interface\\Icons\\Spell_Holy_PrayerofShadowProtection",
280 ["Type"] = "SubGroup"
281 }
282 -- Prayer of Shadow Protection
283 GroupBuffs["Interface\\Icons\\Spell_Holy_PrayerofShadowProtection"] = {
284 ["Lesser"] = "Interface\\Icons\\Spell_Shadow_AntiShadow",
285 ["Type"] = "SubGroup"
286 }
287 -- Arcane Intellect
288 GroupBuffs["Interface\\Icons\\Spell_Holy_MagicalSentry"] = {
289 ["Greater"] = "Interface\\Icons\\Spell_Holy_ArcaneIntellect",
290 ["Type"] = "SubGroup"
291 }
292 -- Arcane Brilliance
293 GroupBuffs["Interface\\Icons\\Spell_Holy_ArcaneIntellect"] = {
294 ["Lesser"] = "Interface\\Icons\\Spell_Holy_MagicalSentry",
295 ["Type"] = "SubGroup"
296 }
297 -- Blessing of Might
298 GroupBuffs["Interface\\Icons\\Spell_Holy_FistOfJustice"] = {
299 ["Greater"] = "Interface\\Icons\\Spell_Holy_GreaterBlessingofKings",
300 ["Type"] = "Class"
301 }
302 -- Greater Blessing of Might
303 GroupBuffs["Interface\\Icons\\Spell_Holy_GreaterBlessingofKings"] = {
304 ["Lesser"] = "Interface\\Icons\\Spell_Holy_FistOfJustice",
305 ["Type"] = "Class"
306 }
307 -- Blessing of Wisdom
308 GroupBuffs["Interface\\Icons\\Spell_Holy_SealOfWisdom"] = {
309 ["Greater"] = "Interface\\Icons\\Spell_Holy_GreaterBlessingofWisdom",
310 ["Type"] = "Class"
311 }
312 -- Greater Blessing of Wisdom
313 GroupBuffs["Interface\\Icons\\Spell_Holy_GreaterBlessingofWisdom"] = {
314 ["Lesser"] = "Interface\\Icons\\Spell_Holy_SealOfWisdom",
315 ["Type"] = "Class"
316 }
317 -- Blessing of Salvation
318 GroupBuffs["Interface\\Icons\\Spell_Holy_SealOfSalvation"] = {
319 ["Greater"] = "Interface\\Icons\\Spell_Holy_GreaterBlessingofSalvation",
320 ["Type"] = "Class"
321 }
322 -- Greater Blessing of Salvation
323 GroupBuffs["Interface\\Icons\\Spell_Holy_GreaterBlessingofSalvation"] = {
324 ["Lesser"] = "Interface\\Icons\\Spell_Holy_SealOfSalvation",
325 ["Type"] = "Class"
326 }
327 -- Blessing of Kings
328 GroupBuffs["Interface\\Icons\\Spell_Magic_MageArmor"] = {
329 ["Greater"] = "Interface\\Icons\\Spell_Magic_GreaterBlessingofKings",
330 ["Type"] = "Class"
331 }
332 -- Greater Blessing of Kings
333 GroupBuffs["Interface\\Icons\\Spell_Magic_GreaterBlessingofKings"] = {
334 ["Lesser"] = "Interface\\Icons\\Spell_Magic_MageArmor",
335 ["Type"] = "Class"
336 }
337 -- Blessing of Light
338 GroupBuffs["Interface\\Icons\\Spell_Holy_PrayerOfHealing02"] = {
339 ["Greater"] = "Interface\\Icons\\Spell_Holy_GreaterBlessingofLight",
340 ["Type"] = "Class"
341 }
342 -- Greater Blessing of Light
343 GroupBuffs["Interface\\Icons\\Spell_Holy_GreaterBlessingofLight"] = {
344 ["Lesser"] = "Interface\\Icons\\Spell_Holy_PrayerOfHealing02",
345 ["Type"] = "Class"
346 }
347 -- Blessing of Sanctuary
348 GroupBuffs["Interface\\Icons\\Spell_Nature_LightningShield"] = {
349 ["Greater"] = "Interface\\Icons\\Spell_Holy_GreaterBlessingofSanctuary",
350 ["Type"] = "Class"
351 }
352 -- Greater Blessing of Sanctuary
353 GroupBuffs["Interface\\Icons\\Spell_Holy_GreaterBlessingofSanctuary"] = {
354 ["Lesser"] = "Interface\\Icons\\Spell_Nature_LightningShield",
355 ["Type"] = "Class"
356 }
357  
358 if LastBuffStatusUpdate == nil then
359 LastBuffStatusUpdate = math.floor(GetTime())
360 BuffUpdateTime = GetTime()
361 end
362  
363 UpdPerSec = { }
364  
365 for i = 0, SAMPLE_SIZE - 1 do
366 UpdPerSec[i] = 0
367 end
368  
369 BW_Options_Init()
370  
371 BW_PlayersFrame:Show()
372  
373 end
374  
375 if BW:IsVisible() then
376  
377 if event == "PLAYER_LOGIN" then
378  
379 BW_Set_UNIT_IDs()
380 BW_GetAllBuffs()
381 BW_ResizeWindow()
382 end
383  
384 if event == "SPELLCAST_START" then
385 lastspellcast = arg1
386 end
387  
388 if event == "UNIT_AURA" then
389  
390 --BW_Print("UNIT_AURA for " .. arg1)
391  
392 for k, v in Player_Info do
393  
394 if arg1 == v.UNIT_ID then
395 --BW_Print(arg1 .. " found as " .. v.Name)
396 BW_Player_GetBuffs(v)
397 BW_Player_AdjustBuffs(v)
398 BW_ResizeWindow()
399 break
400 end
401  
402 end
403  
404 BW_UpdateBuffStatus()
405  
406 end
407  
408 if event == "PARTY_MEMBERS_CHANGED" or event == "RAID_ROSTER_UPDATE" or (event == "UNIT_PET" and BuffWatchConfig.ShowPets == true) then
409  
410 BW_Set_UNIT_IDs()
411 BW_GetAllBuffs()
412 BW_ResizeWindow()
413  
414 end
415  
416 if event == "UNIT_PVP_UPDATE" then
417  
418 local unitpet = BW_GetPetUnitID(arg1)
419  
420 for k, v in Player_Info do
421  
422 if arg1 == v.UNIT_ID or unitpet == v.UNIT_ID then
423 BW_Player_ColourName(v)
424 end
425  
426 end
427  
428 end
429  
430 end
431  
432 end
433  
434  
435 -- //////////////////////////////////////////////////////////////////////////////////////
436 -- //
437 -- // Main Functions
438 -- //
439 -- //////////////////////////////////////////////////////////////////////////////////////
440  
441 -- Setup basic list of possible UNIT_IDs
442 function BW_Set_UNIT_IDs(forced)
443  
444 local numRaidMembers = GetNumRaidMembers()
445  
446 if numRaidMembers > 0 then
447  
448 if lastgrouptype ~= "raid" or forced == true then
449  
450 UNIT_IDs = { }
451  
452 for i = 1, 40 do
453 UNIT_IDs[i] = "raid" .. i
454 end
455  
456 if BuffWatchConfig.ShowPets == true then
457 for i = 1, 40 do
458 UNIT_IDs[i+40] = "raidpet" .. i
459 end
460 end
461  
462 lastgrouptype = "raid"
463  
464 end
465  
466 elseif lastgrouptype ~= "party" or forced == true then
467  
468 UNIT_IDs = { }
469  
470 UNIT_IDs[1] = "player"
471 UNIT_IDs[2] = "party1"
472 UNIT_IDs[3] = "party2"
473 UNIT_IDs[4] = "party3"
474 UNIT_IDs[5] = "party4"
475  
476 if BuffWatchConfig.ShowPets == true then
477 UNIT_IDs[6] = "pet"
478 UNIT_IDs[7] = "partypet1"
479 UNIT_IDs[8] = "partypet2"
480 UNIT_IDs[9] = "partypet3"
481 UNIT_IDs[10] = "partypet4"
482 end
483  
484 lastgrouptype = "party"
485  
486 end
487  
488 BW_GetPlayerInfo()
489  
490 end
491  
492 --[[ Get details of each player we find in the UNIT_IDs list
493  
494 Player_Info[Name] props :
495  
496 ID - Unique number for this player, determines which playerframe to use
497 UNIT_ID - UNIT_ID of this player
498 Name - Players name (same as key, but useful if we are just looping array)
499 Class - Players Class (for colouring name)
500 IsPet - true if a pet (pets are sorted last, and can be hidden)
501 SubGroup - 1 if in party, or 1-8 if in raid (Used for sorting)
502 Checked - Used only in this function to determine players that are no longer present
503 ]] --
504 function BW_GetPlayerInfo()
505  
506 local getnewalignpos = false
507  
508 for i = 1, table.getn(UNIT_IDs) do
509  
510 local unitname = UnitName(UNIT_IDs[i])
511  
512 if unitname ~= nil and unitname ~= "Unknown Entity" then
513  
514 -- Check if we know about this person already, if not capture basic details
515 if not Player_Info[unitname] then
516  
517 local id = BW_GetNextID(unitname)
518 local namebutton = getglobal("BW_Player" .. id .. "_Name")
519 local nametext = getglobal("BW_Player" .. id .. "_NameText")
520  
521 Player_Info[unitname] = { }
522 Player_Info[unitname]["ID"] = id
523 Player_Info[unitname]["Name"] = unitname
524  
525 local _, classname = UnitClass(UNIT_IDs[i])
526  
527 if classname then
528 Player_Info[unitname]["Class"] = classname
529 else
530 Player_Info[unitname]["Class"] = ""
531 end
532  
533 if (lastgrouptype == "party" and i > 5) or (lastgrouptype == "raid" and i > 40) then
534 Player_Info[unitname]["IsPet"] = 1
535 Player_Info[unitname]["Class"] = ""
536 else
537 Player_Info[unitname]["IsPet"] = 0
538 end
539  
540 nametext:SetText(unitname)
541 namebutton:SetWidth(nametext:GetStringWidth())
542  
543 if buttonalignposition < nametext:GetStringWidth() then
544 buttonalignposition = nametext:GetStringWidth()
545 buttonalignid = id
546 end
547  
548 Player_Info[unitname]["UNIT_ID"] = UNIT_IDs[i]
549 BW_Player_ColourName(Player_Info[unitname])
550  
551 end
552  
553 -- Update any information that may have changed about this person,
554 -- if we captured before, or take for first time
555 Player_Info[unitname]["UNIT_ID"] = UNIT_IDs[i]
556  
557 if lastgrouptype == "raid" then
558 local j = math.mod(i, 40)
559 if j == 0 then j = 40 end
560 _, _, Player_Info[unitname]["SubGroup"] = GetRaidRosterInfo(j)
561 else
562 Player_Info[unitname]["SubGroup"] = 1
563 end
564  
565 Player_Info[unitname]["Checked"] = 1
566  
567 end
568  
569 end
570  
571 -- Remove players that are no longer in the group
572 for k, v in Player_Info do
573  
574 if v.Checked == 1 then
575 v.Checked = 0
576 else
577 getglobal("BW_Player" .. v.ID):Hide()
578 getglobal("BW_Player" .. v.ID .. "_NameText"):SetText(nil)
579  
580 if v.ID == buttonalignid then
581 getnewalignpos = true
582 end
583  
584 -- Add ID to temp array in case they come back
585 -- (useful for dismissed or dead pets, or if a player leaves group briefly)
586 Player_Left[v.Name] = v.ID
587  
588 Player_Info[k] = nil
589 end
590  
591 end
592  
593 if getnewalignpos == true then
594  
595 buttonalignposition = 0
596  
597 for k, v in Player_Info do
598  
599 local nametext = getglobal("BW_Player" .. v.ID .. "_NameText")
600  
601 if buttonalignposition < nametext:GetStringWidth() then
602 buttonalignposition = nametext:GetStringWidth()
603 buttonalignid = v.ID
604 end
605  
606 end
607  
608 end
609  
610 end
611  
612 function BW_GetAllBuffs()
613  
614 -- Setup temp array for sorting, and get buffs for all players
615 for k, v in Player_Info do
616 BW_Player_GetBuffs(v)
617 end
618  
619 -- ***** Does this need to be called here?
620 BW_Player_AdjustFrames()
621  
622 -- Adjust buff icon positions
623 for k, v in Player_Info do
624 BW_Player_AdjustBuffs(v)
625 end
626  
627 end
628  
629  
630 function BW_Player_AdjustFrames()
631  
632 -- Only bother to sort player frames if we can see them
633 if not minimized then
634  
635 local firstplayer = true
636 local previousplayer
637 local Player_Copy = { }
638  
639 for k, v in Player_Info do
640 table.insert(Player_Copy, v)
641 end
642  
643 -- Sort the player list in temp array
644 if BuffWatchConfig.SortOrder == "Class" then
645  
646 table.sort(Player_Copy,
647 function(a,b)
648  
649 if a.IsPet == b.IsPet then
650  
651 if a.Class == b.Class then
652 return a.Name < b.Name
653 else
654 return a.Class < b.Class
655 end
656  
657 else
658 return a.IsPet < b.IsPet
659 end
660  
661 end)
662  
663 elseif BuffWatchConfig.SortOrder == "Name" then
664  
665 table.sort(Player_Copy,
666 function(a,b)
667  
668 if a.IsPet == b.IsPet then
669 return a.Name < b.Name
670 else
671 return a.IsPet < b.IsPet
672 end
673  
674 end)
675  
676 else -- Default
677  
678 table.sort(Player_Copy,
679 function(a,b)
680  
681 if a.IsPet == b.IsPet then
682  
683 if a.SubGroup == b.SubGroup then
684 return a.UNIT_ID < b.UNIT_ID
685 else
686 return a.SubGroup < b.SubGroup
687 end
688  
689 else
690 return a.IsPet < b.IsPet
691 end
692  
693 end)
694 end
695  
696 -- Position the player frames
697 for k, v in Player_Copy do
698  
699 local playerframe = getglobal("BW_Player" .. v.ID)
700  
701 playerframe:ClearAllPoints()
702  
703 if playerframe:IsVisible() then
704  
705 if firstplayer then
706 playerframe:SetPoint("TOPLEFT", "BW_Background", "TOPLEFT", 1, -16)
707 previousplayer = v.ID
708 firstplayer = false
709 else
710 playerframe:SetPoint("TOPLEFT", "BW_Player" .. previousplayer, "BOTTOMLEFT", 0, 0)
711 previousplayer = v.ID
712 end
713  
714 end
715  
716 end
717  
718 end
719  
720 end
721  
722  
723 function BW_Player_GetBuffs(v)
724  
725 local curr_lock = getglobal("BW_Player" .. v.ID .. "_Lock")
726  
727 if not curr_lock:GetChecked() then
728  
729 for j = 1, 16 do
730  
731 local texture = UnitBuff(v.UNIT_ID, j, BuffWatchConfig.ShowCastableBuffs)
732 local curr_buff = getglobal("BW_Player" .. v.ID .. "_Buff" .. j)
733 local curr_buff_icon = getglobal("BW_Player" .. v.ID .. "_Buff" .. j .. "Icon")
734  
735 if texture == nil then
736  
737 curr_buff:Hide()
738 curr_buff_icon:SetTexture(nil)
739  
740 elseif texture then
741  
742 curr_buff:Show()
743 curr_buff_icon:SetTexture(texture)
744  
745 end
746  
747 end
748  
749 end
750  
751 for j = 1, 8 do
752  
753 local curr_buff = getglobal("BW_Player" .. v.ID .. "_Debuff" .. j)
754  
755 if BuffWatchConfig.ShowDebuffs == false then
756  
757 curr_buff:Hide()
758  
759 else
760  
761 local texture = UnitDebuff(v.UNIT_ID, j, BuffWatchConfig.ShowDispellableDebuffs)
762 local curr_buff_icon = getglobal("BW_Player" .. v.ID .. "_Debuff" .. j .. "Icon")
763  
764 if texture == nil then
765  
766 curr_buff:Hide()
767  
768 elseif texture then
769  
770 curr_buff:Show()
771 curr_buff_icon:SetTexture(texture)
772  
773 end
774  
775 end
776  
777 end
778  
779 end
780  
781  
782 function BW_Player_AdjustBuffs(v)
783  
784 local firstbutton = true
785 local previousbutton
786  
787 for j = 1, 16 do
788  
789 local curr_buff = getglobal("BW_Player" .. v.ID .. "_Buff" .. j)
790  
791 if curr_buff:IsVisible() then
792  
793 -- ***** Add code to sort this when buffs get hidden/shown, rather than refreshing all each time?
794 curr_buff:ClearAllPoints()
795  
796 if firstbutton then
797 if BuffWatchConfig.AlignBuffs == false then
798 curr_buff:SetPoint("TOPLEFT", "BW_Player" .. v.ID .. "_NameText", "TOPRIGHT", 5, 2)
799 else
800 curr_buff:SetPoint("TOPLEFT", "BW_Player" .. v.ID .. "_NameText", "TOPLEFT", buttonalignposition + 5, 2)
801 end
802 firstbutton = false
803 previousbutton = j
804 else
805 curr_buff:SetPoint("TOPLEFT", "BW_Player" .. v.ID .. "_Buff" .. previousbutton, "TOPRIGHT", 0, 0)
806 previousbutton = j
807 end
808  
809 end
810  
811 end
812  
813 local firstdebuff = true
814 local previousdebuff
815  
816 for j = 1, 8 do
817  
818 local curr_debuff = getglobal("BW_Player" .. v.ID .. "_Debuff" .. j)
819  
820 if curr_debuff:IsVisible() then
821  
822 -- ***** Add code to sort this when buffs get hidden/shown, rather than refreshing all each time?
823 curr_debuff:ClearAllPoints()
824  
825 if firstbutton then
826  
827 if BuffWatchConfig.AlignBuffs == false then
828 curr_debuff:SetPoint("TOPLEFT", "BW_Player" .. v.ID .. "_NameText", "TOPRIGHT", 5, 2)
829 else
830 curr_debuff:SetPoint("TOPLEFT", "BW_Player" .. v.ID .. "_NameText", "TOPLEFT", buttonalignposition + 5, 2)
831 end
832 firstbutton = false
833 previousbutton = j
834 firstdebuff = false
835 previousdebuff = j
836  
837 elseif firstdebuff then
838  
839 curr_debuff:SetPoint("TOPLEFT", "BW_Player" .. v.ID .. "_Buff" .. previousbutton, "TOPRIGHT", 0, 0)
840 firstdebuff = false
841 previousdebuff = j
842  
843 else
844  
845 curr_debuff:SetPoint("TOPLEFT", "BW_Player" .. v.ID .. "_Debuff" .. previousdebuff, "TOPRIGHT", 0, 0)
846 previousdebuff = j
847  
848 end
849  
850 end
851  
852 end
853  
854 end
855  
856  
857 function BW_ColourAllNames()
858  
859 for k, v in Player_Info do
860 BW_Player_ColourName(v)
861 end
862  
863 end
864  
865  
866 function BW_Player_ColourName(v)
867  
868 local nametext = getglobal("BW_Player" .. v.ID .. "_NameText")
869  
870 if BuffWatchConfig.HighlightPvP and UnitIsPVP(v.UNIT_ID) then
871  
872 nametext:SetTextColor(0.0, 1.0, 0.0)
873  
874 else
875  
876 if v.Class ~= "" then
877  
878 local color = RAID_CLASS_COLORS[v.Class]
879  
880 if color then
881 nametext:SetTextColor(color.r, color.g, color.b)
882 else
883 nametext:SetTextColor(1.0, 0.9, 0.8)
884 end
885  
886 else
887 nametext:SetTextColor(1.0, 0.9, 0.8)
888 end
889  
890 end
891  
892 end
893  
894  
895 function BW_ResizeWindow()
896  
897 local bottomcoord = 0
898 local height = 0
899 local rightcoord = 0
900 local width = 0
901  
902 for k, v in Player_Info do
903  
904 if not minimized then
905 local playerframe = getglobal("BW_Player" .. v.ID)
906  
907 if playerframe:GetBottom() ~= nil and playerframe:IsVisible() then
908 if bottomcoord > playerframe:GetBottom() or bottomcoord == 0 then
909 bottomcoord = playerframe:GetBottom()
910 end
911 end
912 end
913  
914 for j = 1, 16 do
915 local curr_buff = getglobal("BW_Player" .. v.ID .. "_Buff" .. j)
916  
917 if curr_buff:IsShown() and curr_buff:GetRight() then
918 if curr_buff:GetRight() > rightcoord then
919 rightcoord = curr_buff:GetRight()
920 end
921 end
922 end
923  
924 for j = 1, 8 do
925 local curr_buff = getglobal("BW_Player" .. v.ID .. "_Debuff" .. j)
926  
927 if curr_buff:IsShown() and curr_buff:GetRight() then
928 if curr_buff:GetRight() > rightcoord then
929 rightcoord = curr_buff:GetRight()
930 end
931 end
932 end
933  
934 end
935  
936 if minimized then
937 height = 20
938 else
939 if bottomcoord and bottomcoord ~= 0 then
940 if BuffWatchConfig.ShowUpdPerSec == true then
941 height = BW_Background:GetTop() - bottomcoord + 25
942 else
943 height = BW_Background:GetTop() - bottomcoord + 15
944 end
945 if height < 65 then height = 65 end
946 else
947 height = 65
948 end
949 end
950  
951 if rightcoord and rightcoord ~= 0 then
952 width = rightcoord - BW_Background:GetLeft() + 20
953 if width < 100 then width = 100 end
954 else
955 width = 100
956 end
957  
958 BW_Background:SetHeight(height)
959 BW:SetHeight(height)
960  
961 BW_Background:SetWidth(width)
962 BW:SetWidth(width)
963  
964 end
965  
966 function BW_UpdateUPS()
967  
968 local TimeDiff = math.floor(GetTime() - LastBuffStatusUpdate)
969  
970 if TimeDiff == 0 then
971 UpdPerSec[CurrSec] = UpdPerSec[CurrSec] + 1
972 elseif TimeDiff < SAMPLE_SIZE then
973  
974 for i = 0, TimeDiff - 2 do
975  
976 CurrSec = math.mod(CurrSec + 1, SAMPLE_SIZE)
977  
978 UpdPerSec[CurrSec] = 0
979  
980 end
981  
982 CurrSec = math.mod(CurrSec + 1, SAMPLE_SIZE)
983  
984 UpdPerSec[CurrSec] = 1
985  
986 else
987  
988 for i = 0, SAMPLE_SIZE - 1 do
989 UpdPerSec[i] = 0
990 end
991  
992 CurrSec = math.mod(CurrSec + TimeDiff, SAMPLE_SIZE)
993  
994 UpdPerSec[CurrSec] = 1
995  
996 end
997  
998 LastBuffStatusUpdate = math.floor(GetTime())
999  
1000 if BuffWatchConfig.ShowUpdPerSec == true then
1001  
1002 local UPS = 0
1003  
1004 for i = 0, SAMPLE_SIZE - 1 do
1005  
1006 UPS = UPS + UpdPerSec[i]
1007  
1008 end
1009  
1010 UPS = UPS / SAMPLE_SIZE
1011  
1012 BW_UPS:SetText("UPS = " .. format("%4.1f", UPS))
1013  
1014 end
1015  
1016 end
1017  
1018  
1019 function BW_UpdateBuffStatus(forced)
1020  
1021 if BuffWatchConfig.UpdPerSec > 0 then
1022  
1023 if (BuffUpdateTime + (1 / BuffWatchConfig.UpdPerSec) < GetTime()) or forced == true then
1024 BuffUpdateTime = GetTime()
1025 BuffUpdatePending = false
1026 else
1027 BuffUpdatePending = true
1028 return
1029 end
1030  
1031 end
1032  
1033 local hasbuffexpired = false
1034 local playerframechanges = false
1035  
1036 BW_UpdateUPS()
1037  
1038 for k, v in Player_Info do
1039  
1040 local player = "BW_Player" .. v.ID
1041 local playerframe = getglobal(player)
1042 local playerbuffexpired = false
1043 local playerhasbuffs = false
1044 local playerhasdebuffs = false
1045 local showframe = true
1046  
1047 if getglobal(player .. "_Lock"):GetChecked() then
1048  
1049 for j = 1, 16 do
1050  
1051 -- Check if there is a buff in this slot
1052 if getglobal(player .. "_Buff" .. j):IsShown() then
1053  
1054 playerhasbuffs = true
1055  
1056 -- If player is linkdead or dead in game, grey buffs out so user doesnt try to buff them
1057 if UnitIsDeadOrGhost(v.UNIT_ID) or UnitIsConnected(v.UNIT_ID) == nil then
1058  
1059 getglobal(player .. "_Buff" .. j .. "Icon"):SetVertexColor(0.4,0.4,0.4)
1060  
1061 else
1062  
1063 local Flag_BuffFound = false
1064 local texture = getglobal(player .. "_Buff" .. j .. "Icon"):GetTexture()
1065  
1066 -- See if we can find this buff on the player still
1067 for j_2 = 1, 16 do
1068 if UnitBuff(v.UNIT_ID, j_2) == texture then
1069 Flag_BuffFound = true
1070 break
1071 end
1072 end
1073  
1074 -- If not found, check if lesser or greater exists instead
1075 if Flag_BuffFound == false then
1076  
1077 if GroupBuffs[texture] and not GroupBuffs[texture].ByName then
1078  
1079 if GroupBuffs[texture].Lesser then
1080  
1081 texture = GroupBuffs[texture].Lesser
1082  
1083 elseif GroupBuffs[texture].Greater then
1084  
1085 texture = GroupBuffs[texture].Greater
1086  
1087 end
1088  
1089 for j_2 = 1, 16 do
1090 if UnitBuff(v.UNIT_ID, j_2) == texture then
1091 Flag_BuffFound = true
1092 getglobal(player .. "_Buff" .. j .. "Icon"):SetTexture(texture)
1093 break
1094 end
1095 end
1096  
1097 end
1098  
1099 end
1100  
1101 -- If buff has expired, highlight it red
1102 if Flag_BuffFound then
1103 getglobal(player .. "_Buff" .. j .. "Icon"):SetVertexColor(1,1,1)
1104 else
1105 getglobal(player .. "_Buff" .. j .. "Icon"):SetVertexColor(1,0,0)
1106  
1107 if BuffWatchConfig.ExpiredWarning and buffexpired ~= true then
1108 UIErrorsFrame:AddMessage("A buffwatch monitored buff has expired!", 0.2, 0.9, 0.9, 1.0, 2.0)
1109 buffexpired = true
1110  
1111 if BuffWatchConfig.ExpiredSound then
1112 PlaySound("igQuestFailed")
1113 end
1114  
1115 if minimized then
1116 BW_HeaderText:SetTextColor(1, 0, 0)
1117 end
1118  
1119 end
1120 hasbuffexpired = true
1121 playerbuffexpired = true
1122 end
1123  
1124 end
1125  
1126 end
1127  
1128 end
1129  
1130 if BuffWatchConfig.DebuffsAlwaysVisible == true then
1131  
1132 for j = 1, 8 do
1133  
1134 -- Check if there is a debuff in this slot
1135 if getglobal(player .. "_Debuff" .. j):IsShown() then
1136 playerhasdebuffs = true
1137 break
1138 end
1139  
1140 end
1141  
1142 end
1143  
1144 -- Determine whether we should show or hide this player
1145 if playerhasdebuffs == true then
1146 showframe = true
1147 else
1148  
1149 if HideMonitored == true then
1150  
1151 if HideUnmonitored == false then
1152  
1153 if playerhasbuffs == true then
1154 showframe = playerbuffexpired
1155 else
1156 showframe = true
1157 end
1158  
1159 else
1160 showframe = playerbuffexpired
1161 end
1162  
1163 else
1164  
1165 if HideUnmonitored == false then
1166 -- We are not hiding monitored or unmonitored, so show the playerframe
1167 showframe = true
1168 else
1169  
1170 -- Just hiding Unmonitored, so determine if any buffs are locked
1171 if playerhasbuffs == true then
1172 showframe = true
1173 else
1174 showframe = false
1175 end
1176  
1177 end
1178  
1179 end
1180  
1181 end
1182  
1183 else
1184 -- Player is unchecked, so show
1185 showframe = true
1186  
1187 -- Make sure buffs are not highlighted
1188 for j = 1, 16 do
1189  
1190 -- Check if there is a buff in this slot
1191 if getglobal(player .. "_Buff" .. j):IsShown() then
1192 getglobal(player .. "_Buff" .. j .. "Icon"):SetVertexColor(1,1,1)
1193 end
1194  
1195 end
1196  
1197 end
1198  
1199 if showframe == true then
1200 if not playerframe:IsShown() then
1201 playerframe:Show()
1202 playerframechanges = true
1203 end
1204 else
1205 if playerframe:IsShown() then
1206 playerframe:Hide()
1207 playerframechanges = true
1208 end
1209 end
1210  
1211 end
1212  
1213 buffexpired = hasbuffexpired
1214  
1215 if buffexpired == false then
1216 BW_HeaderText:SetTextColor(0.2, 0.9, 0.9)
1217 end
1218  
1219 if playerframechanges == true then
1220 BW_Player_AdjustFrames()
1221 end
1222  
1223 end
1224  
1225 -- //////////////////////////////////////////////////////////////////////////////////////
1226 -- //
1227 -- // Slash Commands
1228 -- //
1229 -- //////////////////////////////////////////////////////////////////////////////////////
1230  
1231 function BW_SlashHandler(msg)
1232  
1233 msg = string.lower(msg)
1234  
1235 if msg == "toggle" then
1236  
1237 BW_Toggle()
1238  
1239 elseif msg == "set" then
1240  
1241 BW_SetRightMouse()
1242  
1243 elseif msg == "options" then
1244  
1245 BW_OptionsToggle()
1246  
1247 elseif msg == "" or msg == "help" then
1248  
1249 BW_ShowHelp()
1250  
1251 else
1252  
1253 BW_Print("BuffWatch: Invalid Command or Parameter")
1254  
1255 end
1256  
1257 end
1258  
1259 -- //////////////////////////////////////////////////////////////////////////////////////
1260 -- //
1261 -- // Mouse Events
1262 -- //
1263 -- //////////////////////////////////////////////////////////////////////////////////////
1264  
1265 function BW_OnMouseDown(arg1)
1266 if arg1 == "LeftButton" then
1267 BW:StartMoving()
1268 end
1269 end
1270  
1271  
1272 function BW_OnMouseUp(arg1)
1273 if arg1 == "LeftButton" then
1274 BW:StopMovingOrSizing()
1275 end
1276 end
1277  
1278  
1279 function BW_MouseIsOverFrame()
1280  
1281 if MouseIsOver(BW) then
1282  
1283 BW_MinimizeButton:Show()
1284  
1285 if not minimized then
1286  
1287 BW_OptionsButton:Show()
1288 BW_HideUnmonitoredButton:Show()
1289 BW_HideMonitoredButton:Show()
1290 BW_Lock_All:Show()
1291  
1292 for k, v in Player_Info do
1293 getglobal("BW_Player" .. v.ID .. "_Lock"):Show()
1294 end
1295  
1296 else
1297 BW_Lock_All:Hide()
1298 end
1299  
1300 else
1301  
1302 if not minimized then
1303  
1304 BW_MinimizeButton:Hide()
1305 BW_OptionsButton:Hide()
1306 BW_HideUnmonitoredButton:Hide()
1307 BW_HideMonitoredButton:Hide()
1308  
1309 for k, v in Player_Info do
1310 getglobal("BW_Player" .. v.ID .. "_Lock"):Hide()
1311 end
1312 end
1313  
1314 BW_Lock_All:Hide()
1315  
1316 end
1317  
1318 end
1319  
1320  
1321 function BW_Check_Clicked()
1322  
1323 local checked = this:GetChecked()
1324  
1325 if checked then
1326  
1327 for k, v in Player_Info do
1328  
1329 local curr_lock = getglobal("BW_Player" .. v.ID .. "_Lock")
1330  
1331 -- if curr_lock:IsVisible() then
1332 if not curr_lock:GetChecked() then
1333 checked = nil
1334 break
1335 end
1336 -- end
1337  
1338 end
1339  
1340 if checked then
1341 BW_Lock_All:SetChecked(true)
1342 end
1343  
1344 else
1345 BW_Lock_All:SetChecked(false)
1346 end
1347  
1348 end
1349  
1350  
1351 function BW_Name_Clicked(button)
1352  
1353 local id = this:GetParent():GetID()
1354  
1355 local playername = getglobal("BW_Player" .. id .. "_NameText"):GetText()
1356  
1357 if button == "LeftButton" then
1358 TargetByName(playername)
1359 elseif button == "RightButton" then
1360 AssistByName(playername)
1361 end
1362  
1363 end
1364  
1365  
1366 function BW_Buff_Clicked(button)
1367  
1368 local buffid = this:GetID()
1369 local playerid = this:GetParent():GetID()
1370 local playername = getglobal("BW_Player" .. playerid .. "_NameText"):GetText()
1371 local playerframe = "BW_Player" .. playerid
1372  
1373 if button == "LeftButton" then
1374  
1375 local spellid = nil
1376 local spelltexture = getglobal(this:GetName() .. "Icon"):GetTexture()
1377  
1378 for i = 1, 300 do
1379 if GetSpellTexture(i, 1) == spelltexture then
1380 spellid = i
1381 end
1382 end
1383  
1384 if spellid then
1385  
1386 if BuffWatchConfig.PreventPvPBuff and UnitIsPVP(Player_Info[playername].UNIT_ID) then
1387  
1388 BW_Print(playername .. " is PvP Flagged, aborted casting.")
1389  
1390 elseif UnitIsVisible(Player_Info[playername].UNIT_ID) then
1391  
1392 if UnitName("target") and not UnitIsEnemy("target","player") then
1393 if UnitName("target") ~= playername then
1394 TargetByName(playername)
1395 end
1396 end
1397  
1398 if IsShiftKeyDown() then
1399 SendChatMessage(format("BW: Casting %s on %s", GetSpellName(spellid,1), playername), "PARTY")
1400 end
1401  
1402 -- Check if it's a group buff or a lesser version.
1403 if GroupBuffs[spelltexture] then
1404  
1405 local castgreater = false
1406 local newspelltexture = nil
1407  
1408 -- Check Buff Threshold for whether to cast single or group
1409 if BuffWatchConfig.BuffThreshold > 0 and
1410 (GetNumPartyMembers() >= (BuffWatchConfig.BuffThreshold - 1) or GetNumRaidMembers() >= BuffWatchConfig.BuffThreshold) then
1411  
1412 local castcount = 0
1413 local otherspelltexture
1414 local pvpflagfound
1415  
1416 if GroupBuffs[spelltexture].Greater then
1417 otherspelltexture = GroupBuffs[spelltexture].Greater
1418 else
1419 otherspelltexture = GroupBuffs[spelltexture].Lesser
1420 end
1421  
1422 -- Check if we have other spell, and save OtherSpellID
1423 if not GroupBuffs[spelltexture].OtherSpellID then
1424  
1425 if GroupBuffs[spelltexture].ByName then
1426  
1427 for i = 1, 300 do
1428 local spellName, _ = GetSpellName(i, 1)
1429 if spellName == otherspelltexture then
1430 GroupBuffs[spelltexture].OtherSpellID = i
1431 end
1432 end
1433  
1434 else
1435  
1436 for i = 1, 300 do
1437 if GetSpellTexture(i, 1) == otherspelltexture then
1438 GroupBuffs[spelltexture].OtherSpellID = i
1439 end
1440 end
1441  
1442 end
1443  
1444 if not GroupBuffs[spelltexture].OtherSpellID then
1445 -- Player doesnt have greater spell
1446 GroupBuffs[spelltexture].OtherSpellID = 0
1447 end
1448  
1449 end
1450  
1451 -- Check whether to cast greater or lesser. If we dont have greater, then skip.
1452 if GroupBuffs[spelltexture].OtherSpellID ~= 0 then
1453  
1454 for k, v in Player_Info do
1455  
1456 local Flag_BuffFound = false
1457  
1458 -- Find players with same SubGroup/Class
1459 if Player_Info[v.Name].IsPet == 0 and v[GroupBuffs[spelltexture].Type] == Player_Info[playername][GroupBuffs[spelltexture].Type] then
1460  
1461 if BuffWatchConfig.PreventPvPBuff then
1462  
1463 if UnitIsPVP(v.UNIT_ID) then
1464 pvpflagfound = v.Name -- Enforce a single buff to be cast
1465 end
1466  
1467 end
1468  
1469 -- Check for missing buff
1470 for j = 1, 16 do
1471 if UnitBuff(v.UNIT_ID, j) == spelltexture or UnitBuff(v.UNIT_ID, j) == otherspelltexture then
1472 Flag_BuffFound = true
1473 break
1474 end
1475 end
1476  
1477 if Flag_BuffFound == false then
1478 castcount = castcount + 1
1479 end
1480  
1481 end
1482  
1483 end
1484  
1485 if castcount >= BuffWatchConfig.BuffThreshold then
1486 if pvpflagfound then
1487 BW_Print(pvpflagfound .. " is PvP Flagged, casting single version buff.")
1488 else
1489 castgreater = true
1490 end
1491 end
1492  
1493 end
1494  
1495 end
1496  
1497 if castgreater then
1498 newspelltexture = GroupBuffs[spelltexture].Greater
1499 else
1500 newspelltexture = GroupBuffs[spelltexture].Lesser
1501 end
1502  
1503 if newspelltexture then
1504  
1505 if GroupBuffs[spelltexture].OtherSpellID then
1506  
1507 spellid = GroupBuffs[spelltexture].OtherSpellID
1508  
1509 else
1510  
1511 for i = 1, 300 do
1512 if GetSpellTexture(i, 1) == newspelltexture then
1513 spellid = i
1514 GroupBuffs[spelltexture].OtherSpellID = i
1515 end
1516 end
1517  
1518 end
1519  
1520 end
1521  
1522 end
1523  
1524 CastSpell(spellid, 1)
1525  
1526 if SpellIsTargeting() then
1527 TargetByName(playername)
1528 end
1529  
1530 else
1531  
1532 BW_Print(playername .. " is out of range or not visible.")
1533  
1534 end
1535  
1536 end
1537  
1538 elseif button == "RightButton" then
1539  
1540 if getglobal(playerframe .. "_Lock"):GetChecked() and IsControlKeyDown() then
1541  
1542 this:Hide()
1543 BW_Player_AdjustBuffs(Player_Info[playername])
1544 BW_ResizeWindow()
1545  
1546 elseif getglobal(playerframe .. "_Lock"):GetChecked() and IsAltKeyDown() then
1547  
1548 for i = 1, 16 do
1549 if i ~= buffid then
1550 getglobal(playerframe .. "_Buff" .. i):Hide()
1551 end
1552 end
1553  
1554 BW_Player_AdjustBuffs(Player_Info[playername])
1555 BW_ResizeWindow()
1556  
1557 else
1558  
1559 if BuffWatchConfig.rightMouseSpell then
1560 if UnitName("target") and not UnitIsEnemy("target","player") then
1561 if UnitName("target") ~= playername then
1562 TargetByName(playername)
1563 end
1564 end
1565  
1566 if IsShiftKeyDown() then
1567 SendChatMessage(format("BW: Casting %s on %s", GetSpellName(BuffWatchConfig.rightMouseSpell,1), playername), "PARTY")
1568 end
1569  
1570 CastSpell(BuffWatchConfig.rightMouseSpell,1)
1571  
1572 if SpellIsTargeting() then
1573 TargetByName(playername)
1574 end
1575  
1576 else
1577  
1578 BW_Print(" BuffWatch: Right mouse button spell has not yet been set.")
1579 BW_Print(" Cast any spell with a duration. Then type \"/bw set\"")
1580  
1581 end
1582  
1583 end
1584  
1585 end
1586  
1587 end
1588  
1589  
1590 function BW_Buff_Tooltip()
1591  
1592 local playername = getglobal("BW_Player" .. this:GetParent():GetID() .. "_NameText"):GetText()
1593 local buffbuttonid = nil
1594 local debuffbuttonid = nil
1595 local texture = getglobal(this:GetName() .. "Icon"):GetTexture()
1596  
1597 for i = 1, 16 do
1598 if UnitBuff(Player_Info[playername]["UNIT_ID"], i) == texture then
1599 buffbuttonid = i
1600 break
1601 end
1602 end
1603  
1604 if buffbuttonid == nil then
1605 for i_2 = 1, 8 do
1606 if UnitDebuff(Player_Info[playername]["UNIT_ID"], i_2) == texture then
1607 debuffbuttonid = i_2
1608 break
1609 end
1610 end
1611 end
1612  
1613 if buffbuttonid then
1614 GameTooltip:SetOwner(this, "ANCHOR_BOTTOMLEFT")
1615 GameTooltip:SetUnitBuff(Player_Info[playername]["UNIT_ID"], buffbuttonid)
1616 elseif debuffbuttonid then
1617 GameTooltip:SetOwner(this, "ANCHOR_BOTTOMLEFT")
1618 GameTooltip:SetUnitDebuff(Player_Info[playername]["UNIT_ID"], debuffbuttonid)
1619 end
1620  
1621 end
1622  
1623  
1624 function BW_Set_AllChecks(checked)
1625  
1626 for k, v in Player_Info do
1627 getglobal("BW_Player" .. v.ID .. "_Lock"):SetChecked(checked)
1628 end
1629  
1630 end
1631  
1632  
1633 function BW_Header_Clicked(button)
1634  
1635 if button == "LeftButton" then
1636 BW_Set_UNIT_IDs()
1637 BW_GetAllBuffs()
1638 BW_UpdateBuffStatus()
1639 BW_ResizeWindow()
1640 end
1641  
1642 if button == "RightButton" then
1643 BW_Toggle()
1644 end
1645  
1646 end
1647  
1648  
1649 function BW_MinimizeButton_Clicked()
1650  
1651 minimized = not minimized
1652  
1653 if minimized == true then
1654 BW_PlayersFrame:Hide()
1655 else
1656 BW_PlayersFrame:Show()
1657 end
1658  
1659 BW_ResizeWindow()
1660 BW_MouseIsOverFrame()
1661  
1662 end
1663  
1664 function BW_HideUnmonitored_Clicked()
1665  
1666 HideUnmonitored = not HideUnmonitored
1667  
1668 BW_Player_AdjustFrames()
1669 BW_ResizeWindow()
1670  
1671 BW_HideUnmonitored_OnEnter()
1672  
1673 end
1674  
1675 function BW_HideUnmonitored_OnEnter()
1676  
1677 GameTooltip:SetOwner(this, "ANCHOR_BOTTOM")
1678  
1679 if HideUnmonitored == true then
1680 GameTooltip:SetText("Hiding Unmonitored")
1681 else
1682 GameTooltip:SetText("Showing Unmonitored")
1683 end
1684  
1685 end
1686  
1687 function BW_HideMonitored_Clicked()
1688  
1689 HideMonitored = not HideMonitored
1690  
1691 BW_Player_AdjustFrames()
1692 BW_ResizeWindow()
1693  
1694 BW_HideMonitored_OnEnter()
1695  
1696 end
1697  
1698 function BW_HideMonitored_OnEnter()
1699  
1700 GameTooltip:SetOwner(this, "ANCHOR_BOTTOM")
1701  
1702 if HideMonitored == true then
1703 GameTooltip:SetText("Hiding Monitored")
1704 else
1705 GameTooltip:SetText("Showing Monitored")
1706 end
1707  
1708 end
1709  
1710 -- //////////////////////////////////////////////////////////////////////////////////////
1711 -- //
1712 -- // Miscellaneous
1713 -- //
1714 -- //////////////////////////////////////////////////////////////////////////////////////
1715  
1716 function BW_Toggle()
1717  
1718 if BW:IsVisible() then
1719 HideUIPanel(BW)
1720 else
1721 ShowUIPanel(BW)
1722 end
1723  
1724 end
1725  
1726  
1727 function BW_OptionsToggle()
1728  
1729 if not BW_Options:IsVisible() then
1730 ShowUIPanel(BW_Options)
1731 else
1732 HideUIPanel(BW_Options)
1733 end
1734  
1735 end
1736  
1737  
1738 function BW_SetRightMouse()
1739  
1740 if lastspellcast == nil then
1741  
1742 BW_Print(" BuffWatch: You have not cast any timed spells yet:")
1743 BW_Print(" Cast one, and then try \"/bw set\" again")
1744  
1745 else
1746  
1747 for i = 1, 300 do
1748 if GetSpellName(i,1) == lastspellcast then
1749 BuffWatchConfig.rightMouseSpell = i
1750 -- break
1751 end
1752 end
1753  
1754 if BuffWatchConfig.rightMouseSpell then
1755 BW_Print( format("BuffWatch: Right mouse button set to %s (%s)",
1756 GetSpellName(BuffWatchConfig.rightMouseSpell,1) ), 0.2, 0.9, 0.9 )
1757 end
1758  
1759 end
1760  
1761 end
1762  
1763  
1764 function GetLen(arr)
1765  
1766 local len = 0
1767  
1768 if arr ~= nil then
1769  
1770 for k, v in arr do
1771 len = len + 1
1772 end
1773  
1774 end
1775  
1776 return len
1777 end
1778  
1779  
1780 function BW_GetNextID(unitname)
1781  
1782 local i = 1
1783  
1784 if GetLen(Player_Info) == 0 then
1785  
1786 return i
1787  
1788 else
1789  
1790 local oldID = Player_Left[unitname]
1791  
1792 if oldID then
1793  
1794 local found = false
1795  
1796 for k, v in Player_Info do
1797 if v.ID == oldID then
1798 found = true
1799 break
1800 end
1801 end
1802  
1803 Player_Left[unitname] = nil
1804  
1805 if found == false then
1806 -- getglobal("BW_Player" .. oldID):Show()
1807 return oldID
1808 end
1809  
1810 end
1811  
1812 local Player_Copy = { }
1813  
1814 for k, v in Player_Info do
1815 table.insert(Player_Copy, v)
1816 end
1817  
1818 table.sort(Player_Copy, function(a,b)
1819 return a.ID < b.ID
1820 end)
1821  
1822 for k, v in Player_Copy do
1823  
1824 if i ~= v.ID then
1825 break
1826 end
1827  
1828 i = i + 1
1829  
1830 end
1831  
1832 Player_Copy = nil
1833  
1834 end
1835  
1836 getglobal("BW_Player" .. i .. "_Lock"):SetChecked(false)
1837  
1838 return i
1839  
1840 end
1841  
1842  
1843 function BW_GetPetUnitID(unitid)
1844  
1845 -- if lastgrouptype == "party" then
1846  
1847 if unitid == "player" then
1848 return "pet", 1
1849 end
1850  
1851 return string.gsub(unitid, "([a-z]+)([0-9]+)", "%1pet%2")
1852  
1853 --[[ return "partypet" .. string.sub(unitid, -1)
1854  
1855 else
1856 return "raidpet" .. string.sub(unitid, 5)
1857 end
1858 ]]--
1859 end
1860  
1861  
1862 -- //////////////////////////////////////////////////////////////////////////////////////
1863 -- //
1864 -- // BuffWatch Print Function
1865 -- //
1866 -- //////////////////////////////////////////////////////////////////////////////////////
1867  
1868 function BW_Print(msg, R, G, B)
1869  
1870 DEFAULT_CHAT_FRAME:AddMessage(msg, R, G, B);
1871  
1872 end
1873  
1874 -- //////////////////////////////////////////////////////////////////////////////////////
1875 -- //
1876 -- // BuffWatch Help
1877 -- //
1878 -- //////////////////////////////////////////////////////////////////////////////////////
1879  
1880 function BW_ShowHelp()
1881  
1882 BW_HelpFrame:Show()
1883 BW_HelpFrame:ClearAllPoints()
1884 BW_HelpFrame:SetPoint("CENTER","UIParent","CENTER",0,-32)
1885  
1886 BW_HelpFrameText:SetText(
1887  
1888 " - BuffWatch Usage - v " .. BW_VERSION .. " - " .. [[
1889  
1890 Show/Hide the BuffWatch window:
1891 - Bind a keyboard button to show/hide the window
1892 - You can also close it by right clicking the "BuffWatch" label (appears on mouseover)
1893  
1894 Showing Buffs:
1895 - Left click the BuffWatch label
1896 - Also occurs automatically whenever your gain/lose a party or raid member
1897  
1898 Locking a player's watched buffs:
1899 - If the checkbox to the left is unchecked, buffs will be added automatically whenever they gain a buff
1900 - If checked, buffs will not be added, or removed
1901  
1902 Rebuffing:
1903 - Left click an icon (will auto-target)
1904  
1905 Right click spell:
1906 - Cast any spell with a cast time (not instant). Then type "/bw set"
1907 - To cast it, right click any icon (will auto-target)
1908  
1909 Deleting buffs:
1910 - Lock the player's buffs (check the box). Then [ CTRL + Right Click ] on the buff
1911 - Optionally, [ ALT + Right Click ] to delete all but the selected one.
1912  
1913 Slash Commands ( Use /buffwatch or /bw )
1914 - /bw toggle : shows/hides the window
1915 - /bw options : shows/hides the options window
1916 - /bw : shows this help menu :)
1917  
1918 Verbosity:
1919 - Hold [ Shift ] while left or right-clicking a buff icon to send a cast message to your party
1920 ]] )
1921  
1922 end
1923  
1924 -- //////////////////////////////////////////////////////////////////////////////////////