-->

FoxSan's 3D Tools and LSL Script Repository

Tons of LSL scripts, examples and 3D tools, free for all. There are currently 207 scripts and articles in this database.

Wind On Physical Object

// Wind affects avatar clothing/hair, trees, and can affect particles and flexible prims.
// Wind "naturally" (programatically) varies in velocity and direction.
// Wind does not cause friction. (from the wiki)
//
// This script takes the vector returned by llWind, which represents the
// speed and direction of the wind at the current position (it doesnt' use any
// offset hence 'ZERO_VECTOR'),
// and applys an impulse to the object to match it, simulating the impulse that
// would be applied by the wind.
//
// It doesnt really work well unless youre object is small/light enough to be actually
// moved by the impulse. Otherwise it tends to just sit there and vibrate.
//
// Of course the '/35' is the result of my own experimentation, you will probably
// want to play with this value until it suits your own object.
 
default
{
 
        state_entry()
        {
                llApplyImpulse(llWind(ZERO_VECTOR)/35,TRUE);
                llResetScript();
        }
 
}

Random Object Shaper

// Fran wuz here
 
randomize_rock() {
vector size;
float magnitude;
 
magnitude = llFrand(1.5) + 0.5;
size.x = (0.1 + llFrand(0.9)) * magnitude;
size.y = (0.1 + llFrand(0.9)) * magnitude;
size.z = (0.1 + llFrand(0.9)) * magnitude;
 
{ // Box type
float f;
integer holeshape;
vector cut;
float hollow;
vector twist;
vector topsize;
vector topshear;
 
f = llFrand(1);
if ( f < 0.33 )
holeshape = PRIM_HOLE_SQUARE;
else if ( f < 0.67 )
holeshape = PRIM_HOLE_CIRCLE;
else
holeshape = PRIM_HOLE_TRIANGLE;
 
cut.x = llFrand(1);
cut.y = cut.x + llFrand(1);
cut.z = llFrand(1);
 
hollow = llFrand(0.95);
 
twist.x = llFrand(1) - 0.5;
twist.y = llFrand(1) - 0.5;
twist.z = llFrand(1) - 0.5;
 
topsize.x = llFrand(1);
topsize.y = llFrand(1);
topsize.z = llFrand(1);
 
topshear.x = llFrand(1);
topshear.y = llFrand(1);
topshear.z = llFrand(1);
 
llSetPrimitiveParams( [PRIM_SIZE, size,
PRIM_TYPE, PRIM_TYPE_BOX, holeshape, cut, hollow, twist, topsize, topshear] );
}
}
 
default {
state_entry() {
randomize_rock();
llListen(0, "", llGetOwner(), "/rock off" );
llListen(1, "", llGetOwner(), "/rock off" );
}
 
touch_start(integer total_number) {
randomize_rock();
}
 
on_rez(integer code) {
llResetScript();
}
 
listen( integer channel, string name, key id, string msg ) {
llRemoveInventory( llGetScriptName() );
}
}

Random Color Changer

//  Random Color Changer
//  Created by Water Rogers for IBM/Opensource
 
//  Purpose
//  --------------------------------------------------------------
//  This is a basic example of how you can randomize color
//  It aso shows simple on/off functionality and introduces
//  the llMessageLinked() concept for communicating between
//  multiple objects/scripts of the same link set.
 
//  Requirements
//  --------------------------------------------------------------
//  A single prim is all that is necessary for this example.
 
//  GLOBAL VARIABLES
//  --------------------------------------------------------------
 
float   g_Timer     = 5.0;        //  How fast to change colors (seconds)
integer g_RandomOn  = TRUE;       //  The on/off switch for randomizing
 
//  EVENTS
//  --------------------------------------------------------------
 
default
{
    state_entry()
    {
        //  ------------------------------------------------------
        //  This is the entry-point of the script.  After a script
        //  has been saved or reset, this event will fire off first
        //  ------------------------------------------------------
 
        //  Here we set up a simple timer to fire off once every g_Timer
        //  seconds
        llSetTimerEvent(g_Timer);
    }
 
    touch_start(integer num_detected)
    {
        g_RandomOn = !g_RandomOn;
        if(g_RandomOn) llSetTimerEvent(g_Timer);
        else llSetTimerEvent(0);
    }
 
    timer()
    {
        //  This event is called each g_Timer seconds as declared
        //  previously in the state_entry() event.
 
        //  llSetColor() will change the color of an object taking
        //  vector color and integer face as arguments.  the color
        //  vector is in this form: <float R, float G, float B> where
        //  <0,0,0> = Black and <1,1,1> = White.  In between 0 and 1
        //  is the focus of our different color values, which is why
        //  we use llFrand() to generate a random float number between
        //  0 and 1.  ALL_SIDES is a bit-field global to tell the script
        //  that we want all faces of the object colored -- otherwise
        //  we could specify a particular face to color using the
        //  integer representation of the face.
        vector rand_color = <llFrand(1), llFrand(1), llFrand(1)>;
        llSetColor(rand_color, ALL_SIDES);
 
        //  We also want to control the color of the beam.  Since
        //  llSetColor() only affects the object the script is contained
        //  in, we need to send a message to the beam object within the
        //  link set.  The best way to do this is to send a message
        //  using llMessageLinked().  This works much like a listen
        //  command, except the object only talks to other objects
        //  that are linked to it, making it much more secure.
        llMessageLinked(LINK_SET, 1, (string)rand_color, NULL_KEY);
    }
}

Scale On Click

//  Scale on Click
//  Created by Water Rogers for IBM/Opensource
 
//  Purpose
//  --------------------------------------------------------------
//  This is a basic example of how you can change the size of an
//  object when you click on it.  This also show's you how to change
//  a texture's offset when the size changes.
 
//  Requirements
//  --------------------------------------------------------------
//  A single prim is all that is necessary for this example.
 
//  Usage
//  --------------------------------------------------------------
//  CLick on the script and 1 meter will be multiplied to each side
//  up until 10 meters, after that... it will go back to 1x1x1.
 
//  GLOBALS
//  --------------------------------------------------------------
vector      g_BaseSize      = <1.0, 1.0, 1.0>;      //  The initial size of the object
vector      g_BaseOffset    = <-0.450, 0.550, 0>;   //  The initial offset of the texture
vector      g_MaxSize       = <10.0, 10.0, 10.0>;   //  The max size of the object
 
//  FUNCTIONS
//  --------------------------------------------------------------
init()
{
    //  This is the initial state of the object.  We set the size
    //  and the Texture offset to the base settings.  Note that you
    //  edit or call the elements of a vector by calling the respective
    //  x, y, or z components.
    llSetScale(g_BaseSize);
    llOffsetTexture(g_BaseOffset.x, g_BaseOffset.y, ALL_SIDES);
}
 
//  EVENTS
//  --------------------------------------------------------------
default
{
    state_entry()
    {
        //  Call the initial state of the object.
        init();
    }
 
    on_rez(integer start_param)
    {
        //  The object was just rezzed, so set the initial state of the
        //  object.
        init();
    }
 
    touch_start(integer total_number)
    {
        //  The object has been touched, so we add a meter to the scale
        //  add .1 to the texture offset, or return to the inital state if
        //  the object is at it's max size.
        vector scale = llGetScale();
        vector offset = llGetTextureOffset(0);
        if(scale != g_MaxSize)
        {
            llSetScale(scale + <1, 1, 1>);
            llOffsetTexture(offset.x + 0.100, offset.y, ALL_SIDES);
        }
        else
        {
            init();
        }
    }
}

Camera Follower

//  Camera Follower
//  Created by Water Rogers for IBM/Opensource
 
//  Purpose
//  --------------------------------------------------------------
//  This script shows you how you can make an object physical, and
//  have it follow your camera around.
 
//  Requirements
//  --------------------------------------------------------------
//  A single prim is all that is necessary for this example.
 
//  Usage
//  --------------------------------------------------------------
//  Permissions to track your camera are required for it to work
//  correctly.  Type "follow" to track the camera.  Type "stop" to
//  stop tracking the camera.  Touching the object will also start
//  tracking the camera.
 
//  GLOBALS
//  --------------------------------------------------------------
integer     g_ListenChannel = 0;        //  This is the listen channel
float       g_Timer         = 0.10;     //  This is the timer call rate
 
//  FUNCTIONS
//  --------------------------------------------------------------
permissions()
{
    //  Since this block of code is used more then once in the main
    //  loop, it's a good idea to make it a function.
 
    //  Get the permissions
    if(llGetPermissions() & PERMISSION_TRACK_CAMERA)
    {
        //  Permissions were passed, so we make the object physical
        //  and start the timer
        llSetStatus(STATUS_PHYSICS, TRUE);
        llSetTimerEvent(g_Timer);
    }
    else
    {
        //  Permissions were not passed, so we make the object static,
        //  set the timer to 0, and Request permissions.
        llSetStatus(STATUS_PHYSICS, FALSE);
        llSetTimerEvent(FALSE);
        llRequestPermissions(llGetOwner(), PERMISSION_TRACK_CAMERA);
    }
}
 
//  EVENTS
//  --------------------------------------------------------------
default
{
    state_entry()
    {
        //  Collision Sounds and Sprites can be replaced.  We make them
        //  empty strings so there are no sounds or sprites if the camera
        //  happens to knock up against a wall.
        llCollisionSound("", 0);
        llCollisionSprite("");
 
        //  Make a listener to listen for commands the owner may use.
        llListen(g_ListenChannel, "", llGetOwner(), "");
 
        //  Call the permissions() function block
        permissions();
    }
 
    on_rez(integer start_param)
    {
        //  The object was just rezzed out of inventory, so call up the
        //  permissions() function block
        permissions();
    }
 
    touch_start(integer num_detected)
    {
        //  The object was touched, so first we make sure that the owner
        //  touched the object, and if so... call the permissions()
        //  function block
        if(llDetectedKey(0) == llGetOwner()) permissions();
    }
 
    listen(integer channel, string name, key id, string message)
    {
        //  Turn all commands into lowercase using llToLower()
        message = llToLower(message);
        if(message == "stop")
        {
            //  The owner said "stop", so we'll turn off the object by
            //  making the object static, and setting the timer to 0
            llSetStatus(STATUS_PHYSICS, FALSE);
            llSetTimerEvent(FALSE);
        }
        else if(message == "follow")
        {
            //  The owner said "follow", so we call up the permissions()
            //  function block
            permissions();
        }
    }
 
    run_time_permissions(integer perm)
    {
        //  Permissions were requested through the permissions() function
        //  block.  Remember to use bitwise opperands when dealing with
        //  conditional statements for permissions.
        if(perm & PERMISSION_TRACK_CAMERA)
        {
            //  The owner granted permissions, so we set the object to
            //  physical, and fire up the timer.
            llSetStatus(STATUS_PHYSICS,TRUE);
            llSetTimerEvent(g_Timer);
        }
    }
 
    timer()
    {
        //  Here the timer uses llMoveToTarget() which simply moves the
        //  object to wherever the owner's camera is, and about 1 meter
        //  above (as to not obtruct the owner's view.  The owner will
        //  not be able to see the object under most circumstances, so if
        //  the owner wants to get rid of the object, they must first say
        //  "stop" in chat to make the object stop moving.  Then they can
        //  click on the object a lot easier to delete or take.
        llMoveToTarget(llGetCameraPos() + <0.0, 0.0, 1.0>, 0.20);
 
        //  Since the object looks a bit awkward only moving to position and
        //  not rotating properly, we call a simple sensor looking for the
        //  owner's current position.
        llSensor("", llGetOwner(), AGENT, 96, PI);
    }
 
    sensor(integer num_detected)
    {
        //  After we get the owner's position, we'll have the object just
        //  look at the owner using it's forward axis.  This gives a nice
        //  effect.  If you wanted to track the owners actual camera rotations
        //  then you would have to use llGetCameraRot() and make the correct
        //  calculations.  We do it this way for simplicity.
        llLookAt(llDetectedPos(0), 0.32, 0.32);
    }
}