Find entity
Find entity
Hi all.
I'm a programmer, but it's my first time with LUA. I've looked through the documentation and other mods, but haven't found the solution for these scenários.
Could anyone help please?
There are three questions here:
1 - Is there any way to find the nearest entity of some kind without using the game.findentities or findentitiesfiltered? They are very slow if we use a large area (100 or 1000 for instance).
Example of use that I need: find the nearest spawner from a roboport or find the nearest ore of some type from a certain position.
2 - Is there any way to move an entity from point A to point B without "teleporting" it?
Example of use that I need: Move a custom robot from point A to B. (Mechs )
3 - As a player/bitter moves, they do not have damage from colision on trees, but a car has.
How does it work? Is it possible to remove/customize these settings? (I don't want my bots killing themselves on trees or destroying the base. I could remove the colision box, but they would fly and that's not the initial idea).
Thanks a lot.
I'm a programmer, but it's my first time with LUA. I've looked through the documentation and other mods, but haven't found the solution for these scenários.
Could anyone help please?
There are three questions here:
1 - Is there any way to find the nearest entity of some kind without using the game.findentities or findentitiesfiltered? They are very slow if we use a large area (100 or 1000 for instance).
Example of use that I need: find the nearest spawner from a roboport or find the nearest ore of some type from a certain position.
2 - Is there any way to move an entity from point A to point B without "teleporting" it?
Example of use that I need: Move a custom robot from point A to B. (Mechs )
3 - As a player/bitter moves, they do not have damage from colision on trees, but a car has.
How does it work? Is it possible to remove/customize these settings? (I don't want my bots killing themselves on trees or destroying the base. I could remove the colision box, but they would fly and that's not the initial idea).
Thanks a lot.
Re: Find entity
Hello CarpeDiem, glad you chose to seize the day and work with LUA (couldn't resist, I apologize if that seemed quite silly)
P.S. sorry for late reply...apparently I didn't get an email for this (or it sent me a generic "new topics created" email and I only saw one topic when I read it...).
Not that I'm aware of...I've thought about that a couple times but haven't needed to actually implement it yet... my thought plan for that case has been findentities(filtered) with a small-ish radius that increased until it found one...assuming of course that game.player.force.getentitycount("entity-name") says there is at least one. The other idea I've had is to keep track of all entities of that type that have been placed and loop through them...but that may have even more related issues than findentities. Of course if these do not work (efficiently) for you then you're free to make an interface request.CarpeDiem wrote:Is there any way to find the nearest entity
not unless that entity is a 'unit' (which can be given commands), which kind of makes sense since most entities are stationary "buildings"CarpeDiem wrote:Is there any way to move an entity from point A to point B without "teleporting" it?
This one I don't know, but I'm going to guess that it's the speed at which the entity is moving that determines whether it is damaged when it collides...perhaps also affected by the weight since the wiki says that is " used for physics calculation when car hits something" (default value of 1).CarpeDiem wrote:As a player/bitter moves, they do not have damage from colision on trees, but a car has.
P.S. sorry for late reply...apparently I didn't get an email for this (or it sent me a generic "new topics created" email and I only saw one topic when I read it...).
<I'm really not active any more so these may not be up to date>
~FreeER=Factorio Modding
- Factorio Wiki
- My Factorio Modding Guide
- Wiki Modding Guide
Feel free to pm me
Or drop into #factorio on irc.esper.net
~FreeER=Factorio Modding
- Factorio Wiki
- My Factorio Modding Guide
- Wiki Modding Guide
Feel free to pm me
Or drop into #factorio on irc.esper.net
Re: Find entity
Lol, you don't need to apologize. First, thank you for the answers.
I'll try to create a glob table to control it with the coordinates and use the current position to check the nearest one (X, Y, entity). No idea yet on how to do it, I will learn a little more with the tutorials first since I'm losing hours to make a method call. This will create some problems as I'll have to periodically check if the entity is still "alive".
Great idea with the "unit". This solves all problems (it already has methods to move, does not have collision problems and attack). I've made some tests yesterday and it worked. Unit was created, is player friendly and attack bitters. It's still a little stubborn as I couldn’t find a sample on how to use gotolocation or atackarea methods from Lua/Command and it keeps wandering. Do you have one of these?
Abusing your good will… I’ve seen the event “ontick”, but doing some controls or periodical checks like 1 every minute, I had to implement a counter, but I’m not sure if this is the best way to do it. Is there a better one?
game.onevent(defines.events.ontick, function(event)
if game.tick%60==0 then
glob.second = glob. second + 1
end.
If glob.second==60 then
glob.second = 0
game.showmessagedialog("Test")
end.
end)
I'll try to create a glob table to control it with the coordinates and use the current position to check the nearest one (X, Y, entity). No idea yet on how to do it, I will learn a little more with the tutorials first since I'm losing hours to make a method call. This will create some problems as I'll have to periodically check if the entity is still "alive".
Great idea with the "unit". This solves all problems (it already has methods to move, does not have collision problems and attack). I've made some tests yesterday and it worked. Unit was created, is player friendly and attack bitters. It's still a little stubborn as I couldn’t find a sample on how to use gotolocation or atackarea methods from Lua/Command and it keeps wandering. Do you have one of these?
Abusing your good will… I’ve seen the event “ontick”, but doing some controls or periodical checks like 1 every minute, I had to implement a counter, but I’m not sure if this is the best way to do it. Is there a better one?
game.onevent(defines.events.ontick, function(event)
if game.tick%60==0 then
glob.second = glob. second + 1
end.
If glob.second==60 then
glob.second = 0
game.showmessagedialog("Test")
end.
end)
Re: Find entity
Modulo seems to be popular option, but I dislike it. In my mind, its unnecessary calculation done on "every" tick.
Code: Select all
game.onevent(defines.events.ontick, function(event)
if event.tick > glob.tick then
glob.tick = event.tick + 3600
game.showmessagedialog("Test")
end
end)
Test mode
Searching Flashlight
[WIP]Fluid handling expansion
[WIP]PvP gamescript
[WIP]Rocket Express
Autofill: The torch has been pass to Nexela
Searching Flashlight
[WIP]Fluid handling expansion
[WIP]PvP gamescript
[WIP]Rocket Express
Autofill: The torch has been pass to Nexela
Re: Find entity
I liked this idea since it avoid an unnecessary calculation every tick. I didn't knew about this variable.
Is there a list of all variables available like the wiki or is there any way that I can use to find then?
Best Regards.
Is there a list of all variables available like the wiki or is there any way that I can use to find then?
Best Regards.
Re: Find entity
you mean event variable? Lua/Events#Game_eventsCarpeDiem wrote:I liked this idea since it avoid an unnecessary calculation every tick. I didn't knew about this variable.
Is there a list of all variables available like the wiki or is there any way that I can use to find then?
Best Regards.
I decided to use event.tick over game.tick, because the event variable is local (we both name it as function's parameter in first line) and locals are faster than globals. It might not be big gain, but it is there. So why not.
Test mode
Searching Flashlight
[WIP]Fluid handling expansion
[WIP]PvP gamescript
[WIP]Rocket Express
Autofill: The torch has been pass to Nexela
Searching Flashlight
[WIP]Fluid handling expansion
[WIP]PvP gamescript
[WIP]Rocket Express
Autofill: The torch has been pass to Nexela
Re: Find entity
hm...Personally, no. However, you can find two or three in the ccmod (wip section), it's a bit outdated in some respects but the majority of it and the setcommand methods specifically should be the same.CarpeDiem wrote:It's still a little stubborn as I couldn’t find a sample on how to use gotolocation or atackarea methods from Lua/Command and it keeps wandering. Do you have one of these?
here's one from it which tells a single 'trooper' to move to a (player targeted) location and set's the trooper's distraction level to 'byenemy' (the command will be interrupted when it's 'distracted'):
Code: Select all
trooper.setcommand({ type=defines.command.gotolocation, destination=npos, distraction=defines.distraction.byenemy })
Code: Select all
trooper.setcommand({ type=defines.command.attackarea, destination={x=20, y=30}, radius=50, distraction=defines.distraction.byenemy })
edit: I suppose one method would be to make the unit.active = false...but that has obvious problems associated with it (and may not work at all for what you want)
I've used Modulo mostly because that's how I learned, I would however think that a division would have fairly equal overhead to assigning an incremented value...I haven't tested at all though so no idea how similar the overhead truly is (or not)rk84 wrote:Modulo seems to be popular option, but I dislike it. In my mind, its unnecessary calculation done on "every" tick.
Re: Find entity
Yea me too. Lately I have become more performance driven. Mayby I'm splitting hairs here, but small things tends to add up. Mayby its because my pc is on it's last legFreeER wrote:I've used Modulo mostly because that's how I learned, I would however think that a division would have fairly equal overhead to assigning an incremented value...I haven't tested at all though so no idea how similar the overhead truly is (or not)
When looking past the syntax sugar, modulo is more than just division.
Code: Select all
a % b == a - math.floor(a/b)*b
Test mode
Searching Flashlight
[WIP]Fluid handling expansion
[WIP]PvP gamescript
[WIP]Rocket Express
Autofill: The torch has been pass to Nexela
Searching Flashlight
[WIP]Fluid handling expansion
[WIP]PvP gamescript
[WIP]Rocket Express
Autofill: The torch has been pass to Nexela
Re: Find entity
Oh! Interesting, I wonder if that's due to lua using doubles... in assembly (with ints at least, I've never used floats/doubles in asm) modulo really is just division that returns the remainder rather than the quotient...at least from my understanding of how it works, which could be wrongrk84 wrote:When looking past the syntax sugar, modulo is more than just division.
Re: Find entity
Actually I might have been too fast to post that. (reference manual and some article/post let me assume things)FreeER wrote:Oh! Interesting, I wonder if that's due to lua using doubles... in assembly (with ints at least, I've never used floats/doubles in asm) modulo really is just division that returns the remainder rather than the quotient...at least from my understanding of how it works, which could be wrongrk84 wrote:When looking past the syntax sugar, modulo is more than just division.
I made crude test and % was visually faster than a-floor(a/b)*b (looping over 10mil times)
Test mode
Searching Flashlight
[WIP]Fluid handling expansion
[WIP]PvP gamescript
[WIP]Rocket Express
Autofill: The torch has been pass to Nexela
Searching Flashlight
[WIP]Fluid handling expansion
[WIP]PvP gamescript
[WIP]Rocket Express
Autofill: The torch has been pass to Nexela
Re: Find entity
Well I'm sure the % operator would be optimized enough to at least take out the overhead of a function call so that would account for some of the speed difference, however the real difference/test we care about here is between % and modifying a global table (regardless of how efficient % is compared to other remainder retrieving methods)...rk84 wrote:Actually I might have been too fast to post that. (reference manual and some article/post let me assume things)
I made crude test and % was visually faster than a-floor(a/b)*b (looping over 10mil times)
Re: Find entity
Thanks all, It's nice to see an active comunity.
I've found a mod called "Cobra Commander". It has several calls on "unit" that I could use as example to learn these "unit control commands".
The basic idea that I initially had was to create two automatons.
1º kind is the combat mech. Moves to a position after an order, kills anything on the way and returns. (more than one type here. Probably 1 for each weapon type as a mech, maybe a tank and an aircraft).
Example: In order to store the coordinates I need to create a matrix with "keyValue, position X, position Y, droppedItem". The only way that I've found to do it was using for. Something like this:
This is slow if I have to loop through the entire table every time that I want to find the nearest entity from my mech-base position. The table can became huge deppending of the resource type that I'm controlling(not limited to alien artifacts).
I've found a mod called "Cobra Commander". It has several calls on "unit" that I could use as example to learn these "unit control commands".
The basic idea that I initially had was to create two automatons.
1º kind is the combat mech. Moves to a position after an order, kills anything on the way and returns. (more than one type here. Probably 1 for each weapon type as a mech, maybe a tank and an aircraft).
To test the limits, I will probably insert some return to base conditions (25, 50, 75% damage) or less than X friendly mech units in a certain radius
2º kind is the support mech. Moves to a position and retrieves every alien artifact in their way and returns. (The find entity would be used for this guy to find that destination position without intervention).
The best Idea that I had up to now was to create a logic in the event at "Lua/Events.onentitydied" and log in a glob.array it's coordinates (only for those that could drop the alien artifacts). If this unity finds anything in this array, it moves through there and check the area. (additional control would be necessary at "Lua/Events.onpickedupitem" )
As I'm a complete beginner in LUA and it's veeery diferent from the language that I knoll (ABAP), I'm having some problems with these arrays. I have to study more first hehehe.Example: In order to store the coordinates I need to create a matrix with "keyValue, position X, position Y, droppedItem". The only way that I've found to do it was using for. Something like this:
Code: Select all
mt = {} -- create the matrix
for i=1,N do
mt[i] = {} -- create a new row
for j=1,M do
mt[i][j] = 0
end
end
source http://www.lua.org/pil/11.2.html
Probable solution found for this was to create another array related to the first one. {mech-base, Distance in the cartesian plane, keyValue
What do you guys think about my workarounds?Re: Find entity
You were right. Accessing/modifing global had more impact than I though. Also % is quite same level as division. Below is some test values. Values have bit of fluctuation.FreeER wrote:Well I'm sure the % operator would be optimized enough to at least take out the overhead of a function call so that would account for some of the speed difference, however the real difference/test we care about here is between % and modifying a global table (regardless of how efficient % is compared to other remainder retrieving methods)...
Performance.png
Test setup codes
Notes:
- Usage of local variables had the biggest impact. event.tick is faster then game.tick. Also tick (global) is bit faster then glob.tick.
- I also had loop test setup and assigning every value and function to local variable before loop can improve speed. Example "local floor = math.floor"
Test mode
Searching Flashlight
[WIP]Fluid handling expansion
[WIP]PvP gamescript
[WIP]Rocket Express
Autofill: The torch has been pass to Nexela
Searching Flashlight
[WIP]Fluid handling expansion
[WIP]PvP gamescript
[WIP]Rocket Express
Autofill: The torch has been pass to Nexela
Re: Find entity
I'm not quite sure of your plan yet. What are you planning to do with the matrix? do you use x and y coord as keys?CarpeDiem wrote:What do you guys think about my workarounds?
onpickedupitem works only in case of player. You could monitor your units command execution with "hascommand" possibly and store some value to tell what was it doing?
Code: Select all
if going_after_artifacts and not unit.hascommand then scanArea(unit.position) end
Also I have not fully tested, but you should be able to create groups, add units to group and command them as group. It might be worth exploring. I'm not sure about the behavior, but atleast during gathering units don't wander.
Code: Select all
group = game.createunitgroup(position)
group.addmember(unit)
group.setcommand(command)
Test mode
Searching Flashlight
[WIP]Fluid handling expansion
[WIP]PvP gamescript
[WIP]Rocket Express
Autofill: The torch has been pass to Nexela
Searching Flashlight
[WIP]Fluid handling expansion
[WIP]PvP gamescript
[WIP]Rocket Express
Autofill: The torch has been pass to Nexela
Re: Find entity
sounds pretty good. Also note rk84's comments of courseCarpeDiem wrote:What do you guys think about my workarounds?
Do you need an actual matrix or would a regular associative array (table) work? I personally find associative arrays easier to work with (and there's practically no additional overhead for them in lua, at least from my understanding...). note: a lot of this is pseudo codeCarpeDiem wrote: I need to create a matrix with "keyValue, position X, position Y, droppedItem"
Code: Select all
dropped_items = {}
on_item_dropped do -- pseudo event handler
-- note: I'm not sure what your keyValue is used for...
-- where position will be a typical table of {x=x_coord, y=y_coord}
table.insert(dropped_items, {keyValue=whatever, position=dropped_item.position, name=dropped_item.stack.name})
end
-- example use
on_retrieve_items do -- pseudo event handler (assuming distance from individual collector mech, not from a base)
local closest = {dist = math.huge, position=nil, name=nil}
for _, item in ipairs(dropped_items) do
-- function to calculate distance, assuming 'mech' is the entity that will pick it up, and require "util" (provided by Factorio)
local distance = util.distance(item.position, mech.position)
-- technically a bit of waste here since you create a new table instead of modifying closest's values...you're free to do that instead.
if distance < closest.dist then closest = {dist=distance, position=item.position, name=item.name} end
end
send_robot_to_collect(closest.position, closest.name) -- function (setcommand goto call?)
end
Now there's some interesting test result of course how much is 'a bit', mod-a and mod-tick have a difference of .9% and if it only fluctuates by .2% that's a decent difference (overall), though possibly only a small optimization when compared with any redundant for loops or multiple function calls that often return quickly (without doing anything)...rk84 wrote:Values have bit of fluctuation.
Re: Find entity
Both did a lot more than I hoped for. I will do some thinkering in the weekend when some spare time will be available.
As soon as I have something minimaly usefull I will post here.
Again, thank you.
As soon as I have something minimaly usefull I will post here.
Again, thank you.