Code: Puppeteer Animator

puppeteer_animator.lsl
///////////////////////////////////////////////////////////////////////////
//  Copyright (C) Wizardry and Steamworks 2011 - License: GNU GPLv3      //
//  Please see: http://www.gnu.org/licenses/gpl.html for legal details,  //
//  rights of fair usage, the disclaimer and warranty conditions.        //
///////////////////////////////////////////////////////////////////////////
 
string pupData;
key pQuery;
integer line;
 
list pos = [];
list rot = [];
 
default {
 
    state_entry() {
        if(llGetInventoryType("Puppet") != INVENTORY_NOTECARD) {
            llSay(DEBUG_CHANNEL, "Could not find a notecard named Puppet");
            return;
        }
        pQuery = llGetNotecardLine("Puppet", line);
    }
 
    dataserver(key query_id, string data) {
        if (query_id != pQuery) return;
        if (data == EOF) {
            list tPup = llParseString2List(pupData, ["[K]"], [""]);
            pos = llParseString2List(llList2String(tPup, 0), ["#"], [""]);
            rot = llParseString2List(llList2String(tPup, 1), ["#"], [""]);
            // GC
            pupData = "";
            return;
        }
        if(data == "") jump next;
        pupData += data;
@next;
        pQuery = llGetNotecardLine("Puppet", ++line);
    }
    touch_start(integer num) {
        state start;
    }
 
    on_rez(integer num) { 
        llResetScript(); 
    }
 
    changed(integer change) {
        if(change & CHANGED_INVENTORY)
            llResetScript();
    }
}
 
state start
{
    state_entry() {
        llSetTimerEvent(1);
    }
 
    touch_start(integer num) {
        state stop;
    }
 
    timer() {
        vector p = (vector)llList2String(pos, 0);
        pos = llDeleteSubList(pos, 0, 0);
        pos += p;
        rotation r = (rotation)llList2String(rot, 0);
        rot = llDeleteSubList(rot, 0, 0);
        rot += r;
        llSetPos(p);
        llSetLocalRot(r);
    }
 
    on_rez(integer num) { 
        llResetScript(); 
    }
 
    changed(integer change) {
        if(change & CHANGED_INVENTORY)
            llResetScript();
    }
}
 
state stop {
    touch_start(integer num) {
        state start;
    }
}

If you wish to stop the animation once you have added the [K] Puppeteer Animator script and the notecard, simply delete them both from the prim and the animation will stop. The [K] Puppeteer Recorder script also provides some more useful tools: ◆ Wipe ◆ will delete all the recorded data, ◆ Undo ◆ will remove a step, this works multiple times on a stack-based principle and ◆ Preview ◆ which will allow you to preview the animation itself on the recorder before dumping the data, saving to the notecard and adding the [K] Puppeteer Animator script.

You can also hotswap the path-notecards you generated with the [K] Puppeteer Recorder script by replacing the notecard in the inventory of the primitive.

The script could certainly be extended to include more parameters and perhaps even delays. However, for some basic puppeteering it should work just fine and most of the time positions and rotations is most of what you need. If you need any help setting this up, feel free to contact Wizardry and Steamworks in-world.