SHARE
TWEET

addon PAO LockGuard v1.0

AineCaoimhe Jul 7th, 2017 65 Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. // LOCKGUARD ADD-ON FOR PMAC 1.0
  2. // by Aine Caoimhe (c. LACM) July 2017
  3. // Provided under Creative Commons Attribution-Non-Commercial-ShareAlike 4.0 International license.
  4. // Please be sure you read and adhere to the terms of this license: https://creativecommons.org/licenses/by-nc-sa/4.0/
  5. //
  6. // Command format for this addon:
  7. // PAO_LOCK{chain_data_pos1::chain_data_pos12...}
  8. // for each position the following is needed:
  9. //          child_prim_name=lockguard_link_name and any other valid lg commands
  10. //          to do multiples, separate each with "&&"
  11. //  if a position has no data, it needs to be given "LOCK_NO_COM" instead
  12. //
  13. // Example #1: for a 2-person pose where the 1st position has 3 chains and the 2nd position has none...
  14. // Pose1|POA_LOCK{Point-1=rightwrist&&Point-3=leftwrist&&Point-8=leftankle::LOCK_NO_COM}|...the rest of the animation line data
  15. // Example #2" the exact same pose, except this time it's position 1 that has no chains and position 2 that has 3
  16. // Pose2|POA_LOCK{LOCK_NO_COM::Point-1=rightwrist&&Point-3=leftwrist&&Point-8=leftankle}|...the rest of the animation line data
  17. //
  18. // Each possible LG attachment point of the PMAC object must be a child prim (cannot be root) and must have a UNIQUE name (it also can't
  19. // be "Primitive" even it it's the only prim with that name)
  20. //
  21. integer warnAboutDupes=FALSE;
  22. // During initialization ths add-on has to check child-prim names and retain a list of any that are unique. When discovering duplicated named prims it will
  23. // ignore them but by setting this TRUE you will be notified that it's doing so which could be useful when creating a new item or during an MLP conversion process.
  24. // Leaving it at the default FALSE will have it ignore them silently.
  25. //
  26. // # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
  27. // DO NOT CHANGE ANYTHING BELOW HERE UNLESS YOU KNOW WHAT YOU'RE DOING
  28. // # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
  29. //
  30. integer lgChannel=-9119;    // LG channel per spec.
  31. list targets;       //[child prim name, key,....]
  32. list existingLinks; // pairs of data for avatar and which lg points are being used... [avatar key, point1|point2|point3|....]...order doesn't matter
  33. //
  34. // FOR REFERENCE: LG syntax expected by the receiving object )cuff or whatever):
  35. // llWhisper( -9119, "lockguard " + (string)[targetUUID] +" "+ (string)[item to link]+" " + (string)[commands using space separation] );
  36. // only critical commands are the link and unlink....link is followed by the key of the PMAC object attachment point and unlink has no argument
  37. //
  38. addLinks(key who, string dataBlock)
  39. {
  40.     //ignore invalid or null keys and datablocks marked as empty
  41.     if (who==NULL_KEY) return;
  42.     if (!osIsUUID(who)) return;
  43.     if (dataBlock=="LOCK_NO_COM") return;
  44.     // getting here means we ought to have something we need to draw so now we need to break it by attach points
  45.     list pointsData=llParseString2List(dataBlock,["&&"],[]);
  46.     integer p=llGetListLength(pointsData);
  47.     list targetLinkData=[];
  48.     while (--p>=0)
  49.     {
  50.         list thisPointData=llParseString2List(llList2String(pointsData,p),["="],[]);
  51.         string thisPoint=llList2String(thisPointData,0); // the name of the PMAC attachment point prim
  52.         integer indexThisPoint=llListFindList(targets,[thisPoint]);
  53.         if (indexThisPoint==-1) llOwnerSay("ERROR: told to draw a chain to child prim "+thisPoint+" but it doesn't exist");
  54.         else
  55.         {
  56.             key thisPointKey=llList2Key(targets,indexThisPoint+1);
  57.             string attachString=llList2String(thisPointData,1);
  58.             integer firstSpace=llSubStringIndex(attachString," ");
  59.             if (firstSpace>-1) firstSpace--;    // we don't want to bring the space with it too
  60.             string attachName=llGetSubString(attachString,0,firstSpace); // this is just the cuff name to store in the user list
  61.             targetLinkData=[]+targetLinkData+[attachName];
  62.             llWhisper(lgChannel,"lockguard "+(string)who+" "+attachString+" link "+(string)thisPointKey);
  63.         }
  64.     }
  65.     existingLinks=[]+existingLinks+[who,llDumpList2String(targetLinkData,"|")];
  66. }
  67. stripLinks(key who)
  68. {
  69.     // remove any links
  70.     integer lInd=llListFindList(existingLinks,[who]);
  71.     if (lInd>-1)
  72.     {
  73.         // there are some so parse them to list and remove one by one
  74.         list pointsToStrip=llParseString2List(llList2String(existingLinks,lInd+1),["|"],[]);
  75.         integer p=llGetListLength(pointsToStrip);
  76.         while (--p>=0) { llWhisper(lgChannel,"lockguard "+(string)who+" "+llList2String(pointsToStrip,p)+" unlink"); }
  77.         // delete the entry
  78.         existingLinks=[]+llDeleteSubList(existingLinks,lInd,lInd+1);
  79.     }
  80. }
  81. buildTargetList()
  82. {
  83.     list ignore=[];
  84.     targets=[];
  85.     integer link=llGetNumberOfPrims();
  86.     if (link==1)
  87.     {
  88.         llOwnerSay("LOCKGUARD PMAC addon cannot work with an object that has only 1 prim. Please read the instructions!");
  89.         return;
  90.     }
  91.     while (link>1)
  92.     {
  93.         string name=llGetLinkName(link);
  94.         if (name!="Primitive")
  95.         {
  96.             if (llListFindList(ignore,[name])>-1)
  97.             {
  98.                 if (warnAboutDupes) llOwnerSay("WARNING! LOCKGUARD for PMAC found another child prim with the name \""+name+"\" and will ignore it too.");
  99.             }
  100.             if (llListFindList(targets,[name])>-1)
  101.             {
  102.                 if (warnAboutDupes) llOwnerSay("WARNING! LOCKGUARD for PMAC found two child prims with the same name \""+name+"\" and will ignore them. They cannot be called as attachment points");
  103.                 targets=[]+llDeleteSubList(targets,llListFindList(targets,[name]),llListFindList(targets,[name]));
  104.                 ignore=[]+ignore+[name];
  105.             }
  106.             else targets=[]+[name,llGetLinkKey(link)]+targets;
  107.         }
  108.         link--;
  109.     }
  110. }
  111. default
  112. {
  113.     state_entry()
  114.     {
  115.         // we need a quick-access list of attachment points to potentially attach chains to so might as well build it on start-up when there's no appreciable load
  116.         buildTargetList();
  117.         existingLinks=[];
  118.     }
  119.     link_message(integer fromLink,integer num, string message, key ID)
  120.     {
  121.         list parsed=llParseString2List(message,["|"],[]);
  122.         // see if this is a main PMAC command that we need to pay attention to
  123.         string mainCommand=llList2String(parsed,0);
  124.         if (mainCommand=="GLOBAL_SYSTEM_RESET")
  125.         {
  126.             // release any existingLinks
  127.             while (llGetListLength(existingLinks)>0) { stripLinks(llList2Key(existingLinks,0)); }
  128.             llResetScript();
  129.         }
  130.         else if (mainCommand=="GLOBAL_USER_STOOD")
  131.         {
  132.             // release any existingLinks
  133.             stripLinks(llList2Key(parsed,2));
  134.         }
  135.         else if (mainCommand=="GLOBAL_NEXT_AN")
  136.         {
  137.             // whether or not there's data for the new animation, we need to remove any old
  138.             while (llGetListLength(existingLinks)>0) { stripLinks(llList2Key(existingLinks,0)); }
  139.             // find out if the command block has anything for us..
  140.             list theseCommands=llParseString2List(llList2String(parsed,1),["{","}"],[]);
  141.             integer indexThisBlock=(llListFindList(theseCommands,["PAO_LOCK"]));
  142.             if (indexThisBlock==-1) return; // finished if there isn't any new data
  143.             // otherwise let's read our block and break it into positions first
  144.             list positionData=llParseString2List(llList2String(theseCommands,indexThisBlock+1),["::"],[]);
  145.             // pull the users list from the passed data
  146.             list users=llParseString2List((string)ID,["|"],[]);
  147.             integer u=llGetListLength(users);
  148.             // error-check length match
  149.             if (llGetListLength(positionData)!=u)
  150.             {
  151.                 llOwnerSay("ERROR! LOCKGUARD add-on encountered a mismatch between number of postions in the card chain data and number of positions in the pose. Can't draw chains");
  152.                 return;
  153.             }
  154.             // otherwise send each
  155.             llSleep(0.1);   // yes, this is a deliberate thread-lock - due to potential asynch sending we need to do a short delay to ensure that any new draw commands arrive *after* the last of the strip ones
  156.             while (--u>=0) { addLinks(llList2Key(users,u),llList2String(positionData,u)); }
  157.         }
  158.     }
  159. }
RAW Paste Data
Pastebin PRO Summer Special!
Get 60% OFF on Pastebin PRO accounts!
Top