Difference between revisions of "User:Kimm Paulino/Scripts1"

From Second Life Wiki
Jump to navigation Jump to search
m
 
(3 intermediate revisions by the same user not shown)
Line 1: Line 1:
== Rez and Sense ==
== Rez and Sense ==


<lsl>
<syntaxhighlight lang="lsl2">
// Rezzer that will only rez an object (from inventory) if it
// Rezzer that will only rez an object (from inventory) if it
// can't detect the specified number of objects in the region nearby already.
// can't detect the specified number of objects in the region nearby already.
Line 77: Line 77:
     }
     }
}
}
</lsl>
</syntaxhighlight>


== Derez After Sitting ==
== Derez After Sitting ==


<lsl>
<syntaxhighlight lang="lsl2">
// This will kill the prim it is in, the specified time after someone
// This will kill the prim it is in, the specified time after someone
// sits on the prim.  It will unsit them before derezzing.
// sits on the prim.  It will unsit them before derezzing.
Line 186: Line 186:
     }
     }
}
}
</lsl>
</syntaxhighlight>


== Timer Action Template ==
== Timer Action Template ==


<lsl>
<syntaxhighlight lang="lsl2">
// Basic timer-driven state changing script.
// Basic timer-driven state changing script.
// NB: Does not use the LSL ability to define
// NB: Does not use the LSL ability to define
Line 255: Line 255:
     }
     }
}
}
</lsl>
</syntaxhighlight>


== Multiple Notecard Reading Template ==
== Multiple Notecard Reading Template ==


<lsl>
<syntaxhighlight lang="lsl2">
// Example showing multiple notecard reading.
// Example showing multiple notecard reading.
//
//
Line 336: Line 336:
     }
     }
}
}
</lsl>
</syntaxhighlight>


== Alarm Script ==
== Alarm Script ==


<lsl>
<syntaxhighlight lang="lsl2">
// Simple script to trigger at a certain time and perform a function,
// Simple script to trigger at a certain time and perform a function,
// in the default case send an IM to the specified avatar
// in the default case send an IM to the specified avatar
Line 445: Line 445:
     }
     }
}
}
</lsl>
</syntaxhighlight>


== Simple Channel Relay ==
== Simple Channel Relay ==


<lsl>
<syntaxhighlight lang="lsl2">
// Simple relay script.  Listens on one channel and relays
// Simple relay script.  Listens on one channel and relays
// everything to the another channel.
// everything to the another channel.
Line 496: Line 496:
     }
     }
}
}
</lsl>
</syntaxhighlight>


== HTTP Server and Client Example ==
== HTTP Server and Client Example ==
Line 502: Line 502:
These two scripts can be used (once you've hard-coded in the right URL into the client script) to highlight basic prim to prim communications using HTTP without requiring an external server.
These two scripts can be used (once you've hard-coded in the right URL into the client script) to highlight basic prim to prim communications using HTTP without requiring an external server.


<lsl>
<syntaxhighlight lang="lsl2">
// Very, very simple HTTP server test script, as seen on
// Very, very simple HTTP server test script, as seen on
// http://wiki.secondlife.com/wiki/LSL_http_server/examples
// http://wiki.secondlife.com/wiki/LSL_http_server/examples
Line 540: Line 540:
     }
     }
}
}
</lsl>
</syntaxhighlight>


<lsl>
<syntaxhighlight lang="lsl2">
// HTTP Test.  This will request the contents of the specified
// HTTP Test.  This will request the contents of the specified
// URL.  The idea is that the URL is provided by a companion object
// URL.  The idea is that the URL is provided by a companion object
Line 567: Line 567:
     }
     }
}
}
</lsl>
</syntaxhighlight>
 
== HTTP POST Client and Server Example ==
 
This is similar to the above pair of scripts, but uses HTTP POST to send a message from the client to the server.  The message is entered using a text box.  It also uses the text box to enter in the server's URL when it first starts up.
 
<syntaxhighlight lang="lsl2">
// Very, very simple HTTP server test script, as seen on
// http://wiki.secondlife.com/wiki/LSL_http_server/examples
//
// but configured to accept and display what gets sent to
// it via a POST request.
//
// Note: It gets a new public URL each time it runs or
// when the object moves Sims ...
//
// So, you'll need to update the URL used by any client objects,
// or use some kind of dynamic URL service - there are some around
// on the Internet - search/read about HTTP-in.
//
// Also, as this is a demo script, it doesn't do things like clean
// up URLs and so on - see the wikis for details.
//
// Kimm Paulino, Nov 2012
 
default
{
    on_rez (integer start_param)
    {
        llResetScript();
    }
   
    state_entry()
    {
        llRequestURL();
    }
    http_request(key id, string method, string body)
    {
        if (method == URL_REQUEST_GRANTED)
        {
            llOwnerSay("URL: " + body);
        }
        else if (method == "GET")
        {
            llOwnerSay ("Handling Response ...");
            llHTTPResponse(id,200,"Post me something and I'll display it ...");
        }
        else if (method == "POST")
        {
            llOwnerSay ("Received: " + body);
            llHTTPResponse (id, 200, "");
        }
    }
}
</syntaxhighlight>
 
And the client ...
 
<syntaxhighlight lang="lsl2">
// HTTP Test.  This will POST a message to the specified
// gUrl.  The idea is that the gUrl is provided by a companion object
// in SL.  Note that the gUrl created by the llHRequestgUrl call changes
// when the server object is rezzed or moves sims though ...
//
// There are some services on the Net that provide a semi-permanent
// gUrl for use with HTTP-in like this though ...
//
// The message is entered using a textbox on touch.  When the script
// first starts up, you need to paste in the URL of the server prim
// using the same text box.
//
// This is just a demo script.  You'll need to do proper listen and
// channel handling and so on.
//
// Kimm Paulino, Nov 2012
 
string gUrl = "";
integer gChannel;
 
integer randChannel ()
{
// Based on http://tali.appspot.com/html/scripting/snippets.html
// Always leaves 17th bit set (so never a number less than 65535)
// Always leaves sign bit unset (so is always positive)
integer pos_int = (((integer)llFrand(16384)) << 17) | 65536 | ((integer)llFrand(65535));
    return -pos_int;
}
 
default
{
    on_rez (integer start_param)
    {
        llResetScript();
    }
   
    state_entry ()
    {
        gChannel = randChannel();
        llListen (gChannel, "", "", "");    // Uses simplest and laggiest form of listen/channel handling
    }
 
    touch_start(integer total_number)
    {
        if (gUrl == "")
        {
            llTextBox (llDetectedKey (0), "Paste in the URL from the server prim and click submit", gChannel);
        }
        else
        {
            llTextBox (llDetectedKey (0), "Type in your message to send to the HTTP server", gChannel);
        }
    }
   
    listen (integer channel, string name, key id, string message)
    {
        if (channel != gChannel)
        {
            return;
        }
       
        if (llSubStringIndex (message, "http://") == 0)
        {
            // this is a new gUrl ...
            gUrl = message;
        }
        else if (gUrl != "")
        {
            llHTTPRequest (gUrl, [HTTP_METHOD, "POST"], message);
        }
        else
        {
            llOwnerSay ("You need to provide the URL of the server prim before sending any messages");
        }
    }
   
    http_response(key id, integer status, list meta, string body)
    {
        if (body != "")
        {
            llWhisper (PUBLIC_CHANNEL, "Response: " + (string)body);
        }
    }
}
</syntaxhighlight>
 
== Smooth, non-mesh up/down/rotate ==
 
<syntaxhighlight lang="lsl2">
// Makes an object go up and down gradually whilst slowly rotating.
// In order to make it a gradual movement, it uses a physical
// object, which means it might be a little wobbly ...
//
// The value given to the angular velocity parameter is quite critical
// depending on the mass of the object you wish to rotate. You'll need
// a larger value for larger objects otherwise they'll hardly move.
//
// Whilst this appears to work ok for small objects, it is very unpredictable
// and doesn't really work for large objects.
//
//  Kimm Paulino
//  December 2012
//
integer gState;
integer DOWN=0;
integer GO_UP=1;
integer UP=2;
integer GO_DOWN=3;
float MOVE_DAMPING=4.0;
float MOVE_TIME=4.0;
float DOWN_CORRECTION=1.5;  // Use trial-and-error to correct for SVC-2441
float TIME_PERIOD=0.2;
// Move to 2m above starting position
vector gOffset = <0.0, 0.0, 2.0>;
vector gStartPosition;
float gTimerCount;
 
// Angular Velocity Details - use values to rotate around the specified axis
// between 0.5 and around 5.0 (or even more for very large objects)
vector gAngularVelocity = <0.0, 0.0, 0.5>;  // For small objects
//vector gAngularVelocity = <0.0, 0.0, 5.0>;  // For large objects
 
default
{
    state_entry()
    {
        gTimerCount = 0.0;
 
        // Use physics so that can use MoveToTarget
        gStartPosition = llGetPos ();
        // Stop the object rotating except in Z axis
        llSetStatus(STATUS_ROTATE_X|STATUS_ROTATE_Y, FALSE);
        llSetStatus(STATUS_PHYSICS, TRUE);
        llMoveToTarget (gStartPosition, MOVE_DAMPING);
        llSetTimerEvent (TIME_PERIOD);
    }
    on_rez(integer n)
    {
        llResetScript();
    }
    timer ()
    {
        llSetAngularVelocity (gAngularVelocity, TRUE);
 
        gTimerCount += TIME_PERIOD;
        if (gTimerCount > MOVE_TIME)
        {
            gTimerCount = 0.0;
           
            if (gState == DOWN)
            {
                gState = GO_UP;
                llMoveToTarget(gStartPosition + gOffset, MOVE_DAMPING);
                gState = UP;
            }
            else if (gState == UP)
            {
                gState = GO_DOWN;
                // Need to compensate (a bit) for SVC-2441
                llMoveToTarget(gStartPosition, MOVE_DAMPING*DOWN_CORRECTION);
                gState = DOWN;
            }
        }
    }
}
</syntaxhighlight>
 
== Non-physical, non-mesh up/down/rotate ==
 
<syntaxhighlight lang="lsl2">
// Makes an object go up or down, gradually, using non-physical movement.
//
// Unfortunately, non-physical movement is jerky. If you can support it,
// a better up/down movement can be had using physics and up/down and
// rotate is better using llSetKeyframedmotion.
//
//  Kimm Paulino
//  December 2012
integer gState;
integer DOWN=0;
integer GO_UP=1;
integer UP=2;
integer GO_DOWN=3;
 
// Period for the up/down movement is MOVE_COUNT * MOVE_TIME
integer MOVE_COUNT=40;
float MOVE_TIME=0.1;
 
// Rotation value to use
vector gRotationAxis = <0.0, 0.0, 1.0>;
float    gPiDivisor = 2.0;
// The vector to add to the start position for MOVE_COUNT times
vector gOffset = <0.0, 0.0, 0.05>;
vector gStartPosition;
vector gCurrentPosition;
integer gCount;
integer gDirection;
default
{
    state_entry()
    {
        gCount = 0;
        gDirection = 1;
        gStartPosition = llGetPos ();
        gCurrentPosition = gStartPosition;
       
        // Start the rotation
        llTargetOmega (gRotationAxis, PI/gPiDivisor, 1.0);
        // Stop the object rotating
        llSetTimerEvent (MOVE_TIME);
    }
    on_rez(integer n)
    {
        llResetScript();
    }
    timer ()
    {
        gCount++;
        if (gCount > MOVE_COUNT)
        {
            gCount = 0;
            gDirection = -gDirection;
           
            if (gState == DOWN)
            {
                gState = GO_UP;
                gState = UP;
            }
            else if (gState == UP)
            {
                gState = GO_DOWN;
                gState = DOWN;
            }
        }
       
        gCurrentPosition = gCurrentPosition + (gOffset * gDirection);
       
        llSetPos (gCurrentPosition);
    }
}
</syntaxhighlight>

Latest revision as of 13:14, 18 May 2016

Rez and Sense

// Rezzer that will only rez an object (from inventory) if it
// can't detect the specified number of objects in the region nearby already.
//
// Note: Sensing is limitd to a maximum of 96m in all directions.  If the
// objects pass out of that range, this won't find them.
//
// Always looks for (and rezzes) the first object found in inventory.
// NB: This must have copy permissions if you want to rez it more than once!
//
// Kimm Paulino, July 2012

integer MAX_REZZED_OBJECTS = 5;
vector REZ_POSITION = <1.0, 0.0, 0.0>;       // Relative to the rezzing prim, must be less than 10m away
vector REZ_ROTATION = <0.0, 0.0, 0.0>;      // In degrees

string gObjectName;

rezObject ()
{
    llRezObject (gObjectName, llGetPos() + REZ_POSITION, ZERO_VECTOR, llEuler2Rot (REZ_ROTATION * DEG_TO_RAD), 0);
}

default
{
    on_rez (integer start_param)
    {
        llResetScript();
    }
    
    state_entry ()
    {
        gObjectName = llGetInventoryName (INVENTORY_OBJECT, 0);
        if (gObjectName == "")
        {
            llOwnerSay ("Note to owner: No objects found in this prims inventory");
        }
    }
    
    touch_start (integer num_detected)
    {
        if (gObjectName != "")
        {
            // Trigger a single sensor event for the full range/arc looking for any non-avatar
            // objects with the same name as our rezzing object.
            llSensor (gObjectName, NULL_KEY, (ACTIVE|PASSIVE), 96.0, PI);
        }
    }
    
    sensor (integer num_detected)
    {
        if (num_detected < MAX_REZZED_OBJECTS)
        {
            rezObject();
        }
        else
        {
            llOwnerSay ("Max Objects detected ...");
            // Nothing to do
        }
    }
    
    no_sensor ()
    {
        // None found, so ok to rez one
        rezObject();
    }
    
    changed (integer change)
    {
        if (change & CHANGED_INVENTORY)
        {
            llResetScript();
        }
    }
}

Derez After Sitting

// This will kill the prim it is in, the specified time after someone
// sits on the prim.  It will unsit them before derezzing.
//
// Note: This only works when the prim has a sittarget defined.
//           But this script does not have to be the thing setting it,
//           if the sit target is set to <0.0,0.0,0.0> in this script,
//           then no call to llSitTarget is made - so another script
//           can do it instead.
//
// It can optionally derez on unsit too - i.e. when they get up
// or derez a defined time after they unsit.
//
// Note: It doesn't unsit any other avatars sitting on other
// prims prior to derezzing, but derezzing will unsit them anyway!
//
// It will also (optionally) automatically derez itself after a specified
// time if noone sits down on it.
//
// Kimm Paulino, July 2012

// TRUE if want to immediately auto derez when av gets up.
// (overrides DEREZ_AFTER_UNSIT_TIMEOUT)
integer DEREZ_ON_UNSIT = FALSE;

// Time to derez if noone sits down
// (in seconds - 0.0 to disable)
float DEREZ_TIMEOUT = 60.0;

// Once an av sits down, this timer starts
// and will derez when it times out.
// (in seconds - 0.0 to disable)
float DEREZ_AFTER_SIT_TIMEOUT = 30.0;

// Once an av gets up, this timer starts
// and will derez when it times out.
// (in seconds - 0.0 to disable)
float DEREZ_AFTER_UNSIT_TIMEOUT = 0.0;

// Position of the sittarget
vector SIT_VECTOR = <0.0, 0.0, 0.5>;    // In metres - ZERO_VECTOR to disable
vector SIT_ROTATION = <0.0, 0.0, 0.0>;  // In degrees

key gAvUuid;
integer gSitting = FALSE;
 
default
{
    on_rez (integer start_param)
    {
        llResetScript();
    }

    state_entry()
    {
        if (SIT_VECTOR != ZERO_VECTOR)
        {
            llSitTarget (SIT_VECTOR, llEuler2Rot (SIT_ROTATION * DEG_TO_RAD));
        }
        llSetTimerEvent (DEREZ_TIMEOUT);
    }
 
    timer ()
    {
        if (gAvUuid)
        {
            llUnSit (gAvUuid);
        }
        llSetTimerEvent (0.0);
        llDie();
    }
    
    changed (integer change)
    {
        // When someone sits on an object, the av is considered to be
        // a linked-in child prim, so the link number changes
        if (change & CHANGED_LINK)
        {
            gAvUuid = llAvatarOnSitTarget();
            if (gAvUuid)
            {
                // Avatar has just sat down
                gSitting = TRUE;
                llSetTimerEvent (DEREZ_AFTER_SIT_TIMEOUT);
            }
            else if (gSitting)
            {
                // Assume av just got up - it was sitting and now isn't ...
                gSitting = FALSE;
                if (DEREZ_ON_UNSIT)
                {
                    // Want to derez straight away
                    llDie();
                }
                llSetTimerEvent (DEREZ_AFTER_UNSIT_TIMEOUT);
            }
            else
            {
                // Could be unlinking going on
                // or maybe there is another sit target in a linked prim
                // that someone has just sat on or vacated
            }
        }
    }
}

Timer Action Template

// Basic timer-driven state changing script.
// NB: Does not use the LSL ability to define
// states, but uses a counter to manage a simple
// incrementing state machine.
//
//  Every time interval, it will change its record of state
//  and you can add code to do something, then it will move
//  to the next state.
//
//  To add more things, just add more
//        else if (gState == 4)
//        {
//            // and the next
//        }
//  statements in the appropriate place.
//
// If you want the timer interval to be different for different
// states, then you could add more llSetTimerEvent() calls
// in each state to set the timer for the next one.
//
// Kimm Paulino
// Sept 2012
 
// Timer interval in seconds
float TIMER_INTERVAL = 5.0;

integer gState;

default
{
    on_rez (integer start_param)
    {
        llResetScript();
    }
    
    state_entry ()
    {
        gState = 0;
        llSetTimerEvent (TIMER_INTERVAL);
    }
    
    timer ()
    {
        gState ++;
        if (gState == 1)
        {
            // Do the first thing here
        }
        else if (gState == 2)
        {
            // After the timer interval this is next
        }
        else if (gState == 3)
        {
            // and the next
        }
        // add more else if () statements here
        else
        {
            // Once all states are complete, reset the counter ready for the next time
            gState = 0;
        }
    }
}

Multiple Notecard Reading Template

// Example showing multiple notecard reading.
//
// Kimm Paulino, Oct 2012

key      gNCQueryId;
integer gNCLine;
integer gNCNumber;
string   gNCName;

default
{
    on_rez (integer start_param)
    {
        llResetScript();
    }
    
    state_entry ()
    {
        gNCNumber = 0;
        gNCLine = 0;
        gNCName = llGetInventoryName (INVENTORY_NOTECARD, gNCNumber);
        if (gNCName != "")
        {
            llOwnerSay ("=== Reading notecard " + gNCName + " (" + (string)gNCNumber + ")");
            gNCQueryId = llGetNotecardLine (gNCName, gNCLine);
        }
    }
    
    dataserver (key query_id, string data)
    {
        if (query_id != gNCQueryId)
        {
            // Not for us
            return;
        }

        // Note: If the notecard contains embedded objects (like scripts, landmarks, etc)
        // then EOF is returned - so this will move onto the next one as if the notecard
        // was empty.
        if (data == EOF)
        {
            // Move to the next notecard
            gNCNumber++;
            gNCLine = 0;
            gNCName = llGetInventoryName (INVENTORY_NOTECARD, gNCNumber);
            if (gNCName != "")
            {
                llOwnerSay ("=== Reading notecard " + gNCName + " (" + (string)gNCNumber + ")");
                gNCQueryId = llGetNotecardLine (gNCName, gNCLine);
            }
            else
            {
                llOwnerSay ("=== Complete");
            }

            // Wait for the next line to be read
            return;
        }

        // Do something with the notecard line
        // Note: Only get first 255 characters of each line
        llOwnerSay (data);
        
        // and read the next line
        gNCLine++;
        gNCQueryId = llGetNotecardLine(gNCName, gNCLine);
    }
    
    changed (integer change)
    {
        if (change & CHANGED_INVENTORY)
        {
            llResetScript();
        }
    }
}

Alarm Script

// Simple script to trigger at a certain time and perform a function,
// in the default case send an IM to the specified avatar
//
// Notes
// Can specify a time in GMT (ie no seasonal changes) or SLT
// Uses 24 hour times
// Can include touch control if required
// Sends the specified message to the specified UUID 
//
// If you want it to do something else, code it in the alarm() function
//
// Kimm Paulino
// Oct 2012
// http://kimmscripts.wordpress.com/

integer gHour = 7;  // 24 hour clock
integer gMin = 30;
integer gSec = 0;
integer gGMT = TRUE;   // GMT or SL time
integer gTouchControl = TRUE;
string gMsg = "Wake up!";
key gAv = "00000000-0000-0000-0000-000000000000";

integer gArmed;

setAlarm ()
{
    // set a timer event for destination time - current time
    float desttime = (float)(gHour*60*60 + gMin*60 + gSec);

    // This is the number of seconds since midnight
    // so the required setting until the destination time
    // will depend on if the time is in the past or not.
    // If we happen to get lucky and 
    float nowtime = llGetWallclock ();
    if (gGMT)
    {
        nowtime = llGetGMTclock ();
    }
    
    if (nowtime >= desttime)
    {
        // Need to add 24 hours before subtracting
        desttime = desttime + 24.0*60.0*60.0;
        llOwnerSay ("Dest: " + (string)desttime + " Now: " + (string)nowtime);
        llSetTimerEvent (desttime - nowtime);
    }
    else
    {
        llOwnerSay ("Dest: " + (string)desttime + " Now: " + (string)nowtime);
        llSetTimerEvent (desttime - nowtime);
    }
}

disableAlarm()
{
    llSetTimerEvent (0.0);
}

// This is what happens on the alarm
alarm ()
{
    //llOwnerSay ("Alarm");
    llInstantMessage (gAv, gMsg);
}

default
{
    state_entry()
    {
        string zone = " SLT";
        if (gGMT)
        {
            zone = " GMT";
        }
        llOwnerSay ("Alarm set for " + (string)gHour + " h " + (string)gMin + " m" + (string)gSec + " s " + zone);
        gArmed = TRUE;
        setAlarm();
    }
    
    touch_start (integer num_detected)
    {
        if (gTouchControl)
        {
            if (gArmed)
            {
                gArmed = FALSE;
                disableAlarm();
            }
            else
            {
                gArmed = TRUE;
                setAlarm();
            }
        }
    }
    
    timer ()
    {
        alarm();
        // Reset alarm each time, to allow for any drift in time
        setAlarm();
    }
}

Simple Channel Relay

// Simple relay script.  Listens on one channel and relays
// everything to the another channel.
//
// Can be useful for testing things - e.g. if you are listening
// on a negative channel in your main script and want a way
// to send it test strings, you could drop this in a nearby
// prim and have it listen on a chat channel and pass the messages
// onto your prim under test.
//
// Kimm Paulino
// Nov 2012

integer gListenChannel = 88;
integer gSpeakChannel = -88;

relayMessage (string message)
{
    // Only use one of these as required:
    // whisper = <10m; say = 20m; shout > 20m; region = whole region

    //llWhisper (gSpeakChannel, message);
    llSay (gSpeakChannel, message);
    //llShout (gSpeakChannel, message);
    //llRegionSay (gSpeakChannel, message);
}

default
{
    on_rez (integer start_param)
    {
        llResetScript();
    }

    state_entry ()
    {
        llListen (gListenChannel, "", "", "");
    }
    
    listen (integer channel, string name, key id, string message)
    {
        if (channel == gListenChannel)
        {
            relayMessage (message);
        }
    }
}

HTTP Server and Client Example

These two scripts can be used (once you've hard-coded in the right URL into the client script) to highlight basic prim to prim communications using HTTP without requiring an external server.

// Very, very simple HTTP server test script, as seen on
// http://wiki.secondlife.com/wiki/LSL_http_server/examples
//
// Note: It gets a new public URL each time it runs or
// when the object moves Sims ...
//
// So, you'll need to update the URL used by any client objects,
// or use some kind of dynamic URL service - there are some around
// on the Internet - search/read about HTTP-in
//
// Kimm Paulino, Nov 2009

default
{
    on_rez (integer start_param)
    {
        llResetScript();
    }
    
    state_entry()
    {
        llRequestURL();
    }
 
    http_request(key id, string method, string body)
    {
        if (method == URL_REQUEST_GRANTED)
        {
            llOwnerSay("URL: " + body);
        }
        else if (method == "GET")
        {
            llOwnerSay ("Handling Response ...");
            llHTTPResponse(id,200,"Hello From Kimm's HTTP Test");
        }
    }
}
// HTTP Test.  This will request the contents of the specified
// URL.  The idea is that the URL is provided by a companion object
// in SL.  Note that the URL created by the llRequestURL call changes
// when the server object is rezzed or moves sims though ...
//
// There are some services on the Net that provide a semi-permanent
// URL for use with HTTP-in like this though ...
//
// Kimm Paulino, Nov 2009

string URL = "past in your URL from the server script here";

default
{
    touch_start(integer total_number)
    {
        llHTTPRequest (URL, [HTTP_METHOD, "GET"], "");
    }
    
    http_response(key id, integer status, list meta, string body)
    {
        llWhisper (PUBLIC_CHANNEL, "Response: " + (string)body);
    }
}

HTTP POST Client and Server Example

This is similar to the above pair of scripts, but uses HTTP POST to send a message from the client to the server. The message is entered using a text box. It also uses the text box to enter in the server's URL when it first starts up.

// Very, very simple HTTP server test script, as seen on
// http://wiki.secondlife.com/wiki/LSL_http_server/examples
//
// but configured to accept and display what gets sent to
// it via a POST request.
//
// Note: It gets a new public URL each time it runs or
// when the object moves Sims ...
//
// So, you'll need to update the URL used by any client objects,
// or use some kind of dynamic URL service - there are some around
// on the Internet - search/read about HTTP-in.
//
// Also, as this is a demo script, it doesn't do things like clean
// up URLs and so on - see the wikis for details.
//
// Kimm Paulino, Nov 2012

default
{
    on_rez (integer start_param)
    {
        llResetScript();
    }
    
    state_entry()
    {
        llRequestURL();
    }
 
    http_request(key id, string method, string body)
    {
        if (method == URL_REQUEST_GRANTED)
        {
            llOwnerSay("URL: " + body);
        }
        else if (method == "GET")
        {
            llOwnerSay ("Handling Response ...");
            llHTTPResponse(id,200,"Post me something and I'll display it ...");
        }
        else if (method == "POST")
        {
            llOwnerSay ("Received: " + body);
            llHTTPResponse (id, 200, "");
        }
    }
}

And the client ...

// HTTP Test.  This will POST a message to the specified
// gUrl.  The idea is that the gUrl is provided by a companion object
// in SL.  Note that the gUrl created by the llHRequestgUrl call changes
// when the server object is rezzed or moves sims though ...
//
// There are some services on the Net that provide a semi-permanent
// gUrl for use with HTTP-in like this though ...
//
// The message is entered using a textbox on touch.  When the script
// first starts up, you need to paste in the URL of the server prim
// using the same text box.
//
// This is just a demo script.  You'll need to do proper listen and
// channel handling and so on.
//
// Kimm Paulino, Nov 2012

string gUrl = "";
integer gChannel;

integer randChannel ()
{
	// Based on http://tali.appspot.com/html/scripting/snippets.html
	// Always leaves 17th bit set (so never a number less than 65535)
	// Always leaves sign bit unset (so is always positive)
	integer pos_int = (((integer)llFrand(16384)) << 17) | 65536 | ((integer)llFrand(65535));
    return -pos_int;
}

default
{
    on_rez (integer start_param)
    {
        llResetScript();
    }
    
    state_entry ()
    {
        gChannel = randChannel();
        llListen (gChannel, "", "", "");    // Uses simplest and laggiest form of listen/channel handling
    }

    touch_start(integer total_number)
    {
        if (gUrl == "")
        {
            llTextBox (llDetectedKey (0), "Paste in the URL from the server prim and click submit", gChannel);
        }
        else
        {
            llTextBox (llDetectedKey (0), "Type in your message to send to the HTTP server", gChannel);
        }
    }
    
    listen (integer channel, string name, key id, string message)
    {
        if (channel != gChannel)
        {
            return;
        }
        
        if (llSubStringIndex (message, "http://") == 0)
        {
            // this is a new gUrl ...
            gUrl = message;
        }
        else if (gUrl != "")
        {
            llHTTPRequest (gUrl, [HTTP_METHOD, "POST"], message);
        }
        else
        {
            llOwnerSay ("You need to provide the URL of the server prim before sending any messages");
        }
    }
    
    http_response(key id, integer status, list meta, string body)
    {
        if (body != "")
        {
            llWhisper (PUBLIC_CHANNEL, "Response: " + (string)body);
        }
    }
}

Smooth, non-mesh up/down/rotate

// Makes an object go up and down gradually whilst slowly rotating.
// In order to make it a gradual movement, it uses a physical
// object, which means it might be a little wobbly ...
//
// The value given to the angular velocity parameter is quite critical
// depending on the mass of the object you wish to rotate. You'll need
// a larger value for larger objects otherwise they'll hardly move.
//
// Whilst this appears to work ok for small objects, it is very unpredictable
// and doesn't really work for large objects.
//
//  Kimm Paulino
//  December 2012
//
 
integer gState;
integer DOWN=0;
integer GO_UP=1;
integer UP=2;
integer GO_DOWN=3;
 
float MOVE_DAMPING=4.0;
float MOVE_TIME=4.0;
float DOWN_CORRECTION=1.5;  // Use trial-and-error to correct for SVC-2441
float TIME_PERIOD=0.2;
 
// Move to 2m above starting position
vector gOffset = <0.0, 0.0, 2.0>;
vector gStartPosition;
float gTimerCount;

// Angular Velocity Details - use values to rotate around the specified axis
// between 0.5 and around 5.0 (or even more for very large objects)
vector gAngularVelocity = <0.0, 0.0, 0.5>;  // For small objects
//vector gAngularVelocity = <0.0, 0.0, 5.0>;  // For large objects

default
{
    state_entry()
    {
        gTimerCount = 0.0;

        // Use physics so that can use MoveToTarget
        gStartPosition = llGetPos ();
 
        // Stop the object rotating except in Z axis
        llSetStatus(STATUS_ROTATE_X|STATUS_ROTATE_Y, FALSE);
        llSetStatus(STATUS_PHYSICS, TRUE);
        llMoveToTarget (gStartPosition, MOVE_DAMPING);
        llSetTimerEvent (TIME_PERIOD);
    }
 
    on_rez(integer n)
    {
        llResetScript();
    }
 
    timer ()
    {
        llSetAngularVelocity (gAngularVelocity, TRUE);

        gTimerCount += TIME_PERIOD;
        if (gTimerCount > MOVE_TIME)
        {
            gTimerCount = 0.0;
            
            if (gState == DOWN)
            {
                gState = GO_UP;
                llMoveToTarget(gStartPosition + gOffset, MOVE_DAMPING);
                gState = UP;
            }
            else if (gState == UP)
            {
                gState = GO_DOWN;
                // Need to compensate (a bit) for SVC-2441
                llMoveToTarget(gStartPosition, MOVE_DAMPING*DOWN_CORRECTION);
                gState = DOWN;
            }
        }
    }
}

Non-physical, non-mesh up/down/rotate

// Makes an object go up or down, gradually, using non-physical movement.
//
// Unfortunately, non-physical movement is jerky. If you can support it,
// a better up/down movement can be had using physics and up/down and
// rotate is better using llSetKeyframedmotion.
//
//  Kimm Paulino
//  December 2012
 
integer gState;
integer DOWN=0;
integer GO_UP=1;
integer UP=2;
integer GO_DOWN=3;

// Period for the up/down movement is MOVE_COUNT * MOVE_TIME
integer MOVE_COUNT=40;
float MOVE_TIME=0.1;

// Rotation value to use
vector gRotationAxis = <0.0, 0.0, 1.0>;
float    gPiDivisor = 2.0;
 
// The vector to add to the start position for MOVE_COUNT times
vector gOffset = <0.0, 0.0, 0.05>;
vector gStartPosition;
vector gCurrentPosition;
integer gCount;
integer gDirection;
 
default
{
    state_entry()
    {
        gCount = 0;
        gDirection = 1;
        gStartPosition = llGetPos ();
        gCurrentPosition = gStartPosition;
        
        // Start the rotation
         llTargetOmega (gRotationAxis, PI/gPiDivisor, 1.0);
 
        // Stop the object rotating
        llSetTimerEvent (MOVE_TIME);
    }
 
    on_rez(integer n)
    {
        llResetScript();
    }
 
    timer ()
    {
        gCount++;
        if (gCount > MOVE_COUNT)
        {
            gCount = 0;
            gDirection = -gDirection;
            
            if (gState == DOWN)
            {
                gState = GO_UP;
                gState = UP;
            }
            else if (gState == UP)
            {
                gState = GO_DOWN;
                gState = DOWN;
            }
        }
        
        gCurrentPosition = gCurrentPosition + (gOffset * gDirection);
        
        llSetPos (gCurrentPosition);
    }
}