diff --git a/config.lua b/config.lua index ef9091b3..1972031e 100644 --- a/config.lua +++ b/config.lua @@ -16,6 +16,14 @@ global.config = { -- New Scenario Features, appears in the "What's new" tab new_info_key = 'Nothing is new. The world is at peace' }, + -- redmew_surface allows a map preset to control world generation as well as map and difficulty settings + -- the entire module can be toggled or just individual parts + redmew_surface = { + enabled = true, + map_gen_settings = true, + map_settings = true, + difficulty = true + }, -- saves players' lives if they have a small-plane in their inventory, also adds the small-plane to the market and must therefor be loaded first train_saviour = { enabled = true diff --git a/features/antigrief.lua b/features/antigrief.lua index 641811e9..1becfad3 100644 --- a/features/antigrief.lua +++ b/features/antigrief.lua @@ -1,6 +1,7 @@ local Event = require 'utils.event' local Utils = require 'utils.core' local Game = require 'utils.game' +local RS = require 'map_gen.shared.redmew_surface' global.original_last_users_by_ent_pos = {} @@ -173,7 +174,7 @@ Module.undo = if e.last_user == player then --Place removed entity IF no collision is detected local last_user = global.original_last_users_by_ent_pos[get_position_str(e.position)] - local new_entity = place_entity_on_surface(e, game.surfaces.nauvis, false, last_user) + local new_entity = place_entity_on_surface(e, RS.get_surface(), false, last_user) --Transfer items if new_entity then local player = Utils.ternary(new_entity.last_user, new_entity.last_user, game.player) @@ -197,7 +198,7 @@ end Module.antigrief_surface_tp = function() if game.player then if game.player.surface == global.ag_surface then - game.player.teleport(game.player.position, game.surfaces.nauvis) + game.player.teleport(game.player.position, RS.get_surface()) else game.player.teleport(game.player.position, global.ag_surface) end diff --git a/map_gen/Diggy/Feature/DiggyCaveCollapse.lua b/map_gen/Diggy/Feature/DiggyCaveCollapse.lua index 9d6a436a..35652d17 100644 --- a/map_gen/Diggy/Feature/DiggyCaveCollapse.lua +++ b/map_gen/Diggy/Feature/DiggyCaveCollapse.lua @@ -12,6 +12,8 @@ local Token = require 'utils.token' local Global = require 'utils.global' local Game = require 'utils.game' local CreateParticles = require 'features.create_particles' +local RS = require 'map_gen.shared.redmew_surface' + local random = math.random local floor = math.floor local pairs = pairs @@ -401,7 +403,7 @@ to reinforce it further. mask_init(config) if (config.enable_mask_debug) then - local surface = game.surfaces.nauvis + local surface = RS.get_surface() mask_disc_blur(0, 0, 10, function(x, y, fraction) Debug.print_grid_value(fraction, surface, {x = x, y = y}) end) diff --git a/map_gen/Diggy/Feature/NightTime.lua b/map_gen/Diggy/Feature/NightTime.lua index 908f6f45..76caeac0 100644 --- a/map_gen/Diggy/Feature/NightTime.lua +++ b/map_gen/Diggy/Feature/NightTime.lua @@ -7,6 +7,7 @@ -- dependencies local Event = require 'utils.event' local Game = require 'utils.game' +local RS = require 'map_gen.shared.redmew_surface' -- this local NightTime = {} @@ -55,7 +56,7 @@ end -- a daytime of 0.5 is the value where every light and ambient lights are turned on. -- function NightTime.on_init() - local surface = game.surfaces.nauvis + local surface = RS.get_surface() surface.daytime = 0.5 surface.freeze_daytime = 1 diff --git a/map_gen/Diggy/Feature/SetupPlayer.lua b/map_gen/Diggy/Feature/SetupPlayer.lua index 699a66db..435097bb 100644 --- a/map_gen/Diggy/Feature/SetupPlayer.lua +++ b/map_gen/Diggy/Feature/SetupPlayer.lua @@ -1,5 +1,4 @@ local Event = require 'utils.event' -local Game = require 'utils.game' local SetupPlayer = {} @@ -8,26 +7,13 @@ global.SetupPlayer = { } function SetupPlayer.register(config) - Event.add(defines.events.on_player_created, function (event) - local player = Game.get_player_by_index(event.player_index) - local force = player.force - local position = {0, 0} - local surface = player.surface + Event.add(defines.events.on_player_created, function () local redmew_player_create = global.config.player_create - if global.SetupPlayer.first_player_spawned then - position = surface.find_non_colliding_position('player', position, 3, 0.1) - else - global.SetupPlayer.first_player_spawned = true - end - if #config.starting_items > 0 then redmew_player_create.starting_items = config.starting_items end - force.set_spawn_position(position, surface) - player.teleport(position) - local cheats = config.cheats local redmew_cheats = redmew_player_create.cheats redmew_cheats.manual_mining_speed_modifier = cheats.manual_mining_speed_modifier diff --git a/map_gen/Diggy/Feature/StartingZone.lua b/map_gen/Diggy/Feature/StartingZone.lua index f825ff94..196e2c4b 100644 --- a/map_gen/Diggy/Feature/StartingZone.lua +++ b/map_gen/Diggy/Feature/StartingZone.lua @@ -7,6 +7,8 @@ local Token = require 'utils.token' local Template = require 'map_gen.Diggy.Template' local Retailer = require 'features.retailer' local DiggyCaveCollapse = require 'map_gen.Diggy.Feature.DiggyCaveCollapse' +local RS = require 'map_gen.shared.redmew_surface' + local insert = table.insert local random = math.random local sqrt = math.sqrt @@ -25,6 +27,9 @@ function StartingZone.register(config) local starting_zone_size = config.starting_size local function on_chunk_generated(event) + if event.surface ~= RS.get_surface() then + return + end local start_point_area = {{-0.9, -0.9}, {0.9, 0.9}} local start_point_cleanup = {{-0.9, -0.9}, {1.9, 1.9}} local surface = event.surface diff --git a/map_gen/Diggy/Scenario.lua b/map_gen/Diggy/Scenario.lua index 69f35e8f..c9d3d4ba 100644 --- a/map_gen/Diggy/Scenario.lua +++ b/map_gen/Diggy/Scenario.lua @@ -1,6 +1,7 @@ -- dependencies local Config = require 'map_gen.Diggy.Config' local ScenarioInfo = require 'features.gui.info' +local RS = require 'map_gen.shared.redmew_surface' local Event = require 'utils.event' local type = type local pairs = pairs @@ -11,6 +12,7 @@ require 'utils.core' -- this local Scenario = {} +RS.set_first_player_position_check_override(true) -- forces players to spawn at 0,0 global.diggy_scenario_registered = false --[[-- diff --git a/map_gen/combined/borg_planet.lua b/map_gen/combined/borg_planet.lua index 6940e342..79464235 100644 --- a/map_gen/combined/borg_planet.lua +++ b/map_gen/combined/borg_planet.lua @@ -1,8 +1,10 @@ +-- luacheck: ignore +-- This file is a linting disaster and needs an overhaul --Author: MewMew -- !! ATTENTION !! -- Use water only in starting area as map setting!!! -local Event = require 'utils.event' local perlin = require 'map_gen.shared.perlin_noise' +local RS = require 'map_gen.shared.redmew_surface' wreck_item_pool = {} wreck_item_pool = { @@ -89,7 +91,7 @@ local function find_tile_placement_spot_around_target_position(tilename, positio local x = position.x local y = position.y if not surface then - surface = game.surfaces[1] + surface = RS.get_surface() end local scan_radius = 50 if not tilename then @@ -321,11 +323,7 @@ end local function create_tile_cluster(tilename, position, amount) local mode = 'ball' - local cluster_tiles = {} - local surface = game.surfaces[1] local pos = position - local x = pos.x - local y = pos.y for i = 1, amount, 1 do local b, x, y = find_tile_placement_spot_around_target_position(tilename, pos, mode) if b == true then @@ -356,7 +354,6 @@ function run_combined_module(event) local area = event.area local surface = event.surface local tiles = {} - local decoratives = {} local resource_tiles = {} local special_tiles = true diff --git a/map_gen/combined/dagobah_swamp.lua b/map_gen/combined/dagobah_swamp.lua index 5a34c068..1a99eda0 100644 --- a/map_gen/combined/dagobah_swamp.lua +++ b/map_gen/combined/dagobah_swamp.lua @@ -4,6 +4,7 @@ -- Use water only in starting area as map setting!!! local perlin = require 'map_gen.shared.perlin_noise' local Task = require 'utils.task' +local RS = require 'map_gen.shared.redmew_surface' wreck_item_pool = {} wreck_item_pool = { {name = 'iron-gear-wheel', count = 32}, @@ -81,7 +82,7 @@ local function auto_place_entity_around_target(entity, scan_radius, mode, densit local x = entity.pos.x local y = entity.pos.y if not surface then - surface = game.surfaces[1] + surface = RS.get_surface() end if not scan_radius then scan_radius = 6 diff --git a/map_gen/combined/dimensions.lua b/map_gen/combined/dimensions.lua index 5d870276..ebc09c4f 100644 --- a/map_gen/combined/dimensions.lua +++ b/map_gen/combined/dimensions.lua @@ -1,10 +1,10 @@ --Author: Valansch -local Event = require "utils.event" +local Event = require 'utils.event' +local RS = require 'map_gen.shared.redmew_surface' +local wrech_items_module = require 'map_gen.misc.wreck_items' -local wrech_items_module = require "map_gen.misc.wreck_items" - -local resource_types = {"copper-ore", "iron-ore", "coal", "stone", "uranium-ore", "crude-oil"} +local resource_types = {'copper-ore', 'iron-ore', 'coal', 'stone', 'uranium-ore', 'crude-oil'} global.current_portal_index = 1 global.portals = {} @@ -15,149 +15,148 @@ global.current_magic_chest_index = 1 global.magic_chests = {} --{entity : LuaEntity, target : LuaEntity} - global.last_tp = {} global.teleport_cooldown = 3 global.portal_radius = 2 - local function get_nice_surface_name(name) - name = name:gsub("-ore", ""):gsub("-oil", " Oil") - return name:sub(1,1):upper() .. name:sub(2) + name = name:gsub('-ore', ''):gsub('-oil', ' Oil') + return name:sub(1, 1):upper() .. name:sub(2) end --Creates autoplace_controls with only one resource type enabled local function create_resource_setting(resource) - local settings = game.surfaces[1].map_gen_settings - for _,type in pairs(resource_types) do - settings.autoplace_controls[type] = {frequency = "none", size = "none", richness = "none"} - end - settings.autoplace_controls[resource] = {frequency = "normal", size = "big", richness = "good"} - return settings + local settings = RS.get_surface().map_gen_settings + for _, type in pairs(resource_types) do + settings.autoplace_controls[type] = {frequency = 'none', size = 'none', richness = 'none'} + end + settings.autoplace_controls[resource] = {frequency = 'normal', size = 'big', richness = 'good'} + return settings end local function init() - if not game.surfaces[2] then - for _,type in pairs(resource_types) do - game.create_surface(get_nice_surface_name(type), create_resource_setting(type)) + local rs_index = RS.get_surface().index + 1 + if not game.surfaces[rs_index] then + for _, type in pairs(resource_types) do + game.create_surface(get_nice_surface_name(type), create_resource_setting(type)) + end + local enemy_settings = create_resource_setting('enemy-base') + enemy_settings.autoplace_controls['enemy-base'] = {frequency = 'very-high', size = 'very-big', richness = 'very-good'} + game.create_surface('Zerus', enemy_settings) + game.create_surface('Nihil', create_resource_setting('copper-ore')) end - local enemy_settings = create_resource_setting("enemy-base") - enemy_settings.autoplace_controls["enemy-base"] = {frequency = "very-high", size = "very-big", richness = "very-good"} - game.create_surface("Zerus", enemy_settings) - game.create_surface("Nihil", create_resource_setting("copper-ore")) - end end local function generate_nihil(event) - for _,e in pairs(event.surface.find_entities_filtered{}) do - if e.type ~= "player" then - e.destroy() + for _, e in pairs(event.surface.find_entities_filtered {}) do + if e.type ~= 'player' then + e.destroy() + end end - end - local tiles = {} - for x = event.area.left_top.x, event.area.right_bottom.x -1 do - for y = event.area.left_top.y, event.area.right_bottom.y - 1 do - table.insert(tiles,{name="lab-dark-1", position = {x,y}}) + local tiles = {} + for x = event.area.left_top.x, event.area.right_bottom.x - 1 do + for y = event.area.left_top.y, event.area.right_bottom.y - 1 do + table.insert(tiles, {name = 'lab-dark-1', position = {x, y}}) + end end - end - event.surface.set_tiles(tiles) + event.surface.set_tiles(tiles) end function run_combined_module(event) - init() - if event.surface.name == "Zerus" then - wrech_items_module.on_chunk_generated(event) - elseif event.surface.name == "Nihil" then - generate_nihil(event) - end + init() + if event.surface.name == 'Zerus' then + wrech_items_module.on_chunk_generated(event) + elseif event.surface.name == 'Nihil' then + generate_nihil(event) + end end local function teleport_nearby_players(portal) - for _, player_character in pairs(portal.source.find_entities_filtered{area = {{portal.position.x - global.portal_radius,portal.position.y - global.portal_radius},{portal.position.x + global.portal_radius,portal.position.y + global.portal_radius}}, name = "player", type = "player"}) do - local player = player_character.player - if not global.last_tp[player.name] or global.last_tp[player.name] + global.teleport_cooldown * 60 < game.tick then - player.teleport(portal.target, portal.target_surface) - global.last_tp[player.name] = game.tick - player.print("Wooosh! You are now in the " .. portal.target_surface.name .. " dimention.") - end + for _, player_character in pairs(portal.source.find_entities_filtered {area = {{portal.position.x - global.portal_radius, portal.position.y - global.portal_radius}, {portal.position.x + global.portal_radius, portal.position.y + global.portal_radius}}, name = 'player', type = 'player'}) do + local player = player_character.player + if not global.last_tp[player.name] or global.last_tp[player.name] + global.teleport_cooldown * 60 < game.tick then + player.teleport(portal.target, portal.target_surface) + global.last_tp[player.name] = game.tick + player.print('Wooosh! You are now in the ' .. portal.target_surface.name .. ' dimension.') + end end end local function teleport_players() - local num_portals = #global.portals - if num_portals > 0 then - local portal = global.portals[global.current_portal_index] - if portal.target then - teleport_nearby_players(portal) + local num_portals = #global.portals + if num_portals > 0 then + local portal = global.portals[global.current_portal_index] + if portal.target then + teleport_nearby_players(portal) + end + global.current_portal_index = (global.current_portal_index) % num_portals + 1 --Next portal end - global.current_portal_index = (global.current_portal_index) % num_portals + 1 --Next portal - end end local function teleport_stuff() - local num_chests = #global.magic_chests - if num_chests > 0 then - local chest = global.magic_chests[global.current_magic_chest_index] - if chest.entity and chest.target and chest.entity.valid and chest.target.valid then - local inv = chest.entity.get_inventory(defines.inventory.chest) - local target_inv = chest.target.get_inventory(defines.inventory.chest) - if inv and target_inv then - for item, count in pairs(inv.get_contents()) do - local n_inserted = target_inv.insert{name = item, count = count} - if n_inserted > 0 then - inv.remove{name = item, count = n_inserted} - end + local num_chests = #global.magic_chests + if num_chests > 0 then + local chest = global.magic_chests[global.current_magic_chest_index] + if chest.entity and chest.target and chest.entity.valid and chest.target.valid then + local inv = chest.entity.get_inventory(defines.inventory.chest) + local target_inv = chest.target.get_inventory(defines.inventory.chest) + if inv and target_inv then + for item, count in pairs(inv.get_contents()) do + local n_inserted = target_inv.insert {name = item, count = count} + if n_inserted > 0 then + inv.remove {name = item, count = n_inserted} + end + end + end end - end + global.current_magic_chest_index = (global.current_magic_chest_index) % num_chests + 1 --Next magic chest end - global.current_magic_chest_index = (global.current_magic_chest_index) % num_chests + 1 --Next magic chest - end end -local function dim_on_tick(event) - if game.tick % 2 == 0 then - teleport_stuff() - else - teleport_players() - end +local function dim_on_tick() + if game.tick % 2 == 0 then + teleport_stuff() + else + teleport_players() + end end global.chest_selected = false local function linkchests() - if game.player and game.player.admin and game.player.selected and (game.player.selected.type == "logistic-container" or game.player.selected.type == "container") then - game.player.selected.destructible = false - game.player.selected.minable = false - if global.chest_selected then - global.magic_chests[#global.magic_chests].target = game.player.selected - game.print("Link established.") + if game.player and game.player.admin and game.player.selected and (game.player.selected.type == 'logistic-container' or game.player.selected.type == 'container') then + game.player.selected.destructible = false + game.player.selected.minable = false + if global.chest_selected then + global.magic_chests[#global.magic_chests].target = game.player.selected + game.print('Link established.') + else + table.insert(global.magic_chests, {entity = game.player.selected}) + game.print('Selected first chest.') + end + global.chest_selected = not global.chest_selected else - table.insert(global.magic_chests, {entity = game.player.selected}) - game.print("Selected first chest.") + game.print('failed.') end - global.chest_selected = not global.chest_selected - else - game.print("failed.") - end end global.portal_selected = false local function linkportals() if game.player and game.player.admin then - if global.portal_selected then - global.portals[#global.portals].target = game.player.position - global.portals[#global.portals].target_surface = game.player.surface - --Way back home: - table.insert(global.portals, {position = game.player.position, target = global.portals[#global.portals].position, source = game.player.surface, target_surface = global.portals[#global.portals].source}) - game.print("Portal link established.") - else - table.insert(global.portals, {position = game.player.position, source = game.player.surface}) - game.print("Selected first portal.") - end - global.portal_selected = not global.portal_selected + if global.portal_selected then + global.portals[#global.portals].target = game.player.position + global.portals[#global.portals].target_surface = game.player.surface + --Way back home: + table.insert(global.portals, {position = game.player.position, target = global.portals[#global.portals].position, source = game.player.surface, target_surface = global.portals[#global.portals].source}) + game.print('Portal link established.') + else + table.insert(global.portals, {position = game.player.position, source = game.player.surface}) + game.print('Selected first portal.') + end + global.portal_selected = not global.portal_selected else - game.print("failed.") + game.print('failed.') end end -commands.add_command("linkchests", "Select a chest to link to another. Run this command again to select the other one.", linkchests) -commands.add_command("linkportals", "Select a portal to link to another. Run this command again to select the other one.", linkportals) +commands.add_command('linkchests', 'Select a chest to link to another. Run this command again to select the other one.', linkchests) +commands.add_command('linkportals', 'Select a portal to link to another. Run this command again to select the other one.', linkportals) Event.add(defines.events.on_tick, dim_on_tick) diff --git a/map_gen/combined/meteor_strike.lua b/map_gen/combined/meteor_strike.lua index 308d917b..9c52ef03 100644 --- a/map_gen/combined/meteor_strike.lua +++ b/map_gen/combined/meteor_strike.lua @@ -1,5 +1,6 @@ local perlin = require 'map_gen.shared.perlin_noise' local Event = require 'utils.event' +local RS = require 'map_gen.shared.redmew_surface' local block_size = 1 -- in tiles local start_size = 64 -- in blocks @@ -152,7 +153,7 @@ local function do_strike() table.insert(tiles, {name = 'dry-dirt', position = {x, y}}) end end - local surface = game.surfaces[1] + local surface = RS.get_surface() surface.set_tiles(tiles, false) game.forces.player.chart(surface, {{bx, by}, {bx + block_size, by + block_size}}) diff --git a/map_gen/combined/red_planet_v2.lua b/map_gen/combined/red_planet_v2.lua index 0bd83727..1ca7aaa7 100644 --- a/map_gen/combined/red_planet_v2.lua +++ b/map_gen/combined/red_planet_v2.lua @@ -5,6 +5,7 @@ local perlin = require 'map_gen.shared.perlin_noise' local Task = require 'utils.task' +local RS = require 'map_gen.shared.redmew_surface' wreck_item_pool = {} wreck_item_pool = { @@ -86,7 +87,7 @@ function run_combined_module(event) if not global.perlin_noise_seed then global.perlin_noise_seed = math.random(1000, 1000000) end - local surface = game.surfaces[1] + local surface = RS.get_surface() local entities = surface.find_entities(event.area) for _, entity in pairs(entities) do diff --git a/map_gen/misc/nightfall.lua b/map_gen/misc/nightfall.lua index 0c46c284..06588340 100644 --- a/map_gen/misc/nightfall.lua +++ b/map_gen/misc/nightfall.lua @@ -18,6 +18,7 @@ TODO: Look into triggering existing unit groups to attack in unison with the gro -- Dependencies local Event = require 'utils.event' local Global = require 'utils.global' +local RS = require 'map_gen.shared.redmew_surface' local table = require 'utils.table' local random = math.random @@ -54,7 +55,7 @@ Global.register( -- looking for biters and adding them to a group local function biter_attack() local maxindex = #data.bases - local surface = game.surfaces[1] + local surface = RS.get_surface() for i = data.c_index, data.c_index + processchunk, 1 do if i > maxindex then -- we reached the end of the table @@ -95,8 +96,8 @@ end -- looking for unit spawners and adding them to the bases table, when done iterating -- through chunklist it sets the state to ATTACKING local function find_bases() - local get_pollution = game.surfaces[1].get_pollution - local count_entities_filtered = game.surfaces[1].count_entities_filtered + local get_pollution = RS.get_surface().get_pollution + local count_entities_filtered = RS.get_surface().count_entities_filtered if data.c_index == 1 then data.bases = {} end @@ -136,7 +137,7 @@ end --- When a chunk is generated, add it to the chunklist local function on_chunk_generated(event) - if event.surface == game.surfaces[1] then + if event.surface == RS.get_surface() then local chunk = {} local coords = event.area.left_top chunk.x = coords.x + 16 @@ -158,12 +159,12 @@ end --- Change us from idle to searching for bases if the conditions are met. local function on_interval() if - game.surfaces[1].darkness > 0.5 and random() > 0.5 and data.state == IDLE and + RS.get_surface().darkness > 0.5 and random() > 0.5 and data.state == IDLE and game.tick >= data.lastattack + timeinterval then data.state = BASE_SEARCH if _DEBUG then - game.surfaces[1].print('[NIGHTFALL] entering BASE_SEARCH state') --for debug + RS.get_surface().print('[NIGHTFALL] entering BASE_SEARCH state') --for debug end end end diff --git a/map_gen/misc/rail_grid.lua b/map_gen/misc/rail_grid.lua index 2aced775..297a09f9 100644 --- a/map_gen/misc/rail_grid.lua +++ b/map_gen/misc/rail_grid.lua @@ -1,6 +1,7 @@ local Event = require 'utils.event' +local RS = require 'map_gen.shared.redmew_surface' -mymodule = {} +local mymodule = {} local function rot_pos(pos, rot) local ctr = {x = 15, y = 15} @@ -326,7 +327,7 @@ end Event.on_init(on_init) local function build_intersection(type, origin, rot) - local surface = game.surfaces[1] + local surface = RS.get_surface() for _, v in pairs(rail_grid[type]) do local pos = rot_pos(v.position, rot) local dir = rot_dir(v.direction, rot) @@ -339,7 +340,7 @@ end -- dirs : {E, S, W, N}, array of 0/1 local function build_chunk(origin, dirs) - local surface = game.surfaces[1] + local surface = RS.get_surface() local cnt = 0 local sum = {x = 0, y = 0} local delta = {x = 1, y = 0} @@ -396,21 +397,13 @@ local function find_connections(gx, gy) end end -local function disable_items() - force = game.forces['player'] - force.recipes['logistic-chest-requester'].enabled = false - force.recipes['underground-belt'].enabled = false - force.recipes['fast-underground-belt'].enabled = false - force.recipes['express-underground-belt'].enabled = false -end - function mymodule.on_chunk_generated(event) local bd_box = event.area local surface = event.surface local chunk_size = 32 -- assert(chunk_size == bd_box.right_bottom.x - bd_box.left_top.x) -- assert(chunk_size == bd_box.right_bottom.y - bd_box.left_top.y) - if surface ~= game.surfaces[1] then + if surface ~= RS.get_surface() then return end diff --git a/map_gen/misc/rusky_pvp.lua b/map_gen/misc/rusky_pvp.lua index 6b421a6c..89b66368 100644 --- a/map_gen/misc/rusky_pvp.lua +++ b/map_gen/misc/rusky_pvp.lua @@ -1,5 +1,62 @@ local Event = require 'utils.event' local Game = require 'utils.game' +local RS = require 'map_gen.shared.redmew_surface' + +local function killBitters(pos) + for k, v in pairs(RS.get_surface().find_entities_filtered({area = {{pos.x - 250, pos.y - 250}, {pos.x + 250, pos.y + 250}}, force = 'enemy'})) do + v.destroy() + end +end + +local function dist(position1, position2) + return ((position1.x - position2.x) ^ 2 + (position1.y - position2.y) ^ 2) ^ 0.5 +end + +local function neForceNear(pos) + for k, v in pairs(game.forces) do + if dist(pos, v.get_spawn_position(RS.get_surface())) <= 50 then + return false + end + end + return true +end + +local function validPlayer(name) + if name ~= nil and Game.get_player_by_index(name) ~= nil and Game.get_player_by_index(name).force == game.forces.player then + return true + end + return false +end + +local function guiNewPlayer(gui) + local frame = gui.add {type = 'frame', name = 'new_force', caption = {'gui.create-force'}, direction = 'vertical'} + frame.add {type = 'button', name = 'new_button', caption = {'gui.new-force'}} +end + +local function guiForcePlayer(gui) + local frame = gui.add {type = 'frame', name = 'own_force', caption = {'gui.force'}, direction = 'vertical'} + frame.add {type = 'textfield', name = 'inv_name'} + frame.add {type = 'button', name = 'inv_button', caption = {'gui.invite'}} + frame.add {type = 'button', name = 'leave_button', caption = {'gui.leave'}} +end + +local function printNewPlayer(player) + --player.print{"msg.info13"} + --player.print{"msg.info14"} + player.print {'msg.info1'} + player.print {'msg.info2'} + player.print {'msg.info3'} + player.print {'msg.info4'} + player.print {'msg.info5'} + --player.print{"msg.info6"} + --player.print{"msg.info7"} + --player.print{"msg.info8"} +end + +local function printForcePlayer(player) + player.print {'msg.info11'} + player.print {'msg.info12'} +end Event.on_init( function() @@ -87,7 +144,7 @@ Event.add( if player.force == game.forces.player and event.element.name == 'new_button' then if neForceNear(player.position) then local force = game.create_force(player.name) - force.set_spawn_position(player.position, game.surfaces[1]) + force.set_spawn_position(player.position, RS.get_surface()) player.force = force killBitters(player.position) player.force.chart(player.surface, {{player.position.x - 200, player.position.y - 200}, {player.position.x + 200, player.position.y + 200}}) @@ -107,7 +164,7 @@ Event.add( local igui = iplayer.gui.left iplayer.force = player.force - iplayer.teleport(player.force.get_spawn_position(game.surfaces[1])) + iplayer.teleport(player.force.get_spawn_position(RS.get_surface())) igui.new_force.destroy() guiForcePlayer(igui) @@ -134,59 +191,3 @@ Event.add( end end ) - -function neForceNear(pos) - for k, v in pairs(game.forces) do - if dist(pos, v.get_spawn_position(game.surfaces[1])) <= 50 then - return false - end - end - return true -end - -function killBitters(pos) - for k, v in pairs(game.surfaces[1].find_entities_filtered({area = {{pos.x - 250, pos.y - 250}, {pos.x + 250, pos.y + 250}}, force = 'enemy'})) do - v.destroy() - end -end - -function dist(position1, position2) - return ((position1.x - position2.x) ^ 2 + (position1.y - position2.y) ^ 2) ^ 0.5 -end - -function validPlayer(name) - if name ~= nil and Game.get_player_by_index(name) ~= nil and Game.get_player_by_index(name).force == game.forces.player then - return true - end - return false -end - -function guiNewPlayer(gui) - local frame = gui.add {type = 'frame', name = 'new_force', caption = {'gui.create-force'}, direction = 'vertical'} - frame.add {type = 'button', name = 'new_button', caption = {'gui.new-force'}} -end - -function guiForcePlayer(gui) - local frame = gui.add {type = 'frame', name = 'own_force', caption = {'gui.force'}, direction = 'vertical'} - frame.add {type = 'textfield', name = 'inv_name'} - frame.add {type = 'button', name = 'inv_button', caption = {'gui.invite'}} - frame.add {type = 'button', name = 'leave_button', caption = {'gui.leave'}} -end - -function printNewPlayer(player) - --player.print{"msg.info13"} - --player.print{"msg.info14"} - player.print {'msg.info1'} - player.print {'msg.info2'} - player.print {'msg.info3'} - player.print {'msg.info4'} - player.print {'msg.info5'} - --player.print{"msg.info6"} - --player.print{"msg.info7"} - --player.print{"msg.info8"} -end - -function printForcePlayer(player) - player.print {'msg.info11'} - player.print {'msg.info12'} -end diff --git a/map_gen/misc/terraforming.lua b/map_gen/misc/terraforming.lua index 44a1f427..70aba910 100644 --- a/map_gen/misc/terraforming.lua +++ b/map_gen/misc/terraforming.lua @@ -2,11 +2,14 @@ local Game = require 'utils.game' local Event = require 'utils.event' local Task = require 'utils.task' local Token = require 'utils.token' -local random = math.random -local insert = table.insert local Popup = require 'features.gui.popup' local Global = require 'utils.global' local Command = require 'utils.command' +local RS = require 'map_gen.shared.redmew_surface' + +local random = math.random +local insert = table.insert + if not global.map.terraforming then global.map.terraforming = {} end @@ -176,7 +179,7 @@ Global.register( -- @param tile_table table of tiles to convert -- @param tiles table of potential tiles to convert to local function convert_tiles(tile_table, tiles) - local set_tiles = game.surfaces[1].set_tiles + local set_tiles = RS.get_surface().set_tiles local tile_set = {} local target_tile = tile_table[random(1, #tile_table)] -- convert the LuaTiles table into a new one we can edit @@ -251,7 +254,7 @@ end --- Scans the provided chunk for entities on force _creep_force_. --@param chunk table with position and status of a map chunk local function check_chunk_for_entities(chunk) - local find_entities_filtered = game.surfaces[1].find_entities_filtered + local find_entities_filtered = RS.get_surface().find_entities_filtered local entities_found entities_found = find_entities_filtered { @@ -267,7 +270,7 @@ end --@param state number representing whether we want to expand or contract the chunk (expand = 1, retract = 2) --@param i number of the chunk's key in the chunklist table local function change_creep_state(state, i) - local find_tiles_filtered = game.surfaces[1].find_tiles_filtered + local find_tiles_filtered = RS.get_surface().find_tiles_filtered local tiles_to_set = {} local debug_message local chunk_end_state @@ -309,14 +312,14 @@ local function change_creep_state(state, i) -- if a chunk has lost all creep, do a final check to see if there are any buildings to kill and regen the decoratives if state == 2 then check_chunk_for_entities(chunklist[i]) - game.surfaces[1].regenerate_decorative(decoratives, {{chunklist[i].x, chunklist[i].y}}) + RS.get_surface().regenerate_decorative(decoratives, {{chunklist[i].x, chunklist[i].y}}) end end end --- Every tick scan _processchunk_ number of chunks for their pollution state and if needed, change their state local function on_tick() - local get_pollution = game.surfaces[1].get_pollution + local get_pollution = RS.get_surface().get_pollution local maxindex = #chunklist for i = c_index[1], c_index[1] + processchunk, 1 do if i > maxindex then @@ -339,7 +342,7 @@ end --- Takes newly generated chunks and places them inside the chunklist table local function on_chunk_generated(event) - if event.surface == game.surfaces[1] then + if event.surface == RS.get_surface() then local chunk = {} local coords = event.area.left_top chunk.x = coords.x + 16 diff --git a/map_gen/ores/fluffy_rainbows.lua b/map_gen/ores/fluffy_rainbows.lua index 65a8271c..2623e5ca 100644 --- a/map_gen/ores/fluffy_rainbows.lua +++ b/map_gen/ores/fluffy_rainbows.lua @@ -2,6 +2,7 @@ local perlin = require 'map_gen.shared.perlin_noise' local Event = require 'utils.event' +local RS = require 'map_gen.shared.redmew_surface' --SETTINGS: local width_modifier = 0.8 @@ -14,7 +15,7 @@ local ore_base_amounts = { } local function init() - global.perlin_noise_seed = game.surfaces[1].map_gen_settings.seed + global.perlin_noise_seed = RS.get_surface().map_gen_settings.seed -- math.random(1000, 1000000) end diff --git a/map_gen/ores/neko_crazy_ores.lua b/map_gen/ores/neko_crazy_ores.lua index a626325e..c0db3d1d 100644 --- a/map_gen/ores/neko_crazy_ores.lua +++ b/map_gen/ores/neko_crazy_ores.lua @@ -1,11 +1,12 @@ local perlin = require 'map_gen.shared.perlin_noise' local Event = require 'utils.event' +local RS = require 'map_gen.shared.redmew_surface' local random_ores = {'iron-ore', 'coal', 'copper-ore', 'stone', 'uranium-ore'} local random_dense = {1.6, 0.8, 1, 0.6, 0.5} --ore density reference local function run_ores_module_setup() - local seed = game.surfaces[1].map_gen_settings.seed + local seed = RS.get_surface().map_gen_settings.seed if not global.ores_seed_A then global.ores_seed_A = seed end diff --git a/map_gen/ores/rso/drand.lua b/map_gen/ores/rso/drand.lua deleted file mode 100644 index fc8e8973..00000000 --- a/map_gen/ores/rso/drand.lua +++ /dev/null @@ -1,269 +0,0 @@ ---[[------------------------------------ -RandomLua v0.3.1 -Pure Lua Pseudo-Random Numbers Generator -Under the MIT license. -copyright(c) 2011 linux-man ---]]------------------------------------ - -local _M = {} -local mod = math.fmod -local floor = math.floor -local abs = math.abs - -local function normalize(n) --keep numbers at (positive) 32 bits - return n % 0x80000000 -end - -local function bit_and(a, b) - local r = 0 - local m = 0 - for m = 0, 31 do - if (a % 2 == 1) and (b % 2 == 1) then r = r + 2^m end - if a % 2 ~= 0 then a = a - 1 end - if b % 2 ~= 0 then b = b - 1 end - a = a / 2 b = b / 2 - end - return normalize(r) -end - -local function bit_or(a, b) - local r = 0 - local m = 0 - for m = 0, 31 do - if (a % 2 == 1) or (b % 2 == 1) then r = r + 2^m end - if a % 2 ~= 0 then a = a - 1 end - if b % 2 ~= 0 then b = b - 1 end - a = a / 2 b = b / 2 - end - return normalize(r) -end - -local function bit_xor(a, b) - local r = 0 - local m = 0 - for m = 0, 31 do - if a % 2 ~= b % 2 then r = r + 2^m end - if a % 2 ~= 0 then a = a - 1 end - if b % 2 ~= 0 then b = b - 1 end - a = a / 2 b = b / 2 - end - return normalize(r) -end - -local function seed() - --return normalize(tonumber(tostring(os.time()):reverse())) - return normalize(os.time()) -end - ---Mersenne twister -mersenne_twister = {} -mersenne_twister.__index = mersenne_twister - -function mersenne_twister:randomseed(s) - if not s then s = seed() end - self.mt[0] = normalize(s) - for i = 1, 623 do - self.mt[i] = normalize(0x6c078965 * bit_xor(self.mt[i-1], floor(self.mt[i-1] / 0x40000000)) + i) - end -end - -function mersenne_twister:random(a, b) - local y - if self.index == 0 then - for i = 0, 623 do - --y = bit_or(floor(self.mt[i] / 0x80000000) * 0x80000000, self.mt[(i + 1) % 624] % 0x80000000) - y = self.mt[(i + 1) % 624] % 0x80000000 - self.mt[i] = bit_xor(self.mt[(i + 397) % 624], floor(y / 2)) - if y % 2 ~= 0 then self.mt[i] = bit_xor(self.mt[i], 0x9908b0df) end - end - end - y = self.mt[self.index] - y = bit_xor(y, floor(y / 0x800)) - y = bit_xor(y, bit_and(normalize(y * 0x80), 0x9d2c5680)) - y = bit_xor(y, bit_and(normalize(y * 0x8000), 0xefc60000)) - y = bit_xor(y, floor(y / 0x40000)) - self.index = (self.index + 1) % 624 - if not a then return y / 0x80000000 - elseif not b then - if a == 0 then return y - else return 1 + (y % a) - end - else - return a + (y % (b - a + 1)) - end -end - -function _M.twister(s) - local temp = {} - setmetatable(temp, mersenne_twister) - temp.mt = {} - temp.index = 0 - temp:randomseed(s) - return temp -end - ---Linear Congruential Generator -linear_congruential_generator = {} -linear_congruential_generator.__index = linear_congruential_generator - -function linear_congruential_generator:random(a, b) - local y = (self.a * self.x + self.c) % self.m - self.x = y - if not a then return y / 0x10000 - elseif not b then - if a == 0 then return y - else return 1 + (y % a) end - else - return a + (y % (b - a + 1)) - end -end - -function linear_congruential_generator:randomseed(s) - if not s then s = seed() end - self.x = normalize(s) -end - -function _M.lcg(s, r) - local temp = {} - setmetatable(temp, linear_congruential_generator) - temp.a, temp.c, temp.m = 1103515245, 12345, 0x10000 --from Ansi C - if r then - if r == 'nr' then temp.a, temp.c, temp.m = 1664525, 1013904223, 0x10000 --from Numerical Recipes. - elseif r == 'mvc' then temp.a, temp.c, temp.m = 214013, 2531011, 0x10000 end--from MVC - end - temp:randomseed(s) - return temp -end - --- Multiply-with-carry -multiply_with_carry = {} -multiply_with_carry.__index = multiply_with_carry - -function multiply_with_carry:random(a, b) - local m = self.m - local t = self.a * self.x + self.c - local y = t % m - self.x = y - self.c = floor(t / m) - if not a then return y / 0x10000 - elseif not b then - if a == 0 then return y - else return 1 + (y % a) end - else - local diff = 0 - if a == b then return a end - if a < 0 then - diff = abs(a) - a = a + diff - b = b + diff - end - return a + (y % (b - a + 1)) - diff - end -end - -function multiply_with_carry:randomseed(s) - if not s then s = seed() end - self.c = self.ic - self.x = normalize(s) -end - -function _M.mwc(s, r) - local temp = {} - setmetatable(temp, multiply_with_carry) - temp.a, temp.c, temp.m = 1103515245, 12345, 0x10000 --from Ansi C - if r then - if r == 'nr' then temp.a, temp.c, temp.m = 1664525, 1013904223, 0x10000 --from Numerical Recipes. - elseif r == 'mvc' then temp.a, temp.c, temp.m = 214013, 2531011, 0x10000 end--from MVC - end - temp.ic = temp.c - temp:randomseed(s) - return temp -end - -function _M.mwvc(s) - return _M.mwc(s, 'mvc') -end - -local B = 0x10000 - --- rough adaptation of Knuth float generator -function _M.krandom( seedobj, fVal1, fVal2 ) - local ma = seedobj.ma - local seed = seedobj.seed - local mj, mk - if seed < 0 or not ma then - ma = {} - seedobj.ma = ma - mj = normalize( seed ) - mj = mod( mj, B ) - ma[55] = mj - mk = 1 - for i = 1, 54 do - local ii = mod( 21 * i, 55 ) - ma[ii] = mk - mk = mj - mk - if mk < 0 then mk = mk + B end - mj = ma[ii] - end - for k = 1, 4 do - for i = 1, 55 do - ma[i] = ma[i] - ma[ 1 + mod( i + 30, 55) ] - if ma[i] < 0 then ma[i] = ma[i] + B end - end - end - seedobj.inext = 0 - seedobj.inextp = 31 - seedobj.seed = 1 - end -- if - local inext = seedobj.inext - local inextp = seedobj.inextp - inext = inext + 1 - if inext == 56 then inext = 1 end - seedobj.inext = inext - inextp = inextp + 1 - if inextp == 56 then inextp = 1 end - seedobj.inextp = inextp - mj = ma[ inext ] - ma[ inextp ] - if mj < 0 then mj = mj + B end - ma[ inext ] = mj - local temp_rand = mj / B - if fVal2 then - return floor( fVal1 + 0.5 + temp_rand * ( fVal2 - fVal1 ) ) - elseif fVal1 then - return floor( temp_rand * fVal1 ) + 1 - else - return temp_rand - end -end - --- Sys rand -sys_rand = {} -sys_rand.__index = sys_rand -function sys_rand:random(a, b) - local diff = 0 - if a and b and a == b then math.random(); return a end - if a and b then - if a < 0 then - diff = abs(a) - a = a + diff - b = b + diff - end - return math.random(a, b) - diff - end - if a and a == 0 then return floor(math.random() * 0x10000) end - if a then return math.random(a) end - return math.random() -end - -function sys_rand:randomseed(s) - -- ignore - return -end - -function _M.sys_rand(s) - local temp = {} - setmetatable(temp, sys_rand) - return temp -end - -return _M \ No newline at end of file diff --git a/map_gen/ores/rso/metaball.lua b/map_gen/ores/rso/metaball.lua deleted file mode 100644 index 2981a94c..00000000 --- a/map_gen/ores/rso/metaball.lua +++ /dev/null @@ -1,106 +0,0 @@ ---[[-- -Metaball implementation for LUA by Dark -For bruteforce usage, not efficient nor fast - -Force scales to from inf to 1 at R ---]]-- - -local math = require "utils.math" -local _M = {} -local sqrt = math.sqrt -local cos = math.cos -local sin = math.sin -local abs = math.abs -local zero_value = 0x80000000 - ---Classic ball -local MetaBall = {x=0, y=0, radius=0, goo=1, type="MetaBall"} -MetaBall.__index = MetaBall -_M.MetaBall=MetaBall - -function MetaBall:new(x, y, radius, goo) - goo = goo or 1 - return setmetatable({x=x, y=y, radius=radius, goo=goo}, MetaBall) -end - -function MetaBall:force(x, y) - --Calculate force at point x y - local force = sqrt( (x - self.x)^2 + (y - self.y)^2 ) - if force == 0 then return zero_value end - return (self.radius / force)^self.goo -end - ---Ellipse -local MetaEllipse = {x=0, y=0, radius=0, angle=0, x_scale=1, y_scale=1, type="MetaEllipse"} -MetaEllipse.__index = MetaEllipse -_M.MetaEllipse=MetaEllipse - -function MetaEllipse:new(x, y, radius, angle, x_scale, y_scale, goo) - angle = angle or 0 - x_scale = x_scale or 1 - y_scale = y_scale or 1 - goo = goo or 1 - cosa = cos(angle) - sina = sin(angle) - return setmetatable({x=x, y=y, radius=radius, angle=angle, x_scale=x_scale, y_scale=y_scale, goo=goo, cosa=cosa, sina=sina}, MetaEllipse) -end - -function MetaEllipse:force(x, y) - --Calculate force at point x y - local force = sqrt( (( (x - self.x)*self.cosa + (y - self.y)*self.sina )^2)/(self.x_scale) + - (( (y - self.y)*self.cosa - (x - self.x)*self.sina )^2)/(self.y_scale) ) - if force == 0 then return zero_value end - return (self.radius / force)^self.goo -end - ---SquareBalls -local MetaSquare = {x=0, y=0, radius=0, angle=0, x_scale=1, y_scale=1, type="MetaSquare"} -MetaSquare.__index = MetaSquare -_M.MetaSquare=MetaSquare - -function MetaSquare:new(x, y, radius, angle, x_scale, y_scale, goo) - angle = angle or 0 - x_scale = x_scale or 1 - y_scale = y_scale or 1 - goo = goo or 1 - cosa = cos(angle) - sina = sin(angle) - return setmetatable({x=x, y=y, radius=radius, angle=angle, x_scale=x_scale, y_scale=y_scale, goo=goo, cosa=cosa, sina=sina}, MetaSquare) -end - -function MetaSquare:force(x, y) - --Calculate force at point x y - local force = ( abs( (x - self.x)*self.cosa + (y - self.y)*self.sina )/self.x_scale + - abs( (y - self.y)*self.cosa - (x - self.x)*self.sina )/self.y_scale ) - if force == 0 then return zero_value end - return (self.radius / force)^self.goo -end - ---Donuts -local MetaDonut = {x=0, y=0, radius=0, angle=0, x_scale=1, y_scale=1, type="MetaDonut"} -MetaDonut.__index = MetaDonut -_M.MetaDonut=MetaDonut - -function MetaDonut:new(x, y, out_r, int_r, angle, x_scale, y_scale, goo) - angle = angle or 0 - x_scale = x_scale or 1 - y_scale = y_scale or 1 - goo = goo or 1 - cosa = cos(angle) - sina = sin(angle) - if int_r >= out_r then error("int_r >= out_r ("..int_r.." > "..out_r); return; end - local radius = out_r--(out_r - int_r)*0.5 - local radius2 = int_r--(radius2 + radius)*0.5 - return setmetatable({x=x, y=y, radius=radius, radius2=radius2, x_scale=x_scale, y_scale=y_scale, goo=goo, cosa=cosa, sina=sina}, MetaDonut) -end - -function MetaDonut:force(x, y) - --Calculate force at point x y - local force = abs(self.radius - sqrt( (( (x - self.x)*self.cosa + (y - self.y)*self.sina )^2)/(self.x_scale) + - (( (y - self.y)*self.cosa - (x - self.x)*self.sina )^2)/(self.y_scale) )) - if force == 0 then return zero_value end - return (self.radius2 / force)^self.goo - -end - -return _M diff --git a/map_gen/ores/rso/rso_config.lua b/map_gen/ores/rso/rso_config.lua deleted file mode 100644 index e5495164..00000000 --- a/map_gen/ores/rso/rso_config.lua +++ /dev/null @@ -1,56 +0,0 @@ -rso_debug_enabled = false - -region_size = 6 -- alternative mean to control how further away resources would be, default - 256 tiles or 8 chunks - -- each region is region_size*region_size chunks - -- each chunk is 32*32 tiles - -use_donut_shapes = false -- setting this to false will remove donuts from possible resource layouts - -starting_area_size = 1 -- starting area in regions, safe from random nonsense - -absolute_resource_chance = 0.65 -- chance to spawn an resource in a region -starting_richness_mult = 1 -- multiply starting area richness for resources -global_richness_mult = 1 -- multiply richness for all resources except starting area -global_size_mult = 1 -- multiply size for all ores, doesn't affect starting area - -absolute_enemy_chance = 5 -- chance to spawn enemies per sector (can be more then one base if spawned) -enemy_base_size_multiplier = 1 -- all base sizes will be multiplied by this - larger number means bigger bases - -multi_resource_active = false -- global switch for multi resource chances -multi_resource_richness_factor = 0.60 -- any additional resource is multiplied by this value times resources-1 -multi_resource_size_factor = 0.90 -multi_resource_chance_diminish = 0.6 -- diminishing effect factor on multi_resource_chance - -min_amount=350 -- default value for minimum amount of resource in single pile - -richness_distance_factor=1 -- exponent for richness distance factor calculation -fluid_richness_distance_factor = 0.6 -- exponent for richness distance factor calculation for fluids -size_distance_factor=0.05 -- exponent for size distance factor calculation - -deterministic = true -- set to false to use system for all decisions math.random -removeTrees = true --- mode is no longer used by generation process - it autodetects endless resources --- endless_resource_mode = false -- if true, the size of each resource is modified by the following modifier. Use with the endless resources mod. -endless_resource_mode_sizeModifier = 0.80 - --- This setting isn't used anywhere in the soft mod version of RSO -- OARC --- Just set it from Oarc's config.lua (look for ENEMY_EXPANSION) --- disableEnemyExpansion = false -- allows for disabling of in-game biter base building - --- Leaving these values present, they do nothing in the RedMew RSO --- use_RSO_biter_spawning = false -- enables spawning of biters controlled by RSO mod - less enemies around with more space between bases --- use_vanilla_biter_spawning = true -- enables using of vanilla spawning - --- biter_ratio_segment=3 --the ratio components determining how many biters to spitters will be spawned --- spitter_ratio_segment=1 --eg. 1 and 1 -> equal number of biters and spitters, 10 and 1 -> 10 times as many biters to spitters - -useEnemiesInPeaceMod = false -- additional override for peace mod detection - when set to true it will spawn enemies normally, needs to have enemies enabled in peace mod - --- Leave as true, and instead modify the rso_resource_config instead -ignoreMapGenSettings = true -- stops the default behaviour of reading map gen settings - -fluidResourcesFactor = 20 -- temporary factor for calculation of resource %-ages for fluids - -useResourceCollisionDetection = false -- enables avoidace calculations to reduce ores overlaping of each other -resourceCollisionDetectionRatio = 0.8 -- at least this much of ore field needs to be placable to spawn it -resourceCollisionFieldSkip = true -- determines if ore field should be skipped completely if placement based on ratio failed diff --git a/map_gen/ores/rso/rso_control.lua b/map_gen/ores/rso/rso_control.lua deleted file mode 100644 index 4c50e14c..00000000 --- a/map_gen/ores/rso/rso_control.lua +++ /dev/null @@ -1,1178 +0,0 @@ --- Credit to the oarc folks, and jvmguy for getting an RSO version working in scenarios --- To tie into this, maps must be generated with "NONE" for all resource ores -require("rso_config") -require("util") -require("rso_resource_config") -local Utils = require "utils.core" -local Game = require 'utils.game' -local math = require 'utils.math' - -local MB=require "metaball" -local drand = require 'drand' -local rng = drand.mwvc -if not deterministic then rng = drand.sys_rand end - -if not scenario then scenario = {} end -if not scenario.config then scenario.config = {} end -if not scenario.config.mapsettings then scenario.config.mapsettings = {} end - -scenario.config.mapSettings = { - RSO_TERRAIN_SEGMENTATION = "very-low", -- Frequency of water - RSO_WATER = "high", -- Size of water patches - RSO_PEACEFUL = false, -- Peaceful mode for biters/aliens - RSO_STARTING_AREA = "very-low" -} - --- math shortcuts -local floor = math.floor -local abs = math.abs -local cos = math.cos -local sin = math.sin -local pi = math.pi -local max = math.max - -local function rso_debug(str) - if rso_debug_enabled then - if (type(str) == "table") then - Game.get_player_by_index(1).print(serpent.dump(str)) - else - Game.get_player_by_index(1).print(str) - end - end -end - --- constants -local CHUNK_SIZE = 32 -local REGION_TILE_SIZE = CHUNK_SIZE*region_size -local MIN_BALL_DISTANCE = CHUNK_SIZE/6 -local P_BALL_SIZE_FACTOR = 0.7 -local N_BALL_SIZE_FACTOR = 0.95 -local NEGATIVE_MODIFICATOR = 123456 - -local meta_shapes = nil - -if use_donut_shapes then - meta_shapes = {MB.MetaEllipse, MB.MetaSquare, MB.MetaDonut} -else - meta_shapes = {MB.MetaEllipse, MB.MetaSquare} -end - --- local globals -local index_is_built = false -local max_allotment = 0 -local rgen = nil -local distance = util.distance -local spawner_probability_edge = 0 -- below this value a biter spawner, above/equal this value a spitter spawner -local invalidResources = {} -local config = nil -local configIndexed = nil - --- map gen settings mapping - -local startingAreaMultiplier = -{ - none = 0, - ["very-low"] = 0.25, - low = 0.5, - normal = 1, - high = 1.5, - ["very-high"] = 2, -} - -local frequencyAllotmentMultiplier = -{ - ["very-low"] = 0.5, - low = 0.75, - normal = 1, - high = 1.5, - ["very-high"] = 2, -} - -local sizeMultiplier = -{ - none = 0, - ["very-low"] = 0.5, - low = 0.75, - normal = 1, - high = 1.25, - ["very-high"] = 1.5, -} - -local richnessMultiplier = -{ - ["very-low"] = 0.125, - low = 0.25, - normal = 1, - high = 2, - ["very-high"] = 4, -} - -local entityFrequencyMultiplier = -{ - ["very-low"] = 0.25, - low = 0.5, - normal = 1, - high = 2, - ["very-high"] = 4, -} - -local entitySizeMultiplier = -{ - none = 0, - ["very-low"] = 0.5, - low = 0.75, - normal = 1, - high = 2, - ["very-high"] = 4, -} - ---[[ HELPER METHODS ]]-- - -local function normalize(n) --keep numbers at (positive) 32 bits - return floor(n) % 0x80000000 -end - -local function bearing(origin, dest) - -- finds relative angle - local xd = dest.x - origin.x - local yd = dest.y - origin.y - return math.atan2(xd, yd); -end - -local function str2num(s) - local num = 0 - for i=1,s:len() do - num=num + (s:byte(i) - 33)*i - end - return num -end - -local function mult_for_pos(pos) - local num = 0 - local x = pos.x - local y = pos.y - - if x == 0 then x = 0.5 end - if y == 0 then y = 0.5 end - if x < 0 then - x = abs(x) + NEGATIVE_MODIFICATOR - end - if y < 0 then - y = abs(y) + NEGATIVE_MODIFICATOR - end - - return drand.lcg(y, 'mvc'):random(0)*drand.lcg(x, 'nr'):random(0) -end - -local function rng_for_reg_pos(pos) - local rgen = rng(normalize(global.seed*mult_for_pos(pos))) - rgen:random() - rgen:random() - rgen:random() - return rgen -end - -local function rng_restricted_angle(restrictions) - local rng = rgen:random() - local x_scale, y_scale - local deformX = rgen:random() * 2 - 1 - local deformY = rgen:random() * 2 - 1 - - if restrictions=='xy' then - y_scale=1.0 + deformY*0.5 - x_scale=1.0 + deformX*0.5 - angle = rng*pi*2 - elseif restrictions=='x' then - y_scale=1.0 + deformY*0.6 - x_scale=1.0 + deformX*0.6 - angle = rng*pi/2 - pi/4 - elseif restrictions=='y' then - y_scale=1.0 + deformY*0.6 - x_scale=1.0 + deformX*0.6 - angle = rng*pi/2 + pi/2 - else - y_scale=1.0 + deformY*0.3 - x_scale=1.0 + deformX*0.3 - angle = rng*pi*2 - end - - return angle, x_scale, y_scale -end - -local function vary_by_percentage(x, p) - return x + (0.5 - rgen:random())*2*x*p -end - - -local function remove_trees(surface, x, y, x_size, y_size ) - local bb={{x - x_size, y - y_size}, {x + x_size, y + y_size}} - for _, entity in pairs(surface.find_entities_filtered{area = bb, type="tree"}) do - if entity.valid then - entity.destroy() - end - end -end - -local function find_intersection(surface, x, y) - -- try to get position in between of valid chunks by probing map - -- this may breaks determinism of generation, but so far it returned on first if - local gt = surface.get_tile - local restriction = '' - if gt(x + CHUNK_SIZE*2, y + CHUNK_SIZE*2).valid and gt(x - CHUNK_SIZE*2, y - CHUNK_SIZE*2).valid and gt(x + CHUNK_SIZE*2, y - CHUNK_SIZE*2).valid and gt(x - CHUNK_SIZE*2, y + CHUNK_SIZE*2).valid then - restriction = 'xy' - elseif gt(x + CHUNK_SIZE*2, y + CHUNK_SIZE*2).valid and gt(x + CHUNK_SIZE*2, y).valid and gt(x, y + CHUNK_SIZE*2).valid then - x=x + CHUNK_SIZE/2 - y=y + CHUNK_SIZE/2 - restriction = 'xy' - elseif gt(x + CHUNK_SIZE*2, y - CHUNK_SIZE*2).valid and gt(x + CHUNK_SIZE*2, y).valid and gt(x, y - CHUNK_SIZE*2).valid then - x=x + CHUNK_SIZE/2 - y=y - CHUNK_SIZE/2 - restriction = 'xy' - elseif gt(x - CHUNK_SIZE*2, y + CHUNK_SIZE*2).valid and gt(x - CHUNK_SIZE*2, y).valid and gt(x, y + CHUNK_SIZE*2).valid then - x=x - CHUNK_SIZE/2 - y=y + CHUNK_SIZE/2 - restriction = 'xy' - elseif gt(x - CHUNK_SIZE*2, y - CHUNK_SIZE*2).valid and gt(x - CHUNK_SIZE*2, y).valid and gt(x, y - CHUNK_SIZE*2).valid then - x=x - CHUNK_SIZE/2 - y=y - CHUNK_SIZE/2 - restriction = 'xy' - elseif gt(x + CHUNK_SIZE*2, y).valid then - x=x + CHUNK_SIZE/2 - restriction = 'x' - elseif gt(x - CHUNK_SIZE*2, y).valid then - x=x - CHUNK_SIZE/2 - restriction = 'x' - elseif gt(x, y + CHUNK_SIZE*2).valid then - y=y + CHUNK_SIZE/2 - restriction = 'y' - elseif gt(x, y - CHUNK_SIZE*2).valid then - y=y - CHUNK_SIZE/2 - restriction = 'y' - end - return x, y, restriction -end - -local function find_random_chunk(r_x, r_y) - local offset_x=rgen:random(region_size)-1 - local offset_y=rgen:random(region_size)-1 - local c_x=r_x*REGION_TILE_SIZE + offset_x*CHUNK_SIZE - local c_y=r_y*REGION_TILE_SIZE + offset_y*CHUNK_SIZE - return c_x, c_y -end - -local function is_same_region(c_x1, c_y1, c_x2, c_y2) - if not floor(c_x1/REGION_TILE_SIZE) == floor(c_x2/REGION_TILE_SIZE) then - return false - end - if not floor(c_y1/REGION_TILE_SIZE) == floor(c_y2/REGION_TILE_SIZE) then - return false - end - return true -end - -local function find_random_neighbour_chunk(ocx, ocy) - -- somewhat bruteforce and unoptimized - local x_dir = rgen:random(-1,1) - local y_dir = rgen:random(-1,1) - local ncx = ocx + x_dir*CHUNK_SIZE - local ncy = ocy + y_dir*CHUNK_SIZE - if is_same_region(ncx, ncy, ocx, ocy) then - return ncx, ncy - end - - ncx = ocx - x_dir*CHUNK_SIZE - ncy = ocy - y_dir*CHUNK_SIZE - if is_same_region(ncx, ncy, ocx, ocy) then - return ncx, ncy - end - - ncx = ocx - x_dir*CHUNK_SIZE - if is_same_region(ncx, ocy, ocx, ocy) then - return ncx, ocy - end - - ncy = ocy - y_dir*CHUNK_SIZE - if is_same_region(ocx, ncy, ocx, ocy) then - return ocx, ncy - end - - return ocx, ocy -end - -local function isInStartingArea( regionX, regionY ) - for idx, pos in pairs( global.startingAreas ) do - - local adjustedX = regionX - pos.x / REGION_TILE_SIZE - local adjustedY = regionY - pos.y / REGION_TILE_SIZE - if ((adjustedX * adjustedX + adjustedY * adjustedY) <= starting_area_size * starting_area_size) then - return true - end - end - - return false -end - --- modifies the resource size - only used in endless_resource_mode -local function modify_resource_size(resourceName, resourceSize, startingArea) - - if not startingArea then - resourceSize = math.ceil(resourceSize * global_size_mult) - end - - resourceEntity = game.entity_prototypes[resourceName] - return resourceSize -end - ---[[ SPAWN METHODS ]]-- - -local locationOrder = -{ - { x = 0, y = 0 }, - { x = -1, y = 0 }, - { x = 1, y = 0 }, - { x = 0, y = -1 }, - { x = 0, y = 1 }, - { x = -1, y = -1 }, - { x = 1, y = -1 }, - { x = -1, y = 1 }, - { x = 1, y = 1 } -} - ---[[ entity-field ]]-- -local function spawn_resource_ore(surface, rname, pos, size, richness, startingArea, restrictions) - -- blob generator, centered at pos, size controls blob diameter - restrictions = restrictions or '' - rso_debug("Entering spawn_resource_ore "..rname.." at:"..pos.x..","..pos.y.." size:"..size.." richness:"..richness.." isStart:"..tostring(startingArea).." restrictions:"..restrictions) - - size = modify_resource_size(rname, size, startingArea) - local radius = size / 2 -- to radius - - local p_balls={} - local n_balls={} - local MIN_BALL_DISTANCE = math.min(MIN_BALL_DISTANCE, radius/2) - - local maxPradius = 0 - local outside = { xmin = 1e10, xmax = -1e10, ymin = 1e10, ymax = -1e10 } - local inside = { xmin = 1e10, xmax = -1e10, ymin = 1e10, ymax = -1e10 } - - local function adjustRadius(radius, scaleX, scaleY, up) - return radius - end - - local function updateRect(rect, x, y, radius) - rect.xmin = math.min(rect.xmin, x - radius) - rect.xmax = math.max(rect.xmax, x + radius) - rect.ymin = math.min(rect.ymin, y - radius) - rect.ymax = math.max(rect.ymax, y + radius) - end - - local function updateRects(x, y, radius, scaleX, scaleY) - local adjustedRadius = adjustRadius(radius, scaleX, scaleY, true) - local radiusMax = adjustedRadius * 3 -- arbitrary multiplier - needs to be big enough to not cut any metaballs - updateRect(outside, x, y, radiusMax) - updateRect(inside, x, y, adjustedRadius) - end - - local function generate_p_ball() - local angle, x_scale, y_scale, x, y, b_radius, shape - angle, x_scale, y_scale=rng_restricted_angle(restrictions) - local dev = radius / 2 + rgen:random() * radius / 4--math.min(CHUNK_SIZE/3, radius*1.5) - local dev_x, dev_y = pos.x, pos.y - x = rgen:random(-dev, dev)+dev_x - y = rgen:random(-dev, dev)+dev_y - if p_balls[#p_balls] and Utils.distance(p_balls[#p_balls], {x=x, y=y}) < MIN_BALL_DISTANCE then - local new_angle = bearing(p_balls[#p_balls], {x=x, y=y}) - rso_debug("Move ball old xy @ "..x..","..y) - x=(cos(new_angle)*MIN_BALL_DISTANCE) + x - y=(sin(new_angle)*MIN_BALL_DISTANCE) + y - rso_debug("Move ball new xy @ "..x..","..y) - end - - if #p_balls == 0 then - b_radius = ( 3 * radius / 4 + rgen:random() * radius / 4) -- * (P_BALL_SIZE_FACTOR^#p_balls) - else - b_radius = ( radius / 4 + rgen:random() * radius / 2) -- * (P_BALL_SIZE_FACTOR^#p_balls) - end - - - if #p_balls > 0 then - local tempRect = table.deepcopy(inside) - updateRect(tempRect, x, y, adjustRadius(b_radius, x_scale, y_scale)) - local rectSize = math.max(tempRect.xmax - tempRect.xmin, tempRect.ymax - tempRect.ymin) - local targetSize = size * 1.25 - rso_debug("Rect size "..rectSize.." targetSize "..targetSize) - if rectSize > targetSize then - local widthLeft = (targetSize - (inside.xmax - inside.xmin)) - local heightLeft = (targetSize - (inside.ymax - inside.ymin)) - local widthMod = math.min(x - inside.xmin, inside.xmax - x) - local heightMod = math.min(y - inside.ymin, inside.ymax - y) - local radiusBackup = b_radius - b_radius = math.min(widthLeft + widthMod, heightLeft + heightMod) - b_radius = adjustRadius(b_radius, x_scale, y_scale, false) - rso_debug("Reduced ball radius from "..radiusBackup.." to "..b_radius.." widthLeft:"..widthLeft.." heightLeft:"..heightLeft.." widthMod:"..widthMod.." heightMod:"..heightMod) - end - end - - if b_radius < 2 and #p_balls == 0 then - b_radius = 2 - end - - if b_radius > 0 then - - maxPradius = math.max(maxPradius, b_radius) - shape = meta_shapes[rgen:random(1,#meta_shapes)] - local radiusText = "" - if shape.type == "MetaDonut" then - local inRadius = b_radius / 4 + b_radius / 2 * rgen:random() - radiusText = " inRadius:"..inRadius - p_balls[#p_balls+1] = shape:new(x, y, b_radius, inRadius, angle, x_scale, y_scale, 1.1) - else - p_balls[#p_balls+1] = shape:new(x, y, b_radius, angle, x_scale, y_scale, 1.1) - end - updateRects(x, y, b_radius, x_scale, y_scale) - - rso_debug("P+Ball "..shape.type.." @ "..x..","..y.." radius: "..b_radius..radiusText.." angle: "..math.deg(angle).." scale: "..x_scale..", "..y_scale) - end - end - - local function generate_n_ball(i) - local angle, x_scale, y_scale, x, y, b_radius, shape - angle, x_scale, y_scale=rng_restricted_angle('xy') - if p_balls[i] then - local new_angle = p_balls[i].angle + pi*rgen:random(0,1) + (rgen:random()-0.5)*pi/2 - local dist = p_balls[i].radius - x=(cos(new_angle)*dist) + p_balls[i].x - y=(sin(new_angle)*dist) + p_balls[i].y - angle = p_balls[i].angle + pi/2 + (rgen:random()-0.5)*pi*2/3 - else - x = rgen:random(-radius, radius)+pos.x - y = rgen:random(-radius, radius)+pos.y - end - - if p_balls[i] then - b_radius = (p_balls[i].radius / 4 + rgen:random() * p_balls[i].radius / 2) -- * (N_BALL_SIZE_FACTOR^#n_balls) - else - b_radius = (radius / 4 + rgen:random() * radius / 2) -- * (N_BALL_SIZE_FACTOR^#n_balls) - end - - if b_radius < 1 then - b_radius = 1 - end - - shape = meta_shapes[rgen:random(1,#meta_shapes)] - local radiusText = "" - if shape.type == "MetaDonut" then - local inRadius = b_radius / 4 + b_radius / 2 * rgen:random() - radiusText = " inRadius:"..inRadius - n_balls[#n_balls+1] = shape:new(x, y, b_radius, inRadius, angle, x_scale, y_scale, 1.15) - else - n_balls[#n_balls+1] = shape:new(x, y, b_radius, angle, x_scale, y_scale, 1.15) - end - -- updateRects(x, y, b_radius, x_scale, y_scale) -- should not be needed here - only positive ball can generate ore - rso_debug("N-Ball "..shape.type.." @ "..x..","..y.." radius: "..b_radius..radiusText.." angle: "..math.deg(angle).." scale: "..x_scale..", "..y_scale) - end - - local function calculate_force(x,y) - local p_force = 0 - local n_force = 0 - for _,ball in ipairs(p_balls) do - p_force = p_force + ball:force(x,y) - end - for _,ball in ipairs(n_balls) do - n_force = n_force + ball:force(x,y) - end - local totalForce = 0 - if p_force > n_force then - totalForce = 1 - 1/(p_force - n_force) - end - --rso_debug("Force at "..x..","..y.." p:"..p_force.." n:"..n_force.." result:"..totalForce) - --return (1 - 1/p_force) - n_force - return totalForce - end - - local max_p_balls = 2 - local min_amount = config[rname].min_amount or min_amount - if restrictions == 'xy' then - max_p_balls = 3 - end - - radius = math.min(radius, 2*CHUNK_SIZE) - - local force - -- generate blobs - for i=1,max_p_balls do - generate_p_ball() - end - - for i=1,rgen:random(1, #p_balls) do - generate_n_ball(i) - end - - - local _total = 0 - local oreLocations = {} - local forceTotal = 0 - - -- fill the map - for y=outside.ymin, outside.ymax do - - for x=outside.xmin, outside.xmax do - force = calculate_force(x, y) - if force > 0 then - oreLocations[#oreLocations + 1] = {x = x, y = y, force = force, valid = false} - forceTotal = forceTotal + force - end - end - end - - local validCount, resOffsetX, resOffsetY, ratio - - for _,locationOffset in ipairs(locationOrder) do - validCount = 0 - resOffsetX = locationOffset.x * CHUNK_SIZE - resOffsetY = locationOffset.y * CHUNK_SIZE - - for _, location in ipairs(oreLocations) do - - local newX = location.x + resOffsetX - local newY = location.y + resOffsetY - location.valid = false - if surface.can_place_entity{name = rname, position = {x = newX,y = newY}} then - location.valid = true - validCount = validCount + 1 - end - end - - ratio = 0 - - if validCount > 0 then - ratio = validCount / #oreLocations - end - - rso_debug("Valid ratio ".. ratio) - - if not useResourceCollisionDetection then - break - end - - if ratio > resourceCollisionDetectionRatio then - break - elseif resourceCollisionFieldSkip then -- in case no valid ratio was found we skip the field completely - validCount = 0 - end - end - - if validCount > 0 then - local rectSize = ((inside.xmax - inside.xmin) + (inside.ymax - inside.ymin)) / 2 - - local sizeMultiplier = rectSize ^ 0.6 - local minSize = richness * 5 * sizeMultiplier - local maxSize = richness * 10 * sizeMultiplier - local approxDepositSize = rgen:random(minSize, maxSize) - - approxDepositSize = approxDepositSize - validCount * min_amount - - if approxDepositSize < 0 then - approxDepositSize = 100 * validCount - end - - local forceFactor = approxDepositSize / forceTotal - - -- don't create very dense resources in starting area - another field will be generated - if startingArea and forceFactor > 4000 then - forceFactor = rgen:random(3000, 4000) - end - - rso_debug( "Force total:"..forceTotal.." sizeMin:"..minSize.." sizeMax:"..maxSize.." factor:"..forceFactor.." location#:"..validCount.." rectSize:"..rectSize.." sizeMultiplier:"..sizeMultiplier) - local richnessMultiplier = global_richness_mult - - if startingArea then - richnessMultiplier = starting_richness_mult - end - - -- infinite ore handling for Angels Ores mod - local spawnName = rname - - for _,location in pairs(oreLocations) do - if location.valid then - - local amount = floor(( forceFactor * location.force + min_amount ) * richnessMultiplier) - - if amount > 1e9 then - amount = 1e9 - end - - _total = _total + amount - - spawnName = rname - - if amount > 0 then - surface.create_entity{name = spawnName, - position = {location.x + resOffsetX,location.y + resOffsetY}, - force = game.forces.neutral, - amount = amount} - if removeTrees then - remove_trees(surface, location.x + resOffsetX, location.y + resOffsetY, 1, 1) - end - end - end - end - - end - - if rso_debug_enabled then - rso_debug("Total amount: ".._total) - rso_debug("Leaving spawn_resource_ore") - end - return _total -end - ---[[ entity-liquid ]]-- -local function spawn_resource_liquid(surface, rname, pos, size, richness, startingArea, restrictions) - restrictions = restrictions or '' - rso_debug("Entering spawn_resource_liquid "..rname.." "..pos.x..","..pos.y.." "..size.." "..richness.." "..tostring(startingArea).." "..restrictions) - local _total = 0 - local max_radius = rgen:random()*CHUNK_SIZE/2 + CHUNK_SIZE - - richness = ( 0.75 + rgen:random() / 2 ) * richness * size - - resourceEntity = game.entity_prototypes[rname] - - - local total_share = 0 - local avg_share = 1/size - local angle = rgen:random()*pi*2 - local saved = 0 - while total_share < 1 do - local new_share = vary_by_percentage(avg_share, 0.25) - if new_share + total_share > 1 then - new_share = 1 - total_share - end - - total_share = new_share + total_share - if new_share < avg_share/10 then - -- too small - break - end - local amount = floor(richness*new_share) + saved - - local richnessMultiplier = global_richness_mult - - if startingArea then - richnessMultiplier = starting_richness_mult - end - - --if amount >= game.entity_prototypes[rname].minimum then - if amount >= config[rname].minimum_amount then - saved = 0 - for try=1,5 do - local dist = rgen:random()*(max_radius - max_radius*0.1) - angle = angle + pi/4 + rgen:random()*pi/2 - local x, y = pos.x + cos(angle)*dist, pos.y + sin(angle)*dist - if surface.can_place_entity{name = rname, position = {x,y}} then - rso_debug("@ "..x..","..y.." amount: "..amount.." new_share: "..new_share.." try: "..try) - amount = floor(amount * richnessMultiplier) - - if amount > 1e9 then - amount = 1e9 - end - - _total = _total + amount - - if amount > 0 then - surface.create_entity{name = rname, - position = {x,y}, - force = game.forces.neutral, - amount = amount, - direction = rgen:random(4)} - end - break - elseif not startingArea then -- we don't want to make ultra rich nodes in starting area - failing to make them will add second spawn in different location - entities = surface.find_entities_filtered{area = {{x-2.75, y-2.75}, {x+2.75, y+2.75}}, name=rname} - if entities and #entities > 0 then - _total = _total + amount - for k, ent in pairs(entities) do - ent.amount = ent.amount + floor(amount/#entities) - end - break - end - end - end - else - saved = amount - end - end - rso_debug("Total amount: ".._total) - rso_debug("Leaving spawn_resource_liquid") - return _total -end - ---[[ EVENT/INIT METHODS ]]-- - -local function spawn_starting_resources( surface, index ) - - if global.startingAreas[index].spawned then return end - if surface.map_gen_settings.starting_area == "none" and not ignoreMapGenSettings then return end -- starting area disabled by map gen - if starting_area_size < 0.1 then return end -- skip spawning if starting area is to small - - local position = global.startingAreas[index] - - rso_debug(position) - rgen = rng_for_reg_pos( position ) - local status = true - rso_debug(configIndexed) - - for index,v in ipairs(configIndexed) do - if v.starting then - local prob = rgen:random() -- probability that this resource is spawned - rso_debug("starting resource probability rolled "..prob) - if v.starting.probability > 0 and prob <= v.starting.probability then - local total = 0 - local radius = 25 - local min_threshold = 0 - - if v.type == "resource-ore" then - min_threshold = v.starting.richness * rgen:random(5, 10) -- lets make sure that there is at least 10-15 times starting richness ore at start - elseif v.type == "resource-liquid" then - min_threshold = v.starting.richness * 0.5 * v.starting.size - end - rso_debug("Starting threshold: " .. min_threshold) - - while (radius < 200) and (total < min_threshold) do - local angle = rgen:random() * pi * 2 - local dist = rgen:random() * 30 + radius * 2 - local pos = { x = floor(cos(angle) * dist) + position.x, y = floor(sin(angle) * dist) + position.y } - if v.type == "resource-ore" then - total = total + spawn_resource_ore(surface, v.name, pos, v.starting.size, v.starting.richness, true) - elseif v.type == "resource-liquid" then - total = total + spawn_resource_liquid(surface, v.name, pos, v.starting.size, v.starting.richness, true) - end - radius = radius + 10 - end - if total < min_threshold then - status = false - end - end - end - end - - global.startingAreas[index].spawned = true -end - -local function modifyMinMax(value, mod) - value.min = math.round( value.min * mod ) - value.max = math.round( value.max * mod ) -end - -local function prebuild_config_data(surface) - if index_is_built then return false end - - local mapGenSettings = nil - - if not ignoreMapGenSettings then - mapGenSettings = surface.map_gen_settings - end - local autoPlaceSettings = nil - if mapGenSettings then - autoPlaceSettings = mapGenSettings.autoplace_controls - end - - configIndexed = {} - -- build additional indexed array to the associative array - for res_name, res_conf in pairs(config) do - if res_conf.valid then -- only add valid resources - res_conf.name = res_name - - local settingsForResource = nil - local isEntity = (res_conf.type == "entity") - local addResource = true - - local autoplaceName = res_name - - if res_conf.autoplace_name then - autoplaceName = res_conf.autoplace_name - end - - if autoPlaceSettings then - settingsForResource = autoPlaceSettings[autoplaceName] - end - - if settingsForResource then - local allotmentMod = nil - local sizeMod = nil - if isEntity then - allotmentMod = entityFrequencyMultiplier[settingsForResource.frequency] - sizeMod = entitySizeMultiplier[settingsForResource.size] - else - allotmentMod =frequencyAllotmentMultiplier[settingsForResource.frequency] - sizeMod = sizeMultiplier[settingsForResource.size] - end - - local richnessMod = richnessMultiplier[settingsForResource.richness] - - rso_debug(res_name .. " allotment mod " .. allotmentMod .. " size mod " .. sizeMod .. " richness mod " .. richnessMod ) - - if allotmentMod then - if isEntity then - res_conf.absolute_probability = res_conf.absolute_probability * allotmentMod - rso_debug("Entity chance modified to "..res_conf.absolute_probability) - else - res_conf.allotment = math.round( res_conf.allotment * allotmentMod ) - end - end - - if sizeMod ~= nil and sizeMod == 0 then - addResource = false - end - - if sizeMod then - modifyMinMax(res_conf.size, sizeMod) - - if res_conf.starting then - res_conf.starting.size = math.round( res_conf.starting.size * sizeMod ) - end - - if isEntity then - if res_conf.sub_spawn_size then - modifyMinMax(res_conf.sub_spawn_size, sizeMod) - end - modifyMinMax(res_conf.spawns_per_region, sizeMod) - end - end - - if richnessMod then - if type == "resource-ore" then - res_conf.richness = math.round( res_conf.richness * richnessMod ) - elseif type == "resource-liquid" then - modifyMinMax(res_conf.richness, richnessMod) - end - - if res_conf.starting then - res_conf.starting.richness = math.round( res_conf.starting.richness * richnessMod ) - end - end - end - - if addResource then - configIndexed[#configIndexed + 1] = res_conf - if res_conf.multi_resource and multi_resource_active then - local new_list = {} - for sub_res_name, allotment in pairs(res_conf.multi_resource) do - if config[sub_res_name] and config[sub_res_name].valid then - new_list[#new_list+1] = {name = sub_res_name, allotment = allotment} - end - end - table.sort(new_list, function(a, b) return a.name < b.name end) - res_conf.multi_resource = new_list - else - res_conf.multi_resource_chance = nil - end - end - end - end - - table.sort(configIndexed, function(a, b) return a.name < b.name end) - - local pr=0 - for index,v in pairs(config) do - if v.along_resource_probability then - v.along_resource_probability_range={min=pr, max=pr+v.along_resource_probability} - pr=pr+v.along_resource_probability - end - if v.allotment and v.allotment > 0 then - v.allotment_range={min=max_allotment, max=max_allotment+v.allotment} - max_allotment=max_allotment+v.allotment - end - end - - if mapGenSettings and mapGenSettings.starting_area then - local multiplier = startingAreaMultiplier[mapGenSettings.starting_area] - if multiplier ~= nil then - starting_area_size = starting_area_size * multiplier - rso_debug("Starting area "..starting_area_size) - end - end - - index_is_built = true -end - - -local function checkConfigForInvalidResources() - --make sure that every resource in the config is actually available. - --call this function, before the auxiliary config is prebuilt! - if index_is_built then return end - - local prototypes = game.entity_prototypes - - for resourceName, resourceConfig in pairs(config) do - if prototypes[resourceName] or resourceConfig.type == "entity" then - resourceConfig.valid = true - else - -- resource was in config, but it doesn't exist in game files anymore - mark it invalid - resourceConfig.valid = false - - table.insert(invalidResources, "Resource not available: " .. resourceName) - rso_debug("Resource not available: " .. resourceName) - end - - if resourceConfig.valid and resourceConfig.type ~= "entity" then - if prototypes[resourceName].autoplace_specification == nil then - resourceConfig.valid = false - rso_debug("Resource "..resourceName.." invalidated - autoplace not present") - end - end - end -end - -local function roll_region(c_x, c_y) - --in what region is this chunk? - local r_x=floor(c_x/REGION_TILE_SIZE) - local r_y=floor(c_y/REGION_TILE_SIZE) - local r_data = nil - rso_debug("Region rolling...") - --don't spawn stuff in starting area - if isInStartingArea( c_x/REGION_TILE_SIZE, c_y/REGION_TILE_SIZE ) then - return false - end - - if global.regions[r_x] and global.regions[r_x][r_y] then - r_data = global.regions[r_x][r_y] - else - --if this chunk is the first in its region to be generated - if not global.regions[r_x] then global.regions[r_x] = {} end - global.regions[r_x][r_y]={} - r_data = global.regions[r_x][r_y] - rgen = rng_for_reg_pos{x=r_x,y=r_y} - - local rollCount = math.ceil(#configIndexed / 10) - 1 -- 0 based counter is more convenient here - rollCount = math.min(rollCount, 3) - - for rollNumber = 0,rollCount do - - local resourceChance = absolute_resource_chance - rollNumber * 0.1 - --absolute chance to spawn resource - local abct = rgen:random() - rso_debug("Rolling resource "..abct.." against "..resourceChance.." roll "..rollNumber) - if abct <= resourceChance then - local res_type=rgen:random(1, max_allotment) - for index,v in ipairs(configIndexed) do - if v.allotment_range and ((res_type >= v.allotment_range.min) and (res_type <= v.allotment_range.max)) then - rso_debug("Rolled primary resource "..v.name.." with res_type="..res_type.." @ "..r_x..","..r_y) - local num_spawns=rgen:random(v.spawns_per_region.min, v.spawns_per_region.max) - local last_spawn_coords = {} - local along_ - for i=1,num_spawns do - local c_x, c_y = find_random_chunk(r_x, r_y) - if not r_data[c_x] then r_data[c_x] = {} end - if not r_data[c_x][c_y] then r_data[c_x][c_y] = {} end - local c_data = r_data[c_x][c_y] - c_data[#c_data+1]={v.name, rollNumber} - last_spawn_coords[#last_spawn_coords+1] = {c_x, c_y} - rso_debug("Rolled primary chunk "..v.name.." @ "..c_x.."."..c_y.." reg: "..r_x..","..r_y) - -- Along resource spawn, only once - if i == 1 then - local am_roll = rgen:random() - for index,vv in ipairs(configIndexed) do - if vv.along_resource_probability_range and am_roll >= vv.along_resource_probability_range.min and am_roll <= vv.along_resource_probability_range.max then - c_data = r_data[c_x][c_y] - c_data[#c_data+1]={vv.name, rollNumber} - rso_debug("Rolled along "..vv.name.." @ "..c_x.."."..c_y.." reg: "..r_x..","..r_y) - end - end - end - end - -- roll multiple resources in same region - local deep=0 - while v.multi_resource_chance and rgen:random() <= v.multi_resource_chance*(multi_resource_chance_diminish^deep) do - deep = deep + 1 - local max_allotment = 0 - for index,sub_res in pairs(v.multi_resource) do max_allotment=max_allotment+sub_res.allotment end - - local res_type=rgen:random(1, max_allotment) - local min=0 - for _, sub_res in pairs(v.multi_resource) do - if (res_type >= min) and (res_type <= sub_res.allotment + min) then - local last_coords = last_spawn_coords[rgen:random(1, #last_spawn_coords)] - local c_x, c_y = find_random_neighbour_chunk(last_coords[1], last_coords[2]) -- in same as primary resource chunk - if not r_data[c_x] then r_data[c_x] = {} end - if not r_data[c_x][c_y] then r_data[c_x][c_y] = {} end - local c_data = r_data[c_x][c_y] - c_data[#c_data+1]={sub_res.name, deep} - rso_debug("Rolled multiple "..sub_res.name..":"..deep.." with res_type="..res_type.." @ "..c_x.."."..c_y.." reg: "..r_x.."."..r_y) - break - else - min = min + sub_res.allotment - end - end - end - break - end - end - - end - end - -- roll for absolute_probability - this rolls the enemies - - for index,v in ipairs(configIndexed) do - if v.absolute_probability then - local prob_factor = 1 - if v.probability_distance_factor then - prob_factor = math.min(v.max_probability_distance_factor, v.probability_distance_factor^Utils.distance({x=0,y=0},{x=r_x,y=r_y})) - end - local abs_roll = rgen:random() - if abs_roll 10 then - global.startingAreas[1].spawned = true - end - end - - rso_debug("Starting resources...") - spawn_starting_resources(surface, 1 ) - - initDone = true - - if surface.map_gen_settings.autoplace_controls["iron-ore"].size ~= "none" then - Game.get_player_by_index(1).print("RSO WARNING - VANILLA iron-ore GEN IS NOT DISABLED!") - end - if surface.map_gen_settings.autoplace_controls["copper-ore"].size ~= "none" then - Game.get_player_by_index(1).print("RSO WARNING - VANILLA copper-ore GEN IS NOT DISABLED!") - end - if surface.map_gen_settings.autoplace_controls["uranium-ore"].size ~= "none" then - Game.get_player_by_index(1).print("RSO WARNING - VANILLA uranium-ore GEN IS NOT DISABLED!") - end - if surface.map_gen_settings.autoplace_controls["crude-oil"].size ~= "none" then - Game.get_player_by_index(1).print("RSO WARNING - VANILLA crude-oil GEN IS NOT DISABLED!") - end - if surface.map_gen_settings.autoplace_controls["enemy-base"].size ~= "none" then - -- Not a problem, as this RSO does not gen biters --- Game.get_player_by_index(1).print("RSO WARNING - VANILLA enemy-base GEN IS NOT DISABLED!") - end - if surface.map_gen_settings.autoplace_controls["stone"].size ~= "none" then - Game.get_player_by_index(1).print("RSO WARNING - VANILLA stone GEN IS NOT DISABLED!") - end - if surface.map_gen_settings.autoplace_controls["coal"].size ~= "none" then - Game.get_player_by_index(1).print("RSO WARNING - VANILLA coal GEN IS NOT DISABLED!") - end - end - -end - -local Event = require 'utils.event' - -local function run_ores_module(event) -- AKA RSO_ChunkGenerated(event) - local c_x = event.area.left_top.x - local c_y = event.area.left_top.y - - RSO_init() - - roll_region(c_x, c_y) - roll_chunk(event.surface, c_x, c_y) - end - -Event.add(defines.events.on_chunk_generated, run_ores_module) diff --git a/map_gen/ores/rso/rso_resource_config.lua b/map_gen/ores/rso/rso_resource_config.lua deleted file mode 100644 index f322e9cf..00000000 --- a/map_gen/ores/rso/rso_resource_config.lua +++ /dev/null @@ -1,125 +0,0 @@ - -local function fillVanillaConfig() - - config["iron-ore"] = { - type="resource-ore", - - -- general spawn params - allotment=100, -- how common resource is - spawns_per_region={min=1, max=2}, --number of chunks - richness=12000, -- resource_ore has only one richness value - resource-liquid has min/max - - size={min=20, max=50}, -- rough radius of area, too high value can produce square shaped areas - min_amount=500, - - -- resource provided at starting location - -- probability: 1 = 100% chance to be in starting area - -- 0 = resource is not in starting area - starting={richness=20000, size=35, probability=1}, - - multi_resource_chance=0.20, -- absolute value - multi_resource={ - ["iron-ore"] = 2, -- ["resource_name"] = allotment - ['copper-ore'] = 4, - ["coal"] = 4, - ["stone"] = 4, - } - } - - config["copper-ore"] = { - type="resource-ore", - - allotment=90, - spawns_per_region={min=1, max=2}, - richness=11000, - size={min=20, max=50}, - min_amount=500, - - starting={richness=12000, size=25, probability=1}, - - multi_resource_chance=0.20, - multi_resource={ - ["iron-ore"] = 4, - ['copper-ore'] = 2, - ["coal"] = 4, - ["stone"] = 4, - } - } - - config["coal"] = { - type="resource-ore", - - allotment=80, - - spawns_per_region={min=1, max=1}, - size={min=15, max=25}, - richness=8000, - min_amount=500, - - starting={richness=6000, size=20, probability=1}, - - multi_resource_chance=0.75, - multi_resource={ - ["crude-oil"] = 1, - ["iron-ore"] = 3, - ['copper-ore'] = 3, - } - } - - config["stone"] = { - type="resource-ore", - - allotment=60, - spawns_per_region={min=1, max=1}, - richness=5000, - size={min=15, max=20}, - min_amount=250, - - starting={richness=5000, size=16, probability=1}, - - multi_resource_chance=0.30, - multi_resource={ - ["coal"] = 4, - ["iron-ore"] = 3, - ['copper-ore'] = 3, - } - } - - config["uranium-ore"] = { - type="resource-ore", - - allotment=40, - spawns_per_region={min=1, max=1}, - richness=4000, - size={min=10, max=15}, - min_amount=500, - - starting={richness=2000, size=10, probability=1}, - } - - config["crude-oil"] = { - type="resource-liquid", - minimum_amount=200000, - allotment=70, - spawns_per_region={min=1, max=1}, - richness={min=200000, max=300000}, -- richness per resource spawn - size={min=5, max=20}, - - starting={richness=400000, size=3, probability=1}, - - multi_resource_chance=0.20, - multi_resource={ - ["coal"] = 4, - ["uranium-ore"] = 1, - } - } -end - -function loadResourceConfig() - - config={} - - fillVanillaConfig() - - return config -end diff --git a/map_gen/ores/tiny_ores.lua b/map_gen/ores/tiny_ores.lua index 45c85700..58cd140c 100644 --- a/map_gen/ores/tiny_ores.lua +++ b/map_gen/ores/tiny_ores.lua @@ -1,4 +1,5 @@ local Global = require 'utils.global' +local RS = require 'map_gen.shared.redmew_surface' local table = require 'utils.table' local seed = nil -- Set to number to force seed. @@ -11,7 +12,7 @@ Global.register_init( {}, function(tbl) tbl.generator = game.create_random_generator() - tbl.seed = seed or game.surfaces[1].map_gen_settings.seed + tbl.seed = seed or RS.get_surface().map_gen_settings.seed end, function(tbl) generator = tbl.generator diff --git a/map_gen/presets/ContraSpiral.lua b/map_gen/presets/ContraSpiral.lua index 13691e63..b28c5a45 100644 --- a/map_gen/presets/ContraSpiral.lua +++ b/map_gen/presets/ContraSpiral.lua @@ -1,9 +1,9 @@ local b = require "map_gen.shared.builders" local pic = require "map_gen.data.presets.CSrMap" -local pic = b.decompress(pic) +pic = b.decompress(pic) local map = b.picture(pic) -local map = b.single_pattern(map, pic.width, pic.height) +map = b.single_pattern(map, pic.width, pic.height) -return map \ No newline at end of file +return map diff --git a/map_gen/presets/GoT.lua b/map_gen/presets/GoT.lua index 2c764965..8459688d 100644 --- a/map_gen/presets/GoT.lua +++ b/map_gen/presets/GoT.lua @@ -1,9 +1,9 @@ local b = require "map_gen.shared.builders" local pic = require "map_gen.data.presets.GoT" -local pic = b.decompress(pic) +pic = b.decompress(pic) local shape = b.picture(pic) -local shape = b.translate(shape, 752, -408) +shape = b.translate(shape, 752, -408) return shape diff --git a/map_gen/presets/UK.lua b/map_gen/presets/UK.lua index a13a5ff7..68cca925 100644 --- a/map_gen/presets/UK.lua +++ b/map_gen/presets/UK.lua @@ -1,7 +1,7 @@ local b = require "map_gen.shared.builders" local pic = require "map_gen.data.presets.UK" -local pic = b.decompress(pic) +pic = b.decompress(pic) local map = b.picture(pic) -- this changes the size of the map diff --git a/map_gen/presets/bacon_islands.lua b/map_gen/presets/bacon_islands.lua index 8031ce9c..fd727b0a 100644 --- a/map_gen/presets/bacon_islands.lua +++ b/map_gen/presets/bacon_islands.lua @@ -41,7 +41,6 @@ local ham = b.picture(require 'map_gen.data.presets.ham') pig = b.scale(pig, 64 / 320) ham = b.scale(ham, 64 / 127) -local ores_patch = b.circle(16) local function value(base, mult, pow) return function(x, y) local d = math.sqrt(x * x + y * y) @@ -97,7 +96,7 @@ for r = 1, 50 do end local i = random_ore:next_int(1, ore_t) - index = table.binary_search(total_ore_weights, i) + local index = table.binary_search(total_ore_weights, i) if (index < 0) then index = bit32.bnot(index) end diff --git a/map_gen/presets/beach.lua b/map_gen/presets/beach.lua index 82b84127..99765b17 100644 --- a/map_gen/presets/beach.lua +++ b/map_gen/presets/beach.lua @@ -2,6 +2,7 @@ local b = require 'map_gen.shared.builders' local perlin = require 'map_gen.shared.perlin_noise' local Global = require 'utils.global' local math = require 'utils.math' +local RS = require 'map_gen.shared.redmew_surface' local table = require 'utils.table' local sand_width = 512 @@ -23,7 +24,7 @@ local perlin_seed_2 = nil Global.register_init( {}, function(tbl) - local seed = game.surfaces[1].map_gen_settings.seed + local seed = RS.get_surface().map_gen_settings.seed tbl.perlin_seed_1 = perlin_seed_1 or seed tbl.perlin_seed_2 = perlin_seed_2 or seed * 2 end, diff --git a/map_gen/presets/christmas_tree_of_terror.lua b/map_gen/presets/christmas_tree_of_terror.lua index 6a190da3..05af00f1 100644 --- a/map_gen/presets/christmas_tree_of_terror.lua +++ b/map_gen/presets/christmas_tree_of_terror.lua @@ -7,6 +7,7 @@ local Token = require 'utils.token' local Global = require 'utils.global' local Event = require 'utils.event' local ScenarioInfo = require 'features.gui.info' +local RS = require 'map_gen.shared.redmew_surface' local table = require 'utils.table' ScenarioInfo.set_map_name('Christmas Tree of Terror') @@ -397,7 +398,7 @@ map = b.apply_effect(map, no_resources) local function on_init() game.forces['player'].technologies['landfill'].enabled = false - local surface = game.surfaces.nauvis + local surface = RS.get_surface() surface.map_gen_settings = { cliff_settings = { name = 'cliff', diff --git a/map_gen/presets/cookies.lua b/map_gen/presets/cookies.lua index ee76de0c..0b9a86b0 100644 --- a/map_gen/presets/cookies.lua +++ b/map_gen/presets/cookies.lua @@ -5,7 +5,7 @@ local table = require 'utils.table' local seed1 = 666 local seed2 = 999 -local function value(a, b) +local function value() return 1000000 end @@ -13,7 +13,7 @@ local Random = require "map_gen.shared.random" local random = Random.new(seed1, seed2) local pic = require "map_gen.data.presets.cookie" -local pic = b.decompress(pic) +pic = b.decompress(pic) local cookie1 = b.picture(pic) local cookie = b.scale(cookie1, 0.1, 0.1) @@ -66,10 +66,10 @@ local p_cols = 50 local p_rows = 50 local pattern = {} -for c = 1, p_cols do +for _ = 1, p_cols do local row = {} table.insert(pattern, row) - for r = 1, p_rows do + for _ = 1, p_rows do local chips = makeChips() local shape @@ -103,11 +103,11 @@ local tablecloth = { {"water", "deepwater", } } } -local tablecloth = b.picture(tablecloth) +tablecloth = b.picture(tablecloth) tablecloth = b.single_pattern(tablecloth, 2, 2) tablecloth = b.scale(tablecloth, 42, 42) tablecloth = b.fish(tablecloth, 0.005) -map = b.if_else(cookies, tablecloth) +local map = b.if_else(cookies, tablecloth) return map diff --git a/map_gen/presets/crash_site.lua b/map_gen/presets/crash_site.lua index fd5d9f94..558f4a76 100644 --- a/map_gen/presets/crash_site.lua +++ b/map_gen/presets/crash_site.lua @@ -10,6 +10,22 @@ local math = require 'utils.math' local degrees = math.degrees local ScenarioInfo = require 'features.gui.info' local table = require 'utils.table' +local RS = require 'map_gen.shared.redmew_surface' +local MGSP = require 'resources.map_gen_settings' + +RS.set_map_gen_settings( + { + MGSP.grass_only, + { + terrain_segmentation = 'normal', + water = 'normal' + }, + MGSP.starting_area_very_low, + MGSP.ore_oil_none, + MGSP.enemy_none, + MGSP.cliff_none + } +) -- Comment out this block if you're getting scenario info from another source. ScenarioInfo.set_map_name('Crashsite') @@ -526,9 +542,9 @@ local function init() local max_worm_chance = 1 / 64 local worm_chance_factor = 1 / (40 * 512) - local scale_factor = 1 / 32 + --local scale_factor = 1 / 32 - local function enemy(x, y, world) + local function enemy(_, _, world) local wx, wy = world.x, world.y local d = math.sqrt(wx * wx + wy * wy) @@ -718,10 +734,9 @@ local map Global.register_init( {}, function(tbl) - local seed = game.surfaces[1].map_gen_settings.seed + local seed = RS.get_surface().map_gen_settings.seed tbl.outpost_seed = outpost_seed or seed tbl.ore_seed = ore_seed or seed - global.config.market.enable = false end, function(tbl) diff --git a/map_gen/presets/creation_of_adam.lua b/map_gen/presets/creation_of_adam.lua index 9837fdc7..fc16bcd2 100644 --- a/map_gen/presets/creation_of_adam.lua +++ b/map_gen/presets/creation_of_adam.lua @@ -1,7 +1,7 @@ local b = require "map_gen.shared.builders" local pic = require "map_gen.data.presets.creation_of_adam" -local pic = b.decompress(pic) +pic = b.decompress(pic) local scale_factor = 3 local shape = b.picture(pic) @@ -18,4 +18,4 @@ map = b.translate(map, 128 * scale_factor, 26 * scale_factor) map = b.change_map_gen_collision_tile(map, "water-tile", "grass-1") -return map \ No newline at end of file +return map diff --git a/map_gen/presets/danger_ores.lua b/map_gen/presets/danger_ores.lua index 4c2adfeb..86e16705 100644 --- a/map_gen/presets/danger_ores.lua +++ b/map_gen/presets/danger_ores.lua @@ -1,6 +1,7 @@ local b = require 'map_gen.shared.builders' local Perlin = require 'map_gen.shared.perlin_noise' local Global = require 'utils.global' +local RS = require 'map_gen.shared.redmew_surface' local math = require "utils.math" local table = require 'utils.table' @@ -21,7 +22,7 @@ local density_multiplier = 50 Global.register_init( {}, function(tbl) - tbl.seed = game.surfaces[1].map_gen_settings.seed + tbl.seed = RS.get_surface().map_gen_settings.seed end, function(tbl) local seed = tbl.seed diff --git a/map_gen/presets/diagonal_ribbon.lua b/map_gen/presets/diagonal_ribbon.lua index 7b2381da..18902023 100644 --- a/map_gen/presets/diagonal_ribbon.lua +++ b/map_gen/presets/diagonal_ribbon.lua @@ -12,6 +12,7 @@ local b = require 'map_gen.shared.builders' local perlin = require 'map_gen.shared.perlin_noise' local Global = require 'utils.global' local math = require 'utils.math' +local RS = require 'map_gen.shared.redmew_surface' -- A "very small" starting area is advised at the default 100 width. local play_area_width = 100 -- The approximate width of the play area @@ -31,7 +32,7 @@ local perlin_seed_2 = nil Global.register_init( {}, function(tbl) - local seed = game.surfaces[1].map_gen_settings.seed + local seed = RS.get_surface().map_gen_settings.seed tbl.perlin_seed_1 = perlin_seed_1 or seed tbl.perlin_seed_2 = perlin_seed_2 or seed * 2 end, diff --git a/map_gen/presets/dickbutt.lua b/map_gen/presets/dickbutt.lua index 0ead9ce4..6646cef9 100644 --- a/map_gen/presets/dickbutt.lua +++ b/map_gen/presets/dickbutt.lua @@ -22,7 +22,7 @@ local eye1 = b.translate(b.circle(32),-130, -100) local dickbutt = b.any({body,butt, shaft, ball1, ball2, leg1, leg2, foot1, foot2, eye1 }) dickbutt = b.translate(dickbutt, -80, 0) -local patch = b.scale(dickbutt, 0.15, 0.15) +b.scale(dickbutt, 0.15, 0.15) local iron_patch = b.resource(b.translate(b.scale(dickbutt, 0.15, 0.15), 20, 0), "iron-ore") local copper_patch = b.resource(b.translate(b.scale(dickbutt, 0.115, 0.115), -125, 50), "copper-ore") local coal_patch = b.resource(b.translate(b.scale(dickbutt, 0.1, 0.1), -135, -90), "coal") diff --git a/map_gen/presets/dino_island.lua b/map_gen/presets/dino_island.lua index 8032183b..d8b26934 100644 --- a/map_gen/presets/dino_island.lua +++ b/map_gen/presets/dino_island.lua @@ -147,7 +147,7 @@ for r = 1, 50 do local ore_data i = random:next_int(1, ore_t) - index = table.binary_search(total_ore_weights, i) + local index = table.binary_search(total_ore_weights, i) if (index < 0) then index = bit32.bnot(index) end @@ -166,7 +166,7 @@ local map = b.grid_pattern_full_overlap(land_pattern, 50, 50, 640, 640) map = b.change_tile(map, false, 'deepwater') map = b.fish(map, 0.0025) -local ores = b.grid_pattern_full_overlap(ore_pattern, 50, 50, 128, 128) +ores = b.grid_pattern_full_overlap(ore_pattern, 50, 50, 128, 128) map = b.apply_entity(map, ores) map = b.translate(map, -50, -160) diff --git a/map_gen/presets/factorio_logo.lua b/map_gen/presets/factorio_logo.lua index 48b81145..296bbeb6 100644 --- a/map_gen/presets/factorio_logo.lua +++ b/map_gen/presets/factorio_logo.lua @@ -8,7 +8,7 @@ local island_distance_y = 128 local b = require "map_gen.shared.builders" local pic = require "map_gen.data.presets.factorio_logo" -local pic = b.decompress(pic) +pic = b.decompress(pic) local shape = b.picture(pic) shape = b.scale(shape, scale_factor, scale_factor) @@ -19,4 +19,4 @@ shape = b.single_pattern(shape, pattern_width, pattern_height) shape = b.change_tile(shape, false, "deepwater") -return shape \ No newline at end of file +return shape diff --git a/map_gen/presets/factorio_logo2.lua b/map_gen/presets/factorio_logo2.lua index 8d76228a..be952972 100644 --- a/map_gen/presets/factorio_logo2.lua +++ b/map_gen/presets/factorio_logo2.lua @@ -8,7 +8,7 @@ local island_distance_y = 128 local b = require "map_gen.shared.builders" local pic = require "map_gen.data.presets.factorio_logo2" -local pic = b.decompress(pic) +pic = b.decompress(pic) local shape = b.picture(pic) shape = b.scale(shape, scale_factor, scale_factor) @@ -21,4 +21,4 @@ shape = b.change_tile(shape, false, "water") shape = b.fish(shape, 0.008) -return shape \ No newline at end of file +return shape diff --git a/map_gen/presets/factory.lua b/map_gen/presets/factory.lua index 12660fe3..b3c263ca 100644 --- a/map_gen/presets/factory.lua +++ b/map_gen/presets/factory.lua @@ -1,7 +1,7 @@ local b = require "map_gen.shared.builders" local pic = require "map_gen.data.presets.factory" -local pic = b.decompress(pic) +pic = b.decompress(pic) local map = b.picture(pic) -return map \ No newline at end of file +return map diff --git a/map_gen/presets/fish_islands.lua b/map_gen/presets/fish_islands.lua index 81aad3b0..1f15c7a9 100644 --- a/map_gen/presets/fish_islands.lua +++ b/map_gen/presets/fish_islands.lua @@ -175,8 +175,8 @@ start = b.decompress(start) start = b.picture(start) start = b.change_tile(start, 'water', false) -local pic = require 'map_gen.data.presets.fish_black_and_white' -local pic = b.decompress(pic) +pic = require 'map_gen.data.presets.fish_black_and_white' +pic = b.decompress(pic) local fish_bw = b.picture(pic) fish_bw = b.scale(fish_bw, 0.25, 0.25) @@ -212,14 +212,14 @@ end --worms = b.entity(worms, 'big-worm-turret') -local start = b.apply_entity(start, b.any {start_iron, start_copper, start_stone, start_coal, start_oil, worms_top}) +start = b.apply_entity(start, b.any {start_iron, start_copper, start_stone, start_coal, start_oil, worms_top}) map = b.if_else(start, map) map = b.change_map_gen_collision_tile(map, 'water-tile', 'grass-1') local sea = b.tile('water') -local sea = b.fish(sea, 0.0025) +sea = b.fish(sea, 0.0025) map = b.if_else(map, sea) diff --git a/map_gen/presets/fractal_balls.lua b/map_gen/presets/fractal_balls.lua index 886c73d2..fb73591d 100644 --- a/map_gen/presets/fractal_balls.lua +++ b/map_gen/presets/fractal_balls.lua @@ -7,7 +7,7 @@ local function value(base, mult) end end -local function no_resources(x, y, world, tile) +local function no_resources(_, _, world, tile) for _, e in ipairs( world.surface.find_entities_filtered( {type = 'resource', area = {{world.x, world.y}, {world.x + 1, world.y + 1}}} @@ -29,8 +29,6 @@ local inner = b.circle(22) local outer = b.circle(24) local ring = b.all {outer, b.invert(inner)} -map = b.any {map, ring} - local arms = b.any {arm1, arm2} arms = b.translate(arms, 0, -16) arms = @@ -123,7 +121,7 @@ balls4 = b.choose(b.scale(outer, 3, 3), balls4, b.empty_shape) local function make_ball(shape, sf) local s1 = b.translate(shape, 0, -12 * sf) - local shape = + shape = b.any { s1, b.rotate(s1, degrees(120)), diff --git a/map_gen/presets/goat.lua b/map_gen/presets/goat.lua index 7af77aa9..865aea4e 100644 --- a/map_gen/presets/goat.lua +++ b/map_gen/presets/goat.lua @@ -1,7 +1,7 @@ local b = require "map_gen.shared.builders" local pic = require "map_gen.data.presets.goat" -local pic = b.decompress(pic) +pic = b.decompress(pic) local shape = b.picture(pic) shape = b.translate(shape, 10, -96) diff --git a/map_gen/presets/goats_on_goats.lua b/map_gen/presets/goats_on_goats.lua index 73f76367..b1de7131 100644 --- a/map_gen/presets/goats_on_goats.lua +++ b/map_gen/presets/goats_on_goats.lua @@ -1,7 +1,7 @@ local b = require "map_gen.shared.builders" local pic = require "map_gen.data.presets.goat" -local pic = b.decompress(pic) +pic = b.decompress(pic) local goat1 = b.picture(pic) goat1 = b.invert(goat1) @@ -116,4 +116,4 @@ local pattern = local map = b.grid_pattern(pattern, 2, 2, pic.width, pic.height + t - 105) map = b.change_map_gen_collision_tile(map,"water-tile", "water-green") -return map \ No newline at end of file +return map diff --git a/map_gen/presets/grid_islands.lua b/map_gen/presets/grid_islands.lua index 377c4b19..f64add9b 100644 --- a/map_gen/presets/grid_islands.lua +++ b/map_gen/presets/grid_islands.lua @@ -96,7 +96,7 @@ for r = 1, 50 do row[c] = square else local i = random_ore:next_int(1, ore_t) - index = table.binary_search(total_ore_weights, i) + local index = table.binary_search(total_ore_weights, i) if (index < 0) then index = bit32.bnot(index) end diff --git a/map_gen/presets/grid_islands_rotated.lua b/map_gen/presets/grid_islands_rotated.lua index ec611ebf..6f22a9ae 100644 --- a/map_gen/presets/grid_islands_rotated.lua +++ b/map_gen/presets/grid_islands_rotated.lua @@ -27,9 +27,9 @@ local track = { b.rectangle(3, 22) } -h_track = b.any(track) +local h_track = b.any(track) h_track = b.single_x_pattern(h_track, 15) -v_track = b.rotate(h_track,degrees(90)) +local v_track = b.rotate(h_track,degrees(90)) local square = b.rectangle(190, 190) local circle = b.circle(80) @@ -99,7 +99,7 @@ for r = 1, 50 do row[c] = square else local i = random_ore:next_int(1, ore_t) - index = table.binary_search(total_ore_weights, i) + local index = table.binary_search(total_ore_weights, i) if (index < 0) then index = bit32.bnot(index) end diff --git a/map_gen/presets/honeycomb.lua b/map_gen/presets/honeycomb.lua index 230788e7..eb3ecc48 100644 --- a/map_gen/presets/honeycomb.lua +++ b/map_gen/presets/honeycomb.lua @@ -1,7 +1,7 @@ local b = require "map_gen.shared.builders" local pic = require "map_gen.data.presets.honeycomb" -local pic = b.decompress(pic) +pic = b.decompress(pic) local map = b.picture(pic) -- this builds the map by duplicating the pic in every direction @@ -16,4 +16,4 @@ map = b.single_pattern(map, pic.width-1, pic.height-1) -- this sets the tile outside the bounds of the map to deepwater, remove this and it will be void. --map = b.change_tile(map, false, "deepwater") -return map \ No newline at end of file +return map diff --git a/map_gen/presets/line_and_tree.lua b/map_gen/presets/line_and_tree.lua index c19bfef0..fdc645db 100644 --- a/map_gen/presets/line_and_tree.lua +++ b/map_gen/presets/line_and_tree.lua @@ -56,10 +56,10 @@ local function make_tree() end local pattern = {} - for r = 1, p_rows do + for _ = 1, p_rows do local row = {} table.insert(pattern, row) - for c = 1, p_cols do + for _ = 1, p_cols do local i = random:next_int(1, t) local index = table.binary_search(total_weights, i) diff --git a/map_gen/presets/line_and_trees.lua b/map_gen/presets/line_and_trees.lua index f9c34c6d..80aec1ca 100644 --- a/map_gen/presets/line_and_trees.lua +++ b/map_gen/presets/line_and_trees.lua @@ -44,10 +44,10 @@ local function make_tree() end local pattern = {} - for r = 1, p_rows do + for _ = 1, p_rows do local row = {} table.insert(pattern, row) - for c = 1, p_cols do + for _ = 1, p_cols do local i = random:next_int(1, t) local index = table.binary_search(total_weights, i) diff --git a/map_gen/presets/lines_and_squares.lua b/map_gen/presets/lines_and_squares.lua index 608328d0..fae6f74a 100644 --- a/map_gen/presets/lines_and_squares.lua +++ b/map_gen/presets/lines_and_squares.lua @@ -91,7 +91,7 @@ for _, v in ipairs(squares) do table.insert(total_square_weights, square_t) end -value = b.exponential_value +local value = b.exponential_value local function non_transform(shape) return shape diff --git a/map_gen/presets/plus.lua b/map_gen/presets/plus.lua index d4abe5e6..ee19f5b0 100644 --- a/map_gen/presets/plus.lua +++ b/map_gen/presets/plus.lua @@ -1,7 +1,7 @@ local b = require "map_gen.shared.builders" local pic = require "map_gen.data.presets.plus" --or whatever you called it in data->presets -local pic = b.decompress(pic) +pic = b.decompress(pic) local map = b.picture(pic) map = b.single_pattern(map, pic.width-1, pic.height-1) @@ -11,4 +11,4 @@ map = b.translate(map, 86, 0) -- uncomment the line below to change the size of the map b.scale(x, y) map = b.scale(map, 1.5, 1.5) -return map \ No newline at end of file +return map diff --git a/map_gen/presets/toxic_danger_ore_jungle.lua b/map_gen/presets/toxic_danger_ore_jungle.lua index 24d3c53b..43d5ad58 100644 --- a/map_gen/presets/toxic_danger_ore_jungle.lua +++ b/map_gen/presets/toxic_danger_ore_jungle.lua @@ -3,6 +3,7 @@ local Perlin = require 'map_gen.shared.perlin_noise' local Event = require 'utils.event' local Global = require 'utils.global' local math = require "utils.math" +local RS = require 'map_gen.shared.redmew_surface' local table = require 'utils.table' local match = string.match @@ -26,7 +27,7 @@ local density_multiplier = 50 Global.register_init( {}, function(tbl) - tbl.seed = game.surfaces[1].map_gen_settings.seed + tbl.seed = RS.get_surface().map_gen_settings.seed end, function(tbl) local seed = tbl.seed diff --git a/map_gen/presets/venice.lua b/map_gen/presets/venice.lua index 07681fe2..bd234318 100644 --- a/map_gen/presets/venice.lua +++ b/map_gen/presets/venice.lua @@ -1,7 +1,7 @@ local b = require "map_gen.shared.builders" local pic = require "map_gen.data.presets.venice" -local pic = b.decompress(pic) +pic = b.decompress(pic) local map = b.picture(pic) map = b.translate(map, 90, 190) @@ -10,4 +10,4 @@ map = b.scale(map, 2, 2) map = b.change_tile(map, false, "deepwater") -return map \ No newline at end of file +return map diff --git a/map_gen/presets/venus.lua b/map_gen/presets/venus.lua index 6f130739..3f2e79fb 100644 --- a/map_gen/presets/venus.lua +++ b/map_gen/presets/venus.lua @@ -1,10 +1,13 @@ local b = require 'map_gen.shared.builders' local Event = require 'utils.event' -global.map.terraforming.creep_retraction_tiles = { 'sand-1' } +global.map.terraforming.creep_retraction_tiles = {'sand-1'} require 'map_gen.misc.nightfall' -- forces idle biters to attack at night require 'map_gen.misc.terraforming' -- prevents players from building on non-terraformed tiles local DayNight = require 'map_gen.misc.day_night' local ScenarioInfo = require 'features.gui.info' +local RS = require 'map_gen.shared.redmew_surface' + +-- Info and world settings ScenarioInfo.set_map_name('Terraform Venus') ScenarioInfo.set_map_description('After a long journey you have reached Venus. Your mission is simple, turn this hostile environment into one where humans can thrive') @@ -14,10 +17,36 @@ ScenarioInfo.add_map_extra_info( '- While unsure the exact effects the atmosphere will have, you should be cautios of it\n' .. '- As you spread breathable atmosphere the ground will change to show where you can breathe\n' .. '- The days seem endless, but when the sun begins setting night is upon us immediately.\n' .. - '- The biters here are numerous and seem especially aggressive during the short nights\n' .. - '- Technology seems to take 6 times longer than usual' + '- The biters here are numerous and seem especially aggressive during the short nights' ) +local MGSP = require 'resources.map_gen_settings' -- map gen settings presets +local DSP = require 'resources.difficulty_settings' -- difficulty settings presets +local MSP = require 'resources.map_settings' -- map settings presets + +RS.add_map_gen_settings({MGSP.tree_none, MGSP.enemy_very_high, MGSP.water_very_low,MGSP.cliff_normal, MGSP.starting_area_very_low, MGSP.sand_only}) +RS.add_difficulty_settings({DSP.tech_x2}) +RS.add_map_settings({MSP.pollution_hard_to_spread, MSP.enemy_evolution_punishes_pollution, MSP.enemy_expansion_frequency_x4, MSP.enemy_expansion_aggressive}) + +-- 20 minute cycle, 14m of full light, 1m light to dark, 4m full dark, 1m dark to light +DayNight.day_night_cycle = { + ['ticks_per_day'] = 72000, + ['dusk'] = 0.625, + ['evening'] = 0.775, + ['morning'] = 0.925, + ['dawn'] = 0.975 +} + +--- Sets recipes and techs to be enabled/disabled +local function init() + local player_force = game.forces.player + player_force.recipes['medium-electric-pole'].enabled = true + player_force.recipes['steel-plate'].enabled = true + player_force.technologies['artillery-shell-range-1'].enabled = false +end + +-- Map Generation + local function value(base, mult) return function(x, y) return mult * (math.abs(x) + math.abs(y)) + base @@ -52,16 +81,6 @@ local function no_resources(_, _, world, tile) return tile end -local function no_trees(_, _, world, tile) - for _, e in ipairs( - world.surface.find_entities_filtered({type = 'tree', area = {{world.x, world.y}, {world.x + 1, world.y + 1}}}) - ) do - e.destroy() - end - - return tile -end - -- create a square on which to place each ore local square = b.rectangle(12, 12) square = b.change_tile(square, true, 'lab-dark-2') @@ -112,92 +131,7 @@ start_area = b.apply_effect(start_area, no_resources) local map = b.any {start_area, b.full_shape} map = b.change_map_gen_collision_tile(map, 'ground-tile', 'sand-1') map = b.translate(map, 6, -10) -- translate the whole map away, otherwise we'll spawn in the water -map = b.apply_effect(map, no_trees) ---- Sets the map parameters once the game begins and we have a surface to act on -local function world_settings() - local surface = game.surfaces.nauvis - local player_force = game.forces.player - - -- 20 minute cycle, 14m of full light, 1m light to dark, 4m full dark, 1m dark to light - local day_night_cycle = { - ['ticks_per_day'] = 72000, - ['dusk'] = 0.625, - ['evening'] = 0.775, - ['morning'] = 0.925, - ['dawn'] = 0.975 - } - - DayNight.set_cycle(day_night_cycle, surface) - player_force.recipes['medium-electric-pole'].enabled = true - player_force.recipes['steel-plate'].enabled = true - player_force.technologies['artillery-shell-range-1'].enabled = false - game.difficulty_settings.technology_price_multiplier = 1 - - local map_settings = game.map_settings - local pollution = map_settings.pollution - pollution.enabled = true - pollution.diffusion_ratio = 0.01 - pollution.min_to_diffuse = 30 - pollution.ageing = 1 - pollution.expected_max_per_chunk = 7000 - pollution.min_to_show_per_chunk = 700 - pollution.min_pollution_to_damage_trees = 3500 - pollution.pollution_with_max_forest_damage = 10000 - pollution.pollution_per_tree_damage = 2000 - pollution.pollution_restored_per_tree_damage = 500 - pollution.max_pollution_to_restore_trees = 1000 - - local enemy_evolution = map_settings.enemy_evolution - enemy_evolution.enabled = true - enemy_evolution.time_factor = 0.00004 - enemy_evolution.destroy_factor = 0.002 - enemy_evolution.pollution_factor = 0.000045 - - local enemy_expansion = map_settings.enemy_expansion - enemy_expansion.enabled = true - enemy_expansion.max_expansion_distance = 10 - enemy_expansion.friendly_base_influence_radius = 2 - enemy_expansion.enemy_building_influence_radius = 2 - enemy_expansion.building_coefficient = 0.1 - enemy_expansion.other_base_coefficient = 2.0 - enemy_expansion.neighbouring_chunk_coefficient = 0.5 - enemy_expansion.neighbouring_base_chunk_coefficient = 0.4 - enemy_expansion.max_colliding_tiles_coefficient = 0.9 - enemy_expansion.settler_group_min_size = 2 - enemy_expansion.settler_group_max_size = 30 - enemy_expansion.min_expansion_cooldown = 1 * 3600 - enemy_expansion.max_expansion_cooldown = 15 * 3600 - - surface.map_gen_settings = { - terrain_segmentation = 'very-low', -- water frequency - water = 'very-low', -- water size - autoplace_controls = { - stone = {frequency = 'normal', size = 'high', richness = 'low'}, - coal = {frequency = 'normal', size = 'high', richness = 'normal'}, - ['copper-ore'] = {frequency = 'normal', size = 'high', richness = 'low'}, - ['iron-ore'] = {frequency = 'normal', size = 'high', richness = 'normal'}, - ['uranium-ore'] = {frequency = 'normal', size = 'normal', richness = 'normal'}, - ['crude-oil'] = {frequency = 'normal', size = 'normal', richness = 'normal'}, - trees = {frequency = 'normal', size = 'none', richness = 'normal'}, - ['enemy-base'] = {frequency = 'very-high', size = 'very-high', richness = 'very-high'}, - grass = {frequency = 'normal', size = 'none', richness = 'normal'}, - desert = {frequency = 'normal', size = 'none', richness = 'normal'}, - dirt = {frequency = 'normal', size = 'none', richness = 'normal'}, - sand = {frequency = 'normal', size = 'normal', richness = 'normal'} - }, - cliff_settings = { - name = 'cliff', - cliff_elevation_0 = 10, - cliff_elevation_interval = 10 - }, - width = 0, - height = 0, - starting_area = 'very-low', - peaceful_mode = false, - seed = nil - } -end -Event.on_init(world_settings) +Event.on_init(init) return map diff --git a/map_gen/presets/void_gears.lua b/map_gen/presets/void_gears.lua index 30f28d54..644582cb 100644 --- a/map_gen/presets/void_gears.lua +++ b/map_gen/presets/void_gears.lua @@ -30,7 +30,7 @@ local ores = { {resource_type = 'uranium-ore', value = value(125, 1)}, {resource_type = 'crude-oil', value = value(50000, 250)} } -local function striped(shape) +local function striped(shape) -- luacheck: ignore 431 return function(x, y, world) if not shape(x, y) then return nil @@ -47,7 +47,7 @@ local function striped(shape) end end -local function sprinkle(shape) +local function sprinkle(shape) -- luacheck: ignore 431 return function(x, y, world) if not shape(x, y) then return nil @@ -65,8 +65,7 @@ local function sprinkle(shape) end -local function radial(shape, radius) - local radius_sq = radius * radius +local function radial(shape, radius) -- luacheck: ignore 431 local stone_r_sq = radius * 0.3025 -- radius * 0.55 local coal_r_sq = radius * 0.4225 -- radius * 0.65 local copper_r_sq = radius * 0.64 -- radius * 0.8 @@ -174,7 +173,7 @@ local function do_patches(patches, offset) index = bit32.bnot(index) end - local shape = patches[index][1] + local shape = patches[index][1] -- luacheck: ignore 431 local x = random:next_int(-offset, offset) local y = random:next_int(-offset, offset) diff --git a/map_gen/presets/women.lua b/map_gen/presets/women.lua index 73a7fb63..b5e9e913 100644 --- a/map_gen/presets/women.lua +++ b/map_gen/presets/women.lua @@ -1,7 +1,7 @@ local b = require "map_gen.shared.builders" local pic = require "map_gen.data.presets.woman" -local pic = b.decompress(pic) +pic = b.decompress(pic) local shape = b.picture(pic) local map = b.single_pattern_overlap(shape, pic.width - 50, pic.height - 120) @@ -11,4 +11,4 @@ map = b.translate(map, 135, -65) --map = b.scale(map, 2, 2) -return map \ No newline at end of file +return map diff --git a/map_gen/shape/infinite_mazes.lua b/map_gen/shape/infinite_mazes.lua index 3afbbea0..1372ddbc 100644 --- a/map_gen/shape/infinite_mazes.lua +++ b/map_gen/shape/infinite_mazes.lua @@ -1,3 +1,6 @@ +local Event = require 'utils.event' +local RS = require 'map_gen.shared.redmew_surface' +local Global = require 'utils.global' --Author: Hexicube --The size of each individual maze, in cells. local maze_width = 17 @@ -24,21 +27,46 @@ local resource_density_factor = 500 --DO NOT TOUCH BELOW THIS LINE-- +local bor = bit32.bor +local bxor = bit32.bxor +local band = bit32.band +local rshift = bit32.rshift + +local global_ore_data = {} +local global_maze_data = {} +local primitives = { + maze_seed = 0, +} + +Global.register( + { + primitives = primitives, + global_ore_data = global_ore_data, + }, + function(tbl) + primitives = tbl.primitives + global_ore_data = tbl.global_ore_data + end +) + local function get_random_maze_val(cur_seed) - local new_seed = bit32.bor(cur_seed + 0x9E3779B9, 0) - local return_val = bit32.bor(new_seed * 0xBF58476D, 0) - return_val = bit32.bor(return_val * 0x94D049BB, 0) - return new_seed, bit32.bor(return_val , 0) + local new_seed = bor(cur_seed + 0x9E3779B9, 0) + local return_val = bor(new_seed * 0xBF58476D, 0) + return_val = bor(return_val * 0x94D049BB, 0) + return new_seed, bor(return_val, 0) end -local last_maze_x, last_maze_y, last_maze = nil, nil, nil +local last_maze_x, last_maze_y, last_maze local function get_maze(x, y, seed, width, height) - if last_maze and last_maze_x == x and last_maze_y == y then return last_maze end + if last_maze and last_maze_x == x and last_maze_y == y then + return last_maze + end - if not global.maze_data then global.maze_data = {} end - if not global.maze_data[x] then global.maze_data[x] = {} end - if global.maze_data[x][y] then - last_maze = global.maze_data[x][y] + if not global_maze_data[x] then + global_maze_data[x] = {} + end + if global_maze_data[x][y] then + last_maze = global_maze_data[x][y] last_maze_x = x last_maze_y = y return last_maze @@ -46,29 +74,29 @@ local function get_maze(x, y, seed, width, height) local maze_data = {} local grid = {} - for tx = 1,width do + for tx = 1, width do maze_data[tx] = {} grid[tx] = {} - for ty = 1,height do + for ty = 1, height do maze_data[tx][ty] = 15 grid[tx][ty] = true end end - local maze_seed = bit32.bxor(bit32.lshift(x,16) + bit32.band(y,65535), seed) - local value = 0 + local maze_seed = bxor(bit32.lshift(x, 16) + band(y, 65535), seed) + local value local queue = {} maze_seed, value = get_random_maze_val(maze_seed) local pos = {0, 0} - pos[1] = value % width + 1 - value = bit32.rshift(value,16) + pos[1] = value % width + 1 + value = rshift(value, 16) pos[2] = value % height + 1 - queue[#queue+1] = {pos[1], pos[2], pos[1]-1, pos[2] } - queue[#queue+1] = {pos[1], pos[2], pos[1]+1, pos[2] } - queue[#queue+1] = {pos[1], pos[2], pos[1] , pos[2]-1} - queue[#queue+1] = {pos[1], pos[2], pos[1] , pos[2]+1} + queue[#queue + 1] = {pos[1], pos[2], pos[1] - 1, pos[2]} + queue[#queue + 1] = {pos[1], pos[2], pos[1] + 1, pos[2]} + queue[#queue + 1] = {pos[1], pos[2], pos[1], pos[2] - 1} + queue[#queue + 1] = {pos[1], pos[2], pos[1], pos[2] + 1} while #queue > 0 do maze_seed, value = get_random_maze_val(maze_seed) @@ -87,44 +115,47 @@ local function get_maze(x, y, seed, width, height) else mod_t = 2 end - maze_data[sx][sy] = bit32.band(maze_data[sx][sy], mod_s) - maze_data[tx][ty] = bit32.band(maze_data[tx][ty], mod_t) + maze_data[sx][sy] = band(maze_data[sx][sy], mod_s) + maze_data[tx][ty] = band(maze_data[tx][ty], mod_t) grid[sx][sy] = false grid[tx][ty] = false - queue[#queue+1] = {tx, ty, tx-1, ty } - queue[#queue+1] = {tx, ty, tx+1, ty } - queue[#queue+1] = {tx, ty, tx , ty-1} - queue[#queue+1] = {tx, ty, tx , ty+1} + queue[#queue + 1] = {tx, ty, tx - 1, ty} + queue[#queue + 1] = {tx, ty, tx + 1, ty} + queue[#queue + 1] = {tx, ty, tx, ty - 1} + queue[#queue + 1] = {tx, ty, tx, ty + 1} end end maze_seed, value = get_random_maze_val(maze_seed) - maze_data[value % width + 1][1] = bit32.band(maze_data[value % width + 1][1], 1) - value = bit32.rshift(value, 16) - maze_data[1][value % height + 1] = bit32.band(maze_data[1][value % height + 1], 2) + maze_data[value % width + 1][1] = band(maze_data[value % width + 1][1], 1) + value = rshift(value, 16) + maze_data[1][value % height + 1] = band(maze_data[1][value % height + 1], 2) maze_seed, value = get_random_maze_val(maze_seed) - maze_data[width+1] = {0, 0} - maze_data[width+1][1] = value % width + 1 - value = bit32.rshift(value, 16) - maze_data[width+1][2] = value % height + 1 + maze_data[width + 1] = {0, 0} + maze_data[width + 1][1] = value % width + 1 + value = rshift(value, 16) + maze_data[width + 1][2] = value % height + 1 - global.maze_data[x][y] = maze_data + global_maze_data[x][y] = maze_data last_maze = maze_data last_maze_x = x last_maze_y = y return maze_data end -local last_maze_ore_x, last_maze_ore_y, last_maze_ore = nil, nil, nil +local last_maze_ore_x, last_maze_ore_y, last_maze_ore local function get_maze_ore(x, y, seed, width, height) - if last_maze_ore and last_maze_ore_x == x and last_maze_ore_y == y then return last_maze_ore end + if last_maze_ore and last_maze_ore_x == x and last_maze_ore_y == y then + return last_maze_ore + end - if not global.maze_data_ore then global.maze_data_ore = {} end - if not global.maze_data_ore[x] then global.maze_data_ore[x] = {} end - if global.maze_data_ore[x][y] then - last_maze_ore = global.maze_data_ore[x][y] + if not global_ore_data[x] then + global_ore_data[x] = {} + end + if global_ore_data[x][y] then + last_maze_ore = global_ore_data[x][y] last_maze_ore_x = x last_maze_ore_y = y return last_maze_ore @@ -132,44 +163,44 @@ local function get_maze_ore(x, y, seed, width, height) local coord_list = {} local maze_data = {} - for tx=1,width do + for tx = 1, width do maze_data[tx] = {} - for ty=1,height do + for ty = 1, height do maze_data[tx][ty] = nil - coord_list[#coord_list+1] = {tx,ty} + coord_list[#coord_list + 1] = {tx, ty} end end - local maze_seed = bit32.bxor(bit32.lshift(x,16) + bit32.band(y,65535), seed) - local value = 0 + local maze_seed = bxor(bit32.lshift(x, 16) + band(y, 65535), seed) + local value - for a=1,iron_ore_count do + for _ = 1, iron_ore_count do maze_seed, value = get_random_maze_val(maze_seed) local pos = table.remove(coord_list, value % #coord_list + 1) - maze_data[pos[1]][pos[2]] = "iron-ore" + maze_data[pos[1]][pos[2]] = 'iron-ore' end - for a=1,copper_ore_count do + for _ = 1, copper_ore_count do maze_seed, value = get_random_maze_val(maze_seed) local pos = table.remove(coord_list, value % #coord_list + 1) - maze_data[pos[1]][pos[2]] = "copper-ore" + maze_data[pos[1]][pos[2]] = 'copper-ore' end - for a=1,coal_ore_count do + for _ = 1, coal_ore_count do maze_seed, value = get_random_maze_val(maze_seed) local pos = table.remove(coord_list, value % #coord_list + 1) - maze_data[pos[1]][pos[2]] = "coal" + maze_data[pos[1]][pos[2]] = 'coal' end - for a=1,stone_ore_count do + for _ = 1, stone_ore_count do maze_seed, value = get_random_maze_val(maze_seed) local pos = table.remove(coord_list, value % #coord_list + 1) - maze_data[pos[1]][pos[2]] = "stone" + maze_data[pos[1]][pos[2]] = 'stone' end - for a=1,uranium_ore_count do + for _ = 1, uranium_ore_count do maze_seed, value = get_random_maze_val(maze_seed) local pos = table.remove(coord_list, value % #coord_list + 1) - maze_data[pos[1]][pos[2]] = "uranium-ore" + maze_data[pos[1]][pos[2]] = 'uranium-ore' end - global.maze_data_ore[x][y] = maze_data + global_ore_data[x][y] = maze_data last_maze_ore = maze_data last_maze_ore_x = x last_maze_ore_y = y @@ -178,19 +209,17 @@ end local function global_to_maze_pos(x, y) --Ensures we start in the middle of a tile. - x = x + maze_tile_size/2 - y = y + maze_tile_size/2 + x = x + maze_tile_size / 2 + y = y + maze_tile_size / 2 - local maze_width_raw = (maze_width +1) * maze_tile_size - local maze_height_raw = (maze_height+1) * maze_tile_size + local maze_width_raw = (maze_width + 1) * maze_tile_size + local maze_height_raw = (maze_height + 1) * maze_tile_size local global_maze_x = math.floor(x / maze_width_raw) local global_maze_y = math.floor(y / maze_height_raw) x = x - global_maze_x * maze_width_raw y = y - global_maze_y * maze_height_raw - local inner_x, inner_y = x, y - local local_maze_x = math.floor(x / maze_tile_size) local local_maze_y = math.floor(y / maze_tile_size) x = x - local_maze_x * maze_tile_size @@ -199,9 +228,9 @@ local function global_to_maze_pos(x, y) return global_maze_x, global_maze_y, local_maze_x, local_maze_y, x, y end -local function handle_maze_tile(x, y, surf, seed) +local function handle_maze_tile(x, y, _, seed) local orig_x, orig_y = x, y - local global_maze_x, global_maze_y, local_maze_x, local_maze_y = 0, 0, 0, 0 + local global_maze_x, global_maze_y, local_maze_x, local_maze_y global_maze_x, global_maze_y, local_maze_x, local_maze_y, x, y = global_to_maze_pos(x, y) local maze_data = get_maze(global_maze_x, global_maze_y, seed, maze_width, maze_height) @@ -209,66 +238,83 @@ local function handle_maze_tile(x, y, surf, seed) if local_maze_x == 0 or local_maze_y == 0 then if local_maze_x == 0 then if local_maze_y ~= 0 then - if maze_data[maze_width+1][1] ~= local_maze_y then maze_value = 1 end + if maze_data[maze_width + 1][1] ~= local_maze_y then + maze_value = 1 + end end else - if maze_data[maze_width+1][2] ~= local_maze_x then maze_value = 2 end + if maze_data[maze_width + 1][2] ~= local_maze_x then + maze_value = 2 + end end else maze_value = maze_data[local_maze_x][local_maze_y] end - if x < maze_tile_border and y < maze_tile_border then return {name = "out-of-map", position = {orig_x, orig_y}} end - if x < maze_tile_border and bit32.btest(maze_value,1) then return {name = "out-of-map", position = {orig_x, orig_y}} end - if y < maze_tile_border and bit32.btest(maze_value,2) then return {name = "out-of-map", position = {orig_x, orig_y}} end + if x < maze_tile_border and y < maze_tile_border then + return {name = 'out-of-map', position = {orig_x, orig_y}} + end + if x < maze_tile_border and bit32.btest(maze_value, 1) then + return {name = 'out-of-map', position = {orig_x, orig_y}} + end + if y < maze_tile_border and bit32.btest(maze_value, 2) then + return {name = 'out-of-map', position = {orig_x, orig_y}} + end return nil end local function handle_maze_tile_ore(x, y, surf, seed) local orig_x, orig_y = x, y - local spawn_distance_1k = math.sqrt(x*x + y*y) / 1000 - local global_maze_x, global_maze_y, local_maze_x, local_maze_y = 0, 0, 0, 0 + local spawn_distance_1k = math.sqrt(x * x + y * y) / 1000 + local global_maze_x, global_maze_y, local_maze_x, local_maze_y global_maze_x, global_maze_y, local_maze_x, local_maze_y, x, y = global_to_maze_pos(x, y) - if x < maze_tile_border or y < maze_tile_border then return end - - local seed_x = global_maze_x * maze_width + local_maze_x - local seed_y = global_maze_x * maze_height + local_maze_y + if x < maze_tile_border or y < maze_tile_border then + return + end local ore_name = nil if local_maze_x == 0 or local_maze_y == 0 then - if global_maze_x == 0 and global_maze_y == 0 then - if local_maze_x == 1 and local_maze_y == 0 then ore_name = "iron-ore" end - if local_maze_x == 0 and local_maze_y == 1 then ore_name = "stone" end - elseif global_maze_x == -1 and global_maze_y == 0 and local_maze_x == maze_width and local_maze_y == 0 then ore_name = "copper-ore" - elseif global_maze_x == 0 and global_maze_y == -1 and local_maze_x == 0 and local_maze_y == maze_height then ore_name = "coal" - end + if global_maze_x == 0 and global_maze_y == 0 then + if local_maze_x == 1 and local_maze_y == 0 then + ore_name = 'iron-ore' + end + if local_maze_x == 0 and local_maze_y == 1 then + ore_name = 'stone' + end + elseif global_maze_x == -1 and global_maze_y == 0 and local_maze_x == maze_width and local_maze_y == 0 then + ore_name = 'copper-ore' + elseif global_maze_x == 0 and global_maze_y == -1 and local_maze_x == 0 and local_maze_y == maze_height then + ore_name = 'coal' + end else - local maze_data = get_maze_ore(global_maze_x, global_maze_y, seed, maze_width, maze_height) - ore_name = maze_data[local_maze_x][local_maze_y] + local ore_data = get_maze_ore(global_maze_x, global_maze_y, seed, maze_width, maze_height) + ore_name = ore_data[local_maze_x][local_maze_y] end if ore_name then - if surf.can_place_entity{name=ore_name, position={orig_x, orig_y}} then - local dist_x = math.abs(orig_x) - local dist_y = math.abs(orig_y) - - - dist = spawn_distance_1k - local resource_amount_max = math.floor(resource_density_factor * (dist * dist + 1)) + if surf.can_place_entity {name = ore_name, position = {orig_x, orig_y}} then + local dist = spawn_distance_1k + local resource_amount_max = math.floor(resource_density_factor * (dist * dist + 1)) local dist_x = maze_tile_size - x - 1 - if (x - maze_tile_border) < dist_x then dist_x = (x - maze_tile_border) end + if (x - maze_tile_border) < dist_x then + dist_x = (x - maze_tile_border) + end local dist_y = maze_tile_size - y - 1 - if (y - maze_tile_border) < dist_y then dist_y = (y - maze_tile_border) end + if (y - maze_tile_border) < dist_y then + dist_y = (y - maze_tile_border) + end dist = dist_x - if dist_y < dist then dist = dist_y end + if dist_y < dist then + dist = dist_y + end dist = dist + 1 local resource_amount = resource_amount_max * dist / maze_tile_size * 2 if resource_amount > resource_amount_max / 2 then - surf.create_entity{name=ore_name, position={orig_x, orig_y}, amount=resource_amount} - end + surf.create_entity {name = ore_name, position = {orig_x, orig_y}, amount = resource_amount} + end end end end @@ -276,35 +322,50 @@ end local function on_chunk_generated_ore(event) local entities = event.surface.find_entities(event.area) for _, entity in pairs(entities) do - if entity.type == "resource" and entity.name ~= "crude-oil" then + if entity.type == 'resource' and entity.name ~= 'crude-oil' then entity.destroy() end end local tx, ty = event.area.left_top.x, event.area.left_top.y local ex, ey = event.area.right_bottom.x, event.area.right_bottom.y + local surface = event.surface - for x=tx,ex do - for y=ty,ey do - handle_maze_tile_ore(x, y, game.surfaces[1], global.maze_seed) + for x = tx, ex do + for y = ty, ey do + handle_maze_tile_ore(x, y, surface, primitives.maze_seed) end end end -function run_shape_module(event) - if not global.maze_seed then global.maze_seed = math.random(0, 65536 * 65536 - 1) end - - local tiles = {} - local tx, ty = event.area.left_top.x, event.area.left_top.y - local ex, ey = event.area.right_bottom.x, event.area.right_bottom.y - - for x=tx,ex do - for y=ty,ey do - local new_tile = handle_maze_tile(x, y, game.surfaces[1], global.maze_seed) - if new_tile then table.insert(tiles, new_tile) end - end +Event.on_init( + function() + primitives.maze_seed = math.random(0, 65536 * 65536 - 1) end - game.surfaces[1].set_tiles(tiles, true) +) - on_chunk_generated_ore(event) -end +Event.add( + defines.events.on_chunk_generated, + function(event) + if event.surface ~= RS.get_surface() then + return + end + + local tiles = {} + local tx, ty = event.area.left_top.x, event.area.left_top.y + local ex, ey = event.area.right_bottom.x, event.area.right_bottom.y + local surface = event.surface + + for x = tx, ex do + for y = ty, ey do + local new_tile = handle_maze_tile(x, y, surface, primitives.maze_seed) + if new_tile then + table.insert(tiles, new_tile) + end + end + end + surface.set_tiles(tiles, true) + + on_chunk_generated_ore(event) + end +) diff --git a/map_gen/shape/maze.lua b/map_gen/shape/maze.lua index ba52ecf2..a5536d0b 100644 --- a/map_gen/shape/maze.lua +++ b/map_gen/shape/maze.lua @@ -1,124 +1,147 @@ -require "map_gen.shared.chunk_utils" +local Event = require 'utils.event' +local RS = require 'map_gen.shared.redmew_surface' +local Global = require 'utils.global' local wall_thickness = 1 local cell_size = 3 --must be an uneven number +local wall_delta = math.floor((cell_size - wall_thickness) / 2) +local pixels = {} +local cells = {} -local wall_delta = math.floor((cell_size-wall_thickness)/2) -local chunk_size = 32 +local primitives = { + max = 0, + rnd_p = 1, + walk_seed_w = 0, + walk_seed_h = 0 +} +local rects = {} +local shuffle_pool = {} -pixels = {} -cells = {} -function add_tile(x, y, width, height, add_cell) +Global.register( + { + primitives = primitives, + rects = rects, + shuffle_pool = shuffle_pool + }, + function(tbl) + primitives = tbl.primitives + rects = tbl.rects + end +) + +local function add_tile(x, y, width, height, add_cell) if add_cell then - if cells[x] == nil then cells[x] = {} end + if cells[x] == nil then + cells[x] = {} + end cells[x][y] = 1 end - for xpos = x, x + width -1 do - for ypos = y, y + height -1 do - if pixels[xpos] == nil then pixels[xpos] = {} end + for xpos = x, x + width - 1 do + for ypos = y, y + height - 1 do + if pixels[xpos] == nil then + pixels[xpos] = {} + end pixels[xpos][ypos] = 1 end end end -global.max = 0 -function render() - for x,_ in pairs(pixels) do - for y,_ in pairs(pixels[x]) do - if y * 32 > global.max and y % 2 == 0 then - global.max = y * 32 +primitives.max = 0 +local function render() + for x, _ in pairs(pixels) do + for y, _ in pairs(pixels[x]) do + if y * 32 > primitives.max and y % 2 == 0 then + primitives.max = y * 32 end - global.rects[x*32 .. "/" .. y*32] = 1 + rects[x * 32 .. '/' .. y * 32] = 1 end end end -global.rnd_p = 1 -function psd_rnd(l, h) - while global.shuffle_pool[global.rnd_p] < l do - global.rnd_p = global.rnd_p + 1 - end - local res = global.shuffle_pool[global.rnd_p] - global.rnd_p = global.rnd_p + 1 - return res +primitives.rnd_p = 1 +local function psd_rnd(l) + while shuffle_pool[primitives.rnd_p] < l do + primitives.rnd_p = primitives.rnd_p + 1 end - function shuffle(t) - for i = 1, #t - 1 do + local res = shuffle_pool[primitives.rnd_p] + primitives.rnd_p = primitives.rnd_p + 1 + return res +end + +local function shuffle(t) + for i = 1, #t - 1 do local r = psd_rnd(i, #t) - t[i], t[r] = t[r], t[i] - end + t[i], t[r] = t[r], t[i] + end end -- builds a width-by-height grid of trues -function initialize_grid(w, h) - local a = {} - for i = 1, h do - table.insert(a, {}) - for j = 1, w do - table.insert(a[i], true) +local function initialize_grid(w, h) + local a = {} + for i = 1, h do + table.insert(a, {}) + for j = 1, w do + table.insert(a[i], true) + end end - end - return a + return a end -- average of a and b -function avg(a, b) - return (a + b) / 2 +local function avg(a, b) + return (a + b) / 2 end - -dirs = { - {x = 0, y = -2}, -- north - {x = 2, y = 0}, -- east - {x = -2, y = 0}, -- west - {x = 0, y = 2}, -- south +local dirs = { + {x = 0, y = -2}, -- north + {x = 2, y = 0}, -- east + {x = -2, y = 0}, -- west + {x = 0, y = 2} -- south } -function make_maze(w, h) - w = w or 16 - h = h or 16 +local function make_maze(w, h) + local map = initialize_grid(w * 2 + 1, h * 2 + 1) - local map = initialize_grid(w*2+1, h*2+1) + local walk + walk = function(x, y) + map[y][x] = false - function walk(x, y) - map[y][x] = false - - local d = { 1, 2, 3, 4 } - shuffle(d) - for i, dirnum in ipairs(d) do - local xx = x + dirs[dirnum].x - local yy = y + dirs[dirnum].y - if map[yy] and map[yy][xx] then - map[avg(y, yy)][avg(x, xx)] = false - walk(xx, yy) - end + local d = {1, 2, 3, 4} + shuffle(d) + for i, dirnum in pairs(d) do + local xx = x + dirs[dirnum].x + local yy = y + dirs[dirnum].y + if map[yy] and map[yy][xx] then + map[avg(y, yy)][avg(x, xx)] = false + walk(xx, yy) + end + end end - end - walk(global.walk_seed_w, global.walk_seed_h) + walk(primitives.walk_seed_w, primitives.walk_seed_h) - local s = {} - for i = 1, h*2+1 do - for j = 1, w*2+1 do - if map[i][j] then - add_tile(i*cell_size,j*cell_size,cell_size,cell_size, true) - end + local s = {} + for i = 1, h * 2 + 1 do + for j = 1, w * 2 + 1 do + if map[i][j] then + add_tile(i * cell_size, j * cell_size, cell_size, cell_size, true) + end + end end - end - return table.concat(s) + return table.concat(s) end local function reduce_walls() - for x,_ in pairs(cells) do - for y,_ in pairs(cells[x]) do - if cells[x - cell_size] ~= nil and cells[x-cell_size][y] ~= 1 then - add_tile(x-wall_delta, y, wall_delta, cell_size, false) + for x, _ in pairs(cells) do + for y, _ in pairs(cells[x]) do + if cells[x - cell_size] ~= nil and cells[x - cell_size][y] ~= 1 then + add_tile(x - wall_delta, y, wall_delta, cell_size, false) + end + if cells[x + cell_size] ~= nil and cells[x + cell_size][y] ~= 1 then + add_tile(x + cell_size, y, wall_delta, cell_size, false) end - if cells[x + cell_size] ~= nil and cells[x + cell_size][y] ~= 1 then - add_tile(x + cell_size, y, wall_delta, cell_size, false) - end if cells[x] ~= nil and cells[x][y - cell_size] ~= 1 then - add_tile(x - wall_delta, y - wall_delta, cell_size + 2 * wall_delta , wall_delta, false) + add_tile(x - wall_delta, y - wall_delta, cell_size + 2 * wall_delta, wall_delta, false) end if cells[x] ~= nil and cells[x][y + cell_size] ~= 1 then add_tile(x - wall_delta, y + cell_size, cell_size + 2 * wall_delta, wall_delta, false) @@ -126,30 +149,42 @@ local function reduce_walls() end end end -function init() - if not global.walk_seed_w then global.walk_seed_w = math.random(1, 50)*2 end - if not global.rects then global.rects = {} end - if not global.walk_seed_h then global.walk_seed_h = math.random(1, 50)*2 end - if not global.shuffle_pool then - global.shuffle_pool = {} - for i=1,20000 do - global.shuffle_pool[i] = math.random(1, 4) + +local function remove_chunk(event) + local surface = event.surface + local tiles = {} + for x = event.area.left_top.x, event.area.right_bottom.x do + for y = event.area.left_top.y, event.area.right_bottom.y do + table.insert(tiles, {name = 'out-of-map', position = {x, y}}) end end - make_maze(50, 50) - reduce_walls() - render() + surface.set_tiles(tiles) end +Event.on_init( + function() + primitives.walk_seed_w = math.random(1, 50) * 2 + primitives.walk_seed_h = math.random(1, 50) * 2 + for i = 1, 20000 do + shuffle_pool[i] = math.random(1, 4) + end + make_maze(50, 50) + reduce_walls() + render() + end +) -first = true -function run_shape_module(event) - if first then - first = false - init() +Event.add( + defines.events.on_chunk_generated, + function(event) + if event.surface == RS.get_surface() then + local pos = event.area.left_top + if + math.abs(pos.x) > 10000 or math.abs(pos.y) > 10000 or + (rects[pos.x + primitives.max / 2 .. '/' .. pos.y + primitives.max / 2] == nil) + then + remove_chunk(event) + end + end end - local pos = event.area.left_top - if math.abs(pos.x) > 10000 or math.abs(pos.y) > 10000 or (global.rects[pos.x + global.max/2 .. "/" .. pos.y + global.max/2] == nil) then - removeChunk(event) - end -end +) diff --git a/map_gen/shared/chunk_utils.lua b/map_gen/shared/chunk_utils.lua deleted file mode 100644 index 7101aeea..00000000 --- a/map_gen/shared/chunk_utils.lua +++ /dev/null @@ -1,10 +0,0 @@ -function removeChunk(event) - local surface = event.surface - local tiles = {} - for x = event.area.left_top.x, event.area.right_bottom.x do - for y = event.area.left_top.y, event.area.right_bottom.y do - table.insert(tiles, {name = "out-of-map", position = {x,y}}) - end - end - surface.set_tiles(tiles) -end diff --git a/map_gen/shared/ent_functions.lua b/map_gen/shared/ent_functions.lua index ccbba485..83de8c58 100644 --- a/map_gen/shared/ent_functions.lua +++ b/map_gen/shared/ent_functions.lua @@ -1,6 +1,11 @@ +-- luacheck: ignore +-- This file contains many linting warnings and needs an overhaul +local RS = require 'map_gen.shared.redmew_surface' --allows any gen to access these functions -function place_entities(surface, entity_list) +local Public = {} + +function Public.place_entities(surface, entity_list) local directions = {defines.direction.north, defines.direction.east, defines.direction.south, defines.direction.west} for _, entity in pairs(entity_list) do local r = math.random(1,entity.chance) @@ -22,10 +27,10 @@ function place_entities(surface, entity_list) return false end -function auto_place_entity_around_target(entity, scan_radius, mode, density, surface) +function Public.auto_place_entity_around_target(entity, scan_radius, mode, density, surface) local x = entity.pos.x local y = entity.pos.y - if not surface then surface = game.surfaces[1] end + if not surface then surface = RS.get_surface() end if not scan_radius then scan_radius = 6 end if not entity then return end if not mode then mode = "ball" end @@ -213,9 +218,8 @@ function auto_place_entity_around_target(entity, scan_radius, mode, density, sur return false end -function create_entitie_cluster(name, pos, amount) - - local surface = game.surfaces[1] +function Public.create_entitie_cluster(name, pos, amount) + local surface = RS.get_surface() local entity = {} entity.pos = pos entity.name = name @@ -235,7 +239,7 @@ function create_entitie_cluster(name, pos, amount) return b, e end -function create_rock_cluster(pos, amount) +function Public.create_rock_cluster(pos, amount) if not pos then return false end if amount == nil then amount = 7 end local scan_radius = amount * 2 @@ -259,7 +263,7 @@ function create_rock_cluster(pos, amount) return b, e end -function create_tree_cluster(pos, amount) +function Public.create_tree_cluster(pos, amount) if not pos then return false end if amount == nil then amount = 7 end local scan_radius = amount * 2 @@ -288,10 +292,10 @@ function create_tree_cluster(pos, amount) return b, e end -function find_tile_placement_spot_around_target_position(tilename, position, mode, density) +function Public.find_tile_placement_spot_around_target_position(tilename, position, mode, density) local x = position.x local y = position.y - if not surface then surface = game.surfaces[1] end + if not surface then surface = RS.get_surface() end local scan_radius = 50 if not tilename then return end if not mode then mode = "ball" end @@ -514,15 +518,15 @@ function find_tile_placement_spot_around_target_position(tilename, position, mod return false end -function create_tile_cluster(tilename,position,amount) +function Public.create_tile_cluster(tilename,position,amount) local mode = "ball" local cluster_tiles = {} - local surface = game.surfaces[1] + local surface = RS.get_surface() local pos = position local x = pos.x local y = pos.y for i = 1, amount, 1 do - local b,x,y = find_tile_placement_spot_around_target_position(tilename, pos, mode) + local b,x,y = Public.find_tile_placement_spot_around_target_position(tilename, pos, mode) if b == true then if 1 == math.random(1,2) then pos.x = x @@ -533,3 +537,5 @@ function create_tile_cluster(tilename,position,amount) if i >= amount then return true,x,y end end end + +return Public diff --git a/map_gen/shared/redmew_surface.lua b/map_gen/shared/redmew_surface.lua new file mode 100644 index 00000000..0d1224e8 --- /dev/null +++ b/map_gen/shared/redmew_surface.lua @@ -0,0 +1,290 @@ +--[[ + Creates a custom surface for all redmew maps so that we can ignore all user input at time of world creation. + + Allows map makers to define the map gen settings, map settings, and difficulty settings in as much or as little details as they want. + The aim is to make this a very easy process for map makers, while eliminating the need for some of the existing builder functions. + For example by preventing ores from spawning we no longer need to manually scan for and remove ores. + + When you create a new map you're given many options. These options break into 3 categories which are not made explicitly + clear in the game itself: + map_gen_settings, map_settings, and difficulty_settings + + map_gen_settings: Only affect a given surface. These settings determine everything that surface is made of: + ores, tiles, entities, boundaries, etc. It also contains a less obvious setting: peaceful_mode. + + map_settings: Are kind of a misnomer since they apply to the game at large. Contain settings for pollution, enemy_evolution, enemy_expansion, + unit_group, steering, path_finder, and something called max_failed_behavior_count (shrug) + lastly, difficulty_settings + + difficulty_settings: contains only recipe_difficulty, technology_difficulty (not used in vanilla), and technology_price_multiplier + + In the 16.51 version of factorio's Map Generator page difficulty_settings make up the "Recipes/Technology" section of the + "Advanced settings" tab. map_settings make up the rest of that tab. + map_gen_settings are detemined by everything in the remaining 3 tabs (Basic settings, Resource settings, Terrain settings) + + Unless fed arguments via the public functions, this module will simply clone nauvis, respecting all user settings. + To pass settings to redmew_surface, each of the above-mentioned 3 settings components has a public function. + set_map_gen_settings, set_map_settings, and set_difficulty_settings + The functions all take a list of tables which contain settings. The tables then overwrite any existing user settings. + Therefore, for any settings not explicitly set the user's settings persist. + + Tables of settings can be constructed manually or can be taken from the resource files by the same names (resources/map_gen_settings, etc.) + + Example: to select a 4x tech cost you would call: + RS.set_difficulty_settings({difficulty_settings_presets.tech_x4}) + + It should be noted that tables earlier in the list will be overwritten by tables later in the list. + So in the following example the resulting tech cost would be 4, not 3. + + RS.set_difficulty_settings({difficulty_settings_presets.tech_x3, difficulty_settings_presets.tech_x4}) + + To create a map with no ores, no enemies, no pollution, no enemy evolution, 3x tech costs, and sand set to high we would use the following: + + -- We require redmew_surface to access the public functions and assign the table Public to the RS variable to access them easily. + local RS = require 'map_gen.shared.redmew_surface' + -- We require the resources tables so that we don't have to write settings components by hand. + local MGSP = require 'resources.map_gen_settings' -- map gen settings presets + local DSP = require 'resources.difficulty_settings' -- difficulty settings presets + local MSP = require 'resources.map_settings' -- map settings presets + + -- We create a custom table for the niche settings of wanting more sand + local extra_sand = { + autoplace_controls = { + sand = {frequency = 'high', size = 'high'} + } + } + + RS.set_map_gen_settings({MGSP.enemy_none, MGSP.ore_none, MGSP.oil_none, extra_sand}) + RS.set_difficulty_settings({DSP.tech_x3}) + RS.set_map_settings({MSP.enemy_evolution_off, MSP.pollution_off}) +]] +-- Dependencies +require 'util' +local Event = require 'utils.event' +local Game = require 'utils.game' +local Global = require 'utils.global' +local config = global.config.redmew_surface + +-- Localized functions +local insert = table.insert +local merge = util.merge +local format = string.format + +-- Constants +local set_warn_message = + 'set_%s has already been called. Calling this twice can lead to unexpected settings overwrites.' +local vanilla_surface_name = 'nauvis' +local redmew_surface_name = 'redmew' + +-- Local vars +local set_difficulty_settings_called +local set_map_gen_settings_called +local set_map_settings_called +local data = { + ['map_gen_settings_components'] = {}, + ['map_settings_components'] = {}, + ['difficulty_settings_components'] = {} +} + +local Public = {} + +-- Global tokens +-- The nil definitions are to document what data might exist. +local global_data = { + surface = nil, + first_player_position_check_override = nil +} + +Global.register( + global_data, + function(tbl) + global_data = tbl + end +) + +-- Local functions + +--- Add the tables inside components into the given data_table +local function combine_settings(components, data_table) + for _, v in pairs(components) do + insert(data_table, v) + end +end + +--- Sets up the difficulty settings +local function set_difficulty_settings() + local combined_difficulty_settings = merge(data.difficulty_settings_components) + for k, v in pairs(combined_difficulty_settings) do + game.difficulty_settings[k] = v + end +end + +--- Sets up the map settings +local function set_map_settings() + local combined_map_settings = merge(data.map_settings_components) + + -- Iterating through individual tables because game.map_settings is read-only + if combined_map_settings.pollution then + for k, v in pairs(combined_map_settings.pollution) do + game.map_settings.pollution[k] = v + end + end + if combined_map_settings.enemy_evolution then + for k, v in pairs(combined_map_settings.enemy_evolution) do + game.map_settings.enemy_evolution[k] = v + end + end + if combined_map_settings.enemy_expansion then + for k, v in pairs(combined_map_settings.enemy_expansion) do + game.map_settings.enemy_expansion[k] = v + end + end + if combined_map_settings.unit_group then + for k, v in pairs(combined_map_settings.unit_group) do + game.map_settings.unit_group[k] = v + end + end + if combined_map_settings.steering then + if combined_map_settings.steering.default then + for k, v in pairs(combined_map_settings.steering.default) do + game.map_settings.steering.default[k] = v + end + end + if combined_map_settings.steering.moving then + for k, v in pairs(combined_map_settings.steering.moving) do + game.map_settings.steering.moving[k] = v + end + end + end + if combined_map_settings.path_finder then + for k, v in pairs(combined_map_settings.path_finder) do + game.map_settings.path_finder[k] = v + end + end + if combined_map_settings.max_failed_behavior_count then + game.map_settings.max_failed_behavior_count = combined_map_settings.max_failed_behavior_count + end +end + +--- Creates a new surface with the settings provided by the map file and the player. +local function create_redmew_surface() + if not config.enabled then + -- we still need to set the surface so Public.get_surface() will work. + global_data.surface = game.surfaces[vanilla_surface_name] + return + end + + local surface + + if config.map_gen_settings then + -- Add the user's map gen settings as the first entry in the table + local combined_map_gen = {game.surfaces.nauvis.map_gen_settings} + -- Take the map's settings and add them into the table + for _, v in pairs(data.map_gen_settings_components) do + insert(combined_map_gen, v) + end + surface = game.create_surface(redmew_surface_name, merge(combined_map_gen)) + else + surface = game.create_surface(redmew_surface_name) + end + + global_data.surface = surface + + if config.difficulty then + set_difficulty_settings() + end + if config.map_settings then + set_map_settings() + end + + surface.request_to_generate_chunks({0, 0}, 4) + surface.force_generate_chunk_requests() +end + +--- Teleport the player to the redmew surface and if there is no suitable location, create a lab-white island. +local function player_created(event) + local player = Game.get_player_by_index(event.player_index) + local surface = global_data.surface + + local pos = surface.find_non_colliding_position('player', {0, 0}, 50, 1) + if pos and not global_data.first_player_position_check_override then + player.teleport(pos, surface) + else + -- if there's no position available within range or a map needs players at 0,0: create an island and place the player there + surface.set_tiles( + { + {name = 'lab-white', position = {-1, -1}}, + {name = 'lab-white', position = {-1, 0}}, + {name = 'lab-white', position = {0, -1}}, + {name = 'lab-white', position = {0, 0}} + } + ) + player.teleport({0, 0}, surface) + global_data.first_player_position_check_override = nil + end +end + +-- Public functions + +--- Sets components to the difficulty_settings_components table +-- It is an error to call this twice as later calls will overwrite earlier ones if values overlap. +-- @param components list of difficulty settings components (usually from resources.difficulty_settings) +function Public.set_difficulty_settings(components) + if set_difficulty_settings_called then + log(format(set_warn_message, 'difficulty_settings')) + end + combine_settings(components, data.difficulty_settings_components) + set_difficulty_settings_called = true +end + +--- Adds components to the map_gen_settings_components table +-- It is an error to call this twice as later calls will overwrite earlier ones if values overlap. +-- @param components
list of map gen components (usually from resources.map_gen_settings) +function Public.set_map_gen_settings(components) + if set_map_gen_settings_called then + log(format(set_warn_message, 'map_gen_settings')) + end + combine_settings(components, data.map_gen_settings_components) + set_map_gen_settings_called = true +end + +--- Adds components to the map_settings_components table +-- It is an error to call this twice as later calls will overwrite earlier ones if values overlap. +-- @param components
list of map setting components (usually from resources.map_settings) +function Public.set_map_settings(components) + if set_map_settings_called then + log(format(set_warn_message, 'map_settings')) + end + combine_settings(components, data.map_settings_components) + set_map_settings_called = true +end + +--- Returns the LuaSurface that the map is created on. +-- Not safe to call outside of events. +function Public.get_surface() + return global_data.surface +end + +--- Returns the string name of the surface that the map is created on. +-- This can safely be called at any time. +function Public.get_surface_name() + if config.enabled then + return redmew_surface_name + else + return vanilla_surface_name + end +end + +--- Allows maps to set first_player_position_check_override +-- This is a hack for diggy and forces the first created player to be teleported to {0, 0} and skip the collision check. +function Public.set_first_player_position_check_override(bool) + global_data.first_player_position_check_override = bool +end + +Event.on_init(create_redmew_surface) + +if config.enabled then + Event.add(defines.events.on_player_created, player_created) +end + +return Public diff --git a/map_layout.lua b/map_layout.lua index 436cccc2..a86a77ed 100644 --- a/map_layout.lua +++ b/map_layout.lua @@ -5,8 +5,8 @@ If you want to add your own module, just add it to the others in this file and your run_*type*_module(event) function will be called. --]] local b = require 'map_gen.shared.builders' +local RS = require 'map_gen.shared.redmew_surface' require 'utils.table' -require 'map_gen.shared.perlin_noise' global.map = {} global.map.terraforming = {} @@ -161,7 +161,7 @@ end if shape then local surfaces = { - ['nauvis'] = shape, + [RS.get_surface_name()] = shape, } require('map_gen.shared.generate')({surfaces = surfaces, regen_decoratives = regen_decoratives, tiles_per_tick = tiles_per_tick}) diff --git a/resources/difficulty_settings.lua b/resources/difficulty_settings.lua new file mode 100644 index 00000000..6a1db0bf --- /dev/null +++ b/resources/difficulty_settings.lua @@ -0,0 +1,72 @@ +-- technology_difficulty has no effect in vanilla +return { + -- the default table is included as a reference but also to give the option of overwriting all user settings + default = { + recipe_difficulty = defines.difficulty_settings.recipe_difficulty.normal, + technology_difficulty = defines.difficulty_settings.technology_difficulty.normal, + technology_price_multiplier = 1 + }, + -- turns on expensive recipes + expensive_recipe = { + recipe_difficulty = defines.difficulty_settings.recipe_difficulty.expensive + }, + -- the following are tech cost reducers + ['tech_x0.25'] = { + technology_price_multiplier = 0.25 + }, + ['tech_x0.5'] = { + technology_price_multiplier = 0.5 + }, + ['tech_x0.75'] = { + technology_price_multiplier = 0.75 + }, + -- the following are all tech cost multipliers + tech_x2 = { + technology_price_multiplier = 2 + }, + tech_x3 = { + technology_price_multiplier = 3 + }, + tech_x4 = { + technology_price_multiplier = 4 + }, + tech_x5 = { + technology_price_multiplier = 5 + }, + tech_x6 = { + technology_price_multiplier = 6 + }, + tech_x8 = { + technology_price_multiplier = 8 + }, + tech_x10 = { + technology_price_multiplier = 10 + }, + tech_x12 = { + technology_price_multiplier = 12 + }, + tech_x14 = { + technology_price_multiplier = 14 + }, + tech_x16 = { + technology_price_multiplier = 16 + }, + tech_x20 = { + technology_price_multiplier = 20 + }, + tech_x50 = { + technology_price_multiplier = 50 + }, + tech_x100 = { + technology_price_multiplier = 100 + }, + tech_x250 = { + technology_price_multiplier = 250 + }, + tech_x500 = { + technology_price_multiplier = 500 + }, + tech_x1000 = { + technology_price_multiplier = 1000 + } +} diff --git a/resources/map_gen_settings.lua b/resources/map_gen_settings.lua new file mode 100644 index 00000000..28450a18 --- /dev/null +++ b/resources/map_gen_settings.lua @@ -0,0 +1,330 @@ +--[[ The easiest way to create a preset to add to this file is to use factorio itself. Create a new world + (vanilla, not scenario) and configure the settings you want. When you launch the game, you can run the following: + /c + local str = serpent.block(game.surfaces.nauvis.map_gen_settings) + game.write_file('map_gen_settings.lua', str) + + This will output a file with a table that you can add to this resources file or into your specific map. + In either case, make sure to set seed to nil unless you want your map to be *exactly* the same each time. + The expectation is that all changes that deviate from default generation are noted. + Water size and frequency is not denoted as such. Instead water size = water and water frequency = terrain_segmentation +]] +return { + -- the default table is included as a reference but also to give the option of overwriting all user settings + default = { + autoplace_controls = { + coal = { + frequency = 'normal', + richness = 'normal', + size = 'normal' + }, + ['copper-ore'] = { + frequency = 'normal', + richness = 'normal', + size = 'normal' + }, + ['crude-oil'] = { + frequency = 'normal', + richness = 'normal', + size = 'normal' + }, + desert = { + frequency = 'normal', + richness = 'normal', + size = 'normal' + }, + dirt = { + frequency = 'normal', + richness = 'normal', + size = 'normal' + }, + ['enemy-base'] = { + frequency = 'normal', + richness = 'normal', + size = 'normal' + }, + grass = { + frequency = 'normal', + richness = 'normal', + size = 'normal' + }, + ['iron-ore'] = { + frequency = 'normal', + richness = 'normal', + size = 'normal' + }, + sand = { + frequency = 'normal', + richness = 'normal', + size = 'normal' + }, + stone = { + frequency = 'normal', + richness = 'normal', + size = 'normal' + }, + trees = { + frequency = 'normal', + richness = 'normal', + size = 'normal' + }, + ['uranium-ore'] = { + frequency = 'normal', + richness = 'normal', + size = 'normal' + } + }, + cliff_settings = { + cliff_elevation_0 = 10, + cliff_elevation_interval = 10, + name = 'cliff' + }, + height = 2000000, + peaceful_mode = false, + starting_area = 'normal', + terrain_segmentation = 'normal', + water = 'normal', + width = 2000000 + }, + -- no enemies + enemy_none = { + autoplace_controls = { + ['enemy-base'] = { + frequency = 'normal', + richness = 'normal', + size = 'none' + } + } + }, + -- high frequency and big size enemies + enemy_high = { + autoplace_controls = { + ['enemy-base'] = { + frequency = 'high', + richness = 'normal', + size = 'high' + } + } + }, + -- very high frequency and very big size enemies + enemy_very_high = { + autoplace_controls = { + ['enemy-base'] = { + frequency = 'very-high', + richness = 'normal', + size = 'very-high' + } + } + }, + -- no ores + ore_none = { + autoplace_controls = { + coal = { + frequency = 'normal', + richness = 'normal', + size = 'none' + }, + ['copper-ore'] = { + frequency = 'normal', + richness = 'normal', + size = 'none' + }, + ['iron-ore'] = { + frequency = 'normal', + richness = 'normal', + size = 'none' + }, + stone = { + frequency = 'normal', + richness = 'normal', + size = 'none' + }, + ['uranium-ore'] = { + frequency = 'normal', + richness = 'normal', + size = 'none' + } + } + }, + -- no oil + oil_none = { + autoplace_controls = { + ['crude-oil'] = { + frequency = 'normal', + richness = 'normal', + size = 'none' + } + } + }, + -- no ores, no oil + ore_oil_none = { + autoplace_controls = { + coal = { + frequency = 'normal', + richness = 'normal', + size = 'none' + }, + ['copper-ore'] = { + frequency = 'normal', + richness = 'normal', + size = 'none' + }, + ['crude-oil'] = { + frequency = 'normal', + richness = 'normal', + size = 'none' + }, + ['iron-ore'] = { + frequency = 'normal', + richness = 'normal', + size = 'none' + }, + stone = { + frequency = 'normal', + richness = 'normal', + size = 'none' + }, + ['uranium-ore'] = { + frequency = 'normal', + richness = 'normal', + size = 'none' + } + } + }, + -- no water + water_none = { + terrain_segmentation = 'normal', + water = 'none' + }, + -- very low water + water_very_low = { + terrain_segmentation = 'very-low', + water = 'very-low' + }, + -- no cliffs + cliff_none = { + cliff_settings = { + cliff_elevation_0 = 1024, + cliff_elevation_interval = 10, + name = 'cliff' + } + }, + -- normal cliffs + cliff_normal = { + name = 'cliff', + cliff_elevation_0 = 10, + cliff_elevation_interval = 10 + }, + -- cliffs to very high frequency, very big size + cliff_very_high = { + cliff_settings = { + cliff_elevation_0 = 2.5000572204589844, + cliff_elevation_interval = 2.5000572204589844, + name = 'cliff' + } + }, + -- cliffs to very high frequency, very big size + tree_none = { + autoplace_controls = { + trees = { + frequency = 'normal', + richness = 'normal', + size = 'none' + } + } + }, + -- cliffs to very high frequency, very big size + tree_very_high = { + autoplace_controls = { + trees = { + frequency = 'very-high', + richness = 'very-high', + size = 'very-high' + } + } + }, + -- starting area to very low + starting_area_very_low = { + starting_area = 'very-low' + }, + -- peaceful mode on + peaceful_mode_on = { + peaceful_mode = false + }, + -- random seed, in case you need/want the seed to be unique from nauvis + unique_seed = { + seed = nil + }, + -- grass only + grass_only = { + autoplace_controls = { + grass = {frequency = 'normal', size = 'normal', richness = 'normal'}, + desert = {frequency = 'normal', size = 'none', richness = 'normal'}, + dirt = {frequency = 'normal', size = 'none', richness = 'normal'}, + sand = {frequency = 'normal', size = 'none', richness = 'normal'} + } + }, + -- desert only + desert_only = { + autoplace_controls = { + grass = {frequency = 'normal', size = 'none', richness = 'normal'}, + desert = {frequency = 'normal', size = 'normal', richness = 'normal'}, + dirt = {frequency = 'normal', size = 'none', richness = 'normal'}, + sand = {frequency = 'normal', size = 'none', richness = 'normal'} + } + }, + -- dirt only + dirt_only = { + autoplace_controls = { + grass = {frequency = 'normal', size = 'none', richness = 'normal'}, + desert = {frequency = 'normal', size = 'none', richness = 'normal'}, + dirt = {frequency = 'normal', size = 'normal', richness = 'normal'}, + sand = {frequency = 'normal', size = 'none', richness = 'normal'} + } + }, + -- sand only + sand_only = { + autoplace_controls = { + grass = {frequency = 'normal', size = 'none', richness = 'normal'}, + desert = {frequency = 'normal', size = 'none', richness = 'normal'}, + dirt = {frequency = 'normal', size = 'none', richness = 'normal'}, + sand = {frequency = 'normal', size = 'normal', richness = 'normal'} + } + }, + -- will generate a world with only water (useful for maps that want full terrain control and no entities on the surface) + waterworld = { + autoplace_controls = { + desert = { + frequency = 'normal', + richness = 'normal', + size = 'none' + }, + dirt = { + frequency = 'normal', + richness = 'normal', + size = 'none' + }, + grass = { + frequency = 'normal', + richness = 'normal', + size = 'none' + }, + sand = { + frequency = 'normal', + richness = 'normal', + size = 'none' + } + }, + starting_points = { + { + x = 0, + y = 0 + } + } + }, + -- creates a 1x1 world border, this will prevent chunks from being generated + void = { + height = 1, + width = 1 + } +} diff --git a/resources/map_settings.lua b/resources/map_settings.lua new file mode 100644 index 00000000..c18de210 --- /dev/null +++ b/resources/map_settings.lua @@ -0,0 +1,186 @@ +return { + -- the default table is included as a reference but also to give the option of overwriting all user settings + default = { + pollution = { + enabled = true, + diffusion_ratio = 0.02, + min_to_diffuse = 15, + ageing = 1, + expected_max_per_chunk = 7000, + min_to_show_per_chunk = 700, + min_pollution_to_damage_trees = 3500, + pollution_with_max_forest_damage = 10000, + pollution_per_tree_damage = 2000, + pollution_restored_per_tree_damage = 500, + max_pollution_to_restore_trees = 1000 + }, + enemy_evolution = { + enabled = true, + time_factor = 0.000004, + destroy_factor = 0.002, + pollution_factor = 0.000015 + }, + enemy_expansion = { + enabled = true, + max_expansion_distance = 7, + friendly_base_influence_radius = 2, + enemy_building_influence_radius = 2, + building_coefficient = 0.1, + other_base_coefficient = 2.0, + neighbouring_chunk_coefficient = 0.5, + neighbouring_base_chunk_coefficient = 0.4, + max_colliding_tiles_coefficient = 0.9, + settler_group_min_size = 5, + settler_group_max_size = 20, + min_expansion_cooldown = 4 * 3600, + max_expansion_cooldown = 60 * 3600 + }, + unit_group = { + min_group_gathering_time = 3600, + max_group_gathering_time = 10 * 3600, + max_wait_time_for_late_members = 2 * 3600, + max_group_radius = 30.0, + min_group_radius = 5.0, + max_member_speedup_when_behind = 1.4, + max_member_slowdown_when_ahead = 0.6, + max_group_slowdown_factor = 0.3, + max_group_member_fallback_factor = 3, + member_disown_distance = 10, + tick_tolerance_when_member_arrives = 60, + max_gathering_unit_groups = 30, + max_unit_group_size = 200 + }, + steering = { + default = { + radius = 1.2, + separation_force = 0.005, + separation_factor = 1.2, + force_unit_fuzzy_goto_behavior = false + }, + moving = { + radius = 3, + separation_force = 0.01, + separation_factor = 3, + force_unit_fuzzy_goto_behavior = false + } + }, + path_finder = { + fwd2bwd_ratio = 5, + goal_pressure_ratio = 2, + max_steps_worked_per_tick = 100, + use_path_cache = true, + short_cache_size = 5, + long_cache_size = 25, + short_cache_min_cacheable_distance = 10, + short_cache_min_algo_steps_to_cache = 50, + long_cache_min_cacheable_distance = 30, + cache_max_connect_to_cache_steps_multiplier = 100, + cache_accept_path_start_distance_ratio = 0.2, + cache_accept_path_end_distance_ratio = 0.15, + negative_cache_accept_path_start_distance_ratio = 0.3, + negative_cache_accept_path_end_distance_ratio = 0.3, + cache_path_start_distance_rating_multiplier = 10, + cache_path_end_distance_rating_multiplier = 20, + stale_enemy_with_same_destination_collision_penalty = 30, + ignore_moving_enemy_collision_distance = 5, + enemy_with_different_destination_collision_penalty = 30, + general_entity_collision_penalty = 10, + general_entity_subsequent_collision_penalty = 3, + max_clients_to_accept_any_new_request = 10, + max_clients_to_accept_short_new_request = 100, + direct_distance_to_consider_short_request = 100, + short_request_max_steps = 1000, + short_request_ratio = 0.5, + min_steps_to_check_path_find_termination = 2000, + start_to_goal_cost_multiplier_to_terminate_path_find = 500.0 + }, + max_failed_behavior_count = 3 + }, + -- no pollution + pollution_off = { + pollution = { + enabled = false + } + }, + -- decreases the spread of pollution and increases the absorption per chunk of land + pollution_decreased_per_chunk = { + pollution = { + diffusion_ratio = 0.01, + min_to_diffuse = 30, + ageing = 2 + } + }, + -- tough to spread pollution, pollution rapidly decayse: for venus + pollution_hard_to_spread = { + enabled = true, + diffusion_ratio = 0.01, + min_to_diffuse = 200, + ageing = 5 + }, + -- increases the ability of trees to suck up pollution + pollution_decreased_per_tree = { + pollution = { + pollution_with_max_forest_damage = 20000, + pollution_per_tree_damage = 4000, + max_pollution_to_restore_trees = 2000 + } + }, + -- no enemy evolution + enemy_evolution_off = { + enemy_evolution = { + enabled = false + } + }, + -- evolution from all factors x2 + enemy_evolution_x2 = { + enemy_evolution = { + enabled = true, + time_factor = 0.000008, + destroy_factor = 0.004, + pollution_factor = 0.000030 + } + }, + -- 3x cost for pollution, all else 1x + enemy_evolution_punishes_pollution = { + enemy_evolution = { + enabled = true, + time_factor = 0.000004, + destroy_factor = 0.002, + pollution_factor = 0.000045 + } + }, + -- 3x cost for destroying spawners, all else 1x + enemy_evolution_punishes_destruction = { + enemy_evolution = { + enabled = true, + time_factor = 0.000004, + destroy_factor = 0.006, + pollution_factor = 0.000015 + } + }, + -- no enemy expansion + enemy_expansion_off = { + enemy_expansion = { + enabled = false + } + }, + -- should increase the fequency with which enemies expand + enemy_expansion_frequency_x4 = { + enemy_expansion = { + enabled = true, + min_expansion_cooldown = 1 * 3600, + max_expansion_cooldown = 15 * 3600 + } + }, + -- biters will expand to more chunks and will be more densely packed + enemy_expansion_aggressive = { + enemy_expansion = { + enabled = true, + max_expansion_distance = 21, + friendly_base_influence_radius = 1, + enemy_building_influence_radius = 1, + settler_group_min_size = 1, + settler_group_max_size = 10 + } + } +} diff --git a/utils/event_core.lua b/utils/event_core.lua index 600be1b1..edaa542e 100644 --- a/utils/event_core.lua +++ b/utils/event_core.lua @@ -37,6 +37,9 @@ local function on_init() local handlers = event_handlers[init_event_name] call_handlers(handlers) + event_handlers[init_event_name] = nil + event_handlers[load_event_name] = nil + Public.runtime = true end @@ -44,6 +47,9 @@ local function on_load() local handlers = event_handlers[load_event_name] call_handlers(handlers) + event_handlers[init_event_name] = nil + event_handlers[load_event_name] = nil + Public.runtime = true end diff --git a/utils/global.lua b/utils/global.lua index e173075a..de7a33cf 100644 --- a/utils/global.lua +++ b/utils/global.lua @@ -3,44 +3,31 @@ local Token = require 'utils.token' local Global = {} -local load_data = {} -local init_data = {} - function Global.register(tbl, callback) local token = Token.register_global(tbl) - table.insert(load_data, {callback = callback, token = token}) + + Event.on_load( + function() + callback(Token.get_global(token)) + end + ) end function Global.register_init(tbl, init_handler, callback) local token = Token.register_global(tbl) - table.insert(load_data, {callback = callback, token = token}) - table.insert(init_data, {token = token, init_handler = init_handler, callback = callback}) + Event.on_init( + function() + init_handler(tbl) + callback(tbl) + end + ) + + Event.on_load( + function() + callback(Token.get_global(token)) + end + ) end -Event.on_load( - function() - for _, d in ipairs(load_data) do - local tbl = Token.get_global(d.token) - d.callback(tbl) - end - - load_data = nil - init_data = nil - end -) - -Event.on_init( - function() - for _, d in ipairs(init_data) do - local tbl = Token.get_global(d.token) - d.init_handler(tbl) - d.callback(tbl) - end - - load_data = nil - init_data = nil - end -) - return Global