corrade-lsl-templates – Blame information for rev 42

Subversion Repositories:
Rev:
Rev Author Line No. Line
2 office 1 ///////////////////////////////////////////////////////////////////////////
29 office 2 // Copyright (C) Wizardry and Steamworks 2016 - License: CC BY 2.0 //
2 office 3 ///////////////////////////////////////////////////////////////////////////
4 //
5 // This script will make Corrade scan for primitives in the vicinity and
6 // will then offer a dialog for you to pick to which primitive Corrade will
7 // point to. Note that the point effect can only be observed in case the
8 // outfit that Corrade is currently wearing has a proper mapping for arms.
9 //
10 // For more information on Corrade, please see:
11 // http://grimore.org/secondlife/scripted_agents/corrade
12 //
13 ///////////////////////////////////////////////////////////////////////////
14  
15 ///////////////////////////////////////////////////////////////////////////
29 office 16 // Copyright (C) 2014 Wizardry and Steamworks - License: CC BY 2.0 //
2 office 17 ///////////////////////////////////////////////////////////////////////////
18 string wasKeyValueGet(string k, string data) {
19 if(llStringLength(data) == 0) return "";
20 if(llStringLength(k) == 0) return "";
21 list a = llParseString2List(data, ["&", "="], []);
22 integer i = llListFindList(a, [ k ]);
23 if(i != -1) return llList2String(a, i+1);
24 return "";
25 }
26  
27 ///////////////////////////////////////////////////////////////////////////
29 office 28 // Copyright (C) 2013 Wizardry and Steamworks - License: CC BY 2.0 //
2 office 29 ///////////////////////////////////////////////////////////////////////////
30 string wasKeyValueEncode(list data) {
31 list k = llList2ListStrided(data, 0, -1, 2);
32 list v = llList2ListStrided(llDeleteSubList(data, 0, 0), 0, -1, 2);
33 data = [];
34 do {
35 data += llList2String(k, 0) + "=" + llList2String(v, 0);
36 k = llDeleteSubList(k, 0, 0);
37 v = llDeleteSubList(v, 0, 0);
38 } while(llGetListLength(k) != 0);
39 return llDumpList2String(data, "&");
40 }
41  
42 ///////////////////////////////////////////////////////////////////////////
29 office 43 // Copyright (C) 2011 Wizardry and Steamworks - License: CC BY 2.0 //
2 office 44 ///////////////////////////////////////////////////////////////////////////
45 // http://was.fm/secondlife/wanderer
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 ///////////////////////////////////////////////////////////////////////////
29 office 55 // Copyright (C) 2015 Wizardry and Steamworks - License: CC BY 2.0 //
2 office 56 ///////////////////////////////////////////////////////////////////////////
57 // escapes a string in conformance with RFC1738
58 string wasURLEscape(string i) {
59 string o = "";
60 do {
61 string c = llGetSubString(i, 0, 0);
62 i = llDeleteSubString(i, 0, 0);
63 if(c == "") jump continue;
64 if(c == " ") {
65 o += "+";
66 jump continue;
67 }
68 if(c == "\n") {
69 o += "%0D" + llEscapeURL(c);
70 jump continue;
71 }
72 o += llEscapeURL(c);
73 @continue;
74 } while(i != "");
75 return o;
76 }
77  
78 ///////////////////////////////////////////////////////////////////////////
29 office 79 // Copyright (C) 2015 Wizardry and Steamworks - License: CC BY 2.0 //
2 office 80 ///////////////////////////////////////////////////////////////////////////
81 list wasCSVToList(string csv) {
82 list l = [];
83 list s = [];
84 string m = "";
85 do {
86 string a = llGetSubString(csv, 0, 0);
87 csv = llDeleteSubString(csv, 0, 0);
88 if(a == ",") {
89 if(llList2String(s, -1) != "\"") {
90 l += m;
91 m = "";
92 jump continue;
93 }
94 m += a;
95 jump continue;
96 }
97 if(a == "\"" && llGetSubString(csv, 0, 0) == a) {
98 m += a;
99 csv = llDeleteSubString(csv, 0, 0);
100 jump continue;
101 }
102 if(a == "\"") {
103 if(llList2String(s, -1) != a) {
104 s += a;
105 jump continue;
106 }
107 s = llDeleteSubList(s, -1, -1);
108 jump continue;
109 }
110 m += a;
111 @continue;
112 } while(csv != "");
113 // postcondition: length(s) = 0
114 return l + m;
115 }
116  
117 ///////////////////////////////////////////////////////////////////////////
29 office 118 // Copyright (C) 2015 Wizardry and Steamworks - License: CC BY 2.0 //
2 office 119 ///////////////////////////////////////////////////////////////////////////
120 string wasListToCSV(list l) {
121 list v = [];
122 do {
123 string a = llDumpList2String(
124 llParseStringKeepNulls(
125 llList2String(
126 l,
127  
128 ),
129 ["\""],
130 []
131 ),
132 "\"\""
133 );
134 if(llParseStringKeepNulls(
135 a,
136 [" ", ",", "\n", "\""], []
137 ) !=
138 (list) a
139 ) a = "\"" + a + "\"";
140 v += a;
141 l = llDeleteSubList(l, 0, 0);
142 } while(l != []);
143 return llDumpList2String(v, ",");
144 }
145  
146 ///////////////////////////////////////////////////////////////////////////
29 office 147 // Copyright (C) 2015 Wizardry and Steamworks - License: CC BY 2.0 //
2 office 148 ///////////////////////////////////////////////////////////////////////////
149 // unescapes a string in conformance with RFC1738
150 string wasURLUnescape(string i) {
151 return llUnescapeURL(
152 llDumpList2String(
153 llParseString2List(
154 llDumpList2String(
155 llParseString2List(
156 i,
157 ["+"],
158 []
159 ),
160 " "
161 ),
162 ["%0D%0A"],
163 []
164 ),
165 "\n"
166 )
167 );
168 }
169  
170 ///////////////////////////////////////////////////////////////////////////
29 office 171 // Copyright (C) 2013 Wizardry and Steamworks - License: CC BY 2.0 //
2 office 172 ///////////////////////////////////////////////////////////////////////////
173 integer wasMenuIndex = 0;
174 list wasDialogMenu(list input, list actions, string direction) {
175 integer cut = 11-wasListCountExclude(actions, [""]);
176 if(direction == ">" && (wasMenuIndex+1)*cut+wasMenuIndex+1 < llGetListLength(input)) {
177 ++wasMenuIndex;
178 jump slice;
179 }
180 if(direction == "<" && wasMenuIndex-1 >= 0) {
181 --wasMenuIndex;
182 jump slice;
183 }
184 @slice;
185 integer multiple = wasMenuIndex*cut;
186 input = llList2List(input, multiple+wasMenuIndex, multiple+cut+wasMenuIndex);
187 input = wasListMerge(input, actions, "");
188 return input;
189 }
190  
191 ///////////////////////////////////////////////////////////////////////////
29 office 192 // Copyright (C) 2013 Wizardry and Steamworks - License: CC BY 2.0 //
2 office 193 ///////////////////////////////////////////////////////////////////////////
194 integer wasListCountExclude(list input, list exclude) {
195 if(llGetListLength(input) == 0) return 0;
196 if(llListFindList(exclude, (list)llList2String(input, 0)) == -1)
197 return 1 + wasListCountExclude(llDeleteSubList(input, 0, 0), exclude);
198 return wasListCountExclude(llDeleteSubList(input, 0, 0), exclude);
199 }
200  
201 ///////////////////////////////////////////////////////////////////////////
29 office 202 // Copyright (C) 2013 Wizardry and Steamworks - License: CC BY 2.0 //
2 office 203 ///////////////////////////////////////////////////////////////////////////
204 list wasListMerge(list l, list m, string merge) {
205 if(llGetListLength(l) == 0 && llGetListLength(m) == 0) return [];
206 string a = llList2String(m, 0);
207 if(a != merge) return [ a ] + wasListMerge(l, llDeleteSubList(m, 0, 0), merge);
208 return [ llList2String(l, 0) ] + wasListMerge(llDeleteSubList(l, 0, 0), llDeleteSubList(m, 0, 0), merge);
209 }
210  
211 // configuration data
212 string configuration = "";
213 // callback URL
214 string callback = "";
215 // scanned primitives
216 list names = [];
217 list UUIDs = [];
218 // temporary list for button name normalization
219 list menu = [];
220 integer select = -1;
221  
222 default {
223 state_entry() {
224 llSetTimerEvent(1);
225 }
226 link_message(integer sender, integer num, string message, key id) {
227 if(sender != 1 || id != "configuration") return;
228 configuration = message;
229 state off;
230 }
231 timer() {
232 llMessageLinked(LINK_ROOT, 0, "configuration", NULL_KEY);
233 }
234 attach(key id) {
235 llResetScript();
236 }
237 on_rez(integer num) {
238 llResetScript();
239 }
240 changed(integer change) {
241 if((change & CHANGED_INVENTORY) || (change & CHANGED_REGION_START) || (change & CHANGED_OWNER)) {
242 llResetScript();
243 }
244 }
245 state_exit() {
246 llSetTimerEvent(0);
247 }
248 }
249  
250 state off {
251 state_entry() {
252 llSetColor(<.5,0,0>, ALL_SIDES);
253 }
254 touch_end(integer num) {
255 state on;
256 }
257 attach(key id) {
258 llResetScript();
259 }
260 on_rez(integer num) {
261 llResetScript();
262 }
263 changed(integer change) {
264 if((change & CHANGED_INVENTORY) || (change & CHANGED_REGION_START) || (change & CHANGED_OWNER)) {
265 llResetScript();
266 }
267 }
268 }
269  
270 state on {
271 state_entry() {
272 llSetColor(<0,.5,0>, ALL_SIDES);
273 state url;
274 }
275 attach(key id) {
276 llResetScript();
277 }
278 on_rez(integer num) {
279 llResetScript();
280 }
281 changed(integer change) {
282 if((change & CHANGED_INVENTORY) || (change & CHANGED_REGION_START) || (change & CHANGED_OWNER)) {
283 llResetScript();
284 }
285 }
286 }
287  
288 state url {
289 state_entry() {
290 // DEBUG
291 llOwnerSay("Requesting URL...");
292 llRequestURL();
293 }
294 touch_end(integer num) {
295 llSetColor(<.5,0,0>, ALL_SIDES);
296 llResetScript();
297 }
298 http_request(key id, string method, string body) {
299 if(method != URL_REQUEST_GRANTED) return;
300 callback = body;
301 // DEBUG
302 llOwnerSay("Got URL...");
303 state scan;
304 }
305 attach(key id) {
306 llResetScript();
307 }
308 on_rez(integer num) {
309 llResetScript();
310 }
311 changed(integer change) {
312 if((change & CHANGED_INVENTORY) || (change & CHANGED_REGION_START) || (change & CHANGED_OWNER)) {
313 llResetScript();
314 }
315 }
316 }
317  
318 state scan {
319 state_entry() {
320 // DEBUG
321 llOwnerSay("Getting primitives...");
322 llInstantMessage(
323 wasKeyValueGet(
324 "corrade",
325 configuration
326 ),
327 wasKeyValueEncode(
328 [
329 "command", "getprimitivesdata",
330 "group", wasURLEscape(
331 wasKeyValueGet(
332 "group",
333 configuration
334 )
335 ),
336 "password", wasURLEscape(
337 wasKeyValueGet(
338 "password",
339 configuration
340 )
341 ),
342 "entity", "range",
343 "range", wasURLEscape(
344 wasKeyValueGet(
345 "radar",
346 configuration
347 )
348 ),
349 "data", wasListToCSV(
350 [
351 "Properties.Name",
352 "ID"
353 ]
354 ),
355 "sift", wasListToCSV(
356 [
357 "take", 32
358 ]
359 ),
360 "callback", wasURLEscape(callback)
361 ]
362 )
363 );
364 }
365 touch_end(integer num) {
366 llSetColor(<.5,0,0>, ALL_SIDES);
367 llResetScript();
368 }
369 http_request(key id, string method, string body) {
370 llHTTPResponse(id, 200, "OK");
371 if(wasKeyValueGet("command", body) != "getprimitivesdata" ||
372 wasKeyValueGet("success", body) != "True") {
373 // DEBUG
374 llOwnerSay("Too many primitives or unable to query primitives data...");
375 llResetScript();
376 }
377 string dataKey = wasURLUnescape(
378 wasKeyValueGet(
379 "data",
380 body
381 )
382 );
383 if(dataKey == "") {
384 // DEBUG
385 llOwnerSay("No data for scanned primitives...");
386 llResetScript();
387 }
388 list data = wasCSVToList(dataKey);
389 // Copy the names and UUIDs of the primitives.
390 names = [];
391 UUIDs = [];
392 do {
393 string v = llList2String(data, -1);
394 data = llDeleteSubList(data, -1, -1);
395 string k = llList2String(data, -1);
396 data = llDeleteSubList(data, -1, -1);
397 if(k == "Properties.Name") {
398 names += v;
399 jump continue;
400 }
401 UUIDs += (key)v;
402 @continue;
403 } while(llGetListLength(data));
404 state choose;
405 }
406 attach(key id) {
407 llResetScript();
408 }
409 on_rez(integer num) {
410 llResetScript();
411 }
412 changed(integer change) {
413 if((change & CHANGED_INVENTORY) || (change & CHANGED_REGION_START) || (change & CHANGED_OWNER)) {
414 llResetScript();
415 }
416 }
417 state_exit() {
418 llSetTimerEvent(0);
419 }
420 }
421  
422 state choose {
423 state_entry() {
424 // DEBUG
425 llOwnerSay("Sending menu...");
426 menu = [];
427 integer i = 0;
428 do {
429 menu += llGetSubString(llList2String(names, i), 0, 23);
430 } while(++i < llGetListLength(names));
431 llListen(-10, "", llGetOwner(), "");
432 llDialog(llGetOwner(), "\nPlease choose a primitive for Corrade to point at from the list below:\n", wasDialogMenu(menu, ["⟵ Back", "", "Next ⟶"], ""), -10);
433 llSetTimerEvent(60);
434 }
435 touch_end(integer num) {
436 llSetColor(<.5,0,0>, ALL_SIDES);
437 llResetScript();
438 }
439 listen(integer channel, string name, key id, string message) {
440 if(message == "⟵ Back") {
441 llDialog(id, "\nPlease choose a primitive for Corrade to point at from the list below:\n", wasDialogMenu(menu, ["⟵ Back", "", "Next ⟶"], "<"), -10);
442 return;
443 }
444 if(message == "Next ⟶") {
445 llDialog(id, "\nPlease choose a primitive for Corrade to sit on from the list below:\n", wasDialogMenu(menu, ["⟵ Back", "", "Next ⟶"], ">"), -10);
446 return;
447 }
448 integer i = llGetListLength(menu) - 1;
449 do {
450 string v = llList2String(menu, i);
451 if(llSubStringIndex(v, message) != -1)
452 jump sit;
453 } while(--i > -1);
454 // GC
455 menu = [];
456 // DEBUG
457 llOwnerSay("Invalid menu item selected...");
458 llResetScript();
459 @sit;
460 // GC
461 menu = [];
462 select = i;
463 // Got a menu item so bind to permission notifications and sit.
464 state point_at;
465  
466 }
467 timer() {
468 // DEBUG
469 llOwnerSay("Dialog menu timeout...");
470 llResetScript();
471 }
472 attach(key id) {
473 llResetScript();
474 }
475 on_rez(integer num) {
476 llResetScript();
477 }
478 changed(integer change) {
479 if((change & CHANGED_INVENTORY) || (change & CHANGED_REGION_START) || (change & CHANGED_OWNER)) {
480 llResetScript();
481 }
482 }
483 state_exit() {
484 llSetTimerEvent(0);
485 }
486 }
487  
488 state point_at {
489 state_entry() {
490 // DEBUG
491 llOwnerSay("Pointing at: " +
492 llList2String(names, select) +
493 " UUID: " +
494 llList2String(UUIDs, select)
495 );
496 llInstantMessage(
497 (key)wasKeyValueGet(
498 "corrade",
499 configuration
500 ),
501 wasKeyValueEncode(
502 [
503 "command", "setviewereffect",
504 "group", wasURLEscape(
505 wasKeyValueGet(
506 "group",
507 configuration
508 )
509 ),
510 "password", wasURLEscape(
511 wasKeyValueGet(
512 "password",
513 configuration
514 )
515 ),
516 "effect", "point",
517 "offset", ZERO_VECTOR,
518 "type", "Select",
519 "id", wasURLEscape(
520 llGetKey()
521 ),
522 "item", wasURLEscape(
523 llList2String(
524 UUIDs,
525 select
526 )
527 ),
528 "range", wasURLEscape(
529 wasKeyValueGet(
530 "radar",
531 configuration
532 )
533 ),
534 "callback", wasURLEscape(callback)
535 ]
536 )
537 );
538 }
539 touch_end(integer num) {
540 state remove;
541 }
542 http_request(key id, string method, string body) {
543 llHTTPResponse(id, 200, "OK");
544 if(wasKeyValueGet("command", body) != "setviewereffect" ||
545 wasKeyValueGet("success", body) != "True") {
546 // DEBUG
547 llOwnerSay("Failed to point at...");
548 llResetScript();
549 }
550 // DEBUG
551 llOwnerSay("Pointing...");
552 }
553 attach(key id) {
554 llResetScript();
555 }
556 on_rez(integer num) {
557 llResetScript();
558 }
559 changed(integer change) {
560 if((change & CHANGED_INVENTORY) || (change & CHANGED_REGION_START) || (change & CHANGED_OWNER)) {
561 llResetScript();
562 }
563 }
564 state_exit() {
565 llSetTimerEvent(0);
566 }
567 }
568  
569 state remove {
570 state_entry() {
571 // DEBUG
572 llOwnerSay("Stopping point at...");
573 llInstantMessage(
574 (key)wasKeyValueGet(
575 "corrade",
576 configuration
577 ), wasKeyValueEncode(
578 [
579 "command", "deleteviewereffect",
580 "group", wasURLEscape(
581 wasKeyValueGet(
582 "group",
583 configuration
584 )
585 ),
586 "password", wasURLEscape(
587 wasKeyValueGet(
588 "password",
589 configuration
590 )
591 ),
592 "effect", "point",
593 "id", wasURLEscape(
594 llGetKey()
595 )
596 ]
597 )
598 );
599 llResetScript();
600 }
601 touch_start(integer num) {
602 llResetScript();
603 }
604 attach(key id) {
605 llResetScript();
606 }
607 on_rez(integer num) {
608 llResetScript();
609 }
610 changed(integer change) {
611 if((change & CHANGED_INVENTORY) || (change & CHANGED_REGION_START) || (change & CHANGED_OWNER)) {
612 llResetScript();
613 }
614 }
615 state_exit() {
616 llSetTimerEvent(0);
617 }
618 }