Got an iPhone or iPad? We have a brand new Pastebin App for both devices, and it's totally free! Click here to download the new Pastebin App for iOS.
Guest

Untitled

By: a guest on Feb 19th, 2012  |  syntax: Lua  |  size: 45.20 KB  |  hits: 18  |  expires: Never
download  |  raw  |  embed  |  report abuse
Copied
  1. -- X-Perl UnitFrames
  2. -- Author: Zek <Boodhoof-EU>
  3. -- License: GNU GPL v3, 29 June 2007 (see LICENSE.txt)
  4.  
  5. local playerClass, playerName, playerGUID
  6. local conf
  7. XPerl_RequestConfig(function(new) conf = new end, "$Revision: 590 $")
  8.  
  9. local GetNumPartyMembers = GetNumPartyMembers
  10. local GetNumRaidMembers = GetNumRaidMembers
  11. local GetTime = GetTime
  12. local UnitBuff = UnitBuff
  13. local UnitClass = UnitClass
  14. local UnitInParty = UnitInParty
  15. local UnitInRaid = UnitInRaid
  16. local UnitGUID = UnitGUID
  17. local UnitPlayerOrPetInRaid = UnitPlayerOrPetInRaid
  18. local UnitPlayerOrPetInParty = UnitPlayerOrPetInParty
  19. local UnitName = UnitName
  20. local cos = math.cos
  21. local sin = math.sin
  22. local band = bit.band
  23.  
  24. local new, del, copy = XPerl_GetReusableTable, XPerl_FreeTable, XPerl_CopyTable
  25.  
  26. local hotSpells  = XPERL_HIGHLIGHT_SPELLS.hotSpells
  27. local pomSpells = XPERL_HIGHLIGHT_SPELLS.pomSpells
  28. local shieldSpells = XPERL_HIGHLIGHT_SPELLS.shieldSpells
  29.  
  30. local function GetTalentPosition(findName)
  31.         for i = 1,GetNumTalentTabs() do
  32.                 for j = 1,GetNumTalents(i) do
  33.                         local name = GetTalentInfo(i, j)
  34.                         if (name == findName) then
  35.                                 return i, j
  36.                         end
  37.                 end
  38.         end
  39. end
  40.  
  41. local function GetTalentValueByName(name)
  42.         local group = GetActiveTalentGroup()
  43.         local tab, index = GetTalentPosition(name)
  44.         if (index) then
  45.                 local name, iconPath, tier, column, currentRank, maxRank, isExceptional, meetsPrereq = GetTalentInfo(tab, index, nil, nil, group)
  46.                 return currentRank
  47.         end
  48.         return 0
  49. end
  50.  
  51. local function getTalentModifier(self)
  52.         if (self.improved) then
  53.                 local spent = GetTalentValueByName(self.improved.name)
  54.                 return 1 + (self.improved.percentPerRank * spent) / 100
  55.         end
  56.         return 1
  57. end
  58.  
  59. local function getRankAmount(self, spellId)
  60.         local amount = self.ranks[spellId]
  61.         if (amount) then
  62.                 return amount * self:GetModifier()
  63.         end
  64. end
  65.  
  66. local absorbSpells = {
  67.         [GetSpellInfo(11426)] = {                       -- Ice Barrier
  68.                 ranks = {
  69.                         [11426] = 3686--level 85 (3686 + $SPFR * 0.807)
  70.                 },
  71.                 school = "FROST",
  72.                 class = "MAGE",
  73.                 GetModifier = getTalentModifier,
  74.                 GetRankAmount = getRankAmount,
  75.         },
  76.         [GetSpellInfo(1463)] = {                        -- Mana Shield
  77.                 ranks = {
  78.                         [1463]  = 1485--level 85 (1485 + 0.807 * $SPA)
  79.                 },
  80.                 class = "MAGE",
  81.                 school = "ARCANE",
  82.                 improved = {
  83.                         name = GetSpellInfo(12605),
  84.                         ranks = 2,
  85.                         percentPerRank = 10,
  86.                 },
  87.                 GetModifier = getTalentModifier,
  88.                 GetRankAmount = getRankAmount,
  89.         },
  90.         [GetSpellInfo(17)] = {                          -- Power Word: Shield
  91.                 ranks = {
  92.                         [17]    = 3906--level 85 (3906 + ($SP * 0.418))
  93.                 },
  94.                 class = "PRIEST",
  95.                 targetable = true,
  96.                 school = "HOLY",
  97.                 improved = {
  98.                         name = GetSpellInfo(14748),
  99.                         ranks = 2,
  100.                         percentPerRank = 5,
  101.                 },
  102.                 GetModifier = getTalentModifier,
  103.                 GetRankAmount = getRankAmount,
  104.         },
  105. }
  106.  
  107. local colours = {HOT = {r = 0.2, g = 0.4, b = 0.8, canFlash = true},
  108.                  POM = {r = 0.8, g = 0.6, b = 0.4},
  109.                  SHIELD = {r = 0.6, g = 0.1, b = 0.6, canFlash = true},
  110.                  AGGRO = {r = 0.8, g = 0, b = 0},
  111.                  HEAL = {r = 0.2, g = 0.8, b = 0.2},
  112.                  SEL = {r = 0.86, g = 0.82, b = 0.41},
  113.                  TARGET = {r = 0.7167, g = 0.6833, b = 0.31467}                 -- Coloured so that colour * 1.2 == SEL colour
  114. }
  115.  
  116. local xpHigh = CreateFrame("Frame", "XPerl_Highlight")
  117. xpHigh.list = {}
  118. xpHigh.callbacks = {}
  119. xpHigh.lastExpireCheck = 0
  120. xpHigh.flashers = {}
  121. xpHigh.mendingIcons = {}
  122. xpHigh.shields = {}
  123.  
  124. -- rotate
  125. -- Positive angle is clockwise rotation
  126. local function rotate(angle)
  127.         local hcos = 0.5 * cos(angle)
  128.         local mhcos = -hcos
  129.         local hsin = 0.5 * sin(angle)
  130.         local mhsin = -hsin
  131.         local ULx, ULy, LLx, LLy = hcos - mhsin, mhsin + hcos, hcos - hsin, mhsin + mhcos
  132.         local URx, URy, LRx, LRy = mhcos - mhsin, hsin + hcos, mhcos - hsin, hsin + mhcos
  133.         return ULx+0.5, ULy+0.5, LLx+0.5, LLy+0.5, URx+0.5, URy+0.5, LRx+0.5, LRy+0.5
  134. end
  135.  
  136. function xpHigh:Print(...)
  137.         ChatFrame1:AddMessage("|cFFFFFF80"..format(...))
  138. end
  139.  
  140. -- XPerl_Highlight:Add
  141. function xpHigh:Add(guid, highlightType, duration, source)
  142.         if (not strfind(guid, "^0x")) then
  143.                 guid = self.lookup and self.lookup[guid]
  144.         end
  145.         if (not guid) then
  146.                 return
  147.         end
  148.  
  149.         local a = self.list[guid]
  150.         if (not a) then
  151.                 a = new()
  152.                 self.list[guid] = a
  153.         end
  154.  
  155.         if (not duration) then
  156.                 a[highlightType] = nil
  157.                 self:Send(guid)
  158.         else
  159.                 if (duration == 0) then
  160.                         a[highlightType] = 0
  161.                         self:Send(guid)
  162.                 else
  163.                         if (highlightType == "HOTCOUNT") then
  164.                                 a[highlightType] = duration
  165.                                 self:Send(guid)
  166.                         else
  167.                                 local newEndTime = GetTime() + duration
  168.                                 if (highlightType == "HEAL" and (UnitInRaid(source) or UnitInParty(source))) then
  169.                                         if (source and not UnitIsUnit("player", source)) then
  170.                                                 -- We'll query their cast bar and get accurate highlight time info
  171.                                                 local spellName, rank, spellNameAlso, iconTexture, startTime, endTime, isTradeSkill = UnitCastingInfo(source)
  172.                                                 if (spellName and rank and rank ~= "") then
  173.                                                         newEndTime = endTime / 1000
  174.                                                 end
  175.  
  176.                                                 --newEndTime = newEndTime + 0.8         -- Add some because other highlights expire 1 sec early
  177.                                         end
  178.                                 end
  179.  
  180.                                 local current = a[highlightType]
  181.                                 if (not current or current < newEndTime) then
  182.                                         a[highlightType] = newEndTime
  183.                                         self:Send(guid)
  184.                                 end
  185.                         end
  186.                 end
  187.         end
  188. end
  189.  
  190. -- xpHigh:TooltipInfo
  191. function xpHigh:TooltipInfo(guid)
  192.         local effects = self.list[guid]
  193.         if (effects) then
  194.                 local str = ""
  195.                 local prefix = XPERL_LOC_STATUSTIP
  196.                 for k,v in pairs(effects) do
  197.                         local desc = XPERL_LOC_STATUSTIPLIST[k]
  198.                         local c = colours[k]
  199.                         if (desc and c) then
  200.                                 str = str..prefix..format("|c00%02X%02X%02X", 255 * c.r, 255 * c.g, 255 * c.b)..desc.."|r"
  201.                                 prefix = ", "
  202.                         end
  203.                 end
  204.  
  205.                 if (prefix == ", ") then
  206.                         GameTooltip:AddLine("\r"..str)
  207.                         GameTooltip:Show()
  208.                 end
  209.         end
  210. end
  211.  
  212. -- xpHigh:Remove
  213. function xpHigh:Remove(guid, highlightType)
  214.         if (not strfind(guid, "^0x")) then
  215.                 guid = self.lookup and self.lookup[guid]
  216.         end
  217.         if (not guid) then
  218.                 return
  219.         end
  220.  
  221.         local a = self.list[guid]
  222.         if (a) then
  223.                 a[highlightType] = nil
  224.                 self:Send(guid)
  225.         end
  226. end
  227.  
  228. -- xpHigh:HasEffect
  229. function xpHigh:HasEffect(guid, effect)
  230.         if (not strfind(guid, "^0x")) then
  231.                 guid = self.lookup and self.lookup[guid]
  232.         end
  233.         if (not guid) then
  234.                 return
  235.         end
  236.  
  237.         local list = self.list[guid]
  238.         if (list) then
  239.                 return list[effect]
  240.         end
  241. end
  242.  
  243. -- xpHigh:OnUpdate
  244. function xpHigh:OnUpdate(elapsed)
  245.         if (self.rosterUpdate) then
  246.                 self.rosterUpdate = nil
  247.                 self:RefreshAllAuras()                  -- New roster, get all
  248.                 if (not (conf.highlight.enable and (conf.highlight.HOT or conf.highlight.SHIELD or conf.highlight.HEAL))) then
  249.                         self:SetScript("OnUpdate", nil)
  250.                         return
  251.                 end
  252.         end
  253.  
  254.         if (self.mendingAnimation) then
  255.                 self:MendingAnimationOnUpdate(elapsed)
  256.         end
  257.  
  258.         if (self.sparkleAreas) then
  259.                 self:SparkleAreasOnUpdate(elapsed)
  260.         end
  261.  
  262.         self.lastExpireCheck = self.lastExpireCheck + elapsed
  263.         if (self.lastExpireCheck > 0.2) then
  264.                 self.lastExpireCheck = 0
  265.         else
  266.                 return
  267.         end
  268.  
  269.         -- We expire things 1 second early so people can cast in time for buff to expire
  270.         local now = GetTime()                   --  + 1
  271.  
  272.         for guid,list in pairs(self.list) do
  273.                 local any
  274.                 for k,v in pairs(list) do
  275.                         any = true
  276.                         if (k ~= "HOTCOUNT") then
  277.                                 if (v > 0) then
  278.                                         if (v <= now) then
  279.                                                 self.flashers[guid] = nil
  280.                                                 list[k] = nil
  281.                                                 self:Send(guid)
  282.  
  283.                                         elseif (v <= now + 5 and colours[k] and colours[k].canFlash) then
  284.                                                 if (not self.flashers[guid]) then
  285.                                                         self.flashers[guid] = k
  286.                                                         self:Send(guid)
  287.                                                 end
  288.                                         end
  289.                                 end
  290.                         end
  291.                 end
  292.  
  293.                 if (not any) then
  294.                         self.list[guid] = nil
  295.                         self.flashers[guid] = nil
  296.                 end
  297.         end
  298. end
  299.  
  300. -- xpHigh:Query
  301. function xpHigh:SetHighlight(frame, guid)
  302.         if (not frame.highlight) then
  303.                 XPerl_Notice("No .highlight region for "..frame:GetName()..", unit: "..guid)
  304.                 return
  305.         end
  306.  
  307.         local unitid
  308.         if (not guid) then
  309.                 unitid = SecureButton_GetUnit(frame)
  310.                 if (unitid) then
  311.                         guid = UnitGUID(unitid)
  312.                 else
  313.                         return
  314.                 end
  315.         end
  316.  
  317.         self:OnUpdate(0)
  318.  
  319.         local hotCount, pomActive, hotBar, hotSparks, showShield
  320.         if (guid and conf.highlight.enable) then
  321.                 local r = self.list[guid]
  322.                 if (r) then
  323.                         local r1, g1, b1, r2, g2, b2, t1
  324.                         for k,v in pairs(r) do
  325.                                 if (k == "POM" and conf.highlight.sparkles) then
  326.                                         pomActive = true
  327.                                 elseif (k == "HOTCOUNT") then
  328.                                         hotCount = v
  329.                                 elseif (k == "HOT" and conf.highlight.sparkles) then
  330.                                         hotBar = true
  331.                                 elseif (k == "HOTSPARKS" and conf.highlight.extraSparkles) then
  332.                                         hotSparks = true
  333.                                 else
  334.                                         if (not r1 or t1 == "TARGET") then
  335.                                                 t1 = k
  336.                                                 r1, g1, b1 = colours[k].r, colours[k].g, colours[k].b
  337.                                         else
  338.                                                 r2, g2, b2 = colours[k].r, colours[k].g, colours[k].b
  339.                                                 break
  340.                                         end
  341.                                 end
  342.                         end
  343.  
  344.                         if (r1) then
  345.                                 frame.highlight.tex:Show()
  346.                                 frame.highlight.tex:SetAlpha(1)
  347.  
  348.                                 if (frame.highlight.sel) then
  349.                                         r1 = min(r1 * 1.2, 1)
  350.                                         g1 = min(g1 * 1.2, 1)
  351.                                         b1 = min(b1 * 1.2, 1)
  352.                                 end
  353.  
  354.                                 if (r2) then
  355.                                         if (frame.highlight.sel) then
  356.                                                 r2 = min(r2 * 1.2, 1)
  357.                                                 g2 = min(g2 * 1.2, 1)
  358.                                                 b2 = min(b2 * 1.2, 1)
  359.                                         end
  360.                                         frame.highlight.tex:SetGradient("HORIZONTAL", r1, g1, b1, r2, g2, b2)
  361.                                 else
  362.                                         frame.highlight.tex:SetVertexColor(r1, g1, b1)
  363.                                 end
  364.  
  365.                                 if (self.flashers[guid]) then
  366.                                         XPerl_FrameFlash(frame.highlight.tex)
  367.                                 else
  368.                                         XPerl_FrameFlashStop(frame.highlight.tex)
  369.                                 end
  370.                                 self:ShowHotCount(frame, hotCount)
  371.                                 self:ShowMending(frame, pomActive)
  372.                                 self:ShowHotBar(frame, hotBar)
  373.                                 self:ShowHotSparks(frame, hotSparks)
  374.                                 self:ShowShieldBar(frame, self.shields[guid])
  375.                                 return
  376.                         end
  377.                 end
  378.         end
  379.  
  380.         self:RemoveHighlight(frame)
  381.         self:ShowHotCount(frame, hotCount)
  382.         self:ShowMending(frame, pomActive)
  383.         self:ShowHotBar(frame, hotBar)
  384.         self:ShowHotSparks(frame, hotSparks)
  385.         self:ShowShieldBar(frame, self.shields[guid])
  386. end
  387.  
  388. -- fluctuateOnUpdate
  389. local function fluctuateOnUpdate(self, elapsed)
  390.         if (self.fluctuate) then
  391.                 if (self.fluctuate == "dim" or self.fluctuate == "notbright") then
  392.                         self.fluctuatingBrightness = self.fluctuatingBrightness - elapsed
  393.                         if (self.fluctuatingBrightness < 0.5) then
  394.                                 if (self.fluctuate == "dim") then
  395.                                         self.fluctuatingBrightness = 0.5
  396.                                         self.fluctuate = "notdim"
  397.                                 else
  398.                                         self.fluctuatingBrightness = nil
  399.                                         self.fluctuate = nil
  400.                                 end
  401.                         end
  402.                 elseif (self.fluctuate == "notdim" or self.fluctuate == "bright") then
  403.                         self.fluctuatingBrightness = self.fluctuatingBrightness + elapsed
  404.                         if (self.fluctuatingBrightness >= 1) then
  405.                                 if (self.fluctuate == "notdim") then
  406.                                         self.fluctuatingBrightness = nil
  407.                                         self.fluctuate = nil
  408.                                 else
  409.                                         self.fluctuatingBrightness = 1
  410.                                         self.fluctuate = "notbright"
  411.                                 end
  412.                         end
  413.                 end
  414.         elseif (random(10) == 1) then
  415.                 self.fluctuate = random(3) == 2 and "dim" or "bright"
  416.                 self.fluctuatingBrightness = 1
  417.         end
  418.  
  419.         return self.fluctuatingBrightness or 1
  420. end
  421.  
  422. -- hotBarOnUpdate
  423. local function hotBarOnUpdate(self, elapsed)
  424.         local Min, Max = self:GetMinMaxValues()
  425.         local val = self:GetValue()
  426.         if (self.movementMod) then
  427.                 val = val - elapsed
  428.                 if (val <= 0) then
  429.                         self:Hide()
  430.                         return
  431.                 end
  432.        
  433.                 self:SetValue(val)
  434.         end
  435.  
  436.         local sparkPosition = self:GetWidth() * (val / Max)
  437.         self.spark:SetPoint("CENTER", self, "LEFT", sparkPosition, 0)
  438.  
  439.         self.angle = self.angle + elapsed
  440.         if (self.angle > 360) then
  441.                 self.angle = self.angle - 360
  442.         end
  443.  
  444.         local ULx, ULy, LLx, LLy, URx, URy, LRx, LRy = rotate(self.angle)
  445.         self.spark:SetTexCoord(ULx, ULy, LLx, LLy, URx, URy, LRx, LRy)
  446.         self.shine:SetTexCoord(ULx, ULy, LLx, LLy, URx, URy, LRx, LRy)
  447.  
  448.         local a
  449.         if (val < 5) then
  450.                 if (self.alphaPulse == "in") then
  451.                         a = self.alpha + elapsed * 2
  452.                         if (a >= 1) then
  453.                                 a = 1
  454.                                 self.alphaPulse = "out"
  455.                         end
  456.                 else
  457.                         a = self.alpha - elapsed * 2
  458.                         if (a < 0.3) then
  459.                                 a = 0.3
  460.                                 self.alphaPulse = "in"
  461.                         end
  462.                 end
  463.         else
  464.                 a = 1
  465.                 self.alphaPulse = "out"
  466.         end
  467.  
  468.         self.spark:SetVertexColor(1, 1, 1, a * fluctuateOnUpdate(self.spark, elapsed))
  469.         self.shine:SetVertexColor(1, 1, 1, a * fluctuateOnUpdate(self.shine, elapsed))
  470.         self.alpha = a
  471. end
  472.  
  473. -- CreateShieldBar
  474. function xpHigh:CreateShieldBar(frame)
  475.         local parent = frame.healthBar
  476.         if (not parent) then
  477.                 parent = frame.statsFrame and frame.statsFrame.healthBar
  478.         end
  479.         if (not parent) then
  480.                 return
  481.         end
  482.  
  483.         local f = CreateFrame("StatusBar", nil, parent)
  484.         frame.highlight.shieldBar = f
  485.         f:SetPoint("BOTTOMLEFT")
  486.         f:SetPoint("TOPRIGHT", parent, "BOTTOMRIGHT", 0, 4)
  487.         f:SetMinMaxValues(0, 0.1)
  488.         f:Hide()
  489.  
  490.         f.spark = self:CreateShine(f)
  491.         f.shine = self:CreateShine(f)
  492.         f.shine:SetPoint("CENTER", f, "LEFT")
  493.  
  494.         f:SetStatusBarTexture("Interface\\TargetingFrame\\UI-StatusBar")
  495.         f:GetStatusBarTexture():SetHorizTile(false)
  496.         f:GetStatusBarTexture():SetVertTile(false)
  497.         f:SetStatusBarColor(1, 0.4, 1)
  498.  
  499.         f:SetScript("OnUpdate", hotBarOnUpdate)
  500.         f:SetScript("OnShow",
  501.                 function(self)
  502.                         self.angle = 0
  503.                         self.alpha = 1
  504.                         self.alphaPulse = "out"
  505.                 end)
  506. end
  507.  
  508. -- TotalShield
  509. function xpHigh:TotalShield(guid)
  510.         local list = self.shields[guid]
  511.         if (list) then
  512.                 local total, maxAmount = 0, 0
  513.                 for i,s in pairs(list) do
  514.                         total = total + s.amount
  515.                         maxAmount = maxAmount + s.maxAmount
  516.                 end
  517.                 return total, maxAmount
  518.         end
  519. end
  520.  
  521. -- ShowHotBar
  522. function xpHigh:ShowShieldBar(frame, show)
  523.         local h = frame.highlight
  524.         if (show and conf.highlight.SHIELD and conf.highlight.sparkles) then
  525.                 local unit = SecureButton_GetUnit(frame)
  526.                 local guid = unit and UnitGUID(unit)
  527.                 if (guid) then
  528.                         local shield = self.shields[guid]
  529.                         if (shield) then
  530.                                 if (not h.shieldBar) then
  531.                                         self:CreateShieldBar(frame)
  532.                                 end
  533.  
  534.                                 h.shieldBar.unit = unit
  535.                                 local cur, max = self:TotalShield(guid)
  536.                                 h.shieldBar:SetMinMaxValues(0, max)
  537.                                 h.shieldBar:SetValue(cur)
  538.                                 h.shieldBar:Show()
  539.                                 return
  540.                         end
  541.                 end
  542.         end
  543.  
  544.         if (h.shieldBar) then
  545.                 h.shieldBar:Hide()
  546.                 h.shieldBar:SetMinMaxValues(0, 0.1)
  547.         end
  548. end
  549.  
  550. -- CreateShine
  551. function xpHigh:CreateShine(parent)
  552.         local shine = parent:CreateTexture(nil, "OVERLAY")
  553.         shine:SetTexture("Spells\\SparkleBlue")
  554.         shine:SetBlendMode("ADD")
  555.         shine:SetWidth(12)
  556.         shine:SetHeight(12)
  557.         return shine
  558. end
  559.  
  560. -- CreateHotBar
  561. function xpHigh:CreateHotBar(frame)
  562.         local parent = frame.healthBar
  563.         if (not parent) then
  564.                 parent = frame.statsFrame and frame.statsFrame.healthBar
  565.         end
  566.         if (not parent) then
  567.                 return
  568.         end
  569.  
  570.         local f = CreateFrame("StatusBar", nil, parent)
  571.         frame.highlight.hotBar = f
  572.         f:SetPoint("TOPLEFT")
  573.         f:SetPoint("BOTTOMRIGHT", parent, "TOPRIGHT", 0, -4)
  574.         f:SetMinMaxValues(0, 0.1)
  575.         f:Hide()
  576.         f.movementMod = 1
  577.  
  578.         f.spark = self:CreateShine(f)
  579.         f.shine = self:CreateShine(f)
  580.         f.shine:SetPoint("CENTER", f, "LEFT")
  581.  
  582.         f:SetStatusBarTexture("Interface\\TargetingFrame\\UI-StatusBar")
  583.         f:GetStatusBarTexture():SetHorizTile(false)
  584.         f:GetStatusBarTexture():SetVertTile(false)
  585.         f:SetStatusBarColor(1, 1, 0)
  586.  
  587.         f:SetScript("OnUpdate", hotBarOnUpdate)
  588.         f:SetScript("OnShow",
  589.                 function(self)
  590.                         self.angle = 0
  591.                         self.alpha = 1
  592.                         self.alphaPulse = "out"
  593.                 end)
  594. end
  595.  
  596. -- GetMyHotTime
  597. function xpHigh:GetMyHotTime(unit)
  598.         local maxDur, maxTimeLeft = 0, 0
  599.         for i = 1,40 do
  600.                 local name, rank, tex, count, buffType, dur, endTime, isMine = UnitBuff(unit, i, "PLAYER")
  601.                 if (not name) then
  602.                         break
  603.                 end
  604.  
  605.                 if (hotSpells[name]) then
  606.                         local timeLeft = endTime - GetTime()
  607.                         if (timeLeft > maxTimeLeft) then
  608.                                 maxDur, maxTimeLeft = dur, timeLeft
  609.                         end
  610.                 end
  611.         end
  612.         return maxDur, maxTimeLeft
  613. end
  614.  
  615. -- ShowHotBar
  616. function xpHigh:ShowHotBar(frame, show)
  617.         local h = frame.highlight
  618.         if (show and conf.highlight.HOT and conf.highlight.sparkles) then
  619.                 local unit = SecureButton_GetUnit(frame)
  620.                 if (unit) then
  621.                         local dur, timeLeft = self:GetMyHotTime(unit)
  622.                         if (dur and dur > 0) then
  623.                                 if (not h.hotBar) then
  624.                                         self:CreateHotBar(frame)
  625.                                 end
  626.  
  627.                                 local a, b = h.hotBar:GetMinMaxValues()
  628.                                 if (b > dur) then
  629.                                         -- Changing HOTs shouldn't make the bar jump with varying buff durations, just use the max so far.
  630.                                         dur = b
  631.                                 end
  632.  
  633.                                 h.hotBar.unit = unit
  634.                                 h.hotBar:SetMinMaxValues(0, dur)
  635.                                 h.hotBar:SetValue(timeLeft)
  636.                                 h.hotBar:Show()
  637.                                 return
  638.                         end
  639.                 end
  640.         end
  641.  
  642.         if (h.hotBar) then
  643.                 h.hotBar:Hide()
  644.                 h.hotBar:SetMinMaxValues(0, 0.1)
  645.         end
  646. end
  647.  
  648. -- xpHigh:CreateHotCount(frame)
  649. function xpHigh:CreateHotCount(frame)
  650.  
  651.         local f = frame.highlight:CreateFontString(nil, "OVERLAY", "NumberFontNormalLarge")
  652.         frame.highlight.hot = f
  653.  
  654.         f:SetTextColor(0, 1, 0)
  655.         f:Hide()
  656.  
  657.         local sf = _G[frame:GetName().."statsFrame"]
  658.         if (sf) then
  659.                 if (strfind(frame:GetName(), "XPerl_Raid_Grp")) then
  660.                         f:SetTextHeight(15)
  661.                         f:SetPoint("TOPLEFT", sf, "TOPLEFT", 3, -3)
  662.                 else
  663.                         f:SetPoint("TOPLEFT", sf, "TOPLEFT", 5, -8)
  664.                 end
  665.         else
  666.                 if (strfind(frame:GetName(), "XPerl_Raid_GrpPets")) then
  667.                         f:SetTextHeight(15)
  668.                         f:SetPoint("TOPLEFT", 3, -3)
  669.                 else
  670.                         f:SetPoint("CENTER", 0, 0)
  671.                 end
  672.         end
  673. end
  674.  
  675. -- xpHigh:HasMyHOT(unit)
  676. function xpHigh:HasMyHOT(unit)
  677.         for i = 1,100 do
  678.                 local name, rank, tex, count, buffType, dur, endTime, caster = UnitBuff(unit, i, "PLAYER")
  679.                 if (not name) then
  680.                         break
  681.                 end
  682.                 if (hotSpells[name]) then
  683.                         return true
  684.                 end
  685.         end
  686. end
  687.  
  688. -- ShowHotCount
  689. function xpHigh:ShowHotCount(frame, hotCount, unitid)
  690.         local h = frame.highlight
  691.         if (conf.highlight.HOTCOUNT) then
  692.                 if (hotCount and hotCount > 0) then
  693.                         if (not h.hot) then
  694.                                 self:CreateHotCount(frame)
  695.                         end
  696.  
  697.                         h.hot:SetText(hotCount)
  698.                         h.hot:Show()
  699.  
  700.                         local unit = SecureButton_GetUnit(frame)
  701.                         if (unit and self:HasMyHOT(unit)) then
  702.                                 h.hot:SetTextColor(0, 1, 0)
  703.                         else
  704.                                 h.hot:SetTextColor(0.8, 0, 0)
  705.                         end
  706.                         return
  707.                 end
  708.         end
  709.  
  710.         if (h.hot) then
  711.                 h.hot:Hide()
  712.         end
  713. end
  714.  
  715. -- GetMyPomEndTime
  716. function xpHigh:GetMyPomEndTime(unit)
  717.         for i = 1,40 do
  718.                 local name, rank, tex, count, buffType, dur, endTime, isMine = UnitBuff(unit, i, "PLAYER")
  719.                 if (not name) then
  720.                         break
  721.                 end
  722.                 if (pomSpells[name]) then
  723.                         return endTime
  724.                 end
  725.         end
  726. end
  727.  
  728. -- ShowMending
  729. function xpHigh:ShowMending(frame, show)
  730.         local h = frame.highlight
  731.  
  732.         if (show and conf.highlight.POM and conf.highlight.sparkles) then
  733.                 if (not h.mending or not h.mending:GetParent():IsShown()) then
  734.                         self:CreateMendingIcon(frame)
  735.                 end
  736.  
  737.                 if (h.mending) then
  738.                         local unit = SecureButton_GetUnit(frame)
  739.                         if (unit) then
  740.                                 h.mending.endTime = self:GetMyPomEndTime(unit) or 30
  741.                                 h.mending:Show()
  742.                         end
  743.                 end
  744.                 return
  745.         end
  746.  
  747.         if (h.mending) then
  748.                 h.mending:Hide()
  749.                 tinsert(self.mendingIcons, h.mending)
  750.                 h.mending = nil
  751.         end
  752. end
  753.  
  754. -- mendingOnUpdate
  755. local function mendingOnUpdate(self, elapsed)
  756.         if (self.shineMode == "in") then
  757.                 self.shineAlpha = self.shineAlpha + elapsed
  758.                 if (self.shineAlpha >= 1) then
  759.                         self.shineAlpha = 1
  760.                         self.shineMode = "out"
  761.                 end
  762.         else
  763.                 self.shineAlpha = self.shineAlpha - elapsed
  764.                 if (self.shineAlpha <= 0.3) then
  765.                         self.shineAlpha = 0.3
  766.                         self.shineMode = "in"
  767.                 end
  768.         end
  769.  
  770.         self.shineAngle = self.shineAngle + elapsed * 3
  771.         if (self.shineAngle > 360) then
  772.                 self.shineAngle = self.shineAngle - 360
  773.         end
  774.  
  775.         self.shine:SetTexCoord(rotate(self.shineAngle))
  776.  
  777.         self.shine:SetVertexColor(1, 1, 1, self.shineAlpha)
  778.  
  779.         if (GetTime() > self.endTime - 5) then
  780.                 self:SetAlpha(self.shineAlpha)
  781.         else
  782.                 self:SetAlpha(1)
  783.         end
  784. end
  785.  
  786. -- CreateMendingIcon
  787. function xpHigh:CreateMendingIcon(frame)
  788.         local h = frame.highlight
  789.         local p = frame.statsFrame              -- or frame
  790.         local anchor = "CENTER"
  791.         local anchorRel = "TOP"
  792.         local anchorRelP = p
  793.         local sizeMod = -8
  794.         local xOffset, yOffset = 0, 0
  795.         if (p) then
  796.                 p = p.healthBar or p
  797.                 if (strfind(p:GetName(), "^XPerl_Raid")) then
  798.                         sizeMod = 0
  799.                         yOffset = -2
  800.                 else
  801.                         sizeMod = 10
  802.                         yOffset = -4
  803.                 end
  804.         end
  805.  
  806.         if (h and p) then
  807.                 local icon = h.mending
  808.                 if (not icon) then
  809.                         icon = tremove(self.mendingIcons, 1)
  810.                         h.mending = icon
  811.                 end
  812.                 if (icon) then
  813.                         -- Re-parent
  814.                         icon:SetParent(p)
  815.                         icon:ClearAllPoints()
  816.                 else
  817.                         icon = CreateFrame("Frame", nil, p)
  818.                         h.mending = icon
  819.                         icon.tex = icon:CreateTexture(nil, "BACKGROUND")
  820.                         icon.tex:SetAllPoints()
  821.                         icon.tex:SetTexture("Interface\\Icons\\Spell_Holy_PrayerOfMendingtga")
  822.                         icon.tex:SetTexCoord(0.1, 0.9, 0.1, 0.9)
  823.  
  824.                         icon.shine = self:CreateShine(icon)
  825.                         icon.shine:SetPoint("TOPLEFT", -5, 5)
  826.                         icon.shine:SetPoint("BOTTOMRIGHT", 5, -5)
  827.                 end
  828.  
  829.                 icon:SetWidth(p:GetHeight() + sizeMod)
  830.                 icon:SetHeight(p:GetHeight() + sizeMod)
  831.                 icon:SetPoint(anchor, anchorRelP, anchorRel, xOffset, yOffset)
  832.                 icon:Hide()
  833.  
  834.                 local x1, y1 = icon:GetCenter()
  835.                 local x2, y2 = frame:GetCenter()
  836.                 frame.lastPomPosX = x1 - x2
  837.                 frame.lastPomPosY = y1 - y2
  838.  
  839.                 icon.shine:Show()
  840.                 icon.shine:SetVertexColor(1, 1, 1, 0)
  841.                 icon:SetScript("OnUpdate", mendingOnUpdate)
  842.  
  843.                 icon:SetScript("OnShow",
  844.                         function(self)
  845.                                 self.shineAngle = 0
  846.                                 self.shineAlpha = 0
  847.                                 self.shineMode = "in"
  848.                                 self:SetAlpha(1)
  849.                         end)
  850.         end
  851. end
  852.  
  853. -- TriggerMendingAnimation
  854. function xpHigh:TriggerMendingAnimation(sourceGUID, targetGUID)
  855.         local sourceFrame, targetFrame
  856.         if (GetNumRaidMembers() > 0 and XPerl_Raid_GetUnitFrameByUnit) then
  857.                 sourceFrame, targetFrame = XPerl_Raid_GetUnitFrameByGUID(sourceGUID), XPerl_Raid_GetUnitFrameByGUID(targetGUID)
  858.                 if (not sourceFrame and XPerl_Raid_Pet_GetUnitFrameByGUID) then
  859.                         sourceFrame = XPerl_Raid_Pet_GetUnitFrameByGUID(sourceGUID)
  860.                 end
  861.                 if (not targetFrame and XPerl_Raid_Pet_GetUnitFrameByGUID) then
  862.                         targetFrame = XPerl_Raid_Pet_GetUnitFrameByGUID(targetGUID)
  863.                 end
  864.  
  865.         elseif (GetNumPartyMembers() > 0 and XPerl_Party_GetUnitFrameByUnit) then
  866.                 sourceFrame = sourceID == "player" and XPerl_Player or XPerl_Party_GetUnitFrameByGUID(sourceGUID)
  867.                 targetFrame = targetID == "player" and XPerl_Player or XPerl_Party_GetUnitFrameByGUID(targetGUID)
  868.                 if (not sourceFrame and XPerl_Party_Pet_GetUnitFrameByGUID) then
  869.                         sourceFrame = XPerl_Party_Pet_GetUnitFrameByGUID(sourceGUID)
  870.                 end
  871.                 if (not targetFrame and XPerl_Party_Pet_GetUnitFrameByGUID) then
  872.                         targetFrame = XPerl_Party_Pet_GetUnitFrameByGUID(targetGUID)
  873.                 end
  874.         end
  875.  
  876.         if (sourceFrame and targetFrame) then
  877.                 self:StartMendingAnimation(sourceFrame, targetFrame)
  878.         end
  879. end
  880.  
  881. -- StartMendingAnimation
  882. function xpHigh:StartMendingAnimation(sourceFrame, targetFrame)
  883.     local oldMA = self.mendingAnimation
  884.  
  885.     local ma = new()
  886.         self.mendingAnimation = ma
  887.  
  888.         local sx, sy = sourceFrame:GetCenter()
  889.         local tx, ty = targetFrame:GetCenter()
  890.         local ss, ts = sourceFrame:GetEffectiveScale(), targetFrame:GetEffectiveScale()
  891.  
  892.         if (oldMA) then
  893.                 ma.sourceX = oldMA.currentX
  894.                 ma.sourceY = oldMA.currentY
  895.         else
  896.                 ma.sourceX = (sx + (sourceFrame.lastPomPosX or 0)) * ss
  897.                 ma.sourceY = (sy + (sourceFrame.lastPomPosY or 0)) * ss
  898.         end
  899.  
  900.         ma.targetX = (tx + (targetFrame.lastPomPosX or 0)) * ts
  901.         ma.targetY = (ty + (targetFrame.lastPomPosY or 0)) * ts
  902.         ma.currentX = ma.sourceX
  903.         ma.currentY = ma.sourceY
  904.  
  905.         -- Star will take 0.667 seconds to arrive
  906.         ma.speedX = (ma.targetX - ma.sourceX) * 1.5
  907.         ma.speedY = (ma.targetY - ma.sourceY) * 1.5
  908.  
  909.         ma.shown = 0
  910.         ma.showGap = 1
  911.         local icons = self.mendingAnimationIcons
  912.         if (not icons) then
  913.                 icons = {}
  914.                 self.mendingAnimationIcons = icons
  915.                 for i = 1,3 do
  916.                         local icon = CreateFrame("Frame", nil, UIParent)
  917.                         icons[i] = icon
  918.                         icon:SetFrameStrata("DIALOG")
  919.                         icon:SetHeight((4 - i) * 8)
  920.                         icon:SetWidth((4 - i) * 8)
  921.  
  922.                         icon.tex = icon:CreateTexture(nil, "OVERLAY")
  923.                         icon.tex:SetTexture("Spells\\SparkleBlue")
  924.                         icon.tex:SetAllPoints()
  925.                         icon.tex:SetVertexColor(1 / i, 1 / i, 0.7 / i)
  926.                         icon.tex:SetBlendMode("ADD")
  927.                         icon.angle = 0
  928.                 end
  929.         else
  930.                 for i = 1,3 do
  931.                         icons[i]:Hide()
  932.                 end
  933.         end
  934.  
  935.         del(oldMA)
  936. end
  937.  
  938. -- MendingAnimationOnUpdate
  939. function xpHigh:MendingAnimationOnUpdate(elapsed)
  940.         local ma = self.mendingAnimation
  941.         local icons = self.mendingAnimationIcons
  942.  
  943.         local x, y = ma.currentX, ma.currentY
  944.  
  945.         ma.currentX = ma.currentX + ma.speedX * elapsed
  946.         ma.currentY = ma.currentY + ma.speedY * elapsed
  947.  
  948.         if ((ma.speedX < 0 and ma.currentX < ma.targetX) or (ma.speedX > 0 and ma.currentX > ma.targetX)) then
  949.                 ma.currentX = ma.targetX
  950.                 ma.speedX = 0
  951.                 if (ma.speedY == 0) then
  952.                         ma.endCounter = 0
  953.                 end
  954.         end
  955.         if ((ma.speedY < 0 and ma.currentY < ma.targetY) or (ma.speedY > 0 and ma.currentY > ma.targetY)) then
  956.                 ma.currentY = ma.targetY
  957.                 ma.speedY = 0
  958.                 if (ma.speedX == 0) then
  959.                         ma.endCounter = 0
  960.                 end
  961.         end
  962.  
  963.         if (ma.shown < 3) then
  964.                 ma.showGap = ma.showGap + elapsed
  965.                 if (ma.showGap > 0.2) then
  966.                         ma.showGap = 0
  967.  
  968.                         ma.shown = ma.shown + 1
  969.                         icons[ma.shown]:Show()
  970.                 end
  971.         end
  972.  
  973.         for i = 1,ma.shown do
  974.                 local icon = icons[i]
  975.                 icon:ClearAllPoints()
  976.                 if (i == 1) then
  977.                         icon:SetPoint("CENTER", UIParent, "BOTTOMLEFT", ma.currentX / UIParent:GetScale(), ma.currentY / UIParent:GetScale())
  978.                 else
  979.                         icon:SetPoint("CENTER", UIParent, "BOTTOMLEFT", (ma.currentX - (ma.speedX * elapsed * i)) / UIParent:GetScale(), (ma.currentY - (ma.speedY * elapsed * i)) / UIParent:GetScale())
  980.                 end
  981.  
  982.                 icon.angle = icon.angle + elapsed * 3
  983.                 if (icon.angle > 360) then
  984.                         icon.angle = icon.angle - 360
  985.                 end
  986.                 icon.tex:SetTexCoord(rotate(icon.angle))
  987.         end
  988.  
  989.         if (ma.endCounter) then
  990.                 ma.endCounter = ma.endCounter + 1
  991.                 if (ma.endCounter >= 5) then
  992.                         self:StopMendingAnimation()
  993.                 end
  994.         elseif (self.expectingPOM) then
  995.                 if (GetTime() > self.expectingPOM + 2) then
  996.                         self.expectingPOM = nil
  997.                         self:StopMendingAnimation()
  998.                 end
  999.         end
  1000. end
  1001.  
  1002. -- StopMendingAnimation
  1003. function xpHigh:StopMendingAnimation()
  1004.         self.mendingAnimation = del(self.mendingAnimation)
  1005.         local icons = self.mendingAnimationIcons
  1006.         if (icons) then
  1007.                 for i = 1,3 do
  1008.                         local icon = icons[i]
  1009.                         if (icon) then
  1010.                                 icon:Hide()
  1011.                         end
  1012.                 end
  1013.         end
  1014. end
  1015.  
  1016. -- SparkleArea
  1017. function xpHigh:SparkleArea(a, duration, mode, ttl)
  1018.         local area
  1019.         if (type(a) == "table" and type(a[0]) == "userdata") then
  1020.                 if (a:GetLeft()) then
  1021.                         local s = a:GetEffectiveScale()
  1022.                         area = new()
  1023.                         area.left       = a:GetLeft()   * s
  1024.                         area.right      = a:GetRight()  * s
  1025.                         area.top        = a:GetTop()    * s
  1026.                         area.bottom     = a:GetBottom() * s
  1027.                 end
  1028.         elseif (type(a) == "table") then
  1029.                 if (a.top and a.left and a.bottom and a.right) then
  1030.                         area = new()
  1031.                         area.left, area.right, area.top, area.bottom = a.left, a.right, a.top, a.bottom
  1032.                 end
  1033.         end
  1034.  
  1035.         if (area) then
  1036.                 area.key = format("%d-%d-%d-%d", area.left, area.right, area.top, area.bottom)
  1037.                 area.endTime = GetTime() + duration
  1038.                 area.mode = mode or "evaporate"
  1039.                 area.ttl = ttl or 0.5
  1040.                 area.colour = new()
  1041.                 area.colour.r = 1
  1042.                 area.colour.g = 1
  1043.                 area.colour.b = 0.5
  1044.                 area.fadeInMultiplier = 6
  1045.                 area.fadeOutMultiplier = 1
  1046.                 area.rotateMultiplier = 1
  1047.  
  1048.                 area.sparks = new()
  1049.                 area.sparkTime = 0
  1050.  
  1051.                 if (not self.sparkleAreas) then
  1052.                         self.sparkleAreas = new()
  1053.                 end
  1054.  
  1055.                 if (not self.sparkleAreas[area.key]) then
  1056.                         self.sparkleAreas[area.key] = area
  1057.                 else
  1058.                         del(area)                       -- Duplicate area, discard
  1059.                 end
  1060.         end
  1061. end
  1062.  
  1063. -- sparkOnShow
  1064. local function sparkOnShow(self)
  1065.         self.angle = 0
  1066.         self.alpha = 0
  1067.         self.begin = GetTime()
  1068.         self.state = "new"
  1069. end
  1070.  
  1071. -- sparkOnUpdate
  1072. local function sparkOnUpdate(self, elapsed)
  1073.         self.angle = self.angle + elapsed * self.area.rotateMultiplier
  1074.         if (self.angle > 360) then
  1075.                 self.angle = self.angle - 360
  1076.         end
  1077.         self.tex:SetTexCoord(rotate(self.angle))
  1078.  
  1079.         if (self.mode == "evaporate") then
  1080.                 local x, y = self:GetCenter()
  1081.                 x = x * self:GetEffectiveScale()
  1082.                 y = y * self:GetEffectiveScale()
  1083.    
  1084.                 y = y + elapsed * self.speed
  1085.  
  1086.                 self:ClearAllPoints()
  1087.                 self:SetPoint("CENTER", UIParent, "BOTTOMLEFT", x, y)
  1088.         end
  1089.  
  1090.         if (self.state == "new") then
  1091.                 self.alpha = self.alpha + elapsed * self.area.fadeInMultiplier
  1092.                 if (self.alpha >= 1) then
  1093.                         self.alpha = 1
  1094.                         if (GetTime() > self.begin + self.ttl) then
  1095.                                 self.state = "fade"
  1096.                         else
  1097.                                 self.state = "cycle"
  1098.                         end
  1099.                 end
  1100.  
  1101.         elseif (self.state == "cycle") then
  1102.                 if (GetTime() > self.begin + self.ttl) then
  1103.                         self.state = "fade"
  1104.                 end
  1105.  
  1106.         elseif (self.state == "fade") then
  1107.                 self.alpha = self.alpha - elapsed * self.area.fadeOutMultiplier
  1108.                 if (self.alpha <= 0) then
  1109.                         self:Hide()
  1110.                         xpHigh:SparkleAreaRemoveSpark(self)
  1111.                         return
  1112.                 end
  1113.         end
  1114.  
  1115.         local c = self.area.colour
  1116.         local a = self.alpha * fluctuateOnUpdate(self, elapsed)
  1117.         self.tex:SetVertexColor(c.r, c.g, c.b, a)
  1118. end
  1119.  
  1120. -- SparkleAreaRemoveSpark
  1121. function xpHigh:SparkleAreaRemoveSpark(spark)
  1122.         local area = spark.area
  1123.         spark.area = nil
  1124.         self.activeSparks[spark.id] = nil
  1125.         tinsert(self.inactiveSparks, spark)
  1126.         area.sparks[spark.id] = nil
  1127.  
  1128.         if (not next(area.sparks)) then
  1129.                 area.sparks = del(area.sparks)
  1130.         end
  1131. end
  1132.  
  1133. -- SparkleAreaAddSpark
  1134. function xpHigh:SparkleAreaAddSpark(area, bias)
  1135.         -- Retreive spark from pool
  1136.         if (not self.inactiveSparks) then
  1137.                 self.inactiveSparks = new()
  1138.         end
  1139.         local spark = tremove(self.inactiveSparks, 1)
  1140.  
  1141.         if (not spark) then
  1142.                 -- Create new spark
  1143.                 spark = CreateFrame("Frame", nil, XPerl_Highlight)
  1144.                 spark.tex = self:CreateShine(spark)
  1145.                 spark.tex:SetAllPoints()
  1146.  
  1147.                 spark:SetScript("OnShow", sparkOnShow)
  1148.                 spark:SetScript("OnUpdate", sparkOnUpdate)
  1149.                 spark:Hide()
  1150.  
  1151.                 -- Make unique ID
  1152.                 self.sparkIncrement = (self.sparkIncrement or 0) + 1
  1153.                 spark.id = self.sparkIncrement
  1154.         end
  1155.  
  1156.         -- Store into active sparks list (what gets OnUpdate'd)
  1157.         if (not self.activeSparks) then
  1158.                 self.activeSparks = new()
  1159.         end
  1160.         self.activeSparks[spark.id] = spark
  1161.  
  1162.         spark.mode = area.mode
  1163.         spark.ttl = area.ttl
  1164.         spark.area = area
  1165.  
  1166.         -- Random size
  1167.         local rand = random(6)
  1168.         local size = 8 + rand
  1169.         spark:SetWidth(size)
  1170.         spark:SetHeight(size)
  1171.  
  1172.         local h = area.top - area.bottom
  1173.         --spark.speed = 1 + random(10) / 10
  1174.         spark.speed = size
  1175.  
  1176.         -- Position in area
  1177.         spark:ClearAllPoints()
  1178.         local x, y
  1179.         local w = area.right - area.left
  1180.         if (bias == "left") then
  1181.                 x = area.left + random(w) / 3
  1182.         elseif (bias == "right") then
  1183.                 x = area.right - random(w) / 3
  1184.         elseif (bias == "middle") then
  1185.                 x = area.left + (w / 3) + (random(w) / 3)
  1186.         else
  1187.                 x = area.left + random(w)
  1188.         end
  1189.         y = area.bottom + random(area.top - area.bottom) / (area.mode == "evaporate" and 2 or 1)
  1190.         spark:SetPoint("CENTER", UIParent, "BOTTOMLEFT", x, y)
  1191.  
  1192.         -- Keep ID in area's spark list
  1193.         area.sparks[spark.id] = true
  1194.  
  1195.         spark:Show()
  1196.         return spark
  1197. end
  1198.  
  1199. -- SparkleAreaOnUpdate
  1200. function xpHigh:SparkleAreaOnUpdate(area, elapsed)
  1201.         if (GetTime() < area.endTime) then
  1202.                 area.sparkTime = area.sparkTime + elapsed
  1203.                 if (area.sparkTime > 0.1) then
  1204.                         area.sparkTime = 0
  1205.                         self:SparkleAreaAddSpark(area, "left")
  1206.                         self:SparkleAreaAddSpark(area, "middle")
  1207.                         self:SparkleAreaAddSpark(area, "right")
  1208.                 end
  1209.         else
  1210.                 area.ending = true
  1211.                 if (not area.sparks) then
  1212.                         self.sparkleAreas[area.key] = nil
  1213.                         del(area, true)
  1214.                 end
  1215.         end
  1216. end
  1217.  
  1218. -- SparkleAreasOnUpdate
  1219. function xpHigh:SparkleAreasOnUpdate(elapsed)
  1220.         for key,area in pairs(self.sparkleAreas) do
  1221.                 self:SparkleAreaOnUpdate(area, elapsed)
  1222.         end
  1223. end
  1224.  
  1225. -- ShowHotSparks
  1226. function xpHigh:ShowHotSparks(frame, show)
  1227.         if (show) then
  1228.                 if (frame:IsVisible()) then
  1229.                         local h = frame.healthBar or (frame.statsFrame and frame.statsFrame.healthBar)
  1230.                         if (not h) then
  1231.                                 return
  1232.                         end
  1233.        
  1234.                         self:SparkleArea(h, 0.4, "evaporate", 0.1)
  1235.                 end
  1236.         end
  1237. end
  1238.  
  1239. -- xpHigh:RemoveHighlight
  1240. function xpHigh:RemoveHighlight(frame)
  1241.         XPerl_FrameFlashStop(frame.highlight.tex)
  1242.  
  1243.         frame.highlight.tex:SetVertexColor(0.86, 0.82, 0.41)    -- Default selection colour
  1244.  
  1245.         if (frame.highlight.sel and conf.highlightSelection) then
  1246.                 frame.highlight.tex:Show()
  1247.                 frame.highlight.tex:SetAlpha(1)
  1248.         else
  1249.                 frame.highlight.tex:Hide()
  1250.         end
  1251. end
  1252.  
  1253. -- xpHigh:ClearAll
  1254. function xpHigh:ClearAll(clearType)
  1255.         if (clearType == "SHIELD") then
  1256.                 for guid,s in pairs(self.shields) do
  1257.                         self.shields[guid] = del(self.shields[guid])
  1258.                         self:Send(guid)
  1259.                 end
  1260.         end
  1261.         for k,v in pairs(self.list) do
  1262.                 if (v[clearType]) then
  1263.                         v[clearType] = nil
  1264.                         self:Send(k)
  1265.                 end
  1266.         end
  1267. end
  1268.  
  1269. -- xpHigh:Send
  1270. function xpHigh:Send(guid)
  1271.         for k,v in pairs(self.callbacks) do
  1272.                 v[1](v[2], guid)
  1273.         end
  1274. end
  1275.  
  1276. -- XPerl_RegisterFrameHighlighter
  1277. function xpHigh:Register(callback, slf)
  1278.         tinsert(self.callbacks, {callback, slf})
  1279. end
  1280.  
  1281. -- xpHigh:OnEvent
  1282. function xpHigh:OnEvent(event, ...)
  1283.         self[event](self, ...)
  1284. end
  1285.  
  1286. xpHigh.clEvents = {}
  1287. -- COMBAT_LOG_EVENT_UNFILTERED
  1288. -- Using this instead of UNIT_SPELLCAST_SUCCEEDED so we can use the dstGUID for a guarenteed correct target, rather than implied and not necessarily correct name
  1289. local dstMask = COMBATLOG_OBJECT_AFFILIATION_MINE + COMBATLOG_OBJECT_AFFILIATION_PARTY + COMBATLOG_OBJECT_AFFILIATION_RAID
  1290. function xpHigh:COMBAT_LOG_EVENT_UNFILTERED(timestamp, event, hideCaster, srcGUID, srcName, srcFlags, srcRaidFlags, dstGUID, dstName, dstFlags, dstRaidFlags, ...)
  1291.         local ev = self.clEvents[event]
  1292.         if (ev) then
  1293.                 ev(self, timestamp, event, srcGUID, srcName, srcFlags, dstGUID, dstName, dstFlags, ...)
  1294.         end
  1295. end
  1296.  
  1297. -- COMBATLOG:SPELL_CAST_SUCCESS
  1298. function xpHigh.clEvents:SPELL_CAST_SUCCESS(timestamp, event, srcGUID, srcName, srcFlags, dstGUID, dstName, dstFlags, ...)
  1299.         if (srcGUID == UnitGUID("player")) then
  1300.                 if (band(dstFlags, dstMask) ~= 0) then
  1301.                         local spellId, spellName, spellSchool = ...
  1302.                         if (hotSpells[spellName]) then
  1303.                                 if (conf.highlight.HOT) then
  1304.                                         self:Add(dstGUID, "HOT", hotSpells[spellName])
  1305.                                 end
  1306.                         elseif (shieldSpells[spellName]) then
  1307.                                 if (conf.highlight.SHIELD) then
  1308.                                         self:Add(dstGUID, "SHIELD", shieldSpells[spellName])
  1309.                                 end
  1310.                         elseif (pomSpells[spellName]) then
  1311.                                 if (conf.highlight.POM) then
  1312.                                         self.expectingPOM = nil
  1313.                                         self.pomSourceGUID = nil
  1314.                                         self:ClearAll("POM")
  1315.                                         self:StopMendingAnimation()
  1316.                                         self:Add(dstGUID, "POM", pomSpells[spellName])
  1317.                                         self.expectingPOM = nil
  1318.                                 end
  1319.                         end
  1320.                 end
  1321.         end
  1322. end
  1323.  
  1324. -- COMBATLOG:SPELL_HEAL
  1325. function xpHigh.clEvents:SPELL_HEAL(timestamp, event, srcGUID, srcName, srcFlags, dstGUID, dstName, dstFlags, ...)
  1326.         if (conf.highlight.HEAL and conf.highlight.extraSparkles and srcGUID == UnitGUID("player")) then
  1327.                 if (band(dstFlags, dstMask) ~= 0) then
  1328.                         -- Pretty sparkles for our healing target
  1329.                         self:Add(dstGUID, "HOTSPARKS", 0.1)
  1330.                 end
  1331.         end
  1332. end
  1333.  
  1334. -- COMBATLOG:SPELL_PERIODIC_HEAL
  1335. function xpHigh.clEvents:SPELL_PERIODIC_HEAL(timestamp, event, srcGUID, srcName, srcFlags, dstGUID, dstName, dstFlags, ...)
  1336.         if (conf.highlight.HOT and conf.highlight.extraSparkles and srcGUID == UnitGUID("player")) then
  1337.                 if (band(dstFlags, dstMask) ~= 0) then
  1338.                         local spellId, spellName, spellSchool, amount = ...
  1339.                         if (hotSpells[spellName]) then
  1340.                                 -- Our HOT actually healed someone, so we'll do something pretty
  1341.                                 if (self:HasEffect(dstGUID, "HOT")) then
  1342.                                         self:Add(dstGUID, "HOTSPARKS", 0.1)
  1343.                                 end
  1344.                         end
  1345.                 end
  1346.         end
  1347. end
  1348.  
  1349. -- COMBATLOG:SPELL_DAMAGE
  1350. function xpHigh.clEvents:SPELL_DAMAGE(timestamp, event, srcGUID, srcName, srcFlags, dstGUID, dstName, dstFlags, spellID, spellName, spellSchool, amount, ...)
  1351.         if (band(dstFlags, dstMask) ~= 0) then
  1352.                 local overkill, school, resisted, blocked, absorbed, critical, glancing, crushing = ...
  1353.                 if (absorbed) then
  1354.                         self:Damage(dstGUID, absorbed)
  1355.                 end
  1356.         end
  1357. end
  1358. xpHigh.clEvents.SPELL_PERIODIC_DAMAGE = xpHigh.clEvents.SPELL_DAMAGE
  1359.  
  1360. -- COMBATLOG:SPELL_MISSED
  1361. function xpHigh.clEvents:SPELL_MISSED(timestamp, event, srcGUID, srcName, srcFlags, dstGUID, dstName, dstFlags, ...)
  1362.         if (band(dstFlags, dstMask) ~= 0) then
  1363.                 local spellId, spellName, spellSchool, missType, missAmount = ...
  1364.                 if (missType == "ABSORB") then
  1365.                         self:Damage(dstGUID, missAmount)
  1366.                 end
  1367.         end
  1368. end
  1369. xpHigh.clEvents.SPELL_PERIODIC_MISSED = xpHigh.clEvents.SPELL_MISSED
  1370.  
  1371. -- COMBATLOG:SWING_DAMAGE
  1372. function xpHigh.clEvents:SWING_DAMAGE(timestamp, event, srcGUID, srcName, srcFlags, dstGUID, dstName, dstFlags, amount, ...)
  1373.         if (band(dstFlags, dstMask) ~= 0) then
  1374.                 local overkill, school, resisted, blocked, absorbed, critical, glancing, crushing = ...
  1375.                 if (absorbed) then
  1376.                         self:Damage(dstGUID, absorbed)
  1377.                 end
  1378.         end
  1379. end
  1380.  
  1381. -- COMBATLOG:SWING_MISSED
  1382. function xpHigh.clEvents:SWING_MISSED(timestamp, event, srcGUID, srcName, srcFlags, dstGUID, dstName, dstFlags, ...)
  1383.         if (band(dstFlags, dstMask) ~= 0) then
  1384.                 local missType, missAmount = ...
  1385.                 if (missType == "ABSORB") then
  1386.                         self:Damage(dstGUID, missAmount)
  1387.                 end
  1388.         end
  1389. end
  1390.  
  1391. -- ENVIRONMENTAL_DAMAGE
  1392. function xpHigh.clEvents:ENVIRONMENTAL_DAMAGE(timestamp, event, srcGUID, srcName, srcFlags, dstGUID, dstName, dstFlags, ...)
  1393.         if (band(dstFlags, dstMask) ~= 0) then
  1394.                 local environmentalType, amount, overkill, school, resisted, blocked, absorbed, critical, glancing, crushing = ...
  1395.                 if (missType == "ABSORB") then
  1396.                         self:Damage(dstGUID, absorbed)
  1397.                 end
  1398.         end
  1399. end
  1400.  
  1401. -- COMBATLOG:SPELL_AURA_APPLIED
  1402. function xpHigh.clEvents:SPELL_AURA_APPLIED(timestamp, event, srcGUID, srcName, srcFlags, dstGUID, dstName, dstFlags, spellId, spellName, spellSchool, auraType)
  1403.         if (conf.highlight.SHIELD) then
  1404.                 if ((srcGUID == dstGUID or srcGUID == playerGUID or dstGUID == playerGUID) and band(dstFlags, dstMask) ~= 0) then
  1405.                         local def = absorbSpells[spellName]
  1406.                         if (not def) then
  1407.                                 def = absorbSpells[spellId]
  1408.                         end
  1409.                         if (def) then
  1410.                                 local rankAmount = def:GetRankAmount(spellId)
  1411.                                 if (rankAmount) then
  1412.                                         if (event == "SPELL_AURA_APPLIED") then
  1413.                                                 if (not self.shields[dstGUID]) then
  1414.                                                         self.shields[dstGUID] = new()
  1415.                                                 end
  1416.                                                 tinsert(self.shields[dstGUID], 1, {
  1417.                                                         amount = rankAmount,
  1418.                                                         maxAmount = rankAmount,
  1419.                                                         name = spellName,
  1420.                                                         id = spellId,
  1421.                                                 })
  1422.                                                 self:Send(dstGUID)
  1423.                                         elseif (dstGUID == playerGUID) then
  1424.                                                 local s = self.shields and self.shields[dstGUID]
  1425.                                                 if (s) then
  1426.                                                         for i,data in pairs(s) do
  1427.                                                                 if (data.name == spellName) then
  1428.                                                                         data.amount = rankAmount
  1429.                                                                         data.maxAmount = rankAmount
  1430.                                                                         self:Send(dstGUID)
  1431.                                                                         break
  1432.                                                                 end
  1433.                                                         end
  1434.                                                 end
  1435.                                         end
  1436.                                 end
  1437.                         end
  1438.                 end
  1439.         end
  1440. end
  1441. xpHigh.clEvents.SPELL_AURA_REFRESH = xpHigh.clEvents.SPELL_AURA_APPLIED
  1442.  
  1443. -- COMBATLOG:SPELL_AURA_REMOVED
  1444. function xpHigh.clEvents:SPELL_AURA_REMOVED(timestamp, event, srcGUID, srcName, srcFlags, dstGUID, dstName, dstFlags, spellId, spellName, spellSchool, auraType, ...)
  1445.         if (conf.highlight.SHIELD) then
  1446.                 if (band(dstFlags, dstMask) ~= 0) then
  1447.                         local def = absorbSpells[spellName]
  1448.                         if (not def) then
  1449.                                 def = absorbSpells[spellId]
  1450.                         end
  1451.                         if (def) then
  1452.                                 local rankAmount = def:GetRankAmount(spellId)
  1453.                                 if (rankAmount) then
  1454.                                         local list = self.shields[dstGUID]
  1455.                                         if (list) then
  1456.                                                 for i,info in pairs(list) do
  1457.                                                         if (info.id == spellId) then
  1458.                                                                 del(tremove(list, i))
  1459.                                                                 if (not next(list)) then
  1460.                                                                         self.shields[dstGUID] = del(self.shields[dstGUID])
  1461.                                                                 end
  1462.                                                                 self:Send(dstGUID)
  1463.                                                                 break
  1464.                                                         end
  1465.                                                 end
  1466.                                         end
  1467.                                 end
  1468.                         end
  1469.                 end
  1470.         end
  1471. end
  1472.  
  1473. -- Damage
  1474. function xpHigh:Damage(guid, absorbed)
  1475.         local list = self.shields[guid]
  1476.         if (list) then
  1477.                 local s = list[1]
  1478.                 if (s) and absorbed then
  1479.                         local update
  1480.                         if (absorbed >= s.amount) then
  1481.                                 absorbed = absorbed - s.amount
  1482.                                 del(tremove(list, 1))
  1483.                                 if (not next(list)) then
  1484.                                         self.shields[guid] = del(self.shields[guid])
  1485.                                 end
  1486.                                 if (absorbed > 0) then
  1487.                                         self:Damage(guid, absorbed)                     -- Recursion
  1488.                                 else
  1489.                                         update = true
  1490.                                 end
  1491.                         else
  1492.                                 s.amount = s.amount - absorbed
  1493.                                 update = true
  1494.                         end
  1495.  
  1496.                         if (update) then
  1497.                                 self:Send(guid)
  1498.                         end
  1499.                 end
  1500.         end
  1501. end
  1502.  
  1503. -- UNIT_HEAL_PREDICTION
  1504. function xpHigh:UNIT_HEAL_PREDICTION(unit)
  1505.         local guid = UnitGUID(unit)
  1506.         if (conf.highlight and conf.highlight.HEAL) then
  1507.                 local amount = UnitGetIncomingHeals(unit) or 0
  1508.                 if (amount and amount > 0 and not UnitIsDeadOrGhost(unit)) then
  1509.                         local health, healthmax = UnitHealth(unit), UnitHealthMax(unit)
  1510.                         local missing = healthmax - health
  1511.                         if (missing > healthmax / 20) then                      -- More than 5% to heal
  1512.                                 self:Add(guid, "HEAL", amount)
  1513.                                 return
  1514.                         end
  1515.                 end
  1516.         end
  1517.         self:Remove(guid, "HEAL")
  1518. end
  1519.  
  1520. -- xpHigh:HasMyPomPom(unit)
  1521. function xpHigh:HasMyPomPom(unit)
  1522.         for i = 1,40 do
  1523.                 local name, rank, tex, count, buffType, dur, endTime, isMine = UnitBuff(unit, i, "PLAYER")
  1524.                 if (not name) then
  1525.                         break
  1526.                 end
  1527.                 if (pomSpells[name]) then
  1528.                         return endTime - GetTime()
  1529.                 end
  1530.         end
  1531. end
  1532.  
  1533. -- xpHigh:HasMyShield(unit)
  1534. function xpHigh:HasMyShield(unit)
  1535.         for i = 1,20 do
  1536.                 local name, rank, tex, count, buffType, dur, endTime, isMine = UnitBuff(unit, i, "PLAYER")
  1537.                 if (not name) then
  1538.                         break
  1539.                 end
  1540.                 if (shieldSpells[name]) then
  1541.                         return endTime - GetTime()
  1542.                 end
  1543.         end
  1544. end
  1545.  
  1546. -- xpHigh:FindMyPomPom()
  1547. function xpHigh:FindMyPomPom()
  1548.         for unit, unitName, unitClass, group in XPerl_NextMember do
  1549.                 local timeLeft = self:HasMyPomPom(unit)
  1550.                 if (timeLeft) then
  1551.                         return UnitGUID(unit), timeLeft
  1552.                 end
  1553.  
  1554.                 local petid = unit == "player" and "pet" or unit:gsub("^(%a+)(%d+)$", "%1pet%2")
  1555.                 if (UnitExists(petid)) then
  1556.                         local timeLeft = self:HasMyPomPom(petid)
  1557.                         if (timeLeft) then
  1558.                                 return UnitGUID(petid), timeLeft
  1559.                         end
  1560.                 end
  1561.         end
  1562. end
  1563.  
  1564. -- RemoveAllFromGUID
  1565. function xpHigh:RemoveAllFromGUID(unit)
  1566.         if (guid and self.list[guid]) then
  1567.                 self.list[guid] = nil
  1568.                 self:Send(guid)
  1569.         end
  1570. end
  1571.  
  1572. -- xpHigh:UNIT_AURA
  1573. function xpHigh:UNIT_AURA(unit)
  1574.         if (not UnitInParty(unit) and not UnitPlayerOrPetInRaid(unit) and not UnitPlayerOrPetInParty(unit)) then
  1575.                 return
  1576.         end
  1577.  
  1578.         local guid = UnitGUID(unit)
  1579.  
  1580.         if (UnitIsDeadOrGhost(unit)) then
  1581.                 self:RemoveAllFromGUID(guid)
  1582.                 return
  1583.         end
  1584.  
  1585.         if (playerClass == "PRIEST") then
  1586.                 -- Check pom movement
  1587.                 if (self:HasEffect(guid, "POM")) then
  1588.                         if (not self:HasMyPomPom(unit)) then
  1589.                                 self.pomSourceGUID = guid
  1590.                                 self:Remove(guid, "POM")
  1591.                                 self.expectingPOM = GetTime()
  1592.                         end
  1593.                 end
  1594.  
  1595.                 if (self.expectingPOM) then
  1596.                         local findGUID, timeLeft = self:FindMyPomPom()
  1597.                         if (findGUID) then
  1598.                                 self.expectingPOM = nil
  1599.                                 self:Add(findGUID, "POM", timeLeft)
  1600.                                 self:TriggerMendingAnimation(self.pomSourceGUID, findGUID)
  1601.                         elseif (GetTime() > self.expectingPOM + 2) then
  1602.                                 self.expectingPOM = nil
  1603.                                 self:StopMendingAnimation()
  1604.                         end
  1605.                 end
  1606.         end
  1607.  
  1608.         -- Check for pre-mature end of shield buff (Power Word: Shield, Earth Shield)
  1609.         if (playerClass == "SHAMAN") then       -- or playerClass == "PRIEST") then
  1610.                 if (self:HasEffect(guid, "SHIELD")) then
  1611.                         if (not self:HasMyShield(unit)) then
  1612.                                 self:Remove(guid, "SHIELD")
  1613.                         end
  1614.                 end
  1615.         end
  1616.  
  1617.         if (conf.highlight.HOTCOUNT) then
  1618.                 local hotCount = 0
  1619.                 for i = 1,40 do
  1620.                         local buffName = UnitBuff(unit, i)
  1621.                         if (not buffName) then
  1622.                                 break
  1623.                         end
  1624.                         if (hotSpells[buffName]) then
  1625.                                 hotCount = hotCount + 1
  1626.                         end
  1627.                 end
  1628.  
  1629.                 if (hotCount == 0) then
  1630.                         self:Remove(guid, "HOTCOUNT")
  1631.                 else
  1632.                         self:Add(guid, "HOTCOUNT", hotCount)
  1633.                 end
  1634.         end
  1635. end
  1636.  
  1637. -- xpHigh:RAID_ROSTER_UPDATE
  1638. function xpHigh:RAID_ROSTER_UPDATE()
  1639.         self.rosterUpdate = true
  1640.         self:SetScript("OnUpdate", self.OnUpdate)
  1641. end
  1642.  
  1643. xpHigh.PARTY_MEMBERS_CHANGED = xpHigh.RAID_ROSTER_UPDATE
  1644.  
  1645. -- PLAYER_TARGET_CHANGED
  1646. function xpHigh:PLAYER_TARGET_CHANGED()
  1647.         self:ClearAll("TARGET")
  1648.         if (UnitExists("target") and UnitPlayerOrPetInParty("target") or UnitPlayerOrPetInRaid("target")) then
  1649.                 self:Add(UnitGUID("target"), "TARGET", 0)
  1650.         end
  1651. end
  1652.  
  1653. -- PLAYER_ENTERING_WORLD
  1654. function xpHigh:PLAYER_ENTERING_WORLD()
  1655.         self:UnregisterEvent("PLAYER_ENTERING_WORLD")
  1656.         playerGUID = UnitGUID("player")
  1657.         self.PLAYER_ENTERING_WORLD = nil
  1658. end
  1659.  
  1660. -- xpHigh:RefreshAllAuras
  1661. function xpHigh:RefreshAllAuras()
  1662.         self.expectingPOM = nil
  1663.         for unitid in XPerl_NextMember do
  1664.                 self:UNIT_AURA(unitid)
  1665.         end
  1666. end
  1667.  
  1668. -- xpHigh:OptionChange
  1669. function xpHigh:OptionChange()
  1670.         local events
  1671.  
  1672.         local _
  1673.         _, playerClass = UnitClass("player")
  1674.         playerName = UnitName("player")
  1675.  
  1676.         if (conf.highlight.enable and (conf.highlight.HOT or conf.highlight.SHIELD or conf.highlight.HEAL)) then
  1677.                 events = true
  1678.                 self:RegisterEvent("COMBAT_LOG_EVENT_UNFILTERED")
  1679.         else
  1680.                 self:UnregisterEvent("COMBAT_LOG_EVENT_UNFILTERED")
  1681.         end
  1682.  
  1683.         if (not conf.highlight.enable or not conf.highlight.HOT) then
  1684.                 self:ClearAll("HOT")
  1685.                 self:ClearAll("POM")
  1686.         end
  1687.         if (not conf.highlight.enable or not conf.highlight.SHIELD) then
  1688.                 self:ClearAll("SHIELD")
  1689.         end
  1690.  
  1691.         if (conf.highlight.enable and conf.highlight.HEAL) then
  1692.                 events = true
  1693.                 self:RegisterEvent("UNIT_HEAL_PREDICTION")
  1694.         else
  1695.                 self:UnregisterEvent("UNIT_HEAL_PREDICTION")
  1696.                 self:ClearAll("HEAL")
  1697.         end
  1698.  
  1699.         if (conf.highlight.enable and (conf.highlight.HOTCOUNT or conf.highlight.HOT or conf.highlight.SHIELD)) then
  1700.                 events = true
  1701.                 self:RegisterEvent("UNIT_AURA")
  1702.                 self:RegisterEvent("RAID_ROSTER_UPDATE")
  1703.                 self:RegisterEvent("PARTY_MEMBERS_CHANGED")
  1704.                 self:RefreshAllAuras()
  1705.         else
  1706.                 self:UnregisterEvent("UNIT_AURA")
  1707.                 self:UnregisterEvent("RAID_ROSTER_UPDATE")
  1708.                 self:UnregisterEvent("PARTY_MEMBERS_CHANGED")
  1709.                 self:ClearAll("HOTCOUNT")
  1710.         end
  1711.  
  1712.         if (conf.highlight.TARGET) then
  1713.                 events = true
  1714.                 self:RegisterEvent("PLAYER_TARGET_CHANGED")
  1715.                 self:PLAYER_TARGET_CHANGED()
  1716.         else
  1717.                 self:UnregisterEvent("PLAYER_TARGET_CHANGED")
  1718.                 self:ClearAll("TARGET")
  1719.         end
  1720.  
  1721.         if (not conf.highlight.AGGRO) then
  1722.                 XPerl_Highlight:ClearAll("AGGRO")
  1723.         end
  1724.  
  1725.         if (conf.highlight.enable and events) then
  1726.                 self:SetScript("OnEvent", self.OnEvent)
  1727.         else
  1728.                 self:SetScript("OnEvent", nil)
  1729.         end
  1730.  
  1731.         if (conf.highlight.enable and (conf.highlight.HOT or conf.highlight.SHIELD or conf.highlight.HEAL)) then
  1732.                 self:SetScript("OnUpdate", self.OnUpdate)
  1733.         else
  1734.                 self:SetScript("OnUpdate", nil)
  1735.         end
  1736.  
  1737.         playerGUID = UnitGUID("player")
  1738.         if (not playerGUID and self.PLAYER_ENTERING_WORLD) then
  1739.                 self:RegisterEvent("PLAYER_ENTERING_WORLD")
  1740.         end
  1741. end
  1742.  
  1743. XPerl_RegisterOptionChanger(xpHigh.OptionChange, xpHigh)