Page 1 of 1

Ability to request the nearest enemy

Posted: Mon Oct 10, 2022 4:44 pm
by InappropriatePenguin
I'd like to propose the addition of LuaSurface::request_nearest_enemy.

Briefly, a call to this method would return a uint id for the request and would search for the nearest enemy entity meeting the specified criteria in a rate-limited way. Once the request is finished (upon finding an enemy, upon scanning the entire search radius, or upon invalidation of the search for a different reason like the surface getting deleted), an event is fired bearing the "id" of the request, in addition to the found entity (if any) and some other information (reasoning described below).

The idea is to tap into existing game logic that is used by artillery. The reason to use it over LuaSurface::find_nearest_enemy would be if a modder wants to search over a large or very large radius and does not need an immediate response. Instead of doing a blocking call that that could take many milliseconds to complete, they would make the request and wait for an answer. This would be very helpful in Space Exploration for weapons delivery cannons and energy beam emitters, both of which have surface-wide auto targeting mechanisms. While it would be possible to try to do that in Lua using find_entities_filtered calls in on_tick, it would be much nicer if that functionality is built into the API.

Proposed arguments:

position: <MapPosition> (required) Position around which to search
max_distance: <float> (required) Maximum search radius
min_distance?: <float> (optional, defaults to 0) Minimum distance between target and position
force?: <ForceIdentification> (optional, defaults to "player") Force, whose enemies you want to search for
include_non_military_targets (optional, defaults to false) Whether non-military targets should be included in search
include_mobile_units?: <bool> (optional, defaults to false) Default argument intended to mimic artillery logic
max_rate?: <uint> (optional, defaults to 1) Maximum number of chunks to scan per tick

Nice-to-have arguments, to make the function even more versatile:

only_charted_chunks: <bool> (optional, defaults to false) Whether to only include chunks charted by given force in search
entity?: <string|string[]> (optional) Entity name or names to include in search
type?: <string|string[]> (optional) Entity type or types to include in search
invert?: <bool> (optional, defaults to false) Whether entities matching "entity" and "type" should be ignored, instead of included.

Return value:

<uint>, id of the request

Proposed event:

on_script_nearest_enemy_request_finished, guaranteed to fire whether request is successful or not.

tick: <uint> Tick
name: <defines.event> Identifier of the event
id: <uint> Id identifying the request
entity?: <LuaEntity> Nearest enemy entity, if one was found
position?: <MapPosition> The position of the found entity (if one was found). The reason to include this separately from entity is to allow mods to distinguish between the searched area being clear of enemies and another mod's event handler destroying the entity, making it nil when other mods see it.

Re: Ability to request the nearest enemy

Posted: Mon Oct 10, 2022 7:52 pm
by Klonan
InappropriatePenguin wrote:
Mon Oct 10, 2022 4:44 pm
While it would be possible to try to do that in Lua using find_entities_filtered calls in on_tick, it would be much nicer if that functionality is built into the API.
I mean, you can say that about any part of mod making, hand-off the effort and maintenance of the code to the engine

But generally unless there is a base game use case or the function already exists in the engine and C++ side,
Then this is the sort of request that sounds like "Write my mod for me"

Re: Ability to request the nearest enemy

Posted: Mon Oct 10, 2022 8:20 pm
by InappropriatePenguin
I only thought to ask because I figured the game likely has much of this functionality (or something similar) already implemented for use with artillery based on a comment that Rseding made in the mod-making channel. It also seemed like something that other modders might make use of. Happy to do it on the Lua side if that's not the case.

Re: Ability to request the nearest enemy

Posted: Mon Oct 10, 2022 10:19 pm
by Wiwiweb
Klonan wrote:
Mon Oct 10, 2022 7:52 pm
or the function already exists in the engine and C++ side,
That's apparently the case here, used for the automatic artillery targeting?

Re: Ability to request the nearest enemy

Posted: Tue Oct 11, 2022 6:43 pm
by Rseding91
Wiwiweb wrote:
Mon Oct 10, 2022 10:19 pm
Klonan wrote:
Mon Oct 10, 2022 7:52 pm
or the function already exists in the engine and C++ side,
That's apparently the case here, used for the automatic artillery targeting?
The artillery logic iterates chunks in an outward spiral iterating the entities on the chunks until it finds one it can shoot at. This is split across multiple ticks and tightly integrated with the artillery logic itself. All of the temporary variables required to make it work across ticks are saved on a per-artillery basis and not something that we have any interest in splitting out into its own thing. There's no single function that produces the results if something outside of artillery asked for it.