571 lines
20 KiB
Plaintext
571 lines
20 KiB
Plaintext
|
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.");
|
||
|
loadSettings(2);
|
||
|
} else {
|
||
|
llSay(0, "Access List loaded. " + (string)llGetListLength(Keys) + " with access.");
|
||
|
if (doorClosed) state closed;
|
||
|
else state opened;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
state closed
|
||
|
{
|
||
|
state_entry()
|
||
|
{
|
||
|
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()
|
||
|
{
|
||
|
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_end(integer total_number)
|
||
|
{
|
||
|
if (configDistance > 0.0) {
|
||
|
if (llVecDist(llGetPos(), llDetectedPos(0)) <= configDistance) {
|
||
|
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(<direction / configRotSteps, 0, 0> * 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(<direction/configRotSteps, 0, 0> * 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;
|
||
|
}
|
||
|
}
|
||
|
|