Move Lock Script

Expired

written by Northwest Portland

 

This is your basic don't push me script . Useful if you're around places where someone might take it into their head to run over, shoot, or otherwise molest you. You know, places like SL! It has no configuration but it really doesn't need any. It shouldn't interfere with regular movement at all.

 

When you stop moving, it kicks in, when you move yourself (rather than someone else doing it for you) it lets go. Only requirement is that it needs to be in an attachment.

integer attached = FALSE;
integer key_pressed = FALSE;
integer movement_locked = FALSE;
vector lock_position = ZERO_VECTOR;

lock()
{
    movement_locked = TRUE;
    
    // Basic move lock consists of an llMoveToTarget.
    lock_position = llGetPos();
    llMoveToTarget(lock_position, 0.05);
    
    // This is a bit of a hack, but the idea is to set friction on an avatar.
    // The only way to do that is to make the avatar a vehicle, so we do.
    llSetVehicleType(VEHICLE_TYPE_SLED);
    llSetVehicleVectorParam(VEHICLE_LINEAR_FRICTION_TIMESCALE, <0.05, 0.05, 0.05>);
}

unlock()
{
    movement_locked = FALSE;
    
    llStopMoveToTarget();
    
    // We have to make sure that we remove the vehicle status from the avatar
    // when moving, instead of just removing the friction.  Being a vehicle
    // has strange side effects on a moving avatar.
    llSetVehicleType(VEHICLE_TYPE_NONE);
}

move_lock()
{
    if (!attached) return;
    
    // Collect some relevant information about what that avatar is doing.
    vector velocity = llGetVel();
    integer agent_info = llGetAgentInfo(llGetOwner());
    integer is_flying = ((agent_info & AGENT_FLYING) != 0);
    integer is_falling = ((agent_info & AGENT_IN_AIR) != 0) && !is_flying;
    string animation = llGetAnimation(llGetOwner());
    
    if (movement_locked)
    {
        // If the agent is sitting, or pressing keys, or trying to fall
        // straight down, or starting to jump, then unlock.
        if ((agent_info & AGENT_SITTING) != 0 || key_pressed || (llVecMag(velocity) <0.1 && is_falling) || animation == "PreJumping")
        {
            unlock();
        }
        // If something has managed to push the avatar over 10 meters from
        // where the lock was set, then the move to target will probably have
        // lost it's effect, and it needs to be reset.
        else if (llVecDist(lock_position, llGetPos()) > 10.0)
        {
            // Relock if the lock was broken.
            lock();
        }
    }
    else
    {
        // If the avatar is not sitting, not jumping, moving slower than
        // 0.1 m/s on the ground or hovering, then lock position.
        if ((agent_info & AGENT_SITTING) == 0 && animation != "PreJumping")
        {
            if (llVecMag(velocity) <0.1 || (is_flying && llVecMag() <0.25 && velocity.z > -4.0 && velocity.z <0.25))
            {
                lock();
            }
        }
    }
}

initialize()
{
    llOwnerSay("Initializing Move Lock...");
    
    attached = TRUE;
    
    llRequestPermissions(llGetOwner(), PERMISSION_TAKE_CONTROLS);
}

finalize()
{
    attached = FALSE;
    
    llReleaseControls();
    llSetTimerEvent(0.0);
    
    unlock();
    
    llOwnerSay("Move Lock Finalized.");
}

default
{
    state_entry()
    {
        if (llGetAttached() != 0)
        {
            initialize();
        }
    }
    
    on_rez(integer sparam)
    {
        // If for some reason detach didn't stop move lock and then it was
        // rezzed but NOT attached, then there could be bad things happening.
        // To avoid that, check on rez to see if it's attached and if not then
        // make sure that move lock is off.
        if (llGetAttached() == 0)
        {
            finalize();
        }
    }
    
    attach(key id)
    {
        // Start when attached and stop when detached.
        if (id != NULL_KEY)
        {
            initialize();
        }
        else
        {
            finalize();
        }
    }
    
    run_time_permissions(integer perms)
    {
        if ((perms & PERMISSION_TAKE_CONTROLS) != 0)
        {
            llTakeControls(CONTROL_FWD | CONTROL_BACK | CONTROL_LEFT | CONTROL_RIGHT | CONTROL_UP | CONTROL_DOWN, TRUE, TRUE);
            llSetTimerEvent(0.2);
            
            llOwnerSay("Move Lock Initialized.");
        }
    }
    
    control(key id, integer level, integer edge)
    {
        if (level != 0)
        {
            if (!key_pressed)
            {
                key_pressed = TRUE;
                
                // When a key is pressed, cancel the timer and just use the
                // control event to check the move lock state.  The control
                // event would fire every 0.05 seconds on it's own which is way
                // too fast and unnecessary, so limit it to 0.2 with
                // llMinEventDelay.
                llSetTimerEvent(0.0);
                llMinEventDelay(0.2);
                
                // if keys are pressed we should always be unlocked, so just
                // skip the check and unlock.
                unlock();
            }
        }
        else
        {
            if (key_pressed)
            {
                key_pressed = FALSE;
                
                // Restore the timer since this is the last time the control
                // event will fire.  Restore the minimum event delay so that
                // the next time you push a key it is caught immediately.
                llSetTimerEvent(0.2);
                llMinEventDelay(0.0);
                
                // Check move lock state immediately rather than waiting for
                // the next timer tick.
                move_lock();
            }
        }
    }
    
    timer()
    {
        move_lock();
    }
}

 

Bubble Gum

Expired

//////////////////////////////////////////////////////////
// [K] Kira Komarov - 2011, License: GPLv3              //
// Please see: http://www.gnu.org/licenses/gpl.html     //
// for legal details, rights of fair usage and          //
// the disclaimer and warranty conditions.              //
//////////////////////////////////////////////////////////
 
init() {
    llRequestPermissions(llGetOwner(), PERMISSION_TRIGGER_ANIMATION);
    llPreloadSound("ff0600f0-d8f4-20f6-52ec-a03bc520fee3");
    llSetPos(<0,0,0>);
    llSetScale(<0,0,0>);
}
 
default
{
    on_rez(integer num) {
        if(llGetAttached()) init();
    }
    state_entry() {
        if(llGetAttached()) init();
    }
    attach(key id)
    {
        init();
    }
    run_time_permissions(integer perm)
    {
        if (perm & PERMISSION_TRIGGER_ANIMATION)
        {
            llSetTimerEvent(5 + (integer)llFrand(14));
        }
    }
 
    timer() 
    {
        llSetTimerEvent(0.0);
        llStartAnimation("express_kiss");
        float itra;
        for(itra=0.004; itra<0.06; itra+=0.004) { 
            llSetScale();
            llSetPos(llGetLocalPos()+<0.0007,0.0,0.0>);
 
        }
        llPlaySound("ff0600f0-d8f4-20f6-52ec-a03bc520fee3", 1.0);
        llStopAnimation("express_kiss");
        llSetScale(<0,0,0>);
        llSetPos(<0,0,0>);
        llSetTimerEvent(5 + (integer)llFrand(14));
    }
}

 

AvatarFollower

Expired

Introduction

 

 

It can be hard to follow someone in Second Life; if someone says "follow me" and goes flying off over hill and dale in an even slightly crowded region, it's all too easy to lose track of them. This script lets you specify a person to follow, and if you get too far from them it will exert a force that will make your avatar walk (or run or fly or etc) in their direction, until you are close enough.

 

Useage

 

To use this script, stick it into the root prim of an object, and wear that object. (Anywhere on the body; wearing it as a HUD attachment hasn't been tested.) Then to follow someone, say their name on channel 15 (like "/15 Dale Innis", you know). You will then begin following that person (sometimes for some reason you have to move a bit first using the arrow keys or whatever before the following will start). To stop following them, say "off" on channel 15 ("/15 off" or "/15off").

 

Limitation and Notes

 

The main purpose of this script is to show that llMoveToTarget and family are a good way of moving an avatar about; with appropriate modifications this code could be used to move someone wearing a tour device through a set of waypoints, or to pull an AV wearing a grappling hook attachment to whatever the hook hit, or whatever. All sorts of potential!

 

The interface in the version of the script given here requires you to get the person's name exactly right, including capitalization. The version that I actually use myself allows specifying just a part of the person's name, and having it look around for someone nearby that matches. But the code to do that just complicates the script without adding anything fundamental, so I don't include it here. If you'd like a copy of that version, feel free to contact me.

 

There's no magic in the script; all it actually does is move your AV toward the person whenever they are too far away. This only lets you get to places that you could have gotten to anyway manually using the arrow keys or whatever (with one possible exception noted below). It doesn't let you follow people through teleports or anything like that.

 

The code isn't very smart about its following, and in particular it doesn't do anything about obstacles. If there's a wall or something between you and the person you're following, you may find yourself pressed thoroughly against that wall, pretty much unable to move. Use the "off" command to free yourself, and move to a place where you have a clear line of sight to them before following them again.

If you start following someone when they are quite a distance away (the limit is about 90 meters), or if the person that you are following moves very suddenly and fast, the script can in some circumstances exert enough force that you pass right through intervening walls and/or objects. This can be quite fun. (In damage-enabled areas, it can also be quite fatal.)

 

If the person that you're following flies upward while you are in walking mode, you may find yourself swimming through the air in that awkward "eeeek I'm falling" animation; you can press the "Fly" button to switch to the more graceful flying animation. Similarly, if you're flying while following someone and they land, you may find yourself skimming over the ground behind them; press "Stop Flying" if you'd rather walk also.

 

If the person that you're following TPs away, or logs out, or in some cases crosses into a different sim than the one you're in, the script will say that the person "seems to be out of range. Waiting for return...", and you will be free to move about. If the person comes back into range, you will (suddenly and without warning) start following them again. Myself, I generally issue the "off" command if the person that I'm following goes out of range, just to avoid surprises.

 

While you are following someone, you will be pretty much unable to move very far away from them. It will be as though an invisible force were pressing on you, keeping you nearby. (Because that's in fact exactly what's happening.) If you want to move away from the person, use the "off" command to stop following them.

 

Odd and random things may (or may not) happen if you follow someone while riding a vehicle or sitting. Or vice-versa.

You can change the channel that the script listens on for commands, the frequency with which it looks to see if the followed person is too far away, the number of meters it considers "too far", and the hardness with which it pushes you (or actually the reciprocal thereof) by altering the first four constants in the code (respectively).

 

Code

 

You may do anything you like with this code, without limitation. As far as I'm concerned. Well, except you shouldn't use it for evil. Which is sort of true by the definitions of "should" and "evil"

 

integer CHANNEL = 15;  // That's "f" for "follow", haha
 
float DELAY = 0.5;   // Seconds between blinks; lower for more lag
float RANGE = 3.0;   // Meters away that we stop walking towards
float TAU = 1.0;     // Make smaller for more rushed following
 
// Avatar Follower script, by Dale Innis
// Do with this what you will, no rights reserved
// See https://wiki.secondlife.com/wiki/AvatarFollower for instructions and notes
 
float LIMIT = 60.0;   // Approximate limit (lower bound) of llMoveToTarget
 
integer lh = 0;
integer tid = 0;
string targetName = "";
key targetKey = NULL_KEY;
integer announced = FALSE;
 
init() {
  llListenRemove(lh);
  lh = llListen(CHANNEL,"",llGetOwner(),"");
}
 
stopFollowing() {
  llTargetRemove(tid);  
  llStopMoveToTarget();
  llSetTimerEvent(0.0);
  llOwnerSay("No longer following.");
}
 
startFollowingName(string name) {
  targetName = name;
  llSensor(targetName,NULL_KEY,AGENT_BY_LEGACY_NAME,96.0,PI);  // This is just to get the key
}
 
startFollowingKey(key id) {
  targetKey = id;
  llOwnerSay("Now following "+targetName);
  keepFollowing();
  llSetTimerEvent(DELAY);
}
 
keepFollowing() {
  llTargetRemove(tid);  
  llStopMoveToTarget();
  list answer = llGetObjectDetails(targetKey,[OBJECT_POS]);
  if (llGetListLength(answer)==0) {
    if (!announced) llOwnerSay(targetName+" seems to be out of range.  Waiting for return...");
    announced = TRUE;
  } else {
    announced = FALSE;
    vector targetPos = llList2Vector(answer,0);
    float dist = llVecDist(targetPos,llGetPos());
    if (dist>RANGE) {
      tid = llTarget(targetPos,RANGE);
      if (dist>LIMIT) {
          targetPos = llGetPos() + LIMIT * llVecNorm( targetPos - llGetPos() ) ; 
      }
      llMoveToTarget(targetPos,TAU);
    }
  }
}
 
default {
 
  state_entry() {
    llOwnerSay("/"+(string)CHANNEL+" [name of person to magically follow]");
    init();
  }
 
  on_rez(integer x) {
    llResetScript();   // Why not?
  }
 
  listen(integer c,string n,key id,string msg) {
    if (msg == "off") {
      stopFollowing();
    } else {
      startFollowingName(msg);
    }
  }
 
  no_sensor() {
    llOwnerSay("Did not find anyone named "+targetName);
  }
 
  sensor(integer n) {
    startFollowingKey(llDetectedKey(0));  // Can't have two ppl with the same name, so n will be one.  Promise.  :)
  }
 
  timer() {
    keepFollowing();
  }
 
  at_target(integer tnum,vector tpos,vector ourpos) {
    llTargetRemove(tnum);
    llStopMoveToTarget();  
  }
 

 

 

Get Profile Texture

Expired

When Touched displays Toucher's profile picture on prim. 


TIP: Use the script in other ways. This gets the av key by touch, but you can also get it using llGetOwner, sensor, collision, or others and display their image.

Note: Replaced with version not by Alicia Stella November 2009 for workaround for WEB-1384.

 

 

// Snippets and HTTPRequest bits were taken from:
//~ RANDOM PROFILE PROJECTOR v5.4.5 by Debbie Trilling ~
 
// Get Profile Picture by Valentine Foxdale
// optmisation by SignpostMarv Martin
// workaround for WEB-1384 by Viktoria Dovgal, use meta tag instead of img since it comes earlier
list sides;
list deftextures;
integer s1l; // calculated from profile_key_prefix in state_entry()
string profile_key_prefix = ",1); 
        //Note: Usage of another person's profile picture without their permission may be viewed as copyright infringement. 
        GetDefaultTextures();
    }
    touch_start(integer total_number)
    {
        GetProfilePic(llDetectedKey(0));
    }
    http_response(key req,integer stat, list met, string body)
    {
        integer s1 = llSubStringIndex(body,profile_key_prefix);
        if(s1 == -1){SetDefaultTextures();}
        else
        {
            s1 += s1l;
            key UUID=llGetSubString(body, s1, s1 + 35);
            if (UUID == NULL_KEY) {
                SetDefaultTextures();
            }
            else {
                llSetTexture(UUID,ALL_SIDES);
            }
        }
    }
}