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 AO  

AO

Animation Overrider

Category: AO
By : Francis Chung
Created: 2013-09-06 Edited: 2013-09-07
Worlds: Second Life

the Zip file

Download all files for AO
Contents are in zip format, with .LSL (text) source code and LSLEdit (text + Solution) formats.
Get file # 1. Ao-2.lsl
Get file # 2. Ao-seal.lsl
Get file # 3. Notecard.txt
Get file # 4. Notes.txt
Get file # 5. Script.lsl
1
2
3 // Francis wuz here
4 // For tech support, please contact one of our generous volounteers:
5 // Support Help:
6 // Second Life: Gwyneth Llewelyn
7 // Email: gwyneth.llewelyn@secondlife.game-host.org
8 // MSN: gwyneth.llewelyn@secondlife.game-host.org
9 // Yahoo: gwyneth_llewelyn
10 // Second Life: Ulrika Zugzwang
11
12 // Franimation Overrider v1.5
13 // Copyright (C) 2004 Francis Chung
14 //
15 // This program is free software; you can redistribute it and/or modify
16 // it under the terms of the GNU General Public License as published by
17 // the Free Software Foundation; either version 2 of the License, or
18 // (at your option) any later version.
19 //
20 // This program is distributed in the hope that it will be useful,
21 // but WITHOUT ANY WARRANTY; without even the implied warranty of
22 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23 // GNU General Public License for more details.
24
25 // You should have received a copy of the GNU General Public License
26 // along with this program; if not, write to the Free Software
27 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
28
29
30 // Special thanks to Gwyneth Llewyn and Kex Godel for their technical
31 // suggestions and contributions, as well as their heroic documentation
32 // efforts.
33
34 // I would also like to take the time here to recognize Archanox Underthorn
35 // as the creator of the original animation override.
36
37 // Mods to fix Opensim Crap by Ferd Frederix
38
39
40
41 // CONSTANTS
42 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
43 // Default notecard we read on script_entry
44 integer debug = TRUE;
45 string defaultNoteCard = "Animation Notecard";
46
47 // Instruction notecard
48 string instructionNoteCard = "Manual";
49
50 // Anything we hear through a listen() even will be relayed on this linkmessage channel
51 integer listenRelay = 0x80000000;
52
53 // List of all the animation states
54 list animState = ["Sitting on Ground", "Sitting", "Striding", "Crouching", "CrouchWalking",
55 "Soft Landing", "Standing Up", "Falling Down", "Hovering Down", "Hovering Up",
56 "FlyingSlow", "Flying", "Hovering", "Jumping", "PreJumping", "Running",
57 "Turning Right", "Turning Left", "Walking", "Landing", "Standing" ];
58
59 // Animations in which we automatically disable animation overriding
60 // Try to keep this list short, the longer it is the worse it affects our runtime
61 // (Note: This is *almost* constant. We have to type-convert this to keys instead of strings
62 // on initialization - blargh)
63 list autoDisableList ;
64
65
66 // Index of interesting animations
67 integer noAnimIndex = -1;
68 integer standIndex = 20;
69 integer sittingIndex = 1;
70 integer sitgroundIndex = 0;
71 integer hoverIndex = 12;
72 integer flyingIndex = 11;
73 integer flyingslowIndex = 10;
74 integer hoverupIndex = 9;
75 integer hoverdownIndex = 8;
76 integer waterTreadIndex = 25;
77 integer swimmingIndex = 26;
78 integer swimupIndex = 27;
79 integer swimdownIndex = 28;
80 integer standingupIndex = 6;
81
82 // list of animations that have a different value when underwater
83 list underwaterAnim ;
84
85 // corresponding list of animations that we override the overrider with when underwater
86 list underwaterOverride ;
87
88 // list of animation states that we need to stop the default animations for
89 //list stopAnimState = [ "Sitting" ];
90 list stopAnimState = [ ];
91
92 // corresponding list of animations to stop when entering that state
93 //list stopAnimName = [ "sit" ];
94 list stopAnimName = [ ];
95
96 // Lines in the notecards where to grab animation names
97 // This list is indexed the same as list overrides
98 list lineNums = [ 45, // 0 Sitting on Ground
99 33, // 1 Sitting
100 1, // 2 Striding
101 17, // 3 Crouching
102 5, // 4 CrouchWalking
103 39, // 5 Soft Landing
104 41, // 6 Standing Up
105 37, // 7 Falling Down
106 19, // 8 Hovering Down
107 15, // 9 Hovering Up
108 43, // 10 FlyingSlow
109 7, // 11 Flying
110 31, // 12 Hovering
111 13, // 13 Jumping
112 35, // 14 PreJumping
113 3, // 15 Running
114 11, // 16 Turning Right
115 9, // 17 Turning Left
116 1, // 18 Walking
117 39, // 19 Landing
118 21, // 20 Standing 1
119 23, // 21 Standing 2
120 25, // 22 Standing 3
121 27, // 23 Standing 4
122 29, // 24 Standing 5
123 47, // 25 Treading Water
124 49, // 26 Swimming
125 51, // 27 Swim up
126 43 // 28 Swim Down
127 ];
128
129 // This is an ugly hack, because the standing up animation doesn't work quite right
130 // (SL is borked, this has been bug reported)
131 // If you play a pose overtop the standing up animation, your avatar tends to get
132 // stuck in place.
133 // This is a list of anims that we'll stop automatically
134 list autoStop = [ 5, 6, 19 ];
135 // Amount of time we'll wait before autostopping the animation (set to 0 to turn off autostopping )
136 float autoStopTime = 1.5;
137
138 // List of stands
139 list standIndexes = [ 20, 21, 22, 23, 24 ];
140
141 // How long before flipping stand animations
142 float standTimeDefault = 40.0;
143
144 // Command prefixes we accept
145 list loadCmd = [ "animset ", "/animset " ];
146 list animCmd = [ "ao ", "/ao " ];
147
148 // How fast we should poll for changed anims (as fast as possible)
149 // In practice, you will not poll more than 8 times a second.
150 float timerEventLength = 0.001;
151
152 // The key for the typing animation
153 key typingAnim = "c541c47f-e0c0-058b-ad1a-d6ae3a4584d9";
154
155 // Kex likes the following behaviour:
156 // - When you switch to a standing pose, start again from the beginning of the stand list
157 // - when you switch to a standing pose, don't override with an animation for 5 seconds
158 integer kexMode = FALSE;
159 float kexTime = 5;
160
161 // Send a message if we encounter a state we've never seen before
162 integer DEBUG = FALSE;
163
164 // GLOBALS
165 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
166
167 list stands = [ "", "", "", "", "" ]; // List of stand animations
168 integer curStandIndex = 0; // Current stand we're on (indexed [0, numStands])
169 string curStandAnim = ""; // Current Stand animation
170 integer numStands; // # of stand anims we use (constant: ListLength(stands))
171 integer curStandAnimIndex = 0; // Current stand we're on (indexed [0, numOverrides] )
172
173 list overrides = []; // List of animations we override
174 list notecardLineKey = []; // notecard reading keys
175 integer notecardLinesRead; // number of notecard lines read
176 integer numOverrides; // # of overrides (a constant - llGetListLength(lineNums))
177
178 string lastAnim = ""; // last Animation we ever played
179 integer lastAnimIndex = 0; // index of the last animation we ever played
180 string lastAnimState = ""; // last thing llGetAnimation() returned
181
182 float standTime ; // How long before flipping stand animations
183
184 integer animOverrideOn = TRUE; // Is the animation override on?
185 integer gotPermission = FALSE; // Do we have animation permissions?
186
187 integer listenHandler0; // Listen handlers
188 integer listenHandler1;
189
190 string stopLeftOverAnim = ""; // Hack to get around LSL goofiness
191
192 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
193
194 // This would be totally unecessary if we had arrays
195 // _source[_index] = newEntry
196 list listReplace ( list _source, list _newEntry, integer _index ) {
197 return llListInsertList( llDeleteSubList(_source,_index,_index), _newEntry, _index );
198 }
199
200 // Find if two lists/sets share any elements in common
201 integer hasIntersection( list list1, list list2 ) {
202 list bigList;
203 list smallList;
204 integer smallListLength;
205 integer i;
206
207 if( llGetListLength( list1 ) <= llGetListLength( list2 ) ) {
208 smallList = list1;
209 bigList = list2;
210 }
211 else {
212 bigList = list1;
213 smallList = list2;
214 }
215 smallListLength = llGetListLength( smallList );
216
217 for ( i=0; i<smallListLength; i++ ) {
218 if( llListFindList( bigList, llList2List(smallList,i,i) ) != -1 ) {
219 return TRUE;
220 }
221 }
222
223 return FALSE;
224 }
225
226 startAnimationList( string csvAnims ) {
227 list anims = llCSV2List( csvAnims );
228 integer numAnims = llGetListLength( anims );
229 integer i;
230 for( i=0; i<numAnims; i++ )
231 {
233 if(debug) llOwnerSay(llList2String(anims,i) );
234 }
235 }
236
237 stopAnimationList( string csvAnims ) {
238 list anims = llCSV2List( csvAnims );
239 integer numAnims = llGetListLength( anims );
240 integer i;
241 for( i=0; i<numAnims; i++ ) {
242 if(debug) llOwnerSay("stop " + llList2String(anims,i) );
244 }
245 }
246
247 startNewAnimation( string _anim, integer _animIndex, string _state ) {
248 if( _anim != lastAnim ) {
249
250 if( _anim != "" ) { // Time to play a new animation
251 startAnimationList( _anim );
252
253 if( _state != lastAnimState && llListFindList(stopAnimState, [_state]) != -1 ) {
254 // Stop the default sit/sit ground animation
255 llStopAnimation( llList2String(stopAnimName, llListFindList(stopAnimState, [_state])) );
256 if(debug) llOwnerSay( "stop " + llList2String(stopAnimName, llListFindList(stopAnimState, [_state])) );
257 }
258 else if( llListFindList( autoStop, [_animIndex] ) != -1 ) {
259 // This is an ugly hack, because the standing up animation doesn't work quite right
260 // (SL is borked, this has been bug reported)
261 // If you play a pose overtop the standing up animation, your avatar tends to get
262 // stuck in place.
263 if( lastAnim != "" ) {
264 stopAnimationList( lastAnim );
265 lastAnim = "";
266 }
267 llSleep( autoStopTime );
268 stopAnimationList( _anim );
269 }
270 }
271 if( lastAnim != "" )
272 stopAnimationList( lastAnim );
273 lastAnim = _anim;
274 }
275 lastAnimIndex = _animIndex;
276 lastAnimState = _state;
277 }
278
279 // Load all the animation names from a notecard
280 loadNoteCard( string _notecard ) {
281 integer i;
282
283 if( llGetInventoryKey(_notecard) == NULL_KEY ) {
284 llSay( 0, "Notecard '" + _notecard + "' does not exist." );
285 return;
286 }
287
288 llInstantMessage( llGetOwner(), "Loading notecard '" + _notecard + "'..." );
289 // Start reading the data
290 notecardLinesRead = 0;
291 notecardLineKey = [];
292 for ( i=0; i<numOverrides; i++ )
293 notecardLineKey += [ llGetNotecardLine( _notecard, llList2Integer(lineNums,i) ) ];
294 }
295
296 // Check if any of the list of elements causes a prefix match. If they do, return argv[1], otherwise ""
297 // Used for parsing verbal commands
298 string checkMatch( string str, list prefixes ) {
299 integer numElements = llGetListLength( prefixes );
300 integer i;
301 integer lastChar;
302 string curPrefix;
303 string curStr = llToLower( str );
304
305 // Check against all the list to see if the prefix (argv[0]) matches
306 for( i=0; i<numElements; i++ ) {
307 curPrefix = llList2String(prefixes, i);
308 lastChar = llStringLength( curPrefix ) - 1;
309 if( llGetSubString(curStr, 0, lastChar) == curPrefix )
310 return llGetSubString( str, lastChar+1, llStringLength(str) );
311 }
312 return "";
313 }
314
315 // Figure out what animation we should be playing right now
316 animOverride() {
317 string curAnimState = llGetAnimation(llGetOwner());
318 integer curAnimIndex;
319 integer underwaterAnimIndex;
320 vector curPos;
321
322 // Hack, because, SL really likes to switch between crouch and crouchwalking for no reason
323 if( curAnimState == "CrouchWalking" ) {
324 if( llVecMag(llGetVel()) < .5 )
325 curAnimState = "Crouching";
326 }
327
328 if( curAnimState == lastAnimState ) {
329 // This conditional not absolutely necessary (In fact it's better if it's not here)
330 // But it's good for increasing performance.
331 // One of the drawbacks of this performance hack is the underwater animations
332 // If you fly up, it will keep playing the "swim up" animation even after you've
333 // left the water.
334 return;
335 }
336
337 curAnimIndex = llListFindList( animState, [curAnimState] );
338 underwaterAnimIndex = llListFindList( underwaterAnim, [curAnimIndex] );
339 curPos = llGetPos();
340
341 if( curAnimIndex == -1 ) {
342 if( DEBUG )
343 llInstantMessage( llGetOwner(), "Unknown animation state '" + curAnimState + "'" );
344 }
345 else if( curAnimIndex == standIndex ) {
346 if( kexMode ) {
347 if( lastAnimIndex != standIndex ) {
348 resetStand();
349 standTime = kexTime;
350 }
351 }
352 startNewAnimation( curStandAnim, curStandAnimIndex, curAnimState );
353 }
354 else {
355 if( underwaterAnimIndex != -1 && llWater(ZERO_VECTOR) > curPos.z )
356 curAnimIndex = llList2Integer( underwaterOverride, underwaterAnimIndex );
357 startNewAnimation( llList2String(overrides,curAnimIndex), curAnimIndex, curAnimState );
358 }
359 }
360
361 // For kexMode
362 // Reset to a non-override (last index)
363 resetStand() {
364 curStandIndex = numStands - 1;
365 curStandAnimIndex = llList2Integer(standIndexes,curStandIndex);
366 curStandAnim = "";
368 }
369
370
371 // Switch to the next stand anim
372 doNextStand() {
373 if( kexMode ) {
374 // Make sure we reset to a reasonable stand time
375 standTime = standTimeDefault;
376 }
377 curStandIndex = (curStandIndex+1) % numStands;
378 curStandAnimIndex = llList2Integer(standIndexes,curStandIndex);
379 curStandAnim = llList2String(overrides, curStandAnimIndex);
380 if( lastAnimState == "Standing" )
381 startNewAnimation( curStandAnim, curStandAnimIndex, lastAnimState );
383 }
384
385 // Returns true if we should override the current animation
386 integer shouldOverride() {
387 if( animOverrideOn && gotPermission ) {
388 // Check if we should explicitly NOT override a playing animation
389 if( hasIntersection( autoDisableList, llGetAnimationList(llGetOwner()) ) ) {
390 startNewAnimation( "", noAnimIndex, "" );
391 return FALSE;
392 }
393 return TRUE;
394 }
395 return FALSE;
396 }
397
398 // Initialize listeners, and reset some status variables
399 initialize() {
400 if( animOverrideOn )
401 llSetTimerEvent( timerEventLength );
402 else
403 llSetTimerEvent( 0 );
404
405 // Stop this animation after we regain animation permissions
406 // LSL can be a bit gooofy, because you can teleport somewhere, and have animation permissions
407 // on arrival. Not entirely sure if this is by design, or what, but I'll use a conservative
408 // work-around to this issue.
409 stopLeftOverAnim = lastAnim;
410
411 lastAnim = "";
412 lastAnimIndex = noAnimIndex;
413 lastAnimState = "";
414 gotPermission = FALSE;
415
416 if( listenHandler0 )
417 llListenRemove( listenHandler0 );
418 listenHandler0 = llListen( 0, "", llGetOwner(), "" );
419 if( listenHandler1 )
420 llListenRemove( listenHandler1 );
421 listenHandler1 = llListen( 1, "", llGetOwner(), "" );
422
423 llInstantMessage( llGetOwner(), (string) llGetFreeMemory() + " bytes free" );
424 }
425
426 // STATE
427 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
428
429 default {
430 state_entry() {
431
432 standTime = standTimeDefault;
433 underwaterAnim = [ hoverIndex, flyingIndex, flyingslowIndex, hoverupIndex, hoverdownIndex ];
434 underwaterOverride = [ waterTreadIndex, swimmingIndex, swimmingIndex, swimupIndex, swimdownIndex];
435 autoDisableList = [
436 "3147d815-6338-b932-f011-16b56d9ac18b", // aim_R_handgun
437 "ea633413-8006-180a-c3ba-96dd1d756720", // aim_R_rifle
438 "b5b4a67d-0aee-30d2-72cd-77b333e932ef", // aim_R_bazooka
439 "46bb4359-de38-4ed8-6a22-f1f52fe8f506", // aim_l_bow
440 "9a728b41-4ba0-4729-4db7-14bc3d3df741", // Launa's hug
441 "f3300ad9-3462-1d07-2044-0fef80062da0", // punch_L
442 "c8e42d32-7310-6906-c903-cab5d4a34656", // punch_r
443 "85428680-6bf9-3e64-b489-6f81087c24bd", // sword_strike_R
444 "eefc79be-daae-a239-8c04-890f5d23654a" // punch_onetwo
445 ];
446
447
448 integer i;
449
450 if( llGetAttached() )
452
453 // Initialize!
454 numStands = llGetListLength( stands );
455 numOverrides = llGetListLength(lineNums);
456 curStandAnimIndex = llList2Integer(standIndexes,curStandIndex);
457
458 // Type convert strings to keys :P
459 for ( i=0; i<llGetListLength(autoDisableList); i++ ) {
460 key k = llList2Key( autoDisableList, i );
461 autoDisableList = listReplace ( autoDisableList, [ k ], i );
462 }
463
464 // populate override list with blanks
465 for ( i=0; i<numOverrides; i++ ) {
466 overrides += [ "" ];
467 }
468 initialize();
469 loadNoteCard( defaultNoteCard );
470
471 // turn off the auto-stop anim hack
472 if( autoStopTime == 0 )
473 autoStop = [];
474
476 }
477
482 gotPermission = TRUE;
483 if( stopLeftOverAnim != "" )
484 stopAnimationList( stopLeftOverAnim );
485 }
486 }
487
488 attach( key _k ) {
489 if( _k != NULL_KEY )
491 }
492
493 listen( integer _channel, string _name, key _id,string _message ) {
494 string match;
495
496 // Send a link message to all other scripts, so they don't have to use a listen
497 llMessageLinked( LINK_SET, listenRelay, _message, _id );
498
499 match = checkMatch( _message, loadCmd );
500 if( match != "" )
501 loadNoteCard( match );
502 match = checkMatch( _message, animCmd );
503 if( match == "on" ) {
504 llSetTimerEvent( timerEventLength );
505 animOverrideOn = TRUE;
506 if( gotPermission )
507 animOverride();
508 llInstantMessage( llGetOwner(), "Franimation override on." );
509 }
510 else if( match == "off" ) {
511 llSetTimerEvent( 0 );
512 animOverrideOn = FALSE;
513 startNewAnimation( "", noAnimIndex, lastAnimState );
514 llInstantMessage( llGetOwner(), "Franimation override off." );
515 }
516 else if( match == "hide" ) {
518 llInstantMessage( llGetOwner(), "Franimation override set invisible." );
519 }
520 else if( match == "show" ) {
522 llInstantMessage( llGetOwner(), "Franimation override set visible." );
523 }
524 else if( match == "nextstand" ) {
525 if( animOverrideOn && gotPermission )
526 doNextStand();
527 }
528 else if( match == "reset" ) {
530 }
531 }
532
533 dataserver( key _query_id, string _data ) {
534 integer index = llListFindList( notecardLineKey, [_query_id] );
535 if( _data != EOF && index != -1 ) { // not at the end of the notecard and not random crap
536 if( index == curStandAnimIndex ) // Pull in the current stand animation
537 curStandAnim = _data;
538
539 // Whoops, we're replacing the currently playing anim
540 if( animOverrideOn && gotPermission && index == lastAnimIndex ) {
541 integer stopAnim;
542
543 // Better play the new one :)
544 startNewAnimation( _data, lastAnimIndex, lastAnimState );
545
546 // If we're not override an animation we've explicitly stopped, we
547 // had better replay the explicitly stopped animation
548 if( _data != "" ) {
549 stopAnim = llListFindList( stopAnimState, [ lastAnimState ] );
550 if( stopAnim != -1 )
551 {
552 if(debug) llOwnerSay(llList2String(stopAnimName,stopAnim) );
553 llStartAnimation( llList2String(stopAnimName, stopAnim) );
554 }
555 }
556 }
557
558 // Store the name of the new animation
559 overrides = listReplace( overrides, [_data], index );
560
561 // See if we're done loading the notecard. Users like status messages.
562 if( ++notecardLinesRead == numOverrides )
563 llInstantMessage( llGetOwner(), "Finished reading notecard. (" +
564 (string) llGetFreeMemory() + " bytes free)" );
565 }
566 }
567
568 on_rez( integer _code ) {
569 initialize();
570 }
571
572 control( key _id, integer _level, integer _edge ) {
573 if( shouldOverride() )
574 animOverride();
575 }
576
577 touch_start( integer _num ) {
578 llGiveInventory( llDetectedKey(0), instructionNoteCard );
579 }
580
581 timer() {
582 if( shouldOverride() ) {
583 animOverride();
584
585 // Is it time to switch stand animations?
586 if( llGetTime() > standTime ) {
587 // Don't interupt the typing animation with a stand change
588 if( llListFindList(llGetAnimationList(llGetOwner()), [typingAnim]) == -1 )
589 doNextStand();
590 }
591 }
592 }
593 }

AO

AO

Category: AO
By : Francis Chung
Created: 2013-09-06 Edited: 2013-09-07
Worlds: Second Life

1 :: [ Walking (also Striding) ] ::
2 Tiger Walk Fast
3 :: [ Running ] ::
4 Tiger Walk Fast
5 :: [ CrouchWalking ] ::
6 Tiger Walk
7 :: [ Flying (also FlyingSlow) ] ::
8 Fly
9 :: [ Turning Left ] ::
10 Tiger Walk Fast
11 :: [ Turning Right ] ::
12 Tiger Walk Fast
13 :: [ Jumping ] ::
14 Tiger Walk Fast
15 :: [ Hovering Up ] ::
16 Fly
17 :: [ Crouching ] ::
18 Tiger Growl
19 :: [ Fly Down ] ::
20 Fly
21 :: [ Standing 1 ] ::
22 Tiger Stand
23 :: [ Standing 2 ] ::
24 Tiger Stand
25 :: [ Standing 3 ] ::
26 Tiger Stand
27 :: [ Standing 4 ] ::
28 Tiger Stand
29 :: [ Standing 5 ] ::
30 Fidgit
31 :: [ Hovering ] ::
32 hovering
33 :: [ Sitting ] ::
34 Tiger Sit
35 :: [ PreJumping ] ::
36 Tiger Stand
37 :: [ Falling ] ::
38 hovering
39 :: [ Soft Landing/Landing ] ::
40 hovering
41 :: [ Standing Up (That anim you play after you fall when you stand up and brush yourself off) ] ::
42 Tiger Stand
43 :: [ FlyingSlow ] ::
44 Fly
45 :: [ Sitting on Ground ] ::
46 Tiger Sitting on ground
47 :: [ Floating (Hovering underwater) ] ::
48 hovering
49 :: [ Swimming Forward (Flying underwater) ] ::
50 hovering
51 :: [ Swimming Up (Hover Up underwater) ] ::
52 hovering
53 :: [ Swimming Down (Fly Down underwater) ] ::
54 hovering

AO

AO Notecard

Category: AO
By : Francis Chung
Created: 2013-09-06 Edited: 2013-09-07
Worlds: Second Life

1 Need typing anim
2
3 GLitch in start walkL:
4
5 [12:50] Tiger AO: Tiger Walk Fast
6 [12:50] Tiger AO: stop Fidgit
7 [12:50] Tiger AO: Fidgit
8 [12:50] Tiger AO: stop Tiger Walk Fast

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