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

[TFS 1.1] Monster Arena

Summ

(\/)(;,,;)(\/) Y not?
Staff member
Global Moderator
Joined
Oct 15, 2008
Messages
4,152
Solutions
12
Reaction score
1,107
Location
Germany :O
Orc_Berserker.gif
Monster Arena Player vs. Player

Description:
You need 2 people for this minigame. You stand on the tiles and pull the lever.
Inside the arena each player will get a random summon, which will then attack the enemy's monster. The player whose summon kills the other monster first wins and gets rewarded.

Map:
Mediafire: http://www.mediafire.com/download/qnnqj1rmilmrd5a/monsterarena.otbm
xh9Elvq.jpg


Scripts:

Actions
actions.xml
Code:
<action actionid="1500" script="monsterarena.lua"/>

actions/scripts/monsterarena.lua
Code:
MonsterArena = {
    fromPosition = { Position(1022, 1030, 7), Position(1024, 1030, 7) },
    toPosition = { Position(1020, 1021, 7), Position(1022, 1021, 7) },
    spawnPosition = { Position(1020, 1022, 7), Position(1022, 1020, 7) },
    area = {
        from = Position(1015, 1016, 7),
        to = Position(1027, 1026, 7)
    },
    exitPosition = Position(1022, 1028, 7),
    reward = {itemId = 2160, count = 10},

    blockItemId = 3402,

    -- Only convincable / summonable monsters
    -- You can create custom monsters which are stronger and convincable
    monsters = {'Troll', 'Rat', 'Tortoise', 'Orc Berserker', 'Minotaur'},
    event = 'MonsterArenaDeath',

    players = {}
}

function MonsterArena.hasPlayer(player)
    local position = player:getPosition()
    return position.x >= MonsterArena.area.from.x and position.y >= MonsterArena.area.from.y
            and position.x <= MonsterArena.area.to.x and position.y <= MonsterArena.area.to.y
            and position.z == MonsterArena.area.from.z
end

function MonsterArena.isOccupied()
    for _, pid in ipairs(MonsterArena.players) do
        local player = Player(pid)
        if player and MonsterArena.hasPlayer(player) then
            return true
        end
    end
    return false
end

function MonsterArena.clean()
    for i = 1, #MonsterArena.players do
        MonsterArena.players[i] = nil
    end
end

function onUse(player, item, fromPosition, target, toPosition, isHotkey)
    if item.itemid ~= 1945 then
        item:transform(1946)
        return true
    end

    if MonsterArena.isOccupied() then
        player:sendCancelMessage('The monster arena is currently occupied.')
        return true
    end

    local players = {}
    for _, fromPosition in ipairs(MonsterArena.fromPosition) do
        local creature = Tile(fromPosition):getTopCreature()
        if not creature or not creature:isPlayer() then
            player:sendCancelMessage('You need another player for the monster arena.')
            return true
        end
        table.insert(players, creature)
    end

    MonsterArena.clean()

    local summons = {}
    for i, player in ipairs(players) do
        player:teleportTo(MonsterArena.toPosition[i])
        MonsterArena.fromPosition[i]:sendMagicEffect(CONST_ME_POFF)
        MonsterArena.toPosition[i]:sendMagicEffect(CONST_ME_TELEPORT)

        local monsterName = MonsterArena.monsters[math.random(#MonsterArena.monsters)]
        local monster = Game.createMonster(monsterName, MonsterArena.spawnPosition[i], true)
        monster:setMaster(player)
        monster:registerEvent(MonsterArena.event)
        table.insert(summons, monster)

        Game.createItem(MonsterArena.blockItemId, 1, MonsterArena.spawnPosition[i])

        player:sendTextMessage(MESSAGE_INFO_DESCR, string.format('A %s is fighting for you this round!', monsterName))
        table.insert(MonsterArena.players, player.uid)
    end

    players[1]:setTarget(summons[2])
    players[2]:setTarget(summons[1])

    item:transform(1945)
    return true
end

Creaturescript
creaturescripts.xml
Code:
<event type="death" name="MonsterArenaDeath" script="monsterarenadeath.lua"/>

creaturescripts/scripts/monsterarenadeath.lua
Code:
function onDeath(monster, corpse, killer, mostDamageKiller, unjustified, mostDamageUnjustified)
    local winnerPlayer = killer:getMaster()
    local loserPlayer = monster:getMaster()

    local reward = MonsterArena.reward
    if reward then
        winnerPlayer:sendTextMessage(MESSAGE_INFO_DESCR, 'Your monster won the fight and earned a reward for you!')
        winnerPlayer:addItem(reward.itemId, reward.count)
    else
        winnerPlayer:sendTextMessage(MESSAGE_INFO_DESCR, 'Your monster won the fight!')
    end

    loserPlayer:sendTextMessage(MESSAGE_INFO_DESCR, 'Your monster lost the fight!')

    winnerPlayer:teleportTo(MonsterArena.exitPosition)
    loserPlayer:teleportTo(MonsterArena.exitPosition)
    MonsterArena.exitPosition:sendMagicEffect(CONST_ME_MAGIC_BLUE)

    for _, position in ipairs(MonsterArena.spawnPosition) do
        local item = Tile(position):getItemById(MonsterArena.blockItemId)
        if item then
            item:remove()
        end
    end

    killer:remove()
    return true
end
 
Looking forward to test this out! :)

Kind Regards,
Eldin.
 
"You need another player for the monster Arena", 2 people standing on the tiles, tried setting the tiles to actionid 1500 aswell but it didnt work
 
Hi! My TFS is 1.1, I did something wrong?

I'm getting this error on Distro


Code:
Lua Script Error: [CreatureScript Interface]
data/creaturescripts/scripts/events/monsterarenadeath.lua:onDeath
data/creaturescripts/scripts/events/monsterarenadeath.lua:7: attempt to index lo
cal 'winnerPlayer' (a nil value)
stack traceback:
        [C]: in function '__index'
        data/creaturescripts/scripts/events/monsterarenadeath.lua:7: in function
<data/creaturescripts/scripts/events/monsterarenadeath.lua:1>

The script is:

Code:
function onDeath(monster, corpse, killer, mostDamageKiller, unjustified, mostDamageUnjustified)
    local winnerPlayer = killer:getMaster()
    local loserPlayer = monster:getMaster()

    local reward = MonsterArena.reward
    if reward then
        winnerPlayer:sendTextMessage(MESSAGE_INFO_DESCR, 'Your monster won the fight and earned a reward for you!')
        winnerPlayer:addItem(reward.itemId, reward.count)
    else
        winnerPlayer:sendTextMessage(MESSAGE_INFO_DESCR, 'Your monster won the fight!')
    end

    loserPlayer:sendTextMessage(MESSAGE_INFO_DESCR, 'Your monster lost the fight!')

    winnerPlayer:teleportTo(MonsterArena.exitPosition)
    loserPlayer:teleportTo(MonsterArena.exitPosition)
    MonsterArena.exitPosition:sendMagicEffect(CONST_ME_MAGIC_BLUE)

    for _, position in ipairs(MonsterArena.spawnPosition) do
        local item = Tile(position):getItemById(MonsterArena.blockItemId)
        if item then
            item:remove()
        end
    end

    killer:remove()
    return true
end

If is needed:
local deathListEnabled = true
local maxDeathRecords = 5

function onDeath(player, corpse, killer, mostDamageKiller, unjustified, mostDamageUnjustified)
local playerId = player:getId()
if nextUseStaminaTime[playerId] ~= nil then
nextUseStaminaTime[playerId] = nil
end

player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "You are dead.")
if not deathListEnabled then
return
end

local byPlayer = 0
local killerName
if killer ~= nil then
if killer:isPlayer() then
byPlayer = 1
else
local master = killer:getMaster()
if master and master ~= killer and master:isPlayer() then
killer = master
byPlayer = 1
end
end
killerName = killer:getName()
else
killerName = "field item"
end

local byPlayerMostDamage = 0
local mostDamageKillerName
if mostDamageKiller ~= nil then
if mostDamageKiller:isPlayer() then
byPlayerMostDamage = 1
else
local master = mostDamageKiller:getMaster()
if master and master ~= mostDamageKiller and master:isPlayer() then
mostDamageKiller = master
byPlayerMostDamage = 1
end
end
mostDamageName = mostDamageKiller:getName()
else
mostDamageName = "field item"
end

local playerGuid = player:getGuid()
db.query("INSERT INTO `player_deaths` (`player_id`, `time`, `level`, `killed_by`, `is_player`, `mostdamage_by`, `mostdamage_is_player`, `unjustified`, `mostdamage_unjustified`) VALUES (" .. playerGuid .. ", " .. os.time() .. ", " .. player:getLevel() .. ", " .. db.escapeString(killerName) .. ", " .. byPlayer .. ", " .. db.escapeString(mostDamageName) .. ", " .. byPlayerMostDamage .. ", " .. (unjustified and 1 or 0) .. ", " .. (mostDamageUnjustified and 1 or 0) .. ")")
local resultId = db.storeQuery("SELECT `player_id` FROM `player_deaths` WHERE `player_id` = " .. playerGuid)

local deathRecords = 0
local tmpResultId = resultId
while tmpResultId ~= false do
tmpResultId = result.next(resultId)
deathRecords = deathRecords + 1
end

if resultId ~= false then
result.free(resultId)
end

local limit = deathRecords - maxDeathRecords
if limit > 0 then
db.asyncQuery("DELETE FROM `player_deaths` WHERE `player_id` = " .. playerGuid .. " ORDER BY `time` LIMIT " .. limit)
end

if byPlayer == 1 then
local targetGuild = player:getGuild()
targetGuild = targetGuild and targetGuild:getId() or 0
if targetGuild ~= 0 then
local killerGuild = killer:getGuild()
killerGuild = killerGuild and killerGuild:getId() or 0
if killerGuild ~= 0 and targetGuild ~= killerGuild and isInWar(playerId, killer:getId()) then
local warId = false
resultId = db.storeQuery("SELECT `id` FROM `guild_wars` WHERE `status` = 1 AND ((`guild1` = " .. killerGuild .. " AND `guild2` = " .. targetGuild .. ") OR (`guild1` = " .. targetGuild .. " AND `guild2` = " .. killerGuild .. "))")
if resultId ~= false then
warId = result.getDataInt(resultId, "id")
result.free(resultId)
end

if warId ~= false then
db.asyncQuery("INSERT INTO `guildwar_kills` (`killer`, `target`, `killerguild`, `targetguild`, `time`, `warid`) VALUES (" .. db.escapeString(killerName) .. ", " .. db.escapeString(player:getName()) .. ", " .. killerGuild .. ", " .. targetGuild .. ", " .. os.time() .. ", " .. warId .. ")")
end
end
end
end
end

-------------------------------------- @edit


SOLVED!

https://otland.net/threads/error-attempt-to-index-local-a-nil-value.234683/#post-2263964
 
Last edited:
Which would i have to add to the code if i want people to get removed certain item to take part in the event?

Thanks!. Awesome script.
 
Is it possible to make it impossible to stop attacking the other summon? Because people can block the spawn if they attack their opponents monster and then stop attacking it because then their summon will stop attacking either. Or maybe add something like kick after "X" amount of time if there still is no winner kick all players and send a message.
 
Last edited:
Lua:
function MonsterArena.timeout()  
    for _, k in MonsterArena.players do
        local p = Player(k)
        if p then
            p:sendTextMessage(MESSAGE_INFO_DESCR, 'Times up, nobody won the fight!')
            p:teleportTo(MonsterArena.exitPosition)
            for _, l in pairs(p:getSummons()) do
                if l then l:remove() end
            end
        end
    end
    MonsterArena.exitPosition:sendMagicEffect(CONST_ME_MAGIC_BLUE)
    for _, position in ipairs(MonsterArena.spawnPosition) do
        local item = Tile(position):getItemById(MonsterArena.blockItemId)
        if item then
            item:remove()
        end
    end
end

addEvent(MonsterArena.timeout(),5*60*1000)
 
Back
Top