• 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 Snavy & Levi - Free Scripting Service - TFS 1.3

Status
Not open for further replies.

Snavy

Bakasta
Senator
Joined
Apr 1, 2012
Messages
1,249
Solutions
71
Reaction score
621
Location
Hell
@Levi999x and I will be providing scripting service for free.
The thread will be locked after a while but might be unlocked again later.



[ REQUIREMENTS ]

TFS
: 1.3(+) ( github.com/otland/forgottenserver )

SCRIPTS: Actions, Creaturescripts, Globalevents, Movements, Talkactions

INFO: Give a detailed explanation of what you want.
If we fail to understand what you're saying your request will probably be ignored.



[ SUPPORT ]
If you have any problems with the scripts, feel free to open a new thread in the
support board and make sure you follow the rules.



[⚠️ WARNING ⚠️]
Your post will be deleted if you ask for help in this thread.
You may not PM either of us for script requests.
Requests which require source modifications will be ignored.

Requests for the following engines will be ignored.
  • OTBR,
  • OTX,
  • TFS 1.2(or lower)



If either of us reacts like (👍) on your request, that means it is accepted.
 
Last edited:
hello, could make a lottery system every 2 hours will be drawn among the following parameters:
gold tokens or
30% exp.
in this case all online players will win one of the above parameters
 
[Talkaction]
Teleport player to player. Basically that works like this

If that target you want to teleport is with Skull ur able to do so, but if he doesnt have a skull you cant teleport to him (so its like sensing the player) another think if you want to teleport to a target you have to be higher level then him if hes level 50 you have to be =>50 and not below so people wont abuse quests, and probably it shouldnt allow to teleport to a player if hes in protect zeno so they wont telport in houses or depos and abuse it. And should have 1 hour cooldown, and take 100 stamina. And thats it i think cant think about anything else that would be game breaking.
Haven't tested, try it.
If you find bugs/errors create a thread on the support board and explain what the problem is.
Lua:
--| USAGE:
--| !huntbs player name

local config = {
    staminaMinutes = 100,
    storage        = 414515,
    coolDown       = 1 * 60 * 60 -- 1 hour
}

local ta = TalkAction('!huntbs')
function ta.onSay(player, words, param)
    if player:getStorageValue(config.storage) > os.time() then
        player:sendTextMessage(MESSAGE_STATUS_SMALL, 'Your GPS tracker is broken, try again later.')
        return false
    end

    if player:getName():lower() == param:lower() then
        player:sendTextMessage(MESSAGE_STATUS_SMALL, 'You are drunk, lel :P.')
        return false
    end

    local target = Player(param)
    if not target then
        player:sendTextMessage(MESSAGE_STATUS_SMALL, 'Player is offline or dead, forever in peace.')
        return false
    end

    if target:getZone() == ZONE_PROTECTION then
        player:sendTextMessage(MESSAGE_STATUS_SMALL, 'Your target is a bit busy. Try later.')
        return false
    end

    if player:getLevel() < target:getLevel() then
        player:sendTextMessage(MESSAGE_STATUS_SMALL, 'Alright, slow down. You\'re still too young for chasing down criminals.')
        return false
    end

    local skull = target:getSkull()
    if not skull or table.contains({SKULL_NONE, SKULL_YELLOW, SKULL_GREEN, SKULL_ORANGE}, skull) then
        player:sendTextMessage(MESSAGE_STATUS_SMALL, 'You need to calm yer arse down.')
        return false
    end

    player:setStamina(player:getStamina() - config.staminaMinutes)
    player:setStorageValue(config.storage, config.coolDown + os.time())
    player:teleportTo(target:getPosition())
    player:getPosition():sendMagicEffect(CONST_ME_TELEPORT)
    player:sendTextMessage(MESSAGE_EVENT_ADVANCE, 'You have found your target, good luck.')
    return false
end

ta:separator(' ')
ta:register()
 
Guildmaster npc just like in the old days, here you can make your guild/invite new members/kick members/disband guild/give members an nickname.
 
pease system lever boss with 1 or 5 players anda have time with kikck room and verify so have other team in boss
 
I still don't understand why you need it. lol

Anyway, here you go.

View attachment 57522

Put this in the monster.
XML:
<script>
    <event name="PaleWormDeath" />
</script>
put this in data/scripts
Lua:
local creatureevent = CreatureEvent("PaleWormDeath")

function creatureevent.onDeath(creature, corpse, killer, mostDamageKiller, lastHitUnjustified, mostDamageUnjustified)
    corpse:moveTo(Position(250, 250, 7))
    return true
end

creatureevent:register()

thanks for the code
 
@Snavy im looking on Your codes, and im really impressed :) Nice one, so keep it up.
i wonder, maybe you get some time to help me a little :)

im thinking of situation like that
you create accoun, log into game, and play.. nothing special, but!

you can choose a site to play as (Superhero/Vilian) - i was thinking to do it as a "promotion" - so you got NPC that will promote you to superhero or vilian - thats part 1

part two - i thinking of that, i do event with monsters:
good monster and bad monster (monster dont attack you, only attack back if you attack him - rest like in normal monster like hp/exp/loot/etc)
also monster have a points - that will be stored in your character sql - how many monster good you killed, and how many bad monsters you killed)

if you could help me with that it will be lovely :)

--- this part i take car myself -- >
ok, now we count from all characters from database points (good and bad) and show it on site - so we know that is like
209 good points / and 30 bad points from all players and we can start a good event or bad event :)
 
Appreciate all of you guys that do these scripting threads. I learn so much every day from these kinds of threads :)

I would like to request an event where a monster/something attackable will spawn in a random location based on a list of configurable locations and then broadcast it's location.
When attacked and loses a certain amount of hp% it should spawn randomly either some loot or monsters or both from a list around itself in a defined radius. So if there's many attackers and high dps happening then it would be spawning loot/monsters quite often.
When it dies it should spawn lots of just loot from the list and trigger the countdown for the next spawn. So max 1 on the map at any time.

Preview
lootBoss.gif

Code
YourMonster.XML
XML:
<script>
    <event name="lootBossCE" />
    <event name="lootBossDeath" />
</script>

data/scripts/lootboss.lua
Lua:
--[[
    [+] = done
    [-] = not done

    [+] random spawn location
    [+] lost hp% mob/item spawn
    [+] spawn items + monsters on death & start next spawn countdown
    [-] DPS
]]
local config = {

    SPAWN_AREAS = {
        {
            TOP_LEFT     = Position(47, 399, 7),
            BOTTOM_RIGHT = Position(61, 409, 7)
        }
    },

    BOSS_NAME = 'cyclops smith',

    -- How long after death should the boss respawn?
    SPAWN_INTERVAL = 10, -- seconds

    -- Item rewards
    MIN_REWARD_AMOUNT = 1,
    MAX_REWARD_AMOUNT = 3,
    REWARDS = {
        {2160,  1},
        {2159,  2},
        {8976,  1},
        {13537, 1},
        {2148,  5},
        {2135,  1}
    },

    -- What the boss will spawn
    SUMMONS = { 'rat', 'orc', 'troll', 'bear', 'wolf', 'snake', 'larva', 'donkey' },

    -- Minimum and maximum amount of mobs to be spawned.
    MIN_SUMMON_AMOUNT = 1,
    MAX_SUMMON_AMOUNT = 5,

    -- What will be created everytime a certain HP% is reached.
    SPAWN_CHOICE_ITEMS = 1,
    SPAWN_CHOICE_MOBS  = 2,
    SPAWN_CHOICE_BOTH  = 3,

    -- Radius to top-left & to bottom-right from boss position.
    SPAWN_OBJECT_RADIUS = 3
}

local DAMAGE_REWARD_CONFIG = {
    [1] = { hpPercent = 10 },
    [2] = { hpPercent = 30 },
    [3] = { hpPercent = 60 },
    [4] = { hpPercent = 90 }
}
------------------------------------------------------------------------------------
---------------------------------[  GLOBALEVENT  ]----------------------------------
------------------------------------------------------------------------------------
local function spawnLootBoss()
    local area = config.SPAWN_AREAS[math.random(1, #config.SPAWN_AREAS)]
    local spawnPos = Position(
        math.random(area.TOP_LEFT.x, area.BOTTOM_RIGHT.x),
        math.random(area.TOP_LEFT.y, area.BOTTOM_RIGHT.y),
        area.TOP_LEFT.z
    )
    Game.createMonster(config.BOSS_NAME, spawnPos, false, true)
    Game.broadcastMessage('The vicious boss '.. config.BOSS_NAME ..' has risen from the dead', MESSAGE_EVENT_ADVANCE)
    REWARDS_COLLECTED = {}
end

local lootBoss = GlobalEvent('lootBoss')
function lootBoss.onStartup()
    spawnLootBoss()
    return true
end
lootBoss:register()
------------------------------------------------------------------------------------
-------------------------------[  CREATURESCRIPTS  ]--------------------------------
------------------------------------------------------------------------------------
local function secondsToReadable(s)
    local hours   = math.floor(s / 3600)
    local minutes = math.floor(math.mod(s, 3600)/60)
    local seconds = math.floor(math.mod(s, 60))
    return (hours   > 0 and (hours   .. ' hour'   .. (hours   > 1 and 's ' or ' ')) or '') ..
           (minutes > 0 and (minutes .. ' minute' .. (minutes > 1 and 's ' or ' ')) or '') ..
           (seconds > 0 and (seconds .. ' second' .. (seconds > 1 and 's ' or ' ')) or '')
end

local function getClosestFreeTile(pos, radius)
    for y = pos.y - radius, pos.y + radius do
        for x = pos.x - radius, pos.x + radius do
            local tile = Tile(x, y, pos.z)
            if tile and tile:isWalkable() then
                return Position(x, y, pos.z)
            end
        end
    end
    return nil
end

local function spawnItem(spawnObjectArea)
    local reward_idx = math.random(1, #config.REWARDS)
    local reward_item_pos = Position(
        math.random(spawnObjectArea.TOP_LEFT.x, spawnObjectArea.BOTTOM_RIGHT.x),
        math.random(spawnObjectArea.TOP_LEFT.y, spawnObjectArea.BOTTOM_RIGHT.y),
        spawnObjectArea.TOP_LEFT.z
    )

    local tile = Tile(reward_item_pos)
    if (not tile) or (not tile:isWalkable()) then
        reward_item_pos = getClosestFreeTile(reward_item_pos, 1)
    end

    if not reward_item_pos then
        return
    end

    Game.createItem(config.REWARDS[reward_idx][1], config.REWARDS[reward_idx][2], reward_item_pos)
    reward_item_pos:sendMagicEffect(CONST_ME_MAGIC_BLUE)
end

local function spawnMob(spawnObjectArea)
    local mob_pos = Position(
        math.random(spawnObjectArea.TOP_LEFT.x, spawnObjectArea.BOTTOM_RIGHT.x),
        math.random(spawnObjectArea.TOP_LEFT.y, spawnObjectArea.BOTTOM_RIGHT.y),
        spawnObjectArea.TOP_LEFT.z
    )

    local tile = Tile(mob_pos)
    if (not tile) or (not tile:isWalkable()) then
        mob_pos = getClosestFreeTile(mob_pos, 1)
    end

    if not mob_pos then
        return
    end

    Game.createMonster(config.SUMMONS[math.random(1, #config.SUMMONS)], mob_pos, true, true)
    mob_pos:sendMagicEffect(CONST_ME_MAGIC_BLUE)
end

------------------------------------------------------------------------------------

REWARDS_COLLECTED = {}
local lootBoss_ce = CreatureEvent('lootBossCE')
function lootBoss_ce.onHealthChange(creature, attacker, primaryDamage, primaryType, secondaryDamage, secondaryType, origin)
    local hpAfterDmg = creature:getHealth() - (primaryDamage + secondaryDamage)
    local hpDiffPercent = math.floor((creature:getMaxHealth() - hpAfterDmg) * 100 / creature:getMaxHealth())
    local bossPos = creature:getPosition()

    for i = #DAMAGE_REWARD_CONFIG, 1, -1 do
        local f = (function(hpPercent)
        ----------------------------------------
        if hpDiffPercent < hpPercent then
            return false
        end

        if REWARDS_COLLECTED[i] then
            return false
        end

        REWARDS_COLLECTED[i] = 1

        local spawnObjectArea = {
            TOP_LEFT = Position(
                bossPos.x - config.SPAWN_OBJECT_RADIUS,
                bossPos.y - config.SPAWN_OBJECT_RADIUS,
                bossPos.z
            ),

            BOTTOM_RIGHT = Position(
                bossPos.x + config.SPAWN_OBJECT_RADIUS,
                bossPos.y + config.SPAWN_OBJECT_RADIUS,
                bossPos.z
            ),
        }

        local spawnChoice = math.random(config.SPAWN_CHOICE_ITEMS, config.SPAWN_CHOICE_BOTH)
        if spawnChoice == config.SPAWN_CHOICE_ITEMS then
            for ix = config.MIN_REWARD_AMOUNT, config.MAX_REWARD_AMOUNT do
                spawnItem(spawnObjectArea)
            end
            return true
        end

        if spawnChoice == config.SPAWN_CHOICE_MOBS then
            for ix = config.MIN_REWARD_AMOUNT, config.MAX_REWARD_AMOUNT do
                spawnMob(spawnObjectArea)
            end
            return true
        end

        if spawnChoice == config.SPAWN_CHOICE_BOTH then
            for ix = config.MIN_REWARD_AMOUNT, config.MAX_SUMMON_AMOUNT do
                spawnChoice = math.random(config.SPAWN_CHOICE_ITEMS, config.SPAWN_CHOICE_MOBS)
                if spawnChoice == config.SPAWN_CHOICE_ITEMS then
                    spawnItem(spawnObjectArea)
                else
                    spawnMob(spawnObjectArea)
                end
            end
            return true
        end
        ----------------------------------------
        end)(DAMAGE_REWARD_CONFIG[i].hpPercent)
        if f then break end
    end
    return primaryDamage, primaryType, secondaryDamage, secondaryType
end
lootBoss_ce:register()

local lootBossDeath = CreatureEvent('lootBossDeath')
function lootBossDeath.onDeath(creature, corpse, killer, mostDamageKiller, lastHitUnjustified, mostDamageUnjustified)
    REWARDS_COLLECTED = {}

    local bossPos = creature:getPosition()
    local spawnObjectArea = {
        TOP_LEFT = Position(
            bossPos.x - config.SPAWN_OBJECT_RADIUS,
            bossPos.y - config.SPAWN_OBJECT_RADIUS,
            bossPos.z
        ),

        BOTTOM_RIGHT = Position(
            bossPos.x + config.SPAWN_OBJECT_RADIUS,
            bossPos.y + config.SPAWN_OBJECT_RADIUS,
            bossPos.z
        ),
    }

    for i = config.MIN_REWARD_AMOUNT, config.MAX_REWARD_AMOUNT * 2 do
        spawnItem(spawnObjectArea)
    end

    Game.broadcastMessage(creature:getName() .. ' has been killed. Next spawn in ' .. secondsToReadable(config.SPAWN_INTERVAL), MESSAGE_EVENT_ADVANCE)
    addEvent(spawnLootBoss, config.SPAWN_INTERVAL * 1000)
    return true
end
lootBossDeath:register()
 
Preview
View attachment 57659

Code
YourMonster.XML
XML:
<script>
    <event name="lootBossCE" />
    <event name="lootBossDeath" />
</script>

data/scripts/lootboss.lua
Lua:
--[[
    [+] = done
    [-] = not done

    [+] random spawn location
    [+] lost hp% mob/item spawn
    [+] spawn items + monsters on death & start next spawn countdown
    [-] DPS
]]
local config = {

    SPAWN_AREAS = {
        {
            TOP_LEFT     = Position(47, 399, 7),
            BOTTOM_RIGHT = Position(61, 409, 7)
        }
    },

    BOSS_NAME = 'cyclops smith',

    -- How long after death should the boss respawn?
    SPAWN_INTERVAL = 10, -- seconds

    -- Item rewards
    MIN_REWARD_AMOUNT = 1,
    MAX_REWARD_AMOUNT = 3,
    REWARDS = {
        {2160,  1},
        {2159,  2},
        {8976,  1},
        {13537, 1},
        {2148,  5},
        {2135,  1}
    },

    -- What the boss will spawn
    SUMMONS = { 'rat', 'orc', 'troll', 'bear', 'wolf', 'snake', 'larva', 'donkey' },

    -- Minimum and maximum amount of mobs to be spawned.
    MIN_SUMMON_AMOUNT = 1,
    MAX_SUMMON_AMOUNT = 5,

    -- What will be created everytime a certain HP% is reached.
    SPAWN_CHOICE_ITEMS = 1,
    SPAWN_CHOICE_MOBS  = 2,
    SPAWN_CHOICE_BOTH  = 3,

    -- Radius to top-left & to bottom-right from boss position.
    SPAWN_OBJECT_RADIUS = 3
}

local DAMAGE_REWARD_CONFIG = {
    [1] = { hpPercent = 10 },
    [2] = { hpPercent = 30 },
    [3] = { hpPercent = 60 },
    [4] = { hpPercent = 90 }
}
------------------------------------------------------------------------------------
---------------------------------[  GLOBALEVENT  ]----------------------------------
------------------------------------------------------------------------------------
local function spawnLootBoss()
    local area = config.SPAWN_AREAS[math.random(1, #config.SPAWN_AREAS)]
    local spawnPos = Position(
        math.random(area.TOP_LEFT.x, area.BOTTOM_RIGHT.x),
        math.random(area.TOP_LEFT.y, area.BOTTOM_RIGHT.y),
        area.TOP_LEFT.z
    )
    Game.createMonster(config.BOSS_NAME, spawnPos, false, true)
    Game.broadcastMessage('The vicious boss '.. config.BOSS_NAME ..' has risen from the dead', MESSAGE_EVENT_ADVANCE)
    REWARDS_COLLECTED = {}
end

local lootBoss = GlobalEvent('lootBoss')
function lootBoss.onStartup()
    spawnLootBoss()
    return true
end
lootBoss:register()
------------------------------------------------------------------------------------
-------------------------------[  CREATURESCRIPTS  ]--------------------------------
------------------------------------------------------------------------------------
local function secondsToReadable(s)
    local hours   = math.floor(s / 3600)
    local minutes = math.floor(math.mod(s, 3600)/60)
    local seconds = math.floor(math.mod(s, 60))
    return (hours   > 0 and (hours   .. ' hour'   .. (hours   > 1 and 's ' or ' ')) or '') ..
           (minutes > 0 and (minutes .. ' minute' .. (minutes > 1 and 's ' or ' ')) or '') ..
           (seconds > 0 and (seconds .. ' second' .. (seconds > 1 and 's ' or ' ')) or '')
end

local function getClosestFreeTile(pos, radius)
    for y = pos.y - radius, pos.y + radius do
        for x = pos.x - radius, pos.x + radius do
            local tile = Tile(x, y, pos.z)
            if tile and tile:isWalkable() then
                return Position(x, y, pos.z)
            end
        end
    end
    return nil
end

local function spawnItem(spawnObjectArea)
    local reward_idx = math.random(1, #config.REWARDS)
    local reward_item_pos = Position(
        math.random(spawnObjectArea.TOP_LEFT.x, spawnObjectArea.BOTTOM_RIGHT.x),
        math.random(spawnObjectArea.TOP_LEFT.y, spawnObjectArea.BOTTOM_RIGHT.y),
        spawnObjectArea.TOP_LEFT.z
    )

    local tile = Tile(reward_item_pos)
    if (not tile) or (not tile:isWalkable()) then
        reward_item_pos = getClosestFreeTile(reward_item_pos, 1)
    end

    if not reward_item_pos then
        return
    end

    Game.createItem(config.REWARDS[reward_idx][1], config.REWARDS[reward_idx][2], reward_item_pos)
    reward_item_pos:sendMagicEffect(CONST_ME_MAGIC_BLUE)
end

local function spawnMob(spawnObjectArea)
    local mob_pos = Position(
        math.random(spawnObjectArea.TOP_LEFT.x, spawnObjectArea.BOTTOM_RIGHT.x),
        math.random(spawnObjectArea.TOP_LEFT.y, spawnObjectArea.BOTTOM_RIGHT.y),
        spawnObjectArea.TOP_LEFT.z
    )

    local tile = Tile(mob_pos)
    if (not tile) or (not tile:isWalkable()) then
        mob_pos = getClosestFreeTile(mob_pos, 1)
    end

    if not mob_pos then
        return
    end

    Game.createMonster(config.SUMMONS[math.random(1, #config.SUMMONS)], mob_pos, true, true)
    mob_pos:sendMagicEffect(CONST_ME_MAGIC_BLUE)
end

------------------------------------------------------------------------------------

REWARDS_COLLECTED = {}
local lootBoss_ce = CreatureEvent('lootBossCE')
function lootBoss_ce.onHealthChange(creature, attacker, primaryDamage, primaryType, secondaryDamage, secondaryType, origin)
    local hpAfterDmg = creature:getHealth() - (primaryDamage + secondaryDamage)
    local hpDiffPercent = math.floor((creature:getMaxHealth() - hpAfterDmg) * 100 / creature:getMaxHealth())
    local bossPos = creature:getPosition()

    for i = #DAMAGE_REWARD_CONFIG, 1, -1 do
        local f = (function(hpPercent)
        ----------------------------------------
        if hpDiffPercent < hpPercent then
            return false
        end

        if REWARDS_COLLECTED[i] then
            return false
        end

        REWARDS_COLLECTED[i] = 1

        local spawnObjectArea = {
            TOP_LEFT = Position(
                bossPos.x - config.SPAWN_OBJECT_RADIUS,
                bossPos.y - config.SPAWN_OBJECT_RADIUS,
                bossPos.z
            ),

            BOTTOM_RIGHT = Position(
                bossPos.x + config.SPAWN_OBJECT_RADIUS,
                bossPos.y + config.SPAWN_OBJECT_RADIUS,
                bossPos.z
            ),
        }

        local spawnChoice = math.random(config.SPAWN_CHOICE_ITEMS, config.SPAWN_CHOICE_BOTH)
        if spawnChoice == config.SPAWN_CHOICE_ITEMS then
            for ix = config.MIN_REWARD_AMOUNT, config.MAX_REWARD_AMOUNT do
                spawnItem(spawnObjectArea)
            end
            return true
        end

        if spawnChoice == config.SPAWN_CHOICE_MOBS then
            for ix = config.MIN_REWARD_AMOUNT, config.MAX_REWARD_AMOUNT do
                spawnMob(spawnObjectArea)
            end
            return true
        end

        if spawnChoice == config.SPAWN_CHOICE_BOTH then
            for ix = config.MIN_REWARD_AMOUNT, config.MAX_SUMMON_AMOUNT do
                spawnChoice = math.random(config.SPAWN_CHOICE_ITEMS, config.SPAWN_CHOICE_MOBS)
                if spawnChoice == config.SPAWN_CHOICE_ITEMS then
                    spawnItem(spawnObjectArea)
                else
                    spawnMob(spawnObjectArea)
                end
            end
            return true
        end
        ----------------------------------------
        end)(DAMAGE_REWARD_CONFIG[i].hpPercent)
        if f then break end
    end
    return primaryDamage, primaryType, secondaryDamage, secondaryType
end
lootBoss_ce:register()

local lootBossDeath = CreatureEvent('lootBossDeath')
function lootBossDeath.onDeath(creature, corpse, killer, mostDamageKiller, lastHitUnjustified, mostDamageUnjustified)
    REWARDS_COLLECTED = {}

    local bossPos = creature:getPosition()
    local spawnObjectArea = {
        TOP_LEFT = Position(
            bossPos.x - config.SPAWN_OBJECT_RADIUS,
            bossPos.y - config.SPAWN_OBJECT_RADIUS,
            bossPos.z
        ),

        BOTTOM_RIGHT = Position(
            bossPos.x + config.SPAWN_OBJECT_RADIUS,
            bossPos.y + config.SPAWN_OBJECT_RADIUS,
            bossPos.z
        ),
    }

    for i = config.MIN_REWARD_AMOUNT, config.MAX_REWARD_AMOUNT * 2 do
        spawnItem(spawnObjectArea)
    end

    Game.broadcastMessage(creature:getName() .. ' has been killed. Next spawn in ' .. secondsToReadable(config.SPAWN_INTERVAL), MESSAGE_EVENT_ADVANCE)
    addEvent(spawnLootBoss, config.SPAWN_INTERVAL * 1000)
    return true
end
lootBossDeath:register()
Oh my god i love it, thank you so much :)
 
is there a way of making a script every cycle of life (when boss's health become yellow,red,black) boss will turn into beast mode and his shadow will take place infront of players for a couple of seconds until shooting them with a mutiple distance shot dmg scales with players level

hopefully it doesnt require soruce edit :(


tfs 1.3
 
Last edited:
Preview
View attachment 57659

Code
YourMonster.XML
XML:
<script>
    <event name="lootBossCE" />
    <event name="lootBossDeath" />
</script>

data/scripts/lootboss.lua
Lua:
--[[
    [+] = done
    [-] = not done

    [+] random spawn location
    [+] lost hp% mob/item spawn
    [+] spawn items + monsters on death & start next spawn countdown
    [-] DPS
]]
local config = {

    SPAWN_AREAS = {
        {
            TOP_LEFT     = Position(47, 399, 7),
            BOTTOM_RIGHT = Position(61, 409, 7)
        }
    },

    BOSS_NAME = 'cyclops smith',

    -- How long after death should the boss respawn?
    SPAWN_INTERVAL = 10, -- seconds

    -- Item rewards
    MIN_REWARD_AMOUNT = 1,
    MAX_REWARD_AMOUNT = 3,
    REWARDS = {
        {2160,  1},
        {2159,  2},
        {8976,  1},
        {13537, 1},
        {2148,  5},
        {2135,  1}
    },

    -- What the boss will spawn
    SUMMONS = { 'rat', 'orc', 'troll', 'bear', 'wolf', 'snake', 'larva', 'donkey' },

    -- Minimum and maximum amount of mobs to be spawned.
    MIN_SUMMON_AMOUNT = 1,
    MAX_SUMMON_AMOUNT = 5,

    -- What will be created everytime a certain HP% is reached.
    SPAWN_CHOICE_ITEMS = 1,
    SPAWN_CHOICE_MOBS  = 2,
    SPAWN_CHOICE_BOTH  = 3,

    -- Radius to top-left & to bottom-right from boss position.
    SPAWN_OBJECT_RADIUS = 3
}

local DAMAGE_REWARD_CONFIG = {
    [1] = { hpPercent = 10 },
    [2] = { hpPercent = 30 },
    [3] = { hpPercent = 60 },
    [4] = { hpPercent = 90 }
}
------------------------------------------------------------------------------------
---------------------------------[  GLOBALEVENT  ]----------------------------------
------------------------------------------------------------------------------------
local function spawnLootBoss()
    local area = config.SPAWN_AREAS[math.random(1, #config.SPAWN_AREAS)]
    local spawnPos = Position(
        math.random(area.TOP_LEFT.x, area.BOTTOM_RIGHT.x),
        math.random(area.TOP_LEFT.y, area.BOTTOM_RIGHT.y),
        area.TOP_LEFT.z
    )
    Game.createMonster(config.BOSS_NAME, spawnPos, false, true)
    Game.broadcastMessage('The vicious boss '.. config.BOSS_NAME ..' has risen from the dead', MESSAGE_EVENT_ADVANCE)
    REWARDS_COLLECTED = {}
end

local lootBoss = GlobalEvent('lootBoss')
function lootBoss.onStartup()
    spawnLootBoss()
    return true
end
lootBoss:register()
------------------------------------------------------------------------------------
-------------------------------[  CREATURESCRIPTS  ]--------------------------------
------------------------------------------------------------------------------------
local function secondsToReadable(s)
    local hours   = math.floor(s / 3600)
    local minutes = math.floor(math.mod(s, 3600)/60)
    local seconds = math.floor(math.mod(s, 60))
    return (hours   > 0 and (hours   .. ' hour'   .. (hours   > 1 and 's ' or ' ')) or '') ..
           (minutes > 0 and (minutes .. ' minute' .. (minutes > 1 and 's ' or ' ')) or '') ..
           (seconds > 0 and (seconds .. ' second' .. (seconds > 1 and 's ' or ' ')) or '')
end

local function getClosestFreeTile(pos, radius)
    for y = pos.y - radius, pos.y + radius do
        for x = pos.x - radius, pos.x + radius do
            local tile = Tile(x, y, pos.z)
            if tile and tile:isWalkable() then
                return Position(x, y, pos.z)
            end
        end
    end
    return nil
end

local function spawnItem(spawnObjectArea)
    local reward_idx = math.random(1, #config.REWARDS)
    local reward_item_pos = Position(
        math.random(spawnObjectArea.TOP_LEFT.x, spawnObjectArea.BOTTOM_RIGHT.x),
        math.random(spawnObjectArea.TOP_LEFT.y, spawnObjectArea.BOTTOM_RIGHT.y),
        spawnObjectArea.TOP_LEFT.z
    )

    local tile = Tile(reward_item_pos)
    if (not tile) or (not tile:isWalkable()) then
        reward_item_pos = getClosestFreeTile(reward_item_pos, 1)
    end

    if not reward_item_pos then
        return
    end

    Game.createItem(config.REWARDS[reward_idx][1], config.REWARDS[reward_idx][2], reward_item_pos)
    reward_item_pos:sendMagicEffect(CONST_ME_MAGIC_BLUE)
end

local function spawnMob(spawnObjectArea)
    local mob_pos = Position(
        math.random(spawnObjectArea.TOP_LEFT.x, spawnObjectArea.BOTTOM_RIGHT.x),
        math.random(spawnObjectArea.TOP_LEFT.y, spawnObjectArea.BOTTOM_RIGHT.y),
        spawnObjectArea.TOP_LEFT.z
    )

    local tile = Tile(mob_pos)
    if (not tile) or (not tile:isWalkable()) then
        mob_pos = getClosestFreeTile(mob_pos, 1)
    end

    if not mob_pos then
        return
    end

    Game.createMonster(config.SUMMONS[math.random(1, #config.SUMMONS)], mob_pos, true, true)
    mob_pos:sendMagicEffect(CONST_ME_MAGIC_BLUE)
end

------------------------------------------------------------------------------------

REWARDS_COLLECTED = {}
local lootBoss_ce = CreatureEvent('lootBossCE')
function lootBoss_ce.onHealthChange(creature, attacker, primaryDamage, primaryType, secondaryDamage, secondaryType, origin)
    local hpAfterDmg = creature:getHealth() - (primaryDamage + secondaryDamage)
    local hpDiffPercent = math.floor((creature:getMaxHealth() - hpAfterDmg) * 100 / creature:getMaxHealth())
    local bossPos = creature:getPosition()

    for i = #DAMAGE_REWARD_CONFIG, 1, -1 do
        local f = (function(hpPercent)
        ----------------------------------------
        if hpDiffPercent < hpPercent then
            return false
        end

        if REWARDS_COLLECTED[i] then
            return false
        end

        REWARDS_COLLECTED[i] = 1

        local spawnObjectArea = {
            TOP_LEFT = Position(
                bossPos.x - config.SPAWN_OBJECT_RADIUS,
                bossPos.y - config.SPAWN_OBJECT_RADIUS,
                bossPos.z
            ),

            BOTTOM_RIGHT = Position(
                bossPos.x + config.SPAWN_OBJECT_RADIUS,
                bossPos.y + config.SPAWN_OBJECT_RADIUS,
                bossPos.z
            ),
        }

        local spawnChoice = math.random(config.SPAWN_CHOICE_ITEMS, config.SPAWN_CHOICE_BOTH)
        if spawnChoice == config.SPAWN_CHOICE_ITEMS then
            for ix = config.MIN_REWARD_AMOUNT, config.MAX_REWARD_AMOUNT do
                spawnItem(spawnObjectArea)
            end
            return true
        end

        if spawnChoice == config.SPAWN_CHOICE_MOBS then
            for ix = config.MIN_REWARD_AMOUNT, config.MAX_REWARD_AMOUNT do
                spawnMob(spawnObjectArea)
            end
            return true
        end

        if spawnChoice == config.SPAWN_CHOICE_BOTH then
            for ix = config.MIN_REWARD_AMOUNT, config.MAX_SUMMON_AMOUNT do
                spawnChoice = math.random(config.SPAWN_CHOICE_ITEMS, config.SPAWN_CHOICE_MOBS)
                if spawnChoice == config.SPAWN_CHOICE_ITEMS then
                    spawnItem(spawnObjectArea)
                else
                    spawnMob(spawnObjectArea)
                end
            end
            return true
        end
        ----------------------------------------
        end)(DAMAGE_REWARD_CONFIG[i].hpPercent)
        if f then break end
    end
    return primaryDamage, primaryType, secondaryDamage, secondaryType
end
lootBoss_ce:register()

local lootBossDeath = CreatureEvent('lootBossDeath')
function lootBossDeath.onDeath(creature, corpse, killer, mostDamageKiller, lastHitUnjustified, mostDamageUnjustified)
    REWARDS_COLLECTED = {}

    local bossPos = creature:getPosition()
    local spawnObjectArea = {
        TOP_LEFT = Position(
            bossPos.x - config.SPAWN_OBJECT_RADIUS,
            bossPos.y - config.SPAWN_OBJECT_RADIUS,
            bossPos.z
        ),

        BOTTOM_RIGHT = Position(
            bossPos.x + config.SPAWN_OBJECT_RADIUS,
            bossPos.y + config.SPAWN_OBJECT_RADIUS,
            bossPos.z
        ),
    }

    for i = config.MIN_REWARD_AMOUNT, config.MAX_REWARD_AMOUNT * 2 do
        spawnItem(spawnObjectArea)
    end

    Game.broadcastMessage(creature:getName() .. ' has been killed. Next spawn in ' .. secondsToReadable(config.SPAWN_INTERVAL), MESSAGE_EVENT_ADVANCE)
    addEvent(spawnLootBoss, config.SPAWN_INTERVAL * 1000)
    return true
end
lootBossDeath:register()

some awesome shit i like that
 
Hello.

I wonder is there a chance, to do a new skill like a immunity to e.g energy.
Also every energy attack thick will rise Your skill.
Like a shielding for e.g Energy

How should it work:
Energy fiels takes from you 20 HP points. (1 lvl skill)

You got skill "Resist Energy" on 1 lvl = enegry attack takes form You 20 HP
When you get 10 skill lvl - energy field will take just 18 HP (10 lvl = 10%)
etc..

I have done so far, just a new skill and get it into client - but I dont have it "linked/writed" to train that resist and decreasing energy attacks.
What to look for in the code, what to change to make it work?
Is it in C++ of server or it could be done just with LUA? Maybe both... ?
 
Hey.

Could you make an item script, which the character's loot doubles?
Example: Does the character use a potion and for 15 minutes does he have the loot of all monsters duplicated?

Thanks.
 
You can move on to revscripts.

Lua:
-- CONFIGURAÇÕES DE EXPERIENCIA --

useStages = true -- Usar sistema de Stages , true/false
premiumMultipliqueExp = 1.5 -- Players Premiums terão exp multiplicada, caso não querer deixe 1.
rateExp = 300 -- Exp caso não for usar stages.


local stages = { -- ["DELEVEL-ATELEVEL"] = EXP, (OBS: NUNCA  REPETIR O MSM NUMERO, SEMPRE COLOCAR UM A MAIS.)
    ["1-50"] = 300,
    ["51-100"] = 150,
    ["101-150"] = 75,
    ["151-200"] = 15,
    ["201-250"] = 10,
    ["251-300"] = 3,
    ["301-350"] = 2,
    ["351-400"] = 1,
    ["401-450"] = 0.7,
    ["451-500"] = 0.6,
    ["501-1000"] = 0.3,
   
}
ultimateExp = 0.1 -- exp que vai usar caso o level do player não tiver mais na tabela .

-- CONFIGURAÇÕES DA PARTY

partyPorcent = 40 -- Quantos Porcento da exp vai para os membros da party
levelBlockParty = 1000 -- Diferença Maxima de Level permitida para membro da party ganhar exp.
expShareRadiusX = 30 -- Distancia maxima permitida no eixo X para membro da party ganhar exp.
expShareRadiusY = 30 -- Distancia maxima permitida no eixo Y para membro da party ganhar exp.
expShareRadiusZ = 1 -- Distancia maxima permitida no eixo Z para membro da party ganhar exp.

-- CONFIGURAÇÕES DE RINGS --

local rings = { -- [ID DO ANEL] = EXP MULTIPLICADA POR X EXP.
    [181] = 1.5,
    [148] = 1.5,
   
}

local rate_bonus = get_bonus_weekend_exp()

-- FIM DAS CONFIGURAÇÕES --

function CalculeExp(monsterhp, exptotal, hit)
    hit = hit <= monsterhp and math.ceil(exptotal * hit / monsterhp) or 0
    return hit < 0 and 0 or hit
end

function isSummon(cid)
return getCreatureMaster(cid)
end

function onStatsChange(cid, attacker, type, combat, value)
    if isPlayer(attacker) and isMonster(cid) then
        if getCreatureStorage(cid, 50001) ~= 1 then
            doCreatureSetStorage(cid, 50002, getMonsterInfo(getCreatureName(cid)).experience * rateExp)
            doCreatureSetStorage(cid, 50001, 1)
        end
    end
    if type == STATSCHANGE_HEALTHLOSS then
        if isMonster(cid) then
            if isCreature(attacker) then
                local _cid = isSummon(attacker) and getCreatureMaster(attacker) or attacker
                if isPlayer(_cid) then
                    if useStages then
                        for strstage, experience in pairs(stages) do
                            tabstage = string.explode(strstage, "-")
                            if getPlayerLevel(_cid) >= tonumber(tabstage[1]) and getPlayerLevel(_cid) <= tonumber(tabstage[2]) then
                                ultimateExp = experience
                                   
                            end
                        end
                        experienceRate = ultimateExp
                    else
                        experienceRate = rateExp
                    end
                    local expgain = CalculeExp(getCreatureMaxHealth(cid), getMonsterInfo(getCreatureName(cid)).experience * experienceRate, value)
                    if getCreatureStorage(cid, 50002) > 0 then
                        if getCreatureStorage(cid, 50002) - expgain < 0 then
                            expgain = getCreatureStorage(cid, 50002)
                        end
                        doCreatureSetStorage(cid, 50002, getCreatureStorage(cid, 50002) - expgain)
                        local ringexp = 1
                        for idring, expring in pairs(rings) do
                            if getPlayerSlotItem(_cid, 9).itemid == idring then
                                ringexp = expring
                                break
                            end
                        end
                        local premiumMultipliqueExp = isPremium(_cid) and premiumMultipliqueExp or 1
                   
                        expgain = expgain * ringexp * premiumMultipliqueExp * rate_bonus
                        expboost = expgain
                        local testring2 = expgain - (expgain / rate_bonus)
                        local party = false
                        if isInParty(_cid) then
                            local partyMembers, expParty = getPartyMembers(getPartyLeader(_cid)), expgain / 100 * partyPorcent
                            for indice, partyMember in pairs(partyMembers) do
                                attackerLevel, partyLevel = getPlayerLevel(_cid), getPlayerLevel(partyMember)
                                attackerPos, partyPos = getThingPos(_cid), getThingPos(partyMember)
                                x = false
                                if math.abs(attackerLevel - partyLevel) > levelBlockParty then
                                    x = true
                                elseif math.abs(attackerPos.x - partyPos.x) > expShareRadiusX then
                                    x = true
                                elseif math.abs(attackerPos.y - partyPos.y) > expShareRadiusY then
                                    x = true
                                elseif attackerPos.z ~= partyPos.z then
                                    x = true
                                elseif _cid == partyMember then
                                    x = true
                                end
                                if x then
                                    partyMembers[indice] = nil
                                end
                            end
                            if #partyMembers ~= 0 then
                                expParty = math.ceil(expgain / 100 * partyPorcent)
                                expmember = math.ceil(expParty / #partyMembers)
                                for _, member in pairs(partyMembers) do
                                    if member ~= _cid then
                                        doPlayerSendTextMessage(member, 12, "You received "..expmember.." party exp.")
                                        doPlayerAddExp(member, expmember)
                                    end
                                end
                                doPlayerSendTextMessage(_cid, 12, "You gain "..expgain.." exp. (" ..partyPorcent.."% send to party)")
                                doPlayerAddExp(_cid, expgain - expParty)
                                party = true
                            else
                                party = false
                            end
                        end
                        if not party then
                            doPlayerAddExp(_cid, expgain)
                            doSendAnimatedText(getThingPos(_cid), math.ceil(expgain), 215)
                            doPlayerSendTextMessage(_cid, 23, "Você ganhou "..math.ceil(expgain).." exp.")
                        if getPlayerSlotItem(_cid, 9).itemid == 148 or getPlayerSlotItem(_cid, 9).itemid == 181 then
                        local bonus_ring = math.ceil((expgain-(expgain/(ringexp * premiumMultipliqueExp))))
                                doPlayerSendTextMessage(_cid, 23, "Você ganhou "..bonus_ring.." de bonus experiencia com ROE.")
                                end
                                if getGlobalStorageValue(config_weekend_exp.storage_bonus) == 1 then
                                doPlayerSendTextMessage(_cid, 23, "[Weekend Exp Event] Voce esta com "..((rate_bonus - 1)*100).."% de bonus experiencia.")
                                end
                        end
                    end
                end
            end
        end
    end
    return true
end
   
function onCombat(cid, target)
    if isMonster(target) and not isSummon(target) and not isPlayer(target) then
        registerCreatureEvent(target, "ExpGain")
    end
    return true
end
 
could you please write a script on All quest acces for new players TFS 1.3 ? or an NPC that can sell access to quests/zones etc ?
 
Last edited:
Hi , if u are still taking request then i would like to request one:
- Creating npc next to player
-To create npc you need item X and item Y (ids) together in your bp
-Npc can give X Money or Y Experience(can only choose one)
-After giving what you chose npc dissapears
-Only player who create npc can talk to him
-After you get reward the item dissapear from bp.
-Cant use item to create npc if he is already created by me, items become inactive during the time he is created.

Thanks in advance.
 
Hey im using TFS 1.3 7.72 by nekiro. I wanna add some new outfits to my server but don't really wanna use OTC so it is possible to make something like wardrobe to change outfits?
 
Status
Not open for further replies.
Back
Top