• 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.4.2] Boss Reward Chest System!!

Mateus Robeerto

Excellent OT User
Joined
Jun 5, 2016
Messages
1,341
Solutions
71
Reaction score
703
Location
ლ(ಠ益ಠლ)
This system is based on Reward Chests. Check out the Tibia Wiki to learn more about how it works. It's simple!

In regard to the reward, it will be dispatched to the designated depot. Simply locate the 'depotId' line and specify the number of the city you wish to send it to; this will ensure direct delivery to the depot. For instance, assigning the number 1 for the primary city and 2 for Thais, and so forth, facilitates this process.
This script is the first version..
boss.gif
This script is configured to activate a 5-minute timer upon expiration, automatically removing the Reward Chest Id=21584. Should you wish to extend the duration or adjust it based on Tibia Wiki guidelines, it offers versatility. This system is particularly suitable for boss rooms where defeating the boss results in the transformation of its corpse into the RewardChestId. Players interact with it, and after a designated period, the chest dissipates.


When you kill the boss, it dies and transforms into a Reward Chest with ID 21584.
Follow the step-by-step installation guide provided here.
  • register the event in given monster file
    XML:

    XML:
    <script>
    <event name="BossDeath"/>
    </script>
  • set boss corpse to 0, otherwise you will get additional loot message
    XML:
    XML:
    <look type="201" corpse="0" />


This is RevScripts. Place the script anywhere in the data/scripts folder, whether it's a subfolder or your preferred location.
Lua:
local bossesList = {
    { name = "Orshabaal", storage = 6655, expirationTime = 5 * 60, loot = { {item = 2160, count = 5, chance = 100000}, {item = 2494, count = 1, chance = 50000}, }, RewardChestId = 21584, depotID = 1 },
    { name = "Cave Rat", storage = 6656, expirationTime = 5 * 60, loot = { {item = 2160, count = 10, chance = 100000}, {item = 2498, count = 1, chance = 75000}, }, RewardChestId = 21584, depotID = 1 },
    -- Add more bosses as needed
}

local STORAGE_KEYS = {
    bossData = "boss_data",
}

local function createRewardChest(bossPosition, rewardChestId, expirationTime)
    local rewardItem = Game.createItem(rewardChestId, 1, bossPosition)
    if rewardItem then
        rewardItem:setAttribute(ITEM_ATTRIBUTE_ACTIONID, ACTION_ID)
        addEvent(function()
            if rewardItem and rewardItem:getPosition() then
                rewardItem:remove()
                local players = Game.getPlayers()
                for _, player in ipairs(players) do
                    player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "The reward chest has disappeared!")
                end
            end
        end, expirationTime * 1000)
    else
        print("Error creating reward chest.")
    end
end

local function hasRewardExpired(player, storageKey)
    local expirationTime = player:getStorageValue(storageKey)
    return expirationTime ~= -1 and expirationTime <= os.time()
end

local creatureEvent = CreatureEvent("BossDeath")

function creatureEvent.onDeath(creature, corpse)
    local bossPosition = creature:getPosition()
    local rewardChestId = 0
    local depotID = 0
    local bossName = ""
    for _, boss in ipairs(bossesList) do
        if creature:getName():lower() == boss.name:lower() then
            rewardChestId = boss.RewardChestId
            depotID = boss.depotID
            bossName = boss.name
            break
        end
    end

    if rewardChestId ~= 0 then
        createRewardChest(bossPosition, rewardChestId, bossesList[1].expirationTime)
        creature:say("The reward chest will disappear in 5 minutes!", TALKTYPE_MONSTER_SAY)
    else
        print("Reward chest ID not found.")
    end

    for _, player in ipairs(Game.getPlayers()) do
        if player:isPlayer() then
            for _, boss in ipairs(bossesList) do
                if creature:getName():lower() == boss.name:lower() then
                    player:setStorageValue(boss.storage, 1)
                    local expirationTime = os.time() + boss.expirationTime
                    player:setStorageValue(STORAGE_KEYS.bossData, expirationTime)
                    local message = "You contributed to defeating " .. boss.name .. ". Now go to the chest to claim your reward! Expiration time: " .. os.date("%c", expirationTime)
                    player:sendTextMessage(MESSAGE_EVENT_ADVANCE, message)
                end
            end
        end
    end
end

creatureEvent:register()

local function sendRewardMessage(player, bossName, receivedItems)
    local message
    if #receivedItems > 0 then
        message = "From " .. bossName .. ": " .. table.concat(receivedItems, ", ")
        player:sendTextMessage(MESSAGE_EVENT_ADVANCE, message)
        player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "Your reward has been sent to your depot.")
    else
        message = "From " .. bossName .. ": Unfortunately, you did not receive any items."
        player:sendTextMessage(MESSAGE_EVENT_ADVANCE, message)
    end
end

local rewardAction = Action()

function rewardAction.onUse(player, item, fromPosition, target, toPosition, isHotkey)
    if not player or not player:isPlayer() or not item then
        return false
    end

    local depotID = 0
    for _, boss in ipairs(bossesList) do
        if item:getId() == boss.RewardChestId and player:getStorageValue(boss.storage) == 1 then
            depotID = boss.depotID
            local storageKey = "boss_reward_time"
            if hasRewardExpired(player, storageKey) then
                player:sendTextMessage(MESSAGE_STATUS_CONSOLE_BLUE, "Your reward from " .. boss.name .. " has expired.")
            else
                local depot = player:getDepotChest(depotID, true)  -- Using depotID from the boss configuration
                if not depot then
                    return false
                end

                local bag = depot:addItem(7343, 1)
                if not bag then
                   print("Failed to add the reward bag to the player's depot.")
                    return false
                end

                local receivedItems = {}
                for _, lootItem in ipairs(boss.loot) do
                    if math.random(100000) <= lootItem.chance then
                        local itemAdded = bag:addItem(lootItem.item, lootItem.count or 1)
                        if itemAdded then
                            local itemName = ItemType(lootItem.item):getPluralName() or ItemType(lootItem.item):getName()
                            table.insert(receivedItems, (lootItem.count or 1) .. "x " .. itemName)
                        end
                    end
                end

                sendRewardMessage(player, boss.name, receivedItems)
            end
            player:setStorageValue(boss.storage, 0)
            player:setStorageValue(storageKey, -1)
            break
        end
    end

    return true
end

rewardAction:aid(ACTION_ID)
rewardAction:register()

This script is the second version
In the Reward Chest (for example, in the temple or boss room), you should set it up using the Action ID as shown in the image.

1713715469427.png


boss3.gif

The individual who inflicted the most damage and another who inflicted a lesser amount both receive a reward. Conversely, those who did not contribute to any damage do not receive any reward. This system operates on a straightforward basis. I hope you found this explanation satisfactory. :)

data/scripts.
Lua:
-- Define a table listing the bosses and their respective properties
local bossesList = {
    {
        name = "Orshabaal",
        storage = 6655,
        expirationTime = 7 * 24 * 60 * 60, -- 7 days
        loot = {
            {item = 2160, count = 5, chance = 100000}, -- 100% chance
            {item = 2494, count = 1, chance = 50000}, -- 50% chance
        },
        rewardChestId = 21584, -- Reward chest ID
        depotId = 1, -- Depot ID of the main city where the items will be sent
    },
    {
        name = "Cave Rat",
        storage = 6656,
        expirationTime = 7 * 24 * 60 * 60,
        loot = {
            {item = 2160, count = 10, chance = 100000}, -- 100% chance
            {item = 2498, count = 1, chance = 75000}, -- 75% chance
        },
        rewardChestId = 21584, -- Reward chest ID
        depotId = 1, -- Depot ID of the main city where the items will be sent
    },
    -- Add more bosses as needed
}

local ACTION_ID = 2550 -- You need to open the RME Editor and set it to 2550, then save.

local STORAGE_KEYS = {
    bossData = "boss_data"
}

-- Function to check if a reward has expired
local function hasRewardExpired(player, storageKey)
    local expirationTime = player:getStorageValue(storageKey)
    return expirationTime ~= -1 and expirationTime <= os.time()
end

local creatureEvent = CreatureEvent("BossDeath")

function creatureEvent.onDeath(creature, corpse, killer, mostDamageKiller)
    if killer and killer:isPlayer() then
        local creatureName = creature:getName():lower()
        for _, boss in ipairs(bossesList) do
            if creatureName == boss.name:lower() then
                -- Set reward data for the killer
                killer:setStorageValue(boss.storage, 1)
                local expirationTime = os.time() + boss.expirationTime
                killer:setStorageValue(STORAGE_KEYS.bossData, expirationTime)
                local message = "You contributed to defeating " .. boss.name .. ". Now go to the chest to claim your reward! Expiration time: " .. os.date("%c", expirationTime)
                killer:sendTextMessage(MESSAGE_EVENT_ADVANCE, message)

                -- Check if there's a most damage killer
                if mostDamageKiller and mostDamageKiller:isPlayer() and mostDamageKiller:getId() ~= killer:getId() then
                    mostDamageKiller:setStorageValue(boss.storage, 1)
                    mostDamageKiller:setStorageValue(STORAGE_KEYS.bossData, expirationTime)
                    local messageMostDamage = "You dealt the most damage to " .. boss.name .. ". Now go to the chest to claim your reward! Expiration time: " .. os.date("%c", expirationTime)
                    mostDamageKiller:sendTextMessage(MESSAGE_EVENT_ADVANCE, messageMostDamage)
                end
                break
            end
        end
    end
end

creatureEvent:register()

-- Function to send reward message to player
local function sendRewardMessage(player, bossName, receivedItems)
    if #receivedItems > 0 then
        local message = "From " .. bossName .. ": " .. table.concat(receivedItems, ", ")
        player:sendTextMessage(MESSAGE_EVENT_ADVANCE, message)
        player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "Your reward has been sent to your depot.")
    else
        local message = "From " .. bossName .. ": Unfortunately, you did not receive any items."
        player:sendTextMessage(MESSAGE_EVENT_ADVANCE, message)
    end
end

local rewardAction = Action()

function rewardAction.onUse(player, item, fromPosition, target, toPosition, isHotkey)
    if not player or not player:isPlayer() or not item then
        return false
    end

    local rewardsClaimed = false
    for _, boss in ipairs(bossesList) do
        if item:getId() == boss.rewardChestId and player:getStorageValue(boss.storage) == 1 then
            local storageKey = STORAGE_KEYS.bossData
            if hasRewardExpired(player, storageKey) then
                player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "Your reward from " .. boss.name .. " has expired.")
            else
                local depot = player:getDepotChest(boss.depotId, true)
                if not depot then
                    return false
                end

                local bag = depot:addItem(7343, 1)

                if not bag then
                   print("Failed to add the reward bag to the player's depot.")
                    return false
                end

                local receivedItems = {}
                for _, lootItem in ipairs(boss.loot) do
                    if math.random(100000) <= lootItem.chance then
                        local itemAdded = bag:addItem(lootItem.item, lootItem.count or 1)
                        if itemAdded then
                            local itemName = ItemType(lootItem.item):getPluralName() or ItemType(lootItem.item):getName()
                            table.insert(receivedItems, (lootItem.count or 1) .. "x " .. itemName)
                        end
                    end
                end

                if #receivedItems > 0 then
                    sendRewardMessage(player, boss.name, receivedItems)
                    player:setStorageValue(boss.storage, 0)
                    player:setStorageValue(storageKey, -1)
                    rewardsClaimed = true
                else
                    player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "You did not receive any items from " .. boss.name .. ".")
                end
            end
        end
    end

    if not rewardsClaimed then
        player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "You need to defeat the corresponding boss first to receive the reward.")
        return false
    end

    return true
end

rewardAction:aid(ACTION_ID)
rewardAction:register()
 
Last edited:
bosses and loot in the script... uhm... any each player involved rolls their own loot table?
i mean so what your saying is 50 ppl attacking orshabaal, it can drop 50 thunder hammers in one kill..

yikes
 
Back
Top