- Joined
- Mar 16, 2017
- Messages
- 1,428
- Solutions
- 155
- Reaction score
- 1,996
- 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)
"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.
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:
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: