-- Terrain for Biter Battles -- by MewMew local event = require 'utils.event' local math_random = math.random local simplex_noise = require 'utils.simplex_noise'.d2 local create_tile_chain = require "functions.create_tile_chain" local spawn_circle_size = 28 local ores = {"copper-ore", "iron-ore", "stone", "coal"} local function shuffle(tbl) local size = #tbl for i = size, 1, -1 do local rand = math_random(size) tbl[i], tbl[rand] = tbl[rand], tbl[i] end return tbl end local function get_noise(name, pos) local seed = game.surfaces[1].map_gen_settings.seed local noise_seed_add = 25000 if name == 1 then local noise = {} noise[1] = simplex_noise(pos.x * 0.0042, pos.y * 0.0042, seed) seed = seed + noise_seed_add noise[2] = simplex_noise(pos.x * 0.031, pos.y * 0.031, seed) seed = seed + noise_seed_add local noise = noise[1] + noise[2] * 0.08 return noise end if name == 2 then local noise = {} noise[1] = simplex_noise(pos.x * 0.011, pos.y * 0.011, seed) seed = seed + noise_seed_add noise[2] = simplex_noise(pos.x * 0.08, pos.y * 0.08, seed) seed = seed + noise_seed_add local noise = noise[1] + noise[2] * 0.2 return noise end if name == 3 then local noise = {} noise[1] = simplex_noise(pos.x * 0.02, pos.y * 0.02, seed) seed = seed + noise_seed_add noise[2] = simplex_noise(pos.x * 0.08, pos.y * 0.08, seed) seed = seed + noise_seed_add local noise = noise[1] + noise[2] * 0.1 return noise end end local function draw_smoothed_out_ore_circle(position, name, surface, radius, richness) if not position then return end if not name then return end if not surface then return end if not radius then return end if not richness then return end local math_random = math.random local noise_seed_add = 25000 local richness_part = richness / radius for y = radius * -2, radius * 2, 1 do for x = radius * -2, radius * 2, 1 do local pos = {x = x + position.x, y = y + position.y} local seed = game.surfaces[1].map_gen_settings.seed local noise_1 = simplex_noise(pos.x * 0.08, pos.y * 0.08, seed) seed = seed + noise_seed_add local noise_2 = simplex_noise(pos.x * 0.15, pos.y * 0.15, seed) local noise = noise_1 + noise_2 * 0.2 local distance_to_center = math.sqrt(x^2 + y^2) local a = richness - richness_part * distance_to_center if distance_to_center + ((1 + noise) * 3) < radius 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} end end end end end local function generate_horizontal_river(surface, pos) if pos.y < -32 then return false end if pos.y > -5 and pos.x > -5 and pos.x < 5 then return false end if -13 < pos.y + (get_noise(1, pos) * 5) then return true end --if -12 < pos.y + (get_noise(3, pos) * 6) then return true end return false end local function generate_circle_spawn(event) if event.area.left_top.y < -160 then return end if event.area.left_top.x < -160 then return end if event.area.left_top.x > 160 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) local tile = false if distance_to_center < spawn_circle_size then tile = "deepwater" if math_random(1, 48) == 1 then surface.create_entity({name = "fish", position = pos}) end end if distance_to_center < 9.5 then tile = "refined-concrete" end if distance_to_center < 7 then tile = "sand-1" end if tile then surface.set_tiles({{name = tile, position = pos}}, true) end if surface.can_place_entity({name = "stone-wall", position = pos}) then local noise = get_noise(2, pos) * 15 local r = 100 if distance_to_center + noise < r and distance_to_center + noise > r - 1.75 then surface.create_entity({name = "stone-wall", position = pos, force = "north"}) end if distance_to_center + noise < r - 4 and distance_to_center + noise > r - 6 then if math_random(1,150) == 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(3,6)}) end end end end end end end local function generate_silos(event) if event.area.left_top.y == -96 and event.area.left_top.x == -96 then local surface = event.surface local pos = surface.find_non_colliding_position("rocket-silo", {0,-64}, 32, 1) if not pos then pos = {x = 0, y = -64} 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_tile_chain(surface, {name = "stone-path", position = global.rocket_silo["north"].position}, 32, 10) end 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 generate_horizontal_river(surface, 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 rainbow_ore_and_ponds(event) 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} if surface.can_place_entity({name = "iron-ore", position = pos}) then local noise = get_noise(1, pos) if noise > 0.83 then local amount = math_random(1500, 2000) + math.sqrt(pos.x ^ 2 + pos.y ^ 2) * noise * 4 local i = math.ceil(math.abs(noise * 60)) % 4 if i == 0 then i = 4 end surface.create_entity({name = ores[i], position = pos, amount = amount}) end if noise < -0.86 then if noise < -0.92 then surface.set_tiles({{name = "deepwater", position = pos}}) else surface.set_tiles({{name = "water", position = pos}}) end if math_random(1, 48) == 1 then surface.create_entity({name = "fish", position = pos}) end end end end end end local function generate_potential_spawn_ore(event) if event.area.left_top.y < -128 then return end if event.area.left_top.x < -128 then return end if event.area.left_top.x > 128 then return end local pos = {x = event.area.left_top.x + 16, y = event.area.left_top.y + 16} local area = {{pos.x - 64, pos.y - 64}, {pos.x + 64, pos.y + 64}} local surface = event.surface local ores = {"iron-ore", "coal"} ores = shuffle(ores) if event.area.left_top.y == -96 and event.area.left_top.x == -32 then if surface.count_entities_filtered({name = ores[1], area = area}) < 40 then draw_smoothed_out_ore_circle(pos, ores[1], surface, 13, math_random(1500, 2500)) end end if event.area.left_top.y == -96 and event.area.left_top.x == 0 then if surface.count_entities_filtered({name = ores[2], area = area}) < 40 then draw_smoothed_out_ore_circle(pos, ores[2], surface, 13, math_random(1500, 2500)) end end end local function on_chunk_generated(event) if event.area.left_top.y >= 0 then return end local surface = event.surface 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 rainbow_ore_and_ponds(event) generate_river(event) generate_circle_spawn(event) --generate_potential_spawn_ore(event) generate_silos(event) if event.area.left_top.y == -160 and event.area.left_top.x == -160 then local area = {{-10,-10},{10,10}} for _, e in pairs(surface.find_entities_filtered({area = area})) do if e.name ~= "player" then e.destroy() end end surface.destroy_decoratives({area = area}) end end --Landfill Restriction local function 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 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 generate_horizontal_river(surface, check_position) or distance_to_center < spawn_circle_size then surface.set_tiles({{name = t.old_tile.name, position = t.position}}, true) inventory.insert({name = "landfill", count = 1}) end end end local function on_player_built_tile(event) local player = game.players[event.player_index] restrict_landfill(player.surface, player, event.tiles) end local function on_robot_built_tile(event) restrict_landfill(event.robot.surface, event.robot.get_inventory(defines.inventory.robot_cargo), event.tiles) end --Construction Robot Restriction local function on_robot_built_entity(event) local deny_building = false local force_name = event.robot.force.name if force_name == "north" then if event.created_entity.position.y >= -10 then deny_building = true end end if force_name == "player" then if event.created_entity.position.y <= 10 then deny_building = true end end if not deny_building then return end local inventory = event.robot.get_inventory(defines.inventory.robot_cargo) inventory.insert({name = event.created_entity.name, count = 1}) event.robot.surface.create_entity({name = "explosion", position = event.created_entity.position}) event.created_entity.destroy() end --Prevent Players from damaging the Rocket Silo local function on_entity_damaged(event) if event.cause then if event.cause.type == "unit" then return end end if event.entity.name ~= "rocket-silo" then return end event.entity.health = event.entity.health + event.final_damage_amount end local function on_marked_for_deconstruction(event) if event.entity.name == "fish" then event.entity.cancel_deconstruction(game.players[event.player_index].force.name) end end event.add(defines.events.on_marked_for_deconstruction, on_marked_for_deconstruction) event.add(defines.events.on_entity_damaged, on_entity_damaged) event.add(defines.events.on_robot_built_entity, on_robot_built_entity) event.add(defines.events.on_robot_built_tile, on_robot_built_tile) event.add(defines.events.on_player_built_tile, on_player_built_tile) event.add(defines.events.on_chunk_generated, on_chunk_generated)