list Keys; float configRotTime = 1.0; integer configRotSteps = 2; integer configReverse = 0; integer configRotAngle = 90; string configAxis = "z"; integer configAxisCenter= FALSE; integer configAxisCenterDir = 1; string configAxisCenterAxis = "x"; float configAutoClose = 0.0; float configDistance = 2.0; //integer configCollide = FALSE; integer configSensor = FALSE; string configDouble = ""; string soundOpen = "Door open"; string soundClose = "Door close"; string soundLock = "Lock"; string soundUnlock = "Unlock"; string soundKnock = "Door knock"; integer accessLoaded = FALSE; integer doorLock = FALSE; integer doorClosed = TRUE; integer doorControl = FALSE; key doorActUID = NULL_KEY; float doorActDist = 0.0; float touchTime; float touchDouble = FALSE; integer touchDrag = FALSE; key doubleID = NULL_KEY; integer settingsLine = 0; key settingsKey = NULL_KEY; integer settingsSection = 0; // 1=settings, 2=keys sound(string name) { if (llGetInventoryType(name) == INVENTORY_SOUND) { llPlaySound(name, 1.0); } else if (osIsUUID(name)) { llPlaySound(name, 1.0); } } addKey(string data, integer send) { if (llStringLength(data) > 0) { string name = data; name = llStringTrim(name, STRING_TRIM_HEAD); name = llStringTrim(name, STRING_TRIM_TAIL); if (llGetSubString(name, 0, 0) == "#") return; Keys = Keys + name; if (send) llMessageLinked(LINK_ALL_OTHERS, 1, name, "addkey"); } } string trimString(string data) { if (llStringLength(data) > 0) { data = llStringTrim(data, STRING_TRIM_HEAD); data = llStringTrim(data, STRING_TRIM_TAIL); if (llGetSubString(data, 0, 0) == "#") return ""; else return data; } return ""; } doorMsg(integer status, string part) { if (llStringLength(configDouble) > 0) { llMessageLinked(LINK_ALL_OTHERS, status, configDouble, part); } } lock(integer lock, string name) { if (doorLock != lock) { if (!doorLock) { doorLock = TRUE; doorMsg(doorLock, "lock"); llSay(0, "/me locked."); sound(soundLock); } else { doorLock = FALSE; doorMsg(doorLock, "lock"); llSay(0, "/me unlocked."); sound(soundUnlock); } } } loadSettings() { settingsLine = 0; settingsSection = 0; settingsKey = NULL_KEY; if (loadSettings(1)) { return; } else { loadSettings(2); } } integer loadSettings(integer section) { if (section == 1) { if (llGetInventoryType("Settings") == INVENTORY_NOTECARD) { settingsLine = 0; settingsSection = 1; settingsKey = llGetNotecardLine("Settings", settingsLine); return TRUE; } else { return FALSE; } } else if (section == 2) { if (llGetInventoryType("Access List") == INVENTORY_NOTECARD) { settingsLine = 0; settingsSection = 2; accessLoaded = TRUE; settingsKey = llGetNotecardLine("Access List", settingsLine); return TRUE; } else { Keys = []; accessLoaded = FALSE; llMessageLinked(LINK_ALL_OTHERS, 0, "", "getkeys"); return FALSE; } } return FALSE; } default { state_entry() { state loading; } //collision_start(integer total_number) //{ // if (llDetectedType(0) & AGENT) // if (!doorLock && doorClosed && configCollide) door(); //} } state loading { state_entry() { loadSettings(); } dataserver(key qid, string data) { if (qid == settingsKey) { if (data != EOF) { if (settingsLine == 0 && settingsSection == 2) { Keys = []; llMessageLinked(LINK_ALL_OTHERS, 0, "", "clearkeys"); llSleep(1.0); } data = trimString(data); if (data != "" && llStringLength(data) > 0) { if (settingsSection == 1) { list part = llParseString2List(data, ["="], []); if (llToLower(llList2String(part, 0)) == "time") { if (llList2Float(part, 1) > 0 && llList2Float(part, 1) <= 10) configRotTime = llList2Float(part, 1); } else if (llToLower(llList2String(part, 0)) == "steps") { if (llList2Integer(part, 1) > 0) configRotSteps = llList2Integer(part, 1); } else if (llToLower(llList2String(part, 0)) == "angle") { if (llAbs(llList2Integer(part, 1)) > 0 && llAbs(llList2Integer(part, 1)) < 360) configRotAngle = llList2Integer(part, 1); } else if (llToLower(llList2String(part, 0)) == "axis") { if (llListFindList(["x", "X", "y", "Y", "z", "Z"], llList2List(part, 1, 1)) >= 0) { configAxis = llToLower(llList2String(part, 1)); } } else if (llToLower(llList2String(part, 0)) == "axisoffset") { if (llToLower(llList2String(part, 1)) == "edge") configAxisCenter = FALSE; else if (llToLower(llList2String(part, 1)) == "center") configAxisCenter = TRUE; } else if (llToLower(llList2String(part, 0)) == "axisoffsetbase") { if (llGetSubString(llList2String(part, 1), 0, 0) == "-") { configAxisCenterDir = -1; } else { configAxisCenterDir = 1; } if (llListFindList(["x", "y", "z"], [ llToLower(llGetSubString(llList2String(part, 1), 0, 0)) ]) >= 0) { configAxisCenterAxis = llToLower(llGetSubString(llList2String(part, 1), 0, 0)); } else if (llListFindList(["x", "y", "z"], [ llToLower(llGetSubString(llList2String(part, 1), 1, 1)) ]) >= 0) { configAxisCenterAxis = llToLower(llGetSubString(llList2String(part, 1), 1, 1)); } } else if (llToLower(llList2String(part, 0)) == "autoclose") { if (llList2Float(part, 1) >= 0 && llList2Float(part, 1) <= 300) configAutoClose = llList2Float(part, 1); } else if (llToLower(llList2String(part, 0)) == "touchdist") { if (llList2Float(part, 1) >= 0) { configDistance = llList2Float(part, 1); } else { configDistance = 2.0; } } //else if (llToLower(llList2String(part, 0)) == "collision") { // if (llList2Integer(part, 1) >= 0) // configCollide = llList2Integer(part, 1); //} else if (llToLower(llList2String(part, 0)) == "sensor") { if (llList2Integer(part, 1) >= 1) configSensor = llList2Integer(part, 1); } else if (llToLower(llList2String(part, 0)) == "double_name") { if (llStringLength(llList2String(part, 1)) > 0) { configDouble = llList2String(part, 1); } else { configDouble = ""; } } else if (llToLower(llList2String(part, 0)) == "sound_open") { soundOpen = llList2String(part, 1); } else if (llToLower(llList2String(part, 0)) == "sound_close") { soundClose = llList2String(part, 1); } else if (llToLower(llList2String(part, 0)) == "sound_knock") { soundKnock = llList2String(part, 1); } else if (llToLower(llList2String(part, 0)) == "sound_lock") { soundLock = llList2String(part, 1); } else if (llToLower(llList2String(part, 0)) == "sound_unlock") { soundUnlock = llList2String(part, 1); } } else if (settingsSection == 2) { addKey(data, TRUE); } } if (settingsSection == 1) settingsKey = llGetNotecardLine("Settings", ++settingsLine); else settingsKey = llGetNotecardLine("Access List", ++settingsLine); } else { if (settingsSection == 1) { llSay(0, "Settings loaded."); if (!loadSettings(2)) { if (doorClosed) state closed; else state opened; } } else { llSay(0, "Access List loaded. " + (string)llGetListLength(Keys) + " with access."); if (doorClosed) state closed; else state opened; } } } } } state closed { state_entry() { llPassTouches(0); doorClosed = TRUE; } changed(integer change) { if (change & CHANGED_INVENTORY) { state loading; } } touch_start(integer total_number) { if (configDistance > 0.0) { if (llVecDist(llGetPos(), llDetectedPos(0)) <= configDistance) { llResetTime(); if (touchDrag) touchDrag = FALSE; } } } touch(integer total_number) { if (configDistance > 0.0) { if (llVecDist(llGetPos(), llDetectedPos(0)) <= configDistance) { if (llGetTime() >= 0.25 && !touchDrag) { touchDrag = TRUE; } } } } touch_end(integer total_number) { if (configDistance > 0.0) { if (llVecDist(llGetPos(), llDetectedPos(0)) <= configDistance) { if (touchDrag) { if (llListFindList(Keys, [ llDetectedName(0) ]) > -1) { if (doorLock) lock(FALSE, llDetectedName(0)); else lock(TRUE, llDetectedName(0)); } llSetTimerEvent(0.0); touchDrag = FALSE; } else if (llGetTime() >= 1) { sound(soundKnock); llSay(0, llDetectedName(0) + " knocks."); llSetTimerEvent(0.0); } else { if (!doorLock) { doorControl = TRUE; doorActUID = llDetectedKey(0); doorActDist = llVecDist(llGetPos(), llDetectedPos(0)); state opening; //door(llDetectedKey(0), llVecDist(llGetPos(), llDetectedPos(0))); } else { sound(soundKnock); llSay(0, llDetectedName(0) + " knocks."); } } } } } link_message(integer sender, integer num, string name, key id) { if (llStringLength(configDouble) > 0 && name == configDouble) { if (id == "door") { if (doorControl) return; //llOwnerSay("DEBUG: link_message:door: sender=" + (string)sender + ", num=" + (string)num); if (num == FALSE) state opening; } else if (id == "lock") { doorLock = num; } } if (!accessLoaded) { if (id == "clearkeys") { Keys = []; } else if (id == "addkey") { addKey(name, FALSE); } } else { if (id == "getkeys") { integer i; for (i = 0; i < llGetListLength(Keys); i++) { llMessageLinked(sender, 1, llList2String(Keys, i), "addkey"); } } } } } state opened { state_entry() { llPassTouches(0); doorClosed = FALSE; if (configSensor && doorActUID != NULL_KEY) { if (configAxisCenter) llSensorRepeat("", doorActUID, AGENT, doorActDist + 1.5, TWO_PI, 1.0); else llSensorRepeat("", doorActUID, AGENT, doorActDist + 0.5, TWO_PI, 1.0); llSetTimerEvent(0.0); } else if (configAutoClose > 0.0) { llSetTimerEvent(configAutoClose); } } changed(integer change) { if (change & CHANGED_INVENTORY) { state loading; } } touch_start(integer total_number) { if (configDistance > 0.0) { if (llVecDist(llGetPos(), llDetectedPos(0)) <= configDistance) { llResetTime(); if (touchDrag) touchDrag = FALSE; } } } touch(integer total_number) { if (configDistance > 0.0) { if (llVecDist(llGetPos(), llDetectedPos(0)) <= configDistance) { if (llGetTime() >= 0.25 && !touchDrag) { touchDrag = TRUE; } } } } touch_end(integer total_number) { if (configDistance > 0.0) { if (llVecDist(llGetPos(), llDetectedPos(0)) <= configDistance) { if (touchDrag) { llSetTimerEvent(0.0); llSensorRemove(); touchDrag = FALSE; } else { doorControl = TRUE; state closing; //if (doorClosed) door(llDetectedKey(0), llVecDist(llGetPos(), llDetectedPos(0))); //else door(); } } } } link_message(integer sender, integer num, string name, key id) { if (llStringLength(configDouble) > 0 && name == configDouble) { if (id == "door") { if (doorControl) return; //llOwnerSay("DEBUG: link_message:door: sender=" + (string)sender + ", num=" + (string)num); if (num == TRUE) state closing; } else if (id == "lock") { doorLock = num; } } if (!accessLoaded) { if (id == "clearkeys") { Keys = []; } else if (id == "addkey") { addKey(name, FALSE); } } else { if (id == "getkeys") { integer i; for (i = 0; i < llGetListLength(Keys); i++) { llMessageLinked(sender, 1, llList2String(Keys, i), "addkey"); } } } } no_sensor() { llSensorRemove(); state closing; //door(); } timer() { llSetTimerEvent(0.0); state closing; //if (!doorClosed) door(); } } state closing { state_entry() { integer i; rotation delta; rotation rot = llGetLocalRot(); vector pos = llGetLocalPos(); vector size = llGetScale(); float direction = configRotAngle; vector vPosOffset; vector vPosRotOffset; vector vPosOffsetDiff; vector vPosRotDiff; //llOwnerSay("DEBUG: Door->Close"); doorClosed = TRUE; direction = -configRotAngle; llSetTimerEvent(0.0); llSensorRemove(); //llCollisionFilter("", NULL_KEY, TRUE); if (doorControl) doorMsg(doorClosed, "door"); if (configAxis == "x") delta = llEuler2Rot( * DEG_TO_RAD); else if (configAxis == "y") delta = llEuler2Rot(<0, direction / configRotSteps, 0> * DEG_TO_RAD); else if (configAxis == "z") delta = llEuler2Rot(<0, 0, direction / configRotSteps> * DEG_TO_RAD); if (configAxisCenter) { if (configAxisCenterAxis == "x") vPosOffset.x = (size.x / 2) * configAxisCenterDir; else if (configAxisCenterAxis == "y") vPosOffset.y = (size.y / 2) * configAxisCenterDir; else if (configAxisCenterAxis == "z") vPosOffset.z = (size.z / 2) * configAxisCenterDir; } for (i =0; i < configRotSteps; i++) { rot = delta * rot; pos = llGetLocalPos(); if (configAxisCenter) { vPosRotOffset = vPosOffset * delta; vPosOffsetDiff = vPosOffset - vPosRotOffset; vPosRotDiff = vPosOffsetDiff * llGetLocalRot(); llSetLinkPrimitiveParamsFast(LINK_THIS, [PRIM_POSITION, llGetLocalPos() + (vPosOffset - vPosOffset * delta) * llGetLocalRot(), PRIM_ROT_LOCAL, rot]); } else { llSetLinkPrimitiveParamsFast(LINK_THIS, [PRIM_ROT_LOCAL, rot]); } llSleep(configRotTime / configRotSteps); } sound(soundClose); doorControl = FALSE; state closed; } } state opening { state_entry() { integer i; rotation delta; rotation rot = llGetLocalRot(); vector pos = llGetLocalPos(); vector size = llGetScale(); float direction = configRotAngle; vector vPosOffset; vector vPosRotOffset; vector vPosOffsetDiff; vector vPosRotDiff; //llOwnerSay("DEBUG: Door->Open"); sound(soundOpen); doorClosed = FALSE; direction = configRotAngle; //llCollisionFilter("", NULL_KEY, FALSE); if (doorControl) doorMsg(doorClosed, "door"); if (configAxis == "x") delta = llEuler2Rot( * DEG_TO_RAD); else if (configAxis == "y") delta = llEuler2Rot(<0, direction/configRotSteps, 0> * DEG_TO_RAD); else if (configAxis == "z") delta = llEuler2Rot(<0, 0, direction/configRotSteps> * DEG_TO_RAD); if (configAxisCenter) { if (configAxisCenterAxis == "x") vPosOffset.x = (size.x / 2) * configAxisCenterDir; else if (configAxisCenterAxis == "y") vPosOffset.y = (size.y / 2) * configAxisCenterDir; else if (configAxisCenterAxis == "z") vPosOffset.z = (size.z / 2) * configAxisCenterDir; } for (i =0; i < configRotSteps; i++) { rot = delta * rot; pos = llGetLocalPos(); if (configAxisCenter) { vPosRotOffset = vPosOffset * delta; vPosOffsetDiff = vPosOffset - vPosRotOffset; vPosRotDiff = vPosOffsetDiff * llGetLocalRot(); llSetLinkPrimitiveParamsFast(LINK_THIS, [PRIM_POSITION, llGetLocalPos() + (vPosOffset - vPosOffset * delta) * llGetLocalRot(), PRIM_ROT_LOCAL, rot]); } else { llSetLinkPrimitiveParamsFast(LINK_THIS, [PRIM_ROT_LOCAL, rot]); } llSleep(configRotTime / configRotSteps); } doorControl = FALSE; state opened; } }