Register forum user name Search FAQ

Gammon Forum

Notice: Any messages purporting to come from this site telling you that your password has expired, or that you need to verify your details, confirm your email, resolve issues, making threats, or asking for money, are spam. We do not email users with any such messages. If you have lost your password you can obtain a new one by using the password reset link.

Due to spam on this forum, all posts now need moderator approval.

 Entire forum ➜ MUSHclient ➜ Miniwindows ➜ Add countdown timer to text miniwindow

Add countdown timer to text miniwindow

You need to log onto the forum to reply or create new threads.

  Refresh page


Posted by Nick Gammon   Australia  (23,158 posts)  Bio   Forum Administrator
Date Reply #1 on Thu 10 Apr 2025 09:42 PM (UTC)
Message
Have a look at this page:

https://gammon.com.au/mushclient/mw_text.htm

Near the bottom is "Hints for working with text" and that shows a fairly simple bit of code for setting up a miniwindow for drawing text.

Once you have the window and font set up you basically call WindowText to display the text.

Conceptually it would be very similar to the post I just did for echoing the output window:


https://www.gammon.com.au/forum/?id=15235

The only difference would be that instead of changing the text when you type (OnPluginCommandChanged), you would change the text based on your cooldown. You could make a timer to update the window every second if the cooldown is active.

You might also change the window width (window_width) to some fixed value (eg. 50 pixels).

- Nick Gammon

www.gammon.com.au, www.mushclient.com
Top

Posted by Aardwanderer   (6 posts)  Bio
Date Reply #2 on Thu 10 Apr 2025 10:58 PM (UTC)
Message
Thanks for reply! I already have a miniwindow that I want to add the cooldown timer to. Each line in my miniwindow uses:

my_window:add_text() to display text from variables.

I'll take a look at those links and see if I can figure it out.

My issue is that I'm not even sure which lines from the action bar plugin I'd need to use.
Top

Posted by Nick Gammon   Australia  (23,158 posts)  Bio   Forum Administrator
Date Reply #3 on Fri 11 Apr 2025 06:57 AM (UTC)

Amended on Sun 13 Apr 2025 07:48 PM (UTC) by Nick Gammon

Message
I've made a standalone plugin that lets you display pure text in small boxes, with a cooldown timeout.

Template:saveplugin=Cooldown_Text To save and install the Cooldown_Text plugin do this:
  1. Copy the code below (in the code box) to the Clipboard
  2. Open a text editor (such as Notepad) and paste the plugin code into it
  3. Save to disk on your PC, preferably in your plugins directory, as Cooldown_Text.xml
    • The "plugins" directory is usually under the "worlds" directory inside where you installed MUSHclient.
  4. Go to the MUSHclient File menu -> Plugins
  5. Click "Add"
  6. Choose the file Cooldown_Text.xml (which you just saved in step 3) as a plugin
  7. Click "Close"
  8. Save your world file, so that the plugin loads next time you open it.



<?xml version="1.0" encoding="iso-8859-1"?>
<!DOCTYPE muclient>

<muclient>
<plugin
   name="Cooldown_Text"
   author="Nick Gammon"
   id="2f103c42b3356ee1bcac384b"
   language="Lua"
   purpose="Shows cooldowns in a miniwindow"
   save_state="y"
   date_written="2025-04-08 11:50:44"
   requires="5.06"
   version="1.0"
   >
</plugin>

<!--  Timers  -->

<timers>
  <timer 
    script="handle_cooldowns" 
    enabled="y" second="1.00" 
    active_closed="y" >
  </timer>
</timers>

<!--  Script  -->

<script>
<![CDATA[

require "commas"  -- for convert_time

font_id = "fn"
FONT_NAME = "Sans"    -- input font name
active_windows = { }  -- our windows
MARGIN = 10  -- pixels
  
function ShowWindows ()

  top = 5
  
  for name, details in pairs (active_windows) do
    
    contents = details.contents
    if details.cooldown then
       if details.cooldown <= 0 then
         contents = contents .. " (ready)"
       else
         contents = contents .. " (wait) " .. convert_time (details.cooldown)
       end -- if ready or waiting
    end -- if it has a cooldown
    
    win = GetPluginID () .. "_" .. name
    
    -- make window so I can grab the font info
    WindowCreate (win, 0, 0, 1, 1, miniwin.pos_top_right, miniwin.create_absolute_location, 0) 

    WindowFont (win, font_id, FONT_NAME, 12, false, false, false, false, 0, 0)  -- normal  
    font_height = WindowFontInfo (win, font_id, 1)  -- height
    
    -- calculate window size
    window_height = font_height + MARGIN
    window_width  = WindowTextWidth (win, font_id, contents) + MARGIN
    
    -- work out left of window (output window width - size of window)
    left = GetInfo (281) - window_width - 5  -- position on right, slightly in from edge
    
    -- make window correct size and location
    WindowCreate (win, left, top, window_width, window_height, 
                  miniwin.pos_top_right, miniwin.create_absolute_location, ColourNameToRGB ("white"))
                  
    -- blank the window
    WindowRectOp (win, miniwin.rect_draw_edge, 0, 0, 0, 0, 
                  miniwin.rect_edge_raised, miniwin.rect_edge_at_all + miniwin.rect_option_softer_buttons)
    -- add the text
    WindowText (win, font_id, contents, MARGIN / 2, MARGIN / 2, 0, 0, ColourNameToRGB ("black"))
    -- show the window
    WindowShow (win, true)

    -- next window is further down
    top = top + window_height + 5

  end -- for each window
    
end -- ShowWindows
  
-- add a notification window
function MakeWindow (name, contents, cooldown)
  active_windows [name] = { contents = contents, cooldown = cooldown }
  ShowWindows()
end -- MakeWindow

-- call this to remove a notification window
function RemoveWindow (name)
  active_windows [name] = nil
  win = GetPluginID () .. "_" .. name
  WindowDelete (win)
  ShowWindows()
end -- RemoveWindow

-- called every second on a timer
function handle_cooldowns ()
  for name, details in pairs (active_windows) do
    if details.cooldown then
       details.cooldown = details.cooldown - 1  -- one less second
       if details.cooldown < 1 then
          details.cooldown = 0
       end -- if time is up
    end -- if has a cooldown
  end -- for each window
  ShowWindows()  
end -- function handle_cooldowns

-- remove the windows when we disconnect
function OnPluginDisconnect()
  for name, details in pairs (active_windows) do
    RemoveWindow (name)
  end -- for each window
end -- OnPluginDisconnect

]]>
</script>
</muclient>


To use it:

You can have a text box with or without a timeout. Each text box has a name (it can be anything, eg. "fireball") and then the text you want in the box (that you see). If you use the same name twice it will replace the previous box, if you use a different name then you will get extra boxes (one per name).

You add boxes to the screen with CallPlugin like this:


CallPlugin ("2f103c42b3356ee1bcac384b" , "MakeWindow" , "fireball", "Fireball Spell", 30 )


What that does is call MakeWindow inside the plugin, creates a box name "fireball" and puts the text "Fireball Spell" into the box. It has a timeout of 30 seconds in this example. It will automatically count down every second.

Another example:


CallPlugin ("2f103c42b3356ee1bcac384b" , "MakeWindow" , "rez", "Resurrection", 30 * 60 )


That would show "Resurrection" counting down for 30 minutes (30 times 60 seconds).

You can have a box without a timeout:


CallPlugin ("2f103c42b3356ee1bcac384b" , "MakeWindow" , "quest", "You have active quests")


You can remove a box:


CallPlugin ("2f103c42b3356ee1bcac384b" , "RemoveWindow" , "quest")


It's up to you to activate these windows by detecting game events with triggers or aliases.

This plugin is: now available on GitHub.


The version there splits the XML and Lua portions into different files, for better readability when using an editor that does syntax colouring (and on GitHub).

- Nick Gammon

www.gammon.com.au, www.mushclient.com
Top

Posted by Aardwanderer   (6 posts)  Bio
Date Reply #4 on Fri 11 Apr 2025 12:01 PM (UTC)

Amended on Fri 11 Apr 2025 07:30 PM (UTC) by Aardwanderer

Message
Thank you for that plugin! I like the idea of having custom windows for timers as you made, that's a cool idea. I had read through Fiendish's miniwindow tutorial so I had already created the miniwindow below:


function draw_window()
require "themed_miniwindows"
my_window = ThemedTextWindow("win", 200, 200, 200, 200, "Target", "center", false, true, false))

   my_window:add_text("@gTarget: @G" .. GetVariable("target") .. " @g(@G" .. GetVariable("direction") .. "@g)")
   if GetVariable("abilitystatus") == "wait" then
      my_window:add_text("@gAbility: @R" .. GetVariable("abilityuses") .. "@g (@R" .. GetVariable("abilitystatus") .. "@g)")
   else
      my_window:add_text("@gAbility: @G" .. GetVariable("abilityuses") .. " @g(@G" .. GetVariable("abilitystatus") .. "@g)")
   end --if
end


I was already able to get your cooldown_text plugin working using triggers and aliases to accurately display the cooldown for my ability, so again, thank you!

I know all the pieces are in cooldown_text, but I'm afraid my scripting abilites are too limited to figure out how to modify those pieces so I can get the cooldown timer to show after "abilitystatus" in my miniwindow.
Top

Posted by Aardwanderer   (6 posts)  Bio
Date Reply #5 on Sat 12 Apr 2025 03:20 PM (UTC)

Amended on Sat 12 Apr 2025 03:48 PM (UTC) by Aardwanderer

Message
I'm happy to say I got the cooldown_text plugin to sit on top of my miniwindow by modifying:

  top = 271 -- pixels down from top

and

    left = GetInfo (281) - window_width - 675  -- position on right, slightly in from edge

Now I'm looking at the code to see which parts I need to pull out, so I can get the cooldown in my miniwindow. It seems I need the following:

Necessary, but no need to modify.
  <timer 
    script="handle_cooldowns" 
    enabled="y" second="1.00" 
    active_closed="y" >
  </timer>

I'm wondering if I could use the following, or if I need to write my miniwindow in another way:

my_window:add_text()

To put the below code into my miniwindow after appropriate modifications.

Necessary, but modifications needed.

    contents = details.contents
    if details.cooldown then
       if details.cooldown <= 0 then
         contents = contents .. " (ready)"
       else
         contents = contents .. " (wait) " .. convert_time (details.cooldown)
       end -- if ready or waiting
    end -- if it has a cooldown

I know I will need to incorporate the following as well, but I need to pare down what I don't need.

-- add a notification window
function MakeWindow (name, contents, cooldown)
  active_windows [name] = { contents = contents, cooldown = cooldown }
  ShowWindows()
end -- MakeWindow

-- called every second on a timer
function handle_cooldowns ()
  for name, details in pairs (active_windows) do
    if details.cooldown then
       details.cooldown = details.cooldown - 1  -- one less second
       if details.cooldown < 1 then
          details.cooldown = 0
       end -- if time is up
    end -- if has a cooldown
  end -- for each window
  ShowWindows()  
end -- function handle_cooldowns


Does it look like I'm on the right track? And would it work to use: my_window:add_text()
or is a miniwindow re-write in order?
Top

Posted by Nick Gammon   Australia  (23,158 posts)  Bio   Forum Administrator
Date Reply #6 on Sun 13 Apr 2025 02:09 AM (UTC)
Message
I'm not clear what you are trying to achieve.

Why not just call the plugin from our other plugin, as I showed above?

- Nick Gammon

www.gammon.com.au, www.mushclient.com
Top

Posted by Aardwanderer   (6 posts)  Bio
Date Reply #8 on Mon 14 Apr 2025 02:12 AM (UTC)

Amended on Mon 14 Apr 2025 05:41 PM (UTC) by Aardwanderer

Message
I'm happy to say I was able to add the timer to my miniwindow! I have to do more testing, but I think I have it working. I had to change my triggers to send to a function that set the variables, and I needed the following:

function OnPluginInstall ()
    cooldown = 490
    Send("recovery")
end
  <timer 
    script="handle_cooldowns" 
    enabled="y" second="1.00" 
    active_closed="y" >
  </timer>

  <trigger
   enabled="y"
   match="^Your ability has been used\.$"
   regexp="y"
   script="abilityStat"
   sequence="100"
  >
  </trigger>

  <trigger
   enabled="y"
   group="archery"
   match="^You do not have any recovery times.$"
   regexp="y"
   send_to="12"
   sequence="100"
  >
  <send>SetVariable("volleystat", "ready")draw_window()
  </trigger>

  <trigger
   enabled="y"
   match="^\#\# You may now use the ability again\.$"
   regexp="y"
   send_to="12"
   sequence="100"
  >
  <send>SetVariable("abilitystat", "ready")cooldown = 0 draw_window()
  </trigger>

function abilityStat (name, line, wildcards) --this function does not set the cooldown to the correct time, but does send the correct cooldown time to screen
   SetVariable("abilitystat", "wait")
   cooldown = 490
   Note(cooldown) -- to verify trigger is firing
end -- function abilityStat

local cooldown = 490

local uses = GetVariable("uses")

function draw_window()
require "themed_miniwindows"
my_window = ThemedTextWindow("qtwin", 200, 200, 200, 200, "Target", "center", true, true, false, true, true, false, false, "Courier", 10, "Courier", 10)

   my_window:add_text("@gTarget: @G" .. GetVariable("target") .. " @g(@G" .. GetVariable("target_direc") .. "@g)")
   if GetVariable("abilitystat") == "wait" then
      my_window:add_text("@gAbility: @R" .. GetVariable("uses") .. "@g (@R" .. GetVariable("abilitystat") .. "@g) " .. convert_time(cooldown))
   else
      my_window:add_text("@gAbility: @G" .. GetVariable("uses") .. " @g(@G" .. GetVariable("abilitystat") .. "@g)")
   end --if
end -- draw_window()

Modified functions:
-- called every second on a timer
function handle_cooldowns ()
    if cooldown then
       cooldown = cooldown - 1  -- one less second
       if cooldown < 1 then
          cooldown = 0
       end -- if time is up
    end -- if has a cooldown
    draw_window()
end -- function handle_cooldowns


I know what I have done is a little messsy and probably inefficient, so any tips or pointers would be welcomed.

Also, now that I've added the timer, my miniwindow flickers fairly often. Is that due to using 'my_window:add_text()'? How can I change or what function to create the miniwindow should I use, so it doesn't flicker so much?

Thanks!
Top

The dates and times for posts above are shown in Universal Co-ordinated Time (UTC).

To show them in your local time you can join the forum, and then set the 'time correction' field in your profile to the number of hours difference between your location and UTC time.


986 views.

You need to log onto the forum to reply or create new threads.

  Refresh page

Go to topic:           Search the forum


[Go to top] top

Information and images on this site are licensed under the Creative Commons Attribution 3.0 Australia License unless stated otherwise.