Page 1 of 2
How to stop turrets from firing without electricity?
Posted: Fri Dec 13, 2024 3:53 pm
by Keysivi
I added electricity consumption to turrets using the Electric Powered Belts mod
https://mods.factorio.com/mod/ElectricPoweredBelts
But turrets still fire without electricity.
Can anyone tell me what to do for this?
Here is the code from data-fixed.lua:
Code: Select all
for _, v in pairs(data.raw["ammo-turret"]) do
if not string.match(v.name, "unpowered-") then
-- local e = 160*v.speed*um*10
local x = table.deepcopy(v)
x.name = "unpowered-"..x.name
x.speed = 1e-308
x.localised_name = {"entity-name." .. v.name}
x.localised_description = {"entity-description." .. v.name}
data:extend({x,
{
type = "electric-energy-interface",
name = v.name.."-power",
icon = v.icon,
icon_size = v.icon_size, icon_mipmaps = v.icon_mipmaps,
flags = {"player-creation", "not-deconstructable","not-blueprintable"},
max_health = 1,
resistances = resistances_immune,
collision_box = v.collision_box,
selection_box = v.selection_box,
drawing_box = v.drawing_box,
selectable_in_game = false,
energy_source =
{
type = "electric",
buffer_capacity = "800kJ",
input_flow_limit = "100kW",
usage_priority = "primary-input",
drain = "10kW",
energy_per_shot = "8kJ"
},
energy_production = "0W",
energy_usage = "60kW",
}
})
end
end
Here is the code from control.lua:
Code: Select all
---- INIT ----
script.on_init(function()
storage.entities = {}
storage.power_entities = {}
end)
---- ON EVENT ----
script.on_event({defines.events.on_robot_built_entity, defines.events.on_built_entity}, function(event)
if event.entity.type == "transport-belt" or event.entity.type == "underground-belt" or event.entity.type == "splitter" or event.entity.type == "loader-1x1" or event.entity.type == "loader" or event.entity.type == "ammo-turret" or event.entity.type == "fluid-turret" or event.entity.type == "artillery-turret" then
local pos = event.entity.position.x .. " " .. event.entity.position.y
--game.print(event.entity.name)
--game.print(string.gsub(event.entity.name, "unpowered-", ""))
storage.power_entities[pos] = event.entity.surface.create_entity{
name = event.entity.name.."-power",
position = event.entity.position,
force = event.entity.force,
direction = event.entity.direction,
destructible = false
}
storage.entities[pos] = event.entity
end
end)
script.on_event({defines.events.on_entity_died, defines.events.on_robot_pre_mined, defines.events.on_pre_player_mined_item}, function(event)
local pos = event.entity.position.x .. " " .. event.entity.position.y
if storage.entities[pos] ~= nil then
storage.power_entities[pos].destroy()
storage.entities[pos] = nil
storage.power_entities[pos] = nil
end
end)
Thanks!
Re: How to stop turrets from firing without electricity?
Posted: Fri Dec 13, 2024 4:12 pm
by Natha
Ammo turrets can be given an energy source:
https://lua-api.factorio.com/latest/pro ... rgy_source
The code you quoted does exactly nothing except for creating and destroying electric interfaces
Re: How to stop turrets from firing without electricity?
Posted: Sat Dec 14, 2024 12:23 am
by Keysivi
Firstly, this code works. There is a specific mod
https://mods.factorio.com/mod/ElectricPoweredBelts that makes conveyor belts work from electricity.
Another issue is that I most likely overridden the scripts incorrectly...
And what is shown in the specified link - also does not work at all... Here is the mod
https://mods.factorio.com/mod/Turrets-n ... rgy-source there are such scripts:
Code: Select all
data.raw["ammo-turret"]["gun-turret"].energy_source = {
type = "electric",
buffer_capacity = "800kJ",
input_flow_limit = "100kW",
usage_priority = "primary-input",
drain = "10kW"
}
data.raw["ammo-turret"]["gun-turret"].energy_per_shot = "8kJ"
Only the effect is absolutely the same: there is a no electricity icon - but they still shoot!
Re: How to stop turrets from firing without electricity?
Posted: Sun Dec 22, 2024 8:33 am
by IsaacOscar
Hmm, I may be able to work out how to get a turrets damage to vary based on available electricity, so it can have zero damage when there is no electricity (but it would still fire). I think it might have a bit of a delay (so you might get a shot that does no damage or full damage, despite having some/zero extricity, but the next shot will be correct)
I may also be able to get it to permanently be disabled if it runs out of electricity and require you to rebuild the turret.
Re: How to stop turrets from firing without electricity?
Posted: Sun Dec 22, 2024 8:36 am
by IsaacOscar
I suggest however making a modding interface request to move the 'energy_source' field from AmmoTurretProtoype to TurretPrototype and add it to ArtilleryTurretPrototype (which doesn't inherit from TurretPrototype for some reason)
Re: How to stop turrets from firing without electricity?
Posted: Mon Dec 23, 2024 8:44 am
by Keysivi
IsaacOscar wrote: Sun Dec 22, 2024 8:33 am
Hmm, I may be able to work out how to get a turrets
damage to vary based on available electricity, so it can have zero damage when there is no electricity (but it would still fire). I think it might have a bit of a delay (so you might get a shot that does no damage or full damage, despite having some/zero extricity, but the next shot will be correct)
I may also be able to get it to permanently be disabled if it runs out of electricity and require you to rebuild the turret.
IsaacOscar wrote: Sun Dec 22, 2024 8:36 am
I suggest however making a modding interface request to move the 'energy_source' field from AmmoTurretProtoype to TurretPrototype and add it to ArtilleryTurretPrototype (which doesn't inherit from TurretPrototype for some reason)
I thought it would be better to disable the attack trigger. For example, make a condition that in the absence of electricity, the turret stops "seeing" or "reacting" to enemies.
The only thing that came to mind now is that there is a remote control for Artillery turrets where you can manually force Artillery turrets to shoot at an area.
That is, you also need to somehow block the remote control signals to de-energized Artillery turrets. This is not counting the problem with railway Artillery turrets....
So, I think you are right - only hope for the game developers. I created two requests:
viewtopic.php?f=28&t=124988 and
viewtopic.php?f=28&t=124987
If there are those who want to, they can support.
Re: How to stop turrets from firing without electricity?
Posted: Mon Dec 23, 2024 8:54 am
by IsaacOscar
Keysivi wrote: Mon Dec 23, 2024 8:44 am
I thought it would be better to disable the attack trigger. For example, make a condition that in the absence of electricity, the turret stops "seeing" or "reacting" to enemies.
The only thing that came to mind now is that there is a remote control for Artillery turrets where you can manually force Artillery turrets to shoot at an area.
That is, you also need to somehow block the remote control signals to de-energized Artillery turrets. This is not counting the problem with railway Artillery turrets....
So, I think you are right - only hope for the game developers. I created two requests:
viewtopic.php?f=28&t=124988 and
viewtopic.php?f=28&t=124987
If there are those who want to, they can support.
Disabling the turret when it runs out of electricity is the easy bit. I couldn't work out how to re-enable it when electricity comes back. (Except by allowing it to keep firing with 0 damage, and then checking each time it fires if electricity has arrived).
Re: How to stop turrets from firing without electricity?
Posted: Mon Dec 23, 2024 9:10 am
by Keysivi
IsaacOscar wrote: Mon Dec 23, 2024 8:54 am
Disabling the turret when it runs out of electricity is the easy bit. I couldn't work out how to re-enable it when electricity comes back. (Except by allowing it to keep firing with 0 damage, and then checking each time it fires if electricity has arrived).
I see. I suspect that even if we manage to solve this problem, it will greatly affect performance...
The same mod
https://mods.factorio.com/mod/ElectricPoweredBelts , as I was told, is made in an extremely "crutch" way.
Therefore, if even you find it difficult to understand this issue, we can only hope for the game developers.
Thank you for your participation! It is always valuable to me!!!
Re: How to stop turrets from firing without electricity?
Posted: Tue Dec 24, 2024 3:18 pm
by IsaacOscar
I've come up with an idea for artillery and fluid turrets! It may cause you're game to lag, and/or cause you're turrets to be slow at noticing they have electricity
Firstly, your `local pos` thing isn't very good as it will have problems if you have turrets on multiple planets. The simplest fix is to just use 'event.entity' instead of 'pos', specifically:
- Instead of storage.entities[pos] ~= nil, just use storage.power_entities[event.entity]
- Instead of storage.power_entities[pos], use storage.power_entities[event.entity]
- Now delete the lines declaring "local pos" and the ones that use storage.entities (as it is no longer necessary)
Now in data.lua I'll add a new effect whenever an artillery shell is used, or a flamethrower turret attacks:
Code: Select all
for _, ammo in pairs{data.raw["ammo"]["artillery-shell"], data.raw["fluid-turret"]["flamethrower-turret"].attack_parameters} do
local action_delivery = ammo.ammo_type.action.action_delivery
action_delivery.source_effects = {
action_delivery.source_effects, -- current effect
{type = "script", effect_id = "turret-consume-energy"}}
Now the slow bit, in control.lua:
Code: Select all
local refresh_rate = 20 -- how often to check whether an out-of-power turret should be re-enabled
local energy_per_shot = util.parse_energy("8kJ") -- set to whatever you want
script.on_event(defines.events.on_script_trigger_effect, function (event)
if event.effect_id ~= "turret-consume-energy" then return end
local turret = event.cause_entity -- or should it be event.source_entity?
local interface= storage.power_entities[turret]
if interface.energy >= energy_per_shot then
interface.energy = interface.energy - energy_per_shot
else
turret.disabled_by_script = true end end)
script.on_nth_tick(refresh_rate, function(event)
for turret, interface in pairs(storage.power_entities) do
if turret.disabled_by_script and interface.energy >= energy_per_shot then
interface.energy = interface.energy - energy_per_shot
turret.disabled_by_script = false end end end)
And just before the line that calls 'event.entity.surface.create_entity', you probably want to set event.entity.disabled_by_script = true
How this will work is as follows:
- Once a turret is placed, it will be disabled
- Every refresh_rate ticks, the code will check if enough energy for a single shot has been buffered by the energy interface
- Once enough energy has been buffered, it is consumed, and the turret is enabled
- Once the turret shoots, it checks if there's another energy for another shot
- If there isn't enough energy, the turret is disabled, and we go back to step #2
- Otherwise, energy for the next shot is consumed, and we go back to step #4
Note that the energy-interface needs to have a buffer size of at least buffer_capacity, or the turret will never get enough power.
The downsides to this approach are:
- It may cause a UPS drop if refresh_rate is a small number (I don't know though, as I haven't tested it).
- The total amount of energy buffered by the turret + interface, will be at least two shots worth of energy.
If you want different turrets to have different refresh_rates and energy_per_shots, you can easily turn those into a table keyed by the turret entities prototype.
Re: How to stop turrets from firing without electricity?
Posted: Wed Dec 25, 2024 1:17 pm
by Keysivi
Thank you very much for the idea and the offer! I will try to collect everything you have reported into a single whole. I will definitely provide a report based on the results.
Re: How to stop turrets from firing without electricity?
Posted: Wed Dec 25, 2024 2:52 pm
by Keysivi
I tried to implement your idea.
I tried to follow all your instructions. The only thing is, just in case, I saved part of the old table in a commented form (suddenly I misunderstood something)
Unfortunately, launching the game showed an error:
Code: Select all
Failed to load the following mods:Error while loading entity prototype "flamethrower-turret" (fluid-turret): Key "type" not found in property tree at ROOT.fluid-turret.flamethrower-turret.attack_parameters.ammo_type.action.action_delivery.source_effects
It says that 'source_effects' does not contain the 'type' parameter.
I have attached the files with the changes below
Re: How to stop turrets from firing without electricity?
Posted: Wed Dec 25, 2024 3:11 pm
by IsaacOscar
Keysivi wrote: Wed Dec 25, 2024 2:52 pm
I tried to implement your idea.
I tried to follow all your instructions. The only thing is, just in case, I saved part of the old table in a commented form (suddenly I misunderstood something)
Unfortunately, launching the game showed an error:
Code: Select all
Failed to load the following mods:Error while loading entity prototype "flamethrower-turret" (fluid-turret): Key "type" not found in property tree at ROOT.fluid-turret.flamethrower-turret.attack_parameters.ammo_type.action.action_delivery.source_effects
It says that 'source_effects' does not contain the 'type' parameter.
I have attached the files with the changes below
So sorry, I wrote that code originally for the artillery shell, and then added the flamethrowers after, but the structure of a flamethrwoer turrets action_delivery is slightly different.
Sorry, the effect system is a total mess and the documentation isn't very good, in particular it doesn't actually say what stuff does! In particular, I don't know how the 'stream' effect of the flamethrower turret will behaviour compared to the 'projectile' of the artillery shell.
Re: How to stop turrets from firing without electricity?
Posted: Wed Dec 25, 2024 3:28 pm
by IsaacOscar
[I removed the code from the above post as it was wrong, see below for a fixed version]
Re: How to stop turrets from firing without electricity?
Posted: Wed Dec 25, 2024 3:43 pm
by IsaacOscar
Ok here you go, I wrote two general 'get_trigger' and 'insert_trigger' functions that can be used when you don't know how many triggers are already present.
They are complicated as the various fields (e.g. ammo_type.action at
https://lua-api.factorio.com/latest/typ ... tml#action) can be nil, a single Trigger/TriggerDelivery/TriggerEffect, an empty array, or an array of Triggers.
Code: Select all
-- tbl[field] should be nil, a single Trigger, or an array of Trigger's
-- (Also works for TriggerDelivery's, and TriggerEffect's)
-- get_trigger will either return on of the triggers, or return default_trigger, after storing it in tbl[field]
function get_trigger(tbl, field, default_trigger)
if not tbl[field] then -- no Triggers
tbl[field] = default_trigger
return tbl[field]
elseif tbl[field].type then -- not an array
return tbl[field].type
elseif #tbl[field] > 0 then -- non-empty array of Triggers
return tbl[field[#tbl[field]]] -- use the last Trigger
else -- should be an empty array
table.insert(tbl[field], default_trigger)
return tbl[field][1] end end
-- Similar, but inserts a new trigger
function insert_trigger(tbl, field, new_trigger)
if not tbl[field] then
tbl[field] = new_trigger
elseif tbl[field].type then -- not an array, turn it into one
tbl[field] = {tbl[field].type, new_trigger}
else -- should be an array
tble.insert(tbl[field], new_trigger)
return new_trigger end
for _, ammo in pairs{data.raw["ammo"]["artillery-shell"], data.raw["fluid-turret"]["flamethrower-turret"].attack_parameters} do
local action = get_trigger(ammo.ammo_type, "action", {type = "direct"})
local action_delivery = get_trigger(action, "action_delivery", {type = "instant"})
insert_triger(action_delivery, "source_effects", {type = "script", effect_id = "turret-consume-energy"}) end
The code still assume that ammo_type is a single AmmoType, and not an array.
I still don't know exactly how the various types of Trigger & TriggerDelivery behave, so the above code may be completely stupid, and a better approach might be:
Code: Select all
for _, ammo in pairs{data.raw["ammo"]["artillery-shell"], data.raw["fluid-turret"]["flamethrower-turret"].attack_parameters} do
local direct = insert_trigger(ammo.ammo_type, "action", {type = "direct"})
local action_delivery = insert_trigger(action, "action_delivery", {type = "instant"})
insert_triger(action_delivery, "source_effects", {type = "script", effect_id = "turret-consume-energy"}) end
This ensures that the script TriggerEffect is inside an 'instant' TriggerDeliver within a direct Trigger.
In particular, for the flamethrower, it uses a 'stream' action_delivery, instead of 'instant', and I have no idea what difference this will make.
Re: How to stop turrets from firing without electricity?
Posted: Wed Dec 25, 2024 6:02 pm
by Keysivi
Unfortunately both options showed an error.
First option:
Code: Select all
function get_trigger(tbl, field, default_trigger)
if not tbl[field] then -- no Triggers
tbl[field] = default_trigger
return tbl[field]
elseif tbl[field].type then -- not an array
return tbl[field].type
elseif #tbl[field] > 0 then -- non-empty array of Triggers
return tbl[field[#tbl[field]]] -- use the last Trigger
else -- should be an empty array
table.insert(tbl[field], default_trigger)
return tbl[field][1]
end
end
for _, ammo in pairs{data.raw["ammo"]["artillery-shell"], data.raw["fluid-turret"]["flamethrower-turret"].attack_parameters} do
local action = get_trigger(ammo.ammo_type, "action", {type = "direct"})
local action_delivery = get_trigger(action, "action_delivery", {type = "instant"})
insert_triger(action_delivery, "source_effects", {type = "script", effect_id = "turret-consume-energy"})
end
Error:
Code: Select all
The following mods could not be loaded: __ElectricPoweredBelts__/data-final-fixes.lua:17: attempt to index local 'tbl' (a string value)
stack traceback:
__ElectricPoweredBelts__/data-final-fixes.lua:17: in function 'get_trigger'
__ElectricPoweredBelts__/data-final-fixes.lua:31: in main chunk
Second option:
Code: Select all
function insert_trigger(tbl, field, new_trigger)
if not tbl[field] then
tbl[field] = new_trigger
elseif tbl[field].type then -- not an array, turn it into one
tbl[field] = {tbl[field].type, new_trigger}
else -- should be an array
tble.insert(tbl[field], new_trigger)
return new_trigger
end
end
for _, ammo in pairs{data.raw["ammo"]["artillery-shell"], data.raw["fluid-turret"]["flamethrower-turret"].attack_parameters} do
local direct = insert_trigger(ammo.ammo_type, "action", {type = "direct"})
local action_delivery = insert_trigger(action, "action_delivery", {type = "instant"})
insert_triger(action_delivery, "source_effects", {type = "script", effect_id = "turret-consume-energy"})
end
Error:
Code: Select all
The following mods could not be loaded: __ElectricPoweredBelts__/data-final-fixes.lua:30: attempt to index local 'tbl' (a nil value)
stack traceback:
__ElectricPoweredBelts__/data-final-fixes.lua:30: in function 'insert_trigger'
__ElectricPoweredBelts__/data-final-fixes.lua:50: in main chunk
Re: How to stop turrets from firing without electricity?
Posted: Thu Dec 26, 2024 4:59 am
by IsaacOscar
Well I'm dumb, the line
should have been
And the line
Should be
Oh and the line
Code: Select all
tbl[field] = {tbl[field].type, new_trigger}
should be
Code: Select all
tbl[field] = {tbl[field], new_trigger}
Whwre it says "tble.insert" it should say "tbl.insert"
And where it says "local direct", it should say "local action".
Sorry, I was being lazy was hoping you'd fix any typos, next time I should actually proofread before sending stuff!
Re: How to stop turrets from firing without electricity?
Posted: Thu Dec 26, 2024 6:36 am
by Keysivi
Good day! Unfortunately, this is the cost of working with amateurs...
I apologize for my short-sightedness. I am correcting some of your errors that I was able to identify, but for the most part, they are incomprehensible to me - alas
I cannot make you happy. I made the edits you indicated, but errors still appeared.
In the case of the 'get_trigger' function, the following error appeared:
Code: Select all
Failed to load the following mods: __ElectricPoweredBelts__/data-final-fixes.lua:33: attempt to call global 'insert_triger' (a nil value)
stack traceback:
__ElectricPoweredBelts__/data-final-fixes.lua:33: in main chunk
In the case of the 'insert_trigger' function, the following error appeared:
Code: Select all
Не удалось загрузить следующие моды: __ElectricPoweredBelts__/data-final-fixes.lua:40: attempt to index local 'tbl' (a nil value)
stack traceback:
__ElectricPoweredBelts__/data-final-fixes.lua:40: in function 'insert_trigger'
__ElectricPoweredBelts__/data-final-fixes.lua:52: in main chunk
Re: How to stop turrets from firing without electricity?
Posted: Thu Dec 26, 2024 6:42 am
by IsaacOscar
Keysivi wrote: Thu Dec 26, 2024 6:36 am
Code: Select all
Failed to load the following mods: __ElectricPoweredBelts__/data-final-fixes.lua:33: attempt to call global 'insert_triger' (a nil value)
stack traceback:
__ElectricPoweredBelts__/data-final-fixes.lua:33: in main chunk
Well this is because I spelt it wrong (it should have two g's)
Re: How to stop turrets from firing without electricity?
Posted: Thu Dec 26, 2024 6:43 am
by IsaacOscar
Keysivi wrote: Thu Dec 26, 2024 6:36 am
Code: Select all
Не удалось загрузить следующие моды: __ElectricPoweredBelts__/data-final-fixes.lua:40: attempt to index local 'tbl' (a nil value)
stack traceback:
__ElectricPoweredBelts__/data-final-fixes.lua:40: in function 'insert_trigger'
__ElectricPoweredBelts__/data-final-fixes.lua:52: in main chunk
I'm dumb again, where it says
it should say
Re: How to stop turrets from firing without electricity?
Posted: Thu Dec 26, 2024 8:04 am
by Keysivi
New batch of errors
In the case of the function 'insert_trigger' in data-final-fixes.lua, there are no more errors, but there was one in control.lua:
Code: Select all
__ElectricPoweredBelts__/control.lua:28: attempt to index global 'util' (a nil value)
stack traceback:
__ElectricPoweredBelts__/control.lua:28: in main chunk
In the case of the function 'get_trigger', the error seems to be the same, but now it points to 'insert_trigger'. As far as I understand, the problem is not only in the missing letter 'g'.
Code: Select all
Failed to load the following mods: __ElectricPoweredBelts__/data-final-fixes.lua:33: attempt to call global 'insert_trigger' (a nil value)
stack traceback:
__ElectricPoweredBelts__/data-final-fixes.lua:33: in main chunk
I also took the liberty of replacing:
with:
It didn't change anything though...