A to Z Scripting: Looping a script

From The DarkMod Wiki
Revision as of 11:04, 21 December 2020 by Dragofer (talk | contribs)
Jump to navigationJump to search

Looping a script

You may want a script to keep repeating until stopped, for as long as a condition stays true, or for a number of times.

The scripting engine allows up to 10,000 events per frame, so if you're doing something a finite number of times (i.e. checking all entities of a certain type) you can usually do it all in a single frame.

However, if the script should keep running continuously (i.e. for a "No harm" objective) you need to build some kind of wait() event into the script. This avoids that the script tries to run an infinite number of times in a single frame (crash with "runaway loop" error).


Looping with thread

The easiest way to loop is by making the script call itself at the end with "thread". Unlike other methods, this will always repeat the whole script.

Example: "No harm" objective

void looping_script()
{
	if ( $lord_marlow.getHealth() != 100 ) $player1.setObjectiveState(5, OBJ_FAILED);

	sys.wait(0.5);
	thread looping_script();
}


Looping with while()

while() lets you loop a script for as long as the condition inside the brackets is true. If it should loop permanently, put a 1 into the brackets (true).

Example: timer for a mover

void mover_timer()
{
	 while( $box.isMoving() )
	 {
 		sys.wait(0.1);
		float time_moved = time_moved + 0.1;
	}
}


Repeating with for()

for() lets a script repeat for a number of times that can be either pre-determined or variable. It's well-suited for gradually making a change in many small steps (increments).

Example: fading a shader parameter on an entity

void materialise()
{
    float i;					//define a float (integer) to keep track of the number of steps
    for (i=0;i<100;i++)			//go from 0 to (one under) 100, one at a time
    {
        fade_entity.setShaderParm(5,i);	//set shaderParm5 to the current number of steps
        sys.waitFrame();			//wait one frame until the next step
    }
}


Repeating with do + while()

"Do this script for as long as this condition is met". This one is quite similar to just using while(), the difference is it can begin even if the condition is false at first (the conditional is at the end, not at the beginning).

Example: running a script on every entity of a certain type

//Script by Obsttorte
void lamps_toggle()				//finds and triggers all electric lamps in the map
{
	light lamp;
	do					//do repeat this...
	{
		lamp = sys.getNextEntity("lightType","AIUSE_LIGHTTYPE_ELECTRIC",lamp);	//find the next entity which has this spawnarg value
		if (lamp != $null_entity) sys.trigger(lamp);
	}	while (lamp != $null_entity);		//repeat for as long as sys.getNextEntity finds electric lights
}


Terminating a running script

Terminating with killthread()

It's possible to manually terminate any script by giving it a (thread) name, and letting another script terminate it.

Example:

void check_health()
{
	sys.threadname("looping_script");		//assign a name to this script or thread

	if ( $lord_marlow.getHealth() != 100 ) $player1.setObjectiveState(5, OBJ_FAILED);
	sys.wait(0.5);
}

void terminate_check_health()
{
	sys.killthread("looping_script");	//terminate the script that was named "looping_script"
}

Terminating with return

Alternatively you can terminate a script with simply "return". This causes the script to terminate. Example:

if ( attempts == 3 ) return;


Next / previous article