Transcript
Stefano Cacciaguerra Ph.D in Computer Science 1
Linden Script Language - LSL
by
Stefano Cacciaguerra
Stefano Cacciaguerra Ph.D in Computer Science 2
Outline
I. Basic Script Concept
II. Constants, Variables and Data Type
III. Flow-Control Statement
IV. States
V. Functions
VI. Events Handler
VII. Tutorial
Stefano Cacciaguerra Ph.D in Computer Science 3
I. What is LSL?
LSL is language used to attach behaviors to the objects
It has syntax similar to Java, with an implicit state machine
for every script.
Multiple scripts may also be attached to the same object,
allowing a style of small, single-function scripts to evolve.
This leads to scripts that perform specific functions and
allows them to be combined to form new behaviors.
Stefano Cacciaguerra Ph.D in Computer Science 4
What is LSL?
The script is compiled into an executable byte code.
This byte code is then run within a virtual machine on the
simulator.
Each script receives a time slice of the total simulator time
allocated to scripts in order to guarantee fairness.
Each script executes within its own chunk of memory,
preventing scripts from writing into other protected memory.
Stefano Cacciaguerra Ph.D in Computer Science 5
Creating the Hello ScriptCreating the Hello ScriptCreating the Hello ScriptCreating the Hello Script
default
{
state_entry()
{
llSay(0, "Hello, Avatar!");
}
touch_start(integer total_number)
{
llSay(0, "Touched.");
}
}
This script says “Hello, Avatar!” when it enters
some state, and it says
“Touched.” when it is touched.
Stefano Cacciaguerra Ph.D in Computer Science 6
Default StateDefault StateDefault StateDefault State
default
{
...
}
All scripts have a simple implicit state machine with one
or more states.
They must have a default state. When a script is first
started or reset, it will start out in the default state.
Stefano Cacciaguerra Ph.D in Computer Science 7
Default StateDefault StateDefault StateDefault State
Every time you enter a state, the script engine calls the
state_entry() event and execute the code found there.
On state exit, the script engine calls the state_exit() event.
In our example, we call the llSay() function in state_entry().
The state entry and exit handlers are a convenient place to
initialize state data and clean up state specific data.
Stefano Cacciaguerra Ph.D in Computer Science 8
FunctionsFunctionsFunctionsFunctions
The language has over 200 built in functions which allow
scripts and objects to interact with their environment.
All of the built in functions start with 'll'.
The example calls the llSay() function twice, which is used
to emit text on the specified channel.
llSay( integer channel, string text );
Stefano Cacciaguerra Ph.D in Computer Science 9
FunctionsFunctionsFunctionsFunctions
llSay( integer channel, string text );
Say text on channel.
Channel 0 is the public chat channel that all avatars see as
chat text.
Channels 1 to 2,147,483,648 are private channels that
are not sent to avatars but other scripts can listen for.
Stefano Cacciaguerra Ph.D in Computer Science 10
Touch EventTouch EventTouch EventTouch Event
touch_start(integer total_number)
{
llSay(0, "Touched.");
}
There are many events that can be detected in your scripts
by declaring a handler.
The touch_start() event is raised when a user touches the
object through the user interface.
Stefano Cacciaguerra Ph.D in Computer Science 11
SaveSaveSaveSave
Save the script by clicking on Save.
During the saving process, the editor will
• save the text of the script
• compile the script into bytecode
• and then save that.
When you see message “Compile successful!” in the
preview window, you know the compile and save is done.
Stefano Cacciaguerra Ph.D in Computer Science 12
Test the scriptTest the scriptTest the scriptTest the script
Apply it to an object in the world.
Create a new object in the world by context clicking in the
main world view and selecting Create.
Create a simple primitive by clicking in the world.
Once the object appears, you can drag your newly created
script onto the object to start the script.
Soon, you will see the message Object: Hello Avatar!
Stefano Cacciaguerra Ph.D in Computer Science 13
II. CommentsII. CommentsII. CommentsII. Comments
Comment your scripts:
• at the start of the script to explain the purpose of the script
• before every global variable to describe what it holds
• before every global function to describe what it does
• wherever the code solves a specific problem.
LSL uses Java/C++ style single line comments.
// This script toggles a the rotation of an object
Stefano Cacciaguerra Ph.D in Computer Science 14
ExampleExampleExampleExample
// g_is_rotating stores the current state of rotation. TRUE is rotating else FALSE.
integer g_is_rotating = FALSE;
default
{ // toggle state during the touch handler
touch(integer num)
{
if(g_is_rotating)
{ // turn off rotation
llTargetOmega(<0,0,1>, 0, 0);
g_is_rotating = FALSE;
}
else
{ // rotate around the positive z axis - up.
llTargetOmega(<0,0,1>, 4, 1);
g_is_rotating = TRUE;
}
}
}
Stefano Cacciaguerra Ph.D in Computer Science 15
Arithmetic OperationsArithmetic OperationsArithmetic OperationsArithmetic Operations
Assignment '='
equality '=='
inequality '!=‘
// variables to hold a information about the target
key g_target;
vector g_target_postion;
float g_target_distance;
// function that demonstrates assignment
set_globals(key target, vector pos)
{
g_target = target;
g_target_position = pos;
// assignment from the return value of a function
vector my_pos = llGetPos();
g_target_distance = llVecDist(g_target_position, my_pos);
}
Stefano Cacciaguerra Ph.D in Computer Science 16
Hexadecimal EntryHexadecimal EntryHexadecimal EntryHexadecimal Entry
Integers may be entered in hex form (e.g. 0xffff) starting it
with “0x”:
integer Mask = 0xff; // Equivalent to integer Mask = 255
integer Bit = 0x0100; // Equivalent to integer Mask = 256
Stefano Cacciaguerra Ph.D in Computer Science 17
Binary Arithmetic OperatorsBinary Arithmetic OperatorsBinary Arithmetic OperatorsBinary Arithmetic Operators
Increment and Decrement++ and --
Shift Right>>
Division/
Modulo (remainder)%
Exclusive OR^
Multiplication*
Shift Left<<
Subtraction-
Addition+
MeaningOperator
Stefano Cacciaguerra Ph.D in Computer Science 18
Boolean OperatorsBoolean OperatorsBoolean OperatorsBoolean Operators
True if the LX is greater than or equal to the DX>=
True if the LX and DX hand side are both true&&
Operator returns True if either the LX or DX are True||
True if the LX is less than or equal to the DX<=
Unary operator returns the logical negation of the
expression to the DX!
True if the LX is greater than the DX>
True if the LX is less than the DX<
Operator returnsOperator
Stefano Cacciaguerra Ph.D in Computer Science 19
Bitwise OperatorsBitwise OperatorsBitwise OperatorsBitwise Operators
Unary operator returns the bitwise complement ofthe expression to the DX.~
Returns the bitwise or of the LX and DX.|
Returns the bitwise and of the LX and DX.&
Operator returnsOperator
A bitwise operation operates on one or two bit patterns or
binary numerals at the level of their individual bits
integer mask = AGENT | SCRIPTED | ACTIVE;
Stefano Cacciaguerra Ph.D in Computer Science 20
LSL TypesLSL TypesLSL TypesLSL Types
LSL provides a small set of basic types simple:
integer: A signed, 32-bit integer value with valid range from
-2147483648 to 2147483647.
float: An IEEE 32-bit floating point value with values ranging
from 1.175494351E-38 to 3.402823466E+38.
Stefano Cacciaguerra Ph.D in Computer Science 21
Simple: KeySimple: KeySimple: KeySimple: Key
key: A unique identifier can be used to reference objects and
avatars in SL. Known as UUID (Universal Unique IDentifier).
The special constant NULL_KEY can be used to represent no
key, which is to say there is no object.
It is impossible for a script to change an item’s key
key nokey = NULL_KEY;
key owner = llGetOwner();
Stefano Cacciaguerra Ph.D in Computer Science 22
Composite: VectorComposite: VectorComposite: VectorComposite: Vector
Vector cross product (vector product)%
Vector dot product (scalar product)*
Subtract one vector from another-
Add two vectors together+
Operator returnsOperator
vector: 3 floats that are used together as a single item. Each
component can be accessed via '.x', '.y', and '.z'.
ZERO_VECTOR is equal to <0.0, 0.0, 0.0>
Stefano Cacciaguerra Ph.D in Computer Science 23
ExampleExampleExampleExample
vector p = llGetPos(); // Get the object’s position in the sim
v1= < x1, y1, z1> and v2= < x2, y2, z2>
v3 = v1 + v2 = <x1+x2, y1+y2, z1+z2> similarly for “–”
a1 = v1 * v2 = x1*x2 + y1*y2 + z1*z2
is the angle between v1 and v2
v5 = v1 % v2 = <y1z2 - z1y2, z1x2 - x1z2, x1y2 - y1x2>
is the vector perpendicular to both v1 and v2
v6 = a * v1 = <a*x1, a*y1, a*z1>
Stefano Cacciaguerra Ph.D in Computer Science 24
Composite: RotationComposite: RotationComposite: RotationComposite: Rotation
Rotate the first rotation by the inverse of the second/
Rotate the first rotation by the second*
Subtract one rotation from another-
Add two rotations together+
MeaningOperator
rotation: A quaternion, 4 floats that are used together as a
single item to represent a rotation. Each component can be
accessed via '.x', '.y', and '.z' and '.s'.
Stefano Cacciaguerra Ph.D in Computer Science 25
ExampleExampleExampleExample
Rotation zero = ZERO_ROTATION
zero= <0.0, 0.0, 0.0, 1.0> // to represent no rotation
vector r = llGetRot(); // Get the object’s rotation
Stefano Cacciaguerra Ph.D in Computer Science 26
Composite: ListComposite: ListComposite: ListComposite: List
list: A heterogeneous list of the other data types. Lists are
created via comma separated values of the other data types
enclosed by '[' and ']'. The empty list is represente by []
string StringVar = "Hello, Carbon Unit";
rotation ZERO_ROTATION = <0,0,0,1>;
list MyList = [ 1234, ZERO_ROTATION, StringVar ];
=> [ 1234, <0,0,0,1>, "Hello, Carbon Unit" ]
Stefano Cacciaguerra Ph.D in Computer Science 27
ExamplesExamplesExamplesExamples
MyList = 3.14159 + MyList;
=> [ 3.14159, 1234, <0,0,0,1>, "Hello, Carbon Unit" ]
MyList = MyList + MyList;
=> [ 3.14159, 1234, <0,0,0,1>, "Hello, Carbon Unit", 3.14159, 1234, <0,0,0,1>, "Hello, Carbon Unit" ]
Stefano Cacciaguerra Ph.D in Computer Science 28
Accessing Item Inside a ListAccessing Item Inside a ListAccessing Item Inside a ListAccessing Item Inside a List
Items are accessed by llList2Integer, llList2String, llList2Float
and so on.
Items in the lists are indexed starting at 0
list clothes = [“shirt”, “hat”, “coat”, “pants”, “socks”]
string s;
s = llList2String(clothes, 0) // s is the shirt
s = llList2String(clothes, 4) // s is the coat
Stefano Cacciaguerra Ph.D in Computer Science 29
Accessing Item Inside a ListAccessing Item Inside a ListAccessing Item Inside a ListAccessing Item Inside a List
Lists are immutables, once created the value in the list is not
possible to change it.
It is possible to build a new list with llList2List. It takes three
arguments the list, a start index and an end index
list clothes = [“shirt”, “hat”, “coat”, “pants”, “socks”]
clothes = llList2List(clothes, 0, 0) + [“belt”] + llList2List(clothes, 2, 4)
clothes = [“shirt”, “belt”, “coat”, “pants”, “socks”]
Stefano Cacciaguerra Ph.D in Computer Science 30
Composite: StringComposite: StringComposite: StringComposite: String
Inequality!=
Equality==
Concatenation+
Operator returnsOperator
A string could hold text enclosed by '“' and '”'.
Stefano Cacciaguerra Ph.D in Computer Science 31
Type ConversionType ConversionType ConversionType Conversion
implicit type casts:
• integer to float
• string to key.
explicit type casts:
• integer to string
• float to Integer
• float to string
• vector to string
• rotation to string
• Integer to List
• float to List
• Key to List
• string to List
• vector to List
• rotation to List
• string to Integer
• string to float
• string to vector
• string to rotation
Stefano Cacciaguerra Ph.D in Computer Science 32
Global FunctionsGlobal FunctionsGlobal FunctionsGlobal Functions
Global functions are also declared much like Java/C, with the
exception that no 'void' return value exists:
make_physical_and_spin(vector torque)
{
// double the torque
vector double_torque = 2.0*torque;
llSetStatus(STATUS_PHYSICS, TRUE);
llApplyTorque(double_torque);
}
Stefano Cacciaguerra Ph.D in Computer Science 33
Global VariablesGlobal VariablesGlobal VariablesGlobal Variables
Global variables and functions are accessible from anywhere
in the file. Only one declaration may be made per line:
vector gStartPosition;
Global variables may also be initialized if desired, although
uninitialized global and local variables are initialized to legal
zero values:
vector gStartPosition = <10.0,10.0,10.0>
Stefano Cacciaguerra Ph.D in Computer Science 34
Local VariablesLocal VariablesLocal VariablesLocal Variables
Local variables are scoped below their declaration within
the block of code they are declared in
Local variables may be declared within any block of code.
Stefano Cacciaguerra Ph.D in Computer Science 35
Local VariablesLocal VariablesLocal VariablesLocal Variables
integer test_function()
{
// Test vector that we can use anywhere in the function
vector test = <1,2,3>;
integer j;
for (j = 0; j < 10; j++)
{
// This vector is a different variable than the one declared above
// This IS NOT good coding practice
vector test = <j, j, j>;
}
// this test fails
if (test == <9,9,9>)
{ // never reached}
}
Stefano Cacciaguerra Ph.D in Computer Science 36
III. Conditional StatementsIII. Conditional StatementsIII. Conditional StatementsIII. Conditional Statements
The 'if' statement as the Java/C version.
check_message(string message)
{
if(message == "open")
{ open(); }
else if(message == "close")
{ close(); }
else
{ llSay(0, "Unknown command: " + message); }
}
Stefano Cacciaguerra Ph.D in Computer Science 37
Conditional StatementsConditional StatementsConditional StatementsConditional Statements
The NULL_KEY constant counts as FALSE.
There can be zero or more 'else if' statements, and an
optional final 'else'.
The usual set of integer arithmetic and comparison operators .
// a function that accepts some information about its environment and
// determines 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.
Stefano Cacciaguerra Ph.D in Computer Science 38
Conditional StatementsConditional StatementsConditional StatementsConditional Statements
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); }
}
}
Stefano Cacciaguerra Ph.D in Computer Science 39
for loopfor loopfor loopfor 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.
Stefano Cacciaguerra Ph.D in Computer Science 40
for loopfor loopfor loopfor loop
// move a non-physical block smoothly upward (positive z) 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);
}
}
Stefano Cacciaguerra Ph.D in Computer Science 41
dodododo----while loopwhile loopwhile loopwhile 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 Java and C program.
A simple English translation 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
Stefano Cacciaguerra Ph.D in Computer Science 42
dodododo----while loopwhile loopwhile loopwhile loop
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; }
i++;
} while(continue);
}
Stefano Cacciaguerra Ph.D in Computer Science 43
while loopwhile loopwhile loopwhile loop
The while loop 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));
}
}
Stefano Cacciaguerra Ph.D in Computer Science 44
State ChangeState ChangeState ChangeState 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 '}'.)
Invoke the transition to a new state by calling it with the
syntax: 'state <statename>'.
Stefano Cacciaguerra Ph.D in Computer Science 45
State ChangeState ChangeState ChangeState Change
default
{
state_entry()
{
llSay(0, "I am in the default state");
llSetTimer(1.0);
}
timer()
{
state SpinState;
}
}
Stefano Cacciaguerra Ph.D in Computer Science 46
State ChangeState ChangeState ChangeState Change
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); }
}
Stefano Cacciaguerra Ph.D in Computer Science 47
IV. StatesIV. StatesIV. StatesIV. States
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!
When state changes:
• all callback settings are retained
• and all pending events are cleared.
Stefano Cacciaguerra Ph.D in Computer Science 48
state_entry()state_entry()state_entry()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.
Stefano Cacciaguerra Ph.D in Computer Science 49
Warning: state_entry()Warning: state_entry()Warning: state_entry()Warning: state_entry()
It is a 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.
Stefano Cacciaguerra Ph.D in Computer Science 50
ExampleExampleExampleExample
// global initialization function.
init()
{
// Set up a listen callback for whoever owns this object.
key owner = llGetOwner();
llListen(0, "", owner, "");
}
Stefano Cacciaguerra Ph.D in Computer Science 51
ExampleExampleExampleExample
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.");
}
}
Stefano Cacciaguerra Ph.D in Computer Science 52
state_exitstate_exitstate_exitstate_exit()()()()
Provide a state_exit() if you need to clean up any events
requested in the current state, but do not expect in the next state
default
{
state_entry()
{ state TimerState;}
}
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.
Stefano Cacciaguerra Ph.D in Computer Science 53
state_exitstate_exitstate_exitstate_exit()()()()
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); }
}
Stefano Cacciaguerra Ph.D in Computer Science 54
state_exitstate_exitstate_exitstate_exit()()()()
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); }
}
Stefano Cacciaguerra Ph.D in Computer Science 55
V. Math FunctionsV. Math FunctionsV. Math FunctionsV. Math Functions
llAtan2
llCeil
llCos
llAsin
llFabs
llFloor
llAcos
llAbs
Trigonometry
llSin
llSqrt
llTan
llRound
llPow
llFrand
Trigonometry
llVecNorm
llVecMag
llVecDist
Vector
llRot2Up
llRot2Left
llRot2Fwd
llEuler2Rot
llRot2Angle
llRot2Axis
llAxisAngle2Rot
llRot2Euler
llRotBetween
llAxes2Rot
llAngleBetween
Rotation
Stefano Cacciaguerra Ph.D in Computer Science 56
String and List FunctionsString and List FunctionsString and List FunctionsString and List Functions
llStringToBase64
llToLower
llToUpper
llInsertString
llMD5String
llStringLength
llGetSubString
llSubStringIndex
llXorBase64Strings
llDeleteSubString
llBase64ToString
String
llList2Key
llList2List
llList2ListStrided
llGetListLength
llList2CSV
llList2Float
llGetListEntryType
llList2Integer
llList2Rot
llDeleteSubList
llCSV2List
List
llListInsertList
llListRandomize
llListSort
llListFindList
llParseString2List
llList2Vector
llList2String
List
Stefano Cacciaguerra Ph.D in Computer Science 57
CommunicationCommunicationCommunicationCommunication
llSay
llShout
llWhisper
llListenRemove
llListenControl
llListen
In World
llInstantMessage
llGetNextEmail
llEmail
Messaging
Stefano Cacciaguerra Ph.D in Computer Science 58
InventoryInventoryInventoryInventory FunctionsFunctionsFunctionsFunctions
llGetInventoryName
llGetInventoryType
llGetInventoryNumber
llGetInventoryKey
llGetInventoryPermMask
llGetInventoryCreator
llAllowInventoryDrop
Inventory
llRemoveInventory
llRequestInventoryData
llRezObject
llGiveInventoryList
llRezAtRoot
llGiveInventory
llGetNotecardLine
Inventory
Stefano Cacciaguerra Ph.D in Computer Science 59
VI. Tutorial: The FortuneVI. Tutorial: The FortuneVI. Tutorial: The FortuneVI. Tutorial: The Fortune----
Telling Magic Answer BallTelling Magic Answer BallTelling Magic Answer BallTelling Magic Answer Ball
How about a bell that responds to yes or no questions
spoken on the public chat channel?
Versions:
I Picking a Random Answer
II Listening to Residents
III Cleaning up and Polishing
Stefano Cacciaguerra Ph.D in Computer Science 60
Picking a Random Answer
It contains the bare minimum functionality: generating answer.
It has a global list of answers and a function that picks a
random entry from the list and returns it, on touched event
generation
Stefano Cacciaguerra Ph.D in Computer Science 61
Provide a Random
Answer When Touched
// The global variable holding all the answers
list answers = [
// positive answers
"Yes.",
"It is certain.",
"All signs point to yes.",
"You may rely on it",
"Without a doubt.",
// negative answers
"No.",
"Absolutely not.",
"Doubtful.",
"Most assuredly not.",
"My sources say no.",
//non commital answers
"Outlook hazy.",
"Uncertain.",
"The answer is unknowable.",
"I'd better not tell you now.",
"Cannot predict that at this time."
];
Stefano Cacciaguerra Ph.D in Computer Science 62
Provide a Random
Answer When Touched
// pick a random answer from the list of answers and return it
string generateAnswer()
{
// generate a random number between 0 and the length of the
// list (but not exactly the length of the list), then cast it
// to an integer. This will give us a random number betwen 0
// and the length of the list - 1.
integer answerIndex = (integer)llFrand(llGetListLength(answers));
// return the answerIndex'th item of the list answers
return llList2String(answers, answerIndex);
}
Stefano Cacciaguerra Ph.D in Computer Science 63
Provide a Random
Answer When Touched
default
{
touch_start(integer total_number)
{
llOwnerSay(generateAnswer());
}
}
Stefano Cacciaguerra Ph.D in Computer Science 64
Listening to Residents
It listens for messages on the public channel and generates
answers in response.
In the state_entry event, the script calls the built-in function
llListen and asks for a listen event to be raised whenever
there is a message spoken on channel 0.
In the listen event, the script uses the name parameter to
personalize its response.
Stefano Cacciaguerra Ph.D in Computer Science 65
Provide a Random Personalized
Answer on the Public Channel
default
{
state_entry()
{
// listen on the public chat channel for any text from
// anyone or anything.
llListen(0, "", NULL_KEY, "");
}
listen(integer channel, string name, key id, string message)
{
// script heard something, answer
llSay(0, generateAnswer() + name);
}
}
Stefano Cacciaguerra Ph.D in Computer Science 66
Cleaning up and Polishing
It adds two new global variables, a question prefix, and some
helpful instructions.
Two new functions:
• isQuestion � which will return true if it’s argument is a question directed at the script
• startsWith � a utility function that takes two arguments and return true if the first argument starts with the second.
• In this code we add a new touch_start event handler that displays the help text when the object is touched.
Stefano Cacciaguerra Ph.D in Computer Science 67
Provide a Random Personalized
Answer on the Public Channel
// Script will only answer qestions prefixed by this string
string questionPrefix = "Magic Ball, ";
// provide these instructions with touched
// script will add the questionPrefix string to this string
string instructions = "Ask me a yes or no question starting with ";
// The global variable holding all the answers
list answers = [
…
];
Stefano Cacciaguerra Ph.D in Computer Science 68
Provide a Random Personalized
Answer on the Public Channel
// return TRUE if str starts with prefix.
integer startsWith(string str, string prefix)
{
// get the substring of the string, from 0 to the length
// of the prefix, and compare this substring to prefix
return llGetSubString(str, 0, llStringLength(prefix) - 1) == prefix;
}
Stefano Cacciaguerra Ph.D in Computer Science 69
Provide a Random Personalized
Answer on the Public Channel
// Return TRUE if candidate is a question, which is to say, if
// the candidate begins with the question prefix. This function
// is case-insensitive (it ignores differences between upper and
// lower case in the candidate and prefix)
integer isAQuestion(string candidate)
{
return startsWith(llToUpper(candidate), llToUpper(questionPrefix));
}
Stefano Cacciaguerra Ph.D in Computer Science 70
Provide a Random Personalized
Answer on the Public Channel
default
{
state_entry()
{
// listen on the public chat channel for any text
// from anyone or anything.
llListen(0, "", NULL_KEY, "");
}
touch_start(integer total_number)
{
// provide instructions
llSay(0, instructions + "\"" + questionPrefix + "\"");
}
…
Stefano Cacciaguerra Ph.D in Computer Science 71
Provide a Random Personalized
Answer on the Public Channel
…
listen(integer channel, string name, key id, string message)
{
// script heard something, if it's a question for
// this script, answer it.
if (isAQuestion(message))
{
llSay(0, generateAnswer() + name);
}
}
}
Stefano Cacciaguerra Ph.D in Computer Science 72
Webgrafia
Linden Script Language Tutorial (2007).
http://xahlee.org/sl/ls.html
The Second Life LSL Portal (2008).http://wiki.secondlife.com/wiki/LSL_Portal
Kan-ed – Using the Linden Script language (2005)
http://www.kan-ed.org/second-life/using-LSL.html
Linden Scripting Language Guide (2008)
Help Dialog in SL Client: Scripting Language
Stefano Cacciaguerra Ph.D in Computer Science 73
Bibliografia
“Creating your world:
the official guide to advanced content creation for Second Life”
By A. Weber, K. Rufer-Bach and R. Platel, Wiley editor
top related