• 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 [TFS 1.3] Free Scripting Service 📝

Status
Not open for further replies.

Sarah Wesker

ƐƖєgαηт Sуηтαx ❤
Staff member
TFS Developer
Support Team
Joined
Mar 16, 2017
Messages
1,407
Solutions
154
Reaction score
1,958
Location
London
GitHub
MillhioreBT
Twitch
millhiorebt
I am bored, and I have some days in which I will not have much to do, if you need a script you can post here what you want and if it meets the requirements below, I will do it for you

🗒 Requirements:
🔶 TFS engine 1.3+
🔶 That does not include changes in the sources (if you don't know what this is, you can still ask💬)
🔶 I'll only do one script per person so don't spam🔇too much, until a second chance ...
🔶 It depends on what you ask, I will make the decision to accept or not to do it👀
🔶 I know that several people have posted threads similar to this one, but to add more variety, also not all can be available at the same time👌

Don't be afraid to ask 🤗

👍 If I like your post it means that I have taken the task! 👍
 
Last edited:
Hi @killer990

data/scripts/yourscriptname.lua
Lua:
local stones = {
      [21402] = {
              minLevel = 0, -- minimum level to use
              maxLevel = 15, -- maximum level to you can use
            chance = 75, -- probability of leveling up
            extraPercent = 0 -- extra attribute increase percentage
      },
      [21403] = {
              minLevel = 15,
            maxLevel = 30,
            chance = 50,
            extraPercent = 1
      },
      [6666] = {
              minLevel = 30,
            maxLevel = 50,
            chance = 25,
            extraPercent = 2
      }
}

local attributes = {
    [ITEM_ATTRIBUTE_ATTACK] = {
        getValue = ItemType.getAttack,
        percent = 5 -- attribute increase percentage in this case for attack
    },
    [ITEM_ATTRIBUTE_DEFENSE] = {
        getValue = ItemType.getDefense,
        percent = 5 -- attribute increase percentage in this case for defense
    },
    [ITEM_ATTRIBUTE_EXTRADEFENSE] = {
        getValue = ItemType.getExtraDefense,
        percent = 5 -- attribute increase percentage in this case for extraDefense
    },
    [ITEM_ATTRIBUTE_ARMOR] = {
        getValue = ItemType.getArmor,
        percent = 5 -- attribute increase percentage in this case for armor
    },
    [ITEM_ATTRIBUTE_HITCHANCE] = {
        getValue = ItemType.getHitChance,
        percent = 5 -- attribute increase percentage in this case for hitChance
    }
}

local function onUpgradeLvl(level, chance, config)
    local nextLevel = math.min(config.maxLevel, level +1)
    if math.random(1, chance) <= config.chance then
        return nextLevel
    end
    return level
end

local function isUpgradeable(item)
    local it = item:getType()
    return it:getAttack() > 0 or it:getDefense() > 0 or it:getArmor() > 0 or it:getExtraDefense() > 0
end

local function getItemLevel(item)
    return item:getCustomAttribute("upgradeLevel") or 0
end

local function setItemLevel(item, level)
    return item:setCustomAttribute("upgradeLevel", level)
end

local function upgradeValue(value, level, info, stone)
    return value * ((1.0 + ((info.percent + stone.extraPercent) / 100)) * level)
end

local function doUpgrade(item, level, stone)
    local itemType = item:getType()
    if level <= 0 then
        setItemLevel(item, level)
        item:setAttribute(ITEM_ATTRIBUTE_NAME, itemType:getName())
        for attribute, info in pairs(attributes) do
            item:setAttribute(attribute, info.getValue(itemType))
        end
        return true
    end
    setItemLevel(item, level)
    item:setAttribute(ITEM_ATTRIBUTE_NAME, string.format("%s +%u", itemType:getName(), level))
    for attribute, info in pairs(attributes) do
        local value = info.getValue(itemType)
        if value ~= 0 then
            item:setAttribute(attribute, upgradeValue(value, level, info, stone))
        end
    end
    return true
end

local upgrade = Action()
function upgrade.onUse(player, item, fromPos, target, toPos, isHotkey)
    if not target or not target:isItem() then
        player:sendCancelMessage("You cannot use this object.")
        return true
    end
    local stone = stones[item:getId()]
    if not stone then
        return false
    end
    if not isUpgradeable(target) then
        player:sendCancelMessage("This item cannot be upgrade.")
        return true
    end
    local level = getItemLevel(target)
    if level < stone.minLevel then
        player:sendCancelMessage(string.format("The minimum level to use is %d.", stone.minLevel))
        return true
    end
    local newLevel = onUpgradeLvl(level, 100, stone)
    if level >= stone.maxLevel then
        player:getPosition():sendMagicEffect(CONST_ME_POFF, player)
        player:sendCancelMessage("This item is already at its maximum level.")
        return true
    elseif newLevel == level then
        player:say("Failed!", TALKTYPE_MONSTER_SAY)
        player:getPosition():sendMagicEffect(CONST_ME_POFF)
    elseif newLevel > level then
        player:say("Success!", TALKTYPE_MONSTER_SAY)
        player:getPosition():sendMagicEffect(CONST_ME_FIREWORK_YELLOW)
    end
    doUpgrade(target, newLevel, stone)
    item:remove(1)
    return true
end
for aid, _ in pairs(stones) do
    upgrade:id(aid)
end
upgrade:register()

View attachment 54604

Each stone can be configured so that it can only be used in a range of levels, for example: 0 > 15 | 15 > 30 | 30 > 50 ....
You can also configure a custom attribute increment for each stone.

Important note: If you have a system that modifies the names of the articles, then you will have problems using this update system, since this system will overwrite the original name of the article + the corresponding level, the level is not lost, but it will not be show in name in case another system modifies it.

If you have another system that modifies the names, like for example a slot system or something else, you can tell me and I will help you solve the problem quickly with a little trick.

I love it
Just bad it adds only some boring extra attribute but at end some good script
 
I need boss room script you can join every x hours with x mins time to kill boss.
example click lever teleport you to boss room u have 20 mins to kill boss otherwise tp player outside.
u can join solo or multiple players like oberon
Hi @Sneaky Diller

data/scripts/yourscriptname.lua
Lua:
local configQuest = {
    actionId = 901,
    players = { -- Positions where players are standing to enter
        Tile(3051, 1828, 8),
        Tile(3051, 1829, 8),
        Tile(3051, 1830, 8),
        Tile(3051, 1831, 8),
        Tile(3051, 1832, 8),
        Tile(3051, 1833, 8),
        Tile(3051, 1834, 8)
    },
    minPlayers = 1, -- Minimum number of players that can enter. in this case 1 or more
    destination = Position(3056, 1831, 8), -- Position where the players will be teleported when entering the room
    requirements = {
        level = 2000, -- level required to enter the room
        storages = {} -- if you need some storage to be able to enter or several storages
    },
    room = {
        centerPos = Position(3068, 1831, 8), -- center of the room
        fromPos = Position(3055, 1812, 8), -- the upper left corner of the room
        toPos = Position(3084, 1844, 8) -- the lower right corner of the room
    },
    boss = {
        name = "Demon", -- boss name
        spawnPos = Position(3068, 1831, 8), -- spawn boss position
        exitIn = 1 -- minutes to get out of the room
    },
    debug = {
        enabled = false, -- for testing with /reload scripts
        exitPos = Position(3051, 1826, 8), -- Position to which players will be sent off after a while
        leverIds = {1945, 1946}, -- lever on / lever off
        admins = false -- detect administrators in the room
    }
}

local function getPlayersInQuest()
    local spectators = Game.getSpectators(configQuest.room.centerPos, false, true, configQuest.radius.x, configQuest.radius.x, configQuest.radius.y, configQuest.radius.y)
    local players = {}
    for _, spectator in pairs(spectators) do
        if spectator:getGroup():getId() == 1 or configQuest.debug.admins then
            players[#players +1] = spectator
        end
    end
    return players
end

local function closeQuest()
    local ground = configQuest.players[1]:getGround()
    for _, p in pairs(getPlayersInQuest()) do
        p:teleportTo(configQuest.debug.exitPos)
    end
    local boss = Monster(ground:getCustomAttribute("bossId"))
    if boss then
        boss:remove()
    end
    ground:removeCustomAttribute("evId")
end

local action = Action()
function action.onUse(player, item, fromPos, target, toPos, isHotkey)
    if not configQuest.radius then
        configQuest.radius = {
            x = math.ceil((configQuest.room.toPos.x - configQuest.room.fromPos.x) / 2),
            y = math.ceil((configQuest.room.toPos.y - configQuest.room.fromPos.y) / 2)
        }
    end
    local leverCanUse = false
    local playerPosition = player:getPosition()
    for _, tile in pairs(configQuest.players) do
        leverCanUse = playerPosition == tile:getPosition()
        if leverCanUse then
            break
        end
    end
    if not leverCanUse then
        return false
    end
    local questPlayers = getPlayersInQuest()
    for _, p in pairs(questPlayers) do
        if configQuest.debug.enabled then
            p:teleportTo(configQuest.debug.exitPos)
        end
    end
    if configQuest.debug.enabled then
        configQuest.debug.exitPos:sendMagicEffect(CONST_ME_TELEPORT)
    end
    local ground = configQuest.players[1]:getGround()
    local boss = Monster(ground:getCustomAttribute("bossId"))
    if boss then
        if configQuest.debug.enabled or #questPlayers == 0 then
            boss:remove()
            stopEvent(ground:getCustomAttribute("evId"))
            ground:removeCustomAttribute("evId")
        else
            player:sendCancelMessage(string.format("You must wait for the boss to be defeated or wait %d seconds.", ground:getCustomAttribute("now") - os.time()))
            return true
        end
    end
    local players = {}
    for _, tile in pairs(configQuest.players) do
        local p = tile:getTopCreature()
        if p and p:isPlayer() then
            if p:getLevel() < configQuest.requirements.level then
                player:sendCancelMessage(string.format("%s must be level %d or higher.", p:getName(), configQuest.requirements.level))
                p:getPosition():sendMagicEffect(CONST_ME_POFF)
                return true
            end
            for _, storage in pairs(configQuest.requirements.storages) do
                if p:getStorageValue(storage) == -1 then
                    player:sendCancelMessage(string.format("%s still cannot face this boss.", p:getName()))
                    p:getPosition():sendMagicEffect(CONST_ME_POFF)
                    return true
                end
            end
            players[#players +1] = p
        end
    end
    if #players < configQuest.minPlayers then
        player:sendCancelMessage(string.format("Sorry, only groups of %d or more players are allowed.", configQuest.minPlayers))
        return true
    end
    for _, p in pairs(players) do
        p:getPosition():sendMagicEffect(CONST_ME_POFF)
        p:teleportTo(configQuest.destination)
    end
    configQuest.destination:sendMagicEffect(CONST_ME_TELEPORT)
    boss = Game.createMonster(configQuest.boss.name, configQuest.boss.spawnPos)
    if boss then
        ground:setCustomAttribute("bossId", boss:getId())
        ground:setCustomAttribute("evId", addEvent(closeQuest, configQuest.boss.exitIn * 60 * 1000))
        ground:setCustomAttribute("now", os.time() + (configQuest.boss.exitIn * 60))
    end
    item:transform(item:getId() == configQuest.debug.leverIds[1] and configQuest.debug.leverIds[2] or configQuest.debug.leverIds[1])
    return true
end

action:aid(configQuest.actionId)
action:register()

GIF 06-02-2021 04-50-52 p. m..gifGIF 06-02-2021 04-55-11 p. m..gif

Correctly configure the positions of the boss room and the required level, as well as the positions of the tiles where the players have to stand,
Do not forget to configure the maximum time you have to defeat the boss with the variable: exitIn

For the lever to work, you just have to add the actionId in your RME, or add it manually from the game for testing.

Important note: if you want to do tests, activate the debug.enabled variable and set it as true and if you want to do the tests with players with access, such as: Tutor/GM/God then you must also activate the debug.admins variable, remember to leave these two false variables in production

Suggestions:
  • Add a portal so that players can leave the room (in case they give up and want to leave before departure time)
  • The boss should have a good reward or a boss reward system
 
hi sarah, i want a stamina refill script but that restores 2 hours each time it is used
Hi @Methemia

data/scripts/yourscriptname.lua
Lua:
local action = Action()
function action.onUse(player, item, ...)
    local stamina = player:getStamina()
    if stamina >= 2520 then
        player:sendCancelMessage("You have a full stamina.")
        return true
    end
    player:setStamina(math.min(2520, stamina + 120))
    player:getPosition():sendMagicEffect(CONST_ME_MAGIC_GREEN)
    player:sendCancelMessage("You have regenerate 2 hours of stamina.")
    item:remove(1)
    return true
end

action:id(10022)
action:register()
Post automatically merged:

Hi Sarah , can u make this script if it's possible let's say we have 4 vocations I need these vocations 3 of them disable their losing items and 1 single vocation could lose his items. If this vocation have no amulet and he died he must lose all of his items like if he have a red skull losing his items oncely I'm just highlighting the idea I mean losing all the items at the same time if you can do this with another thing it's okay becaus i'v tried but I've failed. And this vocation can only use this amulets {2138,2141,2201} to save their items from dropping and the other vocations can use those amulets too but when they are going to die it remove their aol and not dropping anything.
I think I did not understand you well, you mean that each vocation must have different amulets to protect their items? In case I used the wrong one, what would happen? Are the items lost anyway?
 
Last edited:
  • Like
Reactions: Wix
Perhaps i have something in my opinion more challenging? idk so i need a spell(exevo vis hur range) but each consecutive third hit on the target will add a bonus damage of 50%, so you hit player once , then second time and then miss and then hit the target there is no bonus damage. I also think this needs to be related to the player? because if he runs out of screen and come back the spell still needs to count those hits? Also its up to you if u want to incorporate this with monsters as well.
 
Hi @Methemia

data/scripts/yourscriptname.lua
Lua:
local action = Action()
function action.onUse(player, item, ...)
    local stamina = player:getStamina()
    if stamina >= 2520 then
        player:sendCancelMessage("You have a full stamina.")
        return true
    end
    player:setStamina(math.min(2520, stamina + 120))
    player:getPosition():sendMagicEffect(CONST_ME_MAGIC_GREEN)
    player:sendCancelMessage("You have regenerate 2 hours of stamina.")
    item:remove(1)
    return true
end

action:id(10022)
action:register()
Post automatically merged:


I think I did not understand you well, you mean that each vocation must have different amulets to protect their items? In case I used the wrong one, what would happen? Are the items lost anyway?
No I mean 1 vocation have those amulets and the other can use those amulets too but this won't affect anything because they arent losing their eq they will only use amulets to get more arm/ Mana regen and all vocations will not lose their items except one vocation when this vocation dies without amulet the full equipment lost in the body that's all I meant. Sorry for bad English
 
Last edited:
Create a system that captures the top 5 of the day that most experiencie and gives the rewards for each example:

1. Example 1 - 5kk experience - won 50kk crystal coin
2. Example 2 - 4kk experience - won 30kk crystal coin
3. Example 3 - 2kk experience - won 15kk crystal coin
4. Example 4 - 1kk experience - won 5kk crystal coin
5. Example 5 - 500k experience, won 200k crystal coin

After that he resets the top experience for the next day.
 
Create a system that captures the top 5 of the day that most experiencie and gives the rewards for each example:

1. Example 1 - 5kk experience - won 50kk crystal coin
2. Example 2 - 4kk experience - won 30kk crystal coin
3. Example 3 - 2kk experience - won 15kk crystal coin
4. Example 4 - 1kk experience - won 5kk crystal coin
5. Example 5 - 500k experience, won 200k crystal coin

After that he resets the top experience for the next day.
50kk crystal coins? 😂hope u got enough backpacks bro
 
It is just an example, in case I would use it to put coins .. but it does not necessarily have to be in the bag, you can transfer it directly to the bank.
I thought so too, was just to fun to not comment! I hope Sarah can do this one tho, would be fun to play around with what you can give players reaching x Exp!
 
YO! Thanks for scripts.



Elemental Spell DMG changer...

So... when we equip example leather helmet then all our spells and melee/distance/wand deal fire dmg
when we equip crown helmet then all our spells and melee/distance/wand deal energy dmg
etc... cofiguration working with all Tibia elements.
 
Hello Sarah, you could create a very simple script, it would be a creature spell, where a wave takes 50% of the player's life.
Hi @Wanheda

data/scripts/yourscriptname.lua
Lua:
local combat = Combat()
combat:setParameter(COMBAT_PARAM_TYPE, COMBAT_LIFEDRAIN)
combat:setParameter(COMBAT_PARAM_EFFECT, CONST_ME_MAGIC_RED)
combat:setArea(createCombatArea(AREA_CROSS5X5))

function onTileCombat(creature, pos)
    local tile = Tile(pos)
    if tile then
        local creatures = tile:getCreatures() or {}
        for i, c in pairs(creatures) do
            if c:isPlayer() then
                local takeHp = c:getMaxHealth() / 2
                doTargetCombatHealth(creature:getId(), c, COMBAT_LIFEDRAIN, -takeHp, -takeHp, CONST_ME_NONE, ORIGIN_NONE)
                creature:addHealth(takeHp)
                creature:getPosition():sendMagicEffect(CONST_ME_MAGIC_GREEN)
            end
        end
    end
end

combat:setCallback(CALLBACK_PARAM_TARGETTILE, "onTileCombat")

local spell = Spell(SPELL_INSTANT)

function spell.onCastSpell(creature, variant)
    return combat:execute(creature, variant)
end

spell:name("Creature Spell Name")
spell:words("###-1")
spell:blockWalls(true)
spell:register()

You just have to register the ability to the monster and test.
I don't know if I understood correctly, but the monster steals 50% of your life and gives it to him himself xd
in case you don't want the monster to regain the same life it takes from you, remove the line: creature:addHealth(takeHp)
GIF 07-02-2021 06-04-25 p. m..gif
 
YO! Thanks for scripts.



Elemental Spell DMG changer...

So... when we equip example leather helmet then all our spells and melee/distance/wand deal fire dmg
when we equip crown helmet then all our spells and melee/distance/wand deal energy dmg
etc... cofiguration working with all Tibia elements.

Uhh why the fuck didnt I have that kind of idea befor

Would make the server more interesting
 
A spell for knights. draws the target towards itself the second spell draws 6x6 monsters towards it. Configuration with number of targets, distance, etc.
When pulled, it stops the monster for 2 seconds and the player for 1.
Hi @gicu0770

It is your turn however, there is a functionality that is not included in TFS 1.3, that of immobilizing a monster with the function: creature: setMovementBlocked(state) for immobilizing monsters is out of scope without source edits or horrible repeat addEvents.

If you have another idea let me know, or any small change in your request.
 
Hey Sarah, thank you for this great contribution.
If i may i would like to ask for spell that teleports user where his mouse is , and is triggered by using right click anywhere on the map (game window range , not minimap). Spell has some exhaust ofcourse and player cannot tp thru walls and on objects/players/monsters. Once more , thank you!
Hi @S p i d i

I'm sorry I didn't answer you, what happens is that what you ask requires a modification in the sources, if it is as I am thinking, and if it is otherwise, it would even require code on the client side, for know where the position of mouse.

and assuming you ask for it is something like the command /cliport, changes are also required in the fonts, if you don't mind you can write something else that meets the requirements and I will gladly help you.

maybe for TFS 1.4 version if we can make /cliport programmed from lua, with the implementation of onParsePacket() in creaturescripts.
 
A treasure goblin the same thats seen in the diablo games


A mob spawns randomly around the map (maybe it highjacks an exisiting spawn at random on the map). The mob is fast, each time you hit it, it spits outs some coins on the ground and on the final kill it drops loot from a configurable loot table (not on the ground in its inventory). The damage it takes is a % of its health that way its the same hits for any player to kill
 
Status
Not open for further replies.
Back
Top