• 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] Loops and some tricks

Colandus

Advanced OT User
Senator
Joined
Jun 6, 2007
Messages
2,434
Solutions
19
Reaction score
218
Location
Sweden
These are my old tutorials, that has gone through several forums and now it's time I put it here at OtLand!

This time I decided to show ya how to check areas, e.g. to check if there is a player on a 10x10 area, but then I thought that I have to learn you how to use loops first, because this works with loops ^_^

First of all, I'll show you a pretty noobish script, the repeat until loop:
Lua:
local message = "Hello, I am Colandus."
local said = 0

function onUse(cid, item, frompos, item2, topos)
    repeat
        doPlayerSendTextMessage(cid, 22, message)
        said = said + 1
    until said == 10
    return 1
end

Well, never had any use of the repeat until loop though, I kinda always use the for loop.

Did you understand that script? It will repeat until the variable said is 10, which means I must increase the variable, except if I want an infinite loop.
As you probably already noticed, the condition goes after "until", which you can see here "until said == 10", is the thing that tells that said has to be 10, and this means the script will say "Hello, I am Colandus" 10 times. But if you decided to write this way instead:
Lua:
local message = "Hello, I am Colandus."
local said = 0
local said2 = 25

function onUse(cid, item, frompos, item2, topos)
    repeat
        doPlayerSendTextMessage(cid, 22, message)
        said = said + 1
        said2 = said2 - 1
    until said >= 10 and said2 <= 10
    return 1
end

Now it would repeat it 15 times, because first of all, "said" will increase and become 10 after a while, by that time "said2" will be 15, and the script said it has to be less than 10, until the loop will break, so it will have to loop an additional 5 times for the variable "said2" to become 10, which breaks the loop.

Now to the while loop, it also works with conditions aswell as the repeat until loop:
Lua:
local message = "Hello, I am Colandus."

function onUse(cid, item, frompos, item2, topos)
    local said = 0
    while said < 10 do
        doPlayerSendTextMessage(cid, 22, message)
        said = said + 1
    end
    return 1
end

I think you get what it does... It will loop as long as the condition returns true. Which means, you cannot, as you did in the repeat until loop, write conditions like: "while said == 10", but the variable "said" is 0, because the while loop will loop as long as the condition returns true!

Now, to the very for loop, that has to got a variable in it, and it does not work with conditions, this is how the for loop works:
Lua:
local message = "Hello, I am Colandus."

function onUse(cid, item, frompos, item2, topos)
    for i = 1, 5 do
        doPlayerSendTextMessage(cid, 22, message)
    end
    return 1
end

This will repeat 5 times, and write "Hello, I am Colandus" 5 times, ofcourse. It will repeat until "i" is 5, you don't need to have "i" as the variable, you could use any word, like "for loop = 1, 5 do", this works aswell...

Why use for loops and not just while or repeat until loops? Because in for loops you don't need to increase the variable in the script all the time, and you could have some nice use of it, this is a small example which is quite nice to know:
Lua:
local names = {"Colandus", "Helveg", "STiX", "Pablol", "Dalkon", "Zaga", "Athen", "Kakan"}

function onUse(cid, item, frompos, item2, topos)
    for i = 1, #names do
        doPlayerSendTextMessage(cid, 22, names)
    end
    return 1
end
This will loop 8 times, saying one name each in the order it's written in the table (array). "#names" checks how many names there is in the table "names", but if the table was called "members" instead of names, then you'd have written "#members" instead of names.
As you probably already know, each name in the table has it's own ID depending on where it's placed in the table, also known as position. For example, "Colandus" would be ID 1, because it's placed at the first place in the table and "Zaga" would have the ID 6, because it's placed in the 6th place in the table. To call these names you'd write "names[5]", which would return the name "Dalkon", because that's the name placed in position 5 (ID 5), that is why I write "names", "i" will increase each time it loops, which means that "i" will be number 3 after the 3rd time it has looped, means "names" would then be "names[3]", which returns "STiX".

Ways to check the max amount of names in a table is, in this example the table will be called "name":
Lua:
#name -- Prefered
table.getn(name) -- Old, use #name

Now I'll learn you some examples of taking/storing information from/to tables, here is an example of taking information from a table by looping:
Lua:
local ids = {}

function onUse(cid, item, frompos, item2, topos)
    for i = 1, 10 do
        newId = 1000 + i * (i + 2)
        table.insert(ids, newId)
    end
    return 1
end
This script will make a loop that repeats 10 times, each time it will insert some numbers to the table "ids", which will increase by using a mathematical formula "newId = 1000 + i * (i + 2)... I think you guys have learned these stuff in school already, so I don't have to explain that.

And now, I'll learn you how to remove information from a table, it's really simple:
Lua:
local names = {"Colandus", "Helveg", "STiX", "Pablol", "Dalkon", "Zaga", "Ispiro", "Super Kakan"}

function onUse(cid, item, frompos, item2, topos)
    for i = 1, #names do
        table.remove(names, #names)
    end
    return 1
end
This would remove one name each from the end, until the loop ends... It will leave the table empty when it has finnished looping :D

Now I'll learn you how to make scripts that removes information from a table and inserts the same information to another table, and because I didn't know what example I should make, I just took a function I made for the Pillow Puzzle script and edited it some:
Lua:
local numbers = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}

function onUse(cid, item, frompos, item2, topos)
    local shuffledNumbers = {}
    for i = 1, #numbers do
        randomId = math.random(1, #numbers)
        table.insert(shuffledNumbers, numbers[randomId])
        table.remove(numbers, randomId)
    end
    return 1
end
This script will loop 10 times, because there is 10 numbers in the table "numbers", and each time it loops, it will pick a random ID between 1 and 10; for example 7, and because I have placed all numbers in correct order the ID 7 will be the number 7 too ofcourse, which means the script will remove the ID 7 from the table "numbers" and then insert the value of ID 7, which is the number 7 in the table shuffledNumbers. When this loop has finnished picking random IDs from the table "numbers", you will get a new table with the same numbers in a different order, because it picked numbers from random positions and placed it in the last position of the new table.

To make it clear for you, I made this little example; let's say, I am the script, that will insert and remove the ID's.
Lua:
First, I take a random ID... PIIIIIIIIIIP... 7 was the random ID.
Now I take the number from the table "numbers" at position 7 and removing it, and then I place it at the end of "shuffledNumbers".
The tables looks like this now:
numbers = {1, 2, 3, 4, 5, 7, 8, 9, 10}
shuffledNumbers = {7}
Let's do it again... Picking random ID... PIIIIIIIIIIIIIIIP... 2 was the random ID.
The tables now looks like this:
numbers = {1, 3, 4, 5, 7, 8, 9, 10}
shuffledNumbers = {7, 2}
I bet you understand it now! Would waste my time if I wrote it all, but it will do it this way until "numbers" is empty.

Now I'll learn you some more OT related loops, which is needed some times:
Lua:
local position = {fromx = 584, tox = 595, y = 371, z = 7}

function onUse(cid, item, frompos, item2, topos)
    for i = position.fromx, position.tox do
        local pos = {x = i, y = position.y, z = position.z, stackpos = 253}
        local getThing = getThingfromPos(pos).uid
        if isPlayer(getThing) == 1 then
            doPlayerSendTextMessage(cid, 22, "Player " .. getPlayerName(getThing) .. " found at position x: " .. i .. ", y: " .. position.y .. ", z: " .. position.z)
        end
    end
    return 1
end
This script will check from the position x: "fromx" which is 584, to "tox", which is 594 and the position z: 371 and the position y: 7. This means that; first it will check on the position x: 584, if a player ain't found there it won't give you any message, and it will go over to the next position, 585... It will do this until "i" is 594. If there is many players at these positions, it will say all of them, but that's maybe not what you want? You only want it to check one name and then break the script! Then you'd do it this way:
Lua:
local position = {fromx = 584, tox = 595, y = 371, z = 7}

function onUse(cid, item, frompos, item2, topos)
    for i = position.fromx, position.tox do
        local pos = {x = i, y = position.y, z = position.z, stackpos = 253}
        local getThing = getThingfromPos(pos).uid
        if isPlayer(getThing) == 1 then
            doPlayerSendTextMessage(cid, 22, "Player " .. getPlayerName(getThing) .. " found at position x: " .. i .. ", y: " .. position.y .. ", z: " .. position.z)
            break
        end
    end
    return 1
end
All I added was "break", which simply breaks the loop. You could use it anytime in the loop to break it, but it's oftenly used when you will check lots of numbers and break it when a (certain) number where found.

Now to the next part, how to check in a bigger area, like a 6x6sqm area, take a look:
Lua:
local position = {fromx = 584, fromy = 371, tox = 589, toy = 376, z = 7}

function onUse(cid, item, frompos, item2, topos)
    for i = position.fromx, position.tox do
        for j = position.fromy, position.toy do
            local pos = {x = i, y = j, z = position.z, stackpos = 253}
            local getThing = getThingfromPos(pos).uid
            if isPlayer(getThing) == 1 then
                doPlayerSendTextMessage(cid, 22, "Player " .. getPlayerName(getThing) .. " found at position x: " .. i .. ", y: " .. j .. ", z: " .. position.z)
                break
            end
        end
    end
    return 1
end
Simple, isn't it? First time, in the "i" loop it will start loop from 584 to 589, and while it's looping another loop will be executed inside it; to check the position y, by the variable "j", it will check if there was a player found at x: "i", and y: "j", and z: "position.z": which is 7.

If you really didn't get it, then look at this:
Lua:
local position = {fromx = 584, fromy = 371, tox = 595, toy = 381, z = 7}
local area = ""

function onUse(cid, item, frompos, item2, topos)
    area = "Creatures at area:\n"
    for i = position.fromy, position.toy do
        for j = position.fromx, position.tox do
            local pos = {x = j, y = i, z = position.z, stackpos = 253}
            local getThing = getThingfromPos(pos).uid
            if isCreature(getThing) == 1 then
                area = area .. "1 "
            else
                area = area .. "0 "
            end
        end
        area = area .. "\n"
    end
    doPlayerSendTextMessage(cid, 17, area)
    return 1
end
Cool, huh? It will show you information about every tile on the positions you entered, if there is a creature there it will return "1", else it will return "0" :)
Still don't get it? Try it in-game, it's easier then.

For more questions concerning loops, ask here.
Was it hard to understand? Then tell me what, So I can try to edit this post to make it easier for you to understand :)

I know this could be hard to understand sometimes, so I'll give you a last explain about how the loops with another loop inside it works:
Lua:
function onUse(cid, item, frompos, item2, topos)
    for i = 1, 5 do
        doPlayerSendTextMessage(cid, 17, 'The "i" loop has looped ' .. i .. ' time(s).')
        for j = 1, 5 do
            doPlayerSendTextMessage(cid, 22, 'The "j" loop has looped ' .. j .. ' time(s).')
        end
    end
    return 1
end
This script will output the following:
18:37 The "i" loop has looped 1 time(s).
18:37 The "j" loop has looped 1 time(s).
18:37 The "j" loop has looped 2 time(s).
18:37 The "j" loop has looped 3 time(s).
18:37 The "j" loop has looped 4 time(s).
18:37 The "j" loop has looped 5 time(s).
18:37 The "i" loop has looped 2 time(s).
18:37 The "j" loop has looped 1 time(s).
18:37 The "j" loop has looped 2 time(s).
18:37 The "j" loop has looped 3 time(s).
18:37 The "j" loop has looped 4 time(s).
18:37 The "j" loop has looped 5 time(s).
18:37 The "i" loop has looped 3 time(s).
18:37 The "j" loop has looped 1 time(s).
18:37 The "j" loop has looped 2 time(s).
18:37 The "j" loop has looped 3 time(s).
18:37 The "j" loop has looped 4 time(s).
18:37 The "j" loop has looped 5 time(s).
18:37 The "i" loop has looped 4 time(s).
18:37 The "j" loop has looped 1 time(s).
18:37 The "j" loop has looped 2 time(s).
18:37 The "j" loop has looped 3 time(s).
18:37 The "j" loop has looped 4 time(s).
18:37 The "j" loop has looped 5 time(s).
18:37 The "i" loop has looped 5 time(s).
18:37 The "j" loop has looped 1 time(s).
18:37 The "j" loop has looped 2 time(s).
18:37 The "j" loop has looped 3 time(s).
18:37 The "j" loop has looped 4 time(s).
18:37 The "j" loop has looped 5 time(s).


Here's a more complete loops tutorial: Tutorials Package

Note that I have added function onUse, only because it should be easier to test the scripts :D

Tell me if you learned, what did you learn and what did you not learn? This will help me improve it.

Sincerely,
Colandus
 
Last edited:
great tutorial Colandus, as always ;)

I remeber when you made this :p back in the Good ol' Days

Good to see your back ;O!

Sincerely,
Yours Pablol
 
After doing remote support to users, I see it gets more and more common with people having issues with lag from CPU spikes. This seems like the solution to that.
 
Very great tutorial Colandus. Love ur work =)

tho i have to say u got an typo here

Lua:
First, I take a random ID... PIIIIIIIIIIP... 6 was the random ID.
Now I take the number from the table "numbers" at position 6 and removing it, and then I place it at the end of "shuffledNumbers".
The tables looks like this now:
numbers = {1, 2, 3, 4, 5, 7, 8, 9, 10}
shuffledNumbers = {7}
Let's do it again... Picking random ID... PIIIIIIIIIIIIIIIP... 2 was the random ID.
The tables now looks like this:
numbers = {1, 3, 4, 5, 7, 8, 9, 10}
shuffledNumbers = {7, 2}

you removed nr 6 but it says nr 7 in shuffled numbers :p

Hope to see more tutorials from you later on Colandus :)
 
I'm glad my tutorials are being viewed the past few days :O

Good luck everyone! Don't forget to reply to the thread if you ever get stuck and need help with anything from the tutorial. Or PM me if you find that more convenient.
 
this actually just really helped me, outdated but very helpful, rep and bump~
 
Back
Top