diff --git a/api/config.lua b/api/config.lua index 0fa26636..e3642760 100644 --- a/api/config.lua +++ b/api/config.lua @@ -516,6 +516,7 @@ function pfUI:LoadConfig() pfUI:UpdateConfig("panel", "micro", "enable", "0") pfUI:UpdateConfig("panel", "bag", "ignorespecial", "1") pfUI:UpdateConfig("panel", "xp", "xp_always", "0") + pfUI:UpdateConfig("panel", "xp", "xp_display", "XPFLEX") pfUI:UpdateConfig("panel", "xp", "xp_timeout", "5") pfUI:UpdateConfig("panel", "xp", "xp_width", "5") pfUI:UpdateConfig("panel", "xp", "xp_height", "5") @@ -526,6 +527,7 @@ function pfUI:LoadConfig() pfUI:UpdateConfig("panel", "xp", "rest_color", "1,.25,1,.5") pfUI:UpdateConfig("panel", "xp", "rep_always", "0") + pfUI:UpdateConfig("panel", "xp", "rep_display", "REP") pfUI:UpdateConfig("panel", "xp", "rep_timeout", "5") pfUI:UpdateConfig("panel", "xp", "rep_width", "5") pfUI:UpdateConfig("panel", "xp", "rep_height", "5") diff --git a/modules/xpbar.lua b/modules/xpbar.lua index fec79bbb..6ffb93ce 100644 --- a/modules/xpbar.lua +++ b/modules/xpbar.lua @@ -2,41 +2,216 @@ pfUI:RegisterModule("xpbar", "vanilla:tbc", function () local rawborder, default_border = GetBorderSize() local parse_faction = SanitizePattern(FACTION_STANDING_INCREASED) + local data = CreateFrame("Frame", "pfExperienceBarData", UIParent) + data:RegisterEvent("CHAT_MSG_COMBAT_FACTION_CHANGE") + data:RegisterEvent("PLAYER_ENTERING_WORLD") + data:RegisterEvent("PLAYER_LEVEL_UP") + data:SetScript("OnEvent", function() + if event == "PLAYER_ENTERING_WORLD" then + this.starttime = GetTime() + this.startxp = UnitXP("player") or 0 + elseif event == "PLAYER_LEVEL_UP" then + -- add previously gained experience to the session + this.startxp = this.startxp - UnitXPMax("player") + elseif event == "CHAT_MSG_COMBAT_FACTION_CHANGE" then + local _,_, faction, amount = string.find(arg1, parse_faction) + this.faction = faction or this.faction + end + end) + + local function OnLeave(self) + local self = self or this + + self.tick = GetTime() + 3.00 + GameTooltip:Hide() + end + +local function OnEnter(self) + local self = self or this + local lines = {} + + -- set either experience, reputation or flex-rep handler + local mode = self.display + if self.display == "XPFLEX" then + mode = UnitLevel("player") < MAX_LEVEL and "XP" or "REP" + elseif self.display == "FLEX" then + mode = "REP" + end + + self:SetAlpha(1) + + if mode == "XP" then + local xp, xpmax, exh = UnitXP("player"), UnitXPMax("player"), GetXPExhaustion() + local xp_perc = round(xp / xpmax * 100) + local remaining = xpmax - xp + local remaining_perc = round(remaining / xpmax * 100) + local exh_perc = GetXPExhaustion() and round(GetXPExhaustion() / xpmax * 100) or 0 + local xp_persec = ((xp - data.startxp)/(GetTime() - data.starttime)) + local session = UnitXP("player") - data.startxp + local avg_hour = floor(((UnitXP("player") - data.startxp) / (GetTime() - data.starttime)) * 60 * 60) + local time_remaining = xp_persec > 0 and SecondsToTime(remaining/xp_persec) or 0 + + -- fill gametooltip data + table.insert(lines, { "|cff555555" .. T["Experience"], "" }) + table.insert(lines, { T["XP"], "|cffffffff" .. xp .. " / " .. xpmax .. " (" .. xp_perc .. "%)" }) + table.insert(lines, { T["Remaining"], "|cffffffff" .. remaining .. " (" .. remaining_perc .. "%)" }) + if IsResting() then + table.insert(lines, { T["Status"], "|cffffffff" .. T["Resting"] }) + end + if GetXPExhaustion() then + table.insert(lines, { T["Rested"], "|cff5555ff+" .. exh .. " (" .. exh_perc .. "%)" }) + end + table.insert(lines, { "" }) + table.insert(lines, { T["This Session"], "|cffffffff" .. session }) + table.insert(lines, { T["Average Per Hour"], "|cffffffff" .. avg_hour }) + table.insert(lines, { T["Time Remaining"], "|cffffffff" .. time_remaining }) + elseif mode == "REP" then + for i=1, 99 do + local name, description, standingID, barMin, barMax, barValue, atWarWith, canToggleAtWar, isHeader, isCollapsed, isWatched = GetFactionInfo(i) + if ( isWatched and not self.faction ) or ( self.faction and name == self.faction) then + barMax = barMax - barMin + barValue = barValue - barMin + + local color = FACTION_BAR_COLORS[standingID] + if color then + color = rgbhex(color.r + .3, color.g + .3, color.b + .3) + else + color = rgbhex(.5, .5, .5) + end + + table.insert(lines, { "|cff555555" .. T["Reputation"], "" }) + table.insert(lines, { color .. name .. " (" .. GetText("FACTION_STANDING_LABEL"..standingID, gender) .. ")"}) + table.insert(lines, { barValue .. " / " .. barMax .. " (" .. round(barValue / barMax * 100) .. "%)" }) + break + end + end + end + + -- draw tooltip + GameTooltip:ClearLines() + GameTooltip_SetDefaultAnchor(GameTooltip, self) + GameTooltip:SetOwner(self, "ANCHOR_CURSOR") + + for id, data in pairs(lines) do + if data[2] then + GameTooltip:AddDoubleLine(data[1], data[2]) + else + GameTooltip:AddLine(data[1]) + end + end + GameTooltip:Show() +end + + local function OnUpdate(self) + local self = self or this + + if self.always then return end + if self:GetAlpha() == 0 or MouseIsOver(self) then return end + if ( self.tick or 1) > GetTime() then return else self.tick = GetTime() + .01 end + self:SetAlpha(self:GetAlpha() - .05) + end + + local function OnEvent(self) + local self = self or this + + -- realign when entering world to ensure all frames got loaded + AlignToPosition(self, _G[self.anchor], self.position, default_border*3) + UpdateMovable(self, true) + + -- set either experience, reputation or flex-rep handler + local mode = self.display + if self.display == "XPFLEX" then + self.faction = data.faction or nil + mode = UnitLevel("player") < MAX_LEVEL and "XP" or "REP" + elseif self.display == "FLEX" then + self.faction = data.faction or nil + mode = "REP" + end + + if self.always then + self:SetAlpha(1) + self:Show() + end + + -- skip on events of no interest + if mode == "XP" and ( event == "CHAT_MSG_COMBAT_FACTION_CHANGE" or event == "UPDATE_FACTION" ) then return end + if mode == "REP" and event == "PLAYER_XP_UPDATE" then return end + + if mode == "XP" then + self.enabled = true + self:SetAlpha(1) + self.bar:SetMinMaxValues(0, UnitXPMax("player")) + self.bar:SetValue(UnitXP("player")) + if GetXPExhaustion() then + self.restedbar:Show() + self.restedbar:SetMinMaxValues(0, UnitXPMax("player")) + self.restedbar:SetValue(UnitXP("player") + GetXPExhaustion()) + else + self.restedbar:Hide() + end + + self.tick = GetTime() + self.timeout + return + elseif mode == "REP" then + self.restedbar:Hide() + + for i=1, 99 do + local name, description, standingID, barMin, barMax, barValue, atWarWith, canToggleAtWar, isHeader, isCollapsed, isWatched = GetFactionInfo(i) + if ( isWatched and not self.faction ) or ( self.faction and name == self.faction) then + self.enabled = true + self:SetAlpha(1) + + barMax = barMax - barMin + barValue = barValue - barMin + + self.bar:SetMinMaxValues(0, barMax) + self.bar:SetValue(barValue) + + local color = FACTION_BAR_COLORS[standingID] + if color then + self.bar:SetStatusBarColor((color.r + .5) * .5, (color.g + .5) * .5, (color.b + .5) * .5, 1) + else + self.bar:SetStatusBarColor(.5,.5,.5,1) + end + + self.tick = GetTime() + self.timeout + return + end + end + end + + self.bar:SetStatusBarColor(.5,.5,.5,1) + self.bar:SetMinMaxValues(0, 1) + self.bar:SetValue(0) + end + local function CreateBar(t) - local xp_timeout = tonumber(C.panel.xp.xp_timeout) - local xp_width = C.panel.xp.xp_width - local xp_height = C.panel.xp.xp_height - local xp_mode = C.panel.xp.xp_mode - local xp_always = C.panel.xp.xp_always == "1" and true or nil - local xp_position = C.panel.xp.xp_position - local xp_anchor = C.panel.xp.xp_anchor - local xp_color = C.panel.xp.xp_color - local rest_color = C.panel.xp.rest_color - - local rep_timeout = tonumber(C.panel.xp.rep_timeout) - local rep_width = C.panel.xp.rep_width - local rep_height = C.panel.xp.rep_height - local rep_mode = C.panel.xp.rep_mode - local rep_always = C.panel.xp.rep_always == "1" and true or nil - local rep_position = C.panel.xp.rep_position - local rep_anchor = C.panel.xp.rep_anchor - - local t = t - local width = t == "XP" and xp_width or rep_width - local height = t == "XP" and xp_height or rep_height - local mode = t == "XP" and xp_mode or rep_mode - local timeout = t == "XP" and xp_timeout or rep_timeout - local always = t == "XP" and xp_always or rep_always local name = t == "XP" and "pfExperienceBar" or "pfReputationBar" - local anchor = t == "XP" and xp_anchor or rep_anchor - local position = t == "XP" and xp_position or rep_position - local b = _G[name] or CreateFrame("Frame", name, UIParent) - b:SetWidth(width) - b:SetHeight(height) + + b.xp_color = C.panel.xp.xp_color + b.rest_color = C.panel.xp.rest_color + b.width = t == "XP" and C.panel.xp.xp_width or C.panel.xp.rep_width + b.height = t == "XP" and C.panel.xp.xp_height or C.panel.xp.rep_height + b.mode = t == "XP" and C.panel.xp.xp_mode or C.panel.xp.rep_mode + b.timeout = t == "XP" and tonumber(C.panel.xp.xp_timeout) or tonumber(C.panel.xp.rep_timeout) + b.anchor = t == "XP" and C.panel.xp.xp_anchor or C.panel.xp.rep_anchor + b.position = t == "XP" and C.panel.xp.xp_position or C.panel.xp.rep_position + b.display = t == "XP" and C.panel.xp.xp_display or C.panel.xp.rep_display + + if t == "XP" and C.panel.xp.xp_always == "1" then + b.always = true + elseif t == "REP" and C.panel.xp.rep_always == "1" then + b.always = true + else + b.always = nil + end + + b:SetWidth(b.width) + b:SetHeight(b.height) b:SetFrameStrata("BACKGROUND") - AlignToPosition(b, _G[anchor], position, default_border*3) + AlignToPosition(b, _G[b.anchor], b.position, default_border*3) UpdateMovable(b, true) CreateBackdrop(b) CreateBackdropShadow(b) @@ -47,169 +222,33 @@ pfUI:RegisterModule("xpbar", "vanilla:tbc", function () b.bar:SetAllPoints(b) b.bar:SetFrameStrata("LOW") - local cr, cg, cb, ca = pfUI.api.GetStringColor(xp_color) + local cr, cg, cb, ca = pfUI.api.GetStringColor(b.xp_color) b.bar:SetStatusBarColor(cr,cg,cb,ca) - b.bar:SetOrientation(mode) + b.bar:SetOrientation(b.mode) b.restedbar = b.restedbar or CreateFrame("StatusBar", nil, b) b.restedbar:SetStatusBarTexture(pfUI.media["img:bar"]) b.restedbar:ClearAllPoints() b.restedbar:SetAllPoints(b) b.restedbar:SetFrameStrata("MEDIUM") - local cr, cg, cb, ca = pfUI.api.GetStringColor(rest_color) + local cr, cg, cb, ca = pfUI.api.GetStringColor(b.rest_color) b.restedbar:SetStatusBarColor(cr,cg,cb,ca) - b.restedbar:SetOrientation(mode) + b.restedbar:SetOrientation(b.mode) -- auto hide b:EnableMouse(true) - b:SetScript("OnLeave", function() - this.tick = GetTime() + 3.00 - GameTooltip:Hide() - end) - - b:SetScript("OnUpdate",function() - if always then return end - if this:GetAlpha() == 0 or MouseIsOver(this) then return end - if ( this.tick or 1) > GetTime() then return else this.tick = GetTime() + .01 end - this:SetAlpha(this:GetAlpha() - .05) - end) b:RegisterEvent("CHAT_MSG_COMBAT_FACTION_CHANGE") b:RegisterEvent("PLAYER_ENTERING_WORLD") b:RegisterEvent("PLAYER_XP_UPDATE") b:RegisterEvent("PLAYER_LEVEL_UP") b:RegisterEvent("UPDATE_FACTION") - b:SetScript("OnEvent", function() - -- realign when entering world to ensure all frames got loaded - AlignToPosition(b, _G[anchor], position, default_border*3) - UpdateMovable(b, true) - -- set either experience, reputation or flex-rep handler - local mode = ( t == "XP" and UnitLevel("player") < MAX_LEVEL ) and "XP" or t == "REP" and "REP" or "FLEX" - - -- skip on events of no interest - if mode == "XP" and ( event == "CHAT_MSG_COMBAT_FACTION_CHANGE" or event == "UPDATE_FACTION" ) then return end - if ( mode == "REP" or mode == "FLEX" ) and event == "PLAYER_XP_UPDATE" then return end - - if mode == "XP" then - this.enabled = true - if event == "PLAYER_ENTERING_WORLD" then - this.starttime = GetTime() - this.startxp = UnitXP("player") or 0 - elseif event == "PLAYER_LEVEL_UP" then - -- add previously gained experience to the session - this.startxp = this.startxp - UnitXPMax("player") - end - - this.bar:SetMinMaxValues(0, UnitXPMax("player")) - this.bar:SetValue(UnitXP("player")) - if GetXPExhaustion() then - this.restedbar:Show() - this.restedbar:SetMinMaxValues(0, UnitXPMax("player")) - this.restedbar:SetValue(UnitXP("player") + GetXPExhaustion()) - else - this.restedbar:Hide() - end - this.tick = GetTime() + timeout - this:SetAlpha(1) - else - this.restedbar:Hide() - - if mode == "FLEX" and event == "CHAT_MSG_COMBAT_FACTION_CHANGE" then - local _,_, faction, amount = string.find(arg1, parse_faction) - this.faction = faction or this.faction - end - - for i=1, 99 do - local name, description, standingID, barMin, barMax, barValue, atWarWith, canToggleAtWar, isHeader, isCollapsed, isWatched = GetFactionInfo(i) - if ( mode == "REP" and isWatched ) or ( mode == "FLEX" and this.faction and name == this.faction) then - this.enabled = true - - barMax = barMax - barMin - barValue = barValue - barMin - barMin = 0 - - this.bar:SetMinMaxValues(barMin, barMax) - this.bar:SetValue(barValue) - local color = FACTION_BAR_COLORS[standingID] - this.bar:SetStatusBarColor((color.r + .5) * .5, (color.g + .5) * .5, (color.b + .5) * .5, 1) - - this.tick = GetTime() + rep_timeout - this:SetAlpha(1) - break - end - end - end - end) - - b:SetScript("OnEnter", function() - if not this.enabled then return end - - -- set either experience, reputation or flex-rep handler - local mode = ( t == "XP" and UnitLevel("player") < MAX_LEVEL ) and "XP" or t == "REP" and "REP" or "FLEX" - local lines = {} - - this:SetAlpha(1) - - if mode == "XP" then - local xp, xpmax, exh = UnitXP("player"), UnitXPMax("player"), GetXPExhaustion() - local xp_perc = round(xp / xpmax * 100) - local remaining = xpmax - xp - local remaining_perc = round(remaining / xpmax * 100) - local exh_perc = GetXPExhaustion() and round(GetXPExhaustion() / xpmax * 100) or 0 - local xp_persec = ((xp - this.startxp)/(GetTime() - this.starttime)) - local session = UnitXP("player") - this.startxp - local avg_hour = floor(((UnitXP("player") - this.startxp) / (GetTime() - this.starttime)) * 60 * 60) - local time_remaining = xp_persec > 0 and SecondsToTime(remaining/xp_persec) or 0 - - -- fill gametooltip data - table.insert(lines, { "|cff555555" .. T["Experience"], "" }) - table.insert(lines, { T["XP"], "|cffffffff" .. xp .. " / " .. xpmax .. " (" .. xp_perc .. "%)" }) - table.insert(lines, { T["Remaining"], "|cffffffff" .. remaining .. " (" .. remaining_perc .. "%)" }) - if IsResting() then - table.insert(lines, { T["Status"], "|cffffffff" .. T["Resting"] }) - end - if GetXPExhaustion() then - table.insert(lines, { T["Rested"], "|cff5555ff+" .. exh .. " (" .. exh_perc .. "%)" }) - end - table.insert(lines, { "" }) - table.insert(lines, { T["This Session"], "|cffffffff" .. session }) - table.insert(lines, { T["Average Per Hour"], "|cffffffff" .. avg_hour }) - table.insert(lines, { T["Time Remaining"], "|cffffffff" .. time_remaining }) - else - for i=1, 99 do - local name, description, standingID, barMin, barMax, barValue, atWarWith, canToggleAtWar, isHeader, isCollapsed, isWatched = GetFactionInfo(i) - if ( mode == "REP" and isWatched ) or ( mode == "FLEX" and this.faction and name == this.faction) then - barMax = barMax - barMin - barValue = barValue - barMin - barMin = 0 - - local color = FACTION_BAR_COLORS[standingID] - if not color then color = 1,1,1 end - - local color = rgbhex(color.r + .3, color.g + .3, color.b + .3) - table.insert(lines, { "|cff555555" .. T["Reputation"], "" }) - table.insert(lines, { color .. name .. " (" .. GetText("FACTION_STANDING_LABEL"..standingID, gender) .. ")"}) - table.insert(lines, { barValue .. " / " .. barMax .. " (" .. round(barValue / barMax * 100) .. "%)" }) - break - end - end - end - - -- draw tooltip - GameTooltip:ClearLines() - GameTooltip_SetDefaultAnchor(GameTooltip, this) - GameTooltip:SetOwner(this, "ANCHOR_CURSOR") - - for id, data in pairs(lines) do - if data[2] then - GameTooltip:AddDoubleLine(data[1], data[2]) - else - GameTooltip:AddLine(data[1]) - end - end - GameTooltip:Show() - end) + b:SetScript("OnUpdate", OnUpdate) + b:SetScript("OnEvent", OnEvent) + b:SetScript("OnEnter", OnEnter) + b:SetScript("OnLeave", OnLeave) + b:GetScript("OnEvent")(b) return b end