1
0
mirror of https://github.com/ComfyFactory/ComfyFactorio.git synced 2025-02-03 13:12:11 +02:00

major internal terrain generator rework

This commit is contained in:
MewMew 2020-04-16 11:42:00 +02:00
parent 4e3a07d806
commit 50337435d2
4 changed files with 410 additions and 389 deletions

View File

@ -18,7 +18,9 @@ function Public.settings()
end
function Public.surface()
--Terrain Source Surface
local map_gen_settings = {}
map_gen_settings.seed = math.random(1, 99999999)
map_gen_settings.water = math.random(15, 65) * 0.01
map_gen_settings.starting_area = 2.5
map_gen_settings.terrain_segmentation = math.random(30, 40) * 0.1
@ -33,13 +35,49 @@ function Public.surface()
["trees"] = {frequency = math.random(8, 24) * 0.1, size = math.random(8, 24) * 0.1, richness = math.random(1, 10) * 0.1},
["enemy-base"] = {frequency = 0, size = 0, richness = 0}
}
game.create_surface("biter_battles", map_gen_settings)
game.create_surface("bb_source", map_gen_settings)
game.map_settings.enemy_evolution.time_factor = 0
game.map_settings.enemy_evolution.destroy_factor = 0
game.map_settings.enemy_evolution.pollution_factor = 0
game.map_settings.pollution.enabled = false
game.map_settings.enemy_expansion.enabled = false
--Playground Surface
local map_gen_settings = {
["water"] = 0,
["starting_area"] = 1,
["cliff_settings"] = {cliff_elevation_interval = 0, cliff_elevation_0 = 0},
["default_enable_all_autoplace_controls"] = false,
["autoplace_settings"] = {
["entity"] = {treat_missing_as_default = false},
["tile"] = {treat_missing_as_default = false},
["decorative"] = {treat_missing_as_default = false},
},
autoplace_controls = {
["coal"] = {frequency = 0, size = 0, richness = 0},
["stone"] = {frequency = 0, size = 0, richness = 0},
["copper-ore"] = {frequency = 0, size = 0, richness = 0},
["iron-ore"] = {frequency = 0, size = 0, richness = 0},
["uranium-ore"] = {frequency = 0, size = 0, richness = 0},
["crude-oil"] = {frequency = 0, size = 0, richness = 0},
["trees"] = {frequency = 0, size = 0, richness = 0},
["enemy-base"] = {frequency = 0, size = 0, richness = 0}
},
}
local surface = game.create_surface("biter_battles", map_gen_settings)
surface.request_to_generate_chunks({0,0}, 2)
surface.force_generate_chunk_requests()
--Disable Nauvis
local surface = game.surfaces[1]
local map_gen_settings = surface.map_gen_settings
map_gen_settings.height = 3
map_gen_settings.width = 3
surface.map_gen_settings = map_gen_settings
for chunk in surface.get_chunks() do
surface.delete_chunk({chunk.x, chunk.y})
end
end
function Public.forces()
@ -152,7 +190,14 @@ function Public.forces()
global.bb_evolution = {}
global.bb_threat_income = {}
global.bb_threat = {}
global.chunks_mirrored = {}
global.terrain_gen = {}
global.terrain_gen.counter = 0
global.terrain_gen.chunk_mirror = {}
global.terrain_gen.size_of_chunk_mirror = 0
global.terrain_gen.chunk_copy = {}
global.terrain_gen.size_of_chunk_copy = 0
global.map_pregen_message_counter = {}
for _, force in pairs(game.forces) do

View File

@ -152,7 +152,7 @@ end
local function on_chunk_generated(event)
Terrain.generate(event)
Mirror_terrain.add_chunks(event)
Mirror_terrain.add_chunk(event)
end
local function on_init()
@ -162,9 +162,24 @@ local function on_init()
Team_manager.init()
local surface = game.surfaces["biter_battles"]
surface.request_to_generate_chunks({x = 0, y = 0}, 1)
surface.force_generate_chunk_requests()
for y = -576, 576, 32 do
surface.request_to_generate_chunks({x = 16, y = y + 16}, 0)
surface.request_to_generate_chunks({x = -16, y = y - 16}, 0)
end
local surface = game.surfaces["bb_source"]
surface.request_to_generate_chunks({x = 0, y = 0}, 2)
surface.force_generate_chunk_requests()
surface.request_to_generate_chunks({x = 0, y = -256}, 8)
surface.force_generate_chunk_requests()
Terrain.generate_north_silo(surface)
Terrain.draw_spawn_area(surface)
Terrain.generate_silo(surface)
Terrain.generate_additional_spawn_ore(surface)
Terrain.draw_spawn_circle(surface)
end
local Event = require 'utils.event'

View File

@ -1,6 +1,8 @@
-- Mirrored Terrain for Biter Battles -- by MewMew and Serennie
local Public = {}
local table_remove = table.remove
local table_insert = table.insert
local direction_translation = {
[0] = 4,
[1] = 5,
@ -36,262 +38,229 @@ local cliff_orientation_translation = {
}
local entity_copy_functions = {
["tree"] = function(surface, entity, mirror_position)
if not surface.can_place_entity({name = entity.name, position = mirror_position}) then return end
entity.clone({position = mirror_position, surface = surface, force = "neutral"})
["tree"] = function(surface, entity, target_position, force_name)
if not surface.can_place_entity({name = entity.name, position = target_position}) then return end
entity.clone({position = target_position, surface = surface, force = "neutral"})
end,
["simple-entity"] = function(surface, entity, mirror_position)
local mirror_entity = {name = entity.name, position = mirror_position, direction = direction_translation[entity.direction]}
["simple-entity"] = function(surface, entity, target_position, force_name)
local mirror_entity = {name = entity.name, position = target_position, direction = direction_translation[entity.direction]}
if not surface.can_place_entity(mirror_entity) then return end
local mirror_entity = surface.create_entity(mirror_entity)
mirror_entity.graphics_variation = entity.graphics_variation
end,
["cliff"] = function(surface, entity, mirror_position)
local mirror_entity = {name = entity.name, position = mirror_position, cliff_orientation = cliff_orientation_translation[entity.cliff_orientation]}
["cliff"] = function(surface, entity, target_position, force_name)
local mirror_entity = {name = entity.name, position = target_position, cliff_orientation = cliff_orientation_translation[entity.cliff_orientation]}
if not surface.can_place_entity(mirror_entity) then return end
surface.create_entity(mirror_entity)
return
end,
["resource"] = function(surface, entity, mirror_position)
surface.create_entity({name = entity.name, position = mirror_position, amount = entity.amount})
["resource"] = function(surface, entity, target_position, force_name)
surface.create_entity({name = entity.name, position = target_position, amount = entity.amount})
end,
["corpse"] = function(surface, entity, mirror_position)
if game.tick > 900 then return end
surface.create_entity({name = entity.name, position = mirror_position})
["corpse"] = function(surface, entity, target_position, force_name)
surface.create_entity({name = entity.name, position = target_position})
end,
["unit-spawner"] = function(surface, entity, mirror_position)
local mirror_entity = {name = entity.name, position = mirror_position, direction = direction_translation[entity.direction], force = "south_biters"}
["unit-spawner"] = function(surface, entity, target_position, force_name)
local mirror_entity = {name = entity.name, position = target_position, direction = direction_translation[entity.direction], force = force_name .. "_biters"}
if not surface.can_place_entity(mirror_entity) then return end
table.insert(global.unit_spawners.south_biters, surface.create_entity(mirror_entity))
table_insert(global.unit_spawners[force_name .. "_biters"], surface.create_entity(mirror_entity))
end,
["turret"] = function(surface, entity, mirror_position)
local mirror_entity = {name = entity.name, position = mirror_position, direction = direction_translation[entity.direction], force = "south_biters"}
["turret"] = function(surface, entity, target_position, force_name)
local mirror_entity = {name = entity.name, position = target_position, direction = direction_translation[entity.direction], force = force_name .. "_biters"}
if not surface.can_place_entity(mirror_entity) then return end
surface.create_entity(mirror_entity)
end,
["rocket-silo"] = function(surface, entity, mirror_position)
if game.tick > 900 then return end
if surface.count_entities_filtered({name = "rocket-silo", area = {{mirror_position.x - 8, mirror_position.y - 8},{mirror_position.x + 8, mirror_position.y + 8}}}) > 0 then return end
global.rocket_silo["south"] = surface.create_entity({name = entity.name, position = mirror_position, direction = direction_translation[entity.direction], force = "south"})
global.rocket_silo["south"].minable = false
["rocket-silo"] = function(surface, entity, target_position, force_name)
if surface.count_entities_filtered({name = "rocket-silo", area = {{target_position.x - 8, target_position.y - 8},{target_position.x + 8, target_position.y + 8}}}) > 0 then return end
global.rocket_silo[force_name] = surface.create_entity({name = entity.name, position = target_position, direction = direction_translation[entity.direction], force = force_name})
global.rocket_silo[force_name].minable = false
end,
["ammo-turret"] = function(surface, entity, mirror_position)
if game.tick > 900 then return end
if not surface.can_place_entity({name = entity.name, position = mirror_position, force = "south"}) then return end
entity.clone({position = mirror_position, surface = surface, force="south"})
["ammo-turret"] = function(surface, entity, target_position, force_name)
if not surface.can_place_entity({name = entity.name, position = target_position, force = force_name}) then return end
entity.clone({position = target_position, surface = surface, force = force_name})
end,
["wall"] = function(surface, entity, mirror_position)
if game.tick > 900 then return end
entity.clone({position = mirror_position, surface = surface, force="south"})
["wall"] = function(surface, entity, target_position, force_name)
entity.clone({position = target_position, surface = surface, force = force_name})
end,
["container"] = function(surface, entity, mirror_position)
if game.tick > 900 then return end
entity.clone({position = mirror_position, surface = surface, force="south"})
["container"] = function(surface, entity, target_position, force_name)
entity.clone({position = target_position, surface = surface, force = force_name})
end,
["fish"] = function(surface, entity, mirror_position)
local mirror_entity = {name = entity.name, position = mirror_position, direction = direction_translation[entity.direction]}
["fish"] = function(surface, entity, target_position, force_name)
local mirror_entity = {name = entity.name, position = target_position, direction = direction_translation[entity.direction]}
if not surface.can_place_entity(mirror_entity) then return end
local e = surface.create_entity(mirror_entity)
end,
}
local function process_entity(surface, entity)
local function process_entity(surface, entity, force_name)
if not entity.valid then return end
if not entity_copy_functions[entity.type] then return end
local mirror_position = {x = entity.position.x * -1, y = entity.position.y * -1}
entity_copy_functions[entity.type](surface, entity, mirror_position)
local target_position
if force_name == "north" then
target_position = entity.position
else
target_position = {x = entity.position.x * -1, y = entity.position.y * -1}
end
entity_copy_functions[entity.type](surface, entity, target_position, force_name)
end
local function mirror_tiles(surface, source_area)
mirrored = {}
local i = 0
for x = source_area.left_top.x, source_area.left_top.x+31 do
for y = source_area.left_top.y, source_area.left_top.y+31 do
local tile = surface.get_tile(x, y)
mirrored[i] = {name = tile.name, position = {-x, -y - 1}}
i = i + 1
end
local function copy_chunk(chunk)
local target_surface = game.surfaces.biter_battles
local source_surface = game.surfaces.bb_source
local source_chunk_position = {chunk[1][1], chunk[1][2]}
local source_left_top = {x = source_chunk_position[1] * 32, y = source_chunk_position[2] * 32}
local source_area = {{source_left_top.x, source_left_top.y}, {source_left_top.x + 32, source_left_top.y + 32}}
local target_chunk_position = chunk[1]
local target_left_top = {x = target_chunk_position[1] * 32, y = target_chunk_position[2] * 32}
local target_area = {{target_left_top.x, target_left_top.y}, {target_left_top.x + 32, target_left_top.y + 32}}
if not source_surface.is_chunk_generated(source_chunk_position) then
source_surface.request_to_generate_chunks({x = source_left_top.x + 16, y = source_left_top.y + 16}, 0)
return
end
surface.set_tiles(mirrored, true)
end
local function clear_chunk(surface, area)
surface.destroy_decoratives{area=area}
if area.left_top.y > 32 or area.left_top.x > 32 or area.left_top.x < -32 then
for _, e in pairs(surface.find_entities_filtered({area = area})) do
if e.valid then
e.destroy()
end
end
else
for _, e in pairs(surface.find_entities_filtered({area = area})) do
if e.valid then
if e.name ~= "character" then
e.destroy()
end
end
if chunk[2] == 1 then
source_surface.clone_area({
source_area = source_area,
destination_area = target_area,
destination_surface = target_surface,
--destination_force = …,
clone_tiles = true,
clone_entities = false,
clone_decoratives = false,
clear_destination_entities = false,
clear_destination_decoratives = false,
expand_map = false
})
chunk[2] = chunk[2] + 1
return
end
if chunk[2] == 2 then
for _, entity in pairs(source_surface.find_entities_filtered({area = source_area})) do
process_entity(target_surface, entity, "north")
end
chunk[2] = chunk[2] + 1
return
end
end
local function mirror_chunk(surface, chunk)
--local x = chunk.x * -32 + 32
--local y = chunk.y * -32 + 32
--clear_chunk(surface, {left_top = {x = x, y = y}, right_bottom = {x = x + 32, y = y + 32}})
local chunk_area = {left_top = {x = chunk.x * 32, y = chunk.y * 32}, right_bottom = {x = chunk.x * 32 + 32, y = chunk.y * 32 + 32}}
if not surface.is_chunk_generated(chunk) then
surface.request_to_generate_chunks({x = chunk_area.left_top.x - 16, y = chunk_area.left_top.y - 16}, 1)
surface.force_generate_chunk_requests()
end
for _, tile in pairs(surface.find_tiles_filtered({area = chunk_area})) do
surface.set_tiles({{name = tile.name, position = {x = tile.position.x * -1, y = (tile.position.y * -1) - 1}}}, true)
end
for _, entity in pairs(surface.find_entities_filtered({area = chunk_area})) do
process_entity(surface, entity)
end
for _, decorative in pairs(surface.find_decoratives_filtered{area=chunk_area}) do
surface.create_decoratives{
check_collision=false,
decoratives={{name = decorative.decorative.name, position = {x = decorative.position.x * -1, y = (decorative.position.y * -1) - 1}, amount = decorative.amount}}
for _, decorative in pairs(source_surface.find_decoratives_filtered{area = source_area}) do
target_surface.create_decoratives{
check_collision = false,
decoratives = {{name = decorative.decorative.name, position = decorative.position, amount = decorative.amount}}
}
end
end
local function is_chunk_already_mirrored(chunk)
local index = chunk[1] .. "_" .. chunk[2]
if not global.chunks_mirrored[index] then global.chunks_mirrored[index] = true return false end
return true
end
local function add_work(work)
if not global.ctp then global.ctp = { continue = 1, last = 0 } end
local idx = global.ctp.last + 1
global.ctp[idx] = work
global.ctp.last = idx
local function mirror_chunk(chunk)
local target_surface = game.surfaces.biter_battles
local source_surface = game.surfaces.bb_source
local source_chunk_position = {chunk[1][1] * -1 - 1, chunk[1][2] * -1 - 1}
local source_left_top = {x = source_chunk_position[1] * 32, y = source_chunk_position[2] * 32}
local source_area = {{source_left_top.x, source_left_top.y}, {source_left_top.x + 32, source_left_top.y + 32}}
if not source_surface.is_chunk_generated(source_chunk_position) then
source_surface.request_to_generate_chunks({x = source_left_top.x + 16, y = source_left_top.y + 16}, 0)
return
end
if chunk[2] == 1 then
for _, tile in pairs(source_surface.find_tiles_filtered({area = source_area})) do
target_surface.set_tiles({{name = tile.name, position = {x = tile.position.x * -1, y = (tile.position.y * -1) - 1}}}, true)
end
chunk[2] = chunk[2] + 1
return
end
if chunk[2] == 2 then
for _, entity in pairs(source_surface.find_entities_filtered({area = source_area})) do
process_entity(target_surface, entity, "south")
end
chunk[2] = chunk[2] + 1
return
end
for _, decorative in pairs(source_surface.find_decoratives_filtered{area = source_area}) do
target_surface.create_decoratives{
check_collision = false,
decoratives = {{name = decorative.decorative.name, position = {x = decorative.position.x * -1, y = (decorative.position.y * -1) - 1}, amount = decorative.amount}}
}
end
return true
end
function Public.add_chunks(event)
local function reveal_chunk(chunk)
local surface = game.surfaces.biter_battles
local chunk_position = chunk[1]
for _, force_name in pairs({"north", "south"}) do
local force = game.forces[force_name]
if force.is_chunk_charted(surface, chunk_position) then
force.chart(surface, {{chunk_position[1] * 32, chunk_position[2] * 32}, {chunk_position[1] * 32 + 31, chunk_position[2] * 32 + 31}})
end
end
end
function Public.add_chunk(event)
local surface = event.surface
if surface.name ~= "biter_battles" then return end
local left_top = event.area.left_top
local terrain_gen = global.terrain_gen
if event.area.left_top.y < 0 then
if game.tick == 0 then return end
local x = event.area.left_top.x / 32
local y = event.area.left_top.y / 32
if is_chunk_already_mirrored({x, y}) then return end
add_work({x = x, y = y, state = 1})
return
if left_top.y < 0 then
terrain_gen.size_of_chunk_copy = terrain_gen.size_of_chunk_copy + 1
terrain_gen.chunk_copy[terrain_gen.size_of_chunk_copy] = {{left_top.x / 32, left_top.y / 32}, 1}
else
terrain_gen.size_of_chunk_mirror = terrain_gen.size_of_chunk_mirror + 1
terrain_gen.chunk_mirror[terrain_gen.size_of_chunk_mirror] = {{left_top.x / 32, left_top.y / 32}, 1}
end
surface.destroy_decoratives{ area = event.area }
-- Destroy biters here before they get active and attack other biters;
-- prevents threat decrease
for _, e in pairs(surface.find_entities_filtered{ area = event.area, force = "enemy" }) do
if e.valid then e.destroy() end
end
local x = (((event.area.left_top.x + 16) * -1) - 16) / 32
local y = (((event.area.left_top.y + 16) * -1) - 16) / 32
if is_chunk_already_mirrored({x, y}) then return end
add_work({x = x, y = y, state = 1})
end
function Public.ticking_work()
if not global.ctp then return end
local work = global.mws or 512 -- define the number of work per tick here (for copies, creations, deletions)
-- 136.5333 is the number of work needed to finish 4*(32*32) operations over 30 ticks (spreading a chunk copy over 30 ticks)
local w = 0
local i = global.ctp.continue
local c = global.ctp[i]
if not c then return end
local state = c.state
local d = c.data
local area = {
left_top = {x = c.x * 32, y = c.y * 32},
right_bottom = {x = c.x * 32 + 32, y = c.y * 32 + 32}
}
local inverted_area = {
left_top = { -area.right_bottom.x, -area.right_bottom.y },
right_bottom = { -area.left_top.x, -area.left_top.y }
}
local surface = game.surfaces["biter_battles"]
if not surface.is_chunk_generated(c) then
--game.print("Chunk not generated yet, requesting..")
surface.request_to_generate_chunks({x = area.left_top.x + 16, y = area.left_top.y + 16}, 0)
surface.force_generate_chunk_requests()
-- requeue
--add_work(c)
--global.ctp.continue = i+1
--global.ctp[i] = nil
--return
end
local tasks = {
[1] = {
name = "Clearing entities",
list = function () return surface.find_entities_filtered({area = inverted_area, name = "character", invert = true}) end,
action = function (e) e.destroy() end
},
[2] = {},
[3] = {
name = "Entity copy",
list = function () return surface.find_entities_filtered({area = area}) end,
action = function (entity) process_entity(surface, entity) end
},
[4] = {
name = "Decorative copy",
list = function () return surface.find_decoratives_filtered{area = area} end,
action = function (decorative)
surface.create_decoratives{
check_collision = false,
decoratives = {{
name = decorative.decorative.name,
position = {x = decorative.position.x * -1, y = (decorative.position.y * -1) - 1},
amount = decorative.amount
}}
}
local terrain_gen = global.terrain_gen
local tick = game.tick
if tick < 60 then return end
if game.tick % 2 == 1 then
for k, chunk in pairs(terrain_gen.chunk_copy) do
if copy_chunk(chunk) then
reveal_chunk(chunk)
table_remove(terrain_gen.chunk_copy, k)
terrain_gen.size_of_chunk_copy = terrain_gen.size_of_chunk_copy - 1
terrain_gen.counter = terrain_gen.counter + 1
end
}
}
if c.state == 2 then
mirror_tiles(surface, area)
c.state = c.state + 1
c.data = nil
else
local task = tasks[c.state]
-- game.print(task.name)
d = d or task.list()
local last_idx = nil
for k, v in pairs(d) do
task.action(v)
d[k] = nil
last_idx = k
w = w + 1
if w > work then break end
break
end
local next_idx, _ = next(d, last_idx)
if next_idx == nil then
c.state = c.state + 1
c.data = nil
else
c.data = d
else
for k, chunk in pairs(terrain_gen.chunk_mirror) do
if mirror_chunk(chunk) then
reveal_chunk(chunk)
table_remove(terrain_gen.chunk_mirror, k)
terrain_gen.size_of_chunk_mirror = terrain_gen.size_of_chunk_mirror - 1
terrain_gen.counter = terrain_gen.counter + 1
end
break
end
end
if c.state == 5 then
-- game.print("Finished processing chunk "..c.x..","..c.y)
global.ctp.continue = i+1
global.ctp[i] = nil
else
global.ctp.continue = i
if terrain_gen.counter % 512 == 511 then
terrain_gen.counter = terrain_gen.counter + 1
local surface = game.surfaces.bb_source
local c = 0
for chunk in surface.get_chunks() do
surface.delete_chunk({chunk.x, chunk.y})
c = c + 1
end
print("Deleted " .. c .. " source surface chunks.")
end
end

View File

@ -1,9 +1,12 @@
local Public = {}
local BiterRaffle = require "functions.biter_raffle"
local bb_config = require "maps.biter_battles_v2.config"
local math_floor = math.floor
local math_random = math.random
local math_abs = math.abs
local math_sqrt = math.sqrt
local simplex_noise = require 'utils.simplex_noise'.d2
local spawn_circle_size = 39
local ores = {"copper-ore", "iron-ore", "stone", "coal"}
@ -69,14 +72,14 @@ local function create_mirrored_tile_chain(surface, tile, count, straightness)
for a = 1, count, 1 do
local tile_placed = false
if math.random(0, 100) > straightness then modifiers = shuffle(modifiers) end
if math_random(0, 100) > straightness then modifiers = shuffle(modifiers) end
for b = 1, 4, 1 do
local pos = {x = position.x + modifiers[b].x, y = position.y + modifiers[b].y}
if surface.get_tile(pos).name ~= tile.name then
surface.set_tiles({{name = "landfill", position = pos}}, true)
surface.set_tiles({{name = tile.name, position = pos}}, true)
surface.set_tiles({{name = "landfill", position = {pos.x * -1, (pos.y * -1) - 1}}}, true)
surface.set_tiles({{name = tile.name, position = {pos.x * -1, (pos.y * -1) - 1}}}, true)
--surface.set_tiles({{name = "landfill", position = {pos.x * -1, (pos.y * -1) - 1}}}, true)
--surface.set_tiles({{name = tile.name, position = {pos.x * -1, (pos.y * -1) - 1}}}, true)
position = {x = pos.x, y = pos.y}
tile_placed = true
break
@ -107,8 +110,8 @@ end
local function get_chunk_position(position)
local chunk_position = {}
position.x = math.floor(position.x, 0)
position.y = math.floor(position.y, 0)
position.x = math_floor(position.x, 0)
position.y = math_floor(position.y, 0)
for x = 0, 31, 1 do
if (position.x - x) % 32 == 0 then chunk_position.x = (position.x - x) / 32 end
end
@ -146,21 +149,14 @@ local function draw_noise_ore_patch(position, name, surface, radius, richness)
local noise_1 = simplex_noise(pos.x * 0.0125, pos.y * 0.0125, seed)
local noise_2 = simplex_noise(pos.x * 0.1, pos.y * 0.1, seed + 25000)
local noise = noise_1 + noise_2 * 0.12
local distance_to_center = math.sqrt(x^2 + y^2)
local distance_to_center = math_sqrt(x^2 + y^2)
local a = richness - richness_part * distance_to_center
if distance_to_center < radius - math.abs(noise * radius * 0.85) and a > 1 then
if distance_to_center < radius - math_abs(noise * radius * 0.85) and a > 1 then
if surface.can_place_entity({name = name, position = pos, amount = a}) then
surface.create_entity{name = name, position = pos, amount = a}
local mirror_pos = {x = pos.x * -1, y = pos.y * -1}
surface.create_entity{name = name, position = mirror_pos, amount = a}
for _, e in pairs(surface.find_entities_filtered({position = pos, name = {"wooden-chest", "stone-wall", "gun-turret"}})) do
e.destroy()
end
for _, e in pairs(surface.find_entities_filtered({position = mirror_pos, name = {"wooden-chest", "stone-wall", "gun-turret"}})) do
e.destroy()
end
end
end
end
@ -170,36 +166,20 @@ end
function is_within_spawn_circle(pos)
if math_abs(pos.x) > spawn_circle_size then return false end
if math_abs(pos.y) > spawn_circle_size then return false end
if math.sqrt(pos.x ^ 2 + pos.y ^ 2) > spawn_circle_size then return false end
if math_sqrt(pos.x ^ 2 + pos.y ^ 2) > spawn_circle_size then return false end
return true
end
local river_y_1 = bb_config.border_river_width * -1.5
local river_y_2 = bb_config.border_river_width * 1.5
local river_width_half = math.floor(bb_config.border_river_width * -0.5)
local river_width_half = math_floor(bb_config.border_river_width * -0.5)
function is_horizontal_border_river(pos)
if pos.y < river_y_1 then return false end
if pos.y > river_y_2 then return false end
if pos.y > -5 and pos.x > -5 and pos.x < 5 then return false end
if pos.y >= river_width_half - (math_abs(get_noise(1, pos)) * 4) then return true end
return false
end
local function generate_inner_spawn_circle(pos, distance_to_center, surface)
-- assert(distance_to_center < spawn_circle_size) == true
local tile = false
if distance_to_center < 7 then
tile = "sand-1"
elseif distance_to_center < 9.5 then
tile = "refined-concrete"
else
tile = "deepwater"
if math_random(1, 48) == 1 then surface.create_entity({name = "fish", position = pos}) end
end
surface.set_tiles({{name = tile, position = pos}}, true)
end
local function generate_starting_area(pos, distance_to_center, surface)
-- assert(distance_to_center >= spawn_circle_size) == true
local spawn_wall_radius = 116
@ -248,28 +228,34 @@ local function generate_starting_area(pos, distance_to_center, surface)
if noise_2 < 0.25 then
if noise_2 > -0.5 then
if distance_from_spawn_wall > -1.75 and distance_from_spawn_wall < 0 then
surface.create_entity({name = "stone-wall", position = pos, force = "north"})
local e = surface.create_entity({name = "stone-wall", position = pos, force = "neutral"})
e.active = false
end
else
if distance_from_spawn_wall > -1.95 and distance_from_spawn_wall < 0 then
surface.create_entity({name = "stone-wall", position = pos, force = "north"})
local e = surface.create_entity({name = "stone-wall", position = pos, force = "neutral"})
e.active = false
elseif distance_from_spawn_wall > 0 and distance_from_spawn_wall < 4.5 then
local name = "wooden-chest"
local r_max = math.floor(math.abs(distance_from_spawn_wall)) + 2
local r_max = math_floor(math.abs(distance_from_spawn_wall)) + 2
if math_random(1,3) == 1 then name = name .. "-remnants" end
if math_random(1,r_max) == 1 then surface.create_entity({name = name, position = pos, force = "north"}) end
if math_random(1,r_max) == 1 then
local e = surface.create_entity({name = name, position = pos, force = "neutral"})
e.active = false
end
elseif distance_from_spawn_wall > -6 and distance_from_spawn_wall < -3 then
if math_random(1, 16) == 1 then
if surface.can_place_entity({name = "gun-turret", position = pos}) then
local t = surface.create_entity({name = "gun-turret", position = pos, force = "north"})
t.insert({name = "firearm-magazine", count = math_random(6,12)})
local e = surface.create_entity({name = "gun-turret", position = pos, force = "neutral"})
e.insert({name = "firearm-magazine", count = math_random(6,12)})
e.active = false
end
else
if math_random(1, 16) == 1 then
if surface.can_place_entity({name = "gun-turret", position = pos}) then
surface.create_entity({name = "gun-turret-remnants", position = pos, force = "north"})
surface.create_entity({name = "gun-turret-remnants", position = pos, force = "neutral"})
end
end
end
@ -279,92 +265,19 @@ local function generate_starting_area(pos, distance_to_center, surface)
end
end
local function generate_circle_spawn(event)
if global.bb_spawn_generated then return end
local surface = event.surface
local left_top_x = event.area.left_top.x
local left_top_y = event.area.left_top.y
if left_top_x < -160 then return end
if left_top_x > 160 then return end
if left_top_y < -160 then return end
local function generate_river(surface, left_top_x, left_top_y)
if left_top_y < -32 then return end
for x = 0, 31, 1 do
for y = 0, 31, 1 do
local pos = {x = left_top_x + x, y = left_top_y + y}
local distance_to_center = math.sqrt(pos.x ^ 2 + pos.y ^ 2)
if distance_to_center < spawn_circle_size then
generate_inner_spawn_circle(pos, distance_to_center, surface)
else
generate_starting_area(pos, distance_to_center, surface)
end
end
end
regenerate_decoratives(surface, event.area.left_top)
end
function Public.generate_north_silo(surface)
local pos = {x = -32 + math.random(0, 64), y = -72}
local mirror_position = {x = pos.x * -1, y = pos.y * -1}
for _, t in pairs(surface.find_tiles_filtered({area = {{pos.x - 6, pos.y - 6},{pos.x + 6, pos.y + 6}}, name = {"water", "deepwater"}})) do
surface.set_tiles({{name = get_replacement_tile(surface, t.position), position = t.position}})
end
for _, t in pairs(surface.find_tiles_filtered({area = {{mirror_position.x - 6, mirror_position.y - 6},{mirror_position.x + 6, mirror_position.y + 6}}, name = {"water", "deepwater"}})) do
surface.set_tiles({{name = get_replacement_tile(surface, t.position), position = t.position}})
end
global.rocket_silo["north"] = surface.create_entity({
name = "rocket-silo",
position = pos,
force = "north"
})
global.rocket_silo["north"].minable = false
for i = 1, 32, 1 do
create_mirrored_tile_chain(surface, {name = "stone-path", position = global.rocket_silo["north"].position}, 32, 10)
end
end
local function generate_river(event)
if event.area.left_top.y < -32 then return end
local surface = event.surface
local left_top_x = event.area.left_top.x
local left_top_y = event.area.left_top.y
for x = 0, 31, 1 do
for y = 0, 31, 1 do
local pos = {x = left_top_x + x, y = left_top_y + y}
local distance_to_center = math.sqrt(pos.x ^ 2 + pos.y ^ 2)
if is_horizontal_border_river(pos) then
local distance_to_center = math_sqrt(pos.x ^ 2 + pos.y ^ 2)
if is_horizontal_border_river(pos) and not is_within_spawn_circle(pos) then
surface.set_tiles({{name = "deepwater", position = pos}})
if math_random(1, 64) == 1 then surface.create_entity({name = "fish", position = pos}) end
end
end
end
end
local function generate_potential_spawn_ore(surface)
local r = 130
local area = {{r * -1, r * -1}, {r, 0}}
local ores = {}
ores["iron-ore"] = surface.count_entities_filtered({name = "iron-ore", area = area})
ores["copper-ore"] = surface.count_entities_filtered({name = "copper-ore", area = area})
ores["coal"] = surface.count_entities_filtered({name = "coal", area = area})
ores["stone"] = surface.count_entities_filtered({name = "stone", area = area})
for ore, ore_count in pairs(ores) do
if ore_count < 1000 or ore_count == nil then
local pos = {}
for a = 1, 32, 1 do
pos = {x = -96 + math_random(0, 192), y = -20 - math_random(0, 96)}
if surface.can_place_entity({name = "coal", position = pos, amount = 1}) then
break
if math_random(1, 64) == 1 then
local e = surface.create_entity({name = "fish", position = pos})
e.active = false
end
end
draw_noise_ore_patch(pos, ore, surface, math_random(18, 24), math_random(1500, 2000))
end
end
end
@ -372,7 +285,7 @@ end
local scrap_vectors = {}
for x = -5, 5, 1 do
for y = -5, 5, 1 do
if math.sqrt(x^2 + y^2) <= 5 then
if math_sqrt(x^2 + y^2) <= 5 then
scrap_vectors[#scrap_vectors + 1] = {x, y}
end
end
@ -380,12 +293,12 @@ end
local size_of_scrap_vectors = #scrap_vectors
local function generate_extra_worm_turrets(surface, left_top)
local chunk_distance_to_center = math.sqrt(left_top.x ^ 2 + left_top.y ^ 2)
local chunk_distance_to_center = math_sqrt(left_top.x ^ 2 + left_top.y ^ 2)
if bb_config.bitera_area_distance > chunk_distance_to_center then return end
local amount = (chunk_distance_to_center - bb_config.bitera_area_distance) * 0.0005
if amount < 0 then return end
local floor_amount = math.floor(amount)
local floor_amount = math_floor(amount)
local r = math.round(amount - floor_amount, 3) * 1000
if math_random(0, 999) <= r then floor_amount = floor_amount + 1 end
@ -396,7 +309,8 @@ local function generate_extra_worm_turrets(surface, left_top)
local v = chunk_tile_vectors[math_random(1, size_of_chunk_tile_vectors)]
local position = surface.find_non_colliding_position(worm_turret_name, {left_top.x + v[1], left_top.y + v[2]}, 8, 1)
if position then
local worm = surface.create_entity({name = worm_turret_name, position = position, force = "north_biters"})
local worm = surface.create_entity({name = worm_turret_name, position = position, force = "enemy"})
worm.active = false
-- add some scrap piles
if math_random(1,2) == 1 then
@ -404,7 +318,8 @@ local function generate_extra_worm_turrets(surface, left_top)
local vector = scrap_vectors[math_random(1, size_of_scrap_vectors)]
local position = {position.x + vector[1], position.y + vector[2]}
if surface.can_place_entity({name = "mineable-wreckage", position = position, force = "neutral"}) then
surface.create_entity({name = "mineable-wreckage", position = position, force = "neutral"})
local e = surface.create_entity({name = "mineable-wreckage", position = position, force = "neutral"})
e.active = false
end
end
end
@ -425,10 +340,7 @@ local function is_biter_area(position)
return true
end
local function draw_biter_area(surface, left_top)
local left_top_x = left_top.x
local left_top_y = left_top.y
local function draw_biter_area(surface, left_top_x, left_top_y)
if left_top_y > bb_config.bitera_area_distance * -1 + 32 then return end
local out_of_map = {}
@ -456,9 +368,11 @@ local function draw_biter_area(surface, left_top)
local position = {x = left_top_x + v[1], y = left_top_y + v[2]}
if is_biter_area(position) and surface.can_place_entity({name = "spitter-spawner", position = position}) then
if math_random(1, 4) == 1 then
table.insert(global.unit_spawners.north_biters, surface.create_entity({name = "spitter-spawner", position = position, force = "north_biters"}))
local e = surface.create_entity({name = "spitter-spawner", position = position, force = "enemy"})
e.active = false
else
table.insert(global.unit_spawners.north_biters, surface.create_entity({name = "biter-spawner", position = position, force = "north_biters"}))
local e = surface.create_entity({name = "biter-spawner", position = position, force = "enemy"})
e.active = false
end
end
end
@ -469,7 +383,7 @@ local function draw_biter_area(surface, left_top)
local position = {x = left_top_x + v[1], y = left_top_y + v[2]}
local worm_turret_name = BiterRaffle.roll("worm", e)
if is_biter_area(position) and surface.can_place_entity({name = worm_turret_name, position = position}) then
surface.create_entity({name = worm_turret_name, position = position, force = "north_biters"})
surface.create_entity({name = worm_turret_name, position = position, force = "enemy"})
end
end
@ -482,11 +396,7 @@ local function draw_biter_area(surface, left_top)
end
end
local function mixed_ore(event)
local surface = event.surface
local left_top_x = event.area.left_top.x
local left_top_y = event.area.left_top.y
local function mixed_ore(surface, left_top_x, left_top_y)
--Draw noise text values to determine which chunks are valid for mixed ore.
--rendering.draw_text{text = get_noise(1, {x = left_top_x + 16, y = left_top_y + 16}), surface = surface, target = {x = left_top_x + 16, y = left_top_y + 16}, color = {255, 255, 255}, time_to_live = 3600, scale = 2, font = "default-game"}
@ -500,73 +410,155 @@ local function mixed_ore(event)
if surface.can_place_entity({name = "iron-ore", position = pos}) then
local noise = get_noise(1, pos)
if noise > 0.81 then
local amount = math_random(1250, 1500) + math.sqrt(pos.x ^ 2 + pos.y ^ 2) * 1.1
local amount = math_random(1250, 1500) + math_sqrt(pos.x ^ 2 + pos.y ^ 2) * 1.1
local m = (noise - 0.75) * 16
amount = amount * m
local i = math.ceil(math.abs(noise * 35)) % 4
local i = math_floor(math_abs(noise * 35)) % 4 + 1
if i == 0 then i = 4 end
surface.create_entity({name = ores[i], position = pos, amount = amount})
end
end
end
end
if left_top_y == -32 and math_abs(left_top_x) <= 32 then
for _, e in pairs(surface.find_entities_filtered({area = {{-12, -12},{12, 12}}})) do e.destroy() end
end
end
function Public.generate(event)
if event.area.left_top.y >= 0 then return end
local surface = event.surface
local left_top = event.area.left_top
if surface.name ~= "biter_battles" then return end
for _, e in pairs(surface.find_entities_filtered({area = event.area, force = "enemy"})) do
surface.create_entity({name = e.name, position = e.position, force = "north_biters", direction = e.direction})
e.destroy()
end
local left_top_x = left_top.x
local left_top_y = left_top.y
mixed_ore(event)
generate_river(event)
generate_circle_spawn(event)
draw_biter_area(surface, left_top)
--[[
if bb_config.builders_area then
for _, t in pairs(surface.find_tiles_filtered({area = event.area, name = {"water", "deepwater"}})) do
builders_area_process_tile(t, surface)
end
for _, e in pairs(surface.find_entities_filtered({area = event.area})) do
builders_area_process_entity(e)
end
end
]]
generate_extra_worm_turrets(surface, left_top)
if global.bb_spawn_generated then return end
if game.tick > 0 then
generate_potential_spawn_ore(surface)
local area = {{-10,-10},{10,10}}
for _, e in pairs(surface.find_entities_filtered({area = area})) do
if e.name ~= "character" then e.destroy() end
end
surface.destroy_decoratives({area = area})
for _, silo in pairs(global.rocket_silo) do
for _, entity in pairs(surface.find_entities({{silo.position.x - 4, silo.position.y - 4}, {silo.position.x + 4, silo.position.y + 4}})) do
if entity.type == "simple-entity" or entity.type == "tree" or entity.type == "resource" then
entity.destroy()
if surface.name == "biter_battles" then
if math_abs(left_top.x) > 128 then
if left_top.y == 0 or left_top.y == -32 then
local tiles = {}
local i = 1
for x = 0, 31, 1 do
for y = 0, 31, 1 do
tiles[i] = {name = "deepwater", position = {x = left_top.x + x, y = left_top.y + y}}
i = i + 1
end
end
surface.set_tiles(tiles, true)
end
end
return
end
global.bb_spawn_generated = true
if surface.name ~= "bb_source" then return end
if left_top_y >= 0 then
surface.destroy_decoratives({area = event.area})
return
end
mixed_ore(surface, left_top_x, left_top_y)
generate_river(surface, left_top_x, left_top_y)
draw_biter_area(surface, left_top_x, left_top_y)
generate_extra_worm_turrets(surface, left_top)
end
function Public.draw_spawn_circle(surface)
for x = spawn_circle_size * -1, spawn_circle_size, 1 do
for y = spawn_circle_size * -1, 0, 1 do
local pos = {x = x, y = y}
local distance_to_center = math_sqrt(pos.x ^ 2 + pos.y ^ 2)
if distance_to_center <= spawn_circle_size then
surface.set_tiles({{name = "deepwater", position = pos}}, true)
if distance_to_center < 9.5 then
surface.set_tiles({{name = "refined-concrete", position = pos}}, true)
if distance_to_center < 7 then
surface.set_tiles({{name = "sand-1", position = pos}}, true)
end
else
if math_random(1, 48) == 1 then
local e = surface.create_entity({name = "fish", position = pos})
e.active = false
end
end
end
end
end
end
function Public.draw_spawn_area(surface)
local chunk_r = 4
local r = chunk_r * 32
for x = r * -1, r, 1 do
for y = r * -1, -32, 1 do
local pos = {x = x, y = y}
local distance_to_center = math_sqrt(pos.x ^ 2 + pos.y ^ 2)
generate_starting_area(pos, distance_to_center, surface)
end
end
surface.destroy_decoratives({})
surface.regenerate_decorative()
end
function Public.generate_additional_spawn_ore(surface)
local r = 130
local area = {{r * -1, r * -1}, {r, 0}}
local ores = {}
ores["iron-ore"] = surface.count_entities_filtered({name = "iron-ore", area = area})
ores["copper-ore"] = surface.count_entities_filtered({name = "copper-ore", area = area})
ores["coal"] = surface.count_entities_filtered({name = "coal", area = area})
ores["stone"] = surface.count_entities_filtered({name = "stone", area = area})
for ore, ore_count in pairs(ores) do
if ore_count < 1000 or ore_count == nil then
local pos = {}
for a = 1, 32, 1 do
pos = {x = -96 + math_random(0, 192), y = -20 - math_random(0, 96)}
if surface.can_place_entity({name = "coal", position = pos, amount = 1}) then
break
end
end
draw_noise_ore_patch(pos, ore, surface, math_random(18, 24), math_random(1500, 2000))
end
end
end
function Public.generate_silo(surface)
local pos = {x = -32 + math_random(0, 64), y = -72}
local mirror_position = {x = pos.x * -1, y = pos.y * -1}
for _, t in pairs(surface.find_tiles_filtered({area = {{pos.x - 6, pos.y - 6},{pos.x + 6, pos.y + 6}}, name = {"water", "deepwater"}})) do
surface.set_tiles({{name = get_replacement_tile(surface, t.position), position = t.position}})
end
for _, t in pairs(surface.find_tiles_filtered({area = {{mirror_position.x - 6, mirror_position.y - 6},{mirror_position.x + 6, mirror_position.y + 6}}, name = {"water", "deepwater"}})) do
surface.set_tiles({{name = get_replacement_tile(surface, t.position), position = t.position}})
end
local silo = surface.create_entity({
name = "rocket-silo",
position = pos,
force = "neutral"
})
silo.minable = false
silo.active = false
for i = 1, 32, 1 do
create_mirrored_tile_chain(surface, {name = "stone-path", position = silo.position}, 32, 10)
end
local p = silo.position
for _, entity in pairs(surface.find_entities({{p.x - 4, p.y - 4}, {p.x + 4, p.y + 4}})) do
if entity.type == "simple-entity" or entity.type == "tree" or entity.type == "resource" then
entity.destroy()
end
end
end
--Landfill Restriction
function Public.restrict_landfill(surface, inventory, tiles)
for _, t in pairs(tiles) do
local distance_to_center = math.sqrt(t.position.x ^ 2 + t.position.y ^ 2)
local distance_to_center = math_sqrt(t.position.x ^ 2 + t.position.y ^ 2)
local check_position = t.position
if check_position.y > 0 then check_position = {x = check_position.x * -1, y = (check_position.y * -1) - 1} end
if is_horizontal_border_river(check_position) or distance_to_center < spawn_circle_size then