diff --git a/Command.lua b/Command.lua index dbf4f78..55f9d3c 100644 --- a/Command.lua +++ b/Command.lua @@ -132,6 +132,36 @@ C:Register({"list", "moblist", "mobs"}, function(args) KT.MobList:ShowGUI() end) +C:Register({"time", "timer"}, function(args) + if #args <= 0 then + KT:Msg("Usage: time <seconds> [minutes] [hours]") + KT:Msg("Usage: time <seconds>[s<minutes>m[<hours>h]]") + return + end + + local s, m, h + + if #args == 1 then + if not tonumber(args[1]) then + args[1] = args[1]:lower() + s = args[1]:match("(%d+)s") + m = args[1]:match("(%d+)m") + h = args[1]:match("(%d+)h") + if not s and not m and not h then + KT:Msg("Invalid number format.") + return + end + else + s = tonumber(args[1]) + end + else + s = tonumber(args[1]) + m = tonumber(args[2]) + h = tonumber(args[3]) + end + KT.TimerFrame:Start(s, m, h) +end) + for i,v in ipairs(C.Slash) do _G["SLASH_" .. KT.Name:upper() .. i] = "/" .. v end diff --git a/KillTrack.lua b/KillTrack.lua index 918f8fe..0f94c53 100644 --- a/KillTrack.lua +++ b/KillTrack.lua @@ -76,6 +76,9 @@ function KT.Events.COMBAT_LOG_EVENT_UNFILTERED(self, ...) local name = tostring((select(9, ...))) if id == 0 then return end self:AddKill(id, name) + if self.Timer:IsRunning() then + self.Timer:SetData("Kills", self.Timer:GetData("Kills", true) + 1) + end end function KT.Events.UPDATE_MOUSEOVER_UNIT(self, ...) diff --git a/KillTrack.toc b/KillTrack.toc index e9153a2..8fe7263 100644 --- a/KillTrack.toc +++ b/KillTrack.toc @@ -16,3 +16,6 @@ KillTrack.lua Dialogs.lua Command.lua MobList.lua +Timer.lua +TimerFrame.lua +TimerFrame.xml diff --git a/Timer.lua b/Timer.lua new file mode 100644 index 0000000..d4bb3ab --- /dev/null +++ b/Timer.lua @@ -0,0 +1,124 @@ +-- + +KillTrack.Timer = { + Time = { + Start = 0, + Stop = 0 + }, + Running = false, + State = { + START = 0, + UPDATE = 1, + STOP = 2 + } +} + +local KT = KillTrack +local T = KT.Timer + +local KTT = KillTrack_Tools + +local TimerData = {} + +local function FormatTime(s) + local h = floor(s/60/60) + local m = floor(s/60) - h * 60 + s = s - h * 60 ^ 2 - m * 60 + return ("%02.0f:%02.0f:%02.0f"):format(h, m, s) +end + +T.Frame = CreateFrame("Frame") + +local function TimeCheck(_, _) + if not T.Running then print("TIMER AUTO-STOP") T.Frame:SetScript("OnUpdate", nil) return end + local now = time() + TimerData.Last = now + TimerData.Current = now - T.Time.Start + TimerData.Start = T.Time.Start + TimerData.Stop = T.Time.Stop + TimerData.Total = TimerData.Stop - TimerData.Start + TimerData.Left = TimerData.Total - TimerData.Current + TimerData.LeftFormat = FormatTime(TimerData.Left) + TimerData.Progress = TimerData.Current / TimerData.Total + T:RunCallback(T:GetAllData(), T.State.UPDATE) + if now >= T.Time.Stop then print("TIMER REACHED END") T:Stop() end +end + +function T:GetAllData() + return KTT:TableCopy(TimerData) +end + +function T:GetData(key, failsafe) + local r + if failsafe then r = 0 end + if not TimerData.__DATA__ then if failsafe then return 0 else return nil end end + return TimerData.__DATA__[key] or r +end + +function T:SetData(key, value) + if type(TimerData.__DATA__) ~= "table" then TimerData.__DATA__ = {} end + TimerData.__DATA__[key] = value +end + +function T:IsRunning() + return self.Running +end + +function T:Start(seconds, minutes, hours, callback, data) + if self.Running then return end + self.Running = true + self:Reset() + seconds = tonumber(seconds) or 0 + minutes = tonumber(minutes) or 0 + hours = tonumber(hours) or 0 + seconds = seconds + minutes * 60 + hours * 60 ^ 2 + if seconds <= 0 then + self.Running = false + KT:Msg("Time must be greater than zero.") + return + end + if type(callback) == "function" then + self:SetCallback(callback) + end + if type(data) == "table" then + for k,v in pairs(data) do + self:SetData(k, v) + end + end + self.Time.Start = time() + self.Time.Stop = self.Time.Start + seconds + self:RunCallback(self:GetAllData(), self.State.START) + self.Frame:SetScript("OnUpdate", TimeCheck) + print("TIMER START") +end + +function T:Stop() + if not self.Running then return end + self.Frame:SetScript("OnUpdate", nil) + self:RunCallback(self:GetAllData(), self.State.STOP) + self.Running = false + self.Time.Diff = self.Time.Stop - self.Time.Start + print("TIMER STOPPED") + return self.Time.Diff +end + +function T:Reset() + wipe(TimerData) + self.Time.Start = 0 + self.Time.Stop = 0 +end + +function T:GetCallback() + return self.Callback +end + +function T:SetCallback(func) + if type(func) ~= "function" then error("Argument 'func' must be of type 'function'.") end + self.Callback = func +end + +function T:RunCallback(data, state) + if type(data) ~= "table" then error("Argument 'data' must be of type 'table'.") end + local callback = self:GetCallback() + if callback then callback(data, state) end +end diff --git a/TimerFrame.lua b/TimerFrame.lua new file mode 100644 index 0000000..6283cd3 --- /dev/null +++ b/TimerFrame.lua @@ -0,0 +1,87 @@ +-- + +local BAR_MAX_WIDTH = 190 + +local function Enabled(object, enabled) + if not object.Enable or not object.Disable then return end + if enabled then + object:Enable() + else + object:Disable() + end +end + +local function Toggle(object) + if not object.IsEnabled or not object.Enable or not object.Disable then return end + if object:IsEnabled() then + object:Disable() + else + object:Enable() + end +end + +KillTrack.TimerFrame = { + Running = false +} + +local KT = KillTrack +local TF = KT.TimerFrame +local T = KillTrack.Timer + +function TF:InitializeControls() + KillTrackTimerFrame_CurrentCount:SetText("0") + KillTrackTimerFrame_TimeCount:SetText("00:00:00") + KillTrackTimerFrame_ProgressLabel:SetText("0%") + KillTrackTimerFrame_ProgressBar:SetWidth(0.01) + self:UpdateControls() +end + +function TF:UpdateControls() + Enabled(KillTrackTimerFrame_CancelButton, self.Running) + Enabled(KillTrackTimerFrame_CloseButton, not self.Running) +end + +function TF:UpdateData(data, state) + if state == T.State.START then + self:InitializeControls() + else + local kills = T:GetData("Kills", true) + local kpm, kps + if data.Current <= 0 then + kpm, kps = 0, 0 + else + kpm = kills / (data.Current / 60) + kps = kills / data.Current + end + KillTrackTimerFrame_CurrentCount:SetText(kills) + KillTrackTimerFrame_TimeCount:SetText(data.LeftFormat) + KillTrackTimerFrame_ProgressLabel:SetText(floor(data.Progress*100) .. "%") + KillTrackTimerFrame_ProgressBar:SetWidth(data.Progress <= 0 and 0.01 or BAR_MAX_WIDTH * data.Progress) + KillTrackTimerFrame_KillsPerMinuteCount:SetText(("%.2f"):format(kpm)) + KillTrackTimerFrame_KillsPerSecondCount:SetText(("%.2f"):format(kps)) + if state == T.State.STOP then self:Stop() end + end + self:UpdateControls() +end + +function TF:Start(s, m, h) + if self.Running then return end + self.Running = true + self:InitializeControls() + KillTrackTimerFrame:Show() + T:Start(s, m, h, function(d, u) TF:UpdateData(d, u) end, nil) +end + +function TF:Stop() + if not self.Running then return end + self.Running = false +end + +function TF:Cancel() + T:Stop() +end + +function TF:Close() + self:InitializeControls() + KillTrackTimerFrame:Hide() +end diff --git a/TimerFrame.xml b/TimerFrame.xml new file mode 100644 index 0000000..d9c4e60 --- /dev/null +++ b/TimerFrame.xml @@ -0,0 +1,166 @@ +<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"> + <Font name="KillTrackFontTemplate" font="Fonts\FRIZQT__.TTF" virtual="true"> + <Color a="1" r="1" g="1" b="1" /> + <FontHeight> + <AbsValue val="10" /> + </FontHeight> + </Font> + <Frame name="KillTrackTimerFrame" hidden="true" movable="true" enableMouse="true"> + <Size> + <AbsDimension x="200" y="93" /> + </Size> + <Anchors> + <Anchor point="CENTER" /> + </Anchors> + <Backdrop bgFile="Interface\DialogFrame\UI-DialogBox-Background" edgeFile="Interface\Tooltips\UI-Tooltip-Border" tile="true"> + <EdgeSize> + <AbsValue val="16" /> + </EdgeSize> + <TileSize> + <AbsValue val="32" /> + </TileSize> + <BackgroundInsets> + <AbsInset left="2.5" right="2.5" top="2.5" bottom="2.5" /> + </BackgroundInsets> + </Backdrop> + <Scripts> + <OnMouseDown>self:StartMoving();</OnMouseDown> + <OnMouseUp>self:StopMovingOrSizing();</OnMouseUp> + </Scripts> + <Layers> + <Layer level="OVERLAY"> + <FontString name="$parent_CurrentLabel" inherits="KillTrackFontTemplate" text="Number of kills:"> + <Anchors> + <Anchor point="TOPLEFT"> + <Offset> + <AbsDimension x="6" y="-6" /> + </Offset> + </Anchor> + </Anchors> + </FontString> + <FontString name="$parent_CurrentCount" inherits="KillTrackFontTemplate" text="0"> + <Anchors> + <Anchor point="TOPRIGHT"> + <Offset> + <AbsDimension x="-6" y="-6" /> + </Offset> + </Anchor> + </Anchors> + </FontString> + <FontString name="$parent_TimeLabel" inherits="KillTrackFontTemplate" text="Time left:"> + <Anchors> + <Anchor point="TOPLEFT" relativeTo="$parent_CurrentLabel" relativePoint="BOTTOMLEFT"> + <Offset> + <AbsDimension x="0" y="-2" /> + </Offset> + </Anchor> + </Anchors> + </FontString> + <FontString name="$parent_TimeCount" inherits="KillTrackFontTemplate" text="00:00:00"> + <Anchors> + <Anchor point="TOPRIGHT" relativeTo="$parent_CurrentCount" relativePoint="BOTTOMRIGHT"> + <Offset> + <AbsDimension x="0" y="-2" /> + </Offset> + </Anchor> + </Anchors> + </FontString> + <FontString name="$parent_KillsPerMinuteLabel" inherits="KillTrackFontTemplate" text="Kills Per Minute:"> + <Anchors> + <Anchor point="TOPLEFT" relativeTo="$parent_TimeLabel" relativePoint="BOTTOMLEFT"> + <Offset> + <AbsDimension x="0" y="-2" /> + </Offset> + </Anchor> + </Anchors> + </FontString> + <FontString name="$parent_KillsPerMinuteCount" inherits="KillTrackFontTemplate" text="0"> + <Anchors> + <Anchor point="TOPRIGHT" relativeTo="$parent_TimeCount" relativePoint="BOTTOMRIGHT"> + <Offset> + <AbsDimension x="0" y="-2" /> + </Offset> + </Anchor> + </Anchors> + </FontString> + <FontString name="$parent_KillsPerSecondLabel" inherits="KillTrackFontTemplate" text="Kills Per Second:"> + <Anchors> + <Anchor point="TOPLEFT" relativeTo="$parent_KillsPerMinuteLabel" relativePoint="BOTTOMLEFT"> + <Offset> + <AbsDimension x="0" y="-2" /> + </Offset> + </Anchor> + </Anchors> + </FontString> + <FontString name="$parent_KillsPerSecondCount" inherits="KillTrackFontTemplate" text="0"> + <Anchors> + <Anchor point="TOPRIGHT" relativeTo="$parent_KillsPerMinuteCount" relativePoint="BOTTOMRIGHT"> + <Offset> + <AbsDimension x="0" y="-2" /> + </Offset> + </Anchor> + </Anchors> + </FontString> + <FontString name="$parent_ProgressLabel" inherits="KillTrackFontTemplate" text="0%"> + <Anchors> + <Anchor point="TOP"> + <Offset> + <AbsDimension x="0" y="-55" /> + </Offset> + </Anchor> + </Anchors> + </FontString> + </Layer> + <Layer level="ARTWORK"> + <Texture name="$parent_ProgressBar" file="Interface\TargetingFrame\UI-StatusBar"> + <Color a="1" r="0" g="1" b="0" /> + <Size> + <AbsDimension x="1" y="12" /> + </Size> + <Anchors> + <Anchor point="TOPLEFT" relativeTo="$parent_KillsPerSecondLabel" relativePoint="BOTTOMLEFT"> + <Offset> + <AbsDimension x="-1" y="-2" /> + </Offset> + </Anchor> + </Anchors> + </Texture> + </Layer> + </Layers> + <Frames> + <Button name="$parent_CancelButton" inherits="UIPanelButtonTemplate2" text="Cancel"> + <Size> + <AbsDimension x="60" y="16" /> + </Size> + <Anchors> + <Anchor point="BOTTOM"> + <Offset> + <AbsDimension x="-40" y="7" /> + </Offset> + </Anchor> + </Anchors> + <Scripts> + <OnLoad>self:Disable();</OnLoad> + <OnClick>KillTrack.TimerFrame:Cancel();</OnClick> + </Scripts> + </Button> + <Button name="$parent_CloseButton" inherits="UIPanelButtonTemplate2" text="Close"> + <Size> + <AbsDimension x="60" y="16" /> + </Size> + <Anchors> + <Anchor point="BOTTOM"> + <Offset> + <AbsDimension x="40" y="7" /> + </Offset> + </Anchor> + </Anchors> + <Scripts> + <OnLoad>self:Disable();</OnLoad> + <OnClick>KillTrack.TimerFrame:Close();</OnClick> + </Scripts> + </Button> + </Frames> + </Frame> +</Ui>