Timers Tutorial
Timers execute code after a period of time has passed. They can be used to reduce the amount of management code you write by letting MMM take care of the timing details. This tutorial will cover the basic usage of timers, as well as touching on some more advanced uses.
The Plan
For the tutorial we'll make a timer that destroys the freighters that are surrounding the sensor station one by one.
Creating the Timer
Here we create a new TImer - add the following code to the setup function of your mission. It creates a Timer called explodeTimer. It has an initial 5.0 second tick interval and runs immediately. By default Timers do not repeat, so we need to change that setting.
local newTimer = Timer( "explodeTimer", 5.0, Timer.State.Started )
newTimer.repeats = true
Finding the Ships
We want to blow up the Mandrils, so we need to find them. The following code added to the setup function will do this for us - we store the results so we can use them as arguments to the Timer later.
--Find all of the Mandril class freighters that are placed
--around the sensor station in the middle.
local ents = EntityFinder( function(e)
return e:isType(Entity.Type.GameObject)
and e.odf == "fed_mandril.odf"
end ):find()
Creating the Hook Function
When the timer ticks we want to blow up one of the ships. The following function will do this - we will use it as the hook function on our timer. The general process is that we blow up the first ship in the list, remove it so we don't blow it up again and then reduce the timing interval slightly to speed up the explosions. We stop when there are no more ships to blow up.
--Timer hook function that blows up a single ship and
--removes it from the list.
function explodeShip( timer, hook )
--The table of ships is stored as the argument
--in the hook - we take the first entry in the list
local ship = hook.argument[1]
if ship not nil and ship.valid then
ship:explode()
end
--Remove the first ship from the results table
--so we don't explode it again
table.remove( hook.argument, 1 )
--Reduce the interval slightly each time to make it
--more interesting
timer.interval = timer.interval * 0.75
--If we don't have any more ships to blow up
--then we stop the timer from repeating.
if #hook.argument == 0 then
timer.repeats = false
end
end
Registering the Hook
Now that we have created our function and the timer, we are ready to register it. This will mean that it will be called every time the timer ticks. For this tutorial, we'll pass ents (the results from the EntityFinder call) as the argument for the hook; this will be stored in the argument field of the hook so that the hook function can access it.
--Passing the entities we found earlier as the argument to the hook
--function
newTimer:hook( "explodeShip", nil, explodeShip, ents )
Final Script
Here is the final script for the mission. Running it you will see freighters exploding with increasing frequency.
class 'TimerTutorial'
function TimerTutorial:__init( )
end
function TimerTutorial:setup( )
--Find all of the Mandril class freighters that are placed
--around the sensor station in the middle.
local ents = EntityFinder( function(e)
return e:isType(Entity.Type.GameObject)
and e.odf == "fed_mandril.odf"
end ):find()
--Timer hook function that blows up a single ship and
--removes it from the list.
function explodeShip( timer, hook )
--The table of ships is stored as the argument
--in the hook - we take the first entry in the list
local ship = hook.argument[1]
if ship ~= nil and ship.valid then
ship:explode()
end
--Remove the first ship from the results table
--so we don't explode it again
table.remove( hook.argument, 1 )
--Reduce the interval slightly each time to make it
--more interesting
timer.interval = timer.interval * 0.75
--If we don't have any more ships to blow up
--then we stop the timer from repeating.
if #hook.argument == 0 then
timer.repeats = false
end
end
local newTimer = Timer( "explodeTimer", 5.0, Timer.State.Started )
newTimer.repeats = true
--Passing the entities we found earlier as the argument to the hook
--function
newTimer:hook( "explodeShip", nil, explodeShip, ents )
Objectives:load( "TimerTutorialObjectives.txt" )
Objectives.visible = true
end
MMM.register( TimerTutorial( ) )