Timers

From SCI Wiki
Jump to navigationJump to search
The printable version is no longer supported and may have rendering errors. Please update your browser bookmarks and please use the default browser print function instead.

By Lars Skovlund

The Timer class in the template game has gone largely unused, and that is a shame. So here's my attempt at explaining how to use it.

First, there is no need to instantiate an object unless you want to change the timeout later on. The class methods are designed to take care of that. Second, the Timer class works by queuing a script when it expires. I can't recall whether that's in the documentation or not, but it simply means incrementing the current state number by 1 and calling changeState. Third, the only real advantage of the Timer class is its mutator methods. All other functionality is available directly in the Script class, so if your timing needs are simple, you don't need this class at all.

Next, I'll describe the architecture of Timer (and Script, in this regard) objects. There are actually two separate properties devoted for timing: They are called 'cycles' ('cycleCnt' in the Timer class) and 'seconds'. The difference between them is (obviously) their resolution and, consequently, also their range. A cycle in SCI parlance is 1/60th of a second. Thus, the maximum range of a timer if you choose to use the cycle counter is about 18 minutes. If you choose to use the second counter, the range is about 45 hours.

The mutator functions I hinted at above are called setCycles, set, and setReal, respectively. The first one is simple; it takes a cycle count (which you would have to calculate yourself) and starts a new timer with that timeout. You would call it like so:

Code:
(Timer:setCycle(RoomScript 30))

where RoomScript is the script that will be cued when the timer expires. The timeout will be half a second (30/60).

The set method is a bit smarter. It automatically calculates the correct cycle count given a count of seconds, minutes, and hours. This method also adjusts the final count for the currently set game speed, which is not always what you want. And it uses the cycle counter (see above for a description); the real range of the Timer class may vary if you use this method. You would use it like so:

Code:
(Timer:set(RoomScript 30))

for a thirty-second delay.

Finally, there's the setReal method. Like set, it performs all calculations on its own, but it uses the seconds counter, and it does not adjust for game speed. Thus, it is ideal for game events that depend on how much "real time" passes. However, it does not work out of the box due to a typo in the template game. To fix it, find the doit method of the timer class (in Timer.sc), and the line that says:

Code:
(if (not seconds)
    CueClient()
)

Fix the first line so it reads:

Code:
(if (not --seconds)

and you're all set.

Finally, the cases where you don't need a Timer object. As I've mentioned, the Script class has comparable properties (but no methods) to the Timer class. So you can simply use your room script and the cycles and seconds properties directly, if you are so inclined. This is what Sierra did in most cases; you don't really see the Timer class used much in the games. You would simply do

Code:
(instance RoomScript of Script
     (method (changeState newState)
        (super:changeState(newState))
        (switch (newState)
           (case 1
            = seconds 15)
           (case 2
            Print("Time's up!")))))

When using the Timer class, you would similarly put your initialization code in case 1 above (or in a room's init method).

See feed back about this post on the forums