diff --git a/Modules/Appearance.lua b/Modules/Appearance.lua
new file mode 100644
index 0000000..51a6b8e
--- /dev/null
+++ b/Modules/Appearance.lua
@@ -0,0 +1,439 @@
+local mod = StarTip:NewModule("Appearance")
+mod.name = "Appearance"
+local _G = _G
+local StarTip = _G.StarTip
+local GameTooltip = _G.GameTooltip
+local ShoppingTooltip1 = _G.ShoppingTooltip1
+local ShoppingTooltip2 = _G.ShoppingTooltip2
+local self = mod
+local LSM = _G.LibStub("LibSharedMedia-3.0")
+
+local defaults = {
+ profile = {
+ scale = 1,
+ font = StarTip:GetLSMIndexByName("font", LSM:GetDefault("font")),
+ edgeFile = StarTip:GetLSMIndexByName("border", "Blizzard Tooltip"),
+ background = StarTip:GetLSMIndexByName("background", "Blizzard Tooltip"),
+ bgColor = { -- Default colors from CowTip
+ guild = {0, 0.15, 0, 1},
+ hostilePC = {0.25, 0, 0, 1},
+ hostileNPC = {0.15, 0, 0, 1},
+ neutralNPC = {0.15, 0.15, 0, 1},
+ friendlyPC = {0, 0, 0.25, 1},
+ friendlyNPC = {0, 0, 0.15, 1},
+ other = {0, 0, 0, 1},
+ dead = {0.15, 0.15, 0.15, 1},
+ tapped = {0.25, 0.25, 0.25, 1},
+ },
+ borderColor = { 1, 1, 1, 1 },
+ padding = 4,
+ edgeSize = 16,
+ }
+}
+
+local backdropParts = {bgFile = true, edgeFile = true, edgeSize = true, background = true}
+local otherParts = {scale = "SetScale", font = "SetFont"}
+
+local get = function(info)
+ return self.db.profile[info[#info]]
+end
+
+local set = function(info, v)
+ self.db.profile[info[#info]] = v
+ if info[#info] == "bgColor" then return end
+ if backdropParts[info[#info]] then
+ self:SetBackdrop()
+ elseif info[#info] == "scale" then
+ self:SetScale()
+ else
+ self:SetFont()
+ end
+end
+
+local options = {
+ scale = {
+ name = "Scale Slider",
+ desc = "Adjust tooltip scale",
+ type = "range",
+ min = 0.25,
+ max = 4,
+ step = 0.01,
+ bigStep = 0.05,
+ isPercent = true,
+ get = get,
+ set = set,
+ order = 4
+ },
+ font = {
+ name = "Tooltip Font",
+ desc = "Set the tooltip's font",
+ type = "select",
+ values = LSM:List("font"),
+ get = get,
+ set = set,
+ order = 5
+ },
+ edgeFile = {
+ name = "Tooltip Border",
+ desc = "Set the tooltip's border style",
+ type = "select",
+ values = LSM:List("border"),
+ get = get,
+ set = set,
+ order = 6
+ },
+ background = {
+ name = "Tooltip Background",
+ desc = "Set the tooltip's background style",
+ type = "select",
+ values = LSM:List("background"),
+ get = get,
+ set = set,
+ order = 7
+ },
+ borderColor = {
+ name = "Tooltip Border Color",
+ desc = "Set the color of the tooltip's border",
+ type = "color",
+ hasAlpha = true,
+ get = function() return unpack(self.db.profile.borderColor) end,
+ set = function(info, r, g, b, a)
+ self.db.profile.borderColor[1] = r
+ self.db.profile.borderColor[2] = g
+ self.db.profile.borderColor[3] = b
+ self.db.profile.borderColor[4] = a
+ end,
+ order = 8
+ },
+ padding = {
+ name = "Tooltip Padding",
+ desc = "Set the tooltip's padding",
+ type = "range",
+ min = 0,
+ max = 20,
+ step = 1,
+ get = get,
+ set = set,
+ order = 9
+ },
+ edgeSize = {
+ name = "Tooltip Edge Size",
+ desc = "Set the tooltip's edge size",
+ type = "range",
+ min = 0,
+ max = 20,
+ step = 1,
+ get = get,
+ set = set,
+ order = 10
+ },
+ bgColor = {
+ name = "Background Color",
+ desc = "Set options for background color",
+ type = "group",
+ get = function(info)
+ return unpack(self.db.profile.bgColor[info[#info]])
+ end,
+ set = function(info, r, g, b, a)
+ self.db.profile.bgColor[info[#info]][1] = r
+ self.db.profile.bgColor[info[#info]][2] = g
+ self.db.profile.bgColor[info[#info]][3] = b
+ self.db.profile.bgColor[info[#info]][4] = a
+ self:SetBackdropColor()
+ end,
+ args = {
+ header = {
+ name = "Background Color",
+ type = "header",
+ order = 1
+ },
+ guild = {
+ name = "Guild and friends",
+ desc = "Background color for your guildmates and friends.",
+ type = "color",
+ hasAlpha = true,
+ width = "full",
+ order = 2
+ },
+ hostilePC = {
+ name = "Hostile players",
+ desc = "Background color for hostile players.",
+ type = "color",
+ hasAlpha = true,
+ width = "full",
+ order = 3
+ },
+ hostileNPC = {
+ name = "Hostile non-player characters",
+ desc = "Background color for hostile non-player characters.",
+ type = "color",
+ hasAlpha = true,
+ width = "full",
+ order = 4
+ },
+ neutralNPC = {
+ name = "Neutral non-player characters",
+ desc = "Background color for neutral non-player characters.",
+ type = "color",
+ hasAlpha = true,
+ width = "full",
+ order = 5
+ },
+ friendlyPC = {
+ name = "Friendly players",
+ desc = "Background color for friendly players.",
+ type = "color",
+ hasAlpha = true,
+ width = "full",
+ order = 6
+ },
+ friendlyNPC = {
+ name = "Friendly non-player characters",
+ desc = "Background color for friendly non-player characters.",
+ type = "color",
+ hasAlpha = true,
+ width = "full",
+ order = 7
+ },
+ dead = {
+ name = "Dead",
+ desc = "Background color for dead units.",
+ type = "color",
+ hasAlpha = true,
+ width = "full",
+ order = 8
+ },
+ tapped = {
+ name = "Tapped",
+ desc = "Background color for when a unit is tapped by another.",
+ type = "color",
+ hasAlpha = true,
+ width = "full",
+ order = 9
+ },
+ other = {
+ name = "Other Tooltips",
+ desc = "Background color for other tooltips.",
+ type = "color",
+ hasAlpha = true,
+ width = "full",
+ order = 10
+ }
+ }
+ }
+}
+
+function mod:OnInitialize()
+ self.db = StarTip.db:RegisterNamespace(self:GetName(), defaults)
+ StarTip:SetOptionsDisabled(options, true)
+ self.st1left, self.st1right, self.st2left, self.st2right = {}, {}, {}, {}
+ for i = 1, 50 do
+ ShoppingTooltip1:AddDoubleLine(' ', ' ')
+ ShoppingTooltip2:AddDoubleLine(' ', ' ')
+ self.st1left[i] = _G["ShoppingTooltip1TextLeft" .. i]
+ self.st1right[i] = _G["ShoppingTooltip1TextLeft" .. i]
+ self.st2left[i] = _G["ShoppingTooltip2TextRight" .. i]
+ self.st2right[i] = _G["ShoppingTooltip2TextRight" .. i]
+ end
+ ShoppingTooltip1:Show()
+ ShoppingTooltip1:Hide()
+ ShoppingTooltip2:Show()
+ ShoppingTooltip2:Hide()
+end
+
+function mod:OnEnable()
+ self:SetScale()
+ self:SetFont()
+ self:SetBackdrop()
+ self:SetBorderColor()
+ self:SetBackdropColor(true)
+ StarTip:SetOptionsDisabled(options, false)
+end
+
+function mod:OnDisable()
+ self:SetScale(true)
+ self:SetFont(true)
+ self:SetBorderColor(true)
+ self:SetBackdrop(true)
+ self:SetBackdropColor(true)
+ StarTip:SetOptionsDisabled(options, true)
+end
+
+function mod:GetOptions()
+ return options
+end
+
+function mod:SetUnit()
+ self.origBackdrop = self.origBackdrop or GameTooltip:GetBackdrop()
+ self.origBackdropColor = self.origBackdropColor or {GameTooltip:GetBackdropColor()}
+end
+
+function mod:OnHide()
+ self:SetBackdropColor(true)
+end
+
+function mod:OnShow()
+ self:SetBackdropColor()
+end
+
+function mod:SetScale(reset)
+ if reset then
+ GameTooltip:SetScale(1)
+ ShoppingTooltip1:SetScale(1)
+ ShoppingTooltip2:SetScale(1)
+
+ else
+ GameTooltip:SetScale(self.db.profile.scale)
+ ShoppingTooltip1:SetScale(self.db.profile.scale)
+ ShoppingTooltip2:SetScale(self.db.profile.scale)
+
+ end
+end
+
+function mod:SetFont(reset)
+ local font
+ if reset then
+ font = "Friz Quadrata TT"
+ else
+ font = LSM:Fetch('font', LSM:List("font")[self.db.profile.font])
+ end
+
+ if StarTip.leftLines[1]:GetFont() == font then
+ return
+ end
+ for i = 1, 50 do
+ local left = StarTip.leftLines[i]
+ local right = StarTip.rightLines[i]
+ local _, size, style = left:GetFont()
+ left:SetFont(font, size, style)
+ _, size, style = right:GetFont()
+ right:SetFont(font, size, style)
+
+ left = self.st1left[i]
+ right = self.st1right[i]
+ _, size, style = left:GetFont()
+ left:SetFont(font, size, style)
+ _, size, style = right:GetFont()
+ right:SetFont(font, size, style)
+
+ left = self.st2left[i]
+ right = self.st2right[i]
+ _, size, style = left:GetFont()
+ left:SetFont(font, size, style)
+ _, size, style = right:GetFont()
+ right:SetFont(font, size, style)
+ end
+end
+
+
+local tmp, tmp2 = {}, {}
+function mod:SetBackdrop()
+ if reset then
+ GameTooltip:SetBackdrop(self.origBackdrop)
+ ShoppingTooltip1:SetBackdrop(self.origBackdrop)
+ ShoppingTooltip2:SetBackdrop(self.origBackdrop)
+ else
+ local bd = GameTooltip:GetBackdrop()
+ local changed = false
+ local bgFile = LSM:Fetch('background', LSM:List('background')[self.db.profile.background])
+ local edgeFile = LSM:Fetch('border', LSM:List('border')[self.db.profile.edgeFile])
+
+ if bd.bgFile ~= bgFile or bd.edgeFile ~= edgeFile or bd.edgeSize ~= self.db.profile.edgeSize or bd.insets.left ~= self.db.profile.padding then
+ changed = true
+ end
+
+ if changed then
+ tmp.bgFile = bgFile
+ tmp.edgeFile = edgeFile
+ tmp.tile = false
+ tmp.edgeSize = self.db.profile.edgeSize
+ tmp.insets = tmp2
+ tmp2.left = self.db.profile.padding
+ tmp2.right = self.db.profile.padding
+ tmp2.top = self.db.profile.padding
+ tmp2.bottom = self.db.profile.padding
+ GameTooltip:SetBackdrop(tmp)
+ ShoppingTooltip1:SetBackdrop(tmp)
+ ShoppingTooltip2:SetBackdrop(tmp)
+ end
+ end
+end
+
+function mod:SetBackdropColor(reset)
+ if reset then
+ if self.origBackdropColor then
+ GameTooltip:SetBackdropColor(unpack(self.origBackdropColor))
+ ShoppingTooltip1:SetBackdropColor(unpack(self.origBackdropColor))
+ ShoppingTooltip2:SetBackdropColor(unpack(self.origBackdropColor))
+ else
+ GameTooltip:SetBackdropColor(0,0,0,1)
+ ShoppingTooltip1:SetBackdropColor(0,0,0,1)
+ ShoppingTooltip2:SetBackdropColor(0,0,0,1)
+ end
+ else -- Snagged from CowTip
+ local kind
+ if UnitExists("mouseover") then
+ if UnitIsDeadOrGhost("mouseover") then
+ kind = 'dead'
+ elseif UnitIsTapped("mouseover") and not UnitIsTappedByPlayer("mouseover") then
+ kind = 'tapped'
+ elseif UnitIsPlayer("mouseover") then
+ if UnitIsFriend("player", "mouseover") then
+ local playerGuild = GetGuildInfo("player")
+ if playerGuild and playerGuild == GetGuildInfo("mouseover") or UnitIsUnit("player", "mouseover") then
+ kind = 'guild'
+ else
+ local friend = false
+ local name = UnitName("mouseover")
+ for i = 1, GetNumFriends() do
+ if GetFriendInfo(i) == name then
+ friend = true
+ break
+ end
+ end
+ if friend then
+ kind = 'guild'
+ else
+ kind = 'friendlyPC'
+ end
+ end
+ else
+ kind = 'hostilePC'
+ end
+ else
+ if UnitIsFriend("player", "mouseover") then
+ kind = 'friendlyNPC'
+ else
+ local reaction = UnitReaction("mouseover", "player")
+ if not reaction or reaction <= 2 then
+ kind = 'hostileNPC'
+ else
+ kind = 'neutralNPC'
+ end
+ end
+ end
+ else
+ kind = 'other'
+ end
+ GameTooltip:SetBackdropColor(unpack(self.db.profile.bgColor[kind]))
+ if kind == 'other' then
+ ShoppingTooltip1:SetBackdropColor(unpack(self.db.profile.bgColor[kind]))
+ ShoppingTooltip2:SetBackdropColor(unpack(self.db.profile.bgColor[kind]))
+ end
+ end
+end
+
+function mod:SetBorderColor(reset)
+ if reset then
+ GameTooltip:SetBackdropBorderColor(1,1,1,1)
+ ShoppingTooltip1:SetBackdropBorderColor(1,1,1,1)
+ ShoppingTooltip2:SetBackdropBorderColor(1,1,1,1)
+ else
+ GameTooltip:SetBackdropBorderColor(unpack(self.db.profile.borderColor))
+ ShoppingTooltip1:SetBackdropBorderColor(unpack(self.db.profile.borderColor))
+ ShoppingTooltip2:SetBackdropBorderColor(unpack(self.db.profile.borderColor))
+ end
+end
+
+
+
diff --git a/Modules/Bars.lua b/Modules/Bars.lua
new file mode 100644
index 0000000..f7b8a81
--- /dev/null
+++ b/Modules/Bars.lua
@@ -0,0 +1,217 @@
+local mod = StarTip:NewModule("Bars", "AceTimer-3.0")
+mod.name = "Bars"
+local _G = _G
+local StarTip = _G.StarTip
+local GameTooltip = _G.GameTooltip
+local GameTooltipStatusBar = _G.GameTooltipStatusBar
+local UnitIsPlayer = _G.UnitIsPlayer
+local RAID_CLASS_COLORS = _G.RAID_CLASS_COLORS
+local UnitSelectionColor = _G.UnitSelectionColor
+local UnitClass = _G.UnitClass
+local self = mod
+local timer
+local LSM = _G.LibStub("LibSharedMedia-3.0")
+
+local defaults = {
+ profile = {
+ showHP = true,
+ showMP = true,
+ hpTexture = StarTip:GetLSMIndexByName("statusbar", LSM:GetDefault("statusbar")),
+ mpTexture = StarTip:GetLSMIndexByName("statusbar", LSM:GetDefault("statusbar")),
+ useGradient = false,
+ }
+}
+
+local options = {
+ hpBar = {
+ name = "HP Bar",
+ type = "group",
+ args = {
+ show = {
+ name = "Show",
+ desc = "Toggle showing the HP bar",
+ type = "toggle",
+ get = function() return self.db.profile.showHP end,
+ set = function(info, v) self.db.profile.showHP = v end,
+ order = 1
+ },
+ useGradient = {
+ name = "Use Gradient",
+ desc = "Set whether to use a gradient based on unit health",
+ type = "toggle",
+ get = function() return self.db.profile.useGradient end,
+ set = function(info, v) self.db.profile.useGradient = v end,
+ order = 3
+ },
+ texture = {
+ name = "Texture",
+ desc = "Change the status bar's texture",
+ type = "select",
+ values = LSM:List("statusbar"),
+ get = function() return self.db.profile.hpTexture end,
+ set = function(info, v)
+ self.db.profile.hpTexture = v
+ self.hpBar:SetStatusBarTexture(LSM:Fetch("statusbar", LSM:List("statusbar")[v]))
+ end,
+ order = 2
+ },
+ }
+ },
+ mpBar = {
+ name = "MP Bar",
+ type = "group",
+ args = {
+ show = {
+ name = "Show",
+ desc = "Toggle showing the MP bar",
+ type = "toggle",
+ get = function() return self.db.profile.showMP end,
+ set = function(info, v) self.db.profile.showMP = v end,
+ order = 1
+ },
+ texture = {
+ name = "Texture",
+ desc = "Change the status bar's texture",
+ type = "select",
+ values = LSM:List("statusbar"),
+ get = function() return self.db.profile.mpTexture end,
+ set = function(info, v)
+ self.db.profile.mpTexture = v
+ self.mpBar:SetStatusBarTexture(LSM:Fetch("statusbar", LSM:List("statusbar")[v]))
+ end,
+ order = 2
+ }
+ }
+ }
+}
+
+
+function mod:OnInitialize()
+ self.db = StarTip.db:RegisterNamespace(self:GetName(), defaults)
+
+ local hpBar = CreateFrame("StatusBar", nil, GameTooltip)
+ hpBar:SetStatusBarTexture(LSM:Fetch("statusbar", LSM:List("statusbar")[self.db.profile.hpTexture]))
+ hpBar:SetPoint("BOTTOMLEFT", GameTooltip, "TOPLEFT")
+ hpBar:SetPoint("LEFT", GameTooltip, "LEFT")
+ hpBar:SetPoint("RIGHT", GameTooltip, "RIGHT")
+ hpBar:SetHeight(5)
+ hpBar:Hide()
+ self.hpBar = hpBar
+
+ local mpBar = CreateFrame("StatusBar", nil, GameTooltip)
+ mpBar:SetStatusBarTexture(LSM:Fetch("statusbar", LSM:List("statusbar")[self.db.profile.mpTexture]))
+ mpBar:SetPoint("TOPLEFT", GameTooltip, "BOTTOMLEFT")
+ mpBar:SetPoint("LEFT")
+ mpBar:SetPoint("RIGHT")
+ mpBar:SetHeight(5)
+ mpBar:Hide()
+ self.mpBar = mpBar
+
+ StarTip:SetOptionsDisabled(options, true)
+end
+
+function mod:OnEnable()
+ local top, bottom = 0, 0
+ if self.db.profile.showHP then
+ top = 5
+ end
+ if self.db.profile.showMP then
+ bottom = -5
+ end
+ GameTooltip:SetClampRectInsets(0, 0, top, bottom)
+ StarTip:SetOptionsDisabled(options, false)
+end
+
+function mod:OnDisable()
+ GameTooltip:SetClampRectInsets(0, 0, 0, 0)
+ StarTip:SetOptionsDisabled(options, true)
+end
+
+function mod:GetOptions()
+ return options
+end
+
+local function updateBars()
+ if self.db.profile.showHP then self:UpdateHealth() end
+ if self.db.profile.showMP then self:UpdateMana() end
+end
+
+function mod:SetUnit()
+ GameTooltipStatusBar:Hide()
+ updateBars()
+ if self.db.profile.showHP then self.hpBar:Show() end
+ if self.db.profile.showMP then self.mpBar:Show() end
+ timer = timer or self:ScheduleRepeatingTimer(updateBars, .5)
+end
+
+function mod:OnHide()
+ if timer then
+ self:CancelTimer(timer)
+ timer = nil
+ end
+ self.hpBar:Hide()
+ self.mpBar:Hide()
+end
+
+local function colorGradient(perc)
+ if perc <= 0.5 then
+ return 1, perc*2, 0
+ else
+ return 2 - perc*2, 1, 0
+ end
+end
+
+-- Colors, snagged from oUF
+local power = {
+ [0] = { r = 48/255, g = 113/255, b = 191/255}, -- Mana
+ [1] = { r = 226/255, g = 45/255, b = 75/255}, -- Rage
+ [2] = { r = 255/255, g = 178/255, b = 0}, -- Focus
+ [3] = { r = 1, g = 1, b = 34/255}, -- Energy
+ [4] = { r = 0, g = 1, b = 1}, -- Happiness
+ [5] = {}, --Unknown
+ [6] = { r = 0.23, g = 0.12, b = 0.77 } -- Runic Power
+}
+local health = {
+ [0] = {r = 49/255, g = 207/255, b = 37/255}, -- Health
+ [1] = {r = .6, g = .6, b = .6} -- Tapped targets
+}
+local happiness = {
+ [1] = {r = 1, g = 0, b = 0}, -- need.... | unhappy
+ [2] = {r = 1 ,g = 1, b = 0}, -- new..... | content
+ [3] = {r = 0, g = 1, b = 0}, -- colors.. | happy
+}
+
+-- Logic snagged from oUF
+function mod:UpdateHealth()
+ local unit = "mouseover"
+ if not UnitExists(unit) then return end
+ local min, max = UnitHealth(unit), UnitHealthMax(unit)
+ self.hpBar:SetMinMaxValues(0, max)
+ self.hpBar:SetValue(min)
+
+ local color
+ if self.db.profile.useGradient then
+ color = {}
+ color.r, color.g, color.b = colorGradient(min/max)
+ elseif(UnitIsTapped(unit) and not UnitIsTappedByPlayer(unit) or not UnitIsConnected(unit)) then
+ color = health[1]
+ elseif UnitIsPlayer(unit) then
+ color = RAID_CLASS_COLORS[select(2, UnitClass(unit))]
+ else
+ color = {}
+ color.r, color.g, color.b = UnitSelectionColor(unit)
+ end
+ if not color then color = health[0] end
+ self.hpBar:SetStatusBarColor(color.r, color.g, color.b)
+end
+
+function mod:UpdateMana()
+ local unit = "mouseover"
+ if not UnitExists(unit) then return end
+ local min, max = UnitMana(unit), UnitManaMax(unit)
+ self.mpBar:SetMinMaxValues(0, max)
+ self.mpBar:SetValue(min)
+
+ local color = power[UnitPowerType(unit)]
+ self.mpBar:SetStatusBarColor(color.r, color.g, color.b)
+end
diff --git a/Modules/Fade.lua b/Modules/Fade.lua
new file mode 100644
index 0000000..be7d0ae
--- /dev/null
+++ b/Modules/Fade.lua
@@ -0,0 +1,201 @@
+local mod = StarTip:NewModule("Fade", "AceHook-3.0")
+mod.name = "Fade"
+local _G = _G
+local GameTooltip = _G.GameTooltip
+local StarTip = _G.StarTip
+local UnitExists = _G.UnitExists
+local self = mod
+
+local defaults = {
+ profile = {
+ unitFrames = 1,
+ otherFrames = 1,
+ units = 2,
+ objects = 2,
+ }
+}
+
+local choices = {
+ "Hide",
+ "Fade out"
+}
+
+local get = function(info)
+ return self.db.profile[info[#info]]
+end
+
+local set = function(info, v)
+ self.db.profile[info[#info]] = v
+end
+
+local options = {
+ units = {
+ name = "World Units",
+ desc = "What to do with tooltips for world frames",
+ type = "select",
+ values = choices,
+ get = get,
+ set = set,
+ order = 4
+ },
+ unitFrames = {
+ name = "Unit Frames",
+ desc = "What to do with tooltips for unit frames",
+ type = "select",
+ values = choices,
+ get = get,
+ set = set,
+ order = 5
+ },
+ otherFrames = {
+ name = "Other Frames",
+ desc = "What to do with tooltips for other frames (spells, macros, items, etc..)",
+ type = "select",
+ values = choices,
+ get = get,
+ set = set,
+ order = 6
+ },
+ objects = {
+ name = "World Objects",
+ desc = "What to do with tooltips for world objects (mailboxes, portals, etc..)",
+ type = "select",
+ values = choices,
+ get = get,
+ set = set,
+ order = 7
+ }
+}
+
+function mod:OnInitialize()
+ self.db = StarTip.db:RegisterNamespace(self:GetName(), defaults)
+ StarTip:SetOptionsDisabled(options, true)
+end
+
+function mod:OnEnable()
+ self:RawHook(GameTooltip, "FadeOut", "GameTooltipFadeOut", true)
+ self:RawHook(GameTooltip, "Hide", "GameTooltipHide", true)
+ StarTip:SetOptionsDisabled(options, false)
+end
+
+function mod:OnDisable()
+ self:Unhook(GameTooltip, "FadeOut")
+ self:Unhook(GameTooltip, "Hide")
+ StarTip:SetOptionsDisabled(options, true)
+ if timer then
+ self:CancelTimer(timer)
+ timer = nil
+ end
+end
+
+function mod:GetOptions()
+ return options
+end
+
+-- CowTip's solution below
+local updateExistenceFrame = CreateFrame("Frame")
+local updateAlphaFrame = CreateFrame("Frame")
+
+local checkExistence = function()
+ if not UnitExists("mouseover") then
+ updateExistenceFrame:SetScript("OnUpdate", nil)
+ local kind
+ if GameTooltip:IsOwned(UIParent) then
+ kind = self.db.profile.units
+ else
+ kind = self.db.profile.unitFrames
+ end
+ if kind == 2 then
+ GameTooltip:FadeOut()
+ else
+ GameTooltip:Hide()
+ end
+ end
+end
+
+local checkTooltipAlpha = function()
+ if GameTooltip:GetAlpha() < 1 then
+ updateAlphaFrame:SetScript("OnUpdate", nil)
+ local kind
+ if GameTooltip:IsOwned(UIParent) then
+ kind = self.db.profile.objects
+ else
+ kind = self.db.profile.otherFrames
+ end
+ if kind == 2 then
+ GameTooltip:FadeOut()
+ else
+ GameTooltip:Hide()
+ end
+ end
+end
+
+function mod:OnShow()
+ if UnitExists("mouseover") then
+ updateExistenceFrame:SetScript("OnUpdate", checkExistence)
+ else
+ updateAlphaFrame:SetScript("OnUpdate", checkTooltipAlpha)
+ end
+end
+
+function mod:GameTooltipFadeOut(this, ...)
+ if self.justFade then
+ self.justFade = nil
+ self.hooks[this].FadeOut(this, ...)
+ return
+ end
+ local kind
+ if self.isUnit then
+ if GameTooltip:IsOwned(UIParent) then
+ kind = self.db.profile.units
+ else
+ kind = self.db.profile.unitFrames
+ end
+ self.isUnit = nil
+ else
+ if GameTooltip:IsOwned(UIParent) then
+ kind = self.db.profile.objects
+ else
+ kind = self.db.profile.otherFrames
+ end
+ end
+ if kind == 2 then
+ self.hooks[this].FadeOut(this, ...)
+ else
+ self.justHide = true
+ GameTooltip:Hide()
+ end
+end
+
+function mod:GameTooltipHide(this, ...)
+ if self.justHide then
+ self.justHide = nil
+ return self.hooks[this].Hide(this, ...)
+ end
+ local kind
+ if self.isUnit then
+ if GameTooltip:IsOwned(UIParent) then
+ kind = self.db.profile.units
+ else
+ kind = self.db.profile.unitFrames
+ end
+ self.isUnit = nil
+ else
+ if GameTooltip:IsOwned(UIParent) then
+ kind = self.db.profile.objects
+ else
+ kind = self.db.profile.otherFrames
+ end
+ end
+ if kind == 2 then
+ self.justFade = true
+ return GameTooltip:FadeOut()
+ else
+ return self.hooks[this].Hide(this, ...)
+ end
+end
+
+function mod:SetUnit()
+ self.isUnit = true
+end
+
diff --git a/Modules/Position.lua b/Modules/Position.lua
new file mode 100644
index 0000000..7ac613b
--- /dev/null
+++ b/Modules/Position.lua
@@ -0,0 +1,364 @@
+local mod = StarTip:NewModule("Position", "AceEvent-3.0", "AceHook-3.0")
+mod.name = "Positioning and Hiding"
+local _G = _G
+local GameTooltip = _G.GameTooltip
+local StarTip = _G.StarTip
+local UIParent = _G.UIParent
+local self = mod
+
+local defaults = {
+ profile = {
+ inCombat = 1,
+ anchor = 1,
+ unitFrames = 13,
+ other = 1,
+ inCombatXOffset = 0,
+ inCombatYOffset = 0,
+ anchorXOffset = 0,
+ anchorYOffset = 0,
+ unitFramesXOffset = 0,
+ unitFramesYOffset = 0,
+ otherXOffset = 0,
+ otherYOffset = 0
+ }
+}
+
+local anchors = {
+ "CURSOR_TOP",
+ "CURSOR_TOPRIGHT",
+ "CURSOR_TOPLEFT",
+ "CURSOR_BOTTOM",
+ "CURSOR_BOTTOMRIGHT",
+ "CURSOR_BOTTOMLEFT",
+ "CURSOR_LEFT",
+ "CURSOR_RIGHT",
+ "TOP",
+ "TOPRIGHT",
+ "TOPLEFT",
+ "BOTTOM",
+ "BOTTOMRIGHT",
+ "BOTTOMLEFT",
+ "RIGHT",
+ "LEFT",
+ "CENTER"
+}
+
+local anchorText = {
+ "Cursor Top",
+ "Cursor Top-right",
+ "Cursor Top-left",
+ "Cursor Bottom",
+ "Cursor Bottom-right",
+ "Cursor Bottom-left",
+ "Cursor Left",
+ "Cursor Right",
+ "Screen Top",
+ "Screen Top-right",
+ "Screen Top-left",
+ "Screen Bottom",
+ "Screen Bottom-right",
+ "Screen Bottom-left",
+ "Screen Right",
+ "Screen Left",
+ "Screen Center"
+}
+
+local opposites = {
+ TOP = "BOTTOM",
+ TOPRIGHT = "BOTTOMLEFT",
+ TOPLEFT = "BOTTOMRIGHT",
+ BOTTOM = "TOP",
+ BOTTOMRIGHT = "TOPLEFT",
+ BOTTOMLEFT = "TOPRIGHT",
+ LEFT = "RIGHT",
+ RIGHT = "LEFT",
+}
+
+local selections = {}
+for i, v in ipairs(anchorText) do
+ selections[i] = v
+end
+selections[#selections+1] = "Hide"
+
+local get = function(info)
+ return self.db.profile[info[#info]]
+end
+
+local set = function(info,v)
+ self.db.profile[info[#info]] = v
+end
+
+local minX = -math.floor(GetScreenWidth()/5 + 0.5) * 5
+local minY = -math.floor(GetScreenHeight()/5 + 0.5) * 5
+local maxX = math.floor(GetScreenWidth()/5 + 0.5) * 5
+local maxY = math.floor(GetScreenHeight()/5 + 0.5) * 5
+local options = {
+ anchor = {
+ name = "World Units",
+ desc = "Where to anchor the tooltip when mousing over world characters",
+ type = "select",
+ values = selections,
+ get = get,
+ set = set,
+ order = 4
+ },
+ anchorXOffset = {
+ name = "X-axis offset",
+ desc = "The x-axis offset used to position the tooltip in relationship to the anchor point",
+ type = "range",
+ min = minX,
+ max = maxX,
+ step = 1,
+ bigStep = 5,
+ get = get,
+ set = set,
+ order = 5
+ },
+ anchorYOffset = {
+ name = "Y-axis offset",
+ desc = "The y-axis offset used to position the tooltip in relationship to the anchor point",
+ type = "range",
+ min = minY,
+ max = maxY,
+ step = 1,
+ bigStep = 5,
+ get = get,
+ set = set,
+ order = 6
+
+ },
+ inCombatHeader = {
+ name = "",
+ type = "header",
+ order = 7
+ },
+ inCombat = {
+ name = "In Combat",
+ desc = "Where to anchor the world unit tooltip while in combat",
+ type = "select",
+ values = selections,
+ get = get,
+ set = set,
+ order = 8
+ },
+ inCombatXOffset = {
+ name = "X-axis offset",
+ desc = "The x-axis offset used to position the tooltip in relationship to the anchor point",
+ type = "range",
+ min = minX,
+ max = maxX,
+ step = 1,
+ bigStep = 5,
+ get = get,
+ set = set,
+ order = 9
+ },
+ inCombatYOffset = {
+ name = "Y-axis offset",
+ desc = "The y-axis offset used to position the tooltip in relationship to the anchor point",
+ type = "range",
+ min = minY,
+ max = maxY,
+ step = 1,
+ bigStep = 5,
+ get = get,
+ set = set,
+ order = 10
+ },
+ unitFramesHeader = {
+ name = "",
+ type = "header",
+ order = 11
+ },
+ unitFrames = {
+ name = "Unit Frames",
+ desc = "Where to anchor the tooltip when mousing over a unit frame",
+ type = "select",
+ values = selections,
+ get = get,
+ set = set,
+ order = 12
+ },
+ unitFramesXOffset = {
+ name = "X-axis offset",
+ desc = "The x-axis offset used to position the tooltip in relationship to the anchor point",
+ type = "range",
+ min = minX,
+ max = maxX,
+ step = 1,
+ bigStep = 5,
+ get = get,
+ set = set,
+ order = 13
+ },
+ unitFramesYOffset = {
+ name = "Y-axis offset",
+ desc = "The y-axis offset used to position the tooltip in relationship to the anchor point",
+ type = "range",
+ min = minY,
+ max = maxY,
+ step = 1,
+ bigStep = 5,
+ get = get,
+ set = set,
+ order = 14
+ },
+ otherHeader = {
+ name = "",
+ type = "header",
+ order = 15
+ },
+ other = {
+ name = "Other tooltips",
+ desc = "Where to anchor tooltips that are not unit tooltips",
+ type = "select",
+ values = selections,
+ get = get,
+ set = set,
+ order = 16
+ },
+ otherXOffset = {
+ name = "X-axis offset",
+ desc = "The x-axis offset used to position the tooltip in relationship to the anchor point",
+ type = "range",
+ min = minX,
+ max = maxX,
+ step = 1,
+ bigStep = 5,
+ get = get,
+ set = set,
+ order = 17
+ },
+ otherYOffset = {
+ name = "Y-axis offset",
+ desc = "The y-axis offset used to position the tooltip in relationship to the anchor point",
+ type = "range",
+ min = minY,
+ max = maxY,
+ step = 1,
+ bigStep = 5,
+ get = get,
+ set = set,
+ order = 18
+ }
+}
+
+function mod:OnInitialize()
+ self.db = StarTip.db:RegisterNamespace(self:GetName(), defaults)
+ StarTip:SetOptionsDisabled(options, true)
+end
+
+function mod:OnEnable()
+ self:RegisterEvent("REGEN_DISABLED")
+ self:RegisterEvent("REGEN_ENABLED")
+ self:SecureHook("GameTooltip_SetDefaultAnchor")
+ StarTip:SetOptionsDisabled(options, false)
+end
+
+function mod:OnDisable()
+ self:UnregisterEvent("REGEN_DISABLED")
+ self:UnregisterEvent("REGEN_ENABLED")
+ self:Unhook("GameTooltip_SetDefaultAnchor")
+ StarTip:SetOptionsDisabled(options, true)
+end
+
+function mod:GetOptions()
+ return options
+end
+
+local updateFrame = CreateFrame("Frame")
+local oldX, oldY
+local currentAnchor
+local xoffset, yoffset
+local positionTooltip = function()
+ local x, y = GetCursorPosition()
+ local effScale = GameTooltip:GetEffectiveScale()
+ if x ~= oldX or y ~= oldY then
+ GameTooltip:ClearAllPoints()
+ GameTooltip:SetPoint(currentAnchor, UIParent, "BOTTOMLEFT", (x + xoffset) / effScale, (y + yoffset) / effScale)
+ end
+ oldX, oldY = x, y
+end
+
+local getIndex = function(owner)
+ local index
+ if UnitExists("mouseover") then
+ if InCombatLockdown() then
+ index = self.db.profile.inCombat
+ elseif owner == UIParent then
+ index = self.db.profile.anchor
+ else
+ index = self.db.profile.unitFrames
+ end
+ else
+ index = self.db.profile.other
+ end
+ return index
+end
+
+local setOffsets = function(owner)
+ if owner == UIParent then
+ if UnitExists("mouseover") then
+ if InCombatLockdown() then
+ xoffset = self.db.profile.inCombatXOffset
+ yoffset = self.db.profile.inCombatYOffset
+ else
+ xoffset = self.db.profile.anchorXOffset
+ yoffset = self.db.profile.anchorYOffset
+ end
+ else
+ xoffset = self.db.profile.otherXOffset
+ yoffset = self.db.profile.otherYOffset
+ end
+ else
+ if UnitExists("mouseover") then
+ xoffset = self.db.profile.unitFramesXOffset
+ yoffset = self.db.profile.unitFramesYOffset
+ else
+ xoffset = self.db.profile.otherXOffset
+ yoffset = self.db.profile.otherYOffset
+ end
+ end
+end
+
+local currentOwner
+local currentThis
+local f = CreateFrame("Frame")
+local function delayAnchor()
+ f:SetScript("OnUpdate", nil)
+ local this = currentThis
+ local owner = currentOwner
+ this:ClearAllPoints()
+ setOffsets(owner)
+ local index = getIndex(owner)
+ if index == #selections then
+ this:Hide()
+ return
+ elseif anchors[index]:find("^CURSOR_") then
+ oldX, oldY = 0, 0
+ currentAnchor = opposites[anchors[index]:sub(8)]
+ updateFrame:SetScript("OnUpdate", positionTooltip)
+ positionTooltip()
+ else
+ if updateFrame:GetScript("OnUpdate") then updateFrame:SetScript("OnUpdate", nil) end
+ this:SetPoint(anchors[index], UIParent, anchors[index], xoffset, yoffset)
+ end
+end
+
+function mod:GameTooltip_SetDefaultAnchor(this, owner)
+ currentOwner = owner
+ currentThis = this
+ if not f:GetScript("OnUpdate") then f:SetScript("OnUpdate", delayAnchor) end
+end
+
+function mod:REGEN_DISABLED()
+ if not currentOwner then return end
+ updateFrame:SetScript("OnUpdate", nil)
+ self:GameTooltip_SetDefaultAnchor(GameTooltip, currentOwner)
+end
+
+mod.REGEN_ENABLED = mod.REGEN_DISABLED
+
+function mod:OnHide()
+ updateFrame:SetScript("OnUpdate", nil)
+end
diff --git a/Modules/PvP.lua b/Modules/PvP.lua
new file mode 100644
index 0000000..c458f0d
--- /dev/null
+++ b/Modules/PvP.lua
@@ -0,0 +1,48 @@
+local mod = StarTip:NewModule("PvP", "AceEvent-3.0")
+mod.name = "PvP"
+local _G = _G
+local GameTooltip = _G.GameTooltip
+local UnitFactionGroup = _G.UnitFactionGroup
+local self = mod
+
+function mod:OnInitialize()
+ self.db = StarTip.db:RegisterNamespace(self:GetName(), defaults)
+ local frame = _G.CreateFrame("Frame", nil, GameTooltip)
+ local pvp = frame:CreateTexture(nil, "OVERLAY")
+ pvp:SetHeight(30)
+ pvp:SetWidth(30)
+ pvp:SetPoint("TOPRIGHT", GameTooltip, 20, 10)
+ pvp:Hide()
+ self.PvP = pvp
+end
+
+function mod:OnEnable()
+ self:RegisterEvent("UNIT_FACTION")
+end
+
+function mod:OnDisable()
+ self:UnregisterEvent("UNIT_FACTION")
+end
+
+function mod:UNIT_FACTION(event, unit)
+ if unit ~= "mouseover" then return end
+
+ local factionGroup = UnitFactionGroup(unit)
+ if(UnitIsPVPFreeForAll(unit)) then
+ self.PvP:SetTexture[[Interface\TargetingFrame\UI-PVP-FFA]]
+ self.PvP:Show()
+ elseif(factionGroup and UnitIsPVP(unit)) then
+ self.PvP:SetTexture([[Interface\TargetingFrame\UI-PVP-]]..factionGroup)
+ self.PvP:Show()
+ else
+ self.PvP:Hide()
+ end
+end
+
+function mod:SetUnit()
+ self:UNIT_FACTION(nil, "mouseover")
+end
+
+function mod:OnHide()
+ self.PvP:Hide()
+end
diff --git a/Modules/RaidIcon.lua b/Modules/RaidIcon.lua
new file mode 100644
index 0000000..bc7f51a
--- /dev/null
+++ b/Modules/RaidIcon.lua
@@ -0,0 +1,47 @@
+local mod = StarTip:NewModule("RaidIcon", "AceEvent-3.0")
+mod.name = "RaidIcon"
+local _G = _G
+local GameTooltip = _G.GameTooltip
+local GetRaidTargetIndex = _G.GetRaidTargetIndex
+local SetRaidTargetIconTexture = _G.SetRaidTargetIconTexture
+local self = mod
+
+function mod:OnInitialize()
+ self.db = StarTip.db:RegisterNamespace(self:GetName(), defaults)
+ local frame = CreateFrame("Frame", nil, GameTooltip)
+ local icon = frame:CreateTexture(nil, "OVERLAY")
+ icon:SetHeight(16)
+ icon:SetWidth(16)
+ icon:SetPoint("TOP", GameTooltip, 0, 4)
+ icon:SetTexture"Interface\\TargetingFrame\\UI-RaidTargetingIcons"
+ icon:Hide()
+ self.icon = icon
+end
+
+function mod:OnEnable()
+ self:RegisterEvent("RAID_TARGET_UPDATE")
+end
+
+function mod:OnDisable()
+ self:UnregisterEvent("RAID_TARGET_UPDATE")
+end
+
+function mod:SetUnit()
+ self:RAID_TARGET_UPDATE()
+end
+
+function mod:OnHide()
+ if self.icon:IsShown() then self.icon:Hide() end
+end
+
+function mod:RAID_TARGET_UPDATE(event)
+ local index = _G.GetRaidTargetIndex("mouseover")
+
+ if(index) then
+ _G.SetRaidTargetIconTexture(self.icon, index)
+ self.icon:Show()
+ else
+ self.icon:Hide()
+ end
+end
+
diff --git a/Modules/Targeting.lua b/Modules/Targeting.lua
new file mode 100644
index 0000000..a6e400c
--- /dev/null
+++ b/Modules/Targeting.lua
@@ -0,0 +1,34 @@
+local mod = StarTip:NewModule("Targeting", "AceEvent-3.0")
+mod.name = "Targeting"
+local _G = _G
+local GameTooltip = _G.GameTooltip
+local UnitFactionGroup = _G.UnitFactionGroup
+local RAID_CLASS_COLORS = _G.RAID_CLASS_COLORS
+local StarTip = _G.StarTip
+local self = mod
+
+function mod:OnInitialize()
+end
+
+function mod:OnEnable()
+end
+
+function mod:OnDisable()
+end
+
+function mod:SetUnit()
+ if UnitInRaid("player") then
+ local txt = ''
+ for i=1, GetNumRaidMembers() do
+ if UnitExists("mouseover") and UnitGUID("mouseover") == UnitGUID("raid" .. i .. "target") then
+ local c = RAID_CLASS_COLORS[select(2, UnitClass("raid" .. i))]
+ local name = UnitName("raid" .. i)
+ txt = txt .. ("|cFF%02x%02x%02x%s|r "):format(c.r*255, c.g*255, c.b*255, name)
+ end
+ end
+ if txt ~= '' then
+ GameTooltip:AddLine("Targeting: " .. txt, .5, .5, 1, 1)
+ end
+ end
+end
+
diff --git a/Modules/Text.lua b/Modules/Text.lua
new file mode 100644
index 0000000..0190883
--- /dev/null
+++ b/Modules/Text.lua
@@ -0,0 +1,730 @@
+local mod = StarTip:NewModule("Text", "AceTimer-3.0", "AceEvent-3.0")
+mod.name = "Text"
+local _G = _G
+local GameTooltip = _G.GameTooltip
+local StarTip = _G.StarTip
+local self = mod
+local GameTooltip = _G.GameTooltip
+local tinsert = _G.tinsert
+local unpack = _G.unpack
+local select = _G.select
+local format = _G.format
+local floor = _G.floor
+local tostring = _G.tostring
+local UnitExists = _G.UnitExists
+local UnitIsPlayer = _G.UnitIsPlayer
+local UnitBuff = _G.UnitBuff
+local GetSpellInfo = _G.GetSpellInfo
+local UnitIsConnected = _G.UnitIsConnected
+local UnitIsFeignDeath = _G.UnitIsFeignDeath
+local UnitIsGhost = _G.UnitIsGhost
+local UnitIsDead = _G.UnitIsDead
+local UnitLevel = _G.UnitLevel
+local UnitClassification = _G.UnitClassification
+local UnitSelectionColor = _G.UnitSelectionColor
+local UnitRace = _G.UnitRace
+local GetNumTalentTabs = _G.GetNumTalentTabs
+local GetTalentTabInfo = _G.GetTalentTabInfo
+local GetGuildInfo = _G.GetGuildInfo
+local UnitName = _G.UnitName
+local UnitClass = _G.UnitClass
+local UnitMana = _G.UnitMana
+local UnitManaMax = _G.UnitManaMax
+local UnitFactionGroup = _G.UnitFactionGroup
+local UnitCreatureFamily = _G.UnitCreatureFamily
+local UnitCreatureType = _G.UnitCreatureType
+local UnitIsUnit = _G.UnitIsUnit
+local RAID_CLASS_COLORS = _G.RAID_CLASS_COLORS
+local timer, talentTimer
+local TalentQuery = LibStub:GetLibrary("LibTalentQuery-1.0", true)
+local TalentGuess = LibStub:GetLibrary("TalentGuess-1.0", true) and LibStub:GetLibrary("TalentGuess-1.0"):Register()
+local spec = setmetatable({}, {__mode='v'})
+local factionList = {}
+local linesToAdd = {}
+local linesToAddR = {}
+local linesToAddG = {}
+local linesToAddB = {}
+local linesToAddRight = {}
+local linesToAddRightR = {}
+local linesToAddRightG = {}
+local linesToAddRightB = {}
+local unitLocation
+local unitName
+local unitGuild
+local NUM_LINES
+
+-- Thanks to ckknight for this
+local short = function(value)
+ if value >= 10000000 or value <= -10000000 then
+ value = ("%.1fm"):format(value / 1000000)
+ elseif value >= 1000000 or value <= -1000000 then
+ value = ("%.2fm"):format(value / 1000000)
+ elseif value >= 100000 or value <= -100000 then
+ value = ("%.0fk"):format(value / 1000)
+ elseif value >= 10000 or value <= -10000 then
+ value = ("%.1fk"):format(value / 1000)
+ else
+ value = tostring(floor(value+0.5))
+ end
+ return value
+end
+
+local classifications = {
+ worldboss = "Boss",
+ rareelite = "+ Rare",
+ elite = "+",
+ rare = "Rare"
+}
+
+local talentTrees = {
+ ["Druid"] = {"Balance", "Feral Combat", "Restoration"},
+ ["Hunter"] = {"Beast Mastery", "Marksmanship", "Survival"},
+ ["Mage"] = {"Arcane", "Fire", "Frost"},
+ ["Paladin"] = {"Holy", "Protection", "Retribution"},
+ ["Priest"] = {"Discipline", "Holy", "Shadow"},
+ ["Rogue"] = {"Assassination", "Combat", "Subtlety"},
+ ["Shaman"] = {"Elemental", "Enhancement", "Restoration"},
+ ["Warlock"] = {"Affliction", "Demonology", "Destruction"},
+ ["Warrior"] = {"Arms", "Fury", "Protection"},
+}
+
+local powers = {
+ ["WARRIOR"] = "Rage:",
+ ["ROGUE"] = "Energy:",
+}
+
+powers = setmetatable(powers, {__index=function(self,key)
+ if type(key) == nil then return nil end
+ if rawget(self,key) then
+ return self[key]
+ else
+ return "Mana:"
+ end
+end})
+
+local updateTalents = function()
+ if not UnitExists("mouseover") then
+ self:CancelTimer(talentTimer)
+ talentTimer = nil
+ return
+ end
+ local nameRealm = select(1, UnitName("mouseover")) .. (select(2, UnitName("mouseover")) or '')
+ if spec[nameRealm] and spec[nameRealm][4] and spec[nameRealm][1] and spec[nameRealm][2] and spec[nameRealm][3] then
+ local specText = ('%s (%d/%d/%d)'):format(spec[nameRealm][4], spec[nameRealm][1], spec[nameRealm][2], spec[nameRealm][3])
+ local lineNum
+ if NUM_LINES < GameTooltip:NumLines() then
+ lineNum = NUM_LINES + 1
+ local j = 0
+ for i = lineNum, GameTooltip:NumLines() do
+ local left = mod.leftLines[i]
+ j = j + 1
+ linesToAdd[j] = left:GetText()
+ local r, g, b = left:GetTextColor()
+ linesToAddR[j] = r
+ linesToAddG[j] = g
+ linesToAddB[j] = b
+ local right = mod.rightLines[i]
+ if right:IsShown() then
+ linesToAddRight[j] = right:GetText()
+ local r, g, b = right:GetTextColor()
+ linesToAddRightR[j] = r
+ linesToAddRightG[j] = g
+ linesToAddRightB[j] = b
+ end
+ end
+ else
+ lineNum = GameTooltip:NumLines() + 1
+ end
+ local replaced
+ for i = 1, GameTooltip:NumLines() do
+ if mod.leftLines[i]:GetText() == "Talents Guessed:" then
+ lineNum = i
+ replaced = true
+ end
+ end
+ if not replaced then
+ GameTooltip:AddDoubleLine(' ', ' ')
+ end
+ local left = mod.leftLines[lineNum]
+ local right = mod.rightLines[lineNum]
+ left:SetText("Talents:")
+ right:SetText(specText)
+ if not right:IsShown() then
+ right:Show()
+ end
+ left:SetTextColor(1, 1, 1)
+ right:SetTextColor(1, 1, 1)
+
+ for i=1, #linesToAdd do
+ local left = mod.leftLines[i + lineNum]
+ left:SetText(linesToAdd[i])
+ left:SetTextColor(linesToAddR[i], linesToAddG[i], linesToAddB[i])
+ if linesToAddRight[i] then
+ local right = mod.rightLines[i + lineNum]
+ right:SetText(linesToAddRight[i])
+ right:SetTextColor(linesToAddRightR[i], linesToAddRightG[i], linesToAddRightB[i])
+ end
+ linesToAdd[i] = nil
+ linesToAddR[i] = nil
+ linesToAddG[i] = nil
+ linesToAddB[i] = nil
+ linesToAddRight[i] = nil
+ linesToAddRightR[i] = nil
+ linesToAddRightG[i] = nil
+ linesToAddRightB[i] = nil
+ end
+
+ self:CancelTimer(talentTimer)
+ talentTimer = nil
+ GameTooltip:Show()
+ elseif spec[nameRealm] then
+ for k in pairs(spec[nameRealm]) do
+ spec[nameRealm][k] = nil
+ end
+ spec[nameRealm] = nil
+ end
+end
+
+local indexOf = function(t, val)
+ for i=1, #t do
+ if t[i] == val then
+ return i
+ end
+ end
+end
+
+local indicesOf = function(t, val)
+ local a = {}
+ for i=1, #t do
+ if t[i] == val then
+ tinsert(a, i)
+ end
+ end
+ return unpack(a)
+end
+
+function mod:TalentQuery_Ready(e, name, realm)
+ if not TalentQuery then return end
+ local nameRealm = name .. (realm or '')
+ local isnotplayer = (name ~= UnitName("player"))
+ if not spec[nameRealm] then
+ spec[nameRealm] = {[4]=NONE}
+ local highPoints = {}
+ local specNames = {}
+ for tab = 1, GetNumTalentTabs(isnotplayer) do
+ local treename, _, pointsspent = GetTalentTabInfo(tab, isnotplayer)
+ highPoints[tab] = pointsspent
+ spec[nameRealm][tab] = pointsspent
+ specNames[tab] = treename
+ end
+ if highPoints[1] == nil or highPoints[2] == nil or highPoints[3] == nil then spec[nameRealm] = nil return end
+ table.sort(highPoints, function(a,b) return a>b end)
+ local first, second = select(1, indicesOf(spec[nameRealm], highPoints[1])), select(2, indicesOf(spec[nameRealm], highPoints[1]))
+ if highPoints[1] > 0 and highPoints[2] > 0 and highPoints[1] - highPoints[2] <= 5 and highPoints[1] ~= highPoints[2] then
+ spec[nameRealm][4] = specNames[indexOf(spec[nameRealm], highPoints[1])] .. "/" .. specNames[indexOf(spec[nameRealm], highPoints[2])]
+ elseif highPoints[1] > 0 and first and second then
+ spec[nameRealm][4] = specNames[first] .. "/" .. specNames[second]
+ elseif highPoints[1] > 0 then
+ spec[nameRealm][4] = specNames[indexOf(spec[nameRealm], highPoints[1])]
+ end
+ end
+end
+
+local unitHasAura = function(aura)
+ local i = 1
+ while true do
+ local buff = UnitBuff("mouseover", i, true)
+ if not buff then return end
+ if buff == aura then return true end
+ i = i + 1
+ end
+end
+
+local options = {
+ titles = {
+ name = "Titles",
+ desc = "Toggle whether to show titles or not",
+ type = "toggle",
+ set = function(info, v) self.db.profile.titles = v end,
+ get = function() return self.db.profile.titles end,
+ order = 5
+ },
+}
+
+local lines = setmetatable({
+ [1] = {
+ db = "Name:",
+ name = "UnitName",
+ left = function()
+ local c
+ if UnitIsPlayer("mouseover") then
+ c = RAID_CLASS_COLORS[select(2, UnitClass("mouseover"))]
+ else
+ c = {}
+ c.r, c.g, c.b = UnitSelectionColor("mouseover")
+ end
+ return unitName, c
+ end,
+ right = nil,
+ updating = false
+ },
+ [2] = {
+ db = "Target:",
+ name = "Target",
+ left = function() return "Target:" end,
+ right = function()
+ if UnitExists("mouseovertarget") then
+ local c
+ if UnitIsPlayer("mouseovertarget") then
+ c = RAID_CLASS_COLORS[select(2, UnitClass("mouseovertarget"))]
+ else
+ c = {}
+ c.r, c.g, c.b = UnitSelectionColor("mouseovertarget")
+ end
+ local name = UnitName("mouseovertarget")
+ return name, c
+ else
+ return "None", {r=1, g=1, b=1}
+ end
+ end,
+ updating = true
+ },
+ [3] = {
+ db = "Guild:",
+ name = "Guild",
+ left = function() return "Guild:" end,
+ right = function()
+ local guild = GetGuildInfo("mouseover")
+ if guild then return guild else return unitGuild end
+ end,
+ updating = false
+ },
+ [4] = {
+ db = "Rank:",
+ name = "Rank",
+ left = function() return "Rank:" end,
+ right = function()
+ return select(2, GetGuildInfo("mouseover"))
+ end,
+ updating = false
+ },
+ [5] = {
+ db = "Realm:",
+ name = "Realm",
+ left = function() return "Realm:" end,
+ right = function()
+ return select(2, UnitName("mouseover"))
+ end,
+ updating = false
+ },
+ [6] = {
+ db = "Level:",
+ name = "Level",
+ left = function() return "Level:" end,
+ right = function()
+ local lvl = UnitLevel("mouseover")
+ local class = UnitClassification("mouseover")
+
+ if lvl <= 0 then
+ lvl = ''
+ end
+
+ if classifications[class] then
+ lvl = lvl .. classifications[class]
+ end
+
+ return lvl
+ end,
+ updating = false
+ },
+ [7] = {
+ db = "Race:",
+ name = "Race",
+ left = function() return "Race:" end,
+ right = function()
+ local race
+ if UnitIsPlayer("mouseover") then
+ race = UnitRace("mouseover");
+ else
+ race = UnitCreatureFamily("mouseover") or UnitCreatureType("mouseover")
+ end
+ return race
+ end,
+ updating = false
+ },
+ [8] = {
+ db = "Class:",
+ name = "Class",
+ left = function() return "Class:" end,
+ right = function()
+ local class = UnitClass("mouseover")
+ if class == UnitName("mouseover") then return end
+ local c = UnitIsPlayer("mouseover") and RAID_CLASS_COLORS[select(2, UnitClass("mouseover"))]
+ return class, c
+ end,
+ updating = false
+ },
+ [9] = {
+ db = "Faction:",
+ name = "Faction",
+ left = function() return "Faction:" end,
+ right = function()
+ return UnitFactionGroup("mouseover")
+ end,
+ updating = false
+ },
+ [10] = {
+ db = "Status:",
+ name = "Status",
+ left = function() return "Status:" end,
+ right = function()
+ if not UnitIsConnected("mouseover") then
+ return "Offline"
+ elseif unitHasAura(GetSpellInfo(19752)) then
+ return "Divine Intervention"
+ elseif UnitIsFeignDeath("mouseover") then
+ return "Feigned Death"
+ elseif UnitIsGhost("mouseover") then
+ return "Ghost"
+ elseif UnitIsDead("mouseover") and unitHasAura(GetSpellInfo(20707)) then
+ return "Soulstoned"
+ elseif UnitIsDead("mouseover") then
+ return "Dead"
+ end
+ end,
+ updating = true
+ },
+ [11] = {
+ db = "Health:",
+ name = "Health",
+ left = function() return "Health:" end,
+ right = function()
+ local health, maxHealth = UnitHealth("mouseover"), UnitHealthMax("mouseover")
+ local value
+ if maxHealth == 100 then
+ value = health .. "%"
+ elseif maxHealth ~= 0 then
+ value = format("%s/%s (%d%%)", short(health), short(maxHealth), health/maxHealth*100)
+ end
+ return value
+ end,
+ updating = true
+ },
+ [12] = {
+ db = "Mana:",
+ name = "Mana",
+ left = function()
+ local class = select(2, UnitClass("mouseover"))
+ return powers[class]
+ end,
+ right = function()
+ local mana = UnitMana("mouseover")
+ local maxMana = UnitManaMax("mouseover")
+ local value
+ if maxMana == 100 then
+ value = mana
+ elseif maxMana ~= 0 then
+ value = format("%s/%s (%d%%)", short(mana), short(maxMana), mana/maxMana*100)
+ end
+ return value
+ end,
+ updating = true
+ },
+ [13] = {
+ db = "Location:",
+ name = "Location",
+ left = function() return "Location:" end,
+ right = function()
+ return unitLocation
+ end,
+ updating = true
+ },
+ [14] = {
+ db = "Talents:",
+ name = "Talents",
+ left = function() return "Talents:" end,
+ right = function()
+ local name = UnitName("mouseover")
+ if TalentQuery and UnitIsUnit("mouseover", "player") then
+ mod:TalentQuery_Ready(_, name)
+ elseif TalentQuery and UnitExists("mouseover") and UnitIsPlayer("mouseover") then
+ TalentQuery:Query("mouseover")
+ talentTimer = talentTimer or self:ScheduleRepeatingTimer(updateTalents, 0)
+ end
+ end,
+ updating = false
+ },
+ [15] = {
+ db = "TalentsGuessed:",
+ name = "Talents Guesssed",
+ left = function() return "Talents Guessed:" end,
+ right = function()
+ local name, realm = UnitName("mouseover")
+ local nameRealm
+ if realm then
+ nameRealm = name .. '-' .. realm
+ else
+ nameRealm = name
+ end
+ local specText
+ if nameRealm and TalentGuess and TalentGuess:GetTalents(nameRealm) then
+ local talents = {}
+ local high = 1
+ talents[1], talents[2], talents[3] = TalentGuess:GetTalents(nameRealm)
+ for i = 2, 3 do
+ if talents[i] > talents[high] then
+ high = i
+ end
+ end
+ local class = UnitClass("mouseover")
+ specText = ("%s (%d/%d/%d)"):format(talentTrees[class][high], talents[1], talents[2], talents[3])
+ end
+ return specText
+ end,
+ updating = true
+ }
+}, {__call=function(this)
+ local lineNum = 0
+ for i, v in ipairs(this) do
+ if self.db.profile[v.db] then
+ local left, right, c
+ if v.right then
+ right, c = v.right()
+ left = v.left()
+ else
+ right = ''
+ left, c = v.left()
+ end
+ if left and right then
+ lineNum = lineNum + 1
+ if v.right then
+ GameTooltip:AddDoubleLine(' ', ' ', 1, 1, 1, 1, 1, 1)
+ mod.leftLines[lineNum]:SetText(left)
+ mod.rightLines[lineNum]:SetText(right)
+ if type(c) == "table" and c.r then
+ mod.rightLines[lineNum]:SetVertexColor(c.r, c.g, c.b)
+ end
+ else
+ GameTooltip:AddLine(' ', 1, 1, 1)
+ mod.leftLines[lineNum]:SetText(left)
+ if type(c) == "table" and c.r then
+ mod.leftLines[lineNum]:SetVertexColor(c.r, c.g, c.b)
+ end
+ end
+ end
+ end
+ end
+ NUM_LINES = lineNum
+end})
+
+local function updateLines()
+ if not UnitExists("mouseover") then
+ mod:CancelTimer(timer)
+ timer = nil
+ return
+ end
+ for _, v in ipairs(lines) do
+ if v.updating and v.right and self.db.profile[v.db] then
+ local left = v.left()
+ local right, c = v.right()
+ if left and right then
+ for i = 1, NUM_LINES do
+ if mod.leftLines[i]:GetText() == left then
+ mod.rightLines[i]:SetText(right)
+ if type(c) == "table" and c.r then
+ mod.rightLines[i]:SetVertexColor(c.r, c.g, c.b)
+ end
+ end
+ end
+ end
+ end
+ end
+end
+
+local defaults = {profile={titles=true}}
+
+do
+ local lnum = 1
+ for i, v in ipairs(lines) do
+ options[v.db] = {
+ name = v.name,
+ desc = "Toggle showing this line",
+ type = "toggle",
+ set = function(info, val) self.db.profile[v.db] = val end,
+ get = function() return self.db.profile[v.db] end,
+ order = 5 + lnum
+ }
+ lnum = lnum + 1
+ defaults.profile[v.db] = true
+ end
+end
+
+function mod:OnInitialize()
+ self.db = StarTip.db:RegisterNamespace(self:GetName(), defaults)
+ self.leftLines = StarTip.leftLines
+ self.rightLines = StarTip.rightLines
+ self:RegisterEvent("UPDATE_FACTION")
+ StarTip:SetOptionsDisabled(options, true)
+end
+
+function mod:OnEnable()
+ local i = 1
+ while true do
+ if not self.db.profile[i] then break end
+ lines[i] = self.db.profile[i]
+ i = i + 1
+ end
+ if TalentQuery then TalentQuery.RegisterCallback(self, "TalentQuery_Ready") end
+ StarTip:SetOptionsDisabled(options, false)
+end
+
+function mod:OnDisable()
+ if TalentQuery then TalentQuery.UnregisterCallback(self, "TalentQuery_Ready") end
+ StarTip:SetOptionsDisabled(options, true)
+end
+
+function mod:GetOptions()
+ return options
+end
+
+function mod:UPDATE_FACTION()
+ for i = 1, GetNumFactions() do
+ local name = GetFactionInfo(i)
+ factionList[name] = true
+ end
+end
+
+
+local getName = function()
+ if self.db.profile.titles then
+ local name = self.leftLines[1]:GetText()
+ if UnitIsPlayer("mouseover") and name:find(" %- ") then
+ name = name:sub(1, name:find(" %- "))
+ end
+ return name
+ else
+ return UnitName("mouseover")
+ end
+end
+
+-- Taken from LibDogTag-Unit-3.0
+local LEVEL_start = "^" .. (type(LEVEL) == "string" and LEVEL or "Level")
+local getLocation = function()
+ if UnitIsVisible("mouseover") or not UnitIsConnected("mouseover") then
+ return nil
+ end
+
+ local left_2 = self.leftLines[2]:GetText()
+ local left_3 = self.leftLines[3]:GetText()
+ if not left_2 or not left_3 then
+ return nil
+ end
+ local hasGuild = not left_2:find(LEVEL_start)
+ local factionText = not hasGuild and left_3 or self.leftLines[4]:GetText()
+ if factionText == PVP then
+ factionText = nil
+ end
+ local hasFaction = factionText and not UnitPlayerControlled("mouseover") and not UnitIsPlayer("mouseover") and (UnitFactionGroup("mouseover") or factionList[factionText])
+ if hasGuild and hasFaction then
+ return self.leftLines[5]:GetText()
+ elseif hasGuild or hasFaction then
+ return self.leftLines[4]:GetText()
+ else
+ return left_3
+ end
+end
+
+local getGuild = function()
+ local left_2 = self.leftLines[2]:GetText()
+ if left_2:find(LEVEL_start) then return nil end
+ return "<" .. left_2 .. ">"
+end
+
+local ff = CreateFrame("Frame")
+function mod:SetUnit()
+ --[[self = mod
+ if not UnitExists("mouseover") then
+ if ff:GetScript("OnUpdate") then
+ ff:SetScript("OnUpdate", nil)
+ else
+ ff:SetScript("OnUpdate", self.SetUnit)
+ end
+ return
+ end]]
+
+ if ff:GetScript("OnUpdate") then ff:SetScript("OnUpdate", nil) end
+
+ unitName = getName()
+ unitLocation = getLocation()
+ unitGuild = getGuild()
+
+ -- Taken from CowTip
+ local lastLine = 2
+ local text2 = self.leftLines[2]:GetText()
+
+ if not text2 then
+ lastLine = lastLine - 1
+ elseif not text2:find("^"..LEVEL) then
+ lastLine = lastLine + 1
+ end
+ if not UnitPlayerControlled("mouseover") and not UnitIsPlayer("mouseover") then
+ local factionText = self.leftLines[lastLine + 1]:GetText()
+ if factionText == PVP then
+ factionText = nil
+ end
+ if factionText and (factionList[factionText] or UnitFactionGroup("mouseover")) then
+ lastLine = lastLine + 1
+ end
+ end
+ if not UnitIsConnected("mouseover") or not UnitIsVisible("mouseover") or UnitIsPVP("mouseover") then
+ lastLine = lastLine + 1
+ end
+
+ lastLine = lastLine + 1
+
+ for i = lastLine, GameTooltip:NumLines() do
+ local left = self.leftLines[i]
+ local j = i - lastLine + 1
+ linesToAdd[j] = left:GetText()
+ local r, g, b = left:GetTextColor()
+ linesToAddR[j] = r
+ linesToAddG[j] = g
+ linesToAddB[j] = b
+ local right = self.rightLines[i]
+ if right:IsShown() then
+ linesToAddRight[j] = right:GetText()
+ local r, g, b = right:GetTextColor()
+ linesToAddRightR[j] = r
+ linesToAddRightG[j] = g
+ linesToAddRightB[j] = b
+ end
+ end
+ -- End
+
+ GameTooltip:ClearLines()
+
+ lines()
+
+ -- Another part taken from CowTip
+ for i, left in ipairs(linesToAdd) do
+ local right = linesToAddRight[i]
+ if right then
+ GameTooltip:AddDoubleLine(left, right, linesToAddR[i], linesToAddG[i], linesToAddB[i], linesToAddRightR[i], linesToAddRightG[i], linesToAddRightB[i])
+ else
+ GameTooltip:AddLine(left, linesToAddR[i], linesToAddG[i], linesToAddB[i], true)
+ end
+ linesToAdd[i] = nil
+ linesToAddR[i] = nil
+ linesToAddG[i] = nil
+ linesToAddB[i] = nil
+ linesToAddRight[i] = nil
+ linesToAddRightR[i] = nil
+ linesToAddRightG[i] = nil
+ linesToAddRightB[i] = nil
+ end
+ -- End
+
+ timer = timer or self:ScheduleRepeatingTimer(updateLines, .5)
+
+ GameTooltip:Show()
+end