Author Topic: TrailMyx's Fun with Timers  (Read 17321 times)

0 Members and 1 Guest are viewing this topic.

Offline TrailMyxTopic starter

  • Officially retired from UO
  • Administrator
  • *
  • *
  • Posts: 13310
  • Activity:
    0%
  • Reputation Power: 154
  • TrailMyx is awe-inspiring!TrailMyx is awe-inspiring!TrailMyx is awe-inspiring!TrailMyx is awe-inspiring!TrailMyx is awe-inspiring!TrailMyx is awe-inspiring!TrailMyx is awe-inspiring!TrailMyx is awe-inspiring!TrailMyx is awe-inspiring!TrailMyx is awe-inspiring!TrailMyx is awe-inspiring!TrailMyx is awe-inspiring!
  • Gender: Male
  • Viper!
  • Respect: +3089
  • Referrals: 34
    • View Profile
    • ScriptUO
TrailMyx's Fun with Timers
« on: April 25, 2020, 07:27:38 AM »
+1
I've been going through my vast collection of unfinished tools, and one that popped out that bugged me that wasn't finished (and probably won't ever be) is my automated timer subs.  Anyone who has played with timers and state machines will know how useful they can be.  I'm attaching a group of subs plus a little tidbit of sample code that shows what's going on.  These subs use the global namespace TM_TIMERS so timer status can be seen through other scripting instances.  You can expand on these subs; I just made what I had started work correctly.

For the example script (found at the beginning of the subs) there's alot going on.  Try and follow along with it:

Code: easyuo
  1. gosub TM_ResetTimers
  2. gosub TM_RegisterTimer Timer1 auto 10 second Callback1
  3. gosub TM_RegisterTimer Timer2 5 1 second
  4.  
  5. set %timer1 0
  6. set %timer2 0
  7. repeat
  8.   gosub TM_ProcessTimers
  9.   if Timer1 in #RESULT
  10.   {
  11.     set %timer1 %timer1 + 1
  12.     if %timer1 % 2 = 1
  13.       gosub TM_RestartTimer Timer2
  14.   }
  15.   if Timer2 in #RESULT
  16.     set %timer2 %timer2 + 1
  17. until #FALSE
  18. stop
  19.  

In this snippet:
  • Timer1 runs forever (auto) and fires every 10 seconds.  Also when the timer fires, the callback function "Callback1" is called
  • Timer2 runs only 5 times, and fires every 1 second.
  • Timer1 is used to rearm Timer2 when the Timer1 is first run and every ODD firing of Timer1 (watch %timer1 and %timer2 variables)
  • #RESULT of TM_ProcessTimers shows a list of expired timers.  If a callback is attached, it will already have run

I have a bunch of subs like this, and perhaps I'll slowly finish them as time goes on.

Code: easyuo
  1. gosub TM_ResetTimers
  2. gosub TM_RegisterTimer Timer1 auto 10 second Callback1
  3. gosub TM_RegisterTimer Timer2 5 1 second
  4.  
  5. set %timer1 0
  6. set %timer2 0
  7. repeat
  8.   gosub TM_ProcessTimers
  9.   if Timer1 in #RESULT
  10.   {
  11.     set %timer1 %timer1 + 1
  12.     if %timer1 % 2 = 1
  13.       gosub TM_RestartTimer Timer2
  14.   }
  15.   if Timer2 in #RESULT
  16.     set %timer2 %timer2 + 1
  17. until #FALSE
  18. stop
  19.  
  20. ; --------------------------------------------------------
  21.  
  22. sub Callback1
  23.   display ok Callback 1 called!
  24. return
  25.  
  26. ; --------------------------------------------------------
  27.  
  28. sub TM_ResetTimers
  29.   namespace push
  30.   namespace global TM_TIMER
  31.   namespace clear
  32.   namespace pop
  33. return
  34.  
  35. ; --------------------------------------------------------
  36.  
  37. sub TM_RegisterTimer
  38.   namespace push
  39.   namespace global TM_TIMER
  40.  
  41.   if !num = N/A
  42.     set !num -1
  43.   if %0 < 4
  44.   {
  45.     display ok 4 arguments required for TM_RegisterTimer - stopping
  46.     stop  
  47.   }
  48.   set !num !num + 1
  49.   set !var %1
  50.   set !function %2 ; auto, number
  51.   set !time_length %3
  52.   set !time_unit %4 ; millisecond, second, minute, hour
  53.   if %0 = 5
  54.     set !callback %5
  55.   else
  56.     set !callback N/A
  57.   set ! . timer , !num !var ; save the name to a list for automatic time updating
  58.   set ! . !var , function !function
  59.   set ! . !var , trigger_max !function
  60.   set ! . !var , time_length !time_length
  61.   set ! . !var , time_unit !time_unit
  62.   set ! . !var , callback !callback
  63.   set ! . !var , enabled #TRUE
  64.  
  65.   if !time_unit notin _millisecond_second_minute_hour_
  66.   {
  67.     display ok time unit not equal to millisecond, second, minute, hour - stopping
  68.     stop
  69.   }
  70.   if !time_unit = millisecond
  71.     set ! . !var , time_unit !time_length
  72.   if !time_unit = second
  73.     set ! . !var , time_unit ( !time_length * 20 )
  74.   if !time_unit = minute
  75.     set ! . !var , time_unit ( !time_length * 20 * 60 )
  76.   if !time_unit = hour
  77.     set ! . !var , time_unit ( !time_length * 20 * 60 * 60 )
  78.  
  79.   set !time_unit !var , time_unit
  80.   set ! . !var , timer ( #SCNT2 + ( ! . !time_unit ) )  ; set the actual end time
  81.   namespace pop
  82. return
  83.  
  84. ; --------------------------------------------------------
  85.  
  86. sub TM_ProcessTimers
  87.   namespace push
  88.   namespace global TM_TIMER
  89.   set !lpc #LPC
  90.   set #LPC 200
  91.  
  92.   set !RESULT
  93.   for !i 0 !num
  94.   {
  95.     set !current_name ! . timer . !i
  96.     set !enabled !current_name , enabled
  97.     set !timer !current_name , timer
  98.     set !time_unit !current_name , time_unit
  99.     set !function !current_name , function
  100.     set !callback !current_name , callback
  101.  
  102.     set !test1 #SCNT2 , _ , ! . !timer
  103.     if ( ( ! . !enabled = #TRUE ) && ( #SCNT2 > ( ! . !timer ) ) )
  104.     {
  105.       set !function !current_name , function
  106.       if ( ( ( ! . !function ) = auto ) || ( ! . !function <> 0 ) )
  107.       {
  108.         set !RESULT !RESULT , _ , !current_name ; add expired timer name to present list
  109.         set ! . !timer ( #SCNT2 + ( ! . !time_unit ) )  ; set the actual end time, resetting timer
  110.         if ! . !function <> auto
  111.           set ! . !function ( ( ! . !function ) - 1 )
  112.         if ! . !callback <> N/A
  113.           gosub ! . !callback
  114.       }
  115.     }
  116.   }
  117.   set #RESULT !RESULT
  118.   set #LPC !lpc
  119.   namespace pop
  120. return #RESULT
  121.  
  122. ; --------------------------------------------------------
  123.  
  124. sub TM_RestartTimer
  125.   namespace push
  126.   namespace global TM_TIMER
  127.   set !name %1
  128.  
  129.   set !function !name , function
  130.   set !trigger_max !name , trigger_max
  131.   set !enabled !name , enabled
  132.   set !timer !name , timer
  133.   set !time_unit !name , time_unit
  134.  
  135.   set ! . !function ! . !trigger_max
  136.   set ! . !enable #TRUE
  137.  
  138.   set ! . !timer ( #SCNT2 + ( ! . !time_unit ) )  ; set the actual end time
  139.   namespace pop
  140. return
  141.  
  142. ; --------------------------------------------------------
  143.  
  144. sub TM_StopTimer
  145.   namespace push
  146.   namespace global TM_TIMER
  147.   set !name %1
  148.   set !enabled !name , enabled
  149.   set ! . !enabled #FALSE
  150.   namespace pop
  151. return
  152.  
« Last Edit: April 25, 2020, 07:34:12 AM by TrailMyx »
Please read the ScriptUO site RULES
Come play RIFT with me!

Offline Gaderian

  • Elite
  • *
  • *
  • Posts: 490
  • Activity:
    0%
  • Reputation Power: 10
  • Gaderian barely matters.Gaderian barely matters.
  • Respect: +283
  • Referrals: 3
    • View Profile
Re: TrailMyx's Fun with Timers
« Reply #1 on: April 25, 2020, 07:52:46 AM »
+1
Thank you for sharing these routines on Timers.

I have had so many conversations about timers in the last maybe 6 months... (hence the signature addition). It is a very nice concept for how to write very efficient code that acts when needed and doesn't have to do anything much when just waiting for timers.

You mention state machines and I have only met a few other programmers who understood these. Personally, I only designed a couple of applications to use a state machine. From a very ubiquitous experience it is a very efficient method to code when you want ultimate UI flexibility. Specifically: Graphical user interfaces (Windows, MacOS, X-Windows) run on a state machine.

It can also be considered/labeled "event driven" programming. The only complexity is being willing to give up the main loop control. The main loop has to be elegant for the system to work smoothly and be understandable. Once a programmer can handle that concept, the code is clean and needs to follow a simple structure.

Combine timers with a state machine and you have a really flexible script. ;)

Gaderian
"Go ahead ask me: 'Should I use hard waits or timers?'"
You say:"Should I"
Gaderian:"Timers!"
You Say:"use hard waits or timers?"

The serious side of timer use is illustrated here: http://www.scriptuo.com/index.php?topic=12094.msg101926#msg101926

However, every time I go back and look at this [AutoLooter] script, I realize I had wrote it in my zen state of EUO scripting - so it makes my brain hurt.

Offline TrailMyxTopic starter

  • Officially retired from UO
  • Administrator
  • *
  • *
  • Posts: 13310
  • Activity:
    0%
  • Reputation Power: 154
  • TrailMyx is awe-inspiring!TrailMyx is awe-inspiring!TrailMyx is awe-inspiring!TrailMyx is awe-inspiring!TrailMyx is awe-inspiring!TrailMyx is awe-inspiring!TrailMyx is awe-inspiring!TrailMyx is awe-inspiring!TrailMyx is awe-inspiring!TrailMyx is awe-inspiring!TrailMyx is awe-inspiring!TrailMyx is awe-inspiring!
  • Gender: Male
  • Viper!
  • Respect: +3089
  • Referrals: 34
    • View Profile
    • ScriptUO
Re: TrailMyx's Fun with Timers
« Reply #2 on: April 25, 2020, 09:40:30 AM »
+1
Thank you for sharing these routines on Timers.

You bet, I have a few others to come

I have had so many conversations about timers in the last maybe 6 months... (hence the signature addition). It is a very nice concept for how to write very efficient code that acts when needed and doesn't have to do anything much when just waiting for timers.

I saw that; you were the one that prompted me to dig through my stash.  :)

You mention state machines and I have only met a few other programmers who understood these. Personally, I only designed a couple of applications to use a state machine. From a very ubiquitous experience it is a very efficient method to code when you want ultimate UI flexibility. Specifically: Graphical user interfaces (Windows, MacOS, X-Windows) run on a state machine.

I'm a digital hardware designer by trade, so I often think about software solutions through the lens of hardware programming in VHDL or Verilog.  By default, those methods of expression are inherently parallel in nature.  So it's fun to force EasyUO kicking and screaming to do something it was never designed to do.  heh.  Your Windows programming example is an excellent example of it.

It can also be considered/labeled "event driven" programming. The only complexity is being willing to give up the main loop control. The main loop has to be elegant for the system to work smoothly and be understandable. Once a programmer can handle that concept, the code is clean and needs to follow a simple structure.

You're right for sure.  If you can break all your total functionality to just use timers and state machines, your main loop can actually look exactly like this:

Code: easyuo
  1. repeat
  2.   gosub TM_ProcessTimers
  3.   gosub TM_HandleStateMachine
  4. until #FALSE
  5.  

Since you have access to the Elite script section, you can see a few of my scripts that are state machine driven.  Here's a couple:

Mining/Lumberjack Assistant:
http://www.scriptuo.com/index.php?topic=13509.msg112203#msg112203

Zoo donation:
http://www.scriptuo.com/index.php?topic=36.msg36#msg36

SOS Autofarmer:
http://www.scriptuo.com/index.php?topic=2048.msg15109#msg15109

All of these have remarkably small main loops.



Please read the ScriptUO site RULES
Come play RIFT with me!

Tags: TrailMyx