User:Hidenori Glushenko/SmoothOpeningDoor
Jump to navigation
Jump to search
DoorInit
<lsl> /**
* door-init.lsl * Released into the public domain by Hidenori Glushenko */
default {
state_entry() { list params = llGetPrimitiveParams([PRIM_TYPE]); params = llListReplaceList(params,[<0.125,0.625,0.0>],2,2); llSetPrimitiveParams([PRIM_TYPE]+params+[PRIM_SIZE,<1.6,2.0,0.05>]); llRemoveInventory(llGetScriptName()); }
}</lsl>
SmoothOpeningDoor
<lsl> /*-------------------------------------------------------------------
* Smooth opening door script * This door opens toward the directrion opposit to the avatar's pos. * Released into the public domain by Hidenori Glushenko *------------------------------------------------------------------- * Please initialise your prim's share using door_init.lsl *------------------------------------------------------------------- */
rotation DOOR_ROT_ORG; // base rotation float DOOR_DIV_EULER = 150.0; // open angle float DOOR_OPEN_SEC = 10.0; // open time(seconds) float DOOR_MOVE_TARGET; integer TIMER_COUNT; integer TIMER_MAX = 40; // open speed
// larger is slower
/**
* @state default state : initialize prim's status */
default {
state_entry() { llSetBuoyancy(1.0); llMinEventDelay( 0.01 ); llSetStatus(STATUS_PHANTOM, FALSE); llSetStatus(STATUS_BLOCK_GRAB, TRUE); state DoorClose; }
}
/**
* @state closed state */
state DoorClose {
touch_start(integer total_number) { DOOR_ROT_ORG = llGetRot(); // check the touched avatar's position vector av_offset = (llDetectedPos(0)-llGetPos())/DOOR_ROT_ORG; float av_offset_z = av_offset.z; // calculate the angle depend on the avatar's pos DOOR_MOVE_TARGET = (av_offset_z/llFabs(av_offset_z)) *DOOR_DIV_EULER; state DoorOpen; }
}
/**
* @state opening-opened-closing state */
state DoorOpen {
state_entry() { TIMER_COUNT = 0; llSetTimerEvent(0.05); llSetStatus(STATUS_PHANTOM, TRUE); // set phantom } state_exit() { llSetStatus(STATUS_PHANTOM, FALSE); // set non-phantom when leaving this state llSetTimerEvent(0.0); } touch_start(integer total_number) { // restart timer llSetTimerEvent(0.05); } timer() { rotation rot; ++TIMER_COUNT; // count up // If counter indicates starting door-close if (TIMER_COUNT == TIMER_MAX + 1) { llSetStatus(STATUS_PHANTOM, TRUE); // set phantom llSetTimerEvent(0.05); } // calculate door-angle from counter float x = PI_BY_TWO*TIMER_COUNT/(float)TIMER_MAX; // calculate x(means the ratio) float new_rot_euler = DOOR_MOVE_TARGET * llPow(llSin(x), 2.0); // calculate angle llRotLookAt(rot = (llEuler2Rot(<0.0,new_rot_euler,0.0> *DEG_TO_RAD))*DOOR_ROT_ORG,1.0,1.0); // set door angle // stop when opened if (TIMER_COUNT == TIMER_MAX) { // switch timer to the 'open-time' llSetTimerEvent(DOOR_OPEN_SEC); llSleep(0.2); llSetStatus(STATUS_PHANTOM, FALSE); // set non-phantom when opened llSetStatus(STATUS_PHYSICS, TRUE); // force update rotation llSetStatus(STATUS_PHYSICS, FALSE); // force update rotation llSetRot(rot); // go to close state when closed } else if (TIMER_COUNT >= (TIMER_MAX*2)) { llSleep(0.2); llSetStatus(STATUS_PHYSICS, TRUE); // force update rotation llSetStatus(STATUS_PHYSICS, FALSE); // force update rotation llSetRot(DOOR_ROT_ORG); state DoorClose; } }
}</lsl>