Thread Tools Display Modes
02-02-15, 02:13 AM   #1
zork
A Pyroguard Emberseer
 
zork's Avatar
AddOn Author - Click to view addons
Join Date: Jul 2008
Posts: 1,740
Best way of updating the target nameplate?

Lately I rewrote rNamePlates to support auras. It took me a while to figure out all the itches but I finally got everything working together perfectly.

http://www.wowinterface.com/download...tesDiablo.html

There is just one small scratch that I want to get rid off.

When having a visible target nameplate. Once I move the camera off the nameplate and then move it back to the nameplate the auras aren't working. That is because the nameplate GUID is reset. (Because the OnHide has been triggered)

The GUID scan is event driven and works perfectly. The only problem left is if I have a target nameplate without a GUID. Which can happed if the nameplate triggered the OnHide event and gets re-shown later on without a PLAYER_TARGET_CHANGED event being fired inbetween.

My question is. How would you re-test for a target nameplate GUID?

Here is what I do atm: https://code.google.com/p/rothui/sou...Plates.lua#614

So. What I'm thinking of is the following. In the OnUpdate I can count the frame with alpha of 1. If the result is 1 after the loop I check if I have a valid target and if the current nameplate marked as targetPlate has a GUID. If it does not I could apply it and scan for auras.

Well. That is my idea. Maybe anyone has a different approach that he might share?

Here is my idea:
Lua Code:
  1. -- // rNamePlates
  2.   -- // zork - 2014
  3.  
  4.   -----------------------------
  5.   -- VARIABLES
  6.   -----------------------------
  7.  
  8.   local an, at = ...
  9.   local plates, namePlateIndex, _G, string, WorldFrame, unpack, math, wipe, mod = {}, nil, _G, string, WorldFrame, unpack, math, wipe, mod
  10.  
  11.   local cfg = {}
  12.   cfg.scale                   = 0.35
  13.   cfg.font                    = STANDARD_TEXT_FONT
  14.   cfg.healthbar_fontsize      = 26
  15.   cfg.castbar_fontsize        = 26
  16.   cfg.aura_stack_fontsize     = 24
  17.   cfg.aura_cooldown_fontsize  = 28
  18.   cfg.point                   = {"CENTER",0,-16}
  19.   cfg.notFocusedPlateAlpha    = 0.5
  20.  
  21.   -----------------------------
  22.   -- AURAS
  23.   -----------------------------
  24.  
  25.   local NUM_MAX_AURAS = 40
  26.  
  27.   local unitDB                = {}  --unit table by guid
  28.   local spellDB                     --aura table by spellid
  29.  
  30.   local AuraModule = CreateFrame("Frame")
  31.   AuraModule.playerGUID       = nil
  32.   AuraModule.petGUID          = nil
  33.   AuraModule.updateTarget     = false
  34.   AuraModule.hasTarget        = false
  35.   AuraModule.updateMouseover  = false
  36.  
  37.   function AuraModule:PLAYER_TARGET_CHANGED(...)
  38.     if not spellDB then return end
  39.     if spellDB.disabled then return end
  40.     if UnitGUID("target") and UnitExists("target") and not UnitIsUnit("target","player") and not UnitIsDead("target") then
  41.       self.updateTarget = true
  42.       self.hasTarget = true
  43.     else
  44.       self.updateTarget = false
  45.       self.hasTarget = false
  46.     end
  47.   end
  48.  
  49.   function AuraModule:UPDATE_MOUSEOVER_UNIT(...)
  50.     if not spellDB then return end
  51.     if spellDB.disabled then return end
  52.     if UnitGUID("mouseover") and UnitExists("mouseover") and not UnitIsUnit("mouseover","player") and not UnitIsDead("mouseover") then
  53.       self.updateMouseover = true
  54.     else
  55.       self.updateMouseover = false
  56.     end
  57.   end
  58.  
  59.   function AuraModule:UNIT_PET(...)
  60.     if UnitGUID("pet") and UnitExists("pet") then
  61.       self.petGUID = UnitGUID("pet")
  62.     end
  63.   end
  64.  
  65.   function AuraModule:PLAYER_LOGIN(...)
  66.     if UnitGUID("player") then
  67.       self.playerGUID = UnitGUID("player")
  68.     end
  69.     if UnitGUID("pet") and UnitExists("pet") then
  70.       self.petGUID = UnitGUID("pet")
  71.     end
  72.   end
  73.  
  74.   AuraModule.CLEU_FILTER = {
  75.     ["SPELL_AURA_APPLIED"]      = true, --UpdateAura
  76.     ["SPELL_AURA_REFRESH"]      = true, --UpdateAura
  77.     ["SPELL_AURA_APPLIED_DOSE"] = true, --UpdateAura
  78.     ["SPELL_AURA_REMOVED_DOSE"] = true, --UpdateAura
  79.     ["SPELL_AURA_STOLEN"]       = true, --RemoveAura
  80.     ["SPELL_AURA_REMOVED"]      = true, --RemoveAura
  81.     ["SPELL_AURA_BROKEN"]       = true, --RemoveAura
  82.     ["SPELL_AURA_BROKEN_SPELL"] = true, --RemoveAura
  83.   }
  84.  
  85.   function AuraModule:COMBAT_LOG_EVENT_UNFILTERED(...)
  86.     if not spellDB then return end
  87.     if spellDB.disabled then return end
  88.     local _, event, _, srcGUID, _, _, _, destGUID, _, _, _, spellID, spellName, _, _, stackCount = ...
  89.     if self.CLEU_FILTER[event] then
  90.       if not unitDB[destGUID] then return end --no corresponding nameplate found
  91.       if not spellDB[spellID] then return end --no spell info found
  92.       local unitCaster = nil
  93.       if srcGUID == self.playerGUID then
  94.         unitCaster = "player"
  95.       elseif srcGUID == self.petGUID then
  96.         unitCaster = "pet"
  97.       else
  98.         return
  99.       end
  100.       if event == "SPELL_AURA_APPLIED" or event == "SPELL_AURA_REFRESH" or event == "SPELL_AURA_APPLIED_DOSE" or event == "SPELL_AURA_REMOVED_DOSE" then
  101.         unitDB[destGUID]:UpdateAura(GetTime(),nil,unitCaster,spellID,stackCount)
  102.       else
  103.         unitDB[destGUID]:RemoveAura(spellID)
  104.       end
  105.     end
  106.   end
  107.  
  108.   function AuraModule:UNIT_AURA(unit)
  109.     if not spellDB then return end
  110.     if spellDB.disabled then return end
  111.     local guid = UnitGUID(unit)
  112.     if guid and unitDB[guid] and not UnitIsUnit(unit,"player") then
  113.       --print("ScanAuras", "UNIT_AURA", unitDB[guid].newPlate.id)
  114.       unitDB[guid]:ScanAuras(unit,"HELPFUL")
  115.       unitDB[guid]:ScanAuras(unit,"HARMFUL")
  116.     end
  117.   end
  118.  
  119.   function AuraModule:ADDON_LOADED(name,...)
  120.     if name == an then
  121.       self:UnregisterEvent("ADDON_LOADED")
  122.       if not rNP_SPELL_DB then
  123.         rNP_SPELL_DB = {}
  124.       end
  125.       spellDB = rNP_SPELL_DB --variable is bound by reference. there is no way this can fuck up. like no way.
  126.       print(an,"AuraModule","loading spell db")
  127.       if spellDB.disabled then
  128.         print(an,"AuraModule","spell db is currently disabled on this character")
  129.       end
  130.     end
  131.   end
  132.  
  133.   AuraModule:RegisterEvent("ADDON_LOADED")
  134.   AuraModule:RegisterEvent("PLAYER_LOGIN")
  135.   --ok unit_aura is important. otherwise new auras will only be found if they are preset on frame init.
  136.   --one cannot add new spells to the DB via CLEU. there is missing data (duration).
  137.   AuraModule:RegisterUnitEvent("UNIT_AURA","target","mouseover")
  138.   AuraModule:RegisterEvent("COMBAT_LOG_EVENT_UNFILTERED")
  139.   AuraModule:RegisterUnitEvent("UNIT_PET", "player")
  140.   AuraModule:RegisterEvent("PLAYER_TARGET_CHANGED")
  141.   AuraModule:RegisterEvent("UPDATE_MOUSEOVER_UNIT")
  142.   AuraModule:SetScript("OnEvent", function(self, event, ...) self[event](self, ...) end)
  143.  
  144.   -----------------------------
  145.   -- FUNCTIONS
  146.   -----------------------------
  147.  
  148.   local trash = CreateFrame("Frame")
  149.   trash:Hide()
  150.  
  151.   local function GetHexColorFromRGB(r, g, b)
  152.     return string.format("%02x%02x%02x", r*255, g*255, b*255)
  153.   end
  154.  
  155.   local function GetFormattedTime(time)
  156.     if time <= 0 then
  157.       return ""
  158.     elseif time < 2 then
  159.       return (math.floor(time*10)/10)
  160.     elseif time < 60 then
  161.       return string.format("%ds", mod(time, 60))
  162.     elseif time < 3600 then
  163.       return string.format("%dm", math.floor(mod(time, 3600) / 60 + 1))
  164.     else
  165.       return string.format("%dh", math.floor(time / 3600 + 1))
  166.     end
  167.   end
  168.  
  169.   local function RoundNumber(n)
  170.     return (math.floor(n*100+0.5)/100)
  171.   end
  172.  
  173.   local function NamePlateSetup(blizzPlate)
  174.  
  175.     blizzPlate.borderTexture:SetTexture(nil)
  176.     blizzPlate.bossIconTexture:SetTexture(nil)
  177.     blizzPlate.eliteDragonTexture:SetTexture(nil)
  178.     blizzPlate.highlightTexture:SetTexture(nil)
  179.     blizzPlate.threatTexture:SetTexture(nil)
  180.  
  181.     local name = blizzPlate.nameString:GetText() or "Unknown"
  182.     local level = blizzPlate.levelString:GetText() or "-1"
  183.     local hexColor = GetHexColorFromRGB(blizzPlate.levelString:GetTextColor()) or "ffffff"
  184.  
  185.     if blizzPlate.bossIconTexture:IsShown() then
  186.       level = "??"
  187.       hexColor = "ff6600"
  188.     elseif blizzPlate.eliteDragonTexture:IsShown() then
  189.       level = level.."+"
  190.     end
  191.     blizzPlate.newPlate.healthBar.name:SetText("|cff"..hexColor..""..level.."|r "..name)
  192.   end
  193.  
  194.   local function NamePlateOnInit(blizzPlate)
  195.  
  196.     blizzPlate.barFrame, blizzPlate.nameFrame = blizzPlate:GetChildren()
  197.     blizzPlate.healthBar, blizzPlate.castBar = blizzPlate.barFrame:GetChildren()
  198.     blizzPlate.threatTexture, blizzPlate.borderTexture, blizzPlate.highlightTexture, blizzPlate.levelString, blizzPlate.bossIconTexture, blizzPlate.raidIconTexture, blizzPlate.eliteDragonTexture = blizzPlate.barFrame:GetRegions()
  199.     blizzPlate.nameString = blizzPlate.nameFrame:GetRegions()
  200.     blizzPlate.healthBar.statusbarTexture = blizzPlate.healthBar:GetRegions()
  201.     blizzPlate.castBar.statusbarTexture, blizzPlate.castBar.borderTexture, blizzPlate.castBar.shieldTexture, blizzPlate.castBar.spellIconTexture, blizzPlate.castBar.nameString, blizzPlate.castBar.nameShadow = blizzPlate.castBar:GetRegions()
  202.  
  203.     blizzPlate.nameFrame:SetParent(trash)
  204.     blizzPlate.levelString:SetParent(trash)
  205.  
  206.     blizzPlate.healthBar.__owner = blizzPlate
  207.     blizzPlate.castBar.__owner = blizzPlate
  208.  
  209.     blizzPlate.healthBar:SetParent(trash)
  210.     blizzPlate.castBar:SetParent(trash)
  211.  
  212.     blizzPlate.castBar.borderTexture:SetTexture(nil)
  213.     blizzPlate.borderTexture:SetTexture(nil)
  214.     blizzPlate.bossIconTexture:SetTexture(nil)
  215.     blizzPlate.eliteDragonTexture:SetTexture(nil)
  216.     blizzPlate.highlightTexture:SetTexture(nil)
  217.     blizzPlate.threatTexture:SetTexture(nil)
  218.  
  219.   end
  220.  
  221.   local function SkinHealthBar(blizzPlate)
  222.  
  223.     local bar = CreateFrame("StatusBar",nil,blizzPlate.newPlate)
  224.     bar:SetSize(256,64)
  225.     bar:SetStatusBarTexture("Interface\\AddOns\\"..an.."\\media\\statusbar_fill")
  226.     bar:SetScale(cfg.scale)
  227.     bar:SetPoint(unpack(cfg.point))
  228.  
  229.     local le = bar:CreateTexture(nil,"BACKGROUND",nil,-8)
  230.     le:SetTexture("Interface\\AddOns\\"..an.."\\media\\edge_left")
  231.     le:SetSize(64,64)
  232.     le:SetPoint("RIGHT",bar,"LEFT",0,0)
  233.  
  234.     local re = bar:CreateTexture(nil,"BACKGROUND",nil,-8)
  235.     re:SetTexture("Interface\\AddOns\\"..an.."\\media\\edge_right")
  236.     re:SetSize(64,64)
  237.     re:SetPoint("LEFT",bar,"RIGHT",0,0)
  238.  
  239.     local bg = bar:CreateTexture(nil,"BACKGROUND",nil,-8)
  240.     bg:SetTexture("Interface\\AddOns\\"..an.."\\media\\statusbar_bg")
  241.     bg:SetAllPoints()
  242.  
  243.     local shadow = bar:CreateTexture(nil,"BACKGROUND",nil,-8)
  244.     shadow:SetTexture("Interface\\Common\\NameShadow")
  245.     shadow:SetPoint("BOTTOM",bar,"TOP",0,-20)
  246.     shadow:SetSize(256,32)
  247.     shadow:SetTexCoord(1,1,1,0,0,1,0,0)
  248.     shadow:SetAlpha(0.5)
  249.  
  250.     local hlf = CreateFrame("Frame",nil,bar)
  251.     hlf:SetAllPoints()
  252.     bar.hlf = hlf
  253.  
  254.     local hl = hlf:CreateTexture(nil,"BACKGROUND",nil,-8)
  255.     hl:SetTexture("Interface\\AddOns\\"..an.."\\media\\statusbar_highlight")
  256.     hl:SetAllPoints()
  257.  
  258.     local name = bar.hlf:CreateFontString(nil, "BORDER")
  259.     name:SetFont(cfg.font, cfg.healthbar_fontsize, "OUTLINE")
  260.     name:SetPoint("BOTTOM",bar,"TOP",0,-24)
  261.     name:SetPoint("LEFT",8,0)
  262.     name:SetPoint("RIGHT",-8,0)
  263.     name:SetText("Ich bin ein Berliner!")
  264.     bar.name = name
  265.  
  266.     blizzPlate.raidIconTexture:SetParent(bar)
  267.     blizzPlate.raidIconTexture:SetSize(60,60)
  268.     blizzPlate.raidIconTexture:ClearAllPoints()
  269.     blizzPlate.raidIconTexture:SetPoint("BOTTOM",bar,"TOP",0,40)
  270.  
  271.     blizzPlate.newPlate.healthBar = bar
  272.  
  273.   end
  274.  
  275.   local function SkinCastBar(blizzPlate)
  276.  
  277.     local bar = CreateFrame("StatusBar",nil,blizzPlate.newPlate)
  278.     bar:SetSize(256,64)
  279.     bar:SetStatusBarTexture("Interface\\AddOns\\"..an.."\\media\\statusbar_fill")
  280.     bar:SetScale(cfg.scale)
  281.     bar:SetPoint("TOP",blizzPlate.newPlate.healthBar,"BOTTOM",0,20)
  282.  
  283.     local le = bar:CreateTexture(nil,"BACKGROUND",nil,-8)
  284.     le:SetTexture("Interface\\AddOns\\"..an.."\\media\\edge_left")
  285.     le:SetSize(64,64)
  286.     le:SetPoint("RIGHT",bar,"LEFT",0,0)
  287.  
  288.     local re = bar:CreateTexture(nil,"BACKGROUND",nil,-8)
  289.     re:SetTexture("Interface\\AddOns\\"..an.."\\media\\edge_right")
  290.     re:SetSize(64,64)
  291.     re:SetPoint("LEFT",bar,"RIGHT",0,0)
  292.  
  293.     local bg = bar:CreateTexture(nil,"BACKGROUND",nil,-8)
  294.     bg:SetTexture("Interface\\AddOns\\"..an.."\\media\\statusbar_bg")
  295.     bg:SetAllPoints()
  296.  
  297.     local shadow = bar:CreateTexture(nil,"BACKGROUND",nil,-8)
  298.     shadow:SetTexture("Interface\\Common\\NameShadow")
  299.     shadow:SetPoint("TOP",bar,"BOTTOM",0,20)
  300.     shadow:SetSize(256,32)
  301.  
  302.     local hlf = CreateFrame("Frame",nil,bar)
  303.     hlf:SetAllPoints()
  304.     bar.hlf = hlf
  305.  
  306.     local hl = hlf:CreateTexture(nil,"BACKGROUND",nil,-8)
  307.     hl:SetTexture("Interface\\AddOns\\"..an.."\\media\\statusbar_highlight")
  308.     hl:SetAllPoints()
  309.  
  310.     local name = bar.hlf:CreateFontString(nil, "BORDER")
  311.     name:SetFont(cfg.font, cfg.castbar_fontsize, "OUTLINE")
  312.     name:SetPoint("TOP",bar,"BOTTOM",0,30)
  313.     name:SetPoint("LEFT",8,0)
  314.     name:SetPoint("RIGHT",-8,0)
  315.     bar.nameString = name
  316.  
  317.     local icon = bar:CreateTexture(nil,"BACKGROUND",nil,-8)
  318.     icon:SetTexCoord(0.08,0.92,0.08,0.92)
  319.     icon:SetPoint("RIGHT",bar,"LEFT",-58,22)
  320.     icon:SetSize(60,60)
  321.     bar.spellIconTexture = icon
  322.  
  323.     local iconBorder = bar:CreateTexture(nil,"BACKGROUND",nil,-7)
  324.     iconBorder:SetTexture("Interface\\AddOns\\"..an.."\\media\\icon_border")
  325.     iconBorder:SetPoint("CENTER",bar.spellIconTexture,"CENTER",0,0)
  326.     iconBorder:SetSize(78,78)
  327.     bar.spellIconBorder = iconBorder
  328.  
  329.     local shield = bar:CreateTexture(nil,"BACKGROUND",nil,-6)
  330.     shield:SetTexture("Interface\\AddOns\\"..an.."\\media\\shield")
  331.     shield:SetPoint("BOTTOM",bar.spellIconBorder,0,-5)
  332.     shield:SetSize(36,36)
  333.     bar.shieldTexture = shield
  334.  
  335.     if not blizzPlate.castBar:IsShown() then
  336.       bar:Hide()
  337.     end
  338.  
  339.     blizzPlate.newPlate.castBar = bar
  340.  
  341.   end
  342.  
  343.   local function NamePlatePosition(blizzPlate)
  344.     local sizer = CreateFrame("Frame", nil, blizzPlate.newPlate)
  345.     sizer:SetPoint("BOTTOMLEFT", WorldFrame)
  346.     sizer:SetPoint("TOPRIGHT", blizzPlate, "CENTER")
  347.     sizer:SetScript("OnSizeChanged", function(self, x, y)
  348.       if blizzPlate:IsShown() then
  349.         blizzPlate.newPlate:Hide() -- Important, never move the frame while it"s visible
  350.         blizzPlate.newPlate:SetPoint("CENTER", WorldFrame, "BOTTOMLEFT", x, y) -- Immediately reposition frame
  351.         blizzPlate.newPlate:Show()
  352.       end
  353.     end)
  354.   end
  355.  
  356.   local function NamePlateSetGUID(blizzPlate,guid)
  357.     if blizzPlate.guid and guid ~= blizzPlate.guid then
  358.       unitDB[blizzPlate.guid] = nil
  359.       wipe(blizzPlate.auras)
  360.       blizzPlate:UpdateAllAuras() --hide visible buttons
  361.       blizzPlate.guid = guid
  362.       unitDB[guid] = blizzPlate
  363.     elseif not blizzPlate.guid then
  364.       blizzPlate.guid = guid
  365.       unitDB[guid] = blizzPlate
  366.     end
  367.   end
  368.  
  369.   local function NamePlateOnShow(blizzPlate)
  370.     NamePlateSetup(blizzPlate)
  371.     blizzPlate.newPlate:Show()
  372.   end
  373.  
  374.   local function NamePlateOnHide(blizzPlate)
  375.     blizzPlate.newPlate.castBar:Hide()
  376.     blizzPlate.newPlate:Hide()
  377.     wipe(blizzPlate.auras)
  378.     blizzPlate:UpdateAllAuras() --hide visible buttons
  379.     if blizzPlate.guid then
  380.       unitDB[blizzPlate.guid] = nil
  381.       blizzPlate.guid = nil
  382.     end
  383.   end
  384.  
  385.   local function NamePlateCastBarOnHide(castBar)
  386.     local blizzPlate = castBar.__owner
  387.     local castBar2 = blizzPlate.newPlate.castBar
  388.     castBar2:Hide()
  389.   end
  390.  
  391.   local function NamePlateCastBarUpdate(castBar, value)
  392.     local blizzPlate = castBar.__owner
  393.     local castBar2 = blizzPlate.newPlate.castBar
  394.     if castBar:IsShown() then
  395.       castBar2:Show()
  396.     else
  397.       castBar2:Hide()
  398.       return
  399.     end
  400.     if value == 0 then
  401.       castBar2:Hide()
  402.       return
  403.     end
  404.     castBar2.spellIconTexture:SetTexture(castBar.spellIconTexture:GetTexture())
  405.     castBar2.nameString:SetText(castBar.nameString:GetText())
  406.     castBar2:SetMinMaxValues(castBar:GetMinMaxValues())
  407.     castBar2:SetValue(castBar:GetValue())
  408.     if castBar.shieldTexture:IsShown() then
  409.       castBar2.shieldTexture:Show()
  410.       castBar2:SetStatusBarColor(0.8,0.8,0.8)
  411.       castBar2.spellIconBorder:SetDesaturated(1)
  412.     else
  413.       castBar2.shieldTexture:Hide()
  414.       castBar2:SetStatusBarColor(castBar:GetStatusBarColor())
  415.       castBar2.spellIconBorder:SetDesaturated(0)
  416.     end
  417.   end
  418.  
  419.   local function NamePlateHealthBarUpdate(healthBar)
  420.     local blizzPlate = healthBar.__owner
  421.     local healthBar2 = blizzPlate.newPlate.healthBar
  422.     healthBar2:SetMinMaxValues(healthBar:GetMinMaxValues())
  423.     healthBar2:SetValue(healthBar:GetValue())
  424.   end
  425.  
  426.   local RAID_CLASS_COLORS = RAID_CLASS_COLORS
  427.   local FACTION_BAR_COLORS = FACTION_BAR_COLORS
  428.  
  429.   local function NamePlateHealthBarColor(blizzPlate)
  430.     if blizzPlate.threatTexture:IsShown() then
  431.       local r,g,b = blizzPlate.threatTexture:GetVertexColor()
  432.       if g+b == 0 then
  433.         blizzPlate.newPlate.healthBar:SetStatusBarColor(0,1,0)--tank mode
  434.       else
  435.         blizzPlate.newPlate.healthBar:SetStatusBarColor(r,g,b)
  436.       end
  437.       return
  438.     end
  439.     local r,g,b = blizzPlate.healthBar:GetStatusBarColor()
  440.     if g+b == 0 then -- hostile
  441.       r,g,b = FACTION_BAR_COLORS[2].r, FACTION_BAR_COLORS[2].g, FACTION_BAR_COLORS[2].b
  442.     elseif r+b == 0 then -- friendly npc
  443.       r,g,b = FACTION_BAR_COLORS[6].r, FACTION_BAR_COLORS[6].g, FACTION_BAR_COLORS[6].b
  444.     elseif r+g > 1.95 then -- neutral
  445.       r,g,b = FACTION_BAR_COLORS[4].r, FACTION_BAR_COLORS[4].g, FACTION_BAR_COLORS[4].b
  446.     elseif r+g == 0 then -- friendly player, we don't like 0,0,1 so we change it to a more likable color
  447.       r,g,b = 0/255, 100/255, 255/255
  448.     end
  449.     blizzPlate.newPlate.healthBar:SetStatusBarColor(r,g,b)
  450.   end
  451.  
  452.   local function CreateNewPlate(blizzPlate)
  453.     blizzPlate.newPlate = CreateFrame("Frame", nil, WorldFrame)
  454.     blizzPlate.newPlate.id = namePlateIndex
  455.     blizzPlate.newPlate:SetSize(36,36)
  456.     plates[blizzPlate] = blizzPlate.newPlate
  457.   end
  458.  
  459.   local function CreateNamePlateAuraFunctions(blizzPlate)
  460.     blizzPlate.auras = {}
  461.     blizzPlate.auraButtons = {}
  462.     function blizzPlate:CreateAuraHeader()
  463.       local auraHeader = CreateFrame("Frame",nil,self.newPlate)
  464.       auraHeader:SetScale(cfg.scale)
  465.       auraHeader:SetPoint("BOTTOMLEFT",self.newPlate.healthBar,"TOPLEFT",0,15)
  466.       auraHeader:SetSize(60,45)
  467.       blizzPlate.auraHeader = auraHeader
  468.     end
  469.     function blizzPlate:UpdateAura(startTime,expirationTime,unitCaster,spellID,stackCount)
  470.       if not spellDB then return end
  471.       if not spellDB[spellID] then return end
  472.       if spellDB[spellID].blacklisted then return end
  473.       if not expirationTime then
  474.         expirationTime = startTime+spellDB[spellID].duration
  475.       elseif not startTime then
  476.         startTime = expirationTime-spellDB[spellID].duration
  477.       end
  478.       self.auras[spellID] = {
  479.         spellId         = spellID,
  480.         name            = spellDB[spellID].name,
  481.         texture         = spellDB[spellID].texture,
  482.         startTime       = startTime,
  483.         expirationTime  = expirationTime,
  484.         duration        = spellDB[spellID].duration,
  485.         unitCaster      = unitCaster,
  486.         stackCount      = stackCount,
  487.       }
  488.     end
  489.     function blizzPlate:RemoveAura(spellID)
  490.       if self.auras[spellID] then
  491.         self.auras[spellID] = nil
  492.       end
  493.     end
  494.     function blizzPlate:ScanAuras(unit,filter)
  495.       if not spellDB then return end
  496.       if spellDB.disabled then return end
  497.       for index = 1, NUM_MAX_AURAS do
  498.         local name, _, texture, stackCount, _, duration, expirationTime, unitCaster, _, _, spellID = UnitAura(unit, index, filter)
  499.         if not name then break end
  500.         if spellID and (unitCaster == "player" or unitCaster == "pet") and not spellDB[spellID] then
  501.           spellDB[spellID] = {
  502.             name        = name,
  503.             texture     = texture,
  504.             duration    = duration,
  505.             blacklisted = false,
  506.           }
  507.           print(an,"AuraModule","adding new spell to db",spellID,name)
  508.         end
  509.         if spellID and (unitCaster == "player" or unitCaster == "pet") then
  510.           self:UpdateAura(nil,expirationTime,unitCaster,spellID,stackCount)
  511.         end
  512.       end
  513.     end
  514.     function blizzPlate:CreateAuraButton(index)
  515.       if not self.auraHeader then
  516.         self:CreateAuraHeader()
  517.       end
  518.       local button = CreateFrame("Frame",nil,self.auraHeader)
  519.       button:SetSize(self.auraHeader:GetSize())
  520.       button.bg = button:CreateTexture(nil,"BACKGROUND",nil,-8)
  521.       button.bg:SetTexture(1,1,1)
  522.       button.bg:SetVertexColor(0,0,0,0.8)
  523.       button.bg:SetAllPoints()
  524.       button.icon = button:CreateTexture(nil,"BACKGROUND",nil,-7)
  525.       button.icon:SetPoint("TOPLEFT",3,-3)
  526.       button.icon:SetPoint("BOTTOMRIGHT",-3,3)
  527.       button.icon:SetTexCoord(0.1,0.9,0.2,0.8)
  528.       button.cooldown = button:CreateFontString(nil, "BORDER")
  529.       button.cooldown:SetFont(cfg.font, cfg.aura_cooldown_fontsize, "OUTLINE")
  530.       button.cooldown:SetPoint("BOTTOM",button,0,-5)
  531.       button.cooldown:SetJustifyH("CENTER")
  532.       button.stack = button:CreateFontString(nil, "BORDER")
  533.       button.stack:SetFont(cfg.font, cfg.aura_stack_fontsize, "OUTLINE")
  534.       button.stack:SetPoint("TOPRIGHT",button,5,5)
  535.       button.stack:SetJustifyH("RIGHT")
  536.       if index == 1 then
  537.         button:SetPoint("CENTER")
  538.       else
  539.         button:SetPoint("LEFT",self.auraButtons[index-1],"RIGHT",10,0)
  540.       end
  541.       button:Hide()
  542.       self.auraButtons[index] = button
  543.       return button
  544.     end
  545.     function blizzPlate:UpdateAllAuras()
  546.       local buttonIndex = 1
  547.       for index, button in next, self.auraButtons do
  548.         button:Hide()
  549.       end
  550.       for spellID, data in next, self.auras do
  551.         local cooldown = data.expirationTime-GetTime()
  552.         if cooldown < 0 then
  553.           self:RemoveAura(spellID)
  554.         else
  555.           local button = self.auraButtons[buttonIndex] or self:CreateAuraButton(buttonIndex)
  556.           --set texture
  557.           button.icon:SetTexture(data.texture)
  558.           --set cooldown
  559.           button.cooldown:SetText(GetFormattedTime(cooldown))
  560.           --set stackCount
  561.           if data.stackCount and data.stackCount > 1 then
  562.             button.stack:SetText(data.stackCount)
  563.           else
  564.             button.stack:SetText("")
  565.           end
  566.           button:Show()
  567.           buttonIndex = buttonIndex + 1
  568.         end
  569.       end
  570.     end
  571.   end
  572.  
  573.   local function SkinPlate(blizzPlate)
  574.     if plates[blizzPlate] then return end
  575.     CreateNewPlate(blizzPlate)
  576.     NamePlateOnInit(blizzPlate)
  577.     SkinHealthBar(blizzPlate)
  578.     SkinCastBar(blizzPlate)
  579.     NamePlateSetup(blizzPlate)
  580.     NamePlatePosition(blizzPlate)
  581.     if not blizzPlate:IsShown() then
  582.       blizzPlate.newPlate:Hide()
  583.     end
  584.     CreateNamePlateAuraFunctions(blizzPlate)
  585.     blizzPlate:HookScript("OnShow", NamePlateOnShow)
  586.     blizzPlate:HookScript("OnHide", NamePlateOnHide)
  587.     blizzPlate.castBar:HookScript("OnShow", NamePlateCastBarUpdate)
  588.     blizzPlate.castBar:HookScript("OnHide", NamePlateCastBarOnHide)
  589.     blizzPlate.castBar:HookScript("OnValueChanged", NamePlateCastBarUpdate)
  590.     blizzPlate.healthBar:HookScript("OnValueChanged", NamePlateHealthBarUpdate)
  591.     NamePlateHealthBarUpdate(blizzPlate.healthBar)
  592.     NamePlateHealthBarColor(blizzPlate)
  593.     namePlateIndex = namePlateIndex+1
  594.   end
  595.  
  596.   -----------------------------
  597.   -- ONUPDATE
  598.   -----------------------------
  599.  
  600.   local countFramesWithFullAlpha = 0
  601.   local targetPlate = nil
  602.   local delayCounter = 0
  603.   local timer = 0.0
  604.   local interval = 0.1
  605.  
  606.   WorldFrame:HookScript("OnUpdate", function(self, elapsed)
  607.     timer = timer+elapsed
  608.     countFramesWithFullAlpha = 0
  609.     for blizzPlate, newPlate in next, plates do
  610.       if blizzPlate:IsShown() then
  611.         if blizzPlate:GetAlpha() == 1 then
  612.           newPlate:SetAlpha(1)
  613.         else
  614.           newPlate:SetAlpha(cfg.notFocusedPlateAlpha)
  615.         end
  616.         if AuraModule.hasTarget and blizzPlate:GetAlpha() == 1 then
  617.           countFramesWithFullAlpha = countFramesWithFullAlpha + 1
  618.           targetPlate = blizzPlate
  619.         end
  620.         if AuraModule.updateMouseover and blizzPlate.highlightTexture:IsShown() and UnitGUID("mouseover") and UnitExists("mouseover") then
  621.           NamePlateSetGUID(blizzPlate,UnitGUID("mouseover"))
  622.           blizzPlate:ScanAuras("mouseover","HELPFUL")
  623.           blizzPlate:ScanAuras("mouseover","HARMFUL")
  624.           AuraModule.updateMouseover = false
  625.         end
  626.         if timer > interval then
  627.           NamePlateHealthBarColor(blizzPlate)
  628.           blizzPlate:UpdateAllAuras()
  629.         end
  630.       end
  631.     end
  632.     if timer > interval then
  633.       timer = 0
  634.     end
  635.     if AuraModule.hasTarget and countFramesWithFullAlpha == 1 and (AuraModule.updateTarget or not targetPlate.guid) then
  636.       --this may look wierd but is actually needed.
  637.       --when the PLAYER_TARGET_CHANGED event fires the nameplate need one cycle to update the alpha, otherwise the old target would be tagged.
  638.       if delayCounter == 1 then
  639.         NamePlateSetGUID(targetPlate,UnitGUID("target"))
  640.         targetPlate:ScanAuras("target","HELPFUL")
  641.         targetPlate:ScanAuras("target","HARMFUL")
  642.         AuraModule.updateTarget = false
  643.         delayCounter = 0
  644.         targetPlate = nil
  645.       else
  646.         delayCounter = delayCounter + 1
  647.       end
  648.     end
  649.     if not namePlateIndex then
  650.       for _, blizzPlate in next, {self:GetChildren()} do
  651.         local name = blizzPlate:GetName()
  652.         if name and string.match(name, "^NamePlate%d+$") then
  653.           namePlateIndex = string.gsub(name,"NamePlate","")
  654.           break
  655.         end
  656.       end
  657.     else
  658.       local blizzPlate = _G["NamePlate"..namePlateIndex]
  659.       if not blizzPlate then return end
  660.       SkinPlate(blizzPlate)
  661.     end
  662.   end)
  663.  
  664.   --reset some outdated (yet still active) bloat variables if people run old config.wtf files
  665.   --setvar
  666.   SetCVar("bloatnameplates",0)
  667.   SetCVar("bloatthreat",0)
  668.   SetCVar("bloattest",0)
  669.  
  670.   -----------------------------
  671.   -- SLASH_COMMAND_LIST
  672.   -----------------------------
  673.  
  674.   local color         = "FFFFAA00"
  675.   local shortcut      = "rnp"
  676.  
  677.   local function HandleSlashCmd(cmd)
  678.     if not spellDB then return end
  679.     local spellID = tonumber(strsub(cmd, (strfind(cmd, " ") or 0)+1))
  680.     if (cmd:match"blacklist") then
  681.       print("|c"..color..an.." blacklist|r")
  682.       if spellID and spellDB[spellID] then
  683.         spellDB[spellID].blacklisted = true
  684.         print(spellID,spellDB[spellID].name,"is now blacklisted")
  685.       else
  686.         print("no matching spellid found")
  687.       end
  688.     elseif (cmd:match"whitelist") then
  689.       print("|c"..color..an.." whitelist|r")
  690.       if spellID and spellDB[spellID] then
  691.         spellDB[spellID].blacklisted = false
  692.         print(spellID,spellDB[spellID].name,"is now whitelisted")
  693.       else
  694.         print("no matching spellid found")
  695.       end
  696.     elseif (cmd:match"list") then
  697.       print("|c"..color..an.." list|r")
  698.       print("spellID","|","name","|","blacklisted")
  699.       print("------------------------------------")
  700.       local count = 0
  701.       for key, data in next, spellDB do
  702.         if type(key) == "number" then
  703.           print(key,"|",data.name,"|",data.blacklisted)
  704.           count = count+1
  705.         end
  706.       end
  707.       if count == 0 then
  708.         print("list has no entries")
  709.       end
  710.     elseif (cmd:match"remove") then
  711.       print("|c"..color..an.." remove|r")
  712.       if spellID and spellDB[spellID] then
  713.         print(spellID,spellDB[spellID].name,"removed")
  714.         spellDB[spellID] = nil
  715.       else
  716.         print("no matching spellid found")
  717.       end
  718.     elseif (cmd:match"resetspelldb") then
  719.       print("|c"..color..an.." resetspelldb|r")
  720.       wipe(spellDB)
  721.       print("spell db has been reset")
  722.     elseif (cmd:match"disable") then
  723.       print("|c"..color..an.." disable|r")
  724.       spellDB.disabled = true
  725.       print("spell db has been disabled")
  726.     elseif (cmd:match"enable") then
  727.       print("|c"..color..an.." enable|r")
  728.       spellDB.disabled = false
  729.       print("spell db has been enabled")
  730.     else
  731.       print("|c"..color..an.." command list|r")
  732.       print("|c"..color.."\/"..shortcut.." list|r to list all entries in spellDB")
  733.       print("|c"..color.."\/"..shortcut.." blacklist SPELLID|r to blacklist a spellid in spellDB")
  734.       print("|c"..color.."\/"..shortcut.." whitelist SPELLID|r to whitelist a spellid in spellDB")
  735.       print("|c"..color.."\/"..shortcut.." remove SPELLID|r to remove a spellid from spellDB")
  736.       print("|c"..color.."\/"..shortcut.." disable|r to disable the spellDB for this character")
  737.       print("|c"..color.."\/"..shortcut.." enable|r to enable the spellDB for this character")
  738.       print("|c"..color.."\/"..shortcut.." resetspelldb|r to reset the spellDB for this character")
  739.     end
  740.   end
  741.  
  742.   --slash commands
  743.   SlashCmdList[shortcut] = HandleSlashCmd
  744.   SLASH_rnp1 = "/"..shortcut;
  745.  
  746.   print("|c"..color..an.." loaded.|r")
  747.   print("|c"..color.."\/"..shortcut.."|r to display the command list")

So basically instead of using AuraModule.updateTarget I use a new variable AuraModule.hasTarget. Thus I'm able to recheck nameplates with no GUID.
__________________
| Simple is beautiful.
| WoWI AddOns | GitHub | Zork (WoW)

"I wonder what the non-pathetic people are doing tonight?" - Rajesh Koothrappali (The Big Bang Theory)

Last edited by zork : 02-02-15 at 02:54 AM.
  Reply With Quote
02-02-15, 03:18 AM   #2
Banknorris
A Chromatic Dragonspawn
 
Banknorris's Avatar
AddOn Author - Click to view addons
Join Date: Oct 2014
Posts: 153
Originally Posted by zork View Post
That is because the nameplate GUID is reset. (Because the OnHide has been triggered)
Do you really need to reset the GUID in the OnHide? Maybe you can store the timestamp of when OnHide triggered for the last time and remove GUID from hidden nameplates once every 10 min (or so) for all nameplates with a OnHide timestamp too old.

If the is a combat log event of that GUID dying then you can remove the info immediately (I guess).

Sorry if that makes no sense.

Last edited by Banknorris : 02-02-15 at 06:02 AM.
  Reply With Quote
02-02-15, 10:38 AM   #3
sticklord
A Wyrmkin Dreamwalker
AddOn Author - Click to view addons
Join Date: Aug 2014
Posts: 57
Originally Posted by Banknorris View Post
Do you really need to reset the GUID in the OnHide? Maybe you can store the timestamp of when OnHide triggered for the last time and remove GUID from hidden nameplates once every 10 min (or so) for all nameplates with a OnHide timestamp too old.

If the is a combat log event of that GUID dying then you can remove the info immediately (I guess).

Sorry if that makes no sense.
You have no guarantee that it's the same nameplate that reshows when its been hidden. Not quite sure how it works but seems like theres a pool of them and it picks a random one. So you have to reset the guid.

And on topic, yeah tht's pretty much my way around it:

Lua Code:
  1. if plate._Highlight:IsShown() then
  2.         if not plate.highlighted then
  3.             plate.highlighted = true
  4.             plate.Highlight:Show()
  5.             plate:SetGuid('mouseover') -- It's moused over, lets grab it while its hot
  6.         end
  7.     elseif plate.highlighted then
  8.         plate.highlighted = nil
  9.         plate.Highlight:Hide()
  10.     end
  11.  
  12.     if isTarget then -- A boolean for alpha > 0.95 and UnitExist('target')
  13.         if not plate.target then
  14.             plate.target = true
  15.             plate:SetGuid('target')
  16.             plate:SetFrameLevel(5)
  17.             plate.Glow:Show()
  18.         end
  19.     elseif plate.target then
  20.         plate.target = nil
  21.         plate:SetFrameLevel(0)
  22.         plate.Glow:Hide()
  23.     end

This is an OnUpdate for every nameplate though, I use it for abit more aswell.

Last edited by sticklord : 02-02-15 at 10:51 AM.
  Reply With Quote
02-04-15, 02:07 AM   #4
Oppugno
A Fallenroot Satyr
Join Date: Sep 2012
Posts: 22
My preferred method is via the use of events/script handlers as opposed to polling (via OnUpdate).

A couple of facts that have already been mentioned but I'm going to mention them again as they're important for the explanation:
  1. We know that when a nameplate belongs to the 'target' unit only that nameplate has an alpha of 1, all others have a lesser amount.
  2. Nameplate alphas don't update until a frame after they are visible and a frame after the PLAYER_TARGET_CHANGED event fires.
  3. When a nameplate is hidden it can no longer be relied upon to have the same correlation between units or GUIDs when/if re-shown.
From this you can expand out what needs to happen in response to each event (I've used your function names for ease):

NamePlateOnShow:
If you have a target and don't know the nameplate wait one frame and then check if the nameplate's alpha == 1.
NamePlateOnInit:
This is essentially a special case of OnShow as we had to wait one frame in order to find it via the main update function. The nameplate's alpha is already up to date so you check if alpha == 1 right away.
NamePlateOnHide:
Wipe any correlation you had established for this nameplate.
AuraModule:PLAYER_TARGET_CHANGED:
The target has changed. Wait one frame and then search all active nameplates for the one with an alpha == 1.

I've put together a dry coded version with the relevant sections of your code:
Lua Code:
  1. local AuraModule = CreateFrame("Frame")
  2. --[[
  3.     Your stuff here...
  4. ]]--
  5. AuraModule.hasTarget        = false -- if there is a target that could be a nameplate
  6. AuraModule.updateTarget     = false -- if the target's nameplate is known / needs to be updated
  7.  
  8. AuraModule:Hide()
  9. AuraModule:SetScript('OnUpdate', function(self, elapsed)
  10.     if self.hasTarget and self.updateTarget then -- Some (mostly) unneeded redundancy, remove if you want.
  11.         for blizzPlate in next, plates do
  12.             if blizzPlate:IsShown() then -- Note: You should probably consider removing the need for this.
  13.                 if blizzPlate:GetAlpha() == 1 then
  14.                     NamePlateSetGUID(blizzPlate,UnitGUID("target"))
  15.                     blizzPlate:ScanAuras("target","HELPFUL")
  16.                     blizzPlate:ScanAuras("target","HARMFUL")
  17.                    
  18.                     -- Stop any other nameplates from trying to update the target.
  19.                     self.updateTarget = false
  20.                     break
  21.                 end
  22.             end
  23.         end
  24.     end
  25.     self:Hide()
  26. end)
  27.  
  28. -- Some aliases for readability.
  29. AuraModule.ExecuteDelayedTargetSearch = AuraModule.Show
  30. AuraModule.PreventDelayedTargetSearch = AuraModule.Hide
  31.  
  32. function AuraModule:PLAYER_TARGET_CHANGED(...)
  33.     --[[
  34.         Your stuff here...
  35.     ]]--
  36.    
  37.     if UnitExists("target") and UnitGUID("target") and not UnitIsUnit("target","player") and not UnitIsDead("target") then
  38.         self.updateTarget = true
  39.         self.hasTarget = true
  40.         self:ExecuteDelayedTargetSearch() -- Look for the target's nameplate on the next frame.
  41.     else
  42.         self.updateTarget = false
  43.         self.hasTarget = false
  44.         self:PreventDelayedTargetSearch() -- Stop any delayed target nameplate search.
  45.     end
  46. end
  47.  
  48. local function NamePlateOnInit(blizzPlate)
  49.     --[[
  50.         Your stuff here...
  51.     ]]--
  52.  
  53.     if AuraModule.hasTarget and AuraModule.updateTarget then -- Have a target but don't know the nameplate.
  54.         -- Plate alphas are accurate when first found because we had to wait a frame to find them.
  55.         if blizzPlate:GetAlpha() == 1 then
  56.             NamePlateSetGUID(blizzPlate,UnitGUID("target"))
  57.             blizzPlate:ScanAuras("target","HELPFUL")
  58.             blizzPlate:ScanAuras("target","HARMFUL")
  59.            
  60.             -- Stop any other nameplates from trying to update the target.
  61.             AuraModule.updateTarget = false
  62.             AuraModule:PreventDelayedTargetSearch() -- Stop any delayed target nameplate search.
  63.         end
  64.     end
  65. end
  66.  
  67. local function NamePlateOnShow(blizzPlate)
  68.     --[[
  69.         Your stuff here...
  70.     ]]--
  71.    
  72.     if AuraModule.hasTarget and AuraModule.updateTarget then -- Have a target but don't know the nameplate.
  73.         -- Plate alphas are updated correctly a frame AFTER being reshown.
  74.         AuraModule:ExecuteDelayedTargetSearch() -- Look for the target's nameplate on the next frame.
  75.     end
  76. end
  77.  
  78. local function NamePlateOnHide(blizzPlate)
  79.     --[[
  80.         Your stuff here...
  81.     ]]--
  82. end

Note that this example issues a complete delayed search in NamePlateOnShow instead of targeted check on the current nameplate. This dry code doesn't have the functionality to efficiently handle checking a subset of nameplates. If you did it this way I'd suggest additional functionality that adds all nameplates re-shown on a given frame to a special list which is checked by a separate delayed search function. Even if you don't implement this particular functionality it is still more practically efficient this way as you currently check all active nameplate each frame. In the worst possible case to reach the same O(n) you would have to be finding a new nameplate each frame or changing targets every frame.

Keen minds will also realise that if you run a delayed search and a frame after some nameplates are re-shown that they would have non-updated alphas and break the search. I've found that I could never get the nameplate's OnShow scripts to fire prior to the search frame's OnUpdate unless I intentionally delayed it. In the event that you do manage to have them show before the search's OnUpdate fires just delay their addition to the list of active nameplates by one frame.

P.S. Not that it really matters but isn't this in the wrong sub-forum (I'd expect General Authoring Discussion as opposed to Lua/XML Help)?
  Reply With Quote
02-04-15, 02:38 AM   #5
zork
A Pyroguard Emberseer
 
zork's Avatar
AddOn Author - Click to view addons
Join Date: Jul 2008
Posts: 1,740
I tested my idea yesterday.
https://code.google.com/p/rothui/sou...s.lua&old=1361
It works perfectly.

@Oppugno
You need the OnUpdate anyway to scan for nameplates. I use that single OnUpdate script for everything.

First I do WorldFrame scans until I find the first evidence of a nameplate and thus the current nameplate index. That index increases on each /reload. After that I just check if _G["NamePlate"..nextIndex] exists. If it does I skin it.

Funny that you found out about the 1frame delay of alpha states aswell.

The AuraModule inside the OnUpdate is event driven. Thus the conditions will not trigger without a leading event. The only exception is the nameplate scan if I have a target and that nameplate has no GUID. After a delay of 1 frame I can be sure that this nameplate is matching the target.

The only part that I really don't like atm is the mixin of local and object functions. Currently each nameplate gets a set of functions. I could just make a single function and pass the nameplate as a parameter.
__________________
| Simple is beautiful.
| WoWI AddOns | GitHub | Zork (WoW)

"I wonder what the non-pathetic people are doing tonight?" - Rajesh Koothrappali (The Big Bang Theory)

Last edited by zork : 02-04-15 at 02:56 AM.
  Reply With Quote
02-04-15, 05:56 AM   #6
Oppugno
A Fallenroot Satyr
Join Date: Sep 2012
Posts: 22
I'm not saying to remove the OnUpdate, that's definently needed for the core. I was just saying move unneeded stuff out of it. For instance, to make my core match yours this would be my entire core (additions, removals):

Code:
--[[------------------------------------
--            Update Core             --
------------------------------------]]--
-- Upvalues
local select = select
local WorldFrame = WorldFrame
local _G = _G

-- Constants
local NAMEPLATE_NAME = 'NamePlate'
local NAMEPLATE_PATTERN = '^'..NAMEPLATE_NAME..'%d+$'

local nameplateIndex = nil

local PreviouslySeenFrames = {}
function Driver:SearchForNameplates(...)
	for i = 1, select("#", ...) do
		local frame = select(i, ...)
		if not PreviouslySeenFrames[frame] then -- Haven't seen the frame before.
			PreviouslySeenFrames[frame] = true
			
			local name = frame:GetName()
			if name and name:find(NAMEPLATE_PATTERN) then -- Is a nameplate
				nameplateIndex = tonumber((string.gsub(name, NAMEPLATE_NAME, '')))
				self:LookUpNameplates()
				
				-- Free up no longer needed table.
				PreviouslySeenFrames = nil
				break
			end
		end
	end
end

function Driver:LookUpNameplates()
	-- This string concatenation could/does happen every frame.
	-- IDEA: Cache it in addition to the nameplateIndex
	local nameplate = _G[NAMEPLATE_NAME..nameplateIndex]
	while nameplate do
		Nameplate.Initialise(nameplate)

		nameplateIndex = nameplateIndex + 1
		nameplate = _G[NAMEPLATE_NAME..nameplateIndex]
	end
end

local WorldFrame_NumChildren = 0
Driver:SetScript('OnUpdate', function(self, elapsed)
	-- Find any new nameplates
	if nameplateIndex then
		self:LookUpNameplates()
	else
		local numChildren = WorldFrame:GetNumChildren()
		if numChildren ~= WorldFrame_NumChildren then
			--Scan for nameplates
			self:SearchForNameplates(WorldFrame:GetChildren())
			
			WorldFrame_NumChildren = numChildren
		end
	end

	-- Update alphas of all active nameplates
	for nameplate, oldNameplate in pairs(ActiveNameplates) do
		nameplate:SetAlpha(oldNameplate:GetAlpha())
	end


	timer = timer + elapsed
	
	if timer <= interval then -- reversed the condition as this is going to be true more often
		for blizzPlate, newPlate in next, plates do
			if blizzPlate:GetAlpha() == 1 then
				newPlate:SetAlpha(1)
			else
				newPlate:SetAlpha(cfg.notFocusedPlateAlpha)
			end
		end
	else -- timer > interval
		-- Yes, this for block has to be duplicated but it's stupidly more efficient 
		-- than before without a million pipeline stalls from the failed ifs.
		for blizzPlate, newPlate in next, plates do
			if blizzPlate:GetAlpha() == 1 then
				newPlate:SetAlpha(1)
			else
				newPlate:SetAlpha(cfg.notFocusedPlateAlpha)
			end
			
			NamePlateHealthBarColor(blizzPlate)
			blizzPlate:UpdateAllAuras()
		end
		
		timer = 0
	end
end)
All Target, Mouseover and RaidIcon nameplates are identified by event handlers that don't use OnUpdate. As a side bonus of this you could also seperate that additional nameplate logic from the core OnUpdate into each nameplate's OnUpdate to fit your object orientated approach.

Miss-communications cleared up (hopefully), I'm glad your approach worked for you.

P.S. Keep up the good work. I appreciated the insights you shared about the moving of shown nameplates and the use of indexing instead of parsing WorldFrame's children.
  Reply With Quote

WoWInterface » Developer Discussions » Lua/XML Help » Best way of updating the target nameplate?


Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

vB code is On
Smilies are On
[IMG] code is On
HTML code is Off