Orbit Maintaining Face Orientation

Written by: Headmaster
// 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());       
            }
        }
    }
}