SHARE
TWEET

addon PAO RLV v1.0

AineCaoimhe Jul 7th, 2017 83 Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. // RLV 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_RLV_SEND{position1commands::position2commands::....}
  8. // where for each position you need to supply either
  9. //      RVL_NO_COM = don't send anything to this position; or
  10. //      one or more valid RLV command in the standard RLV format
  11. // you can send multiple commands by comma-separating them
  12. // DO NOT include any extra spaces between the separators or before/after the curly braces
  13. //
  14. // # # # # # # # # # # # # # #
  15. // USER CONFIGURATION SETTINGS
  16. // # # # # # # # # # # # # # #
  17. // IMPORTANT TO SET THIS ONE CORRECTLY!
  18. integer sendAsRlvComChain=FALSE;
  19. // RLV v1.10 or higher allows multiple commands by using a single "@" followed by the comma-separated command list
  20. // Prior versions allowed only 1 command per send.
  21. // Most Opensim MLP systems with RLV that I've seen use the old syntax but chain them with a pipe-separated list which is later
  22. // parsed out again and sent 1 by one. This add-on supports both.
  23. //
  24. // If your command chain for a position looks like this:
  25. // @tplm=n,@tploc=n,@tplure=n,@sittp=n,@fartouch=n,@showinv=n,@fly=n,@unsit=n,@unsit=n,@edit=n,@rez=n,@showworldmap=n,@showminimap=n,@sendim=n
  26. // then ensure that sendAsRlvComChain = FALSE and each will be sent 1 by 1.
  27. //
  28. // If your command chain looks like this:
  29. // @tplm=n,tploc=n,tplure=n,sittp=n,fartouch=n,showinv=n,fly=n,unsit=n,unsit=n,edit=n,rez=n,showworldmap=n,showminimap=n,sendim=n
  30. // then ensure that the sendAsRlvComChain = TRUE and the entire chain will be sent as a single block (assumes your relay won't choke on it either)
  31. //
  32. // If at all in doubt, use FALSE and make sure that each individual command is preceded by a "@" symbol...it will work on all RLV versions
  33. //
  34. // SETTINGS FOR INTEGRATED CAPTURE:
  35. //
  36. float captureRange=32.0;        // range (in meters) to look for an av to capture...the range is radius from the root prim
  37. float victimTimeout=600.0;     // how long (in seconds) the PMAC object can be idle before any captured victims are released
  38. //
  39. // # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
  40. // DO NOT CHANGE ANYTHING BELOW HERE UNLESS YOU KNOW WHAT YOU'RE DOING!
  41. // # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
  42. //
  43. // With PMAC all commands must be inside the same line so we need two separators: one to distinguish positions and one to distinguish commands for that position
  44. // a blank can use the (local) global "blank" but just to cover potential swaps or whatever it might be safer to use the global !release command for your blank instead
  45. string pSep="::";   // string separating positions
  46. string cSep=",";    // the official RLV command separator string since then we don't have to do any handling of it at all..if this changes all hell's going to break loose....
  47.  
  48. integer RELAY=-1812221819;  // channel that RLV protocal defines for relays
  49.  
  50. key user;                   // for dialog
  51. list butDia;
  52. string txtDia;
  53. string MENU="MENU_NONE";
  54.  
  55. integer crChannelOffset=84; // capture dialog channel (chosen becasue it's the numeric value of the word "capture")
  56. integer crChannel;         // = user key based - the capture channel offset so it doesn't conflict with anything else based on user key
  57. integer crHandle;
  58. float crTimeout=120.0;     // how long (in seconds) to wait before timing out the victim selection dialog
  59. list victims;
  60.  
  61. list detectedKeys;
  62. list detectedNames;
  63.  
  64. relay(key who, string message)
  65. {
  66.     // SEND MESSAGE TO RELAY
  67.     if ((who!=NULL_KEY)&&(osIsUUID(who))) llSay(RELAY,llGetObjectName()+","+(string)who+","+ message);
  68. }
  69. capture(key who)
  70. {
  71.     relay(who,"@sit:"+(string)llGetKey()+"=force");
  72.     victims=[]+victims+[who];
  73. }
  74. release(key who)
  75. {
  76.     // RELEASE A VICTIM
  77.     // it's possible due to asynch handling that the victim list is already updated but remove if not
  78.     integer victimIndex=llListFindList(victims,[who]);
  79.     if (victimIndex>-1) victims=[]+llDeleteSubList(victims,victimIndex,victimIndex);
  80.     relay(who,"@unsit=y");
  81.     relay(who,"!release");
  82.     if(llGetListLength(victims)>0) llSetTimerEvent(victimTimeout);
  83.     else llSetTimerEvent(0.0);
  84. }
  85. validateVictims(string vicList)
  86. {
  87.     // passed pipe-delimited list of users
  88.     // make sure each victim I think I have is still in that list...if not, release
  89.     list currentUsers=llParseString2List(vicList,["|"],[]);
  90.     integer check=llGetListLength(victims);
  91.     while (--check>=0)
  92.     {
  93.         key who=llList2Key(victims,check);
  94.         if (llListFindList(currentUsers,[who])==-1) release(who);
  95.     }
  96. }
  97. returnPMAC()
  98. {
  99.     // RETURN CONTROL TO THE MAIN PMAC MENU
  100.     if (llGetListLength(victims)>0) llSetTimerEvent(victimTimeout);
  101.     else llSetTimerEvent(0.0);
  102.     user=NULL_KEY;
  103.     llMessageLinked(LINK_THIS,-1,"MAIN_RESUME_MAIN_DIALOG",NULL_KEY);       // return to the PMAC main menu handler
  104. }    
  105. showMenu()
  106. {
  107.     crChannel=(0x80000000 | (integer)("0x"+(string)user))-crChannelOffset;
  108.     crHandle=llListen(crChannel,"",user,"");
  109.     llDialog(user,txtDia,llList2List(butDia,9,11)+llList2List(butDia,6,8)+llList2List(butDia,3,5)+llList2List(butDia,0,2),crChannel);
  110.     llSetTimerEvent(crTimeout);
  111. }
  112. default
  113. {
  114.     state_entry()
  115.     {
  116.         victims=[];
  117.         crHandle=FALSE;
  118.         user=NULL_KEY;
  119.     }
  120.     timer()
  121.     {
  122.         if (user!=NULL_KEY) returnPMAC();
  123.         else
  124.         {
  125.             // this is an inactivity timeout...release all
  126.             while (llGetListLength(victims)>0) {release(llList2Key(victims,0));}
  127.         }
  128.         llSetTimerEvent(0.0);   //either way stop the timer
  129.     }
  130.     touch_start(integer num)
  131.     {
  132.         if (llDetectedKey(0)!=user) return;
  133.         showMenu();
  134.     }
  135.     no_sensor()
  136.     {
  137.         llRegionSayTo(user,0,"Unable to detect anyone in range to capture");
  138.         returnPMAC();
  139.     }
  140.     sensor(integer num)
  141.     {
  142.         // build the dialog here so we can access the detected data
  143.         detectedKeys=[];
  144.         detectedNames=[];
  145.         list numbers;
  146.         integer i;
  147.         while (i<num)
  148.         {
  149.             key who=llDetectedKey(i);
  150.             string name=llKey2Name(who);
  151.             if ((who!=user)&&!osIsNpc(who)) // can't capture yourself or any npcs
  152.             {
  153.                 detectedKeys=[]+detectedKeys+[who];
  154.                 detectedNames=[]+detectedNames+[name];
  155.                 numbers=[]+numbers+[(string)llGetListLength(detectedNames)];
  156.             }
  157.             i++;
  158.         }
  159.         if (llGetListLength(numbers)<1)
  160.         {
  161.             // No valid capture targets
  162.             llRegionSayTo(user,0,"Unable to detect anyone in range to capture");
  163.             returnPMAC();
  164.             return;
  165.         }
  166.         txtDia="Select the victim to capture:\n\n"+llDumpList2String(llList2List(detectedNames,0,10),"\n");
  167.         butDia=[]+llList2List(numbers,0,10);
  168.         while (llGetListLength(butDia)<11) { butDia=[]+butDia+["-"]; }
  169.         butDia=[]+butDia+["CANCEL"];
  170.         MENU="MENU_CAPTURE";
  171.         showMenu();
  172.     }
  173.     listen(integer channel, string name, key who, string message)
  174.     {
  175.         llSetTimerEvent(0.0);
  176.         llListenRemove(crHandle);
  177.         // the "CANCEL" response can just fall through
  178.         if (message=="-")
  179.         {
  180.             showMenu();
  181.             return;
  182.         }
  183.         if (MENU=="MENU_CAPTURE")
  184.         {
  185.             integer indexToCapture=(integer)message-1;
  186.             key whoToCapture=llList2Key(detectedKeys,indexToCapture);
  187.             string vic=llList2String(detectedNames,indexToCapture);
  188.             llRegionSayTo(user,0,"Capturing "+vic);
  189.             capture(whoToCapture);
  190.             llSetTimerEvent(victimTimeout);
  191.         }
  192.         else if (MENU=="MENU_RELEASE")
  193.         {
  194.             if (message=="ALL CAPTIVES")
  195.             {
  196.                 while (llGetListLength(victims)>0) { release(llList2Key(victims,0)); }
  197.             }
  198.             else
  199.             {
  200.                 integer indexToRelease=(integer)message-1;
  201.                 key whoToRelease=llList2Key(victims,indexToRelease);
  202.                 string vic=llKey2Name(whoToRelease);
  203.                 llRegionSayTo(user,0,"Releasing "+vic);
  204.                 release(whoToRelease);
  205.             }
  206.         }
  207.         // either way, we return control to PMAC now
  208.         returnPMAC();
  209.     }
  210.     link_message (integer sender, integer num, string message, key id)
  211.     {
  212.         list parsed=llParseString2List(message,["|"],[]);
  213.         string command=llList2String(parsed,0);
  214.         list userList=llParseString2List(id,["|"],[]);
  215.         if (llGetListLength(victims)>0)llSetTimerEvent(victimTimeout);
  216.         if (command=="GLOBAL_SYSTEM_RESET")
  217.         {
  218.             while (llGetListLength(victims)>0)
  219.             {
  220.                 release(llList2Key(victims,0));
  221.             }
  222.             llResetScript();
  223.         }
  224.         else if (command=="GLOBAL_NEW_USER_ASSUMED_CONTROL")
  225.         {
  226.             // new PMAC menu user so need to register the Capture button to the Specials menu
  227.             // anyone with permission to access PMAC menu has permission to capture
  228.             llMessageLinked(LINK_THIS,-1,"MAIN_REGISTER_MENU_BUTTON|RLV Capture","PAO_RLV_Capture");
  229.             llMessageLinked(LINK_THIS,-1,"MAIN_REGISTER_MENU_BUTTON|RLV Release","PAO_RLV_Release");
  230.         }
  231.         else if (command=="GLOBAL_USER_STOOD")
  232.         {
  233.             // check if the user who stood was supposedly a victim...if so, release
  234.             release(llList2Key(parsed,2));
  235.         }
  236.         else if (command=="PAO_RLV_Capture")
  237.         {
  238.             // user selected Capture from the PMAC OPTIONS>SPECIALS menu
  239.             user=llList2Key(parsed,1);
  240.             validateVictims((string)id);
  241.             llSensor("", NULL_KEY, AGENT, captureRange, PI);
  242.         }
  243.         else if (command=="PAO_RLV_Release")
  244.         {
  245.             // handle it here
  246.             user=llList2Key(parsed,1);
  247.             validateVictims((string)id);
  248.             integer vicCount=llGetListLength(victims);
  249.             if (vicCount==0)
  250.             {
  251.                 // nobody on the list...the release button should have been deregistered but there could be asynch or glitchy handling so return
  252.                 llRegionSayTo(user,0,"I don't think I have any victims to release");
  253.                 returnPMAC();
  254.                 return;
  255.             }
  256.             else if (vicCount==1)
  257.             {
  258.                 // only one possible person to release so....
  259.                 release(llList2Key(victims,0));
  260.                 // and can send back to main
  261.                 returnPMAC();
  262.                 return;
  263.             }
  264.             // getting here means that we have 2 more more victims so we need to ask who to release
  265.             integer i;
  266.             butDia=[];
  267.             txtDia="Who would you like to release?\n";
  268.             while (llGetListLength(butDia)<10)
  269.             {
  270.                 if(i<vicCount)
  271.                 {
  272.                     txtDia+="\n"+(string)(i+1)+". "+llKey2Name(llList2Key(victims,i));
  273.                     butDia=[]+butDia+[(string)(i+1)];
  274.                     i++;
  275.                 }
  276.                 else butDia=[]+butDia+["-"];
  277.             }
  278.             butDia=[]+butDia+["ALL CAPTIVES","CANCEL"];
  279.             MENU="MENU_RELEASE";
  280.             showMenu();
  281.         }
  282.         else if (command=="GLOBAL_NEXT_AN")
  283.         {
  284.             // look at the command block for the animation to see if there's anything there for us
  285.             // first break it into individual
  286.             list anCommands=llParseString2List(llList2String(parsed,1),["{","}"],[]);
  287.             integer rlvIndex=llListFindList(anCommands,["PAO_RLV_SEND"]);
  288.             if (rlvIndex>-1)
  289.             {
  290.                 //this command block contains commands for us
  291.                 list rlvCommands=llParseString2List(llList2String(anCommands,rlvIndex+1),[pSep],[]);
  292.                 // error check for mismatch
  293.                 if (llGetListLength(rlvCommands)!=llGetListLength(userList))
  294.                 {
  295.                     llSay(0,"ERROR: Detected a RLV command block but the number of positions in the block doesn't match the number of positions sent");
  296.                     return;
  297.                 }
  298.                 integer position;
  299.                 while (position<llGetListLength(rlvCommands))
  300.                 {
  301.                     string theseCommands=llList2String(rlvCommands,position);
  302.                     if (theseCommands!="RLV_NO_COM")
  303.                     {
  304.                         if (sendAsRlvComChain) relay(llList2Key(userList,position),theseCommands);
  305.                         else
  306.                         {
  307.                             list whatToSend=llParseString2List(theseCommands,[cSep],[]);
  308.                             integer c=llGetListLength(whatToSend);
  309.                             while (--c>=0) { relay(llList2Key(userList,position),llList2String(whatToSend,c)); }
  310.                         }
  311.                     }
  312.                     position++;
  313.                 }
  314.             }
  315.         }
  316.     }
  317. }
RAW Paste Data
Top