|
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" :
// Creator: Tyr Mohr default { touch_start(integer total_number) { llMessageLinked(LINK_ALL_OTHERS, llDetectedGroup(0), "PRIMTOUCH", llDetectedKey(0)); } }
Notecard "memory" :
//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_id, string data) { if (data == EOF) state on; i = llSubStringIndex(data,"{"); //split name from positions, remove junk j = llSubStringIndex(data,"} <"); if (i != -1 && j != -1) { //poses += [ llGetSubString(data, i+1, j - 1) ]; //positions += [ llGetSubString(data, j+2, -1) ]; poses = [ llGetSubString(data, i+1, j - 1) ] + (poses = []) + poses; //saves memory positions = [ llGetSubString(data, j+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 (p < 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>" ]; p = 2; } llMessageLinked(LINK_THIS,2,"OK",NULL_KEY); //msg to menu, in case it's waiting for loading } } state on { link_message(integer from, integer num, string str, key 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=p - 1; i>=0; --i) llOwnerSay("{"+llList2String(poses,i)+"} "+llList2String(positions,i)); } else { i = llListFindList(poses,[ str ]); //find pose if (llGetSubString((string)dkey,0,0) == "<") { //SAVE if (i != -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"
//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(buttonindex, menu); //position of first button for this (sub)menu b = llList2Integer(buttonindex, menu+1); //position of first button for next (sub)menu llDialog(user, llList2String(menus,menu), llList2List(buttons, b0, b - 1), ch - 1); c = llList2Integer(balls,menu); //ballcolors if (c) { //if submenu includes ballcolor(s): if (!rez) rezBalls(); //if no balls present: create balls llSay(ch,(string)(c & 3)); //ball1color: mask with 3 = 0011 binary llSay(ch+1,(string)(c >> 2)); //ball2color: shift 2 bits to the right if (ballusers) setBalls("GROUP"); //if group access only } llResetTime(); //if (user != llGetOwner()) llOwnerSay("("+llKey2Name(user)+" selects "+llList2String(menus,menu)+")"); //owner will receive info } say(string str) { if (menuusers) llWhisper(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 (chat) say("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.1) alpha = 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 from, integer num, string str, key 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_id, string data) { if (data == EOF) state on; i = llSubStringIndex(data,"//"); //remove comments if (i != -1) { if (i == 0) data = ""; else data = llGetSubString(data, 0, i - 1); } while (llGetSubString(data, -1, -1) == " ") data = llDeleteSubString(data, -1, -1); //remove spaces from end if (data != "") { i = llSubStringIndex(data," "); cmd = data; if (i != -1) { //split command from data cmd = llGetSubString(data, 0, i - 1); data = llGetSubString(data, i+1, -1); } list ldata = llParseString2List(data,[" | "," | "," | "," | "," |","| ","|"],[]); data = llList2String(ldata, 0); if (cmd == "MENU") { if (a < 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(ldata, 1) == "GROUP") menu = 1; //access to submenus else if (llList2String(ldata, 1) != "OWNER") menu = 2; //0=owner 1=group 2=all pose = llList2String(ldata, 2); if (pose == "PINK") rez = PINK1; else if (pose == "BLUE") rez = BLUE1; pose = llList2String(ldata, 3); if (pose == "PINK") rez += PINK2; else if (pose == "BLUE") rez += BLUE2; menus += [ data ]; balls += [ rez ]; buttonindex += [ b ]; 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(ldata, 1),llList2String(ldata, 2)); //msg to pose if (!a) pose0 = data; cmd = (string)a; ++a; } else if (cmd == "REDO") { if (llList2String(ldata, 1) != "OFF") redo = 1; } else if (cmd == "CHAT") { if (llList2String(ldata, 1) != "OFF") chat = 1; } else if (cmd == "BALLUSERS") { if (llList2String(ldata, 1) == "GROUP") ballusers = 1; } else if (cmd == "MENUUSERS") { if (llList2String(ldata, 1) == "GROUP") menuusers = 1; else if (llList2String(ldata, 1) != "OWNER") menuusers = 2; } commands += [ cmd ]; buttons += [ data ]; ++b; ++b0; } } ++line; llGetNotecardLine(".MENUITEMS",line); //read next line of menuitems notecard } state_exit() { buttonindex += [ b ]; //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 == 1 && 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 = 0; doMenu(); //mainmenu } } listen(integer channel, string name, key user0, string button) { if (user0 != user) { if (button == "Yes") { user = user0; group = llSameGroup(user0); menu = 0; doMenu(); } 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; } b = 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; i = llList2Integer(users, menu); if (user == owner || (i == 1 && group) || i == 2) { //0=owner 1=group 2=all doMenu(); return; } if (i == 1) llDialog(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 = 0; doMenu(); //mainmenu return; } else if ((integer)cmd > 0) { //POSE llMessageLinked(LINK_THIS,0,"POSE",cmd); //msg to pos/pose if (chat) say(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 (chat) say(button); menu = 0; pose = pose0; } else if (cmd == "STOP") { llMessageLinked(LINK_THIS,0,"POSE","0"); //STAND msg to pos/pose if (chat) say(button); setBalls("DIE"); if (chat && rez) say("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*alpha, ALL_SIDES); } else if (cmd == "REDO") { redo = !redo; if (redo) say(button+" ON"); else say(button+" OFF"); } else if (cmd == "CHAT") { chat = !chat; if (chat) say(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 (chat) say(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(cmd, 0, 0) == "Z" || (cmd == "SAVE")) { //SAVE //Z-adjust llMessageLinked(LINK_THIS,0,cmd,pose); //msg to pos/pose doMenu(); return; } if (redo) doMenu(); } link_message(integer from, integer num, string str, key id) { if (str == "PRIMTOUCH") { user0 = id ; integer detected_group = num; if (user0 == owner || (menuusers == 1 && 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 = 0; doMenu(); //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)(c & 3)); //ball1color: mask with 3 = 0011 binary llSay(ch+1,(string)(c >> 2)); //ball2color: shift 2 bits to the right if (ballusers) setBalls("GROUP"); //if group access only } } }
Notecard "pos" :
//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; z = (integer)llGetObjectDesc(); pos.z += (float)z/100; } getPos() { pos1 = (vector)llList2String(positions1, p); pos2 = (vector)llList2String(positions2, p); rot1 = (vector)llList2String(rotations1, p); rot2 = (vector)llList2String(rotations2, p); } 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 from, integer num, string pdata, key 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 from, integer num, string cmd, key pkey) { if (cmd == "PRIMTOUCH"){ return; } if (num) return; if (cmd == "POSE") { p = (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(cmd, 0, 0) == "Z") { z += (integer)llGetSubString(cmd, 1, -1); pos.z = pos0.z + (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" :
//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) { i = 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.x, 3)+","+round(p.y, 3)+","+round(p.z, 3)+"> <"+round(r.x, 1)+","+round(r.y, 1)+","+round(r.z, 1)+">"; } string round(float number, integer places) { float shifted; integer rounded; string s; shifted = number * llPow(10.0,(float)places); rounded = llRound(shifted); s = (string)((float)rounded / llPow(10.0,(float)places)); s = 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 from, integer num, string an1str, key an2key) { if (num != 9+a) return; if (an1str == "LOADED") state on; an1 = an1str; an2 = (string)an2key; if (a>1) { if (an1 == "") an1 = llList2String(anims, 2); //use default else if (llGetInventoryType(an1) != INVENTORY_ANIMATION) llSay(0,"animation '"+an1+"' not in inventory (ok for build-in animations, otherwise check)"); if (an2 == "") an2 = llList2String(anims, 3); //use default else if (llGetInventoryType(an2) != INVENTORY_ANIMATION) llSay(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 += [ an1, an2 ]; ++a; } state_exit() { llOwnerSay((string)a+" posepairs loaded ("+llGetScriptName()+": "+(string)llGetFreeMemory()+" bytes free)"); } } state on { link_message(integer from, integer num, string cmd, key akey) { if (cmd == "PRIMTOUCH"){ return; } if (num) return; if (cmd == "POSE") { a = (integer)((string)akey) * 2; an1 = llList2String(anims, a); an2 = llList2String(anims, a+1); } else if (cmd == "SWAP") { swap = !swap; } else if (cmd == "SAVE") { pose = (string)akey; state save; } else return; llMessageLinked(LINK_THIS,ch+swap, an1,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 channel, string name, key id, string pr) { if (channel == ch+8+swap) pr1 = pr; else if (channel == ch+8+!swap) pr2 = 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 from, integer num, string posstr, key 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"
//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);++i) llStopAnimation(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 from, integer num, string an, key 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 channel, string name, key id, string 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_KEY) llRequestPermissions(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" :
//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);++i) llStopAnimation(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 from, integer num, string an, key 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 channel, string name, key id, string 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_KEY) llRequestPermissions(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"
//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_num, integer num, string str, key 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
|