• There is NO official Otland's Discord server and NO official Otland's server list. The Otland's Staff does not manage any Discord server or server list. Moderators or administrator of any Discord server or server lists have NO connection to the Otland's Staff. Do not get scammed!

Windows Help to edit for people can open door if I didn't close with the key

What server are you using? The doors seem to be working fine for me on TFS 1.1.
Code:
unlockedDoors = { }

local function isDoorLocked(keyId, position)
    if keyId == 0 then
        return false
    end

    if unlockedDoors[keyId] then
        for i = 1, #unlockedDoors[keyId] do
            if position == unlockedDoors[keyId][i] then
                return false
            end
        end
    end

    return true
end

local function toggleDoorLock(doorItem, locked)
    local doorId = doorItem:getId()
    local keyId = doorItem:getActionId()
    local doorPosition = doorItem:getPosition()

    if locked then
        for i = #unlockedDoors[keyId], 1, -1 do
            if unlockedDoors[keyId][i] == doorPosition then
                table.remove(unlockedDoors[keyId], i)
            end
        end

        if not doors[doorId] then
            doorItem:transform(doorId - 1)
        end
        return
    end

    if not unlockedDoors[keyId] then
        unlockedDoors[keyId] = {}
    end

    doorItem:transform(doors[doorId])
    unlockedDoors[keyId][#unlockedDoors[keyId] + 1] = doorPosition
end

function onUse(player, item, fromPosition, target, toPosition, isHotkey)
    local itemId, actionId = item:getId(), item:getActionId()
    if isInArray(questDoors, itemId) then
        if player:getStorageValue(actionId) ~= -1 then
            item:transform(itemId + 1)
            player:teleportTo(toPosition, true)
        else
            player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "The door seems to be sealed against unwanted intruders.")
        end
        return true

    elseif isInArray(levelDoors, itemId) then
        if actionId > 0 and player:getLevel() >= actionId - 1000 then
            item:transform(itemId + 1)
            player:teleportTo(toPosition, true)
        else
            player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "Only the worthy may pass.")
        end
        return true

    elseif isInArray(keys, itemId) then
        if not target
                or not target:isItem()
                or not target:getType():isDoor()
                or Tile(toPosition):getHouse() then
            return false
        end

        local targetId = target:getId()
        if isInArray(openSpecialDoors, targetId)
                or isInArray(questDoors, targetId)
                or isInArray(levelDoors, targetId) then
            return false
        end

        local targetActionId = target:getActionId()
        if targetActionId > 0 and actionId == targetActionId then
            if not isDoorLocked(targetActionId, toPosition) then
                toggleDoorLock(target, true)
            elseif doors[targetId] then
                toggleDoorLock(target, false)
            end
        else
            player:sendCancelMessage("The key does not match.")
        end

        return true
    end

    if isInArray(horizontalOpenDoors, itemId) or isInArray(verticalOpenDoors, itemId) then
        local doorCreature = Tile(toPosition):getTopCreature()
        if doorCreature then
            toPosition.x = toPosition.x + 1
            local query = Tile(toPosition):queryAdd(doorCreature, bit.bor(FLAG_IGNOREBLOCKCREATURE, FLAG_PATHFINDING))
            if query ~= RETURNVALUE_NOERROR then
                toPosition.x = toPosition.x - 1
                toPosition.y = toPosition.y + 1
                query = Tile(toPosition):queryAdd(doorCreature, bit.bor(FLAG_IGNOREBLOCKCREATURE, FLAG_PATHFINDING))
            end

            if query ~= RETURNVALUE_NOERROR then
                player:sendCancelMessage(query)
                return true
            end

            doorCreature:teleportTo(toPosition, true)
        end
        if not isInArray(openSpecialDoors, itemId) then
            item:transform(itemId - 1)
        end
        return true
    end

    if doors[itemId] then
        if not isDoorLocked(actionId, toPosition) then
            item:transform(doors[itemId])
        else
            player:sendTextMessage(MESSAGE_INFO_DESCR, "It is locked.")
        end
        return true
    end

    return false
end

Edit - Wait, you are trying to do this as a script, rather than just doing it as a normal door?
 
Code:
Door = {}

function Door:new(position, keyaid, openid, closedid)
   return setmetatable({position=position, keyaid=keyaid, openid=openid, closedid=closedid, locked=true, id=closedid}, {__index = Door})
end

function Door:isLocked()
   if self.id == self.closedid then
     return self.locked
   end
end

function Door:setUid(uid)
   self.uid = uid
   return true
end

function Door:unlock(keyaid)
   if self.uid and keyaid == self.keyaid then
     self.locked = false
     self.id = self.openid
     doTransformItem(self.uid, self.openid)
     doItemSetAttribute(self.uid, "aid", 0)
     return true
   end
end

function Door:lock(keyaid)
   if self.uid and keyaid == self.keyaid then
     self.locked = true
     self.id = self.closedid
     doTransformItem(self.uid, self.closedid)
     doItemSetAttribute(self.uid, "aid", keyaid)
     return true
   end
end

function getDoorByPosition(position, doors)
   for _, door in ipairs(doors) do
     if doComparePositions(door.position, position) then
       return door
     end
   end
end

local doors = {
   [1] = Door:new({x=156, y=54, z=7}, 1230, 5100, 5099),
   [2] = Door:new({x=152, y=54, z=7}, 1231, 5100, 5099),
}

function onUse(cid, item, fromPosition, itemEx, toPosition)
   local door = getDoorByPosition(toPosition, doors)
   if door then
     if itemEx.itemid == door.openid or itemEx.itemid == door.closedid then
       door:setUid(itemEx.uid)
       if item.uid == itemEx.uid then
         if door:isLocked() then
           doPlayerSendTextMessage(cid, MESSAGE_INFO_DESCR, "It is locked.")
         end
       else
         if door:isLocked() then
           local unlock = door:unlock(item.actionid)
           if not unlock then
             return   doPlayerSendCancel(cid, "The key does not match.")
           end
         else
           local lock = door:lock(item.actionid)
           if not lock then
             return   doPlayerSendCancel(cid, "The key does not match.")
           end
         end
       end
     end
   end
   return true
end

Just make sure the key and door have the same actionid and the position is right.
 
Last edited:
and last question: what's 1230?
[1] = Door:new({x=156, y=54, z=7}, 1230, 5100, 5099),

Door:new(Position, keyaid/dooraid, opendoorid, closeddoorid)

1230 is the actionid of the key and door.

The tag should be something like:

<action actionid="1230-1231" event="script" value="doors.lua"/>

Thanks!! One question, I don't need to put anything in this first line?
Door = {}

@MatheusMkalo


No you don't, you just need to edit the "doors" table.
 
Last edited:
@MatheusMkalo
I tested and it's happening:

When the door is closed, it doesn't appears "It's locked." when I try to open without the key. Doesn't appears anything when I try to open.
When the door is open, I only can close if I use the key. If I don't use, I can't close the door.

Quando a porta está fechada, não aparece a mensagem quando tento abri-la sem a key, entendeu? E eu só consigo fechar a porta se eu tiver a key, sendo que eu quero que feche normal, com ou sem key. Mas que tranque a porta apenas se eu usar a key. É estilo global mesmo que eu quero. Fechou sem key, qualquer um pode abrir a porta. Fechou com key, apenas quem tiver a key pode abri-la.

O script tá de boa, mas chega nessas partes e complica...
Thanks mate e sorry for writing in Portuguese, it was just for you understand... And thanks again for helping me.
 
@MatheusMkalo
I tested and it's happening:

When the door is closed, it doesn't appears "It's locked." when I try to open without the key. Doesn't appears anything when I try to open.
When the door is open, I only can close if I use the key. If I don't use, I can't close the door.

Quando a porta está fechada, não aparece a mensagem quando tento abri-la sem a key, entendeu? E eu só consigo fechar a porta se eu tiver a key, sendo que eu quero que feche normal, com ou sem key. Mas que tranque a porta apenas se eu usar a key. É estilo global mesmo que eu quero. Fechou sem key, qualquer um pode abrir a porta. Fechou com key, apenas quem tiver a key pode abri-la.

O script tá de boa, mas chega nessas partes e complica...
Thanks mate e sorry for writing in Portuguese, it was just for you understand... And thanks again for helping me.

I've tested it and it was working perfectly. Are you sure that you've set everything correctly?
The door has to be closed and have the actionid 1230, and the key as well. The position must be right and the ids too.

Door:new(Position, keyaid/dooraid, opendoorid, closeddoorid)

When you use the key it should open and remove the actionid, that way anyone could open/close it without the key, but when you use the key again it will close and set back the actionid. Also check if you did remove the old script you were using.
 
@MatheusMkalo
I configured like that:

Code:
Door = {}

function Door:new(position, keyaid, openid, closedid)
    return setmetatable({position=position, keyaid=keyaid, openid=openid, closedid=closedid, locked=true, id=closedid}, {__index = Door})
end

function Door:isLocked()
    if self.id == self.closedid then
        return self.locked
    end
end

function Door:setUid(uid)
    self.uid = uid
    return true
end

function Door:unlock(keyaid)
    if self.uid and keyaid == self.keyaid then
        self.locked = false
        self.id = self.openid
        doTransformItem(self.uid, self.openid)
        doItemSetAttribute(self.uid, "aid", 0)
        return true
    end
end

function Door:lock(keyaid)
    if self.uid and keyaid == self.keyaid then
        self.locked = true
        self.id = self.closedid
        doTransformItem(self.uid, self.closedid)
        doItemSetAttribute(self.uid, "aid", keyaid)
        return true
    end
end

function getDoorByPosition(position, doors)
    for _, door in ipairs(doors) do
        if doComparePositions(door.position, position) then
            return door
        end
    end
end

-- Door:new(position, keyaid, openid, closedid)
local doors = {
    [1] = Door:new({x=32109, y=32172, z=8}, 4600, 5108, 5109),
}

function onUse(cid, item, fromPosition, itemEx, toPosition)
    local door = getDoorByPosition(toPosition, doors)
    if door then
        door:setUid(itemEx.uid)
        if item.uid == itemEx.uid then
            if door:isLocked() then
                doPlayerSendTextMessage(cid, MESSAGE_INFO_DESCR, "It is locked.")
            end
        else
            if door:isLocked() then
                local unlock = door:unlock(item.actionid)
                if not unlock then
                    return doPlayerSendCancel(cid, "The key does not match.")
                end
            else
                local lock = door:lock(item.actionid)
                if not lock then
                    return doPlayerSendCancel(cid, "The key does not match.")
                end
            end
        end
    end
    return true
end

Code:
<action actionid="4600" event="script" value="doors.lua"/>

Key action id: 4600
Key id: 2800
 
@MatheusMkalo
I configured like that:

Code:
Door = {}

function Door:new(position, keyaid, openid, closedid)
    return setmetatable({position=position, keyaid=keyaid, openid=openid, closedid=closedid, locked=true, id=closedid}, {__index = Door})
end

function Door:isLocked()
    if self.id == self.closedid then
        return self.locked
    end
end

function Door:setUid(uid)
    self.uid = uid
    return true
end

function Door:unlock(keyaid)
    if self.uid and keyaid == self.keyaid then
        self.locked = false
        self.id = self.openid
        doTransformItem(self.uid, self.openid)
        doItemSetAttribute(self.uid, "aid", 0)
        return true
    end
end

function Door:lock(keyaid)
    if self.uid and keyaid == self.keyaid then
        self.locked = true
        self.id = self.closedid
        doTransformItem(self.uid, self.closedid)
        doItemSetAttribute(self.uid, "aid", keyaid)
        return true
    end
end

function getDoorByPosition(position, doors)
    for _, door in ipairs(doors) do
        if doComparePositions(door.position, position) then
            return door
        end
    end
end

-- Door:new(position, keyaid, openid, closedid)
local doors = {
    [1] = Door:new({x=32109, y=32172, z=8}, 4600, 5108, 5109),
}

function onUse(cid, item, fromPosition, itemEx, toPosition)
    local door = getDoorByPosition(toPosition, doors)
    if door then
        door:setUid(itemEx.uid)
        if item.uid == itemEx.uid then
            if door:isLocked() then
                doPlayerSendTextMessage(cid, MESSAGE_INFO_DESCR, "It is locked.")
            end
        else
            if door:isLocked() then
                local unlock = door:unlock(item.actionid)
                if not unlock then
                    return doPlayerSendCancel(cid, "The key does not match.")
                end
            else
                local lock = door:lock(item.actionid)
                if not lock then
                    return doPlayerSendCancel(cid, "The key does not match.")
                end
            end
        end
    end
    return true
end

Code:
<action actionid="4600" event="script" value="doors.lua"/>

Key action id: 4600
Key id: 2800

-- Door:new(position, keyaid, openid, closedid)
[1] = Door:new({x=32109, y=32172, z=8}, 4600, 5108, 5109),

5108 is closed id and 5109 is openid, you set it wrong.

Door:new({x=32109, y=32172, z=8}, 4600, 5109, 5108)
 
Back
Top