corrade-lsl-templates – Blame information for rev 37

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