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

Lua Xikini's Free Scripting Service TFS 1.4.2

Xikini

I whore myself out for likes
Senator
Premium User
Joined
Nov 17, 2010
Messages
6,811
Solutions
582
Reaction score
5,370
Request whatever you want, within reason.

Please do not request for things that require source editing or database queries.

------------------------------------
If I've reacted to your post, it means I've read it. 👍😍🤣😲🙁😡🤔😉

------------------------------------
Completed Requests

A boss that randomly creates effects on tiles, that when stepped on, gives the player increased damage/mitigation to that boss.
Kill monster and gain X% extra loot chance or Y% extra experience for Z minutes
A pack of 6 useful simple scripts.
-> (1) Simple quest npc
-> (2,3,4,5) use levers in specific order / stand with 4 players / use 4 objects / place items -> to open wall
-> (6) use lever to add/remove/replace objects
Wave type spell, with multiple effects
-> Same spell, but with default combat system
House market system. (owner places price on blackboard and object on the ground, other players buy with a lever)
Respawn System (closest anchor (like darks souls bonfire) / tavern / temple)
Vocation Death Protection (protect the noobs!)
Spell that shows area it will damage, before it strikes.
RAID SYSTEM - rebuilt in Lua, with some more features.
Modal Window - Teleport Item with saving/deleting of positions
Show top 3 Online Players (outfit, name, level) (as monsters, in set positions)
onLook function showing kill count of player.
Modal Window - Use Item -> choose reward.
Talkaction - !backpacks - to buy backpacks (or single items) anywhere. uses bank & current money on players
Quest/Event? Turn a bunch of objects with a monster, spawn portal.
Spawn Monsters, after they've all been killed, give global increased experience/loot in specific area's
Evolving Weapons - Kill X amount of specific creatures, evolve weapon and gain extra damage to those creatures.
Random Portals spawn at XX:XX time(s). (can exit 'off' portals, if you have the storage.)
Monster that adjusts speed based on target
Monster that increases damage output based on # of players nearby
Experience recovery Item. Die -> Use Item -> gain % of lost experience
Character Snapshot - Keeps track of all skills & level, for resetting later.
Fire Dagger - Physical Damage Melee Weapon, with % added damage
Players in specific level ranges don't lose skills/loot/experience, when they die.
Multiclient Limit Check - with admin account not being counted towards limit
Capacity Increasing Items
Upgradeable Protection Amulet - 10% to all elements
-> upgrade amulet, but for all items.
onKill - give reward to all players who dealt damage
-> example: give reward based on damage contribution
Quest Book - Record your quest progress into a book.
Stat System, using modal windows
Holy Tible (POI) - Require Item to use teleport tiles
Item Upgrade System
Skill Stages
-> individual stages for each skill type
-> talkaction to check rates (by @Extrodus)
Random Reward Item - gives different rewards based on vocation
Bounty Hunter System
NPC & Player Walk System (Follow Nodes to destination)
Health/Mana gain permanent - limited use items

------------------------------------
Support

If you have an issue with one of my scripts, I will attempt to help you, but not in this thread.
Make a thread in the support board.
Ensure to follow all rules of the support board.
Without all necessary information it's impossible to help you.

------------------------------------
I will only be scripting for TFS 1.4.2

Not TFS 1.1 / 1.2
Not OTServBR / OTX
and certainly not TFS 0.4

When requesting a script, don't ask for "this script I saw on super popular OT".

I don't care where the idea came from.
I don't want to see a video of the script in action.

Just describe what the script is supposed to do, and I'll try to make it.

Any script that I make in response to a request from this thread will be shared publicly, here, in this thread.

I'm not going to make anything in private, so post your request in this thread only.
Please, for the love of god, don't pm me asking to make a script.
I will actually add you to my ignore list if you do that.
--------------

Anyways!

Thanks for coming by and checking the thread out.
If you think there is a better way to script something, feel free to let me know.
I'm here to learn.

Cheers,

Xikini
---------

P.S.
I've been doing free scripting service's on/off for awhile.
And if you want to see the previous threads, go check them here.

 
Last edited by a moderator:
A script so that when the item is equipped it adds 1000 points to the total capacity, but when the item is unequipped the capacity that the added item has is removed

bandicam2024-02-1111-08-41-875-ezgif.com-video-to-gif-converter(1).gif

data/scripts/capacityIncreaserItems.lua
Lua:
local config = {
    [2643] = { -- leather boots
        capacityIncrease = 209, -- 200 increase + 9 for weight of boots
        slot = "feet" -- ("head", "necklace", "backpack", "armor", "hand", "legs", "feet", "ring", "ammo")
    },
    [10522] = { -- crown backpack
        capacityIncrease = 1017, -- 1000 increase + 17 for weight of backpack
        slot = "backpack"
    }
}

-- END OF CONFIG

local startingLevelofVocations = 8 -- only edit this if you have a non-vanilla setup
local baseCapacity = 400

local function calculateTotalCapacity(player)   
    local playerLevel = player:getLevel()
    local newCapacity = baseCapacity * 100
    if playerLevel <= startingLevelofVocations then
        newCapacity = newCapacity + (Vocation(0):getCapacityGain() * (playerLevel - 1))
    else
        newCapacity = newCapacity + (Vocation(0):getCapacityGain() * (startingLevelofVocations - 1))
    end
    if playerLevel > startingLevelofVocations then
        newCapacity = newCapacity + (player:getVocation():getCapacityGain() * (player:getLevel() - startingLevelofVocations))
    end

    for i = 1, 10 do
        local slotItem = player:getSlotItem(i)
        if slotItem then
            local index = config[slotItem:getId()]
            if index then
                newCapacity = newCapacity + (index.capacityIncrease * 100)
            end
        end
    end   

    if player:getCapacity() ~= newCapacity then
        player:setCapacity(newCapacity)
    end
end

for itemId, v in pairs(config) do

    local moveevent = MoveEvent()
   
    function moveevent.onEquip(player, item, slot, isCheck)
        if not isCheck then
            calculateTotalCapacity(player)
        end
        return true
    end
   
    moveevent:slot(v.slot)
    moveevent:id(itemId)
       
    moveevent:register()
   
   
    local moveevent = MoveEvent()

    function moveevent.onDeEquip(player, item, slot, isCheck)
        if not isCheck then
            calculateTotalCapacity(player)
        end
        return true
    end
   
    moveevent:slot(v.slot)
    moveevent:id(itemId)
       
    moveevent:register()
end


local creatureevent = CreatureEvent("onLogin_capacityIncreaserItems")

function creatureevent.onLogin(player)
    calculateTotalCapacity(player)
    return true
end

creatureevent:register()
 
Last edited:
all players join a room like this where they have the same speed and can't diagonal movement only south, north, east, west they use !bomb to place a bomb that exploud with 1x1 and kill every player in the explosion area, the green grass is destroyable using these explosions but not the black grass ones.when you exploud the green grass you find orbs below that gives speed, makes your explosion bigger or faster (it takes 3 seconds at the begin with 1x1 area) until 1 player left then he wins the event. you can't use haste spells, magic walls, rush woods or push players.
This is bomberman event and you can already find The script by searching for it.

Edit: Action - [1.3] Bomberman 💣💥 (https://otland.net/threads/1-3-bomberman.275894/#post-2655270)


Works for 1.4 also for servers 10.98
 
So, I went into way too much detail for this, cuz I wanted it to be fairly accurate. xD

View attachment 82022

data/scripts/fireDagger.lua
Lua:
local fireDaggerId = 2418
local fire_percent = 5
local fire_damage = {}


local weapon = Weapon(WEAPON_SWORD)

local combat = Combat()
combat:setParameter(COMBAT_PARAM_TYPE, COMBAT_PHYSICALDAMAGE)

function onGetFormulaValues(player, skill, attack, factor)
    local min = 0
    local max = getMaxWeaponDamage(player:getLevel(), skill, (attack * GLOBAL_vocationMultipliers[player:getVocation():getId()].meleeDamage), factor)
    local damage = normal_random_range(min, max)
    fire_damage[player:getId()] = math.floor(((damage / 100) * fire_percent) + 0.5)
    damage = player:getTarget():calculateDamageAfterArmorandDefence(damage)
    return -damage, -damage
end

combat:setCallback(CALLBACK_PARAM_SKILLVALUE, "onGetFormulaValues")


local combat_fire = Combat()
combat_fire:setParameter(COMBAT_PARAM_TYPE, COMBAT_FIREDAMAGE)

function onGetFormulaValues(player, skill, attack, factor)
    local fireDamage = fire_damage[player:getId()]
    fire_damage[player:getId()] = nil
    return -fireDamage, -fireDamage
end

combat_fire:setCallback(CALLBACK_PARAM_SKILLVALUE, "onGetFormulaValues")


function weapon.onUseWeapon(player, variant)
    if player:getSkull() == SKULL_BLACK then
        return false
    end

    combat:execute(player, variant)
    combat_fire:execute(player, variant)
    return true
end

weapon:id(fireDaggerId)
weapon:register()

data/lib/core/core.lua -- add
Lua:
dofile('data/lib/core/xikiniCustomFunctions.lua')
data/lib/core/xikiniCustomFunctions.lua -- add
Lua:
-- Xikini's Shitty™ Weapon Handling for Physical Melee Weapons

function parseFormulaAttributes(xmlContent)
    local formulas = {}
    -- Pattern to match the <formula> element and extract its attributes
    local pattern = "<formula%s+meleeDamage=\"(.-)\"%s+distDamage=\"(.-)\"%s+defense=\"(.-)\"%s+armor=\"(.-)\"%s*/>"
 
    for meleeDamage, distDamage, defense, armor in xmlContent:gmatch(pattern) do
        table.insert(formulas, {
            meleeDamage = meleeDamage,
            distDamage = distDamage,
            defense = defense,
            armor = armor
        })
    end

    return formulas
end

-- Function to read the XML content from a file
function readXmlFile(filePath)
    local file = io.open(filePath, "r")
    if not file then
        error("Cannot open file: " .. filePath)
        return nil
    end
    local content = file:read("*all")
    file:close()
    return content
end

local filePath = "data/XML/vocations.xml"
local xmlContent = readXmlFile(filePath)
GLOBAL_vocationMultipliers = parseFormulaAttributes(xmlContent)


weaponTypesToSkillType = {
    [WEAPON_SWORD] = SKILL_SWORD,
    [WEAPON_CLUB] = SKILL_CLUB,
    [WEAPON_AXE] = SKILL_AXE
}


function Creature.getDefense(self)
    -- shield and melee weapon
    local defense = 0
 
    if self:isMonster() then
        defense = self:getType():defense()
     
    elseif self:isPlayer() then
        -- if no weapon or shield do fist fighting
        local defenseSkill = self:getSkillLevel(SKILL_FIST)
        local defenseValue = 7;
     
        local weapon = self:getSlotItem(CONST_SLOT_LEFT)
        local weaponDefense = 0
        local weaponExtraDefense = 0
     
        local shield = self:getSlotItem(CONST_SLOT_RIGHT)
        local shieldDefense = 0
 
        if weapon then
            local weaponItemType = ItemType(weapon:getId())
         
            if weapon:hasAttribute(ITEM_ATTRIBUTE_DEFENSE) then
                weaponDefense = weapon:getAttribute(ITEM_ATTRIBUTE_DEFENSE)
            else
                weaponDefense = weaponItemType:getDefense()
            end
            if weapon:hasAttribute(ITEM_ATTRIBUTE_EXTRADEFENSE) then
                weaponExtraDefense = weapon:getAttribute(ITEM_ATTRIBUTE_EXTRADEFENSE)
            else
                weaponExtraDefense = weaponItemType:getExtraDefense()
            end
         
            defenseValue = weaponDefense + weaponExtraDefense
            local skillType = weaponTypesToSkillType[weaponItemType:getWeaponType()]
            defenseSkill = skillType and self:getSkillLevel(skillType) or 0
        end
 
        if shield then
            local shieldItemType = ItemType(shield:getId())
         
            if shield:hasAttribute(ITEM_ATTRIBUTE_DEFENSE) then
                shieldDefense = shield:getAttribute(ITEM_ATTRIBUTE_DEFENSE)
            else
                shieldDefense = shieldItemType:getDefense()
            end
     
            defenseValue = weapon and shieldDefense + weaponExtraDefense or shieldDefense
            defenseSkill = self:getSkillLevel(SKILL_SHIELD)
        end
     
        if defenseSkill == 0 then
            if self:getFightMode() == FIGHTMODE_DEFENSE then
                return 2
            else
                return 1
            end
        end
     
        defense = (defenseSkill / 4. + 2.23) * defenseValue * 0.15 * GLOBAL_vocationMultipliers[self:getVocation():getId()].defense
    end
 
    return defense
end

function Creature.getArmor(self)
    local armor = 0
 
    if self:isMonster() then
        armor = self:getType():armor()

    elseif self:isPlayer() then
        -- loop through equipment, finding armor and adding together
        for slotItem = 1, 10 do
            if slotItem ~= CONST_SLOT_LEFT and slotItem ~= CONST_SLOT_RIGHT then
                local item = self:getSlotItem(slotItem)
                if item then
                    if item:hasAttribute(ITEM_ATTRIBUTE_ARMOR) then
                        armor = armor + item:getAttribute(ITEM_ATTRIBUTE_ARMOR)
                    else
                        armor = armor + ItemType(item:getId()):getArmor()
                    end
                end
            end
        end
 
    end
 
    return armor
end

function Creature.calculateDamageAfterArmorandDefence(self, damage)
    local checkArmor = true
 
    local defense = self:getDefense()
    damage = damage - (math.random(defense / 2, defense))
    if damage <= 0 then
        damage = 0
        checkArmor = false
    end

    if checkArmor then
        armor = math.max(self:getArmor(), 1)
        damage = damage - (math.random(armor / 2, armor - (armor % 2 + 1)))
    end
 
    return math.floor(damage + 0.5)
end

function normal_random(mean, std_dev)
    local u1 = math.random()
    local u2 = math.random()
    local z0 = math.sqrt(-2.0 * math.log(u1)) * math.cos(2.0 * math.pi * u2)
    -- Use z0 for the normal random number (z1 would be the second number, not used here)
    return z0 * std_dev + mean
end

-- Function to generate a random integer within a range based on a normal distribution
function normal_random_range(minNumber, maxNumber)
    local mean = 0.5
    local std_dev = 0.25
    local v
    repeat
        v = normal_random(mean, std_dev)
    until v >= 0.0 and v <= 1.0

    local a, b = math.min(minNumber, maxNumber), math.max(minNumber, maxNumber)
    return math.floor(a + (b - a) * v + 0.5) -- Using floor(x + 0.5) to round to the nearest integer
end

function getMaxWeaponDamage(playerLevel, skillLevel, attackValue, attackFactor)
    return math.ceil((playerLevel / 5) + (((((skillLevel / 4.) + 1) * (attackValue / 3.)) * 1.03) / attackFactor))
end
Working fantastic however i have only 1 bug, if the monster blocks the hit it doesnt show the blocking/missing animation. its does nothing :p
 
Last edited:
View attachment 82028

data/scripts/capacityIncreaserItems.lua
Lua:
local config = {
    [2643] = { -- leather boots
        capacityIncrease = 209, -- 200 increase + 9 for weight of boots
        slot = "feet" -- ("head", "necklace", "backpack", "armor", "hand", "legs", "feet", "ring", "ammo")
    },
    [10522] = { -- crown backpack
        capacityIncrease = 1017, -- 1000 increase + 17 for weight of backpack
        slot = "backpack"
    }
}

-- END OF CONFIG

local startingLevelofVocations = 8 -- only edit this if you have a non-vanilla setup
local baseCapacity = 400

local function calculateTotalCapacity(player) 
    local playerLevel = player:getLevel()
    local newCapacity = baseCapacity * 100
    if playerLevel <= startingLevelofVocations then
        newCapacity = newCapacity + (Vocation(0):getCapacityGain() * (playerLevel - 1))
    else
        newCapacity = newCapacity + (Vocation(0):getCapacityGain() * (startingLevelofVocations - 1))
    end
    if playerLevel > startingLevelofVocations then
        newCapacity = newCapacity + (player:getVocation():getCapacityGain() * (player:getLevel() - startingLevelofVocations))
    end

    for i = 1, 10 do
        local slotItem = player:getSlotItem(i)
        if slotItem then
            local index = config[slotItem:getId()]
            if index then
                newCapacity = newCapacity + (index.capacityIncrease * 100)
            end
        end
    end 

    if player:getCapacity() ~= newCapacity then
        player:setCapacity(newCapacity)
    end
end

for itemId, v in pairs(config) do

    local moveevent = MoveEvent()
 
    function moveevent.onEquip(player, item, slot, isCheck)
        if not isCheck then
            calculateTotalCapacity(player)
        end
        return true
    end
 
    moveevent:slot(v.slot)
    moveevent:id(itemId)
     
    moveevent:register()
 
 
    local moveevent = MoveEvent()

    function moveevent.onDeEquip(player, item, slot, isCheck)
        if not isCheck then
            calculateTotalCapacity(player)
        end
        return true
    end
 
    moveevent:slot(v.slot)
    moveevent:id(itemId)
     
    moveevent:register()
end
Considering that this is onEquip / onDeEquip event what will happen if the player looses the backpack dying? It will still update the capacity of the player once that it spawns again? I also tested it and doesn't add the capacity onLogin, so everytime I log out and log in again it doesn't update the capacity unless I deEquip/Equip it again. ^^
 
Considering that this is onEquip / onDeEquip event what will happen if the player looses the backpack dying? It will still update the capacity of the player once that it spawns again? I also tested it and doesn't add the capacity onLogin, so everytime I log out and log in again it doesn't update the capacity unless I deEquip/Equip it again. ^^
haha during testing I had a login function to trigger, and never thought of the onDeath scenario.

I'll add the login back in.
 
can i ask ask for a fix?
this event is not working properly i know that there's a lot of people wanting to use this

thanks in advance
 
Working fantastic however i have only 1 bug, if the monster blocks the hit it doesnt show the blocking/missing animation. its does nothing :p
I've edited quite a few things to get it to work. xD

Copy everything again.

bandicam2024-02-1303-34-29-575-ezgif.com-video-to-gif-converter.gif
Post automatically merged:

can you do this
i need 1 script to make a monster keep turning east, west, south, north auto every 5 seconds and make another monster look to south always and never change direction
Soo here's the thing..

monster that looks east/west/south/north
monster that looks south always and never changes direction

In both these scenario's, the monster auto-looking in a player direction and while walking, would have the animation of looking in a different direction.

If the monsters cannot be moved, and non-hostile.. it might work?
I'll give it a try, but no promises. lol
Post automatically merged:

can i ask ask for a fix?
this event is not working properly i know that there's a lot of people wanting to use this

thanks in advance
support board.
 
Last edited:
I've edited quite a few things to get it to work. xD

Copy everything again.

View attachment 82072
Post automatically merged:


Soo here's the thing..

monster that looks east/west/south/north
monster that looks south always and never changes direction

In both these scenario's, the monster auto-looking in a player direction and while walking, would have the animation of looking in a different direction.

If the monsters cannot be moved, and non-hostile.. it might work?
I'll give it a try, but no promises. lol
Post automatically merged:


support board.
Amazing, ill try it soon again maybe I can find more haha.
 
Soo here's the thing..

monster that looks east/west/south/north
monster that looks south always and never changes direction

In both these scenario's, the monster auto-looking in a player direction and while walking, would have the animation of looking in a different direction.

If the monsters cannot be moved, and non-hostile.. it might work?
I'll give it a try, but no promises. lol
monsters can't be moved and 1 of them is hostile but one isn't
 
hey man,

i am wondering if you could make a rev script with this function:

there is an amulet (xxxx) id, when you use (x) id item on this amulet it gains stats.

there should be 6 diffrent stones 1 for each element (fire, earth, ice, energy, death and holy) each stone should give 0.5% if thats possible else 1% stats to this amulet stacking up to max 10% protection.

if rev script isnt possible then other things could work aswell.

thx in advance! :)

As requested, can put every element up to 10%.

bandicam2024-02-1307-40-19-501-ezgif.com-video-to-gif-converter.gif

data/scripts/delikeramRequest.lua
Lua:
local amuletItemId = 2173
local maximumUpgradePercent = 10

local protectionItems = {
--    [1111] = {protectionType = "physical", percent = 0.5},
    [8303] = {protectionType = "energy", percent = 0.5},
--    [1111] = {protectionType = "earth", percent = 0.5},
--    [1111] = {protectionType = "fire", percent = 0.5},
    [8302] = {protectionType = "ice", percent = 0.5},
--    [1111] = {protectionType = "holy", percent = 0.5},
--    [1111] = {protectionType = "death", percent = 0.5}
}

-- END OF CONFIG

local protectionTypes = {
    ["physical"] = COMBAT_PHYSICALDAMAGE,
    ["energy"] = COMBAT_ENERGYDAMAGE,
    ["earth"] = COMBAT_EARTHDAMAGE,
    ["fire"] = COMBAT_FIREDAMAGE,
    ["ice"] = COMBAT_ICEDAMAGE,
    ["holy"] = COMBAT_HOLYDAMAGE,
    ["death"] = COMBAT_DEATHDAMAGE
}

local combatTypes = {
    [COMBAT_PHYSICALDAMAGE] = "physical",
    [COMBAT_ENERGYDAMAGE] = "energy",
    [COMBAT_EARTHDAMAGE] = "earth",
    [COMBAT_FIREDAMAGE] = "fire",
    [COMBAT_ICEDAMAGE] = "ice",
    [COMBAT_HOLYDAMAGE] = "holy",
    [COMBAT_DEATHDAMAGE] = "death"
}


local function setProtectionDescription(item)
    local text = ""
    local isMaxUpgraded = true
    local order = {"physical", "energy", "earth", "fire", "ice", "holy", "death"}
    for _, element in ipairs(order) do
        local attributeValue = item:getCustomAttribute(element) or 0
        if attributeValue > 0 then
            if text ~= "" then
                text = text .. ", "
            end
            text = text .. element .. " +" .. attributeValue .. "%"
        end
        if attributeValue ~= maximumUpgradePercent then
            isMaxUpgraded = false
        end
    end
    if isMaxUpgraded then
        text = "[Additional Protections: All Damage Types +" .. maximumUpgradePercent .. "%]"
    else
        text = "[Additional Protections: " .. text .. "]"
    end
    item:setAttribute(ITEM_ATTRIBUTE_DESCRIPTION, text)
end

local action = Action()

function action.onUse(player, item, fromPosition, target, toPosition, isHotkey)
    if not target:isItem() then
        player:getPosition():sendMagicEffect(CONST_ME_POFF)
        return true
    end
    if target:getId() ~= amuletItemId then
        target:getPosition():sendMagicEffect(CONST_ME_POFF)
        return true
    end
    
    local itemId = item:getId()
    local attributeValue = target:getCustomAttribute(protectionItems[itemId].protectionType) or 0
    
    if attributeValue >= maximumUpgradePercent then
        target:getPosition():sendMagicEffect(CONST_ME_MAGIC_RED)
        return true
    end
    
    target:setCustomAttribute(protectionItems[itemId].protectionType, math.min(attributeValue + protectionItems[itemId].percent, maximumUpgradePercent))
    target:getPosition():sendMagicEffect(CONST_ME_MAGIC_GREEN)
    setProtectionDescription(target)
    item:remove(1)
    return true
end

for itemId, _ in pairs(protectionItems) do
    action:id(itemId)
end
action:register()


local function damageCalculator(player, primaryDamage, primaryType, secondaryDamage, secondaryType)
    local slotItem = player:getSlotItem(CONST_SLOT_NECKLACE)
    if slotItem then
        if combatTypes[primaryType] then
            local reductionPecent = slotItem:getCustomAttribute(combatTypes[primaryType]) or 0
            if reductionPecent > 0 then
                primaryDamage = primaryDamage - (primaryDamage * (reductionPecent / 100))
            end
        end
        if combatTypes[secondaryType] then
            local reductionPecent = slotItem:getCustomAttribute(combatTypes[secondaryType]) or 0
            if reductionPecent > 0 then
                secondaryDamage = secondaryDamage - (secondaryDamage * (reductionPecent / 100))
            end
        end
    end
    return primaryDamage, secondaryDamage
end


local healthChange = CreatureEvent("onHealthChange_protectionAmulet")

function healthChange.onHealthChange(creature, attacker, primaryDamage, primaryType, secondaryDamage, secondaryType, origin)
    primaryDamage, secondaryDamage = damageCalculator(creature, primaryDamage, primaryType, secondaryDamage, secondaryType)
    return primaryDamage, primaryType, secondaryDamage, secondaryType
end

healthChange:register()


local manaChange = CreatureEvent("onManaChange_protectionAmulet")

function manaChange.onManaChange(creature, attacker, primaryDamage, primaryType, secondaryDamage, secondaryType, origin)
    primaryDamage, secondaryDamage = damageCalculator(creature, primaryDamage, primaryType, secondaryDamage, secondaryType)
    return primaryDamage, primaryType, secondaryDamage, secondaryType
end

manaChange:register()


local creatureevent = CreatureEvent("example")

function creatureevent.onLogin(player)
    player:registerEvent("onHealthChange_protectionAmulet")
    player:registerEvent("onManaChange_protectionAmulet")
    return true
end

creatureevent:register()
 
As requested, can put every element up to 10%.

View attachment 82075

data/scripts/delikeramRequest.lua
Lua:
local amuletItemId = 2173
local maximumUpgradePercent = 10

local protectionItems = {
--    [1111] = {protectionType = "physical", percent = 0.5},
    [8303] = {protectionType = "energy", percent = 0.5},
--    [1111] = {protectionType = "earth", percent = 0.5},
--    [1111] = {protectionType = "fire", percent = 0.5},
    [8302] = {protectionType = "ice", percent = 0.5},
--    [1111] = {protectionType = "holy", percent = 0.5},
--    [1111] = {protectionType = "death", percent = 0.5}
}

-- END OF CONFIG

local protectionTypes = {
    ["physical"] = COMBAT_PHYSICALDAMAGE,
    ["energy"] = COMBAT_ENERGYDAMAGE,
    ["earth"] = COMBAT_EARTHDAMAGE,
    ["fire"] = COMBAT_FIREDAMAGE,
    ["ice"] = COMBAT_ICEDAMAGE,
    ["holy"] = COMBAT_HOLYDAMAGE,
    ["death"] = COMBAT_DEATHDAMAGE
}

local combatTypes = {
    [COMBAT_PHYSICALDAMAGE] = "physical",
    [COMBAT_ENERGYDAMAGE] = "energy",
    [COMBAT_EARTHDAMAGE] = "earth",
    [COMBAT_FIREDAMAGE] = "fire",
    [COMBAT_ICEDAMAGE] = "ice",
    [COMBAT_HOLYDAMAGE] = "holy",
    [COMBAT_DEATHDAMAGE] = "death"
}


local function setProtectionDescription(item)
    local text = ""
    local isMaxUpgraded = true
    local order = {"physical", "energy", "earth", "fire", "ice", "holy", "death"}
    for _, element in ipairs(order) do
        local attributeValue = item:getCustomAttribute(element) or 0
        if attributeValue > 0 then
            if text ~= "" then
                text = text .. ", "
            end
            text = text .. element .. " +" .. attributeValue .. "%"
        end
        if attributeValue ~= maximumUpgradePercent then
            isMaxUpgraded = false
        end
    end
    if isMaxUpgraded then
        text = "[Additional Protections: All Damage Types +" .. maximumUpgradePercent .. "%]"
    else
        text = "[Additional Protections: " .. text .. "]"
    end
    item:setAttribute(ITEM_ATTRIBUTE_DESCRIPTION, text)
end

local action = Action()

function action.onUse(player, item, fromPosition, target, toPosition, isHotkey)
    if not target:isItem() then
        player:getPosition():sendMagicEffect(CONST_ME_POFF)
        return true
    end
    if target:getId() ~= amuletItemId then
        target:getPosition():sendMagicEffect(CONST_ME_POFF)
        return true
    end
   
    local itemId = item:getId()
    local attributeValue = target:getCustomAttribute(protectionItems[itemId].protectionType) or 0
   
    if attributeValue >= maximumUpgradePercent then
        target:getPosition():sendMagicEffect(CONST_ME_MAGIC_RED)
        return true
    end
   
    target:setCustomAttribute(protectionItems[itemId].protectionType, math.min(attributeValue + protectionItems[itemId].percent, maximumUpgradePercent))
    target:getPosition():sendMagicEffect(CONST_ME_MAGIC_GREEN)
    setProtectionDescription(target)
    item:remove(1)
    return true
end

for itemId, _ in pairs(protectionItems) do
    action:id(itemId)
end
action:register()


local function damageCalculator(player, primaryDamage, primaryType, secondaryDamage, secondaryType)
    local slotItem = player:getSlotItem(CONST_SLOT_NECKLACE)
    if slotItem then
        if combatTypes[primaryType] then
            local reductionPecent = slotItem:getCustomAttribute(combatTypes[primaryType]) or 0
            if reductionPecent > 0 then
                primaryDamage = primaryDamage - (primaryDamage * (reductionPecent / 100))
            end
        end
        if combatTypes[secondaryType] then
            local reductionPecent = slotItem:getCustomAttribute(combatTypes[secondaryType]) or 0
            if reductionPecent > 0 then
                secondaryDamage = secondaryDamage - (secondaryDamage * (reductionPecent / 100))
            end
        end
    end
    return primaryDamage, secondaryDamage
end


local healthChange = CreatureEvent("onHealthChange_protectionAmulet")

function healthChange.onHealthChange(creature, attacker, primaryDamage, primaryType, secondaryDamage, secondaryType, origin)
    primaryDamage, secondaryDamage = damageCalculator(creature, primaryDamage, primaryType, secondaryDamage, secondaryType)
    return primaryDamage, primaryType, secondaryDamage, secondaryType
end

healthChange:register()


local manaChange = CreatureEvent("onManaChange_protectionAmulet")

function manaChange.onManaChange(creature, attacker, primaryDamage, primaryType, secondaryDamage, secondaryType, origin)
    primaryDamage, secondaryDamage = damageCalculator(creature, primaryDamage, primaryType, secondaryDamage, secondaryType)
    return primaryDamage, primaryType, secondaryDamage, secondaryType
end

manaChange:register()


local creatureevent = CreatureEvent("example")

function creatureevent.onLogin(player)
    player:registerEvent("onHealthChange_protectionAmulet")
    player:registerEvent("onManaChange_protectionAmulet")
    return true
end

creatureevent:register()
Works perfect! 😂
 
As requested, can put every element up to 10%.

View attachment 82075

data/scripts/delikeramRequest.lua
Lua:
local amuletItemId = 2173
local maximumUpgradePercent = 10

local protectionItems = {
--    [1111] = {protectionType = "physical", percent = 0.5},
    [8303] = {protectionType = "energy", percent = 0.5},
--    [1111] = {protectionType = "earth", percent = 0.5},
--    [1111] = {protectionType = "fire", percent = 0.5},
    [8302] = {protectionType = "ice", percent = 0.5},
--    [1111] = {protectionType = "holy", percent = 0.5},
--    [1111] = {protectionType = "death", percent = 0.5}
}

-- END OF CONFIG

local protectionTypes = {
    ["physical"] = COMBAT_PHYSICALDAMAGE,
    ["energy"] = COMBAT_ENERGYDAMAGE,
    ["earth"] = COMBAT_EARTHDAMAGE,
    ["fire"] = COMBAT_FIREDAMAGE,
    ["ice"] = COMBAT_ICEDAMAGE,
    ["holy"] = COMBAT_HOLYDAMAGE,
    ["death"] = COMBAT_DEATHDAMAGE
}

local combatTypes = {
    [COMBAT_PHYSICALDAMAGE] = "physical",
    [COMBAT_ENERGYDAMAGE] = "energy",
    [COMBAT_EARTHDAMAGE] = "earth",
    [COMBAT_FIREDAMAGE] = "fire",
    [COMBAT_ICEDAMAGE] = "ice",
    [COMBAT_HOLYDAMAGE] = "holy",
    [COMBAT_DEATHDAMAGE] = "death"
}


local function setProtectionDescription(item)
    local text = ""
    local isMaxUpgraded = true
    local order = {"physical", "energy", "earth", "fire", "ice", "holy", "death"}
    for _, element in ipairs(order) do
        local attributeValue = item:getCustomAttribute(element) or 0
        if attributeValue > 0 then
            if text ~= "" then
                text = text .. ", "
            end
            text = text .. element .. " +" .. attributeValue .. "%"
        end
        if attributeValue ~= maximumUpgradePercent then
            isMaxUpgraded = false
        end
    end
    if isMaxUpgraded then
        text = "[Additional Protections: All Damage Types +" .. maximumUpgradePercent .. "%]"
    else
        text = "[Additional Protections: " .. text .. "]"
    end
    item:setAttribute(ITEM_ATTRIBUTE_DESCRIPTION, text)
end

local action = Action()

function action.onUse(player, item, fromPosition, target, toPosition, isHotkey)
    if not target:isItem() then
        player:getPosition():sendMagicEffect(CONST_ME_POFF)
        return true
    end
    if target:getId() ~= amuletItemId then
        target:getPosition():sendMagicEffect(CONST_ME_POFF)
        return true
    end
  
    local itemId = item:getId()
    local attributeValue = target:getCustomAttribute(protectionItems[itemId].protectionType) or 0
  
    if attributeValue >= maximumUpgradePercent then
        target:getPosition():sendMagicEffect(CONST_ME_MAGIC_RED)
        return true
    end
  
    target:setCustomAttribute(protectionItems[itemId].protectionType, math.min(attributeValue + protectionItems[itemId].percent, maximumUpgradePercent))
    target:getPosition():sendMagicEffect(CONST_ME_MAGIC_GREEN)
    setProtectionDescription(target)
    item:remove(1)
    return true
end

for itemId, _ in pairs(protectionItems) do
    action:id(itemId)
end
action:register()


local function damageCalculator(player, primaryDamage, primaryType, secondaryDamage, secondaryType)
    local slotItem = player:getSlotItem(CONST_SLOT_NECKLACE)
    if slotItem then
        if combatTypes[primaryType] then
            local reductionPecent = slotItem:getCustomAttribute(combatTypes[primaryType]) or 0
            if reductionPecent > 0 then
                primaryDamage = primaryDamage - (primaryDamage * (reductionPecent / 100))
            end
        end
        if combatTypes[secondaryType] then
            local reductionPecent = slotItem:getCustomAttribute(combatTypes[secondaryType]) or 0
            if reductionPecent > 0 then
                secondaryDamage = secondaryDamage - (secondaryDamage * (reductionPecent / 100))
            end
        end
    end
    return primaryDamage, secondaryDamage
end


local healthChange = CreatureEvent("onHealthChange_protectionAmulet")

function healthChange.onHealthChange(creature, attacker, primaryDamage, primaryType, secondaryDamage, secondaryType, origin)
    primaryDamage, secondaryDamage = damageCalculator(creature, primaryDamage, primaryType, secondaryDamage, secondaryType)
    return primaryDamage, primaryType, secondaryDamage, secondaryType
end

healthChange:register()


local manaChange = CreatureEvent("onManaChange_protectionAmulet")

function manaChange.onManaChange(creature, attacker, primaryDamage, primaryType, secondaryDamage, secondaryType, origin)
    primaryDamage, secondaryDamage = damageCalculator(creature, primaryDamage, primaryType, secondaryDamage, secondaryType)
    return primaryDamage, primaryType, secondaryDamage, secondaryType
end

manaChange:register()


local creatureevent = CreatureEvent("example")

function creatureevent.onLogin(player)
    player:registerEvent("onHealthChange_protectionAmulet")
    player:registerEvent("onManaChange_protectionAmulet")
    return true
end

creatureevent:register()

It is sweet!

I wonder if could you create alternate version of this script, in which you can set many different items to be upgradeable, not only single amulet. I am thinking about any other equipment part, or maybe even whole group of items (like all shields, or all armors). In such script you would be able to give the item ID's that you want to be upgradeable one by one.

Thanks in advance!
 
Last edited:
Thank you for your last script! @Xikini

Now I am having issues with a specific part of a POI script (known as holy tibe). If possible, I would like to ask for that part to be redone.

How it works: If the player has an item, they can step on a specific SQM; if they don't have the item, they return to the position where they attempted to move. If they have the item, they are teleported to a certain coordinate. The same logic applies to the other side, but obviously, they are teleported to a different coordinate.

I will also provide the last reference script that I tested and did not work for me: canary/data-otservbr-global/scripts/movements/quests/pits_of_inferno/holy_tible_tile.lua at main · opentibiabr/canary (https://github.com/opentibiabr/canary/blob/main/data-otservbr-global/scripts/movements/quests/pits_of_inferno/holy_tible_tile.lua)

Thank you in advance!
 
here goes another one! :p

would be possible to give an item based on damage map? for example I create a monster, "The Mutated Pumpkin", and if it is killed, give a certain item to every player who contributed on killing the creature. let's use crystal coins as example, so it would be nice if it has a local parameter that defines how much is the maxium amount of crystal coins. then if the monster dies, share the reward to each player who contributed on monster's killing proportionally based on maxium amount (of crystal coins in this case) and damage map.

Nimbus bot throw me this, but i'm not sure if it is the best way to do it:
Lua:
function onKill(cid, target)
    local monsterName = "The Mutated Pumpkin" -- Replace with the actual monster name
    local itemID = 2160 -- Replace with the item ID of crystal coins
    local maxCoins = 100 -- Replace with the maximum amount of crystal coins

    if getCreatureName(target) == monsterName then
        local players = getDamageMap(target)
        local totalDamage = 0

        -- Calculate the total damage dealt by all players
        for _, damageInfo in ipairs(players) do
            totalDamage = totalDamage + damageInfo.damage
        end

        -- Distribute the reward to each player based on their damage contribution
        for _, damageInfo in ipairs(players) do
            local player = damageInfo.cid
            local damage = damageInfo.damage
            local coins = math.floor((damage / totalDamage) * maxCoins)

            doPlayerAddItem(player, itemID, coins)
            doPlayerSendTextMessage(player, MESSAGE_EVENT_ADVANCE, "You received " .. coins .. " crystal coins for your contribution!")
        end
    end
end
 
Last edited:
Back
Top