Skip to content

Commit

Permalink
Rework on the code for closing a door with a creature in it (#2728)
Browse files Browse the repository at this point in the history
With this commit it's accurate to how it works on RL tibia.
In RL tibia it will move the creature in the following prioritization order:
east -> south -> west -> north
-> position where queryAdd() == 0 (non blocked walkable tile) without any creature
-> the previous with a creature
-> position with movable tile-blocking items
-> position with magic wall or wild growth
  • Loading branch information
sundance authored Jun 15, 2020
1 parent db4e8cc commit e2c8ced
Show file tree
Hide file tree
Showing 2 changed files with 74 additions and 14 deletions.
81 changes: 67 additions & 14 deletions data/actions/scripts/other/doors.lua
Original file line number Diff line number Diff line change
@@ -1,3 +1,58 @@
local positionOffsets = {
Position(1, 0, 0), -- east
Position(0, 1, 0), -- south
Position(-1, 0, 0), -- west
Position(0, -1, 0) -- north
}

--[[
When closing a door with a creature in it findPushPosition will find the most appropriate
adjacent position following a prioritization order.
The function returns the position of the first tile that fulfills all the checks in a round.
The function loops trough east -> south -> west -> north on each following line in that order.
In round 1 it checks if there's an unhindered walkable tile without any creature.
In round 2 it checks if there's a tile with a creature.
In round 3 it checks if there's a tile blocked by a movable tile-blocking item.
In round 4 it checks if there's a tile blocked by a magic wall or wild growth.
]]
local function findPushPosition(creature, round)
local pos = creature:getPosition()
for _, offset in ipairs(positionOffsets) do
local offsetPosition = pos + offset
local tile = Tile(offsetPosition)
if tile then
local creatureCount = tile:getCreatureCount()
if round == 1 then
if tile:queryAdd(creature) == RETURNVALUE_NOERROR and creatureCount == 0 then
if not tile:hasFlag(TILESTATE_PROTECTIONZONE) or (tile:hasFlag(TILESTATE_PROTECTIONZONE) and creature:canAccessPz()) then
return offsetPosition
end
end
elseif round == 2 then
if creatureCount > 0 then
if not tile:hasFlag(TILESTATE_PROTECTIONZONE) or (tile:hasFlag(TILESTATE_PROTECTIONZONE) and creature:canAccessPz()) then
return offsetPosition
end
end
elseif round == 3 then
local topItem = tile:getTopDownItem()
if topItem then
if topItem:getType():isMovable() then
return offsetPosition
end
end
else
if tile:getItemById(ITEM_MAGICWALL) or tile:getItemById(ITEM_WILDGROWTH) then
return offsetPosition
end
end
end
end
if round < 4 then
return findPushPosition(creature, round + 1)
end
end

function onUse(player, item, fromPosition, target, toPosition, isHotkey)
local itemId = item:getId()
if table.contains(questDoors, itemId) then
Expand Down Expand Up @@ -29,22 +84,20 @@ function onUse(player, item, fromPosition, target, toPosition, isHotkey)
end

if table.contains(horizontalOpenDoors, itemId) or table.contains(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))
local creaturePositionTable = {}
local doorCreatures = Tile(toPosition):getCreatures()
if #doorCreatures > 0 then
for _, doorCreature in pairs(doorCreatures) do
local pushPosition = findPushPosition(doorCreature, 1)
if not pushPosition then
player:sendCancelMessage(RETURNVALUE_NOTENOUGHROOM)
return true
end
table.insert(creaturePositionTable, {creature = doorCreature, position = pushPosition})
end

if query ~= RETURNVALUE_NOERROR then
player:sendTextMessage(MESSAGE_STATUS_SMALL, Game.getReturnMessage(query))
return true
for _, tableCreature in ipairs(creaturePositionTable) do
tableCreature.creature:teleportTo(tableCreature.position, true)
end

doorCreature:teleportTo(toPosition, true)
end

if not table.contains(openSpecialDoors, itemId) then
Expand Down
7 changes: 7 additions & 0 deletions data/lib/core/creature.lua
Original file line number Diff line number Diff line change
Expand Up @@ -167,3 +167,10 @@ function Creature:addDamageCondition(target, type, list, damage, period, rounds)
target:addCondition(condition)
return true
end

function Creature:canAccessPz()
if self:isMonster() or (self:isPlayer() and self:isPzLocked()) then
return false
end
return true
end

0 comments on commit e2c8ced

Please sign in to comment.