-- rTooltip: core
-- zork, 2018
-----------------------------
-- Variables
-----------------------------
local A, L = ...
local unpack, type = unpack, type
local RAID_CLASS_COLORS, FACTION_BAR_COLORS, ICON_LIST = RAID_CLASS_COLORS, FACTION_BAR_COLORS, ICON_LIST
local GameTooltip, GameTooltipStatusBar = GameTooltip, GameTooltipStatusBar
local GameTooltipTextRight1, GameTooltipTextRight2, GameTooltipTextRight3, GameTooltipTextRight4, GameTooltipTextRight5, GameTooltipTextRight6, GameTooltipTextRight7, GameTooltipTextRight8 = GameTooltipTextRight1, GameTooltipTextRight2, GameTooltipTextRight3, GameTooltipTextRight4, GameTooltipTextRight5, GameTooltipTextRight6, GameTooltipTextRight7, GameTooltipTextRight8
local GameTooltipTextLeft1, GameTooltipTextLeft2, GameTooltipTextLeft3, GameTooltipTextLeft4, GameTooltipTextLeft5, GameTooltipTextLeft6, GameTooltipTextLeft7, GameTooltipTextLeft8 = GameTooltipTextLeft1, GameTooltipTextLeft2, GameTooltipTextLeft3, GameTooltipTextLeft4, GameTooltipTextLeft5, GameTooltipTextLeft6, GameTooltipTextLeft7, GameTooltipTextLeft8
local classColorHex, factionColorHex = {}, {}
local Hider = CreateFrame("Frame", nil, UIParent) Hider:Hide()
-----------------------------
-- Config
-----------------------------
local cfg = {}
cfg.textColor = {0.4,0.4,0.4}
cfg.bossColor = {1,0,0}
cfg.eliteColor = {1,0,0.5}
cfg.rareeliteColor = {1,0.5,0}
cfg.rareColor = {1,0.5,0}
cfg.levelColor = {0.8,0.8,0.5}
cfg.deadColor = {0.5,0.5,0.5}
cfg.targetColor = {1,0.5,0.5}
cfg.guildColor = {1,0,1}
cfg.afkColor = {0,1,1}
cfg.scale = 0.95
cfg.fontFamily = STANDARD_TEXT_FONT
cfg.alwaysCompare = true
cfg.backdrop = {
bgFile = "Interface\\Buttons\\WHITE8x8",
bgColor = {0.08,0.08,0.1,0.92},
edgeFile = "Interface\\Tooltips\\UI-Tooltip-Border",
borderColor = {0.1,0.1,0.1,0.6},
itemBorderColorAlpha = 0.9,
azeriteBorderColor = {1,0.3,0,0.9},
tile = false,
tileEdge = false,
tileSize = 16,
edgeSize = 16,
insets = {left=3, right=3, top=3, bottom=3}
}
--pos can be either a point table or a anchor string
--cfg.pos = { "BOTTOMRIGHT", UIParent, "BOTTOMRIGHT", -10, 180 }
cfg.pos = "ANCHOR_NONE" --"ANCHOR_CURSOR"
-----------------------------
-- Functions
-----------------------------
-- Tooltip skin
local fakeBg = CreateFrame("Frame", nil, UIParent, "BackdropTemplate")
fakeBg:SetBackdrop({ bgFile = cfg.backdrop.bgFile, edgeFile = cfg.backdrop.bgFile, edgeSize = 1 })
local function __GetBackdrop() return fakeBg:GetBackdrop() end
local function __GetBackdropColor() return 0, 0, 0, .7 end
local function __GetBackdropBorderColor() return 0, 0, 0 end
local function GetHexColor(color)
if color.r then
return ("%.2x%.2x%.2x"):format(color.r*255, color.g*255, color.b*255)
else
local r,g,b,a = unpack(color)
return ("%.2x%.2x%.2x"):format(r*255, g*255, b*255)
end
end
local function GetTarget(unit)
if UnitIsUnit(unit, "player") then
return ("|cffff0000%s|r"):format("<YOU>")
elseif UnitIsPlayer(unit, "player") then
local _, class = UnitClass(unit)
return ("|cff%s%s|r"):format(classColorHex[class], UnitName(unit))
elseif UnitReaction(unit, "player") then
return ("|cff%s%s|r"):format(factionColorHex[UnitReaction(unit, "player")], UnitName(unit))
else
return ("|cffffffff%s|r"):format(UnitName(unit))
end
end
local function OnTooltipSetUnit(self)
local unitName, unit = self:GetUnit()
if not unit then return end
--color tooltip textleft2..8
GameTooltipTextLeft2:SetTextColor(unpack(cfg.textColor))
GameTooltipTextLeft3:SetTextColor(unpack(cfg.textColor))
GameTooltipTextLeft4:SetTextColor(unpack(cfg.textColor))
GameTooltipTextLeft5:SetTextColor(unpack(cfg.textColor))
GameTooltipTextLeft6:SetTextColor(unpack(cfg.textColor))
GameTooltipTextLeft7:SetTextColor(unpack(cfg.textColor))
GameTooltipTextLeft8:SetTextColor(unpack(cfg.textColor))
--position raidicon
local raidIconIndex = GetRaidTargetIndex(unit)
if raidIconIndex then
GameTooltipTextLeft1:SetText(("%s %s"):format(ICON_LIST[raidIconIndex].."14|t", unitName))
end
if not UnitIsPlayer(unit) then
--unit is not a player
--color textleft1 and statusbar by faction color
local reaction = UnitReaction(unit, "player")
if reaction then
local color = FACTION_BAR_COLORS[reaction]
if color then
cfg.barColor = color
GameTooltipStatusBar:SetStatusBarColor(color.r,color.g,color.b)
GameTooltipTextLeft1:SetTextColor(color.r,color.g,color.b)
end
end
--color textleft2 by classificationcolor
local unitClassification = UnitClassification(unit)
local levelLine
if string.find(GameTooltipTextLeft2:GetText() or "empty", "%a%s%d") then
levelLine = GameTooltipTextLeft2
elseif string.find(GameTooltipTextLeft3:GetText() or "empty", "%a%s%d") then
GameTooltipTextLeft2:SetTextColor(unpack(cfg.guildColor)) --seems like the npc has a description, use the guild color for this
levelLine = GameTooltipTextLeft3
end
if levelLine then
local l = UnitLevel(unit)
local color = GetCreatureDifficultyColor((l > 0) and l or 999)
levelLine:SetTextColor(color.r,color.g,color.b)
end
if unitClassification == "worldboss" or UnitLevel(unit) == -1 then
self:AppendText(" |cffff0000{B}|r")
GameTooltipTextLeft2:SetTextColor(unpack(cfg.bossColor))
elseif unitClassification == "rare" then
self:AppendText(" |cffff9900{R}|r")
elseif unitClassification == "rareelite" then
self:AppendText(" |cffff0000{R+}|r")
elseif unitClassification == "elite" then
self:AppendText(" |cffff6666{E}|r")
end
else
--unit is any player
local _, unitClass = UnitClass(unit)
--color textleft1 and statusbar by class color
local color = RAID_CLASS_COLORS[unitClass]
cfg.barColor = color
GameTooltipStatusBar:SetStatusBarColor(color.r,color.g,color.b)
GameTooltipTextLeft1:SetTextColor(color.r,color.g,color.b)
--color textleft2 by guildcolor
local unitGuild = GetGuildInfo(unit)
if unitGuild then
GameTooltipTextLeft2:SetText("<"..unitGuild..">")
GameTooltipTextLeft2:SetTextColor(unpack(cfg.guildColor))
end
local levelLine = unitGuild and GameTooltipTextLeft3 or GameTooltipTextLeft2
local l = UnitLevel(unit)
local color = GetCreatureDifficultyColor((l > 0) and l or 999)
levelLine:SetTextColor(color.r,color.g,color.b)
--afk?
if UnitIsAFK(unit) then
self:AppendText((" |cff%s<AFK>|r"):format(cfg.afkColorHex))
end
end
--dead?
if UnitIsDeadOrGhost(unit) then
GameTooltipTextLeft1:SetTextColor(unpack(cfg.deadColor))
end
--target line
if (UnitExists(unit.."target")) then
GameTooltip:AddDoubleLine(("|cff%s%s|r"):format(cfg.targetColorHex, "Target"),GetTarget(unit.."target") or "Unknown")
end
end
local function SetItemBorderColor(tooltip)
local link = select(2, tooltip:GetItem())
local r, g, b
local backdrop = tooltip.Backdrop
if backdrop then
if link then
local quality = select(3, GetItemInfo(link))
if quality then
r, g, b = GetItemQualityColor(quality)
else
r, g, b = unpack(cfg.backdrop.borderColor)
end
backdrop:SetBackdropBorderColor(r, g, b)
else
backdrop:SetBackdropBorderColor(unpack(cfg.backdrop.borderColor))
end
end
end
local function OnTooltipSetItem(self)
local _, link = self:GetItem()
if link then
local id = "|cFFCA3C3CID|r "..link:match(":(%w+)")
local level = GetDetailedItemLevelInfo(link) or 1
local text = "|cFFCA3C3C"..ITEM_LEVEL_ABBR.."|r "..level
self:AddLine(" ")
self:AddDoubleLine(id, text)
end
SetItemBorderColor(self)
end
local function Kill(self)
if (self.UnregisterAllEvents) then
self:UnregisterAllEvents()
self:SetParent(Hider)
else
self.Show = self.Hide
end
self:Hide()
end
local function StripTextures(self, Kill)
for i = 1, self:GetNumRegions() do
local Region = select(i, self:GetRegions())
if (Region and Region:GetObjectType() == "Texture") then
if (Kill and type(Kill) == "boolean") then
Region:Kill()
elseif (Region:GetDrawLayer() == Kill) then
Region:SetTexture(nil)
elseif (Kill and type(Kill) == "string" and Region:GetTexture() ~= Kill) then
Region:SetTexture(nil)
else
Region:SetTexture(nil)
end
end
end
end
local function SetBackdropStyle(self, style)
if self.TopOverlay then self.TopOverlay:Hide() end
if self.BottomOverlay then self.BottomOverlay:Hide() end
StripTextures(self)
self:SetBackdrop(cfg.backdrop)
self:SetBackdropColor(unpack(cfg.backdrop.bgColor))
local _, itemLink = self:GetItem()
if itemLink then
local azerite = false--C_AzeriteEmpoweredItem.IsAzeriteEmpoweredItemByID(itemLink) or C_AzeriteItem.IsAzeriteItemByID(itemLink) or false
local _, _, itemRarity = GetItemInfo(itemLink)
local r,g,b = 1,1,1
if itemRarity then r,g,b = GetItemQualityColor(itemRarity) end
--use azerite coloring or item rarity
if azerite and cfg.backdrop.azeriteBorderColor then
self:SetBackdropBorderColor(unpack(cfg.backdrop.azeriteBorderColor))
else
self:SetBackdropBorderColor(r,g,b,cfg.backdrop.itemBorderColorAlpha)
end
else
--no item, use default border
self:SetBackdropBorderColor(unpack(cfg.backdrop.borderColor))
end
end
local function CreateBackdrop(self)
if self.Backdrop then return end
self.Backdrop = CreateFrame("Frame", nil, self, "BackdropTemplate")
self.Backdrop:SetAllPoints()
self.Backdrop:SetFrameLevel(self:GetFrameLevel())
self.Backdrop:SetBackdrop(cfg.backdrop)
self.Backdrop:SetBackdropColor(unpack(cfg.backdrop.bgColor))
self.Backdrop:SetBackdropBorderColor(unpack(cfg.backdrop.borderColor))
end
local function SetStatusBarColor(self,r,g,b)
if not cfg.barColor then return end
if r == cfg.barColor.r and g == cfg.barColor.g and b == cfg.barColor.b then return end
self:SetStatusBarColor(cfg.barColor.r,cfg.barColor.g,cfg.barColor.b)
end
local function SetDefaultAnchor(self,parent)
if not cfg.pos then return end
if type(cfg.pos) == "string" then
self:SetOwner(parent, cfg.pos)
else
self:SetOwner(parent, "ANCHOR_NONE")
self:ClearAllPoints()
self:SetPoint(unpack(cfg.pos))
end
end
local function ResetBorderColor(self)
if self ~= GameTooltip then
return
end
if self.Backdrop then
self.Backdrop:SetBackdropBorderColor(unpack(cfg.backdrop.borderColor))
end
end
local function SetUnitBorderColor(self)
local unit = self
local r, g, b
local GameTooltip = GameTooltip
local reaction = unit and UnitReaction(unit, "player")
local player = unit and UnitIsPlayer(unit)
local friend = unit and UnitIsFriend("player", unit)
if player and friend then
local class = select(2, UnitClass(unit))
local color = RAID_CLASS_COLORS[class]
r, g, b = color.r, color.g, color.b
GameTooltip.Backdrop:SetBackdropBorderColor(r, g, b)
elseif reaction then
local color = FACTION_BAR_COLORS[reaction]
r, g, b = color.r, color.g, color.b
GameTooltip.Backdrop:SetBackdropBorderColor(r, g, b)
end
end
local function SetCompareItemBorderColor(anchorFrame)
for i = 1, 2 do
local shoptip = _G["ShoppingTooltip"..i]
if shoptip:IsShown() then
local frameLevel = GameTooltip:GetFrameLevel()
local item = shoptip:GetItem()
if frameLevel == shoptip:GetFrameLevel() then
shoptip:SetFrameLevel(i + 1)
end
if item then
local quality = select(3, GetItemInfo(item))
if quality then
local r, g, b = GetItemQualityColor(quality)
shoptip.Backdrop:SetBackdropBorderColor(r, g, b, cfg.backdrop.itemBorderColorAlpha)
else
shoptip.Backdrop:SetBackdropBorderColor(unpack(cfg.backdrop.borderColor))
end
end
end
end
end
local function HideBackdrop(frame)
if frame.NineSlice then frame.NineSlice:SetAlpha(0) end
if frame.SetBackdrop then frame:SetBackdrop(nil) end
end
local function SkinTooltip(self)
if self:IsForbidden() then
return
end
if (not self.isSkinned) then
HideBackdrop(self)
self:DisableDrawLayer("BACKGROUND")
StripTextures(self)
CreateBackdrop(self)
if self.GetBackdrop then
self.GetBackdrop = __GetBackdrop
self.GetBackdropColor = __GetBackdropColor
self.GetBackdropBorderColor = __GetBackdropBorderColor
end
self.isSkinned = true
end
end
local function OnTooltipCleared(self)
if self:IsForbidden() then return end
GameTooltip_ClearMoney(self)
GameTooltip_ClearStatusBars(self)
GameTooltip_ClearProgressBars(self)
GameTooltip_ClearWidgetSet(self)
end
-----------------------------
-- Init
-----------------------------
--hex class colors
for class, color in next, RAID_CLASS_COLORS do
classColorHex[class] = GetHexColor(color)
--if (class == 'SHAMAN') then
-- classColorHex[class] = '0070de'
--end
end
--hex reaction colors
--for idx, color in next, FACTION_BAR_COLORS do
for i = 1, #FACTION_BAR_COLORS do
factionColorHex[i] = GetHexColor(FACTION_BAR_COLORS[i])
end
cfg.targetColorHex = GetHexColor(cfg.targetColor)
cfg.afkColorHex = GetHexColor(cfg.afkColor)
GameTooltipHeaderText:SetFont(cfg.fontFamily, 14, "NONE")
GameTooltipHeaderText:SetShadowOffset(1,-2)
GameTooltipHeaderText:SetShadowColor(0,0,0,0.75)
GameTooltipText:SetFont(cfg.fontFamily, 12, "NONE")
GameTooltipText:SetShadowOffset(1,-2)
GameTooltipText:SetShadowColor(0,0,0,0.75)
Tooltip_Small:SetFont(cfg.fontFamily, 11, "NONE")
Tooltip_Small:SetShadowOffset(1,-2)
Tooltip_Small:SetShadowColor(0,0,0,0.75)
--gametooltip statusbar
GameTooltipStatusBar:ClearAllPoints()
GameTooltipStatusBar:SetPoint("LEFT",5,0)
GameTooltipStatusBar:SetPoint("RIGHT",-5, 0)
GameTooltipStatusBar:SetPoint("TOP",0,-2.5)
GameTooltipStatusBar:SetHeight(4)
--gametooltip statusbar bg
GameTooltipStatusBar.bg = GameTooltipStatusBar:CreateTexture(nil,"BACKGROUND",nil,-8)
GameTooltipStatusBar.bg:SetAllPoints()
GameTooltipStatusBar.bg:SetColorTexture(1,1,1)
GameTooltipStatusBar.bg:SetVertexColor(0,0,0,0.5)
--GameTooltipStatusBar:SetStatusBarColor()
hooksecurefunc(GameTooltipStatusBar, "SetStatusBarColor", SetStatusBarColor)
--GameTooltip_SetDefaultAnchor()
if cfg.pos then hooksecurefunc("GameTooltip_SetDefaultAnchor", SetDefaultAnchor) end
--GameTooltip_SetBackdropStyle
-- hooksecurefunc("GameTooltip_SetBackdropStyle", SetBackdropStyle)
--SharedTooltip_SetBackdropStyle
-- hooksecurefunc("SharedTooltip_SetBackdropStyle", SetBackdropStyle)
-- hooksecurefunc("GameTooltip_UnitColor", SetUnitBorderColor)
hooksecurefunc("GameTooltip_ShowCompareItem", SetCompareItemBorderColor)
hooksecurefunc("GameTooltip_ClearMoney", ResetBorderColor)
--OnTooltipSetUnit
GameTooltip:HookScript("OnTooltipSetUnit", OnTooltipSetUnit)
--OnTooltipSetItem
GameTooltip:HookScript("OnTooltipSetItem", OnTooltipSetItem)
-- loop over tooltips
local tooltips = { GameTooltip,ShoppingTooltip1,ShoppingTooltip2,ItemRefTooltip,ItemRefShoppingTooltip1,ItemRefShoppingTooltip2,WorldMapTooltip,
WorldMapCompareTooltip1,WorldMapCompareTooltip2,SmallTextTooltip,EmbeddedItemTooltip }
for i, tooltip in next, tooltips do
tooltip:SetScale(cfg.scale)
SkinTooltip(tooltip)
if tooltip:HasScript("OnTooltipCleared") then
-- tooltip:HookScript("OnTooltipCleared", SetBackdropStyle)
tooltip:HookScript("OnTooltipCleared", OnTooltipCleared)
end
end
-- SkinTooltip(GameTooltip)
-- SkinTooltip(ItemRefTooltip)
-- SkinTooltip(EmbeddedItemTooltip)
-- SkinTooltip(ShoppingTooltip1)
-- SkinTooltip(ShoppingTooltip2)
--loop over menues
local menues = {
DropDownList1MenuBackdrop,
DropDownList2MenuBackdrop,
}
for i, menu in next, menues do
menu:SetScale(cfg.scale)
end
-- compare items
if cfg.alwaysCompare then
SetCVar("alwaysCompareItems", 1)
else
SetCVar("alwaysCompareItems", 0)
end
--spellid line
--func TooltipAddSpellID
local function TooltipAddSpellID(self,spellid)
if not spellid then return end
self:AddDoubleLine("|cff0099ffspellid|r",spellid)
self:Show()
end
--hooksecurefunc GameTooltip SetUnitBuff
hooksecurefunc(GameTooltip, "SetUnitBuff", function(self,...)
TooltipAddSpellID(self,select(10,UnitBuff(...)))
end)
--hooksecurefunc GameTooltip SetUnitDebuff
hooksecurefunc(GameTooltip, "SetUnitDebuff", function(self,...)
TooltipAddSpellID(self,select(10,UnitDebuff(...)))
end)
--hooksecurefunc GameTooltip SetUnitAura
hooksecurefunc(GameTooltip, "SetUnitAura", function(self,...)
TooltipAddSpellID(self,select(10,UnitAura(...)))
end)
--hooksecurefunc SetItemRef
hooksecurefunc("SetItemRef", function(link)
local type, value = link:match("(%a+):(.+)")
if type == "spell" then
TooltipAddSpellID(ItemRefTooltip,value:match("([^:]+)"))
end
end)
--HookScript GameTooltip OnTooltipSetSpell
GameTooltip:HookScript("OnTooltipSetSpell", function(self)
TooltipAddSpellID(self,select(2,self:GetSpell()))
end)