• 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!
  • 2026 staff recruitment is open! Check it out and consider applying!

Lua Question about teleport creatures in an area

Siegh

Thronar Developer
Joined
Mar 12, 2011
Messages
1,276
Solutions
1
Reaction score
635
Location
Brazil
I'm using this script for a boss that constantly teleports everyone involved between arenas. Its supposed to be doing the following:

Get every creature inside the square area, check if their name is different from Custodis or Ignis (they are arena specific enemies that should be ignored by the teleport function), randomize a location with a x or y variation starting from square.exitpos coordinates, and teleport everyone at the same time. It does function properly most of the times, but sometimes it simply ignores some creatures that should be affected but teleport others.

What's wrong here that may cause this variaton?

LUA:
        function teleportAll()
            local square = {
                frompos = {x = 1230, y = 849, z = 14},
                topos = {x = 1258, y = 872, z = 14},
                exitpos = {x = 1144, y = 859, z = 14}
            }        
            for a = square.frompos.x, square.topos.x do
                for b = square.frompos.y, square.topos.y do
                    local pos = {x = a, y = b, z = 14, stackpos = 255}
                    local creature = getTopCreature(pos)
                    if creature and creature.uid > 0 then
                        if getCreatureName(creature.uid) ~= "Custodis" and getCreatureName(creature.uid) ~= "Ignis" then
                            variationX = math.random(-8,8)
                            variationY = math.random(-8,8)
                            square.exitpos.x = square.exitpos.x + variationX
                            square.exitpos.y = square.exitpos.y + variationY                                
                            doTeleportThing(creature.uid, square.exitpos)
                            doSendMagicEffect(square.exitpos, 41)
                        end                      
                    end
                end
            end
        end      
        teleportAll()
 
Solution
First check only for players, that is better than going through the creature names.
Use isPlayer(creature.uid)
Then create a local targetPos array {x,y,z} something like this:
local targetPos = {
x = square.exitpos.x + math.random(-8, 8),
y = square.exitpos.y + math.random(-8, 8),
z = square.exitpos.z
}

And then doTeleportThing()

The problem is that u are changing square.exitpos permanently inside the loop and using local variable inside the loop ensures new clean math.random with every iteration.

Sry can't test it im on my phone 😅
First check only for players, that is better than going through the creature names.
Use isPlayer(creature.uid)
Then create a local targetPos array {x,y,z} something like this:
local targetPos = {
x = square.exitpos.x + math.random(-8, 8),
y = square.exitpos.y + math.random(-8, 8),
z = square.exitpos.z
}

And then doTeleportThing()

The problem is that u are changing square.exitpos permanently inside the loop and using local variable inside the loop ensures new clean math.random with every iteration.

Sry can't test it im on my phone 😅
 
Solution
First check only for players, that is better than going through the creature names.
Use isPlayer(creature.uid)
Then create a local targetPos array {x,y,z} something like this:
local targetPos = {
x = square.exitpos.x + math.random(-8, 8),
y = square.exitpos.y + math.random(-8, 8),
z = square.exitpos.z
}

And then doTeleportThing()

The problem is that u are changing square.exitpos permanently inside the loop and using local variable inside the loop ensures new clean math.random with every iteration.

Sry can't test it im on my phone 😅
On top of what the previous guy said, you are also only getting the top creature... there may be instances where there are multiple players on one square. You should iterate through all the players on a tile.
 
frompos = {x = 1230, y = 849, z = 14}, topos = {x = 1258, y = 872, z = 14},
Also, when you get creatures in so big area (28 x 23 SQM), you should use getSpectators to save CPU, it will iterate over tiles in C++:
  • OTX2: getSpectators(centerPos, rangex, rangey[, multifloor = false])
  • TFS 0.4: getSpectators(centerPos, rangex, rangey, multifloor, <optional> onlyPlayers)
  • TFS 1.4+: Game.getSpectators(position[, multifloor = false[, onlyPlayer = false[, minRangeX = 0[, maxRangeX = 0[, minRangeY = 0[, maxRangeY = 0]]]]]])
As you can see, on TFS 0.4 and TFS 1.4, it's possible to pass parameter onlyPlayers to make C++ return list of only players, but you may want to teleport creatures (monsters), as they may be player summons.
All these functions take all creatures/players from stack, so there is no problem like with getTopCreature.
 
Thanks! The first solution did help me with all I needed.

I don't have a lot of time right now so I won't work on Gesior's solution as of now but I will try to implement it later as well. I will post the current working version in case anyone else is interested in it, mind that it won't take into consideration possible stacking players since it's not something I have to worry about in this specific scenario.

And yes, I do need to check for monsters, specifically not the ones that I'm checking for names, precisely due to the possibility of players carrying summons with them. Also, the boss itself also has be affected.

LUA:
function teleportAll()
            local square = {
                frompos = {x = 1131, y = 848, z = 14},
                topos = {x = 1159, y = 871, z = 14},
                exitpos = {x = 1245, y = 861, z = 14}
            }       
            for a = square.frompos.x, square.topos.x do
                for b = square.frompos.y, square.topos.y do
                    local pos = {x = a, y = b, z = 14, stackpos = 255}
                    local creature = getTopCreature(pos)
                    if creature and creature.uid > 0 then
                        if getCreatureName(creature.uid) ~= "Custodis" and getCreatureName(creature.uid) ~= "Ignis" then
                            local targetPos = {
                                x = square.exitpos.x + math.random(-8, 8),
                                y = square.exitpos.y + math.random(-8, 8),
                                z = square.exitpos.z
                            }                             
                            doTeleportThing(creature.uid, targetPos)
                            doSendMagicEffect(targetPos, 41)
                        end                 
                    end
                end
            end
        end
 
Back
Top