WoWInterface

WoWInterface (https://www.wowinterface.com/forums/index.php)
-   Lua/XML Help (https://www.wowinterface.com/forums/forumdisplay.php?f=16)
-   -   Count Down Timer (https://www.wowinterface.com/forums/showthread.php?t=49276)

cokedrivers 05-08-14 10:19 PM

Count Down Timer
 
I was wondering if there is a way to add a count down timer to the frame that you click enter dungeon on to show exactly how long you have. Lately ive qued for ramdoms and been in the middle of a quest and would like to lnow how long I have u ntill the window closes.

I am on my phone right now but with /fstack I was able to get the frame name. I would something like
Code:

countdowntimer = CreateFrame ("Frame", nil, (the frames name))
countdowntimer:SetPoint ("BOTTOM", (the frame name), 0, 0)

to create a frame to put the count down in.

Ive seen DBM have a count down stays bar show. But I'm just looking for a numeric count down nothing dance.

Ill look threw DBM maybe I can find how they get the timer info.

Coke

10leej 05-08-14 10:47 PM

Quote:

Originally Posted by cokedrivers (Post 292638)
I was wondering if there is a way to add a count down timer to the frame that you click enter dungeon on to show exactly how long you have. Lately ive qued for ramdoms and been in the middle of a quest and would like to lnow how long I have u ntill the window closes.

I am on my phone right now but with /fstack I was able to get the frame name. I would something like
Code:

countdowntimer = CreateFrame ("Frame", nil, (the frames name))
countdowntimer:SetPoint ("BOTTOM", (the frame name), 0, 0)

to create a frame to put the count down in.

Ive seen DBM have a count down stays bar show. But I'm just looking for a numeric count down nothing dance.

Ill look threw DBM maybe I can find how they get the timer info.

Coke

The basic function is simple enough. I use this for a pull timer, though it uses a chat output
Lua Code:
  1. local pull, seconds, onesec
  2. local frame = CreateFrame("Frame")
  3. frame:Hide()
  4. frame:SetScript("OnUpdate", function(self, elapsed)
  5.     --Start DBM pull timer
  6.     onesec = onesec - elapsed
  7.     pull = pull - elapsed
  8.     if pull <= 0 then
  9.         SendChatMessage("Pulling!", cfg.channelannounce)
  10.         self:Hide()
  11.     elseif onesec <= 0 then
  12.         SendChatMessage(seconds, cfg.channelannounce)
  13.         seconds = seconds - 1
  14.         onesec = 1
  15.     end
  16. end)
  17. SlashCmdList["COUNTDOWN"] = function(t)
  18.     t = tonumber(t) or 6
  19.     pull = t + 1
  20.     seconds = t
  21.     onesec = 1
  22.     frame:Show()
  23. end
  24. SLASH_COUNTDOWN1 = "/inc"

just replace SendChatMessage and a few other things with a status bar fill I imagine.

Phanx 05-08-14 11:55 PM

Quote:

Originally Posted by cokedrivers (Post 292638)
Ive seen DBM have a count down stays bar show. But I'm just looking for a numeric count down nothing dance.

Ill look threw DBM maybe I can find how they get the timer info.

DBM just hardcodes it at 40 seconds; AFAIK there is no API function to get the remaining time.

Code:

local PROPOSAL_DURATION = 40

local frame = CreateFrame("Frame", nil, LFGDungeonReadyPopup)
frame:SetPoint("TOP", LFGDungeonReadyPopup, "BOTTOM", 0, -5)
frame:SetSize(20, 20) -- doesn't actually matter, just needs nonzero dimensions

local text = frame:CreateFontString(nil, "ARTWORK", "GameFontNormalLarge")
text:SetPoint("TOP")

local t = PROPOSAL_DURATION
frame:SetScript("OnUpdate", function(self, elapsed)
    t = t - elapsed
    text:SetText(floor(t + 0.5))
end)

frame:RegisterEvent("LFG_PROPOSAL_SHOW")
frame:SetScript("OnEvent", function(self, event)
    if event == "LFG_PROPOSAL_SHOW" then
          t = PROPOSAL_DURATION
          self:Show()
    else
          self:Hide()
    end
end)

If you wanted a status bar (complete with gradient coloring) instead:

Code:

local PROPOSAL_DURATION = 40

local bar = CreateFrame("StatusBar", nil, LFGDungeonReadyPopup)
bar:SetPoint("TOPLEFT", LFGDungeonReadyPopup, "BOTTOMLEFT", 0, -5)
bar:SetPoint("TOPRIGHT", LFGDungeonReadyPopup, "BOTTOMRIGHT", 0, -5)
bar:SetHeight(5)
bar:SetStatusBarTexture("Interface\\TargetingFrame\\UI-StatusBar")
bar:SetMinMaxValues(0, PROPOSAL_DURATION)

local spark = bar:CreateTexture(nil, "OVERLAY")
spark:SetPoint("CENTER", bar:GetStatusBarTexture(), "LEFT")
spark:SetSize(5, 8) -- height should be about 2.5x width
spark:SetAlpha(0.5)
spark:SetTexture("Interface\\CastingBar\\UI-CastingBar-Spark")
spark:SetBlendMode("ADD")

local t = PROPOSAL_DURATION
local HALF_POINT = PROPOSAL_DURATION / 2
bar:SetScript("OnUpdate", function(self, elapsed)
    t = t - elapsed
    self:SetValue(t)
    if t > HALF_POINT then
          self:SetStatusBarColor(1, t / PROPOSAL_DURATION, 0)
    else
          self:SetStatusBarColor(1 - (t / PROPOSAL_DURATION), 1, 0)
    end
end)

frame:RegisterEvent("LFG_PROPOSAL_SHOW")
frame:SetScript("OnEvent", function(self, event)
    if event == "LFG_PROPOSAL_SHOW" then
          t = PROPOSAL_DURATION
          self:Show()
    else
          self:Hide()
    end
end)


cokedrivers 05-09-14 07:34 AM

Thank you for both versions, ill test it tonight. Now if the 40 seconds is to long all ill need to change is the 40 at the top correct?

Coke

EDIT: Will this also work for PvP, or is that a different frame?

Phanx 05-09-14 07:25 PM

PvP is a different frame, a different event, and possibly a different duration, but the general idea should be the same.

cokedrivers 05-09-14 09:47 PM

Quote:

Originally Posted by Phanx (Post 292676)
PvP is a different frame, a different event, and possibly a different duration, but the general idea should be the same.

so for the PvP I was able to create this:
Code:

        local PROPOSAL_DURATION = 90

        local PVPTimerFrame = CreateFrame("Frame", nil, PVPReadyDialog)
        PVPTimerFrame:SetPoint("TOP", PVPReadyDialog, "BOTTOM", -1, 20)
        PVPTimerFrame:SetWidth(300)
        PVPTimerFrame:SetHeight(35)
        PVPTimerFrame:SetBackdrop({
                bgFile = [[Interface\DialogFrame\UI-DialogBox-Background-Dark]],
                edgeFile = [[Interface\AddOns\nExtras\Media\UI-DialogBox-Border.blp]],
                edgeSize = 25, insets = { left = 5, right = 5, top = 5, bottom = 5 }
        })
        PVPTimerFrame:SetBackdropColor(0, 0, 0, 1)
       
        local text = PVPTimerFrame:CreateFontString(nil, "ARTWORK", "GameFontNormalLarge")
        text:SetPoint("CENTER")

        local t = PROPOSAL_DURATION
        PVPTimerFrame:SetScript("OnUpdate", function(self, elapsed)
                t = t - elapsed
                text:SetText(floor(t + 0.5).."s left to Enter Battleground.")
        end)

        PVPTimerFrame:RegisterEvent("UPDATE_BATTLEFIELD_STATUS")
        PVPTimerFrame:SetScript("OnEvent", function(self, event)
                if event == "UPDATE_BATTLEFIELD_STATUS" then
                          t = PROPOSAL_DURATION
                          self:Show()
                else
                          self:Hide()
                end
        end)

Which inturn gave me this:


But the time keeps reseting, I don't think I have the correct event. There are like 6 of them but in the event doc page the other ones are for like World PvP not battlegrounds.

Thanks for any help.

Coke

Resike 05-10-14 03:27 AM

I don't think the event is the issue here, more like the timer onupdate. Elapsed is a time in miliseconds, and the 90 sec timer is a decimal. I can make an example tonight how do it, if noone will do it faster, but i have to leave now.

Lombra 05-10-14 03:54 AM

No, elapsed is in seconds.

You could try the BATTLEFIELD_MGR_ENTRY_INVITE event.

karmamuscle 05-10-14 05:23 AM

Quote:

Originally Posted by cokedrivers (Post 292678)

That looks really useful for dungeon/lfr/pvp queues!
Is it something that you plan to release as a standalone addon?

cokedrivers 05-10-14 07:32 AM

Quote:

Originally Posted by ckramme (Post 292682)
That looks really useful for dungeon/lfr/pvp queues!
Is it something that you plan to release as a standalone addon?

Its just my idea as far as a stand alone addon that would be up to Phanx she wrote the code all I did was add the border and background.

Personally I still need to test the LFG and LFR to see if the time matches. When I'm done ill post the code here if Phanx chooses not to make a stand alone.

Coke

Phanx 05-10-14 09:15 AM

Based on a quick glance at the code in FrameXML\PVPHelper.lua, I'd guess you want BATTLEFIELD_MGR_ENTRY_INVITE as Lombra suggested.

Also, be careful with your global names. "PVPTimerFrame" is already used by a default UI frame, so overwriting it with your own frame is likely to cause some issues.

cokedrivers 05-10-14 10:47 AM

Quote:

Originally Posted by Phanx (Post 292689)
Based on a quick glance at the code in FrameXML\PVPHelper.lua, I'd guess you want BATTLEFIELD_MGR_ENTRY_INVITE as Lombra suggested.

Also, be careful with your global names. "PVPTimerFrame" is already used by a default UI frame, so overwriting it with your own frame is likely to cause some issues.

Will try the new event this evening when I get home. As for the frame name do you think "LFGQueueCountdown" and "PVPQueueCountdown" would work for names cause i remember you saying i need to make them different so other addons or the main ui dont cross.

Phanx 05-10-14 11:52 AM

Quote:

Originally Posted by cokedrivers (Post 292694)
Will try the new event this evening when I get home. As for the frame name do you think "LFGQueueCountdown" and "PVPQueueCountdown" would work for names cause i remember you saying i need to make them different so other addons or the main ui dont cross.

Log into the game and type "/dump LFGQueueCountdown" -- if you see anything other than "empty result" then that name is already taken.

However, in addition to your globals being unique, you should also make them identifiable as belonging to your addon -- this way you don't have to check if they're already used by some other addon, and other authors following the same best practice also don't have to check other addons to see if the name is in use.

However #2, there's no reason to give these things you're creating global names at all, since you're not using Blizzard templates that require them.

cokedrivers 05-10-14 07:20 PM

BATTLEFIELD_MGR_ENTRY_INVITE doesn't seem to work. If I select "Leave Queue" then sign up again it continues to count down from were it left off.

Will look go hunting around the interweb to see if I can find a solution.

Coke

Phanx 05-11-14 12:30 AM

Upon further reading in the default UI code, you probably want UPDATE_BATTLEFIELD_STATUS after all, but you need to do an additional check to see whether the event is relevant:

Code:

f:RegisterEvent("UPDATE_BATTLEFIELD_STATUS")
f:SetScript("OnEvent", function(self, event, index)
        if GetBattlefieldStatus(index) == "confirm" then
                  t = PROPOSAL_DURATION
                  self:Show()
        else
                  self:Hide()
        end
end)


cokedrivers 05-11-14 08:28 AM

Quote:

Originally Posted by Phanx (Post 292712)
Upon further reading in the default UI code, you probably want UPDATE_BATTLEFIELD_STATUS after all, but you need to do an additional check to see whether the event is relevant:

Code:

f:RegisterEvent("UPDATE_BATTLEFIELD_STATUS")
f:SetScript("OnEvent", function(self, event, index)
        if GetBattlefieldStatus(index) == "confirm" then
                  t = PROPOSAL_DURATION
                  self:Show()
        else
                  self:Hide()
        end
end)


Well this did work either, I did figure it out tho thanks to an addon close to the results I was looking for.

This addon is called SafeQueue.

Here is the new code im using.
Code:

-- Provided by Phanx from WoWInterface
       
        local f = CreateFrame("Frame", nil, PVPReadyDialog)
        f:SetPoint("TOP", PVPReadyDialog, "BOTTOM", 0, 15)
        f:SetWidth(PVPReadyDialog:GetWidth() - 4)
        f:SetHeight(36)
        f:SetBackdrop({
                bgFile = [[Interface\DialogFrame\UI-DialogBox-Background-Dark]],
                edgeFile = [[Interface\DialogFrame\UI-DialogBox-Border.blp]],
                edgeSize = 25, insets = { left = 5, right = 5, top = 5, bottom = 5 }
        })
        f:SetBackdropColor(0, 0, 0, 1)
       
        local text = f:CreateFontString(nil, "ARTWORK", "GameFontNormalLarge")
        text:SetPoint("CENTER", f, "CENTER", 0, 0)

        -- Borrowed from SafeQueue by Jordon
        ------------------------------------------------------------------------------------
        local queueTime
        local queue = 0
        local remaining = 0
       
        f:SetScript("OnUpdate", function(self)
                local secs = GetBattlefieldPortExpiration(queue)
                if secs and secs > 0 and remaining ~= secs then
                        remaining = secs
                        local color = secs > 20 and "f20ff20" or secs > 10 and "fffff00" or "fff0000"
                        text:SetText("Queue Expires in |cf"..color.. SecondsToTime(secs) .. "|r")
                end
        end)
       
        function f:UPDATE_BATTLEFIELD_STATUS()
                local queued
                for i=1, GetMaxBattlefieldID() do
                        local status = GetBattlefieldStatus(i)
                        if status == "queued" then
                                queued = true
                                if not queueTime then queueTime = GetTime() end
                        elseif status == "confirm" then
                                if queueTime then
                                        queueTime = nil
                                        remaining = 0
                                        queue = i
                                end                                       
                        end
                        break
                end
                if not queued and queueTime then queueTime = nil end
        end       
       
        f:RegisterEvent("UPDATE_BATTLEFIELD_STATUS")
        f:SetScript("OnEvent", function(self, event, ...) self[event](self, ...) end)
        ------------------------------------------------------------------------------------

Here is a screen shot:


Now just if I can figure out where wow pulls the time to close the LFG popup like they do for the Battleground.

Thanks
Coke

Clamsoda 05-11-14 05:29 PM

I believe Phanx mentioned at the start of the thread that there is no API to derive the timeout for LFR/LFD. You can surely adapt the code you borrowed from SafeQueue to use the 40 second time-frame (also mentioned by Phanx) instead of a time returned by a function call.

Phanx 05-11-14 08:44 PM

The popup is closed in response to other events. There is no timer.

cokedrivers 05-11-14 09:15 PM

Quote:

Originally Posted by Phanx (Post 292733)
The popup is closed in response to other events. There is no timer.

From what I can find seems to be the normal staic popup timer to close the window.

Sources are:
http://wowprogramming.com/utils/xmlb...L/LFGFrame.lua

In this function:
Code:

function LFGInvitePopup_Update(inviter, roleTankAvailable, roleHealerAvailable, roleDamagerAvailable)
there is a line that shows:
Code:

self.timeOut = STATICPOPUP_TIMEOUT;
Then further down in the code it shows:
Code:

function LFGInvitePopup_OnUpdate(self, elapsed)
    self.timeOut = self.timeOut - elapsed;
    if ( self.timeOut <= 0 ) then
        LFGInvitePopupDecline_OnClick();
    end
end

which I'm guessing closes the popup.

Now in this file:http://wowprogramming.com/utils/xmlb...taticPopup.lua

This is at the top of the file:
Code:

STATICPOPUP_TIMEOUT = 60;
So with this information I should set the timeOut to 60 and it should work.

The one thing im not sure of would be the f:SetScript("OnEvent" function(self, event) -- code)
In the Phanx example I got is show a self:Show() and a self.Hide() would that be all that is needed?

Here is my proposed code for the LFG (also while scrolling threw those codes I notice that this was at the top of the code --LFG is used for for generic functions/values that may be used for LFD, LFR, and any other LF_ system we may implement in the future. so it should work on raids as well)
Here is the code:
Code:

        local PROPOSAL_DURATION = 60

        local f = CreateFrame("Frame", nil, LFGDungeonReadyPopup)
        f:SetPoint("TOP", LFGDungeonReadyPopup, "BOTTOM", 0, 15)
        f:SetWidth(LFGDungeonReadyPopup:GetWidth() - 4)
        f:SetHeight(36)
        f:SetBackdrop({
                bgFile = [[Interface\DialogFrame\UI-DialogBox-Background-Dark]],
                edgeFile = [[Interface\DialogFrame\UI-DialogBox-Border.blp]],
                edgeSize = 25, insets = { left = 5, right = 5, top = 5, bottom = 5 }
        })
        f:SetBackdropColor(0, 0, 0, 1)
       
        local text = f:CreateFontString(nil, "ARTWORK", "GameFontNormalLarge")
        text:SetPoint("CENTER", f, "CENTER", 0, 0)       

        f:SetScript("OnUpdate", function(self)
                local remaining = 0
                local sec = PROPOSAL_DURATION
                if secs and secs > 0 and remaining ~= secs then
                        remaining = secs
                        local color = secs > 20 and "f20ff20" or secs > 10 and "fffff00" or "fff0000"
                        text:SetText("Queue Expires in |cf"..color.. SecondsToTime(secs) .. "|r")
                end
        end)

        f:RegisterEvent("LFG_PROPOSAL_SHOW")
        f:SetScript("OnEvent", function(self, event)
                if event == "LFG_PROPOSAL_SHOW" then
                          self:Show()
                else
                          self:Hide()
                end
        end)

Thanks Everyone
Coke

Phanx 05-12-14 01:08 AM

You're not using OnUpdate correctly. You're setting your "remaining" variable to 0 every time your script runs, and setting "sec" to 60, and then checking a variable named "secs" that isn't defined anywhere, and then checking if "remaining" and "secs" are not equal which (assuming the "sec" definition is actually meant to be "sec") will always pass because 0 will never be equal to 60 and those are the only values those variables can ever have, and you're not actually keeping track of how much time has elapsed at all.

Code:

-- This variable needs to be outside of the OnUpdate so it persists between executions:
local remaining = PROPOSAL_DURATION

f:SetScript("OnUpdate", function(self, elapsed) -- You need to know how much time has elapsed
        -- Deduct the elapsed time (since the last OnUpdate) from the total remaining time:
        remaining = remaining - elapsed

        local color = remaining > 20 and "20ff20" or remaining > 10 and "ffff00" or "ff0000"

        -- Use SetFormattedText here, and don't split the color code in the middle of the alpha value.
        text:SetFormattedText("Queue Expires in |cff%s%s|r", color, SecondsToTime(remaining))
end)

f:RegisterEvent("LFG_PROPOSAL_SHOW")
f:SetScript("OnEvent", function(self, event)
        if event == "LFG_PROPOSAL_SHOW" then
                -- Restart the timer:
                remaining = PROPOSAL_DURATION
                self:Show()
        else
                self:Hide()
        end
end)



All times are GMT -6. The time now is 08:43 AM.

vBulletin © 2024, Jelsoft Enterprises Ltd
© 2004 - 2022 MMOUI