-->

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.

ZHAO-II-core 7/21.1

// ZHAO-II-core - Ziggy Puff, 06/07
 
/////////////////////////////////////////////////////////////////////////////////////////////////////
// Main engine script - receives link messages from any interface script. Handles the core AO work
//
// Interface definition: The following link_message commands are handled by this script. All of
// these are sent in the string field. All other fields are ignored
//
// ZHAO_RESET                          Reset script
// ZHAO_LOAD|<notecardName>            Load specified notecard
// ZHAO_NEXTSTAND                      Switch to next stand
// ZHAO_STANDTIME|<time>               Time between stands. Specified in seconds, expects an integer.
//                                     0 turns it off
// ZHAO_AOON                           AO On
// ZHAO_AOOFF                          AO Off
// ZHAO_SITON                          Sit On
// ZHAO_SITOFF                         Sit Off
// ZHAO_RANDOMSTANDS                   Stands cycle randomly
// ZHAO_SEQUENTIALSTANDS               Stands cycle sequentially
// ZHAO_SETTINGS                       Prints status
// ZHAO_SITS                           Select a sit
// ZHAO_GROUNDSITS                     Select a ground sit
// ZHAO_WALKS                          Select a walk
//
// So, to send a command to the ZHAO-II engine, send a linked message:
//
//   llMessageLinked(LINK_SET, 0, "ZHAO_AOON", NULL_KEY);
//
// This script uses a listener on channel -91234. If other scripts are added to the ZHAO, make sure
// they don't use the same channel
/////////////////////////////////////////////////////////////////////////////////////////////////////
 
/////////////////////////////////////////////////////////////////////////////////////////////////////
// New notecard format
//
/////////////////////////////////////////////////////////////////////////////////////////////////////
// Lines starting with a / are treated as comments and ignored. Blank lines are ignored. Valid lines
// look like this:
//
// [ Walking ]SexyWalk1|SexyWalk2|SexyWalk3
//
// The token (in this case, [ Walking ]) identifies the animation to be overridden. The rest is a
// list of animations, separated by the '|' (pipe) character. You can specify multiple animations
// for Stands, Walks, Sits, and GroundSits. Multiple animations on any other line will be ignored.
// You can have up to 12 animations each for Walks, Sits and GroundSits. There is no hard limit
// on the number of stands, but adding too many stands will make the script run out of memory and
// crash, so be careful. You can repeat tokens, so you can split the Stands up across multiple lines.
// Use the [ Standing ] token in each line, and the script will add the animation lists together.
//
// Advanced: Each 'animation name' can be a comma-separated list of animations, which will be played
// together. For example:
//
// [ Walking ]SexyWalk1UpperBody,SexyWalk1LowerBody|SexyWalk2|SexyWalk3
//
// Note the ',' between SexyWalk1UpperBody and SexyWalk1LowerBody - this tells ZHAO-II to treat these
// as a single 'animation' and play them together. The '|' between this 'animation' and SexyWalk2 tells
// ZHAO-II to treat SexyWalk2 and SexyWalk3 as separate walk animations. You can use this to layer
// animations on top of each other.
//
// Do not add any spaces around animation names!!!
//
// The token can be one of the following:
//
// [ Standing ]
// [ Walking ]
// [ Sitting ]
// [ Sitting On Ground ]
// [ Crouching ]
// [ Crouch Walking ]
// [ Landing ]
// [ Standing Up ]
// [ Falling ]
// [ Flying Down ]
// [ Flying Up ]
// [ Flying ]
// [ Flying Slow ]
// [ Hovering ]
// [ Jumping ]
// [ Pre Jumping ]
// [ Running ]
// [ Turning Right ]
// [ Turning Left ]
// [ Floating ]
// [ Swimming Forward ]
// [ Swimming Up ]
// [ Swimming Down ]
//
/////////////////////////////////////////////////////////////////////////////////////////////////////
 
// Ziggy, 07/16/07 - Warning instead of error on 'no animation in inventory', that way SL's built-in
//                   anims can be used
//
// Ziggy, 07/14/07 - 2 bug fixes. Listens aren't being reset on owner change, and a typo in the
//                   ground sit animation code
//
// Ziggy, 06/07:
//          Reduce script count, since idle scripts take up scheduler time
//          Tokenize notecard reader, to simplify notecard setup
//          Remove scripted texture changes, to simplify customization by animation sellers
 
// Fennec Wind, January 18th, 2007:
//          Changed Walk/Sit/Ground Sit dialogs to show animation name (or partial name if too long)
//          and only show buttons for non-blank entries.
//          Fixed minor bug in the state_entry, ground sits were not being initialized.
//
 
// Dzonatas Sol, 09/06: Fixed forward walk override (same as previous backward walk fix). 
 
// Based on Francis Chung's Franimation Overrider v1.8
 
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
 
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307, USA.
 
// CONSTANTS
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Default notecard we read on script_entry
string defaultNoteCard = "Default";
 
// List of all the animation states
list animState = [ "Sitting on Ground", "Sitting", "Striding", "Crouching", "CrouchWalking",
                   "Soft Landing", "Standing Up", "Falling Down", "Hovering Down", "Hovering Up",
                   "FlyingSlow", "Flying", "Hovering", "Jumping", "PreJumping", "Running",
                   "Turning Right", "Turning Left", "Walking", "Landing", "Standing" ];
 
// Animations in which we automatically disable animation overriding
// Try to keep this list short, the longer it is the worse it affects our runtime
// (Note: This is *almost* constant. We have to type-convert this to keys instead of strings
// on initialization - blargh)
list autoDisableList = [
    "3147d815-6338-b932-f011-16b56d9ac18b", // aim_R_handgun
    "ea633413-8006-180a-c3ba-96dd1d756720", // aim_R_rifle
    "b5b4a67d-0aee-30d2-72cd-77b333e932ef", // aim_R_bazooka
    "46bb4359-de38-4ed8-6a22-f1f52fe8f506", // aim_l_bow
    "9a728b41-4ba0-4729-4db7-14bc3d3df741", // Launa's hug
    "f3300ad9-3462-1d07-2044-0fef80062da0", // punch_L
    "c8e42d32-7310-6906-c903-cab5d4a34656", // punch_r
    "85428680-6bf9-3e64-b489-6f81087c24bd", // sword_strike_R
    "eefc79be-daae-a239-8c04-890f5d23654a"  // punch_onetwo
];
 
// Logic change - we now have a list of tokens. The 'overrides' list is the same length as this,
// i.e. it has one entry per token, *not* one entry per animation. Multiple options for a token
// are stored as | separated strings in a single list entry. This was done to save memory, and
// allow a larger number of stands etc. All the xxxIndex variables now refer to the token index,
// since that's how long 'overrides' is.
 
// List of internal tokens. This *must* be in the same sequence as the animState list. Note that
// we combine some tokens after the notecard is read (striding/walking, landing/soft landing), etc.
// The publicized tokens list only contains one entry for each pair, but we'll accept both, and
// combine them later
list tokens = [
    "[ Sitting On Ground ]",    // 0
    "[ Sitting ]",              // 1
    "",                         // 2 - We don't allow Striding as a token
    "[ Crouching ]",            // 3
    "[ Crouch Walking ]",       // 4
    "",                         // 5 - We don't allow Soft Landing as a token
    "[ Standing Up ]",          // 6
    "[ Falling ]",              // 7
    "[ Flying Down ]",          // 8
    "[ Flying Up ]",            // 9
    "[ Flying Slow ]",          // 10
    "[ Flying ]",               // 11
    "[ Hovering ]",             // 12
    "[ Jumping ]",              // 13
    "[ Pre Jumping ]",          // 14
    "[ Running ]",              // 15
    "[ Turning Right ]",        // 16
    "[ Turning Left ]",         // 17
    "[ Walking ]",              // 18
    "[ Landing ]",              // 19
    "[ Standing ]",             // 20
    "[ Swimming Down ]",        // 21
    "[ Swimming Up ]",          // 22
    "[ Swimming Forward ]",     // 23
    "[ Floating ]"              // 24
];
 
// The tokens for which we allow multiple animations
list multiAnimTokenIndexes = [
    0,  // "[ Sitting On Ground ]"
    1,  // "[ Sitting ]"
    18, // "[ Walking ]"
    20  // "[ Standing ]"
];
 
// Index of interesting animations
integer noAnimIndex     = -1;
integer sitgroundIndex  = 0;
integer sittingIndex    = 1;
integer stridingIndex   = 2;
integer standingupIndex = 6;
integer hoverdownIndex  = 8;
integer hoverupIndex    = 9;
integer flyingslowIndex = 10;
integer flyingIndex     = 11;
integer hoverIndex      = 12;
integer walkingIndex    = 18;
integer standingIndex   = 20;
integer swimdownIndex   = 21;
integer swimupIndex     = 22;
integer swimmingIndex   = 23;
integer waterTreadIndex = 24;
 
// list of animations that have a different value when underwater
list underwaterAnim = [ hoverIndex, flyingIndex, flyingslowIndex, hoverupIndex, hoverdownIndex ];
 
// corresponding list of animations that we override the overrider with when underwater
list underwaterOverride = [ waterTreadIndex, swimmingIndex, swimmingIndex, swimupIndex, swimdownIndex];
 
// This is an ugly hack, because the standing up animation doesn't work quite right
// (SL is borked, this has been bug reported)
// If you play a pose overtop the standing up animation, your avatar tends to get
// stuck in place.
// This is a list of anims that we'll stop automatically
list autoStop = [ 5, 6, 19 ];
// Amount of time we'll wait before autostopping the animation (set to 0 to turn off autostopping)
float autoStopTime = 1.5;
 
// How long before flipping stand animations
integer standTimeDefault = 30;
 
// How fast we should poll for changed anims (as fast as possible)
// In practice, you will not poll more than 8 times a second.
float timerEventLength = 0.25;
 
// The minimum time between events.
// While timerEvents are scaled automatically by the server, control events are processed
// much more aggressively, and needs to be throttled by this script
float minEventDelay = 0.25;
 
// The key for the typing animation
key typingAnim = "c541c47f-e0c0-058b-ad1a-d6ae3a4584d9";
 
// Inline check for hackGetAnimList to save a few bytes
 
// Listen channel for pop-up menu
integer listenChannel = -91234;
 
// GLOBALS
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
 
integer numStands;                          // Number of stands - needed for auto cycle
integer randomStands = FALSE;               // Whether stands cycle randomly
integer curStandIndex;                      // Current stand - needed for cycling
string curStandAnim = "";                   // Current Stand animation
string curSitAnim = "";                     // Current sit animation
string curWalkAnim = "";                    // Current walk animation
string curGsitAnim = "";                    // Current ground sit animation
 
list overrides = [];                        // List of animations we override
key notecardLineKey;                        // notecard reading keys
integer notecardIndex;                      // current line being read from notecard
integer numOverrides;                       // # of overrides
 
string  lastAnim = "";                      // last Animation we ever played
string  lastAnimSet = "";                   // last set of animations we ever played
integer lastAnimIndex = 0;                  // index of the last animation we ever played
string  lastAnimState = "";                 // last thing llGetAnimation() returned
 
integer standTime = standTimeDefault;       // How long before flipping stand animations
 
integer animOverrideOn = TRUE;              // Is the animation override on?
integer gotPermission  = FALSE;             // Do we have animation permissions?
 
integer listenHandle;                       // Listen handlers - only used for pop-up menu, then turned off
 
integer haveWalkingAnim = FALSE;            // Hack to get it so we face the right way when we walk backwards
 
integer sitOverride = TRUE;                 // Whether we're overriding sit or not
 
integer listenState = 0;                    // What pop-up menu we're handling now
 
integer loadInProgress = FALSE;             // Are we currently loading a notecard
string notecardName = "";                   // The notecard we're currently reading
 
key Owner = NULL_KEY;
 
// String constants to save a few bytes
string EMPTY = "";
string SEPARATOR = "|";
string TRYAGAIN = "Please correct the notecard and try again.";
 
// CODE
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
 
// Find if two lists/sets share any elements in common
integer hasIntersection( list _list1, list _list2 ) {
    list bigList;
    list smallList;
    integer smallListLength;
    integer i;
 
    if (  llGetListLength( _list1 ) <= llGetListLength( _list2 ) ) {
        smallList = _list1;
        bigList = _list2;
    }
    else {
        bigList = _list1;
        smallList = _list2;
    }
    smallListLength = llGetListLength( smallList );
 
    for ( i=0; i<smallListLength; i++ ) {
        if ( llListFindList( bigList, llList2List(smallList,i,i) ) != -1 ) {
            return TRUE;
        }
    }
 
    return FALSE;
}
 
startAnimationList( string _csvAnims ) {
    list anims = llCSV2List( _csvAnims );
    integer i;
    for( i=0; i<llGetListLength(anims); i++ )
        llStartAnimation( llList2String(anims,i) );
}
 
stopAnimationList( string _csvAnims ) {
    list anims = llCSV2List( _csvAnims );
    integer i;
    for( i=0; i<llGetListLength(anims); i++ )
        llStopAnimation( llList2String(anims,i) );
}
 
startNewAnimation( string _anim, integer _animIndex, string _state ) {
    if ( _anim != lastAnimSet ) {
        string newAnim;
        if ( lastAnim != EMPTY )
            stopAnimationList( lastAnim );
        if ( _anim != EMPTY ) {   // Time to play a new animation
             list newAnimSet = llParseStringKeepNulls( _anim, [SEPARATOR], [] );
             newAnim = llList2String( newAnimSet, (integer)llFloor(llFrand(llGetListLength(newAnimSet))) );
 
             startAnimationList( newAnim );
 
            if ( llListFindList( autoStop, [_animIndex] ) != -1 ) {
                // This is an ugly hack, because the standing up animation doesn't work quite right
                // (SL is borked, this has been bug reported)
                // If you play a pose overtop the standing up animation, your avatar tends to get
                // stuck in place.
                if ( lastAnim != EMPTY ) {
                   stopAnimationList( lastAnim );
                   lastAnim = EMPTY;
                }
                llSleep( autoStopTime );
                stopAnimationList( _anim );
            }
        }
        lastAnim = newAnim;
        lastAnimSet = _anim;
    }
    lastAnimIndex = _animIndex;
    lastAnimState = _state;
}
 
// Figure out what animation we should be playing right now
animOverride() {
    string  curAnimState = llGetAnimation( Owner );
    integer curAnimIndex;
    integer underwaterAnimIndex;
 
    // Convert the ones we don't handle
    if ( curAnimState == "Striding" ) {
        curAnimState = "Walking";
    } else if ( curAnimState == "Soft Landing" ) {
        curAnimState = "Landing";
    }
 
    // Remove the list check, since it only contains one element
    // Check if we need to work around any bugs in llGetAnimation
    // Hack, because, SL really likes to switch between crouch and crouchwalking for no reason
    if ( curAnimState == "CrouchWalking" ) {
      if ( llVecMag(llGetVel()) < .5 )
         curAnimState = "Crouching";
    }
 
    if ( curAnimState == lastAnimState ) {
        // This conditional not absolutely necessary (In fact it's better if it's not here)
        // But it's good for increasing performance.
        // One of the drawbacks of this performance hack is the underwater animations
        // If you fly up, it will keep playing the "swim up" animation even after you've
        // left the water.
        return;
    }
 
    curAnimIndex        = llListFindList( animState, [curAnimState] );
    underwaterAnimIndex = llListFindList( underwaterAnim, [curAnimIndex] );
 
    // For all the multi-anims, we know the animation name to play. Send
    // in the actual overrides index, since that's what this function
    // expects, not the index into the multi-anim list
    if ( curAnimIndex == standingIndex ) {
        startNewAnimation( curStandAnim, standingIndex, curAnimState );
    }
    else if ( curAnimIndex == sittingIndex ) {
        // Check if sit override is turned off
        if (( sitOverride == FALSE ) && ( curAnimState == "Sitting" )) {
            startNewAnimation( EMPTY, noAnimIndex, curAnimState );
        }
        else {
            startNewAnimation( curSitAnim, sittingIndex, curAnimState );
        }
    }
    else if ( curAnimIndex == walkingIndex ) {
        startNewAnimation( curWalkAnim, walkingIndex, curAnimState );
    }
    else if ( curAnimIndex == sitgroundIndex ) {
        startNewAnimation( curGsitAnim, sitgroundIndex, curAnimState );
    }
    else {
        if ( underwaterAnimIndex != -1 ) {
            // Only call llGetPos if we care about underwater anims
            vector curPos = llGetPos();
            if ( llWater(ZERO_VECTOR) > curPos.z ) {
                curAnimIndex = llList2Integer( underwaterOverride, underwaterAnimIndex );
            }
        }
        startNewAnimation( llList2String(overrides, curAnimIndex), curAnimIndex, curAnimState );
    }
}
 
// Switch to the next stand anim
doNextStand(integer fromUI) {
    if ( numStands > 0 ) {
        if ( randomStands ) {
            curStandIndex = llFloor( llFrand(numStands) );
        } else {
            curStandIndex = (curStandIndex + 1) % numStands;
        }
 
        curStandAnim = findMultiAnim( standingIndex, curStandIndex );
        if ( lastAnimState == "Standing" )
            startNewAnimation( curStandAnim, standingIndex, lastAnimState );
 
        if ( fromUI == TRUE ) {
            llOwnerSay( "Switching to stand '" + curStandAnim + "'." );
        }
    } else {
        if ( fromUI == TRUE ) {
            llOwnerSay( "No stand animations configured." );
        }
    }
 
    llResetTime();
}
 
// Displays menu of animation choices
doMultiAnimMenu( integer _animIndex, string _animType, string _currentAnim )
{
    // Dialog enhancement - Fennec Wind
    // Fix - a no-mod anim with a long name will break this
 
    list anims = llParseString2List( llList2String(overrides, _animIndex), [SEPARATOR], [] );
    integer numAnims = llGetListLength( anims );
    if ( numAnims > 12 ) {
        llOwnerSay( "Too many animations, cannot generate menu. " + TRYAGAIN );
        return;
    }
 
    list buttons = [];
    integer i;
    string animNames = EMPTY;
    for ( i=0; i<numAnims; i++ ) {
        animNames += "\n" + (string)(i+1) + ". " + llList2String( anims, i );
        buttons += [(string)(i+1)];
    }
    // If no animations were configured, say so and just display an "OK" button
    if ( animNames == EMPTY ) {
        animNames = "\n\nNo overrides have been configured.";
    }
    llListenControl(listenHandle, TRUE);
    llDialog( Owner, "Select the " + _animType + " animation to use:\n\nCurrently: " + _currentAnim + animNames,
              buttons, listenChannel );
}
 
// Returns an animation from the multiAnims
string findMultiAnim( integer _animIndex, integer _multiAnimIndex )
{
    list animsList = llParseString2List( llList2String(overrides, _animIndex), [SEPARATOR], [] );
    return llList2String( animsList, _multiAnimIndex );
}
 
// Checks for too many animations - can't do menus with > 12 animations
checkMultiAnim( integer _animIndex, string _animName )
{
    list animsList = llParseString2List( llList2String(overrides, _animIndex), [SEPARATOR], [] );
    if ( llGetListLength(animsList) > 12 )
        llOwnerSay( "You have more than 12 " + _animName + " animations. Please correct this." );
}
 
checkAnimInInventory( string _csvAnims )
{
    list anims = llCSV2List( _csvAnims );
    integer i;
    for( i=0; i<llGetListLength(anims); i++ ) {
        string animName = llList2String( anims, i );
        if ( llGetInventoryType( animName ) != INVENTORY_ANIMATION ) {
            // Only a warning, so built-in anims can be used
            llOwnerSay( "Warning: Couldn't find animation '" + animName + "' in inventory." );
        }
    }
}
 
// Print free memory. Separate function to save a few bytes
printFreeMemory()
{
    float memory = (float)llGetFreeMemory() * 100.0 / 16384.0;
    llOwnerSay( (string)((integer)memory) + "% memory free" );
}
 
// Returns true if we should override the current animation
integer checkAndOverride() {
    if ( animOverrideOn && gotPermission ) {
        // Check if we should explicitly NOT override a playing animation
        if ( hasIntersection( autoDisableList, llGetAnimationList(Owner) ) ) {
            startNewAnimation( EMPTY, noAnimIndex, EMPTY );
            return FALSE;
        }
 
        animOverride();
        return TRUE;
    }
 
    return FALSE;
}
 
// Load all the animation names from a notecard
loadNoteCard() {
 
    if ( llGetInventoryKey(notecardName) == NULL_KEY ) {
        llOwnerSay( "Notecard '" + notecardName + "' does not exist, or does not have full permissions." );
        loadInProgress = FALSE;
        notecardName = EMPTY;
        return;
    }
 
    llOwnerSay( "Loading notecard '" + notecardName + "'..." );
 
    // Faster events while processing our notecard
    llMinEventDelay( 0 );
 
    // Clear out saved override information, since we now allow sparse notecards
    overrides = [];
    integer i;
    for ( i=0; i<numOverrides; i++ )
        overrides += [EMPTY];
 
    // Clear out multi-anim info as well, since we may end up with fewer options
    // that the last time
    curStandIndex = 0;
    curStandAnim = EMPTY;
    curSitAnim = EMPTY;
    curWalkAnim = EMPTY;
    curGsitAnim = EMPTY;
 
    // Start reading the data
    notecardIndex = 0;
    notecardLineKey = llGetNotecardLine( notecardName, notecardIndex );
}
 
// Stop loading notecard
endNotecardLoad()
{
    loadInProgress = FALSE;
    notecardName = EMPTY;
 
    // Restore the minimum event delay
    llMinEventDelay( minEventDelay );
}
 
// Initialize listeners, and reset some status variables
initialize() {
    Owner = llGetOwner();
 
    if ( animOverrideOn )
        llSetTimerEvent( timerEventLength );
    else
        llSetTimerEvent( 0 );
 
    lastAnim = EMPTY;
    lastAnimSet = EMPTY;
    lastAnimIndex = noAnimIndex;
    lastAnimState = EMPTY;
    gotPermission = FALSE;
 
    // Create new listener, and turn it off
    if ( listenHandle )
        llListenRemove( listenHandle );
 
    listenHandle = llListen( listenChannel, EMPTY, Owner, EMPTY );
    llListenControl( listenHandle, FALSE );
 
    printFreeMemory();
}
 
// STATE
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
 
default {
    state_entry() {
        integer i;
 
        Owner = llGetOwner();
 
        // Just a precaution, this shouldn't be on after a reset
        if ( listenHandle )
            llListenRemove( listenHandle );
 
        listenHandle = llListen( listenChannel, EMPTY, Owner, EMPTY );
 
        if ( llGetAttached() )
            llRequestPermissions( llGetOwner(), PERMISSION_TRIGGER_ANIMATION|PERMISSION_TAKE_CONTROLS );
 
        numOverrides = llGetListLength( tokens );
 
        // Type convert strings to keys :P
        for ( i=0; i<llGetListLength(autoDisableList); i++ ) {
            key k = llList2Key( autoDisableList, i );
            autoDisableList = llListReplaceList ( autoDisableList, [ k ], i, i );
        }
 
        // populate override list with blanks
        overrides = [];
        for ( i=0; i<numOverrides; i++ ) {
            overrides += [ EMPTY ];
        }
        randomStands = FALSE;
        initialize();
        notecardName = defaultNoteCard;
        loadInProgress = TRUE;
        loadNoteCard();
 
        // turn off the auto-stop anim hack
        if ( autoStopTime == 0 )
            autoStop = [];
 
        llResetTime();
    }
 
    on_rez( integer _code ) {
        initialize();
    }
 
    attach( key _k ) {
        if ( _k != NULL_KEY )
            llRequestPermissions( llGetOwner(), PERMISSION_TRIGGER_ANIMATION|PERMISSION_TAKE_CONTROLS );
    }
 
    run_time_permissions( integer _perm ) {
      if ( _perm != (PERMISSION_TRIGGER_ANIMATION|PERMISSION_TAKE_CONTROLS) )
         gotPermission = FALSE;
      else {
         llTakeControls( CONTROL_BACK|CONTROL_FWD, TRUE, TRUE );
         gotPermission = TRUE;
      }
    }
 
    link_message( integer _sender, integer _num, string _message, key _id) {
 
        // Coming from an interface script
        if ( _message == "ZHAO_RESET" ) {
            llOwnerSay( "Resetting..." );
            llResetScript();
 
        } else if ( _message == "ZHAO_AOON" ) {
            // AO On
            llSetTimerEvent( timerEventLength );
            animOverrideOn = TRUE;
            checkAndOverride();
 
        } else if ( _message == "ZHAO_AOOFF" ) {
            llSetTimerEvent( 0 );
            animOverrideOn = FALSE;
            startNewAnimation( EMPTY, noAnimIndex, lastAnimState );
            lastAnim = EMPTY;
            lastAnimSet = EMPTY;
            lastAnimIndex = noAnimIndex;
            lastAnimState = EMPTY;
 
        } else if ( _message == "ZHAO_SITON" ) {
            // Turning on sit override
            sitOverride = TRUE;
            llOwnerSay( "Sit override: On" );
            if ( lastAnimState == "Sitting" )
                startNewAnimation( curSitAnim, sittingIndex, lastAnimState );
 
        } else if ( _message == "ZHAO_SITOFF" ) {
            // Turning off sit override
            sitOverride = FALSE;
            llOwnerSay( "Sit override: Off" );
            if ( lastAnimState == "Sitting" )
                startNewAnimation( EMPTY, noAnimIndex, lastAnimState );
 
        } else if ( _message == "ZHAO_RANDOMSTANDS" ) {
            // Cycling to next stand - sequential or random
            randomStands = TRUE;
            llOwnerSay( "Stand cycling: Random" );
 
        } else if ( _message == "ZHAO_SEQUENTIALSTANDS" ) {
            // Cycling to next stand - sequential or random
            randomStands = FALSE;
            llOwnerSay( "Stand cycling: Sequential" );
 
        } else if ( _message == "ZHAO_SETTINGS" ) {
            // Print settings
            if ( sitOverride == TRUE ) {
                llOwnerSay( "Sit override: On" );
            } else {
                llOwnerSay( "Sit override: Off" );
            }
            if ( randomStands == TRUE ) {
                llOwnerSay( "Stand cycling: Random" );
            } else {
                llOwnerSay( "Stand cycling: Sequential" );
            }
            llOwnerSay( "Stand cycle time: " + (string)standTime + " seconds" );
 
        } else if ( _message == "ZHAO_NEXTSTAND" ) {
            // Cycling to next stand - sequential or random. This is from UI, so we
            // want feedback
            doNextStand( TRUE );
 
        } else if ( llGetSubString(_message, 0, 14) == "ZHAO_STANDTIME|" ) {
            // Stand time change
            standTime = (integer)llGetSubString(_message, 15, -1);
            llOwnerSay( "Stand cycle time: " + (string)standTime + " seconds" );
 
        } else if ( llGetSubString(_message, 0, 9) == "ZHAO_LOAD|" ) {
            // Can't load while we're in the middle of a load
            if ( loadInProgress == TRUE ) {
                llOwnerSay( "Cannot load new notecard, still reading notecard '" + notecardName + "'" );
                return;
            }
 
            // Notecard menu
            loadInProgress = TRUE;
            notecardName = llGetSubString(_message, 10, -1);
            loadNoteCard();
 
        } else if ( _message == "ZHAO_SITS" ) {
            // Selecting new sit anim
 
            // Move these to a common function
            doMultiAnimMenu( sittingIndex, "Sitting", curSitAnim );
 
            listenState = 1;
 
        } else if ( _message == "ZHAO_WALKS" ) {
            // Same thing for the walk
 
            // Move these to a common function
            doMultiAnimMenu( walkingIndex, "Walking", curWalkAnim );
 
            listenState = 2;
        } else if ( _message == "ZHAO_GROUNDSITS" ) {
            // And the ground sit
 
            // Move these to a common function
            doMultiAnimMenu( sitgroundIndex, "Sitting On Ground", curGsitAnim );
 
            listenState = 3;
        }
    }
 
    listen( integer _channel, string _name, key _id, string _message) {
        // Turn listen off. We turn it on again if we need to present
        // another menu
        llListenControl(listenHandle, FALSE);
 
        if ( listenState == 1 ) {
            // Dialog enhancement - Fennec Wind
            // Note that this is within one 'overrides' entry
            curSitAnim = findMultiAnim( sittingIndex, (integer)_message - 1 );
            if ( lastAnimState == "Sitting" ) {
                startNewAnimation( curSitAnim, sittingIndex, lastAnimState );
            }
            llOwnerSay( "New sitting animation: " + curSitAnim );
 
        } else if ( listenState == 2 ) {
            // Dialog enhancement - Fennec Wind
            // Note that this is within one 'overrides' entry
            curWalkAnim = findMultiAnim( walkingIndex, (integer)_message - 1 );
            if ( lastAnimState == "Walking" ) {
                startNewAnimation( curWalkAnim, walkingIndex, lastAnimState );
            }
            llOwnerSay( "New walking animation: " + curWalkAnim );
 
        } else if ( listenState == 3 ) {
            // Dialog enhancement - Fennec Wind
            // Note that this is within one 'overrides' entry
            curGsitAnim = findMultiAnim( sitgroundIndex, (integer)_message - 1 );
            // Lowercase 'on' - that's the anim name in SL
            if ( lastAnimState == "Sitting on Ground" ) {
                startNewAnimation( curGsitAnim, sitgroundIndex, lastAnimState );
            }
            llOwnerSay( "New sitting on ground animation: " + curGsitAnim );
        }
    }
 
    dataserver( key _query_id, string _data ) {
 
        if ( _query_id != notecardLineKey ) {
            llOwnerSay( "Error in reading notecard. Please try again." );
 
            endNotecardLoad();
            return;
        }
 
        if ( _data == EOF ) {
            // Now the read ends when we hit EOF
 
            // End-of-notecard handling...
 
             // Do we have a walking animation?
            if ( llList2String(overrides, walkingIndex) != EMPTY ) {
                 haveWalkingAnim = TRUE;
            }
 
            // See how many walks/sits/ground-sits we have
            checkMultiAnim( walkingIndex, "walking" );
            checkMultiAnim( sittingIndex, "sitting" );
            checkMultiAnim( sitgroundIndex, "sitting on ground" );
 
            // Reset stand, walk, sit and ground-sit anims to first entry
            curStandIndex = 0;
            numStands = llGetListLength( llParseString2List(llList2String(overrides, standingIndex),
                                         [SEPARATOR], []) );
 
            curStandAnim = findMultiAnim( standingIndex, 0 );
            curWalkAnim = findMultiAnim( walkingIndex, 0 );
            curSitAnim = findMultiAnim( sittingIndex, 0 );
            curGsitAnim = findMultiAnim( sitgroundIndex, 0 );
 
            // Clear out the currently playing anim so we play the new one on the next cycle
            startNewAnimation( EMPTY, noAnimIndex, lastAnimState );
            lastAnim = EMPTY;
            lastAnimSet = EMPTY;
            lastAnimIndex = noAnimIndex;
            lastAnimState = EMPTY;
 
            llOwnerSay( "Finished reading notecard '" + notecardName + "'." );
            printFreeMemory();
 
            endNotecardLoad();
            return;
        }
 
        // We ignore blank lines and lines which start with a #
        if (( _data == EMPTY ) || ( llGetSubString(_data, 0, 0) == "#" )) {
            notecardLineKey = llGetNotecardLine( notecardName, ++notecardIndex );
            return;
        }
 
        // Check for a valid token
        integer i;
        integer found = FALSE;
        for ( i=0; i<numOverrides; i++ ) {
            string token = llList2String( tokens, i );
            // We have some blank entries in 'tokens' to get it to line up with animState... make
            // sure we don't match on a blank.
            if (( token != EMPTY ) && ( llGetSubString( _data, 0, llStringLength(token) - 1 ) == token )) {
                // We found a token on this line, so we don't have to throw an error or keep
                // trying to match tokens
                found = TRUE;
                // Make sure the line has data after the token, or our sub-string calculation goes off
                if ( _data != token ) {
                    string animPart = llGetSubString( _data, llStringLength(token), -1 );
 
                    // See if this is a token for which we allow multiple animations
                    if ( llListFindList( multiAnimTokenIndexes, [i] ) != -1 ) {
                        list anims2Add = llParseString2List( animPart, [SEPARATOR], [] );
                        // Make sure the anims exist
                        integer j;
                        for ( j=0; j<llGetListLength(anims2Add); j++ ) {
                            checkAnimInInventory( llList2String(anims2Add,j) );
                        }
 
                        // Join the 2 lists and put it back into overrides
                        list currentAnimsList = llParseString2List( llList2String(overrides, i), [SEPARATOR], [] );
                        currentAnimsList += anims2Add;
                        overrides = llListReplaceList( overrides, [llDumpList2String(currentAnimsList, SEPARATOR)], i, i );
                    } else {
                        // This is an animation for which we only allow one override
                        if ( llSubStringIndex( animPart, SEPARATOR ) != -1 ) {
                            llOwnerSay( "Cannot have multiple animations for " + token + ". " + TRYAGAIN );
 
                            endNotecardLoad();
                            return;
                        }
 
                        // Inventory check
                        checkAnimInInventory( animPart );
 
                        // We're good
                        overrides = llListReplaceList( overrides, [animPart], i, i );
                    } // End if-else for multi-anim vs. single-anim
                } // End if line has more than just a token
 
                // Break, no need to continue the search loop
                jump done;
 
            } // End if token matched
        } // End search for tokens
 
        @done;
 
        if ( !found ) {
            llOwnerSay( "Invalid data in notecard on line " + (string)notecardIndex + ": " +
                        _data + ". " + TRYAGAIN );
 
            endNotecardLoad();
            return;
        }
 
        // Wow, after all that, we read one line of the notecard
        notecardLineKey = llGetNotecardLine( notecardName, ++notecardIndex );
        return;
    }
 
    collision_start( integer _num ) {
        checkAndOverride();
    }
 
    collision( integer _num ) {
        checkAndOverride();
    }
 
    collision_end( integer _num ) {
        checkAndOverride();
    }
 
    control( key _id, integer _level, integer _edge ) {
        if ( _edge ) {
            // SL tends to mix animations together on forward or backward walk. It could be because
            // of anim priorities. This helps stop the default walking anims, so it won't mix with
            // the desired anim. This also lets the avi turn around on a backwards walk for a more natural
            // look.
            // Reverse the order of the checks, since we'll often get the control key combination, but we
            // may be flying
            if ( llGetAnimation(Owner) == "Walking" ) {
                if ( _level & _edge & ( CONTROL_BACK | CONTROL_FWD ) ) {
                    if ( haveWalkingAnim ) {
                        llStopAnimation( "walk" );
                        llStopAnimation( "female_walk" );
                    }
                }
            }
 
            checkAndOverride();
            }
        }
 
    timer() {
        if ( checkAndOverride() ) {
            // Is it time to switch stand animations?
            // Stand cycling can be turned off
            if ( (standTime != 0) && (llGetTime() > standTime) ) {
                // Don't interrupt the typing animation with a stand change. Not from
                // UI, no feedback
                if ( llListFindList(llGetAnimationList(Owner), [typingAnim]) == -1 )
                    doNextStand( FALSE );
            }
        }
    }
}

ZHAO-II-interface 7/21.1

// ZHAO-II-interface - Ziggy Puff, 06/07
 
////////////////////////////////////////////////////////////////////////
// Interface script - handles all the UI work, sends link
// messages to the ZHAO-II 'engine' script
//
// Interface definition: The following link_message commands are
// handled by the core script. All of these are sent in the string
// field. All other fields are ignored
//
// ZHAO_RESET                          Reset script
// ZHAO_LOAD|<notecardName>            Load specified notecard
// ZHAO_NEXTSTAND                      Switch to next stand
// ZHAO_STANDTIME|<time>               Time between stands. Specified
//                                     in seconds, expects an integer.
//                                     0 turns it off
// ZHAO_AOON                           AO On
// ZHAO_AOOFF                          AO Off
// ZHAO_SITON                          Sit On
// ZHAO_SITOFF                         Sit Off
// ZHAO_RANDOMSTANDS                   Stands cycle randomly
// ZHAO_SEQUENTIALSTANDS               Stands cycle sequentially
// ZHAO_SETTINGS                       Prints status
// ZHAO_SITS                           Select a sit
// ZHAO_GROUNDSITS                     Select a ground sit
// ZHAO_WALKS                          Select a walk
//
// So, to send a command to the ZHAO-II engine, send a linked message:
//
//   llMessageLinked(LINK_SET, 0, "ZHAO_AOON", NULL_KEY);
//
////////////////////////////////////////////////////////////////////////
 
// Ziggy, 07/16/07 - Single script to handle touches, position changes, etc., since idle scripts take up
//
// Ziggy, 06/07:
//          Single script to handle touches, position changes, etc., since idle scripts take up
//          scheduler time
//          Tokenize notecard reader, to simplify notecard setup
//          Remove scripted texture changes, to simplify customization by animation sellers
 
// Fennec Wind, January 18th, 2007:
//          Changed Walk/Sit/Ground Sit dialogs to show animation name (or partial name if too long)
//          and only show buttons for non-blank entries.
//          Fixed minor bug in the state_entry, ground sits were not being initialized.
//
 
// Dzonatas Sol, 09/06: Fixed forward walk override (same as previous backward walk fix). 
 
// Based on Francis Chung's Franimation Overrider v1.8
 
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
 
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307, USA.
 
// CONSTANTS
//////////////////////////////////////////////////////////////////////////////////////////////////////////
 
// Help notecard
string helpNotecard = "READ ME FIRST - ZHAO-II";
 
// How long before flipping stand animations
integer standTimeDefault = 30;
 
// Listen channel for pop-up menu...
// should be different from channel used by ZHAO engine (-91234)
integer listenChannel = -91235;
 
integer listenHandle;                          // Listen handlers - only used for pop-up menu, then turned off
integer listenState = 0;                       // What pop-up menu we're handling now
 
// Overall AO state
integer zhaoOn = TRUE;
 
list attachPoints = [
    ATTACH_HUD_TOP_RIGHT,
    ATTACH_HUD_TOP_CENTER,
    ATTACH_HUD_TOP_LEFT,
    ATTACH_HUD_BOTTOM_RIGHT,
    ATTACH_HUD_BOTTOM,
    ATTACH_HUD_BOTTOM_LEFT
];
 
// For the on/off (root) prim
list rootPrimOffsets = [
    <0.0,  0.025, -0.05>,    // Top right
    <0.0,  0.00, -0.05>,    // Top middle
    <0.0, -0.025, -0.05>,    // Top left
    <0.0,  0.025,  0.10>,    // Bottom right
    <0.0,  0.00,  0.10>,    // Bottom middle
    <0.0, -0.025,  0.10>    // Bottom left
];
 
// For the menu (child)
list menuPrimOffsets = [
    <0.0, 0.0, -0.05>,
    <0.0, 0.0, -0.05>,
    <0.0, 0.0, -0.05>,
    <0.0, 0.0,  0.05>,
    <0.0, 0.0,  0.05>,
    <0.0, 0.0,  0.05>
];
 
vector onColor = <0.25, 1.0, 0.25>;
vector offColor = <0.5, 0.5, 0.5>;
 
// Interface script now keeps track of these states. The defaults
// match what the core script starts out with
integer sitOverride = TRUE;
integer randomStands = FALSE;
 
key Owner = NULL_KEY;
 
// CODE
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
 
// Initialize listeners, and reset some status variables
Initialize() {
    Owner = llGetOwner();
 
    // On init, open a new listener...
    if ( listenHandle )
        llListenRemove( listenHandle );
 
    listenHandle = llListen( listenChannel, "", Owner, "" );
 
    // ... And turn it off
    llListenControl(listenHandle, FALSE);
}
 
DoMenu()
{
    // The rows are inverted in the actual dialog box. This must match
    // the checks in the listen() handler
    list mainMenu = [
        "Walks", "Sits", "Ground Sits",
        "Sit On/Off", "Rand/Seq", "Stand Time",
        "Load", "Settings", "Next Stand",
        "Help", "Reset"
    ];
 
    listenState = 0;
    llListenControl(listenHandle, TRUE);
    llDialog( Owner, "Please select an option:", mainMenu, listenChannel );
}
 
DoPosition()
{
    // Using 2 for the child prim's link number... if you
    // want to add prims that need to be moved, you'll
    // have to do work here
 
    integer position = llListFindList(attachPoints, [llGetAttached()]);
    if (position != -1) {
        llSetPos((vector)llList2String(rootPrimOffsets, position));
        llSetLinkPrimitiveParams(2, [PRIM_POSITION, (vector)llList2String(menuPrimOffsets, position)]);
    }
}
 
// STATE
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
 
default {
    state_entry() {
        integer i;
 
        Initialize();
        DoPosition();
 
        // Sleep a little to let other script reset (in case this is a reset)
        llSleep(2.0);
 
        // We start out as AO ON
        zhaoOn = TRUE;
        llSetColor(onColor, 4);
        llMessageLinked(LINK_SET, 0, "ZHAO_AOON", NULL_KEY);
    }
 
    on_rez( integer _code ) {
        Initialize();
    }
 
    attach( key _k ) {
        if ( _k != NULL_KEY ) {
            DoPosition();
        }
    }
 
    touch_start( integer _num ) {
        if (llDetectedLinkNumber(0) == 2) {
            // Menu prim... use number instead of name
            DoMenu();
        } else {
            // On/Off prim
            if (zhaoOn) {
                llSetColor(offColor, 4);
                zhaoOn = FALSE;
                llMessageLinked(LINK_SET, 0, "ZHAO_AOOFF", NULL_KEY);
            } else {
                llSetColor(onColor, 4);
                zhaoOn = TRUE;
                llMessageLinked(LINK_SET, 0, "ZHAO_AOON", NULL_KEY);
            }
        }
    }
 
    listen( integer _channel, string _name, key _id, string _message) {
 
        // Turn listen off. We turn it on again if we need to present
        // another menu
        llListenControl(listenHandle, FALSE);
 
        if ( _message == "Help" ) {
            if (llGetInventoryType(helpNotecard) == INVENTORY_NOTECARD)
                llGiveInventory(Owner, helpNotecard);
            else
                llOwnerSay("No help notecard found.");
        }
        else if ( _message == "Reset" ) {
            llMessageLinked(LINK_SET, 0, "ZHAO_RESET", NULL_KEY);
            llSleep(1.0);
            llResetScript();
        }
        else if ( _message == "Settings" ) {
            llMessageLinked(LINK_SET, 0, "ZHAO_SETTINGS", NULL_KEY);
        }
        else if ( _message == "Sit On/Off" ) {
            if (sitOverride == TRUE) {
                llMessageLinked(LINK_SET, 0, "ZHAO_SITOFF", NULL_KEY);
                sitOverride = FALSE;
            } else {
                llMessageLinked(LINK_SET, 0, "ZHAO_SITON", NULL_KEY);
                sitOverride = TRUE;
            }
        }
        else if ( _message == "Rand/Seq" ) {
            if (randomStands == TRUE) {
                llMessageLinked(LINK_SET, 0, "ZHAO_SEQUENTIALSTANDS", NULL_KEY);
                randomStands = FALSE;
            } else {
                llMessageLinked(LINK_SET, 0, "ZHAO_RANDOMSTANDS", NULL_KEY);
                randomStands = TRUE;
            }
        }
        else if ( _message == "Next Stand" ) {
            llMessageLinked(LINK_SET, 0, "ZHAO_NEXTSTAND", NULL_KEY);
        }
        else if ( _message == "Load" ) {
            integer n = llGetInventoryNumber( INVENTORY_NOTECARD );
            // Can only have 12 buttons in a dialog box
            if ( n > 12 ) {
                llOwnerSay( "You cannot have more than 12 animation notecards." );
                return;
            }
 
            integer i;
            list animSets = [];
 
            // Build a list of notecard names and present them in a dialog box
            for ( i = 0; i < n; i++ ) {
                string notecardName = llGetInventoryName( INVENTORY_NOTECARD, i );
                if ( notecardName != helpNotecard )
                    animSets += [ notecardName ];
            }
 
            llListenControl(listenHandle, TRUE);
            llDialog( Owner, "Select the notecard to load:", animSets, listenChannel );
            listenState = 1;
        }
        else if ( _message == "Stand Time" ) {
            // Pick stand times
            list standTimes = ["0", "5", "10", "15", "20", "30", "40", "60", "90", "120", "180", "240"];
            llListenControl(listenHandle, TRUE);
            llDialog( Owner, "Select stand cycle time (in seconds). \n\nSelect '0' to turn off stand auto-cycling.",
                      standTimes, listenChannel);
            listenState = 2;
        }
        else if ( _message == "Sits" ) {
            llMessageLinked(LINK_SET, 0, "ZHAO_SITS", NULL_KEY);
        }
        else if ( _message == "Walks" ) {
            llMessageLinked(LINK_SET, 0, "ZHAO_WALKS", NULL_KEY);
        }
        else if ( _message == "Ground Sits" ) {
            llMessageLinked(LINK_SET, 0, "ZHAO_GROUNDSITS", NULL_KEY);
        }
        else if ( listenState == 1 ) {
            // Load notecard
            llMessageLinked(LINK_SET, 0, "ZHAO_LOAD|" + _message, NULL_KEY);
        }
        else if ( listenState == 2 ) {
            // Stand time change
            llMessageLinked(LINK_SET, 0, "ZHAO_STANDTIME|" + _message, NULL_KEY);
        }
    }
}

Magic Blocks

A fun toy and made by Philip Linden!  Hours of very fun, and pleasure.
Click and drag the block to position.  Block will snap into position when near other blocks.
Click and quickly release to make a new block above the old.

SOUND UUID 's
color = 8e9a7375-2a49-6e81-ec26-c6140891333d
off = bac3e333-9624-4b1a-ade2-d2b01d5960aa
on = 271e6a0f-0a76-230b-011e-f78a55e80c36
pulse = 21b2d9ef-8329-bb72-9eaf-35702e876797

NOTE: You will need to re-assemble this all and edit the scripts because I cannot include sounds in this post ;)

vector pos;
vector found_pos;
vector start_touch_pos;
vector diff;
vector scale;
string name_detected;
 
vector PULSE_COLOR = <1,1,1>;
 
float GRAB_ALPHA = 0.5;
float INC = 2.0;                    // Grid spacing for snap, scale
float MAX_INC = 2.5;                // Biggest dimension
 
list colors = [<1,0,0>, <0,1,0>, <0,0,1>,
                <0,1,1>, <1,0,1>, <1,1,0>];
 
//list tones = ["piano_1", "piano_3", "piano_5"];
 
vector color;
integer color_index = 0; 
 
integer CHANNEL = 3442;
integer pulse = FALSE;
integer inhibit = FALSE;
float INHIBIT_DELAY = 2.0;
float DECAY_FACTOR = 0.5;
 
send_pulse()
{
    // Change color briefly and transmit a neural 'pulse'
    inhibit = TRUE;
    llSetTimerEvent(INHIBIT_DELAY);
    //integer tone = llRound(llFrand((float)(llGetListLength(tones) - 1)));
    //llTriggerSound(llList2String(tones, tone), 1.0);
    llSetColor(PULSE_COLOR, ALL_SIDES);
    llSetObjectName("Magic Block P");
    llWhisper(CHANNEL, "pulse");
}
 
vector vec_round(vector vec, float inc)
{
    //  Rounds vector components to the nearest units of inc
    vec *= 1.0/inc;
    vec.x = ((float)llRound(vec.x));
    vec.y = ((float)llRound(vec.y));
    vec.z = ((float)llRound(vec.z));
    vec *= inc;
    return vec;
}
 
set_pos()
{
   //
   //  On finding a neighbor, snap relative to neighbor
   //
   pos = llGetPos();
    llSetColor(color*0.5, ALL_SIDES);
    diff = pos - found_pos;
    diff = vec_round(diff, INC/2.0);
    diff += found_pos;
    llSetPos(diff);
    llTriggerSound("on", 1.0);
    llSetColor(color, ALL_SIDES);
}
 
vector new_color()
{
    integer num_colors = llGetListLength(colors);
    color_index++;
    if (color_index >= num_colors) color_index = 0;
    return llList2Vector(colors, color_index);
}
 
snap()
{
    //  Issues the sensor to look for nearby blocks to snap to
    float range = 3.0;
    llSensor("Magic Block", "", PASSIVE | SCRIPTED, range, 2.0*PI);
}
 
default
{
    state_entry()
    {
        scale = llGetScale();
        color = new_color();
        llSetColor(color, ALL_SIDES);
        llSetStatus(STATUS_BLOCK_GRAB, FALSE);
        llSetBuoyancy(1.0);
        llListen(CHANNEL, "", "", "pulse");
    }
 
    on_rez(integer param)
    {
        found_pos = llGetPos();
        set_pos();
        snap();
    }
 
    timer()
    {
        llSetObjectName("Magic Block");
        llSetTimerEvent(0.0);
        inhibit = FALSE;
        llSetColor(color, ALL_SIDES);
    }
 
    changed(integer change)
    {
        if (change == CHANGED_SCALE)
        {
            scale = llGetScale();
            scale = vec_round(scale, INC);
            if (scale.x == 0.0) scale.x = INC;
            if (scale.y == 0.0) scale.y = INC;
            if (scale.z == 0.0) scale.z = INC;
            if (scale.x > MAX_INC) scale.x = MAX_INC;
            if (scale.y > MAX_INC) scale.y = MAX_INC;
            if (scale.z > MAX_INC) scale.z = MAX_INC;
            llSay(0, "new scale = " + (string)scale);
            llSetScale(scale);
            // Choose a new color for the block
            snap();
        }
    }
 
    touch_start(integer total_number)
    {
        start_touch_pos = llGetPos();
        llSetAlpha(GRAB_ALPHA, ALL_SIDES);
        llTriggerSound("on", 1.0);
        llResetTime();
        llSetStatus(STATUS_PHYSICS, FALSE);
    }
    touch_end(integer total_number)
    {
        llSetStatus(STATUS_PHYSICS, FALSE);
        llSetAlpha(1.0, ALL_SIDES);
        vector moved = llGetPos() - start_touch_pos;
 
        if (llGetTime() < 0.3)
        {
            //  Cycle colors on short click
            llSetPos(start_touch_pos);
            llTriggerSound("color", 1.0);
            color = new_color();
            llSetColor(color, ALL_SIDES);
        }
        else if (llVecMag(moved) < (INC/10.0))
        {
            llSetPos(start_touch_pos);
            send_pulse();
        }
        else
        {
            // Try to find a block to stick to!
            llSetColor(color, ALL_SIDES);
            snap();
        }
        llSetRot(<0,0,0,1>);
    }
 
    listen(integer channel, string name, key id, string message)
    {
        // Received neural pulse, so sense sender's distance
        if (!inhibit)
        {
            pulse = TRUE;
            llSensor("Magic Block P", id, PASSIVE | SCRIPTED, 10.0, 2.0*PI);
        }
    }
 
    no_sensor()
    {
        pulse = FALSE;
    }
    sensor(integer num_detected)
    {
        if (!pulse)
        {
            //
            //  Rotate/snap to nearest box
            //
            //  Issue scale request to this box
            //
            found_pos = llDetectedPos(0);
            set_pos();
        }
        else
        {
            //
            //  Gauge distance to nearest box, decide whether to 'fire'
            //
            pulse = FALSE;
            pos = llGetPos();
            found_pos = llDetectedPos(0);
            diff = pos - found_pos;
            // probability of neural firing is related to distance
            float distance = llVecMag(diff);
            if (distance > 0.0)
            {
                if (distance < INC)
                //if (llFrand(1.0) < ((INC/(distance*distance))*DECAY_FACTOR))
                {
                    send_pulse();
                }
            }
        }
    }
}

Improved Locking Door

//          Improved locking door script
//
//              Started by: Eric Linden
//           Modified by: Bjorn Nordlicht
//
//My friend wanted a decent locking door script for his new
//  home but we could only find broken free scripts.
//  This script has been modified so it works well enough.
//
 
//Seconds before open door will close on it's own
float timeout = 360.0;
 
// This number must match the channel number of the lock
// and unlock objects you want to use.  If multiple doors
// have the same channel, then a single lock can lock all of
// them at once.
integer gLockChannel = 243;
 
integer locked = FALSE;
 
door(integer doorState)
{
    rotation rot = llGetRot();
    rotation delta = llEuler2Rot(<0,0,doorState*PI/3>);
    rot = delta * rot;
    llSetRot(rot);
 
    llSleep(0.25);
    rot = delta * rot;
    llSetRot(rot);
}
 
default
{
    on_rez(integer param)
    {
        llResetScript();
    }
 
    state_entry()
    {
        llOwnerSay("Door: Say lock or unlock on channel "+(string)gLockChannel);
        state closed;
    }
}
 
state closed
{
    on_rez(integer param)
    {
        llResetScript();
    }
 
    state_entry()
    {
        llListen(gLockChannel, "", llGetOwner(), "");
        //Close door
        //    llTriggerSound("Door close", 0.5);
        door(-1);
    }
 
    listen(integer channel, string name, key id, string message)
    {
        if (channel == gLockChannel)
        {
            if (message == "unlock")
            {
                locked = FALSE;
                //llTriggerSound("door unlock", 10.0);
                llSay(0, "unlocked");
            }
            else if(message == "lock")
            {
                locked = TRUE;
                //llTriggerSound("door lock", 10.0);
                llSay(0, "locked");
            }
        }
    }
 
    touch_start(integer total_number)
    {
        key id = llDetectedKey(0);
        if (id == llGetOwner() || !locked)
        {
    //        llTriggerSound("Door open", 0.5);
            state open;
        }
        else
        {
     //       llTriggerSound("Door knock", 0.5);
        }
    }
}
 
state open
{
    on_rez(integer param)
    {
       llResetScript();
    } 
 
    state_entry()
    {
        //Open door
        door(1);
        llSetTimerEvent(timeout);
    }
 
    touch_start(integer num)
    {
        state closed;
    }
 
    timer()
    {
        state closed;
    }
 
}

Animation Script Example

////////////////////////////////////////////
// Animation Script v1.2.1
//
// Written by Xylor Baysklef
////////////////////////////////////////////
 
/////////////// CONSTANTS ///////////////////
list ANIMATIONS  = [ "aim_L_bow", "aim_R_bazooka", "aim_R_handgun", "aim_R_rifle", "angry_fingerwag",
"angry_tantrum", "away", "backflip", "blowkiss", "bow", "brush", "clap",
"courtbow", "cross_arms", "crouch", "crouchwalk", "curtsy",
"dance1", "dance2", "dance3", "dance4", "dance5", "dance6", "dance7", "dance8",
"dead", "drink", "express_afraid", "express_anger", "express_bored",
"express_cry", "express_embarrased", "express_laugh", "express_repulsed",
"express_sad", "express_shrug", "express_surprise", "express_wink",
"express_worry", "falldown", "female_walk", "fist_pump", "fly", "flyslow",
"hello", "hold_R_bow", "hold_R_bazooka", "hold_R_handgun", "hold_R_rifle",
"hold_throw_R", "hover", "hover_down", "hover_up", "impatient",
"jump", "jumpforjoy", "kick_roundhouse_R", "kissmybutt", "kneel_left",
"kneel_right", "land", "laugh_short", "motorcycle_sit", "musclebeach", "no_head", "no_unhappy",
"nyanya", "peace", "point_me", "point_you" ];
 
list ANIMATIONS2 = [ "prejump", "punch_L", "punch_onetwo", "punch_R",
"RPS_countdown", "RPS_paper", "RPS_rock",
"RPS_scissors", "run", "salute", "shoot_L_bow", "shout", "sit", "sit_female", "sit_ground",
"sit_to_stand", "sleep", "slowwalk", "smoke_idle", "smoke_inhale", "smoke_throw_down",
"snapshot", "soft_land", "stand", "standup", "stand_1", "stand_2",
"stand_3", "stand_4", "stretch", "stride", "surf", "sword_strike_R",
"talk", "throw_R", "tryon_shirt", "turnback_180", "turnleft", "turnright",
"turn_180", "type", "uphillwalk", "walk", "whisper", "whistle", "wink_hollywood", "yell",
"yes_happy", "yes_head", "yoga_float" ];
///////////// END CONSTANTS /////////////////
 
///////////// GLOBAL VARIABLES ///////////////
//integer gToggle = 0;
integer gAnimNumber;
integer gTotalAnims;
 
string gAnimName = "type";
/////////// END GLOBAL VARIABLES /////////////
 
default {
    state_entry() {
        //llSay(0, "Init...");
        llRequestPermissions(llGetOwner(), PERMISSION_TRIGGER_ANIMATION);
 
        ANIMATIONS += ANIMATIONS2;
        ANIMATIONS2 = [];
 
        gTotalAnims = llGetListLength(ANIMATIONS);
        gAnimNumber = -1;
        llListen(0, "", llGetOwner(), "");
    }
 
    on_rez(integer param) {
        //llGiveInventory(llGetOwner(), "Animation Names");
        llResetScript();
    }
 
    listen(integer channel, string name, key id, string mesg) {
        string preamble = llGetSubString(mesg, 0, 3);
        if (preamble != "anim" && preamble != "stop")
            return;
 
        integer perm = llGetPermissions();
 
        if ( !(perm & PERMISSION_TRIGGER_ANIMATION)) {
            llRequestPermissions(llGetOwner(), PERMISSION_TRIGGER_ANIMATION);
            return;
        }
 
        list parsed = llParseString2List(mesg, [ " " ], []);
        //llSay(0, (string)parsed);
 
        string anim = llList2String(parsed, 1);
 
        if (preamble == "stop") {
            //llSay(0, "Stopping: " + llGetAnimation(llGetOwner()));
            //llStopAnimation(llGetAnimation(llGetOwner()));
            if (anim == "")
                anim = gAnimName;
 
            if (anim == "all") {
                integer i;
                llSay(0, "Stopping all animations... please wait.");
                for (i=0; i<gTotalAnims; i++)
                    llStopAnimation(llList2String(ANIMATIONS, i));
 
                llSay(0, "Done.");
 
                return;
            }
 
            //llSay(0, "Stopping: " + anim);
            llStopAnimation(anim);
            return;
        }
 
        gAnimName = anim;
        //llSay(0, "Animation: " + gAnimName);
        llStartAnimation(gAnimName);
    }
 
    run_time_permissions(integer perm) {
        //llStopAnimation(gAnimName);
        //gToggle = 0;
    }
 
    attach(key id) {
        integer perm = llGetPermissions();
 
        if (id != NULL_KEY) {        
 
            if (! (perm & PERMISSION_TRIGGER_ANIMATION)) {
                llRequestPermissions(llGetOwner(), PERMISSION_TRIGGER_ANIMATION);
            }
        }
        else {
 
            if (perm & PERMISSION_TRIGGER_ANIMATION) {
                llStopAnimation(gAnimName);
            }
        }
    }
 
    touch_start(integer total_number) {
        if (llDetectedKey(0) != llGetOwner())
            return;
 
        integer perm = llGetPermissions();
 
        if (perm & PERMISSION_TRIGGER_ANIMATION) {
            if (gAnimNumber != -1) {
                llStopAnimation( llList2String(ANIMATIONS, gAnimNumber) );
            }
 
            gAnimNumber++;
            if (gAnimNumber == gTotalAnims)
                gAnimNumber = 0;
 
            gAnimName = llList2String(ANIMATIONS, gAnimNumber);
 
            llStartAnimation( gAnimName );
            llSay(0, "Animation: " + gAnimName);
        }
        else {
            llRequestPermissions(llGetOwner(), PERMISSION_TRIGGER_ANIMATION);
        }
    }
}