corrade-lsl-templates – Diff between revs 5 and 29

Subversion Repositories:
Rev:
Only display areas with differencesIgnore whitespace
Rev 5 Rev 29
1 /////////////////////////////////////////////////////////////////////////// 1 ///////////////////////////////////////////////////////////////////////////
2 // Copyright (C) Wizardry and Steamworks 2014 - License: GNU GPLv3 // 2 // Copyright (C) Wizardry and Steamworks 2014 - License: CC BY 2.0 //
3 /////////////////////////////////////////////////////////////////////////// 3 ///////////////////////////////////////////////////////////////////////////
4 // 4 //
5 // This is an automatic grid follower for the Corrade Second Life / OpenSim 5 // This is an automatic grid follower for the Corrade Second Life / OpenSim
6 // bot. You can find more details about the bot by following the URL: 6 // bot. You can find more details about the bot by following the URL:
7 // http://was.fm/secondlife/scripted_agents/corrade 7 // http://was.fm/secondlife/scripted_agents/corrade
8 // 8 //
9 // The follower script works together with a "configuration" notecard and 9 // The follower script works together with a "configuration" notecard and
10 // that must be placed in the same primitive as this script. 10 // that must be placed in the same primitive as this script.
11 // You are free to use, change, and commercialize it under the GNU/GPLv3 11 // You are free to use, change, and commercialize it under the CC BY 2.0
12 // license at: http://www.gnu.org/licenses/gpl.html 12 // license at: https://creativecommons.org/licenses/by/2.0
13 // 13 //
14 /////////////////////////////////////////////////////////////////////////// 14 ///////////////////////////////////////////////////////////////////////////
15   15  
16 /////////////////////////////////////////////////////////////////////////// 16 ///////////////////////////////////////////////////////////////////////////
17 // Copyright (C) 2014 Wizardry and Steamworks - License: GNU GPLv3 // 17 // Copyright (C) 2014 Wizardry and Steamworks - License: CC BY 2.0 //
18 /////////////////////////////////////////////////////////////////////////// 18 ///////////////////////////////////////////////////////////////////////////
19 string wasKeyValueGet(string k, string data) { 19 string wasKeyValueGet(string k, string data) {
20 if(llStringLength(data) == 0) return ""; 20 if(llStringLength(data) == 0) return "";
21 if(llStringLength(k) == 0) return ""; 21 if(llStringLength(k) == 0) return "";
22 list a = llParseString2List(data, ["&", "="], []); 22 list a = llParseString2List(data, ["&", "="], []);
23 integer i = llListFindList(a, [ k ]); 23 integer i = llListFindList(a, [ k ]);
24 if(i != -1) return llList2String(a, i+1); 24 if(i != -1) return llList2String(a, i+1);
25 return ""; 25 return "";
26 } 26 }
27 27
28 /////////////////////////////////////////////////////////////////////////// 28 ///////////////////////////////////////////////////////////////////////////
29 // Copyright (C) 2013 Wizardry and Steamworks - License: GNU GPLv3 // 29 // Copyright (C) 2013 Wizardry and Steamworks - License: CC BY 2.0 //
30 /////////////////////////////////////////////////////////////////////////// 30 ///////////////////////////////////////////////////////////////////////////
31 string wasKeyValueEncode(list data) { 31 string wasKeyValueEncode(list data) {
32 list k = llList2ListStrided(data, 0, -1, 2); 32 list k = llList2ListStrided(data, 0, -1, 2);
33 list v = llList2ListStrided(llDeleteSubList(data, 0, 0), 0, -1, 2); 33 list v = llList2ListStrided(llDeleteSubList(data, 0, 0), 0, -1, 2);
34 data = []; 34 data = [];
35 do { 35 do {
36 data += llList2String(k, 0) + "=" + llList2String(v, 0); 36 data += llList2String(k, 0) + "=" + llList2String(v, 0);
37 k = llDeleteSubList(k, 0, 0); 37 k = llDeleteSubList(k, 0, 0);
38 v = llDeleteSubList(v, 0, 0); 38 v = llDeleteSubList(v, 0, 0);
39 } while(llGetListLength(k) != 0); 39 } while(llGetListLength(k) != 0);
40 return llDumpList2String(data, "&"); 40 return llDumpList2String(data, "&");
41 } 41 }
42   42  
43 /////////////////////////////////////////////////////////////////////////// 43 ///////////////////////////////////////////////////////////////////////////
44 // Copyright (C) 2011 Wizardry and Steamworks - License: GNU GPLv3 // 44 // Copyright (C) 2011 Wizardry and Steamworks - License: CC BY 2.0 //
45 /////////////////////////////////////////////////////////////////////////// 45 ///////////////////////////////////////////////////////////////////////////
46 vector wasCirclePoint(float radius) { 46 vector wasCirclePoint(float radius) {
47 float x = llPow(-1, 1 + (integer) llFrand(2)) * llFrand(radius*2); 47 float x = llPow(-1, 1 + (integer) llFrand(2)) * llFrand(radius*2);
48 float y = llPow(-1, 1 + (integer) llFrand(2)) * llFrand(radius*2); 48 float y = llPow(-1, 1 + (integer) llFrand(2)) * llFrand(radius*2);
49 if(llPow(x,2) + llPow(y,2) <= llPow(radius,2)) 49 if(llPow(x,2) + llPow(y,2) <= llPow(radius,2))
50 return <x, y, 0>; 50 return <x, y, 0>;
51 return wasCirclePoint(radius); 51 return wasCirclePoint(radius);
52 } 52 }
53   53  
54 /////////////////////////////////////////////////////////////////////////// 54 ///////////////////////////////////////////////////////////////////////////
55 // Copyright (C) 2014 Wizardry and Steamworks - License: GNU GPLv3 // 55 // Copyright (C) 2014 Wizardry and Steamworks - License: CC BY 2.0 //
56 /////////////////////////////////////////////////////////////////////////// 56 ///////////////////////////////////////////////////////////////////////////
57 integer wasIsAvatarInSensorRange(key avatar) { 57 integer wasIsAvatarInSensorRange(key avatar) {
58 return llListFindList( 58 return llListFindList(
59 llGetAgentList( 59 llGetAgentList(
60 AGENT_LIST_REGION, 60 AGENT_LIST_REGION,
61 [] 61 []
62 ), 62 ),
63 (list)((key)avatar) 63 (list)((key)avatar)
64 ) != -1 && 64 ) != -1 &&
65 llVecDist( 65 llVecDist(
66 llGetPos(), 66 llGetPos(),
67 llList2Vector( 67 llList2Vector(
68 llGetObjectDetails( 68 llGetObjectDetails(
69 avatar, 69 avatar,
70 [OBJECT_POS] 70 [OBJECT_POS]
71 ), 71 ),
72 0 72 0
73 ) 73 )
74 ) <= 96; 74 ) <= 96;
75 } 75 }
76   76  
77 /////////////////////////////////////////////////////////////////////////// 77 ///////////////////////////////////////////////////////////////////////////
78 // Copyright (C) 2015 Wizardry and Steamworks - License: GNU GPLv3 // 78 // Copyright (C) 2015 Wizardry and Steamworks - License: CC BY 2.0 //
79 /////////////////////////////////////////////////////////////////////////// 79 ///////////////////////////////////////////////////////////////////////////
80 // escapes a string in conformance with RFC1738 80 // escapes a string in conformance with RFC1738
81 string wasURLEscape(string i) { 81 string wasURLEscape(string i) {
82 string o = ""; 82 string o = "";
83 do { 83 do {
84 string c = llGetSubString(i, 0, 0); 84 string c = llGetSubString(i, 0, 0);
85 i = llDeleteSubString(i, 0, 0); 85 i = llDeleteSubString(i, 0, 0);
86 if(c == "") jump continue; 86 if(c == "") jump continue;
87 if(c == " ") { 87 if(c == " ") {
88 o += "+"; 88 o += "+";
89 jump continue; 89 jump continue;
90 } 90 }
91 if(c == "\n") { 91 if(c == "\n") {
92 o += "%0D" + llEscapeURL(c); 92 o += "%0D" + llEscapeURL(c);
93 jump continue; 93 jump continue;
94 } 94 }
95 o += llEscapeURL(c); 95 o += llEscapeURL(c);
96 @continue; 96 @continue;
97 } while(i != ""); 97 } while(i != "");
98 return o; 98 return o;
99 } 99 }
100   100  
101 // corrade data 101 // corrade data
102 string CORRADE = ""; 102 string CORRADE = "";
103 string GROUP = ""; 103 string GROUP = "";
104 string PASSWORD = ""; 104 string PASSWORD = "";
105 string RANGE = ""; 105 string RANGE = "";
106   106  
107 // for holding the callback URL 107 // for holding the callback URL
108 string callback = ""; 108 string callback = "";
109   109  
110 // for notecard reading 110 // for notecard reading
111 integer line = 0; 111 integer line = 0;
112 112
113 // key-value data will be read into this list 113 // key-value data will be read into this list
114 list tuples = []; 114 list tuples = [];
115 115
116 default { 116 default {
117 state_entry() { 117 state_entry() {
118 // set color for button 118 // set color for button
119 llSetColor(<1,1,0>, ALL_SIDES); 119 llSetColor(<1,1,0>, ALL_SIDES);
120 if(llGetInventoryType("configuration") != INVENTORY_NOTECARD) { 120 if(llGetInventoryType("configuration") != INVENTORY_NOTECARD) {
121 llOwnerSay("Sorry, could not find an inventory notecard."); 121 llOwnerSay("Sorry, could not find an inventory notecard.");
122 return; 122 return;
123 } 123 }
124 // DEBUG 124 // DEBUG
125 llOwnerSay("Reading configuration file..."); 125 llOwnerSay("Reading configuration file...");
126 llGetNotecardLine("configuration", line); 126 llGetNotecardLine("configuration", line);
127 } 127 }
128 dataserver(key id, string data) { 128 dataserver(key id, string data) {
129 if(data == EOF) { 129 if(data == EOF) {
130 // invariant, length(tuples) % 2 == 0 130 // invariant, length(tuples) % 2 == 0
131 if(llGetListLength(tuples) % 2 != 0) { 131 if(llGetListLength(tuples) % 2 != 0) {
132 llOwnerSay("Error in configuration notecard."); 132 llOwnerSay("Error in configuration notecard.");
133 return; 133 return;
134 } 134 }
135 CORRADE = llList2String( 135 CORRADE = llList2String(
136 tuples, 136 tuples,
137 llListFindList( 137 llListFindList(
138 tuples, 138 tuples,
139 [ 139 [
140 "corrade" 140 "corrade"
141 ] 141 ]
142 ) 142 )
143 +1); 143 +1);
144 if(CORRADE == "") { 144 if(CORRADE == "") {
145 llOwnerSay("Error in configuration notecard: corrade"); 145 llOwnerSay("Error in configuration notecard: corrade");
146 return; 146 return;
147 } 147 }
148 GROUP = llList2String( 148 GROUP = llList2String(
149 tuples, 149 tuples,
150 llListFindList( 150 llListFindList(
151 tuples, 151 tuples,
152 [ 152 [
153 "group" 153 "group"
154 ] 154 ]
155 ) 155 )
156 +1); 156 +1);
157 if(GROUP == "") { 157 if(GROUP == "") {
158 llOwnerSay("Error in configuration notecard: password"); 158 llOwnerSay("Error in configuration notecard: password");
159 return; 159 return;
160 } 160 }
161 PASSWORD = llList2String( 161 PASSWORD = llList2String(
162 tuples, 162 tuples,
163 llListFindList( 163 llListFindList(
164 tuples, 164 tuples,
165 [ 165 [
166 "password" 166 "password"
167 ] 167 ]
168 ) 168 )
169 +1); 169 +1);
170 if(GROUP == "") { 170 if(GROUP == "") {
171 llOwnerSay("Error in configuration notecard: group"); 171 llOwnerSay("Error in configuration notecard: group");
172 return; 172 return;
173 } 173 }
174 RANGE = llList2String( 174 RANGE = llList2String(
175 tuples, 175 tuples,
176 llListFindList( 176 llListFindList(
177 tuples, 177 tuples,
178 [ 178 [
179 "range" 179 "range"
180 ] 180 ]
181 ) 181 )
182 +1); 182 +1);
183 if(RANGE == "") { 183 if(RANGE == "") {
184 llOwnerSay("Error in configuration notecard: range"); 184 llOwnerSay("Error in configuration notecard: range");
185 return; 185 return;
186 } 186 }
187 // DEBUG 187 // DEBUG
188 llOwnerSay("Read configuration file..."); 188 llOwnerSay("Read configuration file...");
189 state url; 189 state url;
190 } 190 }
191 if(data == "") jump continue; 191 if(data == "") jump continue;
192 integer i = llSubStringIndex(data, "#"); 192 integer i = llSubStringIndex(data, "#");
193 if(i != -1) data = llDeleteSubString(data, i, -1); 193 if(i != -1) data = llDeleteSubString(data, i, -1);
194 list o = llParseString2List(data, ["="], []); 194 list o = llParseString2List(data, ["="], []);
195 // get rid of starting and ending quotes 195 // get rid of starting and ending quotes
196 string k = llDumpList2String( 196 string k = llDumpList2String(
197 llParseString2List( 197 llParseString2List(
198 llStringTrim( 198 llStringTrim(
199 llList2String( 199 llList2String(
200 o, 200 o,
201 0 201 0
202 ), 202 ),
203 STRING_TRIM), 203 STRING_TRIM),
204 ["\""], [] 204 ["\""], []
205 ), "\""); 205 ), "\"");
206 string v = llDumpList2String( 206 string v = llDumpList2String(
207 llParseString2List( 207 llParseString2List(
208 llStringTrim( 208 llStringTrim(
209 llList2String( 209 llList2String(
210 o, 210 o,
211 1 211 1
212 ), 212 ),
213 STRING_TRIM), 213 STRING_TRIM),
214 ["\""], [] 214 ["\""], []
215 ), "\""); 215 ), "\"");
216 if(k == "" || v == "") jump continue; 216 if(k == "" || v == "") jump continue;
217 tuples += k; 217 tuples += k;
218 tuples += v; 218 tuples += v;
219 @continue; 219 @continue;
220 llGetNotecardLine("configuration", ++line); 220 llGetNotecardLine("configuration", ++line);
221 } 221 }
222 on_rez(integer num) { 222 on_rez(integer num) {
223 llResetScript(); 223 llResetScript();
224 } 224 }
225 changed(integer change) { 225 changed(integer change) {
226 if((change & CHANGED_INVENTORY) || (change & CHANGED_REGION_START)) { 226 if((change & CHANGED_INVENTORY) || (change & CHANGED_REGION_START)) {
227 llResetScript(); 227 llResetScript();
228 } 228 }
229 } 229 }
230 } 230 }
231 231
232 state url { 232 state url {
233 state_entry() { 233 state_entry() {
234 // DEBUG 234 // DEBUG
235 llOwnerSay("Requesting URL..."); 235 llOwnerSay("Requesting URL...");
236 llRequestURL(); 236 llRequestURL();
237 } 237 }
238 http_request(key id, string method, string body) { 238 http_request(key id, string method, string body) {
239 if(method != URL_REQUEST_GRANTED) return; 239 if(method != URL_REQUEST_GRANTED) return;
240 callback = body; 240 callback = body;
241 // DEBUG 241 // DEBUG
242 llOwnerSay("Got URL..."); 242 llOwnerSay("Got URL...");
243 state off; 243 state off;
244 } 244 }
245 on_rez(integer num) { 245 on_rez(integer num) {
246 llResetScript(); 246 llResetScript();
247 } 247 }
248 changed(integer change) { 248 changed(integer change) {
249 if((change & CHANGED_INVENTORY) || (change & CHANGED_REGION_START)) { 249 if((change & CHANGED_INVENTORY) || (change & CHANGED_REGION_START)) {
250 llResetScript(); 250 llResetScript();
251 } 251 }
252 } 252 }
253 } 253 }
254   254  
255 state off { 255 state off {
256 state_entry() { 256 state_entry() {
257 // set color for button 257 // set color for button
258 llSetColor(<1,0,0>, ALL_SIDES); 258 llSetColor(<1,0,0>, ALL_SIDES);
259 } 259 }
260 touch_start(integer num) { 260 touch_start(integer num) {
261 state on; 261 state on;
262 } 262 }
263 on_rez(integer num) { 263 on_rez(integer num) {
264 llResetScript(); 264 llResetScript();
265 } 265 }
266 changed(integer change) { 266 changed(integer change) {
267 if((change & CHANGED_INVENTORY) || (change & CHANGED_REGION_START)) { 267 if((change & CHANGED_INVENTORY) || (change & CHANGED_REGION_START)) {
268 llResetScript(); 268 llResetScript();
269 } 269 }
270 } 270 }
271 } 271 }
272 272
273 state on { 273 state on {
274 state_entry() { 274 state_entry() {
275 // set color for button 275 // set color for button
276 llSetColor(<0,1,0>, ALL_SIDES); 276 llSetColor(<0,1,0>, ALL_SIDES);
277 // if Corrade is in-range then just follow 277 // if Corrade is in-range then just follow
278 if(wasIsAvatarInSensorRange(CORRADE)) state follow; 278 if(wasIsAvatarInSensorRange(CORRADE)) state follow;
279 // DEBUG 279 // DEBUG
280 llOwnerSay("Detecting if Corrade is online..."); 280 llOwnerSay("Detecting if Corrade is online...");
281 llSetTimerEvent(5); 281 llSetTimerEvent(5);
282 } 282 }
283 timer() { 283 timer() {
284 llRequestAgentData((key)CORRADE, DATA_ONLINE); 284 llRequestAgentData((key)CORRADE, DATA_ONLINE);
285 } 285 }
286 dataserver(key id, string data) { 286 dataserver(key id, string data) {
287 if(data != "1") { 287 if(data != "1") {
288 // DEBUG 288 // DEBUG
289 llOwnerSay("Corrade is not online, sleeping..."); 289 llOwnerSay("Corrade is not online, sleeping...");
290 llSetTimerEvent(30); 290 llSetTimerEvent(30);
291 return; 291 return;
292 } 292 }
293 llSensorRepeat("", (key)CORRADE, AGENT, (integer)RANGE, TWO_PI, 5); 293 llSensorRepeat("", (key)CORRADE, AGENT, (integer)RANGE, TWO_PI, 5);
294 } 294 }
295 no_sensor() { 295 no_sensor() {
296 // DEBUG 296 // DEBUG
297 llOwnerSay("Teleporting Corrade..."); 297 llOwnerSay("Teleporting Corrade...");
298 llInstantMessage((key)CORRADE, 298 llInstantMessage((key)CORRADE,
299 wasKeyValueEncode( 299 wasKeyValueEncode(
300 [ 300 [
301 "command", "teleport", 301 "command", "teleport",
302 "group", wasURLEscape(GROUP), 302 "group", wasURLEscape(GROUP),
303 "password", wasURLEscape(PASSWORD), 303 "password", wasURLEscape(PASSWORD),
304 "entity", "region", 304 "entity", "region",
305 "region", wasURLEscape(llGetRegionName()), 305 "region", wasURLEscape(llGetRegionName()),
306 "position", llGetPos() + wasCirclePoint((integer)RANGE), 306 "position", llGetPos() + wasCirclePoint((integer)RANGE),
307 "callback", callback 307 "callback", callback
308 ] 308 ]
309 ) 309 )
310 ); 310 );
311 } 311 }
312 sensor(integer num) { 312 sensor(integer num) {
313 llSetTimerEvent(0); 313 llSetTimerEvent(0);
314 state follow; 314 state follow;
315 } 315 }
316 http_request(key id, string method, string body) { 316 http_request(key id, string method, string body) {
317 llHTTPResponse(id, 200, "OK"); 317 llHTTPResponse(id, 200, "OK");
318 if(wasKeyValueGet("command", body) != "teleport" || 318 if(wasKeyValueGet("command", body) != "teleport" ||
319 wasKeyValueGet("success", body) != "True") { 319 wasKeyValueGet("success", body) != "True") {
320 // DEBUG 320 // DEBUG
321 llOwnerSay("Teleport failed..."); 321 llOwnerSay("Teleport failed...");
322 return; 322 return;
323 } 323 }
324 llSetTimerEvent(0); 324 llSetTimerEvent(0);
325 state follow; 325 state follow;
326 } 326 }
327 on_rez(integer num) { 327 on_rez(integer num) {
328 llResetScript(); 328 llResetScript();
329 } 329 }
330 changed(integer change) { 330 changed(integer change) {
331 if((change & CHANGED_INVENTORY) || (change & CHANGED_REGION_START)) { 331 if((change & CHANGED_INVENTORY) || (change & CHANGED_REGION_START)) {
332 llResetScript(); 332 llResetScript();
333 } 333 }
334 } 334 }
335 } 335 }
336 336
337 state follow { 337 state follow {
338 state_entry() { 338 state_entry() {
339 // DEBUG 339 // DEBUG
340 llOwnerSay("In follow state..."); 340 llOwnerSay("In follow state...");
341 // check every second whether Corrade is online 341 // check every second whether Corrade is online
342 llRequestAgentData(CORRADE, DATA_ONLINE); 342 llRequestAgentData(CORRADE, DATA_ONLINE);
343 } 343 }
344 touch_start(integer num) { 344 touch_start(integer num) {
345 state off; 345 state off;
346 } 346 }
347 dataserver(key id, string data) { 347 dataserver(key id, string data) {
348 // if Corrade is not online 348 // if Corrade is not online
349 if(data != "1") state on; 349 if(data != "1") state on;
350 // Corrade is online, so attempt to dectect 350 // Corrade is online, so attempt to dectect
351 llSensorRepeat("", CORRADE, AGENT, (integer)RANGE, TWO_PI, 1); 351 llSensorRepeat("", CORRADE, AGENT, (integer)RANGE, TWO_PI, 1);
352 } 352 }
353 no_sensor() { 353 no_sensor() {
354 // check if Corrade is in range, and if not, start detecting 354 // check if Corrade is in range, and if not, start detecting
355 if(!wasIsAvatarInSensorRange(CORRADE)) state on; 355 if(!wasIsAvatarInSensorRange(CORRADE)) state on;
356 // Corrade is in sensor range, so execute move. 356 // Corrade is in sensor range, so execute move.
357 llInstantMessage(CORRADE, 357 llInstantMessage(CORRADE,
358 wasKeyValueEncode( 358 wasKeyValueEncode(
359 [ 359 [
360 "command", "autopilot", 360 "command", "autopilot",
361 "group", wasURLEscape(GROUP), 361 "group", wasURLEscape(GROUP),
362 "password", wasURLEscape(PASSWORD), 362 "password", wasURLEscape(PASSWORD),
363 // move in a radius around the current primitive. 363 // move in a radius around the current primitive.
364 "position", llGetPos() + wasCirclePoint((integer)RANGE), 364 "position", llGetPos() + wasCirclePoint((integer)RANGE),
365 "action", "start" 365 "action", "start"
366 ] 366 ]
367 ) 367 )
368 ); 368 );
369 llSensorRepeat("", CORRADE, AGENT, (integer)RANGE, TWO_PI, 1); 369 llSensorRepeat("", CORRADE, AGENT, (integer)RANGE, TWO_PI, 1);
370 llRequestAgentData(CORRADE, DATA_ONLINE); 370 llRequestAgentData(CORRADE, DATA_ONLINE);
371 } 371 }
372 on_rez(integer num) { 372 on_rez(integer num) {
373 llResetScript(); 373 llResetScript();
374 } 374 }
375 changed(integer change) { 375 changed(integer change) {
376 if((change & CHANGED_INVENTORY) || (change & CHANGED_REGION_START)) { 376 if((change & CHANGED_INVENTORY) || (change & CHANGED_REGION_START)) {
377 llResetScript(); 377 llResetScript();
378 } 378 }
379 } 379 }
380 } 380 }
381   381  
382
Generated by GNU Enscript 1.6.5.90.
382
Generated by GNU Enscript 1.6.5.90.
383   383  
384   384  
385   385