• 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!

Lua [TFS 1.3] Help with script logic

E

Evil Puncker

Guest
Hello, I'm breaking my head to get this to work but no success, currently I have tried the following:

Lua:
    local tile2 = Tile(toPosition)
    if tile2 and not tile2:hasFlag(TILESTATE_HOUSE) and item:getAttribute("wrapid") then
        self:sendCancelMessage(RETURNVALUE_NOTPOSSIBLE)
        return false
    end

What I need is, the script is a OnMoveItem event that needs to do the following:
  • if the moved item have the getAttribute("wrapid") it will only be possible to move to backpack or the character house floor
  • if you try to move it out of the house it should return 'not possible'

but right now my script prevents it to move anywhere, thanks in advance
 
Solution
Lua:
if fromPosition.x ~= CONTAINER_POSITION and toPosition.x ~= CONTAINER_POSITION then
    if not Tile(toPosition):getHouse() and item:getAttribute("wrapid") then
        self:sendCancelMessage(RETURNVALUE_NOTPOSSIBLE)
        return false
    end
end
Not really (ItemType method) but close. There are 3 doors related methods in House userdata.
getDoors - returns list of doors that are a part of the house
getDoorCount - returns number of doors that are a part of the house
getDoorIdByPosition - returns door id by given position (or nil if no door is found), we should use that one

If you are using userdata constructors like Tile(), Player(), Creature() with same argument more than once then store it as a local variable, saves processing time.
Lua:
if fromPosition.x ~= CONTAINER_POSITION and toPosition.x ~= CONTAINER_POSITION then
    local tile = Tile(toPosition)
    if tile then -- make sure there is a tile, we don't want unnecessary errors
        local house = tile:getHouse()
        if not house and item:getAttribute("wrapid") or house and house:getDoorIdByPosition(toPosition) then
            self:sendCancelMessage(RETURNVALUE_NOTPOSSIBLE)
            return false
        end
    end
end
I used this:
Lua:
        if Tile(toPosition):getItemByType(ITEM_TYPE_DOOR) and item:getAttribute("wrapid") ~= 0 then
            self:sendCancelMessage(RETURNVALUE_NOTPOSSIBLE)
            return false
        end
should I change to yours?
 
tested (had to add ~= 0 after warpid) and can move item to door:

Lua:
    if fromPosition.x ~= CONTAINER_POSITION and toPosition.x ~= CONTAINER_POSITION then
        local tile = Tile(toPosition)
        if tile then
            local house = tile:getHouse()
            if not house and item:getAttribute("wrapid") ~= 0 or house and house:getDoorIdByPosition(toPosition) then
                self:sendCancelMessage(RETURNVALUE_NOTPOSSIBLE)
                return false
            end
        end
    end
 
I would suggest you to check if the item has a "wrapid" before everything else, preventing the script to run a bunch of unnecessary code.

That would mainly remove the cost of running this method: otland/forgottenserver (https://github.com/otland/forgottenserver/blob/master/src/map.cpp#L78) everytime this code runs, on an item without a wrapid.

Something like this:
Code:
if item:getAttribute("wrapid") ~= 0 then
    if fromPosition.x ~= CONTAINER_POSITION and toPosition.x ~= CONTAINER_POSITION then
        local tile = Tile(toPosition)
        if tile then
            local house = tile:getHouse()
            if not house or (house and house:getDoorIdByPosition(toPosition)) then
                self:sendCancelMessage(RETURNVALUE_NOTPOSSIBLE)
                return false
            end
        end
    end
end

I haven't tested this code so be sure to test it. I just showed it for you to get a better understading of what I said.
 
Last edited:
I would suggest you to check if the item has a "wrapid" before everything else, preventing the script to run a bunch of unnecessary code.

That would mainly remove the cost of running this method: otland/forgottenserver (https://github.com/otland/forgottenserver/blob/master/src/map.cpp#L78) everytime this code runs, on an item without a wrapid.

Something like this:
Code:
if item:getAttribute("wrapid") ~= 0 then
    if fromPosition.x ~= CONTAINER_POSITION and toPosition.x ~= CONTAINER_POSITION then
        local tile = Tile(toPosition)
        if tile then
            local house = tile:getHouse()
            if not house or (house and house:getDoorIdByPosition(toPosition)) then
                self:sendCancelMessage(RETURNVALUE_NOTPOSSIBLE)
                return false
            end
        end
    end
end

I haven't tested this code so be sure to test it. I just showed it for you to get a better understading of what I said.

still can move to the door tho :(

changing line 6 to this works tho:
Lua:
if not house or (house and tile:getItemByType(ITEM_TYPE_DOOR)) then
 
still can move to the door tho :(

changing line 6 to this works tho:
Lua:
if not house or (house and tile:getItemByType(ITEM_TYPE_DOOR)) then

I'm sorry, I may have confused you.

I didn't add anything new to the code, I just changed what I said about checking the wrapid before anything else.
 
So this allows dropping on door? getDoorIdByPosition returns nil if doors couldn't be found, weird it's not working. Could it be that main doors aren't included? :eek:
Check prints.
Lua:
if item:getAttribute("wrapid") ~= 0 then
    if fromPosition.x ~= CONTAINER_POSITION and toPosition.x ~= CONTAINER_POSITION then
        local tile = Tile(toPosition)
        if tile then
            local house = tile:getHouse()
            if house then
                print(house:getDoorCount(), house:getDoorIdByPosition(toPosition))
            end
            if not house or house and house:getDoorIdByPosition(toPosition) > 0 then
                self:sendCancelMessage(RETURNVALUE_NOTPOSSIBLE)
                return false
            end
        end
    end
end
 
So this allows dropping on door? getDoorIdByPosition returns nil if doors couldn't be found, weird it's not working. Could it be that main doors aren't included? :eek:
Check prints.
Lua:
if item:getAttribute("wrapid") ~= 0 then
    if fromPosition.x ~= CONTAINER_POSITION and toPosition.x ~= CONTAINER_POSITION then
        local tile = Tile(toPosition)
        if tile then
            local house = tile:getHouse()
            if house then
                print(house:getDoorCount(), house:getDoorIdByPosition(toPosition))
            end
            if not house or house and house:getDoorIdByPosition(toPosition) > 0 then
                self:sendCancelMessage(RETURNVALUE_NOTPOSSIBLE)
                return false
            end
        end
    end
end
Code:
data/events/scripts/player.lua:Player@onMoveItem
data/events/scripts/player.lua:135: attempt to compare number with nil
stack traceback:
        [C]: in function '__lt'
        data/events/scripts/player.lua:135: in function <data/events/scripts/player.lua:126>
0       nil
 
Change this line if not house or house and house:getDoorIdByPosition(toPosition) > 0 then.
To if not house or house and house:getDoorIdByPosition(toPosition) ~= nil then.
As getDoorIdByPosition returns nil and not a number if no door is found.
 
nvm, I got it wrong, post below got it right
Change this line if not house or house and house:getDoorIdByPosition(toPosition) > 0 then.
To if not house or house and house:getDoorIdByPosition(toPosition) ~= nil then.
As getDoorIdByPosition returns nil and not a number if no door is found.

both still returns

0 nil


btw mine:
Lua:
                if not house or (house and tile:getItemByType(ITEM_TYPE_DOOR)) then
                    self:sendCancelMessage(RETURNVALUE_NOTPOSSIBLE)
                    return false
                end

is already working, isn't it good enough? 😢
 
As the sources are at the moment, it is not possible to do it in a very direct way, one possibility is this:
Lua:
local houseTile = Tile(toPosition)
    if houseTile then
        if houseTile:getHouse() then
            local foundDoor = houseTile:getItems()
            foundDoor = foundDoor[#foundDoor]
            if foundDoor and ItemType(foundDoor:getId()):isDoor() then
                player:sendCancelMessage("You cannot move items to house doors.")
                return false
            end
        end
    end

Modifying the getItemByType function we can achieve it in 1 single line
 
As the sources are at the moment, it is not possible to do it in a very direct way, one possibility is this:
Lua:
local houseTile = Tile(toPosition)
    if houseTile then
        if houseTile:getHouse() then
            local foundDoor = houseTile:getItems()
            foundDoor = foundDoor[#foundDoor]
            if foundDoor and ItemType(foundDoor:getId()):isDoor() then
                player:sendCancelMessage("You cannot move items to house doors.")
                return false
            end
        end
    end

Modifying the getItemByType function we can achieve it in 1 single line

I mean this one:
Lua:
    if item:getAttribute("wrapid") ~= 0 then
        if fromPosition.x ~= CONTAINER_POSITION and toPosition.x ~= CONTAINER_POSITION then
            local tile = Tile(toPosition)
            if tile then
                local house = tile:getHouse()
                if not house or (house and tile:getItemByType(ITEM_TYPE_DOOR)) then
                    self:sendCancelMessage(RETURNVALUE_NOTPOSSIBLE)
                    return false
                end
            end
        end
    end
the above is working 100% unless I'm missing something
 
that?
Lua:
if item:getAttribute("wrapid") ~= 0 then
        local houseTile = Tile(toPosition)
        if houseTile and houseTile:getItemByType(ITEM_TYPE_DOOR) then
            player:sendCancelMessage("You cannot move items to house doors.")
            return false
        end
end

Yo lo uso de esta manera:
Lua:
if item:getAttribute("wrapid") ~= ITEM_DECORATION_KIT then
        local houseTile = Tile(toPosition)
        if houseTile and houseTile:getItemByType(ITEM_TYPE_DOOR) then
            player:sendCancelMessage("You cannot move items to house doors.")
            return false
        end
end
kkkkkkk.gif
 
Last edited:
kkkkkkk.gif
do that with a carpet and use it on the door and it will be there forever 😁
 
okay guys we are almost there, currently everything is working as intended, except that I can still take the item from the backpack and put it on a tile that is not a house

Lua:
    if item:getAttribute("wrapid") ~= 0 then
        if fromPosition.x ~= CONTAINER_POSITION and toPosition.x ~= CONTAINER_POSITION then
            local tile = Tile(toPosition)
            if tile and not tile:getHouse() then
                self:sendCancelMessage(RETURNVALUE_NOTPOSSIBLE)
                return false
            end
        end
    end

in other words:
  • moving item from house tile to outside house tile is blocked (ok)
  • moving item from house tile to backpack is allowed and vice-versa (ok)
  • moving item from backpack to not house tile is allowed (not ok)
 
Back
Top