Look at this script. I wrote this script to handle placeable doors and its given into OnUsed event:
(note not possible to compile without my custom include with EVENT_ constants)
void LockAtClose(object oDoor);
void main()
{
object oPC = GetLastUsedBy();
object oDoor = OBJECT_SELF;
SignalEvent(oDoor,EventUserDefined(EVENT_PLACEABLE_DOOR_ON_USED));
if(!GetIsTrapped(oDoor))
{
if(GetLocked(oDoor))
{
string sKey = GetTrapKeyTag(oDoor);
object oKey = GetItemPossessedBy(oPC,sKey);
if(sKey != "" && GetIsObjectValid(oKey))
{
SendMessageToPC(oPC,GetStringByStrRef(7945));
SetLocked(oDoor,FALSE);
}
else
{
DelayCommand(0.1,PlaySound("as_dr_locked2"));
FloatingTextStringOnCreature("*"+GetStringByStrRef(8307)+"*",oPC);
SendMessageToPC(oPC,GetStringByStrRef(8296));
SignalEvent(oDoor,EventUserDefined(EVENT_PLACEABLE_DOOR_ON_FAILEDTOOPEN));
return;
}
}
if(!GetLocalInt(oDoor,"IS_OPEN"))
{
AssignCommand(oPC,ActionPlayAnimation(ANIMATION_LOOPING_GET_MID));
DelayCommand(1.0,ActionPlayAnimation(ANIMATION_PLACEABLE_OPEN));
SetLocalInt(oDoor,"IS_OPEN",TRUE);
SignalEvent(oDoor,EventUserDefined(EVENT_PLACEABLE_DOOR_ON_OPEN));
if(GetLocalInt(oDoor,"DOORCLOSE") > -1)
{
int Delay = GetLocalInt(oDoor,"DOORCLOSE_DELAY");
float fDelay = IntToFloat(Delay);
if(!Delay)
{
fDelay = 7.0;
}
DelayCommand(fDelay,ActionPlayAnimation(ANIMATION_PLACEABLE_CLOSE));
DelayCommand(fDelay,LockAtClose(oDoor));
DelayCommand(fDelay,SignalEvent(oDoor,EventUserDefined(EVENT_PLACEABLE_DOOR_ON_CLOSE)));
DelayCommand(fDelay,DeleteLocalInt(oDoor,"IS_OPEN"));
}
int iDoorLock = GetLocalInt(oDoor,"DOORLOCK");
if(iDoorLock > 0 && !GetLocked(oDoor))
{
int isDay = GetIsDay();
if(iDoorLock == 6 || !isDay && iDoorLock == 4 || isDay && iDoorLock == 5)
{
SetLocked(oDoor,TRUE);
}
}
}
else
{
object oTarget = GetObjectByTag(GetLocalString(oDoor,"DOORTARGET"));
if(!GetIsObjectValid(oTarget))
{
return;
}
object oOppositeDoor;
string sTag = GetLocalString(oDoor,"DOOR");
if(sTag == "")
{
oOppositeDoor = GetNearestObject(OBJECT_TYPE_DOOR,oOppositeDoor);
}
else
{
oOppositeDoor = GetObjectByTag(sTag);
}
if(GetLocalInt(oOppositeDoor,"DOOROPEN") != -1)
{
if(!GetIsOpen(oOppositeDoor))
{
ActionOpenDoor(oOppositeDoor);
}
}
AssignCommand(oPC,ClearAllActions());
AssignCommand(oPC,JumpToObject(oTarget));
if(GetArea(oTarget) == GetArea(oDoor))
{
object oHenchman = GetAssociate(ASSOCIATE_TYPE_FAMILIAR,oPC);
if(GetIsObjectValid(oHenchman))
{
AssignCommand(oHenchman,JumpToObject(oTarget));
}
oHenchman = GetAssociate(ASSOCIATE_TYPE_ANIMALCOMPANION,oPC);
if(GetIsObjectValid(oHenchman))
{
AssignCommand(oHenchman,JumpToObject(oTarget));
}
oHenchman = GetAssociate(ASSOCIATE_TYPE_SUMMONED,oPC);
if(GetIsObjectValid(oHenchman))
{
AssignCommand(oHenchman,JumpToObject(oTarget));
}
oHenchman = GetAssociate(ASSOCIATE_TYPE_DOMINATED,oPC);
int counter = 1;
while(GetIsObjectValid(oHenchman))
{
AssignCommand(oHenchman,JumpToObject(oTarget));
oHenchman = GetAssociate(ASSOCIATE_TYPE_DOMINATED,oPC,++counter);
}
counter = 1;
oHenchman = GetAssociate(ASSOCIATE_TYPE_HENCHMAN,oPC);
while(GetIsObjectValid(oHenchman))
{
AssignCommand(oHenchman,JumpToObject(oTarget));
oHenchman = GetAssociate(ASSOCIATE_TYPE_HENCHMAN,oPC,++counter);
}
}
SignalEvent(oDoor,EventUserDefined(EVENT_PLACEABLE_DOOR_ON_AREATRANSITIONCLICK));
}
}
else
{
SignalEvent(oDoor,EventUserDefined(EVENT_PLACEABLE_DOOR_ON_FAILEDTOOPEN));
}
void LockAtClose(object oDoor)
{
int iDoorLock = GetLocalInt(oDoor,"DOORLOCK");
if(iDoorLock > 0 && !GetLocked(oDoor))
{
int isDay = GetIsDay();
if(iDoorLock == 3 || !isDay && iDoorLock == 1 || isDay && iDoorLock == 2)
{
SetLocked(oDoor,TRUE);
}
}
}
Point is that once I need to add custom feature into these doors like "do something at OnFailedToOpen, I can use UserDefined to do this and I dont have to adjust system script.