Orbit Maintaining Face Orientation

Expired

// Script to perform orbit whilst maintaining the same face
// to a specific direction.  This is designed for use with two linked
// prims, the root is the centre prim, and a second prim orbits around
// the root, always keeping its face in the same (global) direction.
//
// There are two ways of using this script - as a single script in
// the root prim, or with copies of the script in both root and any
// rotating child prims.
//
// Set gScriptScriptVersion = TRUE/FALSE as required
//
// The single script version is for placing in the central root
// prim and it will make the 1st linked prim orbit it.
//
// The multi-script version will need the script in the root (centre)
// prim and in any child prims that you wish to be orbiting.
//
// Kimm Paulino
// April 2012
 
// Single or multiple script version
integer gSingleScriptVersion = FALSE;
 
// Configure the script
integer gTouchControl = FALSE;
float   ROT_PERIOD = 5.0;
integer ROT_STEPS = 20;
 
// Don't change below here
integer gStep = 0;
integer gRotating = FALSE;
integer gRoot = FALSE;
 
default
{
    on_rez (integer start_param)
    {
        llResetScript();
    }
 
    state_entry()
    {
        gStep = 0;
        integer num = llGetLinkNumber();
        if (num <= 1)
        {
            gRoot = TRUE;
        }
 
        if (gSingleScriptVersion && !gRoot)
        {
            // In single script version, only function if we are the root
            llOwnerSay ("This script is configured for Single Script use and so must be in the root (centre) prim.");
            return;
        }
 
        if (!gTouchControl)
        {
            llSetTimerEvent (ROT_PERIOD/(float)ROT_STEPS);
        }
    }
 
    touch_start (integer num_detected)
    {
        if (gSingleScriptVersion && !gRoot)
        {
            return;
        }
 
        if (gTouchControl)
        {
            if (gRotating)
            {
                gRotating = FALSE;
                llSetTimerEvent (0.0);
            }
            else
            {
                gRotating = TRUE;
                llSetTimerEvent (ROT_PERIOD/(float)ROT_STEPS);
            }
        }
    }
 
    timer ()
    {
        if (gSingleScriptVersion && !gRoot)
        {
            return;
        }
 
        gStep ++;
        if (gStep > ROT_STEPS)
        {
            gStep = 0;
        }
 
        // If this is the root, it is the centre prim
 
        // If single script, then move the slave then the root together
        if (gSingleScriptVersion)
        {
            // Now move the first linked prim
            float rot = - gStep * (360.0/(float)ROT_STEPS);
            llSetLinkPrimitiveParamsFast (2, [PRIM_ROTATION, llEuler2Rot (<0.0, 0.0, rot>*DEG_TO_RAD) / llGetRootRotation()]);
 
            // Move the root
            rot = gStep * (360.0/(float)ROT_STEPS);
            llSetRot (llEuler2Rot (<0.0, 0.0, rot>*DEG_TO_RAD));       
        }
        else // multiple scripts - just move one ...
        {
            if (gRoot)
            {
                // Move the root
                float rot = gStep * (360.0/(float)ROT_STEPS);
                llSetRot (llEuler2Rot (<0.0, 0.0, rot>*DEG_TO_RAD));       
            }
            else
            {
                // Move this prim, as a child
                float rot = - gStep * (360.0/(float)ROT_STEPS);
                llSetRot (llEuler2Rot (<0.0, 0.0, rot>*DEG_TO_RAD) / llGetRootRotation());       
            }
        }
    }
}

 

Move Up and Down and Rotate

Expired

// Makes an object go up or down, gradually,
// with a slow rotation.
//
// Includes option for touch control.
//
// Warning:
//  * The animation will go a little weird if it is taken into inventory
//     whilst moving.
//  * It can't be used with a rezzer unless it is stopped (so
//     touch control is mandatory to turn it back on).
//
// Thanks to the members of the Advanced Scripters of SL group.
//
// Update Jan 2013: Added touch.
//
//  Kimm Paulino
//  February 2012
//
 
float gMoveTime = 4.0;                // Time for each movement
vector gOffset  = <0.0, 0.0, 2.0>;    // Where to move to (and back from)
vector gDegRot  = <0.0, 0.0, 180.0>;  // rotation to apply going up, then going down again 
integer gTouchControl = TRUE;           // FALSE to disable touch
 
integer gState;
 
default
{
    state_entry ()
    {
        gState = 0;
        llSetLinkPrimitiveParamsFast(LINK_THIS, [PRIM_PHYSICS_SHAPE_TYPE, PRIM_PHYSICS_SHAPE_CONVEX]);
    }
 
    touch_start (integer num_detected)
    {
        if (gTouchControl)
        {
            // 0 = first time; 1 = off; 2 = on
            if (gState == 0)
            {
                gState = 2;
                llSetKeyframedMotion (
                    [
                        gOffset, llEuler2Rot (gDegRot*DEG_TO_RAD), gMoveTime,
                        -gOffset,  llEuler2Rot (gDegRot*DEG_TO_RAD), gMoveTime
                    ],
                    [KFM_MODE, KFM_LOOP]);
            }
            else if (gState == 1)
            {
                // turn on
                gState = 2;
                llSetKeyframedMotion ([], [KFM_COMMAND, KFM_CMD_PLAY]);
            }
            else
            {
                // turn off
                gState = 1;
                llSetKeyframedMotion ([], [KFM_COMMAND, KFM_CMD_PAUSE]);
            }
        }
    }
 
    on_rez (integer n)
    {
        llResetScript();
    }
}

 

Touch to Disappear

Expired

// Touch to make an object disappear and reappear.
//
// Kimm Paulino
// Sept 2011
// Jan 2013: Update to affect entire linkset
 
integer gGone = FALSE;
 
default
{
    state_entry()
    {
        gGone = FALSE;
    }
 
    touch_start(integer total_number)
    {
        if (gGone)
        {
            llSetLinkAlpha (LINK_SET, 1.0, ALL_SIDES);
            gGone = FALSE;
        }
        else
        {
            llSetLinkAlpha (LINK_SET, 0.0, ALL_SIDES);
            gGone = TRUE;
        }
    }
}

 

Path Setting Script

Expired

// Path Setting Script
//
// In 'edit' mode, user moves the object and 'saves' various positions
// over time, then the positions can be replayed.  This either uses the physical
// move functions to create smooth movement or non-physical movements
// for a slightly more jerky movement!
//
// NOTE: Positions and rotations are relative to the region, so if you
// move the prim, then the positions won't move with it - you'd have to
// reset the script (using the 'reset' button) and store a new path.
//
// Depending on the settings, the system can either loop forever
// or play just once.
//
// It also has the option of resetting if you change owners, which
// might be useful if you want new owners to be able to store their
// own paths.
//
// Kimm Paulino
// Oct 2010
 
integer gDebug = FALSE;
integer gPhysics = FALSE;        // Set to use physical movements
integer gLoop = TRUE;                // Set to continually loop through the movements
integer gResetOnOwnerChange = TRUE;    // Set if want script to auto reset when changing owners
 
list gPositionData;            // Always assume that there are the same numbers
list gRotationData;            // of position and rotation data points
integer gCurrentIdx;
float gTimePeriod = 2.0;
float gTau = 5.0;
key gOwnerId; 
integer gListen; 
integer gTimeHandle; 
integer gTauHandle; 
string gHelpMsg = "Use EDIT mode to move your object, selecting 'Save' to save each position.  Select 'Done' once complete.  Don't forget to save your first position too!"; 
string gErrorMsg = "Something unexpected went wrong, suggest you reset the script!";
string SAVE_BTN = "Save";
string DONE_BTN = "Done";
string TIME_BTN = "Time Adjust";
string TAU_BTN = "Tau Adjust";
string RESET_BTN = "Reset";
string START_BTN = "Start";
string STOP_BTN = "Stop";
string START_MSG = "start";        // What a passer by can type in via chat
integer LISTEN_CH = 600;
integer TIME_CH = 900;
integer TAU_CH = 901;
 
doDebug (string msg)
{
    if (gDebug)
    {
        llOwnerSay (msg);
    }
}
 
doMove()
{ 
    integer num_points = llGetListLength(gPositionData); 
    if (num_points != llGetListLength (gRotationData))
    {
        llOwnerSay (gErrorMsg);
        disableMove();
        return;
    }
 
    if (gCurrentIdx >= num_points)
    {
        if (gLoop)
        {
            // Loop around for another go
            gCurrentIdx = 0;
        }
        else
        {
            // All complete
            disableMove();
            return;
        }
    }
 
    doDebug ("Moving to position " + (string)gCurrentIdx);
 
    vector next_pos = llList2Vector (gPositionData, gCurrentIdx);
    rotation next_rot = llList2Rot (gRotationData, gCurrentIdx);
 
    if (next_pos == ZERO_VECTOR && next_rot == ZERO_ROTATION)
    {
        // ignore
    }
    else
    {
        if (gPhysics)
        {
            llMoveToTarget(next_pos, gTau);
            llLookAt(next_pos,1,1);
            llRotLookAt(next_rot,1,1);
        }
        else
        {
//            doDebug ("moving to: " + (string)next_pos);
            llSetRot (next_rot);
            llSetPos (next_pos);
        }
    }
 
    // Move on to the next point
    gCurrentIdx ++;
} 
 
dialog ()
{
    list buttons;
    if (gPhysics)
    {
        buttons = [SAVE_BTN, DONE_BTN, RESET_BTN, START_BTN, STOP_BTN, TIME_BTN, TAU_BTN];
    }
    else
    {
        buttons = [SAVE_BTN, DONE_BTN, RESET_BTN, START_BTN, STOP_BTN, TIME_BTN];
    }
    llDialog (gOwnerId, gHelpMsg, buttons, LISTEN_CH);
}
 
enableMove ()
{
    if (gPhysics)
    {
        doDebug ("Enabling physical move");
        llSetStatus (PRIM_PHYSICS, TRUE);
    }
    else
    {
        doDebug ("Enabling non-physical move");
        llSetStatus(PRIM_PHYSICS, FALSE); 
    }
    llSetTimerEvent (gTimePeriod);
    gCurrentIdx = 0;
    doMove ();
}
 
disableMove ()
{
    doDebug ("Disabling move");
    llSetStatus (PRIM_PHYSICS, FALSE);
    llSetTimerEvent (0.0);
}
 
default 
{
    on_rez (integer start_param)
    {
        // if we reset on rez, then a user can't take an object into
        // inventory have rerez it with the same path stored.
        //
        // Means that if they do want to clear the path, say because
        // the position in the Sim has changed, then they have to use
        // the 'reset' option.
    }
 
    state_entry() 
    {   
        llOwnerSay ("Ready to start saving positions.  Touch for menu, then go to SL Edit mode to move the object and use 'save' on the menu to save each position.");
        gOwnerId = llGetOwner();
    }
 
    touch_start(integer who)
    {
        gListen = llListen (LISTEN_CH,"",NULL_KEY,"");
        if (llDetectedKey(0) == gOwnerId)
        {
            dialog();
        }
        else
        {
            if (!gLoop)
            {
                // Let nearby users start the moving
                llWhisper  (0, "To start the movement, please type the following into local chat:  /" + (string)LISTEN_CH + " " + START_MSG);
            }
        }
    }
 
    listen (integer channel, string name, key id, string msg)
    {
        vector pos = llGetPos();
        rotation rot = llGetRot();
 
        if (channel == LISTEN_CH)
        {
            if (msg == START_BTN || msg == START_MSG)
            {
                enableMove();
            }
 
            // non-owners can't do anything else
            if (id != gOwnerId)
            {
                return;
            }
 
            if (msg == SAVE_BTN)
            {
                gPositionData += pos;
                gRotationData += rot;
                dialog ();
            } 
            else if (msg == STOP_BTN)
            {
                disableMove();
            }
            else if (msg == RESET_BTN)
            {
                llResetScript();
            }
            else if (msg == TIME_BTN)
            {
                gTimeHandle = llListen (TIME_CH, "", gOwnerId, "");
                llOwnerSay ("Adjust time using: /" + (string)TIME_CH + " ");
            } 
            else if (msg == TAU_BTN)
            {
                gTauHandle = llListen(TAU_CH, "", gOwnerId, "");
                llOwnerSay ("Adjust Tau using: /" + (string)TAU_CH + " ");
            } 
            else if (msg == DONE_BTN)
            {
                llOwnerSay("To reset use: /" + (string)LISTEN_CH + " reset");
                llOwnerSay("To start use: /" + (string)LISTEN_CH + " start");
            }
        }
 
        if (channel == TIME_CH)
        {
            gTimePeriod = (float)msg;
            llListenRemove (gTimeHandle);
            llOwnerSay ("Time period set to " + msg);
        } 
 
        if (channel == TAU_CH)
        {
            gTau = (float)msg;
            llListenRemove (gTauHandle);
            llOwnerSay ("Tau set to " + msg);
        } 
    }
 
    changed(integer ch)
    {
        if(ch & CHANGED_OWNER)
        {
            if (gResetOnOwnerChange)
            {
                // This will clear out all stored positions of course!
                llResetScript();
            }
        }
    }
 
    timer()
    {
         doMove();
    }
}