Thread Tools Display Modes
03-16-24, 11:05 PM   #1
Hubb777
A Flamescale Wyrmkin
 
Hubb777's Avatar
AddOn Author - Click to view addons
Join Date: Jan 2024
Posts: 113
2 questions on the timer

Hi all. Thanks again to Fizzlemizz, without him I couldn't do anything.

Data:
There are 4 events (A, B, C and D) and they go cyclically and endlessly (example: A, B, C, D, A, B, C, D, A, B, C and D)
The interval between all events is 1 hour (example Between event A and event B is 1 hour, between event B and event C is one hour, between event C and event D is 1 hour).
Events always last 5 minutes.
What is needed: For the event to be displayed correctly (where starttime = 1679572800, this is the start of event A).
For example, if I enter the game 3 hours 30 minutes after the start of event A, it will show me that event D will begin soon.

Source
Lua Code:
  1. local addonName, addon = ...
  2. local Backdrop = {
  3.     bgFile = "Interface\\DialogFrame\\UI-DialogBox-Background",
  4. }
  5.  
  6. local frame_x = 100    
  7. local frame_y = -250    
  8. local f = CreateFrame("Button", "ZAMTimer777", UIParent, "BackdropTemplate")
  9. f:SetWidth(185)                                          
  10. f:SetHeight(30)
  11. f:SetBackdrop(Backdrop)
  12. f.text = f:CreateFontString(nil,"OVERLAY","GameTooltipText")
  13. f.text:SetPoint("CENTER")
  14. f:SetClampedToScreen(true)
  15. f:SetPoint("CENTER",UIParent,"CENTER",frame_x,frame_y)
  16. f:EnableMouse(true)
  17. f:SetMovable(true)
  18. f:RegisterForDrag("LeftButton")
  19. f:RegisterForClicks("AnyUp")
  20. f:Show()
  21. f:RegisterEvent("PLAYER_ENTERING_WORLD")
  22. f:SetScript("OnDragStart",function(self)
  23.     self:StartMoving()
  24. end)
  25. f:SetScript("OnDragStop",function(self)  
  26.     self:StopMovingOrSizing()
  27. end)
  28. -- first %s is replaced by the color. The second is replaced by the time. |r resets the color back to default
  29. local Localizations = {
  30.     enUS = {
  31.         Waiting = {
  32.             "|c1C7BCEFFFroststone A:\nbefore the start: %s%s|r",
  33.             "|c1C7BCEFFFroststone B:\nbefore the start: %s%s|r",
  34.             "|c1C7BCEFFFroststone C:\nbefore the start: %s%s|r",
  35.             "|c1C7BCEFFFroststone D:\nbefore the start: %s%s|r",
  36.         },     
  37.         Running = {
  38.             "|cFF35BE21Froststone A:\n%s%s until completion|r",
  39.             "|cFF35BE21Froststone B:\n%s%s until completion|r",
  40.             "|cFF35BE21Froststone C:\n%s%s until completion|r",
  41.             "|cFF35BE21Froststone D:\n%s%s until completion|r",
  42.         },
  43.     },
  44. }
  45.  
  46. local locale = GetLocale()
  47. local L = Localizations[locale] or Localizations.enUS -- Default to enUS if locale doesn't exist in the table
  48.  
  49. ------------------------------------------------------------------------------------------------------
  50. -- These might be converted to Saved Variables so each character can determine
  51. -- wether or not to play a sound, the alert times and colors and sound to play.
  52. -- If so then most of the code below will have to move into an event handler for
  53. -- the PLAYER_LOGIN or PLAYER_ENTERING_WORLD event.
  54. local useColor = true
  55. local useSound = true
  56. local alert1 = 600 -- Alarm 1 set to 10 minutes before event
  57. local alert1Color = "|cffffff00" -- Yellow
  58. local alert2 = 300 -- Alarm 2 set to 5 minutes before event
  59. local alert2Color = "|cffff0000" -- Red
  60. local soundKit = 32585 -- Alarm sound
  61. ------------------------------------------------------------------------------------------------------
  62.  
  63. local function printTime(timetotrun, inevent)
  64.     local hideSeconds = timetotrun >= 120
  65.     local msg = L.Waiting
  66.     local msgColor = "|cffffffff"
  67.     if inevent then
  68.         msg = L.Running
  69.     else
  70.         if useColor and timetotrun <= alert2 then
  71.             msgColor = alert2Color
  72.         elseif timetotrun <= alert1 then
  73.             if useSound and not ZAMTimer777.Alerted then
  74.                 ZAMTimer777.Alerted = true
  75.                 PlaySound(soundKit, "Master")
  76.             end
  77.             if useColor then
  78.                 msgColor = alert1Color
  79.             end
  80.         end
  81.     end
  82.     f.text:SetText(format(msg, msgColor, SecondsToTime(timetotrun, hideSeconds)))
  83. end
  84.  
  85. regionEventStartTime = {
  86.     [1] = { -- eu
  87.         starttime = 1679572800,
  88.         eventDuration = 300,
  89.         eventIntervalInSeconds = 3600,
  90.         enable = true,
  91.         datablock = {}
  92.     },
  93. }
  94.  
  95. local inEvent, timeToRun
  96. local eventTime = regionEventStartTime[1].eventDuration -- Time the event runs in seconds(15 mins)
  97. local waitTime = regionEventStartTime[1].eventIntervalInSeconds -- Time between events in seconds (90 mins)
  98. local startTime = regionEventStartTime[1].starttime -- Start time from the table
  99. local serverTime = GetServerTime()
  100. local timeToEvent = (startTime - serverTime) % waitTime -- Remaining time before next event starts
  101.  
  102. if timeToEvent > (waitTime - eventTime) then -- Is there between 1:15 and 1:30 to go? If so, we're in the event
  103.     inEvent = true
  104.     timeToRun = eventTime - (waitTime - timeToEvent)
  105. else                    -- Otherwise, set the ticker timer to time to next event
  106.     inEvent = false
  107.     timeToRun = timeToEvent
  108. end
  109. local ticker = C_Timer.NewTicker(1, function()
  110.     if timeToRun > 0 then
  111.         timeToRun = timeToRun - 1
  112.         printTime(timeToRun, inEvent)
  113.         return
  114.     end
  115.     ZAMTimer777.Alerted = false
  116.     if inEvent then -- The event just finished
  117.         inEvent = false
  118.         timeToRun = waitTime - eventTime -- Reset ticker timer to 90 minutes wait time minus 15 mins event time
  119.     else  -- Waiting for the next event just expired
  120.         inEvent = true
  121.         timeToRun = eventTime -- And the event is running
  122.     end
  123.     printTime(timeToRun, inEvent)
  124. end)
  125. printTime(timeToRun, inEvent)

I tried to do it myself based on the given code and WA
Lua Code:
  1. function(states, event, ...)
  2.     if event ~= "VOZ_TREASURE_GOBLIN_EVENT" and event ~= "STATUS" and event ~= "OPTIONS" then
  3.         return false
  4.     end
  5.    
  6.     local zone_rotation = {
  7.         [0] = 84, -- Stormwind
  8.         [1] = 2023, -- Ohn'ahran Plains
  9.         [2] = 85, -- Orgrimmar
  10.         [3] = 2024, -- The Azure Span
  11.         [4] = 84, -- Stormwind
  12.         [5] = 2025, -- Thaldraszus
  13.         [6] = 85, -- Orgrimmar
  14.         [7] = 2112, -- Valdrakken
  15.         [8] = 84, -- Stormwind
  16.         [9] = 2022, -- The Waking Shores
  17.         [10] = 85, -- Orgrimmar
  18.         [11] = 2023, -- Ohn'ahran Plains
  19.         [12] = 84, -- Stormwind
  20.         [13] = 2024, -- The Azure Span
  21.         [14] = 85, -- Orgrimmar
  22.         [15] = 2025, -- Thaldraszus
  23.         [16] = 84, -- Stormwind
  24.         [17] = 2112, -- Valdrakken
  25.         [18] = 85, -- Orgrimmar
  26.         [19] = 2022, -- The Waking Shores
  27.     }
  28.    
  29.     local region_timers = {
  30.         [1] = 1685041200, -- NA
  31.         [2] = 1684962000, -- KR
  32.         [3] = 1685001666, -- EU
  33.         [4] = nil, -- TW
  34.         [5] = nil  -- CN
  35.     }
  36.    
  37.     local region_start_timestamp = region_timers[GetCurrentRegion()]
  38.     if region_start_timestamp then
  39.         local duration = 300
  40.         local interval = 1800
  41.         local start_timestamp = GetServerTime() - region_start_timestamp
  42.         local next_event = interval - start_timestamp % interval
  43.         local spawning = interval - next_event < duration
  44.         local remaining = duration - (interval - next_event)
  45.        
  46.         local offset = not spawning and interval or 0
  47.         local rotation_index = math.floor((start_timestamp + offset) / interval % 20)
  48.         local zone = C_Map.GetMapInfo(zone_rotation[rotation_index]).name
  49.        
  50.         states[""] = {
  51.             changed = true,
  52.             show = true,
  53.             progressType = "timed",
  54.             autoHide = true,
  55.             duration = spawning and duration or interval - duration,
  56.             expirationTime = GetTime() + (spawning and remaining or next_event),
  57.             spawning = spawning,
  58.             name = zone
  59.         }
  60.     end
  61.    
  62.     return true
  63. end

Here's what I got. But this option works with an error (For testing I used an interval of 1 minute).
Lua Code:
  1. local addonName, addon = ...
  2. local Backdrop = {
  3.     bgFile = "Interface\\DialogFrame\\UI-DialogBox-Background",
  4. }
  5.  
  6. local frame_x = 100    
  7. local frame_y = -250    
  8. local f = CreateFrame("Button", "ZAMTimer777", UIParent, "BackdropTemplate")
  9. f:SetWidth(185)                                        
  10. f:SetHeight(30)
  11. f:SetBackdrop(Backdrop)
  12. f.text = f:CreateFontString(nil,"OVERLAY","GameTooltipText")
  13. f.text:SetPoint("CENTER")
  14. f:SetClampedToScreen(true)
  15. f:SetPoint("CENTER",UIParent,"CENTER",frame_x,frame_y)
  16. f:EnableMouse(true)
  17. f:SetMovable(true)
  18. f:RegisterForDrag("LeftButton")
  19. f:RegisterForClicks("AnyUp")
  20. f:Show()
  21. f:RegisterEvent("PLAYER_ENTERING_WORLD")
  22. f:SetScript("OnDragStart",function(self)
  23.     self:StartMoving()
  24. end)
  25. f:SetScript("OnDragStop",function(self)  
  26.     self:StopMovingOrSizing()
  27. end)
  28. -- first %s is replaced by the color. The second is replaced by the time. |r resets the color back to default
  29.  
  30.  
  31. local Localizations = {
  32.     enUS = {
  33.         Waiting = {
  34.             "|c1C7BCEFFFroststone A:\nbefore the start: %s%s|r",
  35.             "|c1C7BCEFFFroststone B:\nbefore the start: %s%s|r",
  36.             "|c1C7BCEFFFroststone C:\nbefore the start: %s%s|r",
  37.             "|c1C7BCEFFFroststone D:\nbefore the start: %s%s|r",
  38.         },     
  39.         Running = {
  40.             "|cFF35BE21Froststone A:\n%s%s until completion|r",
  41.             "|cFF35BE21Froststone B:\n%s%s until completion|r",
  42.             "|cFF35BE21Froststone C:\n%s%s until completion|r",
  43.             "|cFF35BE21Froststone D:\n%s%s until completion|r",
  44.         },
  45.     },
  46. }
  47.            
  48.  
  49. local locale = GetLocale()
  50. local L = Localizations[locale] or Localizations.enUS -- Default to enUS if locale doesn't exist in the table
  51.  
  52. ------------------------------------------------------------------------------------------------------
  53. -- These might be converted to Saved Variables so each character can determine
  54. -- wether or not to play a sound, the alert times and colors and sound to play.
  55. -- If so then most of the code below will have to move into an event handler for
  56. -- the PLAYER_LOGIN or PLAYER_ENTERING_WORLD event.
  57. local useColor = true
  58. local useSound = true
  59. local alert1 = 600 -- Alarm 1 set to 10 minutes before event
  60. local alert1Color = "|cffffff00" -- Yellow
  61. local alert2 = 300 -- Alarm 2 set to 5 minutes before event
  62. local alert2Color = "|cffff0000" -- Red
  63. local soundKit = 32585 -- Alarm sound
  64. ------------------------------------------------------------------------------------------------------
  65.  
  66.  
  67. regionEventStartTime = {
  68.     [1] = { -- eu
  69.         starttime = 1679572800,
  70.         eventDuration = 7,
  71.         eventIntervalInSeconds = 20,
  72.         enable = true,
  73.     },
  74. }
  75.  
  76.  
  77. local timeToRun
  78. local inEvent = true
  79. local eventTime = regionEventStartTime[1].eventDuration -- Time the event runs in seconds(15 mins)
  80. local waitTime = regionEventStartTime[1].eventIntervalInSeconds -- Time between events in seconds (90 mins)
  81. local startTime = regionEventStartTime[1].starttime -- Start time from the table
  82. local serverTime = 1710590400  --GetServerTime()
  83. local timeToEvent = (startTime - serverTime) % waitTime -- Remaining time before next event starts
  84. local currentEvent = math.floor((serverTime - startTime) / waitTime + 1) % 4
  85.  
  86.  
  87. local function printTime(timetotrun, inevent, eventnumber)
  88.     local hideSeconds = timetotrun >= 120
  89.     local msg = L.Waiting[eventnumber]
  90.     local msgColor = "|cffffffff"
  91.     if inevent then
  92.         msg = L.Running[eventnumber-1]
  93.     else
  94.         if useColor and timetotrun <= alert2 then
  95.             msgColor = alert2Color
  96.         elseif timetotrun <= alert1 then
  97.             if useSound and not ZAMTimer777.Alerted then
  98.                 ZAMTimer777.Alerted = true
  99.                 PlaySound(soundKit, "Master")
  100.             end
  101.             if useColor then
  102.                 msgColor = alert1Color
  103.             end
  104.         end
  105.     end
  106.     f.text:SetText(format(msg, msgColor, SecondsToTime(timetotrun, hideSeconds)))
  107. end
  108.  
  109.  
  110. if timeToEvent > (waitTime - eventTime) then -- Is there between 1:15 and 1:30 to go? If so, we're in the event
  111.     inEvent = true
  112.     timeToRun = eventTime - (waitTime - timeToEvent)
  113. else                    -- Otherwise, set the ticker timer to time to next event
  114.     inEvent = false
  115.     timeToRun = timeToEvent
  116. end
  117.  
  118. local ticker = C_Timer.NewTicker(1, function()
  119.     if timeToRun > 0 then
  120.         timeToRun = timeToRun - 1
  121.         printTime(timeToRun, inEvent, currentEvent+1)
  122.         return
  123.     end
  124.  
  125.     ZAMTimer777.Alerted = false
  126.     if inEvent then -- The event just finished
  127.         inEvent = false
  128.         timeToRun = waitTime - eventTime -- Reset ticker timer to 90 minutes wait time minus 15 mins event time
  129.     else  -- Waiting for the next event just expired
  130.         currentEvent = (currentEvent + 1) % 4
  131.         inEvent = true
  132.         timeToRun = eventTime -- And the event is running
  133.     end
  134.     printTime(timeToRun, inEvent)
  135. end)
  136. printTime(timeToRun, inEvent, currentEvent+1)

Second question
how can I make a button to hide the timer on command?
Lua Code:
  1. SLASH_HUBB1 = "/hubb"
  2. SlashCmdList["HUBB"] = function(msg)
  3.     if strupper(strtrim(msg)) == "BTN" then -- toggle the shown state of the button if the type /hubb btn
  4.         btn:SetShown(not btn:IsShown()) -- show the button
  5.         return
  6.     end
  7.     updateData()
  8.     updateList()
  9.     f:Show()
  10. end
  Reply With Quote
03-16-24, 11:19 PM   #2
Fizzlemizz
I did that?
 
Fizzlemizz's Avatar
Premium Member
AddOn Author - Click to view addons
Join Date: Dec 2011
Posts: 1,879
Or is it two events repeating ie.
  1. 5 mins doing something +
  2. 55 mins doing nothing
Totaling 1 hour repeating 24/7/365.

or is it
  1. 5 mins doing thing A
  2. 55 mins doing nothing
  3. 5 mins doing thing B
  4. 55 mins doing nothing
  5. 5 mins doing thing C
  6. 55 mins doing nothing
  7. 5 mins doing thing D
  8. 55 mins doing nothing
Totaling 4 hours repeatinf 24/7/365.
__________________
Fizzlemizz
Maintainer of Discord Unit Frames and Discord Art.
Author of FauxMazzle, FauxMazzleHUD and Move Pad Plus.

Last edited by Fizzlemizz : 03-16-24 at 11:24 PM.
  Reply With Quote
03-16-24, 11:48 PM   #3
Hubb777
A Flamescale Wyrmkin
 
Hubb777's Avatar
AddOn Author - Click to view addons
Join Date: Jan 2024
Posts: 113
Originally Posted by Fizzlemizz View Post
Or is it two events repeating ie.
or is it
  1. 5 mins doing thing A
  2. 55 mins doing nothing
  3. 5 mins doing thing B
  4. 55 mins doing nothing
  5. 5 mins doing thing C
  6. 55 mins doing nothing
  7. 5 mins doing thing D
  8. 55 mins doing nothing
Totaling 4 hours repeatinf 24/7/365.
Hello. Yes, this is exactly the option.
  Reply With Quote
03-17-24, 10:23 AM   #4
Fizzlemizz
I did that?
 
Fizzlemizz's Avatar
Premium Member
AddOn Author - Click to view addons
Join Date: Dec 2011
Posts: 1,879
It's all variations on a theme (and math). Knowing the remainder of a session (session totalDuration of 1, 2, 4, 6 or 12 hours). This is based on the start time (startTime - serverTime) % totalDuration.

Then figuring out what to do with that remainder based on the breakdown of each sub-session eg. 4 sub-sessions of exactly 5 and 55 (like below) or x sub-sessions of "things" that add up to totalDuration.

Test times are over 4 minutes instead of 4 hours.

Lua Code:
  1. local addonName, addon = ...
  2. local L, MyRegion
  3. local RegionTimes = {
  4.     [1] = {
  5.         startTime = 1679572800,
  6.         totalDuration = 14400, -- complete session time 4 hours repeating
  7.         sub_sessionDuration = 3600, -- 1 hour
  8.         waitTime = 3300, -- 55 minutes
  9.         eventtime = 300, -- 5 minutes implied but..
  10.         [1] = { -- sub-sessions
  11.             name = "A",
  12.         },
  13.         [2] = {
  14.             name = "B",
  15.         },
  16.         [3] = {
  17.             name = "C",
  18.         },
  19.         [4] = {
  20.             name = "D",
  21.         },
  22.     },
  23. }
  24.  
  25. --[[ TEST TIMES ONLY: over 4 minutes instead of 4 hours ]]--
  26.  
  27. --[[
  28. RegionTimes[1].totalDuration = 240 -- 4 minutes
  29. RegionTimes[1].sub_sessionDuration = 60 -- 1 minute
  30. RegionTimes[1].waitTime = 55 -- seconds
  31. RegionTimes[1].eventtime = 5 -- seconds
  32. ]]--
  33.  
  34. --[[ END TEST TIMES ]]--
  35.  
  36. local Localizations = {
  37.     enUS = {
  38.         Waiting = "%s before event %s starts",
  39.         Running = "Event: |cFF35BE21%s|r\n%s remaining",
  40.     },
  41. }
  42.  
  43. local function OnUpdate(self, elapsed)
  44.     self.Elapsed = self.Elapsed - elapsed
  45.     if self.Elapsed > 0 then -- Only check once per second
  46.         return
  47.     end
  48.     self.Elapsed = 1 -- reset the timeout (we've counted down 1 second)
  49.     local serverTime = GetServerTime()
  50.     local remainingTime = (MyRegion.startTime - serverTime) % MyRegion.totalDuration
  51.     local base = math.ceil(remainingTime / MyRegion.sub_sessionDuration)
  52.     local hourRemaining = MyRegion.sub_sessionDuration - ((base * MyRegion.sub_sessionDuration) - remainingTime)
  53.     local id = 4 - (base - 1)
  54.     if id == 5 then
  55.         id = 1
  56.     end
  57.     local msg
  58.     if hourRemaining > MyRegion.waitTime then
  59.         msg = format(L.Running, MyRegion[id].name, SecondsToTime(hourRemaining - MyRegion.waitTime, false))
  60.     else
  61.         id = id == 4 and 1 or id + 1
  62.         msg = format(L.Waiting, SecondsToTime(hourRemaining, false), MyRegion[id].name)
  63.     end
  64.     self.Text:SetText(msg)
  65.     self:SetSize(self.Text:GetWidth() + 10, self.Text:GetHeight() + 10)
  66. end
  67.  
  68. local Backdrop = {
  69.     bgFile = "Interface\\DialogFrame\\UI-DialogBox-Background",
  70. }
  71.  
  72. local f = CreateFrame("Button", "ZAMTimer_4_Events", UIParent, "BackdropTemplate")
  73. f:SetWidth(255)                                          
  74. f:SetHeight(30)
  75. f:SetPoint("CENTER")
  76. f:SetBackdrop(Backdrop)
  77. f:SetClampedToScreen(true)
  78. f:EnableMouse(true)
  79. f:SetMovable(true)
  80. f:SetUserPlaced(true)
  81. f:RegisterForDrag("LeftButton")
  82. f:RegisterForClicks("AnyUp")
  83. f.Text = f:CreateFontString(nil, "OVERLAY", "GameTooltipText")
  84. f.Text:SetPoint("CENTER")
  85. f.Elapsed = 0 -- Set starting timeout (0 second)
  86. f:SetScript("OnDragStart",function(self)
  87.     self:StartMoving()
  88. end)
  89. f:SetScript("OnDragStop",function(self)  
  90.     self:StopMovingOrSizing()
  91. end)
  92.  
  93. f:RegisterEvent("PLAYER_LOGIN")
  94. f:SetScript("OnEvent", function(self)
  95.     local locale = GetLocale()
  96.     L = Localizations[locale] or Localizations.enUS -- Default to enUS if locale doesn't exist in the table
  97.     MyRegion = RegionTimes[GetCurrentRegion()] or RegionTimes[1] -- Default to region 1 (US) if it doesn't exist in the table
  98.     f:SetScript("OnUpdate", OnUpdate)
  99. end)
  100.  
  101. SLASH_ZAM4TIMER1 = "/z4" -- toggle hiding/showing the ZAMTimer_4_Events frame using just /z4
  102. SlashCmdList.ZAM4TIMER = function(msg)
  103.     ZAMTimer_4_Events.Elapsed = 0 -- set the "clock" to re-calculate when shown.
  104.     ZAMTimer_4_Events:SetShown(not ZAMTimer_4_Events:IsShown()) -- hide/show the frame
  105. end
__________________
Fizzlemizz
Maintainer of Discord Unit Frames and Discord Art.
Author of FauxMazzle, FauxMazzleHUD and Move Pad Plus.

Last edited by Fizzlemizz : 03-17-24 at 01:31 PM.
  Reply With Quote
03-17-24, 10:47 AM   #5
Fizzlemizz
I did that?
 
Fizzlemizz's Avatar
Premium Member
AddOn Author - Click to view addons
Join Date: Dec 2011
Posts: 1,879
Originally Posted by Hubb777 View Post
Second question
how can I make a button to hide the timer on command?
Lua Code:
  1. SLASH_HUBB1 = "/hubb"
  2. SlashCmdList["HUBB"] = function(msg)
  3.     if strupper(strtrim(msg)) == "BTN" then -- toggle the shown state of the button if the type /hubb btn
  4.         btn:SetShown(not btn:IsShown()) -- show the button
  5.         return
  6.     end
  7.     updateData()
  8.     updateList()
  9.     f:Show()
  10. end
Your code doesn't contain a btn to hide/show.

You want to hide/show the frame that you created and for that (in this case) you would use the frame name ZAMTimer777. If you are giving frames a name then each one should be completely unique (like using your addon name as a prefix eg. "ZAMTimer_No1" or "Hubb777_Addon_A" etc.)

Lua Code:
  1. SLASH_HUBB1 = "/hubb"
  2. SlashCmdList["HUBB"] = function(msg)
  3.     if strupper(strtrim(msg)) == "BTN" then -- toggle the shown state of the button if the type /hubb btn
  4.         ZAMTimer777:SetShown(not ZAMTimer777:IsShown()) -- show the button
  5.         return
  6.     end
  7.     updateData()
  8.     updateList()
  9.     ZAMTimer777:Show()
  10. end
__________________
Fizzlemizz
Maintainer of Discord Unit Frames and Discord Art.
Author of FauxMazzle, FauxMazzleHUD and Move Pad Plus.
  Reply With Quote
03-17-24, 10:34 PM   #6
Hubb777
A Flamescale Wyrmkin
 
Hubb777's Avatar
AddOn Author - Click to view addons
Join Date: Jan 2024
Posts: 113
Originally Posted by Fizzlemizz View Post
It's all variations on a theme (and math). Knowing the remainder of a session (session totalDuration of 1, 2, 4, 6 or 12 hours). This is based on the start time (startTime - serverTime) % totalDuration.

Then figuring out what to do with that remainder based on the breakdown of each sub-session eg. 4 sub-sessions of exactly 5 and 55 (like below) or x sub-sessions of "things" that add up to totalDuration.

Test times are over 4 minutes instead of 4 hours.

Lua Code:
  1. local addonName, addon = ...
  2. local L, MyRegion
  3. local RegionTimes = {
  4.     [1] = {
  5.         startTime = 1679572800,
  6.         totalDuration = 14400, -- complete session time 4 hours repeating
  7.         sub_sessionDuration = 3600, -- 1 hour
  8.         waitTime = 3300, -- 55 minutes
  9.         eventtime = 300, -- 5 minutes implied but..
  10.         [1] = { -- sub-sessions
  11.             name = "A",
  12.         },
  13.         [2] = {
  14.             name = "B",
  15.         },
  16.         [3] = {
  17.             name = "C",
  18.         },
  19.         [4] = {
  20.             name = "D",
  21.         },
  22.     },
  23. }
  24.  
  25. --[[ TEST TIMES ONLY: over 4 minutes instead of 4 hours ]]--
  26.  
  27. --[[
  28. RegionTimes[1].totalDuration = 240 -- 4 minutes
  29. RegionTimes[1].sub_sessionDuration = 60 -- 1 minute
  30. RegionTimes[1].waitTime = 55 -- seconds
  31. RegionTimes[1].eventtime = 5 -- seconds
  32. ]]--
  33.  
  34. --[[ END TEST TIMES ]]--
  35.  
  36. local Localizations = {
  37.     enUS = {
  38.         Waiting = "%s before event %s starts",
  39.         Running = "Event: |cFF35BE21%s|r\n%s remaining",
  40.     },
  41. }
  42.  
  43. local function OnUpdate(self, elapsed)
  44.     self.Elapsed = self.Elapsed - elapsed
  45.     if self.Elapsed > 0 then -- Only check once per second
  46.         return
  47.     end
  48.     self.Elapsed = 1 -- reset the timeout (we've counted down 1 second)
  49.     local serverTime = GetServerTime()
  50.     local remainingTime = (MyRegion.startTime - serverTime) % MyRegion.totalDuration
  51.     local base = math.ceil(remainingTime / MyRegion.sub_sessionDuration)
  52.     local hourRemaining = MyRegion.sub_sessionDuration - ((base * MyRegion.sub_sessionDuration) - remainingTime)
  53.     local id = 4 - (base - 1)
  54.     if id == 5 then
  55.         id = 1
  56.     end
  57.     local msg
  58.     if hourRemaining > MyRegion.waitTime then
  59.         msg = format(L.Running, MyRegion[id].name, SecondsToTime(hourRemaining - MyRegion.waitTime, false))
  60.     else
  61.         id = id == 4 and 1 or id + 1
  62.         msg = format(L.Waiting, SecondsToTime(hourRemaining, false), MyRegion[id].name)
  63.     end
  64.     self.Text:SetText(msg)
  65.     self:SetSize(self.Text:GetWidth() + 10, self.Text:GetHeight() + 10)
  66. end
  67.  
  68. local Backdrop = {
  69.     bgFile = "Interface\\DialogFrame\\UI-DialogBox-Background",
  70. }
  71.  
  72. local f = CreateFrame("Button", "ZAMTimer_4_Events", UIParent, "BackdropTemplate")
  73. f:SetWidth(255)                                          
  74. f:SetHeight(30)
  75. f:SetPoint("CENTER")
  76. f:SetBackdrop(Backdrop)
  77. f:SetClampedToScreen(true)
  78. f:EnableMouse(true)
  79. f:SetMovable(true)
  80. f:SetUserPlaced(true)
  81. f:RegisterForDrag("LeftButton")
  82. f:RegisterForClicks("AnyUp")
  83. f.Text = f:CreateFontString(nil, "OVERLAY", "GameTooltipText")
  84. f.Text:SetPoint("CENTER")
  85. f.Elapsed = 0 -- Set starting timeout (0 second)
  86. f:SetScript("OnDragStart",function(self)
  87.     self:StartMoving()
  88. end)
  89. f:SetScript("OnDragStop",function(self)  
  90.     self:StopMovingOrSizing()
  91. end)
  92.  
  93. f:RegisterEvent("PLAYER_LOGIN")
  94. f:SetScript("OnEvent", function(self)
  95.     local locale = GetLocale()
  96.     L = Localizations[locale] or Localizations.enUS -- Default to enUS if locale doesn't exist in the table
  97.     MyRegion = RegionTimes[GetCurrentRegion()] or RegionTimes[1] -- Default to region 1 (US) if it doesn't exist in the table
  98.     f:SetScript("OnUpdate", OnUpdate)
  99. end)
  100.  
  101. SLASH_ZAM4TIMER1 = "/z4" -- toggle hiding/showing the ZAMTimer_4_Events frame using just /z4
  102. SlashCmdList.ZAM4TIMER = function(msg)
  103.     ZAMTimer_4_Events.Elapsed = 0 -- set the "clock" to re-calculate when shown.
  104.     ZAMTimer_4_Events:SetShown(not ZAMTimer_4_Events:IsShown()) -- hide/show the frame
  105. end
Hello. Yes it works. Thank you very much. I understood how slash commands work, thanks for that too.

If I want to remove one event that lasts 1 hour or add one event that lasts 1 hour, I will need to change this number 14400, right? And add or remove a letter.

Lua Code:
  1. totalDuration = 14400, -- complete session time 4 hours repeating

How to add localization to other languages for lines A, B, C, D, etc.

Lua Code:
  1. local RegionTimes = {
  2.     [1] = {
  3.         startTime = 1679572800,
  4.         totalDuration = 14400, -- complete session time 4 hours repeating
  5.         sub_sessionDuration = 3600, -- 1 hour
  6.         waitTime = 3300, -- 55 minutes
  7.         eventtime = 300, -- 5 minutes implied but..
  8.         [1] = { -- sub-sessions
  9.             name = "A",
  10.         },
  11.         [2] = {
  12.             name = "B",
  13.         },
  14.         [3] = {
  15.             name = "C",
  16.         },
  17.         [4] = {
  18.             name = "D",
  19.         },
  20.     },
  21. }

and how to return a sound/color alert to the code
Lua Code:
  1. -- These might be converted to Saved Variables so each character can determine
  2. -- wether or not to play a sound, the alert times and colors and sound to play.
  3. -- If so then most of the code below will have to move into an event handler for
  4. -- the PLAYER_LOGIN or PLAYER_ENTERING_WORLD event.
  5. local useColor = true
  6. local useSound = true
  7. local alert1 = 600 -- Alarm 1 set to 10 minutes before event
  8. local alert1Color = "|cffffff00" -- Yellow
  9. local alert2 = 300 -- Alarm 2 set to 5 minutes before event
  10. local alert2Color = "|cffff0000" -- Red
  11. local soundKit = 32585 -- Alarm sound
  12. ------------------------------------------------------------------------------------------------------
  13.  
  14. local function printTime(timetotrun, inevent)
  15.     local hideSeconds = timetotrun >= 120
  16.     local msg = L.Waiting
  17.     local msgColor = "|cffffffff"
  18.     if inevent then
  19.         msg = L.Running
  20.     else
  21.         if useColor and timetotrun <= alert2 then
  22.             msgColor = alert2Color
  23.         elseif timetotrun <= alert1 then
  24.             if useSound and not ZAMTimer777.Alerted then
  25.                 ZAMTimer777.Alerted = true
  26.                 PlaySound(soundKit, "Master")
  27.             end
  28.             if useColor then
  29.                 msgColor = alert1Color
  30.             end
  31.         end
  32.     end
  33.     f.text:SetText(format(msg, msgColor, SecondsToTime(timetotrun, hideSeconds)))
  34. end
  35. ZAMTimer777.Alerted = false

Last edited by Hubb777 : 03-19-24 at 09:45 PM.
  Reply With Quote
03-18-24, 11:07 AM   #7
Fizzlemizz
I did that?
 
Fizzlemizz's Avatar
Premium Member
AddOn Author - Click to view addons
Join Date: Dec 2011
Posts: 1,879
Originally Posted by Hubb777 View Post
If I want to remove one event that lasts 1 hour or add one event that lasts 1 hour, I will need to change this number 14400, right? And add or remove a letter.
If you remove 1 then the overall session of 3 hours would run 8 times in a day (24/3). If you added 1 (5 hours) then it would run 4.8 times (24/5) which wouldn't work as it would break the startTime calculation by causing overlap and you would lose the conistant start time each day.

Originally Posted by Hubb777 View Post
How to add localization to other languages for lines A, B, C, D, etc.
Lua Code:
  1. local Localizations = {
  2.     enUS = {
  3.         Waiting = "%s before event %s starts",
  4.         Running = "Event: |cFF35BE21%s|r\n%s remaining",
  5.         A = "Name of event A",
  6.         B = "Name of event B",
  7.         -- etc.
  8.     },
  9. }
You might want to make the A, B, C more meaningful names in both the localizations table and use the same in the RegionTimes table to replace A, B etc.

Then replace
Lua Code:
  1. MyRegion[id].name
with
Lua Code:
  1. L[MyRegion[id].name]

As for colours and alarms, it would seem you just need to add a caclulation for x time before the end of a wait sub-session and sound the alarm/change the colour. You should have enough already to be able to work that out.
__________________
Fizzlemizz
Maintainer of Discord Unit Frames and Discord Art.
Author of FauxMazzle, FauxMazzleHUD and Move Pad Plus.

Last edited by Fizzlemizz : 03-18-24 at 09:43 PM.
  Reply With Quote
03-18-24, 11:03 PM   #8
Hubb777
A Flamescale Wyrmkin
 
Hubb777's Avatar
AddOn Author - Click to view addons
Join Date: Jan 2024
Posts: 113
Hello thank you very much for your help.

Lua Code:
  1. local addonName, addon = ...
  2. local L, MyRegion
  3. local RegionTimes = {
  4.     [1] = {
  5.         startTime = 1679572800,
  6.         totalDuration = 14400, -- complete session time 4 hours repeating
  7.         sub_sessionDuration = 3600, -- 1 hour
  8.         waitTime = 3300, -- 55 minutes
  9.         eventtime = 300, -- 5 minutes implied but..
  10.         [1] = { -- sub-sessions
  11.             name = "A",
  12.         },
  13.         [2] = {
  14.             name = "B",
  15.         },
  16.         [3] = {
  17.             name = "C",
  18.         },
  19.         [4] = {
  20.             name = "D",
  21.         },
  22.     },
  23. }
  24.  
  25. --[[ TEST TIMES ONLY: over 4 minutes instead of 4 hours ]]--
  26.  
  27. --[[
  28. RegionTimes[1].totalDuration = 240 -- 4 minutes
  29. RegionTimes[1].sub_sessionDuration = 60 -- 1 minute
  30. RegionTimes[1].waitTime = 55 -- seconds
  31. RegionTimes[1].eventtime = 5 -- seconds
  32. ]]--
  33.  
  34. --[[ END TEST TIMES ]]--
  35.  
  36. local Localizations = {
  37.     enUS = {
  38.         Waiting = "%s before event %s starts",
  39.         Running = "Event: |cFF35BE21%s|r\n%s remaining",
  40.         A = "Name of event A",
  41.         B = "Name of event B",
  42.         C = "Name of event B",
  43.         D = "Name of event B",
  44.     },
  45.      deDE = {
  46.         Waiting = "%s verbleibende Zeit bis zur Veranstaltung %s",
  47.         Running = "Ereignis: |cFF35BE21%s|r\n%s Kommen",
  48.         A = "Freiflächen",
  49.         B = "Grüne",
  50.         C = "Rote",
  51.         D = "Weiß",
  52.     },
  53. }
  54.  
  55. ------------------------------------------------------------------------------------------------------
  56. -- These might be converted to Saved Variables so each character can determine
  57. -- wether or not to play a sound, the alert times and colors and sound to play.
  58. -- If so then most of the code below will have to move into an event handler for
  59. -- the PLAYER_LOGIN or PLAYER_ENTERING_WORLD event.
  60. local useColor = true
  61. local useSound = true
  62. local alert1 = 600 -- Alarm 1 set to 5 minutes before event
  63. local alert1Color = "|cffffff00" -- Yellow
  64. local alert2 = 30 -- Alarm 2 set to 30 seconds before event
  65. local alert2Color = "|cffff0000" -- Red
  66. local soundKit = 32585 -- Alarm sound
  67. ------------------------------------------------------------------------------------------------------
  68.  
  69. local function printTime(timetotrun, inevent)
  70.     local hideSeconds = timetotrun >= 120
  71.     local msg = L.Waiting
  72.     local msgColor = "|cffffffff"
  73.     if inevent then
  74.         msg = L.Running
  75.     else
  76.         if useColor and timetotrun <= alert2 then
  77.             msgColor = alert2Color
  78.         elseif timetotrun <= alert1 then
  79.             if useSound and not ZAMTimer_4_Events.Alerted then
  80.                 ZAMTimer_4_Events.Alerted = true
  81.                 PlaySound(soundKit, "Master")
  82.             end
  83.             if useColor then
  84.                 msgColor = alert1Color
  85.             end
  86.         end
  87.     end
  88.     f.text:SetText(format(msg, msgColor, SecondsToTime(timetotrun, hideSeconds)))
  89. end
  90.  
  91. ZAMTimer_4_Events.Alerted = false
  92.  
  93. local function OnUpdate(self, elapsed)
  94.     self.Elapsed = self.Elapsed - elapsed
  95.     if self.Elapsed > 0 then -- Only check once per second
  96.         return
  97.     end
  98.     self.Elapsed = 1 -- reset the timeout (we've counted down 1 second)
  99.     local serverTime = GetServerTime()
  100.     local remainingTime = (MyRegion.startTime - serverTime) % MyRegion.totalDuration
  101.     local base = math.ceil(remainingTime / MyRegion.sub_sessionDuration)
  102.     local hourRemaining = MyRegion.sub_sessionDuration - ((base * MyRegion.sub_sessionDuration) - remainingTime)
  103.     local id = 4 - (base - 1)
  104.     if id == 5 then
  105.         id = 1
  106.     end
  107.     local msg
  108.     if hourRemaining > MyRegion.waitTime then
  109.         msg = format(L.Running, MyRegion[id].name, SecondsToTime(hourRemaining - MyRegion.waitTime, false))
  110.     else
  111.         id = id == 4 and 1 or id + 1
  112.         msg = format(L.Waiting, SecondsToTime(hourRemaining, false), MyRegion[id].name)
  113.     end
  114.     self.Text:SetText(msg)
  115.     self:SetSize(self.Text:GetWidth() + 10, self.Text:GetHeight() + 10)
  116. end
  117.  
  118. local Backdrop = {
  119.     bgFile = "Interface\\DialogFrame\\UI-DialogBox-Background",
  120. }
  121.  
  122. local f = CreateFrame("Button", "ZAMTimer_4_Events", UIParent, "BackdropTemplate")
  123. f:SetWidth(255)                                          
  124. f:SetHeight(30)
  125. f:SetPoint("CENTER")
  126. f:SetBackdrop(Backdrop)
  127. f:SetClampedToScreen(true)
  128. f:EnableMouse(true)
  129. f:SetMovable(true)
  130. f:SetUserPlaced(true)
  131. f:RegisterForDrag("LeftButton")
  132. f:RegisterForClicks("AnyUp")
  133. f.Text = f:CreateFontString(nil, "OVERLAY", "GameTooltipText")
  134. f.Text:SetPoint("CENTER")
  135. f.Elapsed = 0 -- Set starting timeout (0 second)
  136. f:SetScript("OnDragStart",function(self)
  137.     self:StartMoving()
  138. end)
  139. f:SetScript("OnDragStop",function(self)  
  140.     self:StopMovingOrSizing()
  141. end)
  142.  
  143. f:RegisterEvent("PLAYER_LOGIN")
  144. f:SetScript("OnEvent", function(self)
  145.     local locale = GetLocale()
  146.     L = Localizations[locale] or Localizations.enUS -- Default to enUS if locale doesn't exist in the table
  147.     MyRegion = RegionTimes[GetCurrentRegion()] or RegionTimes[1] -- Default to region 1 (US) if it doesn't exist in the table
  148.     f:SetScript("OnUpdate", OnUpdate)
  149. end)
  150.  
  151. SLASH_ZAM4TIMER1 = "/z4" -- toggle hiding/showing the ZAMTimer_4_Events frame using just /z4
  152. SlashCmdList.ZAM4TIMER = function(msg)
  153.     ZAMTimer_4_Events.Elapsed = 0 -- set the "clock" to re-calculate when shown.
  154.     ZAMTimer_4_Events:SetShown(not ZAMTimer_4_Events:IsShown()) -- hide/show the frame
  155. end

Hello. I did the localization, but the translation only affects Waiting and Running, and the letters A, B, C, etc. remain without translation.

For the sound/color singal I added this part of the code. Looks like more changes need to be made to make it work.

Lua Code:
  1. ------------------------------------------------------------------------------------------------------
  2. -- These might be converted to Saved Variables so each character can determine
  3. -- wether or not to play a sound, the alert times and colors and sound to play.
  4. -- If so then most of the code below will have to move into an event handler for
  5. -- the PLAYER_LOGIN or PLAYER_ENTERING_WORLD event.
  6. local useColor = true
  7. local useSound = true
  8. local alert1 = 600 -- Alarm 1 set to 5 minutes before event
  9. local alert1Color = "|cffffff00" -- Yellow
  10. local alert2 = 30 -- Alarm 2 set to 30 seconds before event
  11. local alert2Color = "|cffff0000" -- Red
  12. local soundKit = 32585 -- Alarm sound
  13. ------------------------------------------------------------------------------------------------------
  14.  
  15. local function printTime(timetotrun, inevent)
  16.     local hideSeconds = timetotrun >= 120
  17.     local msg = L.Waiting
  18.     local msgColor = "|cffffffff"
  19.     if inevent then
  20.         msg = L.Running
  21.     else
  22.         if useColor and timetotrun <= alert2 then
  23.             msgColor = alert2Color
  24.         elseif timetotrun <= alert1 then
  25.             if useSound and not ZAMTimer_4_Events.Alerted then
  26.                 ZAMTimer_4_Events.Alerted = true
  27.                 PlaySound(soundKit, "Master")
  28.             end
  29.             if useColor then
  30.                 msgColor = alert1Color
  31.             end
  32.         end
  33.     end
  34.     f.text:SetText(format(msg, msgColor, SecondsToTime(timetotrun, hideSeconds)))
  35. end
  36.  
  37. ZAMTimer_4_Events.Alerted = false

Last edited by Hubb777 : 03-19-24 at 09:20 AM.
  Reply With Quote
03-19-24, 06:20 AM   #9
Xrystal
nUI Maintainer
 
Xrystal's Avatar
Premium Member
AddOn Author - Click to view addons
Join Date: Feb 2006
Posts: 5,934
That is because you didn't use the the localization version.

L.Running, MyRegion[id].name

L.Running is using the localization version
MyRegion[id].name is using the English version

What you need to do is use that English version as a key to the localized version.
Try L[MyRegion[id].name]
__________________


Characters:
Gwynedda - 70 - Demon Warlock
Galaviel - 65 - Resto Druid
Gamaliel - 61 - Disc Priest
Gwynytha - 60 - Survival Hunter
Lienae - 60 - Resto Shaman
Plus several others below level 60

Info Panel IDs : http://www.wowinterface.com/forums/s...818#post136818
  Reply With Quote
03-19-24, 09:23 AM   #10
Hubb777
A Flamescale Wyrmkin
 
Hubb777's Avatar
AddOn Author - Click to view addons
Join Date: Jan 2024
Posts: 113
Originally Posted by Xrystal View Post
That is because you didn't use the the localization version.

L.Running, MyRegion[id].name

L.Running is using the localization version
MyRegion[id].name is using the English version

What you need to do is use that English version as a key to the localized version.
Try L[MyRegion[id].name]
Hi, thanks for the tip. That's right?

Lua Code:
  1. local addonName, addon = ...
  2. local L, MyRegion
  3. local RegionTimes = {
  4.     [1] = {
  5.         startTime = 1679572800,
  6.         totalDuration = 14400, -- complete session time 4 hours repeating
  7.         sub_sessionDuration = 3600, -- 1 hour
  8.         waitTime = 3300, -- 55 minutes
  9.         eventtime = 300, -- 5 minutes implied but..
  10.         [1] = { -- sub-sessions
  11.             name = "A",
  12.         },
  13.         [2] = {
  14.             name = "B",
  15.         },
  16.         [3] = {
  17.             name = "C",
  18.         },
  19.         [4] = {
  20.             name = "D",
  21.         },
  22.     },
  23. }
  24.  
  25. --[[ TEST TIMES ONLY: over 4 minutes instead of 4 hours ]]--
  26.  
  27. --[[
  28. RegionTimes[1].totalDuration = 240 -- 4 minutes
  29. RegionTimes[1].sub_sessionDuration = 60 -- 1 minute
  30. RegionTimes[1].waitTime = 55 -- seconds
  31. RegionTimes[1].eventtime = 5 -- seconds
  32. ]]--
  33.  
  34. --[[ END TEST TIMES ]]--
  35.  
  36. local Localizations = {
  37.     enUS = {
  38.         Waiting = "%s before event %s starts",
  39.         Running = "Event: |cFF35BE21%s|r\n%s remaining",
  40.         A = "Name of event A",
  41.         B = "Name of event B",
  42.         C = "Name of event B",
  43.         D = "Name of event B",
  44.     },
  45.      deDE = {
  46.         Waiting = "%s verbleibende Zeit bis zur Veranstaltung %s",
  47.         Running = "Ereignis: |cFF35BE21%s|r\n%s Kommen",
  48.         A = "Freiflächen",
  49.         B = "Grüne",
  50.         C = "Rote",
  51.         D = "Weiß",
  52.     },
  53. }
  54.  
  55. ------------------------------------------------------------------------------------------------------
  56. -- These might be converted to Saved Variables so each character can determine
  57. -- wether or not to play a sound, the alert times and colors and sound to play.
  58. -- If so then most of the code below will have to move into an event handler for
  59. -- the PLAYER_LOGIN or PLAYER_ENTERING_WORLD event.
  60. local useColor = true
  61. local useSound = true
  62. local alert1 = 600 -- Alarm 1 set to 5 minutes before event
  63. local alert1Color = "|cffffff00" -- Yellow
  64. local alert2 = 30 -- Alarm 2 set to 30 seconds before event
  65. local alert2Color = "|cffff0000" -- Red
  66. local soundKit = 32585 -- Alarm sound
  67. ------------------------------------------------------------------------------------------------------
  68.  
  69. local function printTime(timetotrun, inevent)
  70.     local hideSeconds = timetotrun >= 120
  71.     local msg = L.Waiting
  72.     local msgColor = "|cffffffff"
  73.     if inevent then
  74.         msg = L.Running
  75.     else
  76.         if useColor and timetotrun <= alert2 then
  77.             msgColor = alert2Color
  78.         elseif timetotrun <= alert1 then
  79.             if useSound and not ZAMTimer_4_Events.Alerted then
  80.                 ZAMTimer_4_Events.Alerted = true
  81.                 PlaySound(soundKit, "Master")
  82.             end
  83.             if useColor then
  84.                 msgColor = alert1Color
  85.             end
  86.         end
  87.     end
  88.     f.text:SetText(format(msg, msgColor, SecondsToTime(timetotrun, hideSeconds)))
  89. end
  90.  
  91. ZAMTimer_4_Events.Alerted = false
  92.  
  93. local function OnUpdate(self, elapsed)
  94.     self.Elapsed = self.Elapsed - elapsed
  95.     if self.Elapsed > 0 then -- Only check once per second
  96.         return
  97.     end
  98.     self.Elapsed = 1 -- reset the timeout (we've counted down 1 second)
  99.     local serverTime = GetServerTime()
  100.     local remainingTime = (MyRegion.startTime - serverTime) % MyRegion.totalDuration
  101.     local base = math.ceil(remainingTime / MyRegion.sub_sessionDuration)
  102.     local hourRemaining = MyRegion.sub_sessionDuration - ((base * MyRegion.sub_sessionDuration) - remainingTime)
  103.     local id = 4 - (base - 1)
  104.     if id == 5 then
  105.         id = 1
  106.     end
  107.     local msg
  108.     if hourRemaining > MyRegion.waitTime then
  109.         msg = format(L.Running, L[MyRegion[id].name], SecondsToTime(hourRemaining - MyRegion.waitTime, false))
  110.     else
  111.         id = id == 4 and 1 or id + 1
  112.         msg = format(L.Waiting, SecondsToTime(hourRemaining, false), L[MyRegion[id].name])
  113.     end
  114.     self.Text:SetText(msg)
  115.     self:SetSize(self.Text:GetWidth() + 10, self.Text:GetHeight() + 10)
  116. end
  117.  
  118. local Backdrop = {
  119.     bgFile = "Interface\\DialogFrame\\UI-DialogBox-Background",
  120. }
  121.  
  122. local f = CreateFrame("Button", "ZAMTimer_4_Events", UIParent, "BackdropTemplate")
  123. f:SetWidth(255)                                          
  124. f:SetHeight(30)
  125. f:SetPoint("CENTER")
  126. f:SetBackdrop(Backdrop)
  127. f:SetClampedToScreen(true)
  128. f:EnableMouse(true)
  129. f:SetMovable(true)
  130. f:SetUserPlaced(true)
  131. f:RegisterForDrag("LeftButton")
  132. f:RegisterForClicks("AnyUp")
  133. f.Text = f:CreateFontString(nil, "OVERLAY", "GameTooltipText")
  134. f.Text:SetPoint("CENTER")
  135. f.Elapsed = 0 -- Set starting timeout (0 second)
  136. f:SetScript("OnDragStart",function(self)
  137.     self:StartMoving()
  138. end)
  139. f:SetScript("OnDragStop",function(self)  
  140.     self:StopMovingOrSizing()
  141. end)
  142.  
  143. f:RegisterEvent("PLAYER_LOGIN")
  144. f:SetScript("OnEvent", function(self)
  145.     local locale = GetLocale()
  146.     L = Localizations[locale] or Localizations.enUS -- Default to enUS if locale doesn't exist in the table
  147.     MyRegion = RegionTimes[GetCurrentRegion()] or RegionTimes[1] -- Default to region 1 (US) if it doesn't exist in the table
  148.     f:SetScript("OnUpdate", OnUpdate)
  149. end)
  150.  
  151. SLASH_ZAM4TIMER1 = "/z4" -- toggle hiding/showing the ZAMTimer_4_Events frame using just /z4
  152. SlashCmdList.ZAM4TIMER = function(msg)
  153.     ZAMTimer_4_Events.Elapsed = 0 -- set the "clock" to re-calculate when shown.
  154.     ZAMTimer_4_Events:SetShown(not ZAMTimer_4_Events:IsShown()) -- hide/show the frame
  155. end

yes it worked.

The remaining question is how to attach a sound/color alert. (Just pasting a piece of code didn't work)

Last edited by Hubb777 : 03-19-24 at 09:50 PM.
  Reply With Quote
03-19-24, 10:54 AM   #11
Xrystal
nUI Maintainer
 
Xrystal's Avatar
Premium Member
AddOn Author - Click to view addons
Join Date: Feb 2006
Posts: 5,934
This has some examples and info on using it for sound
https://warcraft.wiki.gg/wiki/API_PlaySound

As to a colour alert, it depends on what you mean.

You could do something as simple as colourizing the text.
This can be done using hex code colouring when you set the text

eg |cAARRGGBBTextToDisplay|r

or for clarity and flexibility where ColorOn can be set to a different colour before setting the text.
Lua Code:
  1. local ColorOn = "|cAARRGGBB"
  2. local ColorOff = "|r"
  3. f.Text:SetText(ColorOn .. "Text to Display" .. ColorOff)

Or you could add a texture to the frame holding the text and colourise that according to your needs
More Info : https://warcraft.wiki.gg/wiki/API_Te...etColorTexture

Set the texture up at frame Creation time
Lua Code:
  1. f.Color = f:CreateTexture(nil,"BACKGROUND") - Set to Background so that the text appears above it
  2. f.Color:SetAllPoints()

Then, when you need to change it's color use this line
Lua Code:
  1. f.Color:SetColorTexture(r, g, b, a) - Where r,g,b and a are values between 0 and 1.
__________________


Characters:
Gwynedda - 70 - Demon Warlock
Galaviel - 65 - Resto Druid
Gamaliel - 61 - Disc Priest
Gwynytha - 60 - Survival Hunter
Lienae - 60 - Resto Shaman
Plus several others below level 60

Info Panel IDs : http://www.wowinterface.com/forums/s...818#post136818
  Reply With Quote
03-19-24, 09:46 PM   #12
Hubb777
A Flamescale Wyrmkin
 
Hubb777's Avatar
AddOn Author - Click to view addons
Join Date: Jan 2024
Posts: 113
Originally Posted by Xrystal View Post
This has some examples and info on using it for sound
https://warcraft.wiki.gg/wiki/API_PlaySound

As to a colour alert, it depends on what you mean.

You could do something as simple as colourizing the text.
This can be done using hex code colouring when you set the text

eg |cAARRGGBBTextToDisplay|r

or for clarity and flexibility where ColorOn can be set to a different colour before setting the text.
Lua Code:
  1. local ColorOn = "|cAARRGGBB"
  2. local ColorOff = "|r"
  3. f.Text:SetText(ColorOn .. "Text to Display" .. ColorOff)

Or you could add a texture to the frame holding the text and colourise that according to your needs
More Info : https://warcraft.wiki.gg/wiki/API_Te...etColorTexture

Set the texture up at frame Creation time
Lua Code:
  1. f.Color = f:CreateTexture(nil,"BACKGROUND") - Set to Background so that the text appears above it
  2. f.Color:SetAllPoints()

Then, when you need to change it's color use this line
Lua Code:
  1. f.Color:SetColorTexture(r, g, b, a) - Where r,g,b and a are values between 0 and 1.


Hello. I have the code, but I don't understand how to use it.


Lua Code:
  1. ------------------------------------------------------------------------------------------------------
  2. -- These might be converted to Saved Variables so each character can determine
  3. -- wether or not to play a sound, the alert times and colors and sound to play.
  4. -- If so then most of the code below will have to move into an event handler for
  5. -- the PLAYER_LOGIN or PLAYER_ENTERING_WORLD event.
  6. local useColor = true
  7. local useSound = true
  8. local alert1 = 600 -- Alarm 1 set to 5 minutes before event
  9. local alert1Color = "|cffffff00" -- Yellow
  10. local alert2 = 30 -- Alarm 2 set to 30 seconds before event
  11. local alert2Color = "|cffff0000" -- Red
  12. local soundKit = 32585 -- Alarm sound
  13. ------------------------------------------------------------------------------------------------------
  14.  
  15. local function printTime(timetotrun, inevent)
  16.     local hideSeconds = timetotrun >= 120
  17.     local msg = L.Waiting
  18.     local msgColor = "|cffffffff"
  19.     if inevent then
  20.         msg = L.Running
  21.     else
  22.         if useColor and timetotrun <= alert2 then
  23.             msgColor = alert2Color
  24.         elseif timetotrun <= alert1 then
  25.             if useSound and not ZAMTimer_4_Events.Alerted then
  26.                 ZAMTimer_4_Events.Alerted = true
  27.                 PlaySound(soundKit, "Master")
  28.             end
  29.             if useColor then
  30.                 msgColor = alert1Color
  31.             end
  32.         end
  33.     end
  34.     f.text:SetText(format(msg, msgColor, SecondsToTime(timetotrun, hideSeconds)))
  35. end
  36.  
  37. ZAMTimer_4_Events.Alerted = false



The result should be something like this.


Lua Code:
  1. local addonName, addon = ...
  2. local L, MyRegion
  3. local RegionTimes = {
  4.     [1] = {
  5.         startTime = 1679572800,
  6.         totalDuration = 14400, -- complete session time 4 hours repeating
  7.         sub_sessionDuration = 3600, -- 1 hour
  8.         waitTime = 3300, -- 55 minutes
  9.         eventtime = 300, -- 5 minutes implied but..
  10.         [1] = { -- sub-sessions
  11.             name = "A",
  12.         },
  13.         [2] = {
  14.             name = "B",
  15.         },
  16.         [3] = {
  17.             name = "C",
  18.         },
  19.         [4] = {
  20.             name = "D",
  21.         },
  22.     },
  23. }
  24.  
  25. --[[ TEST TIMES ONLY: over 4 minutes instead of 4 hours ]]--
  26.  
  27. --[[
  28. RegionTimes[1].totalDuration = 240 -- 4 minutes
  29. RegionTimes[1].sub_sessionDuration = 60 -- 1 minute
  30. RegionTimes[1].waitTime = 55 -- seconds
  31. RegionTimes[1].eventtime = 5 -- seconds
  32. ]]--
  33.  
  34. --[[ END TEST TIMES ]]--
  35.  
  36. local Localizations = {
  37.     enUS = {
  38.         Waiting = "%s before event %s starts",
  39.         Running = "Event: |cFF35BE21%s|r\n%s remaining",
  40.         A = "Name of event A",
  41.         B = "Name of event B",
  42.         C = "Name of event B",
  43.         D = "Name of event B",
  44.     },
  45.      deDE = {
  46.         Waiting = "%s verbleibende Zeit bis zur Veranstaltung %s",
  47.         Running = "Ereignis: |cFF35BE21%s|r\n%s Kommen",
  48.         A = "Freiflächen",
  49.         B = "Grüne",
  50.         C = "Rote",
  51.         D = "Weiß",
  52.     },
  53. }
  54.  
  55. ------------------------------------------------------------------------------------------------------
  56. -- These might be converted to Saved Variables so each character can determine
  57. -- wether or not to play a sound, the alert times and colors and sound to play.
  58. -- If so then most of the code below will have to move into an event handler for
  59. -- the PLAYER_LOGIN or PLAYER_ENTERING_WORLD event.
  60. local useColor = true
  61. local useSound = true
  62. local alert1 = 600 -- Alarm 1 set to 5 minutes before event
  63. local alert1Color = "|cffffff00" -- Yellow
  64. local alert2 = 30 -- Alarm 2 set to 30 seconds before event
  65. local alert2Color = "|cffff0000" -- Red
  66. local soundKit = 32585 -- Alarm sound
  67. ------------------------------------------------------------------------------------------------------
  68.  
  69. local function printTime(timetotrun, inevent)
  70.     local hideSeconds = timetotrun >= 120
  71.     local msg = L.Waiting
  72.     local msgColor = "|cffffffff"
  73.     if inevent then
  74.         msg = L.Running
  75.     else
  76.         if useColor and timetotrun <= alert2 then
  77.             msgColor = alert2Color
  78.         elseif timetotrun <= alert1 then
  79.             if useSound and not ZAMTimer_4_Events.Alerted then
  80.                 ZAMTimer_4_Events.Alerted = true
  81.                 PlaySound(soundKit, "Master")
  82.             end
  83.             if useColor then
  84.                 msgColor = alert1Color
  85.             end
  86.         end
  87.     end
  88.     f.text:SetText(format(msg, msgColor, SecondsToTime(timetotrun, hideSeconds)))
  89. end
  90.  
  91. ZAMTimer_4_Events.Alerted = false
  92.  
  93. local function OnUpdate(self, elapsed)
  94.     self.Elapsed = self.Elapsed - elapsed
  95.     if self.Elapsed > 0 then -- Only check once per second
  96.         return
  97.     end
  98.     self.Elapsed = 1 -- reset the timeout (we've counted down 1 second)
  99.     local serverTime = GetServerTime()
  100.     local remainingTime = (MyRegion.startTime - serverTime) % MyRegion.totalDuration
  101.     local base = math.ceil(remainingTime / MyRegion.sub_sessionDuration)
  102.     local hourRemaining = MyRegion.sub_sessionDuration - ((base * MyRegion.sub_sessionDuration) - remainingTime)
  103.     local id = 4 - (base - 1)
  104.     if id == 5 then
  105.         id = 1
  106.     end
  107.     local msg
  108.     if hourRemaining > MyRegion.waitTime then
  109.         msg = format(L.Running, L[MyRegion[id].name], SecondsToTime(hourRemaining - MyRegion.waitTime, false))
  110.     else
  111.         id = id == 4 and 1 or id + 1
  112.         msg = format(L.Waiting, SecondsToTime(hourRemaining, false), L[MyRegion[id].name])
  113.     end
  114.     self.Text:SetText(msg)
  115.     self:SetSize(self.Text:GetWidth() + 10, self.Text:GetHeight() + 10)
  116. end
  117.  
  118. local Backdrop = {
  119.     bgFile = "Interface\\DialogFrame\\UI-DialogBox-Background",
  120. }
  121.  
  122. local f = CreateFrame("Button", "ZAMTimer_4_Events", UIParent, "BackdropTemplate")
  123. f:SetWidth(255)                                          
  124. f:SetHeight(30)
  125. f:SetPoint("CENTER")
  126. f:SetBackdrop(Backdrop)
  127. f:SetClampedToScreen(true)
  128. f:EnableMouse(true)
  129. f:SetMovable(true)
  130. f:SetUserPlaced(true)
  131. f:RegisterForDrag("LeftButton")
  132. f:RegisterForClicks("AnyUp")
  133. f.Text = f:CreateFontString(nil, "OVERLAY", "GameTooltipText")
  134. f.Text:SetPoint("CENTER")
  135. f.Elapsed = 0 -- Set starting timeout (0 second)
  136. f:SetScript("OnDragStart",function(self)
  137.     self:StartMoving()
  138. end)
  139. f:SetScript("OnDragStop",function(self)  
  140.     self:StopMovingOrSizing()
  141. end)
  142.  
  143. f:RegisterEvent("PLAYER_LOGIN")
  144. f:SetScript("OnEvent", function(self)
  145.     local locale = GetLocale()
  146.     L = Localizations[locale] or Localizations.enUS -- Default to enUS if locale doesn't exist in the table
  147.     MyRegion = RegionTimes[GetCurrentRegion()] or RegionTimes[1] -- Default to region 1 (US) if it doesn't exist in the table
  148.     f:SetScript("OnUpdate", OnUpdate)
  149. end)
  150.  
  151. SLASH_ZAM4TIMER1 = "/z4" -- toggle hiding/showing the ZAMTimer_4_Events frame using just /z4
  152. SlashCmdList.ZAM4TIMER = function(msg)
  153.     ZAMTimer_4_Events.Elapsed = 0 -- set the "clock" to re-calculate when shown.
  154.     ZAMTimer_4_Events:SetShown(not ZAMTimer_4_Events:IsShown()) -- hide/show the frame
  155. end

Last edited by Hubb777 : 03-19-24 at 09:51 PM.
  Reply With Quote
03-19-24, 11:04 PM   #13
Fizzlemizz
I did that?
 
Fizzlemizz's Avatar
Premium Member
AddOn Author - Click to view addons
Join Date: Dec 2011
Posts: 1,879
The PrintTime function is not actually being used in this version so I removed it. Because we replaced the ticker, the calculating and display is all done in the OnUpdate function.

Added some test times for the alarm/colours at 10 and 3 seconds for use with the event test times.

Lua Code:
  1. local addonName, addon = ...
  2. ------------------------------------------------------------------------------------------------------
  3. -- The Data (and Settings?) Section
  4.  
  5. local L, MyRegion
  6. local RegionTimes = {
  7.     [1] = {
  8.         startTime = 1679572800,
  9.         totalDuration = 14400, -- complete session time 4 hours repeating
  10.         sub_sessionDuration = 3600, -- 1 hour
  11.         waitTime = 3300, -- 55 minutes
  12.         eventtime = 300, -- 5 minutes implied but..
  13.         [1] = { -- sub-sessions
  14.             name = "A",
  15.         },
  16.         [2] = {
  17.             name = "B",
  18.         },
  19.         [3] = {
  20.             name = "C",
  21.         },
  22.         [4] = {
  23.             name = "D",
  24.         },
  25.     },
  26. }
  27.  
  28. --[[ TEST TIMES ONLY: over 4 minutes instead of 4 hours ]]--
  29.  
  30. --[[
  31. RegionTimes[1].totalDuration = 240 -- 4 minutes
  32. RegionTimes[1].sub_sessionDuration = 60 -- 1 minute
  33. RegionTimes[1].waitTime = 55 -- seconds
  34. RegionTimes[1].eventtime = 5 -- seconds
  35. ]]--
  36.  
  37. --[[ END TEST TIMES ]]--
  38.  
  39. local Localizations = {
  40.     enUS = {
  41.         Waiting = "%s before event %s starts",
  42.         Running = "Event: |cFF35BE21%s|r\n%s remaining",
  43.         A = "Name of event A",
  44.         B = "Name of event B",
  45.         C = "Name of event B",
  46.         D = "Name of event B",
  47.     },
  48.      deDE = {
  49.         Waiting = "%s verbleibende Zeit bis zur Veranstaltung %s",
  50.         Running = "Ereignis: |cFF35BE21%s|r\n%s Kommen",
  51.         A = "Freiflächen",
  52.         B = "Grüne",
  53.         C = "Rote",
  54.         D = "Weiß",
  55.     },
  56. }
  57.  
  58. -- These might be converted to Saved Variables so each character can determine
  59. -- wether or not to play a sound, the alert times and colors and sound to play.
  60. -- If so then most of the code below will have to move into an event handler for
  61. -- the PLAYER_LOGIN or PLAYER_ENTERING_WORLD event.
  62. local useColor = true
  63. local useSound = true
  64. local alert1 = 300 -- Alarm 1 set to 5 minutes before event
  65. local alert1Color = "|cffffff00" -- Yellow
  66. local alert2 = 30 -- Alarm 2 set to 30 seconds before event
  67. local alert2Color = "|cffff0000" -- Red
  68. local soundKit = 32585 -- Alarm sound
  69.  
  70. --[[ TEST TIMES ONLY: over 10/3 seconds ]]--
  71.  
  72. --[[
  73. local alert1 = 10 -- Alarm 1 set to 5 minutes before event
  74. local alert2 = 3 -- Alarm 2 set to 30 seconds before event
  75. ]]--
  76.  
  77. --[[ END TEST TIMES ]]--
  78.  
  79. ------------------------------------------------------------------------------------------------------
  80. --- The Calculation (work) Section
  81.  
  82. local function OnUpdate(self, elapsed)
  83.     self.Elapsed = self.Elapsed - elapsed
  84.     if self.Elapsed > 0 then -- Only check once per second
  85.         return
  86.     end
  87.     self.Elapsed = 1 -- reset the timeout (we've counted down 1 second)
  88.     local serverTime = GetServerTime()
  89.     local remainingTime = (MyRegion.startTime - serverTime) % MyRegion.totalDuration
  90.     local base = math.ceil(remainingTime / MyRegion.sub_sessionDuration)
  91.     local hourRemaining = MyRegion.sub_sessionDuration - ((base * MyRegion.sub_sessionDuration) - remainingTime)
  92.     local id = 4 - (base - 1)
  93.     if id == 5 then
  94.         id = 1
  95.     end
  96.     local msg
  97.     if hourRemaining > MyRegion.waitTime then
  98.         self.Alarm = false
  99.         msg = format(L.Running, L[MyRegion[id].name], SecondsToTime(hourRemaining - MyRegion.waitTime, false))
  100.     else
  101.         id = id == 4 and 1 or id + 1
  102.         local cm = L.Waiting
  103.         if useColor and hourRemaining <= alert2 then
  104.             cm = alert2Color .. L.Waiting
  105.         elseif hourRemaining <= alert1 then
  106.             if useColor then
  107.                 cm = alert1Color .. L.Waiting
  108.             end
  109.             if useSound and not self.Alarm then
  110.                 self.Alarm = true
  111.                 PlaySound(soundKit, "Master")
  112.             end
  113.         end
  114.         msg = format(cm, SecondsToTime(hourRemaining, false), L[MyRegion[id].name])
  115.     end
  116.     self.Text:SetText(msg)
  117.     self:SetSize(self.Text:GetWidth() + 10, self.Text:GetHeight() + 10)
  118. end
  119.  
  120. ------------------------------------------------------------------------------------------------------
  121. -- The Visual (Frame) Section
  122.  
  123. local Backdrop = {
  124.     bgFile = "Interface\\DialogFrame\\UI-DialogBox-Background",
  125. }
  126.  
  127. local f = CreateFrame("Button", "ZAMTimer_4_Events", UIParent, "BackdropTemplate")
  128. f:SetWidth(255)                                          
  129. f:SetHeight(30)
  130. f:SetPoint("CENTER")
  131. f:SetBackdrop(Backdrop)
  132. f:SetClampedToScreen(true)
  133. f:EnableMouse(true)
  134. f:SetMovable(true)
  135. f:SetUserPlaced(true)
  136. f:RegisterForDrag("LeftButton")
  137. f:RegisterForClicks("AnyUp")
  138. f.Text = f:CreateFontString(nil, "OVERLAY", "GameTooltipText")
  139. f.Text:SetPoint("CENTER")
  140. f.Elapsed = 0 -- Set starting timeout (0 second)
  141. f:SetScript("OnDragStart",function(self)
  142.     self:StartMoving()
  143. end)
  144. f:SetScript("OnDragStop",function(self)  
  145.     self:StopMovingOrSizing()
  146. end)
  147.  
  148. ------------------------------------------------------------------------------------------------------
  149. -- The "Getting Started" Section:
  150. -- Get the players locale at login and start the OnUpdate timer (to do the work).
  151.  
  152. f:RegisterEvent("PLAYER_LOGIN")
  153. f:SetScript("OnEvent", function(self)
  154.     local locale = GetLocale()
  155.     L = Localizations[locale] or Localizations.enUS -- Default to enUS if locale doesn't exist in the table
  156.     MyRegion = RegionTimes[GetCurrentRegion()] or RegionTimes[1] -- Default to region 1 (US) if it doesn't exist in the table
  157.     f:SetScript("OnUpdate", OnUpdate)
  158. end)
  159.  
  160. ------------------------------------------------------------------------------------------------------
  161. -- Slash Command
  162.  
  163. SLASH_ZAM4TIMER1 = "/z4" -- toggle hiding/showing the ZAMTimer_4_Events frame using just /z4
  164. SlashCmdList.ZAM4TIMER = function(msg)
  165.     ZAMTimer_4_Events.Elapsed = 0 -- set the "clock" to re-calculate when shown.
  166.     ZAMTimer_4_Events:SetShown(not ZAMTimer_4_Events:IsShown()) -- hide/show the frame
  167. end
__________________
Fizzlemizz
Maintainer of Discord Unit Frames and Discord Art.
Author of FauxMazzle, FauxMazzleHUD and Move Pad Plus.

Last edited by Fizzlemizz : 03-20-24 at 11:56 AM.
  Reply With Quote
03-20-24, 10:24 PM   #14
Hubb777
A Flamescale Wyrmkin
 
Hubb777's Avatar
AddOn Author - Click to view addons
Join Date: Jan 2024
Posts: 113
Hello, thank you very much, you helped me a lot. I have already started creating my second addon.
  Reply With Quote

WoWInterface » AddOns, Compilations, Macros » AddOn Help/Support » 2 questions on the timer


Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

vB code is On
Smilies are On
[IMG] code is On
HTML code is Off