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

Action Advanced Monster Arena TFS 1.2

Mkalo

ボーカロイド
Senator
Joined
Jun 1, 2011
Messages
1,118
Solutions
55
Reaction score
946
Location
Japan
This is supposed to suit any idea you have of arena, you just have to use it correctly.

Lib: http://pastebin.com/tnkwCDCa Updated (17/04/2016)
Old: http://pastebin.com/R4s96bwZ

Creaturescripts: (Both death events)
Code:
  <event type="death" name="ArenaEvent" script="arenaevent.lua"/>
   <event type="death" name="JokerDeath" script="jokerdeath.lua"/>

arenaevent.lua: http://pastebin.com/4xkEiqvG
jokerdeath.lua: http://pastebin.com/c1K37RCG

Now I will explain every single option you have to use this lib. You can use the same lib to do any number of arenas. (You can't use the same space for different arenas.). Parameters between [] are optional.
Starting:

Arena(name, position/center, exitposition, radius[, rewardposition]):

This should be used outside the action script!!! DO NOT USE IT INSIDE ONUSE FFS.
Exitposition is only used in case someone is inside and the arena is not started (like from some crash or something).
You can have a normal teleport inside the arena to leave it, it wont bug the arena and it will reset if no player is inside it (Make sure players cant logout inside there)

This function will return the object that you will use to set all the other options.

Arena:addPlayerPosition(position[, level[, vocation]])
This will add a position to the arena, the player then must be in this position. You must add atleast 1 for the arena to work (ofcourse). With this you can set individual vocations/level something like desert quest and anihi together.

Arena:addWaves(wave, ...)
This is used to add the waves to your arena. Wave is the wave object and I will explain it later on. You can add multiple waves at once.

You SHOULD add atleast one please. Otherwise the player will teleport straight to the reward.

Arena:useLever(player)

Use this to start the arena, it will start and return true if it meets the requirements otherwise it will return false (Its useLever but you can use for talkaction or whatever you want)

-------------------------
From now on all these functions are optional you can choose to use them or not.

Arena:setJokerCreature(name)
Sets a "joker" creature to your arena (players will have to kill it before every wave to start it.)

Arena:setDelayWaves(delay)
Delay in miliseconds before spawning the next wave after killing all monsters (default is 1000).

Arena:setDelayEnd(delay) NEW
Time to end after the last wave was killed. (Added because before it was instant and the player couldn't loot the monsters.) Default is 2000.


Callbacks (also optionals), they are going to be called for each player inside the arena.

Arena:setRewardCallback(callback)
This will set the callback function to be called once the players finish the arena. It will be called with parameters: (player, arena)

Arena:setCheckCallback(callback)
This is the only callback where the return value matters. It will be called once the player uses the lever and the arena will only start if all the calls return true for every player. (This could be used to check some storage to prevent players from doing 2 times or anything else use your imagination) and the parameter is: (player)

Arena:setSpawnCallback(callback)
This callback function will be called at every spawn (the moment the wave actually spawns) with the parameters: (player, waveid, arena)

Arena:setWaveclearCallback(callback)
This callback function will be called at every wave clear, with parameters: (player, waveid, arena)

Arena:setJokerdeathCallback(callback)
This callback function will be called every time the joker dies, with parameters: (player, waveid, arena) (ONLY IF YOU'RE USING A JOKER OFCOURSE)

NEW

Arena:setStartCallback(callback)
This callback function will be called when the arena starts, with parameters: (player, arena)

Arena:setThinkCallback(callback[, interval = 2000])
This callback will be called whenever the arena is active with default interval 2000. (You should never reload the lib arena if any arena is active using this).
You should aswell reset the arena inside the callback if there is no player inside (Preventing it to call think function with no players inside)


Player:getLastArena()
Returns the last arena object that the player was in. (It will reset if you reload)

Player:isInsideArena(arena)
Self explanatory, true if inside, false if not.


Now the wave constructor function:
Look in the code in the second post its pretty straightforward.

Continues in the next post.
 
Last edited:
After reading the first post. Really please read it.

GO READ IT FFS.

Here is an example using every single function in the lib:

Code:
local waves = {
    [1] = Wave({
            ["Rat"] = 1,
        }),
    [2] = Wave({
            ["Cave Rat"] = 2,
        }),
}

local config = {
    levers = {1945, 1946},
}

function rewardPlayers(player, arena)
    player:addItem(2160, 100)
    player:setStorageValue(2101, 1)
    player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "Congratulations, you finished the arena " .. arena.name .. ".")
    return true
end

function checkPlayer(player)
    if player:getStorageValue(2101) <= 0 then
        return true
    else
        return false
    end
end

function spawnBroadcast(player, waveid, arena)
    player:sendTextMessage(MESSAGE_STATUS_CONSOLE_BLUE, "Spawning wave " .. waveid .. ".")
    return true
end

function waveClear(player, waveid, arena)
    player:sendTextMessage(MESSAGE_STATUS_CONSOLE_BLUE, "You cleared wave " .. waveid .. ".")
    if player:getMaxHealth()-player:getHealth() > 0 then
        player:addHealth(player:getMaxHealth()-player:getHealth())
    end
    return true
end

function jokerDeath(player, waveid, arena)
    player:say("MUAHAHAHA", TALKTYPE_MONSTER_SAY, false, player, arena.position)
end

function arenaStart(player, arena)
    player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "You have entered the arena " .. arena.name .. ".")
end

function arenaThink(arena, interval)
    local players = arena:getPlayersInside()
    if #players == 0 then
        arena:reset()
    else
        for i, player in ipairs(players) do
            player:addHealth(-50)
        end
    end
end

local arena = Arena("Hell", Position(146, 432, 7), Position(149, 432, 7), 1, Position(146, 427, 7))
arena:addPlayerPosition(Position(150, 438, 7))
arena:addWaves(unpack(waves))
arena:setJokerCreature("Bug")
arena:setDelayWaves(5000)
arena:setRewardCallback(rewardPlayers)
arena:setCheckCallback(checkPlayer)
arena:setSpawnCallback(spawnBroadcast)
arena:setWaveclearCallback(waveClear)
arena:setJokerdeathCallback(jokerDeath)

arena:setStartCallback(arenaStart)
arena:setThinkCallback(arenaThink)

function onUse(player, item, fromPosition, target, toPosition, isHotkey)
    if item:getId() == config.levers[1] then
        local ret = arena:useLever(player)

        if ret then
            item:transform(config.levers[2])
        else
            item:getPosition():sendMagicEffect(CONST_ME_POFF)
        end

    elseif item:getId() == config.levers[2] then
        item:transform(config.levers[1])
    end

    return true
end

In this example I used the callbacks to:
Send messages. (This is all handled through the callbacks so you can customize it for each arena as you like)
Heal the player at every waveclear
Add the reward, in this case 100 crystal coins and to set a storage to 1.
Check if the players don't have that storage set so players can only do it once.
Make a monster say effect once you kill the joker.

NEW

Think function to reset the arena when there is no player inside and if there is players inside, damage them -50 every interval.
Start callback to send message when players enter the arena.

Things missing in the example:
You can add more than 1 player position to have team arenas. And levels/vocation for each position. (Just add another line of arena:addPlayerPosition with a different position.)


Alright thats it use it for whatever you want. If something is missing or if you have any sugestion just post here.

Video:
 
Last edited:
Wow, thank you for your contribution MatheusMkalo.

This script is very-well written and flexible. I have a pretty old arena script that I was considering rewriting, but I might not have to start from scratch anymore.

Thank you!
Red
 
There was a issue with the joker function because monsters are loaded after actions so it would say that the joker creature does not exist on the startup so I removed that check. So set the name correctly otherwise it will give stackoverflow error or crash because infinit loop.

Lib pastebin changed.
 
@MatheusMkalo Hello! First of all, great work on that scripts, it works perfectly.
I did some changes to add a storage +1 everytime a wave is cleared and give a reward according to that storage.. But i've encountered a problem here. Is it possible to make character, instead of dying, tp him to the exit and give the reward that he deserves?
 
Lib updated! You can see what was added below NEW in the posts
@MatheusMkalo Hello! First of all, great work on that scripts, it works perfectly.
I did some changes to add a storage +1 everytime a wave is cleared and give a reward according to that storage.. But i've encountered a problem here. Is it possible to make character, instead of dying, tp him to the exit and give the reward that he deserves?

Alright now that I updated the lib you can. Use something like this:
Code:
function arenaStart(player, arena)
    player:registerEvent("ArenaDeath")
end

And the event is a "preparedeath" like this:
Code:
function onPrepareDeath(player, killer)
    local arena = player:getLastArena()
    if arena and player:isInsideArena(arena) then
        player:addHealth(player:getMaxHealth())
        player:unregisterEvent("ArenaDeath")
        player:teleportTo(arena.rewardpos)
        if arena.rewardcallback then
            arena.rewardcallback(player, arena)
        end

        return false
    end

    return true
end

Change to suit your code. Also make it unregister the event in the reward callback.
 
Last edited:
@MatheusMkalo It's working perfect. I nearly have it done. One last issue, is it possible to make waves "unpack" EVEN if the last wave havent been killed?

f.e: Wave 1 spawns, after X time, wave 2 spawns. (Even there's still monsters alive from wave 1)..

I thought that getting rid of the joker would work that way, but it didnt.. soooo... any solutions? Thanks!
 
@MatheusMkalo It's working perfect. I nearly have it done. One last issue, is it possible to make waves "unpack" EVEN if the last wave havent been killed?

f.e: Wave 1 spawns, after X time, wave 2 spawns. (Even there's still monsters alive from wave 1)..

I thought that getting rid of the joker would work that way, but it didnt.. soooo... any solutions? Thanks!
Copy the new lib (removed finish from spawnWave and moved to startWave).

Now you have to hardcode it in your spawn callback, check for the waveid if its the second last id you add an event to start the next wave
 
Code:
local waves = {
    [1] = Wave({
            ["Rat"] = 2,
        }),
    [2] = Wave({
            ["Cave Rat"] = 3,
        }),
    [3] = Wave({
            ["Cave Rat"] = 4,
        })
}

local config = {
    levers = {5501},
}


function spawnBroadcast(player, waveid, arena)
    player:sendTextMessage(MESSAGE_STATUS_CONSOLE_BLUE, "Spawning wave " .. waveid .. ".")
    return true
end

function waveClear(player, waveid, arena)
    player:sendTextMessage(MESSAGE_STATUS_CONSOLE_BLUE, "You cleared wave " .. waveid .. ".")

    return true
end

function jokerDeath(player, waveid, arena)
    player:say("MUAHAHAHA", TALKTYPE_MONSTER_SAY, false, player, arena.position)
end

function arenaStart(player, arena)
    player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "You have entered the arena " .. arena.name .. ".")
    player:registerEvent("Mechanica")
end

function arenaThink(arena, interval)
    local players = arena:getPlayersInside()
    if #players == 0 then
        arena:reset()
    else
        for i, player in ipairs(players) do
            player:addHealth(-50)
        end
    end
end

local arena = Arena("Mechanica", Position(31990, 32438, 7), Position(31986, 32444, 7), 4, Position(31986, 32444, 7))
arena:addPlayerPosition(Position(31990, 32444, 7))
arena:addWaves(unpack(waves))
--arena:setJokerCreature("Bug")
arena:setDelayWaves(2000)
Arena:setDelayEnd(2000)
--arena:setRewardCallback(rewardPlayers)
arena:setCheckCallback(checkPlayer)
arena:setSpawnCallback(spawnBroadcast)
arena:setWaveclearCallback(waveClear)
--arena:setJokerdeathCallback(jokerDeath)

arena:setStartCallback(arenaStart)
arena:setThinkCallback(arenaThink)

function onStepIn(player, item, position, fromPosition)
    if not player:isPlayer() then
        return false
    else
        if item.actionid == config.levers[1] then
        local ret = arena:useLever(player)
    end
    end
    return true
   
end
It sapwns only 2 rats at the begining and nothing happen than when I kill it next mobs does not appear
 
Code:
local waves = {
    [1] = Wave({
            ["Rat"] = 2,
        }),
    [2] = Wave({
            ["Cave Rat"] = 3,
        }),
    [3] = Wave({
            ["Cave Rat"] = 4,
        })
}

local config = {
    levers = {5501},
}


function spawnBroadcast(player, waveid, arena)
    player:sendTextMessage(MESSAGE_STATUS_CONSOLE_BLUE, "Spawning wave " .. waveid .. ".")
    return true
end

function waveClear(player, waveid, arena)
    player:sendTextMessage(MESSAGE_STATUS_CONSOLE_BLUE, "You cleared wave " .. waveid .. ".")

    return true
end

function jokerDeath(player, waveid, arena)
    player:say("MUAHAHAHA", TALKTYPE_MONSTER_SAY, false, player, arena.position)
end

function arenaStart(player, arena)
    player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "You have entered the arena " .. arena.name .. ".")
    player:registerEvent("Mechanica")
end

function arenaThink(arena, interval)
    local players = arena:getPlayersInside()
    if #players == 0 then
        arena:reset()
    else
        for i, player in ipairs(players) do
            player:addHealth(-50)
        end
    end
end

local arena = Arena("Mechanica", Position(31990, 32438, 7), Position(31986, 32444, 7), 4, Position(31986, 32444, 7))
arena:addPlayerPosition(Position(31990, 32444, 7))
arena:addWaves(unpack(waves))
--arena:setJokerCreature("Bug")
arena:setDelayWaves(2000)
Arena:setDelayEnd(2000)
--arena:setRewardCallback(rewardPlayers)
arena:setCheckCallback(checkPlayer)
arena:setSpawnCallback(spawnBroadcast)
arena:setWaveclearCallback(waveClear)
--arena:setJokerdeathCallback(jokerDeath)

arena:setStartCallback(arenaStart)
arena:setThinkCallback(arenaThink)

function onStepIn(player, item, position, fromPosition)
    if not player:isPlayer() then
        return false
    else
        if item.actionid == config.levers[1] then
        local ret = arena:useLever(player)
    end
    end
    return true
 
end
It sapwns only 2 rats at the begining and nothing happen than when I kill it next mobs does not appear
Did you add the creaturescripts correctly?
Did you set the center position correctly?
Is the radius of the room really 4 squares?

Arena:setDelayEnd(2000) this should be arena not Arena.
 
Did you add the creaturescripts correctly?
Did you set the center position correctly?
Is the radius of the room really 4 squares?

Arena:setDelayEnd(2000) this should be arena not Arena.
ok it work now
can I make in this script endless wave with timer?
 
@Verrine What was wrong? sometimes my waves dont spawn.. sometimes it works perfect :/
 
Back
Top