/source/puppeteer-pathfinding/puppeteer-pathfinding.lsl |
@@ -1,5 +1,5 @@ |
/////////////////////////////////////////////////////////////////////////// |
// Copyright (C) Wizardry and Steamworks 2014 - License: CC BY 2.0 // |
// Copyright (C) Wizardry and Steamworks 2014 - License: GNU GPLv3 // |
/////////////////////////////////////////////////////////////////////////// |
// |
// This is a puppeteer script for the Corrade Second Life / OpenSim bot |
@@ -6,45 +6,48 @@ |
// that, given a set of local coordinates, will make the bot traverse a |
// path while also minding collisions with object. You can find more |
// details about the Corrade bot and how to get it to work on your machine |
// by following the URL: http://grimore.org/secondlife/scripted_agents/corrade |
// by following the URL: http://was.fm/secondlife/scripted_agents/corrade |
// |
// This script works together with a "configuration" notecard that must |
// be placed in the same primitive as this script. The purpose of this |
// script is to demonstrate how Corrade can be made to walk on a path and |
// you are free to use, change, and commercialize it under the CC BY 2.0 |
// license at: https://creativecommons.org/licenses/by/2.0 |
// you are free to use, change, and commercialize it under the GNU/GPLv3 |
// license at: http://www.gnu.org/licenses/gpl.html |
// |
/////////////////////////////////////////////////////////////////////////// |
|
/////////////////////////////////////////////////////////////////////////// |
// Copyright (C) 2014 Wizardry and Steamworks - License: CC BY 2.0 // |
// Copyright (C) 2013 Wizardry and Steamworks - License: GNU GPLv3 // |
/////////////////////////////////////////////////////////////////////////// |
string wasKeyValueGet(string k, string data) { |
if(llStringLength(data) == 0) return ""; |
if(llStringLength(k) == 0) return ""; |
list a = llParseString2List(data, ["&", "="], []); |
integer i = llListFindList(a, [ k ]); |
if(i != -1) return llList2String(a, i+1); |
string wasKeyValueGet(string var, string kvp) { |
list dVars = llParseString2List(kvp, ["&"], []); |
do { |
list data = llParseString2List(llList2String(dVars, 0), ["="], []); |
string k = llList2String(data, 0); |
if(k != var) jump continue; |
return llList2String(data, 1); |
@continue; |
dVars = llDeleteSubList(dVars, 0, 0); |
} while(llGetListLength(dVars)); |
return ""; |
} |
|
|
/////////////////////////////////////////////////////////////////////////// |
// Copyright (C) 2013 Wizardry and Steamworks - License: CC BY 2.0 // |
// Copyright (C) 2013 Wizardry and Steamworks - License: GNU GPLv3 // |
/////////////////////////////////////////////////////////////////////////// |
string wasKeyValueEncode(list data) { |
list k = llList2ListStrided(data, 0, -1, 2); |
list v = llList2ListStrided(llDeleteSubList(data, 0, 0), 0, -1, 2); |
data = []; |
do { |
data += llList2String(k, 0) + "=" + llList2String(v, 0); |
k = llDeleteSubList(k, 0, 0); |
v = llDeleteSubList(v, 0, 0); |
} while(llGetListLength(k) != 0); |
return llDumpList2String(data, "&"); |
string wasKeyValueEncode(list kvp) { |
if(llGetListLength(kvp) < 2) return ""; |
string k = llList2String(kvp, 0); |
kvp = llDeleteSubList(kvp, 0, 0); |
string v = llList2String(kvp, 0); |
kvp = llDeleteSubList(kvp, 0, 0); |
if(llGetListLength(kvp) < 2) return k + "=" + v; |
return k + "=" + v + "&" + wasKeyValueEncode(kvp); |
} |
|
|
/////////////////////////////////////////////////////////////////////////// |
// Copyright (C) 2015 Wizardry and Steamworks - License: CC BY 2.0 // |
// Copyright (C) 2015 Wizardry and Steamworks - License: GNU GPLv3 // |
/////////////////////////////////////////////////////////////////////////// |
// escapes a string in conformance with RFC1738 |
string wasURLEscape(string i) { |
@@ -68,7 +71,7 @@ |
} |
|
/////////////////////////////////////////////////////////////////////////// |
// Copyright (C) 2015 Wizardry and Steamworks - License: CC BY 2.0 // |
// Copyright (C) 2015 Wizardry and Steamworks - License: GNU GPLv3 // |
/////////////////////////////////////////////////////////////////////////// |
// unescapes a string in conformance with RFC1738 |
string wasURLUnescape(string i) { |
@@ -90,9 +93,8 @@ |
) |
); |
} |
|
/////////////////////////////////////////////////////////////////////////// |
// Copyright (C) 2015 Wizardry and Steamworks - License: CC BY 2.0 // |
// Copyright (C) 2015 Wizardry and Steamworks - License: GNU GPLv3 // |
/////////////////////////////////////////////////////////////////////////// |
list wasCSVToList(string csv) { |
list l = []; |
@@ -344,7 +346,7 @@ |
// DEBUG |
llOwnerSay("Binding to the collision notification..."); |
llInstantMessage( |
(key)CORRADE, |
CORRADE, |
wasKeyValueEncode( |
[ |
"command", "notify", |
@@ -469,26 +471,28 @@ |
PATH = llDeleteSubList(PATH, 0, 0); |
PATH += next; |
|
// We now determine the waiting time for Corrade to reach |
// its next destination by extracting time as a function |
// of the distance it has to walk and the speed of travel: |
// t = s / v |
// This, of course, is prone to error since the distance |
// is calculated on the shortest direct path. Nevertheless, |
// it is a pretty good appoximation for terrain that is |
// mostly flat and without too many curvatures. |
// NB. 3.20 m/s is the walking speed of an avatar. |
llInstantMessage(CORRADE, |
wasKeyValueEncode( |
[ |
"command", "autopilot", |
"command", "walkto", |
"group", wasURLEscape(GROUP), |
"password", wasURLEscape(PASSWORD), |
"position", next, |
"action", "start" |
"vicinity", "1", |
"timeout", llVecDist(origin, next)/3.20 |
] |
) |
); |
// We now determine the waiting time for Corrade to reach |
// its next destination by extracting time as a function |
// of the distance it has to walk and the speed of travel: |
// t = s / v |
// This, of course, is prone to error since the distance |
// is calculated on the shortest direct path. Nevertheless, |
// it is a pretty good appoximation for terrain that is |
// mostly flat and without too many curvatures. |
// NB. 3.20 m/s is the walking speed of an avatar. |
|
llSetTimerEvent(llVecDist(origin, next)/3.20); |
} |
http_request(key id, string method, string body) { |
@@ -501,17 +505,7 @@ |
llOwnerSay("Collided..."); |
|
llHTTPResponse(id, 200, "OK"); |
|
llInstantMessage(CORRADE, |
wasKeyValueEncode( |
[ |
"command", "autopilot", |
"group", wasURLEscape(GROUP), |
"password", wasURLEscape(PASSWORD), |
"action", "stop" |
] |
) |
); |
|
// We did not reach our destination since we collided with |
// something on our path, so switch directly to waiting and |
// attempt to reach the next destination on our path. |