• 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.X] Give player items by table

Infernum

Senator
Joined
Feb 14, 2015
Messages
5,643
Solutions
559
Reaction score
3,949
inspired by @Xikini, his code for 0.x linked here
If someone wants to convert the scant amount of actual functions for TFS 1.0+, please do so.


Lua:
function Player.giveItems(self, t)
    local cap = (ItemType(1988):getWeight() / 100) * (math.floor(#t / 20) + 1)
    for i = 1, #t do
        local v = t[i]
        cap = cap + ((ItemType(v[1]):getWeight() / 100) * v[2])
    end
    local resultCap = (self:getCapacity() / 100) - cap
    if resultCap < 0 then
        self:sendCancelMessage("You found a container weighing ".. cap .." oz. You require ".. math.abs(resultCap) .." more capacity in order to hold it.")
        self:getPosition():sendMagicEffect(CONST_ME_POFF)
        return false
    end
    local container = self:addItem(1988)
    local size = 0
    local slots = container:getCapacity()
    for i = 1, #t do
        local v = t[i]
        local itemType = ItemType(v[1])
        local n = itemType:isStackable() and 100 or 1
        local count = v[2]
        while count > 0 do
            -- create a new container in place of the last slot in the container
            if size + 1 == slots then
                container = container:addItem(1988)
                size = 0
            end

            container:addItem(v[1], n)
            count = count - n
            size = size + 1
        end
    end
    return true
end

example, gives a backpack with 48 arbalests and 300cc:
Lua:
local items = {
    {5803, 48},
    {2160, 300}
}

player:giveItems(items)
 
Last edited by a moderator:
You may add second optional parameter backpackId, probably this question can may happen.

If someone may have problem with it, solution:
Lua:
function Player.giveItems(self, t, backpackId)
  backpackId = backpackId or 1988
... and replace 1988 -> backpackId
 
You may add second optional parameter backpackId, probably this question can may happen.

If someone may have problem with it, solution:
Lua:
function Player.giveItems(self, t, backpackId)
  backpackId = backpackId or 1988
... and replace 1988 -> backpackId
Gave the optional containerId variable (which also allows containers with any size instead of only 20)

Fixed an issue where stackable items always gave 100
Fixed an issue where items with charges would only give 1 charge and multiple items, instead of 1 item and multiple charges.
Lua:
function Player.giveItems(self, itemTable, containerId) -- if containerId is nil or not a container, defaults to a brown bag 1987
    containerId = containerId and ItemType(containerId):isContainer() and containerId or 1987
    local cap = (ItemType(containerId):getWeight() / 100) * (math.floor(#itemTable / ItemType(containerId):getCapacity()) + 1)
    for i = 1, #itemTable do
        local v = itemTable[i]
        local itemType = ItemType(v[1])
        cap = cap + ((itemType:getWeight() / 100) * (itemType:getCharges() and 1 or v[2]))
    end
    local resultCap = (self:getFreeCapacity() / 100) - cap
    if resultCap < 0 then
        self:sendCancelMessage("You found a container weighing ".. cap .." oz. You require ".. math.abs(resultCap) .." more capacity in order to hold it.")
        self:getPosition():sendMagicEffect(CONST_ME_POFF)
        return false
    end
    local container = self:addItem(containerId)
    local size = 0
    local slots = container:getCapacity()
    for i = 1, #itemTable do
        local v = itemTable[i]
        local itemType = ItemType(v[1])
        local n = itemType:isStackable() and v[2] or itemType:getCharges() and v[2] or 1
        local count = itemType:getCharges() and 1 or v[2]
        while count > 0 do
            -- create a new container in place of the last slot in the container
            if size + 1 == slots then
                container = container:addItem(containerId)
                size = 0
            end
  
            container:addItem(v[1], n)
            count = count - n
            size = size + 1
        end
    end
    return true
end
 
Last edited:
Edited post above with some minor bug fixes.
 
Edited my above post again with 1 more bug fix to the weight check -> a bug I caused due to adding the check for item charges.

Additional bug/change self:getCapacity() -> self:getFreeCapacity()
Which checks the player free capacity instead of their full capacity.

---
However, here is an additional modification/upgrade

You'll need to install this in data/lib/core/container.lua for it to work.

-> new parameter canDropOnGround
-> new check, to confirm if a player has any inventory slots available to hold the item/container.
-> aforementioned bug fix to the weight/capacity

Because of the additional lib required, this is not a stand-alone function anymore..,
Hence the reason for a new post to separate it from the bug-fixed one.
Lua:
-- player:giveItems(itemTable[, containerId[, canDropOnGround = false]])

function Player.giveItems(self, itemTable, containerId, canDropOnGround)
    containerId = containerId and ItemType(containerId):isContainer() and containerId or 1987
    if canDropOnGround ~= nil and not canDropOnGround then
        -- check if player has 1 available slot to receive container
        local slotItem = getPlayerSlotItem(self, CONST_SLOT_BACKPACK).uid
        if getContainerFreeSlots(slotItem) == 0 and slotItem > 0 then
            self:sendCancelMessage("You have no available inventory slots to receive this item.")
            self:getPosition():sendMagicEffect(CONST_ME_POFF)
            return false
        end
        -- check if player has capacity to receive container + rewards
        local cap = (ItemType(containerId):getWeight() / 100) * (math.floor(#itemTable / ItemType(containerId):getCapacity()) + 1)
        for i = 1, #itemTable do
            local v = itemTable[i]
            local itemType = ItemType(v[1])
            cap = cap + ((itemType:getWeight() / 100) * (itemType:getCharges() and 1 or v[2]))
        end
        local resultCap = (self:getFreeCapacity() / 100) - cap
        if resultCap < 0 then
            self:sendCancelMessage("You found a container weighing ".. cap .." oz. You require ".. math.abs(resultCap) .." more capacity in order to hold it.")
            self:getPosition():sendMagicEffect(CONST_ME_POFF)
            return false
        end
    end
    -- create container and items to give to the player
    local container = self:addItem(containerId)
    local size = 0
    local slots = container:getCapacity()
    for i = 1, #itemTable do
        local v = itemTable[i]
        local itemType = ItemType(v[1])
        local n = itemType:isStackable() and v[2] or itemType:getCharges() and v[2] or 1
        local count = itemType:getCharges() and 1 or v[2]
        while count > 0 do
            -- create a new container in place of the last slot in the container
            if size + 1 == slots then
                container = container:addItem(containerId)
                size = 0
            end
  
            container:addItem(v[1], n)
            count = count - n
            size = size + 1
        end
    end
    return true
end
 
Last edited:
here is a slight alternative:

  • different reward depending on voc
  • if knight, it checks your highest melee skill first to give you right type of weapon
it doesn't take into consideration promotions as it was for an rpg server, didn't have em
you can edit that bit yourself ;)

Lua:
function onUse(player, item, fromPosition, target, toPosition, isHotkey)

local primarySkillList = {
    ["SKILL_SWORD"] = player:getSkillLevel(SKILL_SWORD),
    ["SKILL_AXE"] = player:getSkillLevel(SKILL_AXE),
    ["SKILL_CLUB"] = player:getSkillLevel(SKILL_CLUB)}

-- Get Knight primary weapon type

    local max_val, skillname = -math.huge
    for k, v in pairs(primarySkillList) do
        if v > max_val then
        max_val, skillname = v, k
        end
    end

local primarySkill = skillname
local vocation = player:getVocation():getId()
local reward = 2160

-- Calculate reward based of Vocation and primary weapon type if Knight.

    if vocation == 1 then
        reward = 8867
    elseif vocation == 2 then
        reward = 8891
    elseif vocation == 3 then
        if primarySkill == "SKILL_SWORD" then
            reward = 2438
        elseif primarySkill == "SKILL_AXE" then
            reward = 3962
        elseif primarySkill == "SKILL_CLUB" then
            reward = 7437
        end
    else
        reward = 23531 -- rookstayers or vocs you have not entered correctly here get a heat core bro
    end
 

local itemType = ItemType(reward)
local itemWeight = itemType:getWeight()
local playerCap = player:getFreeCapacity()

    if player:getStorageValue(reward) == -1 then
        if playerCap >= itemWeight then
            player:sendTextMessage(MESSAGE_INFO_DESCR, 'You have found a ' .. itemType:getName() .. '.')
            player:addItem(reward, 1)
            player:setStorageValue(reward, 1)
        else
            player:sendTextMessage(MESSAGE_INFO_DESCR, 'You have found a ' .. itemType:getName() .. ' weighing ' ..(itemWeight / 100).. ' oz. It\'s too heavy.')
        end
    else
        player:sendTextMessage(MESSAGE_INFO_DESCR, "It is empty.")
    end
    return true
end
 
Last edited:
I think something wrong here

Lua:
if vocation == 1 then
        reward = 8867
    elseif vocation == 2 then
        reward = 8891
    elseif vocation == 3 then
        if primarySkill == "SKILL_SWORD" then
            reward = 2438
        elseif primarySkill == "SKILL_AXE" then
            reward = 3962
        elseif primarySkill == "SKILL_CLUB" then
            reward = 7437
        end
    else
        reward = 23531 -- rookstayers or vocs you have not entered correctly here get a heat core bro
    end
 
Back
Top