Page 1 of 1

How to remove the collision field from the turret and make it invisible to enemies until the attack?

Posted: Thu Nov 21, 2024 5:55 am
by Keysivi
Good day? I'm trying to revive my mod for Factorio 2

Specifically, there was a problem with poisonous barbed barriers

The parameters "collision_mask" and "hidden" stopped working

The task: so that the Character and Enemies can freely pass through the barriers, but during the passage through the barrier, the enemies take damage.

Here is the code that was originally:

Code: Select all

-- require("__My_add_pack__.prototype.barbed-spikes-wooden.effects")	

data:extend(
{
	{
		type = "sticker",
		name = "wooden-barbed-spike-slowdown-sticker_ke",
		flags = { "not-on-map" },
		flags = {},
		animation =
		{
			filename = "__My_add_pack__/graphics/barbed-spikes-wooden/clear.png",
			priority = "extra-high",
			width = 2,
			height = 2,
			frame_count = 1
		},
		duration_in_ticks = 100,
		target_movement_modifier = 0.5
	}
})

function data_sheet(inputs)
return
	{
		layers = 
		{
			{
				  filename = "__My_add_pack__/graphics/barbed-spikes-wooden/base.png",
				  priority = "high",
				  width = 172,
				  height = 172,
				  direction_count = 1,
				  frame_count = 1,
				  line_length = 0,
				  run_mode = inputs.run_mode or "forward",
				  axially_symmetrical = false,
				  shift = { 0, 0 },
				  scale = 0.5
			}
		}
	}
end
data:extend(
{
  
  {
    type = "turret",
    name = "wooden-barbed-spike",
    icon = "__My_add_pack__/graphics/barbed-spikes-wooden/icon.png",
    icon_size = 64, icon_mipmaps = 4,
    flags = {"placeable-player","not-rotatable","player-creation","not-flammable","hidden"},
    minable = {mining_time = 1, result = "wooden-barbed-spike"},
    max_health = 56,
    corpse = "wooden-barbed-spike-remnants",
    dying_explosion = "wall-explosion",
    selection_box = {{-1, -1 }, {1, 1}},
	collision_box = {{-0.8, -0.8}, {0.8, 0.8}},
    collision_mask = {"object-layer","water-tile","resource-layer"},
    rotation_speed = 1,
    preparing_speed = 1,
	walking_speed_modifier = 1.0,
    folding_speed = 1.0,
    starting_attack_speed = 0.01,
    attacking_speed = 1.0,
    alert_when_attacking = true,
	alert_when_damaged = true,
	create_ghost_on_death = true,
	folded_animation = data_sheet{direction_count = 8, line_length = 0},

	preparing_animation = data_sheet{frame_count=1, line_length = 0},
    prepared_animation = data_sheet{},
    attacking_animation = data_sheet{},
	folding_animation = data_sheet{frame_count=1, line_length = 0, run_mode = "backward"},
	resistances = {
      {
        type = "fire",
        percent = 4.0
      },
      {
        type = "physical",
        percent = 4.0
      },
	  {
        type = "poison",
        percent = 100
      },
	  {
        type = "explosion",
        percent = 4.0
      },
	  {
        type = "laser",
        percent = 4.0
      },
	  {
        type = "acid",
        percent = 4.0
      },
	  {
        type = "electric",
        percent = 100
      },
	}, 
    base_picture =
    {
      layers =
      {
        {
          filename = "__My_add_pack__/graphics/barbed-spikes-wooden/base.png",
          priority = "high",
          width = 86,
          height = 86,
          axially_symmetrical = false,
          direction_count = 1,
          frame_count = 1,
          shift = { 0, 0 },
          hr_version =
          {
            filename = "__My_add_pack__/graphics/barbed-spikes-wooden/hr-base.png",
            priority = "high",
            width = 172,
            height = 172,
            axially_symmetrical = false,
            direction_count = 1,
            frame_count = 1,
            shift = { 0, 0 },
            scale = 0.5
          }
        },
      }
    },
	attack_parameters =
		{
		  type = "projectile",
		  ammo_category = "bullet",
		  cooldown = 0.01,
		  projectile_creation_distance = 0,
		  projectile_center = {0, 0},
		  damage_modifier = 1,
		  ammo_type =
		  {
			category = "biological",
			action =
			{
				type = "area",
				radius = 2.0,
				action_delivery = 
				{
					type = "instant",
					target_effects =
					{
						{
							type = "damage",
							damage = {amount = 2.1, type = "physical"}
						},
						{
							type = "damage",
							damage = {amount = 2.1, type = "poison"}
						},
						{
							type = "create-sticker",
							sticker = "slowdown-sticker"
						},
						{
							type = "create-sticker",
							sticker = "wooden-barbed-spike-slowdown-sticker_ke"
						},
					}
				
				},
			}
		  },
		  range = 2.00,
		  min_range = 0,
		},
    call_for_help_radius = 0,
  },
})

Here are the lines that stopped working correctly with Factorio 2:

Code: Select all

 
flags = {"placeable-player","not-rotatable","player-creation","not-flammable","hidden"},
collision_mask = {"object-layer","water-tile","resource-layer"},
I tried to replace them with the lines:

Code: Select all

 
flags = {"placeable-player","not-rotatable","player-creation","not-flammable"},
hidden = true,
collision_mask = {layers = {item = true, meltable = true, object = true, player = true, water_tile = true, is_object = true, is_lower_object = true}},	
It doesn't work!

It also shows an error:
4.822 Error ModManager.cpp:1738: Error while loading entity prototype "wooden-barbed-spike" (turret): Value must be a dictionary in property tree at ROOT.turret.wooden-barbed-spike.collision_mask
Modifications: My_add_pack

Re: How to remove the collision field from the turret and make it invisible to enemies until the attack?

Posted: Sun Dec 22, 2024 4:46 pm
by IsaacOscar
Hmm, from reading the documentation (https://lua-api.factorio.com/latest/pro ... ision_mask, and https://lua-api.factorio.com/latest/typ ... ector.html) you're collision_mask seems correct.
It also follows the format used in the base game luas, e.g. https://github.com/wube/factorio-data/b ... s.lua#L583

So that error message doesn't make any sense, I think you'll have to attach your mod zip so I can try and work it out.

Re: How to remove the collision field from the turret and make it invisible to enemies until the attack?

Posted: Mon Dec 23, 2024 6:36 am
by Keysivi
IsaacOscar wrote: Sun Dec 22, 2024 4:46 pm Hmm, from reading the documentation (https://lua-api.factorio.com/latest/pro ... ision_mask, and https://lua-api.factorio.com/latest/typ ... ector.html) you're collision_mask seems correct.
It also follows the format used in the base game luas, e.g. https://github.com/wube/factorio-data/b ... s.lua#L583

So that error message doesn't make any sense, I think you'll have to attach your mod zip so I can try and work it out.
Good day! Thanks for the comment!

I moved "Poisonous Thorns" to a separate mod. Attached is the archive with the mod.

Re: How to remove the collision field from the turret and make it invisible to enemies until the attack?

Posted: Mon Dec 23, 2024 1:06 pm
by Keysivi
IsaacOscar wrote: Sun Dec 22, 2024 4:46 pm Так что это сообщение об ошибке не имеет никакого смысла.
The problem is that the Factorio 2.0 update broke 2 things

1. Previously, both the player and enemies could move along the spikes.
Now this is not possible.
2. Enemies did not see the spikes and attacked the spikes only when they started to take damage from the spikes.
Now enemies attack the spikes as soon as they see them.

Re: How to remove the collision field from the turret and make it invisible to enemies until the attack?

Posted: Tue Dec 24, 2024 1:58 pm
by IsaacOscar
Using the collision_mask you provided above did not cause any errors, unfortunately I couldn't get the behaviour you described (bitters just run straight towards the spikes and attack them).

I tried various ways of fiddling with the collision mask, but I still couldn't get it to work as you described.
So my advice would be to consider making them 'land-mines' and not 'turrets', because bitters will walk straight through land mines without attacking.

Re: How to remove the collision field from the turret and make it invisible to enemies until the attack?

Posted: Wed Dec 25, 2024 7:08 pm
by Keysivi
IsaacOscar wrote: Tue Dec 24, 2024 1:58 pm Using the collision_mask you provided above did not cause any errors, unfortunately I couldn't get the behaviour you described (bitters just run straight towards the spikes and attack them).

I tried various ways of fiddling with the collision mask, but I still couldn't get it to work as you described.
So my advice would be to consider making them 'land-mines' and not 'turrets', because bitters will walk straight through land mines without attacking.
Got it. Thanks for your participation and advice.I had thoughts about mines too.

I'll have to experiment in this direction. The only problem is how to remove the mine's self-destruction upon contact with enemies? But, at the same time, make it so that during contact with enemies it receives gradual damage?

Re: How to remove the collision field from the turret and make it invisible to enemies until the attack?

Posted: Thu Dec 26, 2024 5:07 am
by IsaacOscar
Try setting force_die_on_attack to false (see https://lua-api.factorio.com/latest/pro ... _on_attack)
and have the action trigger damage the 'landmine'

Re: How to remove the collision field from the turret and make it invisible to enemies until the attack?

Posted: Thu Jan 02, 2025 5:15 pm
by Keysivi
In general, I tried to change the "turret" type to the "land-mine" type.... Some kind of crap came out...

And some strange error. It complains about "unknown damage". As I understand it - that for "land-mine" damage of the "poison" type is unacceptable.

As they say - "the trick failed - the fakir was drunk"...

Just in case, I am attaching the code of the "entity" file and errors

Code: Select all

data:extend(
{
	{
		type = "sticker",
		name = "wooden-barbed-spike-slowdown-sticker_ke",
		flags = { "not-on-map" },
		animation =
		{
			filename = "__Poisonous_barbed_spikes__/graphics/barbed-spikes-wooden/clear.png",
			priority = "extra-high",
			width = 2,
			height = 2,
			frame_count = 1
		},
		duration_in_ticks = 200,
		target_movement_modifier = 0.2
	}
})

local hit_effects = require("__base__.prototypes.entity.hit-effects")
local sounds = require("__base__.prototypes.entity.sounds")

data:extend(
{
	{
		type = "land-mine",
		name = "wooden-barbed-spike",
		icon = "__base__/graphics/icons/land-mine.png",
		flags =
		{
			"placeable-player",
			"placeable-enemy",
			"player-creation",
			"placeable-off-grid",
			"not-on-map"
		},
		minable = {mining_time = 1, result = "wooden-barbed-spike"},
		fast_replaceable_group = "land-mine",
		mined_sound = sounds.deconstruct_small(1.0),
		max_health = 56,
		corpse = "land-mine-remnants",
		dying_explosion = "wall-explosion",
		selection_box = {{-1, -1 }, {1, 1}},
		collision_box = {{-0.8, -0.8}, {0.8, 0.8}},
		damaged_trigger_effect = hit_effects.entity(),
		open_sound = sounds.machine_open,
		close_sound = sounds.machine_close,
		force_die_on_attack = false,
		picture_safe =
		{
			filename = "__Poisonous_barbed_spikes__/graphics/barbed-spikes-wooden/base.png",
			priority = "medium",
			width = 172,
			height = 172,
			scale = 0.5
		},
		picture_set =
		{
			filename = "__Poisonous_barbed_spikes__/graphics/barbed-spikes-wooden/base.png",
			priority = "medium",
			width = 172,
			height = 172,
			scale = 0.5
		},
		picture_set_enemy =
		{
			filename = "__Poisonous_barbed_spikes__/graphics/barbed-spikes-wooden/base.png",
			priority = "medium",
			width = 172,
			height = 172,
		},
		trigger_radius = 2.0,
		ammo_category = "land-mine",
		action =
		{
			type = "direct",
			action_delivery =
			{
				type = "instant",
				source_effects =
				{
					{
						type = "nested-result",
						affects_target = true,
						action =
						{
							type = "area",
							radius = 2.0,
							force = "enemy",
							action_delivery =
							{
								{
									type = "damage",
									damage = {amount = 2.1, type = "physical"}
								},
								{
									type = "damage",
									damage = {amount = 4.2, type = "poison"}
								},
								{
									type = "create-sticker",
									sticker = "slowdown-sticker"
								},
								{
									type = "create-sticker",
									sticker = "wooden-barbed-spike-slowdown-sticker_ke"
								}
							}
						}
					}
				}
			}
		}
	}
})

Code: Select all

The following mods failed to load: Error while loading entity prototype "wooden-barbed-spike" (land-mine): Unknown attack delivery type: damage

Re: How to remove the collision field from the turret and make it invisible to enemies until the attack?

Posted: Fri Jan 03, 2025 3:28 am
by IsaacOscar
Keysivi wrote: Thu Jan 02, 2025 5:15 pm In general, I tried to change the "turret" type to the "land-mine" type.... Some kind of crap came out...

And some strange error. It complains about "unknown damage". As I understand it - that for "land-mine" damage of the "poison" type is unacceptable.

Code: Select all

The following mods failed to load: Error while loading entity prototype "wooden-barbed-spike" (land-mine): Unknown attack delivery type: damage
That's not what the error message means! It's saying that you can't use "type = "damage"" where an "attack delivery" is expected..
Specifically, as listed here https://lua-api.factorio.com/latest/typ ... rItem.html, the "action_delivery" field of your "type = "area" object, should be a single TriggerDelivery or an array of TriggerDelivery. You've got an array, but if you look at https://lua-api.factorio.com/latest/typ ... ivery.html. you will see that none of the valid TriggerDelivery's have type = damage (i.e. there is no DamageTriggerDelivery). There is a DamageTriggerEffectItem ( https://lua-api.factorio.com/latest/typ ... tItem.html), but that's not a TriggerDelivery!

Sorry, triggers are very annoying (as there are three 'kinds': Triggers, TriggerDeliverys, and TriggerEffects).

I've also noticed you have a 'nested-result' (a https://lua-api.factorio.com/latest/typ ... tItem.html), which seems entirely redundant. Also I assume you want the spikes to damage any biters that step on them (and not damage the spikes themselves), in which case I think that you should use source_effects instead of target_effects (I'm not sure, as the trigger/effect system is very much not documented!)

So I suggest making the following changes:
  • 1. To remove the unecessary 'nested-result' thing, replace the lines

    Code: Select all

    action =
    {
    	type = "direct",
    	action_delivery =
    	{
    		type = "instant",
    		source_effects =
    		{
    			{
    				type = "nested-result",
    				affects_target = true,
    				action =
    				{
    
    With:

    Code: Select all

    action = 
    {
    
    (and remove four closing '}' lines at the end).

    2. To fix the error about 'damage' and use my suggestion to not use source_effects
    Replace

    Code: Select all

    action_delivery =
    {
    	{
    		type = "damage",
    
    With

    Code: Select all

    action_delivery =
    {
    	type = "instant",
    	target_effects = 
    	{
    		{
    			type = "damage",
    
    You'll also need to add a closing curly brace "}" (after the sticker = ... line)

Re: How to remove the collision field from the turret and make it invisible to enemies until the attack?

Posted: Fri Jan 03, 2025 5:14 pm
by Keysivi
Thank you very much!

I made the changes you suggested to the code and everything worked out! Thank you! Everything works even better than in the old version. (Just in case, I am attaching the file with the changes.)

However, now I will rebalance the spikes. Because enemies die on them almost instantly

Regarding nesting: I formed an experimental table of the "poisonous spikes" entity based on the "land-mine" table, there was exactly this nesting... But if it is unnecessary - I agree with you!

Regarding damage - balance is important to me, so that the spikes do not become an absolute cheat...

In the old version in Factorio 1.1 and in the new version - "land-mine", enemies attack the spikes after they start receiving damage from the spikes... This is a fairly logical solution

I was thinking about the option that the spikes themselves would receive a little damage at the moment of causing damage to enemies, but how difficult it is, I do not know...

Re: How to remove the collision field from the turret and make it invisible to enemies until the attack?

Posted: Fri Jan 03, 2025 10:19 pm
by Keysivi
Unfortunately, I was wrong. Enemies attack spikes only within the framework of priorities - in the absence of more important targets.

If enemies see the character or other objects and buildings - enemies ignore spikes and stupidly crawl on them until they die. Which breaks the entire game balance...

There are four points that I would like to implement in this mod, but I don't know how to do it.:

1. So that spikes start to deal damage with a small delay, about a quarter of a second...
2. So that enemies "do not see" spikes until the moment of receiving damage from spikes...
3. So that enemies start to attack spikes only after receiving damage from spikes...
4. So that spikes, while dealing damage to enemies, themselves also take a little damage...

Re: How to remove the collision field from the turret and make it invisible to enemies until the attack?

Posted: Sat Jan 04, 2025 11:12 am
by IsaacOscar
Keysivi wrote: Fri Jan 03, 2025 10:19 pm 1. So that spikes start to deal damage with a small delay, about a quarter of a second...
I showed you how to do this before with your explosive mining drill thingy. But here's what to do for your spikes.
Replace

Code: Select all

action_delivery =
{
	type = "instant",
	target_effects =
	{
		... -- all your { type = "damage", ... } things you want to be delayed
		... -- anything you don't want to be delayed
	}
}
With

Code: Select all

action_delivery = 
{
	{
		type = "instant",
		target_effects =
		{
			... -- anything you don't want to be delayed
		}
	},
	{
		type = "delayed",
		delayed_trigger = "spike-trigger",
	}
}
And add

Code: Select all

data:extend
{
	{
		type = "delayed-active-trigger"
		name = "spike-trigger",
		delay = 60/4, -- a quarter of a second
		action = 
		{
			type = "direct",
			action_delivery = 
			{
				type = "instant",
				target_effects = 
				{
					... -- all your { type = "damage", ... } things you want to be delayed
				}
			}
		}
	}
}
Keysivi wrote: Fri Jan 03, 2025 10:19 pm 2. So that enemies "do not see" spikes until the moment of receiving damage from spikes...
3. So that enemies start to attack spikes only after receiving damage from spikes...
I was hoping that's what a land-mine prototype would do. My only other idea is to fiddle with is_militrary_target. The idea is that at runtime, it will initially be false, so that bitters will prioritise attacking other military targets (like turrets). But once a bitter has been hurt by the spikes, they will become military targets, causing bitters to prioritise attacking the spikes (assuming they are closer than any other military targets). Unfortunately, is_militrary_target applies to all enemies, not just a single bitter. So any other bitters (even those that haven't been hit by the spikes yet), will also prioritise attacking the spikes.
I'll also have a cooldown so that is_military_target turns off after a while, so the biters will forget about them. (In particular, if you get attacked later by another group of bitters, they will not prioritise the spikes, unless the attack is within the cooldown period).

So to do this, in the prototype of your 'land-mine', set:

Code: Select all

is_military_target = false,
allow_run_time_change_of_is_military_target = true,
Then add a script trigger effect in the same target_effects list as the one with your damage effect:

Code: Select all

{
	type = "script",
	effect_id = "spike-effect"
}
Then in control.lua

Code: Select all

local cooldown = 60 -- how long after the bitters are hit should they forget about the spikes?
local accuracy = 1 -- how accurate you want the cooldown to be (1 for perfect accuracy, higher numbers will be faster).
storage.spikes = storage.spikes or {} -- storage.spikes[id] will be the last tick that the spikes with the given id hit something

script.on_event(defines.event.on_script_trigger_effect, function(event) -- will be run every time a spike damages someone
	if effect_id == "spike-effect" then
		event.target_entity.is_military_target = true -- bitters should now attack the spikes more aggressively
		storage[event.target_entity.unit_number] = {entity = event.target_entity, tick = event.tick} -- remember when the spikes where last trigerred
	end
end)

-- Now periodically, have the bitters forget about the spikes
script.on_nth_tick(accuracy, function(event) 
	for id, record in pairs(storage.spikes) do
		if event.tick >= record.tick + cooldown then
			if record.entity.valid then -- need to check that the spikes haven't been destroyed yet
				record.entity.is_military_target = false
			end
			storage.spikes[id] = nil -- don't bother checking on these spikes again
		end
	end
end)
Warning, as usual I haven't tested any of that, but hopefully you're getting good enough to fix any typos I've made?
Keysivi wrote: Fri Jan 03, 2025 10:19 pm 4. So that spikes, while dealing damage to enemies, themselves also take a little damage...
Now that is what source_effects are for! (I think).
Right above one of the target_effects = lines (depending on whether you want this self damage to be delayed by a quarter second or not), add:

Code: Select all

source_effects = 
{
	type = "damage",
	damage =
	{
		amount = 10, -- or however much damage you want
		type  = "physical" -- or whatever damage type you want (I think it will only make a difference if your spikes have a resistance to this type of damage)
	}
},

Re: How to remove the collision field from the turret and make it invisible to enemies until the attack?

Posted: Sat Jan 04, 2025 3:30 pm
by Keysivi
IsaacOscar wrote: Sat Jan 04, 2025 11:12 am Warning, as usual I haven't tested any of that, but hopefully you're getting good enough to fix any typos I've made?
Unfortunately, you had too high an opinion of my abilities...

I couldn't figure out this error:

Code: Select all

__Poisonous_barbed_spikes__/control.lua:5: attempt to index field 'event' (a nil value)
stack traceback:
	__Poisonous_barbed_spikes__/control.lua:5: in main chunk
Complains about this line:

Code: Select all

script.on_event(defines.event.on_script_trigger_effect, function(event)

Re: How to remove the collision field from the turret and make it invisible to enemies until the attack?

Posted: Sat Jan 04, 2025 3:39 pm
by IsaacOscar
Keysivi wrote: Sat Jan 04, 2025 3:30 pm Unfortunately, you had too high an opinion of my abilities...

I couldn't figure out this error:

Code: Select all

__Poisonous_barbed_spikes__/control.lua:5: attempt to index field 'event' (a nil value)
stack traceback:
	__Poisonous_barbed_spikes__/control.lua:5: in main chunk
Complains about this line:

Code: Select all

script.on_event(defines.event.on_script_trigger_effect, function(event)
That's because it's defines.events not defines.event (I forgot an "s") (check for any other occurrences of defines.event as well)

Re: How to remove the collision field from the turret and make it invisible to enemies until the attack?

Posted: Sat Jan 04, 2025 8:23 pm
by Keysivi
Unfortunately, during testing it turned out that the "spike-effect" does not work. Biters do not attack spikes.

Another problematic point was also revealed. Pentapods creatures have the ability to destroy buildings under their feet while walking. But in the case of the "land-mine" this effect does not work.

Re: How to remove the collision field from the turret and make it invisible to enemies until the attack?

Posted: Wed Jan 08, 2025 1:23 am
by IsaacOscar
Keysivi wrote: Sat Jan 04, 2025 8:23 pm Unfortunately, during testing it turned out that the "spike-effect" does not work. Biters do not attack spikes.

Another problematic point was also revealed. Pentapods creatures have the ability to destroy buildings under their feet while walking. But in the case of the "land-mine" this effect does not work.
Sorry, I haven't forgotten about this. My guess is this is due to the land-mine prototype having weird behaviour. I've been a bit busy lately, but I will give it a test soon and see if there's anything I can do about it.

Re: How to remove the collision field from the turret and make it invisible to enemies until the attack?

Posted: Wed Jan 08, 2025 6:58 pm
by Keysivi
IsaacOscar wrote: Wed Jan 08, 2025 1:23 am Sorry, I haven't forgotten about this. My guess is this is due to the land-mine prototype having weird behaviour. I've been a bit busy lately, but I will give it a test soon and see if there's anything I can do about it.
I see. It's just a hobby. So everything is fine. Thank you!