illarion-content/base/keys.lua
2024-07-17 11:56:41 +02:00

326 lines
11 KiB
Lua
Raw Permalink Blame History

--[[
Illarion Server
This program is free software: you can redistribute it and/or modify it under
the terms of the GNU Affero General Public License as published by the Free
Software Foundation, either version 3 of the License, or (at your option) any
later version.
This program is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
PARTICULAR PURPOSE. See the GNU Affero General Public License for more
details.
You should have received a copy of the GNU Affero General Public License along
with this program. If not, see <http://www.gnu.org/licenses/>.
]]
local doors = require("base.doors")
local common = require("base.common")
local housingUtility = require("housing.utility")
local M = {}
--[[
Checks if the key is a master key and in the hands of an admin. A master key
can open and close all doors.
@param User - character struct to check if the owner of the key is an admin
@param key - ItemStruct of the key that shall be checked
@return boolean - true in case of a master key else false
]]
local function checkForMasterKey(User, key)
if User:isAdmin() and key:getData("lockId")=="666" then
return true
else
return false
end
end
--[[
LockDoor
Lock a door. This function checks if that item is a closed on that can be
locked.
It does not check if the player has a fitting key.
@param ItemStruct - the item that is the closed door that shall be locked
@return boolean - true in case the door got locked, false if anything went
wrong
]]
function M.LockDoor(Door, user)
if doors.CheckClosedDoor(Door.id) then
if (Door:getData("doorLock") == "unlocked") then
if housingUtility.getStairsTrapDoor(Door.pos, false) then
if not M.lockTrapDoor(user, Door) then
return false
end
end
Door:setData("doorLock","locked")
world:changeItem(Door)
world:makeSound(19, Door.pos)
return true
else
return false
end
else
if user then -- this function is also called by a script where user is not present
user:inform("Nur geschlossen T<>ren k<>nnen auch abgeschlossen werden.", "The door must be closed for you to lock it.")
end
return false
end
end
--[[
UnlockDoor
Unlock a door. This function checks if the item is a closed locked door and
unlocks it.
It does not check if the player has a fitting key.
@param ItemStruct - the item that is the closed door that shall be unlocked
@return boolean - true in case the door got locked, false if anything went
wrong
]]
function M.UnlockDoor(Door, user)
if doors.CheckClosedDoor(Door.id) then
if (Door:getData("doorLock") == "locked" or Door:getData("lockId")~="") then
if housingUtility.getStairsTrapDoor(Door.pos, false) then
if not M.unlockTrapDoor(user, Door) then
return false
end
end
Door:setData("doorLock","unlocked")
world:changeItem(Door)
world:makeSound(20, Door.pos)
return true
else
return false
end
else
return false
end
end
--To make use of the lock stair/trapdoor function outside of housing, a trapDoor position must be added to the item data of the stairs and vice versa
local function isHousingEstate(pos)
local propertyName = housingUtility.fetchPropertyName(nil, pos)
if not propertyName then
return false
end
return housingUtility.checkIfEstateViaName(propertyName)
end
function M.UnlockStairs(Door, user)
if Door.id ~= 4339 then
return false
end
world:erase(Door, 1) -- Erase the invisible blockade that blocks the stairs
local stair = housingUtility.getStairsTrapDoor(Door.pos, true)
local trapDoorPosition
local X = stair:getData("trapdoorX")
local Y = stair:getData("trapdoorY")
local Z = stair:getData("trapdoorZ")
if not common.IsNilOrEmpty(X) then -- The position was supplied by the stair item itself, meaning it was put in by GM, map editor or script outside of housing
trapDoorPosition = position(tonumber(X), tonumber(Y), tonumber(Z))
elseif isHousingEstate(Door.pos) then --It belongs to housing so we can determine where the position is based on how housing places them
trapDoorPosition = housingUtility.getTrapDoorOrStairPosition(stair)
end
local trapDoor = housingUtility.getStairsTrapDoor(trapDoorPosition, false)
if trapDoor:getData("doorLock") == "locked" then
trapDoor:setData("doorLock", "unlocked")
stair:setData("doorLock", "unlocked")
world:changeItem(trapDoor)
world:changeItem(stair)
world:makeSound(20, trapDoor.pos)
world:makeSound(20, stair.pos)
end
return true
end
function M.LockStairs(user, stair)
local stairFound = false
for index , stairId in pairs(housingUtility.stairs) do
if stair.id == stairId then
stairFound = true
end
end
if not stairFound then
return
end
local trapDoorPosition
local X = stair:getData("trapdoorX")
local Y = stair:getData("trapdoorY")
local Z = stair:getData("trapdoorZ")
if not common.IsNilOrEmpty(X) then -- The position was supplied by the stair item itself, meaning it was put in by GM, map editor or script outside of housing
trapDoorPosition = position(tonumber(X), tonumber(Y), tonumber(Z))
elseif isHousingEstate(stair.pos) then --It belongs to housing so we can determine where the position is based on how housing places them
trapDoorPosition = housingUtility.getTrapDoorOrStairPosition(stair)
end
if not trapDoorPosition and user then
user:inform("Dieser Treppe fehlt die Fallt<6C>r.", "This staircase has no assigned trap door.") --Should only happen if a master key is used or someone fucked up implementation
elseif not trapDoorPosition then
return
end
local trapDoor = housingUtility.getStairsTrapDoor(trapDoorPosition, false)
if not trapDoor and user then
user:inform("The trap door above the stairs appears to be obstructed by something.")
return false
elseif not trapDoor then
return false
end
local closed = doors.CheckClosedDoor(trapDoor.id)
if not closed then
doors.CloseDoor(trapDoor)
trapDoor = housingUtility.getStairsTrapDoor(trapDoorPosition, false) -- refresh the item since it was changed above
end
if trapDoor:getData("doorLock") == "unlocked" then
trapDoor:setData("doorLock", "locked")
stair:setData("doorLock", "locked")
world:changeItem(trapDoor)
world:changeItem(stair)
world:makeSound(20, trapDoor.pos)
world:makeSound(20, stair.pos)
end
world:createItemFromId(4339, 1, stair.pos, true, 333, {lockId = trapDoor:getData("lockId")})
return true
end
function M.unlockTrapDoor(user, trapDoor)
local stairPosition
local X = trapDoor:getData("stairX")
local Y = trapDoor:getData("stairY")
local Z = trapDoor:getData("stairZ")
if not common.IsNilOrEmpty(X) then -- The position was supplied by the trap door item itself, meaning it was put in by GM, map editor or script outside of housing
stairPosition = position(tonumber(X), tonumber(Y), tonumber(Z))
elseif isHousingEstate(trapDoor.pos) then --It belongs to housing so we can determine where the position is based on how housing places them
stairPosition = housingUtility.getTrapDoorOrStairPosition(nil, trapDoor)
end
local potentialStairBlockade
if world:isItemOnField(stairPosition) then
potentialStairBlockade = world:getItemOnField(stairPosition)
end
if potentialStairBlockade then
if potentialStairBlockade.id == 4339 then
world:erase(potentialStairBlockade, 1)
end
end
local stair = housingUtility.getStairsTrapDoor(stairPosition, true)
if not stair then
return
end
if stair:getData("doorLock") == "locked" then
stair:setData("doorLock", "unlocked")
world:changeItem(stair)
world:makeSound(20, stair.pos)
end
return true
end
function M.lockTrapDoor(user, trapDoor)
local stairPosition
local X = trapDoor:getData("stairX")
local Y = trapDoor:getData("stairY")
local Z = trapDoor:getData("stairZ")
if not common.IsNilOrEmpty(X) then -- The position was supplied by the trap door item itself, meaning it was put in by GM, map editor or script outside of housing
stairPosition = position(tonumber(X), tonumber(Y), tonumber(Z))
elseif isHousingEstate(trapDoor.pos) then --It belongs to housing so we can determine where the position is based on how housing places them
stairPosition = housingUtility.getTrapDoorOrStairPosition(nil, trapDoor)
end
if not stairPosition and user then
user:inform("Dieser Treppe fehlt die Fallt<6C>r.", "This trap door has no assigned staircase.") --Should only happen if a master key is used or someone fucked up implementation
elseif not stairPosition then
return
end
local stair = housingUtility.getStairsTrapDoor(stairPosition, true)
if not stair and user then
user:inform("Ein Stockwerk weiter unten blockiert die Treppe.", "Something is obstructing the stairs below.")
return
end
if stair:getData("doorLock") == "unlocked" then
stair:setData("doorLock", "locked")
world:changeItem(stair)
world:makeSound(20, stair.pos)
end
world:createItemFromId(4339, 1, stair.pos, true, 333, {lockId = trapDoor:getData("lockId")})
return true
end
--[[
CheckKey
Check if a key fits into a door. This function does not check if the item is
really a key. It assumes that it is one and checks the lock that is encoded
in the data value.
How ever it checks if the door item is a opened or a closed door.
@param ItemStruct - the item that is the key for a door
@param ItemStruct - the item that is the door that shall be checked
@param CharacterStruct - the user that has the key
@return boolean - true in case the key item would fit to the door, false if
it does not fit
]]
function M.CheckKey(Key, Door, User)
if Door == nil then
return false
end
if doors.CheckClosedDoor(Door.id) or doors.CheckOpenDoor(Door.id) or Door.id == 4339 or housingUtility.doorIsAStair(Door.id) then
if (Key:getData("lockId") == Door:getData("lockId") and Door:getData("lockId") ~= "") or checkForMasterKey(User, Key) then
return true
else
return false
end
else
return false
end
end
return M