Jump to content

Store and restore rezzed linkset positions


You are about to reply to a thread that has been inactive for 1791 days.

Please take a moment to consider if this thread is worth bumping.

Recommended Posts

These two scripts will record the inworld position and rotation of a link set in the description field and reposition a wayward linkset to the saved position and rotation. They replicate the "Restore to last position" ability that some TPVs offer without having to take the item back into inventory.

Warning! If a linkset already uses the description field for some other purpose this is going to break it! 

// set the position and euler rotation into the object description field

key owner;

vector myPos;
rotation myRot;
vector myAng;
string details;

default
{
    state_entry()
    {
        owner = llGetOwner();
        myPos = llGetPos();
        myRot = llGetRot();
        myAng = (llRot2Euler(myRot)) * RAD_TO_DEG;
        details = "@" + (string) myPos + "&" + (string) myAng;
        llOwnerSay(details);
        llSetPrimitiveParams([PRIM_DESC, details]);
        llRemoveInventory(llGetScriptName());
    }
}

 

This second script is dropped into a linkset to reposition it.

// use the position and euler rotation in the object description field to put the linkst back

key owner;

vector myPos;
rotation myRot;
vector myAng;
string details;

integer posAt = -1;
integer rotAt = -1;
integer len;

default
{
    state_entry()
    {
        owner = llGetOwner();
        details = llList2String( llGetPrimitiveParams([PRIM_DESC]), 0);
        len = llStringLength(details);
        posAt = llSubStringIndex(details, "@");
        rotAt = llSubStringIndex(details, "&");
        if( posAt == -1 || rotAt == -1)
        {
            llOwnerSay("No entries detected in " + details);
        }
        else
        {        
            myPos = (vector) llGetSubString(details, posAt + 1, rotAt - 1);
            myRot = llEuler2Rot( ((vector) (llGetSubString(details, rotAt + 1, len)) * DEG_TO_RAD) );

        llOwnerSay("Position at " + (string) myPos + " rotated to " + (string) myRot );
            if( myPos != ZERO_VECTOR)
            {
                llSetRegionPos(myPos);
                llSetRot(myRot);
            }
        }
        llRemoveInventory(llGetScriptName());
    }
}

 

Edited by Profaitchikenz Haiku
me, I typo, what the eff else?
  • Like 2
Link to comment
Share on other sites

  • 2 weeks later...

Recommendations. 

1. Recommend that you consider using the human-readable "myAng" in the llOwnerSay(), rather than the less intuitive "myRot".

2. Strongly recommend that Immediately after "llSetRegionPos(myPos)" that you in the very next line-of-code follow up with an llSetPos(myPos) or  llSetPrimitiveParams() with PRIM_POSITION (or perhaps llSetLinkPrimitiveParamsFast() with PRIM_POSITION).  

Concerning recommendation 2, the reason is that "llSetRegionPos(myPos)" is only guaranteed accurate to within 0.1 meters, whereas the llSetPos(myPos), though limited to 10 meter movements, sets position precisely.  The "llSetRegionPos(myPos)" gets you to within 0.1 meters and removes the burden of testing for no-greater-than-10-meter movements (an llSetPos() limitation) or 54 meters (a limitation of llSetPrimitiveParams with PRIM_POSITION), and the llSetPos(myPos) or  llSetPrimitiveParams with PRIM_POSITION establishes position precisely.  All of these accuracy issues are related to limitations in the use of 32 bit float variables (cf. http://wiki.secondlife.com/wiki/Category:LSL_Float).  

3. Weakly recommend that you consider storing "myRot" in the description field rather than "myAng" so that any roundoff error that creeps in doesn't affect your positioning.  That being said, you are doing it the way rezzer systems have always done it, and so I guess it is good enough because has been working fine for so many for so long.

Concerning recommendation 3, "rotation myRot" is what the Region Server gave you via llGetRot(), and "rotation myRot" is what your script has to give back to the RegionServer in llSetRot(myRot).  There is no reason to (and good reasons not to) pass the numbers through four conversions prior to giving them back to the Region Server.  "vector myAng" is just for humans, and so give that to the humans in your llOwnerSay.  The four conversions are: (1) your Rot-to-Euler conversion prior to your string conversion, (2) your to-string conversion to store in description, (3) your from-string conversion after reading from the description field, and (4) your Euler-to-Rot conversion prior to your llSetRot.  Conversions 1 and 4 have 32 bit binary-float round off, and conversions 2 and 3 are rounded to 6 decimal digits (cf. http://wiki.secondlife.com/wiki/Category:LSL_Float, which states "Remember that string casting in LSL only gives up to 6 [sic] so is safe, and human input is rarely going to be that accurate, plus values that small are not usually all that useful.").  Storing as a rotation still incurs conversion 2 and 3.

Frivolous comment: myPos, myRot, and myAng variable names remind me of Cory's code in certain objects in the standard-inventory set, like the dominos. 

Link to comment
Share on other sites

You are about to reply to a thread that has been inactive for 1791 days.

Please take a moment to consider if this thread is worth bumping.

Please sign in to comment

You will be able to leave a comment after signing in



Sign In Now
 Share

×
×
  • Create New...