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

Dungeon System [1.2 TFS]

Piifafa

Member
Joined
Apr 16, 2023
Messages
67
Reaction score
16
Hello friends, I'm trying to create a small Dungeon system on my server that is simple and functional. It uses almost an aside from my otserver's The Annihilator Quest script. In a few words I will show you how it works.

A person uses the lever and can pull it with up to 4 friends or alone.
1694267493025.png
Script:
Lua:
function onUse(player, item, fromPosition, target, toPosition)

    local annihiCenter = Position(6061, 5852, 7)
    local spectators = Game.getSpectators(annihiCenter, false, false, 10, 10, 10, 10)
    local needPlayers = 1

    local demonSpots = {
                Position(6057, 5856, 7),
                Position(6059, 5857, 7),
                Position(6060, 5862, 7),
                Position(6058, 5862, 7),
                Position(6056, 5865, 7),
                Position(6058, 5871, 7),
                Position(6057, 5879, 7),
                Position(6068, 5879, 7),
                Position(6065, 5876, 7),
                Position(6070, 5871, 7),
                Position(6077, 5875, 7),
                Position(6082, 5867, 7),
                Position(6075, 5853, 7),
                Position(6064, 5858, 7),
                Position(6064, 5868, 7),

            }

    for ci=1,#spectators do
        local creature = spectators[ci]
        if creature:isPlayer() then
            player:sendTextMessage(MESSAGE_INFO_DESCR, "Have another team inside the annihilator.")
            return true
        end
    end

    for ci=1,#spectators do
        local creature = spectators[ci]
        if creature:isMonster() then
            creature:remove()
        end
    end

    for dsp=1,#demonSpots do
        local dPos = demonSpots[dsp]
        Game.createMonster('Big Orc Warrior',dPos)
    end

    local playersInside = {}
    for pi=1,needPlayers do
        local playerPos = Position(fromPosition.x-pi,fromPosition.y,fromPosition.z)
        local PlayerTile = Tile(playerPos)
        local player = PlayerTile:getTopCreature()
        if player then
            if player:isPlayer() then
                local playerSpot = {pid=player,pos=playerPos}
                table.insert(playersInside,playerSpot)
            end
        end
    end

    if #playersInside == needPlayers then
        for pgo=1,needPlayers do
            local player = playersInside[pgo].pid
            local playerPos = playersInside[pgo].pos
            playerPos:sendMagicEffect(CONST_ME_POFF)
            local newPos = Position(annihiCenter.x-pgo,annihiCenter.y,annihiCenter.z)
            player:teleportTo(newPos)
            newPos:sendMagicEffect(CONST_ME_TELEPORT)
        end
    else
        player:sendTextMessage(MESSAGE_INFO_DESCR, "You need ".. needPlayers .." players to start dungeon.")
        return true
    end

    if item:getId() == 2773 then
        item:transform(2772)
    else
        item:transform(2773)
    end
    return true
end

1) Here I have a problem, I would like one person to enter, only every 24 hours, I don't know how to do this for the 4 who would enter there.

2) Another problem I have is how can I add more creatures than the ones I have? And how do I know why the dungeon is busy right now?

1694267701464.png
while they are there it is occupied, but if you go outside, it ends up being unoccupied, I would like the entire map to be occupied.
Thank you from the bottom of my heart to anyone who can help me! Good weekend to everyone.
 
Hello friends, I'm trying to create a small Dungeon system on my server that is simple and functional. It uses almost an aside from my otserver's The Annihilator Quest script. In a few words I will show you how it works.

A person uses the lever and can pull it with up to 4 friends or alone.
View attachment 78286
Script:
Lua:
function onUse(player, item, fromPosition, target, toPosition)

    local annihiCenter = Position(6061, 5852, 7)
    local spectators = Game.getSpectators(annihiCenter, false, false, 10, 10, 10, 10)
    local needPlayers = 1

    local demonSpots = {
                Position(6057, 5856, 7),
                Position(6059, 5857, 7),
                Position(6060, 5862, 7),
                Position(6058, 5862, 7),
                Position(6056, 5865, 7),
                Position(6058, 5871, 7),
                Position(6057, 5879, 7),
                Position(6068, 5879, 7),
                Position(6065, 5876, 7),
                Position(6070, 5871, 7),
                Position(6077, 5875, 7),
                Position(6082, 5867, 7),
                Position(6075, 5853, 7),
                Position(6064, 5858, 7),
                Position(6064, 5868, 7),

            }

    for ci=1,#spectators do
        local creature = spectators[ci]
        if creature:isPlayer() then
            player:sendTextMessage(MESSAGE_INFO_DESCR, "Have another team inside the annihilator.")
            return true
        end
    end

    for ci=1,#spectators do
        local creature = spectators[ci]
        if creature:isMonster() then
            creature:remove()
        end
    end

    for dsp=1,#demonSpots do
        local dPos = demonSpots[dsp]
        Game.createMonster('Big Orc Warrior',dPos)
    end

    local playersInside = {}
    for pi=1,needPlayers do
        local playerPos = Position(fromPosition.x-pi,fromPosition.y,fromPosition.z)
        local PlayerTile = Tile(playerPos)
        local player = PlayerTile:getTopCreature()
        if player then
            if player:isPlayer() then
                local playerSpot = {pid=player,pos=playerPos}
                table.insert(playersInside,playerSpot)
            end
        end
    end

    if #playersInside == needPlayers then
        for pgo=1,needPlayers do
            local player = playersInside[pgo].pid
            local playerPos = playersInside[pgo].pos
            playerPos:sendMagicEffect(CONST_ME_POFF)
            local newPos = Position(annihiCenter.x-pgo,annihiCenter.y,annihiCenter.z)
            player:teleportTo(newPos)
            newPos:sendMagicEffect(CONST_ME_TELEPORT)
        end
    else
        player:sendTextMessage(MESSAGE_INFO_DESCR, "You need ".. needPlayers .." players to start dungeon.")
        return true
    end

    if item:getId() == 2773 then
        item:transform(2772)
    else
        item:transform(2773)
    end
    return true
end

1) Here I have a problem, I would like one person to enter, only every 24 hours, I don't know how to do this for the 4 who would enter there.

2) Another problem I have is how can I add more creatures than the ones I have? And how do I know why the dungeon is busy right now?

View attachment 78287
while they are there it is occupied, but if you go outside, it ends up being unoccupied, I would like the entire map to be occupied.
Thank you from the bottom of my heart to anyone who can help me! Good weekend to everyone.

1. You would need to set a storage based on os.time, credits to @Summ and the OTLand search feature for this one.
Lua:
-- Setting the 2 hour "cooldown"
player:setStorageValue(YOUR_STORAGE_KEY, os.time() + 7200)

-- Checking if the player can enter again
if os.time() > player:getStorageValue(YOUR_STORAGE_KEY) then
    -- player can enter again
else
    -- player has to wait
end

2a). To add more monsters, signify where you would like them to spawn, for example on Line 22 your last position is: Position(6064, 5868, 7),
Copy/paste this line below it and modify the x, y, z portions to where you would like the new monster to spawn.

2b). To increase the size of the arena/area it checks for participants in the dungeon is set by the last 4 values that signify (north, west, south, east) <-- probably not in that order though. So essentially it is checking 10 sqm in each direction from the annihiCenter
local spectators = Game.getSpectators(annihiCenter, false, false, 10, 10, 10, 10)
 
1. You would need to set a storage based on os.time, credits to @Summ and the OTLand search feature for this one.
Lua:
-- Setting the 2 hour "cooldown"
player:setStorageValue(YOUR_STORAGE_KEY, os.time() + 7200)

-- Checking if the player can enter again
if os.time() > player:getStorageValue(YOUR_STORAGE_KEY) then
    -- player can enter again
else
    -- player has to wait
end

2a). To add more monsters, signify where you would like them to spawn, for example on Line 22 your last position is: Position(6064, 5868, 7),
Copy/paste this line below it and modify the x, y, z portions to where you would like the new monster to spawn.

2b). To increase the size of the arena/area it checks for participants in the dungeon is set by the last 4 values that signify (north, west, south, east) <-- probably not in that order though. So essentially it is checking 10 sqm in each direction from the annihiCenter
local spectators = Game.getSpectators(annihiCenter, false, false, 10, 10, 10, 10)
I would like to add different shows.
 
Heyo instead of using getSpectators i would use just tables

Lua:
local DungeonSystem = {}

function DungeonSystem:addPlayer(player)
  
    if not self.players then
       self.players = {}
    end
  
    return table.insert(self.players, player:getId())
end

function DungeonSystem:removePlayer(player)
  
    if not self.players then
       return false
    end
  
    for i, v in pairs(self.players) do
        if v == player:getId() then
           return table.remove(self.players, i)
        end
    end
    return false
end

function DungeonSystem:getPlayers()
    if not self.players then
       return false
    end
    return self.players
end
  
function DungeonSystem:isDungeonEmpty()
    if not self.players or #self.players == 0 then
       return true
    end
    return false
end

And just simply add these functions in correctly way in events like onDeath, onLogout, onFinish to prevent bugs =)
with this way server dont need to scan whole map based on position, you can easily get participants of dungeon and do with them whatever you wanna with almost 0 memory usage

(And you can do exactly the same way for monsters that are supposed to be deleted when new team join the dungeon and old team failed the dungeon)
 
Last edited:
I ended up doing it like this. How can I improve then?
Heyo instead of using getSpectators i would use just tables

Lua:
local DungeonSystem = {}

function DungeonSystem:addPlayer(player)
 
    if not self.players then
       self.players = {}
    end
 
    return table.insert(self.players, player:getId())
end

function DungeonSystem:removePlayer(player)
 
    if not self.players then
       return false
    end
 
    for i, v in pairs(self.players) do
        if v == player:getId() then
           return table.remove(self.players, i)
        end
    end
    return false
end

function DungeonSystem:getPlayers()
    if not self.players then
       return false
    end
    return self.players
end
 
function DungeonSystem:isDungeonEmpty()
    if not self.players or #self.players == 0 then
       return true
    end
    return false
end

And just simply add these functions in correctly way in events like onDeath, onLogout, onFinish to prevent bugs =)
with this way server dont need to scan whole map based on position, you can easily get participants of dungeon and do with them whatever you wanna with almost 0 memory usage

(And you can do exactly the same way for monsters that are supposed to be deleted when new team join the dungeon and old team failed the dungeon)
I can't understand how you would do it.


Lua:
function onUse(player, item, fromPosition, target, toPosition)
    local annihiCenter = Position(6061, 5852, 7)
    local spectators = Game.getSpectators(annihiCenter, false, false, 15, 15, 15, 15)
    local needPlayers = 1

    -- Verifique se há jogadores dentro da área
    local playersInside = {}
    for pi=1, needPlayers do
        local playerPos = Position(fromPosition.x - pi, fromPosition.y, fromPosition.z)
        local PlayerTile = Tile(playerPos)
        local player = PlayerTile:getTopCreature()
        if player and player:isPlayer() then
            local playerSpot = { pid = player, pos = playerPos }
            table.insert(playersInside, playerSpot)
        end
    end

    if #playersInside < needPlayers then
        player:sendTextMessage(MESSAGE_INFO_DESCR, "You need ".. needPlayers .." players inside to start the dungeon.")
        return true
    end

    -- Agora verifique a storage e o tempo
    local lastUsedTime = player:getStorageValue(45396)
    local currentTime = os.time()

    if lastUsedTime == 0 or currentTime >= lastUsedTime + 24 * 60 * 60 then
        player:setStorageValue(45396, currentTime)
    else
        local remainingTime = (lastUsedTime + 24 * 60 * 60) - currentTime
        local hours = math.floor(remainingTime / 3600)
        local minutes = math.floor((remainingTime % 3600) / 60)

        local errorMessage = string.format("You have already used this item. You can use it again in %d hours and %d minutes.", hours, minutes)
        player:sendTextMessage(MESSAGE_INFO_DESCR, errorMessage)
        return true
    end

    local demonSpots = {
        Position(6057, 5856, 7),
        Position(6059, 5857, 7),
        Position(6060, 5862, 7),
        Position(6058, 5862, 7),
        Position(6056, 5865, 7),
        Position(6058, 5871, 7),
        Position(6057, 5879, 7),
        Position(6068, 5879, 7),
        Position(6065, 5876, 7),
        Position(6070, 5871, 7),
        Position(6077, 5875, 7),
        Position(6082, 5867, 7),
        Position(6075, 5853, 7),
        Position(6064, 5858, 7),
        Position(6064, 5868, 7),
        -- Adicione novas posições aqui, se desejado
    }

    local additionalCreatures = {
        { name = 'Big Orc Warrior', position = Position(6060, 5862, 7) },
        { name = 'Big Orc', position = Position(6058, 5862, 7) },
        { name = 'Big Orc', position = Position(6060, 5875, 7) },
        { name = 'Big Orc', position = Position(6060, 5875, 7) },
        { name = 'Big Orc', position = Position(6056, 5873, 7) },
        { name = 'Big Orc', position = Position(6062, 5872, 7) },
        { name = 'Big Orc', position = Position(6070, 5875, 7) },
        { name = 'Big Orc', position = Position(6070, 5865, 7) },
        { name = 'Big Orc', position = Position(6070, 5862, 7) },
        { name = 'Big Orc', position = Position(6069, 5858, 7) },
        { name = 'Big Orc', position = Position(6062, 5860, 7) },
        { name = 'Big Orc', position = Position(6075, 5865, 7) },
        { name = 'Big Orc', position = Position(6077, 5865, 7) },
        { name = 'Big Orc', position = Position(6079, 5857, 7) },
        { name = 'Big Orc', position = Position(6079, 5858, 7) },
        { name = 'Fernfang', position = Position(6062, 5876, 7) },
        -- Adicione mais criaturas com nomes e posições diferentes, se desejar
    }

    for ci=1, #spectators do
        local creature = spectators[ci]
        if creature:isPlayer() then
            player:sendTextMessage(MESSAGE_INFO_DESCR, "There's another team inside the Dungeon.")
            return true
        end
    end

    for ci=1, #spectators do
        local creature = spectators[ci]
        if creature:isMonster() then
            creature

:remove()
        end
    end

    for dsp=1, #demonSpots do
        local dPos = demonSpots[dsp]
        Game.createMonster('Big Orc Warrior', dPos)
    end

    for i=1, #additionalCreatures do
        local creatureData = additionalCreatures[i]
        Game.createMonster(creatureData.name, creatureData.position)
    end

    -- Restante do seu script permanece o mesmo
    -- ...

    if item:getId() == 2773 then
        item:transform(2772)
    else
        item:transform(2773)
    end
    return true
end
 
Back
Top