AO Flip Mod

Written by Kitsune
// Francis wuz here
//
// modded by FliperPA to cut down on lag by 1000% without cutting much performance
// also set to listen on alternate channel to stop server parsing everything wearer says in chat
// GREAT WORK FRANCIS! :-)
//
// MOD THE NEXT LINE TO CHOOSE WHICH CHANNEL TO RUN ON
integer LISTEN_CHANNEL = 1904;
// Default notecard we read on script_entry
string defaultNoteCard = "*Default Anims";
//
// Don't ask me for tech support. I won't give it.
// Copyright (C) 2004 Francis Chung
//
// 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  U

// 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" ];
                  
// Index of interesting animations
integer standIndex      = 20;
integer sittingIndex    = 1;
integer sitgroundIndex  = 0;
integer hoverIndex      = 12;
integer flyingIndex     = 11;
integer flyingslowIndex = 10;
integer hoverupIndex    = 9;
integer hoverdownIndex  = 8;
integer waterTreadIndex = 25;
integer swimmingIndex   = 26;
integer swimupIndex     = 27;
integer swimdownIndex   = 28;
integer standingupIndex = 6;

// 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];

// list of animation states that we need to stop the default animations for
list stopAnimState = [ "Sitting", "Sitting on Ground" ];

// corresponding list of animations to stop when entering that state
list stopAnimName  = [ "sit", "sit_ground" ];

// Lines in the notecards where to grab animation names
// This list is indexed the same as list overrides
list lineNums = [ 45, // 0  Sitting on Ground
                  33, // 1  Sitting
                   1, // 2  Striding
                  17, // 3  Crouching
                   5, // 4  CrouchWalking
                  39, // 5  Soft Landing
                  41, // 6  Standing Up
                  37, // 7  Falling Down
                  19, // 8  Hovering Down
                  15, // 9  Hovering Up
                  43, // 10 FlyingSlow
                   7, // 11 Flying
                  31, // 12 Hovering
                  13, // 13 Jumping
                  35, // 14 PreJumping
                   3, // 15 Running
                  11, // 16 Turning Right
                   9, // 17 Turning Left
                   1, // 18 Walking
                  39, // 19 Landing
                  21, // 20 Standing 1
                  23, // 21 Standing 2
                  25, // 22 Standing 3
                  27, // 23 Standing 4
                  29, // 24 Standing 5
                  47, // 25 Treading Water
                  49, // 26 Swimming
                  51, // 27 Swim up
                  43  // 28 Swim Down
                ];

// 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
float autoStopTime = 1.5;

// List of stands                      
list    standIndexes    = [ 20, 21, 22, 23, 24 ];

// How long before flipping stand animations
float standTime = 40.0;

// How fast we should poll for changed anims, changed by FlipperPA to cut lag
// Changed from 0.001 to 0.25
// running at 0.001 doesn't have much benefit; it causes the server to process 1000 times a second
// 0.25 causes server to process only 4 times a second, which in a streaming environment
// should be just fine, with almost no affect noticed by the end user. The cost to the server versus
// benefit to the user is a good chance, IMHO. :-)
float timerEventLength = 0.25;

// Send a message if we encounter a state we've never seen before
integer DEBUG = TRUE;

// GLOBALS
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

list stands = [ "", "", "", "", "" ];          // List of stand animations
integer curStandIndex = 0;                     // Current stand we're on (indexed [0, numStands])
string curStandAnim = "";                      // Current Stand animation
integer numStands;                             // # of stand anims we use (constant: ListLength(stands))
integer curStandAnimIndex = 0;                 // Current stand we're on (indexed [0, numOverrides] )

list overrides = [];                           // List of animations we override
list notecardLineKey = [];                     // notecard reading keys
integer notecardLinesRead;                     // number of notecard lines read
integer numOverrides;                          // # of overrides (a constant - llGetListLength(lineNums))

string  lastAnim = "";                         // last Animation we ever played
integer lastAnimIndex = 0;                     // index of the last animation we ever played
string  lastAnimState = "";                    // last thing llGetAnimation() returned


integer animOverrideOn = TRUE;                 // Is the animation override on?
integer gotPermission  = FALSE;                // Do we have animation permissions?

integer listenHandler0;                        // Listen handlers

// CODE
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
list listReplace ( list _source, list _newEntry, integer _index ) {
    return llListInsertList( llDeleteSubList(_source,_index,_index), _newEntry, _index );
}

startNewAnimation( string _anim, integer _animIndex, string _state ) {
    if ( _anim != lastAnim ) {
        if ( _anim != "" ) {   // Time to play a new animation
            llStartAnimation( _anim );
            
            if ( _state != lastAnimState && llListFindList(stopAnimName, [_state]) != -1 ) {
                // Stop the default sit/sit ground animation
                llStopAnimation( llList2String(stopAnimName, llListFindList(stopAnimName, [_state])) );
            } 
            else 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 != "" ) {
                    llStopAnimation( lastAnim );
                    lastAnim = "";
                }
                llSleep( autoStopTime );
                llStopAnimation( _anim );
            }
        }
        if ( lastAnim != "" )
            llStopAnimation( lastAnim );
        lastAnim = _anim;
    }
    lastAnimIndex = _animIndex;
    lastAnimState = _state;
}

// Load all the animation names from a notecard
loadNoteCard( string _notecard ) {
    integer i;
    
    if ( llGetInventoryKey(_notecard) == NULL_KEY ) {
        llSay( 0, "Notecard '" + _notecard + "' does not exist." );
        return;
    }

    llInstantMessage( llGetOwner(), "Loading notecard '" + _notecard + "'..." );
    // Start reading the data
    notecardLinesRead = 0;
    notecardLineKey = [];
    for ( i=0; i curPos.z )
            curAnimIndex = llList2Integer( underwaterOverride, underwaterAnimIndex );
        startNewAnimation( llList2String(overrides,curAnimIndex), curAnimIndex, curAnimState );
    }
}

// Initialize listeners, and reset some status variables
initialize() {
    if ( animOverrideOn )
        llSetTimerEvent( timerEventLength );
    else
        llSetTimerEvent( 0 );
    lastAnim = "";
    lastAnimIndex = -1;
    lastAnimState = "";
    gotPermission = FALSE;
    if ( listenHandler0 )
        llListenRemove( listenHandler0 );
    listenHandler0 = llListen( LISTEN_CHANNEL, "", llGetOwner(), "" );
}

// STATE
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

default {
    state_entry() {
        integer i;
        
        if ( llGetAttached() )
            llRequestPermissions(llGetOwner(),PERMISSION_TRIGGER_ANIMATION|PERMISSION_TAKE_CONTROLS);
            
        // Initialize!
        numStands = llGetListLength( stands );
        numOverrides = llGetListLength(lineNums);
        curStandAnimIndex = llList2Integer(standIndexes,curStandIndex);

        // populate override list with blanks
        for ( i=0; i standTime ) {
                curStandIndex = (curStandIndex+1) % numStands;
                curStandAnimIndex = llList2Integer(standIndexes,curStandIndex);
                curStandAnim = llList2String(overrides, curStandAnimIndex);
                if ( lastAnimState == "Standing" )
                    startNewAnimation( curStandAnim, curStandAnimIndex, lastAnimState );
                llResetTime();
            }
        }
    }
}