// Display the simulator time dilation, as a percentage. integer COMMAND_CHANNEL = 4000; integer gListenerNumber = 0; integer gGot = 0; vector gYouPos = <0,0,0>; integer gTicks = 0; float gCellSize = .3; float gStrutSize = 1.1; //Crystal behavior: // //Scan for victim. If a victim is near, activate... // //From time to time, at longer intervals, choose a random //gridpoint around the victim, +/- 3 cells, and a random //orientation, and go there. // //Keep growing x, less and less, up to 3 * gridsize //Keep growing z, less and less, up to .4 * gridSize // //Gradually turn from green to white // //After a time, stop growing. // //After a time, dis-integrate. float gXSize = .1; float gYSize = .1; float gZSize = .1; float gXMax; float gYMax; float gZMax; integer gDebug = 1; integer gLifeState = 0; integer STATE_NULL = 0; // inert, waiting to start integer STATE_FOLLOWING = 1; integer STATE_FROZEN = 2; integer STATE_FALLING = 3; integer STATE_ENDED = 4; integer gFreezeTicks = 300; integer gFallingTicks = 700; integer gLifeTicks = 1000; float gAlpha = .5; // halftrans. 1 is opaque vector gColor; ///* // * Advance s towards m in a stately random fashion // */ float bumpSize(float s,float m) { float d = m - s; float b = llFrand(d * .2); s += b; return s; } d(list ell) { llOwnerSay((string)ell); } bumpSizes() { if(llFrand(10) < 8) return; llSetStatus(STATUS_PHYSICS + STATUS_PHANTOM,FALSE); gXSize = bumpSize(gXSize,gXMax); gYSize = bumpSize(gYSize,gYMax); gZSize = bumpSize(gZSize,gZMax); llSetScale(); } bumpColoring() { gAlpha = bumpSize(gAlpha,1.0); gColor.x = bumpSize(gColor.x,1.0); gColor.y = bumpSize(gColor.y,1.0); gColor.z = bumpSize(gColor.z,1.0); llSetColor(gColor,ALL_SIDES); llSetAlpha(gAlpha,ALL_SIDES); } float randomGridSpot(float coord) { float r = llFrand(6.9); r = llRound(r - 3.45); r = coord + r * gCellSize; return r; } float randomRot() { return PI * llFloor(llFrand(8)) / 2; } float gMoveOdds = 0; randomPosAndRot() { if(llFrand(10) < gMoveOdds) return; gMoveOdds += llFrand((10 - gMoveOdds) * .5); float x = randomGridSpot(gYouPos.x); float y = randomGridSpot(gYouPos.y); float z = randomGridSpot(gYouPos.z); vector p = ; float rx = randomRot(); float ry = randomRot(); float rz = randomRot(); rotation r = llEuler2Rot(); // llSetPos(p); // llSetRot(r); llSetStatus(STATUS_PHYSICS + STATUS_PHANTOM,TRUE); llRotLookAt(r,1.0,.3 + llFrand(.5)); llMoveToTarget(p,.2 + llFrand(.3)); } freeze() { llSetColor(<1,1,1>,ALL_SIDES); llSetStatus(STATUS_PHYSICS + STATUS_PHANTOM,FALSE); gLifeState = STATE_FROZEN; llSetTimerEvent(.2 + llFrand(.2)); } fall() { llSetColor(< 0.7 , 1.0 , 0.7 >,ALL_SIDES); llSetStatus(STATUS_PHYSICS,TRUE); gLifeState = STATE_FALLING; llStopMoveToTarget(); llStopLookAt(); llSetTimerEvent(.2 + llFrand(.2)); } endOfLife() { llSetColor(< 0.2 , 0.5 , 0.2 >,ALL_SIDES); gLifeState = STATE_ENDED; llSetStatus(STATUS_PHYSICS,FALSE); llSetStatus(STATUS_PHANTOM,TRUE); llSetTimerEvent(0); llSleep(100); if(gDebug) llSetText("llDie();",<.2,.2,.2>,1); else llDie(); } init() { llSetObjectName("white_crystal"); llSetObjectDesc("Do not use cavorite pack above 4000m!"); llCollisionSound("",0); gColor = <.1,1,.2>; gAlpha = 0.5; bumpColoring(); gGot = 0; key victim = ""; victim = llGetOwner(); // only the owner llSensorRepeat("",victim,AGENT,96.0,PI,.5); llSetTimerEvent(.2 + llFrand(.2)); gXSize = .1; gYSize = .1; gZSize = .01; gXMax = gStrutSize * 3; gYMax = gStrutSize * .1; gZMax = gStrutSize * .2; gTicks = 0; llListenRemove(gListenerNumber); gListenerNumber = llListen(COMMAND_CHANNEL,"","",""); // only you gLifeState = STATE_NULL; } doCommand(string message) { list messageL = llParseString2List(message,[" "],[]); string cmd = llToLower(llList2String(messageL,0)); integer arg1 = llList2Integer(messageL,1); string arg1S = llToLower(llList2String(messageL,1)); if(arg1S == "" || arg1S == "on") arg1 = 1; if(cmd == "debug") { gDebug = arg1; d(["memory: ",llGetFreeMemory()]); if(!gDebug) llSetText(" ",<0,0,0>,0); } else if(cmd == "go") { gTicks = 0; gLifeState = STATE_FOLLOWING; llSetTimerEvent(.2 + llFrand(.2)); } else if(cmd == "init") { init(); } else if(cmd == "reset") { llResetScript(); } } default { state_entry() { init(); } sensor(integer k) { // moving triggers them up again... heh heh gGot = 1; vector newPos = llDetectedPos(0); float d = llVecDist(gYouPos,newPos); if(d > 2) { gMoveOdds /= 3.0; // increase movement again! gYouPos = llDetectedPos(0); } } no_sensor() { gGot = 0; } touch_start(integer k) { init(); } timer() { if(gDebug) { string s = (string)[gTicks,"\nstate:",gLifeState]; llSetText(s,<1,1,1>,1); } gTicks++; if(gLifeState == STATE_FOLLOWING) { if(gGot) { bumpSizes(); randomPosAndRot(); } // time to freeze? if(gTicks >= gFreezeTicks) freeze(); } if(gLifeState == STATE_FROZEN) { bumpSizes(); bumpColoring(); if(gTicks >= gFallingTicks) fall(); } if(gLifeState == STATE_FALLING) { vector here = llGetPos(); if(gTicks >= gLifeTicks) endOfLife(); } } // safety! short utterance on command channel stops it. listen(integer channel,string name,key id,string message) { if(llStringLength(message) > 1) doCommand(message); else endOfLife(); } }