04 – Flow Control

but the most basic scripts will require some kind of flow contol. LSL comes with a complete complement of
constructs meant to deal with conditional processing, looping, as well as simply jumping to a different point in
the script.

4.1. Conditional Statements

The ’if’ statement operates and has the same syntax as the Java/C version.

check_message(string message)
{
if(message == “open”)
{
open();
}
else if(message == “close”)
{
close();
}
else
{
llSay(0, “Unknown command: ” + message);
}
}

The statements between the open and close curly brace are performed if the conditional inside the parentheses
evaluates to a non-zero integer. Once a conditional is determined to be true (non-zero), no further processing of
’else’ conditionals will be considered. The NULL_KEY constant is counted as FALSE by conditional
expressions.

There can be zero or more ’else if’ statements, and an optional final ’else’ to handle the case when none of the if
statements evaluate to a non-zero integer.

The usual set of integer arithmetic and comparison operators are available.

// a function that accepts some information about its environment and
// determines the the ’best’ next step. This kind of code might be
// part of a simple box meant to move close to an agent and attach to
// them once near. This code sample relies on the standard linden
// library functions as well as two other methods not defined here.

assess_next_step(integer perm, integer attached, integer balance, float dist)
{
string msg;
if(!attached)
{
if((perm & PERMISSION_ATTACH) && (dist < 10.0))
{
attach();
}
else if((dist > 10.0) || ((dist > 20.0) && (balance > 1000)))
{
move_closer();
}
else
{
llRequestPermissions(llGetOwner(), PERMISSION_ATTACH);
}
}
}

4.2. Loop Constructs

Loops are a basic building block of most useful programming languages, and LSL offers the the same loop
costructs as found in Java or C.

4.2.1. for loop

A for loop is most useful for when you know how many times you need to iterate over an operation. Just like a
Java or C for loop, the parentheses have three parts, the initializer, the continuation condition, and the increment.

The loop continues while the middle term evaluates to true, and the increment step is performed at the end of
every loop.

// move a non-physical block smootly upward (positive z) the the total
// distance specified divided into steps discrete moves.
move_up(float distance, integer steps)
{
float step_distance = distance / (float)steps;
vector offset = <0.0, 0.0, step_distance>;
vector base_pos = llGetPos();
integer i;
for(i = 0; i <= steps; ++i)
{
llSetPos(base_pos + i * offset);
llSleep(0.1);
}
}

4.2.2. do-while loop

The do-while loop construct is most useful when you are sure that you want to perform an operation at least
once, but you are not sure how many times you want to loop. The syntax is the same as you would find in a Java
or C program. A simple english transation would be ’do the code inside the curly braces and continue doing it if
the statement after the while is true.

// output the name of all inventory items attached to this object
talk_about_inventory(integer type)
{
string name;
integer i = 0;
integer continue = TRUE;
do
{
name = llGetInventoryName(type, i);
if(llStringLength(name) > 0)
{
llSay(0, “Inventory ” + (string)i + “: ” + name);
}
else
{
llSay(0, “No more inventory items”);
continue = FALSE;
}
} while(continue);
}

4.2.3. while loop

The while loop behaves similarly to the do-while loop, excpet it allows you to exit the loop without doing a
single iteration inside.

mention_inventory_type(integer type)
{
integer i = llGetInventoryNumber(type);
while(i–)
{
llSay(0, “item: ” + llGetInventory(i));
}
}

4.3. Jumps

A jump is used to move the running script to a new point inside of a function or event handler. You cannot jump
into other functions or event handlers. Usually, you will want to use a jump for in situations where the if..else
statements would become too cumbersome. For example, you may want to check several preconditions, and exit
if any of them are not met.

attach_if_ready(vector target_pos)
{
// make sure we have permission
integer perm = llGetPerm();
if(!(perm & PERMISSION_ATTACH))
{
jump early_exit;
}
// make sure we’re 10 or less meters away
vector pos = llGetPos()
float dist = llVecDist(pos, target_pos);
if(dist > 10.0)
{
jump early_exit;
}
// make sure we’re roughly pointed toward the target.
// the calculation of max_cos_theta could be precomputed
// as a constant, but is manually computed here to
// illustrate the math.
float max_cos_theta = llCos(PI / 4.0);
vector toward_target = llVecNorm(target_pos – pos);
rotation rot = llGetRot();
vector fwd = llRot2Fwd(rot);
float cos_theta = toward_target * fwd;
if(cos_theta > max_cos_theta)
{
jump early_exit;
}
// at this point, we’ve done all the checks.
attach();
@early_exit;
}

 

4.4. State Change

State change allow you to move through the lsl virtual machine’s flexible state machine by transitioning your
script to and from user defined states and the default state. You can define your own script state by placing the

keyword ’state’ before its name and enclosing the event handlers with open and close curly braces (’{’ and ’}’.)
You can invoke the transition to a new state by calling it with the syntax: ’state <statename>’.

default
{
state_entry()
{
llSay(0, “I am in the default state”);
llSetTimer(1.0);
}
timer()
{
state SpinState;
}
}

 

state SpinState
{
state_entry()
{
llSay(0, “I am in SpinState!”);
llTargetOmega(<0,0,1>, 4, 1.0);
llSetTimer(2.0);
}
timer()
{
state default;
}
state_exit()
{
llTargetOmega(<0,0,1>, 0, 0.0);
}
}

 

Esta entrada fue publicada en SL Scripting guide. Guarda el enlace permanente.

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos necesarios están marcados *

*

Puedes usar las siguientes etiquetas y atributos HTML: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>