vanilla-wow-addons – Blame information for rev 1

Subversion Repositories:
Rev:
Rev Author Line No. Line
1 office 1 local XPerl_Raid_Events = {}
2 local RaidGroupCounts = {0,0,0,0,0,0,0,0,0}
3 local FrameArray = {}
4 local PulloutFrameArray = {}
5 local perlSetupDone = nil
6 local ResArray = {}
7 local MovingMember = nil
8 local RosterUpdate = nil
9 local RaidPositions = {}
10 local oldRaidFrameDropDown_Initialize
11  
12 XPERL_RAIDGRP_PREFIX = "XPerl_Raid_Grp"
13 XPERL_RAIDMEMBER_PREFIX = "XPerl_raid"
14  
15 local CELL_MOTION_SPEED = 0.8 -- Motion offset mulitplied by this per frame (TODO, make this time based)
16  
17 -- Hold some raid roster information (AFK, DND etc.)
18 -- Is also stored between sessions to maintain timers and flags
19 XPerl_Roster = {}
20 local Last_Roster = {}
21  
22 -- Uses some variables from FrameXML\RaidFrame.lua:
23 -- MAX_RAID_MEMBERS = 40
24 -- NUM_RAID_GROUPS = 8
25 -- MEMBERS_PER_RAID_GROUP = 5
26  
27 -- This array will be built up on the fly whenever we pick up a localized class name that we don't already have.
28 -- The UnitClass function returns both english and localized versions, so it won't matter where the mod is run.
29 local ClassNames = {}
30  
31 ----------------------
32 -- Loading Function --
33 ----------------------
34  
35 -- XPerl_Raid_OnLoad
36 function XPerl_Raid_OnLoad()
37 this:RegisterEvent("PLAYER_ENTERING_WORLD")
38 this:RegisterEvent("PLAYER_LEAVING_WORLD")
39 this:RegisterEvent("VARIABLES_LOADED")
40 this:RegisterEvent("RAID_ROSTER_UPDATE")
41 this:RegisterEvent("ADDON_LOADED")
42 this.time = 0
43 this.Array = {}
44 end
45  
46 -- GetRaidGroup
47 local function GetRaidGroup(num, createIfAbsent)
48 local frame = getglobal(XPERL_RAIDGRP_PREFIX..num)
49  
50 if (not frame and createIfAbsent) then
51 frame = CreateFrame("Frame", XPERL_RAIDGRP_PREFIX..num, XPerl_Raid_Frame, "XPerl_Raid_TitleFrameTemplate")
52 frame:SetScale(XPerlConfig.Scale_Raid)
53  
54 frame = getglobal(XPERL_RAIDGRP_PREFIX..num.."_NameFrame_NameBarText")
55 frame:SetText("Group "..num)
56 end
57  
58 return frame
59 end
60  
61 -- Setup1RaidFrame
62 local function Setup1RaidFrame(frame)
63 local frameStats = getglobal(frame:GetName().."_StatsFrame")
64 local frameMana = getglobal(frame:GetName().."_StatsFrame_ManaBar")
65  
66 if (XPerlConfig.RaidMana == 1) then
67 frameStats:SetHeight(30)
68 frameMana:Show()
69 else
70 frameStats:SetHeight(25)
71 frameMana:Hide()
72 end
73 end
74  
75 -- GetRaidUnit
76 local function GetRaidUnit(num, createIfAbsent)
77 local frame = getglobal(XPERL_RAIDMEMBER_PREFIX..num)
78  
79 if (not frame and createIfAbsent) then
80 frame = CreateFrame("Frame", XPERL_RAIDMEMBER_PREFIX..num, XPerl_Raid_Frame, "XPerl_Raid_FrameTemplate")
81  
82 frame:SetScale(XPerlConfig.Scale_Raid)
83 Setup1RaidFrame(frame)
84 end
85  
86 return frame
87 end
88  
89 -- Non local by request
90 Perl_Raid_FindID = XPerl_Frame_FindID
91  
92 local function Perl_Raid_FindNum(partyid)
93 local _, _, num = strfind(partyid, "(%d+)")
94 return tonumber(num)
95 end
96  
97 local function Spacing()
98 return XPerlConfig.RaidVerticalSpacing + ((-1 + XPerlConfig.RaidMana) * 5)
99 end
100  
101 -- XPerl_Raid_Group_OnLoad
102 function XPerl_Raid_Group_OnLoad()
103 local id = XPerl_Frame_FindID(this)
104 this:SetID(id)
105  
106 local x, y
107 if (XPerlConfig.RaidPositions) then
108 local pos = XPerlConfig.RaidPositions[this:GetName()]
109  
110 if (pos and pos.left and pos.top) then
111 x = pos.left
112 y = pos.top
113 end
114 end
115  
116 if (not (x and y)) then
117 y = 565
118 x = (id - 1) * 77
119 end
120  
121 this:ClearAllPoints()
122 this:SetPoint("TOPLEFT", UIParent, "BOTTOMLEFT", x, y)
123  
124 function this:SavePosition()
125 XPerlConfig.RaidPositions[this:GetName()] = {top = this:GetTop(), left = this:GetLeft()}
126 end
127 end
128  
129 -- SaveAllPositions
130 local function SaveAllPositions()
131 for i = 1,NUM_RAID_GROUPS do
132 local frame = GetRaidGroup(i)
133 if (frame) then
134 XPerlConfig.RaidPositions[frame:GetName()] = {top = frame:GetTop(), left = frame:GetLeft()}
135 end
136 end
137 end
138  
139 -- XPerl_Raid_Single_OnLoad
140 function XPerl_Raid_Single_OnLoad()
141 if (strsub(this:GetName(), 1, 5) == "XPerl") then
142 local id = XPerl_Frame_FindID(this)
143 this:SetID(id)
144  
145 this.partyid = "raid"..this:GetID()
146  
147 FrameArray[this.partyid] = this
148 else
149 this:SetID(99)
150 end
151  
152 this.showing = 0
153  
154 XPerl_RegisterHighlight(getglobal(this:GetName().."_CastClickOverlay"), 2)
155 XPerl_RegisterPerlFrames(this, {"NameFrame", "StatsFrame"})
156  
157 this.FlashFrames = {getglobal(this:GetName().."_NameFrame"), getglobal(this:GetName().."_StatsFrame")}
158 end
159  
160 local events = {"UNIT_FACTION", "UNIT_FLAGS", "UNIT_DYNAMIC_FLAGS", "UNIT_AURA",
161 "UNIT_SPELLMISS", "CHAT_MSG_ADDON", "CHAT_MSG_RAID", "CHAT_MSG_RAID_LEADER",
162 "CHAT_MSG_PARTY"}
163  
164 -- XPerl_Raid_RegisterSome
165 local function XPerl_Raid_RegisterSome()
166 for i,event in pairs(events) do
167 this:RegisterEvent(event)
168 end
169 XPerl_RegisterBasics()
170 this:UnregisterEvent("UNIT_LEVEL") -- Don't care about player level
171 end
172  
173 -- XPerl_Raid_UnregisterSome
174 local function XPerl_Raid_UnregisterSome()
175 for i,event in pairs(events) do
176 this:UnregisterEvent(event)
177 end
178 XPerl_UnregisterBasics()
179 end
180  
181 -- XPerl_Raid_UpdateName
182 local function XPerl_Raid_UpdateName(thisFrame)
183 local name = UnitName(thisFrame.partyid)
184  
185 if (name or thisFrame.pet) then
186 local frame = getglobal(thisFrame:GetName().."_NameFrame_NameBarText")
187 local frameParent = getglobal(thisFrame:GetName().."_NameFrame")
188  
189 if (thisFrame.pet and name) then
190 thisFrame.petname = name -- Store it for when pet is absent
191 end
192  
193 if (not name) then
194 if (thisFrame.petname) then
195 name = thisFrame.petname
196 else
197 name = UnitName(thisFrame.petOwner).."'s "..PET
198 end
199 end
200  
201 frame:SetText(name)
202  
203 local remCount = 1
204 while ((frame:GetStringWidth() >= (frameParent:GetWidth() - 6)) and (string.len(name) > remCount)) do
205 name = string.sub(name, 1, string.len(name) - remCount)..".."
206 remCount = 3
207 frame:SetText(name)
208 end
209  
210 if (thisFrame.pet) then
211 color = XPerlConfig.ColourReactionNone
212 frame:SetTextColor(color.r, color.g, color.b)
213 else
214 XPerl_ColourFriendlyUnit(frame, thisFrame.partyid)
215 end
216 end
217 end
218  
219 -- XPerl_Raid_CheckFlags
220 local function XPerl_Raid_CheckFlags(partyid)
221  
222 local unitName = UnitName(partyid)
223 local resser
224  
225 for i,name in pairs(ResArray) do
226 if (name == unitName) then
227 resser = i
228 break
229 end
230 end
231  
232 if (resser) then
233 -- Verify they're dead..
234 if (UnitIsDeadOrGhost(partyid)) then
235 return {flag = resser.." ressing", bgcolor = {r = 0, g = 0.5, b = 1}}
236 end
237  
238 ResArray[resser] = nil
239 end
240  
241 local unitInfo = XPerl_Roster[unitName]
242 if (unitInfo) then
243 if (unitInfo.afk) then
244 return {flag = "AFK"}
245  
246 elseif (unitInfo.dnd) then
247 return {flag = "DND"}
248  
249 elseif (unitInfo.ressed) then
250 if (UnitIsDead(partyid)) then
251 if (unitInfo.ressed == 2) then
252 return {flag = XPERL_LOC_SS_AVAILABLE, bgcolor = {r = 0, g = 1, b = 0.5}}
253 else
254 return {flag = XPERL_LOC_RESURRECTED, bgcolor = {r = 0, g = 0.5, b = 1}}
255 end
256 else
257 unitInfo.ressed = nil
258 XPerl_Raid_UpdateManaType(FrameArray[partyid], true)
259 end
260 end
261 end
262 end
263  
264 -- XPerl_Raid_UpdateManaType
265 function XPerl_Raid_UpdateManaType(thisFrame, skipFlags)
266 local flags
267 if (not skipFlags) then
268 flags = XPerl_Raid_CheckFlags(thisFrame.partyid)
269 end
270 if (not flags) then
271 if (XPerlConfig.RaidMana == 1) then
272 local frame = getglobal(thisFrame:GetName().."_StatsFrame_ManaBar")
273 local frameBG = getglobal(thisFrame:GetName().."_StatsFrame_ManaBarBG")
274 XPerl_SetManaBarType(thisFrame.partyid, frame, frameBG)
275 end
276 end
277 end
278  
279 -- XPerl_Raid_ShowFlags
280 local function XPerl_Raid_ShowFlags(thisFrame, flags)
281 --thisFrame.flags = flags
282 local f, color, bgcolor
283  
284 if (flags.bgcolor) then
285 bgcolor = flags.bgcolor
286 else
287 bgcolor = {r = 0.5, g = 0.5, b = 0.5}
288 end
289  
290 if (flags.color) then
291 color = flags.color
292 else
293 color = {r = 1, g = 1, b = 1}
294 end
295  
296 f = getglobal(thisFrame:GetName().."_StatsFrame_HealthBar"); if (f) then f:SetStatusBarColor(bgcolor.r, bgcolor.g, bgcolor.b); end
297 f = getglobal(thisFrame:GetName().."_StatsFrame_HealthBarBG"); if (f) then f:SetVertexColor(bgcolor.r, bgcolor.g, bgcolor.b, 0.5); end
298 f = getglobal(thisFrame:GetName().."_StatsFrame_ManaBar"); if (f) then f:SetStatusBarColor(bgcolor.r, bgcolor.g, bgcolor.b); end
299 f = getglobal(thisFrame:GetName().."_StatsFrame_ManaBarBG"); if (f) then f:SetVertexColor(bgcolor.r, bgcolor.g, bgcolor.b, 0.5); end
300 f = getglobal(thisFrame:GetName().."_StatsFrame_HealthBarText")
301 if (f) then
302 f:SetText(flags.flag)
303 f:SetTextColor(color.r, color.g, color.b)
304 end
305 end
306  
307 -- XPerl_IsFeignDeath(unit)
308 function XPerl_IsFeignDeath(unit)
309 for i = 1,20 do
310 local buff = UnitBuff(unit, i)
311  
312 if (buff) then
313 if (strfind(strlower(buff), "feigndeath")) then
314 return true
315 end
316 else
317 break
318 end
319 end
320 end
321  
322 -- XPerl_Raid_UpdateHealth
323 local function XPerl_Raid_UpdateHealth(thisFrame)
324 local partyid = thisFrame.partyid
325 local health = UnitHealth(partyid)
326 local healthmax = UnitHealthMax(partyid)
327 local healthBar = getglobal(thisFrame:GetName().."_StatsFrame_HealthBar")
328 local frameText = getglobal(thisFrame:GetName().."_StatsFrame_HealthBarText")
329  
330 healthBar:SetMinMaxValues(0, healthmax)
331 if (XPerlConfig.InverseBars == 1) then
332 healthBar:SetValue(healthmax - health)
333 else
334 healthBar:SetValue(health)
335 end
336  
337 local name = UnitName(partyid)
338 local myRoster = XPerl_Roster[name]
339 local feigning
340 if (name and UnitIsConnected(partyid)) then
341 if (myRoster and myRoster.fd and health > 0) then
342 -- Seems we don't always get the UNIT_AURA messages, so we'll check their health on updates.
343 -- health > 0 means they can't be FD
344 myRoster.fd = nil
345 end
346  
347 local flags = XPerl_Raid_CheckFlags(partyid)
348 if (flags) then
349 XPerl_Raid_ShowFlags(thisFrame, flags)
350  
351 if (UnitIsDeadOrGhost(partyid)) then
352 thisFrame.dead = true
353 XPerl_Raid_UpdateName(thisFrame)
354 end
355 return
356  
357 elseif (UnitIsDead(partyid) or myRoster and myRoster.fd) then
358 if (myRoster and myRoster.fd) then --XPerl_IsFeignDeath(partyid)) then
359 feigning = true
360  
361 healthBar:SetMinMaxValues(0, 1)
362 healthBar:SetValue(0)
363 frameText:SetText(XPERL_LOC_FEIGNDEATH)
364 XPerl_SetSmoothBarColor(healthBar, 0)
365 else
366 thisFrame.dead = true
367 XPerl_Raid_ShowFlags(thisFrame, {flag = XPERL_LOC_DEAD})
368 XPerl_Raid_UpdateName(thisFrame)
369 end
370  
371 elseif (UnitIsGhost(partyid)) then
372 thisFrame.dead = true
373 XPerl_Raid_ShowFlags(thisFrame, {flag = XPERL_LOC_GHOST})
374 XPerl_Raid_UpdateName(thisFrame)
375  
376 else
377 if (thisFrame.dead or (myRoster and (myRoster.fd or myRoster.ressed))) then
378 XPerl_Raid_UpdateManaType(thisFrame, true)
379 end
380 thisFrame.dead = nil
381  
382 local percentHp = health / healthmax
383 local phealthPct = string.format("%3.0f", percentHp * 100)
384  
385 if (XPerlConfig.HealerMode == 1) then
386 frameText:SetText(-(healthmax - health))
387 else
388 frameText:SetText(phealthPct.."%")
389 end
390  
391 XPerl_SetSmoothBarColor(healthBar, percentHp)
392  
393 if (myRoster) then
394 myRoster.resCount = nil
395 if (myRoster.ressed) then
396 myRoster.ressed = nil
397 XPerl_Raid_UpdateManaType(thisFrame, true)
398 end
399 end
400 end
401 else
402 thisFrame.dead = nil
403 XPerl_Raid_ShowFlags(thisFrame, {flag = XPERL_LOC_OFFLINE})
404  
405 if (name and myRoster and not myRoster.offline) then
406 myRoster.offline = GetTime()
407 myRoster.afk = nil
408 myRoster.dnd = nil
409 end
410 end
411  
412 if (myRoster) then
413 if (not feigning) then
414 myRoster.fd = nil
415 end
416 end
417 end
418  
419 -- XPerl_Raid_UpdateMana
420 local function XPerl_Raid_UpdateMana(thisFrame)
421 local mana = UnitMana(thisFrame.partyid)
422 local manamax = UnitManaMax(thisFrame.partyid)
423  
424 local manaBar = getglobal(thisFrame:GetName().."_StatsFrame_ManaBar")
425 local manaBarText = getglobal(thisFrame:GetName().."_StatsFrame_ManaBarText")
426  
427 if (UnitPowerType(thisFrame.partyid) == 0 and not thisFrame.pet) then
428 local pmanaPct = (mana * 100.0) / manamax
429 manaBarText:SetText(string.format("%3.0f%%", pmanaPct))
430 else
431 manaBarText:SetText("")
432 end
433  
434 manaBar:SetMinMaxValues(0, manamax)
435 manaBar:SetValue(mana)
436 end
437  
438 -- XPerl_Raid_CombatFlash
439 local function XPerl_Raid_CombatFlash(thisFrame, elapsed, argNew, argGreen)
440 if (XPerl_CombatFlashSet (elapsed, thisFrame, argNew, argGreen)) then
441 XPerl_CombatFlashSetFrames(thisFrame)
442 end
443 end
444  
445 -- UpdateUnitByName
446 local function UpdateUnitByName(name,flagsOnly)
447 local id = XPerl_GetRaidPosition(name)
448 if (id) then
449 local frame = FrameArray["raid"..id]
450 if (frame) then
451 if (flagsOnly) then
452 XPerl_Raid_UpdateHealth(frame)
453 else
454 XPerl_Raid_UpdateDisplay(frame)
455 end
456 end
457  
458 for k,v in pairs(PulloutFrameArray) do
459 if (v.partyid == "raid"..id) then
460 if (flagsOnly) then
461 XPerl_Raid_UpdateHealth(frame)
462 else
463 XPerl_Raid_UpdateDisplay(frame)
464 end
465 end
466 end
467 end
468 end
469  
470 -- Raid_Motion
471 local function Raid_Motion(cell)
472  
473 local motion = cell.motion
474  
475 motion.currentLeft = motion.currentLeft * CELL_MOTION_SPEED
476 if (motion.currentLeft > -1 and motion.currentLeft < 1) then
477 motion.currentLeft = 0
478 end
479  
480 motion.currentTop = motion.currentTop * CELL_MOTION_SPEED
481 if (motion.currentTop > -1 and motion.currentTop < 1) then
482 motion.currentTop = 0
483 end
484  
485 cell:ClearAllPoints()
486 if (XPerlConfig.RaidUpward == 1) then
487 cell:SetPoint("BOTTOMLEFT", motion.parent, "TOPLEFT", motion.currentLeft, motion.targetTop - motion.currentTop)
488 else
489 cell:SetPoint("TOPLEFT", motion.parent, "BOTTOMLEFT", motion.currentLeft, motion.targetTop + motion.currentTop)
490 end
491  
492 if (motion.currentLeft == 0 and motion.currentTop == 0) then
493 cell.motion = nil
494 end
495 end
496  
497 -------------------
498 -- Raid movement --
499 -------------------
500  
501 -- XPerl_Raid_StartMovingMember
502 function XPerl_Raid_StartMovingMember()
503  
504 if (not MovingMember) then
505 local frame = this:GetParent()
506  
507 if (frame:GetID() ~= 99) then
508 HideDropDownMenu(1)
509 MovingMember = frame
510 frame:StartMoving()
511 frame:SetAlpha(XPerlConfig.Transparency / 2)
512 XPerl_RaidTitles()
513 end
514 end
515 end
516  
517 -- XPerl_Raid_CheckMovingMember
518 local function XPerl_Raid_CheckMovingMember()
519  
520 local x = MovingMember:GetLeft() + ((MovingMember:GetRight() - MovingMember:GetLeft()) / 2)
521 local y = MovingMember:GetBottom() + ((MovingMember:GetTop() - MovingMember:GetBottom()) / 2)
522  
523 XPerl_Raid_Mover:ClearAllPoints()
524 XPerl_Raid_Mover:Hide()
525 XPerl_Raid_Mover:SetScale(XPerlConfig.Scale_Raid)
526  
527 for i,cell in pairs(FrameArray) do
528 getglobal(cell:GetName().."_CastClickOverlay"):UnlockHighlight()
529 end
530  
531 local name = UnitName(MovingMember.partyid)
532 local spacing = Spacing()
533  
534 for i = 1,NUM_RAID_GROUPS do
535 if (i ~= RaidPositions[name].group) then
536 local frame = GetRaidGroup(i, true)
537  
538 if (frame) then
539 local left = (frame:GetLeft() or 0)
540 local right = (frame:GetRight() or 0)
541 local top
542 if (XPerlConfig.RaidUpward == 1) then
543 top = frame:GetTop() or 0
544 else
545 top = frame:GetBottom() or 0
546 end
547 if (left) then
548 local bottom
549 if (XPerlConfig.RaidUpward == 1) then
550 bottom = top + (MEMBERS_PER_RAID_GROUP * spacing)
551 local t = top
552 top = bottom
553 bottom = t
554 else
555 bottom = top - (MEMBERS_PER_RAID_GROUP * spacing)
556 end
557  
558 if (x >= left and x <= right and y >= bottom and y <= top) then
559 if (XPerlConfig.RaidUpward == 1) then
560 XPerl_Raid_Mover:SetPoint("BOTTOMLEFT", frame, "TOPLEFT", 0, 0)
561 XPerl_Raid_Mover:SetPoint("TOPRIGHT", frame, "TOPRIGHT", 0, -(bottom - top))
562 else
563 XPerl_Raid_Mover:SetPoint("TOPLEFT", frame, "BOTTOMLEFT", 0, 0)
564 XPerl_Raid_Mover:SetPoint("BOTTOMRIGHT", frame, "BOTTOMRIGHT", 0, (bottom - top))
565 end
566 XPerl_Raid_Mover:Show()
567  
568 local size = (bottom - top) / 5
569 local sub = math.floor((y - top - size) / size) + 2
570 if (sub < 1) then
571 sub = 1
572 elseif (sub > 5) then
573 sub = 5
574 end
575  
576 if (XPerlConfig.RaidUpward == 1) then
577 sub = 6 - sub
578 end
579  
580 for j,cell in pairs(FrameArray) do
581 local pos = RaidPositions[UnitName(cell.partyid)]
582  
583 if (pos and cell ~= MovingMember and pos.group == i and pos.row == sub) then
584 getglobal(cell:GetName().."_CastClickOverlay"):LockHighlight()
585 break
586 end
587 end
588 return i, sub
589 end
590 end
591 end
592 end
593 end
594 end
595  
596 -- XPerl_Raid_StopMovingMember
597 function XPerl_Raid_StopMovingMember(commit)
598 if (MovingMember) then
599 local good
600 MovingMember:StopMovingOrSizing()
601  
602 if (commit) then
603 local group,subpos = XPerl_Raid_CheckMovingMember()
604  
605 --ChatFrame7:AddMessage("group "..(group or "nil").." row "..(subpos or "nil"))
606  
607 if (group) then
608 local pos = RaidPositions[UnitName(MovingMember.partyid)]
609 if (pos and group ~= pos.group) then
610 local unit
611 for i,cell in pairs(FrameArray) do
612 local cellPos = RaidPositions[UnitName(cell.partyid)]
613 if (cellPos and cellPos.group == group and cellPos.row == subpos) then
614 unit = cell
615 break
616 end
617 end
618  
619 local index = Perl_Raid_FindNum(MovingMember.partyid)
620  
621 --ChatFrame7:AddMessage(" index "..(index or "nil"))
622  
623 if (unit) then
624 local targetIndex = Perl_Raid_FindNum(unit.partyid)
625 --ChatFrame7:AddMessage(" targetIndex "..(targetIndex or "nil"))
626 SwapRaidSubgroup(index, targetIndex)
627 else
628 SetRaidSubgroup(index, group)
629 end
630 good = true
631 else
632 --ChatFrame7:AddMessage("Cancelled, same as my current group")
633 end
634 else
635 --ChatFrame7:AddMessage("Cancelled, no group")
636 end
637 end
638  
639 for i,cell in pairs(FrameArray) do
640 getglobal(cell:GetName().."_CastClickOverlay"):UnlockHighlight()
641 end
642  
643 if (not good) then
644 local pos = RaidPositions[UnitName(MovingMember.partyid)]
645 if (pos) then
646 local parentGroup = GetRaidGroup(pos.group)
647 MovingMember:ClearAllPoints()
648 if (XPerlConfig.RaidUpward == 1) then
649 MovingMember:SetPoint("BOTTOMLEFT", parentGroup, "TOPLEFT", 0, -2 + ((pos.row - 1) * Spacing()))
650 else
651 MovingMember:SetPoint("TOPLEFT", parentGroup, "BOTTOMLEFT", 0, 2 - ((pos.row - 1) * Spacing()))
652 end
653 end
654 end
655  
656 if (UnitIsConnected(MovingMember.partyid)) then
657 MovingMember:SetAlpha(XPerlConfig.Transparency)
658 else
659 MovingMember:SetAlpha(XPerlConfig.Transparency / 2)
660 end
661  
662 MovingMember = nil
663 XPerl_RaidTitles()
664  
665 XPerl_Raid_Mover:Hide()
666 end
667 end
668  
669 -- XPerl_Raid_OnUpdate
670 -- 1.8.3 Converted OnUpdate to 1 single routine for all frames, instead of calling
671 -- potentially the same function 40 times Globally, this is more efficient on time
672 -- and memory usage. It does remove from the concept of object oriented updates
673 -- and such, but X-Perl is a rather intensive mod that is the focus of much of the
674 -- user interface, so I felt it was important to be over cautious.
675 function XPerl_Raid_OnUpdate()
676 if (RosterUpdate) then
677 RosterUpdate = nil
678  
679 XPerl_Raid_Position()
680 if (GetNumRaidMembers() == 0) then
681 ResArray = {}
682 XPerl_Roster = {}
683 RaidPositions = {}
684 end
685 end
686  
687 local updateTanker
688 if (XPerlConfig.RaidHighlightTanker == 1) then
689 if arg1 then this.time = this.time + arg1; end
690 if this.time >= 0.2 then
691 this.time = 0
692 updateTanker = true
693 end
694 end
695  
696 for i,frame in pairs(FrameArray) do
697 if (frame.showing == 1) then
698 if (frame.PlayerFlash) then
699 XPerl_Raid_CombatFlash(frame, arg1, false) -- << Frame
700 end
701  
702 if (frame.motion) then
703 Raid_Motion(frame)
704 end
705  
706 if (updateTanker) then
707 local set
708 if (UnitExists("target")) then
709 if (UnitCanAttack("player", "target")) then
710 if (UnitInRaid("targettarget")) then
711 set = UnitIsUnit("targettarget", frame.partyid)
712 end
713 elseif (UnitCanAttack("player", "targettarget")) then
714 if (UnitInRaid("targettargettarget")) then
715 set = UnitIsUnit("targettargettarget", frame.partyid)
716 end
717 end
718 end
719  
720 local highlightFrame = getglobal(frame:GetName().."_CastClickOverlay")
721 if (XPerlConfig.HighlightSelection == 0) then
722 if (set) then
723 highlightFrame:SetHighlightTexture("Interface\\Addons\\XPerl\\Images\\XPerl_Highlight", "ADD")
724 local tex = highlightFrame:GetHighlightTexture(); tex:SetTexCoord(0.25, 0.75, 0, 0.5)
725 tex:SetVertexColor(0.86, 0.82, 0.41)
726 else
727 highlightFrame:SetHighlightTexture("")
728 end
729 else
730 highlightFrame:SetHighlightTexture("Interface\\Addons\\XPerl\\Images\\XPerl_Highlight", "ADD")
731 local tex = highlightFrame:GetHighlightTexture(); tex:SetTexCoord(0.25, 0.75, 0, 0.5)
732 tex:SetVertexColor(0.86, 0.82, 0.41)
733 end
734  
735 if (set) then
736 highlightFrame:LockHighlight()
737 else
738 highlightFrame:UnlockHighlight()
739 end
740 end
741 end
742 end
743  
744 if (MovingMember) then
745 XPerl_Raid_CheckMovingMember()
746 end
747 end
748  
749 -- GetBuffButton(thisFrame, buffnum, debuff, createIfAbsent)
750 -- debuff must be 1 or 0, as it's used in size calc
751 local function GetBuffButton(thisFrame, buffnum, createIfAbsent)
752  
753 local name = thisFrame:GetName().."_BuffFrame_Buff"..buffnum
754 local button = getglobal(name)
755  
756 if (not button and createIfAbsent) then
757 button = CreateFrame("Button", name, getglobal(thisFrame:GetName().."_BuffFrame"), "XPerl_BuffTemplate")
758 button:SetID(buffnum)
759  
760 button:SetHeight(10)
761 button:SetWidth(10)
762  
763 local icon = getglobal(name.."Icon")
764 icon:SetTexCoord(0.078125, 0.921875, 0.078125, 0.921875)
765  
766 button:SetScript("OnEnter", XPerl_Raid_SetBuffTooltip)
767 button:SetScript("OnLeave", XPerl_PlayerTipHide)
768 end
769  
770 return button
771 end
772  
773 -- GetShowCast
774 local function GetShowCast(thisFrame)
775 local show,cureCast
776 if (thisFrame:GetID() == 99) then
777 -- Pullout frames all have ID 99
778 local RaidPullout = thisFrame:GetParent()
779  
780 if (RaidPullout.showBuffs == 1) then
781 show = "b"
782 else
783 show = "d"
784 end
785 if (RaidPullout.cureCast) then
786 cureCast = 1
787 else
788 cureCast = 0
789 end
790 else
791 if (XPerlConfig.RaidBuffs == 1) then
792 show = "b"
793 elseif (XPerlConfig.RaidDebuffs == 1) then
794 show = "d"
795 end
796 cureCast = XPerlConfig.BuffsCastableCurable
797 end
798  
799 return show,cureCast
800 end
801  
802 -- UpdateBuffs
803 local function UpdateBuffs(thisFrame)
804 local partyid = thisFrame.partyid
805 local cursed, color = XPerl_CheckDebuffs(partyid, {getglobal(thisFrame:GetName().."_NameFrame"), getglobal(thisFrame:GetName().."_StatsFrame")})
806  
807 local frameText = getglobal(thisFrame:GetName().."_NameFrame_NameBarText")
808 if (cursed) then
809 frameText:SetTextColor(1,0,0)
810 else
811 XPerl_ColourFriendlyUnit(frameText, partyid)
812 end
813  
814 local buffCount = 0
815 local maxBuff = 8 - ((abs(1 - XPerlConfig.RaidMana) * 2) * XPerlConfig.RaidBuffsRight)
816  
817 local show, cureCast = GetShowCast(thisFrame)
818 if (show) then
819 for buffnum=1,maxBuff do
820 local buff, count
821 if (show == "b") then
822 buff = XPerl_UnitBuff(partyid, buffnum, cureCast)
823 else
824 buff = XPerl_UnitDebuff(partyid, buffnum, cureCast)
825 end
826 local button = GetBuffButton(thisFrame, buffnum, buff) -- 'buff' flags whether to create icon
827 if (button) then
828 local icon = getglobal(button:GetName().."Icon")
829  
830 if (buff) then
831 buffCount = buffCount + 1
832  
833 icon:SetTexture(buff)
834 button:Show()
835 else
836 button:Hide()
837 end
838 end
839 end
840 for buffnum=maxBuff+1,8 do
841 local button = getglobal(thisFrame:GetName().."_BuffFrame_Buff"..buffnum)
842 if (button) then
843 button:Hide()
844 end
845 end
846 end
847  
848 --local myRoster = XPerl_Roster[UnitName(partyid)]
849 --if (myRoster and XPerlConfig.RaidBuffs == 1 and buffCount == 0 and cureCast == 0) then
850 -- if (UnitIsConnected(partyid)) then
851 -- -- Already scanned raid buffs and there are none
852 -- myRoster.Buffs = nil
853 -- end
854 --else
855 -- CheckRosterBuffs(partyid)
856 --end
857  
858 local buffFrame = getglobal(thisFrame:GetName().."_BuffFrame")
859 local nameFrame = getglobal(thisFrame:GetName().."_NameFrame")
860 local statsFrame = getglobal(thisFrame:GetName().."_StatsFrame")
861  
862 if (buffCount > 0) then
863 buffFrame:ClearAllPoints()
864 buffFrame:Show()
865 local id = thisFrame:GetID()
866  
867 if (XPerlConfig.RaidBuffsRight == 1 or id == 99) then
868 buffFrame:SetPoint("BOTTOMLEFT", thisFrame:GetName().."_StatsFrame", "BOTTOMRIGHT", -2, 2)
869  
870 if (XPerlConfig.RaidBuffsInside == 1 and id ~= 99) then
871 if (buffCount > 5 + XPerlConfig.RaidMana) then
872 nameFrame:SetWidth(60)
873 elseif (buffCount > 2) then
874 nameFrame:SetWidth(70)
875 else
876 nameFrame:SetWidth(80)
877 end
878  
879 if (buffCount > 3 + XPerlConfig.RaidMana) then
880 statsFrame:SetWidth(60)
881 else
882 statsFrame:SetWidth(70)
883 end
884 else
885 nameFrame:SetWidth(80)
886 statsFrame:SetWidth(80)
887 end
888  
889 getglobal(thisFrame:GetName().."_BuffFrame_Buff1"):ClearAllPoints()
890 getglobal(thisFrame:GetName().."_BuffFrame_Buff1"):SetPoint("BOTTOMLEFT", 0, 0)
891 for i = 2,buffCount do
892 if (i > buffCount) then break end
893  
894 local buffI = getglobal(thisFrame:GetName().."_BuffFrame_Buff"..i)
895 buffI:ClearAllPoints()
896  
897 if (i == 4 + XPerlConfig.RaidMana) then
898 if (XPerlConfig.RaidBuffsInside == 1 and id ~= 99) then
899 buffI:SetPoint("BOTTOMLEFT", 0, 0)
900 getglobal(thisFrame:GetName().."_BuffFrame_Buff1"):SetPoint("BOTTOMLEFT", buffI, "BOTTOMRIGHT", 0, 0)
901 else
902 buffI:SetPoint("BOTTOMLEFT", thisFrame:GetName().."_BuffFrame_Buff"..(i-(4 - abs(1 - XPerlConfig.RaidMana))), "BOTTOMRIGHT", 0, 0)
903 end
904 else
905 buffI:SetPoint("BOTTOMLEFT", thisFrame:GetName().."_BuffFrame_Buff"..(i-1), "TOPLEFT", 0, 0)
906 end
907 end
908 else
909 nameFrame:SetWidth(80)
910 statsFrame:SetWidth(80)
911  
912 buffFrame:SetPoint("TOPLEFT", thisFrame:GetName().."_StatsFrame", "BOTTOMLEFT", 0, 2)
913  
914 local prevBuff
915 for i = 1,buffCount do
916 local buff = getglobal(thisFrame:GetName().."_BuffFrame_Buff"..i)
917 buff:ClearAllPoints()
918 if (prevBuff) then
919 buff:SetPoint("TOPLEFT", prevBuff, "TOPRIGHT", 0, 0)
920 else
921 buff:SetPoint("TOPLEFT", 0, 0)
922 end
923 prevBuff = buff
924 end
925 end
926 else
927 nameFrame:SetWidth(80)
928 statsFrame:SetWidth(80)
929 buffFrame:Hide()
930 end
931  
932 local myRoster = XPerl_Roster[UnitName(partyid)]
933 if (myRoster) then
934 local _,class = UnitClass(partyid)
935 if (class == "HUNTER") then
936 if (XPerl_IsFeignDeath(partyid)) then
937 if (not myRoster.fd) then
938 myRoster.fd = GetTime()
939 XPerl_Raid_UpdateHealth(thisFrame)
940 end
941 elseif (myRoster.fd) then
942 myRoster.fd = nil
943 XPerl_Raid_UpdateManaType(thisFrame, true)
944 end
945 end
946 end
947 end
948  
949 -- UpdateRosterBuffs
950 -- Scans a unit's buffs and sets up initial buff time remaining entries
951 local duplicateTextures = {
952 ["Interface\\Icons\\Spell_Nature_Regeneration"] = true,
953 ["Interface\\Icons\\Spell_Nature_LightningShield"] = true
954 };
955 local function UpdateRosterBuffs(thisFrame)
956  
957 local unit = thisFrame.partyid
958 local myRoster = XPerl_Roster[unit]
959  
960 if (myRoster) then
961 if (not myRoster.Buffs) then
962 myRoster.Buffs = {}
963 end
964  
965 local oldAuras = {}
966 for k, v in pairs(myRoster.Buffs) do
967 oldAuras[k] = 1
968 end
969  
970 local num, buff = 0, UnitBuff(unit, 1);
971 while (buff) do
972 num = num + 1;
973 if (not duplicateTextures[buff]) then
974 for k, v in pairs(XPerl_CTBuffTextures) do
975 if ("Interface\\Icons\\"..v[1] == buff) then
976 buffName = k
977 break
978 end
979 end
980 else
981 PerlBuffStatusTooltip:SetOwner(WorldFrame, "ANCHOR_NONE")
982 PerlBuffStatusTooltipTextLeft1:SetText("")
983 PerlBuffStatusTooltip:SetUnitBuff(unit, num)
984 local tooltipName = PerlBuffStatusTooltipTextLeft1:GetText()
985 if (strlen(tooltipName or "") > 0 and XPerl_CTBuffTextures[tooltipName]) then
986 buffName = tooltipName
987 end
988 end
989  
990 if (buffName) then
991 oldAuras[buffName] = nil
992 if (not myRoster.Buffs[buffName]) then
993 -- We store the fade time of raid member's buffs
994  
995 local duration = XPerl_CTBuffTextures[buffName][2]
996  
997 if (not duration) then
998 duration = 5*60
999 end
1000  
1001 myRoster.Buffs[buffName] = GetTime() + duration
1002 end
1003 end
1004  
1005 buff = UnitBuff(unit, num + 1)
1006 end
1007  
1008 for k, v in pairs(oldAuras) do
1009 myRoster.Buffs[k] = nil
1010 end
1011 end
1012 end
1013  
1014 -- XPerl_Raid_Update_Control
1015 local function XPerl_Raid_Update_Control(thisFrame)
1016 if (UnitIsVisible(thisFrame.partyid) and UnitIsCharmed(thisFrame.partyid)) then
1017 getglobal(thisFrame:GetName().."_NameFrame_Warning"):Show()
1018 else
1019 getglobal(thisFrame:GetName().."_NameFrame_Warning"):Hide()
1020 end
1021 end
1022  
1023 -- XPerl_Raid_UpdateCombat
1024 local function XPerl_Raid_UpdateCombat(thisFrame)
1025 local frame = getglobal(thisFrame:GetName().."_NameFrame_ActivityStatus")
1026 if (not (frame == nil)) then
1027 if (UnitExists(thisFrame.partyid) and UnitAffectingCombat(thisFrame.partyid)) then
1028 frame:Show()
1029 else
1030 frame:Hide()
1031 end
1032 end
1033 end
1034  
1035 -------------------------
1036 -- The Update Function --
1037 -------------------------
1038 function XPerl_Raid_UpdateDisplay(thisFrame)
1039 if (thisFrame.showing == 1) then
1040 if (UnitExists(thisFrame.partyid) or thisFrame.pet) then
1041 if (UnitIsConnected(thisFrame.partyid) and MovingMember ~= thisFrame) then
1042 thisFrame:SetAlpha(XPerlConfig.Transparency)
1043 else
1044 thisFrame:SetAlpha(XPerlConfig.Transparency/2)
1045 getglobal(thisFrame:GetName().."_StatsFrame_HealthBarText"):SetText("Offine")
1046 end
1047  
1048 local manaBarText = getglobal(thisFrame:GetName().."_StatsFrame_ManaBarText")
1049 local healthBarText = getglobal(thisFrame:GetName().."_StatsFrame_HealthBarText")
1050 if (XPerlConfig.ShowRaidPercents==0) then
1051 manaBarText:Hide()
1052 healthBarText:Hide()
1053 else
1054 manaBarText:Show()
1055 healthBarText:Show()
1056 end
1057  
1058 -- Health must be updated after mana, since ctra flag checks are done here.
1059 XPerl_Raid_UpdateManaType(thisFrame)
1060 XPerl_Raid_UpdateMana(thisFrame)
1061 XPerl_Raid_UpdateHealth(thisFrame) -- <<< -- AFTER MANA -- <<< --
1062 XPerl_Raid_UpdateName(thisFrame)
1063 XPerl_Raid_UpdateCombat(thisFrame)
1064 XPerl_Raid_Update_Control(thisFrame)
1065 UpdateBuffs(thisFrame)
1066 else
1067 thisFrame:StopMovingOrSizing()
1068 thisFrame:Hide()
1069 end
1070 else
1071 thisFrame:StopMovingOrSizing()
1072 thisFrame:Hide()
1073 end
1074 end
1075  
1076 -------------------
1077 -- Event Handler --
1078 -------------------
1079 function XPerl_Raid_OnEvent()
1080 local func = XPerl_Raid_Events[event]
1081 if (func) then
1082 func()
1083 else
1084 XPerl_ShowMessage("EXTRA EVENT")
1085 end
1086 end
1087  
1088 function XPerl_Raid_Events:ADDON_LOADED()
1089 if (arg1 == "Blizzard_RaidUI") then
1090 if (not oldRaidFrameDropDown_Initialize) then
1091 oldRaidFrameDropDown_Initialize = RaidFrameDropDown_Initialize
1092 RaidFrameDropDown_Initialize = XPerl_RaidFrameDropDown_Initialize
1093 end
1094  
1095 if (CT_RATab_newRaidFrameDropDown_Initialize) then
1096 if (not oldCT_RATab_newRaidFrameDropDown_Initialize) then
1097 oldCT_RATab_newRaidFrameDropDown_Initialize = CT_RATab_newRaidFrameDropDown_Initialize
1098 CT_RATab_newRaidFrameDropDown_Initialize = XPerl_CT_RATab_newRaidFrameDropDown_Initialize
1099 --RaidFrameDropDown_Initialize = XPerl_CTRaidFrameDropDown_Initialize
1100 end
1101 end
1102  
1103 XPerl_ReplaceBlizzardPullouts()
1104 this:UnregisterEvent("ADDON_LOADED")
1105 end
1106 end
1107  
1108 function XPerl_Raid_Events:VARIABLES_LOADED()
1109 this:UnregisterEvent("VARIABLES_LOADED")
1110  
1111 XPerl_Raid_RegisterSome()
1112  
1113 if (GetNumRaidMembers() == 0) then
1114 ResArray = {}
1115 XPerl_Roster = {}
1116 RaidPositions = {}
1117 else
1118 local myRoster = XPerl_Roster[UnitName("player")]
1119 if (myRoster) then
1120 myRoster.afk, myRoster.dnd, myRoster.dnd, myRoster.ressed, myRoster.resCount = nil, nil, nil, nil, nil
1121 end
1122 end
1123  
1124 XPerl_ScaleRaid(XPerlConfig.Scale_Raid)
1125 XPerl_RaidTitles()
1126 end
1127  
1128 -- PLAYER_ENTERING_WORLD
1129 function XPerl_Raid_Events:PLAYER_ENTERING_WORLD()
1130 XPerl_Raid_RegisterSome()
1131  
1132 if (not XPerl_raid1 and GetNumRaidMembers() > 0) then
1133 XPerl_Raid_Position()
1134 end
1135 end
1136  
1137 -- PLAYER_LEAVING_WORLD
1138 function XPerl_Raid_Events:PLAYER_LEAVING_WORLD()
1139 XPerl_Raid_UnregisterSome()
1140 end
1141  
1142 -- RAID_ROSTER_UPDATE
1143 function XPerl_Raid_Events:RAID_ROSTER_UPDATE()
1144 if (MovingMember) then
1145 XPerl_Raid_StopMovingMember()
1146 end
1147  
1148 if (not XPerl_raid1 or XPerl_raid1.showing == 0) then
1149 -- If no raid yet, just setup anyway
1150 XPerl_Raid_Position()
1151 if (GetNumRaidMembers() == 0) then
1152 ResArray = {}
1153 XPerl_Roster = {}
1154 RaidPositions = {}
1155 end
1156 if (XPerl_SendModules) then
1157 XPerl_SendModules() -- Let other X-Perl users know which version we're running
1158 end
1159 else
1160 -- Otherwise, we defer the roster update until the next frame for
1161 -- cases where we get more than 1 RAID_ROSTER_UPDATE per data packet
1162 RosterUpdate = true
1163 end
1164 end
1165  
1166 -- UNIT_FLAGS
1167 function XPerl_Raid_Events:UNIT_FLAGS()
1168 local f = FrameArray[arg1]
1169 if (f) then
1170 XPerl_Raid_UpdateCombat(f)
1171  
1172 for name,f in pairs(PulloutFrameArray) do
1173 if (f.partyid == arg1 and f:IsShown()) then
1174 XPerl_Raid_UpdateCombat(f)
1175 end
1176 end
1177 end
1178 end
1179  
1180 XPerl_Raid_Events.UNIT_DYNAMIC_FLAGS = XPerl_Raid_Events.UNIT_FLAGS
1181  
1182 -- UNIT_FACTION
1183 function XPerl_Raid_Events:UNIT_FACTION()
1184 local f = FrameArray[arg1]
1185 if (f) then
1186 XPerl_Raid_Update_Control(f)
1187 XPerl_Raid_UpdateName(f)
1188 end
1189  
1190 for name,f in pairs(PulloutFrameArray) do
1191 if (f.partyid == arg1 and f:IsShown()) then
1192 XPerl_Raid_Update_Control(f)
1193 XPerl_Raid_UpdateName(f)
1194 end
1195 end
1196 end
1197  
1198 -- UNIT_COMBAT
1199 function XPerl_Raid_Events:UNIT_COMBAT()
1200 local f = FrameArray[arg1]
1201 if (f) then
1202 if (arg2 == "HEAL") then
1203 XPerl_Raid_CombatFlash(f, 0, true, true)
1204 elseif (arg4 and arg4 > 0) then
1205 XPerl_Raid_CombatFlash(f, 0, true)
1206 end
1207 end
1208 end
1209  
1210 -- UNIT_HEALTH
1211 function XPerl_Raid_Events:UNIT_HEALTH()
1212 local f = FrameArray[arg1]
1213 if (f) then
1214 XPerl_Raid_UpdateHealth(f)
1215 XPerl_Raid_UpdateCombat(f)
1216 end
1217  
1218 for name,f in pairs(PulloutFrameArray) do
1219 if (f.partyid == arg1 and f:IsShown()) then
1220 XPerl_Raid_UpdateHealth(f)
1221 end
1222 end
1223 end
1224 XPerl_Raid_Events.UNIT_MAXHEALTH = XPerl_Raid_Events.UNIT_HEALTH
1225  
1226 function XPerl_Raid_Events:UNIT_DISPLAYPOWER()
1227 local f = FrameArray[arg1]
1228 if (f) then
1229 XPerl_Raid_UpdateManaType(f)
1230 XPerl_Raid_UpdateMana(f)
1231 end
1232  
1233 for name,f in pairs(PulloutFrameArray) do
1234 if (f.partyid == arg1 and f:IsShown()) then
1235 XPerl_Raid_UpdateManaType(f)
1236 XPerl_Raid_UpdateMana(f)
1237 end
1238 end
1239 end
1240  
1241 -- UNIT_MANA
1242 function XPerl_Raid_Events:UNIT_MANA()
1243 if (XPerlConfig.RaidMana == 1) then
1244 local f = FrameArray[arg1]
1245 if (f) then
1246 XPerl_Raid_UpdateMana(f)
1247 end
1248  
1249 for name,f in pairs(PulloutFrameArray) do
1250 if (f.partyid == arg1 and f:IsShown()) then
1251 XPerl_Raid_UpdateMana(f)
1252 end
1253 end
1254 end
1255 end
1256 XPerl_Raid_Events.UNIT_MAXMANA = XPerl_Raid_Events.UNIT_MANA
1257 XPerl_Raid_Events.UNIT_RAGE = XPerl_Raid_Events.UNIT_MANA
1258 XPerl_Raid_Events.UNIT_MAXRAGE = XPerl_Raid_Events.UNIT_MANA
1259 XPerl_Raid_Events.UNIT_ENERGY = XPerl_Raid_Events.UNIT_MANA
1260 XPerl_Raid_Events.UNIT_MAXENERGY = XPerl_Raid_Events.UNIT_MANA
1261  
1262 -- UNIT_NAME_UPDATE
1263 function XPerl_Raid_Events:UNIT_NAME_UPDATE()
1264 local f = FrameArray[arg1]
1265 if (f) then
1266 XPerl_Raid_UpdateName(f)
1267  
1268 for name,f in pairs(PulloutFrameArray) do
1269 if (f.partyid == arg1 and f:IsShown()) then
1270 XPerl_Raid_UpdateName(f)
1271 end
1272 end
1273 end
1274 end
1275  
1276 -- UNIT_AURA
1277 function XPerl_Raid_Events:UNIT_AURA()
1278 local f = FrameArray[arg1]
1279 if (f) then
1280 UpdateRosterBuffs(f)
1281 UpdateBuffs(f)
1282  
1283 for name,f in pairs(PulloutFrameArray) do
1284 if (f.partyid == arg1 and f:IsShown()) then
1285 UpdateBuffs(f)
1286 end
1287 end
1288 end
1289 end
1290  
1291 -- UNIT_PET
1292 function XPerl_Raid_Events:UNIT_PET()
1293 if (strsub(arg1, 1, 4) == "raid") then
1294 for k,v in pairs(PulloutFrameArray) do
1295 if (v.petOwner == arg1) then
1296 XPerl_Raid_UpdateDisplay(v)
1297 end
1298 end
1299 end
1300 end
1301  
1302 -- SetRes
1303 local function SetResStatus(resserName, resTargetName)
1304  
1305 --frame.beingRessed = true
1306 local resEnd
1307  
1308 if (resTargetName) then
1309 ResArray[resserName] = resTargetName
1310 else
1311 resEnd = true
1312  
1313 for i,name in pairs(ResArray) do
1314 if (i == resserName) then
1315 resTargetName = name
1316 break
1317 end
1318 end
1319  
1320 ResArray[resserName] = nil
1321 end
1322  
1323 if (resTargetName) then
1324 if (XPerl_Roster[resTargetName]) then
1325 if (resEnd) then
1326 if (not XPerl_Roster[resTargetName].resCount) then
1327 XPerl_Roster[resTargetName].resCount = 1
1328 else
1329 XPerl_Roster[resTargetName].resCount = XPerl_Roster[resTargetName].resCount + 1
1330 end
1331 end
1332 UpdateUnitByName(resTargetName)
1333 end
1334 end
1335 end
1336  
1337 -- Direct string matches can be done via table lookup
1338 local QuickFuncs = {
1339 AFK = function(m) m.afk = GetTime(); m.dnd = nil; end,
1340 UNAFK = function(m) m.afk = nil; end,
1341 DND = function(m) m.dnd = GetTime(); m.afk = nil; end,
1342 UNDND = function(m) m.dnd = nil; end,
1343 RESNO = function(m,n) SetResStatus(n) end,
1344 RESSED = function(m) m.ressed = 1; end,
1345 CANRES = function(m) m.ressed = 2; end,
1346 NORESSED= function(m) m.ressed = nil; m.resCount = nil; end,
1347 SR = XPerl_SendModules
1348 }
1349  
1350 -- ProcessCTRAMessage
1351 local function ProcessCTRAMessage(unitName, msg)
1352 local myRoster = XPerl_Roster[unitName]
1353  
1354 if (not myRoster) then
1355 return
1356 end
1357  
1358 local update = true
1359  
1360 local func = QuickFuncs[msg]
1361 if (func) then
1362 func(myRoster, unitName)
1363 else
1364 if (strsub(msg, 1, 4) == "RES ") then
1365 SetResStatus(unitName, strsub(msg, 5))
1366 return
1367  
1368 elseif (strsub(msg, 1, 3) == "RN ") then
1369 -- Buff durations
1370 local _, _, secsLeft, buffIndex, buffSub = strfind(msg, "^RN ([^%s]+) ([^%s]+) ([^%s]+)$")
1371  
1372 if (secsLeft and buffIndex and buffSub) then
1373 secsLeft = tonumber(secsLeft)
1374 buffIndex = tonumber(buffIndex)
1375 buffSub = tonumber(buffSub)
1376  
1377 local buff = XPerl_CTBuffArray[buffIndex]
1378  
1379 if (buff) then
1380 local buffName
1381 -- Shouldn't come with string and sub index > 0, but it does.. Will investigate when and why
1382 -- Druid Thorns... /shrug
1383 if (buffSub == 0 or type(buff.name) == "string") then
1384 buffName = buff.name
1385 else
1386 buffName = buff.name[buffSub]
1387 end
1388  
1389 if (buffName) then
1390 if (not myRoster.Buffs) then
1391 myRoster.Buffs = {}
1392 end
1393 myRoster.Buffs[buffName] = GetTime() + secsLeft
1394 --CheckRosterBuffs(unitName)
1395 end
1396 end
1397 end
1398 update = nil
1399  
1400 elseif (strsub(msg, 1, 3) == "CD ") then
1401 local _, _, num, cooldown = strfind(msg, "^CD (%d+) (%d+)$")
1402 if ( num == "1" ) then
1403 myRoster.Rebirth = GetTime() + tonumber(cooldown)*60
1404 elseif ( num == "2" ) then
1405 myRoster.Reincarnation = GetTime() + tonumber(cooldown)*60
1406 elseif ( num == "3" ) then
1407 myRoster.Soulstone = GetTime() + tonumber(cooldown)*60
1408 end
1409 update = nil
1410  
1411 elseif (strsub(msg, 1, 2) == "V ") then
1412 myRoster.version = strsub(msg, 3)
1413 update = nil
1414 else
1415 update = nil
1416 end
1417 end
1418  
1419 if (update) then
1420 UpdateUnitByName(unitName)
1421 end
1422 end
1423  
1424 -- ProcessoRAMessage
1425 local function ProcessoRAMessage(unitName, msg)
1426 local myRoster = XPerl_Roster[unitName]
1427  
1428 if (not myRoster) then
1429 return
1430 end
1431  
1432 if (strsub(msg, 1, 5) == "oRAV ") then
1433 myRoster.oRAversion = strsub(msg, 6)
1434 end
1435 end
1436  
1437 -- XPerl_Raid_Events:CHAT_MSG_RAID
1438 -- Check for AFK/DND flags in chat
1439 function XPerl_Raid_Events:CHAT_MSG_RAID()
1440 local myRoster = XPerl_Roster[arg4]
1441 if (myRoster) then
1442 if (arg6 == "AFK") then
1443 if (not myRoster.afk) then
1444 myRoster.afk = GetTime()
1445 myRoster.dnd = nil
1446 end
1447 elseif (arg6 == "DND") then
1448 if (not myRoster.dnd) then
1449 myRoster.dnd = GetTime()
1450 myRoster.afk = nil
1451 end
1452 else
1453 myRoster.dnd, myRoster.afk = nil, nil
1454 end
1455 end
1456 end
1457 XPerl_Raid_Events.CHAT_MSG_RAID_LEADER = XPerl_Raid_Events.CHAT_MSG_RAID
1458 XPerl_Raid_Events.CHAT_MSG_PARTY = XPerl_Raid_Events.CHAT_MSG_RAID
1459  
1460 -- CHAT_MSG_ADDON
1461 function XPerl_Raid_Events:CHAT_MSG_ADDON()
1462 XPerl_Raid_Events.CHAT_MSG_RAID()
1463 if (arg3 == "RAID") then
1464 if (arg1 == "CTRA") then
1465 XPerl_ParseCTRA(arg4, arg2, ProcessCTRAMessage)
1466 elseif (arg1 == "oRA") then
1467 XPerl_ParseCTRA(arg4, arg2, ProcessoRAMessage)
1468 end
1469 end
1470 end
1471  
1472 -- SetRaidRoster
1473 local function SetRaidRoster()
1474  
1475 local NewRoster = {}
1476 Last_Roster = XPerl_Roster
1477  
1478 for i = 1,GetNumRaidMembers() do
1479 local name = UnitName("raid"..i)
1480  
1481 if (XPerl_Roster[name]) then
1482 NewRoster[name] = XPerl_Roster[name]
1483 else
1484 NewRoster[name] = {}
1485 end
1486  
1487 if (Last_Roster[name]) then
1488 if (RaidPositions[name]) then
1489 Last_Roster[name].lastPos = RaidPositions[name]
1490 else
1491 Last_Roster[name].lastPos = nil
1492 end
1493 end
1494 end
1495  
1496 RaidPositions = {}
1497 XPerl_Roster = NewRoster
1498 end
1499  
1500 --------------------
1501 -- Raid Functions --
1502 --------------------
1503  
1504 -- MoveCell
1505 local function MoveCell(cell, grp, wasShowing)
1506  
1507 local parentGroup = getglobal(XPERL_RAIDGRP_PREFIX..grp)
1508 local name = UnitName(cell.partyid)
1509 local noMotion = true
1510  
1511 if (wasShowing == 1) then
1512 if (cell.lastPos) then
1513 if (cell.lastPos.group ~= grp or cell.lastPos.row ~= RaidGroupCounts[grp] + 1) then
1514 noMotion = false
1515 end
1516 end
1517  
1518 local oldCell = Last_Roster[name]
1519 if (oldCell) then
1520 if (oldCell.lastPos) then
1521 if (oldCell.lastPos.group ~= grp or oldCell.lastPos.row ~= RaidGroupCounts[grp] + 1) then
1522 noMotion = false
1523 end
1524 end
1525 end
1526 end
1527  
1528 RaidPositions[name] = {group = grp, row = RaidGroupCounts[grp] + 1}
1529  
1530 local t
1531 if (XPerlConfig.RaidUpward == 1) then
1532 t = -2 + (RaidGroupCounts[grp] * Spacing())
1533 else
1534 t = 2 - (RaidGroupCounts[grp] * Spacing())
1535 end
1536  
1537 if (cell.motion or (not noMotion and cell.showing == 1 and cell:IsShown() and XPerlConfig.RaidMotion == 1)) then
1538 if (XPerlConfig.RaidUpward == 1) then
1539 cell.motion = {
1540 targetTop = t,
1541 parent = parentGroup,
1542 currentLeft = cell:GetLeft() - parentGroup:GetLeft(),
1543 currentTop = parentGroup:GetTop() - cell:GetBottom() + t
1544 }
1545 else
1546 cell.motion = {
1547 targetTop = t,
1548 parent = parentGroup,
1549 currentLeft = cell:GetLeft() - parentGroup:GetLeft(),
1550 currentTop = cell:GetTop() - parentGroup:GetBottom() - t
1551 }
1552 end
1553 else
1554 cell:ClearAllPoints()
1555 if (XPerlConfig.RaidUpward == 1) then
1556 cell:SetPoint("BOTTOMLEFT", parentGroup, "TOPLEFT", 0, t)
1557 else
1558 cell:SetPoint("TOPLEFT", parentGroup, "BOTTOMLEFT", 0, t)
1559 end
1560 end
1561 end
1562  
1563 -- XPerl_Raid_Classes
1564 local function XPerl_Raid_Classes()
1565 local groups = {WARRIOR = 1, MAGE = 2, PRIEST = 3, WARLOCK = 4, DRUID = 5, ROGUE = 6, HUNTER = 7, PALADIN = 8, SHAMAN = 9}
1566  
1567 for num=1,MAX_RAID_MEMBERS do
1568 local localClass, class = UnitClass("raid"..num)
1569 if (class) then
1570 if (not ClassNames[class]) then
1571 ClassNames[class] = localClass
1572 end
1573  
1574 local frame = GetRaidUnit(num, true)
1575  
1576 local subgroup = groups[class]
1577 if (subgroup) then
1578 if (subgroup == 9) then -- Burning Crusade - REMOVE THIS
1579 subgroup = 8
1580 end
1581  
1582 GetRaidGroup(subgroup, true)
1583 local wasShowing = frame.showing
1584 frame.showing = XPerlConfig["ShowGroup"..subgroup]
1585 MoveCell(frame, subgroup, wasShowing)
1586 RaidGroupCounts[subgroup] = RaidGroupCounts[subgroup] + 1
1587 end
1588  
1589 else
1590 local frame = GetRaidUnit(num)
1591 if (frame) then
1592 frame.showing = 0
1593 end
1594 end
1595 end
1596  
1597 for name,index in pairs(groups) do
1598 local frame = getglobal(XPERL_RAIDGRP_PREFIX..index.."_NameFrame_NameBarText")
1599 if (frame) then
1600 if (index == 8) then -- Burning Crusade - REMOVE THIS
1601 if (UnitFactionGroup("player") == "Horde") then
1602 frame:SetText(ClassNames["SHAMAN"])
1603 else
1604 frame:SetText(ClassNames["PALADIN"])
1605 end
1606 break
1607 end
1608  
1609 frame:SetText(ClassNames[name])
1610 end
1611 end
1612 end
1613  
1614 -- XPerl_Raid_Groups
1615 local function XPerl_Raid_Groups()
1616 for num=1,MAX_RAID_MEMBERS do
1617 local name, rank, subgroup= GetRaidRosterInfo(num)
1618 if (name and subgroup) then
1619 local frame = GetRaidUnit(num, true)
1620  
1621 if (frame) then
1622 GetRaidGroup(subgroup, true)
1623 local localClass, class = UnitClass("raid"..num)
1624  
1625 if (class and not ClassNames[class]) then
1626 ClassNames[class] = localClass
1627 end
1628  
1629 if (name and subgroup and subgroup >= 1 and subgroup <= NUM_RAID_GROUPS) then
1630 local wasShowing = frame.showing
1631 frame.showing = XPerlConfig["ShowGroup"..subgroup]
1632 MoveCell(frame, subgroup, wasShowing)
1633 RaidGroupCounts[subgroup] = RaidGroupCounts[subgroup] + 1
1634 else
1635 frame.showing = 0
1636 end
1637 end
1638 else
1639 local frame = GetRaidUnit(num)
1640 if (frame) then
1641 frame.showing = 0
1642 end
1643 end
1644 end
1645  
1646 for index = 1,NUM_RAID_GROUPS do
1647 local frame = getglobal(XPERL_RAIDGRP_PREFIX..index.."_NameFrame_NameBarText")
1648 if (frame) then
1649 frame:SetText(string.format(XPERL_RAID_GROUP, index))
1650 end
1651 end
1652 end
1653  
1654 -- XPerl_Raid_Position()
1655 function XPerl_Raid_Position()
1656 SetRaidRoster()
1657 RaidGroupCounts = {0,0,0,0,0,0,0,0,0}
1658  
1659 if (XPerlConfig.SortRaidByClass==1) then
1660 XPerl_Raid_Classes()
1661 else
1662 XPerl_Raid_Groups()
1663 end
1664  
1665 if (GetNumRaidMembers() == 0 or XPerlConfig.ShowRaid == 0) then
1666 XPerl_Raid_Frame:Hide()
1667 else
1668 XPerl_Raid_Frame:Show()
1669  
1670 for num=1,MAX_RAID_MEMBERS do
1671 local frame = getglobal(XPERL_RAIDMEMBER_PREFIX..num)
1672  
1673 if (frame) then
1674 if (frame.showing == 1) then
1675 frame:Show()
1676 XPerl_Raid_UpdateDisplay(frame)
1677 else
1678 frame:Hide()
1679 end
1680 end
1681 end
1682 end
1683  
1684 XPerl_RaidTitles()
1685  
1686 Last_Roster = nil
1687 for i,unit in XPerl_Roster do
1688 unit.lastPos = nil
1689 end
1690 end
1691  
1692 --------------------
1693 -- Click Handlers --
1694 --------------------
1695 function XPerl_CT_RATab_newRaidFrameDropDown_Initialize()
1696 XPerl_RaidFrameDropDown_Initialize(true)
1697 end
1698  
1699 function XPerl_RaidFrameDropDown_Initialize(ct)
1700 if (type(UIDROPDOWNMENU_MENU_VALUE) == "table" and UIDROPDOWNMENU_MENU_VALUE[1] == "Main Tanks") then
1701 local info = {}
1702 info.text = XPERL_RAID_DROPDOWN_MAINTANKS
1703 info.isTitle = 1
1704 UIDropDownMenu_AddButton(info, UIDROPDOWNMENU_MENU_LEVEL)
1705 for i = 1,10 do
1706 info = {}
1707 if (XPerl_MainTanks[i] and XPerl_MainTanks[i][2] == UIDROPDOWNMENU_MENU_VALUE[2]) then
1708 info.text = string.format("|c00FFFF80"..XPERL_RAID_DROPDOWN_REMOVEMT.."|r", i)
1709 info.value = {UIDROPDOWNMENU_MENU_VALUE[1], UIDROPDOWNMENU_MENU_VALUE[2], i, 1}
1710 else
1711 info.text = string.format(XPERL_RAID_DROPDOWN_SETMT, i)
1712 info.value = {UIDROPDOWNMENU_MENU_VALUE[1], UIDROPDOWNMENU_MENU_VALUE[2], i}
1713 end
1714 info.func = XPerl_MainTankSet_OnClick
1715 UIDropDownMenu_AddButton(info, UIDROPDOWNMENU_MENU_LEVEL)
1716 end
1717 return
1718 end
1719  
1720 oldRaidFrameDropDown_Initialize()
1721  
1722 if (IsRaidOfficer()) then
1723 if (DropDownList1.numButtons > 0) then
1724 -- We want our MT option above the Cancel option, so we trick the menu into thinking it's got 1 less button
1725 DropDownList1.numButtons = DropDownList1.numButtons - 1
1726 end
1727  
1728 info = {}
1729 info.text = XPERL_RAID_DROPDOWN_MAINTANKS
1730 info.value = {"Main Tanks", this.name}
1731 info.hasArrow = 1
1732 info.notCheckable = 1
1733 UIDropDownMenu_AddButton(info)
1734  
1735 -- Re-add the cancel button after our MT option
1736 info = {}
1737 info.text = CANCEL
1738 info.value = "CANCEL"
1739 info.owner = "RAID"
1740 info.func = UnitPopup_OnClick
1741 info.notCheckable = 1
1742 UIDropDownMenu_AddButton(info)
1743 end
1744  
1745 if (ct and CT_RATab_AutoPromotions) then
1746 local info = {}
1747 info.text = "Auto-Promote"
1748 info.checked = CT_RATab_AutoPromotions[this.name]
1749 info.value = this.id
1750 info.func = CT_RATab_AutoPromote_OnClick
1751 UIDropDownMenu_AddButton(info)
1752 end
1753 end
1754  
1755 -- XPerl_MainTankSet_OnClick
1756 function XPerl_MainTankSet_OnClick()
1757 if (this.value[1] == "Main Tanks") then
1758 if (this.value[4]) then
1759 SendAddonMessage("CTRA", "R "..this.value[2], "RAID")
1760 else
1761 SendAddonMessage("CTRA", "SET "..this.value[3].." "..this.value[2], "RAID")
1762 end
1763 end
1764 CloseMenus()
1765 end
1766  
1767 -- ShowPopup
1768 local function ShowPopup(thisFrame)
1769 HideDropDownMenu(1)
1770 FriendsDropDown.initialize = RaidFrameDropDown_Initialize
1771 FriendsDropDown.displayMode = "MENU"
1772  
1773 this.unit = thisFrame.partyid
1774 this.name = UnitName(thisFrame.partyid)
1775  
1776 local _, _, id = strfind(thisFrame.partyid, "(%d+)")
1777 this.id = id
1778  
1779 ToggleDropDownMenu(1, nil, FriendsDropDown, thisFrame:GetName(), 0, 0)
1780  
1781 this.unit, this.name, this.id = nil, nil, nil
1782 end
1783  
1784 -- XPerl_Raid_OnClick
1785 function XPerl_Raid_OnClick()
1786 local thisFrame = this:GetParent()
1787 local unitid = thisFrame.partyid
1788  
1789 if (not XPerl_OnClick_Handler(arg1, unitid)) then
1790 if (arg1 == "RightButton" and not thisFrame.pet) then
1791 ShowPopup(thisFrame)
1792 end
1793 end
1794 end
1795  
1796 -- XPerl_ScaleRaid
1797 function XPerl_ScaleRaid(num)
1798 for frame=1,NUM_RAID_GROUPS do
1799 local f = GetRaidGroup(frame)
1800 if (f) then
1801 f:SetScale(num)
1802 end
1803 end
1804 for id,f in pairs(FrameArray) do
1805 f:SetScale(num)
1806 end
1807 for name,f in pairs(PulloutFrameArray) do
1808 f:SetScale(num)
1809 end
1810 end
1811  
1812 -- XPerl_RaidTitles
1813 function XPerl_RaidTitles()
1814 for i = 1,NUM_RAID_GROUPS do
1815 local frame = GetRaidGroup(i)
1816 if (frame) then
1817 frame:SetAlpha(XPerlConfig.Transparency)
1818 if (MovingMember or XPerlLocked == 0 or (XPerlConfig.ShowRaidTitles == 1 and RaidGroupCounts[i] > 0 and XPerlConfig["ShowGroup"..i] == 1)) then
1819 frame:Show()
1820 else
1821 frame:Hide()
1822 end
1823 end
1824 end
1825 end
1826  
1827 -- XPerl_RaidShowAllTitles
1828 function XPerl_RaidShowAllTitles()
1829 for i = 1,NUM_RAID_GROUPS do
1830 GetRaidGroup(i, true)
1831 end
1832 XPerl_RaidTitles()
1833 end
1834  
1835 -- Moving stuff
1836 function XPerl_Raid_GetGap()
1837 if (XPerl_Raid_Grp1 and XPerl_Raid_Grp2) then
1838 return math.floor((math.floor((XPerl_Raid_Grp2:GetLeft() - XPerl_Raid_Grp1:GetRight() + 0.01) * 100) / 100) + 4)
1839 end
1840  
1841 return (0)
1842 end
1843  
1844 -- InterestingFrames
1845 local function InterestingFrames()
1846 local interest = XPerl_Options.raidAlign
1847 local ret = {}
1848  
1849 if (interest == "all") then
1850 for i = 1,NUM_RAID_GROUPS do
1851 tinsert(ret, GetRaidGroup(i, true))
1852 end
1853 elseif (interest == "odd") then
1854 for i = 1,NUM_RAID_GROUPS,2 do
1855 tinsert(ret, GetRaidGroup(i, true))
1856 end
1857 elseif (interest == "even") then
1858 for i = 2,NUM_RAID_GROUPS,2 do
1859 tinsert(ret, GetRaidGroup(i, true))
1860 end
1861 elseif (interest == "first4") then
1862 for i = 1,4 do
1863 tinsert(ret, GetRaidGroup(i, true))
1864 end
1865 elseif (interest == "last4") then
1866 for i = 5,NUM_RAID_GROUPS do
1867 tinsert(ret, GetRaidGroup(i, true))
1868 end
1869 end
1870 return ret
1871 end
1872  
1873 -- XPerl_Raid_SetGap
1874 function XPerl_Raid_SetGap(newGap)
1875 if (not XPerl_Raid_Grp1) then
1876 return
1877 end
1878  
1879 if (type(newGap) == "number") then
1880 local frames = InterestingFrames()
1881  
1882 local left = frames[1]:GetLeft()
1883 local framePrev
1884  
1885 for i,frame in pairs(frames) do
1886 if (framePrev and frame) then
1887 local right = framePrev:GetRight()
1888 local top = frame:GetTop()
1889  
1890 frame:ClearAllPoints()
1891 frame:SetPoint("TOPLEFT", UIParent, "BOTTOMLEFT", right + newGap - 4, top)
1892 end
1893  
1894 framePrev = frame
1895 end
1896  
1897 SaveAllPositions()
1898 end
1899 end
1900  
1901 -- XPerl_Raid_AlignTop
1902 function XPerl_Raid_AlignTop()
1903 if (not XPerl_Raid_Grp1) then
1904 return
1905 end
1906  
1907 local frames = InterestingFrames()
1908  
1909 local top = frames[1]:GetTop()
1910  
1911 for i,frame in pairs(frames) do
1912 local left = frame:GetLeft()
1913  
1914 frame:ClearAllPoints()
1915 frame:SetPoint("TOPLEFT", UIParent, "BOTTOMLEFT", left, top)
1916 end
1917  
1918 SaveAllPositions()
1919 end
1920  
1921 -- XPerl_Raid_SetBuffTooltip
1922 function XPerl_Raid_SetBuffTooltip ()
1923 local partyid = this:GetParent():GetParent().partyid
1924 GameTooltip:SetOwner(this,"ANCHOR_BOTTOMRIGHT",30,0)
1925  
1926 local show, cureCast = GetShowCast(this:GetParent():GetParent())
1927 if (show == "b") then
1928 XPerl_TooltipSetUnitBuff(GameTooltip, partyid, this:GetID(), cureCast)
1929 XPerl_Raid_AddBuffDuration(partyid)
1930 elseif (show == "d") then
1931 XPerl_TooltipSetUnitDebuff(GameTooltip, partyid, this:GetID(), cureCast)
1932 end
1933 end
1934  
1935 ------- XPerl_ToggleRaidBuffs -------
1936 -- Raid Buff Key Binding function --
1937 function XPerl_ToggleRaidBuffs(castable)
1938  
1939 if (castable) then
1940 if (XPerlConfig.BuffsCastableCurable == 1) then
1941 XPerlConfig.BuffsCastableCurable = 0
1942 XPerl_Notice(XPERL_KEY_NOTICE_RAID_BUFFANY)
1943 else
1944 XPerlConfig.BuffsCastableCurable = 1
1945 XPerl_Notice(XPERL_KEY_NOTICE_RAID_BUFFCURECAST)
1946 end
1947 else
1948 if (XPerlConfig.RaidBuffs == 1) then
1949 XPerlConfig.RaidBuffs = 0
1950 XPerlConfig.RaidDebuffs = 1
1951 XPerl_Notice(XPERL_KEY_NOTICE_RAID_DEBUFFS)
1952  
1953 elseif (XPerlConfig.RaidDebuffs == 1) then
1954 XPerlConfig.RaidDebuffs = 0
1955 XPerlConfig.RaidBuffs = 0
1956 XPerl_Notice(XPERL_KEY_NOTICE_RAID_NOBUFFS)
1957  
1958 else
1959 XPerlConfig.RaidBuffs = 1
1960 XPerlConfig.RaidDebuffs = 0
1961 XPerl_Notice(XPERL_KEY_NOTICE_RAID_BUFFS)
1962 end
1963 end
1964  
1965 for i = 1,GetNumRaidMembers() do
1966 local frame = GetRaidUnit(i)
1967 if (frame) then
1968 XPerl_Raid_UpdateDisplay(frame)
1969 end
1970 end
1971 end
1972  
1973 -- GetCombatRezzerList()
1974 local normalRezzers = {PRIEST = true, SHAMAN = true, PALADIN = true}
1975 local function GetCombatRezzerList()
1976  
1977 local anyCombat = 0
1978 local anyAlive = 0
1979 for i = 1,GetNumRaidMembers() do
1980 local _, class = UnitClass("raid"..i)
1981 if (normalRezzers[class]) then
1982 if (UnitAffectingCombat("raid"..i)) then
1983 anyCombat = anyCombat + 1
1984 end
1985 if (not UnitIsDeadOrGhost("raid"..i) and UnitIsConnected("raid"..i)) then
1986 anyAlive = anyAlive + 1
1987 end
1988 end
1989 end
1990  
1991 -- We only need to know about battle rezzers if any normal rezzers are in combat
1992 if (anyCombat > 0) then
1993 local ret = {}
1994 local t = GetTime()
1995  
1996 for i = 1,GetNumRaidMembers() do
1997 if (not UnitIsDeadOrGhost("raid"..i) and UnitIsVisible("raid"..i)) then
1998 local name, rank, subgroup, level, _, fileName, zone, online, isDead = GetRaidRosterInfo(i)
1999  
2000 local good
2001 if (not UnitAffectingCombat("raid"..i)) then
2002 if (fileName == "PRIEST" or fileName == "SHAMAN" or fileName == "PALADIN") then
2003 tinsert(ret, {["name"] = name, class = fileName, cd = 0})
2004 end
2005 else
2006 if (fileName == "DRUID") then
2007 local myRoster = XPerl_Roster[name]
2008  
2009 if (myRoster) then
2010 if (myRoster.Rebirth and myRoster.Rebirth - t <= 0) then
2011 myRoster.Rebirth = nil -- Check for expired cooldown
2012 end
2013 if (myRoster.Rebirth) then
2014 if (myRoster.Rebirth - t < 120) then
2015 tinsert(ret, {["name"] = name, cd = myRoster.Rebirth - t})
2016 end
2017 else
2018 tinsert(ret, {["name"] = name, class = fileName, cd = 0})
2019 end
2020 end
2021 end
2022 end
2023 end
2024 end
2025  
2026 if (getn(ret) > 0) then
2027 sort(ret, function(a,b) return a.cd < b.cd end)
2028  
2029 local list = ""
2030 for k,v in pairs(ret) do
2031 local name = XPerlColourTable[v.class]..v.name.."|r"
2032  
2033 if (v.cd > 0) then
2034 name = name.." (in "..SecondsToTime(v.cd)..")"
2035 end
2036  
2037 if (list == "") then
2038 list = name
2039 else
2040 list = list..", "..name
2041 end
2042 end
2043  
2044 return list
2045 else
2046 return "|c00FF0000"..NONE.."|r"
2047 end
2048 end
2049  
2050 if (anyAlive == 0) then
2051 return "|c00FF0000"..NONE.."|r"
2052 elseif (anyCombat == 0) then
2053 return "|c00FFFFFF"..ALL.."|r"
2054 end
2055 end
2056  
2057 -- XPerl_RaidTipExtra
2058 function XPerl_RaidTipExtra(unitid)
2059  
2060 if (UnitInRaid(unitid)) then
2061 local unitName = UnitName(unitid)
2062 local zone
2063 local name, rank, subgroup, level, class, fileName, zone, online, isDead
2064  
2065 for i = 1,GetNumRaidMembers() do
2066 name, rank, subgroup, level, class, fileName, zone, online, isDead = GetRaidRosterInfo(i)
2067 if (name == unitName) then
2068 break
2069 end
2070 zone = ""
2071 end
2072  
2073 local stats = XPerl_Roster[unitName]
2074 if (stats) then
2075 local t = GetTime()
2076  
2077 if (stats.version) then
2078 if (stats.oRAversion) then
2079 GameTooltip:AddLine("CTRA "..stats.version.." (oRA "..stats.oRAversion..")", 1, 1, 1)
2080 else
2081 GameTooltip:AddLine("CTRA "..stats.version, 1, 1, 1)
2082 end
2083 else
2084 GameTooltip:AddLine(XPERL_RAID_TOOLTIP_NOCTRA, 0.7, 0.7, 0.7)
2085 end
2086  
2087 if (stats.offline and UnitIsConnected(unitid)) then
2088 stats.offline = nil
2089 end
2090  
2091 if (stats.offline) then
2092 GameTooltip:AddLine(string.format(XPERL_RAID_TOOLTIP_OFFLINE, SecondsToTime(t - stats.offline)))
2093  
2094 elseif (stats.afk) then
2095 GameTooltip:AddLine(string.format(XPERL_RAID_TOOLTIP_AFK, SecondsToTime(t - stats.afk)))
2096  
2097 elseif (stats.dnd) then
2098 GameTooltip:AddLine(string.format(XPERL_RAID_TOOLTIP_DND, SecondsToTime(t - stats.dnd)))
2099  
2100 elseif (stats.fd) then
2101 if (not UnitIsDead(unitid)) then
2102 stats.fd = nil
2103 else
2104 local x = stats.fd + 360 - t
2105 if (x > 0) then
2106 GameTooltip:AddLine(string.format(XPERL_RAID_TOOLTIP_DYING, SecondsToTime(x)))
2107 end
2108 end
2109 end
2110  
2111 if (stats.Rebirth) then
2112 if (stats.Rebirth - t > 0) then
2113 GameTooltip:AddLine(string.format(XPERL_RAID_TOOLTIP_REBIRTH, SecondsToTime(stats.Rebirth - t)))
2114 else
2115 stats.Rebirth = nil
2116 end
2117  
2118 elseif (stats.Reincarnation) then
2119 if (stats.Reincarnation - t > 0) then
2120 GameTooltip:AddLine(string.format(XPERL_RAID_TOOLTIP_ANKH, SecondsToTime(stats.Reincarnation - t)))
2121 else
2122 stats.Reincarnation = nil
2123 end
2124  
2125 elseif (stats.Soulstone) then
2126 if (stats.Soulstone - t > 0) then
2127 GameTooltip:AddLine(string.format(XPERL_RAID_TOOLTIP_SOULSTONE, SecondsToTime(stats.Soulstone - t)))
2128 else
2129 stats.Soulstone = nil
2130 end
2131 end
2132  
2133 if (UnitIsDeadOrGhost(unitid)) then
2134 if (stats.resCount) then
2135 GameTooltip:AddLine(XPERL_LOC_RESURRECTED.." x"..stats.resCount)
2136 end
2137  
2138 local Rezzers = GetCombatRezzerList()
2139 if (Rezzers) then
2140 GameTooltip:AddLine("Rezzers Available: "..Rezzers, NORMAL_FONT_COLOR.r, NORMAL_FONT_COLOR.g, NORMAL_FONT_COLOR.b, 1)
2141 end
2142 end
2143 end
2144  
2145 GameTooltip:Show()
2146 end
2147 end
2148  
2149 -- GetNamesWithoutBuff
2150 local function GetNamesWithoutBuff(tex, with)
2151 local matches = {
2152 {"Holy_WordFortitude", "Holy_PrayerOfFortitude"},
2153 {"Holy_MagicalSentry", "Holy_ArcaneIntellect"},
2154 {"Shadow_AntiShadow", "Holy_PrayerofShadowProtection"},
2155 {"Holy_DivineSpirit", "Holy_PrayerofSpirit"},
2156 {"Holy_FistOfJustice", "Holy_GreaterBlessingofKings"},
2157 {"Holy_SealOfWisdom", "Holy_GreaterBlessingofWisdom"},
2158 {"Magic_MageArmor", "Magic_GreaterBlessingofKings"},
2159 {"Holy_SealOfSalvation", "Holy_GreaterBlessingofSalvation"},
2160 {"Holy_PrayerOfHealing02", "Holy_GreaterBlessingofLight"},
2161 {"Nature_LightningShield", "Holy_GreaterBlessingofSanctuary"}
2162 }
2163  
2164 local count = 0
2165 local names
2166 local checkExpiring
2167  
2168 local _, class = UnitClass("player")
2169 if (IsRaidOfficer()) then
2170 checkExpiring = {all = 5}
2171  
2172 elseif (class == "PRIEST") then
2173 checkExpiring = {Spell_Holy_WordFortitude = 5, Spell_Holy_PrayerOfFortitude = 5,
2174 Spell_Holy_DivineSpirit = 2, Spell_Holy_PrayerofSpirit = 2,
2175 Spell_Shadow_AntiShadow = 2, Spell_Holy_PrayerofShadowProtection = 2}
2176  
2177 elseif (class == "DRUID") then
2178 checkExpiring = {Spell_Nature_Regeneration = 5, Spell_Nature_Thorns = 2}
2179  
2180 elseif (class == "MAGE") then
2181 checkExpiring = {Spell_Holy_MagicalSentry = 5, Spell_Holy_ArcaneIntellect = 5, Spell_Holy_FlashHeal = 2, Spell_Nature_AbolishMagic = 2}
2182  
2183 elseif (class == "PALADIN") then
2184 checkExpiring = {Spell_Holy_Excorcism = 2,
2185 Spell_Holy_FistOfJustice = 1, Spell_Holy_GreaterBlessingofKings = 1,
2186 Spell_Holy_SealOfWisdom = 1, Spell_Holy_GreaterBlessingofWisdom = 1,
2187 Spell_Magic_MageArmor = 1, Spell_Magic_GreaterBlessingofKings = 1,
2188 Spell_Holy_SealOfSalvation = 1, Spell_Holy_GreaterBlessingofSalvation = 1,
2189 Spell_Holy_PrayerOfHealing02 = 1, Spell_Holy_GreaterBlessingofLight = 1,
2190 Spell_Nature_LightningShield = 1, Spell_Holy_GreaterBlessingofSanctuary = 1}
2191 end
2192  
2193 for i = 1,GetNumRaidMembers() do
2194 local name = UnitName("raid"..i)
2195 local _, unitClass = UnitClass("raid"..i)
2196 if (name and UnitIsConnected("raid"..i) and not UnitIsDeadOrGhost("raid"..i)) then
2197 local hasBuff
2198 for num = 1,25 do
2199 local buffTexture = UnitBuff("raid"..i, num)
2200 if (not buffTexture) then
2201 break
2202 end
2203  
2204 if (buffTexture == tex) then
2205 hasBuff = true
2206 break
2207 else
2208 for dups,pair in pairs(matches) do
2209 if (tex == "Interface\\Icons\\Spell_"..pair[1] or tex == "Interface\\Icons\\Spell_"..pair[2]) then
2210 if (buffTexture == "Interface\\Icons\\Spell_"..pair[1] or buffTexture == "Interface\\Icons\\Spell_"..pair[2]) then
2211 hasBuff = true
2212 end
2213 end
2214 end
2215 if (hasBuff) then
2216 if (without and checkExpiring) then
2217 local found = checkExpiring.all
2218  
2219 if (not found) then
2220 found = checkExpiring[strsub(buffTexture, 23)]
2221 end
2222  
2223 if (found) then
2224 local myRoster = XPerl_Roster[name]
2225 if (myRoster and myRoster.Buffs) then
2226 local buffName
2227 for k,v in pairs(XPerl_CTBuffTextures) do
2228 if (v[1] == "Interface\\Icons\\"..buffTexture) then
2229 buffName = k
2230 break
2231 end
2232 end
2233  
2234 if (buffName) then
2235 if (myRoster.Buffs[buffName]) then
2236 local expire = myRoster.Buffs[buffName]
2237 if (expire > GetTime() + (found*60)) then
2238 GameTooltip:AddLine(string.format(XPERL_RAID_TOOLTIP_BUFFEXPIRING, XPerlColourTable[unitClass]..name.."|c", buffName, SecondsToTime(buff - GetTime())), 1, 0.2, 0)
2239 end
2240 end
2241 end
2242 end
2243 end
2244 end
2245 break
2246 end
2247 end
2248 end
2249  
2250 if ((with and hasBuff) or (not with and not hasBuff)) then
2251 count = count + 1
2252 local _, class = UnitClass("raid"..i)
2253 if (class) then
2254 names = (names or "")..XPerlColourTable[class]..name.." "
2255 else
2256 names = (names or "")..name.." "
2257 end
2258 end
2259 end
2260 end
2261  
2262 return names, count
2263 end
2264  
2265 -- XPerl_Raid_AddBuffDuration
2266 function XPerl_Raid_AddBuffDuration(partyid, x)
2267 local XTooltip
2268 if (x) then
2269 XTooltip = x
2270 else
2271 XTooltip = GameTooltip
2272 end
2273  
2274 if (UnitInRaid("player") and XTooltip:IsOwned(this)) then
2275 if (partyid ~= "player") then
2276 local stats = XPerl_Roster[UnitName(partyid)]
2277  
2278 if (stats and stats.Buffs) then
2279 local buffName = getglobal("GameTooltipTextLeft1"):GetText()
2280 if (buffName) then
2281 local buff = stats.Buffs[buffName]
2282 if (buff) then
2283 if (buff > GetTime()) then
2284 XTooltip:AddLine(SecondsToTime(buff - GetTime())..XPERL_RAID_TOOLTIP_REMAINING, 1, 0.82, 0)
2285 end
2286 end
2287 end
2288 end
2289 end
2290  
2291 if (XPerlConfig.BuffTooltipHelper == 1 and partyid and UnitInRaid(partyid)) then
2292 local icon = getglobal(this:GetName().."Icon")
2293 if (icon) then
2294 local tex = icon:GetTexture()
2295 if (tex) then
2296 local names, count = GetNamesWithoutBuff(tex, IsAltKeyDown())
2297 if (names) then
2298 if (IsAltKeyDown()) then
2299 XTooltip:AddLine(string.format(XPERL_RAID_TOOLTIP_WITHBUFF, count), 0.3, 1, 0.2)
2300 else
2301 XTooltip:AddLine(string.format(XPERL_RAID_TOOLTIP_WITHOUTBUFF, count), 1, 0.3, 0.1)
2302 end
2303 XTooltip:AddLine(names, 0.8, 0.5, 0.4, 1)
2304 end
2305 end
2306 end
2307 end
2308  
2309 XTooltip:Show()
2310 end
2311 end
2312  
2313 -- XPerl_Raid_Set_Bits
2314 function XPerl_Raid_Set_Bits()
2315  
2316 local msgs = { "UNIT_DISPLAYPOWER",
2317 "UNIT_MANA", "UNIT_MAXMANA",
2318 "UNIT_ENERGY", "UNIT_MAXENERGY",
2319 "UNIT_RAGE", "UNIT_MAXRAGE"}
2320  
2321 for i,msg in pairs(msgs) do
2322 if (XPerlConfig.RaidMana == 1) then
2323 XPerl_Raid_Frame:RegisterEvent(msg)
2324 else
2325 XPerl_Raid_Frame:UnregisterEvent(msg)
2326 end
2327 end
2328  
2329 for i,frame in pairs(FrameArray) do
2330 Setup1RaidFrame(frame)
2331 if (frame.showing == 1) then
2332 XPerl_Raid_UpdateName(frame)
2333 end
2334 end
2335  
2336 for i,frame in pairs(PulloutFrameArray) do
2337 Setup1RaidFrame(frame)
2338 if (frame.showing == 1) then
2339 XPerl_Raid_UpdateName(frame)
2340 end
2341 end
2342 end
2343  
2344 -- Blizzard raid pullout replacements
2345  
2346 local PetClasses = {HUNTER = true, WARLOCK = true}
2347  
2348 function XPerl_ReplaceBlizzardPullouts()
2349  
2350 -- RaidPullout_GenerateGroupFrame(groupID)
2351 RaidPullout_GenerateGroupFrame = function(groupID)
2352 local pets = (IsControlKeyDown() == 1)
2353  
2354 -- construct the button listing
2355 if ( not groupID ) then
2356 groupID = this:GetParent():GetID()
2357 end
2358  
2359 -- Get a handle on a pullout frame
2360 local pullOutFrame = RaidPullout_GetFrame(groupID)
2361 if ( pullOutFrame ) then
2362 pullOutFrame.filterID = groupID
2363 pullOutFrame.showBuffs = nil
2364  
2365 -- Set pullout name
2366 local title = GROUP.." "..groupID
2367 if (pets) then
2368 title = title.." "..PET
2369 end
2370 getglobal(pullOutFrame:GetName().."Name"):SetText(title)
2371  
2372 -- TODO Title scale to 0.75, but we can't set scale of a fontstring
2373 if (RaidPullout_Update(pullOutFrame, pets)) then
2374 return pullOutFrame
2375 end
2376 end
2377 end
2378  
2379 RaidPullout_GenerateClassFrame = function(class, fileName)
2380 local pets = (IsControlKeyDown() == 1)
2381  
2382 -- construct the button listing
2383 if ( not class ) then
2384 class = this:GetParent().class;
2385 end
2386  
2387 if (pets and not PetClasses[fileName]) then -- not AnyPets(fileName)) then
2388 return
2389 end
2390  
2391 -- Get a handle on a pullout frame
2392 local pullOutFrame = RaidPullout_GetFrame(fileName);
2393 if ( pullOutFrame ) then
2394 pullOutFrame.filterID = fileName;
2395 pullOutFrame.showBuffs = nil;
2396  
2397 -- Set pullout name
2398 if (pets) then
2399 class = class.." "..PET
2400 end
2401 getglobal(pullOutFrame:GetName().."Name"):SetText(class);
2402  
2403 -- TODO Title scale to 0.75, but we can't set scale of a fontstring
2404 if ( RaidPullout_Update(pullOutFrame, pets) ) then
2405 return pullOutFrame;
2406 end
2407 end
2408 end
2409  
2410 RaidPullout_GetFrame = function(groupID)
2411 -- Grab an available pullout frame
2412 local frame;
2413 for i=1, NUM_RAID_PULLOUT_FRAMES do
2414 frame = getglobal("RaidPullout"..i);
2415 -- if frame is visible see if its group id is already taken
2416 if ( frame:IsVisible() and filterID == frame.filterID ) then
2417 return nil;
2418 end
2419 end
2420 for i=1, NUM_RAID_PULLOUT_FRAMES do
2421 frame = getglobal("RaidPullout"..i);
2422 if ( not frame:IsVisible() ) then
2423 return frame;
2424 end
2425 end
2426 NUM_RAID_PULLOUT_FRAMES = NUM_RAID_PULLOUT_FRAMES + 1;
2427 frame = CreateFrame("Button", "RaidPullout"..NUM_RAID_PULLOUT_FRAMES, UIParent, "RaidPulloutFrameTemplate");
2428 frame.numPulloutButtons = 0;
2429  
2430 local f = getglobal("RaidPullout"..NUM_RAID_PULLOUT_FRAMES.."MenuBackdrop")
2431 f:Hide()
2432  
2433 return frame;
2434 end
2435  
2436 RaidPullout_Update = function(pullOutFrame, pets)
2437 if ( not pullOutFrame ) then
2438 pullOutFrame = this
2439 end
2440  
2441 if (pets ~= nil) then
2442 pullOutFrame.pets = pets
2443 end
2444 pets = pullOutFrame.pets
2445  
2446 local filterID = pullOutFrame.filterID
2447 local numPulloutEntries = 0
2448 if ( RAID_SUBGROUP_LISTS[filterID] ) then
2449 numPulloutEntries = getn(RAID_SUBGROUP_LISTS[filterID])
2450 end
2451 local pulloutList = RAID_SUBGROUP_LISTS[filterID]
2452  
2453 -- Hide the pullout if no entries
2454 if ( numPulloutEntries == 0 ) then
2455 pullOutFrame:Hide()
2456 return nil
2457 end
2458  
2459 -- Fill out the buttons
2460 local pulloutButton, pulloutButtonName, color, unit, pulloutHealthBar, pulloutManaBar, unitHPMin, unitHPMax
2461 local name, rank, subgroup, level, class, fileName, zone, online, isDead
2462 local debuff
2463  
2464 if (numPulloutEntries > pullOutFrame.numPulloutButtons) then
2465 local index = pullOutFrame.numPulloutButtons + 1
2466 local relative
2467 for i = index, numPulloutEntries do
2468 pulloutButton = CreateFrame("Frame", pullOutFrame:GetName().."Button"..i, pullOutFrame, "XPerl_Raid_FrameTemplate")
2469 PulloutFrameArray[pulloutButton:GetName()] = pulloutButton
2470  
2471 if (i == 1) then
2472 pulloutButton:SetPoint("TOP", pullOutFrame, "TOP", 0, 0)
2473 else
2474 relative = getglobal(pullOutFrame:GetName().."Button"..(i-1).."_StatsFrame")
2475 pulloutButton:SetPoint("TOP", relative, "BOTTOM", 0, 4)
2476 end
2477 end
2478 pullOutFrame.numPulloutButtons = numPulloutEntries;
2479 end
2480  
2481 local j = 1
2482 for i = 1,numPulloutEntries do
2483 pulloutButton = getglobal(pullOutFrame:GetName().."Button"..j)
2484 if (pulloutButton) then
2485 local _, ownerClass = UnitClass("raid"..pulloutList[i])
2486 if (not pets or PetClasses[ownerClass]) then
2487 pulloutButton.showing = 1
2488 pulloutButton:SetScale(XPerlConfig.Scale_Raid)
2489 Setup1RaidFrame(pulloutButton)
2490  
2491 pulloutButton.petname = nil
2492 if (pets) then
2493 XPerl_Raid_Frame:RegisterEvent("UNIT_PET")
2494 pulloutButton.partyid = "raidpet"..pulloutList[i]
2495 pulloutButton.petOwner = "raid"..pulloutList[i]
2496 pulloutButton.pet = true
2497 else
2498 pulloutButton.partyid = "raid"..pulloutList[i]
2499 pulloutButton.pet = nil
2500 pulloutButton.petOwner = nil
2501 end
2502  
2503 XPerl_Raid_UpdateDisplay(pulloutButton)
2504 pulloutButton:Show()
2505 j = j + 1
2506 end
2507 end
2508 end
2509 for i = j,pullOutFrame.numPulloutButtons do
2510 pulloutButton = getglobal(pullOutFrame:GetName().."Button"..i)
2511 if (pulloutButton) then
2512 pulloutButton.showing = 0
2513 pulloutButton:Hide()
2514 end
2515 end
2516  
2517 pullOutFrame:SetHeight(1)
2518 pullOutFrame:Show()
2519 return 1
2520 end
2521  
2522 RaidPulloutDropDown_Initialize = function()
2523 if ( not UIDROPDOWNMENU_OPEN_MENU or not getglobal(UIDROPDOWNMENU_OPEN_MENU).raidPulloutDropDown ) then
2524 return;
2525 end
2526 local currentPullout = getglobal(UIDROPDOWNMENU_OPEN_MENU):GetParent();
2527 local info;
2528  
2529 -- Show buffs or debuffs they are exclusive for now
2530 info = {};
2531 info.text = SHOW_BUFFS;
2532 info.func = function()
2533 currentPullout.showBuffs = 1;
2534 RaidPullout_Update(currentPullout);
2535 end;
2536 if ( currentPullout.showBuffs ) then
2537 info.checked = 1;
2538 end
2539 UIDropDownMenu_AddButton(info);
2540  
2541 info = {};
2542 info.text = SHOW_DEBUFFS;
2543 info.func = function()
2544 currentPullout.showBuffs = nil;
2545 RaidPullout_Update(currentPullout);
2546 end;
2547 if ( not currentPullout.showBuffs ) then
2548 info.checked = 1;
2549 end
2550 UIDropDownMenu_AddButton(info);
2551  
2552 -- Castable/Curable
2553 info = {};
2554 if (currentPullout.showBuffs) then
2555 info.text = SHOW_CASTABLE_BUFFS_TEXT
2556 else
2557 info.text = SHOW_DISPELLABLE_DEBUFFS_TEXT
2558 end
2559 info.func = function()
2560 currentPullout.cureCast = not currentPullout.cureCast
2561 RaidPullout_Update(currentPullout);
2562 end;
2563 if (currentPullout.cureCast) then
2564 info.checked = 1;
2565 end
2566 UIDropDownMenu_AddButton(info);
2567  
2568 -- Pets
2569 info = {}
2570 if (currentPullout.pets) then
2571 info.text = "Show Owners"
2572 else
2573 info.text = "Show Pets"
2574 end
2575 info.func = function()
2576 currentPullout.pets = not currentPullout.pets
2577 RaidPullout_Update(currentPullout)
2578  
2579 local titleFrame = getglobal(currentPullout:GetName().."Name")
2580 local title = titleFrame:GetText()
2581 if (currentPullout.pets) then
2582 title = title.." "..PET
2583 else
2584 title = string.gsub(title, " "..PET, "")
2585 end
2586 titleFrame:SetText(title)
2587 end;
2588 if (currentPullout.pets) then
2589 info.checked = 1
2590 end
2591 UIDropDownMenu_AddButton(info)
2592  
2593 -- Close option
2594 info = {};
2595 info.text = CLOSE;
2596 info.func = function()
2597 currentPullout:Hide();
2598 end;
2599 UIDropDownMenu_AddButton(info);
2600 end
2601  
2602 end