Hacks
Hacks are usually undocumented features, surprising unexpected consequences, or unintended uses of features of
LSL and
Second Life. Given the crazy-glue-and-duct-tape nature of hacks, there is no guarantee that a hack that works today will work tomorrow, or will work in exactly the same way.
This page is not a guide to hacking the
client, an act which is against the TOS.
Agent Key Determination
With
sensor,
collision, and
touch events, the
object type being dealt with can be detected with
llDetectedType. This is not so with
listen events. To determine whether the
key returned by a listen is an
agent or not, you can check the agent's size. Objects return ZERO_VECTOR, agents return their size.
Example
Example
default
{
state_entry()
{
llListen(0,"",NULL_KEY,"");
}
listen(integer channel, string name, key id, string msg)
{
if(isAgent(id))
{
llSetColor(<0,1,0>,ALL_SIDES); //Prim turns green if an Agent speaks
} else
{
llSetColor(<1,0,0>,ALL_SIDES); //Prim turns red if a scripted object speaks
}
}
}
Very useful in an intercom system, so you don't relay spammy vendor ads too!
Note: this will not work across sim borders as llGetAgentSize only works on keys of agents in the current sim. Using llGetOwnerKey on a key not in the simulator will return the key passed to it. If you use it to check if a key is an agent it will falsely identify invalid keys (if using it on a key returned from a listen and the chat originated from a neighboring sim, the key will be invalid). -
BW
Short-Distance (In-Sim) faked "Teleportation"
If using a large
offset vector with
llSitTarget, and then
llUnSit when detecting the
changed event, an effective short-range (up to 300m as of 1.3.0)
teleporter can be made that works when a
resident chooses to "
Sit" on the object. (Note that this is not the same as actually
teleporting; it just looks that way to the user.)
2-String Linked Message Transmission
Because a key is really just a fancy
string, a second string can be substituted instead of the key and
llMessageLinked can send it without
typecasting.
However, because there's no limit to the length a string can be, it's primarily useful as a way to organize data by reducing the amount of work the recieving script must do to parse input. Also, having two strings already seperated is marginally more efficient then having one string and later parsing it into two.
Note: as keys cannot be directly typecast to or from
floats,
integers,
rotations, or
vectors, if the intended second message is one of these types, first
cast it to a string, then to the type of choice. The inverse is true when recieving the message.
Example
Permanent Small-Memory Information Storage
Besides using a script's
memory as permanent storage (and just never
resetting it), a script can store short strings in the
object name (using
llSetObjectName/
llGetObjectName) and description (
llSetObjectDesc/
llGetObjectDesc) of each prim. If the object is not going to change it's name, use
child prims in a
link set for that. Floats can also be stored in other object properties such as texture rotation,
offset,
alpha,
scale, etc. Basically anything that has a get/set combination. To store integers, you can simply convert them to floats and back by scaling them down to fit into the usual 0 - 1.0 range.
llSetTexture can also store strings using the typecast (but the object will always have to have full
permissions to read back the data), as well as
llSetAlpha for floats,
llSetColor for vectors. Combined, a lot of information can be stored permanently.
Note: The
llSetTexture hack no longer works attempting to specify a texture that is not a valid texture key or not the name of a texture in the objects inventory will return an error "Couldn't find texture (your string)"
In-Function State Change
Usually, the
compiler gives an
error when the
state tries to change from within a function. There is a workaround to this though: put the state change within a
conditional statement's
brackets.
Example
changeState()
{
state foo;
}
// Doesn't compile.
changeState()
{
if(1 == 1)
{
state foo;
}
}
// Compiles.
See
this page for more details.
llSetPos > 10m per call
llSetPrimitiveParams executes its rules as it comes across them, so if a
list has multiple
PRIM_POSITIONs in it, each one will be executed. This allows the 10m limit on
llSetPos to be avoided.
See
WarpPos for more details and
code.
Please note WarpPos no longer appears to work in havok4 sims. (In havok4 sims you see the seperate jumps, but less delay then llSetPos). -
Christophe003Carter
Detect Which Grid Script is running on
If you use an external system to keep track of sales on your vendor, you don't want People on Beta Grid messing up your tidy book keeping, by simply buying something from you. Here is a simple but slow routine to identify which Grid a script is running on (if you know a faster way than llGetSimulatorHostname, please correct me)
Example
integer idGrid()
{
list Grids = ["agni","teen","dmz","colo","siva","durga","aditi"];
string server = llGetSimulatorHostname();
list serverParsed = llParseString2List(server,["."],[]);
string grid = llList2String(serverParsed, llGetListLength(serverParsed) - 3);
return llListFindList(Grids, [grid]);
}
Example
default
{
//Update by Bobbyb30 Zohari to llOwnerSay v. llSay
touch_start(integer total_number)
{
integer grid = idGrid();
if(grid == 0)
llOwnerSay("You are on the Main Grid.");
else if(grid == 1)
llOwnerSay("You are on the Teen Grid.");
else if(grid == 2)
llOwnerSay("You are on the Linden Only Grid.");
else if(grid >= 3)
llOwnerSay("You are on the Beta Grid.");
else
llOwnerSay("I don't recognize this grid!");
}
}
Local Application Launching via llLoadURL
llLoadURL functionality can be altered to allow for user initiated interactions between the
SecondLife Client and applications running on the same computer workstation.
On Windows machines, the HKEY_CLASSES_ROOT\HTTP\shell\open\command can be modified to a batch or command line processing application, resulting in
llLoadURL calls executing the specified application. This has the unfortunate side effect of breaking any other standard uses of
llLoadURL in world.
Alternatively, changes could be made to a machines host file or the machine's local IP address could be specified in a URL and a webserver run on the local machine.
Discussion of usage:
http://forums.secondlife.com/showthread.php?t=110251
Making lslwiki.net the default WikiHelp in the SL LSL Editor
If you prefer to use
this wiki as your reference when writing LSL script inworld, you can change the SL client's
LSL Wiki Help menu option (on the Help menu in the LSL Editor) to link here instead of the default LSL Portal:
1) If you cannot see the "Advanced" menu option (or "Client" and "Server" for older versions) on the Menu Bar of your SL client program, you need to turn on DEBUG mode:
Press: CTRL-ALT-D (or CTRL-ALT-SHIFT-D on some systems)
This will toggle these hidden menu options on and off.
2) From the Advanced (or Client) menu, select "Debug Settings"
3) A small window will open, use the dropdown menu, or type it in, to find the key: LSLHelpURL
4) Change the value to: http://www.lslwiki.net/lslwiki/wakka.php?wakka=[LSL_STRING]
You can change it back any time by repeating steps 1-3, and selecting "Reset to default"
str_replace Workaround
Since there's no nifty way to simply have all instances of a substring replaced at once, you can use
llParseStringKeepNulls (to avoid losing replaced character on the end of a string) and
llDumpList2String to do it for you. The method looks like this:
Example
str_replace("@","_","Hello@world! The@method@is@working@properly.");
// Returns: Hello_world! The_method_is_working_properly.
Rotating an object you're sat on without affecting Mouselook
A very useful trick if you are trying to make a sittable object which rotates according to the user's Mouselook camera rotation; this works both for physical and non-physical objects. Put those 2 calls in the
state_entry of a script within the object that is sat upon:
-
AgentRevolution
LSL Style Guide |
Lag