corrade-lsl-templates – Diff between revs 29 and 37
?pathlinks?
Rev 29 | Rev 37 | |||
---|---|---|---|---|
Line 1... | Line 1... | |||
1 | /////////////////////////////////////////////////////////////////////////// |
1 | /////////////////////////////////////////////////////////////////////////// |
|
2 | // Copyright (C) Wizardry and Steamworks 2014 - License: CC BY 2.0 // |
2 | // Copyright (C) Wizardry and Steamworks 2014 - License: GNU GPLv3 // |
|
3 | /////////////////////////////////////////////////////////////////////////// |
3 | /////////////////////////////////////////////////////////////////////////// |
|
4 | // |
4 | // |
|
5 | // This is a puppeteer script for the Corrade Second Life / OpenSim bot |
5 | // This is a puppeteer script for the Corrade Second Life / OpenSim bot |
|
6 | // that, given a set of local coordinates, will make the bot traverse a |
6 | // that, given a set of local coordinates, will make the bot traverse a |
|
7 | // path while also minding collisions with object. You can find more |
7 | // path while also minding collisions with object. You can find more |
|
8 | // details about the Corrade bot and how to get it to work on your machine |
8 | // details about the Corrade bot and how to get it to work on your machine |
|
9 | // by following the URL: http://grimore.org/secondlife/scripted_agents/corrade |
9 | // by following the URL: http://was.fm/secondlife/scripted_agents/corrade |
|
10 | // |
10 | // |
|
11 | // This script works together with a "configuration" notecard that must |
11 | // This script works together with a "configuration" notecard that must |
|
12 | // be placed in the same primitive as this script. The purpose of this |
12 | // be placed in the same primitive as this script. The purpose of this |
|
13 | // script is to demonstrate how Corrade can be made to walk on a path and |
13 | // script is to demonstrate how Corrade can be made to walk on a path and |
|
14 | // you are free to use, change, and commercialize it under the CC BY 2.0 |
14 | // you are free to use, change, and commercialize it under the GNU/GPLv3 |
|
15 | // license at: https://creativecommons.org/licenses/by/2.0 |
15 | // license at: http://www.gnu.org/licenses/gpl.html |
|
16 | // |
16 | // |
|
17 | /////////////////////////////////////////////////////////////////////////// |
17 | /////////////////////////////////////////////////////////////////////////// |
|
Line 18... | Line 18... | |||
18 | |
18 | |
|
19 | /////////////////////////////////////////////////////////////////////////// |
19 | /////////////////////////////////////////////////////////////////////////// |
|
20 | // Copyright (C) 2014 Wizardry and Steamworks - License: CC BY 2.0 // |
20 | // Copyright (C) 2013 Wizardry and Steamworks - License: GNU GPLv3 // |
|
21 | /////////////////////////////////////////////////////////////////////////// |
21 | /////////////////////////////////////////////////////////////////////////// |
|
- | 22 | string wasKeyValueGet(string var, string kvp) { |
||
- | 23 | list dVars = llParseString2List(kvp, ["&"], []); |
||
- | 24 | do { |
||
22 | string wasKeyValueGet(string k, string data) { |
25 | list data = llParseString2List(llList2String(dVars, 0), ["="], []); |
|
23 | if(llStringLength(data) == 0) return ""; |
26 | string k = llList2String(data, 0); |
|
24 | if(llStringLength(k) == 0) return ""; |
27 | if(k != var) jump continue; |
|
- | 28 | return llList2String(data, 1); |
||
25 | list a = llParseString2List(data, ["&", "="], []); |
29 | @continue; |
|
26 | integer i = llListFindList(a, [ k ]); |
30 | dVars = llDeleteSubList(dVars, 0, 0); |
|
27 | if(i != -1) return llList2String(a, i+1); |
31 | } while(llGetListLength(dVars)); |
|
28 | return ""; |
32 | return ""; |
|
29 | } |
33 | } |
|
30 | |
34 | |
|
31 | /////////////////////////////////////////////////////////////////////////// |
35 | /////////////////////////////////////////////////////////////////////////// |
|
32 | // Copyright (C) 2013 Wizardry and Steamworks - License: CC BY 2.0 // |
36 | // Copyright (C) 2013 Wizardry and Steamworks - License: GNU GPLv3 // |
|
33 | /////////////////////////////////////////////////////////////////////////// |
37 | /////////////////////////////////////////////////////////////////////////// |
|
34 | string wasKeyValueEncode(list data) { |
38 | string wasKeyValueEncode(list kvp) { |
|
35 | list k = llList2ListStrided(data, 0, -1, 2); |
39 | if(llGetListLength(kvp) < 2) return ""; |
|
36 | list v = llList2ListStrided(llDeleteSubList(data, 0, 0), 0, -1, 2); |
- | ||
37 | data = []; |
- | ||
38 | do { |
40 | string k = llList2String(kvp, 0); |
|
39 | data += llList2String(k, 0) + "=" + llList2String(v, 0); |
41 | kvp = llDeleteSubList(kvp, 0, 0); |
|
40 | k = llDeleteSubList(k, 0, 0); |
42 | string v = llList2String(kvp, 0); |
|
41 | v = llDeleteSubList(v, 0, 0); |
43 | kvp = llDeleteSubList(kvp, 0, 0); |
|
42 | } while(llGetListLength(k) != 0); |
44 | if(llGetListLength(kvp) < 2) return k + "=" + v; |
|
43 | return llDumpList2String(data, "&"); |
45 | return k + "=" + v + "&" + wasKeyValueEncode(kvp); |
|
Line -... | Line 46... | |||
- | 46 | } |
||
44 | } |
47 | |
|
45 | |
48 | |
|
46 | /////////////////////////////////////////////////////////////////////////// |
49 | /////////////////////////////////////////////////////////////////////////// |
|
47 | // Copyright (C) 2015 Wizardry and Steamworks - License: CC BY 2.0 // |
50 | // Copyright (C) 2015 Wizardry and Steamworks - License: GNU GPLv3 // |
|
48 | /////////////////////////////////////////////////////////////////////////// |
51 | /////////////////////////////////////////////////////////////////////////// |
|
49 | // escapes a string in conformance with RFC1738 |
52 | // escapes a string in conformance with RFC1738 |
|
50 | string wasURLEscape(string i) { |
53 | string wasURLEscape(string i) { |
|
Line 66... | Line 69... | |||
66 | } while(i != ""); |
69 | } while(i != ""); |
|
67 | return o; |
70 | return o; |
|
68 | } |
71 | } |
|
Line 69... | Line 72... | |||
69 | |
72 | |
|
70 | /////////////////////////////////////////////////////////////////////////// |
73 | /////////////////////////////////////////////////////////////////////////// |
|
71 | // Copyright (C) 2015 Wizardry and Steamworks - License: CC BY 2.0 // |
74 | // Copyright (C) 2015 Wizardry and Steamworks - License: GNU GPLv3 // |
|
72 | /////////////////////////////////////////////////////////////////////////// |
75 | /////////////////////////////////////////////////////////////////////////// |
|
73 | // unescapes a string in conformance with RFC1738 |
76 | // unescapes a string in conformance with RFC1738 |
|
74 | string wasURLUnescape(string i) { |
77 | string wasURLUnescape(string i) { |
|
75 | return llUnescapeURL( |
78 | return llUnescapeURL( |
|
Line 88... | Line 91... | |||
88 | ), |
91 | ), |
|
89 | "\n" |
92 | "\n" |
|
90 | ) |
93 | ) |
|
91 | ); |
94 | ); |
|
92 | } |
95 | } |
|
93 | |
- | ||
94 | /////////////////////////////////////////////////////////////////////////// |
96 | /////////////////////////////////////////////////////////////////////////// |
|
95 | // Copyright (C) 2015 Wizardry and Steamworks - License: CC BY 2.0 // |
97 | // Copyright (C) 2015 Wizardry and Steamworks - License: GNU GPLv3 // |
|
96 | /////////////////////////////////////////////////////////////////////////// |
98 | /////////////////////////////////////////////////////////////////////////// |
|
97 | list wasCSVToList(string csv) { |
99 | list wasCSVToList(string csv) { |
|
98 | list l = []; |
100 | list l = []; |
|
99 | list s = []; |
101 | list s = []; |
|
100 | string m = ""; |
102 | string m = ""; |
|
Line 342... | Line 344... | |||
342 | state notify { |
344 | state notify { |
|
343 | state_entry() { |
345 | state_entry() { |
|
344 | // DEBUG |
346 | // DEBUG |
|
345 | llOwnerSay("Binding to the collision notification..."); |
347 | llOwnerSay("Binding to the collision notification..."); |
|
346 | llInstantMessage( |
348 | llInstantMessage( |
|
347 | (key)CORRADE, |
349 | CORRADE, |
|
348 | wasKeyValueEncode( |
350 | wasKeyValueEncode( |
|
349 | [ |
351 | [ |
|
350 | "command", "notify", |
352 | "command", "notify", |
|
351 | "group", wasURLEscape(GROUP), |
353 | "group", wasURLEscape(GROUP), |
|
352 | "password", wasURLEscape(PASSWORD), |
354 | "password", wasURLEscape(PASSWORD), |
|
Line 467... | Line 469... | |||
467 | // extract next destination and permute the set |
469 | // extract next destination and permute the set |
|
468 | vector next = (vector)llList2String(PATH, 0); |
470 | vector next = (vector)llList2String(PATH, 0); |
|
469 | PATH = llDeleteSubList(PATH, 0, 0); |
471 | PATH = llDeleteSubList(PATH, 0, 0); |
|
470 | PATH += next; |
472 | PATH += next; |
|
Line 471... | Line -... | |||
471 | |
- | ||
472 | llInstantMessage(CORRADE, |
- | ||
473 | wasKeyValueEncode( |
- | ||
474 | [ |
- | ||
475 | "command", "autopilot", |
- | ||
476 | "group", wasURLEscape(GROUP), |
- | ||
477 | "password", wasURLEscape(PASSWORD), |
- | ||
478 | "position", next, |
- | ||
479 | "action", "start" |
- | ||
480 | ] |
- | ||
481 | ) |
- | ||
482 | ); |
473 | |
|
483 | // We now determine the waiting time for Corrade to reach |
474 | // We now determine the waiting time for Corrade to reach |
|
484 | // its next destination by extracting time as a function |
475 | // its next destination by extracting time as a function |
|
485 | // of the distance it has to walk and the speed of travel: |
476 | // of the distance it has to walk and the speed of travel: |
|
486 | // t = s / v |
477 | // t = s / v |
|
487 | // This, of course, is prone to error since the distance |
478 | // This, of course, is prone to error since the distance |
|
488 | // is calculated on the shortest direct path. Nevertheless, |
479 | // is calculated on the shortest direct path. Nevertheless, |
|
489 | // it is a pretty good appoximation for terrain that is |
480 | // it is a pretty good appoximation for terrain that is |
|
490 | // mostly flat and without too many curvatures. |
481 | // mostly flat and without too many curvatures. |
|
- | 482 | // NB. 3.20 m/s is the walking speed of an avatar. |
||
- | 483 | llInstantMessage(CORRADE, |
||
- | 484 | wasKeyValueEncode( |
||
- | 485 | [ |
||
- | 486 | "command", "walkto", |
||
- | 487 | "group", wasURLEscape(GROUP), |
||
- | 488 | "password", wasURLEscape(PASSWORD), |
||
- | 489 | "position", next, |
||
- | 490 | "vicinity", "1", |
||
- | 491 | "timeout", llVecDist(origin, next)/3.20 |
||
- | 492 | ] |
||
- | 493 | ) |
||
- | 494 | ); |
||
491 | // NB. 3.20 m/s is the walking speed of an avatar. |
495 | |
|
492 | llSetTimerEvent(llVecDist(origin, next)/3.20); |
496 | llSetTimerEvent(llVecDist(origin, next)/3.20); |
|
493 | } |
497 | } |
|
494 | http_request(key id, string method, string body) { |
498 | http_request(key id, string method, string body) { |
|
495 | // since we have bound to the collision notification, |
499 | // since we have bound to the collision notification, |
|
Line 499... | Line 503... | |||
499 | |
503 | |
|
500 | // DEBUG |
504 | // DEBUG |
|
Line 501... | Line 505... | |||
501 | llOwnerSay("Collided..."); |
505 | llOwnerSay("Collided..."); |
|
502 | |
506 | |
|
503 | llHTTPResponse(id, 200, "OK"); |
- | ||
504 | |
- | ||
505 | llInstantMessage(CORRADE, |
- | ||
506 | wasKeyValueEncode( |
- | ||
507 | [ |
- | ||
508 | "command", "autopilot", |
- | ||
509 | "group", wasURLEscape(GROUP), |
- | ||
510 | "password", wasURLEscape(PASSWORD), |
- | ||
511 | "action", "stop" |
- | ||
512 | ] |
- | ||
513 | ) |
507 | llHTTPResponse(id, 200, "OK"); |
|
514 | ); |
508 | |
|
515 | // We did not reach our destination since we collided with |
509 | // We did not reach our destination since we collided with |
|
516 | // something on our path, so switch directly to waiting and |
510 | // something on our path, so switch directly to waiting and |
|
517 | // attempt to reach the next destination on our path. |
511 | // attempt to reach the next destination on our path. |