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>