Finding entities around position in direction

Place to get help with not working mods / modding interface.
Post Reply
Pi-C
Smart Inserter
Smart Inserter
Posts: 1653
Joined: Sun Oct 14, 2018 8:13 am
Contact:

Finding entities around position in direction

Post by Pi-C »

I want to compile a list of targets for a fluid turret. Gun turrets are easy as they cover 360°, but fluid turrets face one direction and can operate only on the segment of a circle.

I tried this:

Code: Select all

local enemies = turret.surface.find_entities_filtered{
            type = targets,
            position = turret.position,
            radius = turret.prototype.attack_parameters.range,
            direction = turret.direction,
        }
It doesn't work. Apparently, the parameter "direction" takes precedence over radius, so this actually searches for enemies along a straight line with length radius starting from turret.position and going in turret.direction. However, I want find enemies in the complete area covered by that turret, so this is not an option.

For my next attempt, I removed direction:

Code: Select all

local enemies = turret.surface.find_entities_filtered{
            type = targets,
            position = turret.position,
            radius = turret.prototype.attack_parameters.range,
        }
It doesn't work either. I find a number of enemies that way, but they may be within the complete circle around turret.position -- so this would also find enemies behind the turret. If I assign turret.shooting_target to one of the enemies the turret can't reach, it will do nothing because it has an order, but can't shoot at the given enemy.

I thought I could cover such cases by eliminating enemies where "turret.can_shoot(enemy, enemy.position) == false" from the list. Of course, that didn't work because can_shoot is for characters only.

So, what options do I have to find enemies within the area covered by a fluid turret?
A good mod deserves a good changelog. Here's a tutorial (WIP) about Factorio's way too strict changelog syntax!

User avatar
darkfrei
Smart Inserter
Smart Inserter
Posts: 2903
Joined: Thu Nov 20, 2014 11:11 pm
Contact:

Re: Finding entities around position in direction

Post by darkfrei »

1. (somehow) Recover from prototype the covered area https://lua-api.factorio.com/latest/Lua ... rret_range
2. Recalculate area as tiles respect to entity direction, save them into your global; also save minimal and maximal x and y
3. Find all enemies in area {{min_x, min_y}, {max_x, max_y}}, check if they are actually in saved area.

User avatar
Deadlock989
Smart Inserter
Smart Inserter
Posts: 2528
Joined: Fri Nov 06, 2015 7:41 pm

Re: Finding entities around position in direction

Post by Deadlock989 »

Trigonometry. Retrieve all filtered entities within radius, then test them all for their angle of incidence between the direction of fire and the value of attack_parameters.turn_range, which is the fraction of the full circle that the turret covers. Exclude those closer than min_range while you're at it.

https://www.euclideanspace.com/maths/al ... leBetween/
Image

Pi-C
Smart Inserter
Smart Inserter
Posts: 1653
Joined: Sun Oct 14, 2018 8:13 am
Contact:

Re: Finding entities around position in direction

Post by Pi-C »

darkfrei wrote:
Fri Mar 06, 2020 11:22 am
1. (somehow) Recover from prototype the covered area https://lua-api.factorio.com/latest/Lua ... rret_range
2. Recalculate area as tiles respect to entity direction, save them into your global; also save minimal and maximal x and y
3. Find all enemies in area {{min_x, min_y}, {max_x, max_y}}, check if they are actually in saved area.
1. Doing that already, that's how I could set the radius for my search.
2. Storing the area makes sense because the covered area will usually by constant. However, I'll need to listen to on_player_rotated_entity and recalculate the values for x and y if turret.direction has changed. Which reminds me: I'll also have to look at how entities are moved by Picker Dollies, so I can react if turret.position has been changed.
3. Shouldn't I look enemies in a radius around the turret here?
Deadlock989 wrote:
Fri Mar 06, 2020 11:27 am
Trigonometry. Retrieve all filtered entities within radius, then test them all for their angle of incidence between the direction of fire and the value of attack_parameters.turn_range, which is the fraction of the full circle that the turret covers.
This would mean calculations per unit found. I wanted to avoid that. :-D But thanks for attack_parameters.turn_range! I hadn't found how to determine the angle in which the turret operates, so that's quite useful.
Exclude those closer than min_range while you're at it.
I've been doing that already. :-)

While waiting for answers, I've been done some thinking of my own. I've come up with an approach similar to darkfrei's:
  • Determine rectangular area depending on turret direction.
  • Find enemies in that area and temporarily store them as enemy_area[enemy.unit_number] = unit.
  • Find enemies in radius around turret.position and store them as enemy_radius[enemy.unit_number] = 1. (Only the index is needed here!)
  • Check enemies in the area: if not (enemy_area[enemy.unit_number] and and enemy_radius[enemy.unit_number]), remove unit from enemy_area.
  • Also check that units stored in enemy_area are outside turret.min_range, discard unit otherwise.
  • Return enemy_area.
Now, this involves doing two searches and traversing one list to eliminate units the turret can't reach from the list. Intersecting two sets should work, but is it efficient or would using trigonometry calculations per unit be faster? Keep in mind that these turrets do only little damage, but cover a big area (default range: 50), so there could be quite a lot of enemies to check.
A good mod deserves a good changelog. Here's a tutorial (WIP) about Factorio's way too strict changelog syntax!

User avatar
Deadlock989
Smart Inserter
Smart Inserter
Posts: 2528
Joined: Fri Nov 06, 2015 7:41 pm

Re: Finding entities around position in direction

Post by Deadlock989 »

I'm curious as to why you want/need to do this. What can't you do with the normal turret operations? Some kind of "wave effect"?
Image

Pi-C
Smart Inserter
Smart Inserter
Posts: 1653
Joined: Sun Oct 14, 2018 8:13 am
Contact:

Re: Finding entities around position in direction

Post by Pi-C »

Deadlock989 wrote:
Fri Mar 06, 2020 12:38 pm
I'm curious as to why you want/need to do this. What can't you do with the normal turret operations? Some kind of "wave effect"?
It's about this mod. I want water turrets to be used for defense only, not offensively. The turrets do pretty little damage themselves, but they apply a "slow" sticker to hit targets, giving other turrets more time to target them. However, once they attack a spawner or worm, they won't quit until it is dead -- which will take a long time. The attack on spawners/worms will aggro a lot of biters -- the turret should attack them and leave spawners/worms alone.

Also, it seems only natural that water turrets can also function as fire extinguishers. Fighting enemies should be their top priority, though. Therefore I check each turret in regular intervals if it attacks a spawner/worm (immediately set shooting_target to nil and look for a better target) or fire (if there are enemies in the area, immediately set shooting_target to first enemy found, otherwise resume attacking the fire). Then I leave the turret alone for the next period (not sure yet, probably 5 to 10 seconds) and it will look for targets on its own. My script just gives the turret a nudge in the right direction. :-)
A good mod deserves a good changelog. Here's a tutorial (WIP) about Factorio's way too strict changelog syntax!

User avatar
Deadlock989
Smart Inserter
Smart Inserter
Posts: 2528
Joined: Fri Nov 06, 2015 7:41 pm

Re: Finding entities around position in direction

Post by Deadlock989 »

I have a similar entity, which fires an electric "stun beam", which does no damage, but applies the slow sticker in an area effect, so it catches a bunch of mobs.

Turrets can de-prioritise targets that are on fire automatically (maybe even prioritise them if it's a negative penalty but haven't tested that). It's used by the vanilla flame turret to stop focusing on a mob that's already burning. It would be nice if we could extend that to any specified sticker, but it's not in the API, it's hardcoded for fire only. You might be able to hax0r this by giving them a spread fire penalty effect of 0 or whatever but I didn't want to go there (and then also any nearby flame turrets will ignore them).
Image

Pi-C
Smart Inserter
Smart Inserter
Posts: 1653
Joined: Sun Oct 14, 2018 8:13 am
Contact:

Re: Finding entities around position in direction

Post by Pi-C »

Deadlock989 wrote:
Fri Mar 06, 2020 1:49 pm
Turrets can de-prioritise targets that are on fire automatically (maybe even prioritise them if it's a negative penalty but haven't tested that). It's used by the vanilla flame turret to stop focusing on a mob that's already burning. It would be nice if we could extend that to any specified sticker, but it's not in the API, it's hardcoded for fire only.
Darn it, I haven't done anything about fire stickers yet! So far, I'm looking for fire entities and mark them with a dummy (simple-entity-with-health) that's only vulnerable to damage done by my turret. If a dummy dies, I destroy the fire entities in a radius around it. But of course, that wouldn't work for, say, an assembling machine that has been set aflame, right?
A good mod deserves a good changelog. Here's a tutorial (WIP) about Factorio's way too strict changelog syntax!

User avatar
Deadlock989
Smart Inserter
Smart Inserter
Posts: 2528
Joined: Fri Nov 06, 2015 7:41 pm

Re: Finding entities around position in direction

Post by Deadlock989 »

I don't know. I didn't think stickers could be applied to anything that isn't a unit, but I might be wrong. I don't think turrets will target anything that doesn't have force aggro - so they'll go for units and they'll go for turrets (worms are turrets) and I guess they might go for SimpleEntityWithForce-s (don't know, but biters love to eat them), but I don't think a turret will attempt to attack an enemy assembling machine or even a wall.

Edited to add, confirmed that turrets ignore everything that doesn't explicitly have a force. The Text Plates letter in the below is a SimpleEntityWithForce. Everything else was ignored.
Untitled.jpg
Untitled.jpg (411.46 KiB) Viewed 1269 times

I realise this has drifted off topic a bit, I was just wondering whether there was a zero- or very light-scripted way of achieving what you want.
Image

Pi-C
Smart Inserter
Smart Inserter
Posts: 1653
Joined: Sun Oct 14, 2018 8:13 am
Contact:

Re: Finding entities around position in direction

Post by Pi-C »

Deadlock989 wrote:
Fri Mar 06, 2020 2:29 pm
I don't know. I didn't think stickers could be applied to anything that isn't a unit, but I might be wrong.
If cars/tanks are attacked by worms/spitters, don't they get a sticker as well?
I don't think turrets will target anything that doesn't have force aggro - so they'll go for units and they'll go for turrets (worms are turrets) and I guess they might go for SimpleEntityWithForce-s (don't know, but biters love to eat them), but I don't think a turret will attempt to attack an enemy assembling machine or even a wall.
I was thinking of extinguishing fire if my own assemblers are burning. Fire could have been caused by player + flamethrower, area effects of own flamethrower turrets, modded units that cause fire damage, or disaster mods for all I care. :-)
Edited to add, confirmed that turrets ignore everything that doesn't explicitly have a force. The Text Plates letter in the below is a SimpleEntityWithForce. Everything else was ignored.
In this case, placing a dummy on top of the assembler (like I do with fire entities) would be the way to go, I guess.
I realise this has drifted off topic a bit, I was just wondering whether there was a zero- or very light-scripted way of achieving what you want.
I don't mind about drifting off topic as I got some new pointers by it. :-)

The solution with least hassle would be if fluid-turret prototypes would also get the property can_shoot(target, position). Guess I'll make an interface request. :-)
A good mod deserves a good changelog. Here's a tutorial (WIP) about Factorio's way too strict changelog syntax!

User avatar
Deadlock989
Smart Inserter
Smart Inserter
Posts: 2528
Joined: Fri Nov 06, 2015 7:41 pm

Re: Finding entities around position in direction

Post by Deadlock989 »

Pi-C wrote:
Fri Mar 06, 2020 3:07 pm
If cars/tanks are attacked by worms/spitters, don't they get a sticker as well?
Makes sense, they are unit-like in some ways.
Image

Post Reply

Return to “Modding help”