GridTalk.de

Normale Version: Mirrorscript von Aine Caoimhe
Du siehst gerade eine vereinfachte Darstellung unserer Inhalte. Normale Ansicht mit richtiger Formatierung.
Hier ein schönes Mirror Script, wurde von Spike gefunden, werde es mal hier unterbringen, da es im Blog von der Aime ein bisschen unglücklich eingebunden wurrde.

Code:
// Mirror script
// by Aine Caoimhe (c. LACM) July 2015
// Provided under Creative Commons Attribution-Non-Commercial-ShareAlike 4.0 International license.
// Please be sure you read and adhere to the terms of this license: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// When an avatar sits on an object containing this script the avi will be cloned to an NPC who will also sit
// Paired aniamtions supplied in the object will be played, making it appear as though the NPC is the mirrored user
// If the sitter touches the mirror it will advance to the next pose (if there are more to play)
// when the sitter stands, the NPC is removed
// (Note: if sitter changes appearance during use the NPC will not change to copy that change...it will continue to appear as intiailly rezzed)
//
// Place this script in the ROOT prim which can either be the mirror object itself or ain invisible prim placed at that location.
// It is assumed that the root prim's XZ-plane is the axis to be mirrored
//
// Add animations to the contents of the root prim in pairs where each pair consists of:
//      - an animation for the sitter to play
//      - an animation that mirrors this, that has the IDENTICAL NAME with " mirror" (including the leading space) added after it
//      example: "sit 1" and "sit 1 mirror"
// DO NOT have a main sitter pose end with the word mirror because it would be interpretted as being a mirror pose and ignored
//
// ***** IF YOU ADD OR REMOVE ANIMATIONS YOU WILL NEED TO RESET THE SCRIPT TO PICK UP THE CHANGES!!! *****
//
// The sitter's pose position is determined by the base sitPos and sitRot settings (see user settings section below) UNLESS you
// overide these for an animation by placing new values in the DESCRIPTION field of the main pose in the format:
//      <sitpose>::<sit rot>        <--- note the double colon separator between position and rotation
//                                  example:  <0.0, 1.0, 0.0>::<0.0, 0.0, 0.0, 1.0>
// at which point the sitter will be moved to that sit target posision instead
//
// In all cases, the clone (mirror NPC) will be positioned exactly 180 rotated around the root prim's LOCAL Z axis
// If you have already rotated the mirror pose animation on axis when creating the mirror and do not need it subequently rotated
// when the clone NPC plays it, set the user variable mirrorRot to FALSE, otherwise leave it TRUE (this applies to all animations played
// so you can't use a mixture of both, sorry)
//
// USER SETTINGS
// use something like the Magic Sit Kit to set the value of these two
integer sayPoseName=TRUE;                   // TURE = owner will be told the name of the pose each time one is activated, FALSE = mirror will be silent
integer userName=FALSE;                     // TRUE = NPC will have the sitter's name, FALSE = NPC will have empty name
vector sitPos=<0.0, 1.0, 0.0>;              // base sit target position to set for the main sitter relative to the mirror - NPC clone will mirror this position on the opposite side of the mirror
rotation sitRot=<0.0, 0.0, 0.0, 1.0>;       // base sit target rotation to set for the main sitter relative to the mirror - NPC clone will mirror this on the opposite side of the mirror
integer mirrorRot=TRUE;     // FALSE = the mirror animations you are supplying are already rotated on root; TRUE = they need to be rotated by the script
string baseAn="*****base__stand priority 1";    // name of a base priority 1 animation to use for underlying synch (no mirror pose of it is needed)
//
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
// DO NOT CHANGE ANYTHING BELOW HERE UNLESS YOU KNOW WHAT YOU'RE DOING
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
list poses;
list mirrors;
integer anIndex;
key user;
key npc;
integer linkNpc;
integer linkUser;

updatePositions()
{
    vector pos=sitPos;
    rotation rot=sitRot;
    // see if this pose requires position override
    string posOverride=osGetInventoryDesc(llList2String(poses,anIndex));
    if (llSubStringIndex(posOverride,"::")>=0)
    {
        list orData=llParseString2List(posOverride,["::"],[]);
        pos=llList2Vector(orData,0);
        rot=llList2Rot(orData,1);
    }
    vector size = llGetAgentSize(user);
    float fAdjust = ((((0.008906 * size.z) + -0.049831) * size.z) + 0.088967) * size.z;
    vector newPos=(pos + <0.0, 0.0, 0.4>) - (llRot2Up(rot) * fAdjust);
    llSetLinkPrimitiveParamsFast(linkUser, [PRIM_POS_LOCAL,newPos,PRIM_ROT_LOCAL, rot]);
    newPos.y=-newPos.y;
    if (mirrorRot)
    {
        vector aviRot=llRot2Euler(rot);
        aviRot.z=-aviRot.z;
        aviRot.x=-aviRot.x;
        rot =llEuler2Rot(aviRot);
    }
    llSetLinkPrimitiveParamsFast(linkNpc, [PRIM_POS_LOCAL,newPos,PRIM_ROT_LOCAL, rot]);
    if (sayPoseName) llOwnerSay("New pose: "+llList2String(poses,anIndex));
}
buildPoseList()
{
    list an;
    poses=[];
    mirrors=[];
    integer i=llGetInventoryNumber(INVENTORY_ANIMATION);
    while (--i>=0) { an=[]+[llGetInventoryName(INVENTORY_ANIMATION,i)]+an; }
    i=llListFindList(an,[baseAn]);
    if (i==-1)
    {
        llOwnerSay("ERROR! Unable to locate the base priototy 1 aniamtion: "+baseAn);
        user="ERROR";
    }
    else an=[]+llDeleteSubList(an,i,i);
    i=llGetListLength(an);
    while (--i>=0)
    {
        string name=llList2String(an,i);
        if (llGetSubString(name,-7,-1)!=" mirror")
        {
            integer m=llListFindList(an,[name+" mirror"]);
            if (m==-1) llOwnerSay("WARNING: found an animation with the name \""+name+"\" but no matching animation was located");
            else
            {
                poses=[]+[name]+poses;
                mirrors=[]+[name+" mirror"]+mirrors;
            }
        }
    }
    // double-check even though mismatch ought to be impossible;
    if (llGetListLength(poses)!=llGetListLength(mirrors))
    {
        llOwnerSay("ERROR! Somehow build pose and mirror lists with mismatched lengths. Dump of data:\n\nPOSES: "+llDumpList2String(poses,", ")+"\nMIRRORS: "+llDumpList2String(mirrors,", "));
        user="ERROR";
    }
    else
    {
        anIndex=0;
        if (llGetListLength(poses)==1) llOwnerSay("Pose list built. Found only 1 mirrored pose in inventory so disabling touch advance");
        else llOwnerSay("Pose list built. Found "+(string)llGetListLength(poses)+" mirrored pose in inventory");
    }
}
cleanSitters()
{
    user=NULL_KEY;
    npc=NULL_KEY;
    integer l=llGetNumberOfPrims();
    while (l>0)
    {
        key who=llGetLinkKey(l);
        if (llGetAgentSize(who)==ZERO_VECTOR) l=0; // agents are always the last link numbers
        else
        {
            if (osIsNpc(who)) osNpcRemove(who);
            else
            {
                llRegionSayTo(who,0,"Sorry, the system has been reset so you will need to sit down again");
                llUnSit(who);
            }
        }
        l--;
    }
}
default
{
    state_entry()
    {
        buildPoseList();
        llSitTarget(<0.0, 0.0, 0.000001>,ZERO_ROTATION);
        llSetClickAction(CLICK_ACTION_SIT);
        if (user=="ERROR") llOwnerSay("Cannot active device until animation list building errors are correct");
        else cleanSitters();
    }
    on_rez(integer foo)
    {
        llResetScript();
    }
    touch_start(integer num)
    {
        key who=llDetectedKey(0);
        if (who!=user)
        {
            if (user==NULL_KEY) llRegionSayTo(who,0,"Please sit on me to use me");
            else llRegionSayTo(who,0,"Sorry, only the current user can touch me");
        }
        else
        {
            if (llGetListLength(poses)==1) return;   // with only 1 pose no changing
            osAvatarStopAnimation(user,llList2String(poses,anIndex));
            osAvatarStopAnimation(npc,llList2String(mirrors,anIndex));
            anIndex++;
            if (anIndex>=llGetListLength(poses)) anIndex=0;
            osAvatarPlayAnimation(user,llList2String(poses,anIndex));
            osAvatarPlayAnimation(npc,llList2String(mirrors,anIndex));
            updatePositions();
        }
    }
    changed (integer change)
    {
        if (change & CHANGED_OWNER) llResetScript();
        if (change & CHANGED_REGION_START) llResetScript();
        if (change & CHANGED_INVENTORY) llOwnerSay("Detected a change in inventory. Remember to reset the script if you have changed the animations");
        if (change & CHANGED_LINK)
        {
            // find out who is currently sitting
            list aviSitters=[];
            list npcSitters=[];
            integer l=llGetNumberOfPrims();
            while (l>0)
            {
                key who=llGetLinkKey(l);
                if (llGetAgentSize(who)==ZERO_VECTOR) l=0;  // sitters are always last links
                else
                {
                    if (osIsNpc(who))
                    {
                        npcSitters=[]+[who]+npcSitters;
                        if (who==npc) linkNpc=l;
                    }
                    else
                    {
                        aviSitters=[]+[who]+aviSitters;
                        if (who==user) linkUser=l;
                    }
                }
                l--;
            }
            if (user==NULL_KEY)
            {
                l=llGetListLength(npcSitters);
                while (--l>=0) { osNpcRemove(llList2Key(npcSitters,l)); }
                npc=NULL_KEY;
                if (llGetListLength(aviSitters)==0)
                {
                    llSetClickAction(CLICK_ACTION_SIT); // back to sit as default action
                    return;     // link change triggered by user standing or a change in some other linkset action
                }
                // getting here means a new avi sat
                user=llList2Key(aviSitters,0);
                osAvatarPlayAnimation(user,baseAn); // initiate base an
                llSetClickAction(CLICK_ACTION_TOUCH);   // now in use so default action should be touch
                string first=" ";
                string last=" ";
                if (userName)
                {
                    string nameToParse=llList2String(llGetObjectDetails(user,[OBJECT_NAME]),0);
                    list parsedName=llParseString2List(nameToParse,[" ",".","@"],[]);
                    first=llList2String(parsedName,0);
                    last=llList2String(parsedName,1);
                }
                npc=osNpcCreate(first,last,llGetPos()+<0.0,0.0,1.0>,user);
                osAvatarPlayAnimation(npc,baseAn);
                osNpcSit(npc,llGetKey(),OS_NPC_SIT_NOW);
                // everything else handled when NPC is detected as sitting
            }
            else if (user=="ERROR")
            {
                l=llGetListLength(npcSitters);
                while (--l>=0) { osNpcRemove(llList2Key(npcSitters,l)); }
                l=llGetListLength(aviSitters);
                while (--l>=0)
                {
                    llRegionSayTo(llList2Key(aviSitters,l),0,"Sorry, the mirror has encountered an error and needs to be reset");
                    llUnSit(llList2Key(aviSitters,l));
                }
            }
            else
            {
                // we already have a user on record
                if (llListFindList(aviSitters,[user])==-1)
                {
                    // but no longer sitting so need to release animations, clear user, and remove NPC
                    if (llGetAgentSize(user)!=ZERO_VECTOR)
                    {
                        osAvatarPlayAnimation(user,"Stand");
                        osAvatarStopAnimation(user,llList2Key(poses,anIndex));
                        osAvatarStopAnimation(user,baseAn);
                    }
                    user=NULL_KEY;
                    if (osIsNpc(npc))
                    {
                        osNpcRemove(npc);
                        npc=NULL_KEY;
                    }
                    llSetClickAction(CLICK_ACTION_SIT); // back to sit as default action
                }
                // make sure someone else didn't sit down when user was set
                l=llGetListLength(aviSitters);
                while (--l>=0)
                {
                    if (llList2Key(aviSitters,l)!=user)
                    {
                        llRegionSayTo(llList2Key(aviSitters,l),0,"Sorry, the mirror is already being used by someone else");
                        llUnSit(llList2Key(aviSitters,l));
                    }
                }
                // prevent any NPC from sitting other than the current one on record
                l=llGetListLength(npcSitters);
                while (--l>=0) { if (llList2Key(npcSitters,l)!=npc) osNpcRemove(llList2Key(npcSitters,l)); }
                if ((npc!=NULL_KEY) && osIsNpc(npc))
                {
                    // most of the time we only get here if a new NPC sat after initial creation so this should trigger start of animation
                    // need to wait briefly for base an to kick in
                    llSleep(0.25);
                    // then clear any existing AO/sit animations
                    key dontStop=llGetInventoryKey(baseAn);
                    list anToStop=llGetAnimationList(user);
                    l=llGetListLength(anToStop);
                    while (--l>=0) { if (llList2Key(anToStop,l)!=dontStop) osAvatarStopAnimation(user,llList2Key(anToStop,l)); }
                    anToStop=[]+llGetAnimationList(npc);
                    l=llGetListLength(anToStop);
                    while (--l>=0) { if (llList2Key(anToStop,l)!=dontStop) osAvatarStopAnimation(npc,llList2Key(anToStop,l)); }
                    // now start the mirrored animations
                    osAvatarPlayAnimation(user,llList2String(poses,anIndex));
                    osAvatarPlayAnimation(npc,llList2String(mirrors,anIndex));
                    updatePositions();
                }
            }
        }
    }
}

Das Script steht unter Creative Commons Attribution-Non-Commercial-ShareAlike 4.0 International license. http://ainetutorials.blogspot.de/2015/07...cript.html