[Aide] Synchoniser des animations dans un menu

Répondre
Partager Rechercher
Bonjour,

Je suis en possession d'un kit "full perm" pour jouer des animations de couple depuis un menu, quelque chose d'extrêmement classique.

Seulement, j'ai un petit problème : pour peu que les deux partenaires ne s'assoient pas au même moment sur les poseballs (ou plus précisément, n'acceptent pas en même temps d'animer leur avatar via la fenêtre bleue), l'animation des deux avatars n'est pas synchronisée.

Je me demandais s'il était possible d'ajouter une fonctionnalité aux scripts, de façon à ce que l'animation A ne ne puisse commencer à être jouée qu'à partir du moment ou l'animation B démarre, et réciproquement, ce qui est le cas de la plupart des animations de couple que l'on trouve dans le commerce.

Comment faire ?

Voici les scripts qui composent mon système. Je suis certaine qu'il n'y a qu'une ligne ou deux à ajouter... Mais lesquelles ? Je donne ma langue au chat !

Notecard " tch_passer" :

Code PHP:

// Creator: Tyr Mohr
default
{
    
touch_start(integer total_number)
    {
        
llMessageLinked(LINK_ALL_OTHERSllDetectedGroup(0), "PRIMTOUCH"llDetectedKey(0));
    }

Notecard "memory" :

Code PHP:

//MLP MULTI-LOVE-POSE V1.2 - Copyright (c) 2006, by Miffy Fluffy (BSD License)
integer i;
integer j;
integer line;
integer p;
list 
poses;
list 
positions;
default {
    
state_entry() {
        
llOwnerSay("Memory is empty, loading notecard: .POSITIONS");
        
llGetNotecardLine(".POSITIONS",0);          //read first line of positions notecard
    
}
     
dataserver(key query_idstring data) {                                 
        if (
data == EOFstate on;
        
llSubStringIndex(data,"{");             //split name from positions, remove junk
        
llSubStringIndex(data,"} <");
        if (
!= -&& != -1) {
            
//poses += [ llGetSubString(data, i+1, j - 1) ];
            //positions += [ llGetSubString(data, j+2, -1) ];
            
poses = [ llGetSubString(datai+11) ] + (poses = []) + poses;            //saves memory
            
positions = [ llGetSubString(dataj+2, -1) ] + (positions = []) + positions;   //saves memory
            
++p;   
        }
        ++
line;
        
llGetNotecardLine(".POSITIONS",line);       //read next line of positions notecard
    
}
    
state_exit() {
        
llOwnerSay((string)p+" positions stored in memory ("+llGetScriptName()+": "+(string)llGetFreeMemory()+" bytes free)");
        if (
2) {
            
poses = [ "stand","default" ];
            
positions = [ "<-0.7,0.0,0.9> <0.0,0.0,0.0> <0.7,0.0,0.9> <0.0,0.0,-180.0>",
                          
"<-0.7,0.0,0.7> <0.0,0.0,0.0> <0.7,0.0,0.7> <0.0,0.0,-180.0>" ];
            
2;
        }
        
llMessageLinked(LINK_THIS,2,"OK",NULL_KEY); //msg to menu, in case it's waiting for loading
    
}
}
state on {
 
    
link_message(integer frominteger numstring strkey dkey) {
        if (
str == "PRIMTOUCH"){
            return;
        }
        if (
num != 1) return;        
        if (
str == "OK?") {                                 //question from menu, before loading menu
            
llMessageLinked(from,2,"OK",NULL_KEY);          //answer to menu
        
} else if (str == "LOADED") {                       //msg from menu: loaded
            
llMessageLinked(from,3,"LOADED",dkey);          //forward msg to pos
        
} else if (str == "DUMP") {
            
llOwnerSay("_______________________________________________________________________________");
            
llOwnerSay("");
            
llOwnerSay("Copy to notecard: .POSITIONS");
            
llOwnerSay("_______________________________________________________________________________");
            
llOwnerSay(""); 
            
//for (i=0; i < p; ++i) llOwnerSay("{"+llList2String(poses,i)+"} "+llList2String(positions,i));
            
for (i=1i>=0; --illOwnerSay("{"+llList2String(poses,i)+"} "+llList2String(positions,i));
        } else {
            
llListFindList(poses,[ str ]);              //find pose
            
if (llGetSubString((string)dkey,0,0) == "<") {  //SAVE
                
if (!= -1) {
                    
positions llListReplaceList(positions,[ (string)dkey ],i,i);
                    
llOwnerSay("{"+str+"} position updated in memory");
                } else {
                    
//poses += [ str ];
                    //positions += [ (string)dkey ];
                    
poses = [ str ] + (poses = []) + poses;                         //saves memory
                    
positions = [ (string)dkey ] + (positions = []) + positions;    //saves memory
                    
++p;
                    
llOwnerSay("{"+str+"} position added to memory");
                }
                
llOwnerSay("("+llGetScriptName()+": "+(string)llGetFreeMemory()+" bytes free, "+(string)p+" positions)");
            } else {                                        
//LOAD
                //if (i == -1) i = 0;                                         //not found, send default (-1 if save mem)     
                
llMessageLinked(from,3,llList2String(positions,i),dkey);    //msg to pos: sent position
            

        }        
    }

Notecard "menu"

Code PHP:

//MLP MULTI-LOVE-POSE V1.2 - Copyright (c) 2006, by Miffy Fluffy (BSD License)
integer PINK1 1;  //0001 binary
integer BLUE1 2;  //0010 binary
integer PINK2 4;  //0100 binary
integer BLUE2 8;  //1000 binary
integer a;
integer alive;
integer b;
integer b0;
integer ballusers;
integer c;
integer ch;
integer chat 1;
integer group;
integer hear;
integer i;
integer line;
integer menu;
integer menuusers;
integer redo 1;
integer rez;
integer swap;
integer visible;
float alpha;
string cmd;
string pose;
string pose0;
key owner;
key user;
key user0;
list 
buttons;
list 
buttonindex;
list 
commands;
list 
menus;
list 
balls;
list 
users;
//menu partly based on Menu Engine by Zonax Delorean (BSD License)
//llDialog(user, menuname, buttons(from index to nextindex-1), channel)  
doMenu() {
    
b0 llList2Integer(buttonindexmenu);         //position of first button for this (sub)menu
    
llList2Integer(buttonindexmenu+1);        //position of first button for next (sub)menu
    
llDialog(userllList2String(menus,menu), llList2List(buttonsb01), ch 1);
    
llList2Integer(balls,menu);         //ballcolors
    
if (c) {                                //if submenu includes ballcolor(s):
        
if (!rezrezBalls();               //if no balls present: create balls
        
llSay(ch,(string)(3));          //ball1color: mask with 3 = 0011 binary
        
llSay(ch+1,(string)(>> 2));       //ball2color: shift 2 bits to the right
        
if (balluserssetBalls("GROUP");   //if group access only
    
}
    
llResetTime();
    
//if (user != llGetOwner()) llOwnerSay("("+llKey2Name(user)+" selects "+llList2String(menus,menu)+")");     //owner will receive info
}
say(string str) {
    if (
menuusersllWhisper(0,str);
    else 
llOwnerSay(str);
}
setBalls(string cmd) {
    
llSay(ch,cmd);      //msg to balls
    
llSay(ch+1,cmd);
}
rezBalls() {
    
setBalls("DIE");
    
llRezObject("~ball",llGetPos(),ZERO_VECTOR,ZERO_ROTATION,ch);
    
llRezObject("~ball",llGetPos(),ZERO_VECTOR,ZERO_ROTATION,ch+1);
    
llMessageLinked(LINK_THIS,0,"REPOS",NULL_KEY);  //msg to pos
    
llMessageLinked(LINK_THIS,0,"POSE","0");        //msg to pos/pose
    
rez 1;
    
alive 2;
    
pose pose0;
    
llSetTimerEvent(60);
    if (
chatsay("Balls ready");
}
default {
    
state_entry() {
        
//llSetScriptState("~run", TRUE);
        
llResetOtherScript("~pos");
        
llResetOtherScript("~pose");
        
llResetOtherScript("~pose1");
        
llResetOtherScript("~pose2");
        
ch = (integer)("0x"+llGetSubString((string)llGetKey(),-4,-1));  //fixed channel for prim
        
setBalls("DIE");
        
alpha llGetAlpha(0);                                          //store object transparancy (alpha)
        
if (alpha 0.1alpha 0.5; else visible 1;                 //if invisible store a visible alpha
        
llMessageLinked(LINK_THIS,1,"OK?",NULL_KEY);                    //msg to memory: ask if ready
    
}
    
link_message(integer frominteger numstring strkey id) {
        if (
num == 2) {
            if (
str == "OK"state load;                                //memory ready
        
}
    }
}           
state load {
    
state_entry() {
        
llGetNotecardLine(".MENUITEMS",0);                              //read first line of menuitems notecard
    
}
    
dataserver(key query_idstring data) {                                 
        if (
data == EOFstate on;
        
llSubStringIndex(data,"//");                                //remove comments
        
if (!= -1) {
            if (
== 0data "";
            else 
data llGetSubString(data01);
        }
        while (
llGetSubString(data, -1, -1) == " "data llDeleteSubString(data, -1, -1); //remove spaces from end
        
if (data != "") {
            
llSubStringIndex(data," ");
            
cmd data;                      
            if (
!= -1) {                                              //split command from data
                
cmd llGetSubString(data01);
                
data llGetSubString(datai+1, -1);
            }
            list 
ldata llParseString2List(data,["  |  ","  | "," |  "," | "," |","| ","|"],[]);
            
data llList2String(ldata0);
            if (
cmd == "MENU") {
                if (
2) {
                    
llOwnerSay("warning: first item in .MENUITEMS must be: POSE stand");
                    
llOwnerSay("warning: second item in .MENUITEMS must be: POSE default");
                }
                
llOwnerSay("loading data for '"+data+"'");             
                if (
llList2String(ldata1) == "GROUP"menu 1;       //access to submenus
                
else if (llList2String(ldata1) != "OWNER"menu 2;  //0=owner 1=group 2=all
                
pose llList2String(ldata2);
                if (
pose == "PINK"rez PINK1;
                else if (
pose == "BLUE"rez BLUE1;
                
pose llList2String(ldata3);
                if (
pose == "PINK"rez += PINK2;
                else if (
pose == "BLUE"rez += BLUE2;
                
menus += [ data ];
                
balls += [ rez ];
                
buttonindex += [ ];
                
users += [ menu ];
                
rez 0;
                
b0 0;
                
menu 0;
            } else if (
b0 12) {                                       //maximum 12 buttons per menu
                
if (cmd == "POSE") {
                    
llMessageLinked(LINK_THIS,1,data,(string)a);        //msg to memory
                    
llMessageLinked(LINK_THIS,9+a,llList2String(ldata1),llList2String(ldata2));  //msg to pose
                    
if (!apose0 data;
                    
cmd = (string)a;
                    ++
a;
                } else if (
cmd == "REDO") {
                    if (
llList2String(ldata1) != "OFF"redo 1;
                } else if (
cmd == "CHAT") {
                    if (
llList2String(ldata1) != "OFF"chat 1;
                } else if (
cmd == "BALLUSERS") {
                    if (
llList2String(ldata1) == "GROUP"ballusers 1;
                } else if (
cmd == "MENUUSERS") {
                    if (
llList2String(ldata1) == "GROUP"menuusers 1;
                    else if (
llList2String(ldata1) != "OWNER"menuusers 2;
                }   
                
commands += [ cmd ];
                
buttons += [ data ];
                ++
b;
                ++
b0;
            }
        }
        ++
line;
        
llGetNotecardLine(".MENUITEMS",line);                           //read next line of menuitems notecard
    
}
    
state_exit() {
        
buttonindex += [ ];                                           //enter last buttonindex
        
commands += [ "" ];                                             //empty command for undefined buttons (-1)
        
llOwnerSay("READY");
        
llOwnerSay((string)b+" menuitems loaded ("+llGetScriptName()+": "+(string)llGetFreeMemory()+" bytes free)");
        
llMessageLinked(LINK_THIS,1,"LOADED",(string)a);                //msg to memory
        
llMessageLinked(LINK_THIS,9+a,"LOADED",NULL_KEY);               //msg to pose
    
}
}
state on {
    
state_entry() {
        
owner llGetOwner();
        
llSetTimerEvent(0);
        
llListenRemove(hear);
        
hear llListen(ch 1""NULL_KEY"");                      //listen for pressed buttons
    
}
    
touch_start(integer i) {
        
user0 llDetectedKey(0);
        if (
user0 == owner || (menuusers == && llDetectedGroup(0)) || menuusers == 2) {   //0=owner 1=group 2=all
            
if (user0 != user) {
                if (
llGetTime() < 60) {
                    
llDialog(user0"\n"+llKey2Name(user)+" has just selected the menu, do you want to continue?", ["Yes","Cancel"], ch 1);
                    return;
                }
                
user user0;
                
group llDetectedGroup(0);
            }
            
menu 0doMenu();                                         //mainmenu
        
}                 
    }
 
    
listen(integer channelstring namekey user0string button) {
        if (
user0 != user) {
            if (
button == "Yes") {
                
user user0;
                
group llSameGroup(user0);
                
menu 0doMenu();
            } else if (
button != "Cancel") {
                
llDialog(user0"\nSelection cancelled because "+llKey2Name(user)+" has just selected the menu, do you want to operate the menu again?", ["Yes","Cancel"], ch 1);
            }
            return;
        }
        
llListFindList(buttons,[ button ]);                         //find position of cmd
        
string cmd llList2String(commands,b);                         //get command
        //llSay(0,button+" "+cmd);                                      //debug
        
if (cmd == "TOMENU") {                                             
            
menu llListFindList(menus,[ button ]);                    //find submenu
            
if (menu == -1) return;
            
llList2Integer(usersmenu); 
            if (
user == owner || (== && group) || == 2) {         //0=owner 1=group 2=all
                
doMenu(); return;
            }
            if (
== 1llDialog(user0"\n"+button+" menu deactivated\n(access by group only)", ["OK"], ch 1);
            else 
llDialog(user0"\n"+button+" menu deactivated\n(access by owner only)", ["OK"], ch 1);
            
menu 0;
            return;
        } else if (
cmd == "BACK") {
            
menu 0doMenu();                                         //mainmenu
            
return;
        } else if ((integer)
cmd 0) {                                  //POSE
            
llMessageLinked(LINK_THIS,0,"POSE",cmd);                    //msg to pos/pose
            
if (chatsay(button);
            
pose button;
        } else if (
cmd == "SWAP") {
            
llMessageLinked(LINK_THIS,0,"SWAP",NULL_KEY);               //msg to pos/pose
            
swap = !swap;
        } else if (
cmd == "STAND") {
            
llMessageLinked(LINK_THIS,0,"POSE","0");                    //STAND msg to pos/pose
            
if (chatsay(button);
            
menu 0;
            
pose pose0;
        } else if (
cmd == "STOP") {
            
llMessageLinked(LINK_THIS,0,"POSE","0");                    //STAND msg to pos/pose
            
if (chatsay(button);
            
setBalls("DIE");
            if (
chat && rezsay("Balls removed");
            
rez 0;
            
llSetTimerEvent(0);
            return;
        } else if (
cmd == "ADJUST") {
            
setBalls("ADJUST");
        } else if (
cmd == "HIDE") {
            
setBalls("0");
        } else if (
cmd == "SHOW") {
            
setBalls("SHOW");
        } else if (
cmd == "DUMP") {
            
llMessageLinked(LINK_THIS,1,"DUMP",NULL_KEY);
        } else if (
cmd == "INVISIBLE") {
            
visible = !visible;
            
llSetAlpha((float)visible*alphaALL_SIDES);
        } else if (
cmd == "REDO") {
            
redo = !redo;
            if (
redosay(button+" ON"); else say(button+" OFF");
        } else if (
cmd == "CHAT") {
            
chat = !chat;
            if (
chatsay(button+" ON"); else say(button+" OFF");
        } else if (
cmd == "BALLUSERS") {
            
ballusers = !ballusers;
            if (
ballusers) {
                
llOwnerSay(button+" GROUP");
                
setBalls("GROUP");
            } else {    
                
llOwnerSay(button+" ALL");
                
setBalls("ALL");
            }
        } else if (
cmd == "MENUUSERS") {
            if (
user == owner) {
                if (!
menuusers) {
                    
menuusers 1;
                    
llOwnerSay(button+" GROUP");
                } else if (
menuusers == 1) {
                    
menuusers 2;
                    
llOwnerSay(button+" ALL");
                } else if (
menuusers == 2) {
                    
menuusers 0;
                    
llOwnerSay(button+" OWNER");
                }
            } else 
llWhisper(0,button+" (can be switched by owner only)");
        } else if (
cmd == "RESET") {
            
llMessageLinked(LINK_THIS,0,"POSE","0");                    //STAND msg to pos/pose
            
setBalls("DIE");
            
//llSleep(0.5);        
            
if (chatsay(button);
            
llResetScript();
        } else if (
cmd == "OFF") {
            
llMessageLinked(LINK_THIS,0,"POSE","0");                    //STAND msg to pos/pose
            
setBalls("DIE");
            
//llSleep(0.5);
            
if (user == owner) {
                
llOwnerSay(button);
                
llResetOtherScript("~run");
                
llResetScript();
            }
            
llDialog(user0"\n"+button+" button deactivated\n(access by owner only)", ["OK"], -1);
            return;
        } else if (
llGetSubString(cmd00) == "Z" || (cmd == "SAVE")) {    //SAVE //Z-adjust
            
llMessageLinked(LINK_THIS,0,cmd,pose);                      //msg to pos/pose
            
doMenu();
            return;
        }
        if (
redodoMenu();
    }
 
 
    
link_message(integer frominteger numstring strkey id) { 
      if (
str == "PRIMTOUCH") {
        
user0 id ;
        
integer detected_group num;    
        if (
user0 == owner || (menuusers == && detected_group) || menuusers == 2) {   //0=owner 1=group 2=all
            
if (user0 != user) {
                if (
llGetTime() < 60) {
                    
llDialog(user0"\n"+llKey2Name(user)+" has just selected the menu, do you want to continue?", ["Yes","Cancel"], ch 1);
                    return;
                }
                
user user0;
                
group llDetectedGroup(0);
            }
            
menu 0doMenu();                                         //mainmenu
        
}                 
             return;
      }
 
        if (
num != 2) return;
        if (
str == "ALIVE") {
            ++
alive;
        } else if (
str == "DIE") {                                      //suicide msg from ball
            
setBalls("DIE");
            
menu 0;
            
rez 0;
            
llSetTimerEvent(0);
        } 
    }
    
on_rez(integer r) {
        if (
owner != llGetOwner()) llResetScript();
    }
    
timer() {
        if (
alive 1) {    
            
alive 0;
            
llSay(ch,"LIVE");           //msg to balls: stay alive
            
llSay(ch+1,"LIVE"); 
        } else {                        
//balls not rezzed properly anymore
            
rezBalls();
            
llSay(ch,(string)(3));          //ball1color: mask with 3 = 0011 binary
            
llSay(ch+1,(string)(>> 2));       //ball2color: shift 2 bits to the right
            
if (balluserssetBalls("GROUP");   //if group access only
        
}
    }

Notecard "pos" :

Code PHP:

//MLP MULTI-LOVE-POSE V1.2 - Copyright (c) 2006, by Miffy Fluffy (BSD License)
integer a;
integer ch;
integer p;
integer swap;
integer z;
string pr1;
string pr2;
list 
plist;
list 
positions1;
list 
positions2;
list 
rotations1;
list 
rotations2;
vector pos;
vector pos0;
vector pos1;
vector pos2;
vector rot1;
vector rot2;
rotation rot;
getRefPos() {   //reference position
    
pos llGetPos();
    
rot llGetRot();
    
pos0 pos;
    
= (integer)llGetObjectDesc();
    
pos.+= (float)z/100;
}
getPos() {
    
pos1 = (vector)llList2String(positions1p);
    
pos2 = (vector)llList2String(positions2p);
    
rot1 = (vector)llList2String(rotations1p);
    
rot2 = (vector)llList2String(rotations2p);
}
setPos() {
    
pr1 = (string)(pos1*rot pos);
    
pr2 = (string)(pos2*rot pos);
    
pr1 += (string)(llEuler2Rot(rot1*DEG_TO_RAD) * rot);
    
pr2 += (string)(llEuler2Rot(rot2*DEG_TO_RAD) * rot);
    
llSay(ch+swap,pr1);     //msg to ball1/2
    
llSay(ch+!swap,pr2);
}
default {
    
state_entry() {
        
getRefPos();
        
ch = (integer)("0x"+llGetSubString((string)llGetKey(),-4,-1));          //fixed channel for prim
    
}
    
link_message(integer frominteger numstring pdatakey akey) {
        if (
pdata == "PRIMTOUCH"){
            return;
        }
        if (
num != 3) return;
        if ((integer)((string)
akey) != a) { llOwnerSay("debug ~pos mismatch a "+(string)akey+" "+(string)a); return; }//
        
if (pdata == "LOADED"state on;
        
plist llParseString2List(pdata,[" "],[]);
        
positions1 += llList2List(plist,0,0);
        
positions2 += llList2List(plist,2,2);
        
rotations1 += llList2List(plist,1,1);
        
rotations2 += llList2List(plist,3,3);
        
//positions1 = llList2List(plist,0,0) + (positions1 = []) + positions1;   //trick to save memory
        //positions2 = llList2List(plist,2,2) + (positions2 = []) + positions2;   //but not useful after
        //rotations1 = llList2List(plist,1,1) + (rotations1 = []) + rotations1;   // replacing positions
        //rotations2 = llList2List(plist,3,3) + (rotations2 = []) + rotations2;
        
++a;
    }
    
state_exit() {
        
llOwnerSay((string)a+" positions loaded ("+llGetScriptName()+": "+(string)llGetFreeMemory()+" bytes free)");
    }
}
state on {    
    
link_message(integer frominteger numstring cmdkey pkey) {
        if (
cmd == "PRIMTOUCH"){
            return;
      }
        if (
num) return;
        if (
cmd == "POSE") {
            
= (integer)((string)pkey);
            
//p = -(integer)((string)pkey) - 1;   //read reversed when using memory saving trick above ^
            
getPos();
            
setPos();
        } else if (
cmd == "SWAP") {
            
swap = !swap;
            
llSay(ch+swap,pr1);         //msg to ball1/2
            
llSay(ch+!swap,pr2);
        } else if (
cmd == "REPOS") {
            
getRefPos();
        } else if (
llGetSubString(cmd00) == "Z") {
            
+= (integer)llGetSubString(cmd1, -1);
            
pos.pos0.+ (float)z/100;
            
setPos();
            
llOwnerSay("Height Adjustment Z "+(string)z+"cm");
            
llSetObjectDesc((string)z);
        } else if (
cmd == "GETREFPOS") {
            
llMessageLinked(LINK_THIS,8,(string)pos,(string)rot);   //send reference position to pose
        
} else if (cmd == "SAVE2") {                                //replace positions
            
plist llParseString2List((string)pkey,[" "],[]);
            
positions1 llListReplaceList(positions1,llList2List(plist,0,0),p,p);
            
positions2 llListReplaceList(positions2,llList2List(plist,2,2),p,p);
            
rotations1 llListReplaceList(rotations1,llList2List(plist,1,1),p,p);
            
rotations2 llListReplaceList(rotations2,llList2List(plist,3,3),p,p);
            
llOwnerSay("("+llGetScriptName()+": "+(string)llGetFreeMemory()+" bytes free, "+(string)a+" positions)");
            
getPos();
            
setPos();
        }
    }

Notecard "pose" :

Code PHP:

//MLP MULTI-LOVE-POSE V1.2 - Copyright (c) 2006, by Miffy Fluffy (BSD License)
integer a;
integer ch;
integer hear1;
integer hear2;
integer i;
integer swap;
string an1;
string an2;
string pose;
string pr1;
string pr2;
list 
anims;
vector pos;
rotation rot;
string prStr(string str) {
    
llSubStringIndex(str,">");
    
vector p = ((vector)llGetSubString(str,0,i) - pos) / rot;
    
vector r llRot2Euler((rotation)llGetSubString(str,i+1,-1) / rot)*RAD_TO_DEG;
    return 
"<"+round(p.x3)+","+round(p.y3)+","+round(p.z3)+"> <"+round(r.x1)+","+round(r.y1)+","+round(r.z1)+">";
}
string round(float numberinteger places) {
    
float shifted;
    
integer rounded;
    
string s;
    
shifted number llPow(10.0,(float)places);
    
rounded llRound(shifted);
    
= (string)((float)rounded llPow(10.0,(float)places));
    
llGetSubString(s,0,llSubStringIndex(s".")+places);
    
//while (llGetSubString(s,-1,-1) == "0") s = llDeleteSubString(s,-1,-1);
    //if (llGetSubString(s,-1,-1) == ".") s = llDeleteSubString(s,-1,-1);
    
return s;
}
default {
    
state_entry() {
        
ch = (integer)("0x"+llGetSubString((string)llGetKey(),-4,-1));  //fixed channel for prim
    
}
    
link_message(integer frominteger numstring an1strkey an2key) {
        if (
num != 9+a) return;
        if (
an1str == "LOADED"state on;
        
an1 an1str;
        
an2 = (string)an2key;
        if (
a>1) {
            if (
an1 == ""an1 llList2String(anims2);   //use default
            
else if (llGetInventoryType(an1) != INVENTORY_ANIMATIONllSay(0,"animation '"+an1+"' not in inventory (ok for build-in animations, otherwise check)");
            if (
an2 == ""an2 llList2String(anims3);   //use default
            
else if (llGetInventoryType(an2) != INVENTORY_ANIMATIONllSay(0,"animation '"+an2+"' not in inventory (ok for build-in animations, otherwise check)");
        } else if (
a) { //pose1: set default
            
if (an1 == ""an1 "sit_ground";
            if (
an2 == ""an2 "sit_ground";
        } else {        
//pose0: set stand
            
if (an1 == ""an1 "stand";
            if (
an2 == ""an2 "stand";
        }
        
anims += [ an1an2 ];
        ++
a;
    }
    
state_exit() {
        
llOwnerSay((string)a+" posepairs loaded ("+llGetScriptName()+": "+(string)llGetFreeMemory()+" bytes free)");
    }
}
state on {
    
link_message(integer frominteger numstring cmdkey akey) {
        if (
cmd == "PRIMTOUCH"){
            return;
        }
        if (
num) return;
        if (
cmd == "POSE") {      
            
= (integer)((string)akey) * 2;
            
an1 llList2String(animsa);
            
an2 llList2String(animsa+1);
        } else if (
cmd == "SWAP") {
            
swap = !swap;
        } else if (
cmd == "SAVE") {
            
pose = (string)akey;
            
state save;
        } else return;
        
llMessageLinked(LINK_THIS,ch+swapan1,NULL_KEY);   //msg to pose1/2
        
llMessageLinked(LINK_THIS,ch+!swap,an2,NULL_KEY);
    }
}
state save {
    
state_entry() {
        
llMessageLinked(LINK_THIS,0,"GETREFPOS","");    //msg to pos: ask ref position
        
pr1 "";
        
pr2 "";
        
hear1 llListen(ch+8""NULL_KEY"");
        
hear2 llListen(ch+9""NULL_KEY"");
        
llSay(ch,"SAVE");       //msg to balls
        
llSay(ch+1,"SAVE");
        
llSetTimerEvent(3);
    }
    
listen(integer channelstring namekey idstring pr) {
        if (
channel == ch+8+swappr1 pr;
        else if (
channel == ch+8+!swappr2 pr;
        if (
pr1 != "" && pr2 != "") {
            
pr prStr(pr1)+" "+prStr(pr2);
            
llOwnerSay("{"+pose+"} "+pr);
            
llMessageLinked(LINK_THIS,0,"SAVE2",pr);    //save to pos
            
llMessageLinked(LINK_THIS,1,pose,pr);       //write to memory
            
state on;
        }
    }
    
link_message(integer frominteger numstring posstrkey rotkey) {
        if (
posstr == "PRIMTOUCH"){
            return;
        }
        if (
num != 8) return;
        
pos = (vector)posstr;                   //reveive reference position from pos
        
rot = (rotation)((string)rotkey);
    }
    
timer() {
        
state on;
    } 
     
state_exit() {
        
llSetTimerEvent(0);
        
llListenRemove(hear1);
        
llListenRemove(hear2);
    }   

Notecard "pose1"

Code PHP:

//MLP MULTI-LOVE-POSE V1.2 - Copyright (c) 2006, by Miffy Fluffy (BSD License)
integer ch 0;  //pose1: ch=0  //pose2: ch=1
string animation "stand";
key avatar;
stopAnim() {
    list 
l=llGetAnimationList(llGetPermissionsKey()); 
    
integer i
    for (
i;i<llGetListLength(l);++illStopAnimation(llList2String(l,i));
}
default {
   
state_entry() {
        
ch += (integer)("0x"+llGetSubString((string)llGetKey(),-4,-1)); //fixed channel for prim
        
llListen(ch+4,"",NULL_KEY,"");
    }
    
link_message(integer frominteger numstring ankey id) {        //an animation is set
        
if (an == "PRIMTOUCH") {
            return;
        }
        if(
num != ch) return;
        if (
llGetPermissionsKey() == avatar && avatar != NULL_KEY) {    //permissions
            
llStopAnimation(animation);
            
llStartAnimation(an);
        }
        
animation=an;
    }
    
listen(integer channelstring namekey idstring str) {           
        if (
str == "ALIVE" || str == "DIE") {
            
llMessageLinked(LINK_THIS,2,str,"");                        //send msg from ball to menu
            
return;
        }
        
avatar str;                                                   //avatar sits or stands up
        
if (llGetPermissions() & PERMISSION_TRIGGER_ANIMATION) {        //permissions ok
            
stopAnim();
            if (
llGetPermissionsKey() == avatar) { llStartAnimation(animation); return; }   //if avatar is the same: animate
        
}
        if (
avatar != NULL_KEYllRequestPermissions(avatar,PERMISSION_TRIGGER_ANIMATION);  //ask permission from new avatar
    
}
    
run_time_permissions(integer perm) {
        if (
perm PERMISSION_TRIGGER_ANIMATION && llGetPermissionsKey() == avatar) {   //avatar gave permission
            
stopAnim();
            
llStartAnimation(animation);
        }
    }

Notecard "pose2" :

Code PHP:

//MLP MULTI-LOVE-POSE V1.2 - Copyright (c) 2006, by Miffy Fluffy (BSD License)
integer ch 1;  //pose1: ch=0  //pose2: ch=1
string animation "stand";
key avatar;
stopAnim() {
    list 
l=llGetAnimationList(llGetPermissionsKey()); 
    
integer i
    for (
i;i<llGetListLength(l);++illStopAnimation(llList2String(l,i));
}
default {
   
state_entry() {
        
ch += (integer)("0x"+llGetSubString((string)llGetKey(),-4,-1)); //fixed channel for prim
        
llListen(ch+4,"",NULL_KEY,"");
    }
    
link_message(integer frominteger numstring ankey id) {        //an animation is set
        
if (an == "PRIMTOUCH"){
            return;
        }
        if(
num != ch) return;
        if (
llGetPermissionsKey() == avatar && avatar != NULL_KEY) {    //permissions
            
llStopAnimation(animation);
            
llStartAnimation(an);
        }
        
animation=an;
    }
    
listen(integer channelstring namekey idstring str) {           
        if (
str == "ALIVE" || str == "DIE") {
            
llMessageLinked(LINK_THIS,2,str,"");                        //send msg from ball to menu
            
return;
        }
        
avatar str;                                                   //avatar sits or stands up
        
if (llGetPermissions() & PERMISSION_TRIGGER_ANIMATION) {        //permissions ok
            
stopAnim();
            if (
llGetPermissionsKey() == avatar) { llStartAnimation(animation); return; }   //if avatar is the same: animate
        
}
        if (
avatar != NULL_KEYllRequestPermissions(avatar,PERMISSION_TRIGGER_ANIMATION);  //ask permission from new avatar
    
}
    
run_time_permissions(integer perm) {
        if (
perm PERMISSION_TRIGGER_ANIMATION && llGetPermissionsKey() == avatar) {   //avatar gave permission
            
stopAnim();
            
llStartAnimation(animation);
        }
    }

Et enfin, notecard "run"

Code PHP:

//MLP MULTI-LOVE-POSE V1.2 - Copyright (c) 2006, by Miffy Fluffy (BSD License)
//To donate, go to my profile (Search - People - Miffy Fluffy) and use the "Pay..." button, thanks!
//You can also find the link to the latest version here.
// DESCRIPTION OF THE SCRIPTS
//
// ~run:
//  Default: sets other scripts to not running.
//  When the object is touched it will start all scrips.
//
// ~memory:
//  Here the positions are stored permanently. Information is still kept when the script is
//  not running or when everything is placed in inventory. The information will be lost only
//  when the ~memory script is reset.
//  A backup can be made on the .POSITIONS notecard, when the memory is empty, it will start
//  reading the .POSITIONS notecard automatically.
//
// ~menu:
//  1.loading: reads the .MENUITEMS notecard and builds the menu.
//    When it reads a "POSE": - the animations are stored in ~pose
//                            - their matching positions are looked up in ~memory and stored
//                              in ~pos.
//  2.ready:
//    When the object is touched: - shows the main menu
//                                - listens for menu selections.
//
//    When a submenu is selected: - shows the submenu
//                                - when balls are defined for this submenu it will rez
//                                  balls (if not already there) and set their colors.
//
//    When a pose is selected:  - ~pose will send the animations to ~pose1 and ~pose2,
//                                 they will set the animations to the avatars
//                              - ~pos wil send the matching positions to each ball.
//
//    When a position is saved: - ~pose will ask the balls for their position
//                              -  the positions are saved in ~memory ("permanent")
//                              -  the positions are updated in ~pos
//                                  
//    When "STOP" is selected:  - will hide the balls
//                              - will stop the pose
//                              When "STOP" is selected again (or if no pose is started yet):
//                              - will remove the balls (derez/die)
//
// ~pos:
//  - loads the positions from ~memory and stores them (until shutdown/restart)
//  - sends positions for the selected pose to the balls
//
// ~pose:
//  - loads the animations from the .MENUITEMS notecard and stores them (until shutdown/restart)
//  - sends animations for the selected pose to ~pose1 and ~pose2
//  - when saving a position: will ask balls for their position and sends it to ~pos and ~memory
//    (~pos would be a more logical place to handle this, but ~pose has more free memory).
//
// ~pose1 & pose2:
//  - will ask permission to animate the avatar on ball 1&2
//  - will set the animations to avatar 1&2
//
// ~ball
//  - when balls are defined for a submenu (in .MENUITEMS), ~menu will rez two copies of ~ball
//  - ball 1&2 will receive a unique communication channel from ~menu
//  - the color for ball 1&2 is set by ~menu
//  - the position of ball 1&2 is set by ~pos
//  - when an avatar selects to sit on a ball, the avatar info is sent to ~pose1 or ~pose2, they
//    will ask permission and set the animation directly to the avatar (not via the ball)
//  - balls will commit suicide when they don't hear a "LIVE" message each minute (from ~menu).
//
// have fun!
//Note: if you make a revised version, please mention something like this:
//"MLP - alternative version by ... .... - Revision 1 (based on MLP V1.2 by Miffy Fluffy)
setRunning(integer st) {
    
llSetScriptState("~menu"st);
    
llSetScriptState("~pos"st);
    
llSetScriptState("~pose"st);
    
llSetScriptState("~pose1"st);
    
llSetScriptState("~pose2"st);
    
llResetOtherScript("~menu");
    
llSetScriptState("~memory"TRUE);
}
default {
    
state_entry() {
        
llOwnerSay("OFF (touch to switch on)");
        
setRunning(FALSE);
    }
    
touch_start(integer i) {
       if (
llDetectedKey(0) == llGetOwner()) state run;
    }   
 
    
// Waits for another script to send a link message.
    
link_message(integer sender_numinteger numstring strkey id)
    {
        if (
str == "PRIMTOUCH"){
          if (
id == llGetOwner()){
            
state run;
          }
        }
    }
 
}
state run {
    
state_entry() {
        
llOwnerSay("MULTI-LOVE-POSE (version 1.2)");
        
setRunning(TRUE);
    }

Merci pour votre aide précieuse
La seule méthode que je connaisse pour faire démarrer plusieurs animations simultanément avec un MLP (à jour) c'est de paramétrer une séquence, c'est à dire une suite d'animations, incluant la commande "WAIT".

Dans ce cas, l'une ou l'autre des animations ne se déclenchera que lorsque tous les avatars seront assis sur leur "ball" respective.

L'idéal étant d'être en possession de l'animation en mode "statique", de la placer en tête de la séquence, puis de faire jouer ensuite la ou les animations "dynamiques" en boucle. Précision : il faut définir un tempo, qui correspondra à la durée originale de chaque animation jouée au cours de la séquence.

Enjoy !

http://wiki.secondlife.com/wiki/MLPV...rial#SEQUENCES
Merci à tous les deux, mais mon problème n'est pas résolu avec les scripts d'Elenia.

Je crois que Django fait fausse route par rapport à ma demande : je souhaite simplement que l'animation 1 de l'avatar 1 démarre en même temps que l'animation 2 de l'avatar 2 de façon à synchroniser leurs mouvements, le séquençage n'a rien à voir là-dedans.

Il suffirait que lorsque l'avatar 1 est sur sa pose-ball et a accepté son animation, celle-ci ne soit enclenchée que lorsque l'avatar 2 en a fait de même.

C'est trop demander ? Ca me semble pas super complexe pourtant, le premier sexbed freebie en propose autant...

Détrompe-toi !

Avec un système MLP, c'est le seul moyen de bloquer le déclenchement de l'animation 1 en attendant que le second avatar soit assis sur l'animation 2, et qui va effectivement déclencher la pose.

Et comme la plupart des sexbeds sont basés sur ce système, ils réagissent tous de la même manière.

Certes après tu as des systèmes de scripts spécifiques "propriétaires", mais ceux-ci ne seront pas modifiables.

Détrompe toi synchroniser des poses balls n'est pas simple.

Il faut jouer une animation d'attente différente de l'animation finale. Quand les 2 avatars ont l'animation d'attente en cours, alors on l'arrête et simultanément on lance les animations finales. Sans garantie qu'elles restent synchronisées sur la durée (même si elles ont rigoureusement la même durée elles peuvent se décaler, surtout que les animations sont jouées côté client et que l'un peut voir synchro et l'autre pas), auquel cas il est de bon ton de prévoir une commande par chat pour resynchroniser.

Alors dans ton cas tu vois la difficulté: hormis modifier le script, il faut dégoter ou faire des animations d'attente qui soit en accord avec les animations finales et compatibles avec la position des balles à ce moment là sans ça le remède sera pire que le mal.
Et puis la modification des scripts MLP pour intégrer dans les notecards de configuration ces animations d'attente je te dit pas le boulot.

Normalement, toute bonne application du MLP doit comprendre une position stand où les avatars sont debout face à face ou cote à cote. Le mieux pour moi est d'utiliser cette position avant d'enchainer sur les animations là on est sur d'être synchro.

On doit par contre assez facilement pouvoir modifier les scripts MLP pour forcer cette position stand, ou une autre position ne nécessitant pas de synchro, quand un seul avatar s'asseoit et attend le 2éme. Après, on sera synchro sur les animations suivantes.

Si ça peut t'aider, j'ai fait une version trafiquée du MLP où on change de position simplement en cliquand dessus. Taper /10 menu pour ouvrir le menu traditionnel. https://marketplace.secondlife.com/p...Y-CLICK/494122

Edit : la solution de Django d'utiliser les séquences possibles avec le MLP V2.4 me parait élégante. Mais on en revient à ce que je disait: il faut trouver des animations d'attente.
Merci pour vos réponses

Bon, c'est tout vu, mes tentatives pour faire des séquençages sur le modèle de l'exemple fourni à l'intérieur du pack proposé par Elenia ayant toutes échoué, j'ai essayé de changer de tactique en mettant les pose balls telles que je les ai achetées, c'est-à-dire déjà synchronisées avec anim d'attente, dans un rezer. L'ennui, c'est qu'il doit y avoir je ne sais quel script pourri dans mes poseballs qui empêchent la sauvegarde des coordonnées de rezage, et, celles-ci rerezées, elles apparaissent donc beaucoup trop bas par rapport à ce qu'il faudrait...

Découragée...
Citation :
Publié par Elenia B.
Si ça peut t'aider, j'ai fait une version trafiquée du MLP où on change de position simplement en cliquand dessus. Taper /10 menu pour ouvrir le menu traditionnel. https://marketplace.secondlife.com/p...Y-CLICK/494122
Si ! ça m'aide ! avec ce script là j'ai réussi ma synchronisation ! ! !

Je confirme, ça fonctionne, même si, clic mis à part, je ne vois pas la différence avec le système normal... ^^
Répondre

Connectés sur ce fil

 
1 connecté (0 membre et 1 invité) Afficher la liste détaillée des connectés