Quantcast
Lua Error Help with LiteStats and OrderHall Page - WoWInterface
 
 
Thread Tools Display Modes
Prev Previous Post   Next Post Next
01-19-17, 11:32 PM   #1
badness
A Cliff Giant
 
badness's Avatar
Join Date: May 2010
Posts: 74
Lua Error Help with LiteStats and OrderHall Page

Hey guys, I'm getting couple errors with my litestats addon and the orderhall mission page and was wondering if you could help me fix them

LiteStats: This error occurs when I moveover the coordinate module while inside any dungeon

Error:
Lua Code:
  1. Message: Interface\AddOns\LiteStats\core.lua:116: attempt to perform arithmetic on upvalue 'coordX' (a nil value)
  2. Time: 01/20/17 00:28:30
  3. Count: 78
  4. Stack: Interface\AddOns\LiteStats\core.lua:116: in function <Interface\AddOns\LiteStats\core.lua:116>
  5. Interface\AddOns\LiteStats\core.lua:659: in function <Interface\AddOns\LiteStats\core.lua:654>
  6.  
  7. Locals: (*temporary) = <function> defined =[C]:-1
  8. (*temporary) = "%d,%d"
  9. (*temporary) = nil
  10. (*temporary) = nil
  11. (*temporary) = "attempt to perform arithmetic on upvalue 'coordX' (a nil value)"
  12. format = <function> defined =[C]:-1
  13. coords = <table> {
  14.  enabled = false
  15.  anchor_to = "top"
  16.  y_off = -10
  17.  x_off = 0
  18.  anchor_frame = "UIParent"
  19.  fmt = "%d,%d"
  20.  anchor_from = "top"
  21. }
  22. coordX = nil
  23. coordY = nil

Code:
Lua Code:
  1. local P = "player" -- Because I'm tired of typing it.
  2. local realm, char, class, layout = GetRealmName(), UnitName(P), select(2, UnitClass(P)), {}
  3.  
  4. -- Tooltip text colors
  5. local tthead = {r=0.40, g=0.78, b=1.00} -- Headers
  6. local ttsubh = {r=0.75, g=0.90, b=1.00} -- Subheaders
  7.  
  8. -- Strata/Level for text objects
  9. local strata, level = "MEDIUM", 99
  10.  
  11. -- Globals
  12. local profiles = LPSTAT_PROFILES
  13. local font = LPSTAT_FONT
  14. local t_icon = LTIPICONSIZE or 20
  15. local allcombat = HIDE_IN_COMBAT
  16. local IsAltKeyDown = IsAltKeyDown
  17. local UpdateMemUse = UpdateAddOnMemoryUsage
  18. local format = string.format
  19. local strmatch = string.match
  20. local strfind = string.find
  21. local strtrim = strtrim
  22. local unpack = unpack
  23. local pairs = pairs
  24. local ipairs = ipairs
  25. local floor = math.floor
  26. local select = select
  27. local max = max
  28. local gsub = gsub
  29.  
  30. -- Config
  31. local modules = LPSTAT_CONFIG
  32.  
  33. local fps = modules.FPS
  34. local latency = modules.Latency
  35. local mail = modules.Mail
  36. local memory = modules.Memory
  37. local durability = modules.Durability
  38. local gold = modules.Gold
  39. local clock = modules.Clock
  40. local location = modules.Location
  41. local coords = modules.Coords
  42. local ping = modules.Ping
  43. local dps = modules.DPS
  44. local guild = modules.Guild
  45. local friends = modules.Friends
  46. local bags = modules.Bags
  47. local talents = modules.Talents
  48. local stats = modules.Stats
  49. local experience = modules.Experience
  50.  
  51. -- Locale
  52. local locale = LSTLOCALE or {}
  53. local function L(str) return locale[str] or str end
  54.  
  55. -- Lazy Events Reg
  56. local function RegEvents(f,l) for _,e in ipairs{strsplit(" ",l)} do f:RegisterEvent(e) end end
  57.  
  58. ------------------------------------------
  59. -- Saved Vars Init / Coords
  60. local ls, coordX, coordY, conf, Coords = CreateFrame'frame', 0, 0, {}
  61. RegEvents(ls,"ADDON_LOADED PLAYER_REGEN_DISABLED PLAYER_REGEN_ENABLED")
  62. ls:SetScript("OnEvent", function(_,event,addon)
  63.     if event == "ADDON_LOADED" and addon == "LiteStats" then
  64.         if not modules then
  65.             -- Missing config, print an error message.
  66.             print(format("|cffFFFFFFLite|cff44CCFFStats|cffFFFFFF: "..L"Copy %s to %s and restart.","|cffFF9912config_default.lua|r","|cffFF9912config.lua|r"))
  67.             return
  68.         end
  69.         if not LPSTAT then LPSTAT = {} end
  70.         if not LPSTAT[realm] then LPSTAT[realm] = {} end
  71.         if not LPSTAT[realm][char] then LPSTAT[realm][char] = {} end
  72.         conf = LPSTAT[realm][char]
  73.        
  74.         -- Migrating older saved vars, pre-0.9.8
  75.         for charstr,config in pairs(LPSTAT) do
  76.             if strmatch(charstr," %- ") then
  77.                 local char, realm = strmatch(charstr,"(.-) %- (.*)")
  78.                 if not LPSTAT[realm] then LPSTAT[realm] = {} end
  79.                 conf = config
  80.                 LPSTAT[charstr] = nil
  81.             end
  82.         end
  83.         -- true/false defaults for autosell and autorepair
  84.         if conf.AutoSell == nil then conf.AutoSell = true end
  85.         if conf.AutoRepair == nil then conf.AutoRepair = false end
  86.     end
  87.     if event == "ZONE_CHANGED_NEW_AREA" and not WorldMapFrame:IsShown() then
  88.         SetMapToCurrentZone()
  89.     end
  90.     -- Combat fading
  91.     if event == "PLAYER_REGEN_DISABLED" or event == "PLAYER_REGEN_ENABLED" then
  92.         for n,t in pairs(modules) do
  93.             if t.incombat or (allcombat and t.incombat ~= false) then
  94.                 if event == "PLAYER_REGEN_DISABLED" then UIFrameFadeOut(_G['LP_'..n].text,0.5,font.alpha or 1,0)
  95.                 else UIFrameFadeIn(_G['LP_'..n].text,0.5,0,font.alpha or 1) end
  96.             end
  97.         end
  98.     end
  99. end)
  100.  
  101. -- Config missing?
  102. if not modules then return end
  103.  
  104. if modules and ((coords and coords.enabled) or (location and location.enabled)) then
  105.     ls:RegisterEvent'ZONE_CHANGED_NEW_AREA'
  106.     ls:SetScript("OnUpdate", function() coordX, coordY = GetPlayerMapPosition(P) end)
  107.     WorldMapFrame:HookScript("OnHide", SetMapToCurrentZone)
  108.     function Coords() return format(coords and coords.fmt or "%d,%d",coordX*100, coordY*100) end
  109. end
  110.  
  111. -- Set profile
  112. if profiles then for _,p in ipairs{class,format("%s - %s",char,realm)} do
  113.     if profiles[p] then for k,v in pairs(profiles[p]) do
  114.         for _k,_v in pairs(v) do modules[k][_k] = _v end
  115.     end end
  116. end profiles = nil end
  117.  
  118.  
  119. ------------------------------------------
  120. local function zsub(s,...) local t={...} for i=1,#t,2 do s=gsub(s,t[i],t[i+1]) end return s end
  121.  
  122. local function formatgold(style, amount)
  123.     local gold, silver, copper = floor(amount * 0.0001), floor(mod(amount * 0.01, 100)), floor(mod(amount, 100))
  124.     if style == 1 then
  125.         return (gold > 0 and format("%s|cffffd700%s|r ",gold,GOLD_AMOUNT_SYMBOL) or "")
  126.             .. (silver > 0 and format("%s|cffc7c7cf%s|r ",silver,SILVER_AMOUNT_SYMBOL) or "")
  127.             .. ((copper > 0 or (gold == 0 and silver == 0)) and format("%s|cffeda55f%s|r",copper,COPPER_AMOUNT_SYMBOL) or "")
  128.     elseif style == 2 or not style then
  129.         return format("%.1f|cffffd700%s|r", amount * 0.0001, GOLD_AMOUNT_SYMBOL)
  130.     elseif style == 3 then
  131.         return format("|cffffd700%s|r.|cffc7c7cf%s|r.|cffeda55f%s|r", gold, silver, copper)
  132.     elseif style == 4 then
  133.         return (gold > 0 and format(GOLD_AMOUNT_TEXTURE,gold,12,12) or "") .. (silver > 0 and format(SILVER_AMOUNT_TEXTURE,silver,12,12) or "")
  134.             .. ((copper > 0 or (gold == 0 and silver == 0)) and format(COPPER_AMOUNT_TEXTURE,copper,12,12) or "") .. " "
  135.     end
  136. end
  137.  
  138. local function abbr(t,s) return t[s] or zsub(_G[strupper(s).."_ONELETTER_ABBR"],"%%d","","^%s*","") end
  139. local function fmttime(sec,t)
  140.     local t = t or {}
  141.     local d,h,m,s = ChatFrame_TimeBreakDown(floor(sec))
  142.     local string = zsub(format(" %dd %dh %dm "..((d==0 and h==0) and "%ds" or ""),d,h,m,s)," 0[dhms]"," ","%s+"," ")
  143.     string = strtrim(gsub(string,"([dhms])",{d=abbr(t,"day"),h=abbr(t,"hour"),m=abbr(t,"minute"),s=abbr(t,"second")})," ")
  144.     return strmatch(string,"^%s*$") and "0"..abbr(t,"second") or string
  145. end
  146.  
  147. function gradient(perc)
  148.     perc = perc > 1 and 1 or perc < 0 and 0 or perc -- Stay between 0-1
  149.     local seg, relperc = math.modf(perc*2)
  150.     local r1,g1,b1,r2,g2,b2 = select(seg*3+1,1,0,0,1,1,0,0,1,0,0,0,0) -- R -> Y -> G
  151.     local r,g,b = r1+(r2-r1)*relperc,g1+(g2-g1)*relperc,b1+(b2-b1)*relperc
  152.     return format("|cff%02x%02x%02x",r*255,g*255,b*255),r,g,b
  153. end
  154.                    
  155. local function HideTT(self) GameTooltip:Hide() self.hovered = false end
  156.  
  157. local pxpx = {height=1, width=1}
  158. local function Inject(name, stat)
  159.     if not name then return end
  160.     if not stat then stat = pxpx end
  161.    
  162.     local m = modules[name]
  163.     for k,v in pairs{ -- retrieving config variables from LPSTAT_CONFIG
  164.         name = name, anchor_frame = m.anchor_frame,
  165.         anchor_to = m.anchor_to, anchor_from = m.anchor_from,
  166.         x_off = m.x_off, y_off = m.y_off,
  167.         height = m.height, width = m.width,
  168.         strata = strata, level = level
  169.     } do if not stat[k] then stat[k] = v end end
  170.     if not stat.text then stat.text = {} end
  171.    
  172.     -- retrieve font variables and insert them into text table
  173.     for k,v in pairs(font) do
  174.         if not stat.text[k] then
  175.             stat.text[k] = m[k] or v
  176.         end
  177.     end
  178.  
  179.     if stat.OnEnter then if stat.OnLeave then hooksecurefunc(stat,"OnLeave",HideTT) else stat.OnLeave = HideTT end end
  180.     tinsert(layout, stat)
  181. end
  182.  
  183. -- Inject dummy frames for disabled modules
  184. for name, conf in pairs(modules) do
  185.     if not conf.enabled then Inject(name) end
  186. end
  187.  
  188.  
  189.  
  190. SLASH_LSTATS1, SLASH_LSTATS2, SLASH_LSTATS3 = "/ls", "/lstats", "/litestats"
  191. local function slprint(...)
  192.     local m, l = "|cffbcee68", "|cffff9912 -|r"
  193.     local t = {...} print(m,t[1])
  194.     for i = 2, #t do print(l,t[i]) end
  195. end
  196. function SlashCmdList.LSTATS()
  197.     print("|cffffffffLite|cff66C6FFStats|cffffffff "..L"tips"..":")
  198.     if memory.enabled then
  199.         slprint(L"Memory",
  200.             L"Right-Click collects Lua garbage.")
  201.     end if gold.enabled then
  202.         slprint(strtrim(gsub(GOLD_AMOUNT,"%%d","")),
  203.             L"Left-Click opens currency tab.",
  204.             L"Right-Click toggles AutoSelling.",
  205.             L"Use /junk to configure which items not to sell.",
  206.             L"Watched currency tab items will reflect onto the tooltip.")
  207.     end if durability.enabled then
  208.         slprint(DURABILITY,
  209.             L"Left-Click opens character tab.",
  210.             L"Right-Click toggles AutoRepairing.",
  211.             L"Shift-Click or Middle-Click for equipment set changer.")
  212.     end if location.enabled or coords.enabled then
  213.         slprint(L"Location/Coords",
  214.             L"Clicking opens world map.",
  215.             L"Shift-Clicking location or coords module inserts your coords into chat.")
  216.     end if clock.enabled then
  217.         slprint(TIMEMANAGER_TITLE,
  218.             L"Left-Click opens calendar (/cal).",
  219.             L"Right-Click opens time manager frame.",
  220.             L"Local/realm & 24hr time can be toggled from the time manager.")
  221.     end if friends.enabled or guild.enabled then
  222.         slprint(format("%s/%s",FRIENDS,GUILD),
  223.             L"Hold alt key to view ranks, notes and officer notes.",
  224.             L"(Guild) Right-Click to change the sorting, shift-right-click to reverse order.")
  225.     end if talents.enabled then
  226.         slprint(TALENTS,
  227.             L"Left-Click opens the talent UI frame.",
  228.             L"Right-Click toggles your dual specs.")
  229.     end if experience.enabled then
  230.         slprint(format("%s/%s/%s",COMBAT_XP_GAIN,TIME_PLAYED_MSG,FACTION),
  231.             L"Right-Click to cycle through experience, time played, and faction watcher.",
  232.             L"Watch factions from the character faction UI.")
  233.     end
  234.     print("|cffBCEE68",format(L"Other options may be configured in %s","|cff66C6FFLiteStats\\config.lua"))
  235. end
  236.  
  237. CreateFrame("Frame", "LSMenus", UIParent, "UIDropDownMenuTemplate")
  238.  
  239. ------------------------------------------
  240. --  FPS
  241. if fps.enabled then
  242.     Inject("FPS", { height = 12,
  243.         text = { string = function() return format(fps.fmt, floor(GetFramerate())) end }
  244.     })
  245. end
  246. ------------------------------------------
  247. --  Latency
  248. if latency.enabled then
  249.     Inject("Latency", { height = 12,
  250.         text = {
  251.             string = function()
  252.                 local _,_,home,world = GetNetStats()
  253.                 local lat = math.max(home, world)
  254.                 return format(gsub(latency.fmt, "%[color%]", (gradient(1-lat/750))),lat)
  255.             end
  256.         },
  257.         OnEnter = function(self)
  258.             local _,_,home,world = GetNetStats();
  259.             GameTooltip:SetOwner(self, latency.tip_anchor or "ANCHOR_BOTTOMLEFT", latency.tip_x or 0, latency.tip_y or 0)
  260.             GameTooltip:ClearLines()
  261.             GameTooltip:AddLine(zsub(MAINMENUBAR_LATENCY_LABEL,"\n.*","",":",""), tthead.r, tthead.g, tthead.b)
  262.             GameTooltip:AddDoubleLine(CHANNEL_CATEGORY_WORLD, gradient(1-world/750)..world, ttsubh.r, ttsubh.g, ttsubh.b, 1, 1, 1)
  263.             GameTooltip:AddDoubleLine(HOME, gradient(1-home/750)..home, ttsubh.r, ttsubh.g, ttsubh.b, 1, 1, 1)
  264.             GameTooltip:Show()
  265.         end,
  266.     })
  267. end
  268. ------------------------------------------
  269. --  Mail
  270. if mail.enabled then
  271.     MiniMapMailFrame.Show = MiniMapMailFrame.Hide
  272.     Inject("Mail", {
  273.         text = { string = function() return mail[HasNewMail() and "newmail" or "nomail"] end },
  274.         OnEnter = function(self)
  275.             if not HasNewMail() then return end
  276.             GameTooltip:SetOwner(self, mail.tip_anchor, mail.tip_x, mail.tip_y)
  277.             MinimapMailFrameUpdate()
  278.             GameTooltip:Show()
  279.         end
  280.     })
  281. end
  282. ------------------------------------------
  283. --  Memory
  284. if memory.enabled then
  285.     local function sortdesc(a, b) return a[2] > b[2] end   
  286.     local function formatmem(val,dec)
  287.         return format(format("%%.%df %s",dec or 1,val > 1024 and "MB" or "KB"),val/(val > 1024 and 1024 or 1))
  288.     end
  289.     local memoryt = {}
  290.     Inject("Memory", { height = 12,
  291.         text = {
  292.             string = function(self)
  293.                 self.total = 0
  294.                 UpdateMemUse()
  295.                 local parent = self:GetParent()
  296.                 for i = 1, GetNumAddOns() do self.total = self.total + GetAddOnMemoryUsage(i) end
  297.                 if parent.hovered then self:GetParent():GetScript("OnEnter")(parent) end
  298.                 return self.total >= 1024 and format(memory.fmt_mb, self.total / 1024) or format(memory.fmt_kb, self.total)
  299.             end, update = 5,
  300.         },
  301.         OnEnter = function(self)
  302.             self.hovered = true
  303.             GameTooltip:SetOwner(self, memory.tip_anchor, memory.tip_x, memory.tip_y)
  304.             GameTooltip:ClearLines()
  305.             local _,_,home,world = GetNetStats()
  306.             local lat, r = math.max(home,world), 750
  307.             GameTooltip:AddDoubleLine(
  308.                 format("|cffffffff%s|r %s, %s%s|r %s",floor(GetFramerate()),FPS_ABBR,gradient(1-lat/r),lat,MILLISECONDS_ABBR),
  309.                 format("%s: |cffffffff%s",ADDONS,formatmem(self.text.total)),
  310.                 tthead.r,tthead.g,tthead.b,tthead.r,tthead.g,tthead.b)
  311.             GameTooltip:AddLine' '
  312.             if memory.max_addons ~= 0 or IsAltKeyDown() then
  313.                 if not self.timer or self.timer + 5 < time() then
  314.                     self.timer = time()
  315.                     UpdateMemUse()
  316.                     for i = 1, #memoryt do memoryt[i] = nil end
  317.                     for i = 1, GetNumAddOns() do
  318.                         local addon, name = GetAddOnInfo(i)
  319.                         if IsAddOnLoaded(i) then tinsert(memoryt,{name or addon, GetAddOnMemoryUsage(i)}) end
  320.                     end
  321.                     table.sort(memoryt, sortdesc)
  322.                 end
  323.                 local exmem = 0
  324.                 for i,t in ipairs(memoryt) do
  325.                     if memory.max_addons and i > memory.max_addons and not IsAltKeyDown() then
  326.                         exmem = exmem + t[2]
  327.                     else
  328.                         local color = t[2] <= 102.4 and {0,1} -- 0 - 100
  329.                             or t[2] <= 512 and {0.75,1} -- 100 - 512
  330.                             or t[2] <= 1024 and {1,1} -- 512 - 1mb
  331.                             or t[2] <= 2560 and {1,0.75} -- 1mb - 2.5mb
  332.                             or t[2] <= 5120 and {1,0.5} -- 2.5mb - 5mb
  333.                             or {1,0.1} -- 5mb +
  334.                         GameTooltip:AddDoubleLine(t[1],formatmem(t[2]),1,1,1,color[1],color[2],0)
  335.                     end
  336.                 end
  337.                 if exmem > 0 and not IsAltKeyDown() then
  338.                     local more = #memoryt - memory.max_addons
  339.                     GameTooltip:AddDoubleLine(format("%d %s (%s)",more,L"Hidden",L"ALT"),formatmem(exmem),ttsubh.r,ttsubh.g,ttsubh.b,ttsubh.r,ttsubh.g,ttsubh.b)
  340.                 end
  341.                 GameTooltip:AddDoubleLine(" ","--------------",1,1,1,0.5,0.5,0.5)
  342.             end
  343.             GameTooltip:AddDoubleLine(L"Default UI Memory Usage"..":",formatmem(gcinfo() - self.text.total),ttsubh.r,ttsubh.g,ttsubh.b,1,1,1)
  344.             GameTooltip:AddDoubleLine(L"Total Memory Usage"..":",formatmem(collectgarbage'count'),ttsubh.r,ttsubh.g,ttsubh.b,1,1,1)
  345.             GameTooltip:Show()
  346.         end,
  347.         OnUpdate = AltUpdate,
  348.         OnLeave = function(self) self.hovered = false end,
  349.         OnClick = function(self, button)
  350.             if button == "RightButton" then
  351.                 UpdateMemUse()
  352.                 local before = gcinfo()
  353.                 collectgarbage()
  354.                 UpdateMemUse()
  355.                 print(format("|cff66C6FF%s:|r %s",L"Garbage collected",formatmem(before - gcinfo())))
  356.                 self.timer, self.text.elapsed = nil, 5
  357.                 self:GetScript("OnEnter")(self)
  358.             end
  359.         end
  360.     })
  361. end
  362. ------------------------------------------
  363. --  Durability
  364. if durability.enabled then
  365.     Inject("Durability", {
  366.         OnLoad = function(self)
  367.             CreateFrame("GameTooltip", "LPDURA")
  368.             LPDURA:SetOwner(WorldFrame,"ANCHOR_NONE")
  369.             if durability.man then DurabilityFrame.Show = DurabilityFrame.Hide end
  370.             RegEvents(self,"UPDATE_INVENTORY_DURABILITY MERCHANT_SHOW PLAYER_LOGIN")
  371.         end,
  372.         OnEvent = function(self, event, ...)
  373.             if event == "UPDATE_INVENTORY_DURABILITY" or event == "PLAYER_LOGIN" then
  374.                 local dmin = 100
  375.                 for id = 1, 18 do
  376.                     local dur, dmax = GetInventoryItemDurability(id)
  377.                     if dur ~= dmax then dmin = floor(min(dmin,dur/dmax*100)) end
  378.                 end
  379.                 self.text:SetText(format(gsub(durability.fmt,"%[color%]",(gradient(dmin/100))), dmin))
  380.             elseif event == "MERCHANT_SHOW" and not IsAltKeyDown() then
  381.                 if conf.AutoRepair and CanMerchantRepair() then
  382.                     local cost, total = GetRepairAllCost(), 0
  383.                     if cost > 0 then
  384.                         if durability.gfunds and CanGuildBankRepair() then RepairAllItems(1) total = cost end
  385.                         if GetRepairAllCost() > 0 then
  386.                             if not durability.ignore_inventory and GetRepairAllCost() <= GetMoney() then
  387.                                 total = GetRepairAllCost(); RepairAllItems()
  388.                             else
  389.                                 for id = 1, 18 do
  390.                                     local cost = select(3,LPDURA:SetInventoryItem(P,id))
  391.                                     if cost ~= 0 and cost <= GetMoney() then
  392.                                         if not InRepairMode() then ShowRepairCursor() end
  393.                                         PickupInventoryItem(id)
  394.                                         total = total + cost
  395.                                     end
  396.                                 end
  397.                             end
  398.                             HideRepairCursor()
  399.                         end
  400.                         if total > 0 then print(format("|cff66C6FF%s |cffFFFFFF%s",REPAIR_COST,formatgold(1, total))) end
  401.                     end
  402.                 end
  403.             end
  404.         end,
  405.         OnEnter = function(self)
  406.             GameTooltip:SetOwner(self, durability.tip_anchor, durability.tip_x, durability.tip_y)
  407.             GameTooltip:ClearLines()
  408.             GameTooltip:AddDoubleLine(DURABILITY,format(ITEM_LEVEL,GetAverageItemLevel()),tthead.r,tthead.g,tthead.b,tthead.r,tthead.g,tthead.b)
  409.             GameTooltip:AddLine' '
  410.             local nodur, totalcost = true, 0
  411.             for slot, string in gmatch("1HEAD3SHOULDER5CHEST6WAIST7LEGS8FEET9WRIST10HANDS16MAINHAND17SECONDARYHAND18RANGED","(%d+)([^%d]+)") do
  412.                 local dur, dmax = GetInventoryItemDurability(slot)
  413.                 local string = _G[string.."SLOT"]
  414.                 if dur ~= dmax then
  415.                     local perc = dur ~= 0 and dur/dmax or 0
  416.                     local hex = gradient(perc)
  417.                     GameTooltip:AddDoubleLine(durability.gear_icons and format("|T%s:%d|t %s",GetInventoryItemTexture(P,slot),t_icon,string) or string,format("|cffaaaaaa%s/%s | %s%s%%",dur,dmax,hex,floor(perc*100)),1,1,1)
  418.                     totalcost, nodur = totalcost + select(3,LPDURA:SetInventoryItem(P,slot))
  419.                 end
  420.             end
  421.             if nodur then
  422.                 GameTooltip:AddLine("100%",0.1,1,0.1)
  423.             else
  424.                 GameTooltip:AddDoubleLine(" ","--------------",1,1,1,0.5,0.5,0.5)
  425.                 GameTooltip:AddDoubleLine(REPAIR_COST, formatgold(1, totalcost),ttsubh.r,ttsubh.g,ttsubh.b,1,1,1)  
  426.             end
  427.             GameTooltip:AddLine' '
  428.             GameTooltip:AddDoubleLine(" ",L"AutoRepair"..": "..(conf.AutoRepair and "|cff55ff55"..L"ON" or "|cffff5555"..strupper(OFF)),1,1,1,ttsubh.r,ttsubh.g,ttsubh.b)
  429.             GameTooltip:Show()
  430.         end,
  431.         OnClick = function(self, button)
  432.             if button == "RightButton" then
  433.                 conf.AutoRepair = not conf.AutoRepair
  434.                 self:GetScript("OnEnter")(self)
  435.             elseif GetNumEquipmentSets() > 0 and ((button == "LeftButton" and IsShiftKeyDown()) or button == "MiddleButton") then
  436.                 local menulist = {{ isTitle=true, text=format(gsub(EQUIPMENT_SETS,":",""),"") }}
  437.                 if GetNumEquipmentSets() == 0 then
  438.                     tinsert(menulist, {text = NONE, disabled = true})
  439.                 else
  440.                     for i = 1, GetNumEquipmentSets() do
  441.                         local name, icon = GetEquipmentSetInfo(i)
  442.                         tinsert(menulist, {text = format("|T%s:%s|t %s",icon,t_icon+5,name), func = function() UseEquipmentSet(name) end})
  443.                     end
  444.                 end
  445.                 EasyMenu(menulist, LSMenus, "cursor", 0, 0, "MENU")
  446.             elseif button == "LeftButton" then
  447.                 ToggleCharacter'PaperDollFrame'
  448.             end
  449.         end
  450.     })
  451. end
  452. ------------------------------------------
  453. --  Gold
  454. if gold.enabled then
  455.     Inject("Gold", {
  456.         OnLoad = function(self)
  457.             self.started = GetMoney()
  458.             RegEvents(self,"PLAYER_LOGIN PLAYER_MONEY MERCHANT_SHOW")
  459.             if not LPSTAT.JunkIgnore then LPSTAT.JunkIgnore = {} end
  460.         end,
  461.         OnEvent = function(self, event)
  462.             conf.Gold = GetMoney()
  463.             if event == "MERCHANT_SHOW" then
  464.                 if conf.AutoSell and not IsAltKeyDown() then
  465.                     local profit = 0
  466.                     for bag = 0, NUM_BAG_SLOTS do for slot = 0, GetContainerNumSlots(bag) do
  467.                         local link = GetContainerItemLink(bag, slot)
  468.                         if link then
  469.                             local itemstring, ignore = strmatch(link,"|Hitem:(%d-):"), false
  470.                             for _, exception in pairs(LPSTAT.JunkIgnore) do
  471.                                 if exception == itemstring then ignore = true; break end
  472.                             end
  473.                             if select(3, GetItemInfo(link)) == 0 and not ignore then
  474.                                 profit = profit + select(11, GetItemInfo(link)) * select(2, GetContainerItemInfo(bag, slot))
  475.                                 UseContainerItem(bag, slot)
  476.                             end
  477.                         end
  478.                     end end
  479.                     if profit > 0 then print(format("|cff66C6FF%s: |cffFFFFFF%s",L"Junk profit",formatgold(1, profit))) end
  480.                 end
  481.                 return
  482.             end
  483.             self.text:SetText(formatgold(gold.style, conf.Gold))
  484.         end,
  485.         OnEnter = function(self)
  486.             local curgold = GetMoney()
  487.             conf.Gold = curgold
  488.             GameTooltip:SetOwner(self, gold.tip_anchor, gold.tip_x, gold.tip_y)
  489.             GameTooltip:ClearLines()
  490.             GameTooltip:AddLine(CURRENCY,tthead.r,tthead.g,tthead.b)
  491.             GameTooltip:AddLine' '
  492.             if self.started ~= curgold then
  493.                 local gained = curgold > self.started
  494.                 local color = gained and "|cff55ff55" or "|cffff5555"
  495.                 GameTooltip:AddDoubleLine(L"Session Gain/Loss", format("%s$|r %s %s$|r",color,formatgold(1, abs(self.started - curgold)),color),1,1,1,1,1,1)
  496.                 GameTooltip:AddLine' '
  497.             end
  498.             GameTooltip:AddLine(L"Server Gold",ttsubh.r,ttsubh.g,ttsubh.b)
  499.             local total = 0
  500.             for char, conf in pairs(LPSTAT[realm]) do
  501.                 if conf.Gold and conf.Gold > 99 then
  502.                     GameTooltip:AddDoubleLine(char, formatgold(1, conf.Gold),1,1,1,1,1,1)
  503.                     total = total + conf.Gold
  504.                 end
  505.             end
  506.             GameTooltip:AddDoubleLine(" ","-----------------",1,1,1,0.5,0.5,0.5)
  507.             GameTooltip:AddDoubleLine(L"Total", formatgold(1, total),ttsubh.r,ttsubh.g,ttsubh.b,1,1,1)
  508.             GameTooltip:AddLine' '
  509.            
  510.             local currencies = 0
  511.             for i = 1, GetCurrencyListSize() do
  512.                 local name,_,_,_,watched,count,icon = GetCurrencyListInfo(i)
  513.                 if watched then
  514.                     if currencies == 0 then GameTooltip:AddLine(format("%s %s",PLAYER,CURRENCY),ttsubh.r,ttsubh.g,ttsubh.b) end
  515.                     local r,g,b
  516.                     if count > 0 then r,g,b = 1,1,1 else r,g,b = 0.5,0.5,0.5 end
  517.                     GameTooltip:AddDoubleLine(name, format("%d |T%s:%d|t",count,icon,t_icon),r,g,b,r,g,b)
  518.                     currencies = currencies + 1
  519.                 end
  520.             end
  521.             if currencies > 0 then GameTooltip:AddLine' ' end
  522.             GameTooltip:AddDoubleLine(" ",L"AutoSell junk"..": "..(conf.AutoSell and "|cff55ff55"..L"ON" or "|cffff5555"..strupper(OFF)),1,1,1,ttsubh.r,ttsubh.g,ttsubh.b)
  523.             GameTooltip:Show()
  524.         end,
  525.         OnClick = function(self, button)
  526.             if button == "LeftButton" then
  527.                 ToggleCharacter'TokenFrame'
  528.             elseif button == "RightButton" then
  529.                 conf.AutoSell = not conf.AutoSell              
  530.                 self:GetScript("OnEnter")(self)            
  531.             end
  532.         end
  533.     })
  534.     SLASH_KJUNK1 = "/junk"
  535.     function SlashCmdList.KJUNK(s)
  536.         local action = strsplit(" ",s)
  537.         if action == "list" then
  538.             print(format("|cff66C6FF%s:|r %s",L"Junk exceptions",(#LPSTAT.JunkIgnore == 0 and NONE or "")))
  539.             for i, id in pairs(LPSTAT.JunkIgnore) do
  540.                 local link = select(2, GetItemInfo(id))
  541.                 print("- ["..i.."]",link)
  542.             end
  543.         elseif action == "clear" then
  544.             LPSTAT.JunkIgnore = {}
  545.             print("|cff66C6FF"..L"Cleared junk exceptions list.")
  546.         elseif action == "add" or strfind(action,"^del") or strfind(action,"^rem") then
  547.             for id in s:gmatch("|Hitem:(%d-):") do
  548.                 local link = select(2, GetItemInfo(id))
  549.                 if action == "add" then
  550.                     if select(3, GetItemInfo(id)) == 0 then
  551.                         if not tContains(LPSTAT.JunkIgnore,id) then
  552.                             tinsert(LPSTAT.JunkIgnore,id)
  553.                             print(format("|cff66C6FF%s:|r %s",L"Added junk exception",link))
  554.                         else
  555.                             print(format("%s |cff66C6FF%s",link,L"is already in exceptions list."))
  556.                         end
  557.                     else print(format("|cff66C6FF",link,L"is not junk.")) end
  558.                 elseif strfind(action,"^del") or strfind(action,"^rem") then
  559.                     tDeleteItem(LPSTAT.JunkIgnore,id)
  560.                     print(format("|cff66C6FF%s:|r %s",L"Removed junk exception",link))
  561.                 end
  562.             end
  563.         else
  564.             print("|cffffffffLite|cff66C6FFStats|r:",L"Junk List")
  565.             print(format("/junk <add||rem(ove)> [%s] - %s",L"itemlink",L"Add/remove exception."))
  566.             print("/junk list -",L"List currently ignored items.")
  567.             print("/junk clear -",L"Clear exceptions list.")
  568.         end
  569.     end
  570. end
  571. ------------------------------------------
  572. --  Clock
  573. if clock.enabled then
  574.     Inject("Clock", {  height = 12,
  575.         text = {
  576.             string = function()
  577.                 return zsub(GameTime_GetTime(true),'%s*AM',clock.AM,'%s*PM',clock.PM,':',clock.colon)
  578.             end
  579.         },
  580.         OnLoad = function(self)
  581.             RequestRaidInfo()
  582.             self:RegisterEvent'UPDATE_INSTANCE_INFO'
  583.             TimeManagerClockButton:Hide()
  584.             GameTimeFrame:Hide()
  585.         end,
  586.         OnEvent = function(self) if self.hovered then self:GetScript("OnEnter")(self) end end,
  587.         OnEnter = function(self)
  588.             if not self.hovered then RequestRaidInfo() self.hovered = true end         
  589.             GameTooltip:SetOwner(self, clock.tip_anchor, clock.tip_x, clock.tip_y)
  590.             GameTooltip:ClearLines()
  591.             GameTooltip:AddLine(date'%A, %B %d',tthead.r,tthead.g,tthead.b)
  592.             GameTooltip:AddLine' '
  593.             GameTooltip:AddDoubleLine(gsub(TIMEMANAGER_TOOLTIP_LOCALTIME,':',''),zsub(GameTime_GetLocalTime(true),'%s*AM','am','%s*PM','pm'),ttsubh.r,ttsubh.g,ttsubh.b,1,1,1)
  594.             GameTooltip:AddDoubleLine(gsub(TIMEMANAGER_TOOLTIP_REALMTIME,':',''),zsub(GameTime_GetGameTime(true),'%s*AM','am','%s*PM','pm'),ttsubh.r,ttsubh.g,ttsubh.b,1,1,1)
  595.             GameTooltip:AddLine' '
  596.             for i = 1, 2 do
  597.                 local _, localizedName, isActive, _, startTime, _ = GetWorldPVPAreaInfo(i)
  598.                 GameTooltip:AddDoubleLine(format(localizedName,""), isActive and WINTERGRASP_IN_PROGRESS or (startTime==0) and "N/A" or fmttime(startTime),ttsubh.r,ttsubh.g,ttsubh.b,1,1,1)
  599.             end
  600.            
  601.             local oneraid
  602.             for i = 1, GetNumSavedInstances() do
  603.                 local name,_,reset,difficulty,locked,extended,_,isRaid,maxPlayers = GetSavedInstanceInfo(i)
  604.                 if isRaid and (locked or extended) then
  605.                     local tr,tg,tb,diff
  606.                     if not oneraid then
  607.                         GameTooltip:AddLine' '
  608.                         GameTooltip:AddLine(RAID_INFO,ttsubh.r,ttsubh.g,ttsubh.b)
  609.                         oneraid = true
  610.                     end
  611.                     if extended then tr,tg,tb = 0.3,1,0.3 else tr,tg,tb = 1,1,1 end
  612.                     if difficulty == 3 or difficulty == 4 then diff = "H" else diff = "N" end
  613.                     GameTooltip:AddDoubleLine(format("%s |cffaaaaaa(%s%s)",name,maxPlayers,diff),fmttime(reset),1,1,1,tr,tg,tb)
  614.                 end
  615.             end
  616.             GameTooltip:Show()
  617.         end,
  618.         OnClick = function(_,b) (b == "RightButton" and ToggleTimeManager or ToggleCalendar)() end
  619.     })
  620. end
  621. ------------------------------------------
  622. --  Location
  623. if location.enabled then
  624.     Inject("Location", {  height = 12, width = 113,
  625.         OnLoad = function(self)
  626.             MiniMapWorldMapButton:Hide() -- Hide minimap world map button.
  627.             MinimapZoneTextButton:Hide() -- Hide minimap zone text.
  628.             RegEvents(self,"ZONE_CHANGED ZONE_CHANGED_INDOORS ZONE_CHANGED_NEW_AREA PLAYER_ENTERING_WORLD")
  629.             -- Territory names and colors.
  630.             self.sanctuary = {SANCTUARY_TERRITORY, {0.41,0.8,0.94}}
  631.             self.arena = {FREE_FOR_ALL_TERRITORY, {1,0.1,0.1}}
  632.             self.friendly = {FACTION_CONTROLLED_TERRITORY, {0.1,1,0.1}}
  633.             self.hostile = {FACTION_CONTROLLED_TERRITORY, {1,0.1,0.1}}
  634.             self.contested = {CONTESTED_TERRITORY, {1,0.7,0}}
  635.             self.combat = {COMBAT_ZONE, {1,0.1,0.1}}
  636.             self.neutral = {format(FACTION_CONTROLLED_TERRITORY,FACTION_STANDING_LABEL4), {1,0.93,0.76}}
  637.         end,
  638.         OnEvent = function(self)
  639.             self.subzone, self.zone, self.pvp = GetSubZoneText(), GetZoneText(), {GetZonePVPInfo()}
  640.             if not self.pvp[1] then self.pvp[1] = "neutral" end
  641.             local label = (self.subzone ~= "" and location.subzone) and self.subzone or self.zone
  642.             local r,g,b = unpack(self.pvp[1] and (self[self.pvp[1]][2] or self.other) or self.other)
  643.             self.text:SetText(location.truncate == 0 and label or strtrim(strsub(label,1,location.truncate)))
  644.             self.text:SetTextColor(r,g,b,font.alpha)
  645.         end,
  646.         OnUpdate = function(self,u)
  647.             if self.hovered then
  648.                 self.elapsed = self.elapsed + u
  649.                 if self.elapsed > 1 or self.init then
  650.                     GameTooltip:ClearLines()
  651.                     GameTooltip:AddLine(format("%s |cffffffff(%s)",self.zone,Coords()),tthead.r,tthead.g,tthead.b,1,1,1)
  652.                     if self.pvp[1] and not IsInInstance() then
  653.                         local r,g,b = unpack(self[self.pvp[1]][2])
  654.                         if self.subzone and self.subzone ~= self.zone then GameTooltip:AddLine(self.subzone,r,g,b) end             
  655.                         GameTooltip:AddLine(format(self[self.pvp[1]][1],self.pvp[3] or ""),r,g,b)
  656.                     end
  657.                     GameTooltip:Show()
  658.                     self.elapsed, self.init = 0, false
  659.                 end
  660.             end
  661.         end,
  662.         OnEnter = function(self)
  663.             self.hovered, self.init = true, true
  664.             GameTooltip:SetOwner(self, location.tip_anchor, location.tip_x, location.tip_y)
  665.         end,
  666.         OnClick = function(self,button)
  667.             if IsShiftKeyDown() then
  668.                 ChatFrameEditBox:Show()
  669.                 ChatFrameEditBox:Insert(format(" (%s: %s)",self.zone,Coords()))
  670.             else ToggleFrame(WorldMapFrame) end
  671.         end
  672.     })
  673. end
  674. ------------------------------------------
  675. -- Coordinates
  676. if coords.enabled then
  677.     Inject("Coords", {
  678.         text = { string = Coords },
  679.         OnClick = function(_,button)
  680.             if button == "LeftButton" then
  681.                 ToggleFrame(WorldMapFrame)
  682.             else
  683.                 ChatFrameEditBox:Show()
  684.                 ChatFrameEditBox:Insert(format(" (%s: %s)",GetZoneText(),Coords()))
  685.             end
  686.         end
  687.     })
  688. end
  689. ------------------------------------------
  690. --  Ping
  691. if ping.enabled then
  692.     Inject("Ping", {
  693.         text = { alpha = 1 },
  694.         OnLoad = function(self) self:RegisterEvent'MINIMAP_PING' end,
  695.         OnEvent = function(self, event, unit)
  696.             if unit == P and ping.hide_self then return end
  697.             if (unit == P and self.timer and time() - self.timer > 1) or not self.timer or unit ~= P then
  698.                 local class = (CUSTOM_CLASS_COLORS or RAID_CLASS_COLORS)[select(2,UnitClass(unit))]
  699.                 self.text:SetText(format(ping.fmt, UnitName(unit)))
  700.                 self.text:SetTextColor(class.r,class.g,class.b,1)
  701.                 if UIFrameIsFading(self) then UIFrameFlashRemoveFrame(self) end
  702.                 UIFrameFlash(self,0.2,2.8,8,false,0,5)
  703.                 self.timer = time()
  704.             end
  705.         end
  706.     })
  707. end
  708. ------------------------------------------
  709. --  DPS
  710. if dps.enabled then
  711.     local function short(num)
  712.         if dps.short then
  713.             num = tonumber(num)
  714.             if num >= 1000000 then
  715.                 return gsub(format("%.1f%s", num/1000000, experience.million or 'm'),"%.0","")
  716.             elseif num >= 1000 then
  717.                 return gsub(format("%.1f%s", num/1000, experience.thousand or 'k'),"%.0","")
  718.             end
  719.         end
  720.         return floor(tonumber(num))
  721.     end
  722.     Inject("DPS", {
  723.         text = {
  724.             string = function(self)
  725.                 self = self:GetParent()
  726.                 if dps.hide_inactive and not self.active and self.inactive_time and
  727.                    GetTime() - self.inactive_time > 10 then self:Hide()
  728.                 end
  729.                 self.dps = self.active and self.damage / (GetTime() - self.starttime) or self.dps or 0
  730.                 return format(dps.fmt, short(self.dps))
  731.             end
  732.         },
  733.         OnLoad = function(self)
  734.             RegEvents(self,"UNIT_PET COMBAT_LOG_EVENT_UNFILTERED PLAYER_REGEN_ENABLED PLAYER_REGEN_DISABLED")
  735.             self.events = "SWING_DAMAGE RANGE_DAMAGE SPELL_DAMAGE SPELL_PERIODIC_DAMAGE DAMAGE_SHIELD DAMAGE_SPLIT"
  736.             self.inactive_time = GetTime()
  737.             self.player, self.pet, self.damage, self.active = UnitGUID(P), UnitGUID'pet' or '0x0', 0, false
  738.             if dps.hide_inactive then self:Hide() end
  739.         end,
  740.         OnEvent = function(self, event, ...)
  741.             if event == "COMBAT_LOG_EVENT_UNFILTERED" then
  742.                 local params = {...}
  743.                 local spellevent = params[2]
  744.                 local unit = params[4]
  745.                 local damage = params[spellevent == "SWING_DAMAGE" and 12 or 15]
  746.  
  747.                 if not strmatch(self.events, spellevent) then return end
  748.                 if unit == self.player or unit == self.pet then
  749.                     if self.damage == 0 then
  750.                         self.starttime, self.active = GetTime(), true
  751.                         self.text:SetText(format(dps.fmt, 0))
  752.                     end
  753.                     if not self:IsShown() and dps.hide_inactive then self:Show() end
  754.                     self.damage = self.damage + damage
  755.                 end
  756.             elseif event == "UNIT_PET" then
  757.                 self.pet = UnitGUID'pet' or '0x0'
  758.             elseif event == "PLAYER_REGEN_ENABLED" then
  759.                 self.inactive_time = GetTime()
  760.                 self.active = false
  761.             elseif event == "PLAYER_REGEN_DISABLED" then
  762.                 self.damage = 0
  763.             end
  764.         end,
  765.         OnClick = function(self, button)
  766.             if button == "RightButton" then
  767.                 self.starttime, self.damage, self.dps = GetTime(), 0, 0
  768.                 self.text:SetText(format(dps.fmt, short(self.dps)))
  769.             end
  770.         end
  771.     })
  772. end
  773. ------------------------------------------
  774. --  Guild
  775. if guild.enabled then
  776.     hooksecurefunc("SortGuildRoster", function(type) CURRENT_GUILD_SORTING = type end)
  777.     Inject("Guild", {
  778.         text = {
  779.             string = function()
  780.                 if IsInGuild() then
  781.                     local online, total = 0, GetNumGuildMembers(true)
  782.                     for i = 0, total do if select(9, GetGuildRosterInfo(i)) then online = online + 1 end end
  783.                     return format(guild.fmt, online, total)
  784.                 else return format("%s %s",NO,GUILD) end
  785.             end, update = 5
  786.         },
  787.         OnLoad = function(self)
  788.             GuildRoster()
  789.             SortGuildRoster(guild.sorting == "note" and "rank" or "note")
  790.             SortGuildRoster(guild.sorting)
  791.             self:RegisterEvent'PARTY_MEMBERS_CHANGED'
  792.         end,
  793.         OnEvent = function(self) if self.hovered then self:GetScript("OnEnter")(self) end end,
  794.         OnUpdate = function(self,u)
  795.             if IsInGuild() then
  796.                 AltUpdate(self)
  797.                 if not self.gmotd then
  798.                     -- Give me the GMOTD *today* pls.
  799.                     if self.elapsed > 1 then GuildRoster(); self.elapsed = 0 end
  800.                     if GetGuildRosterMOTD() ~= '' then self.gmotd = true; if self.hovered then self:GetScript("OnEnter")(self) end end
  801.                     self.elapsed = self.elapsed + u
  802.                 end
  803.             end
  804.         end,
  805.         OnClick = function(self,b)
  806.             if b == "LeftButton" then
  807.                 ToggleGuildFrame(1)
  808.             elseif b == "RightButton" then
  809.                 local s = CURRENT_GUILD_SORTING
  810.                 SortGuildRoster(IsShiftKeyDown() and s or (IsAltKeyDown() and (s == "rank" and "note" or "rank") or s == "class" and "name" or s == "name" and "level" or s == "level" and "zone" or "class"))
  811.                 self:GetScript("OnEnter")(self)
  812.             end
  813.         end,
  814.         OnEnter = function(self)
  815.             if IsInGuild() then
  816.                 self.hovered = true
  817.                 GuildRoster()
  818.                 local name, rank, level, zone, note, officernote, connected, status, class, zone_r, zone_g, zone_b, classc, levelc, grouped
  819.                 local online, total, gmotd = 0, GetNumGuildMembers(true), GetGuildRosterMOTD()
  820.                 for i = 0, total do if select(9, GetGuildRosterInfo(i)) then online = online + 1 end end
  821.                
  822.                 GameTooltip:SetOwner(self, guild.tip_anchor, guild.tip_x, guild.tip_y)
  823.                 GameTooltip:ClearLines()
  824.                 GameTooltip:AddDoubleLine(GetGuildInfo(P),format("%s: %d/%d",GUILD_ONLINE_LABEL,online,total),tthead.r,tthead.g,tthead.b,tthead.r,tthead.g,tthead.b)
  825.                 if gmotd ~= "" then GameTooltip:AddLine(format("  %s |cffaaaaaa- |cffffffff%s",GUILD_MOTD,gmotd),ttsubh.r,ttsubh.g,ttsubh.b,1) end
  826.                 if guild.maxguild ~= 0 then
  827.                     GameTooltip:AddLine' '
  828.                     for i = 1, total do
  829.                         if guild.maxguild and i > guild.maxguild then
  830.                             if online > 2 then GameTooltip:AddLine(format("%d %s (%s)",online - guild.maxguild,L"Hidden",L"ALT"),ttsubh.r,ttsubh.g,ttsubh.b) end
  831.                             break
  832.                         end
  833.                         -- name, rank, rankIndex, level, class, zone, note, officernote, online, status, classFileName
  834.                         name, rank, _, level, _, zone, note, officernote, connected, status, class = GetGuildRosterInfo(i)
  835.                         if connected and level >= guild.threshold then
  836.                             if GetRealZoneText() == zone then zone_r, zone_g, zone_b = 0.3, 1.0, 0.3 else zone_r, zone_g, zone_b = 0.65, 0.65, 0.65 end
  837.                             classc, levelc = (CUSTOM_CLASS_COLORS or RAID_CLASS_COLORS)[class], GetQuestDifficultyColor(level)
  838.                             grouped = (UnitInParty(name) or UnitInRaid(name)) and (GetRealZoneText() == zone and " |cff7fff00*|r" or " |cffff7f00*|r") or ""
  839.                             if self.altdown then
  840.                                 GameTooltip:AddDoubleLine(format("%s%s |cff999999- |cffffffff%s",grouped,name,rank),zone,classc.r,classc.g,classc.b,zone_r,zone_g,zone_b)
  841.                                 if note ~= "" then GameTooltip:AddLine('  "'..note..'"',ttsubh.r,ttsubh.g,ttsubh.b,1) end
  842.                                 if officernote ~= "" then GameTooltip:AddLine("  o: "..officernote,0.3,1,0.3,1) end
  843.                             else
  844.                                 GameTooltip:AddDoubleLine(format("|cff%02x%02x%02x%d|r %s%s%s",levelc.r*255,levelc.g*255,levelc.b*255,level,name,(status~="" and " "..status or ""),grouped),zone,classc.r,classc.g,classc.b,zone_r,zone_g,zone_b)
  845.                             end
  846.                         end
  847.                     end
  848.                     GameTooltip:AddLine' '
  849.                     GameTooltip:AddDoubleLine(" ",format("%s %s",L"Sorting by",CURRENT_GUILD_SORTING),1,1,1,ttsubh.r,ttsubh.g,ttsubh.b)
  850.                 end
  851.                 GameTooltip:Show()
  852.             end
  853.         end
  854.     })
  855. end
  856. ------------------------------------------
  857. --  Friends
  858. if friends.enabled then
  859.     Inject("Friends", {
  860.         OnLoad = function(self) RegEvents(self,"PLAYER_LOGIN FRIENDLIST_UPDATE BN_FRIEND_LIST_SIZE_CHANGED PARTY_MEMBERS_CHANGED") end,
  861.         OnEvent = function(self, event)
  862.             if event ~= "PARTY_MEMBERS_CHANGED" then
  863.                 local numBNetTotal, numBNetOnline = BNGetNumFriends()
  864.                 local online, total = 0, GetNumFriends()
  865.                 for i = 0, total do if select(5, GetFriendInfo(i)) then online = online + 1 end end
  866.                 online=online+numBNetOnline
  867.                 total=total+numBNetTotal
  868.                 self.text:SetText(format(friends.fmt, online, total))
  869.             end
  870.             if self.hovered then self:GetScript("OnEnter")(self) end
  871.         end,
  872.         OnUpdate = AltUpdate,
  873.         OnClick = function(_,b) (b=="RightButton" and ToggleIgnorePanel or ToggleFriendsPanel)() end,
  874.         OnEnter = function(self)
  875.             ShowFriends()
  876.             self.hovered = true
  877.             local numBNetTotal, numBNetOnline = BNGetNumFriends()
  878.             local online, total = 0, GetNumFriends()
  879.             local name, level, class, zone, connected, status, note, zone_r, zone_g, zone_b, grouped
  880.             for i = 0, total do if select(5, GetFriendInfo(i)) then online = online + 1 end end
  881.             online=online+numBNetOnline
  882.             total=total+numBNetTotal
  883.             if online > 0 then
  884.                 GameTooltip:SetOwner(self, friends.tip_anchor, friends.tip_x, friends.tip_y)
  885.                 GameTooltip:ClearLines()
  886.                 GameTooltip:AddDoubleLine(FRIENDS_LIST, format("%s: %s/%s",GUILD_ONLINE_LABEL,online,total),tthead.r,tthead.g,tthead.b,tthead.r,tthead.g,tthead.b)
  887.                 GameTooltip:AddLine' '
  888.            
  889.                 -- track redundancy of battle/wow friends
  890.                 local fList = {}
  891.            
  892.                 for i =1,numBNetOnline do
  893.                     presenceID, givenName, surname, toonName, toonID, client, connected, lastOnline, isAFK, isDND, broadcastText, noteText, isFriend, broadcastTime = BNGetFriendInfo(i)
  894.                     local numToons = BNGetNumFriendToons(i)
  895.                     for m=1,numToons do
  896.                         local _, name, client, realm, _, _, race, class, _, zone, level = BNGetFriendToonInfo(i,m)
  897.                         if not connected then break end
  898.                         tinsert(fList, name)
  899.                    
  900.                         local status = isAFK and FRIENDS_TEXTURE_AFK or isDND and FRIENDS_TEXTURE_DND or FRIENDS_TEXTURE_ONLINE
  901.                    
  902.                         for k,v in pairs(LOCALIZED_CLASS_NAMES_MALE) do if class == v then class = k end end
  903.                         if GetLocale() ~= "enUS" then -- feminine class localization (unsure if it's really needed)
  904.                             for k,v in pairs(LOCALIZED_CLASS_NAMES_FEMALE) do if class == v then class = k end end
  905.                         end
  906.                         local classc, levelc = (CUSTOM_CLASS_COLORS or RAID_CLASS_COLORS)[class] or {r=1,g=1,b=1}, GetQuestDifficultyColor(level ~= "" and level or 1)
  907.                         if GetRealZoneText() == zone then zone_r, zone_g, zone_b = 0.3, 1.0, 0.3 else zone_r, zone_g, zone_b = 0.65, 0.65, 0.65 end
  908.                         grouped = client ~= "WoW" and "" or (UnitInParty(name) or UnitInRaid(name)) and (GetRealZoneText() == zone and " |cff7fff00*|r" or " |cffff7f00*|r") or ""
  909.                         zone = client ~= "WoW" and format("|T%s:%d|t",client ~= "WoW" and "Interface\\FriendsFrame\\Battlenet-Sc2icon",24) or zone
  910.                         name = client == "WoW" and " "..name or format("|cff67D6FF%s %s|r%s",givenName, surname, (name and " |cffaaaaaa("..name..")|r" or ""))
  911.                         GameTooltip:AddDoubleLine(format("|T%s:%d|t|cff%02x%02x%02x%s|r|cff%02x%02x%02x%s|r%s",status,20,levelc.r*255,levelc.g*255,levelc.b*255,level,classc.r*255,classc.g*255,classc.b*255,name,grouped),zone,1,1,1,zone_r,zone_g,zone_b)
  912.                         if self.altdown then GameTooltip:AddLine(" "..(cl