• 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!
  • New resources must be posted under Resources tab. A discussion thread will be created automatically, you can't open threads manually anymore.

[TFS 1.4.2] Boss Reward Bag - onDeath (with DamageMap)

I really liked it, and it’s great for TFS 1.4+. This system works only with TFS 1.4+ that supports version 10.x or higher. For those who want to use TFS 1.5 as a downgrade with Nekiro, you just need to remove the mailbox system, as Nekiro does not have this implemented in the source. Simply change it to:
LUA:
local townId = 1 -- Set city ID to 1
local depotChest = player:getDepotChest(townId, true) 
reward:moveTo(depotChest)

This will send the item to the depot. Of course, it works as expected. I hope this is clear for new developers or those who already know about it.
Post automatically merged:

Sneaky Diller specifically asked me to make Nekiro TFS 1.5 work, so I fulfilled the request and decided to share it here with the OTLand community. I configured each table with town ID 1 to send rewards, and for another boss, town ID 2 for another city, based on their preference for setting the town ID. I didn’t change anything else, just kept the original script. I only removed the mailbox and replaced it with the city depot.

LUA:
local bossConfig = {
    ["orshabaal"] = {
        timeCounterStorage = 66666,
        delayTimer = 10, -- in seconds
        bagId = 1993,
        allowedDistance = 20, -- max distance between boss and player for reward eligibility
        townId = 1, -- Primary town ID for rewards
        loot = {
            {item = 2160, minCount = 25, count = 50, chance = 100000, unique = 1}, -- crystal coin
            {item = 2494, count = 1, chance = 100000}, -- demon armor
            {item = 18408, count = 1, chance = 100000}, -- prismatic ring
            {item = 18407, charges = 750, count = 1, chance = 100000, unique = 1}, -- prismatic necklace
            {item = 5903, count = 1, chance = 100000, unique = 1} -- ferumbras hat
        }
    },
    ["demodras"] = {
        timeCounterStorage = 66667,
        delayTimer = 20, -- in seconds
        bagId = 1991,
        allowedDistance = 20, -- max distance between boss and player for reward eligibility
        townId = 2, -- Secondary town ID for rewards
        loot = {
            {item = 2160, minCount = 5, count = 5, chance = 100000, unique = 1}, -- crystal coin
            {item = 2492, count = 1, chance = 100000}, -- dsm
            {item = 18408, count = 1, chance = 100000}, -- prismatic ring
            {item = 18407, charges = 750, count = 1, chance = 100000, unique = 1}, -- prismatic necklace
            {item = 5919, count = 1, chance = 100000, unique = 1} -- dragon claw
        }
    },
}

local creatureevent = CreatureEvent("bossDeath")

function creatureevent.onDeath(creature, corpse, killer, mostDamageKiller, unjustified, mostDamageUnjustified)
    local creatureKey = creature:getName():lower()
    local bossData = bossConfig[creatureKey]
    if bossData then
        local creaturePos = creature:getPosition()
        local topDamage = 0
        local topDamagerId = nil

        for i, damage in pairs(creature:getDamageMap()) do
            local totalDamage = damage.total or 0
            if totalDamage > topDamage then
                topDamage = totalDamage
                topDamagerId = i
            end
        end

        for i, damage in pairs(creature:getDamageMap()) do
            local p = Player(i)
            if p then
                local ppos = p:getPosition()
                if ppos:getDistance(creaturePos) <= bossData.allowedDistance then
                    sendReward(p, bossData, topDamagerId == i)
                else
                    p:sendTextMessage(MESSAGE_EVENT_ADVANCE, "The monster you fought has fallen, but you are too far away to claim your prize.")
                end
            end
        end
    end
end

creatureevent:register()

function sendReward(player, bossData, isTopDamager)
    local currentTime, currentStorage = os.time(), player:getStorageValue(bossData.timeCounterStorage)
    if currentStorage > currentTime then
        player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "You can obtain the reward again in " .. os.date("!%H hours %M minutes and %S seconds", currentStorage - currentTime) .. ".")
        return false
    end

    local message = "You found reward bag containing: "
    local bag = Game.createItem(bossData.bagId, 1)

    for i = 1, #bossData.loot do
        local rand = math.random(100000)
        local itemConfig = bossData.loot[i]
        if rand <= itemConfig.chance then
            local randomcount = math.random(itemConfig.minCount or 1, itemConfig.count or 100)
            local item = nil

            if itemConfig.count and not itemConfig.charges then
                if itemConfig.unique == 1 then
                    if isTopDamager then
                        item = Game.createItem(itemConfig.item, randomcount)
                    end
                else
                    item = Game.createItem(itemConfig.item, randomcount)
                end
            elseif itemConfig.charges then
                if itemConfig.unique == 1 then
                    if isTopDamager then
                        item = Game.createItem(itemConfig.item, itemConfig.charges)
                    end
                else
                    item = Game.createItem(itemConfig.item, itemConfig.charges)
                end
            else
                if itemConfig.unique == 1 then
                    if isTopDamager then
                        item = Game.createItem(itemConfig.item)
                    end
                else
                    item = Game.createItem(itemConfig.item)
                end
            end

            if item then
                bag:addItemEx(item)
                if message ~= "You found reward bag containing: " then
                    message = message .. ", "
                end
                message = message .. randomcount .. " " .. ItemType(itemConfig.item):getName()
            end
        end
    end

    if message == "You found reward bag containing: " then
        message = message .. "nothing"
    end

    local depotChest = player:getDepotChest(bossData.townId, true)
    if depotChest then
        bag:moveTo(depotChest)
        message = message .. ".\n\nIt was sent to your depot in town ID " .. bossData.townId .. "."
    else
        return false
    end

    currentTime = currentTime + bossData.delayTimer
    player:setStorageValue(bossData.timeCounterStorage, currentTime)
    player:sendTextMessage(MESSAGE_EVENT_ADVANCE, message .. ".")

    return true
end
 
Last edited:
I really liked it, and it’s great for TFS 1.4+. This system works only with TFS 1.4+ that supports version 10.x or higher. For those who want to use TFS 1.5 as a downgrade with Nekiro, you just need to remove the mailbox system, as Nekiro does not have this implemented in the source. Simply change it to:
LUA:
local townId = 1 -- Set city ID to 1
local depotChest = player:getDepotChest(townId, true)
reward:moveTo(depotChest)

This will send the item to the depot. Of course, it works as expected. I hope this is clear for new developers or those who already know about it.
Post automatically merged:

Sneaky Diller specifically asked me to make Nekiro TFS 1.5 work, so I fulfilled the request and decided to share it here with the OTLand community. I configured each table with town ID 1 to send rewards, and for another boss, town ID 2 for another city, based on their preference for setting the town ID. I didn’t change anything else, just kept the original script. I only removed the mailbox and replaced it with the city depot.

LUA:
local bossConfig = {
    ["orshabaal"] = {
        timeCounterStorage = 66666,
        delayTimer = 10, -- in seconds
        bagId = 1993,
        allowedDistance = 20, -- max distance between boss and player for reward eligibility
        townId = 1, -- Primary town ID for rewards
        loot = {
            {item = 2160, minCount = 25, count = 50, chance = 100000, unique = 1}, -- crystal coin
            {item = 2494, count = 1, chance = 100000}, -- demon armor
            {item = 18408, count = 1, chance = 100000}, -- prismatic ring
            {item = 18407, charges = 750, count = 1, chance = 100000, unique = 1}, -- prismatic necklace
            {item = 5903, count = 1, chance = 100000, unique = 1} -- ferumbras hat
        }
    },
    ["demodras"] = {
        timeCounterStorage = 66667,
        delayTimer = 20, -- in seconds
        bagId = 1991,
        allowedDistance = 20, -- max distance between boss and player for reward eligibility
        townId = 2, -- Secondary town ID for rewards
        loot = {
            {item = 2160, minCount = 5, count = 5, chance = 100000, unique = 1}, -- crystal coin
            {item = 2492, count = 1, chance = 100000}, -- dsm
            {item = 18408, count = 1, chance = 100000}, -- prismatic ring
            {item = 18407, charges = 750, count = 1, chance = 100000, unique = 1}, -- prismatic necklace
            {item = 5919, count = 1, chance = 100000, unique = 1} -- dragon claw
        }
    },
}

local creatureevent = CreatureEvent("bossDeath")

function creatureevent.onDeath(creature, corpse, killer, mostDamageKiller, unjustified, mostDamageUnjustified)
    local creatureKey = creature:getName():lower()
    local bossData = bossConfig[creatureKey]
    if bossData then
        local creaturePos = creature:getPosition()
        local topDamage = 0
        local topDamagerId = nil

        for i, damage in pairs(creature:getDamageMap()) do
            local totalDamage = damage.total or 0
            if totalDamage > topDamage then
                topDamage = totalDamage
                topDamagerId = i
            end
        end

        for i, damage in pairs(creature:getDamageMap()) do
            local p = Player(i)
            if p then
                local ppos = p:getPosition()
                if ppos:getDistance(creaturePos) <= bossData.allowedDistance then
                    sendReward(p, bossData, topDamagerId == i)
                else
                    p:sendTextMessage(MESSAGE_EVENT_ADVANCE, "The monster you fought has fallen, but you are too far away to claim your prize.")
                end
            end
        end
    end
end

creatureevent:register()

function sendReward(player, bossData, isTopDamager)
    local currentTime, currentStorage = os.time(), player:getStorageValue(bossData.timeCounterStorage)
    if currentStorage > currentTime then
        player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "You can obtain the reward again in " .. os.date("!%H hours %M minutes and %S seconds", currentStorage - currentTime) .. ".")
        return false
    end

    local message = "You found reward bag containing: "
    local bag = Game.createItem(bossData.bagId, 1)

    for i = 1, #bossData.loot do
        local rand = math.random(100000)
        local itemConfig = bossData.loot[i]
        if rand <= itemConfig.chance then
            local randomcount = math.random(itemConfig.minCount or 1, itemConfig.count or 100)
            local item = nil

            if itemConfig.count and not itemConfig.charges then
                if itemConfig.unique == 1 then
                    if isTopDamager then
                        item = Game.createItem(itemConfig.item, randomcount)
                    end
                else
                    item = Game.createItem(itemConfig.item, randomcount)
                end
            elseif itemConfig.charges then
                if itemConfig.unique == 1 then
                    if isTopDamager then
                        item = Game.createItem(itemConfig.item, itemConfig.charges)
                    end
                else
                    item = Game.createItem(itemConfig.item, itemConfig.charges)
                end
            else
                if itemConfig.unique == 1 then
                    if isTopDamager then
                        item = Game.createItem(itemConfig.item)
                    end
                else
                    item = Game.createItem(itemConfig.item)
                end
            end

            if item then
                bag:addItemEx(item)
                if message ~= "You found reward bag containing: " then
                    message = message .. ", "
                end
                message = message .. randomcount .. " " .. ItemType(itemConfig.item):getName()
            end
        end
    end

    if message == "You found reward bag containing: " then
        message = message .. "nothing"
    end

    local depotChest = player:getDepotChest(bossData.townId, true)
    if depotChest then
        bag:moveTo(depotChest)
        message = message .. ".\n\nIt was sent to your depot in town ID " .. bossData.townId .. "."
    else
        return false
    end

    currentTime = currentTime + bossData.delayTimer
    player:setStorageValue(bossData.timeCounterStorage, currentTime)
    player:sendTextMessage(MESSAGE_EVENT_ADVANCE, message .. ".")

    return true
end
It works thank you
 
Removed parcel, label and mailbox, no need to use them anymore.


LUA:
local bossConfig = {
    ["orshabaal"] = {
        timeCounterStorage = 66666,
        delayTimer = 10, --in seconds
        bagId = 1993,
        allowedDistance = 20, --max distance between boss and player, above this value no reward will be given to the remote player
        loot = {
            {item = 2160, minCount = 25, count = 50, chance = 100000, unique = 1}, --crystal coin
            {item = 2494, count = 1, chance = 100000}, --demon armor
            {item = 18408, count = 1, chance = 100000}, --prismatic ring
            {item = 18407, charges = 750, count = 1, chance = 100000, unique = 1}, --prismatic necklace
            {item = 5903, count = 1, chance = 100000, unique = 1} --ferumbras hat
        }
    },
    ["demodras"] = {
        timeCounterStorage = 66667,
        delayTimer = 20, --in seconds
        bagId = 1991,
        allowedDistance = 20, --max distance between boss and player, above this value no reward will be given to the remote player
        loot = {
            {item = 2160, minCount = 5, count = 5, chance = 100000, unique = 1}, --crystal coin
            {item = 2492, count = 1, chance = 100000}, --dsm
            {item = 18408, count = 1, chance = 100000}, --prismatic ring
            {item = 18407, charges = 750, count = 1, chance = 100000, unique = 1}, --prismatic necklace
            {item = 5919, count = 1, chance = 100000, unique = 1} --dragon claw
        }
    },
}

local creatureevent = CreatureEvent("bossDeath")

function creatureevent.onDeath(creature, corpse, killer, mostDamageKiller, unjustified, mostDamageUnjustified)
    local creatureKey = creature:getName():lower()
    local bossData = bossConfig[creatureKey]
    if bossData then
        local creaturePos = getCreaturePosition(creature)
        local topDamage = 0
        local topDamagerId = nil

        for i, damage in pairs(creature:getDamageMap()) do
            local totalDamage = damage.total or 0
            if totalDamage > topDamage then
                topDamage = totalDamage
                topDamagerId = i
            end
        end

        for i, damage in pairs(creature:getDamageMap()) do
            local p = Player(i)
            if p then
                local ppos = p:getPosition()
                if ppos:getDistance(creaturePos) <= bossData.allowedDistance then
                    sendReward(p, bossData, topDamagerId == i)
                else
                    p:sendTextMessage(MESSAGE_EVENT_ADVANCE,"The monster you fought has fallen, but you are too far away to claim your prize.")
                end
            end
        end
    end
end

creatureevent:register()

function sendReward(player, bossData, isTopDamager)
    local currentTime, currentStorage = os.time(), player:getStorageValue(bossData.timeCounterStorage)
    if currentStorage > currentTime then
        player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "You can obtain the reward again in " .. os.date("!%H hours %M minutes and %S seconds", currentStorage - currentTime) .. ".")
        return false
    end

    local message = "You found reward bag containing: "
    local bag = Game.createItem(bossData.bagId, 1)

    for i = 1, #bossData.loot do
        local rand = math.random(100000)
        local itemConfig = bossData.loot[i]
        if rand <= itemConfig.chance then
            local randomcount = math.random(itemConfig.minCount or 1, itemConfig.count or 100)
            if not itemConfig.count then itemConfig.count = 100 end
     
            if itemConfig.count >= 2 and not itemConfig.charges then --for items with count 2 or more and without charges obviously
                if itemConfig.unique == 1 then
                    if isTopDamager then
                        item = Game.createItem(itemConfig.item, randomcount)
                    else
                        item = nil
                    end
                else
                    item = Game.createItem(itemConfig.item, randomcount)
                end
            elseif itemConfig.charges then --for items with charges
                if itemConfig.unique == 1 then
                    if isTopDamager then
                        item = Game.createItem(itemConfig.item, itemConfig.charges)
                    else
                        item = nil
                    end
                else
                    item = Game.createItem(itemConfig.item, itemConfig.charges)
                end
            else --no charges and no count
                if itemConfig.unique == 1 then
                    if isTopDamager then
                        item = Game.createItem(itemConfig.item, count)
                    else
                        item = nil
                    end
                else
                    item = Game.createItem(itemConfig.item, count)
                end
            end
     
            if item then
                bag:addItemEx(item)
                if message ~= "You found reward bag containing: " then
                    message = message .. ", "
                end
                message = message .. randomcount .. " " .. ItemType(itemConfig.item):getName()
            end
        end
    end

    if message == "You found reward bag containing: " then
        message = message .. "nothing"
    end

    if player:addItemEx(bag) ~= RETURNVALUE_NOERROR then
        local inbox = player:getInbox()
        if not inbox then
            print("Failed to get inbox for player: " .. player:getName())
            return false
        end

        local addResult = inbox:addItemEx(bag, 1, FLAG_NOLIMIT)
        if addResult ~= RETURNVALUE_NOERROR then
            print("Failed to add item to inbox for player: " .. player:getName())
            player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "An error occurred while delivering your reward. Contact support.")
            return false
        end
        
        message = message .. ".\n\nIt was sent directly to your inbox due to lack of space/capacity."
    end

    currentTime = currentTime + bossData.delayTimer
    player:setStorageValue(bossData.timeCounterStorage, currentTime)
    player:sendTextMessage(MESSAGE_EVENT_ADVANCE, message .. ".")
 
    return true
end
 

Similar threads

Back
Top