Add trigger_target_mask directly to land-mine

Place to ask discuss and request the modding support of Factorio. Don't request mods here.
Post Reply
User avatar
raiguard
Factorio Staff
Factorio Staff
Posts: 449
Joined: Wed Dec 13, 2017 8:29 pm
Contact:

Add trigger_target_mask directly to land-mine

Post by raiguard »

Greetings,

I am (ab)using land mines for range detection on Krastorio 2's tesla coil. It's working wonderfully, but there is one small issue: The land mine is constantly exploding due to the fact that it is directly overlapping the tesla coil tower, and it's set to explode for allied forces. Its script action is filtering on trigger_target_mask, but that only happens after the land mine has already exploded.

This is causing a noticeable UPS drain. With 900 tesla coils, land-mine is consuming about 4 ms of update time. This is obviously not ideal. The only way I can think of to solve this is to add a filtering mechanism directly to the land mine, so it only explodes when it needs to.

Using land mines is the only solution that works, because there were issues I ran in to with using turrets. The turrets were not staying "awake" and the tesla coils were not waking them up. Adding an entity to keep the tesla coil turrets or the active defense equipment awake caused enormous problems with friendly fire and/or UPS drain.

But, I digress. Adding a way to filter targets on the land-mine itself is the only solution I see short of making a dedicated range detection entity.
Don't forget, you're here forever.

User avatar
raiguard
Factorio Staff
Factorio Staff
Posts: 449
Joined: Wed Dec 13, 2017 8:29 pm
Contact:

Re: Add trigger_target_mask directly to land-mine

Post by raiguard »

Update: The UPS drain gets worse as you add entities around the tesla coils. The mine has a radius of 20, so it triggering on absolutely every entity around it. Adding filtering directly to the land-mine would solve this issue as well.
Don't forget, you're here forever.

User avatar
Klonan
Factorio Staff
Factorio Staff
Posts: 5148
Joined: Sun Jan 11, 2015 2:09 pm
Contact:

Re: Add trigger_target_mask directly to land-mine

Post by Klonan »

Raiguard wrote:
Thu Jan 06, 2022 5:38 am
The turrets were not staying "awake" and the tesla coils were not waking them up.
In this case, what I have found to work well is to make a proxy turret on an enemy force, set it to non-destructible, and then you have the filtering and everything,

I have found it works better than the landmine situation

I attach an example:

Code: Select all

function Object:create_detectors()
  self.detectors = {}
  local position = self.entity.position
  for k, offset in pairs (detector_offsets) do
    local detector = self.entity.surface.create_entity
    {
      name = "detector",
      position = {position.x + offset[1], position.y + offset[2]},
      force = Object.get_detector_force()
    }
    detector.destructible = false
    script_data.detector_mapping[detector.unit_number] = self.unit_number
    self.detectors[detector.unit_number] = detector
  end
end

function Object:triggered(entity)
  -- your code here
end

local on_script_trigger_effect = function(event)

  local source = event.source_entity
  if not (source and source.valid) then return end

  if source.name ~= "object-detector" then
    return
  end

  local target = event.target_entity
  if not (target and target.valid) then return end

  local object_unit_number = script_data.detector_mapping[source.unit_number]
  if not object_unit_number then return end

  local object = Object.get(object_unit_number)
  if not object then return end

  object:triggered(target)

end

Code: Select all

local detector =
{
  type = "electric-turret",
  name = "object-detector",
  icon = "__base__/graphics/icons/small-worm.png",
  icon_size = 64, icon_mipmaps = 4,
  flags = {"placeable-off-grid", "player-creation", "not-on-map"},
  order="b-c-a",
  max_health = 9999999,
  subgroup="enemies",
  collision_box = {{0,0}, {0, 0}},
  collision_mask = {},
  selectable_in_game = false,
  shooting_cursor_size = 0,
  folded_speed = 1,
  folded_animation = empty,
  preparing_speed = 1,
  preparing_animation = empty,
  prepared_speed = 1,
  prepared_animation = empty,
  prepared_alternative_speed = 1,
  starting_attack_speed = 1,
  starting_attack_animation = empty,
  ending_attack_speed = 1,
  ending_attack_animation = empty,
  folding_speed = 1,
  folding_animation = empty,
  attack_parameters =
  {
    type = "projectile",
    range = 1,
    cooldown = 1,
    ammo_type =
    {
      category = "melee",
      target_type = "position",
      energy_consumption = "1J",
      action =
      {
        type = "direct",
        action_delivery =
        {
          type = "instant",
          source_effects =
          {
            {
              type = "nested-result",
              affects_target = true,
              action =
              {
                type = "area",
                radius = 1,
                collision_mode = "distance-from-center",
                ignore_collision_condition = true,
                force = "enemy",
                action_delivery =
                {
                  type = "instant",
                  target_effects =
                  {
                    {
                      type = "script",
                      effect_id = "object-triggered"
                    }
                  }
                }
              }
            }
          }
        }
      }
    }
  },
  call_for_help_radius = 0,
  energy_source =
  {
    type = "void",
    emissions_per_minute = 0.0001
  }
}
Internally also, turret finds only 'EntityWithForce', things like character, units, spiders,
This uses a much faster search than landmine, which finds all EntityWithOwner, doing an expensive surface search

User avatar
raiguard
Factorio Staff
Factorio Staff
Posts: 449
Joined: Wed Dec 13, 2017 8:29 pm
Contact:

Re: Add trigger_target_mask directly to land-mine

Post by raiguard »

Using a proxy turret was the original solution I tried. However, it didn't work properly, because it would not wake up and fire upon locomotives. Charging locomotives is one of the primary usecases for the Tesla coil.

Adding an EntityWithForce to keep the turrets from going to sleep caused massive UPS issues. 1000 Tesla coils used 18 ms of update time. I then switched to using active defense equipment, but that required me to put an entitywithforce in the Tesla coil so make the defense equipment fire at something. However, friendly turrets would also fire at Tesla coils using this method.

This is why I ended up at land mines - it's the only solution that works with locomotives without introducing other major issues. The only issue is the UPS, which is the problem I'm looking to solve.
Don't forget, you're here forever.

User avatar
Klonan
Factorio Staff
Factorio Staff
Posts: 5148
Joined: Sun Jan 11, 2015 2:09 pm
Contact:

Re: Add trigger_target_mask directly to land-mine

Post by Klonan »

Raiguard wrote:
Thu Jan 06, 2022 5:05 pm
However, it didn't work properly, because it would not wake up and fire upon locomotives. Charging locomotives is one of the primary usecases for the Tesla coil.
Yea, locomotives are not an entityWithForce,
I would have suggested to use a small invisible combat robot set to follow the locomotive

Using landmine will always have a performance penalty in this way,
The problem isn't just the triggering on entities, but the entity search itself is a very large part of the performance problem,
And any filtering is still going to have to find all the entities nearby and match against the trigger target mask

User avatar
Klonan
Factorio Staff
Factorio Staff
Posts: 5148
Joined: Sun Jan 11, 2015 2:09 pm
Contact:

Re: Add trigger_target_mask directly to land-mine

Post by Klonan »

One small thing, the collision mask that the landmine was checking for the triggering was hardcoded,
For the next release we've added `trigger_collision_mask` to the land mine prototype

So now for instance, you can set the trigger collision mask to `{"train-layer"}`, and it will only trigger on entities that collide with the train layer (so things like trains, player character, etc.)

User avatar
boskid
Factorio Staff
Factorio Staff
Posts: 2227
Joined: Thu Dec 14, 2017 6:56 pm
Contact:

Re: Add trigger_target_mask directly to land-mine

Post by boskid »

LandMines are quite heavy due to EntitySearch they are doing every 10 ticks, but they are able to detect any type of EntityWithHealth. There is one small catch, when a LandMine has forceCondition of "Enemy", a landmine that is armed and did not blowup immediately after arming will go to sleep and it can only be woken up by EntityWithForce in current or nearby chunk.

For 1.1.51 i extracted LandMinePrototype::trigger_collision_mask since there was a certain collision mask hardcoded inside of the LandMine logic (it was using "item-layer", "object-layer", "player-layer", "water-tile") used to test if it should explode. This does not fulfill this modding interface request (i guess).

User avatar
raiguard
Factorio Staff
Factorio Staff
Posts: 449
Joined: Wed Dec 13, 2017 8:29 pm
Contact:

Re: Add trigger_target_mask directly to land-mine

Post by raiguard »

Thanks for looking into it. I'm still going to have to keep the land mines, because the turrets have edge cases that I cannot solve for. So I appreciate the improvements that you're making!
Don't forget, you're here forever.

Post Reply

Return to “Modding interface requests”