aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/~MLP lite tools.lsl
diff options
context:
space:
mode:
authorDave Seikel2018-05-20 23:17:24 +1000
committerDave Seikel2018-05-20 23:17:24 +1000
commit9dd74045373c39d8a35a59f3c2801b0348a44a9b (patch)
treeb3cdc4ba800ffa44b98291ce12a0eb1c9ad809e4 /~MLP lite tools.lsl
parentInitial commit (diff)
downloadMLP-lite-9dd74045373c39d8a35a59f3c2801b0348a44a9b.zip
MLP-lite-9dd74045373c39d8a35a59f3c2801b0348a44a9b.tar.gz
MLP-lite-9dd74045373c39d8a35a59f3c2801b0348a44a9b.tar.bz2
MLP-lite-9dd74045373c39d8a35a59f3c2801b0348a44a9b.tar.xz
Initial commit.
This is the current alpha version, it was time to put it somewhere.
Diffstat (limited to '~MLP lite tools.lsl')
-rw-r--r--~MLP lite tools.lsl595
1 files changed, 595 insertions, 0 deletions
diff --git a/~MLP lite tools.lsl b/~MLP lite tools.lsl
new file mode 100644
index 0000000..b8e9925
--- /dev/null
+++ b/~MLP lite tools.lsl
@@ -0,0 +1,595 @@
1//
2// MLP lite v3.0 for OpenSim
3// Based on the original MLP - MULTI-LOVE-POSE V1.2 - Copyright (c) 2006, by Miffy Fluffy (BSD License)
4// This code has bounced around the Second Life and OpenSim for over a decade, with various people working on it.
5// MLP lite for OpenSim is almost a complete rewrite by onefang rejected.
6
7string Version = "MLP lite tools v3.0 alpha";
8
9key Owner;
10integer Channel;
11
12list Need = [];
13string Todo = "";
14
15// NOTE - This one uses \n to separate sub lists, coz | is used in some of the commands.
16list Menus; // List of menus.
17integer MENU_NAME = 0; // Name of menu.
18integer MENU_AUTH = 1; // Authorised users of menu - 0 = owner, 1 = group, 2 = all
19integer MENU_COLOURS = 2; // \n spearated list of ball colours.
20integer MENU_ENTRIES = 3; // \n separated list of entries.
21integer MENU_CMDS = 4; // \n separated list of commands, matching the entries.
22integer MENU_SWAPS = 5; // \n separated list of colour sets.
23integer MENU_STRIDE = 6;
24
25string Pose = "";
26list Poses; // List of poses.
27integer POSE_NAME = 0; // Name of pose.
28integer POSE_ANIM = 1; // | separated animations.
29integer POSE_EMOTE = 2; // | separated emotions and timers list.
30integer POSE_POSROT = 3; // | separated posiiton and rotation pairs.
31integer POSE_STRIDE = 4;
32
33list Props; // List of props.
34integer PROP_NAME = 0; // Name of prop, which should match a POSE name.
35integer PROP_OBJECT = 1; // | separated names of props in inventory.
36integer PROP_POSROT = 2; // | separated position and rotation pairs.
37integer PROP_STRIDE = 3;
38
39list Sounds;
40integer SOUND_NAME = 0;
41integer SOUND_INV = 1;
42integer SOUND_STRIDE = 2;
43
44string LIST_SEP = "$!#"; // Used to seperate lists when sending them as strings.
45
46// The various link messages. The first lot are historical.
47//integer OLD_TOUCH = -1; // msg = "PRIMTOUCH"
48integer OLD_POSEB = 0; // msg = "POSEB" id = pose name
49// // Also CHECK1 and CHECK2 instead of pose name.
50integer OLD_STOP = 1; // msg = "STOP"
51//integer OLD_REF = 8; // msg = RefPos id = RefRot
52integer OLD_SITS = -11000; // msg = ball number|anim name id = avatar key
53integer OLD_STANDS = -11001; // msg = ball number id = avatar key
54integer OLD_ANIM = -11002; // msg = ball number|anim name id = avatar key
55//integer SEQ_CMD = -12001; // msg = ~sequencer command
56integer OLD_CMD = -12002; // msg = menu command for ~MLP id = user key
57
58integer MLP_CMD = -13001; // A command that ~MLP dealt with, so other scripts can hook it.
59integer TOOL_DATA = -13002; // Get Menus, Poses, Props, or Sounds list.
60integer MLP_DATA = -13003; // Set Menus, Poses, Props, or Sounds list.
61integer MLP_POSE = -13004; // doPose(pose, type);
62integer MLP_UNKNOWN = -13005; // ~MLP doesn't know this command, might be for other scripts.
63
64// Types for doPose(),
65integer POSES_POSE = -14001; // Change pose, even if it's changing to the same pose.
66integer POSES_SWAP = -14002; // Swap poses.
67integer POSES_DUMP = -14003; // Dump or save poses.
68integer POSES_Z = -14004; // Change height.
69
70integer PERMS_CT = PERM_COPY | PERM_TRANSFER;
71
72
73integer listFindString(list lst, string name, integer stride)
74{
75 integer f = llListFindList(lst, [name]);
76 integer ix = f / stride;
77
78 // Round to nearest stride.
79 ix = ix * stride;
80
81 // Sanity check, make sure we found a name, not something else, else do it the slow way.
82 if ((-1 != f) && (ix != f))
83 {
84 integer l = llGetListLength(lst);
85 integer i;
86
87 f = -1;
88 for (i = 0; i < l; i += stride)
89 {
90 if (llList2String(lst, i) == name)
91 {
92 f = i;
93 i = l;
94 }
95 }
96 }
97 return f;
98}
99
100integer findMenu(string name)
101{
102 return listFindString(Menus, name, MENU_STRIDE);
103}
104
105list reportPose()
106{
107 list result = [];
108 integer l = llGetListLength(Poses);
109 integer i;
110
111 for (i = 0; i < l; i += POSE_STRIDE)
112 {
113 list prs = llParseString2List(llList2String(Poses, i + POSE_POSROT), ["|"], []);
114 string r = "{" + llList2String(Poses, i) + "} ";
115 integer m = llGetListLength(prs);
116 integer j;
117
118 for (j = 0; j < m; j++)
119 r += llList2String(prs, j);
120 result += [r];
121 }
122
123 return result;
124}
125
126list reportProp()
127{
128 list result = [];
129 integer l = llGetListLength(Props);
130 integer i;
131
132 for (i = 0; i < l; i += PROP_STRIDE)
133 {
134 list obs = llParseString2List(llList2String(Props, i + PROP_OBJECT), ["|"], []);
135 list prs = llParseString2List(llList2String(Props, i + PROP_POSROT), ["|"], []);
136 string r = "|" + llList2String(Props, i) + "|";
137 integer m = llGetListLength(prs);
138 integer j;
139
140 // See ~MLP lite props for a comment about why this is different from reportPose().
141 for (j = 0; j < m; j++)
142 r += llList2String(obs, j) + "|" + osReplaceString(llList2String(prs, j), "><", ">/<", -1, 0);
143 result += [r];
144 }
145
146 return result;
147}
148
149list checkPerms(string name, integer type)
150{
151 list ans = [];
152 integer i = llGetInventoryNumber(type);
153 integer p;
154
155 while (i-- > 0)
156 {
157 string a = llGetInventoryName(type, i);
158
159 ans += [a];
160 p = llGetInventoryPermMask(a, MASK_OWNER);
161 if (PERMS_CT != (p & PERMS_CT))
162 llSay(0, name + " '" + a + "' does not have copy or transfer permissions for the owner.");
163 p = llGetInventoryPermMask(a, MASK_NEXT);
164 if (PERMS_CT != (p & PERMS_CT))
165 llSay(0, name + " '" + a + "' does not have copy or transfer permissions for the next owner.");
166 }
167 return ans;
168}
169
170checkConfig()
171{
172 list ans;
173 integer l = llGetListLength(Poses);
174 integer m;
175 integer i;
176 integer j;
177 integer f;
178
179 llSay(0, "Checking most things...");
180 ans = checkPerms("Animation", INVENTORY_ANIMATION);
181 for (i = 0; i < l; i += POSE_STRIDE)
182 {
183 string name = llList2String(Poses, i + POSE_NAME);
184
185 if ("" == llList2String(Poses, i + POSE_POSROT))
186 llSay(0, "No .POSITIONS* entry for '" + name + "'.");
187 else if ("" == llList2String(Poses, i + POSE_ANIM))
188 {
189 if (("default" != name) && ("stand" != name))
190 llSay(0, "No .MENUITEMS* entry for '" + name + "'.");
191 }
192 else
193 {
194 list anims = llParseString2List(llList2String(Poses, i + POSE_ANIM), ["|"], []);
195
196 m = llGetListLength(anims);
197 for (j = 0; j < m; j++)
198 {
199 string aname = llList2String(anims, j);
200
201 if (aname != "")
202 {
203 if ((aname != "stand") && (aname != "sit_ground"))
204 {
205 if (llGetSubString(aname, -1, -1) == "*")
206 aname = llGetSubString(aname, 0, -2);
207 else
208 {
209 f = llSubStringIndex(aname, "::");
210 if (-1 != f)
211 aname = llGetSubString(aname, 0, f - 1);
212 }
213
214 if (llGetInventoryType(aname) != INVENTORY_ANIMATION)
215 llSay(0, "Animation '" + aname + "' is not in inventory (ok for build-in animations, otherwise check).");
216 f = llListFindList(ans, aname);
217 if (-1 != f)
218 ans = llDeleteSubList(ans, f, f);
219 }
220 }
221 }
222 }
223 }
224 if (0 < llGetListLength(ans))
225 llSay(0, "These animations are not in any config cards - " + llList2CSV(llListSort(ans, 1, TRUE)));
226
227 ans = checkPerms("Object", INVENTORY_OBJECT);
228 l = llGetListLength(Props);
229 f = llListFindList(ans, "~ball");
230 if (-1 != f)
231 ans = llDeleteSubList(ans, f, f);
232 for (i = 0; i < l; i += PROP_STRIDE)
233 {
234 list objs = llParseStringKeepNulls(llList2String(Props, i + PROP_OBJECT), ["|"], []);
235
236 m = llGetListLength(objs);
237 for (j = 0; j < m; j++)
238 {
239 string s = llList2String(objs, j);
240
241 f = llListFindList(ans, s);
242 if (-1 != f)
243 ans = llDeleteSubList(ans, f, f);
244 else
245 llSay(0, "Object '" + s + "' is not in inventory.");
246 }
247 }
248 if (0 < llGetListLength(ans))
249 llSay(0, "These objects are not in any config cards - " + llList2CSV(llListSort(ans, 1, TRUE)));
250
251 ans = checkPerms("Sound", INVENTORY_SOUND);
252 l = llGetListLength(Sounds);
253 if (l)
254 {
255 for (i = 0; i < l; i += SOUND_STRIDE)
256 {
257 string s = llList2String(Sounds, i + SOUND_INV);
258
259// TODO - No idea why checkPerms() is handing me ["", ""].
260 if (llStringLength(s))
261 {
262 f = llListFindList(ans, s);
263 if (-1 != f)
264 ans = llDeleteSubList(ans, f, f);
265 else
266 llSay(0, "Sound '" + s + "' is not in inventory.");
267 }
268 }
269 }
270 if (0 < llGetListLength(ans))
271 llSay(0, "These sounds are not in any config cards - " + llList2CSV(llListSort(ans, 1, TRUE)));
272
273 l = llGetListLength(Poses);
274 for (i = 0; i < l; i += MENU_STRIDE)
275 {
276 string name = llList2String(Menus, i + MENU_NAME);
277
278 ans = llParseStringKeepNulls(llList2String(Menus, i + MENU_CMDS), ["\n"], []);
279 if (12 < llGetListLength(ans))
280 llSay(0, "To many menu items in '" + name + "' menu.");
281 m = llGetListLength(ans);
282 for (j = 0; j < m; j++)
283 {
284 string cmd = llList2String(ans, j);
285
286 if ("TOMENU " == llGetSubString(cmd, 0, 6))
287 {
288 cmd = llGetSubString(cmd, 7, -1);
289 if (-1 == findMenu(cmd))
290 llSay(0, "Menu '" + cmd + "' not found.");
291 }
292 }
293 }
294
295 list scripts = llParseStringKeepNulls("memory menu menucfg pos pose poser prop props run timeout", [""],[]);
296 list found = [];
297
298 ans = checkPerms("Script", INVENTORY_SCRIPT);
299 l = llGetListLength(scripts);
300 for (i = 0; i < l; i++)
301 {
302 f = llListFindList(ans, ["~" + llList2String(scripts, i)]);
303 if (-1 != f)
304 {
305 found += ["~" + llList2String(scripts, i)];
306 ans = llDeleteSubList(ans, f, f);
307 }
308 }
309 for (i = 1; i < 9; i++)
310 {
311 f = llListFindList(ans, ["~poser " + i]);
312 if (-1 != f)
313 {
314 found += ["~poser " + i];
315 ans = llDeleteSubList(ans, f, f);
316 }
317 }
318 f = llListFindList(ans, ["~ball"]);
319 if (-1 != f)
320 {
321 found += ["~ball"];
322 ans = llDeleteSubList(ans, f, f);
323 llSay(0, "There is a '~ball' script, it should be in the '~ball' object, and in any prop objects.");
324 llSay(0, "There is a '~ball' script, it should NOT be in this '" + llGetObjectName() + "' object.");
325 }
326 f = llListFindList(ans, ["~sequencer"]);
327 if (-1 != f)
328 {
329 ans = llDeleteSubList(ans, f, f);
330 llSay(0, "There is a '~sequencer' script, which you wont need unless you where using the old MLP sequences.");
331 llSay(0, "If any old '.SEQUENCER' cards are in use, try them, see if it still works.");
332 }
333 if (0 < llGetListLength(found))
334 llSay(0, "These scripts are likely left overs from an older MLP, you can probably remove them - " + llList2CSV(llListSort(found, 1, TRUE)));
335
336
337 f = llListFindList(ans, ["~MLP lite for OpenSim"]);
338 if (-1 != f)
339 ans = llDeleteSubList(ans, f, f);
340 else
341 llSay(0, llGetScriptName() + " says it wants '~MLP lite for OpenSim'.");
342 f = llListFindList(ans, ["~MLP lite tools"]);
343 if (-1 != f)
344 ans = llDeleteSubList(ans, f, f);
345 else
346 llSay(0, llGetScriptName() + " != ~MLP lite tools!");
347
348 list cards = checkPerms("Notecard", INVENTORY_NOTECARD);
349 l = llGetListLength(cards);
350 f = -1;
351 for (i = 0; i < l; i++)
352 {
353 string crd = llList2String(cards, i);
354
355 if (llSubStringIndex(crd, ".SEQUENCES") == 0)
356 llSay(0, "Old MLP sequences might be in notecard - '" + crd + "'.");
357 if (llSubStringIndex(crd, ".PROPS") == 0)
358 f = i;
359 }
360 if (-1 == f)
361 {
362 f = llListFindList(ans, ["~MLP lite props"]);
363 if (-1 != f)
364 llSay(0, "'~MLP lite props' script is not needed if there are no .PROPS* cards.");
365 }
366 else
367 {
368 f = llListFindList(ans, ["~MLP lite props"]);
369 if (-1 == f)
370 llSay(0, "'~MLP lite props' script is needed if there are .PROPS* cards.");
371 }
372
373
374 llSay(0, "Checks completed.");
375}
376
377doMenu(key id)
378{
379 llDialog(id, Version, [
380 "All poses", " ", "Quit tools",
381 "Height>>", "Pose match>>", "Adjust pos>>",
382 "RELOAD", "RESET", "REDECORATE",
383 "CHECK", "DUMP", "SAVE"
384 ], Channel);
385}
386
387doHeight(key id)
388{
389 llDialog(id, Version, [
390 " ", " ", "Back",
391 "Z-1", "Z-5", "Z-25",
392 "Z+1", "Z+5", "Z+25"
393 ], Channel);
394}
395
396getData(string name)
397{
398 Need += [name];
399 llMessageLinked(LINK_SET, TOOL_DATA, "", name);
400}
401
402default
403{
404 state_entry()
405 {
406 Owner = llGetOwner();
407 Channel = (integer) ("0x" + llGetSubString((string) llGetKey(), -4, -1) + 1);
408 llListen(Channel, "", Owner, "");
409 }
410
411 link_message(integer from, integer num, string str, key id)
412 {
413 if (((0 == num) && ("POSEB" == str)) || ((1 == num) && ("STOP" == str)))
414 ;
415 else if ((MLP_UNKNOWN == num) && ("TOOLS" == str))
416 doMenu(id);
417 else if ((MLP_POSE == num) || (OLD_CMD == num) || (MLP_CMD == num) || (MLP_UNKNOWN == num)
418 || (OLD_SITS == num) || (OLD_STANDS == num) || (OLD_ANIM == num))
419 ;
420 else if ((TOOL_DATA == num) && ("" == str))
421 ;
422 else if ((TOOL_DATA == num) && ("" != str))
423 {
424 list data = llParseStringKeepNulls(llGetSubString(str, llStringLength(LIST_SEP), -1), [LIST_SEP], []);
425 integer f = llListFindList(Need, id);
426
427 if ("Menus" == id)
428 Menus = data;
429 else if ("Poses" == id)
430 Poses = data;
431 else if ("Props" == id)
432 Props = data;
433 else if ("Sounds" == id)
434 Sounds = data;
435 if (-1 != f)
436 {
437 integer i;
438
439 Need = llDeleteSubList(Need, f, f);
440 if (0 == llGetListLength(Need))
441 {
442 if ("CHECK" == Todo)
443 {
444 checkConfig();
445 Todo = "";
446 }
447 else if ("DUMP" == Todo)
448 {
449 string objectName = llGetObjectName();
450 list report = reportPose();
451 integer l = llGetListLength(report);
452
453 llSetObjectName(".");
454 llOwnerSay(".POSITIONS---------------------------------------------------------------");
455 for (i = 0; i < l; i++)
456 llOwnerSay(llList2String(report, i));
457 llOwnerSay(".PROPS-------------------------------------------------------------------");
458 report = reportProp();
459 l = llGetListLength(report);
460 for (i = 0; i < l; i++)
461 llOwnerSay(llList2String(report, i));
462 llOwnerSay("-------------------------------------------------------------------------");
463 llSetObjectName(objectName);
464 Todo = "";
465 }
466 else if ("SAVE" == Todo)
467 {
468 i = llGetInventoryNumber(INVENTORY_NOTECARD);
469 list cards = [];
470
471 llSay(0, "Backing up old cards.");
472 while (i-- > 0)
473 {
474 string item = llGetInventoryName(INVENTORY_NOTECARD, i);
475
476 if ((llSubStringIndex(item, ".POSITIONS") == 0) || (llSubStringIndex(item, ".PROPS") == 0))
477 cards += [llGetInventoryName(INVENTORY_NOTECARD, i)];
478 }
479 i = llGetListLength(cards);
480 while (i-- > 0)
481 {
482 string item = llList2String(cards, i);
483
484 osMakeNotecard(".backup" + item, llParseStringKeepNulls(osGetNotecard(item), ["\n"], []));
485 llRemoveInventory(item);
486 }
487
488 osMakeNotecard(".POSITIONS", reportPose());
489 llSay(0, "Current ball positions saved to the .POSITIONS notecard.");
490 if (llGetListLength(Props))
491 {
492 osMakeNotecard(".PROPS", reportProp());
493 llSay(0, "Current props positions saved to the .PROPS notecard.");
494 }
495 Todo = "";
496 }
497 else if ("All poses" == Todo)
498 {
499
500 f = llGetListLength(Menus);
501 for (i = 0; i < f; i += MENU_STRIDE)
502 {
503 string name = llList2String(Menus, i + MENU_NAME);
504 list cmds = llParseStringKeepNulls(llList2String(Menus, i + MENU_CMDS), ["\n"], []);
505 integer l = llGetListLength(cmds);
506 integer j;
507
508 llOwnerSay("Running through all the poses in menu '" + name + "'.");
509 for (j = 0; j < l; j++)
510 {
511 string p = llList2String(cmds, j);
512
513 if ("POSE " == llGetSubString(p, 0, 4))
514 {
515 string pose = llGetSubString(p, 5, -1);
516
517 llMessageLinked(LINK_SET, OLD_CMD, "TOMENU " + name, Owner);
518 llMessageLinked(LINK_SET, MLP_POSE, (string) POSES_POSE, pose);
519 llSleep(5.0);
520 }
521 }
522 }
523 llMessageLinked(LINK_SET, OLD_CMD, "STOP", Owner);
524 llOwnerSay("Finished all poses.");
525 Todo = "";
526 }
527 }
528 }
529 }
530 else
531 llOwnerSay(llGetScriptName() + " Unknown link message " + num + ", " + str);
532 }
533
534 listen(integer channel, string name, key id, string button)
535 {
536 if ("CHECK" == button)
537 {
538 Todo = button;
539 getData("Menus");
540 getData("Poses");
541 if (llGetInventoryType("~MLP lite props") == INVENTORY_SCRIPT)
542 getData("Props");
543 getData("Sounds");
544 }
545 else if ("DUMP" == button)
546 {
547 // Save any edits to the current pose first.
548 llMessageLinked(LINK_SET, MLP_POSE, (string) POSES_DUMP, NULL_KEY);
549 getData("Poses");
550 if (llGetInventoryType("~MLP lite props") == INVENTORY_SCRIPT)
551 getData("Props");
552 Todo = button;
553 }
554 else if ("SAVE" == button)
555 {
556 // Save any edits to the current pose first.
557 llMessageLinked(LINK_SET, MLP_POSE, (string) POSES_DUMP, NULL_KEY);
558 getData("Poses");
559 if (llGetInventoryType("~MLP lite props") == INVENTORY_SCRIPT)
560 getData("Props");
561 Todo = button;
562 }
563 else if ("All poses" == button)
564 {
565 getData("Menus");
566 Todo = button;
567 }
568 else if ("RESET" == button || "RELOAD" == button || "REDECORATE" == button)
569 llMessageLinked(LINK_SET, OLD_CMD, button, Owner);
570 else if ("Height>>" == button)
571 {
572 doHeight(id);
573 return;
574 }
575 else if ("Z" == llGetSubString(button, 0, 0))
576 {
577 integer i = (integer) llGetSubString(button, 1, 10);
578 integer Zoffset = (integer) llGetObjectDesc() + i;
579
580 llSetObjectDesc((string) Zoffset);
581 llMessageLinked(LINK_SET, MLP_POSE, (string) POSES_Z, NULL_KEY);
582 llOwnerSay("Height Adjustment: change by " + (string) i + "cm, new offset: " + (string) Zoffset + "cm.");
583 doHeight(id);
584 return;
585 }
586 else if ("Back" == button)
587 ;
588 else if ("Quit tools" == button)
589 {
590 llMessageLinked(LINK_SET, OLD_CMD, "TOMENU", Owner);
591 return;
592 }
593 doMenu(id);
594 }
595}