• 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.5 lua error

Akira1992

New Member
Joined
Jun 8, 2025
Messages
9
Reaction score
1
Was trying to add this daily chest script in temple for people to take but a bit lost in the 1.5 TFS
Thanks for the help in making me understand what is wrong!

LUA:
data\scripts\actions\daily_chest.lua:21: attempt to perform arithmetic on a nil value
stack traceback:
        [C]: in metamethod 'sub'

LUA:
local expItem = Action()

local items = {{2160, 1}}

local function secondsToReadable(s)
    local hours   = math.floor(s / 3600)
    local minutes = math.floor(math.fmod(s, 3600)/60)
    local seconds = math.floor(math.fmod(s, 60))
    return (hours   > 0 and (hours   .. ' hour'   .. (hours   > 1 and 's ' or ' ')) or '') ..
           (minutes > 0 and (minutes .. ' minute' .. (minutes > 1 and 's ' or ' ')) or '') ..
           (seconds > 0 and (seconds .. ' second' .. (seconds > 1 and 's ' or ' ')) or '')
end

function expItem.onUse(player, item, fromPosition, target, toPosition, isHotkey)

    local randomIndex = math.random(1, #items)
    local itemId = items[randomIndex][1]
    local itemCount = items[randomIndex][2]
    local exhaust = 53964

    if player:getStorageValue(exhaust) - os.time() > 0 then
        local timeRemaining = secondsToReadable(player:getStorageValue(exhaust) - os.time())
        player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "You can take your daily reward again in: ".. timeRemaining .."")
        return true
    end

    local item = player:addItem(itemId, itemCount)
    player:setStorageValue(exhaust, os.time() + 1)
    --player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "You have received "..itemCount.."x "..itemId:getName().."")
    print(item:getName())
    return true
end

expItem:aid(64053)
expItem:register()
 
Thank you for the replies, still learning so just to be clear this, doesn't this entire part check for storage?
LUA:
if player:getStorageValue(exhaust) - os.time() > 0 then
        local timeRemaining = secondsToReadable(player:getStorageValue(exhaust) - os.time())

I tried adding the line you mentioned above but getting
LUA:
'then' expected near '='

Thank you for all your help and helping me understand!
 
Just find this part of the code,

LUA:
if player:getStorageValue(exhaust) - os.time() > 0 then
        local timeRemaining = secondsToReadable(player:getStorageValue(exhaust) - os.time())
        player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "You can take your daily reward again in: ".. timeRemaining .."")
        return true
    end

replace it with the new version, and test it. It should work fine.

LUA:
 local storedTime = player:getStorageValue(exhaust)
    if storedTime ~= -1 and storedTime - os.time() > 0 then
        local timeRemaining = secondsToReadable(storedTime - os.time())
        player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "You can take your daily reward again in: " .. timeRemaining)
        return true
    end
 
Just find this part of the code,

LUA:
if player:getStorageValue(exhaust) - os.time() > 0 then
        local timeRemaining = secondsToReadable(player:getStorageValue(exhaust) - os.time())
        player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "You can take your daily reward again in: ".. timeRemaining .."")
        return true
    end

replace it with the new version, and test it. It should work fine.

LUA:
 local storedTime = player:getStorageValue(exhaust)
    if storedTime ~= -1 and storedTime - os.time() > 0 then
        local timeRemaining = secondsToReadable(storedTime - os.time())
        player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "You can take your daily reward again in: " .. timeRemaining)
        return true
    end

Thank you for providing me with this code, however this is showing now :p

LUA:
\data\scripts\actions\daily_chest.lua:callback
\data\scripts\actions\daily_chest.lua:22: attempt to perform arithmetic on a nil value (local 'storedTime')
stack traceback:
        [C]: in metamethod 'sub'
        \data\scripts\actions\daily_chest.lua:22: in function <\data\scripts\actions\daily_chest.lua:14>

Kind Regards :)
Post automatically merged:

I have only provided you with pseudocode logic you will have to figure out how operators and or == work first before you start scripting i recommend going into lua tutorials :)
if you feel like this is too hard then just try using the local forum tutorials.
I will defo look into it and hopefully learn something useful my friend. Thank you
Post automatically merged:

Also I am using TFS 1.5 by GitHub - MillhioreBT/forgottenserver-downgrade: TFS Downgrade 1.5+ is an engine based on nekiro downgrade but highly updated with current tfs code, it also has the lua modules divided and uses lua5.4 (https://github.com/MillhioreBT/forgottenserver-downgrade/tree/main) so not sure how much different it is compared to Nekiros original 1.5
 
Last edited:
LUA:
local expItem = Action()

local items = {
    {2160, 1}
}

local function secondsToReadable(s)
    local hours   = math.floor(s / 3600)
    local minutes = math.floor(math.fmod(s, 3600) / 60)
    local seconds = math.floor(math.fmod(s, 60))
    return (hours   > 0 and (hours   .. ' hour'   .. (hours   > 1 and 's ' or ' ')) or '') ..
           (minutes > 0 and (minutes .. ' minute' .. (minutes > 1 and 's ' or ' ')) or '') ..
           (seconds > 0 and (seconds .. ' second' .. (seconds > 1 and 's ' or ' ')) or '')
end

function expItem.onUse(player, item, fromPosition, target, toPosition, isHotkey)
    local exhaust = 53964

    local lastUse = player:getStorageValue(exhaust)
    local now = os.time()

    if lastUse ~= -1 and lastUse > now then
        local timeRemaining = secondsToReadable(lastUse - now)
        player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "You can take your daily reward again in: " .. timeRemaining)
        return true
    end

    local randomIndex = math.random(1, #items)
    local itemId = items[randomIndex][1]
    local itemCount = items[randomIndex][2]

    local addedItem = player:addItem(itemId, itemCount)
    if addedItem then
        player:setStorageValue(exhaust, math.floor(now + 86400))  -- 24h cooldown
        player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "You have received " .. itemCount .. "x " .. addedItem:getName())
        print(addedItem:getName())
    else
        player:sendTextMessage(MESSAGE_STATUS_WARNING, "Unable to add item to your inventory.")
    end

    return true
end

expItem:aid(64053)
expItem:register()


LUA:
Lua Script Error: [Scripts Interface]
C:\Users\Desktop\TFS 1.5\data\scripts\actions\others\daily_chest.lua:callback
... Updated\data\scripts\actions\others\daily_chest.lua:22: attempt to compare number with nil
stack traceback:
        [C]: in metamethod 'lt'
        ... Updated\data\scripts\actions\others\daily_chest.lua:22: in function <... Updated\data\scripts\actions\others\daily_chest.lua:16>

Thanks for trying to help :)
 
LUA:
local lastUse = player:getStorageValue(exhaust) or 0
you can also try.

LUA:
local lastUse = tonumber(player:getStorageValue(exhaust)) or 0
Tonumber will ensure that even if it returns nil it will return a number most

LUA:
local rawValue = player:getStorageValue(exhaust)

local lastUse = tonumber(rawValue)



if not lastUse then

    lastUse = 0

end



LUA:
local rawValue = player:getStorageValue(exhaust)

local lastUse = type(rawValue) == "number" and rawValue or tonumber(rawValue) or 0

try any of those combinations I have not used this engine ( and for good reasons such as this bs)

Thank you I will try this, you think the engine is the issue here? Have been looking at other possibilites such us 0.4 or just the 1.5 Nekiros without any further work as this one seems to use lua 5.4 and others older versions? Just wanted a stable trunk without major issues :p
Post automatically merged:

LUA:
local lastUse = player:getStorageValue(exhaust) or 0
you can also try.

LUA:
local lastUse = tonumber(player:getStorageValue(exhaust)) or 0
Tonumber will ensure that even if it returns nil it will return a number most

LUA:
local rawValue = player:getStorageValue(exhaust)

local lastUse = tonumber(rawValue)



if not lastUse then

    lastUse = 0

end



LUA:
local rawValue = player:getStorageValue(exhaust)

local lastUse = type(rawValue) == "number" and rawValue or tonumber(rawValue) or 0

try any of those combinations I have not used this engine ( and for good reasons such as this bs)

LUA:
local lastUse = player:getStorageValue(exhaust) or 0

This seems to have fixed it and is working without any issues or errors in console.

Appreciate the help :) also is there a reason why the console prints out the reward name? After pressing on the chest the crystal coin message shows up in the console x


daily test.webp
 
Last edited:
Just find this part of the code,

LUA:
if player:getStorageValue(exhaust) - os.time() > 0 then
        local timeRemaining = secondsToReadable(player:getStorageValue(exhaust) - os.time())
        player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "You can take your daily reward again in: ".. timeRemaining .."")
        return true
    end

replace it with the new version, and test it. It should work fine.

LUA:
 local storedTime = player:getStorageValue(exhaust)
    if storedTime ~= -1 and storedTime - os.time() > 0 then
        local timeRemaining = secondsToReadable(storedTime - os.time())
        player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "You can take your daily reward again in: " .. timeRemaining)
        return true
    end
i will change
LUA:
local storedTime = player:getStorageValue(exhaust)
to
LUA:
local storedTime = player:getStorageValue(exhaust) or -1
 
Back
Top