• 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+ Double loot rate for single player

Evil Puncker

prolonged absenteeism
TFS Developer
Joined
May 30, 2009
Messages
7,263
Solutions
142
Reaction score
2,891
Hi everyone! Back in the days (0.x) we used to have a setLootRate or something like this, that allowed us to make loot rings etc, but how do we do it on TFS 1.3 now?

we can already do limited time exp boost like this one by @Ninja by playing with the OnGainExperience

but how/where should we look into to make something similar but for loot? (for example +50% loot chance for X minutes), I think it is Monster:eek:nDropLoot, but how? 🤔
 
Solution
So this is my onDeath for creatures:
Lua:
function onDeath(monster, corpse, killer, mostdamagekiller, lasthitunjustified, mostdamageunjustified)
    if not monster:isMonster() or monster:getMaster() then
        return true
    end
  
    if not corpse then
        return false
    end
  
    if not corpse:isContainer() then
        return true
    end

    local owner = mostdamagekiller
    if killer and killer:isPlayer() then
        owner = killer
    end

    if owner and owner:isPlayer() then
        corpse:setAttribute(ITEM_ATTRIBUTE_CORPSEOWNER, owner:getId())
    end

    monster:getType():createLoot(corpse, 1)

    return true
end

take note of this line
monster:getType():createLoot(corpse, 1)

So...

Leo32

Getting back into it...
Joined
Sep 21, 2007
Messages
971
Solutions
14
Reaction score
471
So this is my onDeath for creatures:
Lua:
function onDeath(monster, corpse, killer, mostdamagekiller, lasthitunjustified, mostdamageunjustified)
    if not monster:isMonster() or monster:getMaster() then
        return true
    end
  
    if not corpse then
        return false
    end
  
    if not corpse:isContainer() then
        return true
    end

    local owner = mostdamagekiller
    if killer and killer:isPlayer() then
        owner = killer
    end

    if owner and owner:isPlayer() then
        corpse:setAttribute(ITEM_ATTRIBUTE_CORPSEOWNER, owner:getId())
    end

    monster:getType():createLoot(corpse, 1)

    return true
end

take note of this line
monster:getType():createLoot(corpse, 1)

So when createloot is triggered, take note of this line:
Lua:
function MonsterType.createLoot(self, corpse, modifier)
    ...
    local randvalue = math.random(0, 100000) / (configManager.getNumber(configKeys.RATE_LOOT) * modifier);
    ...
end

So the modifier parameter is what you can use to modify the lootrate bonus.

So you could edit your onDeath like this as an example:
Lua:
function onDeath(monster, corpse, killer, mostdamagekiller, lasthitunjustified, mostdamageunjustified)
    if not monster:isMonster() or monster:getMaster() then
        return true
    end
  
    if not corpse then
        return false
    end
  
    if not corpse:isContainer() then
        return true
    end

    local owner = mostdamagekiller
    if killer and killer:isPlayer() then
        owner = killer
    end

    local lootrate = 1
    if owner and owner:isPlayer() then
        corpse:setAttribute(ITEM_ATTRIBUTE_CORPSEOWNER, owner:getId())
        if owner:getStorageValue(XXXXX) ~= -1 then
             lootrate = owner:getStorageValue(XXXXX)
        end
    end

    monster:getType():createLoot(corpse, lootrate)

    return true
end

Edit it however you get loot bonus data from players and their items.
 
Last edited:
Solution
OP
Evil Puncker

Evil Puncker

prolonged absenteeism
TFS Developer
Joined
May 30, 2009
Messages
7,263
Solutions
142
Reaction score
2,891
@Leo32

sorry, only got time to check and test it now, but seems like my TFS is too different from the files you posted, but anyway I found a way to do it, but the problem is that it is choosing a random loot and sometimes it triplicates it instead of doubling and I don't know why nor how to fix it, look how I made it on this file (check comments to see what I intended):

Lua:
function Monster:onDropLoot(corpse)
    if configManager.getNumber(configKeys.RATE_LOOT) == 0 then
        return
    end

    local player = Player(corpse:getCorpseOwner())
    local autolooted = "" -- i have custom autoloot system
    local mType = self:getType()
    local randomValue = math.random(1, 2) -- 50% chance to have "double" loot
    if not player or player:getStamina() > 840 then
        local monsterLoot = mType:getLoot()
        for i = 1, #monsterLoot do
            local item = corpse:createLootItem(monsterLoot[i])
            local randomDoubleItem = monsterLoot[math.random(#monsterLoot)] -- the way I used to get a random item from monster loot list, I don't know if it is right but seems like it is not
            if player:getStorageValue(32423) >= os.time() and randomValue == 2 then -- checking if player have the required storage to trigger the "double" loot and chance
                corpse:createLootItem(randomDoubleItem) -- creating the loot (duplicated and triplicated lmao)
                player:sendCancelMessage("You received a bonus loot.") -- ingame msg to see that it succeded
            end
            if not item then
                print('[Warning] DropLoot:', 'Could not add loot item to corpse.')
            end
 

Leo32

Getting back into it...
Joined
Sep 21, 2007
Messages
971
Solutions
14
Reaction score
471
Wow its in global.lua
monster.lua,
container.lua,
container.lua,
global.lua

To fix your current solution change:
Lua:
local randomDoubleItem = monsterLoot[math.random(#monsterLoot)]

To:
Lua:
local randomDoubleItem = monsterLoot[i]

This has flaws where you're basically just duplicating existing drops.
Stuff is still just as hard to drop.

If you want like a % based system...
This is as close as you can get to adjusting the lootrate cleanly.

replace:
Lua:
local lootrate = false
if player:getStorageValue(XXXXX) ~= -1 then
     lootrate = player:getStorageValue(XXXXX) -- Lootrate multiplier as a percent (10 = +10%, 100 = +100% always drops everything)
end
local item = corpse:createLootItem(monsterLoot[i], lootrate)

replace:
Lua:
function Container.createLootItem(self, item, lootrate)
    if self:getEmptySlots() == 0 then
        return true
    end

    local itemCount = 0
    local randvalue = getLootRandom(lootrate)

replace:
Lua:
function getLootRandom(lootrate)
    local roll = math.random(0, MAX_LOOTCHANCE) / configManager.getNumber(configKeys.RATE_LOOT)
    if lootrate then
         roll = math.floor(lootrate/100 * roll) - roll
    end
    return roll
end


Otherwise you could do what rl tibia does and treat it like a boosted roll.
This is kinda what you're doin, but instead of just duplicating something that already dropped - you're doing 2 drop rolls of each item.

And you only need to change the 1 file, instead of 3:

replace:
Lua:
local boostedChance = player:getStorageValue(XXXXX) -- Chance of a boosted role (10 = +10%, 100 = +100% always a boosted roll)
local boostedRoll = false
if boostedChance~= -1 then
      if math.random(1, 100) >= boostedChance then
          boostedRoll = true
          --player:sendCancelMessage("Boosted roll on this corpse.")
     end
end
for i = 1, #monsterLoot do
    local item = corpse:createLootItem(monsterLoot[i])
        if boostedRoll then -- roll item again.
            corpse:createLootItem(monsterLoot[i])
        end
    end
    if not item then
        print('[Warning] DropLoot:', 'Could not add loot item to corpse.')
    end
end
 
Last edited:

Shadow_

Advanced OT User
Joined
Jun 2, 2018
Messages
754
Solutions
25
Reaction score
240
Location
Cairo, Egypt
well i found a better way than doing all of this instead editting 1 file you will edit 1 line ^^
if it asks to start adding the item by that way if randvalue < item.chance then it means that if item.chance == 99999 and randvalue == 1 the item will be added because monster loot chance wise is 100% = 100000, then if the item is rare and 1% it will be 1000 so if the randvalue have to be less than than item chance so what about decrease the randvalue by /2 so it will decrease by half which is higher loot rate 100% do you got it? don't read
if you didn't come here <--
lets say the rand now is 50k which means any item with chance higher than 50% will be added to loot but if we did /2 it will be any item higher than 25% isn't that the same 100% but more accurate?^^
so why don't you setPlayerStorageValue == X and add this under this
if self:getStorageValue(X) == 5 then(
randvalue = randvalue / 2
end
 
Top