Quantcast
--Inspired by Author Tekkub and his mod PicoEXP

local start, max, starttime, startlevel

local f = CreateFrame("frame","xanEXP",UIParent)
f:SetScript("OnEvent", function(self, event, ...) if self[event] then return self[event](self, event, ...) end end)

local debugf = tekDebug and tekDebug:GetFrame("xanEXP")
local function Debug(...)
    if debugf then debugf:AddMessage(string.join(", ", tostringall(...))) end
end

----------------------
--      Enable      --
----------------------

function f:PLAYER_LOGIN()

	if not XanEXP_DB then XanEXP_DB = {} end
	if XanEXP_DB.bgShown == nil then XanEXP_DB.bgShown = 1 end
	if XanEXP_DB.scale == nil then XanEXP_DB.scale = 1 end

	self:CreateEXP_Frame()
	self:RestoreLayout("xanEXP")

	start, max, starttime = UnitXP("player"), UnitXPMax("player"), GetTime()
	startlevel = UnitLevel("player") + start/max

	self:RegisterEvent("PLAYER_XP_UPDATE")
	self:RegisterEvent("PLAYER_LEVEL_UP")

	self:PLAYER_XP_UPDATE()

	SLASH_XANEXP1 = "/xanexp";
	SlashCmdList["XANEXP"] = xanEXP_SlashCommand;

	local ver = GetAddOnMetadata("xanEXP","Version") or '1.0'
	DEFAULT_CHAT_FRAME:AddMessage(string.format("|cFF99CC33%s|r [v|cFFDF2B2B%s|r] loaded:   /xanexp", "xanEXP", ver or "1.0"))

	self:UnregisterEvent("PLAYER_LOGIN")
	self.PLAYER_LOGIN = nil
end

function xanEXP_SlashCommand(cmd)

	local a,b,c=strfind(cmd, "(%S+)"); --contiguous string of non-space characters

	if a then
		if c and c:lower() == "bg" then
			xanEXP:BackgroundToggle()
			return true
		elseif c and c:lower() == "reset" then
			DEFAULT_CHAT_FRAME:AddMessage("xanEXP: Frame position has been reset!");
			xanEXP:ClearAllPoints()
			xanEXP:SetPoint("CENTER", UIParent, "CENTER", 0, 0)
			return true
		elseif c and c:lower() == "scale" then
			if b then
				local scalenum = strsub(cmd, b+2)
				if scalenum and scalenum ~= "" and tonumber(scalenum) then
					XanEXP_DB.scale = tonumber(scalenum)
					xanEXP:SetScale(tonumber(scalenum))
					DEFAULT_CHAT_FRAME:AddMessage("xanEXP: scale has been set to ["..tonumber(scalenum).."]")
					return true
				end
			end
		end
	end

	DEFAULT_CHAT_FRAME:AddMessage("xanEXP");
	DEFAULT_CHAT_FRAME:AddMessage("/xanexp reset - resets the frame position");
	DEFAULT_CHAT_FRAME:AddMessage("/xanexp bg - toggles the background on/off");
	DEFAULT_CHAT_FRAME:AddMessage("/xanexp scale # - Set the scale of the xanEXP frame")
end

local function FormatTime(sTime)
	if type(sTime) == "number" and sTime > 0 then
        local day = floor(sTime / 86400)
		local hour = floor((sTime - (day * 86400)) / 3600)
		local minute = floor((sTime - (day * 86400) - (hour * 3600)) / 60)
		local second = floor(mod(sTime, 60))

		if day < 0 then
			return "Waiting..."
		else
            local sString = ""
            if day > 0 then
               sString = day .. "d "
            end
            if hour > 0 or sString ~= "" then
               sString = sString .. hour .. "h "
            end
            if minute > 0 or sString ~= "" then
               sString = sString .. minute .. "m "
            end
            if second > 0 or sString ~= "" then
               sString = sString .. second .. "s"
            end
            return sString
		end
	else
		return "Waiting..."
	end
end

function f:CreateEXP_Frame()

	f:SetWidth(61)
	f:SetHeight(27)
	f:SetMovable(true)
	f:SetClampedToScreen(true)

	f:SetScale(XanEXP_DB.scale)

	if XanEXP_DB.bgShown == 1 then
		f:SetBackdrop( {
			bgFile = "Interface\\TutorialFrame\\TutorialFrameBackground";
			edgeFile = "Interface\\Tooltips\\UI-Tooltip-Border";
			tile = true; tileSize = 32; edgeSize = 16;
			insets = { left = 5; right = 5; top = 5; bottom = 5; };
		} );
		f:SetBackdropBorderColor(0.5, 0.5, 0.5);
		f:SetBackdropColor(0.5, 0.5, 0.5, 0.6)
	else
		f:SetBackdrop(nil)
	end

	f:EnableMouse(true);

	local t = f:CreateTexture("$parentIcon", "ARTWORK")
	t:SetTexture("Interface\\AddOns\\xanEXP\\icon")
	t:SetWidth(16)
	t:SetHeight(16)
	t:SetPoint("TOPLEFT",5,-6)

	local g = f:CreateFontString("$parentText", "ARTWORK", "GameFontNormalSmall")
	g:SetJustifyH("LEFT")
	g:SetPoint("CENTER",8,0)
	g:SetText("lala")

	f:SetScript("OnMouseDown",function()
		if (IsShiftKeyDown()) then
			self.isMoving = true
			self:StartMoving();
	 	end
	end)
	f:SetScript("OnMouseUp",function()
		if( self.isMoving ) then

			self.isMoving = nil
			self:StopMovingOrSizing()

			f:SaveLayout(self:GetName());

		end
	end)
	f:SetScript("OnLeave",function()
		GameTooltip:Hide()
	end)

	f:SetScript("OnEnter",function()

		GameTooltip:SetOwner(self, "ANCHOR_NONE")
		GameTooltip:SetPoint(self:GetTipAnchor(self))
		GameTooltip:ClearLines()

		GameTooltip:AddLine("xanEXP")

		local cur = UnitXP("player")
		local maxXP = UnitXPMax("player")
		local restXP = GetXPExhaustion() or 0
		local remainXP = maxXP - (cur + restXP)
		local toLevelXPPercent = math.floor((maxXP - cur) / maxXP * 100)

        local sessionTime = GetTime() - starttime
		local xpGainedSession = (cur - start)
        local xpPerSecond = ceil(xpGainedSession / sessionTime)
		local xpPerMinute = ceil(xpPerSecond * 60)
        local xpPerHour = ceil(xpPerSecond * 3600)
        local timeToLevel
		if xpPerSecond <= 0 then
			timeToLevel = "None"
		else
			timeToLevel = (maxXP - cur) / xpPerSecond
		end
		GameTooltip:AddDoubleLine("EXP:", cur.."/"..max, nil,nil,nil, 1,1,1)
		GameTooltip:AddDoubleLine("Rest:", string.format("%d%%", (GetXPExhaustion() or 0)/max*100), nil,nil,nil, 1,1,1)
		GameTooltip:AddDoubleLine("TNL:", maxXP-cur..(" ("..toLevelXPPercent.."%)"), nil,nil,nil, 1,1,1)
		GameTooltip:AddDoubleLine("XP/Sec:", xpPerSecond, nil,nil,nil, 1,1,1)
		GameTooltip:AddDoubleLine("XP/Minute:", xpPerMinute, nil,nil,nil, 1,1,1)
		GameTooltip:AddDoubleLine("XP/Hour:", xpPerHour, nil,nil,nil, 1,1,1)
		GameTooltip:AddDoubleLine("Time To Level:", FormatTime(timeToLevel), nil,nil,nil, 1,1,1)
		GameTooltip:AddLine(string.format("%s hours played this session", ceil(sessionTime/3600)), 1,1,1)
		GameTooltip:AddLine(xpGainedSession.." EXP gained this session", 1,1,1)
		GameTooltip:AddLine(string.format("%s levels gained this session", ceil(UnitLevel("player") + cur/max - startlevel)), 1,1,1)

		GameTooltip:Show()
	end)


	f:Show();
end

function f:SaveLayout(frame)
	if type(frame) ~= "string" then return end
	if not _G[frame] then return end
	if not XanEXP_DB then XanEXP_DB = {} end

	local opt = XanEXP_DB[frame] or nil

	if not opt then
		XanEXP_DB[frame] = {
			["point"] = "CENTER",
			["relativePoint"] = "CENTER",
			["xOfs"] = 0,
			["yOfs"] = 0,
		}
		opt = XanEXP_DB[frame]
		return
	end

	local point, relativeTo, relativePoint, xOfs, yOfs = _G[frame]:GetPoint()
	opt.point = point
	opt.relativePoint = relativePoint
	opt.xOfs = xOfs
	opt.yOfs = yOfs
end

function f:RestoreLayout(frame)
	if type(frame) ~= "string" then return end
	if not _G[frame] then return end
	if not XanEXP_DB then XanEXP_DB = {} end

	local opt = XanEXP_DB[frame] or nil

	if not opt then
		XanEXP_DB[frame] = {
			["point"] = "CENTER",
			["relativePoint"] = "CENTER",
			["xOfs"] = 0,
			["yOfs"] = 0,
		}
		opt = XanEXP_DB[frame]
	end

	_G[frame]:ClearAllPoints()
	_G[frame]:SetPoint(opt.point, UIParent, opt.relativePoint, opt.xOfs, opt.yOfs)
end



function f:BackgroundToggle()
	if not XanEXP_DB then XanEXP_DB = {} end
	if XanEXP_DB.bgShown == nil then XanEXP_DB.bgShown = 1 end

	if XanEXP_DB.bgShown == 0 then
		XanEXP_DB.bgShown = 1;
		DEFAULT_CHAT_FRAME:AddMessage("xanEXP: Background Shown");
	elseif XanEXP_DB.bgShown == 1 then
		XanEXP_DB.bgShown = 0;
		DEFAULT_CHAT_FRAME:AddMessage("xanEXP: Background Hidden");
	else
		XanEXP_DB.bgShown = 1
		DEFAULT_CHAT_FRAME:AddMessage("xanEXP: Background Shown");
	end

	--now change background
	if XanEXP_DB.bgShown == 1 then
		f:SetBackdrop( {
			bgFile = "Interface\\TutorialFrame\\TutorialFrameBackground";
			edgeFile = "Interface\\Tooltips\\UI-Tooltip-Border";
			tile = true; tileSize = 32; edgeSize = 16;
			insets = { left = 5; right = 5; top = 5; bottom = 5; };
		} );
		f:SetBackdropBorderColor(0.5, 0.5, 0.5);
		f:SetBackdropColor(0.5, 0.5, 0.5, 0.6)
	else
		f:SetBackdrop(nil)
	end

end

------------------------------
--      Event Handlers      --
------------------------------

function f:PLAYER_XP_UPDATE()
	local currentXP = UnitXP("player")
	local maxXP = UnitXPMax("player")
	local restXP = GetXPExhaustion() or 0
	local remainXP = maxXP - (currentXP + restXP)
	local toLevelXPPercent = math.floor((maxXP - currentXP) / maxXP * 100)

	--getglobal("xanEXPText"):SetText(string.format("%d%%", currentXP/maxXP*100).." TNL: "..toLevelXPPercent.."%")
	getglobal("xanEXPText"):SetText(string.format("%d%%", currentXP/maxXP*100))
end

function f:PLAYER_LEVEL_UP()
	start = start - max
	max = UnitXPMax("player")
end

------------------------
--      Tooltip!      --
------------------------

function f:GetTipAnchor(frame)
	local x,y = frame:GetCenter()
	if not x or not y then return "TOPLEFT", "BOTTOMLEFT" end
	local hhalf = (x > UIParent:GetWidth()*2/3) and "RIGHT" or (x < UIParent:GetWidth()/3) and "LEFT" or ""
	local vhalf = (y > UIParent:GetHeight()/2) and "TOP" or "BOTTOM"
	return vhalf..hhalf, frame, (vhalf == "TOP" and "BOTTOM" or "TOP")..hhalf
end

if IsLoggedIn() then f:PLAYER_LOGIN() else f:RegisterEvent("PLAYER_LOGIN") end