• 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 Loot message script with a separate error for cap or container space [OTHire 0.0.2 Tibia 7.72]

Xapafe

Member
Joined
Jul 22, 2013
Messages
83
Reaction score
6
I have been using the basic built in system, but I decided to go the real tibia route and make it to where you can't loot a quest container unless you have the proper cap and inventory space to do so.

I'm not extremely familiar with scripting but I have done quite a bit of scripting by piecing together various scripts plus some of my own (Almost all quests finished for tibia 7.72 :D ). Anyways, I have been using my functions.lua as a major reference when creating my own scripts, and so I was easily able to adapt one for checking player cap, and then displaying an error message just like old tibia.

Code:
-- Script by Nottinghster
function onUse(cid, item, fromPosition, itemEx, toPosition)

if item.uid == 10007 then
  queststatus = getPlayerStorageValue(cid,10007)
 
  if queststatus == -1 and getPlayerFreeCap(cid) > getItemWeightById(2170, 1) then
   doPlayerSendTextMessage(cid,22,"You have found a silver amulet.")
   doPlayerAddItem(cid, 2170, 1)
   setPlayerStorageValue(cid,10007,1)
  
  elseif queststatus == -1 and getPlayerFreeCap(cid) > getItemWeightById(2170, 1) then
  doPlayerSendTextMessage(cid,22,"You do not have enough space.")
  
  elseif queststatus == -1 and getPlayerFreeCap(cid) < getItemWeightById(2170, 1) then
  doPlayerSendTextMessage(cid,22,"You have found a silver amulet weighing " .. getItemWeightById(2170, 1) .. " oz. It is too heavy.")
 
  
  elseif queststatus == 1 then
   doPlayerSendTextMessage(cid,22,"The chest is empty.")
  
  
end
end
return true
end

The section that says "you do not have enough space" will be where this code will go.

Everything else works fine for me, do you guys have any places I should start? I've been searching the forums and most solutions aren't really geared towards me and they all contain a lot of variable declarations that I would need help with.

I'm not exactly asking for a complete solution (though I won't deny one either!) but I would love if you guys could help me find a place to start. I was kind of hoping there was an easy path to these, because I don't want to do anything crazy with the script. I thought I could use getcontainercap or something, I dunno.

Thanks for reading!

(Also if my code is garbage, let me know, it is mostly from Nottinghster though I believe.)
 
I hope to add some declarations to allow me to universalize this script, but for now I'm going to leave my basic ones intact. lol
 
Code:
  elseif queststatus == -1 and getPlayerFreeCap(cid) > getItemWeightById(2170, 1) then
  doPlayerSendTextMessage(cid,22,"You do not have enough space.")

  elseif queststatus == -1 and getPlayerFreeCap(cid) < getItemWeightById(2170, 1) then

Shouldn't it be like:
Code:
  elseif queststatus == -1 and getPlayerFreeCap(cid) < getItemWeightById(2170, 1) then
  doPlayerSendTextMessage(cid,22,"You do not have enough space.")

  elseif queststatus == -1 and getPlayerFreeCap(cid) >= getItemWeightById(2170, 1) then


if free cap of player is less than weight of item, not enough cap
elseif cap of player equal or greater than weight of item, enough cap.
 
I do like the addition of an >= . Thanks, I totally overlooked that.

Code:
function onUse(cid, item, fromPosition, itemEx, toPosition)

if item.uid == 10007 then
  queststatus = getPlayerStorageValue(cid,10007)
 
  if queststatus == -1 and getPlayerFreeCap(cid) >= getItemWeightById(2170, 1) then
   doPlayerSendTextMessage(cid,22,"You have found a silver amulet.")
   doPlayerAddItem(cid, 2170, 1)
   setPlayerStorageValue(cid,10007,1)
  
  elseif queststatus == -1 and getPlayerFreeCap(cid) > getItemWeightById(2170, 1) then
  doPlayerSendTextMessage(cid,22,"You do not have enough space.")
  
  elseif queststatus == -1 and getPlayerFreeCap(cid) < getItemWeightById(2170, 1) then
  doPlayerSendTextMessage(cid,22,"You have found a reward weighing " .. getItemWeightById(2170, 1) .. " oz. It is too heavy.")
 
  
  elseif queststatus == 1 then
   doPlayerSendTextMessage(cid,22,"The chest is empty.")
  
  
end
end
return true
end


Code:
  if queststatus == -1 and getPlayerFreeCap(cid) >= getItemWeightById(2170, 1) then
   doPlayerSendTextMessage(cid,22,"You have found a silver amulet.")
   doPlayerAddItem(cid, 2170, 1)
   setPlayerStorageValue(cid,10007,1)


I feel like this is okay now for sure. If you haven't finished the quest before and have greater than or equal cap of the quest item then it will give you the item.

I will put this last though, so it will check for the others first, or I could add another and argument for the inventory cap too, I dunno.


Code:
elseif queststatus == -1 and getPlayerFreeCap(cid) > getItemWeightById(2170, 1) then
  doPlayerSendTextMessage(cid,22,"You do not have enough space.")

Here is the incomplete argument, the one I want to have check the inventory space. I would also like it to check the corresponding slot, hands, and arrow slot before bag if possible. Just like the looting system does.

Code:
elseif queststatus == -1 and getPlayerFreeCap(cid) < getItemWeightById(2170, 1) then
  doPlayerSendTextMessage(cid,22,"You have found a reward weighing " .. getItemWeightById(2170, 1) .. " oz. It is too heavy.")

And I feel like this is okay too, because it works as intended.

BTW, thanks for you help!!
 
I do like the addition of an >= . Thanks, I totally overlooked that.

Code:
function onUse(cid, item, fromPosition, itemEx, toPosition)

if item.uid == 10007 then
  queststatus = getPlayerStorageValue(cid,10007)

  if queststatus == -1 and getPlayerFreeCap(cid) >= getItemWeightById(2170, 1) then
   doPlayerSendTextMessage(cid,22,"You have found a silver amulet.")
   doPlayerAddItem(cid, 2170, 1)
   setPlayerStorageValue(cid,10007,1)
 
  elseif queststatus == -1 and getPlayerFreeCap(cid) > getItemWeightById(2170, 1) then
  doPlayerSendTextMessage(cid,22,"You do not have enough space.")
 
  elseif queststatus == -1 and getPlayerFreeCap(cid) < getItemWeightById(2170, 1) then
  doPlayerSendTextMessage(cid,22,"You have found a reward weighing " .. getItemWeightById(2170, 1) .. " oz. It is too heavy.")

 
  elseif queststatus == 1 then
   doPlayerSendTextMessage(cid,22,"The chest is empty.")
 
 
end
end
return true
end


Code:
  if queststatus == -1 and getPlayerFreeCap(cid) >= getItemWeightById(2170, 1) then
   doPlayerSendTextMessage(cid,22,"You have found a silver amulet.")
   doPlayerAddItem(cid, 2170, 1)
   setPlayerStorageValue(cid,10007,1)


I feel like this is okay now for sure. If you haven't finished the quest before and have greater than or equal cap of the quest item then it will give you the item.

I will put this last though, so it will check for the others first, or I could add another and argument for the inventory cap too, I dunno.


Code:
elseif queststatus == -1 and getPlayerFreeCap(cid) > getItemWeightById(2170, 1) then
  doPlayerSendTextMessage(cid,22,"You do not have enough space.")

Here is the incomplete argument, the one I want to have check the inventory space. I would also like it to check the corresponding slot, hands, and arrow slot before bag if possible. Just like the looting system does.

Code:
elseif queststatus == -1 and getPlayerFreeCap(cid) < getItemWeightById(2170, 1) then
  doPlayerSendTextMessage(cid,22,"You have found a reward weighing " .. getItemWeightById(2170, 1) .. " oz. It is too heavy.")

And I feel like this is okay too, because it works as intended.

BTW, thanks for you help!!
For all that you should just use doPlayerAddItemEx with canDropOnMap set to false, it will return the right returnvalue and you just have to send the message to the player.
 
I didn't realize there was a canDropOnMap argument!

So do I just add it in the line like

Code:
elseif queststatus == -1 and getPlayerFreeCap(cid) < getItemWeightById(2170, 1) then
doPlayerAddItem(cid, canDropOnMap == false, 2170, 1)

or something? xD
 
Code:
function onUse(cid, item, fromPosition, itemEx, toPosition)
    if item.uid == 10007 then
        queststatus = getPlayerStorageValue(cid,10007)
        if queststatus == -1 then
            local item = doCreateItemEx(2170, 1)
            if item then
                local ret = doPlayerAddItemEx(cid, item, false)
                if ret == RETURNVALUE_NOERROR then
                    setPlayerStorageValue(cid,10007,1)
                    doPlayerSendTextMessage(cid,22,"You have found a silver amulet.")
                else
                    doPlayerSendDefaultCancel(cid, ret)
                end
            end
        else
            doPlayerSendTextMessage(cid,22,"The chest is empty.")
        end
    end
    return true
end
 
Oh you are awesome.

Okay, one more question them, since this script is super simple.. is there a way to make it display the separate messages just like in rl tibia 7.6. "This item weighs so and so oz, it is too heavy" and "you do not have enough space".

At least, I'm pretty sure 7.6/7.72 tibia said those things..
 
Oh you are awesome.

Okay, one more question them, since this script is super simple.. is there a way to make it display the separate messages just like in rl tibia 7.6. "This item weighs so and so oz, it is too heavy" and "you do not have enough space".

At least, I'm pretty sure 7.6/7.72 tibia said those things..
Code:
function onUse(cid, item, fromPosition, itemEx, toPosition)
    if item.uid == 10007 then
        queststatus = getPlayerStorageValue(cid,10007)
        if queststatus == -1 then
            local item = doCreateItemEx(2170, 1)
            if item then
                local ret = doPlayerAddItemEx(cid, item, false)
                if ret == RETURNVALUE_NOERROR then
                    setPlayerStorageValue(cid,10007,1)
                    doPlayerSendTextMessage(cid,22,"You have found a silver amulet.")
                elseif ret == RETURNVALUE_NOTENOUGHCAPACITY then
                    doPlayerSendTextMessage(cid,22,"You have found a reward weighing " .. getItemWeight(item) / 100 .. " oz. It is too heavy.")
                elseif ret == RETURNVALUE_NOTENOUGHROOM or ret == RETURNVALUE_CONTAINERNOTENOUGHROOM then
                    doPlayerSendTextMessage(cid,22,"You do not have enough space.")
                else
                    doPlayerSendDefaultCancel(cid, ret)
                end
            end
        else
            doPlayerSendTextMessage(cid,22,"The chest is empty.")
        end
    end
    return true
end
 
Just tried it. It works perfectly. You have single handedly fixed my entire quest system at its core. I'm going to add your name to all my scripts just in case I plan to release my files on day.

Thanks you so much, wow.

Can I ask what ret does exactly? I'm guessing its short for return.
 
Just tried it. It works perfectly. You have single handedly fixed my entire quest system at its core. I'm going to add your name to all my scripts just in case I plan to release my files on day.

Thanks you so much, wow.

Can I ask what ret does exactly? I'm guessing its short for return.
https://github.com/TwistedScorpio/OTHire/blob/master/data/global.lua#L329-L396

doPlayerAddItemEx return one of those, if the item was added with no problems, the function result will be RETURNVALUE_NOERROR, if its not added it will return one of those, depending on what happened that made the function not work.
 
how would this script look like with 2 or more different items inside a bag?, and also can it calculate the weight of that bag? , i know that you can do something like container = doPlayerAddItem(cid, id_bag, 1), doAddContainerItem(container, id_weapon, 1)
 
how would this script look like with 2 or more different items inside a bag?, and also can it calculate the weight of that bag? , i know that you can do something like container = doPlayerAddItem(cid, id_bag, 1), doAddContainerItem(container, id_weapon, 1)
You can create a item that is a container with the same function (doCreateItemEx) and then add items to this virtual item(container) using doAddContainerItem and then try to add to the player, from there it's the same thing.
 
Oh wow this is also something I didn't think about..

I have changed this code around a bit to make it more universal, if you guys wanna give me your input that'd be great. I'd hope to make it fully universal and be able to do containers of items too just like Emky asked.

Code:
-- Code structured by MatheusMkalo
function onUse(cid, item, fromPosition, itemEx, toPosition)

local reward = 2170 --Item ID (single item for now..)
local unique = 10007 --Unique ID
local quest = 10007 --Usually same as unique or action.. but I added space for univerial creation
local action = 0 --Action ID


    if item.uid == (unique) then
        queststatus = getPlayerStorageValue(cid,quest)
        if queststatus == -1 then
            local item = doCreateItemEx(reward, 1)
            if item then
                local ret = doPlayerAddItemEx(cid, item, false)
                if ret == RETURNVALUE_NOERROR then
                    setPlayerStorageValue(cid,quest, 1)
                    doPlayerSendTextMessage(cid,22,"You have found a "  .. getItemNameById(reward, 1) .. ".")
                elseif ret == RETURNVALUE_NOTENOUGHCAPACITY then
                    doPlayerSendTextMessage(cid, MESSAGE_EVENT_ADVANCE, "You have found a reward weighing " .. getItemWeightById(reward) / 100 .. " oz. It is too heavy.")
                elseif ret == RETURNVALUE_NOTENOUGHROOM or ret == RETURNVALUE_CONTAINERNOTENOUGHROOM then
                    doPlayerSendTextMessage(cid, MESSAGE_EVENT_ADVANCE, 'You do not have enough space.')
                else
                    doPlayerSendDefaultCancel(cid, ret)
                end
            end
        else
            doPlayerSendTextMessage(cid,22,"The chest is empty.")
        end
    end
    return true
end

To me, the main hurdles would be allowing to correctly calculate weight for the cap query but also show the correct reward name. Right now I have it set to show the name of the reward by ID.
 
We could add a kind of... array to the reward variable I suppose. Then add a function on the doPlayerAddItem to add the items within the array, but would it cause issues trying to add items that aren't there?
 
just a concept, could need adjustments and improvements since this wont work i think, my lua is terrible i know
Code:
-- id and count, probably not written like this
local itemRewardArray = {
    id_sword, 1,
    id_emerald, 16,
    id_goldcoin, 100
}

function addReward(useContainer, bagtype)
    if useContainer == true then
        item = doCreateItemEx(bagtype, 1)
        for i, v in pairs(itemRewardArray) do
            doAddContainerItem(item, v, v[1]) -- id and count
        end
    else
        for i, v in pairs(itemRewardArray) do
            doPlayerAdditem(v, v[1]) -- id and count
        end
    end
    return true
end

for use later: addReward(true/false, id_backpack)
 
Last edited by a moderator:
Ahh okay I like your array idea. But I'm not sure what's going on here logically.

Okay, here is my new little template and you guys can look at it again.

Code:
-- Code structured by MatheusMkalo
function onUse(cid, item, fromPosition, itemEx, toPosition)

local itemRewardArray = {
    2170, 1,  
    2148, 100
}

local bps = {1988, 1998, 1999, 2000, 2001, 2002, 2003, 2004}
local bags = {1987, 1991, 1992, 1993, 1994, 1995, 1996, 1997}

local reward = 2170   --Item ID (single item for now..)
local unique = 10007  --Unique ID
local quest = 10007   --Usually same as unique but I added space for univerial creation
local addContainer = 0   --  bags -- 1987(brown), 1991(green), 1992(yellow), 1993(red), 1994(purple), 1995(blue), 1996(grey), 1997(gold)
                      --  backpacks -- 1988(brown), 1998(green), 1999(yellow), 2000(red), 2001(purple), 2002(blue), 2003(grey), 2004(gold)
local specialloot = 0 -- Ignore this for now


    if item.uid == (unique) then  
        queststatus = getPlayerStorageValue(cid,quest)
        if queststatus == -1 and addContainer == 0 then
            local item = doCreateItemEx(reward, 1)
            if item then
                local ret = doPlayerAddItemEx(cid, item, false)
                if ret == RETURNVALUE_NOERROR then
                    setPlayerStorageValue(cid,quest, 1)
                    doPlayerSendTextMessage(cid,22,"You have found a "  .. getItemNameById(reward, 1) .. ".")
                elseif ret == RETURNVALUE_NOTENOUGHCAPACITY then
                    doPlayerSendTextMessage(cid, MESSAGE_EVENT_ADVANCE, "You have found a reward weighing " .. getItemWeightById(reward) / 100 .. " oz. It is too heavy.")
                elseif ret == RETURNVALUE_NOTENOUGHROOM or ret == RETURNVALUE_CONTAINERNOTENOUGHROOM then
                    doPlayerSendTextMessage(cid, MESSAGE_EVENT_ADVANCE, 'You do not have enough space in your inventory.')
                else
                    doPlayerSendDefaultCancel(cid, ret)
                end
            end
        else
            doPlayerSendTextMessage(cid,22,"The chest is empty.")
        end
    end
    return true
end

This is NOT a finished code. It's just the first outcome, which is there is no bag only the reward.

I went ahead and put in the array idea just for brain storming.

Now, how do I reference that table with isInArray? and if the addContainer is > 0 how do I take the array and then ADD it into a container? I have some of my old code for the dead mino quest we might can reference. It's simple.

Code:
function onUse(cid, item, frompos, item2, topos)
if item.uid == 4019 then
  queststatus = getPlayerStorageValue(cid,4019)
  if queststatus == -1 then
   doPlayerSendTextMessage(cid, 22, "You have found a bag.")
      bag = doPlayerAddItem(cid, 1987, 1)
      item_uid = doAddContainerItem(bag, 2456, 1)
      item_uid = doAddContainerItem(bag, 2545, 5)
      item_uid = doAddContainerItem(bag, 2006, 7)
      item_uid = doAddContainerItem(bag, 2006, 10)
      setPlayerStorageValue(cid,4019,1)
  else
   doPlayerSendTextMessage(cid,22,"The dead minotaur is empty.")
  end
else
  return 0
end
return 1
end

Maybe if the addContainer is > 0 (or even make a separate array for this too so it won't be able to execute all kinds of weird shit like me accidentally putting an un-moveable object in their inventory) we could add in the items this way within the script? It seems a bit dirty but I don't care so long as it works!

So my main question is how do I reference the array.. as in, how can tell it to keep adding in the array items until it is finished? be in 1 or 100?

Thanks you guys, so much for you help. This is really helping to polish my server!!
 
Code:
local errors = {
[RETURNVALUE_NOERROR] = {text = "You have found a |ITEM|."},
[RETURNVALUE_NOTENOUGHCAPACITY] = {text = "You have found a reward weighing |WEIGHT| oz. It is too heavy."},
[RETURNVALUE_NOTENOUGHROOM] = {text = "You do not have enough space in your inventory."},
[RETURNVALUE_CONTAINERNOTENOUGHROOM] = {text = "You do not have enough space in your inventory."}
}

-- Code structured by MatheusMkalo
function onUse(cid, item, fromPosition, itemEx, toPosition)

local itemRewardArray = {
    2170, 1,
    2148, 100
}

local bps = {1988, 1998, 1999, 2000, 2001, 2002, 2003, 2004}
local bags = {1987, 1991, 1992, 1993, 1994, 1995, 1996, 1997}

local reward = 2170   --Item ID (single item for now..)
local unique = 10007  --Unique ID
local quest = 10007   --Usually same as unique but I added space for univerial creation
local addContainer = 0   --  bags -- 1987(brown), 1991(green), 1992(yellow), 1993(red), 1994(purple), 1995(blue), 1996(grey), 1997(gold)
                      --  backpacks -- 1988(brown), 1998(green), 1999(yellow), 2000(red), 2001(purple), 2002(blue), 2003(grey), 2004(gold)
local specialloot = 0 -- Ignore this for now


    if item.uid == (unique) then
        queststatus = getPlayerStorageValue(cid,quest)
        if queststatus == -1 and addContainer == 0 then
            local item = doCreateItemEx(reward, 1)
            if item then
                local ret = doPlayerAddItemEx(cid, item, false)
             
                ERROR = errors[ret]
             
                if not ERROR then return doPlayerSendDefaultCancel(cid, ret) end
             
                text = ERROR.text
             
                local weight = getItemWeightById(reward) / 100
                local itemName = getItemNameById(reward, 1)
             
                text:gsub("|WEIGHT|", ""..weight.."")
                text:gsub("|ITEM|", ""..itemName.."")
             
                doPlayerSendTextMessage(cid, MESSAGE_EVENT_ADVANCE, text)
             
                if ret == RETURNVALUE_NOERROR
                setPlayerStorageValue(cid,quest, 1)
                end
            end
        else
            doPlayerSendTextMessage(cid,22,"The chest is empty.")
        end
    end
    return true
end
 
Back
Top