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

Random Titles Quest

juansanchez

Advanced OT User
Joined
Apr 2, 2015
Messages
223
Reaction score
156


Hey otland people!
Today i need a help with a quest that i'm trying to do on my server. A friend of mine told me it's easy, but i just don't know how to do it.

So, first of all, when the player enter the quest, he starts in this room:

cpqIs4X.jpg


At the very center. No mobs around, nothing. As you can see there are the pressure titles around. When the player walks in the pressure title, he gets teleported to another room, just as the first one. But this time, there will be 8 monster around him (lets say we have, demons, dragons and hydras). When the player steps in the title, he gets teleported to a random room in the area (there will be lot's of rooms just like the first one), and when he gets teleported, 8 monster will spawn around him, either Demons, Dragons or Hydras, also random.

So basically, the player gets teleported to a random room in a certain area. Eight random monsters spawn around him, but not, eight random like, 2 dragons, 1 demon, 5 hydras. Like, it could be 8 demons, it could be 8 dragons or it could be 8 hydras.

I hope someone can help me out with this. If someone has any questions, just let me know. I'd really appreciate if someone could help me. Thanks for the attention.

 
Alright. I have time to test my script from earlier tonight.
As I've said wouldn't it be simpler if you just teleport the player back again to the center and clean the room so it looks like it is another room?

The amount of effort to add an actionid to those tiles is just... '-'

Then if it was going to be 25 rooms, just set the chance of the tile teleporting the player to the final room to 1/25
Not really. If your trying to confuse your players, then going into the same room multiple times won't help.
Going to random rooms will open up more map, and make the quest seem harder/more intricate then it actually is.
Mystery is a good incentive for players to continue the quest.
And having the thread moved really confused me. :P
 
Alright. I have time to test my script from earlier tonight.

Not really. If your trying to confuse your players, then going into the same room multiple times won't help.
Going to random rooms will open up more map, and make the quest seem harder/more intricate then it actually is.
Mystery is a good incentive for players to continue the quest.
And having the thread moved really confused me. :p

The problem is, if it is really a quest like this, I guess you should do it alone, so only 1 player could enter inside the room, and checking if there is a player inside 1 room is okay, but checking if there is a player inside 25 rooms could take a while. Of course you could use globalstorages to update when a player enters and leaves the quest but the amount of effort put into it to make it work properly would not be worth it. (You would have to do atleast an onDeath, onLogin and onStartup to reset the globalstorage)
 
@juansanchez
Or just let the player go willie-nillie, and let a server reset every 24 hour do the work for you. :p
If you remove the monsters when the player leaves an area, then they simply have to run to the tiles until they win. Making the monsters static, and not removing them, gives the character a reason to kill them.. so they don't get overwhelmed the next time they enter that room.

In either case, we are just scripting it the way OP currently wants it.

Fully tested.
The only time you'll receive an error is when the room is packed full of monsters, and they have no-where to spawn.

Code:
local win_chance = 500 -- 1/x = win chance.. 1/500 (1 out of 500)
local reward_area = {x = 1398, y = 1419, z = 7}

local pos = {
   [1] =  {x = 1398, y = 1419, z = 7},
   [2] =  {x = 1400, y = 1419, z = 7},
   [3] =  {x = 1402, y = 1419, z = 7}
}

local monsters = {
   [1] = {name = "cave rat"},
   [2] = {name = "cave rat"},
   [3] = {name = "cave rat"}
}

function onStepIn(cid, item, position, fromPosition)
 
   -- Send to win area if lucky
   if math.random(1, win_chance) == 1 then
     doTeleportThing(cid, reward_area)
     return true
   end
 
   -- teleport random position
   local randP = pos[math.random(#pos)]
   doTeleportThing(cid, randP)
 
   -- choose random monster
   local randM = monsters[math.random(#monsters)]
 
   -- spawn 8 of selected random monster in area around random position
   for var = 1, 8 do
     doCreateMonster(randM.name, {x = math.random(randP.x - 5, randP.x + 5), y = math.random(randP.y - 4, randP.y + 4), z = randP.z})
   end
 
   return true
end

@Codex NG
The issue was line 30, (now line 33).
It was generating a table where it wanted a value.
I did it this way, so that a new location is chosen each time it loops.
Unsure if there is a better way to do this.
 
Last edited by a moderator:
@juansanchez
Or just let the player go willie-nillie, and let a server reset every 24 hour do the work for you. :p
If you remove the monsters when the player leaves an area, then they simply have to run to the tiles until they win. Making the monsters static, and not removing them, gives the character a reason to kill them.. so they don't get overwhelmed the next time they enter that room.

In either case, we are just scripting it the way OP currently wants it.

Fully tested.
The only time you'll receive an error is when the room is packed full of monsters, and they have no-where to spawn.

The thing is I don't know if the player has to go inside by himself or if he is allowed to go with other persons, as he asked for the monsters to be spawned beside the player in that image:

Here is my version for this, it works like this:

If the total number of rooms were going to be 3, the number of players allowed inside them is 2 so they always have 1 room free to teleport to.
*The player can only leave its assigned room when he kills all the 8 spawned monsters
*Only one player is allowed inside the room.

Code:
Room = {}

function Room:new(pos, sqarea)
    return setmetatable({pos=pos, sqarea=sqarea, monsters={}}, {__index = Room})
end

function Room:isInside(pos)
    if pos.x >= self.pos.x-(self.sqarea-1)/2 and pos.y >= self.pos.y-(self.sqarea-1)/2 and pos.x <= self.pos.x+(self.sqarea-1)/2 and pos.y <= self.pos.y+(self.sqarea-1)/2 then
        return true
    end
end

function Room:teleportPlayer(player)
    if not self.player or not (isPlayer(self.player) and self:isInside(getCreaturePosition(self.player))) then
        self.player = player
        doTeleportThing(player, self.pos, false)
        doSendMagicEffect(self.pos, 10)
        return true
    end
end

function Room:addMonster(name)
    local bool, monsters = self:areMonstersDead()
    if not bool then
        for i = 1, #monsters do
            doRemoveCreature(monsters[i])
        end
    end
    for y = self.pos.y-1, self.pos.y+1 do
        for x = self.pos.x-1, self.pos.x+1 do
            if x ~= self.pos.x or y ~= self.pos.y then
                local _cid = doSummonCreature(name, {x=x, y=y, z=self.pos.z})
                table.insert(self.monsters, _cid)
            end
        end
    end
end

function Room:areMonstersDead()
    local ret = true
    local t = {}
    for i, creature in ipairs(self.monsters) do
        if isCreature(creature) then
            ret = false
            table.insert(t, creature)
        end
    end
    return ret, t
end

function isPlayerInside(rooms, player)
    local ppos = getCreaturePosition(player)
    for i, room in ipairs(rooms) do
        if room:isInside(ppos) and room.player == player then
            return room
        end
    end
end

function getFreeRooms(rooms)
    local free = {}
    for i, room in ipairs(rooms) do
        if not room.player or not (isPlayer(room.player) and room:isInside(getCreaturePosition(room.player))) then
            table.insert(free, room)
        end
    end
    return free
end

local square = 3 -- SQUARE SIZE OF ROOM MUST BE AN ODD NUMBER! 3x3, 5x5 etc..

-- Room:new(centerpos, squaresize)
local rooms = {
[1] = Room:new({x=277, y=59, z=7}, square),
[2] = Room:new({x=281, y=59, z=7}, square),
[3] = Room:new({x=285, y=59, z=7}, square),
}
local successchance = 1/10 -- 1 out of 10 tries, 10%
local successpos = {x=270, y=56, z=7} -- pos of final room
local monsters = {"wolf", "troll"} -- monsters

function onStepIn(cid, item, pos, frompos)
    if isPlayer(cid) then
        local freeRooms = getFreeRooms(rooms)
        local isinside = isPlayerInside(rooms, cid)
        if (isinside and #freeRooms > 0) or #freeRooms > 1 then
            if isinside and not isinside:areMonstersDead() then
                doTeleportThing(cid, frompos, true)
                return doPlayerSendCancel(cid, "You got to kill all monsters first.")
            end
            local successrd = math.random(1, 100)
            if isinside and successrd <= successchance*100 then
                doTeleportThing(cid, successpos)
                doSendMagicEffect(successpos, 10)
            else
                local rd = math.random(#freeRooms)
                freeRooms[rd]:teleportPlayer(cid)
                freeRooms[rd]:addMonster(monsters[math.random(#monsters)])
            end
        else
            doTeleportThing(cid, frompos, true)
            return doPlayerSendCancel(cid, "All rooms are full now, please wait.")
        end
    end
end

EDIT: Use the same actionid for all tiles inside the rooms and use the same actionid on the tile that the player is going to enter the rooms for the first time. Be sure players cant logout inside the rooms just for safety, it will work even if they logout inside them.
 
Last edited:
@juansanchez
Or just let the player go willie-nillie, and let a server reset every 24 hour do the work for you. :p
If you remove the monsters when the player leaves an area, then they simply have to run to the tiles until they win. Making the monsters static, and not removing them, gives the character a reason to kill them.. so they don't get overwhelmed the next time they enter that room.

In either case, we are just scripting it the way OP currently wants it.

Fully tested.
The only time you'll receive an error is when the room is packed full of monsters, and they have no-where to spawn.

Code:
local win_chance = 500 -- 1/x = win chance.. 1/500 (1 out of 500)
local reward_area = {x = 1398, y = 1419, z = 7}

local pos = {
   [1] =  {x = 1398, y = 1419, z = 7},
   [2] =  {x = 1400, y = 1419, z = 7},
   [3] =  {x = 1402, y = 1419, z = 7}
}

local monsters = {
   [1] = {name = "cave rat"},
   [2] = {name = "cave rat"},
   [3] = {name = "cave rat"}
}

function onStepIn(cid, item, position, fromPosition)

   -- Send to win area if lucky
   if math.random(1, win_chance) == 1 then
     doTeleportThing(cid, reward_area)
     return true
   end

   -- teleport random position
   local randP = pos[math.random(#pos)]
   doTeleportThing(cid, randP)

   -- choose random monster
   local randM = monsters[math.random(#monsters)]

   -- spawn 8 of selected random monster in area around random position
   for var = 1, 8 do
     doCreateMonster(randM.name, {x = math.random(randP.x - 5, randP.x + 5), y = math.random(randP.y - 4, randP.y + 4), z = randP.z})
   end

   return true
end

@Codex NG
The issue was line 30, (now line 33).
It was generating a table where it wanted a value.
I did it this way, so that a new location is chosen each time it loops.
Unsure if there is a better way to do this.

It worked perfectly! But.. The monster are not spawning around the player, they're spawning in random places in the room.
Think of a Exori. It hits the area around the player. That's the area i'd like the monsters to spawn in, so the player cannot run from the monsters.
 
The thing is I don't know if the player has to go inside by himself or if he is allowed to go with other persons, as he asked for the monsters to be spawned beside the player in that image:


Here is my version for this, it works like this:

If the total number of rooms were going to be 3, the number of players allowed inside them is 2 so they always have 1 room free to teleport to.
*The player can only leave its assigned room when he kills all the 8 spawned monsters
*Only one player is allowed inside the room.

Code:
Room = {}

function Room:new(pos, sqarea)
    return setmetatable({pos=pos, sqarea=sqarea, monsters={}}, {__index = Room})
end

function Room:isInside(pos)
    if pos.x >= self.pos.x-(self.sqarea-1)/2 and pos.y >= self.pos.y-(self.sqarea-1)/2 and pos.x <= self.pos.x+(self.sqarea-1)/2 and pos.y <= self.pos.y+(self.sqarea-1)/2 then
        return true
    end
end

function Room:teleportPlayer(player)
    if not self.player or not (isPlayer(self.player) and self:isInside(getCreaturePosition(self.player))) then
        self.player = player
        doTeleportThing(player, self.pos, false)
        doSendMagicEffect(self.pos, 10)
        return true
    end
end

function Room:addMonster(name)
    local bool, monsters = self:areMonstersDead()
    if not bool then
        for i = 1, #monsters do
            doRemoveCreature(monsters[i])
        end
    end
    for y = self.pos.y-1, self.pos.y+1 do
        for x = self.pos.x-1, self.pos.x+1 do
            if x ~= self.pos.x or y ~= self.pos.y then
                local _cid = doSummonCreature(name, {x=x, y=y, z=self.pos.z})
                table.insert(self.monsters, _cid)
            end
        end
    end
end

function Room:areMonstersDead()
    local ret = true
    local t = {}
    for i, creature in ipairs(self.monsters) do
        if isCreature(creature) then
            ret = false
            table.insert(t, creature)
        end
    end
    return ret, t
end

function isPlayerInside(rooms, player)
    local ppos = getCreaturePosition(player)
    for i, room in ipairs(rooms) do
        if room:isInside(ppos) and room.player == player then
            return room
        end
    end
end

function getFreeRooms(rooms)
    local free = {}
    for i, room in ipairs(rooms) do
        if not room.player or not (isPlayer(room.player) and room:isInside(getCreaturePosition(room.player))) then
            table.insert(free, room)
        end
    end
    return free
end

local square = 3 -- SQUARE SIZE OF ROOM MUST BE AN ODD NUMBER! 3x3, 5x5 etc..

-- Room:new(centerpos, squaresize)
local rooms = {
[1] = Room:new({x=277, y=59, z=7}, square),
[2] = Room:new({x=281, y=59, z=7}, square),
[3] = Room:new({x=285, y=59, z=7}, square),
}
local successchance = 1/10 -- 1 out of 10 tries, 10%
local successpos = {x=270, y=56, z=7} -- pos of final room
local monsters = {"wolf", "troll"} -- monsters

function onStepIn(cid, item, pos, frompos)
    if isPlayer(cid) then
        local freeRooms = getFreeRooms(rooms)
        local isinside = isPlayerInside(rooms, cid)
        if (isinside and #freeRooms > 0) or #freeRooms > 1 then
            if isinside and not isinside:areMonstersDead() then
                doTeleportThing(cid, frompos, true)
                return doPlayerSendCancel(cid, "You got to kill all monsters first.")
            end
            local successrd = math.random(1, 100)
            if isinside and successrd <= successchance*100 then
                doTeleportThing(cid, successpos)
                doSendMagicEffect(successpos, 10)
            else
                local rd = math.random(#freeRooms)
                freeRooms[rd]:teleportPlayer(cid)
                freeRooms[rd]:addMonster(monsters[math.random(#monsters)])
            end
        else
            doTeleportThing(cid, frompos, true)
            return doPlayerSendCancel(cid, "All rooms are full now, please wait.")
        end
    end
end

EDIT: Use the same actionid for all tiles inside the rooms and use the same actionid on the tile that the player is going to enter the rooms for the first time. Be sure players cant logout inside the rooms just for safety, it will work even if they logout inside them.

I like the idea of only 1 player at a time in the quest, and even more the idea that the player has to kill all the monsters to go to the next room. But i want the player to see in the minimap that he's not in the same room. That he's always moving around in the quest, just as @Xikini said.


@Edit: I just tested your script, it works, but, the player can leave even if he doesn't kill the monster, and the player is also not being teleported to the final room.
 
Last edited:
And thats what i've done.

I'll try to explain again:

You have 25 rooms, so this is a total of 24 players total inside the quest, if any other player try to go inside he will get a message saying that all rooms are full. (editable)

So if you have 24 players inside 1 room would always be empty so if 1 of those 24 players kills all monsters and step in the tile he would get teleported to the empty room.

So the player would see in the minimap that his position is actually changing and as the time that the player kills the monsters is not the same for all of them, the empty room would always be kinda random.

The player is always assigned a random empty room.

Try the code, i've tested it already and its working fine for me :p


Edit:

I like the idea of only 1 player at a time in the quest, and even more the idea that the player has to kill all the monsters to go to the next room. But i want the player to see in the minimap that he's not in the same room. That he's always moving around in the quest, just as @Xikini said.


@Edit: I just tested your script, it works, but, the player can leave even if he doesn't kill the monster, and the player is also not being teleported to the final room.

Did you set the square size of your room? It must be an odd number.

Based on the image I counted 13 x 13 room so you should have

local square = 13 -- SQUARE SIZE OF ROOM MUST BE AN ODD NUMBER! 3x3, 5x5 etc..
 
Last edited:
And thats what i've done.

I'll try to explain again:

You have 25 rooms, so this is a total of 24 players total inside the quest, if any other player try to go inside he will get a message saying that all rooms are full. (editable)

So if you have 24 players inside 1 room would always be empty so if 1 of those 24 players kills all monsters and step in the tile he would get teleported to the empty room.

So the player would see in the minimap that his position is actually changing and as the time that the player kills the monsters is not the same for all of them, the empty room would always be kinda random.

The player is always assigned a random empty room.

Try the code, i've tested it already and its working fine for me :p


Edit:



Did you set the square size of your room? It must be an odd number.

Based on the image I counted 13 x 13 room so you should have

local square = 13 -- SQUARE SIZE OF ROOM MUST BE AN ODD NUMBER! 3x3, 5x5 etc..

Bro, to be honest, i think your script it's too confusing for me xD, i'd rather use @Xikini 's one.. I just need to fix the position of the monsters.. But thanks anyways, you realllly helped me :))
 
Bro, to be honest, i think your script it's too confusing for me xD, i'd rather use @Xikini 's one.. I just need to fix the position of the monsters.. But thanks anyways, you realllly helped me :))

It is not confusing, you just have to change those things:

Code:
local square = 3 -- SQUARE SIZE OF ROOM MUST BE AN ODD NUMBER! 3x3, 5x5 etc..

-- Room:new(centerpos, squaresize)
local rooms = {
[1] = Room:new({x=277, y=59, z=7}, square),
[2] = Room:new({x=281, y=59, z=7}, square),
[3] = Room:new({x=285, y=59, z=7}, square),
}
local successchance = 1/10 -- 1 out of 10 tries, 10%
local successpos = {x=270, y=56, z=7} -- pos of final room
local monsters = {"wolf", "troll"} -- monsters

It's pretty simple but you can use the one you feel like using anyway :p
 
It is not confusing, you just have to change those things:

Code:
local square = 3 -- SQUARE SIZE OF ROOM MUST BE AN ODD NUMBER! 3x3, 5x5 etc..

-- Room:new(centerpos, squaresize)
local rooms = {
[1] = Room:new({x=277, y=59, z=7}, square),
[2] = Room:new({x=281, y=59, z=7}, square),
[3] = Room:new({x=285, y=59, z=7}, square),
}
local successchance = 1/10 -- 1 out of 10 tries, 10%
local successpos = {x=270, y=56, z=7} -- pos of final room
local monsters = {"wolf", "troll"} -- monsters

It's pretty simple but you can use the one you feel like using anyway :p

Ok!! Now i understood the script, it's working perfeclty! Thanks!!!!

Edit: So, if in the Rooms, i use just 9 coordinates, only 8 players will be able to enter it?
 
Back
Top