RLV Collision Grabber

==Introduction==
This script placed in a prim makes that prim a collision detector that tries to force sit the colliding avatar on a set target using RLV.
The victim needs RLV and a relay to be grabbed by the script. 
/* This program is free software. It comes without any warranty, to
 * the extent permitted by applicable law. You can redistribute it
 * and/or modify it under the terms of the Do What The Fuck You Want
 * To Public License, Version 2, as published by Sam Hocevar. See
 * http://sam.zoy.org/wtfpl/COPYING for more details. */ 
 
/* Place the script in the prim you want to turn into the sensor.
 * The object will then detect collisions and tries to
 * force sit and lock the victim on the set target (see below).
 * It also tries to detect and lock people who just sit on the target
 * Feel free to contact me, Vala Vella, if you have questions 
 * If you use this in your project I'd like to hear about it :) */
key target = "00000000-0000-0000-0000-000000000000"; // UUID of the target object the victim will sit on. Must contain any sit script
integer sitscan = TRUE; // try to detect and lock people who sit manually (TRUE/FALSE)
integer lockseconds = 30; // time in seconds the victim will be locked to the target
integer sleeptime = 10; // time in seconds the victim has to leave the area after being freed to avoid instant regrabbing
// do not set sleeptime to 0!
//=======================================================================================================================//
key victim = NULL_KEY; //current victim
integer freetime; //end of timer as unix timestamp
list queue; // list for queueing victims in case more than one walk into the trap
integer RLVchan = -1812221819; //RLV Relay channel. do NOT change!
integer commchan; // channel to listen for client answers
float targetmass; // mass of the target to check if someone is sitting
string locktime; // lock time in human readable format
integer locked; // TRUE if someone is locked up
integer sitting; // TRUE is the victim is sitting on target (checked via RLV) 
debug(string txt)
{
 // uncomment the next line to see debugging messages
 //llSay(DEBUG_CHANNEL, "DEBUG-INFO: "+txt);
}
relay(string type,key victim,string command) //send command to relay
{
 llRegionSayTo(victim, RLVchan, type+","+(string)victim+","+command);
}
next() //process next entry in queue
{
 debug("next()");
 if (llGetObjectMass(target) > targetmass) //stop here if someone is sitting on the object
 {
 debug("Someone is sitting");
 queue = [];
 return;
 }
 if (victim == NULL_KEY && llGetListLength(queue) > 0)
 {
 key this = llList2Key(queue, 0);
 if (llVecDist(llList2Vector(llGetObjectDetails(this, [OBJECT_POS]), 0), llGetPos() ) < 10.0)
 {
 locked = FALSE;
 sitting = FALSE;
 relay("sit", llList2Key(queue, 0), "@sit:"+(string)target+"=force");
 llSetTimerEvent(10);
 }
 else
 {
 queue = llDeleteSubList(queue, 0, 0);
 next();
 }
 }
}
default
{
 state_entry()
 {
 list objectinfo = llGetObjectDetails(target, [OBJECT_NAME, OBJECT_POS]);
 if (llList2Vector(objectinfo, 1) != <0,0,0>) //check if target exists
 {
 targetmass = llGetObjectMass(target);
 locktime = (string)llFloor((float)lockseconds / 60)+" minutes";
 if (lockseconds%60) locktime += ", "+(string)(lockseconds%60)+" seconds";
 llOwnerSay("Set to target: "+llList2String(objectinfo, 0));
 llOwnerSay("Locktime: "+locktime);
 commchan = (integer)("0x"+llGetSubString((string)llGetKey(), 0, 6))+(integer)"0x70000000";
 debug("command channel: "+(string)commchan);
 debug("object mass: "+(string)targetmass);
 llListen(RLVchan, "", "", "");
 llListen(commchan, "", victim, "");
 llVolumeDetect(TRUE);
 llSetTimerEvent(10);
 }
 else
 {
 llOwnerSay("Set target not found. Please edit the script and check the settings");
 }
 }
 
 on_rez(integer num)
 {
 llResetScript();
 }
 
 collision_start(integer num)
 {
 debug ((string)num+" collisions");
 if (!locked)
 {
 while (num)
 {
 num--;
 if (!~llListFindList(queue, [llDetectedKey(num)]) && victim == NULL_KEY) //if detected agent is not queued and no victim queue them 
 {
 queue += llDetectedKey(num);
 debug (llList2CSV(queue));
 if (llGetListLength(queue) == 1) next(); //process queue if it has one entry
 }
 }
 }
 }
 
 listen(integer chn, string name, key id, string msg)
 {
 if (chn == RLVchan) //answers from relay
 {
 list answer = llCSV2List(msg);
 key rkey = llList2Key(answer, 1);
 if (rkey == llGetKey())
 {
 debug("RLV answer: "+msg);
 string rhandle = llList2String(answer, 0);
 string rcommand = llList2String(answer, 2);
 string rok = llList2String(answer, 3);
 if (rhandle == "sit" && rok == "ok")
 {
 llSetTimerEvent(0);
 victim = llGetOwnerKey(id);
 llSleep(1);
 relay("sitcheck", victim, "@getsitid="+(string)commchan);
 llSetTimerEvent(3);
 }
 if (rhandle == "sitlock" && rok == "ok" && llGetOwnerKey(id) == victim)
 {
 llRegionSayTo(victim, 0, "You are locked for "+locktime);
 }
 if (rcommand == "!release" && rok == "ok" && llGetOwnerKey(id) == victim)
 {
 debug("released");
 locked = FALSE;
 victim = NULL_KEY;
 next();
 }
 } 
 }
 else if (chn == commchan) //answers from the victims client
 {
 debug("Comm answer: "+msg);
 if ((key)msg == target) //when the victim is sitting on the target it will send the targets key on the comm channel
 {
 if (!locked)
 {
 victim = id;
 llSetTimerEvent(10);
 freetime = llGetUnixTime()+lockseconds;
 relay("sitlock", victim, "@unsit=n");
 locked = TRUE;
 }
 sitting = TRUE;
 }
 }
 }
 
 timer()
 {
 if (locked)
 {
 if (llGetUnixTime() >= freetime)
 {
 relay("release", victim, "!release");
 llRegionSayTo(victim, 0, "You are free. You have "+(string)sleeptime+" seconds to leave!");
 locked = FALSE;
 llSetTimerEvent(sleeptime);
 }
 else if (sitting == TRUE)
 {
 sitting = FALSE;
 relay("sitcheck", victim, "@getsitid="+(string)commchan);
 } 
 }
 else
 {
 llSetTimerEvent(5);
 if (llGetObjectMass(target) > targetmass && sitscan == TRUE) //is someone sitting?
 {
 llSensor("", "", AGENT, llVecDist(llGetPos(), llList2Vector(llGetObjectDetails(target, [OBJECT_POS]), 0))+2.0, PI); // find possible victims
 }
 else
 {
 queue = llDeleteSubList(queue, 0, 0);
 victim = NULL_KEY;
 locked = FALSE;
 next();
 }
 }
 }
 
 sensor(integer num)
 {
 while(num)
 {
 num--;
 if (llGetAgentInfo(llDetectedKey(num)) & AGENT_SITTING) relay("sitcheck", llDetectedKey(0), "@getsitid="+(string)commchan); // check if sitting and if so ask relay for object they are sitting on
 }
 }
}
RLV Collision Grabber
Category:RestrainedLove