Advertisement
Guest User

Buffoon

a guest
Sep 7th, 2012
127
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 10.66 KB | None | 0 0
  1. -- Buffoon by Jzar / Spirestone
  2. -- Adds info to buff tooltips showing who granted you that buff, who else has it, and who's missing it.
  3.  
  4. local ADDON_NAME = "Buffoon"
  5. local ADDON_VERSION = "1.4"
  6. local ADDON_COLOR = "00a2d9"
  7.  
  8. local _
  9.  
  10. local f = CreateFrame("FRAME", ADDON_NAME)
  11.  
  12. f.Defaults = {
  13.     debug = false, -- Display notification upon loading and debug status messages
  14.     enabled = true, -- Do anything
  15.     groupSize = "party", -- Only display caster and other information when in this type of group or larger
  16.     showCaster = true, -- Show the caster's name.  Core functionality IMO, but I guess some people want to turn it off.  :/
  17.     showBuffed = false, -- Show people that DO have the buff you're hovering over
  18.     showUnbuffed = true, -- Show people that DO NOT have the buff you're hovering over
  19.     showInGroups = false, -- Show people grouped by what party they're in, rather than packed tightly together
  20.     showExtras = false, -- Show everyone in raid past the first 10 / 25 players, depending on your current raid difficulty
  21. }
  22.  
  23. f:SetScript("OnEvent", function(self, event, ...) if self[event] then return self[event](self, event, ...) end end)
  24. function f:Print(text) if text then DEFAULT_CHAT_FRAME:AddMessage("|cff" .. ADDON_COLOR .. ADDON_NAME .. "|r: " .. tostring(text)) end end
  25. function f:Debug(text) if self.Options.debug and text then DEFAULT_CHAT_FRAME:AddMessage("|cff" .. ADDON_COLOR .. ADDON_NAME .. "|r: " .. tostring(text)) end end
  26.  
  27. f:RegisterEvent("ADDON_LOADED")
  28. function f:ADDON_LOADED(event, addon)
  29.     if addon == ADDON_NAME then
  30.         if not _G[ADDON_NAME .. "DB"] then _G[ADDON_NAME .. "DB"] = {} end
  31.        
  32.         -- Recursively create / update options table with default options if not yet set
  33.         local function updateTable(source, dest)
  34.             if not dest then dest = {} end
  35.             for key, val in pairs(source) do
  36.                 if type(val) == "table" then
  37.                     updateTable(val, dest[key])
  38.                 else
  39.                     if dest[key] == nil then dest[key] = val end
  40.                 end
  41.             end
  42.         end
  43.         updateTable(self.Defaults, _G[ADDON_NAME .. "DB"])
  44.         self.Options = _G[ADDON_NAME .. "DB"]
  45.        
  46.         self:Debug(ADDON_NAME .. " v" .. ADDON_VERSION .. " loaded.")
  47.  
  48.         -- Prepare to register a slash command based on the capitolized letters in the addon's name
  49.         local abbreviatedName = ""
  50.         for i = 1, #ADDON_NAME do
  51.             if ADDON_NAME:sub(i, i) ~= ADDON_NAME:lower():sub(i, i) then
  52.                 abbreviatedName = abbreviatedName .. ADDON_NAME:lower():sub(i, i)
  53.             end
  54.         end
  55.  
  56.         _G["SLASH_" .. ADDON_NAME .. "1"] = "/" .. ADDON_NAME:lower()
  57.         if #abbreviatedName > 2 then _G["SLASH_" .. ADDON_NAME .. "2"] = "/" .. abbreviatedName end
  58.         SlashCmdList[ADDON_NAME] = function(msg) self:SlashCommandHandler(msg) end
  59.  
  60.         self:UnregisterEvent("ADDON_LOADED")
  61.         self.ADDON_LOADED = nil
  62.     end
  63. end
  64.  
  65. -- Using table to emulate a switch statement for slash command handling
  66. f.SlashCommandTable = {
  67.     ["debug"] = function() f.Options.debug = not f.Options.debug; f:Print("Debug: " .. (f.Options.debug and "Enabled" or "Disabled")) end,
  68.     ["default"] = function()
  69.         f:Print(ADDON_NAME .. " " .. ADDON_VERSION);
  70.         f:Print("  /buffoon {toggle | on | off}");
  71.         f:Print("  /buffoon {solo | party | raid}");
  72.         f:Print("  /buffoon {caster | buffed | unbuffed}");
  73.         f:Print("  /buffoon {extras}"); end,
  74.     ["status"] = function()
  75.         f:Print(f.Options.enabled and "Enabled" or "Disabled");
  76.         f:Print("Show when " .. f.Options.groupSize);
  77.         f:Print("Buffed - " .. (f.Options.showBuffed and "True" or "False"));
  78.         f:Print("Unbuffed - " .. (f.Options.showUnbuffed and "True" or "False"));
  79.         f:Print("Groups - " .. (f.Options.showInGroups and "True" or "False")); end,
  80.     ["toggle"] = function() f.Options.enabled = not f.Options.enabled; f:Print(f.Options.enabled and "Enabled" or "Disabled") end,
  81.     ["on"] = function() f.Options.enabled = true; f:Print("Enabled") end,
  82.     ["off"] = function() f.Options.enabled = false; f:Print("Disabled") end,
  83.     ["solo"] = function() f.Options.groupSize = "solo"; f:Print("Groupsize: " .. f.Options.groupSize) end,
  84.     ["party"] = function() f.Options.groupSize = "party"; f:Print("Groupsize: " .. f.Options.groupSize) end,
  85.     ["raid"] = function() f.Options.groupSize = "raid"; f:Print("Groupsize: " .. f.Options.groupSize) end,
  86.     ["caster"] = function() f.Options.showCaster = not f.Options.showCaster; f:Print("Show caster: " .. (f.Options.showCaster and "True" or "False")) end,
  87.     ["buffed"] = function() f.Options.showBuffed = not f.Options.showBuffed; f:Print("Show buffed: " .. (f.Options.showBuffed and "True" or "False")) end,
  88.     ["unbuffed"] = function() f.Options.showUnbuffed = not f.Options.showUnbuffed; f:Print("Show unbuffed: " .. (f.Options.showUnbuffed and "True" or "False")) end,
  89.     ["groups"] = function() f.Options.showInGroups = not f.Options.showInGroups; f:Print("Show in groups: " .. (f.Options.showInGroups and "True" or "False")) end,
  90.     ["extras"] = function() f.Options.showExtras = not f.Options.showExtras; f:Print("Show extras in raid: " .. (f.Options.showExtras and "True" or "False")) end,
  91.     ["rl"] = function() ReloadUI() end,
  92. }
  93. function f:SlashCommandHandler(msg)
  94.     if self.SlashCommandTable[msg:lower()] then
  95.         self.SlashCommandTable[msg:lower()]()
  96.     else
  97.         self.SlashCommandTable["default"]()
  98.     end
  99. end
  100.  
  101. -- Hook Gametooltip when it shows unit auras, and add our buff text to the bottom
  102. function f:SetUnitAura(_, unitId, auraIndex)
  103.     local showCaster = false
  104.     if self.Options.groupSize == "solo" then showCaster = true end
  105.     if self.Options.groupSize == "party" and GetNumSubgroupMembers() > 0 then showCaster = true end
  106.     if self.Options.groupSize == "raid" and IsInRaid() then showCaster = true end
  107.    
  108.     if self.Options.enabled and showCaster then
  109.         local function wrapWhite(text) return ("|cffffffff%s|r"):format(text) end
  110.         local auraName = select(1, UnitAura(unitId, auraIndex)) or select(1, UnitAura(unitId, auraIndex, "HARMFUL"))
  111.         local caster = select(8, UnitAura(unitId, auraIndex)) or select(8, UnitAura(unitId, auraIndex, "HARMFUL"))
  112.         local consol = select(10, UnitAura(unitId, auraIndex)) or select(10, UnitAura(unitId, auraIndex, "HARMFUL"))
  113.         local blankAdded = false
  114.         if self.Options.showCaster and caster then
  115.             GameTooltip:AddLine(" ")
  116.             blankAdded = true
  117.             GameTooltip:AddLine(wrapWhite("Caster: ") .. self:colorByClass(caster))
  118.         end
  119.  
  120.         if self.Options.showBuffed or self.Options.showUnbuffed and UnitIsFriend("player", unitId) then
  121.             local buffed, unbuffed
  122.  
  123.             if GetNumGroupMembers() > 0 and IsInRaid() then
  124.                 buffed, unbuffed = self:findAura(auraName, "raid", GetNumGroupMembers())
  125.             elseif GetNumSubgroupMembers() > 0 then
  126.                 buffed, unbuffed = self:findAura(auraName, "party", GetNumSubgroupMembers())
  127.                 tempBuffed, tempUnbuffed = self:findAura(auraName, "player")
  128.                 if tempBuffed[1] and not buffed[1] then buffed[1] = {} end
  129.                 if tempBuffed[1] then table.insert(buffed[1], 1, tempBuffed[1][1]) end
  130.                 if tempUnbuffed[1] and not unbuffed[1] then unbuffed[1] = {} end
  131.                 if tempUnbuffed[1] then table.insert(unbuffed[1], 1, tempUnbuffed[1][1]) end
  132.             else
  133.                 buffed, unbuffed = self:findAura(auraName, "player")
  134.             end
  135.            
  136.             if self.Options.showBuffed and table.maxn(buffed) > 0 and consol then
  137.                 if not blankAdded then GameTooltip:AddLine(" "); blankAdded = true end
  138.                 GameTooltip:AddLine(wrapWhite("Buffed: ") .. self:buildList(buffed))
  139.             end
  140.             if self.Options.showUnbuffed and table.maxn(unbuffed) > 0 and consol then
  141.                 if not blankAdded then GameTooltip:AddLine(" "); blankAdded = true end
  142.                 GameTooltip:AddLine(wrapWhite("Unbuffed: ") .. self:buildList(unbuffed))
  143.             end
  144.         end
  145.     end
  146.     GameTooltip:Show()
  147. end
  148. hooksecurefunc(GameTooltip, "SetUnitAura", function(...) f:SetUnitAura(...) end)
  149.  
  150. -- Search the group (up to limit number of players) for auraName, and return a 2 dimensional
  151. -- table with parties and player names of those holding and missing the buff
  152. function f:findAura(auraName, group, limit)
  153.     local buffed, unbuffed = {}, {}
  154.     for i = 1, limit or 1 do
  155.         local maxMembers = (group == "raid") and ((GetRaidDifficulty() == 1 or GetRaidDifficulty() == 3) and 10 or 25) or 1
  156.         if GetNumGroupMembers() == 0 or select(3, GetRaidRosterInfo(i)) * 5 <= maxMembers or f.Options.showExtras then -- 3rd argument from GetRaidRosterInfo is the raid member's subgroup
  157.             local unitId = limit and (group .. i) or group
  158.             local party = (group == "raid") and select(3, GetRaidRosterInfo(i)) or 1
  159.             local hasBuff = false
  160.             for j = 1, 40 do
  161.                 local groupAuraName = UnitAura(unitId, j)
  162.                 if not groupAuraName then break end
  163.                 if auraName == groupAuraName then
  164.                     hasBuff = true
  165.                     if not buffed[party] then buffed[party] = {} end
  166.                     table.insert(buffed[party], unitId)
  167.                 end
  168.             end
  169.             if not hasBuff then
  170.                 if not unbuffed[party] then unbuffed[party] = {} end
  171.                 table.insert(unbuffed[party], unitId)
  172.             end
  173.         end
  174.     end
  175.     return buffed, unbuffed
  176. end
  177.  
  178. -- Take a table of parties and unitIds, and build a formatted list of players
  179. function f:buildList(list)
  180.     local returnList = ""
  181.     local totalEntries = 0
  182.     for i = 1, table.maxn(list) do
  183.         if list[i] then
  184.             totalEntries = totalEntries + #list[i]
  185.         end
  186.     end
  187.    
  188.     -- Show groups in raid
  189.     if self.Options.showInGroups and table.maxn(list) > 1 then
  190.         returnList = returnList .. totalEntries
  191.         for i = 1, table.maxn(list) do
  192.             if list[i] then
  193.                 local tempList = ""
  194.                 for j = 1, #list[i] do
  195.                     if tempList == "" then
  196.                         tempList = "\r\n  " .. i .. ". " .. self:colorByClass(list[i][j])
  197.                     else
  198.                         tempList = tempList .. ", " .. self:colorByClass(list[i][j])
  199.                     end
  200.                 end
  201.                 returnList = returnList .. tempList
  202.             end
  203.         end
  204.        
  205.     -- Show all together in raid
  206.     elseif table.maxn(list) > 1 then
  207.         local wordsOnLine = 0
  208.         for i = 1, table.maxn(list) do
  209.             if list[i] then
  210.                 for j = 1, #list[i] do
  211.                     if wordsOnLine == 0 then
  212.                         returnList = self:colorByClass(list[i][j])
  213.                         wordsOnLine = 2
  214.                     elseif wordsOnLine == 5 then
  215.                         returnList = returnList .. "\r\n  " .. self:colorByClass(list[i][j])
  216.                         wordsOnLine = 1
  217.                     else
  218.                         returnList = returnList .. ", " .. self:colorByClass(list[i][j])
  219.                         wordsOnLine = wordsOnLine + 1
  220.                     end
  221.                 end
  222.             end
  223.         end
  224.  
  225.     -- Show all on single line
  226.     else
  227.         for i = 1, #list[1] do
  228.             if returnList == "" then
  229.                 returnList = self:colorByClass(list[1][i])
  230.             else
  231.                 returnList = returnList .. ", " .. self:colorByClass(list[1][i])
  232.             end
  233.         end
  234.     end
  235.     return returnList
  236. end
  237.  
  238. -- Input a unitId, identify its class, then return the target's name wrapped in class specific color codes
  239. function f:colorByClass(unitId)
  240.     if not unitId then return end
  241.     local color = RAID_CLASS_COLORS[select(2, UnitClass(unitId))] or {r = 1.0, g = 1.0, b = 1.0}
  242.     return ("|cff%02x%02x%02x%s|r"):format(color.r * 255, color.g * 255, color.b * 255, UnitName(unitId))
  243. end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement