03-09-2006 22:26
Hello all,

I found this really nice pet/bot/follower script {THANK YOU Jesrad Seraph} and would like to use it for a personal project. I have to admit it is a bit over my head, I understand how it all works, but it does way more than I need. I love the movement, but the animation and even the vehicle portion are not needed by me. I also notice the "wander" function tends to send the object wandering off and being returned or lost. I was looking for the ability to control the "teather if you will... send the object up and out, like a kite. the higher it goes the wider it roams. I would think that even a close, medium and far leash would work.

I would also like to be able to have the object follow another object. Think of a pearch or patrol point. It would use this point as if it were me. Locking my pet to it's pearch while I am gone. Any help would be great.

CODE

// Command
//
// Control script for single link set synchronized animation
// Author: Jesrad Seraph

// This script has the vehicle parameters and the controls event for your mount.
// It calculates the animation step needed after the rider control inputs
// then sends it to the animated parts of the link_set, who each must have a Movement
// script to listen to these messages and move.

// These are the constants you need to change to adapt this script to another beast:
list animframes = [1,4,4];
list animoffsets = [0,1,5];
// Copy these constants in the Movement scripts for the mobile parts of your beast,
// and change the rotations for the steps (the number of rotations in the lists must
// match the max_anims numbers entered above !)

vector fwd_vel = <16,0,0>;
vector left_vel = <6,0,-3>;
vector vert_vel = <0,0,8>;

integer step;
integer anim;
float timerate = 0.25;

integer roam_state = 0;
vector roam_around;
float roam_range = 8.0;
float follow_range = 200.0;
float roam_delay = 8.0;
key roam_target;

vector PUSH_OFF = <0,9,8>;
vector sit_pos = <0.37,0,0.2>;
vector sit_rot = <0,0,0>;

integer menu_handle;
integer menu_channel;

integer chan;
integer ALTERN = 0;
integer max_listeners = 2;

default
{
control(key id, integer level, integer edge)
{
vector motor = ZERO_VECTOR;
if(level & CONTROL_FWD)
{
llSetStatus(STATUS_PHYSICS, TRUE);
llSetVehicleFloatParam(VEHICLE_BUOYANCY, 0.94);
if (anim != 2) anim = 2;
motor += fwd_vel;
} else if(level & CONTROL_BACK)
{
llSetVehicleFloatParam(VEHICLE_BUOYANCY, 0.94);
if (anim != 2) anim = 2;
motor -= fwd_vel;
} else {
if (anim != 1) anim = 1;
}

if(level & (CONTROL_RIGHT|CONTROL_ROT_RIGHT))
{
//llStopLookAt();
llSetVehicleVectorParam(VEHICLE_ANGULAR_MOTOR_DIRECTION, left_vel);
} else if(level & (CONTROL_LEFT|CONTROL_ROT_LEFT))
{
//llStopLookAt();
llSetVehicleVectorParam(VEHICLE_ANGULAR_MOTOR_DIRECTION, -left_vel);
} else {
//if (edge & (CONTROL_LEFT|CONTROL_ROT_LEFT|CONTROL_RIGHT|CONTROL_ROT_RIGHT))
// llRotLookAt(llGetRot(), 1.0, 0.5);
llSetVehicleVectorParam(VEHICLE_ANGULAR_MOTOR_DIRECTION, ZERO_VECTOR);
}

if (level & CONTROL_UP)
{
motor += vert_vel;
llSetVehicleFloatParam(VEHICLE_BUOYANCY, 0.99);
} else if (level & CONTROL_DOWN)
{
motor -= vert_vel;
llSetVehicleFloatParam(VEHICLE_BUOYANCY, 0.67);
}

llSetVehicleVectorParam(VEHICLE_LINEAR_MOTOR_DIRECTION, motor);
}

timer()
{
step = (step + 1) % llList2Integer(animframes, anim);
ALTERN = (ALTERN + 1) % max_listeners;
llSay(chan + ALTERN, (string)(step + llList2Integer(animoffsets, anim)));
if (step == 3) llPlaySound("flap", 1);
}

changed(integer change)
{
if (change & CHANGED_LINK)
{
key agent = llAvatarOnSitTarget();
if (agent)
{
if (agent != llGetOwner())
{
llUnSit(agent);
llPushObject(agent, PUSH_OFF * llGetRot(), ZERO_VECTOR, FALSE);
//llPlaySound("cui", 1);
//llSay(0, "Wah!");
}
else
{
llSensorRemove();
roam_state = 0;
llRequestPermissions(agent, PERMISSION_TRIGGER_ANIMATION | PERMISSION_TAKE_CONTROLS);
llCollisionSound("", 0);
llPlaySound("aigle", 1);
llSay(0, ">:)");
llSetTimerEvent(timerate);
llSetStatus(STATUS_PHYSICS, TRUE);
llSetStatus(STATUS_PHANTOM, FALSE);
llStopLookAt();
}
}
else
{
llReleaseControls();
llSetTimerEvent(0);
llSay(chan, "0");
llSay(chan + 1, "0");
//llStopAnimation("motorcycle_sit");
llSetStatus(STATUS_PHYSICS, FALSE);
llPushObject(llGetOwner(), PUSH_OFF, ZERO_VECTOR, TRUE);
}
}
}

on_rez(integer a)
{
llSleep(1);
llResetScript();
}

state_entry()
{
llSetSitText("Ride");
llSetTouchText("Command");
llSitTarget(sit_pos, llEuler2Rot(DEG_TO_RAD * sit_rot));

llSetCameraEyeOffset(<-6.0, 0.0, 2.0>);
llSetCameraAtOffset(<2.0, 0.0, 1.0>);

roam_around = llGetPos();
roam_target = llGetOwner();

anim = 0;
step = 0;

llSetVehicleFlags(-1);
llSetVehicleType(VEHICLE_TYPE_AIRPLANE);

llRemoveVehicleFlags(VEHICLE_FLAG_LIMIT_ROLL_ONLY);
llSetVehicleFloatParam(VEHICLE_ANGULAR_DEFLECTION_EFFICIENCY, 0.8);
llSetVehicleFloatParam(VEHICLE_LINEAR_DEFLECTION_EFFICIENCY, 0.8);
llSetVehicleFloatParam(VEHICLE_ANGULAR_DEFLECTION_TIMESCALE, .5);
llSetVehicleFloatParam(VEHICLE_LINEAR_DEFLECTION_TIMESCALE, .5);

llSetVehicleFloatParam(VEHICLE_LINEAR_MOTOR_TIMESCALE, .1);
llSetVehicleFloatParam(VEHICLE_LINEAR_MOTOR_DECAY_TIMESCALE, .1);
llSetVehicleFloatParam(VEHICLE_ANGULAR_MOTOR_TIMESCALE, .1);
llSetVehicleFloatParam(VEHICLE_ANGULAR_MOTOR_DECAY_TIMESCALE, .1);

llSetVehicleVectorParam(VEHICLE_LINEAR_FRICTION_TIMESCALE, <1.0, .1, 1.0>);
llSetVehicleVectorParam(VEHICLE_ANGULAR_FRICTION_TIMESCALE, <.1, .1, .1>);

llSetVehicleFloatParam(VEHICLE_VERTICAL_ATTRACTION_EFFICIENCY, .5);
llSetVehicleFloatParam(VEHICLE_VERTICAL_ATTRACTION_TIMESCALE, .5);

llSetVehicleFloatParam(VEHICLE_BANKING_EFFICIENCY, 0.4);
llSetVehicleFloatParam(VEHICLE_BANKING_TIMESCALE, 0.1);
llSetVehicleFloatParam(VEHICLE_BANKING_MIX, 1.0);
llSetVehicleFloatParam(VEHICLE_BUOYANCY, 0.8);
llSetBuoyancy(0.0);

llSensorRemove();
chan = (integer)llFrand(200000000) + 54321;
llMessageLinked(LINK_SET, chan, "defchan", NULL_KEY);
llSay(chan, "0");
llSay(chan + 1, "0");
}

listen(integer chan, string name, key sayer, string msg)
{
if (sayer != llGetOwner())
return;
llSetText("", ZERO_VECTOR, 0.0);
if (msg == "Help")
{
llGiveInventory(sayer, "Instructions");
} else if (msg == "Stay here")
{
roam_state = 0;
anim = 1;
llSetStatus(STATUS_PHANTOM, FALSE);
llSensorRemove();
} else if (msg == "Wander")
{
roam_state = 1;
roam_around = llGetPos();
llSetStatus(STATUS_PHANTOM, TRUE);
llSensorRepeat("", NULL_KEY, PASSIVE | ACTIVE, roam_range, TWO_PI, 1.6);
} else if (msg == "Follow me")
{
roam_state = 2;
roam_target = llGetOwner();
llSetStatus(STATUS_PHANTOM, TRUE);
llSensorRepeat("", roam_target, AGENT | ACTIVE, follow_range, TWO_PI, 1.6);
}
}

sensor(integer count)
{
vector facing;
vector dir;
float dist;
integer n;
integer selected;

if (roam_state == 2)
{
// Following, found owner
llSetText("", ZERO_VECTOR, 0.0);
dir = llDetectedPos(0) + 2.0 * llDetectedVel(0) - llGetPos() + <0,0,1.8>;
facing = llRot2Euler(llRotBetween(llRot2Fwd(llGetRot()), dir));
facing.x = 0.0;
facing.y = 0.0;
llRotLookAt(llGetRot() * llEuler2Rot(facing), 1.0, 0.2);
llSleep(0.25);
dist = llVecMag(dir) / 2;
llSetVehicleFloatParam(VEHICLE_BUOYANCY, 0.96 + 0.125 * dir.z);
if (dist > 4.0)
{
llSetStatus(STATUS_PHYSICS, TRUE);
anim = 2;
llSetTimerEvent(timerate);
llStopMoveToTarget();
llSetVehicleVectorParam(VEHICLE_LINEAR_MOTOR_DIRECTION, dir / llGetRot());
} else {
anim = 1;
llSetVehicleVectorParam(VEHICLE_LINEAR_MOTOR_DIRECTION, dir / llGetRot());
}
} else if (roam_state == 1)
{
dir = llGetPos();
dir.x = llFrand(128) + roam_around.x - 64;
dir.y = llFrand(128) + roam_around.y - 64;
facing = llRot2Euler(llRotBetween(llRot2Fwd(llGetRot()), dir - llGetPos()));
dir.z = 0.5 * (llGround(dir - llGetPos()) + 9.0 - dir.z);
facing.x = 0.0;
facing.y = 0.0;
llRotLookAt(llGetRot() * llEuler2Rot(facing), 1.0, 0.2);
llSleep(0.25);
dist = llVecMag(dir) / 4.0;
llSetVehicleFloatParam(VEHICLE_BUOYANCY, 0.96 + 0.125 * dir.z);
if (dist > 4.0)
{
llSetStatus(STATUS_PHYSICS, TRUE);
llStopMoveToTarget();
llSetVehicleVectorParam(VEHICLE_LINEAR_MOTOR_DIRECTION, dir / llGetRot());
anim = 2;
llSetTimerEvent(timerate);
} else {
anim = 1;
llSetVehicleVectorParam(VEHICLE_LINEAR_MOTOR_DIRECTION, dir / llGetRot());
}
}
}

no_sensor()
{
vector facing;
vector dir;
float dist;
integer selected;

if (roam_state == 2)
{
// Following, did not found owner
llSetText("I'm a poor, stranded Arwind who lost its owner...", <1,.7,.4>, 1.0);
} else if (roam_state == 1)
{
dir = llGetPos();
dir.x = llFrand(128) + roam_around.x - 64;
dir.y = llFrand(128) + roam_around.y - 64;
facing = llRot2Euler(llRotBetween(llRot2Fwd(llGetRot()), dir - llGetPos()));
dir.z = 0.5 * (llGround(dir - llGetPos()) + 9.0 - dir.z);
facing.x = 0.0;
facing.y = 0.0;
llRotLookAt(llGetRot() * llEuler2Rot(facing), 1.0, 0.2);
llSleep(0.25);
dist = llVecMag(dir) / 4.0;
llSetVehicleFloatParam(VEHICLE_BUOYANCY, 0.96 + 0.125 * dir.z);
if (dist > 4.0)
{
llSetStatus(STATUS_PHYSICS, TRUE);
llStopMoveToTarget();
llSetVehicleVectorParam(VEHICLE_LINEAR_MOTOR_DIRECTION, 0.67 * fwd_vel);
anim = 2;
llSetTimerEvent(timerate);
} else {
anim = 1;
}
}
}

touch_start(integer a)
{
if (llDetectedType(0) == AGENT | ACTIVE)
{
llPlaySound("aigle", 1);
if (llDetectedKey(0) == llGetOwner())
{
llSay(0, ">:)");
llListenRemove(menu_handle);
menu_channel = (integer)llFrand(2000000)+1234;
menu_handle = llListen(menu_channel, "", "", "");
llDialog(llDetectedKey(0), "Tell " + llGetObjectName() + " to:", ["Stay here", "Wander", "Follow me", "Help"], menu_channel);
} else {
llSay(0, ">:(");
}
}
}

run_time_permissions(integer perm)
{
if (perm)
{
llTakeControls( CONTROL_FWD |
CONTROL_BACK |
CONTROL_RIGHT |
CONTROL_LEFT |
CONTROL_ROT_RIGHT |
CONTROL_ROT_LEFT |
CONTROL_UP |
CONTROL_DOWN, TRUE, FALSE);
}
}
}