corrade-lsl-templates – Blame information for rev 32

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() {
394 // DEBUG
395 llOwnerSay("Stopping autopilot for flight...");
396 llRegionSayTo(
397 (key)wasKeyValueGet(
398 "corrade",
399 configuration
400 ),
401 0,
402 wasKeyValueEncode(
403 [
404 "command", "autopilot",
405 "group", wasURLEscape(
406 wasKeyValueGet(
407 "group",
408 configuration
409 )
410 ),
411 "password", wasURLEscape(
412 wasKeyValueGet(
413 "password",
414 configuration
415 )
416 ),
417 // move in a radius around the current primitive.
418 "position", llGetPos() + wasCirclePoint(
419 (integer)wasURLEscape(
420 wasKeyValueGet(
421 "range",
422 configuration
423 )
424 )
425 ),
426 "action", "stop",
427 "callback", wasURLEscape(callback)
428 ]
429 )
430 );
431 llSetTimerEvent(60);
432 }
433 timer() {
434 state on;
435 }
436 touch_end(integer num) {
437 llSetColor(<.5,0,0>, ALL_SIDES);
438 llResetScript();
439 }
440 http_request(key id, string method, string body) {
441 llHTTPResponse(id, 200, "OK");
442 if(wasKeyValueGet("command", body) != "autopilot" ||
443 wasKeyValueGet("success", body) != "True") {
444 // DEBUG
445 llOwnerSay("Failed to stop autopilot...");
446 state on;
447 }
448 state fly;
449 }
450 attach(key id) {
451 llResetScript();
452 }
453 on_rez(integer num) {
454 llResetScript();
455 }
456 changed(integer change) {
457 if(change & CHANGED_INVENTORY || (change & CHANGED_OWNER))
458 llResetScript();
459 if(
460 (change & CHANGED_REGION_START) ||
461 (change & CHANGED_REGION)) {
462 state on;
463 }
464 }
465 state_exit() {
466 llSetTimerEvent(0);
467 }
468 }
469  
470 state fly {
471 state_entry() {
472 // DEBUG
473 llOwnerSay("Flying to agent...");
474 llRegionSayTo(
475 (key)wasKeyValueGet(
476 "corrade",
477 configuration
478 ),
479 0,
480 wasKeyValueEncode(
481 [
482 "command", "flyto",
483 "group", wasURLEscape(
484 wasKeyValueGet(
485 "group",
486 configuration
487 )
488 ),
489 "password", wasURLEscape(
490 wasKeyValueGet(
491 "password",
492 configuration
493 )
494 ),
495 // move in a radius around the current primitive.
496 "position", llGetPos() + wasCirclePoint(
497 (integer)wasURLEscape(
498 wasKeyValueGet(
499 "range",
500 configuration
501 )
502 )
503 ),
504 "fly", "True",
505 "vicinity", wasCirclePoint(
506 (integer)wasURLEscape(
507 wasKeyValueGet(
508 "range",
509 configuration
510 )
511 )
512 ),
513 "duration", "2500",
514 "callback", wasURLEscape(callback)
515 ]
516 )
517 );
518 llSetTimerEvent(60);
519 }
520 timer() {
521 state on;
522 }
523 touch_end(integer num) {
524 llSetColor(<.5,0,0>, ALL_SIDES);
525 llResetScript();
526 }
527 http_request(key id, string method, string body) {
528 llHTTPResponse(id, 200, "OK");
529 if(wasKeyValueGet("command", body) != "flyto" ||
530 wasKeyValueGet("success", body) != "True") {
531 // DEBUG
532 llOwnerSay("Flight failed...");
533 state on;
534 }
535 state select;
536 }
537 attach(key id) {
538 llResetScript();
539 }
540 on_rez(integer num) {
541 llResetScript();
542 }
543 changed(integer change) {
544 if(change & CHANGED_INVENTORY || (change & CHANGED_OWNER))
545 llResetScript();
546 if(
547 (change & CHANGED_REGION_START) ||
548 (change & CHANGED_REGION)) {
549 state on;
550 }
551 }
552 state_exit() {
553 llSetTimerEvent(0);
554 }
555 }
556  
557 state stop_flight {
558 state_entry() {
559 // DEBUG
560 llOwnerSay("Landing agent for walking...");
561 llRegionSayTo(
562 wasKeyValueGet(
563 "corrade",
564 configuration
565 ),
566 0,
567 wasKeyValueEncode(
568 [
569 "command", "fly",
570 "group", wasURLEscape(
571 wasKeyValueGet(
572 "group",
573 configuration
574 )
575 ),
576 "password", wasURLEscape(
577 wasKeyValueGet(
578 "password",
579 configuration
580 )
581 ),
582 "action", "stop",
583 "callback", wasURLEscape(callback)
584 ]
585 )
586 );
587 llSetTimerEvent(60);
588 }
589 timer() {
590 state on;
591 }
592 touch_end(integer num) {
593 llSetColor(<.5,0,0>, ALL_SIDES);
594 llResetScript();
595 }
596 http_request(key id, string method, string body) {
597 llHTTPResponse(id, 200, "OK");
598 if(wasKeyValueGet("command", body) != "fly" ||
599 wasKeyValueGet("success", body) != "True") {
600 // DEBUG
601 llOwnerSay("Landing failed...");
602 state on;
603 }
604 llOwnerSay("Landed...");
605 state walk;
606 }
607 attach(key id) {
608 llResetScript();
609 }
610 on_rez(integer num) {
611 llResetScript();
612 }
613 changed(integer change) {
614 if(change & CHANGED_INVENTORY || (change & CHANGED_OWNER))
615 llResetScript();
616 if(
617 (change & CHANGED_REGION_START) ||
618 (change & CHANGED_REGION)) {
619 state on;
620 }
621 }
622 state_exit() {
623 llSetTimerEvent(0);
624 }
625 }
626  
627 state walk {
628 state_entry() {
629 // DEBUG
630 llOwnerSay("Walking to agent...");
631 llRegionSayTo(
632 (key)wasKeyValueGet(
633 "corrade",
634 configuration
635 ),
636 0,
637 wasKeyValueEncode(
638 [
639 "command", "autopilot",
640 "group", wasURLEscape(
641 wasKeyValueGet(
642 "group",
643 configuration
644 )
645 ),
646 "password", wasURLEscape(
647 wasKeyValueGet(
648 "password",
649 configuration
650 )
651 ),
652 // move in a radius around the current primitive.
653 "position", llGetPos() + wasCirclePoint(
654 (integer)wasURLEscape(
655 wasKeyValueGet(
656 "range",
657 configuration
658 )
659 )
660 ),
661 "action", "start",
662 "callback", wasURLEscape(callback)
663 ]
664 )
665 );
666 llSetTimerEvent(60);
667 }
668 timer() {
669 state on;
670 }
671 touch_end(integer num) {
672 llSetColor(<.5,0,0>, ALL_SIDES);
673 llResetScript();
674 }
675 http_request(key id, string method, string body) {
676 llHTTPResponse(id, 200, "OK");
677 if(wasKeyValueGet("command", body) != "autopilot" ||
678 wasKeyValueGet("success", body) != "True") {
679 // DEBUG
680 llOwnerSay("Failed to start autopilot...");
681 state on;
682 }
683 state select;
684 }
685 attach(key id) {
686 llResetScript();
687 }
688 on_rez(integer num) {
689 llResetScript();
690 }
691 changed(integer change) {
692 if(change & CHANGED_INVENTORY || (change & CHANGED_OWNER))
693 llResetScript();
694 if(
695 (change & CHANGED_REGION_START) ||
696 (change & CHANGED_REGION)) {
697 state on;
698 }
699 }
700 state_exit() {
701 llSetTimerEvent(0);
702 }
703 }