diff --git a/.pkgmeta b/.pkgmeta new file mode 100644 index 0000000..426410c --- /dev/null +++ b/.pkgmeta @@ -0,0 +1,15 @@ +externals: + Libs/LibStub: svn://svn.wowace.com/wow/libstub/mainline/trunk + Libs/CallbackHandler-1.0: svn://svn.wowace.com/wow/callbackhandler/mainline/tags/1.0.3/CallbackHandler-1.0 + Libs/AceAddon-3.0: svn://svn.wowace.com/wow/ace3/mainline/trunk/AceAddon-3.0 + Libs/AceHook-3.0: svn://svn.wowace.com/wow/ace3/mainline/trunk/AceHook-3.0 + Libs/AceTimer-3.0: svn://svn.wowace.com/wow/ace3/mainline/trunk/AceTimer-3.0 + Libs/AceConfig-3.0: svn://svn.wowace.com/wow/ace3/mainline/trunk/AceConfig-3.0 + Libs/AceConsole-3.0: svn://svn.wowace.com/wow/ace3/mainline/trunk/AceConsole-3.0 + Libs/AceDB-3.0: svn://svn.wowace.com/wow/ace3/mainline/trunk/AceDB-3.0 + Libs/AceEvent-3.0: svn://svn.wowace.com/wow/ace3/mainline/trunk/AceEvent-3.0 + Libs/AceGUI-3.0: svn://svn.wowace.com/wow/ace3/mainline/trunk/AceGUI-3.0 + Libs/AceLocale-3.0: svn://svn.wowace.com/wow/ace3/mainline/trunk/AceLocale-3.0 + Libs/AceDBOptions-3.0: svn://svn.wowace.com/wow/ace3/mainline/trunk/AceDBOptions-3.0 + Libs/LibSharedMedia-3.0: svn://svn.wowace.com/wow/libsharedmedia-3-0/mainline/trunk + Libs/LibTalentQuery-1.0: svn://svn.wowace.com/wow/libtalentquery-1-0/mainline/trunk \ No newline at end of file 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..f85cbbb --- /dev/null +++ b/Modules/Text.lua @@ -0,0 +1,691 @@ +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 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 + GameTooltip:AddDoubleLine(' ', ' ') + 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 + }, +}, {__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 diff --git a/StarTip.lua b/StarTip.lua new file mode 100644 index 0000000..9570764 --- /dev/null +++ b/StarTip.lua @@ -0,0 +1,185 @@ +StarTip = LibStub("AceAddon-3.0"):NewAddon("StarTip", "AceConsole-3.0", "AceHook-3.0") +local AceConfigDialog = LibStub("AceConfigDialog-3.0") +local _G = _G +local GameTooltip = _G.GameTooltip +local ipairs, pairs = _G.ipairs, _G.pairs +local LSM = _G.LibStub("LibSharedMedia-3.0") + +local defaults = { + profile = { + modules = {} + } +} + +local options = { + type = "group", + args = { + modules = { + name = "Modules", + desc = "Modules", + type = "group", + args = {} + } + } +} + +StarTip:SetDefaultModuleState(false) + +function StarTip:OnInitialize() + + for k, v in self:IterateModules() do + defaults.profile.modules[k] = true + options.args.modules.args[v:GetName()] = { + name = v.name, + type = "group", + args = nil + } + local t + if v.GetOptions then + t = v:GetOptions() + t.optionsHeader = { + name = "Settings", + type = "header", + order = 3 + } + if v:GetName() == "Bars" then + options.args.modules.args[v:GetName()].childGroups = "tab" + end + else + t = {} + end + t.header = { + name = v.name, + type = "header", + order = 1 + } + t.toggle = { + name = "Enable", + desc = "Enable or disable this module", + type = "toggle", + set = function(info,v) + self.db.profile.modules[k] = v + if v then + self:EnableModule(k) + else + self:DisableModule(k) + end + end, + get = function() return self.db.profile.modules[k] end, + order = 2 + } + options.args.modules.args[v:GetName()].args = t + end + + self.db = LibStub("AceDB-3.0"):New("StarTipDB", defaults, "Default") + LibStub("AceConfig-3.0"):RegisterOptionsTable("StarTip", options) + self:RegisterChatCommand("startip", "OpenConfig") + + self.leftLines = {} + self.rightLines = {} + for i = 1, 50 do + GameTooltip:AddDoubleLine(' ', ' ') + self.leftLines[i] = _G["GameTooltipTextLeft" .. i] + self.rightLines[i] = _G["GameTooltipTextRight" .. i] + end + GameTooltip:Show() + GameTooltip:Hide() +end + +function StarTip:OnEnable() + GameTooltip:HookScript("OnTooltipSetUnit", self.OnTooltipSetUnit) + GameTooltip:HookScript("OnTooltipSetItem", self.OnTooltipSetItem) + GameTooltip:HookScript("OnTooltipSetSpell", self.OnTooltipSetSpell) + self:RawHookScript(GameTooltip, "OnHide", "OnTooltipHide") + self:RawHookScript(GameTooltip, "OnShow", "OnTooltipShow") + + for k,v in self:IterateModules() do + if self.db.profile.modules[k] then + v:Enable() + end + end +end + +function StarTip:OnDisable() + self:Unhook(GameTooltip, "OnTooltipSetUnit") + self:Unhook(GameTooltip, "OnTooltipSetItem") + self:Unhook(GameTooltip, "OnTooltipSetSpell") + self:Unhook(GameTooltip, "OnHide") + self:Unhook(GameTooltip, "OnShow") +end + +function StarTip:OpenConfig() + AceConfigDialog:SetDefaultSize("StarTip", 500, 450) + AceConfigDialog:Open("StarTip") +end + +local ff = CreateFrame("Frame") +function StarTip.OnTooltipSetUnit() + if not StarTip.justSetUnit then + if not UnitExists("mouseover") then + if ff:GetScript("OnUpdate") then + ff:SetScript("OnUpdate", nil) + else + ff:SetScript("OnUpdate", function() GameTooltip:SetUnit("mouseover") end) + end + return + else + if ff:GetScript("OnUpdate") then ff:SetScript("OnUpdate", nil) end + end + for k, v in StarTip:IterateModules() do + if v.SetUnit and v:IsEnabled() then v:SetUnit() end + end + end +end + +function StarTip.OnTooltipSetItem(...) + if not StarTip.justSetItem then + for k, v in StarTip:IterateModules() do + if v.SetItem and v:IsEnabled() then v:SetItem() end + end + end +end + +function StarTip.OnTooltipSetSpell(...) + if not StarTip.justSetSpell then + for k, v in StarTip:IterateModules() do + if v.SetSpell and v:IsEnabled() then v:SetSpell() end + end + end +end + +function StarTip:OnTooltipHide(...) + if not self.justHide then + for k, v in self:IterateModules() do + if v.OnHide and v:IsEnabled() then v:OnHide() end + end + end + self.hooks[GameTooltip].OnHide(...) +end + +function StarTip:OnTooltipShow(...) + if not self.justShow then + for k, v in self:IterateModules() do + if v.OnShow and v:IsEnabled() then v:OnShow() end + end + end + self.hooks[GameTooltip].OnShow(...) +end + +function StarTip:GetLSMIndexByName(category, name) + for i, v in ipairs(LSM:List(category)) do + if v == name then + return i + end + end +end + +function StarTip:SetOptionsDisabled(t, bool) + for k, v in pairs(t) do + if not v.args then + if k ~= "toggle" then v.disabled = bool end + else + self:SetOptionsDisabled(v.args, bool) + end + end +end diff --git a/StarTip.toc b/StarTip.toc new file mode 100644 index 0000000..96d9e35 --- /dev/null +++ b/StarTip.toc @@ -0,0 +1,30 @@ +## Interface: 30000 +## Title: StarTip +## Notes: Tooltips from outerspace +## Author: Starlon +## Version: 1.0 +## X-Category: Interface Enhancements +## X-Embeds: Ace3, LibTalentQuery-1.0 +## X-License: BSD-2.0 +## X-Credits: ckknight for CowTip and DogTags, haste for oUF +## OptionalDeps: Ace3, LibTalentQuery-1.0, LibMobHealth-4.0, TalentGuess-1.0 +## SavedVariables: StarTipDB + +Libs\LibStub\LibStub.lua +Libs\CallbackHandler-1.0\CallbackHandler-1.0.lua +Libs\TalentGuess-1.0\TalentGuess-1.0.xml + +embeds.xml + +Localization\enUS.lua + +StarTip.lua +Modules\Fade.lua +Modules\Appearance.lua +Modules\Bars.lua +Modules\Position.lua +Modules\PvP.lua +Modules\RaidIcon.lua +Modules\Targeting.lua +Modules\Text.lua + diff --git a/embeds.xml b/embeds.xml new file mode 100644 index 0000000..c465e4a --- /dev/null +++ b/embeds.xml @@ -0,0 +1,20 @@ +<Ui xmlns="http://www.blizzard.com/wow/ui/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.blizzard.com/wow/ui/ +..\FrameXML\UI.xsd"> + +<Script file="Libs\LibStub\LibStub.lua"/> +<Script file="Libs\CallbackHandler-1.0\CallbackHandler-1.0.lua"/> +<Include file="Libs\AceAddon-3.0\AceAddon-3.0.xml"/> +<Include file="Libs\AceEvent-3.0\AceEvent-3.0.xml"/> +<Include file="Libs\AceHook-3.0\AceHook-3.0.xml"/> +<Include file="Libs\AceDB-3.0\AceDB-3.0.xml"/> +<Include file="Libs\AceDBOptions-3.0\AceDBOptions-3.0.xml"/> +<Include file="Libs\AceConsole-3.0\AceConsole-3.0.xml"/> +<Include file="Libs\AceGUI-3.0\AceGUI-3.0.xml"/> +<Include file="Libs\AceLocale-3.0\AceLocale-3.0.xml"/> +<Include file="Libs\AceConfig-3.0\AceConfig-3.0.xml"/> +<Include file="Libs\AceTimer-3.0\AceTimer-3.0.xml"/> +<Include file="Libs\LibSharedMedia-3.0\lib.xml"/> +<Include file="Libs\LibMobHealth-4.0\lib.xml"/> +<Script file="Libs\LibTalentQuery-1.0\LibTalentQuery-1.0.lua"/> + +</Ui>