corrade-lsl-templates – Blame information for rev 29

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 ),
283 "region", wasURLEscape(llGetRegionName()),
284 "position", llGetPos() + wasCirclePoint(
285 (integer)wasURLEscape(
286 wasKeyValueGet(
287 "range",
288 configuration
289 )
290 )
291 ),
292 "deanimate", "True",
293 "callback", callback
294 ]
295 )
296 );
297 }
298 sensor(integer num) {
299 state select;
300 }
301 http_request(key id, string method, string body) {
302 llHTTPResponse(id, 200, "OK");
303 if(wasKeyValueGet("command", body) != "teleport" ||
304 wasKeyValueGet("success", body) != "True") {
305 // DEBUG
306 llOwnerSay("Teleport failed...");
307 return;
308 }
309 state select;
310 }
311 attach(key id) {
312 llResetScript();
313 }
314 on_rez(integer num) {
315 llResetScript();
316 }
317 changed(integer change) {
318 if(change & CHANGED_INVENTORY || (change & CHANGED_OWNER))
319 llResetScript();
320 if(
321 (change & CHANGED_REGION_START) ||
322 (change & CHANGED_REGION)) {
323 state on;
324 }
325 }
326 }
327  
328 state select {
329 state_entry() {
330 // DEBUG
331 llOwnerSay("Selecting follow engine...");
332 llSetTimerEvent(1);
333 }
334 touch_end(integer num) {
335 llSetColor(<.5,0,0>, ALL_SIDES);
336 llResetScript();
337 }
338 timer() {
339 vector cPos = llList2Vector(
340 llGetObjectDetails(
341 (key)wasKeyValueGet(
342 "corrade",
343 configuration
344 ),
345 [OBJECT_POS]
346 ),
347  
348 );
349 vector mPos = llGetPos();
350 // If Corrade is in range then stop.
351 if(llVecDist(mPos, cPos) < 5) return;
352 // If we are flying or the distance between us and Corrade
353 // is larger than a given distance then make Corrade fly.
354 if(
355 (
356 llGetAgentInfo(llGetOwner()) & AGENT_FLYING
357 ) ||
358 llFabs(mPos.z - cPos.z) > 5) {
359 state stop_pilot;
360 }
361 // Otherwise, stop flight and walk.
362 if(llGetAgentInfo(
363 (key)wasKeyValueGet(
364 "corrade",
365 configuration
366 )
367 ) & AGENT_FLYING) state stop_flight;
368 // If Corrade is not flying then walk.
369 state walk;
370 }
371 attach(key id) {
372 llResetScript();
373 }
374 on_rez(integer num) {
375 llResetScript();
376 }
377 changed(integer change) {
378 if(change & CHANGED_INVENTORY || (change & CHANGED_OWNER))
379 llResetScript();
380 if(
381 (change & CHANGED_REGION_START) ||
382 (change & CHANGED_REGION)) {
383 state on;
384 }
385 }
386 state_exit() {
387 llSetTimerEvent(0);
388 }
389 }
390  
391 state stop_pilot {
392 state_entry() {
393 // DEBUG
394 llOwnerSay("Stopping autopilot for flight...");
395 llRegionSayTo(
396 (key)wasKeyValueGet(
397 "corrade",
398 configuration
399 ),
400 0,
401 wasKeyValueEncode(
402 [
403 "command", "autopilot",
404 "group", wasURLEscape(
405 wasKeyValueGet(
406 "group",
407 configuration
408 )
409 ),
410 "password", wasURLEscape(
411 wasKeyValueGet(
412 "password",
413 configuration
414 )
415 ),
416 // move in a radius around the current primitive.
417 "position", llGetPos() + wasCirclePoint(
418 (integer)wasURLEscape(
419 wasKeyValueGet(
420 "range",
421 configuration
422 )
423 )
424 ),
425 "action", "stop",
426 "callback", wasURLEscape(callback)
427 ]
428 )
429 );
430 llSetTimerEvent(60);
431 }
432 timer() {
433 state on;
434 }
435 touch_end(integer num) {
436 llSetColor(<.5,0,0>, ALL_SIDES);
437 llResetScript();
438 }
439 http_request(key id, string method, string body) {
440 llHTTPResponse(id, 200, "OK");
441 if(wasKeyValueGet("command", body) != "autopilot" ||
442 wasKeyValueGet("success", body) != "True") {
443 // DEBUG
444 llOwnerSay("Failed to stop autopilot...");
445 state on;
446 }
447 state fly;
448 }
449 attach(key id) {
450 llResetScript();
451 }
452 on_rez(integer num) {
453 llResetScript();
454 }
455 changed(integer change) {
456 if(change & CHANGED_INVENTORY || (change & CHANGED_OWNER))
457 llResetScript();
458 if(
459 (change & CHANGED_REGION_START) ||
460 (change & CHANGED_REGION)) {
461 state on;
462 }
463 }
464 state_exit() {
465 llSetTimerEvent(0);
466 }
467 }
468  
469 state fly {
470 state_entry() {
471 // DEBUG
472 llOwnerSay("Flying to agent...");
473 llRegionSayTo(
474 (key)wasKeyValueGet(
475 "corrade",
476 configuration
477 ),
478 0,
479 wasKeyValueEncode(
480 [
481 "command", "flyto",
482 "group", wasURLEscape(
483 wasKeyValueGet(
484 "group",
485 configuration
486 )
487 ),
488 "password", wasURLEscape(
489 wasKeyValueGet(
490 "password",
491 configuration
492 )
493 ),
494 // move in a radius around the current primitive.
495 "position", llGetPos() + wasCirclePoint(
496 (integer)wasURLEscape(
497 wasKeyValueGet(
498 "range",
499 configuration
500 )
501 )
502 ),
503 "fly", "True",
504 "vicinity", wasCirclePoint(
505 (integer)wasURLEscape(
506 wasKeyValueGet(
507 "range",
508 configuration
509 )
510 )
511 ),
512 "duration", "2500",
513 "callback", wasURLEscape(callback)
514 ]
515 )
516 );
517 llSetTimerEvent(60);
518 }
519 timer() {
520 state on;
521 }
522 touch_end(integer num) {
523 llSetColor(<.5,0,0>, ALL_SIDES);
524 llResetScript();
525 }
526 http_request(key id, string method, string body) {
527 llHTTPResponse(id, 200, "OK");
528 if(wasKeyValueGet("command", body) != "flyto" ||
529 wasKeyValueGet("success", body) != "True") {
530 // DEBUG
531 llOwnerSay("Flight failed...");
532 state on;
533 }
534 state select;
535 }
536 attach(key id) {
537 llResetScript();
538 }
539 on_rez(integer num) {
540 llResetScript();
541 }
542 changed(integer change) {
543 if(change & CHANGED_INVENTORY || (change & CHANGED_OWNER))
544 llResetScript();
545 if(
546 (change & CHANGED_REGION_START) ||
547 (change & CHANGED_REGION)) {
548 state on;
549 }
550 }
551 state_exit() {
552 llSetTimerEvent(0);
553 }
554 }
555  
556 state stop_flight {
557 state_entry() {
558 // DEBUG
559 llOwnerSay("Landing agent for walking...");
560 llRegionSayTo(
561 wasKeyValueGet(
562 "corrade",
563 configuration
564 ),
565 0,
566 wasKeyValueEncode(
567 [
568 "command", "fly",
569 "group", wasURLEscape(
570 wasKeyValueGet(
571 "group",
572 configuration
573 )
574 ),
575 "password", wasURLEscape(
576 wasKeyValueGet(
577 "password",
578 configuration
579 )
580 ),
581 "action", "stop",
582 "callback", wasURLEscape(callback)
583 ]
584 )
585 );
586 llSetTimerEvent(60);
587 }
588 timer() {
589 state on;
590 }
591 touch_end(integer num) {
592 llSetColor(<.5,0,0>, ALL_SIDES);
593 llResetScript();
594 }
595 http_request(key id, string method, string body) {
596 llHTTPResponse(id, 200, "OK");
597 if(wasKeyValueGet("command", body) != "fly" ||
598 wasKeyValueGet("success", body) != "True") {
599 // DEBUG
600 llOwnerSay("Landing failed...");
601 state on;
602 }
603 llOwnerSay("Landed...");
604 state walk;
605 }
606 attach(key id) {
607 llResetScript();
608 }
609 on_rez(integer num) {
610 llResetScript();
611 }
612 changed(integer change) {
613 if(change & CHANGED_INVENTORY || (change & CHANGED_OWNER))
614 llResetScript();
615 if(
616 (change & CHANGED_REGION_START) ||
617 (change & CHANGED_REGION)) {
618 state on;
619 }
620 }
621 state_exit() {
622 llSetTimerEvent(0);
623 }
624 }
625  
626 state walk {
627 state_entry() {
628 // DEBUG
629 llOwnerSay("Walking to agent...");
630 llRegionSayTo(
631 (key)wasKeyValueGet(
632 "corrade",
633 configuration
634 ),
635 0,
636 wasKeyValueEncode(
637 [
638 "command", "autopilot",
639 "group", wasURLEscape(
640 wasKeyValueGet(
641 "group",
642 configuration
643 )
644 ),
645 "password", wasURLEscape(
646 wasKeyValueGet(
647 "password",
648 configuration
649 )
650 ),
651 // move in a radius around the current primitive.
652 "position", llGetPos() + wasCirclePoint(
653 (integer)wasURLEscape(
654 wasKeyValueGet(
655 "range",
656 configuration
657 )
658 )
659 ),
660 "action", "start",
661 "callback", wasURLEscape(callback)
662 ]
663 )
664 );
665 llSetTimerEvent(60);
666 }
667 timer() {
668 state on;
669 }
670 touch_end(integer num) {
671 llSetColor(<.5,0,0>, ALL_SIDES);
672 llResetScript();
673 }
674 http_request(key id, string method, string body) {
675 llHTTPResponse(id, 200, "OK");
676 if(wasKeyValueGet("command", body) != "autopilot" ||
677 wasKeyValueGet("success", body) != "True") {
678 // DEBUG
679 llOwnerSay("Failed to start autopilot...");
680 state on;
681 }
682 state select;
683 }
684 attach(key id) {
685 llResetScript();
686 }
687 on_rez(integer num) {
688 llResetScript();
689 }
690 changed(integer change) {
691 if(change & CHANGED_INVENTORY || (change & CHANGED_OWNER))
692 llResetScript();
693 if(
694 (change & CHANGED_REGION_START) ||
695 (change & CHANGED_REGION)) {
696 state on;
697 }
698 }
699 state_exit() {
700 llSetTimerEvent(0);
701 }
702 }