Lua Make it work in globalevents cleanning specific area

dervin13

Excellent OT User
Joined
Apr 26, 2008
Messages
436
Reaction score
16
I get this script in another place and trying to make it work in globalevent, but already chance to function onThink(interval) but not happens...

Can anyone help? It's to clean a specific area thanks

Code:
function cleanmap()
  local configClean = {
    Map = {
      LS = {x = 550, y = 441, z = 7},   -- LIMIT NORT WEST
      LI = {x = 720, y = 346, z = 7}, -- LIMIT SUL EAST
    },
  }
  local ItensIDS = {2148, 2152} -- IDS FOR REMOVE
  for x = configClean.Map.LS.x, configClean.Map.LI.x do
    for y = configClean.Map.LS.y, configClean.Map.LI.y do
      for z = 1, 6 do
        for lista = 1, #ItensIDS do
          local tile = Tile(x, y, z)
          if tile then
            local field = tile:getItemById(ItensIDS[lista])
            if field then
              field:remove()
            end
          end
        end
      end
    end
  end
end
 

Xikini

I whore myself out for likes
Premium User
Joined
Nov 17, 2010
Messages
4,097
Reaction score
2,173
Code:
LS = {x = 550, y = 441, z = 7},   -- LIMIT NORT WEST
LI = {x = 720, y = 346, z = 7}, -- LIMIT SUL EAST

18:40 You see hunting horn.
Position: [X: 200] [Y: 100] [Z: 6].
--------
18:40 You see a ferumbras doll.
Position: [X: 203] [Y: 103] [Z: 6].
---------------------------
The numbers to the south east should always be larger then the numbers to the north west.
Currently, your south east Y position is lower then the north west Y position..
So the script is going to be doing really really weird shit, or it's not going to work at all.
---
So, fix your positions, and your problem should be fixed.
 
OP
dervin13

dervin13

Excellent OT User
Joined
Apr 26, 2008
Messages
436
Reaction score
16

18:40 You see hunting horn.
Position: [X: 200] [Y: 100] [Z: 6].
--------
18:40 You see a ferumbras doll.
Position: [X: 203] [Y: 103] [Z: 6].
---------------------------
The numbers to the south east should always be larger then the numbers to the north west.
Currently, your south east Y position is lower then the north west Y position..
So the script is going to be doing really really weird shit, or it's not going to work at all.
---
So, fix your positions, and your problem should be fixed.
I put function onThink(interval) at the topo and changed the positions then come this error

[Error - GlobalEvents::think] Failed to execute event: cleantemple
 

Xikini

I whore myself out for likes
Premium User
Joined
Nov 17, 2010
Messages
4,097
Reaction score
2,173
I put function onThink(interval) at the topo and changed the positions then come this error

[Error - GlobalEvents::think] Failed to execute event: cleantemple
Post the full current script?
 
OP
dervin13

dervin13

Excellent OT User
Joined
Apr 26, 2008
Messages
436
Reaction score
16
Post the full current script?

Code:
function onThink(interval)
  local configClean = {
    Map = {
      LS = {x = 651, y = 541, z = 7},   -- LIMIT NORT WEST
      LI = {x = 670, y = 556, z = 7}, -- LIMIT SUL EAST
    },
  }
  local ItensIDS = {2148, 2152} -- IDS FOR REMOVE
  for x = configClean.Map.LS.x, configClean.Map.LI.x do
    for y = configClean.Map.LS.y, configClean.Map.LI.y do
      for z = 1, 6 do
        for lista = 1, #ItensIDS do
          local tile = Tile(x, y, z)
          if tile then
            local field = tile:getItemById(ItensIDS[lista])
            if field then
              field:remove()
            end
          end
        end
end
end
end
end
 

Xikini

I whore myself out for likes
Premium User
Joined
Nov 17, 2010
Messages
4,097
Reaction score
2,173
Code:
function onThink(interval)
  local configClean = {
    Map = {
      LS = {x = 651, y = 541, z = 7},   -- LIMIT NORT WEST
      LI = {x = 670, y = 556, z = 7}, -- LIMIT SUL EAST
    },
  }
  local ItensIDS = {2148, 2152} -- IDS FOR REMOVE
  for x = configClean.Map.LS.x, configClean.Map.LI.x do
    for y = configClean.Map.LS.y, configClean.Map.LI.y do
      for z = 1, 6 do
        for lista = 1, #ItensIDS do
          local tile = Tile(x, y, z)
          if tile then
            local field = tile:getItemById(ItensIDS[lista])
            if field then
              field:remove()
            end
          end
        end
end
end
end
end
Is there nothing above or near this error?
No lines indicating an issue?
 
OP
dervin13

dervin13

Excellent OT User
Joined
Apr 26, 2008
Messages
436
Reaction score
16
no, only this, i think it was a part of action, but I want to use this to clean a part of the map
 

Nekiro

Support Team
Support Team
Joined
Sep 7, 2015
Messages
1,824
Reaction score
573
You are not returning true, thats why server thinks your globalevent failed to execute. This error has nothing to do with your code.
 
OP
dervin13

dervin13

Excellent OT User
Joined
Apr 26, 2008
Messages
436
Reaction score
16
It's working now thanks

Code:
function onThink(interval)
local area = {
      fromPos = {x = 300, y = 300, z = 7},   
      toPos = {x = 400, y = 400, z = 7}
  }
  local itemIds = {2148, 2152}
    for x = area.fromPos.x, area.toPos.x do
        for y = area.fromPos.y, area.toPos.y do
            for z = area.fromPos.z, area.toPos.z do
                local t = Tile(x, y, z)
                if t and t:getTopDownItem() then
                    for i = 255, 1, -1 do
                        for _ = 1, #itemIds do
                            if t:getTopDownItem():getId() == itemIds[_] then
                                t:getTopDownItem():remove()
                            end
    return true
                        end
                    end
                end
            end
        end
end
end
 

Xikini

I whore myself out for likes
Premium User
Joined
Nov 17, 2010
Messages
4,097
Reaction score
2,173
It's working now thanks

Code:
function onThink(interval)
local area = {
      fromPos = {x = 300, y = 300, z = 7},
      toPos = {x = 400, y = 400, z = 7}
  }
  local itemIds = {2148, 2152}
    for x = area.fromPos.x, area.toPos.x do
        for y = area.fromPos.y, area.toPos.y do
            for z = area.fromPos.z, area.toPos.z do
                local t = Tile(x, y, z)
                if t and t:getTopDownItem() then
                    for i = 255, 1, -1 do
                        for _ = 1, #itemIds do
                            if t:getTopDownItem():getId() == itemIds[_] then
                                t:getTopDownItem():remove()
                            end
    return true
                        end
                    end
                end
            end
        end
end
end
That return true is in a very bad spot.
It's going to clean like 1 square then stop.

I'd recommend finding a better method of locating items to remove.. because I feel like this script is going to lag severely.
even the 100 by 100 test area you have is 10,000 tiles.. and then you are looping through every tile 255 times..
10,000 * 255 = 2,550,000 checks.

With that many checks.. even if your server could somehow go through 50,000 checks per millisecond, your server is going to hang and be unable to do anything for 51 millseconds.
And trust me, your server cannot perform 50,000 checks per millisecond. That would be phenomenally fast.

In any case, here's where the return true should be located.
Lua:
local area = {
    fromPos = {x = 300, y = 300, z = 7}, 
    toPos = {x = 400, y = 400, z = 7}
}
local itemIds = {2148, 2152}

function onThink(interval)
    for x = area.fromPos.x, area.toPos.x do
        for y = area.fromPos.y, area.toPos.y do
            for z = area.fromPos.z, area.toPos.z do
                local t = Tile(x, y, z)
                if t and t:getTopDownItem() then
                    for i = 255, 1, -1 do
                        for _ = 1, #itemIds do
                            if t:getTopDownItem():getId() == itemIds[_] then
                                t:getTopDownItem():remove()
                            end
                        end
                    end
                end
            end
        end
    end
    return true
end
 
Last edited:

Stigma

Veteran OT User
Joined
Feb 14, 2015
Messages
4,581
Reaction score
2,141
That return true is in a very bad spot.
It's going to clean like 1 square then stop.

I'd recommend finding a better method of locating items to remove.. because I feel like this script is going to lag severely.
even the 100 by 100 test area you have is 10,000 tiles.. and then you are looping through every tile 255 times..
10,000 * 255 = 2,550,000 checks.

With that many checks.. even if your server could somehow go through 50,000 checks per millisecond, your server is going to hang and be unable to do anything for 51 millseconds.
And trust me, your server cannot perform 50,000 checks per millisecond. That would be phenomenally fast.

In any case, here's where the return true should be located.
Lua:
local area = {
    fromPos = {x = 300, y = 300, z = 7},
    toPos = {x = 400, y = 400, z = 7}
}
local itemIds = {2148, 2152}

function onThink(interval)
    for x = area.fromPos.x, area.toPos.x do
        for y = area.fromPos.y, area.toPos.y do
            for z = area.fromPos.z, area.toPos.z do
                local t = Tile(x, y, z)
                if t and t:getTopDownItem() then
                    for i = 255, 1, -1 do
                        for _ = 1, #itemIds do
                            if t:getTopDownItem():getId() == itemIds[_] then
                                t:getTopDownItem():remove()
                            end
                        end
                    end
                end
            end
        end
    end
    return true
end
Cleaner & faster:
Lua:
local area = {
    fromPos = Position(300, 300, 7),
    toPos = Position(400, 400, 7)
}

local tileCache = {}

local itemIds = {2148, 2152}

function onThink(interval)
    -- initialize tiles we need to clean, store all tiles in a cache to avoid reconstructing them in the future
    if #tileCache == 0 then
        for x = area.fromPos.x, area.toPos.x do
            for y = area.fromPos.y, area.toPos.y do
                for z = area.fromPos.z, area.toPos.z do
                    tileCache[#tileCache+1] = Tile(x, y, z)
                end
            end
        end
    end
    -- clean based off of cache, pairs iterates faster than ipairs
    for tile in pairs(tileCache) do
        for _, item in pairs(tile:getItems()) do
            if table.contains(itemIds, item:getId()) then
                item:remove()
            end
        end
    end
    return true
end
 

Evil Hero

Legacy Member
Joined
Dec 12, 2007
Messages
1,156
Reaction score
529
Location
Germany
Lua:
    -- clean based off of cache, pairs iterates faster than ipairs
    for tile in pairs(tileCache) do
        for _, item in pairs(tile:getItems()) do
            if table.contains(itemIds, item:getId()) then
                item:remove()
            end
        end
    end
    return true
end
actually this is even faster than pairs
Lua:
for i = 1, #tileCache do
    local tileItems = tileCache[i]:getItems()
    for items = 1, #tileItems do
        local item = tileItems[items]    
        if table.contains(itemIds, item:getId()) then
            item:remove()
        end
    end
end
test with 1million loops
yours => 2.747075
mine => 1.945673

It's ofcourse not significant which loop method you use for smaller loops anyway
 

Stigma

Veteran OT User
Joined
Feb 14, 2015
Messages
4,581
Reaction score
2,141
actually this is even faster than pairs
Lua:
for i = 1, #tileCache do
    local tileItems = tileCache[i]:getItems()
    for items = 1, #tileItems do
        local item = tileItems[items]   
        if table.contains(itemIds, item:getId()) then
            item:remove()
        end
    end
end
test with 1million loops
yours => 2.747075
mine => 1.945673

It's ofcourse not significant which loop method you use for smaller loops anyway
Forgot that manual iteration is way faster, very nice.
 
OP
dervin13

dervin13

Excellent OT User
Joined
Apr 26, 2008
Messages
436
Reaction score
16
Cleaner & faster:
Lua:
local area = {
    fromPos = Position(300, 300, 7),
    toPos = Position(400, 400, 7)
}

local tileCache = {}

local itemIds = {2148, 2152}

function onThink(interval)
    -- initialize tiles we need to clean, store all tiles in a cache to avoid reconstructing them in the future
    if #tileCache == 0 then
        for x = area.fromPos.x, area.toPos.x do
            for y = area.fromPos.y, area.toPos.y do
                for z = area.fromPos.z, area.toPos.z do
                    tileCache[#tileCache+1] = Tile(x, y, z)
                end
            end
        end
    end
    -- clean based off of cache, pairs iterates faster than ipairs
    for tile in pairs(tileCache) do
        for _, item in pairs(tile:getItems()) do
            if table.contains(itemIds, item:getId()) then
                item:remove()
            end
        end
    end
    return true
end
Im getting this error
Lua Script Error: [GlobalEvent Interface]
data/globalevents/scripts/clean.lua:eek:nThink
data/globalevents/scripts/clean.lua:23: attempt to index local 'tile' (a n
umber value)

and with Evil Hero
Lua Script Error: [GlobalEvent Interface]
data/globalevents/scripts/clean.lua:eek:nThink
data/globalevents/scripts/clean.lua:24: attempt to get length of local 'ti
leItems' (a nil value)
 

Stigma

Veteran OT User
Joined
Feb 14, 2015
Messages
4,581
Reaction score
2,141
Im getting this error
Lua Script Error: [GlobalEvent Interface]
data/globalevents/scripts/clean.lua:eek:nThink
data/globalevents/scripts/clean.lua:23: attempt to index local 'tile' (a n
umber value)

and with Evil Hero
Lua Script Error: [GlobalEvent Interface]
data/globalevents/scripts/clean.lua:eek:nThink
data/globalevents/scripts/clean.lua:24: attempt to get length of local 'ti
leItems' (a nil value)
Oops, I'm too used to Python. Use the way @Evil Hero showed, manual iteration is much faster.
Lua:
local area = {
    fromPos = Position(300, 300, 7),
    toPos = Position(400, 400, 7)
}

local tileCache = {}

local itemIds = {2148, 2152}

function onThink(interval)
    -- initialize tiles we need to clean, store all tiles in a cache to avoid reconstructing them in the future
    if #tileCache == 0 then
        for x = area.fromPos.x, area.toPos.x do
            for y = area.fromPos.y, area.toPos.y do
                for z = area.fromPos.z, area.toPos.z do
                    tileCache[#tileCache+1] = Tile(x, y, z)
                end
            end
        end
    end
    -- clean based off of cache
    for i = 1, #tileCache do
        local items = tileCache[i]:getItems()
        for index = 1, #items do
            local item = items[index]
            if table.contains(itemIds, item:getId()) then
                item:remove()
            end
        end
    end
    return true
end
 
OP
dervin13

dervin13

Excellent OT User
Joined
Apr 26, 2008
Messages
436
Reaction score
16
Oops, I'm too used to Python. Use the way @Evil Hero showed, manual iteration is much faster.
Lua:
local area = {
    fromPos = Position(300, 300, 7),
    toPos = Position(400, 400, 7)
}

local tileCache = {}

local itemIds = {2148, 2152}

function onThink(interval)
    -- initialize tiles we need to clean, store all tiles in a cache to avoid reconstructing them in the future
    if #tileCache == 0 then
        for x = area.fromPos.x, area.toPos.x do
            for y = area.fromPos.y, area.toPos.y do
                for z = area.fromPos.z, area.toPos.z do
                    tileCache[#tileCache+1] = Tile(x, y, z)
                end
            end
        end
    end
    -- clean based off of cache
    for i = 1, #tileCache do
        local items = tileCache[i]:getItems()
        for index = 1, #items do
            local item = items[index]
            if table.contains(itemIds, item:getId()) then
                item:remove()
            end
        end
    end
    return true
end
It's working, but if there's an water placed in the area I get this error
data/globalevents/scripts/clean.lua:24: attempt to get length of local 'ti
leItems' (a nil value)

It's possible to solve or is better to remove this water?
 

Stigma

Veteran OT User
Joined
Feb 14, 2015
Messages
4,581
Reaction score
2,141
Why do you still have a variable named tileItems?
This should make sure an items table exists before iterating over it.
Lua:
local area = {
    fromPos = Position(300, 300, 7),
    toPos = Position(400, 400, 7)
}

local tileCache = {}

local itemIds = {2148, 2152}

function onThink(interval)
    -- initialize tiles we need to clean, store all tiles in a cache to avoid reconstructing them in the future
    if #tileCache == 0 then
        for x = area.fromPos.x, area.toPos.x do
            for y = area.fromPos.y, area.toPos.y do
                for z = area.fromPos.z, area.toPos.z do
                    tileCache[#tileCache+1] = Tile(x, y, z)
                end
            end
        end
    end
    -- clean based off of cache
    for i = 1, #tileCache do
        local items = tileCache[i]:getItems()
        if items and next(items) then
            for index = 1, #items do
                local item = items[index]
                if table.contains(itemIds, item:getId()) then
                    item:remove()
                end
            end
        end
    end
    return true
end
 
Top