User:Susicat Oh
Background:
Name: Susicat Oh
Born: June 07
Time in SL 5 years in 2012
Aim of this page is to provide simple plain English explanations of LSL commands and functions with examples where I can.
Trip ups, idiosyncrasies and foibles.
Some sections may appear poorly worded, may have typos and or poor grammar. This should be considered "work in progress" if on the other hand you feel an over riding need to correct my work please do. Thank you.
NULL_KEY
An undefined key may not be held as 00000000.. undefined keys as variables are held as empty NOT 000000... as such if you need to test for NULL_KEY be sure to set the variable to NULL_KEY as required.
PRIM_POSITION
<lsl>llSetPrimitiveParams([PRIM_POSITION, dest]);</lsl>
This needs to be in the root prim or will fail. In a child prim not only does it fail it can throw "stack heap collision"
Sensors
sensor returns at most the 16 closest detected "items" in order of closest to farthest, sensor( integer num)
num is 1 to 16. this function will NEVER return a zero!! if you need to test for zero use no_sensor as a zero scan will not trigger a sensor event..
Also note llSensorRemove() not only shuts down the active sensor set up with llSensorRepeat BUT will ALSO kill the sensor found data.
as such
<lsl>sensor(integer num_detected) { llSensorRemove(); }</lsl>
is futile as the senor data will get wiped. <lsl>sensor(integer num_detected) { //code functions what ever your trying to do etc. //.... //... //followed by llSensorRemove(); }</lsl> will work fine.
Also note if your using a single sweep one-off type scan look at llSensor. Using llSensorRepeat() then shutting it off immediately is a waste of byte code.
Lists, Vectors and Rotations
llList2Vector and llList2Rot do work as documented (or have been fixed) the problem with them stems from the fact that sometimes numerical data passed between scripts is usually passed as strings the receiving script accepts the string, you then add it to a list. The data then sits in the list as a STRING!! not a numeric value. if you llDumpList2string you will see something with looks like a numerical value, feels like a numerical value BUT its a string!! You need to be on your toes all the time when transferring data types and remember to typecast correctly.
llSetPos
llSetPos does not work in attached prims Linden are aware of this and are fixing it
Key2Name
llKey2Name avatar MUST be online AND in the sim or a child avatar of the sim, or a NULL_KEY is returned. use llRequestAgentData and dataserver to get round this.
- child avatar is defined as avatar on a neighboring sim which can be seen from the sim the script is in (less than 35M from sim boundary).
llKey2Name is now only legacy (as of Dec 2010). Use llGetUsername( key id )
instead..
Also be aware of llGetDisplayName( key id );
you are reminded that displaynames are not unique and easily changed, using them in ANY security script is a really bad plan!! Use llGetUsername(id)
or do it with avatar keys!!
I would suggest using llRequestDisplayName(id)
it will raise a dataserver event but gets round the issue of avatar not in sim.
Newer people in SL will have the second name "Resident"
Creators
This one does actually work as documented BUT you need to be clear what it returns.
<lsl>key llGetCreator(); //returns the creator of the prim! NOT the script! key llGetInventoryCreator(string <inventory name>); //returns the creator of inventory item ie script author or texture creator etc.. </lsl>
change & CHANGED_INVENTORY
changed & CHANGED_INVENTORY does not trigger for llAllowInventoryDrop or llRemoveInventory documented elsewhere on wiki
CHANGED_INVENTORY will work when the prim owner edits the prim manually (adding a texture editing a notecard)
Use CHANGED_ALLOWED_DROP instead which will trigger when inventory is added via llAllowInventoryDrop
the llRemoveInventory issue has been acknowledged by Linden who are "working on it"
On the subject of llAllowInventoryDrop it allows any one to add anything (except scripts) to the prim. Its up to you to figure out the validity of who dropped what.
DATA_ONLINE
DATA_ONLINE returns binary integer TRUE/FALSE BUT!! the dataserver event can only accept strings as such dataserver(key queryid, string data) data will be a "1" (online) or "0"(offline) as a string. attempting to use dataserver(key queryid, integer data) will force a syntax error when you try to compile.
Semicolon
Adding a semi colon to if
statements as if( a == B);
will cause the test to return TRUE every time handy for debugging but may have you scratching your head for hours.
on the subject of ; in the wrong place...
<lsl>while (a < b);</lsl>
with a semi-colon will stall the script. It will compile it will not error the script will just sulk!
llGiveMoney
llGiveMoney(key,amount);
key MUST be an avatar and amount MUST be an integer greater than zero passing a float or a zero will error.
side note for give money profit split
integer to float and division
<lsl>integer a = whatever; integer b = whatever; float c = a/b;</lsl>
May yield c = zero due to internal integer rounding in LSL which will cause llGiveMoney to throw invalid amount error.
use <lsl>float a = money_amount; float b = percent_split; integer given = llRound((money_amount/100) * percent_split); llGiveMoney(id,given);</lsl>
OR
<lsl>integer a = whatever; integer b = whatever; float c = a/(float)b;</lsl>
I have tripped up on this more than once!
Lists
List length limit at compile is 72 elements BUT once compiled lists can be added together
list huge = list1 + list2; will work fine
The only real limit is script memory.
For those of you trying to read notecard lines into lists be aware of the line length limit for a script reading a notecard line is 255 characters. see llGetNotecardLine
llDialog
The problem is that the client font is proportionally spaced not fixed with font soo this is best guess guide.
Question text is circa 35 characters per line Its ok to use \n and \t for new line and tab At more than 8 lines you get a scroll bar.
Whatever you do question text MUST be greater than none and LESS than 512 characters.
Button labels MUST be strings. Cannot be empty or NULL sting (spaces are permitted).
Cannot exceed 24 characters.
Long button labels will be truncated in the display to circa 12 characters (remember its proportional spacing) in practice aim for max 10 chrs. Similar button labels which get truncated will look the same in the display avoid "sitting here pose 1","sitting here pose 2" as truncation will show them as the same, the script knows they are different and will work correctly but the human user will not see a difference.
llMessageLinked
This will appear to stall or not work if messages are sent to quickly you need to allow the processing time of the receiving script. slow things down with llSleep(x) in practice 0.1 is normally enough.
llParticleSystem
llParticleSystem the list option PSYS_SRC_TARGET_KEY, NULL_KEY
will compile but crashes the script.. Use PSYS_SRC_TARGET_KEY,(key)""
as a work round. Or PSYS_SRC_TARGET_KEY, (key)NULL_KEY
Didn't they fix this in SVC-185?
Money
money event is not capable of telling if a "correct amount" was paid it will return amount and the payers key but thats it.. its up to you to test amount
<lsl>if(amount paid == price) { deliver item }</lsl>
The money event can be in any prim and will work as "pay this prim" just fine BUT llSetPayPrice(integer,[list]); for the pay dialog box MUST be in the root prim. If llSetPayPrice is in a child prim it will fail silently. Its ok to have it in the root as all money events in the object will be updated automatically.
it is NOT possible to pay a worn attachment.
llSetPayPrice(integer,list) is worth a closer look
You would reasonably expect llSetPayPrice(llList2Integer(price,0),price);
To work would'nt you?
Yep its type casting again!! The problem is the list MUST contain integers. If pay button amounts are read from a notecard .. (as
is my habbit) they will load up as strings and need to be converted.
<lsl>integer a = 0; while (a < llGetListLength(price)) {
price = llListReplaceList(price,[llList2Integer(price,a)],a,a); a++;
} llSetPayPrice(llList2Integer(price,0),price);</lsl> Will work just fine.
HOT TIP!! If your button value list contains a -1 LSL will interpret it as a PAY_HIDE
Events
There is a 64 event limit on any given state. Events are processed on a strict first in first out order (FIFO) The only thing that can jump the queue is state_entry
The event queue is 64 events after that events are discarded until there is free space in the queue. That's why if you are sending batches of LinkMessage( some of them get lost or never arrive.
Side note: The word "event" is an LSL keyword and will syntax error if used.
UUIDs
keys as 36 character UUIDs can be type cast to string and back fluidly just be aware of type casting when performing key functions.
HOWEVER having been given a key there is no way of testing if its an avatar, texture, group, sound, animation or whatever. Your expected to know!!
<lsl>list tmp = llGetObjectDetails(id,[OBJECT_OWNER]);
if(llList2Key(tmp,0) == id) { key is an avatar; } if(llList2Key(tmp,0) == NULL_KEY) { key is NOT an avatar; } </lsl> thats the best I have for now
Integer rounding
When rounding the results of llFrand. <lsl>integer a = llRound(llFrand(4)); //returns values in the range 0 - 4 inc. integer a = llFloor(llFrand(4)); //0 - 3 inc. integer a = llCeil(llFrand(4)); //1 - 4 inc.</lsl>
On Rez reset fails when taken from inventory for the first time
Never got to the bottom of this as reseting scripts manually in world or shift drag copying clears the fault. Current thinking is that you use CHANGED_OWNER reset and may be a permission request like permission money.
What may be happening is you are setting up next owner permissions which triggers your CHANGED_INVENTORY reset then in your haste you take back to inventory without granting the money permission. As a result the object sits in inventory without money permission being granted and just hangs in limbo. It has asked for money permission once and cannot ask again without a reset, the section of code that does the resetting cannot be executed as permission has not been granted thus preventing the script advancing through to the code to get to the reset routines.
Solutions
- Add an on-rez reset to the same state (usually default) as the money request.
- Always remember to set it up correctly before taking to inventory.
- Test rez the item to be sure it does initialize correctly.
- Slap your self for being stupid.
- All of the above.
PRIM_SLICE
May 2012 the long overdue PRIM_SLICE parameter was introduced. I was hoping to have it incorporated into the the PRIM_TYPE list of parameters. Please be aware its a stand alone function. It is still in the llGetPrimitiveParams llSetPrimitiveParams category but is not part of PRIM_TYPE parameter list.
llDie
Be aware be warned llDie will remove the prim and its contents from the grid!
It does not go to trash.
It does not go to lost and found
It does not return to inventory
it has ceased to be
it has curled up its toes and shuffled off this mortal coil
it is an ex-prim!
Not even Linden can get it back for you. Its gone!!
Now all that said, and the reason for this section... llDie will silently fail in a worn attachment. All you can do in a script to permanently disable a worn scripted prim is use llRemoveInventory
Reading a notecard
Most of us have seen or indeed created scripts that read notecards. Did you realise there is no need to have the notecard saved in the prim? Its a little quirky with a boatload of caveats but does work.
It works like this... instead of naming your notecard as in llGetNotecardLine("config", lineval);
use llGetNotecardLine("asset UUID of the notecard", lineval);
Caveats
- Editing the notecard changes the UUID even while in inventory editing will reassign a new UUID.
- while this will not directly break the reading script the reading script will read the old/unedited card.
- The notecard does not have to be in world (in a prim), it can be read from your inventory.
- Copying the notecard will not change the UUID.
- Renaming does not change the UUID.
- Multiple copies of the same notecard is ok, the reading script will only read it once.
- Once created the UUID is good even if you delete it.
- Works grid wide.
And yes I do have a product that reads a notecard of settings that will never be changed.