fa7549f4bc82e3e7e5437f0ddfc24c23eefbf8b5
[feisty_meow.git] / huffware / huffotronic_scripts / simpy_pet_v3.7.txt
1 
2 // huffware script: simple follower script, by fred huffhines.
3 //
4 // this has been condensed from other pet scripts but still retains all the vitamins!
5 //
6 // this script is licensed by the GPL v3 which is documented at: http://www.gnu.org/licenses/gpl.html
7 // do not use it in objects without fully realizing you are implicitly accepting that license.
8 //
9
10 // global constants...
11
12 float HEIGHT_ABOVE_AVATAR = 0.3;  // how far above the av do we float.
13 float ROOM_FOR_ERROR = 0.1;  // how far away from the target locale can we roam.
14 float MAXIMUM_VELOCITY = 200.0;  // the fastest the object can zoom towards us.
15 float SENSOR_PERIOD = 1.0;  // how frequently we look for the avatar.
16 float SENSOR_RANGE =  64.0;  // the farthest away we will try to look for the avatar.
17
18 // global variables...
19
20 vector last_detected_position;  // where the avatar was last detected.
21 integer target_identifier;  // the id assigned when we registered our target.
22 integer last_physics_state;  // this remembers if physics should be enabled currently.
23 vector perch_position;  // place we inhabit near the owner.    
24
25 // returns the location where we should perch, given the target's location.
26 vector target_to_perch(key av, vector target)
27 {
28     vector av_bounds = llGetAgentSize(av);
29     return <target.x, target.y, target.z + av_bounds.z / 2.0 + HEIGHT_ABOVE_AVATAR>;
30 }
31
32 // returns the location of the target given where we're trying to aim at.
33 vector perch_to_target(key av, vector perch)
34 {
35     vector av_bounds = llGetAgentSize(av);
36     return <perch.x, perch.y, perch.z - av_bounds.z / 2 - HEIGHT_ABOVE_AVATAR>;
37 }
38 //hmmm: the two target and perch funcs both assume we don't want any lateral offset.
39 //      and currently they're only taking into account the avatar's size in the z direction.
40
41
42 // makes the pet completely stop travelling around and just sit there.
43 cease_movement()
44 {
45     llStopMoveToTarget();
46     llTargetRemove(target_identifier);
47     full_stop();        
48     llSetStatus(STATUS_PHYSICS, FALSE);
49     last_physics_state = FALSE;
50     // if we're not quite there, jump to the perch.
51     if (llVecDist(perch_position, llGetPos()) > ROOM_FOR_ERROR) {
52         // we're not close enough so make a flying leap.
53 //llOwnerSay("jumping to perch at " + (string)perch_position + ", was at " + (string)llGetPos());
54         llSetPos(perch_position);  // make us very accurate until something changes.
55     }
56 }
57
58 // tells the pet to target the avatar "av" at the location "pos".  this will assume
59 // the avatar is actually present in the same sim when it calculates the avatar's size.
60 // we use that size in calculating where to perch nearby the avatar.
61 move_toward_target(key av, vector destination)
62 {
63     // first of all we'll remember where we're supposed to go.
64     perch_position = target_to_perch(av, destination);
65     // now see how far away we are from that.
66     float distance = llVecDist(perch_position, llGetPos());
67     if (distance < 1.0) {
68         // we're close enough; stop moving for a bit.
69 //llOwnerSay("dist small enough to go non-phys: " + (string)distance);
70         cease_movement();
71         return;
72     }
73     // well, now we know that we need to move somewhere.  let's set up a
74     // physics target and head that way.
75     llSetStatus(STATUS_PHYSICS, TRUE);
76     last_physics_state = TRUE;
77     llTargetRemove(target_identifier);
78     float time = distance / MAXIMUM_VELOCITY;
79     // if we go too low, then SL will ignore the move to target request.
80     if (time < 0.14) time = 0.14;
81 //llOwnerSay("tau=" + (string)time);
82     target_identifier = llTarget(perch_position, ROOM_FOR_ERROR);
83     llMoveToTarget(perch_position, time);
84 }
85
86 // startup the object.
87 initialize()
88 {
89     llSetStatus(STATUS_PHYSICS, TRUE);
90     last_physics_state = TRUE;
91     llSetBuoyancy(1.0);
92     llSetStatus(STATUS_PHANTOM, TRUE);
93     llSensorRemove();
94     // start looking for the owner.
95     llSensorRepeat("", llGetOwner(), AGENT, SENSOR_RANGE, PI * 2, SENSOR_PERIOD);
96 }
97
98 // sets the object's speed to "new_velocity".
99 // if "local_axis" is TRUE, then it will be relative to the object's
100 // own local coordinates.
101 set_velocity(vector new_velocity, integer local_axis)
102 {
103     vector current_velocity = llGetVel();
104          
105     if (local_axis) {
106         rotation rot = llGetRot();
107         current_velocity /= rot;  // undo the rotation.
108     }
109     
110     new_velocity -= current_velocity;
111     new_velocity *= llGetMass();
112     
113     llApplyImpulse(new_velocity, local_axis);
114 }
115
116 // attempts to bring the object to a complete stop.
117 full_stop()
118 {
119     llSetForce(<0,0,0>, FALSE);
120     set_velocity(<0,0,0>, FALSE);
121 }
122
123 default {
124     state_entry() { if (llSubStringIndex(llGetObjectName(), "huffotronic") < 0) state real_default; }
125     on_rez(integer parm) { state rerun; }
126 }
127 state rerun { state_entry() { state default; } }
128
129 state real_default
130 {
131     state_entry() { initialize(); }
132
133     on_rez(integer param) { llResetScript(); }
134
135     sensor(integer num_detected)
136     {
137         // save where we saw the av just now.
138         last_detected_position = llDetectedPos(0);
139         // move closer if we're not near enough to our beloved owner.
140         move_toward_target(llGetOwner(), last_detected_position);
141         // if we find that our rotation is incorrect, we'll fix that here.
142         // we only reorient on the sensor period, since that's slower
143         // than hitting our target.  plus we try to ensure we never get
144         // out of place again.
145         vector curr_rot = llRot2Euler(llGetRot());
146         if ( (curr_rot.x != 0.0 ) || (curr_rot.y != 0.0) ) {
147             // we are out of rotational goodness right now even.  fix that.
148             llSetStatus(STATUS_PHYSICS, FALSE);
149             llSetStatus(STATUS_ROTATE_X, FALSE);
150             llSetStatus(STATUS_ROTATE_Y, FALSE);
151             // save the z value before correcting the rotation.
152             vector new_rot = ZERO_VECTOR;
153             new_rot.z = curr_rot.z;
154             llSetRot(llEuler2Rot(new_rot));
155             llSetStatus(STATUS_PHYSICS, last_physics_state);
156         }
157     }
158
159     no_sensor()
160     {
161         // we lost track of the avatar.  turn off phyics and wait.
162         cease_movement();
163     }
164
165     at_target(integer number, vector targetpos, vector ourpos)
166     {
167         // wait until we see the av again before picking a new target.
168 ///??seems bad        cease_movement();
169     }
170     
171     not_at_target()
172     {
173     }
174 }