• 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!

[SOLVED] Random loot in crates/boxes

Andréew

Humble mapper.
Joined
Apr 14, 2015
Messages
833
Solutions
2
Reaction score
1,929
Location
Sweden
Hi guys!
The basic idea is that when you open a box or crate ( Id's : 1738,1739,1741 ) there might or might not be an item or several items.

I was thinking that maybe it can be done with a action script, onUse.
with a 30% chance that you get nothing at all, and like 20% that you get 5-50 gold and so on other items,
it must also be a timer so that you just cant loot it over and over and over again, lets say 2 hours.

would be nice if the script was easy to change loot items and chance of getting it and so on, tables or what its called :p
 
already exist something like this.
Code:
function onUse(player, item, fromPosition, target, toPosition, isHotkey)
    if player:getStorageValue(Storage.Timer) >= os.time() then
        return player:sendTextMessage(MESSAGE_EVENT_ADVANCE, 'You are exhausted.')
    end
    player:setStorageValue(Storage.Timer, os.time() + 2 * 3600)
    local chance = math.random(100)
    if chance <= 30 then
        player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "You get nothing.")
        return true
    else
        player:addItem(2148, math.random(50)) -- exemple
        player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "msg......")
    end
    return true
end
also you need create a table with the values or table of items...
 
Yes! this is what i was looking for! i used search but diden't find it!
will try it out right away! :)

Edit:
Uhm, does not work. it does nothing..
no error on start up and no error onUse either :/

I use TFS 1.1
and i added the script in a LUA in actions/scripts also added all box id's to the script inside actions.xml
 
Last edited:
you can edit this script to your liking and add chances
Code:
local t = {
    ['Loot Chest [Tier 1]'] = {
    effect = CONST_ME_FIREAREA,
    items  = {
            {id = 2146, minCount = 1, maxCount = 30},
            {id = 2147, minCount = 5, maxCount = 45},
            {id = 2149, minCount = 1, maxCount = 50},
            {id = 2150, minCount = 10, maxCount = 30}
        }
    },
    ['Loot Chest [Tier 2]'] = {
    effect = CONST_ME_HOLYAREA,
    items  = {
            {id = 7759, minCount = 1, maxCount = 30},
            {id = 7760, minCount = 5, maxCount = 45},
            {id = 7761, minCount = 1, maxCount = 50},
            {id = 7762, minCount = 10, maxCount = 30}
        }
    }
}

function onUse(player, item, fromPosition, target, toPosition, isHotkey)
    local boxName = item:getName()
    local tmp     = t[boxName]
    if not tmp then
        return false
    end
    local container = item -- easier to understand
    local tab = tmp.items
    while container:getSize() < (tmp.num or container:getCapacity()) do
        local rItem    = tab[math.random(#tab)]
        local min, max = rItem.minCount, rItem.maxCount
        container:addItem(1685):transform(rItem.id, (min and max) and math.random(min, max) or -1)
    end
    player:say('Opened:\n'.. boxName, TALKTYPE_MONSTER_SAY)
    item:setAttribute('name', 'Opened Loot Chest')
    player:getPosition():sendMagicEffect(tmp.effect)
    return true
end
 
Well, yeah thanks @Xeraphus, the bad news is that i dont really understand how to edit this.. :/

Isn't it possible to make the script look like

Code:
local rewarditems = {
[25] = {
tilllevel = 50,
{id = 3982, chance = 5, count = 1}, -- start with the lowest chances
{id = 2476, chance = 10, count = 1},
{id = 2479, chance = 15, count = 1},
{id = 2148, chance = 70, count = math.random(10, 50)}
},
[50] = {
tilllevel = 100,
{id = 7730, chance = 5, count = 1},
{id = 2466, chance = 10, count = 1},
{id = 2497, chance = 15, count = 1},
{id = 2152, chance = 70, count = math.random(1, 20)}
},
[100] = {
tilllevel = 200,
{id = 2472, chance = 5, count = 1},
{id = 2496, chance = 10, count = 1},
{id = 2520, chance = 15, count = 1},
{id = 2160, chance = 70, count = math.random(20, 50)}
}
( This code have nothing to do with this what so ever just wanted to use it to explain the structure of the code)
 
Code:
local rewards = {
    [{25, 50}] = {
        {id = 3982, chance = 5, count = 1}, -- start with the lowest chances
        {id = 2476, chance = 10, count = 1},
        {id = 2479, chance = 15, count = 1},
        {id = 2148, chance = 70, count = {10, 50}}
    },
    [{50, 100}] = {
        {id = 7730, chance = 5, count = 1},
        {id = 2466, chance = 10, count = 1},
        {id = 2497, chance = 15, count = 1},
        {id = 2152, chance = 70, count = {1, 20}}
    },
    [{100, 200}] = {
        {id = 2472, chance = 5, count = 1},
        {id = 2496, chance = 10, count = 1},
        {id = 2520, chance = 15, count = 1},
        {id = 2160, chance = 70, count = {20, 50}}
    }
}

local function getRewardsByLevel(lv)
    for k, v in pairs(rewards) do
        if (lv >= k[1] and lv <= k[2]) then
            return v
        end
    end
    return false
end

function onUse(player, item, fromPosition, target, toPosition, isHotkey)
    local tmp = getRewardsByLevel(player:getLevel())

    if item:getName() == 'Opened Loot Chest' then
        return true
    end

    if not tmp then
        player:sendTextMessage(MESSAGE_STATUS_SMALL, 'You are not high enough level.')
        return false
    end

    for k, v in ipairs(tmp) do
        if math.random(100) <= v.chance then
            item:addItem(v.id, v.count == 'number' and v.count or math.random(v.count[1], v.count[2]))
        end
    end

    player:say('Opened:\n'.. boxName, TALKTYPE_MONSTER_SAY)
    item:setAttribute('name', 'Opened Loot Chest')
    player:getPosition():sendMagicEffect(CONST_ME_MORTAREA)
    return true
end
try this
 
This script looked a lot better and easier for me to work with, but it still dont work :(
can you please explain to me where do i assign this 1738,1739,1741 boxes gets assigned in the script?
is it in actions.xml or in table?

25, 50? 50,100? 100, 200? in the table what does that mean? or is it the reward you get between those lvls?
 
This script looked a lot better and easier for me to work with, but it still dont work :(
can you please explain to me where do i assign this 1738,1739,1741 boxes gets assigned in the script?
is it in actions.xml or in table?

25, 50? 50,100? 100, 200? in the table what does that mean? or is it the reward you get between those lvls?
the {25, 50} {50, 100} is {minlevel, maxlevel}
you assign the itemids in the xml to the same script
if you want different ids use this
Code:
local rewards = {
    [1738] = {
        [{25, 50}] = {
            {id = 3982, chance = 5, count = 1}, -- start with the lowest chances
            {id = 2476, chance = 10, count = 1},
            {id = 2479, chance = 15, count = 1},
            {id = 2148, chance = 70, count = {10, 50}}
        },
        [{50, 100}] = {
            {id = 7730, chance = 5, count = 1},
            {id = 2466, chance = 10, count = 1},
            {id = 2497, chance = 15, count = 1},
            {id = 2152, chance = 70, count = {1, 20}}
        },
        [{100, 200}] = {
            {id = 2472, chance = 5, count = 1},
            {id = 2496, chance = 10, count = 1},
            {id = 2520, chance = 15, count = 1},
            {id = 2160, chance = 70, count = {20, 50}}
        }
    },
    [id2] = {}
}

local function getRewardsByLevel(tmp, lv)
    for k, v in pairs(tmp) do
        if (lv >= k[1] and lv <= k[2]) then
            return v
        end
    end
    return false
end

function onUse(player, item, fromPosition, target, toPosition, isHotkey)
    local tmp = rewards[item:getId()]

    if item:getName() == 'Opened Loot Chest' then
        return true
    end

    if not tmp then
        return false
    end

    local rew = getRewardsByLevel(tmp, player:getLevel())

    if not rew then
        player:sendTextMessage(MESSAGE_STATUS_SMALL, 'You are not high enough level.')
        return false
    end

    for k, v in ipairs(tmp) do
        if math.random(100) <= v.chance then
            item:addItem(v.id, v.count == 'number' and v.count or math.random(v.count[1], v.count[2]))
        end
    end

    player:say('Opened:\n'.. boxName, TALKTYPE_MONSTER_SAY)
    item:setAttribute('name', 'Opened Loot Chest')
    player:getPosition():sendMagicEffect(CONST_ME_MORTAREA)
    return true
end
 
Thank you for explaining! now i will be able to change loot as i want and stuff thank you, get this error however :(

Code:
Lua Script Error: [Action Interface]
data/actions/scripts/randomitem.lua:onUse
data/actions/scripts/randomitem.lua:77: attempt to concatenate global 'boxName' (a nil value)
stack traceback:
        [C]: in function '__concat'
        data/actions/scripts/randomitem.lua:77: in function <data/actions/scripts/randomitem.lua:53>
 
Thank you for explaining! now i will be able to change loot as i want and stuff thank you, get this error however :(

Code:
Lua Script Error: [Action Interface]
data/actions/scripts/randomitem.lua:onUse
data/actions/scripts/randomitem.lua:77: attempt to concatenate global 'boxName' (a nil value)
stack traceback:
        [C]: in function '__concat'
        data/actions/scripts/randomitem.lua:77: in function <data/actions/scripts/randomitem.lua:53>
just replace the concatenation with opened loot box
 
When im not high enough lvl i get no error at all, just opens up and no items, but when i am high enough lvl i get this error,

Code:
Lua Script Error: [Action Interface]
data/actions/scripts/randomitem.lua:onUse
data/actions/scripts/randomitem.lua:77: attempt to concatenate global 'boxName' (a nil value)
stack traceback:
        [C]: in function '__concat'
        data/actions/scripts/randomitem.lua:77: in function <data/actions/scripts/randomitem.lua:53>

here is the code
Code:
local rewards = {
    [1738] = {
        [{8, 50}] = {
            {id = 3982, chance = 5, count = 1}, -- start with the lowest chances
            {id = 2476, chance = 10, count = 1},
            {id = 2479, chance = 15, count = 1},
            {id = 2148, chance = 70, count = {10, 50}}
        },
        [{50, 100}] = {
            {id = 7730, chance = 5, count = 1},
            {id = 2466, chance = 10, count = 1},
            {id = 2497, chance = 15, count = 1},
            {id = 2152, chance = 70, count = {1, 20}}
        },
        [{100, 200}] = {
            {id = 2472, chance = 5, count = 1},
            {id = 2496, chance = 10, count = 1},
            {id = 2520, chance = 15, count = 1},
            {id = 2160, chance = 70, count = {20, 50}}
        }
    },
    [1739] = {
    [{25, 50}] = {
            {id = 3982, chance = 5, count = 1}, -- start with the lowest chances
            {id = 2476, chance = 10, count = 1},
            {id = 2479, chance = 15, count = 1},
            {id = 2148, chance = 70, count = {10, 50}}
        },
        [{50, 100}] = {
            {id = 7730, chance = 5, count = 1},
            {id = 2466, chance = 10, count = 1},
            {id = 2497, chance = 15, count = 1},
            {id = 2152, chance = 70, count = {1, 20}}
        },
        [{100, 200}] = {
            {id = 2472, chance = 5, count = 1},
            {id = 2496, chance = 10, count = 1},
            {id = 2520, chance = 15, count = 1},
            {id = 2160, chance = 70, count = {20, 50}}
        }
}
}

local function getRewardsByLevel(tmp, lv)
    for k, v in pairs(tmp) do
        if (lv >= k[1] and lv <= k[2]) then
            return v
        end
    end
    return false
end

function onUse(player, item, fromPosition, target, toPosition, isHotkey)
    local tmp = rewards[item:getId()]

    if item:getName() == 'Opened Loot Box' then
        return true
    end

    if not tmp then
        return false
    end

    local rew = getRewardsByLevel(tmp, player:getLevel())

    if not rew then
        player:sendTextMessage(MESSAGE_STATUS_SMALL, 'You are not high enough level.')
        return false
    end

    for k, v in ipairs(tmp) do
        if math.random(100) <= v.chance then
            item:addItem(v.id, v.count == 'number' and v.count or math.random(v.count[1], v.count[2]))
        end
    end

    player:say('Opened:\n'.. boxName, TALKTYPE_MONSTER_SAY)
    item:setAttribute('name', 'Opened Loot Box')
    player:getPosition():sendMagicEffect(CONST_ME_MORTAREA)
    return true
end

also @Xeraphus i wanna thank you for your help and time, send me your paypal email in PM and i will send a small donation. ( cant send a PM to you )
 
below:
Code:
local rew = getRewardsByLevel(tmp, player:getLevel())
paste
Code:
local boxName = item:getName():lower()
 
you can edit this script to your liking and add chances
Code:
local t = {
    ['Loot Chest [Tier 1]'] = {
    effect = CONST_ME_FIREAREA,
    items  = {
            {id = 2146, minCount = 1, maxCount = 30},
            {id = 2147, minCount = 5, maxCount = 45},
            {id = 2149, minCount = 1, maxCount = 50},
            {id = 2150, minCount = 10, maxCount = 30}
        }
    },
    ['Loot Chest [Tier 2]'] = {
    effect = CONST_ME_HOLYAREA,
    items  = {
            {id = 7759, minCount = 1, maxCount = 30},
            {id = 7760, minCount = 5, maxCount = 45},
            {id = 7761, minCount = 1, maxCount = 50},
            {id = 7762, minCount = 10, maxCount = 30}
        }
    }
}

function onUse(player, item, fromPosition, target, toPosition, isHotkey)
    local boxName = item:getName()
    local tmp     = t[boxName]
    if not tmp then
        return false
    end
    local container = item -- easier to understand
    local tab = tmp.items
    while container:getSize() < (tmp.num or container:getCapacity()) do
        local rItem    = tab[math.random(#tab)]
        local min, max = rItem.minCount, rItem.maxCount
        container:addItem(1685):transform(rItem.id, (min and max) and math.random(min, max) or -1)
    end
    player:say('Opened:\n'.. boxName, TALKTYPE_MONSTER_SAY)
    item:setAttribute('name', 'Opened Loot Chest')
    player:getPosition():sendMagicEffect(tmp.effect)
    return true
end
This works on 1.3? Help please!
 
working code is here:
Lua:
local rewards = {
    [1738] = {
        [{8, 50}] = {
            {id = 3982, chance = 5, count = 1}, -- start with the lowest chances
            {id = 2476, chance = 10, count = 1},
            {id = 2479, chance = 15, count = 1},
            {id = 2148, chance = 70, count = {10, 50}}
        },
        [{50, 100}] = {
            {id = 7730, chance = 5, count = 1},
            {id = 2466, chance = 10, count = 1},
            {id = 2497, chance = 15, count = 1},
            {id = 2152, chance = 70, count = {1, 20}}
        },
        [{100, 200}] = {
            {id = 2472, chance = 5, count = 1},
            {id = 2496, chance = 10, count = 1},
            {id = 2520, chance = 15, count = 1},
            {id = 2160, chance = 70, count = {20, 50}}
        }
    },
    [1739] = {
        [{25, 50}] = {
            {id = 3982, chance = 5, count = 1}, -- start with the lowest chances
            {id = 2476, chance = 10, count = 1},
            {id = 2479, chance = 15, count = 1},
            {id = 2148, chance = 70, count = {10, 50}}
        },
        [{50, 100}] = {
            {id = 7730, chance = 5, count = 1},
            {id = 2466, chance = 10, count = 1},
            {id = 2497, chance = 15, count = 1},
            {id = 2152, chance = 70, count = {1, 20}}
        },
        [{100, 200}] = {
            {id = 2472, chance = 5, count = 1},
            {id = 2496, chance = 10, count = 1},
            {id = 2520, chance = 15, count = 1},
            {id = 2160, chance = 70, count = {20, 50}}
        }
    }
}

local function getRewardsByLevel(tmp, lv)
    for k, v in pairs(tmp) do
        if (lv >= k[1] and lv <= k[2]) then
            return v
        end
    end
    return false
end

function onUse(player, item, fromPosition, target, toPosition, isHotkey)
    local tmp = rewards[item:getId()]

    if item:getName() == 'Opened Loot Box' then
        return false
    end

    if not tmp then
        return true
    end

    local rew = getRewardsByLevel(tmp, player:getLevel())

    if not rew then
        return true
    end

    for k, v in ipairs(rew) do
        if math.random(100) <= v.chance then
            item:addItem(v.id, type(v.count) == 'number' and v.count or math.random(v.count[1], v.count[2]))
        end
    end

    player:say('Opened Loot Box', TALKTYPE_MONSTER_SAY)
    item:setAttribute('name', 'Opened Loot Box')
    player:getPosition():sendMagicEffect(CONST_ME_MORTAREA)
    return true
end
 
working code is here:
Lua:
local rewards = {
    [1738] = {
        [{8, 50}] = {
            {id = 3982, chance = 5, count = 1}, -- start with the lowest chances
            {id = 2476, chance = 10, count = 1},
            {id = 2479, chance = 15, count = 1},
            {id = 2148, chance = 70, count = {10, 50}}
        },
        [{50, 100}] = {
            {id = 7730, chance = 5, count = 1},
            {id = 2466, chance = 10, count = 1},
            {id = 2497, chance = 15, count = 1},
            {id = 2152, chance = 70, count = {1, 20}}
        },
        [{100, 200}] = {
            {id = 2472, chance = 5, count = 1},
            {id = 2496, chance = 10, count = 1},
            {id = 2520, chance = 15, count = 1},
            {id = 2160, chance = 70, count = {20, 50}}
        }
    },
    [1739] = {
        [{25, 50}] = {
            {id = 3982, chance = 5, count = 1}, -- start with the lowest chances
            {id = 2476, chance = 10, count = 1},
            {id = 2479, chance = 15, count = 1},
            {id = 2148, chance = 70, count = {10, 50}}
        },
        [{50, 100}] = {
            {id = 7730, chance = 5, count = 1},
            {id = 2466, chance = 10, count = 1},
            {id = 2497, chance = 15, count = 1},
            {id = 2152, chance = 70, count = {1, 20}}
        },
        [{100, 200}] = {
            {id = 2472, chance = 5, count = 1},
            {id = 2496, chance = 10, count = 1},
            {id = 2520, chance = 15, count = 1},
            {id = 2160, chance = 70, count = {20, 50}}
        }
    }
}

local function getRewardsByLevel(tmp, lv)
    for k, v in pairs(tmp) do
        if (lv >= k[1] and lv <= k[2]) then
            return v
        end
    end
    return false
end

function onUse(player, item, fromPosition, target, toPosition, isHotkey)
    local tmp = rewards[item:getId()]

    if item:getName() == 'Opened Loot Box' then
        return false
    end

    if not tmp then
        return true
    end

    local rew = getRewardsByLevel(tmp, player:getLevel())

    if not rew then
        return true
    end

    for k, v in ipairs(rew) do
        if math.random(100) <= v.chance then
            item:addItem(v.id, type(v.count) == 'number' and v.count or math.random(v.count[1], v.count[2]))
        end
    end

    player:say('Opened Loot Box', TALKTYPE_MONSTER_SAY)
    item:setAttribute('name', 'Opened Loot Box')
    player:getPosition():sendMagicEffect(CONST_ME_MORTAREA)
    return true
end

aa9ad1f51991f70f71487c41cef17188.png

Thanks a lot!
btw im getting this error and the box doesn't give me the items and is not dissapearing on use
sorry my bad english
 
aa9ad1f51991f70f71487c41cef17188.png

Thanks a lot!
btw im getting this error and the box doesn't give me the items and is not dissapearing on use
sorry my bad english
it's for a chest, you open it and it inserts items into the chest
are you needing a script that removes the item and gives you random items?
if so, create your own support thread because that's a different script unrelated to this thread
 
Back
Top