MLPV2 RLV Plugin
- MLPV2
- Back to MLPV2_Addons
This Plugin combines the possibilities of MLPV2 with the commands of the Restrained Love Viewer.
It reads a notecard, which must me named .RLV to define a RLV command for a Pose.
<lsl>// ---------------------------------------------------------------------------------- // MLPV2 Plugin for RLV Script V1.02 // // Use with a notecard named .RLV with the format: // Pose|Ball no.: 0,1...*|@RLV-Command // e.g. // Missionary|1|@unsit=n // stand|*|!release // ---------------------------------------------------------------------------------- // Copyright (c) 2010, Jenni Eales. All rights reserved. // ---------------------------------------------------------------------------------- // Redistribution and use in source and binary forms, with or without modification, // are permitted provided that the following conditions are met: // // * Redistributions of source code must retain the above copyright notice, // this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above copyright notice, // this list of conditions and the following disclaimer in the documentation // and/or other materials provided with the distribution. // * The names of its contributors may not be used to endorse or promote products // derived from this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES // OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. // IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, // INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, // BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, // OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, // WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY // OF SUCH DAMAGE. // // Changes: // ---------------------------------------------------------------------------------- // Version 1.02 // - use | as seperator // - support multiple lines for one pose // - additional link message for direct call from ball menu // // Version 1.01 // - use ; instead of | as seperator // // Version 1.0 // - first version released // ---------------------------------------------------------------------------------- // // constants string NOTECARD = ".RLV"; // name of config notecard integer DEBUG = FALSE; // switch debug on/off integer RELAY_CHANNEL = -1812221819; // channel for RLV relay float TIMER_SEC = 1800.0; // 30 min. string CMD_RELEASE = "!release"; // release command integer LM_NUMBER = -1819; // number for link message
// internal use key kQuery; integer iLine;
string pose = "stand"; // pose set by the Ball Menu list poses = []; // configured poses list balls = []; // configured balls list commands = []; // configured commands list avatars = []; // avatars sitting on balls
// log a message log(string message) { if(DEBUG) llOwnerSay(message); }
// only for testing purposes log_data() { log("List:"); integer total_number = llGetListLength(commands); integer i; for(i=0; i<total_number; i++) { log("- " + llList2String(poses, i) + ": (" + llList2String(balls, i) + ") "+ llList2String(commands, i)); } }
// write a message to the RLV Relay relay(key avatar, string message) { list tokens = llParseString2List(message, ["|"], [""]); integer total_number = llGetListLength(tokens); integer i; for(i=0; i<total_number; i++) { string token = llList2String(tokens, i); log("RLV: MLPV2," + (string) avatar + "," + token); llSay(RELAY_CHANNEL, "MLPV2," + (string) avatar + "," + token); } }
// find commands for pose and play it for avatars on ball rlv(string pose) { log("command for: " + pose); llSetTimerEvent(TIMER_SEC);
integer total_number = llGetListLength(poses); integer i; for(i=0; i<total_number; i++) { if (pose == llList2String(poses, i)) { string ball = llList2String(balls, i); log("command for pose: " + pose + " (" + ball + ")"); if (ball == "*") { integer b; for (b=0; b<6; b++) { // get avatar for ball index key avatar = llList2Key(avatars, b); if(avatar != NULL_KEY) relay(avatar, llList2String(commands, i)); } } else { key avatar = llList2Key(avatars, (integer) ball); if(avatar != NULL_KEY) relay(avatar, llList2String(commands, i)); } } } }
// new find: pose and ball needs to match integer find_pose(string pose, string ball) { integer total_number = llGetListLength(poses); integer i; for(i=0; i<total_number; i++) { if (pose == llList2String(poses, i) && ball == llList2String(balls, i)) { return i; } } return -1; }
// add a pose/ball/command entry add_pose(string pose, string ball, string command) { // look for existing entry for pose integer found = find_pose(pose, ball); if (found == -1) { // add a new pose poses += [pose]; balls += [ball]; commands += [command];
log("Added from " + NOTECARD + ": " + pose + " | " + ball + " | " + command); } else { // append to existing pose string c = llList2String(commands, found) + "|" + command; commands = llListReplaceList(commands, [c], found, found);
log("Added " + command + " to pose " + pose); } }
// parse and store a line process_line(string line) { list tokens = llParseString2List(line, [" | "," | "," | "," | "," |","| ","|"],[""]); if(llGetListLength(tokens) < 3) return;
string pose = llList2String(tokens, 0); string ball = llList2String(tokens, 1);
integer total_number = llGetListLength(tokens); integer i; for(i=2; i<total_number; i++) { add_pose(pose, ball, llList2String(tokens, i)); } }
// check if object is in the inventory integer exists_notecard(string notecard) { return llGetInventoryType(notecard) == INVENTORY_NOTECARD; }
// initialize me initialize() { log("Initializing..."); poses = []; balls = []; commands = []; avatars = [NULL_KEY, NULL_KEY, NULL_KEY, NULL_KEY, NULL_KEY, NULL_KEY];
if (exists_notecard(NOTECARD)) { log("Reading " + NOTECARD + "..."); iLine = 0; kQuery = llGetNotecardLine(NOTECARD, iLine); } else { llOwnerSay("Not found: " + NOTECARD ); } }
default { // on state entry initialize me state_entry() { initialize(); }
// reset on Inventory change changed(integer change) { if (change & CHANGED_INVENTORY) initialize(); }
// read a line from notecard dataserver(key _query_id, string _data) { // were we called to work on notecard? if (_query_id == kQuery) { // this is a line of our notecard if (_data == EOF) { if (DEBUG) log_data(); log(NOTECARD + " read."); } else { // increment line count // data has the current line from this notecard if(_data != "") { process_line(_data); }
// request next line // read another line when you can iLine++; kQuery = llGetNotecardLine(NOTECARD, iLine); } } }
timer() { integer b; for (b=0; b<6; b++) { // get avatar for ball index key avatar = llList2Key(avatars, b);
// if not null send command if(avatar != NULL_KEY) relay(avatar, CMD_RELEASE); } llSetTimerEvent(0.0); }
// link message from MLPV2 link_message(integer sender_number, integer number, string message, key id) { // pose from ball menu selected if (number == 0 && message == "POSEB") { pose = (string)id; rlv(pose); return; }
// direct call from ball menu // configure in .MENUITEMS with // LINKMSG Resctriction | 0,-1,-1819,Restriction if (number == LM_NUMBER) { pose = message; rlv(pose); return; }
// unsit avatar if (number == -11001) { integer ball = (integer) message; log("Avatar unsit from ball " + (string) ball +": " + (string) llList2Key(avatars, ball)); relay(llList2Key(avatars, ball), CMD_RELEASE); avatars = llListReplaceList(avatars, [NULL_KEY], ball, ball); }
// sit avatar if (number == -11000) { list tokens = llParseString2List(message, ["|"], [" "]); integer ball = llList2Integer(tokens, 0); log("Avatar sit on ball " + (string) ball +": " + (string) id); avatars = llListReplaceList(avatars, [id], ball, ball); rlv(pose); } } }</lsl>
The .RLV notecard might be look like this:
Trapped | 0 | @unsit=n Strip | 0 | @remoutfit:shirt=force|@remoutfit:pants=force|@remoutfit:socks=force Strip | 0 | @remoutfit:undershirt=force|@remoutfit:underpants=force stand | * | !release
Fully Featured RLV Menu EXample
The following configuration adds a full RLV menu to your device. Make sure to add TOMENU RLV to your .MENUITEMS notecard to enable access to the RLV functions. This configuration applies the restrictions only to the avatar sitting on the poseball number 0. Replace the 0 with the appropriate number if your device has a different configuration. Devices that have the victim on different poseballs in different poses will have to be adjusted to use the same poseball for all poses. You also might want to add @touchworld=n|@fartouch=n to the above config for each pose to prevent the victim from calling up the MLP2 menu and touching other people's attachments and things out of reach.
Add this to your .RLV notecard:
NoWear | 0 | @addoutfit=n NoUnwear | 0 | @remoutfit=n Wear | 0 | @addoutfit=y Unwear | 0 | @remoutfit=y StripUpper | 0 | @addoutfit=n|@remoutfit:shirt=force|@remoutfit:undershirt=force StripUpper | 0 | @remoutfit:jacket=force|@remoutfit:gloves=force StripLower | 0 | @addoutfit=n|@addattach=n|@remoutfit:pants=force StripLower | 0 | @remoutfit:underpants=force|@remoutfit:skirt=force|@remoutfit:socks=force StripLower | 0 | @remoutfit:shoes=force|@remattach:pelvis=force|@remattach:stomach=force StripLower | 0 | @remattach:left foot=force|@remattach:right foot=force StripAll | 0 | @addoutfit=n|@remoutfit=force NoAttach | 0 | @addattach=n NoDetach | 0 | @remattach=n Attach | 0 | @addattach=y Detach | 0 | @remattach=y StripJacket | 0 | @addoutfit=n|@remoutfit:jacket=force StripShirt | 0 | @addoutfit=n|@remoutfit:shirt=force StripGloves | 0 | @addoutfit=n|@remoutfit:gloves=force StripUndershirt | 0 | @addoutfit=n|@remoutfit:undershirt=force StripPants | 0 | @addoutfit=n|@remoutfit:pants=force StripSkirt | 0 | @addoutfit=n|@addattach=n|@remoutfit:skirt=force|@remattach:stomach=force StripSkirt | 0 | @remattach:pelvis=force StripSocks | 0 | @addoutfit=n|@remoutfit:socks=force StripShoes | 0 | @addoutfit=n|@addattach=n|@remoutfit:shoes=force StripShoes | 0 | @remattach:left foot=force|@remattach:right foot=force NoShout | 0 | @chatshout=n Shout | 0 | @chatshout=y NoNormal | 0 | @chatnormal=n Normal | 0 | @chatnormal=y Mute | 0 | @sendchat=n|@emote=add Unmute | 0 | @sendchat=y|@emote=rem Deaf | 0 | @recvchat=n Hear | 0 | @recvchat=y MuteIM | 0 | @sendim=n UnmuteIM | 0 | @sendim=y DeafIM | 0 | @recvim=n HearIM | 0 | @recvim=y NoMinimap | 0 | @showminimap=n Minimap | 0 | @showminimap=y NoMap | 0 | @showworldmap=n Map | 0 | @showworldmap=y NoLocation | 0 | @showloc=n Location | 0 | @showloc=y NoNames | 0 | @shownames=n Names | 0 | @shownames=y NoInventory | 0 | @showinv=n Inventory | 0 | @showinv=y NoRez | 0 | @rez=n Rez | 0 | @rez=y NoEdit | 0 | @edit=n Edit | 0 | @edit=y NoNotecards | 0 | @viewnote=n Notecards | 0 | @viewnote=y NoScripts | 0 | @viewscript=n Scripts | 0 | @viewscript=y NoTextures | 0 | @vewtexture=n Textures | 0 | @vewtexture=y stand | * | !release
.MENUITEMS.RLV notecard
MENU RLV TOMENU Clothes TOMENU Chat TOMENU Disorient TOMENU Other BACK MENU Clothes | ALL LINKMSG No Wear | 0,-1,-1819,NoWear LINKMSG No Unwear | 0,-1,-1819,NoUnwear LINKMSG Wear | 0,-1,-1819,Wear LINKMSG Unwear | 0,-1,-1819,Unwear LINKMSG Strip Upper | 0,-1,-1819,StripUpper LINKMSG Strip Lower | 0,-1,-1819,StripLower LINKMSG Strip All | 0,-1,-1819,StripAll TOMENU Strip Single LINKMSG No Attach | 0,-1,-1819,NoAttach LINKMSG No Detach | 0,-1,-1819,NoDetach LINKMSG Attach | 0,-1,-1819,Attach LINKMSG Detach | 0,-1,-1819,Detach BACK MENU Strip Single LINKMSG Jacket | 0,-1,-1819,StripJacket LINKMSG Shirt | 0,-1,-1819,StripShirt LINKMSG Gloves | 0,-1,-1819,StripGloves LINKMSG Undershirt | 0,-1,-1819,StripUndershirt LINKMSG Pants | 0,-1,-1819,StripPants LINKMSG Skirt | 0,-1,-1819,StripSkirt LINKMSG Socks | 0,-1,-1819,StripSocks LINKMSG Shoes | 0,-1,-1819,StripShoes BACK MENU Chat | ALL LINKMSG No Shout | 0,-1,-1819,NoShout LINKMSG Shout | 0,-1,-1819,Shout LINKMSG No Normal | 0,-1,-1819,NoNormal LINKMSG Normal | 0,-1,-1819,Normal LINKMSG Mute | 0,-1,-1819,Mute LINKMSG Unmute | 0,-1,-1819,Unmute LINKMSG Deaf | 0,-1,-1819,Deaf LINKMSG Hear | 0,-1,-1819,Hear LINKMSG Mute IM| 0,-1,-1819,MuteIM LINKMSG Unmute IM| 0,-1,-1819,UnmuteIM LINKMSG Deaf IM| 0,-1,-1819,DeafIM LINKMSG Hear IM| 0,-1,-1819,HearIM BACK MENU Disorient LINKMSG No Minimap | 0,-1,-1819,NoMinimap LINKMSG Minimap | 0,-1,-1819,Minimap LINKMSG No Map | 0,-1,-1819,NoMap LINKMSG Map | 0,-1,-1819,Map LINKMSG No Location | 0,-1,-1819,NoLocation LINKMSG Location | 0,-1,-1819,Location LINKMSG No Names | 0,-1,-1819,NoNames LINKMSG Names | 0,-1,-1819,Names BACK MENU Other LINKMSG No Inventory | 0,-1,-1819,NoInventory LINKMSG Inventory | 0,-1,-1819,Inventory LINKMSG No Rez | 0,-1,-1819,NoRez LINKMSG Rez | 0,-1,-1819,Rez LINKMSG No Edit | 0,-1,-1819,NoEdit LINKMSG Edit | 0,-1,-1819,Edit LINKMSG No Notecards | 0,-1,-1819,NoNotecards LINKMSG Notecards | 0,-1,-1819,Notecards LINKMSG No Scripts | 0,-1,-1819,NoScripts LINKMSG Scripts | 0,-1,-1819,Scripts LINKMSG No Textures | 0,-1,-1819,NoTextures LINKMSG Textures | 0,-1,-1819,Textures BACK
See also: