Factorio: avoid ores when spawning silo

and minor code clean-up
This commit is contained in:
black-sliver 2021-08-07 13:15:41 +02:00 committed by Fabian Dill
parent 0423c22d7f
commit eb8e8691e9
1 changed files with 29 additions and 21 deletions

View File

@ -24,7 +24,7 @@ function check_spawn_silo(force)
if force.players and #force.players > 0 and force.get_entity_count("rocket-silo") < 1 then if force.players and #force.players > 0 and force.get_entity_count("rocket-silo") < 1 then
local surface = game.get_surface(1) local surface = game.get_surface(1)
local spawn_position = force.get_spawn_position(surface) local spawn_position = force.get_spawn_position(surface)
spawn_entity(surface, force, "rocket-silo", spawn_position.x, spawn_position.y, 80, true) spawn_entity(surface, force, "rocket-silo", spawn_position.x, spawn_position.y, 80, true, true)
end end
end end
@ -245,7 +245,7 @@ function chain_lookup(table, ...)
end end
function spawn_entity(surface, force, name, x, y, radius, randomize) function spawn_entity(surface, force, name, x, y, radius, randomize, avoid_ores)
local prototype = game.entity_prototypes[name] local prototype = game.entity_prototypes[name]
local args = { -- For can_place_entity and place_entity local args = { -- For can_place_entity and place_entity
name = prototype.name, name = prototype.name,
@ -262,13 +262,13 @@ function spawn_entity(surface, force, name, x, y, radius, randomize)
} }
local entity_radius = math.ceil(math.max(dims.w, dims.h) / math.sqrt(2) / 2) local entity_radius = math.ceil(math.max(dims.w, dims.h) / math.sqrt(2) / 2)
local bounds = { local bounds = {
xmin = math.ceil(x - (radius - dims.w/2)), xmin = math.ceil(x - radius - box.left_top.x),
xmax = math.floor(x + (radius - dims.w/2)), xmax = math.floor(x + radius - box.right_bottom.x),
ymin = math.ceil(y - (radius - dims.h/2)), ymin = math.ceil(y - radius - box.left_top.y),
ymax = math.floor(y + (radius - dims.h/2)) ymax = math.floor(y + radius - box.right_bottom.y)
} }
local entity = nil local new_entity = nil
local attempts = 1000 local attempts = 1000
for i = 1,attempts do -- Try multiple times for i = 1,attempts do -- Try multiple times
-- Find a position -- Find a position
@ -288,7 +288,6 @@ function spawn_entity(surface, force, name, x, y, radius, randomize)
not surface.is_chunk_generated({x = x2, y = y1}) or not surface.is_chunk_generated({x = x2, y = y1}) or
not surface.is_chunk_generated({x = x1, y = y2}) or not surface.is_chunk_generated({x = x1, y = y2}) or
not surface.is_chunk_generated({x = x2, y = y2}) then not surface.is_chunk_generated({x = x2, y = y2}) then
--player.print("Generating chunk at " .. serpent.line(args.position) .. ", radius=" .. entity_radius)
surface.request_to_generate_chunks(args.position, entity_radius) surface.request_to_generate_chunks(args.position, entity_radius)
surface.force_generate_chunk_requests() surface.force_generate_chunk_requests()
end end
@ -298,40 +297,49 @@ function spawn_entity(surface, force, name, x, y, radius, randomize)
local collision_area = { local collision_area = {
{ {
args.position.x + prototype.collision_box.left_top.x, args.position.x + prototype.collision_box.left_top.x,
args.position.y + prototype.collision_box.left_top.x args.position.y + prototype.collision_box.left_top.y
}, },
{ {
args.position.x + prototype.collision_box.right_bottom.x, args.position.x + prototype.collision_box.right_bottom.x,
args.position.y + prototype.collision_box.right_bottom.x args.position.y + prototype.collision_box.right_bottom.y
} }
} }
local entities = surface.find_entities_filtered { local entities = surface.find_entities_filtered {
area = collision_area, area = collision_area,
collision_mask = prototype.collision_mask collision_mask = prototype.collision_mask
} }
local has_invalid_entities = false local can_place = true
for _, entity in pairs(entities) do for _, entity in pairs(entities) do
if entity.force and (entity.force.name ~= 'neutral') then if entity.force and entity.force.name ~= 'neutral' then
has_invalid_entities = true can_place = false
break
end end
end end
if not has_invalid_entities then local allow_placement_on_resources = not avoid_ores or i > attempts/2
if can_place and not allow_placement_on_resources then
local resources = surface.find_entities_filtered {
area = collision_area,
type = 'resource'
}
can_place = (next(resources) == nil)
end
if can_place then
for _, entity in pairs(entities) do for _, entity in pairs(entities) do
entity.destroy({do_cliff_correction=true, raise_destroy=true}) entity.destroy({do_cliff_correction=true, raise_destroy=true})
end end
args.build_check_type = defines.build_check_type.script args.build_check_type = defines.build_check_type.script
args.create_build_effect_smoke = false args.create_build_effect_smoke = false
entity = surface.create_entity(args) new_entity = surface.create_entity(args)
if entity then if new_entity then
entity.destructible = false new_entity.destructible = false
entity.minable = false new_entity.minable = false
entity.rotatable = false new_entity.rotatable = false
break break
end end
end end
end end
end end
if entity == nil then if new_entity == nil then
force.print("Failed to place " .. args.name .. " in " .. serpent.line({x = x, y = y, radius = radius})) force.print("Failed to place " .. args.name .. " in " .. serpent.line({x = x, y = y, radius = radius}))
end end
end end
@ -434,7 +442,7 @@ end)
{% if allow_cheats -%} {% if allow_cheats -%}
commands.add_command("ap-spawn-silo", "Attempts to spawn a silo around 0,0", function(call) commands.add_command("ap-spawn-silo", "Attempts to spawn a silo around 0,0", function(call)
spawn_entity(game.player.surface, game.player.force, "rocket-silo", 0, 0, 80, true) spawn_entity(game.player.surface, game.player.force, "rocket-silo", 0, 0, 80, true, true)
end) end)
{% endif -%} {% endif -%}