• 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.X] Rarity Rolls & Custom Attributes Library

The function
LUA:
function statChange(creature, attacker, primaryDamage, primaryType, secondaryDamage, secondaryType, origin)
is called only when one player attack other player. For exemple, when one player attack a monster the critical or ice,fire,earth damage doesnt work. Im using TFS 1.5 DOWNGRADE NEKIRO 7.72



LUA:
function statChange(creature, attacker, primaryDamage, primaryType, secondaryDamage, secondaryType, origin)
    
    -- Defaults
    local chance = 0 -- Crit Chance
    local spellmodifier = 0 -- Spell Damage
    local manaleech = 0
    local lifeleech = 0
    local stunDuration = 2000
    local sourceDamage = primaryDamage -- Used for multi-shot when secondary targets are immune
    local elementalroll = false -- Flag for if weapon has an element on it
    local doubleroll = false -- Flag for if the weapon has two elements on it
    --local dawnbreaker = false
    --local rainbowshield = false
    
    -- What elements should be checked when calculating resistances
    local resistances = {
        [COMBAT_PHYSICALDAMAGE] = {Native = 0, Custom = 0, String = "Physical"},
        [COMBAT_FIREDAMAGE] = {Native = 0, Custom = 0, String = "Fire"},
        [COMBAT_ICEDAMAGE] = {Native = 0, Custom = 0, String = "Ice"},
        [COMBAT_ENERGYDAMAGE] = {Native = 0, Custom = 0, String = "Energy"},
        [COMBAT_POISONDAMAGE] = {Native = 0, Custom = 0, String = "Poison"},
        [COMBAT_PHYSICALDAMAGE] = {Native = 0, Custom = 0, String = "Death"}
    }
    
    -- Check resistences if victim is a player before applying extra elemental damage below
    if creature:isPlayer() then
        for i = 1,#checkallslots do
            if creature:getSlotItem(checkallslots[i]) ~= nil then
                local resistanceitem = creature:getSlotItem(checkallslots[i])
                local resistanceitemdesc = resistanceitem:getDescription()
                getResistences(resistanceitemdesc, resistances, true)
                --[[
                -- if rainbow shield
                if resistanceitem.itemid == 8905 then
                    if checkallslots[i] == CONST_SLOT_LEFT or checkallslots[i] == CONST_SLOT_RIGHT then -- Only if equipped
                        rainbowshield = resistanceitem
                    end
                end
                --]]
            end
        end
        
         -- Reduce main damage on custom resistance rolls before applying extra elemental damage below
        if primaryType ~= 0 then
            if resistances[primaryType] then
                if resistances[primaryType].Custom ~= 0 then
                    local resistancePercent = (100 - resistances[primaryType].Custom)
                    primaryDamage = (resistancePercent / 100) * primaryDamage
                end
            end
        end
        if secondaryType ~= 0 then
            if resistances[secondaryType] then
                if resistances[secondaryType].Custom ~= 0 then
                    local resistancePercent = (100 - resistances[secondaryType].Custom)
                    secondaryDamage = (resistancePercent / 100) * secondaryDamage
                end
            end
        end
    end

    if attacker then -- Ignore HP changes from healing fountains, terrain elemental fields (neutral sources basically)
        if attacker:isPlayer() then
            if origin == ORIGIN_RANGED or origin == ORIGIN_MELEE then -- Skip if player is using spells
                -- Natural elemental damage (wand, fire sword, flaming arrow etc) swap Types around for better visuals and set flags
                if secondaryType ~= 0 or primaryType ~= COMBAT_PHYSICALDAMAGE then
                    -- Cache original physical damage
                    local originalDamage = primaryDamage
                    local originalType = primaryType
                    
                    -- Swap primary & secondary
                    primaryDamage = secondaryDamage
                    primaryType = secondaryType
                    secondaryDamage = originalDamage
                    secondaryType = originalType
                    
                    -- damageTypes have been swapped, flag it
                    elementalroll = true
                end
                
                -- Check weapons for crit/elemental damage
                for i = 1,#checkweaponslots do -- Roll for each slot
                    if attacker:getSlotItem(checkweaponslots[i]) ~= nil then
                        local slotitem = attacker:getSlotItem(checkweaponslots[i])
                        local slotitemdesc = slotitem:getDescription()
                        
                    
                    
function doTargetCombatCondition(attacker, creature, condition, effect)
    -- Implementação da função
end

-- Verificar dano elemental
if slotitemdesc:find("%[Enhanced Fire Damage") then
    primaryDamage, primaryType, secondaryDamage, secondaryType, elementalroll = elementalDmg(slotitemdesc, COMBAT_FIREDAMAGE, true, creature, resistances, primaryDamage, primaryType, secondaryDamage, secondaryType, elementalroll)

    -- 33% de chance de aplicar queimadura
    if math.random(1, 3) == 3 then
        local condition = createConditionObject(CONDITION_FIRE)
        local burnDamage = 20

        -- Ajustar dano de queimadura com base nas resistências
        if creature:isPlayer() then
            if resistances[COMBAT_FIREDAMAGE].Custom ~= 0 or resistances[COMBAT_FIREDAMAGE].Native ~= 0 then
                local resistancePercent = (100 - (resistances[COMBAT_FIREDAMAGE].Custom + resistances[COMBAT_FIREDAMAGE].Native))
                burnDamage = (resistancePercent / 100) * burnDamage
            end
        elseif creature:isMonster() then
            local resistance = creature:getType():getElementList()
            local immunity = creature:getType():getCombatImmunities()

            -- Ajustar dano de queimadura com base nas resistências do monstro
            if resistance[COMBAT_FIREDAMAGE] then
                local resistancePercent = (100 - resistance[COMBAT_FIREDAMAGE])
                burnDamage = (resistancePercent / 100) * burnDamage
            end

            -- Se o monstro for imune ao dano de fogo, definir dano de queimadura como zero
            if bit.band(immunity, COMBAT_FIREDAMAGE) == COMBAT_FIREDAMAGE then
                burnDamage = 0
            end
        end

        -- Se o dano de queimadura não for zero, criar condição e aplicar ao alvo
        if burnDamage ~= 0 then
            addDamageCondition(condition, 10, 2000, burnDamage)
            setConditionParam(condition, CONDITION_PARAM_DELAYED, true)
            doTargetCombatCondition(attacker, creature, condition, CONST_ME_FIRE)
        end
    end
end
                        if slotitemdesc:find "%[Enhanced Ice Damage" then
                            primaryDamage, primaryType, secondaryDamage, secondaryType, elementalroll = elementalDmg(slotitemdesc, COMBAT_ICEDAMAGE, false, creature, resistances, primaryDamage, primaryType, secondaryDamage, secondaryType, elementalroll)
                            if math.random(1,5) == 5 then -- 20% to paralyze/slow
                                local condition = createConditionObject(CONDITION_PARALYZE)
                                setConditionParam(condition, CONDITION_PARAM_TICKS, 3000)
                                setConditionParam(condition, CONDITION_PARAM_SPEED, -300)
                                doTargetCombatCondition(attacker, creature, condition, CONST_ME_MAGIC_ICEAREA)
                            end
                        end
                        if slotitemdesc:find "%[Enhanced Energy Damage" then
                            primaryDamage, primaryType, secondaryDamage, secondaryType, elementalroll = elementalDmg(slotitemdesc, COMBAT_ENERGYDAMAGE, true, creature, resistances, primaryDamage, primaryType, secondaryDamage, secondaryType, elementalroll)
                        end
                        
                        -- Check crit chance of slots and add together
                        if slotitemdesc:find "%[Crit Chance" then
                            local crit = string.match(slotitemdesc, "Crit Chance: [+-](%d+)%%")
                            chance = chance + crit
                        end
                        
                        -- Mana leech gather %
                        if slotitemdesc:find "%[Mana Leech" then
                            manaleech = string.match(slotitemdesc, '%[Mana Leech: %+(%d+)%%%]') or 0
                        end
                        
                        -- Life leech gather %
                        if slotitemdesc:find "%[Life Leech" then
                            lifeleech = string.match(slotitemdesc, '%[Life Leech: %+(%d+)%%%]') or 0
                        end
                        
                        -- Stun Chance
                        if slotitemdesc:find "%[Stun Chance" then
                            local stunchance = tonumber(string.match(slotitemdesc, '%[Stun Chance: %+(%d+)%%%]')) or 0
                            local rollchance = math.random(1,100)
                            if stunchance >= rollchance and attacker ~= creature then
                                stunTarget(creature.uid, stunDuration)
                            end
                        end
                            
                        -- Multi-shot
                        if slotitemdesc:find "%[Multi Shot" then
                            if attacker:getSlotItem(CONST_SLOT_AMMO) ~= nil then -- Does player have ammo
                                local multishot = tonumber(string.match(slotitemdesc, "%[Multi Shot: %+(%d+)%]"))
                                local ammoSlot = attacker:getSlotItem(CONST_SLOT_AMMO).itemid
                                local validammo = false
                                for k,v in pairs(animation) do
                                    if k == ammoSlot then
                                        validammo = true -- Ammo they're using exists in animation table
                                        break
                                    end
                                end
                                if validammo then -- (!) You may need to add more CONST_ANI_XXXX animations to the animation table
                                    local targetpos = creature:getPosition()
                                    local targets = getSpectators(targetpos, 2, 2) -- get possible multi-shot targets
                                    local victims = {}
                                    if targets ~= nil then
                                        -- do the shuffle
                                        shuffle(targets)
                                        for i = 1,#targets do
                                            local target = Creature(targets[i])
                                            if target:isMonster() then -- only target monsters
                                                if isSightClear(attacker:getPosition(), target:getPosition()) then -- that are in sight
                                                    if target:getPosition() ~= targetpos then -- ignore the original target
                                                        local victimcount = #victims or 0
                                                        if victimcount < multishot then
                                                            table.insert(victims, target) -- collate valid targets into victims table
                                                        else
                                                            break -- exit the for loop, have enough targets
                                                        end
                                                    end
                                                end
                                            end
                                        end
                                    end
                                    function doTargetCombatHealth(attacker, target, damageType, adjustedDamage, originalDamage)
                                    -- Implementação da função aqui
                                                 end
                                -- this a rats nest due to swapping primaryType/secondaryType above for visuals
                                            if victims ~= nil then
                                        for i = 1, #victims do
                                            -- Defaults
                                            local damage = 0
                                            local elementalDamage = 0
                                            local backupDamage = 0
                                            local mainType = primaryType
                                            local altType = secondaryType
                                            local resistance = victims[i]:getType():getElementList()
                                            local immunity = victims[i]:getType():getCombatImmunities()
                                            local distanceEffect = animation[ammoSlot]

                                            -- Animation
                                            attacker:getPosition():sendDistanceEffect(victims[i]:getPosition(), animation[ammoSlot])

                                            -- Damage calculation
                                            if elementalroll then -- Check if types are swapped
                                                mainType = secondaryType
                                                altType = primaryType
                                                damage = filterResistance(secondaryDamage, secondaryType, immunity, resistance)
                                                elementalDamage = filterResistance(primaryDamage, primaryType, immunity, resistance)
                                            else -- Types haven't been swapped
                                                damage = filterResistance(primaryDamage, primaryType, immunity, resistance)
                                                elementalDamage = filterResistance(secondaryDamage, secondaryType, immunity, resistance)
                                            end

                                            -- Apply secondary damage if any
                                            if elementalDamage ~= 0 then
                                                doTargetCombatHealth(attacker, victims[i], altType, math.ceil((80 / 100) * elementalDamage), elementalDamage)
                                            end

                                            -- Apply main damage if any
                                            if damage ~= 0 then
                                                doTargetCombatHealth(attacker, victims[i], mainType, math.ceil((80 / 100) * damage), damage)
                                            else -- No damage; fallback to original physical damage
                                                backupDamage = filterResistance(sourceDamage, COMBAT_PHYSICALDAMAGE, immunity, resistance)
                                                if backupDamage ~= 0 then -- Try rolling back to base physical damage
                                                    doTargetCombatHealth(attacker, victims[i], COMBAT_PHYSICALDAMAGE, math.ceil((80 / 100) * sourceDamage), sourceDamage)
                                                else -- Monster is immune to physical damage too
                                                    victims[i]:getPosition():sendMagicEffect(CONST_ME_BLOCKHIT)
                                                end
                                            end
                                        end
                                    end
                                end
                            end
                        end
                    end
                end
                
                -- Roll crit chance and apply if critical strike
                if chance > 0 then
                    if math.random(100) <= chance then
                        local pos = creature:getPosition()
                        pos:sendMagicEffect(criteffect)
                         -- if elemental roll flag, crit the swapped secondaryDamage instead of primaryDamage
                        if elementalroll then
                            secondaryDamage = secondaryDamage * critmodifier
                        else
                            primaryDamage = primaryDamage * critmodifier
                        end
                    end
                end
                
                -- Apply mana leech
                if manaleech ~= 0 then
                    local manatoadd = math.floor((manaleech / 100) * (primaryDamage + secondaryDamage))
                    local attackerpos = attacker:getPosition()
                    addEvent(manaLeechConcat, 5, attacker.uid, manatoadd)
                end
                
-- Apply life leech
if lifeleech ~= 0 then
    -- Calcula a quantidade de vida a ser roubada com base na porcentagem de life leech
    local lifetoadd = math.floor((lifeleech / 100) * (primaryDamage + secondaryDamage))
    
    -- Obtém a posição do atacante (se necessário)
    local attackerpos = attacker:getPosition()

    print("Life leech applied. Attacker ID: " .. attacker.uid .. ", Lifetoadd: " .. lifetoadd)

    -- Agende o evento para adicionar a vida roubada ao jogador
    addEvent(lifeLeechConcat, 5, attacker.uid, lifetoadd)
else
    print("Life leech not applied. Lifeleech is zero.")
end


            elseif origin == ORIGIN_SPELL then   
                -- Reduce spell damage based on custom resistances
                if resistances[primaryType] then
                    if resistances[primaryType].Custom ~= 0 then
                        local resistancePercent = (100 - resistances[primaryType].Custom)
                        primaryDamage = (resistancePercent / 100) * primaryDamage
                    end
                end
                
                -- Check slots that can roll the following attributes
                for i = 1,#checkweaponslots do
                    if attacker:getSlotItem(checkweaponslots[i]) ~= nil then
                        local slotitem = attacker:getSlotItem(checkweaponslots[i])
                        local slotitemdesc = slotitem:getDescription()
                        
                        -- Check crit chance of slots and add together
                        if slotitemdesc:find "%[Spell Damage" then
                            local spellDamage = string.match(slotitemdesc, "Spell Damage: [+-](%d+)%%")
                            spellmodifier = spellmodifier + spellDamage
                        end
                        
                        -- Mana leech gather %
                        if slotitemdesc:find "%[Mana Leech" then
                            manaleech = string.match(slotitemdesc, '%[Mana Leech: %+(%d+)%%%]') or 0
                        end
                        
                        -- Life leech gather %
                        if slotitemdesc:find "%[Life Leech" then
                            lifeleech = string.match(slotitemdesc, '%[Life Leech: %+(%d+)%%%]') or 0
                        end
                        
                        -- Stun Chance
                        if slotitemdesc:find "%[Stun Chance" then
                            local stunchance = tonumber(string.match(slotitemdesc, '%[Stun Chance: %+(%d+)%%%]')) or 0
                            local rollchance = math.random(1,100)
                            if stunchance >= rollchance and attacker ~= creature then
                                stunTarget(creature.uid, stunDuration)
                            end
                        end
                    end
                end
                
                -- if using a +%spelldamage wand, adjust damage
                if spellmodifier > 0 then
                    local extraDamage = (spellmodifier / 100) * primaryDamage
                    primaryDamage = primaryDamage + extraDamage
                end
                
                -- Apply mana leech
                if manaleech ~= 0 and primaryType ~= COMBAT_HEALING and secondaryType ~= COMBAT_HEALING then
                    local manatoadd = math.floor((manaleech / 100) * (primaryDamage + secondaryDamage))
                    manaLeechConcat(attacker.uid, manatoadd)
                end
                
                -- Apply life leech
                if lifeleech ~= 0 and primaryType ~= COMBAT_HEALING and secondaryType ~= COMBAT_HEALING then
                    local lifetoadd = math.floor((lifeleech / 100) * (primaryDamage + secondaryDamage))
                    lifeLeechConcat(attacker.uid, lifetoadd)
                end
            end
        end
    end
    
    return primaryDamage, primaryType, secondaryDamage, secondaryType, origin
end

function onHealthChange(creature, attacker, primaryDamage, primaryType, secondaryDamage, secondaryType, origin)
    if primaryType ~= 128 then -- Ignore health potions
        -- Call statChange for both player and monster attacks
        primaryDamage, primaryType, secondaryDamage, secondaryType, origin = statChange(creature, attacker, primaryDamage, primaryType, secondaryDamage, secondaryType, origin)
    end

    return primaryDamage, primaryType, secondaryDamage, secondaryType, origin
end

function onManaChange(creature, attacker, primaryDamage, primaryType, secondaryDamage, secondaryType, origin)
    if primaryType ~= 64 then -- Ignore mana potions
        -- Call statChange for both player and monster attacks
        primaryDamage, primaryType, secondaryDamage, secondaryType, origin = statChange(creature, attacker, primaryDamage, primaryType, secondaryDamage, secondaryType, origin)
        
        -- Apply magic shield bonus, even if neutral source
        if creature:isPlayer() then
            local manashield = 0
            for i = 1,#checkweaponslots do
                if creature:getSlotItem(checkweaponslots[i]) ~= nil then
                    local slotitem = creature:getSlotItem(checkweaponslots[i])
                    local slotitemdesc = slotitem:getDescription()
                    if slotitemdesc:find "%[Mana Shield" then
                        manashield = manashield + tonumber(string.match(slotitemdesc, '%[Mana Shield: %+(%d+)%%%]'))
                    end
                end
            end
            if manashield ~= 0 then
                local shieldPercent = (100 - manashield)
                primaryDamage = (shieldPercent / 100) * primaryDamage
                secondaryDamage = (shieldPercent / 100) * secondaryDamage
            end
        end
        
    end
    
    return primaryDamage, primaryType, secondaryDamage, secondaryType, origin
end
 
< 10.94
The first post is for versions earlier than 10.94, before crit and mana/life leech was added to the game.
Someone should try it on an 8.6 server ;)

10.94+
If you are using the latest TFS release, refer to the post here.

What is this?
A newer version of this:
A variant of this, this and this mod.
It gives items a chance to roll rare, epic or legendary when it drops from a monster:

iSCVyA6.png


With the following possible attributes:
(For config and if you want to understand the code, start at the stats table in lib/core/attributes.lua)
LUA:
[1] = { -- Attack
[2] = { -- Defense
[3] = { -- Extra Defense
[4] = { -- Armor
[5] = { -- Accuracy
[6] = { -- Range
[7] = { -- Equipment with < 50 charges
[8] = { -- Equipment with >= 50 charges
[9] = { -- Time
[10] = { -- Crit Chance
[11] = { -- Crit Amount (Currently Unused)
[12] = { -- Fire Damage
[13] = { -- Ice Damage
[14] = { -- Energy Damage
[15] = { -- Fire Resistance
[16] = { -- Ice Resistance
[17] = { -- Energy Resistance
[18] = { -- Earth Resistance
[19] = { -- Physical Resistance
[20] = { -- Death Resistance
[21] = { -- Spell Damage
[22] = { -- Multi Shot
[23] = { -- Stun Chance
[24] = { -- Mana Shield
[25] = { -- Sword Skill
[26] = { -- Skill Axe
[27] = { -- Skill Club
[28] = { -- Skill Melee
[29] = { -- Skill Distance
[30] = { -- Skill Shielding
[31] = { -- Magic Level
[32] = { -- Max Health i.e +100
[33] = { -- Max Mana i.e +100
[34] = { -- Max Health % i.e +10%
[35] = { -- Max Mana % i.e +10%
[36] = { -- Life Leech Chance (Currently Unused)
[37] = { -- Life Leech Amount
[38] = { -- Mana Leech Chance (Currently Unused)
[39] = { -- Mana Leech Amount


Cw1kJDN.png


Some of these are completely custom attributes, like elemental damage:

56C8xHU.gif


This requires the following updates/features:

1) Loot drop handled via Lua
2) Add the new health/mana gain coloured text messages
3) onInventoryUpdate()
4) onSpawn()


Installation:
📁 rollAttributes.zip
paste in /data

lib/core/core.lua
add below:
LUA:
-- Rolls & Custom Item Attributes
dofile('data/lib/core/attributes.lua')

talkactions.xml
add below:
XML:
<talkaction words="/roll" separator=" " script="roll.lua" />

creaturescripts.xml
add below:
XML:
<!-- Roll & Attribute Damage -->
<event type="healthchange" name="rollHealth" script="attributes.lua"/>
<event type="manachange" name="rollMana" script="attributes.lua"/>

creaturescripts/scripts/login.lua
add below:
LUA:
-- Activate Custom Item Attributes
for i = 1,10 do -- CONST_SLOT_FIRST,CONST_SLOT_LAST
    local item = player:getSlotItem(i)
    if item then
        itemAttributes(player, item, i, true)
    end
end
-- If player logged with more 'current health' than their db 'max health' due to an item attribute
local query = db.storeQuery("SELECT `health`,`mana` FROM players where `id`="..player:getGuid())
if query then
    local health = tonumber(result.getDataString(query, 'health'))
    local mana = tonumber(result.getDataString(query, 'mana'))
    local playerHealth = player:getHealth()
    local playerMana = player:getMana()
    if playerHealth < health then
        player:addHealth(health - playerHealth)
    end
    if playerMana < mana then
        player:addMana(mana - playerMana)
    end
    result.free(query)
end

add below:
LUA:
player:registerEvent("rollHealth")
player:registerEvent("rollMana")

events/scripts/player.lua
add to the bottom:
LUA:
function Player:onInventoryUpdate(item, slot, equip)
    itemAttributes(self, item, slot, equip)
end

events/scripts/monster.lua
add to the top of the file:
LUA:
-- Rarity Animations
local rare_popup = true
local rare_effect = true
local rare_effect_id = CONST_ME_STUN
add between:
LUA:
-- Apply rarity chance to corpse contents and apply animation
if rollRarity(corpse) > 0 then -- If a rare item was rolled, play animation
        if rare_popup then
            local spectators = Game.getSpectators(corpse:getPosition(), false, true, 7, 7, 5, 5)
            for i = 1, #spectators do
                spectators[i]:say(rare_text, TALKTYPE_MONSTER_SAY, false, spectators[i], corpse:getPosition())
            end
        end
    if rare_effect then
        corpse:getPosition():sendMagicEffect(rare_effect_id)
    end
end
add at the end:
LUA:
function Monster:onSpawn(position, startup, artificial)
    self:registerEvent("rollHealth")
    self:registerEvent("rollMana")
   return true
end


The core scripts are attached because they are to big to embed in post, so they're attached as rollAttributes.zip
Don't forget to paste the core scripts into your /data dir.

Extras
  • 'Stun Target' is disabled by default, add the condition from here and uncomment the lines in creaturescripts/scripts/attributes.lua
  • primaryDamage and primaryType are swapped with secondaryDamage and secondaryType on elemental damage (better, consistent visuals)
  • Use the included /roll <rarity> talkaction for testing i.e /roll legendary
  • Mana Leech and Life Leech apply 5ms after damage is done, this may feel different to vanilla Tibia.
  • Multi shot ignores creature armor/shielding - its quite primitive.
  • If you want to re-roll an item you should item:remove() it and re-create it (so it has stock base stats).
  • Custom resistances apply after natural resistances and are additive.
  • A unique weapon & shield using this systems on-hit mechanics can be found in extras.xml
    Overwrite their information in items.xml and uncomment their code in attributes.lua for cool points.

Link for 10.94+ Github is down
 
finally got it to work! Now it seems i got the same problem as people above also have.

Lua Script Error: [CreatureScript Interface]
data/creaturescripts/scripts/attributes.lua:eek:nHealthChange
data/creaturescripts/scripts/attributes.lua:418: attempt to call global 'doTargetCombatCondition' (a nil value)
stack traceback:
[C]: in function 'doTargetCombatCondition'
data/creaturescripts/scripts/attributes.lua:418: in function 'statChange'
data/creaturescripts/scripts/attributes.lua:685: in function <data/creaturescripts/scripts/attributes.lua:682>

tfs 1.5 772 downgrade
ive got the same problem, share how you fix that
 
After my second try I managed to get it to work on a downgraded TFS, monsters weren't dropping loot at first, and had to double check the commits that I pushed, forgot the very first edit... it is working flawlessly now and will play around with it for sure!

Merci!
 
After my second try I managed to get it to work on a downgraded TFS, monsters weren't dropping loot at first, and had to double check the commits that I pushed, forgot the very first edit... it is working flawlessly now and will play around with it for sure!

Merci!
This system works flawless ;D
 
Here are the 10.94+ files for the latest version of TFS.
It uses the native Crit and Leech system.

Here is a branch you can simply merge:
Comparison can be found here.


Alternatively, follow the instructions below if you want to install it manually:

You need these commits/changes:
1) Leech fix (If you don't have 👇 your leech amounts will be all messed up)
2) onInventoryUpdate()
3) onSpawn()

I managed to get it to work partially for the canary repository, but I still don't have a solution for the correct update of my statuses with the assigned ones that were assigned to the item. I'll include a video here for a better understanding of what happens during the update, in case someone wants to help fix it. Also, here is the step-by-step guide on how to set it up in your canary repository.​

Installation in the canary repository:

scripts/eventcallbacks/monster/ondroploot__base.lua

add to the top of the file:
LUA:
local rare_popup = true
local rare_effect = true
local rare_effect_id = 56
-- local roll_drop_effect = 56
-- Custom special item drops
local jewelDrops = true
local jewelChance = 75000 -- 2%
local jewelCorpse = {
    [4097] = { -- Demon
        2493, -- Demon Helmet
        2494, -- Demon Armor
        2495, -- Demon Legs
        2400, -- Magic Sword
        2431, -- SCA
        2421, -- Thunder Hammer
        16112,-- Spellbook of Arcana
        8852, -- The Devileye
        8905,  -- Rainbow Shield
        2131  -- Star Amulet
    },
    [5999] = { -- Behemoth
        2503,  -- Dwarven Armor
        2504,  -- Dwarven Legs
        2502   -- Dwarven Helmet
    },
    [6332] = { -- Hellhound
        15406, -- Ornate Chest
        15414, -- Ornate Mace
        15412, -- Ornate Legs
        15644, -- Ornate Crossbow
        15407, -- Depth Lorica
        8905,  -- Rainbow Shield
        22424, -- Master Umbral Spellbook
        12644, -- Shield of Corruption
        12649, -- Blade of Corruption
        7390,  -- Justice Seeker
        7435   -- Impaler
    },
    [8955] = { -- Grim Reaper
        9778,  -- Yalahari Mask
        9776,  -- Yalahari Armor
        7429,  -- Blessed Sceptre
        14327, -- Bronze Ring
        12645  -- Elite Draken Helmet
    },
    [5984] = { -- Dragon Lord
        11118, -- Dragon Scale Boots
        2506,  -- Dragon Scale Helmet
        8886,  -- Molten Plate
    },
    [19963] = {-- Lost Basher
        2503,  -- Dwarven Armor
        2504,  -- Dwarven Legs
        2502,  -- Dwarven Helmet
    },
    [19998] = {-- Lost Thrower
        2503,  -- Dwarven Armor
        2504,  -- Dwarven Legs
        2502,  -- Dwarven Helmet
    },
    [17408] = {-- Enslaved Dwarf
        2503,  -- Dwarven Armor
        2504,  -- Dwarven Legs
        2502,  -- Dwarven Helmet
    },
    [17416] = {-- Lost Berserker
        2503,  -- Dwarven Armor
        2504,  -- Dwarven Legs
        2502,  -- Dwarven Helmet
    },
    [6320] = { -- Destroyer
        2503,  -- Dwarven Armor
        2504,  -- Dwarven Legs
        2502,  -- Dwarven Helmet
        7455,  -- Mythril Axe
        7390,  -- Justice Seeker
        8888   -- MAA
    },
    [6324] = { -- Hellfire Fighter
        18409, -- Wand of Everblazing
        8925,  -- Solar Axe
        7417,  -- Runed Sword
        8927,  -- Dark Trinity Mace
        8905,  -- Rainbow Shield
        12647, -- Snakegod's Wristguard
        8881   -- Fireborn
    },
    [6336] = { -- Juggernaut
        2522,  -- Great Shield
        21693, -- Horn
        8882,  -- Earthborn
        8930,  -- Emerald Sword
        8929,  -- Stomper
        8932,  -- The Calamity
        7405,  -- Havoc
        2415   -- Great Axe
    },
    [10524] = { -- Medusa
        8869,   -- Greenwood Coat
        2537,   -- Amazon Shield
        5803    -- Arbalest
    },
    [8951] = { -- Bog Raider
        21706, -- Goo Shell
        23528  -- Glooth Cape
    },
    [6532] = { -- Defiler
        21706  -- Goo Shell
    },
    [6061] = { -- Serpent Spawn
        12642, -- Royal Draken Mail
        12643, -- Royal Scale Robe
        8851   -- Royal Crossbow
    },
    [6012] = { -- Elf Scout
        2505   -- Elven Mail
    },
    [6011] = { -- Elf Arcanist
        2505   -- Elven Mail
    },
    [6028] = { -- Lich
        7429,  -- Blessed Sceptre
        7730   -- Blue Legs
    },
    [15354] = { -- Kollos
        8883,   -- Windborn
        16111,  -- Thorn Spitter
        15413   -- Ornate Shield
    },
    [15296] = { -- Spidris
        11374,  -- Beetle Necklace
        16111   -- Thorn Spitter
    },
    [20455] = { -- Necromancer
        6433,   -- Necromancer Shield
        7429    -- Blessed Sceptre
    },
    [9923] = { -- Hellspawn
        12607, -- Elite Draken Mail
        7390,  -- Justice Seeker
        21693, -- Horn
        7433   -- Ravenwing
    },
    [6328] = { -- Dark Torturer
        12607, -- Elite Draken Mail
        12644, -- Shield of Corruption
        12649, -- Blade of Corruption
        8924,  -- Hellforged Axe
        8927,  -- Dark Trinity Mace
        21693, -- Horn
        7453,  -- Executioner
        6391,  -- Nightmare Shield
        2415   -- Great Axe
    },
    [6048] = { -- Hydra
        2424,  -- Silver Mace
        14327, -- Bronze Ring
        11305, -- Drakinata
        7411,  -- Ornamented Axe
        7384,  -- Mystic Blade
        2508   -- Native Armor
    },
    [20527] = { -- Warlock
        2542,   -- Tempest Shield
        7410,   -- Queen's Sceptre
        2662    -- Magician Hat
    },
    [20415] = { -- Hero
        8885,   -- Divine Plate
        11302,  -- Zaoan Helmet
        7384,   -- Mystic Blade
        2424,   -- Silver Mace
        14327,  -- Bronze Ring
        2508    -- Native Armor
    }
}
[/CÓDIGO]


add below:
[CODE=lua]
    local lootTable = mType:generateLootRoll({ factor = factor, gut = gut }, {})
    corpse:addLoot(lootTable)
Copy the text:
LUA:
    -- Apply rarity chance to corpse contents and apply animation
    if rollRarity(corpse) > 0 then -- If a rare item was rolled, play animation
        if rare_popup then
            local spectators = Game.getSpectators(corpse:getPosition(), false, true, 7, 7, 5, 5)
                for i = 1, #spectators do
                    spectators[i]:say(rare_text, TALKTYPE_MONSTER_SAY, false, spectators[i], corpse:getPosition())
                end
        end
        if rare_effect then
            corpse:getPosition():sendMagicEffect(rare_effect_id)
            corpse:getPosition():sendMagicEffect(57)
        end
        if jewelCorpse[corpse:getId()] then
            if math.random(50,50) == 1 then -- 1/50 = 2%
                local jewelCase = corpse:addItem(6104, 1)
            if jewelCase then
                local jewelItem = jewelCase:addItem(jewelCorpse[corpse:getId()][math.random(1,#jewelCorpse[corpse:getId()])], 1)
            if checkrollable(jewelItem) then
                rollItems(jewelItem, true) -- Force roll a rarity
            end
                jewel = 1
            end
        end
    end
end

events/scripts/player.lua
add at the end:
LUA:
function Player:onInventoryUpdate(item, slot, equip)
    itemAttributes(self, item, slot, equip)
end

libs/libs.lua
Paste the text:
LUA:
-- rollAtributos
dofile(CORE_DIRECTORY .. "/libs/core/attributes.lua")


scripts/creaturescripts/login.lua
add below:
LUA:
-- Activate Custom Item Attributes
for i = 1,10 do -- CONST_SLOT_FIRST,CONST_SLOT_LAST
    local item = player:getSlotItem(i)
    if item then
        itemAttributes(player, item, i, true)
    end
end
-- If player logged with more 'current health' than their db 'max health' due to an item attribute
local query = db.storeQuery("SELECT `health`,`mana` FROM players where `id`="..player:getGuid())
if query then
    local health = tonumber(result.getDataString(query, 'health'))
    local mana = tonumber(result.getDataString(query, 'mana'))
    local playerHealth = player:getHealth()
    local playerMana = player:getMana()
    if playerHealth < health then
        player:addHealth(health - playerHealth)
    end
    if playerMana < mana then
        player:addMana(mana - playerMana)
    end
    result.free(query)
end

scripts/creaturescripts/login_events.lua
add below:
Code:
        "rollHealth",
        "rollMana",

video of the status update error:
 

Attachments

Back
Top