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

[TFS 1.5] ❤ TradeTimes System ❤

Sarah Wesker

ƐƖєgαηт Sуηтαx ❤
Staff member
TFS Developer
Support Team
Joined
Mar 16, 2017
Messages
1,418
Solutions
155
Reaction score
1,975
Location
London
GitHub
MillhioreBT
Twitch
millhiorebt
TradeTimes System

System that controls how many times a specific item can be traded.
The system does not time any items, you must do it yourself in your own scripts.
If you want to try using it on TFS 1.4 here is a solution


Here is an example of how you can add an item to the system:
yourscript.lua
Lua:
item:setCustomAttribute("TradeTimes", 3)
Why use the key "TradeTimes"? - We use this key because it is the one we are using in the system script.

Once you understand this, we can continue with the installation of the system...
data/scripts/tradetimes.lua
Lua:
local tradeStoneId = 8302
local maxTradeTimes = 3
local tradeKey = "TradeTimes"
local effect = CONST_ME_FIREWORK_BLUE

-- Warning:
-- This prints a warning to the console if the execution order is not correct.
-- If the warning is triggered, it means that there is a possibility that an item with TradeTimes will fall to the ground.
-- If you are sure that the order is correct, you can disable this to make your script faster.
local checkDropLootOrder = true

-- If an item with TradeTimes is found on the corpse, should we remove it?
local removeDropedItem = true

-- If an item with TradeTimes is found on the corpse, should we reduce the times?
-- If removeDropedItem is false and this variable is true, then the item will be removed if it has no more times.
local reduceDropedItem = false

local function isSentToPlayer(player, toCylinder)
    if not toCylinder then
        return RETURNVALUE_NOTPOSSIBLE
    end
    if toCylinder:isTile() then
        return RETURNVALUE_NOTPOSSIBLE
    end
    if toCylinder == player or toCylinder:getTopParent() == player then
        return RETURNVALUE_NOERROR
    end
    return RETURNVALUE_NOTPOSSIBLE
end

local ec = EventCallback

function ec.onMoveItem(player, item, count, fromPosition, toPosition, fromCylinder, toCylinder)
    local toTile = Tile(toPosition)
    if toTile and toTile:hasFlag(TILESTATE_TRASHHOLDER) then
        return RETURNVALUE_NOERROR
    elseif item:getCustomAttribute(tradeKey) then
        return isSentToPlayer(player, toCylinder)
    elseif item:getType():isContainer() then
        for _, item in pairs(item:getItems(true)) do
            if item:getCustomAttribute(tradeKey) then
                return isSentToPlayer(player, toCylinder)
            end
        end
    end
    return RETURNVALUE_NOERROR
end

ec:register(-1)

function ec.onTradeRequest(player, target, item)
    local itemTT = item:getCustomAttribute(tradeKey)
    if itemTT and itemTT < 1 then
        player:sendCancelMessage("You can't trade this item anymore.")
        return false
    end

    if item:getType():isContainer() then
        for _, it in pairs(item:getItems(true)) do
            local itTT = it:getCustomAttribute(tradeKey)
            if itTT and itTT < 1 then
                player:sendCancelMessage("You can't trade this item anymore.")
                return false
            end
        end
    end
    return true
end

ec:register(-1)

function ec.onTradeCompleted(player, target, item, targetItem, isSuccess)
    if not isSuccess then
        return
    end

    local itemTT = item:getCustomAttribute(tradeKey)
    if itemTT then
        item:setCustomAttribute(tradeKey, itemTT - 1)
    end

    if item:getType():isContainer() then
        for _, it in pairs(item:getItems(true)) do
            local itTT = it:getCustomAttribute(tradeKey)
            if itTT then
                it:setCustomAttribute(tradeKey, itTT - 1)
            end
        end
    end

    local targetItemTT = targetItem:getCustomAttribute(tradeKey)
    if targetItemTT then
        targetItem:setCustomAttribute(tradeKey, targetItemTT - 1)
    end

    if targetItem:getType():isContainer() then
        for _, it in pairs(targetItem:getItems(true)) do
            local itTT = it:getCustomAttribute(tradeKey)
            if itTT then
                it:setCustomAttribute(tradeKey, itTT - 1)
            end
        end
    end
end

ec:register(-1)

local function onLook(item, description)
    local tradeTimes = item:getCustomAttribute(tradeKey)
    if not tradeTimes then
        return description
    end
    if tradeTimes > 0 then
        return string.format("%s\nIt can be traded %d more times.", description, tradeTimes)
    end
    return string.format("%s\nIt can no longer be traded.", description)
end

function ec.onLook(player, thing, position, distance, description)
    if not thing:isItem() then
        return description
    end
    return onLook(thing, description)
end

ec:register(1)

function ec.onLookInTrade(player, partner, item, distance, description)
    return onLook(item, description)
end

ec:register(1)

local action = Action()

function action.onUse(player, item, fromPos, target, toPos, isHotkey)
    if not target or not target:isItem() then
        player:sendCancelMessage(RETURNVALUE_NOTPOSSIBLE)
        return true
    end

    local tradeTimes = target:getCustomAttribute(tradeKey)
    if not tradeTimes then
        player:sendCancelMessage("This item not support trade times.")
        return true
    end

    if tradeTimes >= maxTradeTimes then
        player:sendCancelMessage("This item already has the maximum trade times.")
        return true
    end

    tradeTimes = tradeTimes + 1
    target:setCustomAttribute(tradeKey, tradeTimes)
    item:remove(1)
    player:getPosition():sendMagicEffect(effect)
    return true
end

action:id(tradeStoneId)
action:register()

local death = CreatureEvent("TradeTimesDeath")

function death.onDeath(player, corpse, lastHitKiller, mostDamageKiller, lastHitUnjustified, mostDamageUnjustified)
    if checkDropLootOrder then
        local foundDropLoot = false
        for _, eventName in pairs(player:getEvents(CREATURE_EVENT_DEATH)) do
            if eventName == "DropLoot" then
                foundDropLoot = true
            elseif eventName == "TradeTimesDeath" and not foundDropLoot then
                print("[TradeTimesDeath - Warning] must be after DropLoot.")
            end
        end
    end

    for _, item in pairs(corpse:getItems(true)) do
        local tradeTimes = item:getCustomAttribute(tradeKey)
        if tradeTimes then
            if removeDropedItem then
                item:remove()
            elseif reduceDropedItem then
                if tradeTimes > 1 then
                    item:setCustomAttribute(tradeKey, tradeTimes - 1)
                else
                    item:remove()
                end
            end
        end
    end
    return true
end

death:register()

local login = CreatureEvent("TradeTimesLogin")

function login.onLogin(player)
    player:registerEvent("TradeTimesDeath")
    return true
end

login:register()

OFC how to forget it, we also have a special item that serves to add time to the item that are working with this system.
1667542917149.png ID: 8302, Name: iced soil
this item will add times up to the maximum limit, if the item can't get them it will send you a message saying you can't add times.

The items that are working with the system will show a description with the number of times it has:
1667543260636.png1667543333511.png


Important:
These items for obvious reasons cannot be thrown on the ground, nor in containers that are on the ground.
They also cannot be contained in the deposits since in this way they could be traded through the market and would lose their personalized attributes.
Although you can't throw them on the ground, you can throw them in dumpsters for disposal.
If you have several items inside a backpack and it is exchanged, all its items with times will be affected.
You can't trade items that don't have enough times.

Suggestions:
If you manage to find a way to break the system by making timed items tradable to other players without wasting time or simply ignoring the system let me know so I can fix it.
If you get any errors let me know.
Please if you don't use the engine TFS 1.5 (master) don't complain here, this system was not designed for other versions.

Warnings:
The system parses containers with the getItems function recursively so if you have items stored too deep it could affect your server performance if you have a sizeable amount of players constantly moving containers too deep. (if you have few players you shouldn't mind this at all)
What I said above may not be true, I have never tried this on a large scale, please do your testing and let me know.
 
Last edited:
TradeTimes System

System that controls how many times a specific item can be traded.
The system does not time any items, you must do it yourself in your own scripts.

Here is an example of how you can add an item to the system:
yourscript.lua
Lua:
item:setCustomAttribute("TradeTimes", 3)
Why use the key "TradeTimes"? - We use this key because it is the one we are using in the system script.

Once you understand this, we can continue with the installation of the system...
data/scripts/tradetimes.lua
Lua:
local tradeStoneId = 8302
local maxTradeTimes = 3
local tradeKey = "TradeTimes"
local effect = CONST_ME_FIREWORK_BLUE

-- Warning:
-- This prints a warning to the console if the execution order is not correct.
-- If the warning is triggered, it means that there is a possibility that an item with TradeTimes will fall to the ground.
-- If you are sure that the order is correct, you can disable this to make your script faster.
local checkDropLootOrder = true

-- If an item with TradeTimes is found on the corpse, should we remove it?
local removeDropedItem = true

-- If an item with TradeTimes is found on the corpse, should we reduce the times?
-- If removeDropedItem is false and this variable is true, then the item will be removed if it has no more times.
local reduceDropedItem = false

local function isSentToPlayer(player, toCylinder)
    if not toCylinder then
        return RETURNVALUE_NOTPOSSIBLE
    end
    if toCylinder:isTile() then
        return RETURNVALUE_NOTPOSSIBLE
    end
    if toCylinder == player or toCylinder:getTopParent() == player then
        return RETURNVALUE_NOERROR
    end
    return RETURNVALUE_NOTPOSSIBLE
end

local ec = EventCallback

function ec.onMoveItem(player, item, count, fromPosition, toPosition, fromCylinder, toCylinder)
    local toTile = Tile(toPosition)
    if toTile and toTile:hasFlag(TILESTATE_TRASHHOLDER) then
        return RETURNVALUE_NOERROR
    elseif item:getCustomAttribute(tradeKey) then
        return isSentToPlayer(player, toCylinder)
    elseif item:getType():isContainer() then
        for _, item in pairs(item:getItems(true)) do
            if item:getCustomAttribute(tradeKey) then
                return isSentToPlayer(player, toCylinder)
            end
        end
    end
    return RETURNVALUE_NOERROR
end

ec:register(-1)

function ec.onTradeRequest(player, target, item)
    local itemTT = item:getCustomAttribute(tradeKey)
    if itemTT and itemTT < 1 then
        player:sendCancelMessage("You can't trade this item anymore.")
        return false
    end

    if item:getType():isContainer() then
        for _, it in pairs(item:getItems(true)) do
            local itTT = it:getCustomAttribute(tradeKey)
            if itTT and itTT < 1 then
                player:sendCancelMessage("You can't trade this item anymore.")
                return false
            end
        end
    end
    return true
end

ec:register(-1)

function ec.onTradeCompleted(player, target, item, targetItem, isSuccess)
    if not isSuccess then
        return
    end

    local itemTT = item:getCustomAttribute(tradeKey)
    if itemTT then
        item:setCustomAttribute(tradeKey, itemTT - 1)
    end

    if item:getType():isContainer() then
        for _, it in pairs(item:getItems(true)) do
            local itTT = it:getCustomAttribute(tradeKey)
            if itTT then
                it:setCustomAttribute(tradeKey, itTT - 1)
            end
        end
    end

    local targetItemTT = targetItem:getCustomAttribute(tradeKey)
    if targetItemTT then
        targetItem:setCustomAttribute(tradeKey, targetItemTT - 1)
    end

    if targetItem:getType():isContainer() then
        for _, it in pairs(targetItem:getItems(true)) do
            local itTT = it:getCustomAttribute(tradeKey)
            if itTT then
                it:setCustomAttribute(tradeKey, itTT - 1)
            end
        end
    end
end

ec:register(-1)

local function onLook(item, description)
    local tradeTimes = item:getCustomAttribute(tradeKey)
    if not tradeTimes then
        return description
    end
    if tradeTimes > 0 then
        return string.format("%s\nIt can be traded %d more times.", description, tradeTimes)
    end
    return string.format("%s\nIt can no longer be traded.", description)
end

function ec.onLook(player, thing, position, distance, description)
    if not thing:isItem() then
        return description
    end
    return onLook(thing, description)
end

ec:register(1)

function ec.onLookInTrade(player, partner, item, distance, description)
    return onLook(item, description)
end

ec:register(1)

local action = Action()

function action.onUse(player, item, fromPos, target, toPos, isHotkey)
    if not target or not target:isItem() then
        player:sendCancelMessage(RETURNVALUE_NOTPOSSIBLE)
        return true
    end

    local tradeTimes = target:getCustomAttribute(tradeKey)
    if not tradeTimes then
        player:sendCancelMessage("This item not support trade times.")
        return true
    end

    if tradeTimes >= maxTradeTimes then
        player:sendCancelMessage("This item already has the maximum trade times.")
        return true
    end

    tradeTimes = tradeTimes + 1
    target:setCustomAttribute(tradeKey, tradeTimes)
    item:remove(1)
    player:getPosition():sendMagicEffect(effect)
    return true
end

action:id(tradeStoneId)
action:register()

local death = CreatureEvent("TradeTimesDeath")

function death.onDeath(player, corpse, lastHitKiller, mostDamageKiller, lastHitUnjustified, mostDamageUnjustified)
    if checkDropLootOrder then
        local foundDropLoot = false
        for _, eventName in pairs(player:getEvents(CREATURE_EVENT_DEATH)) do
            if eventName == "DropLoot" then
                foundDropLoot = true
            elseif eventName == "TradeTimesDeath" and not foundDropLoot then
                print("[TradeTimesDeath - Warning] must be after DropLoot.")
            end
        end
    end

    for _, item in pairs(corpse:getItems(true)) do
        local tradeTimes = item:getCustomAttribute(tradeKey)
        if tradeTimes then
            if removeDropedItem then
                item:remove()
            elseif reduceDropedItem then
                if tradeTimes > 1 then
                    item:setCustomAttribute(tradeKey, tradeTimes - 1)
                else
                    item:remove()
                end
            end
        end
    end
    return true
end

death:register()

local login = CreatureEvent("TradeTimesLogin")

function login.onLogin(player)
    player:registerEvent("TradeTimesDeath")
    return true
end

login:register()

OFC how to forget it, we also have a special item that serves to add time to the item that are working with this system.
View attachment 71503 ID: 8302, Name: iced soil
this item will add times up to the maximum limit, if the item can't get them it will send you a message saying you can't add times.

The items that are working with the system will show a description with the number of times it has:
View attachment 71504View attachment 71505


Important:
These items for obvious reasons cannot be thrown on the ground, nor in containers that are on the ground.
They also cannot be contained in the deposits since in this way they could be traded through the market and would lose their personalized attributes.
Although you can't throw them on the ground, you can throw them in dumpsters for disposal.
If you have several items inside a backpack and it is exchanged, all its items with times will be affected.
You can't trade items that don't have enough times.

Suggestions:
If you manage to find a way to break the system by making timed items tradable to other players without wasting time or simply ignoring the system let me know so I can fix it.
If you get any errors let me know.
Please if you don't use the engine TFS 1.5 (master) don't complain here, this system was not designed for other versions.

Warnings:
The system parses containers with the getItems function recursively so if you have items stored too deep it could affect your server performance if you have a sizeable amount of players constantly moving containers too deep. (if you have few players you shouldn't mind this at all)
What I said above may not be true, I have never tried this on a large scale, please do your testing and let me know.


I have a problem since it does not work I get the following error
scripts\tradetimes.lua:34: attempt to index local 'ec' (a nil value)
stack traceback:
[C]: in function '__newindex'
 
can anyone tell what is needed to make it work on tfs 1.4?

If needed I can add mission functions from tfs 1.5 github to my 1.4 server

The items are showing "can be traded another x times" or "can no longer be traded", but I can still trade them and throw in the ground as well.

No errors on the console, anyone have any advice?
 
The items are showing "can be traded another x times" or "can no longer be traded", but I can still trade them and throw in the ground as well.
Make sure you have all the necessary events enabled on events.xml (onMoveItem, onTradeCompleted, onTradeRequest)
 
Make sure you have all the necessary events enabled on events.xml (onMoveItem, onTradeCompleted, onTradeRequest)
I didn't have those trade events enabled, but even after I enabled (and restarted the server) they are still not working and there is no errors on console as well.

My Guess is that maybe something is missing on tfs 1.4, I would love to know what is that
 
My Guess is that maybe something is missing on tfs 1.4, I would love to know what is that
In 1.4 for some reason, negative register numbers don't work.
So changing this ec:register(-1) to this ec:register(1) would solve your issue.
Posted it here also incase someone will use the system in 1.4
 
In 1.4 for some reason, negative register numbers don't work.
So changing this ec:register(-1) to this ec:register(1) would solve your issue.
Posted it here also incase someone will use the system in 1.4
Just tried those changes, ec:register(-1) to ec:register(1), still not working, also tried changing to ec:register()

Same thing...no console errors, but letting me trade and drop on the floor items that have 0 trading times.
 
Hi @farp I'm so sorry if it doesn't work for you in your version, do what @Roddet said about enabled the necessary events.
If it doesn't work for you, then it's possible that you don't have the eventcallback system configured correctly, or you're just using a custom TFS 1.4 version where these events don't work correctly.
It is worth mentioning that although this system may work on TFS 1.4, it does not mean that this system is free of potential bugs.
that's why I recommend using TFS 1.5
 
Hi @farp I'm so sorry if it doesn't work for you in your version, do what @Roddet said about enabled the necessary events.
If it doesn't work for you, then it's possible that you don't have the eventcallback system configured correctly, or you're just using a custom TFS 1.4 version where these events don't work correctly.
It is worth mentioning that although this system may work on TFS 1.4, it does not mean that this system is free of potential bugs.
that's why I recommend using TFS 1.5
M0ustafa found a solution, My old tfs 1.4 didn't work with those returns "RETURNVALUE_NOTPOSSIBLE" and "RETURNVALUE_NOERROR" had to change them to "true, false"


Yea, i get that using TFS 1.5 is ideal, but my server have too many changes already, that make it too hard to migrate.
 
TradeTimes System

System that controls how many times a specific item can be traded.
The system does not time any items, you must do it yourself in your own scripts.
If you want to try using it on TFS 1.4 here is a solution


Here is an example of how you can add an item to the system:
yourscript.lua
Lua:
item:setCustomAttribute("TradeTimes", 3)
Why use the key "TradeTimes"? - We use this key because it is the one we are using in the system script.

Once you understand this, we can continue with the installation of the system...
data/scripts/tradetimes.lua
Lua:
local tradeStoneId = 8302
local maxTradeTimes = 3
local tradeKey = "TradeTimes"
local effect = CONST_ME_FIREWORK_BLUE

-- Warning:
-- This prints a warning to the console if the execution order is not correct.
-- If the warning is triggered, it means that there is a possibility that an item with TradeTimes will fall to the ground.
-- If you are sure that the order is correct, you can disable this to make your script faster.
local checkDropLootOrder = true

-- If an item with TradeTimes is found on the corpse, should we remove it?
local removeDropedItem = true

-- If an item with TradeTimes is found on the corpse, should we reduce the times?
-- If removeDropedItem is false and this variable is true, then the item will be removed if it has no more times.
local reduceDropedItem = false

local function isSentToPlayer(player, toCylinder)
    if not toCylinder then
        return RETURNVALUE_NOTPOSSIBLE
    end
    if toCylinder:isTile() then
        return RETURNVALUE_NOTPOSSIBLE
    end
    if toCylinder == player or toCylinder:getTopParent() == player then
        return RETURNVALUE_NOERROR
    end
    return RETURNVALUE_NOTPOSSIBLE
end

local ec = EventCallback

function ec.onMoveItem(player, item, count, fromPosition, toPosition, fromCylinder, toCylinder)
    local toTile = Tile(toPosition)
    if toTile and toTile:hasFlag(TILESTATE_TRASHHOLDER) then
        return RETURNVALUE_NOERROR
    elseif item:getCustomAttribute(tradeKey) then
        return isSentToPlayer(player, toCylinder)
    elseif item:getType():isContainer() then
        for _, item in pairs(item:getItems(true)) do
            if item:getCustomAttribute(tradeKey) then
                return isSentToPlayer(player, toCylinder)
            end
        end
    end
    return RETURNVALUE_NOERROR
end

ec:register(-1)

function ec.onTradeRequest(player, target, item)
    local itemTT = item:getCustomAttribute(tradeKey)
    if itemTT and itemTT < 1 then
        player:sendCancelMessage("You can't trade this item anymore.")
        return false
    end

    if item:getType():isContainer() then
        for _, it in pairs(item:getItems(true)) do
            local itTT = it:getCustomAttribute(tradeKey)
            if itTT and itTT < 1 then
                player:sendCancelMessage("You can't trade this item anymore.")
                return false
            end
        end
    end
    return true
end

ec:register(-1)

function ec.onTradeCompleted(player, target, item, targetItem, isSuccess)
    if not isSuccess then
        return
    end

    local itemTT = item:getCustomAttribute(tradeKey)
    if itemTT then
        item:setCustomAttribute(tradeKey, itemTT - 1)
    end

    if item:getType():isContainer() then
        for _, it in pairs(item:getItems(true)) do
            local itTT = it:getCustomAttribute(tradeKey)
            if itTT then
                it:setCustomAttribute(tradeKey, itTT - 1)
            end
        end
    end

    local targetItemTT = targetItem:getCustomAttribute(tradeKey)
    if targetItemTT then
        targetItem:setCustomAttribute(tradeKey, targetItemTT - 1)
    end

    if targetItem:getType():isContainer() then
        for _, it in pairs(targetItem:getItems(true)) do
            local itTT = it:getCustomAttribute(tradeKey)
            if itTT then
                it:setCustomAttribute(tradeKey, itTT - 1)
            end
        end
    end
end

ec:register(-1)

local function onLook(item, description)
    local tradeTimes = item:getCustomAttribute(tradeKey)
    if not tradeTimes then
        return description
    end
    if tradeTimes > 0 then
        return string.format("%s\nIt can be traded %d more times.", description, tradeTimes)
    end
    return string.format("%s\nIt can no longer be traded.", description)
end

function ec.onLook(player, thing, position, distance, description)
    if not thing:isItem() then
        return description
    end
    return onLook(thing, description)
end

ec:register(1)

function ec.onLookInTrade(player, partner, item, distance, description)
    return onLook(item, description)
end

ec:register(1)

local action = Action()

function action.onUse(player, item, fromPos, target, toPos, isHotkey)
    if not target or not target:isItem() then
        player:sendCancelMessage(RETURNVALUE_NOTPOSSIBLE)
        return true
    end

    local tradeTimes = target:getCustomAttribute(tradeKey)
    if not tradeTimes then
        player:sendCancelMessage("This item not support trade times.")
        return true
    end

    if tradeTimes >= maxTradeTimes then
        player:sendCancelMessage("This item already has the maximum trade times.")
        return true
    end

    tradeTimes = tradeTimes + 1
    target:setCustomAttribute(tradeKey, tradeTimes)
    item:remove(1)
    player:getPosition():sendMagicEffect(effect)
    return true
end

action:id(tradeStoneId)
action:register()

local death = CreatureEvent("TradeTimesDeath")

function death.onDeath(player, corpse, lastHitKiller, mostDamageKiller, lastHitUnjustified, mostDamageUnjustified)
    if checkDropLootOrder then
        local foundDropLoot = false
        for _, eventName in pairs(player:getEvents(CREATURE_EVENT_DEATH)) do
            if eventName == "DropLoot" then
                foundDropLoot = true
            elseif eventName == "TradeTimesDeath" and not foundDropLoot then
                print("[TradeTimesDeath - Warning] must be after DropLoot.")
            end
        end
    end

    for _, item in pairs(corpse:getItems(true)) do
        local tradeTimes = item:getCustomAttribute(tradeKey)
        if tradeTimes then
            if removeDropedItem then
                item:remove()
            elseif reduceDropedItem then
                if tradeTimes > 1 then
                    item:setCustomAttribute(tradeKey, tradeTimes - 1)
                else
                    item:remove()
                end
            end
        end
    end
    return true
end

death:register()

local login = CreatureEvent("TradeTimesLogin")

function login.onLogin(player)
    player:registerEvent("TradeTimesDeath")
    return true
end

login:register()

OFC how to forget it, we also have a special item that serves to add time to the item that are working with this system.
View attachment 71503 ID: 8302, Name: iced soil
this item will add times up to the maximum limit, if the item can't get them it will send you a message saying you can't add times.

The items that are working with the system will show a description with the number of times it has:
View attachment 71504View attachment 71505


Important:
These items for obvious reasons cannot be thrown on the ground, nor in containers that are on the ground.
They also cannot be contained in the deposits since in this way they could be traded through the market and would lose their personalized attributes.
Although you can't throw them on the ground, you can throw them in dumpsters for disposal.
If you have several items inside a backpack and it is exchanged, all its items with times will be affected.
You can't trade items that don't have enough times.

Suggestions:
If you manage to find a way to break the system by making timed items tradable to other players without wasting time or simply ignoring the system let me know so I can fix it.
If you get any errors let me know.
Please if you don't use the engine TFS 1.5 (master) don't complain here, this system was not designed for other versions.

Warnings:
The system parses containers with the getItems function recursively so if you have items stored too deep it could affect your server performance if you have a sizeable amount of players constantly moving containers too deep. (if you have few players you shouldn't mind this at all)
What I said above may not be true, I have never tried this on a large scale, please do your testing and let me know.
hello i am trying but i am missing eventscalls i use tfs 1.3 otclientv8
tibia 1098
any link to be able to implement this of eventscalls?
 
Back
Top