Secondlife Blog
 
  • English
  • Spanish
  HOME arrow SL SCRIPTING GUIDE
Bookmark Website    Bookmark Page 
HOME
2LIFE NEWS
News From Reuters
SL Games
SEARCH
SL SCRIPTING GUIDE
SL Scripts Downloads
INTEREST SITES
CONTACT US
exchange marketplace
seconlife videos
Secondlife Blogs
Who's Online
 
We have 7 guests online
mod_vvisit_counterToday62
mod_vvisit_counterYesterday379
Who's Online


 Subscribe in a reader










Scripts Download
File Icon Texture Menu Management (1230)
File Icon Email to IM (898)
File Icon Code Racer (768)
File Icon Chat Logger (927)
File Icon Builders Buddy (1083)
File Icon Binary Clock (944)
File Icon Overriding Pose Ball (967)
File Icon Scan Ball (1009)
File Icon 3D Radar (1084)
File Icon Teleport Script (2281)
File Icon Super Jump Script (1724)
File Icon SetText Rotating Banner (1519)
File Icon Particle engine 1.0 (1843)
File Icon JetPack Script (2119)
File Icon Follow Camera (1480)
SL SCRIPTING GUIDE

04 - Flow Control

SL Scripting Guide
Written by Linden Lab   
viernes, 11 mayo 2007

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);
        }
}
 
 
Last Updated ( jueves, 12 julio 2007 )
 

05 - States

SL Scripting Guide
Written by Linden Lab   
viernes, 11 mayo 2007

All scripts must have a ’default’ state, which is the first state entered when the script starts. States contain event handlers that are triggered by the LSL virtual machine. All states must supply at least one event handler - it’s not really a state without one.

When state changes, all callback settings are retained and all pending events are cleared. For example, if you have set a listen callback in the default state and do not remove it during state_exit(), the listen callback will be called in your new state if a new listen event passes the filter set in the default state.


5.1. state_entry()

The state_entry event occurs whenever a new state is entered, including program start, and is always the first event handled. No data is passed to this event handler.

You will usually want to set callbacks for things such as timers and seonsor in the state_entry() callback of the state to put your object into a useful condition for that state.

 

Warning

It is a common mistake to assume that the state_entry() callback is called when you rez an object out
of your inventory. When you derez an object into your inventory the current state of the script is saved,

so there will not be a call to state_entry() during the rez. If you need to provide startup code every time
an object is created, you should create a global function and call it from both state_entry() and the
on_rez() callbacks.

 

// global initialization function.
init()
{
        // Set up a listen callback for whoever owns this object.
        key owner = llGetOwner();
        llListen(0, "", owner, "");
}
default
{
        state_entry()
        {
            init();
        }
        on_rez(integer start_param)
        {
            init();
        }
        listen(integer channel, string name, key id, string message)
        {
            llSay(0, "Hi " + name + "! You own me.");
        }
}

5.2. state_exit()


The state_entry event occurs whenever the state command is used to transition to another state. It is handled before the new state’s state_entry event.

You will want to provide a state_exit() if you need to clean up any events that you have requested in the current state, but do not expect in the next state.

default
{
        state_entry()
        {
            state TimerState;
        }

}
state TimerState
{
        state_entry()
        {
            // set a timer event for 5 seconds in the future.
            llSetTimerEvent(5.0);
        }
        timer()
        {
            llSay(0, "timer");
            state ListenState;
        }
        state_exit()
        {
            // turn off future timer events.
            llSetTimerEvent(0.0);
        }
}

integer g_listen_control;

state ListenState
{
        state_entry()
        {
            // listen for anything on the public channel
            g_listen_control = llListen(0, "", NULL_KEY, "");
        }
        listen(integer channel, string name, key id, string message)
        {
            llSay(0, "listen");
            state TimerState;
        }
        state_exit()
        {
            // turn off the listener
            llListenRemove(g_listen_control);
        }
}

 The state_exit() handler is not called when an object is being deleted - all callbacks, handlers, sounds, etc, will be cleaned up automatically for you.

 

 5.3. States vs. Global variables


A state and a set of global variables can serve the same purpose, and each can be expressed in terms of the other.
In general, you should prefer the use of states over global variables since states allow you to immediately assume script state without making comparisons. The less comparisons a script makes, the more regular code statements it can run.

Last Updated ( jueves, 12 julio 2007 )
 
<< Start < Prev 1 2 3 Next > End >>

Results 4 - 6 of 9
Related Items
HOME | 2LIFE NEWS | News From Reuters | SL Games | SEARCH | SL SCRIPTING GUIDE | SL Scripts Downloads | INTEREST SITES | CONTACT US | exchange marketplace | seconlife videos | Secondlife Blogs |
Advertisement
login





Lost Password?
No account yet?
Register
Friendly Webs

   
© 2012 2lifeBlog
Second Life® and Linden Lab® are trademarks or registered trademarks of Linden Research, Inc.
All rights reserved. No infringement is intended.