Thread Tools Display Modes
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(" "..(client == "WoW" and format("|cffffffff%s %s%s |r",givenName,surname,((noteText and noteText ~= "") and ": "..noteText or "")) or ""),ttsubh.r,ttsubh.g,ttsubh.b,1) end
  913.                     end
  914.                 end
  915.            
  916.                 for i = 1, GetNumFriends() do
  917.                     name, level, class, zone, connected, status, note = GetFriendInfo(i)
  918.                     if not connected then break end
  919.                     if not tContains(fList, name) then
  920.                         status = string.find(status,AFK) and FRIENDS_TEXTURE_AFK or string.find(status,AFK) and FRIENDS_TEXTURE_DND or FRIENDS_TEXTURE_ONLINE
  921.                         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
  922.                         for k,v in pairs(LOCALIZED_CLASS_NAMES_MALE) do if class == v then class = k end end
  923.                         if GetLocale() ~= "enUS" then -- feminine class localization (unsure if it's really needed)
  924.                             for k,v in pairs(LOCALIZED_CLASS_NAMES_FEMALE) do if class == v then class = k end end
  925.                         end
  926.                         local classc, levelc = (CUSTOM_CLASS_COLORS or RAID_CLASS_COLORS)[class], GetQuestDifficultyColor(level)
  927.                         grouped = (UnitInParty(name) or UnitInRaid(name)) and (GetRealZoneText() == zone and " |cff7fff00*|r" or " |cffff7f00*|r") or ""
  928.                         GameTooltip:AddDoubleLine(format("|T%s:%d|t|cff%02x%02x%02x%d|r %s%s",status,20,levelc.r*255,levelc.g*255,levelc.b*255,level or "",name,grouped),zone,classc.r,classc.g,classc.b,zone_r,zone_g,zone_b)
  929.                         if self.altdown and note then GameTooltip:AddLine(" "..note,ttsubh.r,ttsubh.g,ttsubh.b,1) end
  930.                     end
  931.                 end
  932.                 GameTooltip:Show()
  933.             else HideTT(self) end
  934.         end
  935.     })
  936. end
  937. ------------------------------------------
  938. --  Bags
  939. if bags.enabled then
  940.     Inject("Bags", {
  941.         OnLoad = function(self) RegEvents(self,"PLAYER_LOGIN BAG_UPDATE") end,
  942.         OnEvent = function(self)
  943.             local free, total = 0, 0
  944.             for i = 0, NUM_BAG_SLOTS do
  945.                 free, total = free + GetContainerNumFreeSlots(i), total + GetContainerNumSlots(i)
  946.             end
  947.             self.text:SetText(format(bags.fmt, free, total))
  948.         end,
  949.         OnClick = function() OpenAllBags() end
  950.     })
  951. end
  952. ------------------------------------------
  953. --  Talents
  954. if talents.enabled then
  955.     Inject("Talents", {
  956.         OnLoad = function(self)
  957.             RegEvents(self,"PLAYER_LOGIN PLAYER_TALENT_UPDATE CHARACTER_POINTS_CHANGED PLAYER_ENTERING_WORLD PLAYER_LEAVING_WORLD")
  958.         end,
  959.         OnEvent = function(self, event, ...)
  960.             if event == "PLAYER_ENTERING_WORLD" then
  961.                 self:RegisterEvent'PLAYER_TALENT_UPDATE'
  962.             elseif event == "PLAYER_LEAVING_WORLD" then
  963.                 self:UnregisterEvent'PLAYER_TALENT_UPDATE'
  964.             elseif event == "UNIT_SPELLCAST_START" then
  965.                 local unit, spell = ...
  966.                 if unit == P and (spell == GetSpellInfo(63645) or spell == GetSpellInfo(63644)) then timer = GetTime() end
  967.             else
  968.                 if UnitLevel(P) < 10 then
  969.                     self.text:SetText(format("%s %s",NO,TALENTS))
  970.                 elseif GetNumTalentTabs() == 3 then
  971.                     self.talents = {}
  972.                     self.unspent = GetUnspentTalentPoints(false, false, GetActiveTalentGroup())
  973.                     for i = 1, GetNumTalentGroups() do
  974.                         tinsert(self.talents, {})
  975.                         local tal, pts, icon, name = self.talents[i], -1
  976.                         for tree = 1, GetNumTalentTabs() do
  977.                             tinsert(tal, {GetTalentTabInfo(tree,nil,nil,i)})
  978.                             if tal[tree][5] ~= 0 and tal[tree][5] > pts then
  979.                                 name, icon, pts = {tal[tree][2],tree}, tal[tree][4], tal[tree][5]
  980.                             end
  981.                         end
  982.                         if not name then name, icon = {format("%s %s",NO,TALENTS)}, "Interface\\Icons\\INV_Misc_QuestionMark" end
  983.                         tinsert(tal, name)
  984.                         if i == GetActiveTalentGroup() then
  985.                        
  986.                             self.text:SetText(zsub(talents.fmt,"%[(.-)%]", {
  987.                                 name = name[1], shortname = gsub(name[1],".*",talents.name_subs),
  988.                                 icon = format("|T%s:%d|t",icon,talents.iconsize),
  989.                                 unspent = self.unspent > 0 and format("|cff55ff55+"..self.unspent) or ''
  990.                             },"%[spec(.-)%]", function(spec)
  991.                                 return format(spec == '' and "%d/%d/%d" or gsub(spec,'^ ',''),tal[1][5],tal[2][5],tal[3][5])
  992.                             end,' $',''))
  993.                             tinsert(tal, 1)
  994.                         end
  995.                     end
  996.                     if self.hovered then self:GetScript("OnEnter")(self) end
  997.                 end
  998.             end
  999.         end,
  1000.         OnUpdate = function(self)
  1001.             if GetNumTalentTabs() == 3 then
  1002.                 self:SetScript("OnUpdate",nil)
  1003.                 self:GetScript("OnEvent")(self)
  1004.             end
  1005.         end,
  1006.         OnEnter = function(self)
  1007.             self.hovered = true
  1008.             if UnitLevel(P) >= 10 then
  1009.                 GameTooltip:SetOwner(self, talents.tip_anchor, talents.tip_x, talents.tip_y)
  1010.                 GameTooltip:ClearLines()
  1011.                 GameTooltip:AddDoubleLine(TALENTS,self.unspent > 0 and format("%d %s",self.unspent,UNUSED) or '',tthead.r,tthead.g,tthead.b,tthead.r,tthead.g,tthead.b)
  1012.                 GameTooltip:AddLine' '
  1013.                 for i = 1, GetNumTalentGroups() do
  1014.                     local tal = self.talents[i]
  1015.                     local tree = tal[4][2]
  1016.                     local name, icon, spent = tree and tal[tree][2] or NONE, tree and tal[tree][4] or "Interface\\Icons\\INV_Misc_QuestionMark", format("%d/%d/%d",tal[1][5],tal[2][5],tal[3][5])
  1017.                     if tal[5] then r,g,b = 0.3,1,0.3 else r,g,b = 0.5,0.5,0.5 end
  1018.                     GameTooltip:AddDoubleLine(format("|T%s:%d|t %s %s",icon,t_icon,gsub(name,".*",talents.name_subs),spent), i==1 and PRIMARY or SECONDARY,1,1,1,r,g,b)
  1019.                 end
  1020.                 GameTooltip:Show()
  1021.             end
  1022.         end,
  1023.         OnLeave = function(self) self.hovered = false end,
  1024.         OnClick = function(_,b)
  1025.             if b == "RightButton" and GetNumTalentGroups() > 1 then
  1026.                 SetActiveTalentGroup(3 - GetActiveTalentGroup())
  1027.             elseif b == "LeftButton" then
  1028.                 ToggleTalentFrame()
  1029.             end
  1030.         end
  1031.     })
  1032. end
  1033. ------------------------------------------
  1034. --  Character Stats
  1035. if stats.enabled then
  1036.     local function tags(sub)
  1037.         local percent, string = true
  1038.         if sub == "ap" then
  1039.             local base, pos, neg = UnitAttackPower(P)
  1040.             string, percent = base + neg + pos
  1041.         elseif sub == "rangedap" then      
  1042.             local base, pos, neg = UnitRangedAttackPower(P)
  1043.             string, percent = base + neg + pos
  1044.         elseif sub == "armorpen" then
  1045.             string = GetArmorPenetration()
  1046.         elseif sub == "expertise" then
  1047.             string = GetExpertisePercent()
  1048.         elseif strmatch(sub,"hit$") then
  1049.             local var = _G["CR_HIT_"..(strupper(strmatch(sub,"(%w-)hit$")) or "")]
  1050.             string, percent = var and GetCombatRatingBonus(var) or format("[%s]",sub), var
  1051.         elseif strmatch(sub,"haste$") then
  1052.             local var = _G["CR_HASTE_"..(strupper(strmatch(sub,"(%w-)haste$")) or "")]
  1053.             string, percent = var and GetCombatRatingBonus(var) or format("[%s]",sub), var
  1054.         elseif sub == "meleecrit" then
  1055.             string = GetCritChance()
  1056.         elseif sub == "rangedcrit" then
  1057.             string = GetRangedCritChance()
  1058.         elseif sub == "spellcrit" then
  1059.             local rate = 0
  1060.             for i = 1, 7 do rate = max(rate, GetSpellCritChance(i)) end
  1061.             string = rate
  1062.         elseif sub == "spellpower" then
  1063.             local power = 0
  1064.             for i = 1, 7 do power = max(power, GetSpellBonusDamage(i)) end
  1065.             string, percent = power
  1066.         elseif sub == "healing" then
  1067.             string, percent = GetSpellBonusHealing()
  1068.         elseif sub == "spellpen" then
  1069.             string, percent = GetSpellPenetration()
  1070.         elseif sub == "dodge" then
  1071.             string = GetDodgeChance()
  1072.         elseif sub == "parry" then
  1073.             string = GetParryChance()
  1074.         elseif sub == "block" then
  1075.             string = GetBlockChance()
  1076.         elseif sub == "defense" then
  1077.             local base, add = UnitDefense(P)
  1078.             string, percent = base + add
  1079.         elseif sub == "avoidance" then
  1080.             string = GetDodgeChance() + GetParryChance() + GetBlockChance()
  1081.         elseif sub == "manaregen" then
  1082.             local _,class = UnitClass(P)
  1083.             local I5SR = true -- oo5sr/i5sr swapping NYI
  1084.             if class == "ROGUE" or class == "WARRIOR" or class == "DEATHKNIGHT" then
  1085.                 string, percent = "??"
  1086.             else
  1087.                 local base, cast = GetManaRegen()
  1088.                 string, percent = floor((I5SR and cast or base) * 5)
  1089.             end
  1090.         elseif sub == "armor" then
  1091.             local _,eff = UnitArmor(P)
  1092.             string, percent = eff
  1093.         else
  1094.             string, percent = format("[%s]",sub)
  1095.         end
  1096.         if not percent then return string end
  1097.         return format("%.2f", string)
  1098.     end
  1099.     Inject("Stats", {
  1100.         OnUpdate = function(self, u)
  1101.             self.elapsed = self.elapsed + u
  1102.             if self.elapsed > 2.5 then
  1103.                 self.text:SetText(gsub(stats[format("spec%dfmt", GetActiveTalentGroup())], "%[(%w-)%]", tags))
  1104.                 self.elapsed = 0
  1105.             end
  1106.         end
  1107.     })
  1108. end
  1109. ------------------------------------------
  1110. --  Experience/Played/Rep
  1111. if experience.enabled then
  1112.     local logintime, playedtotal, playedlevel, playedmsg, gained, lastkill, lastquest = GetTime(), 0, 0, 0, 0
  1113.     local repname, repcolor, standingname, currep, minrep, maxrep, reppercent
  1114.     local mobxp = gsub(COMBATLOG_XPGAIN_FIRSTPERSON,"%%[sd]","(.*)")
  1115.     local questxp = gsub(COMBATLOG_XPGAIN_FIRSTPERSON_UNNAMED,"%%[sd]","(.*)")
  1116.     local function short(num,tt)
  1117.         if short or tt then
  1118.             num = tonumber(num)
  1119.             if num >= 1000000 then
  1120.                 return gsub(format("%.1f%s", num/1000000, experience.million or 'm'),"%.0","")
  1121.             elseif num >= 1000 then
  1122.                 return gsub(format("%.1f%s", num/1000, experience.thousand or 'k'),"%.0","")
  1123.             end
  1124.         end
  1125.         return floor(tonumber(num))
  1126.     end
  1127.     local function tags(sub,tt)
  1128.         local t = experience
  1129.             -- exp tags
  1130.         return sub == "level" and UnitLevel(P)
  1131.             or sub == "curxp" and short(UnitXP(P),tt)
  1132.             or sub == "remainingxp" and short(UnitXPMax(P) - UnitXP(P),tt)
  1133.             or sub == "totalxp" and short(UnitXPMax(P),tt)
  1134.             or sub == "cur%" and floor(UnitXP(P) / UnitXPMax(P) * 100)
  1135.             or sub == "remaining%" and 100 - floor(UnitXP(P) / UnitXPMax(P) * 100)
  1136.             or sub == "restxp" and short(GetXPExhaustion() or 0,tt)
  1137.             or sub == "rest%" and min(150, floor((GetXPExhaustion() or 0) / UnitXPMax(P) * 100))
  1138.             or sub == "sessiongained" and short(gained,tt)
  1139.             or sub == "sessionrate" and short(gained / (GetTime() - playedmsg) * 3600,tt)
  1140.             or sub == "levelrate" and short(UnitXP(P) / (playedlevel + GetTime() - playedmsg) * 3600,tt)
  1141.             or sub == "sessionttl" and (gained ~= 0 and fmttime((UnitXPMax(P) - UnitXP(P)) / (gained / (GetTime() - playedmsg)),t) or L"inf")
  1142.             or sub == "levelttl" and (UnitXP(P) ~= 0 and fmttime((UnitXPMax(P) - UnitXP(P)) / (UnitXP(P) / (playedlevel + GetTime() - playedmsg)),t) or L"inf")
  1143.             or sub == "questsleft" and (lastquest and ceil((UnitXPMax(P) - UnitXP(P)) / tonumber(lastquest)) or "??")
  1144.             or sub == "killsleft" and (lastkill and ceil((UnitXPMax(P) - UnitXP(P)) / tonumber(lastkill)) or "??")
  1145.             -- time played tags
  1146.             or sub == "playedtotal" and fmttime(playedtotal + GetTime() - playedmsg,t)
  1147.             or sub == "playedlevel" and fmttime(playedlevel + GetTime() - playedmsg,t)
  1148.             or sub == "playedsession" and fmttime(GetTime() - logintime,t)
  1149.             -- rep tags
  1150.             or sub == "repname" and (t.faction_subs[repname] or repname)
  1151.             or sub == "repcolor" and "|cff"..repcolor
  1152.             or sub == "standing" and standingname
  1153.             or sub == "currep" and abs(currep-minrep)
  1154.             or sub == "repleft" and abs(maxrep-currep)
  1155.             or sub == "maxrep" and abs(maxrep-minrep)
  1156.             or sub == "rep%" and floor(abs(currep-minrep) / abs(maxrep-minrep) * 100)
  1157.             or format("[%s]",sub)
  1158.     end
  1159.     Inject("Experience", {
  1160.         text = {
  1161.             string = function(self)
  1162.                 if conf.ExpMode == "rep" then
  1163.                     return self:GetText()
  1164.                 elseif conf.ExpMode == "played" then
  1165.                     return gsub(experience.played_fmt,"%[([%w%%]-)%]",tags)
  1166.                 elseif conf.ExpMode == "xp" then
  1167.                     return gsub(experience[format("xp_%s_fmt",(GetXPExhaustion() or 0) > 0 and "rested" or "normal")],"%[([%w%%]-)%]",tags) or " "
  1168.                 end
  1169.             end
  1170.         },
  1171.         OnLoad = function(self)
  1172.             RegEvents(self,"TIME_PLAYED_MSG PLAYER_LOGOUT PLAYER_LOGIN UPDATE_FACTION CHAT_MSG_COMBAT_XP_GAIN PLAYER_LEVEL_UP")
  1173.             -- Filter first time played message.
  1174.             local ofunc = ChatFrame_DisplayTimePlayed
  1175.             function ChatFrame_DisplayTimePlayed() ChatFrame_DisplayTimePlayed = ofunc end
  1176.             RequestTimePlayed()
  1177.             if not conf.ExpMode or conf.ExpMode == "xp" then
  1178.                 conf.ExpMode = UnitLevel(P) ~= MAX_PLAYER_LEVEL and "xp" or "played"
  1179.             end
  1180.         end,
  1181.         OnEvent = function(self, event, ...)
  1182.             if event == "CHAT_MSG_COMBAT_XP_GAIN" then
  1183.                 local msg = ...
  1184.                 if msg:find(mobxp) then
  1185.                     _, lastkill = strmatch(msg,mobxp)
  1186.                     gained = gained + lastkill
  1187.                 elseif msg:find(questxp) then
  1188.                     lastquest = strmatch(msg,questxp)
  1189.                     gained = gained + lastquest
  1190.                 end
  1191.             elseif event == "PLAYER_LEVEL_UP" then
  1192.                 playedlevel, playedmsg = 0, GetTime()
  1193.             elseif event == "TIME_PLAYED_MSG" then
  1194.                 playedtotal, playedlevel = ...
  1195.                 playedmsg = GetTime()
  1196.             elseif (event == "UPDATE_FACTION" or event == "PLAYER_LOGIN") and conf.ExpMode == "rep" then
  1197.                 local standing
  1198.                 repname, standing, minrep, maxrep, currep = GetWatchedFactionInfo()            
  1199.                 if not repname then repname = NONE end
  1200.                 local color = {}
  1201.                 if standing == 0 then
  1202.                     color.r, color.g, color.b = GetItemQualityColor(0)
  1203.                 elseif standing == 7 then
  1204.                     color.r, color.g, color.b = GetItemQualityColor(3)
  1205.                 elseif standing == 8 then
  1206.                     color.r, color.g, color.b = GetItemQualityColor(4)
  1207.                 else
  1208.                     color = FACTION_BAR_COLORS[standing]
  1209.                 end
  1210.                 standingname = _G[format("FACTION_STANDING_LABEL%s%s",standing,UnitSex(P) == 3 and "_FEMALE" or "")]
  1211.                 if not standingname then standingname = UNKNOWN end
  1212.                 repcolor = format("%02x%02x%02x", min(color.r*255+40,255), min(color.g*255+40,255), min(color.b*255+40,255))
  1213.                 self.text:SetText(gsub(experience.faction_fmt,"%[([%w%%]-)%]",tags))
  1214.             end
  1215.             if event == "PLAYER_LOGOUT" or event == "TIME_PLAYED_MSG" then
  1216.                 conf.Played = floor(playedtotal + GetTime() - playedmsg)
  1217.             end
  1218.         end,
  1219.         OnEnter = function(self)
  1220.             self.hovered = true
  1221.             GameTooltip:SetOwner(self, experience.tip_anchor, experience.tip_x, experience.tip_y)
  1222.             GameTooltip:ClearLines()
  1223.             if conf.ExpMode == "played" then
  1224.                 GameTooltip:AddLine(TIME_PLAYED_MSG,tthead.r,tthead.g,tthead.b)
  1225.                 GameTooltip:AddLine' '
  1226.                 GameTooltip:AddDoubleLine(L"Played this session",tags("playedsession",1),ttsubh.r,ttsubh.g,ttsubh.b,1,1,1)
  1227.                 GameTooltip:AddDoubleLine(L"Played this level",tags("playedlevel",1),ttsubh.r,ttsubh.g,ttsubh.b,1,1,1)
  1228.                 GameTooltip:AddLine' '
  1229.                 GameTooltip:AddLine(L"Account Played",ttsubh.r,ttsubh.g,ttsubh.b)              
  1230.                 local total = 0
  1231.                 for realm, t in pairs(LPSTAT) do
  1232.                     for name, conf in pairs(t) do
  1233.                         if conf.Played then
  1234.                             local r,g,b,player = 1,1,1
  1235.                             if name == UnitName(P) and realm == GetRealmName() then
  1236.                                 conf.Played,player,r,g,b = floor(playedtotal+GetTime()-playedmsg),true,0.5,1,0.5
  1237.                             end
  1238.                             if conf.Played > 3600 or player then -- 1hr threshold displayed
  1239.                                 GameTooltip:AddDoubleLine(format("%s-%s",name,realm), fmttime(conf.Played),r,g,b,1,1,1)
  1240.                             end
  1241.                             total = total + conf.Played
  1242.                         end
  1243.                     end
  1244.                 end            
  1245.                 GameTooltip:AddDoubleLine(" ","------------------",1,1,1,0.5,0.5,0.5)
  1246.                 GameTooltip:AddDoubleLine(L"Total",fmttime(total),ttsubh.r,ttsubh.g,ttsubh.b,1,1,1)
  1247.             elseif conf.ExpMode == "xp" then
  1248.                 GameTooltip:AddDoubleLine(COMBAT_XP_GAIN,format(LEVEL_GAINED,UnitLevel(P)),tthead.r,tthead.g,tthead.b,tthead.r,tthead.g,tthead.b)
  1249.                 GameTooltip:AddLine' '
  1250.                 GameTooltip:AddDoubleLine(L"Current/Max XP",format("%s/%s (%s%%)",tags'curxp',tags'totalxp',tags'cur%'),ttsubh.r,ttsubh.g,ttsubh.b,1,1,1)
  1251.                 GameTooltip:AddDoubleLine(L"Remaining XP",format("%s (%s%%)",tags'remainingxp',tags'remaining%'),ttsubh.r,ttsubh.g,ttsubh.b,1,1,1)
  1252.                 if GetXPExhaustion() and GetXPExhaustion() ~= 0 then
  1253.                     GameTooltip:AddDoubleLine(L"Rested XP",format("%s (%s%%)",tags'restxp',tags'rest%'),ttsubh.r,ttsubh.g,ttsubh.b,1,1,1)
  1254.                 end
  1255.                 GameTooltip:AddLine' '             
  1256.                 GameTooltip:AddDoubleLine(L"Session XP rate",format("%s/%s (%s)",tags'sessionrate',L"hr",tags'sessionttl'),ttsubh.r,ttsubh.g,ttsubh.b,1,1,1)
  1257.                 GameTooltip:AddDoubleLine(L"Level XP rate",format("%s/%s (%s)",tags'levelrate',L"hr",tags'levelttl'),ttsubh.r,ttsubh.g,ttsubh.b,1,1,1)
  1258.                 GameTooltip:AddDoubleLine(format(L"Quests/Kills to %s",UnitLevel(P)+1), format("%s:%s %s:%s",L"Q",tags'questsleft',L"K",tags'killsleft'),ttsubh.r,ttsubh.g,ttsubh.b,1,1,1)
  1259.                 GameTooltip:AddLine' '
  1260.                 GameTooltip:AddDoubleLine(L"Played this session",tags'playedsession',ttsubh.r,ttsubh.g,ttsubh.b,1,1,1)
  1261.                 GameTooltip:AddDoubleLine(L"Played this level",tags'playedlevel',ttsubh.r,ttsubh.g,ttsubh.b,1,1,1)
  1262.                 GameTooltip:AddDoubleLine(L"Played total",tags'playedtotal',ttsubh.r,ttsubh.g,ttsubh.b,1,1,1)
  1263.             elseif conf.ExpMode == "rep" then
  1264.                 local desc, war, watched
  1265.                 for i = 1, GetNumFactions() do
  1266.                     _,desc,_,_,_,_,war,_,_,_,_,watched = GetFactionInfo(i)
  1267.                     if watched then break end
  1268.                 end
  1269.                 GameTooltip:AddLine(tags'repname',tthead.r,tthead.g,tthead.b)
  1270.                 GameTooltip:AddLine(desc,ttsubh.r,ttsubh.g,ttsubh.b,1)
  1271.                 GameTooltip:AddLine' '
  1272.                 GameTooltip:AddDoubleLine(format("%s%s",tags'repcolor',tags'standing'),war and format("|cffff5555%s",AT_WAR))
  1273.                 GameTooltip:AddDoubleLine(format("%s%% | %s/%s",tags'rep%',tags'currep',tags'maxrep'),-tags'repleft',ttsubh.r,ttsubh.g,ttsubh.b,1,0.33,0.33)
  1274.             end
  1275.             GameTooltip:Show()
  1276.         end,
  1277.         OnClick = function(self, button)
  1278.             if button == "RightButton" then
  1279.                 conf.ExpMode = conf.ExpMode == "xp" and "played"
  1280.                     or conf.ExpMode == "played" and "rep"
  1281.                     or (conf.ExpMode == "rep" and UnitLevel(P) ~= MAX_PLAYER_LEVEL) and "xp"
  1282.                     or conf.ExpMode == "rep" and "played"
  1283.                 if conf.ExpMode == "rep" then
  1284.                     self:GetScript("OnEvent")(self,"UPDATE_FACTION")
  1285.                 else
  1286.                     self:GetScript("OnUpdate")(self,5)
  1287.                 end
  1288.                 self:GetScript("OnEnter")(self)
  1289.             elseif button == "LeftButton" and conf.ExpMode == "rep" then
  1290.                 ToggleCharacter("ReputationFrame")
  1291.             end
  1292.         end
  1293.     })
  1294. end
  1295. ------------------------------------------
  1296. -- Applying modules
  1297. lpanels:CreateLayout("LiteStats", layout)
  1298. lpanels:ApplyLayout(nil, "LiteStats")
  1299.  
  1300. Inject = nil

OrderHall Mission Page: This error occurs whenever I have the mission page open and change zones

Error:
Lua Code:
  1. Message: ...Blizzard_GarrisonUI\Blizzard_GarrisonLandingPage.lua:685: attempt to get length of local 'items' (a nil value)
  2. Time: 01/20/17 01:21:36
  3. Count: 36
  4. Stack: ...Blizzard_GarrisonUI\Blizzard_GarrisonLandingPage.lua:685: in function `GarrisonLandingPageReportMission_FilterOutCombatAllyMissions'
  5. ...Blizzard_GarrisonUI\Blizzard_GarrisonLandingPage.lua:449: in function `GarrisonLandingPageReportList_UpdateItems'
  6. ...Blizzard_GarrisonUI\Blizzard_GarrisonLandingPage.lua:211: in function <...Blizzard_GarrisonUI\Blizzard_GarrisonLandingPage.lua:207>
  7.  
  8. Locals: items = nil
  9. (*temporary) = nil
  10. (*temporary) = nil
  11. (*temporary) = nil
  12. (*temporary) = nil
  13. (*temporary) = nil
  14. (*temporary) = nil
  15. (*temporary) = nil
  16. (*temporary) = "attempt to get length of local 'items' (a nil value)"

Any help whatsoever fixing these errors would be greatly appreciated!
  Reply With Quote
01-22-17, 01:04 AM   #2
ceylina
A Wyrmkin Dreamwalker
Join Date: Oct 2014
Posts: 50
Might be because coordinate positioning inside instances is disabled as of 7.xx something (I forget now the exact patch that did it)

You need to check against the function IsInInstance() and if true set coordX and coordY to 0

I think the second error is a well known bug and nothing you can do about it
  Reply With Quote
02-10-17, 11:17 AM   #3
badness
A Cliff Giant
 
badness's Avatar
Join Date: May 2010
Posts: 74
What do you mean exactly by check against the IsInInstance() function and could you provide an example if possible?
  Reply With Quote
02-10-17, 11:55 AM   #4
Yukyuk
A Chromatic Dragonspawn
 
Yukyuk's Avatar
AddOn Author - Click to view addons
Join Date: Apr 2015
Posts: 179
You can do

Code:
local isInstance, instanceType = IsInInstance()
This will tell you if you are in an Instance (isInstance = true or false) and what type of instance

instanceType =
"none" when outside an instance
"pvp" when in a battleground
"arena" when in an arena
"party" when in a 5-man instance
"raid" when in a raid instance
"scenario" when in a scenario


The workaround I now use for Deathcounter

Code:
	posX, posY = GetPlayerMapPosition("player")

	if posX == nil and posY == nil then
		self:Debug("Default coordinates")
		posX = 0.5
		posY = 0.5
		Xposition = 0.5
		Yposition = 0.5
	else
		self:Debug("Found coordinates")
		Xposition = addon:round(posX, 2)
		Yposition = addon:round(posY, 2)
	end
__________________
Better to fail then never have tried at all.

Last edited by Yukyuk : 02-10-17 at 12:00 PM.
  Reply With Quote

WoWInterface » AddOns, Compilations, Macros » AddOn Help/Support » Lua Error Help with LiteStats and OrderHall Page

Thread Tools
Display Modes

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