Join us in Outworldz at www.outworldz.com:9000 or follow us:

Search dozens of selected web sites for OpenSim and LSL script

New! Script Meta-Search will search thousands of scripts here and at other sites for LSL or Opensim scripts.
Loading

Want to add a script or a project? Upload it and a half million people will see it and your name here this year.

Home   Show All
Category: Contributor: Creator
AO ZHAO-II AO for Second life  

ZHAO-II AO for Second life

ZHAO=II compatible AO using the new LSL Animation functions, timer is now used only to detect swimming

Category: AO
By : Chloe1982 Constantine and others
Created: 2014-01-30 Edited: 2014-01-30
Worlds: Second Life

the Zip file

Download all files for ZHAO-II AO for Second life
Contents are in zip format, with .LSL (text) source code and LSLEdit (text + Solution) formats.
Get file # 1. ZHAO-II.lsl
1 // As an exercise, I took a version of ZHAO II core and rewrote it to be compatible with a linked message interface, but used the new functions;
2 // It still needs to poll for swimming but I figured that could be done at a much slower rate than normally used in an AO.
3 // I had to forgo the ability to replace the typing anim since that would require a faster timer.
4 // The new animation override functions don't allow for stacking anims in the way you used to with the , separator so that was given up.
5 // Finally, in the interests of cramming the core into a single 16k LSL compiled script I didn't implement the timing option for the different anims;
6 // it could certainly be done, I just chose not to do so!
7
8
9 // ZHAO-II-core - Ziggy Puff, 07/07
10 /////////////////////////////////////////////////////////////////////////////////////////////////////
11 //
12 // Chloe1982 Constantine, 05/08/13 - Modified/Updated to use the new LSL Animation functions, timer is
13 // now used only to detect swimming (timerEventLength)
14 //
15 // Ziggy, 07/16/07 - Warning instead of error on 'no animation in inventory', that way SL's built-in
16 // anims can be used
17 //
18 // Ziggy, 07/14/07 - 2 bug fixes. Listens aren't being reset on owner change, and a typo in the
19 // ground sit animation code
20 //
21 // Ziggy, 06/07:
22 // Reduce script count, since idle scripts take up scheduler time
23 // Tokenize notecard reader, to simplify notecard setup
24 // Remove scripted texture changes, to simplify customization by animation sellers
25
26 // Fennec Wind, January 18th, 2007:
27 // Changed Walk/Sit/Ground Sit dialogs to show animation name (or partial name if too long)
28 // and only show buttons for non-blank entries.
29 // Fixed minor bug in the state_entry, ground sits were not being initialized.
30 //
31 //
32 // Dzonatas Sol, 09/06: Fixed forward walk override (same as previous backward walk fix).
33 //
34 // Based on Francis Chung's Franimation Overrider v1.8
35 //
36 // This program is free software; you can redistribute it and/or modify
37 // it under the terms of the GNU General Public License as published by
38 // the Free Software Foundation; either version 2 of the License, or
39 // (at your option) any later version.
40 //
41 // This program is distributed in the hope that it will be useful,
42 // but WITHOUT ANY WARRANTY; without even the implied warranty of
43 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
44 // GNU General Public License for more details.
45 //
46 // You should have received a copy of the GNU General Public License
47 // along with this program; if not, write to the Free Software
48 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
49
50 /////////////////////////////////////////////////////////////////////////////////////////////////////
51 // Main engine script - receives link messages from any interface script. Handles the core AO work
52 //
53 // Interface definition: The following link_message commands are handled by this script. All of
54 // these are sent in the string field. All other fields are ignored
55 //
56 // ZHAO_RESET Reset script
57 // ZHAO_LOAD|<notecardName> Load specified notecard
58 // ZHAO_NEXTSTAND Switch to next stand
59 // ZHAO_STANDTIME|<time> Time between stands. Specified in seconds, expects an integer.
60 // 0 turns it off
61 // ZHAO_AOON AO On
62 // ZHAO_AOOFF AO Off
63 // ZHAO_SITON Sit On
64 // ZHAO_SITOFF Sit Off
65 // ZHAO_RANDOMSTANDS Stands cycle randomly
66 // ZHAO_SEQUENTIALSTANDS Stands cycle sequentially
67 // ZHAO_SETTINGS Prints status
68 // ZHAO_SITS Select a sit
69 // ZHAO_GROUNDSITS Select a ground sit
70 // ZHAO_WALKS Select a walk
71 //
72 // So, to send a command to the ZHAO-II engine, send a linked message:
73 //
74 // llMessageLinked(LINK_SET, 0, "ZHAO_AOON", NULL_KEY);
75 //
76 // This script uses a listener on channel -91234. If other scripts are added to the ZHAO, make sure
77 // they don't use the same channel
78 /////////////////////////////////////////////////////////////////////////////////////////////////////
79
80 /////////////////////////////////////////////////////////////////////////////////////////////////////
81 // New notecard format
82 //
83 /////////////////////////////////////////////////////////////////////////////////////////////////////
84 // Lines starting with a / are treated as comments and ignored. Blank lines are ignored. Valid lines
85 // look like this:
86 //
87 // [ Walking ]SexyWalk1|SexyWalk2|SexyWalk3
88 //
89 // The token (in this case, [ Walking ]) identifies the animation to be overridden. The rest is a
90 // list of animations, separated by the '|' (pipe) character. You can specify multiple animations
91 // for Stands, Walks, Sits, and GroundSits. Multiple animations on any other line will be ignored.
92 // You can have up to 12 animations each for Walks, Sits and GroundSits. There is no hard limit
93 // on the number of stands, but adding too many stands will make the script run out of memory and
94 // crash, so be careful. You can repeat tokens, so you can split the Stands up across multiple lines.
95 // Use the [ Standing ] token in each line, and the script will add the animation lists together.
96 //
97 // Advanced: Each 'animation name' can be a comma-separated list of animations, which will be played
98 // together. For example:
99 //
100 // [ Walking ]SexyWalk1UpperBody,SexyWalk1LowerBody|SexyWalk2|SexyWalk3
101 //
102 // Note the ',' between SexyWalk1UpperBody and SexyWalk1LowerBody - this tells ZHAO-II to treat these
103 // as a single 'animation' and play them together. The '|' between this 'animation' and SexyWalk2 tells
104 // ZHAO-II to treat SexyWalk2 and SexyWalk3 as separate walk animations. You can use this to layer
105 // animations on top of each other.
106 //
107 // Do not add any spaces around animation names!!!
108 //
109 // The token can be one of the following:
110 //
111 // [ Standing ]
112 // [ Walking ]
113 // [ Sitting ]
114 // [ Sitting On Ground ]
115 // [ Crouching ]
116 // [ Crouch Walking ]
117 // [ Landing ]
118 // [ Standing Up ]
119 // [ Falling ]
120 // [ Flying Down ]
121 // [ Flying Up ]
122 // [ Flying ]
123 // [ Flying Slow ]
124 // [ Hovering ]
125 // [ Jumping ]
126 // [ Pre Jumping ]
127 // [ Running ]
128 // [ Turning Right ]
129 // [ Turning Left ]
130 // [ Floating ]
131 // [ Swimming Forward ]
132 // [ Swimming Up ]
133 // [ Swimming Down ]
134 //
135
136
137 // CONSTANTS
138 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
139 // Default notecard we read on script_entry
140 string defaultNoteCard = "Default";
141
142 // List of all the animation states
143 list animState = [ "Sitting on Ground", "Sitting", "Striding", "Crouching", "CrouchWalking",
144 "Soft Landing", "Standing Up", "Falling Down", "Hovering Down", "Hovering Up",
145 "FlyingSlow", "Flying", "Hovering", "Jumping", "PreJumping", "Running",
146 "Turning Right", "Turning Left", "Walking", "Landing", "Standing", "Taking Off" ];
147
148 // Logic change - we now have a list of tokens. The 'overrides' list is the same length as this,
149 // i.e. it has one entry per token, *not* one entry per animation. Multiple options for a token
150 // are stored as | separated strings in a single list entry. This was done to save memory, and
151 // allow a larger number of stands etc. All the xxxIndex variables now refer to the token index,
152 // since that's how long 'overrides' is.
153
154 // List of internal tokens. This *must* be in the same sequence as the animState list. Note that
155 // we combine some tokens after the notecard is read (striding/walking, landing/soft landing), etc.
156 // The publicized tokens list only contains one entry for each pair, but we'll accept both, and
157 // combine them later
158 list tokens = [ "Sitting On Ground", "Sitting", "Striding", "Crouching", "Crouch Walking", // 0-4
159 "Soft Landing", "Standing Up", "Falling", "Flying Down", "Flying Up", // 5-9
160 "Flying Slow", "Flying", "Hovering", "Jumping", "Pre Jumping", // 10-14
161 "Running", "Turning Right", "Turning Left", "Walking", "Landing", // 15-19
162 "Standing", "Taking Off", "Swimming Down", "Swimming Up", "Swimming Forward", // 20-24
163 "Floating" ]; // 25
164
165 // The tokens for which we allow multiple animations
166 string multiAnimTokenIndexes = ",0,1,18,20,"; // Groundsit, Sitting, Walking, Standing
167
168 // Index of interesting animations
169 integer noAnimIndex = -1;
170 integer sitgroundIndex = 0;
171 integer sittingIndex = 1;
172 /*
173 integer hoverdownIndex = 8;
174 integer hoverupIndex = 9;
175 integer flyingslowIndex = 10;
176 integer flyingIndex = 11;
177 integer hoverIndex = 12;
178 */
179 integer walkingIndex = 18;
180 integer standingIndex = 20;
181 /*
182 integer swimdownIndex = 22;
183 integer swimupIndex = 23;
184 integer swimmingIndex = 24;
185 integer waterTreadIndex = 25;
186 */
187
188 // magic string that replaces the following commented out lists
189 string magicPos = "12111009082524242322";
190 // number of swimming replacement anims
191 integer magicSwim = 5;
192
193 // list of animations that have a different value when underwater
194 //list underwaterAnim = [ hoverIndex, flyingIndex, flyingslowIndex, hoverupIndex, hoverdownIndex ];
195
196 // corresponding list of animations that we override the overrider with when underwater
197 //list underwaterOverride = [ waterTreadIndex, swimmingIndex, swimmingIndex, swimupIndex, swimdownIndex];
198
199 // How long before flipping stand animations
200 integer standTimeDefault = 30;
201
202 // How fast should we poll for whether or not we're under water?
203 // NOTE, you can change this to whatever value you like, it will just change the delay on how long it takes
204 // you to start/stop swimming
205
206 float timerEventLength = 3.0;
207
208 // Number of timer events that will have to pass to change an anim
209 integer maxTicks;
210 // Number of ticks that have passed
211 integer numTicks = 0;
212 // Are we underwater?
213 integer isUnder = FALSE;
214
215 // Listen channel for pop-up menu
216 integer listenChannel = -91234;
217
218 // GLOBALS
219 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
220
221 integer numStands; // Number of stands - needed for auto cycle
222 integer randomStands = FALSE; // Whether stands cycle randomly
223 integer curStandIndex; // Current stand - needed for cycling
224 string curStandAnim = ""; // Current Stand animation
225 string curSitAnim = ""; // Current sit animation
226 string curWalkAnim = ""; // Current walk animation
227 string curGsitAnim = ""; // Current ground sit animation
228
229 list overrides = []; // List of animations we override
230 key notecardLineKey; // notecard reading keys
231 integer notecardIndex; // current line being read from notecard
232 integer numOverrides; // # of overrides
233
234 integer standTime = standTimeDefault; // How long before flipping stand animations
235
236 integer animOverrideOn = TRUE; // Is the animation override on?
237 integer gotPermission = FALSE; // Do we have animation permissions?
238
239 integer listenHandle; // Listen handlers - only used for pop-up menu, then turned off
240
241 integer haveWalkingAnim = FALSE; // Hack to get it so we face the right way when we walk backwards
242
243 integer sitOverride = TRUE; // Whether we're overriding sit or not
244
245 integer listenState = 0; // What pop-up menu we're handling now
246
247 integer loadInProgress = FALSE; // Are we currently loading a notecard
248 string notecardName = ""; // The notecard we're currently reading
249
250 key Owner = NULL_KEY;
251
252 // String constants to save a few bytes
253 string EMPTY = "";
254 string SEPARATOR = "|";
255 string TRYAGAIN = "\nPlease correct the notecard and try again.";
256
257 // CODE
258 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
259
260 // Enable or disable the AO
261
262 AO_Enable()
263 {
264 llSetTimerEvent(timerEventLength);
265 numTicks = 0;
266 if(gotPermission)
267 sendOverrides();
268 }
269
270 AO_Disable()
271 {
272 llSetTimerEvent(0.0);
273 if(gotPermission)
274 llResetAnimationOverride("ALL"); // Clear them all out
275 }
276
277 // Send new overrides to the server
278 sendOverrides()
279 {
280 integer n = llGetListLength(animState);
281 string anim = EMPTY;
282 string st;
283 while(n--)
284 {
285 st = llList2String(animState, n);
286 if((anim = llList2String(overrides, n)) == EMPTY)
287 llResetAnimationOverride(st);
288 else if(llSubStringIndex(multiAnimTokenIndexes, "," + (string)n + ",") == -1)
289 doAnimSet(st, anim);
290 else
291 {
292 if(n == 0)
293 anim = curGsitAnim;
294 else if(n == 1)
295 anim = curSitAnim;
296 else if(n == 18)
297 anim = curWalkAnim;
298 else
299 anim = curStandAnim;
300 doAnimSet(st, anim);
301 }
302 }
303 }
304
305 // Switch to the next stand anim
306 doNextStand(integer fromUI)
307 {
308 if(numStands > 0)
309 {
310 if(randomStands)
311 curStandIndex = llFloor(llFrand(numStands));
312 else
313 curStandIndex = (curStandIndex + 1) % numStands;
314
315 doAnimSet("Standing", curStandAnim = findMultiAnim(20, curStandIndex)); //, 20
316
317 if(fromUI)
318 llOwnerSay("Switching to stand '" + curStandAnim + "'.");
319 }
320 else if(fromUI)
321 llOwnerSay("No stand animations configured.");
322 }
323
324 // Actually set the animation (if we need to)
325 doAnimSet(string st, string anim)
326 {
327 if(anim == EMPTY)
328 return;
329 if(animOverrideOn)
330 llSetAnimationOverride(st, anim);
331 }
332
333 // Displays menu of animation choices
334 doMultiAnimMenu( integer _animIndex, string _animType, string _currentAnim )
335 {
336 // Dialog enhancement - Fennec Wind
337 // Fix - a no-mod anim with a long name will break this
338
339 list anims = llParseString2List( llList2String(overrides, _animIndex), [SEPARATOR], [] );
340 integer numAnims = llGetListLength( anims );
341 if( numAnims > 12 ) {
342 llOwnerSay( "Too many animations, cannot generate menu. " + TRYAGAIN );
343 return;
344 }
345
346 list buttons = [];
347 integer i;
348 string animNames = EMPTY;
349 for ( i=0; i<numAnims; i++ ) {
350 animNames += "\n" + (string)(i+1) + ". " + llList2String( anims, i );
351 buttons += [(string)(i+1)];
352 }
353 // If no animations were configured, say so and just display an "OK" button
354 if( animNames == EMPTY ) {
355 animNames = "\n\nNo overrides have been configured.";
356 }
357 llListenControl(listenHandle, TRUE);
358 llDialog( Owner, "Select the " + _animType + " animation to use:\n\nCurrently: " + _currentAnim + animNames,
359 buttons, listenChannel );
360 }
361
362 // Returns an animation from the multiAnims
363 string findMultiAnim( integer _animIndex, integer _multiAnimIndex )
364 {
365 list animsList = llParseString2List( llList2String(overrides, _animIndex), [SEPARATOR], [] );
366 return llList2String( animsList, _multiAnimIndex );
367 }
368
369 // Checks for too many animations - can't do menus with > 12 animations
370 checkMultiAnim( integer _animIndex, string _animName )
371 {
372 list animsList = llParseString2List( llList2String(overrides, _animIndex), [SEPARATOR], [] );
373 if( llGetListLength(animsList) > 12 )
374 llOwnerSay( "You have more than 12 " + _animName + " animations. Please correct this." );
375 }
376
377 checkAnimInInventory( string _csvAnims )
378 {
379 list anims = llCSV2List( _csvAnims );
380 integer i;
381 for( i=0; i<llGetListLength(anims); i++ ) {
382 string animName = llList2String( anims, i );
383 if( llGetInventoryType( animName ) != INVENTORY_ANIMATION ) {
384 // Only a warning, so built-in anims can be used
385 llOwnerSay( "Warning: Couldn't find animation '" + animName + "' in inventory." );
386 }
387 }
388 }
389
390 // Print free memory. Separate function to save a few bytes
391 printFreeMemory()
392 {
393 float memory = (float)llGetFreeMemory() * 100.0 / 16384.0;
394 llOwnerSay( (string)((integer)memory) + "% memory free" );
395 }
396
397 doWater(integer drowning)
398 {
399 if(isUnder == drowning)
400 return;
401 integer n = magicSwim;
402 integer off = 0;
403 if(isUnder = drowning)
404 off = 2 * n;
405
406 integer p;
407 integer po;
408 string anim;
409 string st;
410 while(n--)
411 {
412 po = p = (integer)llGetSubString(magicPos, n * 2, n * 2 + 1);
413 if(isUnder)
414 po = (integer)llGetSubString(magicPos, n * 2 + off, n * 2 + 1 + off);
415 st = llList2String(animState, p);
416 if((anim = llList2String(overrides, po)) == EMPTY)
417 llResetAnimationOverride(st);
418 else
419 doAnimSet(st, anim);
420 }
421 }
422
423 // Load all the animation names from a notecard
424 loadNoteCard() {
425
426 if( llGetInventoryKey(notecardName) == NULL_KEY ) {
427 llOwnerSay( "Notecard '" + notecardName + "' does not exist, or does not have full permissions." );
428 loadInProgress = FALSE;
429 notecardName = EMPTY;
430 return;
431 }
432
433 llOwnerSay( "Loading notecard '" + notecardName + "'..." );
434
435 // Faster events while processing our notecard
436 llMinEventDelay( 0 );
437
438 // Clear out saved override information, since we now allow sparse notecards
439 overrides = [];
440 integer i;
441 for ( i=0; i<numOverrides; i++ )
442 overrides += [EMPTY];
443
444 // Clear out multi-anim info as well, since we may end up with fewer options
445 // that the last time
446 curStandIndex = 0;
447 curStandAnim = EMPTY;
448 curSitAnim = EMPTY;
449 curWalkAnim = EMPTY;
450 curGsitAnim = EMPTY;
451
452 // Start reading the data
453 notecardIndex = 0;
454 notecardLineKey = llGetNotecardLine( notecardName, notecardIndex );
455 }
456
457 // Stop loading notecard
458 endNotecardLoad()
459 {
460 loadInProgress = FALSE;
461 notecardName = EMPTY;
462 }
463
464 // Initialize listeners, and reset some status variables
465 initialize() {
466 Owner = llGetOwner();
467
468 float tevent = 0.0;
469 if(animOverrideOn)
470 tevent = standTime;
471 llSetTimerEvent(tevent);
472 numTicks = 0;
473 maxTicks = llRound(standTime / timerEventLength);
474
475 gotPermission = FALSE;
476
477 // Create new listener, and turn it off
478 if( listenHandle )
479 llListenRemove( listenHandle );
480
481 listenHandle = llListen( listenChannel, EMPTY, Owner, EMPTY );
482 llListenControl( listenHandle, FALSE );
483
484 printFreeMemory();
485 }
486
487 // STATE
488 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
489
490 default {
491 state_entry() {
492 integer i;
493
494 Owner = llGetOwner();
495
496 // Just a precaution, this shouldn't be on after a reset
497 if( listenHandle )
498 llListenRemove( listenHandle );
499
500 listenHandle = llListen( listenChannel, EMPTY, Owner, EMPTY );
501
503 llRequestPermissions(Owner, PERMISSION_OVERRIDE_ANIMATIONS);
504
505 numOverrides = llGetListLength(tokens);
506
507 // populate override list with blanks
508 overrides = [];
509 for ( i=0; i<numOverrides; i++ ) {
510 overrides += [ EMPTY ];
511 }
512 randomStands = FALSE;
513 initialize();
514 notecardName = defaultNoteCard;
515 loadInProgress = TRUE;
516 loadNoteCard();
517 }
518
519 on_rez( integer _code ) {
520 initialize();
521 }
522
523 attach( key _k ) {
524 if(_k != NULL_KEY)
525 llRequestPermissions(Owner, PERMISSION_OVERRIDE_ANIMATIONS);
526 else if(gotPermission)
527 llResetAnimationOverride("ALL");
528 gotPermission = FALSE;
529 }
530
532 if(_perm & PERMISSION_OVERRIDE_ANIMATIONS)
533 {
534 if(animOverrideOn)
535 sendOverrides();
536 gotPermission = TRUE;
537 }
538 }
539
540 link_message( integer _sender, integer _num, string _message, key _id) {
541
542 // Coming from an interface script
543 if( _message == "ZHAO_RESET" ) {
544 llOwnerSay( "Resetting..." );
546
547 } else if( _message == "ZHAO_AOON" ) {
548 animOverrideOn = TRUE;
549 llOwnerSay("AO Enabled.");
550 AO_Enable();
551
552 } else if( _message == "ZHAO_AOOFF" ) {
553 animOverrideOn = FALSE;
554 llOwnerSay("AO Disabled.");
555 AO_Disable();
556
557 } else if( _message == "ZHAO_SITON" ) {
558 // Turning on sit override
559 sitOverride = TRUE;
560 llOwnerSay("Sit override: On");
561 doAnimSet("Sitting", curSitAnim);
562
563 } else if( _message == "ZHAO_SITOFF" ) {
564 // Turning off sit override
565 sitOverride = FALSE;
566 llOwnerSay("Sit override: Off");
567 llResetAnimationOverride("Sitting");
568
569 } else if( _message == "ZHAO_RANDOMSTANDS" ) {
570 // Cycling to next stand - sequential or random
571 randomStands = TRUE;
572 llOwnerSay( "Stand cycling: Random" );
573
574 } else if( _message == "ZHAO_SEQUENTIALSTANDS" ) {
575 // Cycling to next stand - sequential or random
576 randomStands = FALSE;
577 llOwnerSay( "Stand cycling: Sequential" );
578
579 } else if( _message == "ZHAO_SETTINGS" ) {
580 // Print settings
581 if( sitOverride == TRUE ) {
582 llOwnerSay( "Sit override: On" );
583 } else {
584 llOwnerSay( "Sit override: Off" );
585 }
586 if( randomStands == TRUE ) {
587 llOwnerSay( "Stand cycling: Random" );
588 } else {
589 llOwnerSay( "Stand cycling: Sequential" );
590 }
591 llOwnerSay( "Stand cycle time: " + (string)standTime + " seconds" );
592
593 } else if( _message == "ZHAO_NEXTSTAND" ) {
594 // Cycling to next stand - sequential or random. This is from UI, so we
595 // want feedback
596 doNextStand( TRUE );
597
598 } else if( llGetSubString(_message, 0, 14) == "ZHAO_STANDTIME|" ) {
599 // Stand time change
600 maxTicks = llRound((standTime = (integer)llGetSubString(_message, 15, -1)) / timerEventLength);
601 llOwnerSay( "Stand cycle time: " + (string)standTime + " seconds" );
602
603 } else if( llGetSubString(_message, 0, 9) == "ZHAO_LOAD|" ) {
604 // Can't load while we're in the middle of a load
605 if( loadInProgress == TRUE ) {
606 llOwnerSay( "Cannot load new notecard, still reading notecard '" + notecardName + "'" );
607 return;
608 }
609
610 // Notecard menu
611 loadInProgress = TRUE;
612 notecardName = llGetSubString(_message, 10, -1);
613 loadNoteCard();
614
615 } else if( _message == "ZHAO_SITS" ) {
616 // Selecting new sit anim
617
618 // Move these to a common function
619 doMultiAnimMenu( sittingIndex, "Sitting", curSitAnim );
620
621 listenState = 1;
622
623 } else if( _message == "ZHAO_WALKS" ) {
624 // Same thing for the walk
625
626 // Move these to a common function
627 doMultiAnimMenu( walkingIndex, "Walking", curWalkAnim );
628
629 listenState = 2;
630 } else if( _message == "ZHAO_GROUNDSITS" ) {
631 // And the ground sit
632
633 // Move these to a common function
634 doMultiAnimMenu( sitgroundIndex, "Sitting On Ground", curGsitAnim );
635
636 listenState = 3;
637 }
638 }
639
640 listen( integer _channel, string _name, key _id, string _message) {
641 // Turn listen off. We turn it on again if we need to present
642 // another menu
643 llListenControl(listenHandle, FALSE);
644
645 if( listenState == 1 ) {
646 doAnimSet("Sitting", curSitAnim = findMultiAnim(1, (integer)_message - 1));
647 llOwnerSay("New sitting animation: " + curSitAnim);
648
649 } else if( listenState == 2 ) {
650 doAnimSet("Walking", curWalkAnim = findMultiAnim(18, (integer)_message - 1));
651 llOwnerSay("New walking animation: " + curWalkAnim);
652
653 } else if( listenState == 3 ) {
654 doAnimSet("Sitting on Ground", curGsitAnim = findMultiAnim(0, (integer)_message - 1));
655 llOwnerSay("New groundsit animation: " + curGsitAnim);
656 }
657 }
658
659 dataserver( key _query_id, string _data )
660 {
661 if( _query_id != notecardLineKey )
662 return;
663
664 if( _data == EOF )
665 {
666 // Now the read ends when we hit EOF
667
668 // End-of-notecard handling...
669
670 // See how many walks/sits/ground-sits we have
671 checkMultiAnim(18, "walking");
672 checkMultiAnim(1, "sitting");
673
674 // Reset stand, walk, sit and ground-sit anims to first entry
675 curStandIndex = 0;
676 numStands = llGetListLength(llParseString2List(llList2String(overrides, 20), (list)SEPARATOR, [])); //FI
677
678 X curStandAnim = findMultiAnim(20, 0);
679 curWalkAnim = findMultiAnim(18, 0);
680 curSitAnim = findMultiAnim(1, 0);
681
682 endNotecardLoad();
683 llOwnerSay("LSL Functions/AO loaded. Mem:" + (string)llGetFreeMemory());
684
685 return;
686 }
687
688 // We ignore blank lines and lines which start with a #
689 if(_data == EMPTY || llGetSubString(_data, 0, 0) == "#")
690 {
691 notecardLineKey = llGetNotecardLine(notecardName, ++notecardIndex);
692 return;
693 }
694
695 // Let's get a token
696 integer p = llSubStringIndex(_data, "[");
697 string token = EMPTY;
698 string anims = EMPTY;
699 if(p != -1)
700 {
701 if((p = llSubStringIndex(_data = llDeleteSubString(_data, 0, p), "]")) != -1)
702 {
703 token = llStringTrim(llGetSubString(_data, 0, p - 1), STRING_TRIM);
704 anims = llStringTrim(llDeleteSubString(_data, 0, p), STRING_TRIM);
705 if((p = llListFindList(tokens, [token])) == -1)
706 {
707 llOwnerSay("AO:bad data on line " + (string)(notecardIndex+1) + " of " + notecardName + TRYAGAIN); // start from 1
708 endNotecardLoad();
709 return;
710 }
711 }
712 }
713
714 if(anims != EMPTY)
715 {
716 // See if this is a token for which we allow multiple animations
717 if(llSubStringIndex(multiAnimTokenIndexes, "," + (string)p + ",") != -1)
718 { //FI
719 X list anims2Add = llParseString2List(anims, (list)SEPARATOR, []); //FI
720 X // Make sure the anims exist
721 integer k = llGetListLength(anims2Add);
722 while(k--)
723 checkAnimInInventory(llList2String(anims2Add, k));
724
725 // Join the string and list and put it back into overrides
726 overrides = llListReplaceList(overrides, (list)(llList2String(overrides, p) + SEPARATOR + llDumpList2String(anims2Add, SEPARATOR)), p, p ); //FI
727 X }
728 else
729 {
730 // This is an animation for which we only allow one override
731 if(llSubStringIndex(anims, SEPARATOR) != -1)
732 {
733 llOwnerSay("Multiple anims for " + token + " not allowed. " + TRYAGAIN);
734 endNotecardLoad();
735 return;
736 }
737
738 // Inventory check
739 checkAnimInInventory(anims);
740
741 // We're good
742 overrides = llListReplaceList(overrides, (list)anims, p, p); //FI
743 X }
744 }
745
746 // Wow, after all that, we read one line of the notecard
747 notecardLineKey = llGetNotecardLine(notecardName, ++notecardIndex);
748 }
749
750 timer() {
751 vector cur = llGetPos();
752 doWater(cur.z < llWater(ZERO_VECTOR));
753 if(!(numTicks = (numTicks + 1) % maxTicks))
754 {
755 if(llGetAnimation(Owner) == "Standing")
756 doNextStand(FALSE);
757 }
758 }
759 }

Back to the Best Free Tools in Second Life and OpenSim.