User:Clarknova Helvetic/Sit TP Positioner

From Second Life Wiki
< User:Clarknova Helvetic
Revision as of 20:36, 24 January 2008 by Clarknova Helvetic (talk | contribs) (updated to add sensor fallback)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to navigation Jump to search

This set of scripts is for making perfect sit targets. It was first written by Lex Neva and heavily abused by me to adapt it for 300m sit-teleport support. You can use it for a sit target just 2cm away, or for from region corner to corner.

Behavior

The sit target setter comes in two parts: the Helper object and the Setter script.

  • First you sit on the Helper. If you have an animation to align, put the anim in the Helper before sitting.
  • After moving the Helper so your avatar is aligned and rotated properly, Put the Setter script into your chair or teleport object.
  • First the Setter broadcasts a region-wide message. When the Helper replies, it sets the target. The Helper also draws a line of particles to the chair.
  • If the Helper is too far away, the Setter warns you and tells you how many meters too far.
  • If the Helper doesn't reply, the Setter script tries to find it by sensor instead. This is useful if your teleport offset needs to be over no-script land.
  • If the Setter can't find the Helper at all, it tells you and gives you a list of possible reasons.


An unlimited number of builders can use their own copy simultaneously. They will never interfere.


There are two flavors of Setter script: touch_start and drag 'n drop. The touch_start sets a new sit target each time the chair is touched. You must remove this script manually. The drag 'n drop Setter sets the sit target and then removes from object inventory.


Helper script

Drop this script into a new box prim. It transforms the prim into the Helper.

<lsl>// Sit target system by Lex Neva. Please distribute willy-nilly. // http://forums.secondlife.com/showthread.php?t=153278&highlight=target

// Helper prim script


// Support for Teleport-range setting shoehorned in by Clarknova Helvetic // https://wiki.secondlife.com/wiki/User:Clarknova_Helvetic/Sit_TP_Positioner


default {

   on_rez(integer p) { llResetScript(); }
   
   state_entry() {
       
       // This ugly part turns our prim into a purple ball with the right name.
       llSetPrimitiveParams([PRIM_TYPE,3,0,<0.000000, 1.000000, 0.000000>,0.000000,<0.000000, 0.000000, 0.000000>,<0.000000, 1.000000, 0.000000> , PRIM_POINT_LIGHT,0,<1.000000, 1.000000, 1.000000>,1.000000,10.000000,0.750000 , PRIM_COLOR,0,<0.729412, 0.160784, 0.717647>,1.000000 , PRIM_BUMP_SHINY,0,1,0 ]);
       llSetPrimitiveParams([PRIM_ROTATION,<0.000000, 0.000000, 0.000000, 1.000000> , PRIM_TEXTURE,0,"5748decc-f629-461c-9a36-a35a221fe21f",<1.000000, 1.000000, 0.000000>,<0.000000, 0.000000, 0.000000>,0.000000 , PRIM_SIZE,<0.250000, 0.250000, 0.250000> ]);
       // Ugly all done :)
       
       
       llParticleSystem([]);
       llSitTarget(<0,0,1>, ZERO_ROTATION);
       llListen( -13374138 , "" , NULL_KEY , "Ping?");
       
   }
   listen(integer chan , string name , key id , string msg )
   {
       
       if (llList2Key(llGetObjectDetails(id,[OBJECT_OWNER]),0) == llGetOwner() )
       {
       
       ////// Some neat particles to show the link line  :)
       //
       //  Calculate the lifespan of the particles so they don't move to fast
       vector start_scale = <.2,.4,.0>; vector end_scale = <.25,.45,.0>;
       float part_age =  .3 * (llVecDist(llList2Vector(llGetObjectDetails(id,[OBJECT_POS]),0),llGetPos()));
       if (part_age > 30.) { 
       vector mod = < 0., (part_age / 30.), 0.>; part_age = 30.; start_scale = start_scale + mod; end_scale = end_scale + mod; }
       //  Generate the particles
       llParticleSystem([2,1.0,4,1.0,1,<0.847059, 0.301961, 0.835294>,3,<0.729412, 0.160784, 0.717647>,5,start_scale,6,end_scale,19,0.0,7,part_age,13,0.0,15,10,9,2,8,<75.0,0.0,0.0>,0,483,20,id]);


       //// Pong!
       llRegionSay(-13374137 , "Pong!"  ); 
       }
   }
   
   changed(integer change) {
       if (llAvatarOnSitTarget() != NULL_KEY)
           llRequestPermissions(llAvatarOnSitTarget(), PERMISSION_TRIGGER_ANIMATION);
   }


   run_time_permissions(integer perm) {
       string anim = llGetInventoryName(INVENTORY_ANIMATION, 0);
       if (anim != "") {
           llStopAnimation("sit");
           llStopAnimation("sit_generic");
           llStopAnimation("sit_female");
           llStartAnimation(anim);
       }
   }

}</lsl>

Make sure you stick your animation in the helper prim before you sit.


Target Setter (on touch)

Next drop this script into your chair or teleport pad or whatever. Then touch.

<lsl>// Sit target system by Lex Neva. Please distribute willy-nilly. // http://forums.secondlife.com/showthread.php?t=153278&highlight=target

// Sit target setting script. Sets on touch.

// Support for Teleport-range setting shoehorned in by Clarknova Helvetic // https://wiki.secondlife.com/wiki/User:Clarknova_Helvetic/Sit_TP_Positioner


key owner;

default {

state_entry() { owner = llGetOwner(); }

touch_start(integer total_number) {

integer i;

   for (i = 0 ; i < total_number ; ++i )
   {
       if (llDetectedKey(i) == llGetOwner())   
       {
           llOwnerSay("Querying Sit Target Helper...");
           llListen( -13374137 , "" , NULL_KEY , "Pong!");
           llRegionSay(-13374138,"Ping?");
           llSetTimerEvent( 10. );
       }
   }

}

listen(integer chan , string name , key id , string msg ) {

   list details = llGetObjectDetails(id,[OBJECT_OWNER,OBJECT_POS,OBJECT_ROT]);
   
   if ( llList2Key(details,0) == owner )
   {


   vector helper_pos = llList2Vector(details,1);
   rotation helper_rot = llList2Rot(details,2);


   vector my_pos = llGetPos();
   rotation my_rot = llGetRot();

   float distance = llVecDist(my_pos,helper_pos);

   vector target_pos = ZERO_VECTOR;

   if ( distance > 300.) {
   llOwnerSay("Sit target is " + (string)(distance - 300.) + "m too far away! \n( if you lost your Helper it's at " + (string)helper_pos +" )");
   
   }



   else 
   {


   // calculate where the avatar actually is
   vector avatar_pos = helper_pos + <0,0,1> * helper_rot; // due to helper's sit target
   avatar_pos = avatar_pos - <0,0,0.186> + <0,0,0.4> * helper_rot; // correct for a bug in llSitTarget(), for helper sit target

   target_pos = (avatar_pos - my_pos) / my_rot;
   target_pos = target_pos + <0,0,0.186>/my_rot - <0,0,0.4>; // correct for the bug again, this time in my sit target
   rotation target_rot = helper_rot / my_rot;

   llSitTarget(target_pos, target_rot);
   llOwnerSay("llSitTarget(" + (string)target_pos + ", " + (string)target_rot + ");");

   }
   llSetTimerEvent(0.);
   }

}

changed(integer change) { if (llAvatarOnSitTarget() != NULL_KEY) llRequestPermissions(llAvatarOnSitTarget(), PERMISSION_TRIGGER_ANIMATION); }

run_time_permissions(integer perm) { string anim = llGetInventoryName(INVENTORY_ANIMATION, 0); if (anim != "") { llStopAnimation("sit"); llStopAnimation("sit_generic"); llStopAnimation("sit_female"); llStartAnimation(anim);

   }

} timer() {

   llOwnerSay("Query timed out.  Now trying by sensor...");  
   llSensor("Sit Target/Teleport Helper",NULL_KEY,SCRIPTED,96,PI);

} sensor(integer num) {


   integer i;
   for ( i = 0 ; i < num ; ++i)
   {
   if ( llList2Key(llGetObjectDetails(llDetectedKey(i),[OBJECT_OWNER]),0) == owner ) 
   {
   rotation helper_rot = llDetectedRot(i);
   vector helper_pos = llDetectedPos(i);

   vector my_pos = llGetPos();
   rotation my_rot = llGetRot();

   float distance = llVecDist(my_pos,helper_pos);

   vector target_pos = ZERO_VECTOR;
   
   // calculate where the avatar actually is
   vector avatar_pos = helper_pos + <0,0,1> * helper_rot; // due to helper's sit target
   avatar_pos = avatar_pos - <0,0,0.186> + <0,0,0.4> * helper_rot; // correct for a bug in llSitTarget(), for helper sit target

   target_pos = (avatar_pos - my_pos) / my_rot;
   target_pos = target_pos + <0,0,0.186>/my_rot - <0,0,0.4>; // correct for the bug again, this time in my sit target
   rotation target_rot = helper_rot / my_rot;

   llSitTarget(target_pos, target_rot);
   
   llOwnerSay("Sit target set by sensor.  Helper's probbaly in a no-script parcel.\nllSitTarget(" + (string)target_pos + ", " + (string)target_rot + ");");
   }
   }    
   llSetTimerEvent(0.);

} no_sensor() {

   llOwnerSay("Can't find helper!  Problem could be:\nA) Helper's in no-script parcel and further away than 96m\nB) Helper's in another sim\nC) Laaaaaaaaaaag!\n\tAnyway, try again!");
   
   llSetTimerEvent(0.);
   }

}</lsl>

Adjust and touch as many times as you need. Remember to remove the script when done.


Target setter (drag 'n drop)

This script does the same as the one above. The difference is that once you drag the script in your chair it sets the target and deletes from prim inventory. Fire and forget.

<lsl>// Sit target system by Lex Neva. Please distribute willy-nilly. // http://forums.secondlife.com/showthread.php?t=153278&highlight=target

// Sit target setting script. Drag -n- drop version.

// Support for Teleport-range setting shoehorned in by Clarknova Helvetic // Drag 'n drop adaptation also by CH. I like doing things this way :) // https://wiki.secondlife.com/wiki/User:Clarknova_Helvetic/Sit_TP_Positioner

key owner;

default { state_entry() { owner = llGetOwner(); llOwnerSay("Querying Sit Target Helper..."); llListen( -13374137 , "" , NULL_KEY , "Pong!"); llRegionSay(-13374138,"Ping?"); llSetTimerEvent( 10. ); }

listen(integer chan , string name , key id , string msg ) {


   list details = llGetObjectDetails(id,[OBJECT_OWNER,OBJECT_POS,OBJECT_ROT]);
   
   if ( llList2Key(details,0) == owner )
   {

   vector helper_pos = llList2Vector(details,1);
   rotation helper_rot = llList2Rot(details,2);


   vector my_pos = llGetPos();
   rotation my_rot = llGetRot();

   float distance = llVecDist(my_pos,helper_pos);

   vector target_pos = ZERO_VECTOR;
   
   
   if ( distance > 300.) {
   llOwnerSay("Sit target is " + (string)(distance - 300.) + "m too far away! \n( if you lost your Helper it's at " + (string)helper_pos +" )");
   }
   
   
   
   else {
   
   // calculate where the avatar actually is
   vector avatar_pos = helper_pos + <0,0,1> * helper_rot; // due to helper's sit target
   avatar_pos = avatar_pos - <0,0,0.186> + <0,0,0.4> * helper_rot; // correct for a bug in llSitTarget(), for helper sit target
   target_pos = (avatar_pos - my_pos) / my_rot;
   target_pos = target_pos + <0,0,0.186>/my_rot - <0,0,0.4>; // correct for the bug again, this time in my sit target
   rotation target_rot = helper_rot / my_rot;
   
   llSitTarget(target_pos, target_rot);
   llOwnerSay("llSitTarget(" + (string)target_pos + ", " + (string)target_rot + ");");
   
   }
   
   
   llRemoveInventory(llGetScriptName());
   }

}

changed(integer change) { if (llAvatarOnSitTarget() != NULL_KEY) llRequestPermissions(llAvatarOnSitTarget(), PERMISSION_TRIGGER_ANIMATION); }

run_time_permissions(integer perm) { string anim = llGetInventoryName(INVENTORY_ANIMATION, 0); if (anim != "") { llStopAnimation("sit"); llStopAnimation("sit_generic"); llStopAnimation("sit_female"); llStartAnimation(anim);

   }

} timer() {

   llOwnerSay("Query timed out.  Now trying by sensor...");  
   llSensor("Sit Target/Teleport Helper",NULL_KEY,SCRIPTED,96,PI);

} sensor(integer num) {


   integer i;
   for ( i = 0 ; i < num ; ++i)
   {
   if ( llList2Key(llGetObjectDetails(llDetectedKey(i),[OBJECT_OWNER]),0) == owner ) 
   {
   rotation helper_rot = llDetectedRot(i);
   vector helper_pos = llDetectedPos(i);

   vector my_pos = llGetPos();
   rotation my_rot = llGetRot();

   float distance = llVecDist(my_pos,helper_pos);

   vector target_pos = ZERO_VECTOR;
   
   // calculate where the avatar actually is
   vector avatar_pos = helper_pos + <0,0,1> * helper_rot; // due to helper's sit target
   avatar_pos = avatar_pos - <0,0,0.186> + <0,0,0.4> * helper_rot; // correct for a bug in llSitTarget(), for helper sit target

   target_pos = (avatar_pos - my_pos) / my_rot;
   target_pos = target_pos + <0,0,0.186>/my_rot - <0,0,0.4>; // correct for the bug again, this time in my sit target
   rotation target_rot = helper_rot / my_rot;

   llSitTarget(target_pos, target_rot);
   
   llOwnerSay("Sit target set by sensor.  Helper's probbaly in a no-script parcel.\nllSitTarget(" + (string)target_pos + ", " + (string)target_rot + ");");
   }
   }    
   llRemoveInventory(llGetScriptName());

} no_sensor() {

   llOwnerSay("Can't find helper!  Problem could be:\nA) Helper's in no-script parcel and further away than 96m\nB) Helper's in another sim\nC) Laaaaaaaaaaag!\n\tAnyway, try again!");
   
   llRemoveInventory(llGetScriptName());
   }

}</lsl>