Join us in Outworldz at www.outworldz.com:9000 or follow us:

Search dozens of selected web sites for OpenSim and LSL script

New! Script Meta-Search will search thousands of scripts here and at other sites for LSL or Opensim scripts.
Loading

Want to add a script or a project? Upload it and a half million people will see it and your name here this year.

Home   Show All
Category: Contributor: Creator
Animal Low_lag_Follower_script_for_animals  

Low_lag_Follower_script_for_animals

Script several linked prim sets to fly (loosely) as in a "flock" around a pre-set course. Low lag Follower script for birds, horse and other things that flock.

You put a vector offset in the description of each "bird". They will follow that spot as an offset from a prim named 'Chaser'. The speed is controlled by a single variable in the notecard line. It can move very quickly.

When the birds lead or follow the chaser prim, they swing wildly out. If you route has many zig zags, they would fly like a flock.
See http://phazedemesnes.blogspot.com/2011/02/herding-behaviour-in-animals-in-second.html for a description of this behavior using this script.

This is the Follower script. It goes in multiple birds or other animal

Category: Animal
By : Ferd Frederix
Created: 2011-08-04 Edited: 2011-08-04
Worlds: Second Life

the Zip file

Download all files for Low_lag_Follower_script_for_animals
Contents are in zip format, with .LSL (text) source code and LSLEdit (text + Solution) formats.
Get file # 1. Low_lag_Follower_script_for_animals_1.lsl
Get file # 2. Low_lag_Follower_script_for_animals_2.lsl

This script by Ferd Frederix may be used in any manner, modified, and republished.  Unless specified otherwise, my scripts are always free and open source.  Objects made with these scripts may be sold with no restrictions.  All I ask is that you point others to this location should they ask you about it and to not sell this script, unless it is for $0 L. Please help improve my work by reporting bugs and improvements.

1 // Author Ferd Frederix
2 // Low lag Follower script for birds, horse and other things that flock
3 // see http://phazedemesnes.blogspot.com/2011/02/herding-behaviour-in-animals-in-second.html
4 // for this works on herds of horses.
5 //
6 //
7 // Chases after a prim named "CHaser" at a offset
8 // You must have an offset vector in this objects description like this:
9 // <1.5,2,3> follow 1.5 meters to one side, 2 in front of, and 3 meters above the Chaser ( negative numbers are behind, positive in front of)
10
11 // Copyright 2011. Licensed under the GNU open source license at
12 // http://www.gnu.org/copyleft/gpl.html
13 // Open source, you must make this script copy/tranfer AND mod and leave the headers, including this license and other attributions intact.
14 //
15
16
17 integer _debug = 0;
18 vector priorpos;
19 float INTERVAL = .050; // seconds to move
20 vector offset = < -1, 0, 1>; //1 meter behind and 1 meter above owner's center.
21 key Follower;
22
23
24 // movement
25
26 float DAMPING = .7; // .3
27
28 // rotation
29 float STRENGTH = 1;
30 float DAMP = .2;
31
32 /////////////// CONSTANTS ///////////////////
33 string FWD_DIRECTION = "-x";
34 vector POSITION_OFFSET ;
35 float SCAN_REFRESH = 0.2;
36 string FOLLOW = "/follow";
37 string STAY = "/stay";
38 integer FOLLOW_STOP = 5000;
39 integer FOLLOW_START = 5001;
40 float MOVETO_INCREMENT = 6.0;
41 ///////////// END CONSTANTS /////////////////
42
43 ///////////// GLOBAL VARIABLES ///////////////
44
45 rotation gFwdRot = <0,0,0,1>;
46 float gTau = .2;
47
48
49 /////////// END GLOBAL VARIABLES /////////////
50
51 rotation GetFwdRot()
52 {
53 // Special case... 180 degrees gives a math error
54 if(FWD_DIRECTION == "-x")
55 {
56 return llAxisAngle2Rot(<0, 0, 1>, PI);
57 }
58
59 string Direction = llGetSubString(FWD_DIRECTION, 0, 0);
60 string Axis = llToLower(llGetSubString(FWD_DIRECTION, 1, 1));
61
62 vector Fwd;
63 if(Axis == "x")
64 Fwd = <1, 0, 0>;
65 else if(Axis == "y")
66 Fwd = <0, 1, 0>;
67 else
68 Fwd = <0, 0, 1>;
69
70 if(Direction == "-")
71 Fwd *= -1;
72
73 return llRotBetween(Fwd, <1, 0, 0>);
74 }
75
76 rotation GetRotation(rotation rot)
77 {
78 vector Fwd;
79 Fwd = llRot2Fwd(rot);
80
81 float Angle = llAtan2( Fwd.y, Fwd.x );
82 return gFwdRot * llAxisAngle2Rot(<0, 0, 1>, Angle);
83 }
84
85
86 default
87 {
89 {
90 llSensor("Chaser","",SCRIPTED|ACTIVE,96,PI);
92
93 // set to a 1 if you want to crawl sideways.
94 if(FALSE)
95 {
96 // rotate the vehicle frame -PI/2 about the local y-axis (left-axis)
97 rotation rot =llEuler2Rot(<PI/2, 0,0>);
99 }
100
103
104 }
105
106 sensor(integer num_detected)
107 {
108 if(_debug) llOwnerSay("C0unt:" + (string) num_detected);
109 Follower = llDetectedKey(0);
110 if(_debug) llOwnerSay("Dest:" + (string) Follower);
112 // Little pause to allow server to make potentially large linked object physical.
113 llSleep(0.1);
115 //llGroundRepel(0.5, TRUE, 0.2);
116 priorpos = llGetPos();
117
118 }
119
120 no_sensor()
121 {
122 llOwnerSay("No Chaser! Quitting");
123 }
124
125 timer()
126 {
127 vector myPos = llGetPos();
128
129 // Get position and rotation
130 list det = llGetObjectDetails(Follower,[OBJECT_POS,OBJECT_ROT" title="View Definition" class="tooltip">OBJECT_ROT]);
131 vector Pos = llList2Vector(det,0);
132 rotation Rot = llList2Rot(det,1);
133
134 rotation TargetRot = GetRotation(Rot);
135 POSITION_OFFSET = (vector) llGetObjectDesc();
136
137 vector Offset = POSITION_OFFSET * Rot;
138 Pos += Offset;
139
140 float howfar = llVecMag(myPos - Pos);
141
142 if(_debug) llOwnerSay("Delta: " + (string) howfar);
143
144 if(howfar > 0.5)
145 {
146 llLookAt(Pos, STRENGTH , DAMP );
147 llMoveToTarget((llVecNorm(Pos - myPos) * howfar) + myPos, DAMPING);
148 }
149
150 }
151 }

Low_lag_Follower_script_for_animals

This Chaser Script goes into an invisible prim. Make it large and visible at first. or you will certainly have an invisible, tiny, hard to catch prim wandering your sim!

Category: Animal
By : Ferd Frederix
Created: 2011-08-04 Edited: 2011-08-04
Worlds: Second Life


This script by Ferd Frederix may be used in any manner, modified, and republished.  Unless specified otherwise, my scripts are always free and open source.  Objects made with these scripts may be sold with no restrictions.  All I ask is that you point others to this location should they ask you about it and to not sell this script, unless it is for $0 L. Please help improve my work by reporting bugs and improvements.

1 // Primchaser script
2 // Author: Ferd Frederix
3
4 // Copyright 2011. Licensed under the GNU open source license GPLv3
5 // http://www.gnu.org/copyleft/gpl.html
6 // You must make this script copy/tranfer AND mod and leave the headers, including this license and other attributions intact.
7 // modifications are allowed, but the code must always be open. See the GPL for details on your responsibilities under this license.
8
9 // requires a notecard "named Route"
10 // Notecard format
11
12 //there are 6 columns:
13 //column 1: wait interval (floating point number) This is the numbner of seconds the prim will wait when it reads this coordinate. Must be a 0 for no wait.
14 //column 2: x coordinate (floating point number)
15 //column 3: y coordinate (floating point number)
16 //column 4: z coordinate (floating point number)
17 //column 5: a space, or text to be spoken on a chat 'CommandChannel', which is -236. This allow you to open doors, gates, and such at specifi points in the tour
18 //column 6: a command, currently only one command is used Speed: N, where N is anumber for how quickly the Chaser will go from one point to another, in seconds. 1 = 1 meter a second, 2 = 2 meters a second
19
20 // for some strange reason llParseString2List does not work without some content between the separators,
21 // Here, I use a space
22
23 //Typical notecard:
24 // 0|56|131|24| | | //goto 56,131,29
25 // 0|66|123|23| |Speed: 0.5| //goto 66,123,23 at double speed
26 // 0|76|122|22| |Speed:1| //default speed
27 // 0|84|122|22| |Speed:20| //really slow
28 // 30|97|125|23| | | //pause 30 seconds at end of tour
29
30
31 integer _debug = FALSE; // set to TRUE for progress messages
32
33 integer CommandChannel = -236; // a possible command channel to open gates, close doors, whatever
34
35 list lTimeouts = []; // storages for notecard columns
36 list lCoordinate = [];
37 list lDescriptions = [];
38 list lCommands = [];
39
40 vector priorpos;
41
42 // notecard reading
43 integer iIndexLines;
44 string NOTECARD = "Route"; // the notecard for configuring
45
46 key kNoteCardLines; // the key of the notecard
47 key kGetIndexLines; // the key of the current line
48 integer i = 0;
49 integer count = 0;
50
51
52 // speed control
53 float DAMPING = 1; // 1 meters per second
54 vector TargetLocation; // where we are heading at any moment in time
55 float INTERVAL = .2; // seconds of timer tick to push us, slower = jerjier motion
56
57 string SpeakThis; // what is to be said
58
59
60 // modified from the original wiki, which is basically broken
61 string left(string src, string divider) {
62 integer index = llSubStringIndex( src, divider );
63 if(~index)
64 return llDeleteSubString( src, index , -1);
65 return src;
66 }
67
68 string right(string src, string divider) {
69 integer index = llSubStringIndex( src, divider );
70 if(~index)
71 return llDeleteSubString( src, 0, index + llStringLength(divider) - 1);
72 return src;
73 }
74
75 // stripo white spaces
76 string strip( string str)
77 {
78 string out;
79 integer i;
80
81 for ( ; i < llStringLength(str); i++)
82 {
83 out += llGetSubString(str,i,i);
84 out = llStringTrim(out, STRING_TRIM);
85 }
86 return out;
87 }
88
89 string Getline(list Input, integer line)
90 {
91 return strip(llList2String(Input, line));
92 }
93
94
95 default
96 {
97 on_rez(integer param)
98 {
100 }
101
103 {
105 kNoteCardLines = llGetNumberOfNotecardLines(NOTECARD);
106 kGetIndexLines = llGetNotecardLine(NOTECARD,0);
107 llSay(0, "Tour guide initialising. Please wait.");
108 }
109
110 // read notecard on bootup
111 dataserver(key queryid, string data)
112 {
113 vector TempLocation;
114 if(queryid == kNoteCardLines)
115 iIndexLines = (integer) data;
116 if(queryid == kGetIndexLines)
117 {
118 if(data != EOF)
119 {
120 queryid = llGetNotecardLine(NOTECARD, i);
121 list lLine = (llParseString2List(data, ["|"], []));
122
123 float Timeout = (float) Getline(lLine,0); // Sleep
124 float X = (float) Getline(lLine,1);
125 float Y = (float) Getline(lLine,2);
126 float Z = (float) Getline(lLine,3);
127
128 string Msg = llList2String(lLine,4);
129 string sCommand = llList2String(lLine,5);
130
131 TempLocation.x = X;
132 TempLocation.y = Y;
133 TempLocation.z = Z;
134
135 lTimeouts += Timeout;
136 lCoordinate += TempLocation;
137 lDescriptions += Msg;
138 lCommands += sCommand;
139
140
141 integer locationLength = (llGetListLength(lCoordinate));
142 integer InitPerCent = (integer) llRound(((float) locationLength / (float) iIndexLines) * 100);
143 llSetText("Initialising... \n" + (string) InitPerCent + "%" , <1,1,1>, 1.0);
144 if(InitPerCent == 100)
145 state Paused;
146 i++;
147 }
148 kGetIndexLines = llGetNotecardLine(NOTECARD,i);
149 }
150 }
151
152
153 touch_start(integer total_number)
154 {
155 integer check = llGetListLength(lCoordinate);
156 if(_debug)
157 llOwnerSay("List is " + (string) check + " destinations long");
158
159 if(check >= iIndexLines)
160 state Paused;
161
162 if(check < iIndexLines)
163 llSay(0, "Hang on a sec, still initialising...");
164 }
165
167 {
168 llSetText("", <1,1,1>, 1.0);
169 TargetLocation = (vector) llList2String(lCoordinate, 0); // Look at 0th
170 }
171 }
172
173
174 state Paused
175 {
177 {
178 TargetLocation = (vector) llList2String(lCoordinate, count);
180 state moving;
181 }
182 }
183
184 state moving
185 {
186
188 {
189 if(_debug) llOwnerSay("Mooving to " + (string) TargetLocation);
190 llSetTimerEvent(INTERVAL);
191 priorpos = llGetPos();
193 }
194
195 on_rez(integer param)
196 {
198 }
199
200
201 timer()
202 {
203 vector myPos = llGetPos();
204 if(_debug)
205 {
206 float dist = llVecDist(myPos, priorpos);
207 float velocity = dist / DAMPING;
208 if(_debug) llOwnerSay("Velocity:" + (string) velocity);
209 }
210
211 if(llVecMag(myPos - TargetLocation) > DAMPING)
212 {
213 llLookAt(TargetLocation, .4, .2);
214 llSetPos((llVecNorm(TargetLocation- myPos) * DAMPING) + myPos);
215 }
216 else
217 {
218 SpeakThis = llList2String(lDescriptions, count);
219
220 if(llStringLength(SpeakThis) > 0)
221 llSay(CommandChannel,SpeakThis);
222
223 SpeakThis = llList2String(lCommands, count);
224
225 string CmdName = left(SpeakThis,":");
226 string VarName = right(SpeakThis,":");
227
228 if(_debug) llOwnerSay("Cmd:" + (string) CmdName);
229 if(_debug) llOwnerSay("Val:" + (string) VarName);
230
231 if(CmdName == "Speed")
232 {
233 //llSay(0,"New Speed:" + (string) VarName);
234 DAMPING = (float) VarName;
235 }
236
237
238 float Timeout = llList2Float(lTimeouts, count);
239
240 if(Timeout)
241 {
242 if(_debug) llOwnerSay("Pauseing:" + (string) Timeout);
243 llSleep(Timeout);
244 }
245
246 count ++;
247
248 if(count > (iIndexLines - 1))
249 state end;
250
251 if(count <= (iIndexLines - 1))
252 {
253 //Say(0,"At " + (string) TargetLocation);
254 TargetLocation = (vector) llList2String(lCoordinate, count);
255 if(_debug) llOwnerSay("New Target: " + (string) TargetLocation);
256 }
257 }
258 }
259
261 {
263 }
264 }
265
266 state GetCoordinate
267 {
269 {
270 if(_debug) llOwnerSay("state GetCoordinate");
271 count ++;
272
273 if(count > (iIndexLines - 1))
274 state end;
275
276 if(count <= (iIndexLines - 1))
277 {
278 TargetLocation = (vector) llList2String(lCoordinate, count);
279 if(_debug) llOwnerSay("New Target: " + (string) TargetLocation);
280 state moving;
281 }
282 }
283
284 }
285
286 state end
287 {
289 {
290 //llSay(0, "Tour end. " );
291 count = 0;
292 TargetLocation = (vector) llList2String(lCoordinate, 0); // Start over
293 state moving; // start over
294 }
295
296
297 }

Back to the Best Free Tools in Second Life and OpenSim.