corrade-lsl-templates – Blame information for rev 36

Subversion Repositories:
Rev:
Rev Author Line No. Line
2 office 1 ///////////////////////////////////////////////////////////////////////////
29 office 2 // Copyright (C) Wizardry and Steamworks 2014 - License: CC BY 2.0 //
2 office 3 ///////////////////////////////////////////////////////////////////////////
4 //
5 // This is an automatic grid follower for the Corrade Second Life / OpenSim
6 // bot. It uses two different engines: the simulator's built-in autopilot
7 // and a fly engine that will make Corrade fly to your location.
8 // You can find more details about the bot by following the URL:
9 // http://grimore.org/secondlife/scripted_agents/corrade
10 //
11 // The follower script works together with a "configuration" notecard and
12 // that must be placed in the same primitive as this script.
29 office 13 // You are free to use, change, and commercialize it under the CC BY 2.0
14 // license at: https://creativecommons.org/licenses/by/2.0
2 office 15 //
16 ///////////////////////////////////////////////////////////////////////////
17  
18 ///////////////////////////////////////////////////////////////////////////
29 office 19 // Copyright (C) 2014 Wizardry and Steamworks - License: CC BY 2.0 //
2 office 20 ///////////////////////////////////////////////////////////////////////////
21 string wasKeyValueGet(string k, string data) {
22 if(llStringLength(data) == 0) return "";
23 if(llStringLength(k) == 0) return "";
24 list a = llParseString2List(data, ["&", "="], []);
25 integer i = llListFindList(a, [ k ]);
26 if(i != -1) return llList2String(a, i+1);
27 return "";
28 }
29  
30 ///////////////////////////////////////////////////////////////////////////
29 office 31 // Copyright (C) 2013 Wizardry and Steamworks - License: CC BY 2.0 //
2 office 32 ///////////////////////////////////////////////////////////////////////////
33 string wasKeyValueEncode(list data) {
34 list k = llList2ListStrided(data, 0, -1, 2);
35 list v = llList2ListStrided(llDeleteSubList(data, 0, 0), 0, -1, 2);
36 data = [];
37 do {
38 data += llList2String(k, 0) + "=" + llList2String(v, 0);
39 k = llDeleteSubList(k, 0, 0);
40 v = llDeleteSubList(v, 0, 0);
41 } while(llGetListLength(k) != 0);
42 return llDumpList2String(data, "&");
43 }
44  
45 ///////////////////////////////////////////////////////////////////////////
29 office 46 // Copyright (C) 2011 Wizardry and Steamworks - License: CC BY 2.0 //
2 office 47 ///////////////////////////////////////////////////////////////////////////
48 vector wasCirclePoint(float radius) {
49 float x = llPow(-1, 1 + (integer) llFrand(2)) * llFrand(radius*2);
50 float y = llPow(-1, 1 + (integer) llFrand(2)) * llFrand(radius*2);
51 if(llPow(x,2) + llPow(y,2) <= llPow(radius,2))
52 return <x, y, 0>;
53 return wasCirclePoint(radius);
54 }
55  
56 ///////////////////////////////////////////////////////////////////////////
29 office 57 // Copyright (C) 2014 Wizardry and Steamworks - License: CC BY 2.0 //
2 office 58 ///////////////////////////////////////////////////////////////////////////
59 integer wasIsAvatarInSensorRange(key avatar) {
60 return llListFindList(
61 llGetAgentList(
62 AGENT_LIST_REGION,
63 []
64 ),
65 (list)((key)avatar)
66 ) != -1 &&
67 llVecDist(
68 llGetPos(),
69 llList2Vector(
70 llGetObjectDetails(
71 avatar,
72 [OBJECT_POS]
73 ),
74  
75 )
76 ) <= 96;
77 }
78  
79 ///////////////////////////////////////////////////////////////////////////
29 office 80 // Copyright (C) 2015 Wizardry and Steamworks - License: CC BY 2.0 //
2 office 81 ///////////////////////////////////////////////////////////////////////////
82 // escapes a string in conformance with RFC1738
83 string wasURLEscape(string i) {
84 string o = "";
85 do {
86 string c = llGetSubString(i, 0, 0);
87 i = llDeleteSubString(i, 0, 0);
88 if(c == "") jump continue;
89 if(c == " ") {
90 o += "+";
91 jump continue;
92 }
93 if(c == "\n") {
94 o += "%0D" + llEscapeURL(c);
95 jump continue;
96 }
97 o += llEscapeURL(c);
98 @continue;
99 } while(i != "");
100 return o;
101 }
102  
103 // for holding the callback URL
104 string callback = "";
105  
106 // key-value data will be read into this list
107 string configuration = "";
108  
109 default {
110 state_entry() {
111 llSetTimerEvent(1);
112 }
113 link_message(integer sender, integer num, string message, key id) {
114 if(sender != 1 || id != "configuration") return;
115 configuration = message;
116 state off;
117 }
118 timer() {
119 llMessageLinked(LINK_ROOT, 0, "configuration", NULL_KEY);
120 }
121 attach(key id) {
122 llResetScript();
123 }
124 on_rez(integer num) {
125 llResetScript();
126 }
127 changed(integer change) {
128 if(change & CHANGED_INVENTORY || (change & CHANGED_OWNER))
129 llResetScript();
130 if(
131 (change & CHANGED_REGION_START) ||
132 (change & CHANGED_REGION)) {
133 state on;
134 }
135 }
136 state_exit() {
137 llSetTimerEvent(0);
138 }
139 }
140  
141 state off {
142 state_entry() {
143 llSetColor(<.5,0,0>, ALL_SIDES);
144 }
145 touch_end(integer num) {
146 state on;
147 }
148 attach(key id) {
149 llResetScript();
150 }
151 on_rez(integer num) {
152 llResetScript();
153 }
154 changed(integer change) {
155 if(change & CHANGED_INVENTORY || (change & CHANGED_OWNER))
156 llResetScript();
157 }
158 }
159  
160 state on {
161 state_entry() {
162 llSetColor(<0,.5,0>, ALL_SIDES);
163 state url;
164 }
165 attach(key id) {
166 llResetScript();
167 }
168 on_rez(integer num) {
169 llResetScript();
170 }
171 changed(integer change) {
172 if(change & CHANGED_INVENTORY || (change & CHANGED_OWNER))
173 llResetScript();
174 }
175 }
176  
177 state url {
178 state_entry() {
179 // DEBUG
180 llOwnerSay("Requesting URL...");
181 llRequestURL();
182 }
183 touch_end(integer num) {
184 llSetColor(<.5,0,0>, ALL_SIDES);
185 llResetScript();
186 }
187 http_request(key id, string method, string body) {
188 if(method != URL_REQUEST_GRANTED) return;
189 callback = body;
190 // DEBUG
191 llOwnerSay("Got URL...");
192 state detect;
193 }
194 attach(key id) {
195 llResetScript();
196 }
197 on_rez(integer num) {
198 llResetScript();
199 }
200 changed(integer change) {
201 if(change & CHANGED_INVENTORY || (change & CHANGED_OWNER))
202 llResetScript();
203 if(
204 (change & CHANGED_REGION_START) ||
205 (change & CHANGED_REGION)) {
206 state on;
207 }
208 }
209 }
210  
211 state detect {
212 state_entry() {
213 // set color for button
214 llSetColor(<0,.5,0>, ALL_SIDES);
215 // if Corrade is in-range then just follow
216 if(wasIsAvatarInSensorRange(
217 (key)wasKeyValueGet(
218 "corrade",
219 configuration
220 )
221 )
222 ) state select;
223 // DEBUG
224 llOwnerSay("Detecting if Corrade is online...");
225 llRequestAgentData(
226 (key)wasKeyValueGet(
227 "corrade",
228 configuration
229 ),
230 DATA_ONLINE
231 );
232 }
233 touch_end(integer num) {
234 llSetColor(<.5,0,0>, ALL_SIDES);
235 llResetScript();
236 }
237 dataserver(key id, string data) {
238 if(data != "1") {
239 // DEBUG
240 llOwnerSay("Corrade is not online, sleeping...");
241 llResetScript();
242 return;
243 }
244 llSensorRepeat("",
245 (key)wasKeyValueGet(
246 "corrade",
247 configuration
248 ),
249 AGENT,
250 (integer)wasURLEscape(
251 wasKeyValueGet(
252 "range",
253 configuration
254 )
255 ),
256 TWO_PI,
257 5
258 );
259 }
260 no_sensor() {
261 // DEBUG
262 llOwnerSay("Teleporting Corrade...");
263 llInstantMessage(
264 (key)wasKeyValueGet(
265 "corrade",
266 configuration
267 ),
268 wasKeyValueEncode(
269 [
270 "command", "teleport",
271 "group", wasURLEscape(
272 wasKeyValueGet(
273 "group",
274 configuration
275 )
276 ),
277 "password", wasURLEscape(
278 wasKeyValueGet(
279 "password",
280 configuration
281 )
282 ),
32 office 283 "entity", "region",
2 office 284 "region", wasURLEscape(llGetRegionName()),
285 "position", llGetPos() + wasCirclePoint(
286 (integer)wasURLEscape(
287 wasKeyValueGet(
288 "range",
289 configuration
290 )
291 )
292 ),
293 "deanimate", "True",
294 "callback", callback
295 ]
296 )
297 );
298 }
299 sensor(integer num) {
300 state select;
301 }
302 http_request(key id, string method, string body) {
303 llHTTPResponse(id, 200, "OK");
304 if(wasKeyValueGet("command", body) != "teleport" ||
305 wasKeyValueGet("success", body) != "True") {
306 // DEBUG
307 llOwnerSay("Teleport failed...");
308 return;
309 }
310 state select;
311 }
312 attach(key id) {
313 llResetScript();
314 }
315 on_rez(integer num) {
316 llResetScript();
317 }
318 changed(integer change) {
319 if(change & CHANGED_INVENTORY || (change & CHANGED_OWNER))
320 llResetScript();
321 if(
322 (change & CHANGED_REGION_START) ||
323 (change & CHANGED_REGION)) {
324 state on;
325 }
326 }
327 }
328  
329 state select {
330 state_entry() {
331 // DEBUG
332 llOwnerSay("Selecting follow engine...");
333 llSetTimerEvent(1);
334 }
335 touch_end(integer num) {
336 llSetColor(<.5,0,0>, ALL_SIDES);
337 llResetScript();
338 }
339 timer() {
340 vector cPos = llList2Vector(
341 llGetObjectDetails(
342 (key)wasKeyValueGet(
343 "corrade",
344 configuration
345 ),
346 [OBJECT_POS]
347 ),
348  
349 );
350 vector mPos = llGetPos();
351 // If Corrade is in range then stop.
352 if(llVecDist(mPos, cPos) < 5) return;
353 // If we are flying or the distance between us and Corrade
354 // is larger than a given distance then make Corrade fly.
355 if(
356 (
357 llGetAgentInfo(llGetOwner()) & AGENT_FLYING
358 ) ||
359 llFabs(mPos.z - cPos.z) > 5) {
360 state stop_pilot;
361 }
362 // Otherwise, stop flight and walk.
363 if(llGetAgentInfo(
364 (key)wasKeyValueGet(
365 "corrade",
366 configuration
367 )
368 ) & AGENT_FLYING) state stop_flight;
369 // If Corrade is not flying then walk.
370 state walk;
371 }
372 attach(key id) {
373 llResetScript();
374 }
375 on_rez(integer num) {
376 llResetScript();
377 }
378 changed(integer change) {
379 if(change & CHANGED_INVENTORY || (change & CHANGED_OWNER))
380 llResetScript();
381 if(
382 (change & CHANGED_REGION_START) ||
383 (change & CHANGED_REGION)) {
384 state on;
385 }
386 }
387 state_exit() {
388 llSetTimerEvent(0);
389 }
390 }
391  
392 state stop_pilot {
393 state_entry() {
36 office 394 state fly;
2 office 395 llSetTimerEvent(60);
396 }
397 timer() {
398 state on;
399 }
400 touch_end(integer num) {
401 llSetColor(<.5,0,0>, ALL_SIDES);
402 llResetScript();
403 }
404 attach(key id) {
405 llResetScript();
406 }
407 on_rez(integer num) {
408 llResetScript();
409 }
410 changed(integer change) {
411 if(change & CHANGED_INVENTORY || (change & CHANGED_OWNER))
412 llResetScript();
413 if(
414 (change & CHANGED_REGION_START) ||
415 (change & CHANGED_REGION)) {
416 state on;
417 }
418 }
419 state_exit() {
420 llSetTimerEvent(0);
421 }
422 }
423  
424 state fly {
425 state_entry() {
426 // DEBUG
427 llOwnerSay("Flying to agent...");
428 llRegionSayTo(
429 (key)wasKeyValueGet(
430 "corrade",
431 configuration
432 ),
433 0,
434 wasKeyValueEncode(
435 [
436 "command", "flyto",
437 "group", wasURLEscape(
438 wasKeyValueGet(
439 "group",
440 configuration
441 )
442 ),
443 "password", wasURLEscape(
444 wasKeyValueGet(
445 "password",
446 configuration
447 )
448 ),
449 // move in a radius around the current primitive.
450 "position", llGetPos() + wasCirclePoint(
451 (integer)wasURLEscape(
452 wasKeyValueGet(
453 "range",
454 configuration
455 )
456 )
457 ),
458 "fly", "True",
459 "vicinity", wasCirclePoint(
460 (integer)wasURLEscape(
461 wasKeyValueGet(
462 "range",
463 configuration
464 )
465 )
466 ),
467 "duration", "2500",
468 "callback", wasURLEscape(callback)
469 ]
470 )
471 );
472 llSetTimerEvent(60);
473 }
474 timer() {
475 state on;
476 }
477 touch_end(integer num) {
478 llSetColor(<.5,0,0>, ALL_SIDES);
479 llResetScript();
480 }
481 http_request(key id, string method, string body) {
482 llHTTPResponse(id, 200, "OK");
483 if(wasKeyValueGet("command", body) != "flyto" ||
484 wasKeyValueGet("success", body) != "True") {
485 // DEBUG
486 llOwnerSay("Flight failed...");
487 state on;
488 }
489 state select;
490 }
491 attach(key id) {
492 llResetScript();
493 }
494 on_rez(integer num) {
495 llResetScript();
496 }
497 changed(integer change) {
498 if(change & CHANGED_INVENTORY || (change & CHANGED_OWNER))
499 llResetScript();
500 if(
501 (change & CHANGED_REGION_START) ||
502 (change & CHANGED_REGION)) {
503 state on;
504 }
505 }
506 state_exit() {
507 llSetTimerEvent(0);
508 }
509 }
510  
511 state stop_flight {
512 state_entry() {
513 // DEBUG
514 llOwnerSay("Landing agent for walking...");
515 llRegionSayTo(
516 wasKeyValueGet(
517 "corrade",
518 configuration
519 ),
520 0,
521 wasKeyValueEncode(
522 [
523 "command", "fly",
524 "group", wasURLEscape(
525 wasKeyValueGet(
526 "group",
527 configuration
528 )
529 ),
530 "password", wasURLEscape(
531 wasKeyValueGet(
532 "password",
533 configuration
534 )
535 ),
536 "action", "stop",
537 "callback", wasURLEscape(callback)
538 ]
539 )
540 );
541 llSetTimerEvent(60);
542 }
543 timer() {
544 state on;
545 }
546 touch_end(integer num) {
547 llSetColor(<.5,0,0>, ALL_SIDES);
548 llResetScript();
549 }
550 http_request(key id, string method, string body) {
551 llHTTPResponse(id, 200, "OK");
552 if(wasKeyValueGet("command", body) != "fly" ||
553 wasKeyValueGet("success", body) != "True") {
554 // DEBUG
555 llOwnerSay("Landing failed...");
556 state on;
557 }
558 llOwnerSay("Landed...");
559 state walk;
560 }
561 attach(key id) {
562 llResetScript();
563 }
564 on_rez(integer num) {
565 llResetScript();
566 }
567 changed(integer change) {
568 if(change & CHANGED_INVENTORY || (change & CHANGED_OWNER))
569 llResetScript();
570 if(
571 (change & CHANGED_REGION_START) ||
572 (change & CHANGED_REGION)) {
573 state on;
574 }
575 }
576 state_exit() {
577 llSetTimerEvent(0);
578 }
579 }
580  
581 state walk {
582 state_entry() {
583 // DEBUG
584 llOwnerSay("Walking to agent...");
585 llRegionSayTo(
586 (key)wasKeyValueGet(
587 "corrade",
588 configuration
589 ),
590 0,
591 wasKeyValueEncode(
592 [
36 office 593 "command", "walkto",
2 office 594 "group", wasURLEscape(
595 wasKeyValueGet(
596 "group",
597 configuration
598 )
599 ),
600 "password", wasURLEscape(
601 wasKeyValueGet(
602 "password",
603 configuration
604 )
605 ),
606 // move in a radius around the current primitive.
607 "position", llGetPos() + wasCirclePoint(
608 (integer)wasURLEscape(
609 wasKeyValueGet(
610 "range",
611 configuration
612 )
613 )
614 ),
36 office 615 "vicinity", wasCirclePoint(
616 (integer)wasURLEscape(
617 wasKeyValueGet(
618 "range",
619 configuration
620 )
621 )
622 ),
623 "duration", "2500",
2 office 624 "callback", wasURLEscape(callback)
625 ]
626 )
627 );
628 llSetTimerEvent(60);
629 }
630 timer() {
631 state on;
632 }
633 touch_end(integer num) {
634 llSetColor(<.5,0,0>, ALL_SIDES);
635 llResetScript();
636 }
637 http_request(key id, string method, string body) {
638 llHTTPResponse(id, 200, "OK");
36 office 639 if(wasKeyValueGet("command", body) != "walkto" ||
2 office 640 wasKeyValueGet("success", body) != "True") {
641 // DEBUG
36 office 642 llOwnerSay("Failed to start walkto...");
2 office 643 state on;
644 }
645 state select;
646 }
647 attach(key id) {
648 llResetScript();
649 }
650 on_rez(integer num) {
651 llResetScript();
652 }
653 changed(integer change) {
654 if(change & CHANGED_INVENTORY || (change & CHANGED_OWNER))
655 llResetScript();
656 if(
657 (change & CHANGED_REGION_START) ||
658 (change & CHANGED_REGION)) {
659 state on;
660 }
661 }
662 state_exit() {
663 llSetTimerEvent(0);
664 }
665 }