Lua This free inventory check script won't work.

Demnish

Tibian Hero
Joined
Sep 28, 2011
Messages
276
Reaction score
17
Location
Sweden
I need a check to determine if the player has any available slots where items can be placed.
This script will be used for quests etc, I've already made a check on the player's cap, now I need to check for the player's available slots.
Code:
function onUse(cid, item, frompos, item2, topos)
    local BP = getPlayerSlotItem(cid, CONST_SLOT_BACKPACK).uid
    if getContainerCapByID(BP) < 1 then
        doStuff
    else
        doOtherStuff
    end
Can't get it to work, all I get is:
attempt to call global 'getContainerCapByID' (a nil value)
With or without a backpack.

This is the function from functions.lua:
Code:
getContainerCapById(itemid)
Any help will be greatly appreciated! :)
 
Last edited:

gudan garam

Intermediate OT User
Joined
Feb 13, 2011
Messages
276
Reaction score
85
Location
Tibialand
Which tfs version are you running?

I think getContainerCapByID expects you to pass the items id, depending on the tfs version you are running the BP variable could be userdata or whatever it was in the earlier versions.

Maybe try
Code:
getContainerCapByID(BP.itemid)
or
getContainerCapByID(BP:getId())
or something like that.

Remember to always post the tfs version you are using, it is really helpful.
 
OP
Demnish

Demnish

Tibian Hero
Joined
Sep 28, 2011
Messages
276
Reaction score
17
Location
Sweden
I'm not running TFS, I'm actually running OTServ 0.6.4 since I read it is the most stable distro.
I tried the ones you mentioned and while it didn't work. I got a new error which was quite interesting:
attempt to index local 'BP' (a number value)
(I also tried "getContainerCapByID(BP.uid)" and got the same result)

This works as far as checking for backpack, however checking for remaining slots does not:
Code:
function onUse(cid, item, frompos, item2, topos)'
    local BP = getPlayerSlotItem(cid, CONST_SLOT_BACKPACK)
    if BP.uid == 0 or getContainerCap(BP.uid) == false then
        doPlayerSendTextMessage(cid, MESSAGE_INFO_DESCR, "You have no backpack.")
    elseif getContainerCap(BP.uid) >= 1 then
        doPlayerSendTextMessage(cid, MESSAGE_INFO_DESCR, "Item added!")
    else
        doPlayerSendTextMessage(cid, MESSAGE_INFO_DESCR, "You have no room.")
    end
 
Last edited:

Xikini

I whore myself out for likes
Joined
Nov 17, 2010
Messages
3,925
Reaction score
2,046
I'm not running TFS, I'm actually running OTServ 0.6.4 since I read it is the most stable distro.
I tried the ones you mentioned and while it didn't work. I got a new error which was quite interesting:

(I also tried "getContainerCapByID(BP.uid)" and got the same result)

This works as far as checking for backpack, however checking for remaining slots does not:
Code:
function onUse(cid, item, frompos, item2, topos)'
    local BP = getPlayerSlotItem(cid, CONST_SLOT_BACKPACK)
    if BP.uid == 0 or getContainerCap(BP.uid) == false then
        doPlayerSendTextMessage(cid, MESSAGE_INFO_DESCR, "You have no backpack.")
    elseif getContainerCap(BP.uid) >= 1 then
        doPlayerSendTextMessage(cid, MESSAGE_INFO_DESCR, "Item added!")
    else
        doPlayerSendTextMessage(cid, MESSAGE_INFO_DESCR, "You have no room.")
    end
I believe you are trying to use a cube in place of a triangle.

Try something like this instead.
Lua:
local item_id, count = 1988, 1

function onUse(cid, item, fromPosition, itemEx, toPosition)
    local reward, weight = doCreateItemEx(item_id, count), getItemWeightById(item_id, count)
    if doPlayerAddItemEx(cid, reward, false) == RETURNVALUE_NOERROR then
        doPlayerSendTextMessage(cid, MESSAGE_INFO_DESCR, "You have found a " .. getItemNameById(item_id) .. " weighing ".. string.format("%.2f", weight) .." oz.")
        return true
    else
        local cap = getPlayerFreeCap(cid)
        if cap < weight then
            doPlayerSendTextMessage(cid, MESSAGE_INFO_DESCR, "Require " .. string.format("%.2f", weight - cap) .. " more capacity to receive this reward weighing ".. string.format("%.2f", weight) .." oz.")
        else
            doPlayerSendTextMessage(cid, MESSAGE_INFO_DESCR, "You don't have any room to obtain this reward.")
        end
    end
    return true
end
-- Edit
If you are getting errors with 'weight' check below.

-- in case your lib doesn't have the function for whatever reason, put this into data/lib/050-function.lua
Lua:
function getItemWeightById(itemid, count, precision)
    local item, count, precision = getItemInfo(itemid), count or 1, precision or false
    if(not item) then
        return false
    end
   
    if(count > 100) then
        -- print a warning, as its impossible to have more than 100 stackable items without "cheating" the count
        --print('[Warning] getItemWeightById', 'Calculating weight for more than 100 items!')
    end
   
    local weight = item.weight * count
    return precission and weight or math.round(weight, 2)
end
 
OP
Demnish

Demnish

Tibian Hero
Joined
Sep 28, 2011
Messages
276
Reaction score
17
Location
Sweden
I think it's easier if I just post my whole script:
Code:
local ITEM = 2195
local COUNT = 1
local DROPONGROUND = false

local ITEMNAME = getItemName(ITEM)
local STORAGE = getItemIdByName(ITEMNAME)
local WEIGHT = getItemWeightById(ITEM, COUNT)

function onUse(cid, item, frompos, item2, topos)
    if getPlayerFreeCap(cid) >= WEIGHT then
        if getPlayerStorageValue(cid, STORAGE) ~= 1 then
            if COUNT == 1 then
                doPlayerAddItem(cid, ITEM, COUNT, DROPONGROUND)
                doPlayerSendTextMessage(cid, MESSAGE_INFO_DESCR, "You have found "..ITEMNAME.."!")
                doSendMagicEffect(getCreaturePosition(cid), CONST_ME_MAGIC_GREEN)
                setPlayerStorageValue(cid, STORAGE, 1)
            elseif COUNT > 1 then
                doPlayerAddItem(cid, ITEM, COUNT, DROPONGROUND)
                doPlayerSendTextMessage(cid, MESSAGE_INFO_DESCR, "You have found "..COUNT.."x "..ITEMNAME.."!")
                doSendMagicEffect(getCreaturePosition(cid), CONST_ME_MAGIC_GREEN)
                setPlayerStorageValue(cid, STORAGE, 1)
            end
        else
            doPlayerSendTextMessage(cid, MESSAGE_INFO_DESCR, "It is empty.")
            doSendMagicEffect(getCreaturePosition(cid), CONST_ME_POFF)
        end
    else
        doPlayerSendTextMessage(cid, MESSAGE_INFO_DESCR, "You do not have enough capacity.")
    end
end
I've solved the cap check, more or less. But what I haven't solved is the check to see if the player has any free inventory.
Since my script runs on "DROPONGROUND = false" the player will recieve the reward even if he lacks the inventory slot but has the capacity, which triggers the storage and the item can never again be claimed.
I managed to make a temporary fix like they used back in the old OT's by making DROPONGROUND = true, which in turn just drops the item on the ground, but then again other players can pick it up instead, which makes it just a temporary solution to a permanent problem.
 
Last edited:

Xikini

I whore myself out for likes
Joined
Nov 17, 2010
Messages
3,925
Reaction score
2,046
I think it's easier if I just post my whole script:
Code:
local ITEM = 2195
local COUNT = 1
local DROPONGROUND = false

local ITEMNAME = getItemName(ITEM)
local STORAGE = getItemIdByName(ITEMNAME)
local WEIGHT = getItemWeightById(ITEM, COUNT)

function onUse(cid, item, frompos, item2, topos)
    if getPlayerFreeCap(cid) >= WEIGHT then
        if getPlayerStorageValue(cid, STORAGE) ~= 1 then
            if COUNT == 1 then
                doPlayerAddItem(cid, ITEM, COUNT, DROPONGROUND)
                doPlayerSendTextMessage(cid, MESSAGE_INFO_DESCR, "You have found "..ITEMNAME.."!")
                doSendMagicEffect(getCreaturePosition(cid), CONST_ME_MAGIC_GREEN)
                setPlayerStorageValue(cid, STORAGE, 1)
            elseif COUNT > 1 then
                doPlayerAddItem(cid, ITEM, COUNT, DROPONGROUND)
                doPlayerSendTextMessage(cid, MESSAGE_INFO_DESCR, "You have found "..COUNT.."x "..ITEMNAME.."!")
                doSendMagicEffect(getCreaturePosition(cid), CONST_ME_MAGIC_GREEN)
                setPlayerStorageValue(cid, STORAGE, 1)
            end
        else
            doPlayerSendTextMessage(cid, MESSAGE_INFO_DESCR, "It is empty.")
            doSendMagicEffect(getCreaturePosition(cid), CONST_ME_POFF)
        end
    else
        doPlayerSendTextMessage(cid, MESSAGE_INFO_DESCR, "You do not have enough capacity.")
    end
end
I've solved the cap check, more or less. But what I haven't solved is the check to see if the player has any free inventory.
Since my script runs on "DROPONGROUND = false" the player will recieve the reward even if he lacks the inventory slot but has the capacity, which triggers the storage and the item can never again be claimed.
I managed to make a temporary fix like they used back in the old OT's by making DROPONGROUND = true, which in turn just drops the item on the ground, but then again other players can pick it up instead, which makes it just a temporary solution to a permanent problem.
I posted exactly what you wanted 3 hours before you posted this reply.
Here's the exact same script.. but with your '1 time use storage' requirement.
Lua:
local item_id, count = 1988, 1
local storage = 45001

function onUse(cid, item, fromPosition, itemEx, toPosition)
    if getPlayerStorageValue(cid, storage) == 1 then
        doSendMagicEffect(fromPosition, CONST_ME_POFF)
        doPlayerSendCancel(cid, "Chest is empty.")
        return true
    end
   
    local reward, weight = doCreateItemEx(item_id, count), getItemWeightById(item_id, count)
    if doPlayerAddItemEx(cid, reward, false) == RETURNVALUE_NOERROR then
        doPlayerSendTextMessage(cid, MESSAGE_INFO_DESCR, "You have found a " .. getItemNameById(item_id) .. " weighing ".. string.format("%.2f", weight) .." oz.")
        setPlayerStorageValue(cid, storage, 1)
        return true
    else
        local cap = getPlayerFreeCap(cid)
        if cap < weight then
            doPlayerSendTextMessage(cid, MESSAGE_INFO_DESCR, "Require " .. string.format("%.2f", weight - cap) .. " more capacity to receive this reward weighing ".. string.format("%.2f", weight) .." oz.")
        else
            doPlayerSendTextMessage(cid, MESSAGE_INFO_DESCR, "You don't have any room to obtain this reward.")
        end
    end
    return true
end
 
OP
Demnish

Demnish

Tibian Hero
Joined
Sep 28, 2011
Messages
276
Reaction score
17
Location
Sweden
Yeah, thanks a lot for helping me out mate, however I had to abandon that distro. Way too many bugs and glitches to be worth working on, I switched to a 10.98 distro instead since the nature of my project doesn't really depend on the client version. Also a newer distro might be more worth putting time into, the OTServ 0.6.4 had problems such as manas not usable on ladders and this problem I mentioned in this thread among a lot of other problems. Since my VC17 is problematic I really have no energy to work with the sources either so I chose TFS 1.2 instead since it seems to have what I'm looking for, more or less anyway.

Keep helping the community, we appreciate you around here!
 

cbrm

Just another mod
Staff member
Global Moderator
Joined
Jan 6, 2009
Messages
6,551
Reaction score
804
Location
Caribbean Sea
Lua:
function _getContainerFreeSlots(container)
    return getContainerCap(container) - getContainerSize(container)
end

function getContainerFreeSlots(container)
    if not isContainer(container) then
        return 0
    end

    local t, v = {}, 0
    for i = 0, getContainerSize(container)-1 do
        local item = getContainerItem(container, i)
        if isContainer(item.uid) then
            table.insert(t, item.uid)
        end
    end

    for _, check in pairs(t) do
        v = v + _getContainerFreeSlots(check)
    end

    return v + _getContainerFreeSlots(container)
end
usage
Lua:
if (getContainerFreeSlots(getPlayerSlotItem(cid, CONST_SLOT_BACKPACK).uid) == 0) then
-- has full bp!
 
Top