diff --git a/.luacheckrc b/.luacheckrc index cf3c9744c..fa2fe22ab 100644 --- a/.luacheckrc +++ b/.luacheckrc @@ -36,7 +36,7 @@ -- For more information, please refer to -- ]] --- Current Factorio Version 0.17.0, luacheck version 0.23.0 +-- Current Factorio Version 2.1.9, luacheck version 1.1.1 ------------------------------------------------------------------------------- --[Set Defaults]-- @@ -217,6 +217,7 @@ stds.factorio_control = { 'get_event_order', 'level', 'mod_name', + 'new_notification_queue', 'on_configuration_changed', 'raise_biter_base_built', 'raise_console_chat', @@ -261,6 +262,7 @@ stds.factorio_control = { 'draw_arc', 'draw_polygon', 'draw_sprite', + 'draw_animation', 'draw_light', 'destroy', 'is_font_valid', @@ -340,7 +342,9 @@ stds.factorio_control = { 'get_intensity', 'set_intensity', 'get_minimum_darkness', - 'set_minimum_darkness' + 'set_minimum_darkness', + 'get_light_mode', + 'set_light_mode' } }, @@ -349,15 +353,24 @@ stds.factorio_control = { read_only = true, fields = { "check_prototype_translations", + "compare_versions", + "create_profiler", "decode_string", "direction_to_string", "encode_string", "evaluate_expression", + "game_version", + "is_valid_ambient_sound", + "is_valid_animation_path", "is_valid_sound_path", "is_valid_sprite_path", "json_to_table", + "multilingual_to_lower", "parse_map_exchange_string", + "recv_udp", "remove_path", + "send_udp", + "stage", "table_to_json", "write_file", } @@ -370,13 +383,14 @@ stds.factorio_control = { other_fields = false, read_only = false, fields = { + "allow_debug_settings", "auto_save", "ban_player", - "check_consistency", + "check_consistency", "create_force", - "create_profiler", "create_random_generator", "create_surface", + "delete_blueprint_library", "delete_surface", "desync_players", "disable_replay", @@ -399,6 +413,7 @@ stds.factorio_control = { "mute_player", "planet", "planets", + "play_music", "play_sound", "print_stack_size", "print", @@ -503,6 +518,7 @@ stds.factorio_control = { technology = {read_only = true, other_fields = true}, tile = {read_only = true, other_fields = true}, trivial_smoke = {read_only = true, other_fields = true}, + utility_constants = {read_only = true, other_fields = true}, virtual_signal = {read_only = true, other_fields = true}, "max_beacon_supply_area_distance", "max_electric_pole_connection_distance", @@ -841,6 +857,45 @@ stds.factorio_defines = { 'wall' } }, + constant = { + fields = { + 'default_icon_size' + } + }, + electric_interface_mode = { + fields = { + 'accumulator', + 'primary_input', + 'primary_output', + 'secondary_input', + 'secondary_output', + 'solar_output', + 'tertiary_input', + 'tertiary_input_output', + 'tertiary_output' + } + }, + inventory_actions = { + fields = { + 'cursor_split', + 'cursor_transfer', + 'inventory_split', + 'inventory_transfer', + 'open_item', + 'open_mod_item', + 'send_stack_to_trash', + 'send_stacks_to_trash', + 'stack_split', + 'stack_transfer' + } + }, + target_type = { + fields = { + 'electric_network', + 'electric_sub_network', + 'force' + } + }, command = { fields = { 'attack', @@ -921,6 +976,16 @@ stds.factorio_defines = { } } }, + radar = { + fields = { + mode = { + fields = { + 'surface', + 'universe' + } + } + } + }, train_stop = { fields = { circuit_mode_of_operation = { @@ -947,19 +1012,23 @@ stds.factorio_defines = { fields = { 'accumulator', 'arithmetic_combinator', + 'boiler', 'constant_combinator', 'container', 'decider_combinator', 'generic_on_off', + 'heat_pipe', 'inserter', + 'lab', 'lamp', + 'land_mine', 'logistic_container', 'mining_drill', 'programmable_speaker', 'rail_chain_signal', 'rail_signal', 'roboport', - 'storage_tank', + 'single_fluid_box', 'train_stop', 'transport_belt', 'wall' @@ -1093,6 +1162,11 @@ stds.factorio_defines = { 'waiting_to_launch_rocket', 'waiting_for_source_items', 'waiting_for_space_in_destination', + 'hatches_blocked_by_elevated_rail', + 'too_far_from_pad_to_unload', + 'waiting_for_upgrade', + 'waiting_to_clear_drop_slots', + 'armed', } }, render_mode = { @@ -1108,6 +1182,7 @@ stds.factorio_defines = { 'on_ai_command_completed', 'on_area_cloned', 'on_biter_base_built', + 'on_blueprint_settings_pasted', 'on_built_entity', 'on_cancelled_deconstruction', 'on_cancelled_upgrade', @@ -1138,8 +1213,14 @@ stds.factorio_defines = { 'on_gui_checked_state_changed', 'on_gui_click', 'on_gui_closed', + 'on_gui_confirmed', 'on_gui_elem_changed', + 'on_gui_hover', + 'on_gui_inventory_action', + 'on_gui_leave', + 'on_gui_location_changed', 'on_gui_opened', + 'on_gui_selected_tab_changed', 'on_gui_selection_state_changed', 'on_gui_switch_state_changed', 'on_gui_text_changed', @@ -1163,6 +1244,7 @@ stds.factorio_defines = { 'on_player_changed_surface', 'on_player_cheat_mode_disabled', 'on_player_cheat_mode_enabled', + 'on_player_color_changed', 'on_player_configured_blueprint', 'on_player_controller_changed', 'on_player_crafted_item', @@ -1185,6 +1267,7 @@ stds.factorio_defines = { 'on_player_mined_entity', 'on_player_mined_item', 'on_player_mined_tile', + 'on_player_music_changed', 'on_player_muted', 'on_player_pipette', 'on_player_placed_equipment', @@ -1253,6 +1336,7 @@ stds.factorio_defines = { 'on_train_schedule_changed', 'on_trigger_created_entity', 'on_trigger_fired_artillery', + 'on_udp_packet_received', 'on_undo_applied', 'on_unit_added_to_group', 'on_unit_group_created', @@ -1286,6 +1370,7 @@ stds.factorio_defines = { gui_type = { fields = { 'achievement', + 'alerts_config', 'blueprint_library', 'bonus', 'controller', @@ -1320,6 +1405,7 @@ stds.factorio_defines = { 'achievement_gui', 'additional_entity_info_gui', 'admin_gui', + 'alerts_config_gui', 'arithmetic_combinator_gui', 'armor_gui', 'assembling_machine_gui', @@ -1328,6 +1414,7 @@ stds.factorio_defines = { 'blueprint_book_gui', 'blueprint_library_gui', 'blueprint_setup_gui', + 'boiler_gui', 'bonus_gui', 'burner_equipment_gui', 'car_gui', @@ -1336,6 +1423,7 @@ stds.factorio_defines = { 'controller_gui', 'decider_combinator_gui', 'deconstruction_item_gui', + 'electric_energy_interface_equipment_gui', 'electric_energy_interface_gui', 'electric_network_gui', 'entity_variations_gui', @@ -1360,6 +1448,7 @@ stds.factorio_defines = { 'power_switch_gui', 'production_gui', 'programmable_speaker_gui', + 'radar_gui', 'rail_chain_signal_gui', 'rail_signal_gui', 'reactor_gui', @@ -1371,7 +1460,6 @@ stds.factorio_defines = { 'spider_vehicle_gui', 'splitter_gui', 'standalone_character_gui', - 'storage_tank_gui', 'tile_variations_gui', 'train_gui', 'train_stop_gui', @@ -1565,11 +1653,11 @@ stds.factorio_defines = { }, inventory = { fields = { + 'agricultural_tower_input', + 'agricultural_tower_output', 'artillery_turret_ammo', 'artillery_wagon_ammo', - 'assembling_machine_input', - 'assembling_machine_modules', - 'assembling_machine_output', + 'asteroid_collector_output', 'beacon_modules', 'burnt_result', 'car_ammo', @@ -1577,14 +1665,17 @@ stds.factorio_defines = { 'cargo_wagon', 'character_corpse', 'chest', + 'crafter_input', + 'crafter_modules', + 'crafter_output', + 'crafter_trash', 'fuel', - 'furnace_modules', - 'furnace_result', - 'furnace_source', 'god_main', 'item_main', 'lab_input', 'lab_modules', + 'lab_trash', + 'linked_container_main', 'mining_drill_modules', 'character_ammo', 'character_armor', @@ -1592,6 +1683,7 @@ stds.factorio_defines = { 'character_main', 'character_trash', 'character_vehicle', + 'proxy_main', 'roboport_material', 'roboport_robot', 'robot_cargo', diff --git a/features/auto_stash.lua b/features/auto_stash.lua index 45f4bfcb7..32fc28987 100644 --- a/features/auto_stash.lua +++ b/features/auto_stash.lua @@ -163,7 +163,7 @@ local function get_nearby_chests(player, a, furnace, wagon) if furnace then container_type = { 'furnace' } - inventory_type = defines.inventory.furnace_source + inventory_type = defines.inventory.crafter_input end if wagon then container_type = { 'cargo-wagon', 'logistic-container' } @@ -570,8 +570,11 @@ function Public.auto_stash(player, event) this.floating_text_y_offsets = {} local hotbar_items = {} + local quick_bar_width = player.quick_bar_width for i = 1, 100, 1 do - local prototype = player.get_quick_bar_slot(i) + local page = math.ceil(i / quick_bar_width) + local slot = i - (page - 1) * quick_bar_width + local prototype = player.get_quick_bar_slot(page, slot) if prototype then hotbar_items[prototype.name] = true end diff --git a/features/dump_offline_inventories.lua b/features/dump_offline_inventories.lua index 2b946b4fa..8aba60d5f 100644 --- a/features/dump_offline_inventories.lua +++ b/features/dump_offline_inventories.lua @@ -71,7 +71,7 @@ local function spawn_player_corpse(player, banned, timeout_minutes) inventory_size = #inv_contents, player_index = player_index } - corpse.active = false + corpse.disabled_by_script = true local inv_corpse = corpse.get_inventory(defines.inventory.character_corpse) for _, item_stack in pairs(inv_contents) do diff --git a/features/enemy_turret.lua b/features/enemy_turret.lua index 6fd1876cb..465b533cc 100644 --- a/features/enemy_turret.lua +++ b/features/enemy_turret.lua @@ -100,7 +100,7 @@ function Public.register(entity, refill_name) if data.is_fluid then data.fluid_stack = { name = data.refill, - amount = data.entity.fluidbox.get_capacity(1) or 100 + amount = data.entity.get_fluid_capacity(1) or 100 } else data.item_stack = { diff --git a/features/infinite_storage_chest.lua b/features/infinite_storage_chest.lua index 1ce051894..b2d92d428 100644 --- a/features/infinite_storage_chest.lua +++ b/features/infinite_storage_chest.lua @@ -37,7 +37,7 @@ local function built_entity(event) return end - entity.active = false + entity.disabled_by_script = true chests[entity.unit_number] = {entity = entity, storage = {}} end diff --git a/features/player_quick_bars.lua b/features/player_quick_bars.lua index 609886a81..8a9747f5d 100644 --- a/features/player_quick_bars.lua +++ b/features/player_quick_bars.lua @@ -27,6 +27,15 @@ Global.register( end ) +--- Converts a linear 1-100 quick bar slot index into the page/slot pair +-- expected by LuaPlayer::get/set_quick_bar_slot. +local function quick_bar_page_slot(player, i) + local width = player.quick_bar_width + local page = math.ceil(i / width) + local slot = i - (page - 1) * width + return page, slot +end + --- Scans all quickbar_slots into a table, then saves that table server-side local function save_bars(_, player) if not primitives.server_available then @@ -37,7 +46,8 @@ local function save_bars(_, player) local bars = {} for i = 1, quickbar_slots do - local item_prot = player.get_quick_bar_slot(i) + local page, slot = quick_bar_page_slot(player, i) + local item_prot = player.get_quick_bar_slot(page, slot) if item_prot then bars[i] = item_prot.name end @@ -81,7 +91,8 @@ local set_bars_callback = for i = 1, quickbar_slots do item = validate_entry(bars[i], item_prototypes, player) if item then - player.set_quick_bar_slot(i, item) + local page, slot = quick_bar_page_slot(player, i) + player.set_quick_bar_slot(page, slot, item) end end end diff --git a/features/snake/game.lua b/features/snake/game.lua index e8e014a24..9c2835c32 100644 --- a/features/snake/game.lua +++ b/features/snake/game.lua @@ -110,7 +110,7 @@ local function spawn_food() entity = surface.create_entity({name = 'compilatron', position = pos, force = 'neutral', direction = random(7)}) - entity.active = false + entity.disabled_by_script = true entity.destructible = false food_count = food_count + 1 @@ -213,8 +213,8 @@ local function tick_snake(index, snake) player.character = nil player.character = tail_entity tail_entity.walking_state = walking_state - head.entity.active = false - tail_entity.active = true + head.entity.disabled_by_script = true + tail_entity.disabled_by_script = false local entity = find_entity('compilatron', new_head_position) if entity and entity.valid then @@ -224,7 +224,7 @@ local function tick_snake(index, snake) surface.create_entity {name = 'character', position = cords_map[tail_cord.x][tail_cord.y], force = 'player'} entity.character_running_speed_modifier = -1 entity.color = player.color - entity.active = false + entity.disabled_by_script = true entity.destructible = false push_to_end(snake_queue, {entity = entity, cord = tail_cord}) diff --git a/features/turret_active_delay.lua b/features/turret_active_delay.lua index 5bf09f7b9..e264c4143 100644 --- a/features/turret_active_delay.lua +++ b/features/turret_active_delay.lua @@ -33,7 +33,7 @@ entity_built_callback = end if entity.health == 0 then - entity.active = true + entity.disabled_by_script = false entity.die('neutral') return end @@ -41,7 +41,7 @@ entity_built_callback = local tick = data.tick local now = game.tick if now >= tick then - entity.active = true + entity.disabled_by_script = false return end @@ -76,7 +76,7 @@ local function entity_built(event) return end - entity.active = false + entity.disabled_by_script = true set_timeout_in_ticks( update_rate, entity_built_callback, diff --git a/locale/en/redmew_utils.cfg b/locale/en/redmew_utils.cfg index 646db94bb..56a3a4166 100644 --- a/locale/en/redmew_utils.cfg +++ b/locale/en/redmew_utils.cfg @@ -29,6 +29,12 @@ print_admins=__1__(ADMIN) __2__: __3__ [gui_util] button_tooltip=[font=var][color=1,0.9,0.75]Toolbar[/color][/font]\nCollapse / Expand the toolbar +[mod_compatibility] +recommended_title=Recommended mods missing +recommended_message=The following mods are recommended for the best experience but are not installed:\n__1__ +discouraged_title=Discouraged mods detected +discouraged_message=The following installed mods are discouraged and are not guaranteed to work correctly:\n__1__ + [redmew_settings_util] fraction_invalid_value=fraction setting type requires the input to be a valid number between 0 and 1. integer_invalid_value=integer setting type requires the input to be a valid number. diff --git a/map_gen/data/.map_previews/danger_ore_omnimatter_maze.png b/map_gen/data/.map_previews/danger_ore_omnimatter_maze.png new file mode 100644 index 000000000..992d4488c Binary files /dev/null and b/map_gen/data/.map_previews/danger_ore_omnimatter_maze.png differ diff --git a/map_gen/data/.map_previews/danger_ore_scrap_maze.png b/map_gen/data/.map_previews/danger_ore_scrap_maze.png new file mode 100644 index 000000000..7c7748f75 Binary files /dev/null and b/map_gen/data/.map_previews/danger_ore_scrap_maze.png differ diff --git a/map_gen/data/.map_previews/danger_ore_tetrominoes.png b/map_gen/data/.map_previews/danger_ore_tetrominoes.png new file mode 100644 index 000000000..238a13ec2 Binary files /dev/null and b/map_gen/data/.map_previews/danger_ore_tetrominoes.png differ diff --git a/map_gen/data/.map_previews/danger_ore_voronoi.png b/map_gen/data/.map_previews/danger_ore_voronoi.png new file mode 100644 index 000000000..68fe53b2f Binary files /dev/null and b/map_gen/data/.map_previews/danger_ore_voronoi.png differ diff --git a/map_gen/maps/april_fools/2024.lua b/map_gen/maps/april_fools/2024.lua index 979ca2e90..b3fb5727d 100644 --- a/map_gen/maps/april_fools/2024.lua +++ b/map_gen/maps/april_fools/2024.lua @@ -3,16 +3,20 @@ 2024 revamped version of "Pinguin" scenario from 2019 with several addons. Required mods: - - Alien Biomes v0.7.2 - - RedMew Data v1.1.0 + - Alien Biomes v0.8.0 + - RedMew Data v4.0.0 ]] -if not script.active_mods['alien-biomes'] or not (script.active_mods['redmew-data'] and settings.startup.redmew_scenario.value == 'april-fools') then - error([[ - Missing dependencies. Please check that the following mods have been correctly installed: - - Alien Biomes >= v0.7.2 - - RedMew Data >= v1.1.0 & scenario setting "April Fools" - ]]) +local ModCompatibility = require 'utils.mod_compatibility' +ModCompatibility.check { + dependencies = { + { name = 'alien-biomes', version = '0.8.0' }, + { name = 'redmew-data', version = '4.0.0' } + } +} + +if settings.startup.redmew_scenario.value ~= 'april-fools' then + error('The "April Fools" scenario setting must be enabled to play Double Trouble.', 0) end local ScenarioInfo = require 'features.gui.info' diff --git a/map_gen/maps/april_fools/modules/crazy_toolbar.lua b/map_gen/maps/april_fools/modules/crazy_toolbar.lua index 2d082399f..c2ff0aa9f 100644 --- a/map_gen/maps/april_fools/modules/crazy_toolbar.lua +++ b/map_gen/maps/april_fools/modules/crazy_toolbar.lua @@ -39,7 +39,10 @@ local function change_quickbar_item() end if valid_item then local rand_position = math.random(1, SEARCHED_QUICKBAR_SLOTS) - player.set_quick_bar_slot(rand_position, rand_item) + local quick_bar_width = player.quick_bar_width + local page = math.ceil(rand_position / quick_bar_width) + local slot = rand_position - (page - 1) * quick_bar_width + player.set_quick_bar_slot(page, slot, rand_item) end end end diff --git a/map_gen/maps/april_fools/scenario/template.lua b/map_gen/maps/april_fools/scenario/template.lua index 25730b4d9..a1bb6e763 100644 --- a/map_gen/maps/april_fools/scenario/template.lua +++ b/map_gen/maps/april_fools/scenario/template.lua @@ -173,20 +173,20 @@ function Template.resources(surface, resources) end Template.diggy_rocks = { - 'rock-huge-volcanic', - 'rock-big-volcanic', - 'rock-huge-black', - 'rock-big-black', - 'rock-huge-grey', - 'rock-big-grey', - 'rock-huge-red', - 'rock-big-red', - 'rock-huge-white', - 'rock-big-white', - 'rock-huge-brown', - 'rock-big-brown', - 'rock-huge-dustyrose', - 'rock-big-dustyrose', + 'huge-rock-volcanic', + 'big-rock-volcanic', + 'huge-rock-black', + 'big-rock-black', + 'huge-rock-grey', + 'big-rock-grey', + 'huge-rock-red', + 'big-rock-red', + 'huge-rock-white', + 'big-rock-white', + 'huge-rock-brown', + 'big-rock-brown', + 'huge-rock-dustyrose', + 'big-rock-dustyrose', } Template.diggy_rocks_map = util.list_to_map(Template.diggy_rocks) diff --git a/map_gen/maps/crash_site/outpost_builder.lua b/map_gen/maps/crash_site/outpost_builder.lua index 136a9a781..10526e3b7 100644 --- a/map_gen/maps/crash_site/outpost_builder.lua +++ b/map_gen/maps/crash_site/outpost_builder.lua @@ -1171,7 +1171,7 @@ local function do_refill_turrets() local data = turret_data.data if data.liquid then - turret.fluidbox[1] = data + turret.set_fluid(1, data) elseif data then turret.insert(data) end @@ -1400,11 +1400,10 @@ local function do_magic_fluid_crafters() if fcount > 0 then local fluidbox_index = data.fluidbox_index - local fb = entity.fluidbox - local fb_data = fb[fluidbox_index] or {name = data.item, amount = 0} + local fb_data = entity.get_fluid(fluidbox_index) or {name = data.item, amount = 0} fb_data.amount = fb_data.amount + fcount - fb[fluidbox_index] = fb_data + entity.set_fluid(fluidbox_index, fb_data) data.last_tick = tick - (count - fcount) / rate end @@ -1542,7 +1541,7 @@ local set_inactive_token = Token.register( function(entity) if entity.valid then - entity.active = false + entity.disabled_by_script = true end end ) @@ -1576,7 +1575,7 @@ Public.magic_item_crafting_callback = else local furnace_item = callback_data.furnace_item if furnace_item then - local inv = entity.get_inventory(2) -- defines.inventory.furnace_source + local inv = entity.get_inventory(defines.inventory.crafter_input) inv.insert(furnace_item) entity.get_output_inventory().insert(callback_data.output.item) end @@ -1639,7 +1638,7 @@ Public.magic_item_crafting_callback_weighted = else local furnace_item = stack.furnace_item if furnace_item then - local inv = entity.get_inventory(2) -- defines.inventory.furnace_source + local inv = entity.get_inventory(defines.inventory.crafter_input) inv.insert {name = furnace_item, count = 200} local output_inv = entity.get_output_inventory() output_inv.insert {name = stack.output.item, count = 200 } @@ -1703,7 +1702,7 @@ Public.wall_callback = Public.deactivate_callback = Token.register( function(entity) - entity.active = false + entity.disabled_by_script = true entity.operable = false entity.destructible = false end @@ -1921,7 +1920,7 @@ function Public.do_random_fluid_loot(entity, weights, loot) count = stack.count end - entity.fluidbox[1] = {name = stack.name, amount = count} + entity.set_fluid(1, {name = stack.name, amount = count}) end function Public.do_factory_loot(entity, weights, loot) diff --git a/map_gen/maps/danger_ores/changelog.lua b/map_gen/maps/danger_ores/changelog.lua index 73a4d6eb7..c3ef0532a 100644 --- a/map_gen/maps/danger_ores/changelog.lua +++ b/map_gen/maps/danger_ores/changelog.lua @@ -151,4 +151,25 @@ return [[ 2026-06-14: - [DO] Disabled radioactivity by default, expect for Joker preset + + 2026-07-06: + - [DO:Tetrominoes] Added DO/Tetrominoes preset + - [DO:Voronoi] Added DO/Voronoi preset + + 2026-07-07: + - [DO:ScrapMaze] Added DO/Scrapworld-Maze preset + - [DO:OmniMaze] Added DO/Omnimatter-Maze preset + + 2026-07-08: + - [DO] Updated for Factorio 2.1 compatibility + - [DO] Rewrote biters-drop-resources loot to new ItemProductPrototype format + - [DO] Fixed MineEntityTechnologyTrigger entity field renamed to entities (array) in milestones triggers + - [DO] Added ModCompatibility module for minimum mod requirements for modded scenarios + - [DO:SA] Replaced removed "chemistry-or-cryogenics" recipe category with categories = {"chemistry", "cryogenics"} in coal-gasification + - [DO:SA] Replaced custom solar-system-edge-discovery technology with a modified vanilla stellar-discovery-solar-system-edge + - [DO:SA] Updated coal-gasification recipe unlock to reference stellar-discovery-solar-system-edge + - [DO:SA] Fixed MineEntityTechnologyTrigger entity field renamed to entities (array) in holmium-processing triggers + - [DO:SA] Fixed startup crash from invalid decorative name 'fulgoran-gravewort' + - [DO:SA] Fixed startup crash from dangling unlock-recipe effects left by removed ore-recycling recipes + - [DO:Scrap] Fixed danger-ores package dependency: replaced obsolete 'quality' mod with 'recycler' ]] diff --git a/map_gen/maps/danger_ores/compatibility/angel/mod-list.lua b/map_gen/maps/danger_ores/compatibility/angel/mod-list.lua new file mode 100644 index 000000000..0aec4ccb1 --- /dev/null +++ b/map_gen/maps/danger_ores/compatibility/angel/mod-list.lua @@ -0,0 +1,23 @@ +return { + dependencies = { + { name = 'angelsaddons-bots' }, + { name = 'angelsaddons-cab' }, + { name = 'angelsaddons-mobility-graphics-crawler' }, + { name = 'angelsaddons-mobility-graphics-petro' }, + { name = 'angelsaddons-mobility-graphics-smelting' }, + { name = 'angelsaddons-mobility' }, + { name = 'angelsaddons-storage' }, + { name = 'angelsbioprocessing' }, + { name = 'angelsbioprocessinggraphics' }, + { name = 'angelspetrochem' }, + { name = 'angelspetrochemgraphics' }, + { name = 'angelsrefining' }, + { name = 'angelsrefininggraphics' }, + { name = 'angelssmelting' }, + { name = 'angelssmeltinggraphics' }, + { name = 'redmew-data' }, + }, + recommended = { + { name = 'reskins-angels' }, + } +} diff --git a/map_gen/maps/danger_ores/compatibility/bob/mod-list.lua b/map_gen/maps/danger_ores/compatibility/bob/mod-list.lua new file mode 100644 index 000000000..70fbc5d33 --- /dev/null +++ b/map_gen/maps/danger_ores/compatibility/bob/mod-list.lua @@ -0,0 +1,27 @@ +return { + dependencies = { + { name = 'bobassembly' }, + { name = 'bobclasses' }, + { name = 'bobelectronics' }, + { name = 'bobequipment' }, + { name = 'bobgreenhouse' }, + { name = 'bobinserters' }, + { name = 'boblibrary' }, + { name = 'boblogistics' }, + { name = 'bobmining' }, + { name = 'bobmodules' }, + { name = 'bobores' }, + { name = 'bobplates' }, + { name = 'bobpower' }, + { name = 'bobrevamp' }, + { name = 'bobtech' }, + { name = 'bobvehicleequipment' }, + { name = 'bobwarfare' }, + { name = 'redmew-data' }, + }, + recommended = { + { name = 'angelsaddons-storage' }, + { name = 'reskins-angels' }, + { name = 'reskins-bobs' }, + } +} diff --git a/map_gen/maps/danger_ores/compatibility/bob/ores.lua b/map_gen/maps/danger_ores/compatibility/bob/ores.lua index 8cd85ddc9..2183619a3 100644 --- a/map_gen/maps/danger_ores/compatibility/bob/ores.lua +++ b/map_gen/maps/danger_ores/compatibility/bob/ores.lua @@ -29,7 +29,7 @@ return { {resource = b.resource(b.full_shape, 'bob-silver-ore', value), weight = 5}, --{resource = b.resource(b.full_shape, 'bob-sulfur', value), weight = 5}, {resource = b.resource(b.full_shape, 'bob-tin-ore', value), weight = 10}, - {resource = b.resource(b.full_shape, 'bob-tungsten-ore', value), weight = 5}, + {resource = b.resource(b.full_shape, 'tungsten-ore', value), weight = 5}, {resource = b.resource(b.full_shape, 'bob-zinc-ore', value), weight = 3} } }, @@ -59,7 +59,7 @@ return { {resource = b.resource(b.full_shape, 'bob-silver-ore', value), weight = 5}, --{resource = b.resource(b.full_shape, 'bob-sulfur', value), weight = 5}, {resource = b.resource(b.full_shape, 'bob-tin-ore', value), weight = 10}, - {resource = b.resource(b.full_shape, 'bob-tungsten-ore', value), weight = 5}, + {resource = b.resource(b.full_shape, 'tungsten-ore', value), weight = 5}, {resource = b.resource(b.full_shape, 'bob-zinc-ore', value), weight = 3} } }, @@ -92,7 +92,7 @@ return { {resource = b.resource(b.full_shape, 'bob-silver-ore', value), weight = 5}, --{resource = b.resource(b.full_shape, 'bob-sulfur', value), weight = 5}, {resource = b.resource(b.full_shape, 'bob-tin-ore', value), weight = 10}, - {resource = b.resource(b.full_shape, 'bob-tungsten-ore', value), weight = 5}, + {resource = b.resource(b.full_shape, 'tungsten-ore', value), weight = 5}, {resource = b.resource(b.full_shape, 'bob-zinc-ore', value), weight = 3} } }, @@ -121,7 +121,7 @@ return { {resource = b.resource(b.full_shape, 'bob-silver-ore', value), weight = 5}, --{resource = b.resource(b.full_shape, 'bob-sulfur', value), weight = 5}, {resource = b.resource(b.full_shape, 'bob-tin-ore', value), weight = 10}, - {resource = b.resource(b.full_shape, 'bob-tungsten-ore', value), weight = 5}, + {resource = b.resource(b.full_shape, 'tungsten-ore', value), weight = 5}, {resource = b.resource(b.full_shape, 'bob-zinc-ore', value), weight = 3} } }, @@ -151,7 +151,7 @@ return { {resource = b.resource(b.full_shape, 'bob-silver-ore', value), weight = 5}, --{resource = b.resource(b.full_shape, 'bob-sulfur', value), weight = 5}, {resource = b.resource(b.full_shape, 'bob-tin-ore', value), weight = 10}, - {resource = b.resource(b.full_shape, 'bob-tungsten-ore', value), weight = 5}, + {resource = b.resource(b.full_shape, 'tungsten-ore', value), weight = 5}, {resource = b.resource(b.full_shape, 'bob-zinc-ore', value), weight = 3} } }, @@ -181,7 +181,7 @@ return { {resource = b.resource(b.full_shape, 'bob-silver-ore', value), weight = 5}, --{resource = b.resource(b.full_shape, 'bob-sulfur', value), weight = 5}, {resource = b.resource(b.full_shape, 'bob-tin-ore', value), weight = 10}, - {resource = b.resource(b.full_shape, 'bob-tungsten-ore', value), weight = 5}, + {resource = b.resource(b.full_shape, 'tungsten-ore', value), weight = 5}, {resource = b.resource(b.full_shape, 'bob-zinc-ore', value), weight = 3} } }, @@ -214,7 +214,7 @@ return { {resource = b.resource(b.full_shape, 'bob-silver-ore', value), weight = 5}, --{resource = b.resource(b.full_shape, 'bob-sulfur', value), weight = 5}, {resource = b.resource(b.full_shape, 'bob-tin-ore', value), weight = 10}, - {resource = b.resource(b.full_shape, 'bob-tungsten-ore', value), weight = 5}, + {resource = b.resource(b.full_shape, 'tungsten-ore', value), weight = 5}, {resource = b.resource(b.full_shape, 'bob-zinc-ore', value), weight = 3} } }, @@ -243,7 +243,7 @@ return { {resource = b.resource(b.full_shape, 'bob-silver-ore', value), weight = 5}, --{resource = b.resource(b.full_shape, 'bob-sulfur', value), weight = 5}, {resource = b.resource(b.full_shape, 'bob-tin-ore', value), weight = 10}, - {resource = b.resource(b.full_shape, 'bob-tungsten-ore', value), weight = 5}, + {resource = b.resource(b.full_shape, 'tungsten-ore', value), weight = 5}, {resource = b.resource(b.full_shape, 'bob-zinc-ore', value), weight = 3} } }, @@ -273,7 +273,7 @@ return { {resource = b.resource(b.full_shape, 'bob-silver-ore', value), weight = 5}, --{resource = b.resource(b.full_shape, 'bob-sulfur', value), weight = 5}, {resource = b.resource(b.full_shape, 'bob-tin-ore', value), weight = 10}, - {resource = b.resource(b.full_shape, 'bob-tungsten-ore', value), weight = 5}, + {resource = b.resource(b.full_shape, 'tungsten-ore', value), weight = 5}, {resource = b.resource(b.full_shape, 'bob-zinc-ore', value), weight = 3} } }, @@ -303,7 +303,7 @@ return { {resource = b.resource(b.full_shape, 'bob-silver-ore', value), weight = 5}, --{resource = b.resource(b.full_shape, 'bob-sulfur', value), weight = 5}, {resource = b.resource(b.full_shape, 'bob-tin-ore', value), weight = 10}, - {resource = b.resource(b.full_shape, 'bob-tungsten-ore', value), weight = 5}, + {resource = b.resource(b.full_shape, 'tungsten-ore', value), weight = 5}, {resource = b.resource(b.full_shape, 'bob-zinc-ore', value), weight = 3} } }, @@ -336,7 +336,7 @@ return { {resource = b.resource(b.full_shape, 'bob-silver-ore', value), weight = 5}, --{resource = b.resource(b.full_shape, 'bob-sulfur', value), weight = 5}, {resource = b.resource(b.full_shape, 'bob-tin-ore', value), weight = 10}, - {resource = b.resource(b.full_shape, 'bob-tungsten-ore', value), weight = 5}, + {resource = b.resource(b.full_shape, 'tungsten-ore', value), weight = 5}, {resource = b.resource(b.full_shape, 'bob-zinc-ore', value), weight = 3} } }, @@ -365,7 +365,7 @@ return { {resource = b.resource(b.full_shape, 'bob-silver-ore', value), weight = 5}, --{resource = b.resource(b.full_shape, 'bob-sulfur', value), weight = 5}, {resource = b.resource(b.full_shape, 'bob-tin-ore', value), weight = 10}, - {resource = b.resource(b.full_shape, 'bob-tungsten-ore', value), weight = 5}, + {resource = b.resource(b.full_shape, 'tungsten-ore', value), weight = 5}, {resource = b.resource(b.full_shape, 'bob-zinc-ore', value), weight = 3} } }, @@ -395,7 +395,7 @@ return { {resource = b.resource(b.full_shape, 'bob-silver-ore', value), weight = 120}, --{resource = b.resource(b.full_shape, 'bob-sulfur', value), weight = 5}, {resource = b.resource(b.full_shape, 'bob-tin-ore', value), weight = 10}, - {resource = b.resource(b.full_shape, 'bob-tungsten-ore', value), weight = 5}, + {resource = b.resource(b.full_shape, 'tungsten-ore', value), weight = 5}, {resource = b.resource(b.full_shape, 'bob-zinc-ore', value), weight = 3} } }, @@ -425,7 +425,7 @@ return { {resource = b.resource(b.full_shape, 'bob-silver-ore', value), weight = 5}, {resource = b.resource(b.full_shape, 'bob-sulfur', value), weight = 120}, {resource = b.resource(b.full_shape, 'bob-tin-ore', value), weight = 10}, - {resource = b.resource(b.full_shape, 'bob-tungsten-ore', value), weight = 5}, + {resource = b.resource(b.full_shape, 'tungsten-ore', value), weight = 5}, {resource = b.resource(b.full_shape, 'bob-zinc-ore', value), weight = 3} } }, ]] @@ -458,12 +458,12 @@ return { {resource = b.resource(b.full_shape, 'bob-silver-ore', value), weight = 5}, --{resource = b.resource(b.full_shape, 'bob-sulfur', value), weight = 5}, {resource = b.resource(b.full_shape, 'bob-tin-ore', value), weight = 120}, - {resource = b.resource(b.full_shape, 'bob-tungsten-ore', value), weight = 5}, + {resource = b.resource(b.full_shape, 'tungsten-ore', value), weight = 5}, {resource = b.resource(b.full_shape, 'bob-zinc-ore', value), weight = 3} } }, { - name = 'bob-tungsten-ore', + name = 'tungsten-ore', ['tiles'] = { [1] = 'sand-1', [2] = 'sand-2', @@ -487,7 +487,7 @@ return { {resource = b.resource(b.full_shape, 'bob-silver-ore', value), weight = 5}, --{resource = b.resource(b.full_shape, 'bob-sulfur', value), weight = 5}, {resource = b.resource(b.full_shape, 'bob-tin-ore', value), weight = 10}, - {resource = b.resource(b.full_shape, 'bob-tungsten-ore', value), weight = 120}, + {resource = b.resource(b.full_shape, 'tungsten-ore', value), weight = 120}, {resource = b.resource(b.full_shape, 'bob-zinc-ore', value), weight = 3} } }, @@ -517,7 +517,7 @@ return { {resource = b.resource(b.full_shape, 'bob-silver-ore', value), weight = 5}, --{resource = b.resource(b.full_shape, 'bob-sulfur', value), weight = 5}, {resource = b.resource(b.full_shape, 'bob-tin-ore', value), weight = 10}, - {resource = b.resource(b.full_shape, 'bob-tungsten-ore', value), weight = 5}, + {resource = b.resource(b.full_shape, 'tungsten-ore', value), weight = 5}, {resource = b.resource(b.full_shape, 'bob-zinc-ore', value), weight = 120} } } diff --git a/map_gen/maps/danger_ores/compatibility/bob/ores_unmixed.lua b/map_gen/maps/danger_ores/compatibility/bob/ores_unmixed.lua index e4d960d58..0a791343f 100644 --- a/map_gen/maps/danger_ores/compatibility/bob/ores_unmixed.lua +++ b/map_gen/maps/danger_ores/compatibility/bob/ores_unmixed.lua @@ -222,7 +222,7 @@ return { }, }, { - name = 'bob-tungsten-ore', + name = 'tungsten-ore', ['tiles'] = { [1] = 'sand-1', [2] = 'sand-2', @@ -231,7 +231,7 @@ return { ['start'] = value(125, 0), ['weight'] = 1, ['ratios'] = { - { resource = b.resource(b.full_shape, 'bob-tungsten-ore', value(0, 0.5)), weight = 120 }, + { resource = b.resource(b.full_shape, 'tungsten-ore', value(0, 0.5)), weight = 120 }, }, }, { diff --git a/map_gen/maps/danger_ores/compatibility/bz/mod-list.lua b/map_gen/maps/danger_ores/compatibility/bz/mod-list.lua new file mode 100644 index 000000000..a4f8e4189 --- /dev/null +++ b/map_gen/maps/danger_ores/compatibility/bz/mod-list.lua @@ -0,0 +1,20 @@ +return { + dependencies = { + { name = 'bzaluminum' }, + { name = 'bzcarbon' }, + { name = 'bzchlorine' }, + { name = 'bzfoundry' }, + { name = 'bzgas' }, + { name = 'bzgold' }, + { name = 'bzlead' }, + { name = 'bzsilicon' }, + { name = 'bztin' }, + { name = 'bztitanium' }, + { name = 'bztungsten' }, + { name = 'bzzirconium' }, + { name = 'redmew-data' }, + }, + recommended = { + { name = 'alien-biomes' }, + } +} diff --git a/map_gen/maps/danger_ores/compatibility/exotic_industries/mod-list.lua b/map_gen/maps/danger_ores/compatibility/exotic_industries/mod-list.lua new file mode 100644 index 000000000..1d5684673 --- /dev/null +++ b/map_gen/maps/danger_ores/compatibility/exotic_industries/mod-list.lua @@ -0,0 +1,13 @@ +return { + dependencies = { + { name = 'exotic-industries' }, + { name = 'exotic-industries-graphics' }, + { name = 'exotic-industries-loaders' }, + { name = 'exotic-industries-containers' }, + { name = 'exotic-industries-robots' }, + { name = 'exotic-industries-tanks' }, + { name = 'exotic-industries-fueler' }, + { name = 'exotic-industries-trains' }, + { name = 'redmew-data' }, + }, +} diff --git a/map_gen/maps/danger_ores/compatibility/industrial_revolution_3/mod-list.lua b/map_gen/maps/danger_ores/compatibility/industrial_revolution_3/mod-list.lua new file mode 100644 index 000000000..5b7265d5b --- /dev/null +++ b/map_gen/maps/danger_ores/compatibility/industrial_revolution_3/mod-list.lua @@ -0,0 +1,19 @@ +return { + dependencies = { + { name = 'IndustrialRevolution3' }, + { name = 'IndustrialRevolution3Assets1' }, + { name = 'IndustrialRevolution3Assets2' }, + { name = 'IndustrialRevolution3Assets3' }, + { name = 'IndustrialRevolution3Assets4' }, + { name = 'IndustrialRevolution3ForestryCombinators' }, + { name = 'IndustrialRevolution3Airships' }, + { name = 'IndustrialRevolution3LoadersStacking' }, + { name = 'IndustrialRevolution3SpaceMining' }, + { name = 'IndustrialRevolution3Inspiration' }, + { name = 'redmew-data' }, + }, + recommended = { + { name = 'black-rubber-belts-remastered' }, + { name = 'LargerLamps-2_0' }, + }, +} diff --git a/map_gen/maps/danger_ores/compatibility/krastorio2/mod-list.lua b/map_gen/maps/danger_ores/compatibility/krastorio2/mod-list.lua new file mode 100644 index 000000000..000f195fd --- /dev/null +++ b/map_gen/maps/danger_ores/compatibility/krastorio2/mod-list.lua @@ -0,0 +1,12 @@ +return { + dependencies = { + { name = 'Krastorio2' }, + { name = 'Krastorio2Assets' }, + { name = 'Krastorio2MenuSimulations' }, + { name = 'redmew-data' }, + }, + recommended = { + { name = 'ChangeInserterDropLane' }, + { name = 'flib' }, + } +} \ No newline at end of file diff --git a/map_gen/maps/danger_ores/compatibility/omnimatter/mod-list.lua b/map_gen/maps/danger_ores/compatibility/omnimatter/mod-list.lua new file mode 100644 index 000000000..d2ab1768e --- /dev/null +++ b/map_gen/maps/danger_ores/compatibility/omnimatter/mod-list.lua @@ -0,0 +1,22 @@ +return { + dependencies = { + { name = 'omnilib' }, + { name = 'omnimatter' }, + { name = 'omnimatter_compression' }, + { name = 'omnimatter_crystal' }, + { name = 'omnimatter_energy' }, + { name = 'omnimatter_fluid' }, + { name = 'omnimatter_water' }, + { name = 'omnimatter_wood' }, + { name = 'redmew-data' }, + }, + recommended = { + { name = 'Warehousing' }, + }, + discouraged = { + { name = 'omnimatter_science' }, + }, + incompatibles = { + { name = 'omnimatter_move' }, + } +} \ No newline at end of file diff --git a/map_gen/maps/danger_ores/compatibility/pyanodon/mod-list.lua b/map_gen/maps/danger_ores/compatibility/pyanodon/mod-list.lua new file mode 100644 index 000000000..4c20d136f --- /dev/null +++ b/map_gen/maps/danger_ores/compatibility/pyanodon/mod-list.lua @@ -0,0 +1,17 @@ +return { + dependencies = { + { name = 'pycoalprocessing' }, + { name = 'pycoalprocessinggraphics' }, + { name = 'pyfusionenergy' }, + { name = 'pyfusionenergygraphics' }, + { name = 'pyindustry' }, + { name = 'pypostprocessing' }, + { name = 'redmew-data' }, + }, + recommended = { + { name = 'aai-loaders' }, + }, + incompatibles = { + { name = 'pyrawores' }, + } +} \ No newline at end of file diff --git a/map_gen/maps/danger_ores/compatibility/space-age/mod-list.lua b/map_gen/maps/danger_ores/compatibility/space-age/mod-list.lua new file mode 100644 index 000000000..8dbc31446 --- /dev/null +++ b/map_gen/maps/danger_ores/compatibility/space-age/mod-list.lua @@ -0,0 +1,6 @@ +return { + dependencies = { + { name = 'space-age' }, + { name = 'redmew-data' }, + } +} \ No newline at end of file diff --git a/map_gen/maps/danger_ores/config/tetromino_ores.lua b/map_gen/maps/danger_ores/config/tetromino_ores.lua new file mode 100644 index 000000000..faa191593 --- /dev/null +++ b/map_gen/maps/danger_ores/config/tetromino_ores.lua @@ -0,0 +1,55 @@ +local b = require 'map_gen.shared.builders' +local start_value = b.euclidean_value(0, 0.35) +local value = b.exponential_value(0, 0.07, 1.45) + +-- Order is significant: it maps to ore indices 1..4 produced by tetromino_layout. +return { + { + name = 'iron-ore', + tiles = { 'grass-1', 'grass-2', 'grass-3', 'grass-4' }, + start = start_value, + weight = 1, + ratios = { + { resource = b.resource(b.full_shape, 'iron-ore', value), weight = 75 }, + { resource = b.resource(b.full_shape, 'copper-ore', value), weight = 13 }, + { resource = b.resource(b.full_shape, 'stone', value), weight = 7 }, + { resource = b.resource(b.full_shape, 'coal', value), weight = 5 }, + }, + }, + { + name = 'copper-ore', + tiles = { 'red-desert-0', 'red-desert-1', 'red-desert-2', 'red-desert-3' }, + start = start_value, + weight = 1, + ratios = { + { resource = b.resource(b.full_shape, 'iron-ore', value), weight = 15 }, + { resource = b.resource(b.full_shape, 'copper-ore', value), weight = 70 }, + { resource = b.resource(b.full_shape, 'stone', value), weight = 10 }, + { resource = b.resource(b.full_shape, 'coal', value), weight = 5 }, + }, + }, + { + name = 'coal', + tiles = { 'dirt-1', 'dirt-2', 'dirt-3', 'dirt-4', 'dirt-5', 'dirt-6', 'dirt-7' }, + start = start_value, + weight = 1, + ratios = { + { resource = b.resource(b.full_shape, 'iron-ore', value), weight = 18 }, + { resource = b.resource(b.full_shape, 'copper-ore', value), weight = 9 }, + { resource = b.resource(b.full_shape, 'stone', value), weight = 8 }, + { resource = b.resource(b.full_shape, 'coal', value), weight = 65 }, + }, + }, + { + name = 'stone', + tiles = { 'sand-1', 'sand-2', 'sand-3' }, + start = start_value, + weight = 1, + ratios = { + { resource = b.resource(b.full_shape, 'iron-ore', value), weight = 25 }, + { resource = b.resource(b.full_shape, 'copper-ore', value), weight = 10 }, + { resource = b.resource(b.full_shape, 'stone', value), weight = 60 }, + { resource = b.resource(b.full_shape, 'coal', value), weight = 5 }, + }, + }, +} diff --git a/map_gen/maps/danger_ores/config/tetromino_shapes.lua b/map_gen/maps/danger_ores/config/tetromino_shapes.lua new file mode 100644 index 000000000..8e540b72e --- /dev/null +++ b/map_gen/maps/danger_ores/config/tetromino_shapes.lua @@ -0,0 +1,12 @@ +-- Tetromino palette for the Danger Ores "Tetrominoes" map. +-- Each shape is a list of {dx, dy} chunk offsets. Rotations and reflections are +-- generated in code (see tetromino_layout.orientations), so mirror pieces (J, Z) are +-- NOT listed here to avoid double-weighting. The packer tiles with these tetrominoes +-- only (no gaps, no smaller pieces). +return { + { {0, 0}, {1, 0}, {2, 0}, {3, 0} }, -- I + { {0, 0}, {1, 0}, {0, 1}, {1, 1} }, -- O + { {0, 0}, {1, 0}, {2, 0}, {1, 1} }, -- T + { {1, 0}, {2, 0}, {0, 1}, {1, 1} }, -- S (reflection yields Z) + { {0, 0}, {0, 1}, {0, 2}, {1, 2} }, -- L (reflection yields J) +} diff --git a/map_gen/maps/danger_ores/config/voronoi_ores.lua b/map_gen/maps/danger_ores/config/voronoi_ores.lua new file mode 100644 index 000000000..9544a2b8c --- /dev/null +++ b/map_gen/maps/danger_ores/config/voronoi_ores.lua @@ -0,0 +1,55 @@ +local b = require 'map_gen.shared.builders' +local start_value = b.euclidean_value(0, 0.35) +local value = b.exponential_value(0, 0.07, 1.45) + +-- Order is significant: it maps to ore indices 1..4 produced by voronoi_layout. +return { + { + name = 'iron-ore', + tiles = { 'grass-1', 'grass-2', 'grass-3', 'grass-4' }, + start = start_value, + weight = 1, + ratios = { + { resource = b.resource(b.full_shape, 'iron-ore', value), weight = 75 }, + { resource = b.resource(b.full_shape, 'copper-ore', value), weight = 13 }, + { resource = b.resource(b.full_shape, 'stone', value), weight = 7 }, + { resource = b.resource(b.full_shape, 'coal', value), weight = 5 }, + }, + }, + { + name = 'copper-ore', + tiles = { 'red-desert-0', 'red-desert-1', 'red-desert-2', 'red-desert-3' }, + start = start_value, + weight = 1, + ratios = { + { resource = b.resource(b.full_shape, 'iron-ore', value), weight = 15 }, + { resource = b.resource(b.full_shape, 'copper-ore', value), weight = 70 }, + { resource = b.resource(b.full_shape, 'stone', value), weight = 10 }, + { resource = b.resource(b.full_shape, 'coal', value), weight = 5 }, + }, + }, + { + name = 'coal', + tiles = { 'dirt-1', 'dirt-2', 'dirt-3', 'dirt-4', 'dirt-5', 'dirt-6', 'dirt-7' }, + start = start_value, + weight = 1, + ratios = { + { resource = b.resource(b.full_shape, 'iron-ore', value), weight = 18 }, + { resource = b.resource(b.full_shape, 'copper-ore', value), weight = 9 }, + { resource = b.resource(b.full_shape, 'stone', value), weight = 8 }, + { resource = b.resource(b.full_shape, 'coal', value), weight = 65 }, + }, + }, + { + name = 'stone', + tiles = { 'sand-1', 'sand-2', 'sand-3' }, + start = start_value, + weight = 1, + ratios = { + { resource = b.resource(b.full_shape, 'iron-ore', value), weight = 25 }, + { resource = b.resource(b.full_shape, 'copper-ore', value), weight = 10 }, + { resource = b.resource(b.full_shape, 'stone', value), weight = 60 }, + { resource = b.resource(b.full_shape, 'coal', value), weight = 5 }, + }, + }, +} diff --git a/map_gen/maps/danger_ores/configuration.lua b/map_gen/maps/danger_ores/configuration.lua index 381f95598..248f4c5c1 100644 --- a/map_gen/maps/danger_ores/configuration.lua +++ b/map_gen/maps/danger_ores/configuration.lua @@ -2,148 +2,148 @@ local B = require 'map_gen.shared.builders' local H = require 'map_gen.maps.danger_ores.modules.helper' return { - scenario_name = 'danger-ore', - restart_command = { - enabled = true, - }, - allowed_entities = { - enabled = true, - refund = true, - types = require 'map_gen.maps.danger_ores.config.vanilla_allowed_entities', - allowed_entities = {}, - banned_entities = {}, - }, - biter_drops = { - enabled = true, - }, - compatibility = { - aai_loaders = { - enabled = true, - }, - early_construction = { - enabled = true, - }, - deadlock = { - enabled = true, - items = require 'map_gen.maps.danger_ores.compatibility.deadlock.allowed_items', - }, - redmew_data = { - enabled = true, - remove_resource_patches = true, - } - }, - container_dump = { - enabled = true, - entity_name = 'coal' - }, - concrete_on_landfill = { - enabled = true, - tile = 'blue-refined-concrete', - refund_tile = 'refined-concrete', - }, - disable_mining_productivity = { - enabled = true, - replace = true, -- replace mining productivity with robot cargo capacity - }, - map_poll = { - enabled = true, - }, - map_gen_settings = { - enabled = true, - settings = H.empty_map_settings(), - }, - maze = { - enabled = false, - size = 50, -- in chunks - wall_thickness = 1, -- in chunks - cell_size = 3, -- must be an odd number - }, - prevent_quality_mining = { - enabled = true, - }, - radioactivity = { - enabled = false, - }, - rocket_launched = { - enabled = true, - win_satellite_count = 1000, - win_satellite_quality = 'normal', - }, - terraforming = { - enabled = true, - start_size = 12 * 32, - min_pollution = 400, - max_pollution = 15000, - pollution_increment = 4, - }, - technologies = { - enabled = true, - unlocks = { - ['uranium-mining'] = { 'uranium-processing' }, - ['oil-gathering'] = { 'oil-processing', 'coal-liquefaction' }, - }, - }, - game = { - draw_resource_selection = false, - technology_price_multiplier = 25, - manual_mining_speed_modifier = 1, - always_day = false, - peaceful_mode = true, - enemy_evolution = { - enabled = true, - time_factor = 0.000007, -- default 0.000004 - destroy_factor = 0.000010, -- default 0.002 - pollution_factor = 0.000000, -- Pollution has no affect on evolution default 0.0000009 - }, - on_init = nil, - }, - map_config = { - enabled = true, - -- Start area - spawn_shape = B.circle(64), - start_ore_shape = B.circle(68), - -- Ore pattern - main_ores = require 'map_gen.maps.danger_ores.config.vanilla_ores', - main_ores_shuffle_order = true, - main_ores_rotate = 30, - no_resource_patch_shape = B.circle(80), - resource_patches = require 'map_gen.maps.danger_ores.modules.resource_patches', - resource_patches_config = require 'map_gen.maps.danger_ores.config.vanilla_resource_patches', - -- Dense patches - dense_patches = nil, - dense_patches_scale = 1 / 48, - dense_patches_threshold = 0.5, - dense_patches_multiplier = 50, - -- Water - water = require 'map_gen.maps.danger_ores.modules.water', - water_scale = 1 / 96, - water_threshold = 0.4, - deepwater_threshold = 0.45, - no_water_shape = B.circle(102), - fish_spawn_rate = 0.025, - -- Trees - trees = require 'map_gen.maps.danger_ores.modules.trees', - trees_scale = 1 / 64, - trees_threshold = 0.3, - trees_chance = 0.875, - -- Enemies - enemy = require 'map_gen.maps.danger_ores.modules.enemy', - enemy_factor = 10 / (768 * 32), - enemy_max_chance = 1 / 6, - enemy_scale_factor = 32, - enemy_starting_radius = 64, - -- Additional parameters - ore_width = nil, - spawn_tile = nil, - post_map_func = nil, - circle_thickness = nil, - circle_grow_factor = nil, - main_ores_split_count = nil, - main_ores_start_ore_offset = nil, - main_ore_resource_patches_config = nil, - spawner_names = nil, - spawn_builder = nil, - tile_builder = nil, - tree_names = nil, - }, + scenario_name = 'danger-ore', + restart_command = { + enabled = true, + }, + allowed_entities = { + enabled = true, + refund = true, + types = require 'map_gen.maps.danger_ores.config.vanilla_allowed_entities', + allowed_entities = {}, + banned_entities = {}, + }, + biter_drops = { + enabled = true, + }, + compatibility = { + aai_loaders = { + enabled = true, + }, + early_construction = { + enabled = true, + }, + deadlock = { + enabled = true, + items = require 'map_gen.maps.danger_ores.compatibility.deadlock.allowed_items', + }, + redmew_data = { + enabled = true, + remove_resource_patches = true, + }, + }, + container_dump = { + enabled = true, + entity_name = 'coal', + }, + concrete_on_landfill = { + enabled = true, + tile = 'blue-refined-concrete', + refund_tile = 'refined-concrete', + }, + disable_mining_productivity = { + enabled = true, + replace = true, -- replace mining productivity with robot cargo capacity + }, + map_poll = { + enabled = true, + }, + map_gen_settings = { + enabled = true, + settings = H.empty_map_settings(), + }, + maze = { + enabled = false, + size = 50, -- in chunks + wall_thickness = 1, -- in chunks + cell_size = 3, -- must be an odd number + }, + prevent_quality_mining = { + enabled = true, + }, + radioactivity = { + enabled = false, + }, + rocket_launched = { + enabled = true, + win_satellite_count = 1000, + win_satellite_quality = 'normal', + }, + terraforming = { + enabled = true, + start_size = 12 * 32, + min_pollution = 400, + max_pollution = 15000, + pollution_increment = 4, + }, + technologies = { + enabled = true, + unlocks = { + ['uranium-mining'] = { 'uranium-processing' }, + ['oil-gathering'] = { 'oil-processing', 'coal-liquefaction' }, + }, + }, + game = { + draw_resource_selection = false, + technology_price_multiplier = 25, + manual_mining_speed_modifier = 1, + always_day = false, + peaceful_mode = true, + enemy_evolution = { + enabled = true, + time_factor = 0.000007, -- default 0.000004 + destroy_factor = 0.000010, -- default 0.002 + pollution_factor = 0.000000, -- Pollution has no affect on evolution default 0.0000009 + }, + on_init = nil, + }, + map_config = { + enabled = true, + -- Start area + spawn_shape = B.circle(64), + start_ore_shape = B.circle(68), + -- Ore pattern + main_ores = require 'map_gen.maps.danger_ores.config.vanilla_ores', + main_ores_shuffle_order = true, + main_ores_rotate = 30, + no_resource_patch_shape = B.circle(80), + resource_patches = require 'map_gen.maps.danger_ores.modules.resource_patches', + resource_patches_config = require 'map_gen.maps.danger_ores.config.vanilla_resource_patches', + -- Dense patches + dense_patches = nil, + dense_patches_scale = 1 / 48, + dense_patches_threshold = 0.5, + dense_patches_multiplier = 50, + -- Water + water = require 'map_gen.maps.danger_ores.modules.water', + water_scale = 1 / 96, + water_threshold = 0.4, + deepwater_threshold = 0.45, + no_water_shape = B.circle(102), + fish_spawn_rate = 0.025, + -- Trees + trees = require 'map_gen.maps.danger_ores.modules.trees', + trees_scale = 1 / 64, + trees_threshold = 0.3, + trees_chance = 0.875, + -- Enemies + enemy = require 'map_gen.maps.danger_ores.modules.enemy', + enemy_factor = 10 / (768 * 32), + enemy_max_chance = 1 / 6, + enemy_scale_factor = 32, + enemy_starting_radius = 64, + -- Additional parameters + ore_width = nil, + spawn_tile = nil, + post_map_func = nil, + circle_thickness = nil, + circle_grow_factor = nil, + main_ores_split_count = nil, + main_ores_start_ore_offset = nil, + main_ore_resource_patches_config = nil, + spawner_names = nil, + spawn_builder = nil, + tile_builder = nil, + tree_names = nil, + }, } diff --git a/map_gen/maps/danger_ores/modules/main_ores_tetrominoes.lua b/map_gen/maps/danger_ores/modules/main_ores_tetrominoes.lua new file mode 100644 index 000000000..54b48fcc4 --- /dev/null +++ b/map_gen/maps/danger_ores/modules/main_ores_tetrominoes.lua @@ -0,0 +1,39 @@ +local b = require 'map_gen.shared.builders' +local Layout = require 'map_gen.maps.danger_ores.modules.tetromino_layout' +local palette = require 'map_gen.maps.danger_ores.config.tetromino_shapes' + +local floor = math.floor + +local CELL_SIZE = 64 -- tiles per grid cell; each tetromino is 4 cells (32 = 1 chunk; 64 = 2x larger, 48 = 1.5x) +local SUPER_TILE = 32 -- layout cells per super-tile; pattern repeats every SUPER_TILE*CELL_SIZE tiles + +return function(config) + local main_ores = config.main_ores + + return function(tile_builder, ore_builder, spawn_shape, water_shape, random_gen) + local shapes = {} + for _, ore_data in ipairs(main_ores) do + local land = tile_builder(ore_data.tiles) + local ratios = ore_data.ratios + local weighted = b.prepare_weighted_array(ratios) + local ore = ore_builder(ore_data.name, ore_data.start, ratios, weighted) + shapes[#shapes + 1] = b.apply_entity(land, ore) + end + + local ore_grid = Layout.generate { + size = SUPER_TILE, + palette = palette, + num_ores = #shapes, + random = random_gen, + } + + local function tetrominoes(x, y, world) + local cx = floor(x / CELL_SIZE) % SUPER_TILE + local cy = floor(y / CELL_SIZE) % SUPER_TILE + local index = ore_grid[cx][cy] + return shapes[index](x, y, world) + end + + return b.any { spawn_shape, water_shape, tetrominoes } + end +end diff --git a/map_gen/maps/danger_ores/modules/main_ores_voronoi.lua b/map_gen/maps/danger_ores/modules/main_ores_voronoi.lua new file mode 100644 index 000000000..802abc54b --- /dev/null +++ b/map_gen/maps/danger_ores/modules/main_ores_voronoi.lua @@ -0,0 +1,39 @@ +local b = require 'map_gen.shared.builders' +local Layout = require 'map_gen.maps.danger_ores.modules.voronoi_layout' + +local CELL_SIZE = 32 -- tiles per cell-space unit (only sets the scale; boundaries are smooth) +local SUPER_TILE = 64 -- cell-space units per super-tile side; repeats every SUPER_TILE*CELL_SIZE tiles +local SEED_SPACING = 4 -- cell-space units between seeds; avg cell ~ SEED_SPACING*CELL_SIZE tiles (~128) +local RELAXATION = 2 -- Lloyd passes: 0 = jittered, 2-3 = even/relaxed + +return function(config) + local main_ores = config.main_ores + + return function(tile_builder, ore_builder, spawn_shape, water_shape, random_gen) + local shapes = {} + for _, ore_data in ipairs(main_ores) do + local land = tile_builder(ore_data.tiles) + local ratios = ore_data.ratios + local weighted = b.prepare_weighted_array(ratios) + local ore = ore_builder(ore_data.name, ore_data.start, ratios, weighted) + shapes[#shapes + 1] = b.apply_entity(land, ore) + end + + local layout = Layout.build { + size = SUPER_TILE, + spacing = SEED_SPACING, + relaxation = RELAXATION, + num_ores = #shapes, + random = random_gen, + } + + local function voronoi(x, y, world) + -- continuous cell-space coords -> smooth (tile-resolution) Voronoi boundaries + local fx = (x / CELL_SIZE) % SUPER_TILE + local fy = (y / CELL_SIZE) % SUPER_TILE + return shapes[Layout.ore_at(layout, fx, fy)](x, y, world) + end + + return b.any { spawn_shape, water_shape, voronoi } + end +end diff --git a/map_gen/maps/danger_ores/modules/map_poll.lua b/map_gen/maps/danger_ores/modules/map_poll.lua index fce10b055..857052f4a 100644 --- a/map_gen/maps/danger_ores/modules/map_poll.lua +++ b/map_gen/maps/danger_ores/modules/map_poll.lua @@ -59,19 +59,23 @@ local maps = { { name = 'danger-ore-normal-science', display_name = 'Normal science (+ biters)', mod_pack = mod_packs.danger_ore_normal }, { name = 'danger-ore-omnimatter', display_name = 'Omnimatter (1 ore)', mod_pack = mod_packs.danger_ore_omnimatter }, { name = 'danger-ore-omnimatter-cages', display_name = 'Omnimatter Cages (1 ore + frames)', mod_pack = mod_packs.danger_ore_omnimatter }, + { name = 'danger-ore-omnimatter-maze', display_name = 'Omnimatter Maze (1 ore + maze)', mod_pack = mod_packs.danger_ore_omnimatter }, { name = 'danger-ore-one-direction', display_name = 'One Direction (right ribbon world)', mod_pack = mod_packs.danger_ore_normal }, { name = 'danger-ore-one-direction-wide', display_name = 'One Direction Wide (wide right ribbon world)', mod_pack = mod_packs.danger_ore_normal }, { name = 'danger-ore-patches', display_name = 'Patches (ore islands in coal)', mod_pack = mod_packs.danger_ore_normal }, { name = 'danger-ore-permanence', display_name = 'Permanence (rebuilding penalty)', mod_pack = mod_packs.danger_ore_normal }, --{ name = 'danger-ore-poor-mans-coal-fields', display_name = 'Poor Man\'s Coal Fields (Alex Gaming\'s map)', mod_pack = mod_packs.danger_ore_normal }, { name = 'danger-ore-pyfe', display_name = 'Pyanodon Short (PyFe)', mod_pack = mod_packs.danger_ore_py_short }, - { name = 'danger-ore-safety', display_name = 'Safety Ores (inverse Danger Ores)', mod_pack = mod_packs.danger_ore_scrap }, + { name = 'danger-ore-safety', display_name = 'Safety Ores (inverse Danger Ores)', mod_pack = mod_packs.danger_ore_normal }, { name = 'danger-ore-scrap', display_name = 'Scrapworld (no ores, all scraps)', mod_pack = mod_packs.danger_ore_scrap }, + { name = 'danger-ore-scrap-maze', display_name = 'Scrapworld Maze (all scraps + maze)', mod_pack = mod_packs.danger_ore_scrap }, { name = 'danger-ore-space-age', display_name = 'Space Age (everything on Nauvis)', mod_pack = mod_packs.danger_ore_space_age }, { name = 'danger-ore-spiral', display_name = 'Spiral (without void)', mod_pack = mod_packs.danger_ore_normal }, { name = 'danger-ore-split', display_name = 'Split (4x sectors)', mod_pack = mod_packs.danger_ore_normal }, { name = 'danger-ore-square', display_name = 'Square (corner start)', mod_pack = mod_packs.danger_ore_normal }, { name = 'danger-ore-terraforming', display_name = 'Terraforming (default)', mod_pack = mod_packs.danger_ore_normal }, + { name = 'danger-ore-tetrominoes', display_name = 'Tetrominoes (interlocking pieces)', mod_pack = mod_packs.danger_ore_normal }, + { name = 'danger-ore-voronoi', display_name = 'Voronoi (organic cells)', mod_pack = mod_packs.danger_ore_normal }, { name = 'danger-ore-x-cross', display_name = 'X Cross (45 degrees)', mod_pack = mod_packs.danger_ore_normal }, --{ name = 'danger-ore-xmas-tree', display_name = 'Christmas Tree (triangle)', mod_pack = mod_packs.danger_ore_normal }, } diff --git a/map_gen/maps/danger_ores/modules/tetromino_layout.lua b/map_gen/maps/danger_ores/modules/tetromino_layout.lua new file mode 100644 index 000000000..6b694f8aa --- /dev/null +++ b/map_gen/maps/danger_ores/modules/tetromino_layout.lua @@ -0,0 +1,332 @@ +-- Pure-Lua layout generator for the Danger Ores "Tetrominoes" map. +-- ZERO Factorio dependencies: unit-testable with a standalone Lua interpreter. +-- All randomness is injected via `random(n) -> integer in [1, n]`, so the caller +-- owns the seed (the Factorio builder passes the map-seeded generator; tests pass +-- math.random). +-- +-- Packing produces ONLY valid tetrominoes (all seven: I/O/T/S/Z/L/J) with no gaps, by +-- seeding a trivial 4x4-block tiling and then randomizing it with local 4x4 flips (a standard +-- approach for random tilings -- brute-force exact cover is intractable at this size). +local sort = table.sort +local concat = table.concat + +local M = {} + +-- Normalize a shape (list of {dx,dy}) so its min dx/dy are 0; return a sorted copy +-- plus a string key for de-duplication. +local function normalize(cells) + local min_x, min_y = math.huge, math.huge + for _, c in ipairs(cells) do + if c[1] < min_x then min_x = c[1] end + if c[2] < min_y then min_y = c[2] end + end + local out = {} + for i, c in ipairs(cells) do + out[i] = { c[1] - min_x, c[2] - min_y } + end + sort(out, function(a, b) + if a[1] ~= b[1] then return a[1] < b[1] end + return a[2] < b[2] + end) + local parts = {} + for i, c in ipairs(out) do parts[i] = c[1] .. ',' .. c[2] end + return out, concat(parts, ';') +end + +-- All unique orientations (4 rotations x reflection) of a shape. +function M.orientations(shape) + local variants = {} + local seen = {} + local cur = shape + for _ = 1, 4 do + local rotated = {} -- rotate 90deg: (x,y) -> (y, -x) + for i, c in ipairs(cur) do rotated[i] = { c[2], -c[1] } end + local reflected = {} -- reflect the rotated variant: (x,y) -> (-x, y) + for i, c in ipairs(rotated) do reflected[i] = { -c[1], c[2] } end + for _, variant in ipairs({ rotated, reflected }) do + local norm, key = normalize(variant) + if not seen[key] then + seen[key] = true + variants[#variants + 1] = norm + end + end + cur = rotated + end + return variants +end + +-- Enumerate every way to tile a w x h rectangle with tetrominoes. `tetros_rel` is a list of +-- tetromino orientations, each as offsets relative to its scan-leading cell (offset {0,0}). +-- w*h is tiny (8), so this exhaustive DFS is instant. Returns a list of tilings; each tiling +-- is a list of pieces; each piece a list of {x,y} cells within the rectangle. +local function enumerate(w, h, tetros_rel) + local g = {} + for x = 0, w - 1 do g[x] = {}; for y = 0, h - 1 do g[x][y] = 0 end end + local sols, cur = {}, {} + local function first_empty() + for x = 0, w - 1 do for y = 0, h - 1 do if g[x][y] == 0 then return x, y end end end + end + local function rec() + local x, y = first_empty() + if not x then + local snap = {} + for _, piece in ipairs(cur) do + local cc = {} + for _, c in ipairs(piece) do cc[#cc + 1] = { c[1], c[2] } end + snap[#snap + 1] = cc + end + sols[#sols + 1] = snap + return + end + for _, rel in ipairs(tetros_rel) do + local placed, ok = {}, true + for _, c in ipairs(rel) do + local px, py = x + c[1], y + c[2] + if px < 0 or px >= w or py < 0 or py >= h or g[px][py] ~= 0 then + ok = false + break + end + placed[#placed + 1] = { px, py } + end + if ok then + for _, p in ipairs(placed) do g[p[1]][p[2]] = 1 end + cur[#cur + 1] = placed + rec() + cur[#cur] = nil + for _, p in ipairs(placed) do g[p[1]][p[2]] = 0 end + end + end + end + rec() + return sols +end + +-- Pack a size x size torus entirely with tetrominoes (size must be a multiple of 4). +-- Returns grid[x][y] = piece id (1..count) and the piece count. +function M.pack(size, oriented, random) + -- tetromino orientations only, as offsets relative to the scan-leading cell + local tetros_rel = {} + for _, cells in ipairs(oriented) do + if #cells == 4 then + local bx, by = cells[1][1], cells[1][2] + local rel = {} + for _, c in ipairs(cells) do rel[#rel + 1] = { c[1] - bx, c[2] - by } end + tetros_rel[#tetros_rel + 1] = rel + end + end + -- All tilings of a 4x4 block by four tetrominoes. Using a 4x4 base (rather than 2x4) is + -- what lets all seven tetrominoes appear -- T, S and Z cannot pair-tile a 2x4 rectangle. + local decomp = enumerate(4, 4, tetros_rel) + + local grid = {} + for x = 0, size - 1 do grid[x] = {}; for y = 0, size - 1 do grid[x][y] = 0 end end + local nid = 0 + + -- Base tiling: fill 4x4 blocks, each with a random valid 4-tetromino decomposition. + for bx = 0, size - 1, 4 do + for by = 0, size - 1, 4 do + local d = decomp[random(#decomp)] + for _, piece in ipairs(d) do + nid = nid + 1 + for _, c in ipairs(piece) do grid[(bx + c[1]) % size][(by + c[2]) % size] = nid end + end + end + end + + -- Local flip shuffling: repeatedly pick a 4x4 window; if it currently holds exactly four + -- whole tetrominoes, re-tile it with a random decomposition. This mixes the rigid base + -- grid into an organic layout while staying a valid tetromino tiling. + local function try_flip() + local x, y = random(size) - 1, random(size) - 1 + local counts, order = {}, {} + for i = 0, 3 do + for j = 0, 3 do + local id = grid[(x + i) % size][(y + j) % size] + if not counts[id] then counts[id] = 0; order[#order + 1] = id end + counts[id] = counts[id] + 1 + end + end + if #order ~= 4 then return end + for _, id in ipairs(order) do if counts[id] ~= 4 then return end end + local d = decomp[random(#decomp)] + for _, piece in ipairs(d) do + nid = nid + 1 + for _, c in ipairs(piece) do grid[(x + c[1]) % size][(y + c[2]) % size] = nid end + end + end + + local passes = size * size * 80 + for _ = 1, passes do try_flip() end + + -- Renumber surviving piece ids to a contiguous 1..count range. + local remap, count = {}, 0 + for x = 0, size - 1 do + for y = 0, size - 1 do + local id = grid[x][y] + if not remap[id] then count = count + 1; remap[id] = count end + grid[x][y] = remap[id] + end + end + return grid, count +end + +-- neighbors[id] = { other_id = true, ... } over the torus (4-adjacency). +function M.adjacency(grid, size) + local neighbors = {} + local function link(a, b) + if a == b then return end + neighbors[a] = neighbors[a] or {} + neighbors[b] = neighbors[b] or {} + neighbors[a][b] = true + neighbors[b][a] = true + end + for x = 0, size - 1 do + for y = 0, size - 1 do + local id = grid[x][y] + link(id, grid[(x + 1) % size][y]) + link(id, grid[x][(y + 1) % size]) + end + end + return neighbors +end + +-- Complete graph coloring via dynamic DSATUR (incremental saturation) + backtracking. +-- Returns colors[id] = 1..num_colors (no two adjacent pieces equal) or nil if impossible. +-- Colors are tried lowest-first, so the highest color index is used only when forced -- +-- generate() maps that rarest color to the last ore (stone), keeping sand scarce. A static +-- (non-adaptive) trial order also keeps the backtracking near-linear. +function M.color(count, neighbors, num_colors) + local adj = {} + local deg = {} + for id = 1, count do + local a = {} + local nb = neighbors[id] + if nb then + for o in pairs(nb) do a[#a + 1] = o end + end + adj[id] = a + deg[id] = #a + end + + local colors = {} -- id -> color, or nil + local sat = {} -- id -> number of distinct colors among its coloured neighbours + local ncolor = {} -- id -> { [c] = number of neighbours currently coloured c } + for id = 1, count do + sat[id] = 0 + local t = {} + for c = 1, num_colors do t[c] = 0 end + ncolor[id] = t + end + + local uncolored = count + -- Backtracking node ceiling. With the static DSATUR order the solve is near-linear, so + -- this is a generous safety net; it fails closed to nil, letting generate() re-pack. + local SAFETY = 200000 + local nodes = 0 + + local function assign(id, c) + colors[id] = c + uncolored = uncolored - 1 + for _, o in ipairs(adj[id]) do + if colors[o] == nil then + local nc = ncolor[o] + if nc[c] == 0 then sat[o] = sat[o] + 1 end + nc[c] = nc[c] + 1 + end + end + end + + local function unassign(id, c) + for _, o in ipairs(adj[id]) do + if colors[o] == nil then + local nc = ncolor[o] + nc[c] = nc[c] - 1 + if nc[c] == 0 then sat[o] = sat[o] - 1 end + end + end + colors[id] = nil + uncolored = uncolored + 1 + end + + local function pick() + local best, best_sat, best_deg = nil, -1, -1 + for id = 1, count do + if colors[id] == nil then + local s = sat[id] + local d = deg[id] + if s > best_sat or (s == best_sat and d > best_deg) then + best, best_sat, best_deg = id, s, d + end + end + end + return best + end + + local function solve() + if uncolored == 0 then return true end + nodes = nodes + 1 + if nodes > SAFETY then return false end + local id = pick() + local nc = ncolor[id] + for c = 1, num_colors do + if nc[c] == 0 then + assign(id, c) + if solve() then return true end + unassign(id, c) + end + end + return false + end + + if solve() then return colors end + return nil +end + +-- Pack + color, retrying with fresh randomness until a clean coloring exists. Returns +-- ore_grid[x][y] = ore index in 1..num_ores (0-based x,y in [0,size-1]). +function M.generate(opts) + local size = opts.size + local num_ores = opts.num_ores + local random = opts.random + local max_attempts = opts.max_attempts or 8 + + local oriented = {} + for _, shape in ipairs(opts.palette) do + for _, variant in ipairs(M.orientations(shape)) do + oriented[#oriented + 1] = variant + end + end + + for _ = 1, max_attempts do + local grid, count = M.pack(size, oriented, random) + local neighbors = M.adjacency(grid, size) + local colors = M.color(count, neighbors, num_ores) + if colors then + -- Map colors -> ores. Lowest-first coloring makes the highest color the rarest, + -- so pin it to the last ore (stone) to keep sand scarce; permute the remaining + -- colors among the remaining ores for per-seed variety in which ore dominates. + local ore_of = {} + local perm = {} + for i = 1, num_ores - 1 do perm[i] = i end + for i = num_ores - 1, 2, -1 do + local j = random(i) + perm[i], perm[j] = perm[j], perm[i] + end + for c = 1, num_ores - 1 do ore_of[c] = perm[c] end + ore_of[num_ores] = num_ores + + local ore_grid = {} + for x = 0, size - 1 do + ore_grid[x] = {} + for y = 0, size - 1 do + ore_grid[x][y] = ore_of[colors[grid[x][y]]] + end + end + return ore_grid + end + end + error('tetromino_layout: could not ' .. num_ores .. '-color the packing after ' + .. max_attempts .. ' attempts') +end + +return M diff --git a/map_gen/maps/danger_ores/modules/tetromino_layout.test.lua b/map_gen/maps/danger_ores/modules/tetromino_layout.test.lua new file mode 100644 index 000000000..081067e9e --- /dev/null +++ b/map_gen/maps/danger_ores/modules/tetromino_layout.test.lua @@ -0,0 +1,165 @@ +-- Standalone unit tests for the pure Tetrominoes layout algorithm. +-- Run from the repo root: lua map_gen/maps/danger_ores/modules/tetromino_layout.test.lua +package.path = './?.lua;' .. package.path + +local Layout = require 'map_gen.maps.danger_ores.modules.tetromino_layout' + +local failures = 0 +local function check(cond, msg) + if cond then + print('ok: ' .. msg) + else + failures = failures + 1 + print('FAIL: ' .. msg) + end +end + +-- orientations: a square (O) collapses to 1; a chiral L expands to 8. +local o_square = Layout.orientations({ {0, 0}, {1, 0}, {0, 1}, {1, 1} }) +check(#o_square == 1, 'square (O) has 1 unique orientation, got ' .. #o_square) + +local l_shape = Layout.orientations({ {0, 0}, {0, 1}, {0, 2}, {1, 2} }) +check(#l_shape == 8, 'L has 8 unique orientations, got ' .. #l_shape) + +-- Build the flat oriented palette used by packing/generate. +local palette = require 'map_gen.maps.danger_ores.config.tetromino_shapes' +local function oriented_palette() + local oriented = {} + for _, s in ipairs(palette) do + for _, v in ipairs(Layout.orientations(s)) do + oriented[#oriented + 1] = v + end + end + return oriented +end +local function rand(n) return math.random(n) end + +-- pack: fully covers the torus (no empty cells) and is deterministic per seed. +math.randomseed(1) +local oriented = oriented_palette() +local PSIZE = 12 +local grid = Layout.pack(PSIZE, oriented, rand) +local empty = 0 +for x = 0, PSIZE - 1 do + for y = 0, PSIZE - 1 do + if grid[x][y] == 0 then empty = empty + 1 end + end +end +check(empty == 0, 'pack leaves no empty cells, empty=' .. empty) + +-- every piece is a valid tetromino: exactly 4 cells, at test and production sizes +local function all_tetrominoes(g, sz) + local sizes = {} + for x = 0, sz - 1 do + for y = 0, sz - 1 do + sizes[g[x][y]] = (sizes[g[x][y]] or 0) + 1 + end + end + local bad = 0 + for _, s in pairs(sizes) do if s ~= 4 then bad = bad + 1 end end + return bad +end +for _, sz in ipairs({ 12, 32 }) do + math.randomseed(sz) + local pg = Layout.pack(sz, oriented, rand) + check(all_tetrominoes(pg, sz) == 0, 'every piece is a 4-cell tetromino at size ' .. sz + .. ', non-tetromino=' .. all_tetrominoes(pg, sz)) +end + +math.randomseed(99) +local g1 = Layout.pack(PSIZE, oriented, rand) +math.randomseed(99) +local g2 = Layout.pack(PSIZE, oriented, rand) +local identical = true +for x = 0, PSIZE - 1 do + for y = 0, PSIZE - 1 do + if g1[x][y] ~= g2[x][y] then identical = false end + end +end +check(identical, 'pack is deterministic for a fixed random sequence') + +-- clean borders: adjacent cells from DIFFERENT pieces must get DIFFERENT ores +-- (including across the torus wrap). +math.randomseed(42) +local cg, ccount = Layout.pack(PSIZE, oriented, rand) +local nb = Layout.adjacency(cg, PSIZE) +local colors = Layout.color(ccount, nb, 4) +check(colors ~= nil, 'color returns a valid 4-coloring') +if colors then + local bad = 0 + for x = 0, PSIZE - 1 do + for y = 0, PSIZE - 1 do + local id = cg[x][y] + local right = cg[(x + 1) % PSIZE][y] + local down = cg[x][(y + 1) % PSIZE] + if right ~= id and colors[right] == colors[id] then bad = bad + 1 end + if down ~= id and colors[down] == colors[id] then bad = bad + 1 end + end + end + check(bad == 0, 'no two touching pieces share an ore (incl. wrap), violations=' .. bad) +end + +-- generate: deterministic per seed. +math.randomseed(7) +local a = Layout.generate { size = 16, palette = palette, num_ores = 4, random = rand } +math.randomseed(7) +local b = Layout.generate { size = 16, palette = palette, num_ores = 4, random = rand } +local same = true +for x = 0, 15 do for y = 0, 15 do if a[x][y] ~= b[x][y] then same = false end end end +check(same, 'generate is deterministic for a fixed seed') + +-- generate: different seeds produce different layouts. +math.randomseed(1) +local c1 = Layout.generate { size = 16, palette = palette, num_ores = 4, random = rand } +math.randomseed(2) +local c2 = Layout.generate { size = 16, palette = palette, num_ores = 4, random = rand } +local diff = false +for x = 0, 15 do for y = 0, 15 do if c1[x][y] ~= c2[x][y] then diff = true end end end +check(diff, 'different seeds produce different layouts') + +-- Production-size guard (the real map uses a 32-chunk super-tile). +do + local PROD = 32 + local ok_count = 0 + for seed = 1, 25 do + math.randomseed(seed) + local ok = pcall(function() + return Layout.generate { size = PROD, palette = palette, num_ores = 4, random = rand } + end) + if ok then ok_count = ok_count + 1 end + end + check(ok_count == 25, 'generate succeeds for all 25 seeds at production size 32, got ' .. ok_count) + + -- clean borders + all 4 ores at size 32, tested at pack+color level + math.randomseed(3) + local g32, c32 = Layout.pack(PROD, oriented, rand) + local nb32 = Layout.adjacency(g32, PROD) + local col32 = Layout.color(c32, nb32, 4) + check(col32 ~= nil, 'color succeeds at size 32') + if col32 then + local bad, palette_seen = 0, {} + for x = 0, PROD - 1 do + for y = 0, PROD - 1 do + local id = g32[x][y] + palette_seen[col32[id]] = true + local right = g32[(x + 1) % PROD][y] + local down = g32[x][(y + 1) % PROD] + if right ~= id and col32[right] == col32[id] then bad = bad + 1 end + if down ~= id and col32[down] == col32[id] then bad = bad + 1 end + end + end + check(bad == 0, 'no two touching pieces share an ore at size 32, violations=' .. bad) + -- stone (the 4th colour) is intentionally rare and may be absent on some seeds, + -- so the coloring uses at least 3 colours (all main ores) and never more than 4. + local ore_types = 0 + for _ in pairs(palette_seen) do ore_types = ore_types + 1 end + check(ore_types >= 3 and ore_types <= 4, 'uses 3-4 ores at size 32, got ' .. ore_types) + end +end + +if failures == 0 then + print('\nALL PASSED') +else + print('\n' .. failures .. ' FAILURE(S)') + os.exit(1) +end diff --git a/map_gen/maps/danger_ores/modules/voronoi_layout.lua b/map_gen/maps/danger_ores/modules/voronoi_layout.lua new file mode 100644 index 000000000..c33da0201 --- /dev/null +++ b/map_gen/maps/danger_ores/modules/voronoi_layout.lua @@ -0,0 +1,284 @@ +-- Pure-Lua layout generator for the Danger Ores "Voronoi" map. +-- ZERO Factorio dependencies: unit-testable with a standalone Lua interpreter. +-- Randomness is injected via `random(n) -> integer in [1, n]`, so the caller owns the seed. +-- +-- Pipeline: jittered-grid seeds on a toroidal super-tile -> optional Lloyd relaxation -> +-- nearest-seed Voronoi partition -> region adjacency -> DSATUR 4-colouring (lowest-first, so +-- the 4th colour = stone stays rare) -> colour->ore mapping. +local floor = math.floor +local abs = math.abs +local huge = math.huge + +local M = {} + +-- Squared toroidal distance between (ax,ay) and (bx,by) on a size x size torus. +local function torus_d2(ax, ay, bx, by, size) + local dx = abs(ax - bx); if dx > size - dx then dx = size - dx end + local dy = abs(ay - by); if dy > size - dy then dy = size - dy end + return dx * dx + dy * dy +end + +-- One jittered seed per grid square. seeds[i][j] = {x,y}, i,j in 0..g-1. +function M.place_seeds(size, spacing, random) + local g = floor(size / spacing) + local seeds = {} + for i = 0, g - 1 do + seeds[i] = {} + for j = 0, g - 1 do + seeds[i][j] = { + x = i * spacing + (random(spacing) - 1), + y = j * spacing + (random(spacing) - 1), + } + end + end + return seeds +end + +-- Assign each cell to its nearest seed (toroidal). Region id = si*g + sj + 1. The nearest +-- seed is always within +/-2 grid squares (seeds never drift more than ~1 square under +-- relaxation), so only a 5x5 neighbourhood is searched. +function M.partition(size, spacing, seeds) + local g = floor(size / spacing) + local grid = {} + for x = 0, size - 1 do + grid[x] = {} + local gi = floor(x / spacing) + for y = 0, size - 1 do + local gj = floor(y / spacing) + local best_id, best_d = 0, huge + for di = -2, 2 do + for dj = -2, 2 do + local si = (gi + di) % g + local sj = (gj + dj) % g + local s = seeds[si][sj] + local d = torus_d2(x, y, s.x, s.y, size) + if d < best_d then + best_d = d + best_id = si * g + sj + 1 + end + end + end + grid[x][y] = best_id + end + end + return grid +end + +-- Lloyd relaxation: move each seed to the toroidal centroid of the cells nearest it, `passes` +-- times. Centroids are computed from nearest-image offsets so the torus wrap is handled. +-- Seeds move less than a grid square per pass, keeping the 5x5 partition search valid. +function M.relax(size, spacing, seeds, passes) + local g = floor(size / spacing) + local half = size / 2 + for _ = 1, passes do + local grid = M.partition(size, spacing, seeds) + local sumx, sumy, cnt = {}, {}, {} + for x = 0, size - 1 do + for y = 0, size - 1 do + local id = grid[x][y] + local si = floor((id - 1) / g) + local sj = (id - 1) % g + local s = seeds[si][sj] + local dx = ((x - s.x + half) % size) - half + local dy = ((y - s.y + half) % size) - half + sumx[id] = (sumx[id] or 0) + dx + sumy[id] = (sumy[id] or 0) + dy + cnt[id] = (cnt[id] or 0) + 1 + end + end + for i = 0, g - 1 do + for j = 0, g - 1 do + local id = i * g + j + 1 + local c = cnt[id] + if c then + local s = seeds[i][j] + s.x = (s.x + sumx[id] / c) % size + s.y = (s.y + sumy[id] / c) % size + end + end + end + end + return seeds +end + +-- neighbors[id] = { other_id = true, ... } over the torus (4-adjacency). +function M.adjacency(grid, size) + local neighbors = {} + local function link(a, b) + if a == b then return end + neighbors[a] = neighbors[a] or {} + neighbors[b] = neighbors[b] or {} + neighbors[a][b] = true + neighbors[b][a] = true + end + for x = 0, size - 1 do + for y = 0, size - 1 do + local id = grid[x][y] + link(id, grid[(x + 1) % size][y]) + link(id, grid[x][(y + 1) % size]) + end + end + return neighbors +end + +-- Complete graph colouring via dynamic DSATUR (incremental saturation) + backtracking. +-- Colours are tried lowest-first, so the highest colour is used only when forced; generate() +-- maps that rarest colour to stone. Returns colors[id] = 1..num_colors, or nil if impossible. +function M.color(count, neighbors, num_colors) + local adj = {} + local deg = {} + for id = 1, count do + local a = {} + local nb = neighbors[id] + if nb then for o in pairs(nb) do a[#a + 1] = o end end + adj[id] = a + deg[id] = #a + end + + local colors = {} + local sat = {} + local ncolor = {} + for id = 1, count do + sat[id] = 0 + local t = {} + for c = 1, num_colors do t[c] = 0 end + ncolor[id] = t + end + + local uncolored = count + local SAFETY = 200000 + local nodes = 0 + + local function assign(id, c) + colors[id] = c + uncolored = uncolored - 1 + for _, o in ipairs(adj[id]) do + if colors[o] == nil then + local nc = ncolor[o] + if nc[c] == 0 then sat[o] = sat[o] + 1 end + nc[c] = nc[c] + 1 + end + end + end + + local function unassign(id, c) + for _, o in ipairs(adj[id]) do + if colors[o] == nil then + local nc = ncolor[o] + nc[c] = nc[c] - 1 + if nc[c] == 0 then sat[o] = sat[o] - 1 end + end + end + colors[id] = nil + uncolored = uncolored + 1 + end + + local function pick() + local best, best_sat, best_deg = nil, -1, -1 + for id = 1, count do + if colors[id] == nil then + local s = sat[id] + local d = deg[id] + if s > best_sat or (s == best_sat and d > best_deg) then + best, best_sat, best_deg = id, s, d + end + end + end + return best + end + + local function solve() + if uncolored == 0 then return true end + nodes = nodes + 1 + if nodes > SAFETY then return false end + local id = pick() + local nc = ncolor[id] + for c = 1, num_colors do + if nc[c] == 0 then + assign(id, c) + if solve() then return true end + unassign(id, c) + end + end + return false + end + + if solve() then return colors end + return nil +end + +-- Place seeds -> relax -> partition -> 4-colour -> map colours to ores, retrying with fresh +-- seeds until a clean colouring exists. Returns a layout: { size, spacing, g, seeds, seed_ore } +-- where seed_ore[region_id] is the ore index for the seed at region_id = si*g + sj + 1. +-- Adjacency/colouring use the cell raster (which captures every edge-adjacency of the diagram), +-- so the guarantee holds for the smooth per-tile boundaries drawn by ore_at(). +function M.build(opts) + local size = opts.size + local spacing = opts.spacing + local relaxation = opts.relaxation or 0 + local num_ores = opts.num_ores + local random = opts.random + local max_attempts = opts.max_attempts or 8 + local g = floor(size / spacing) + + for _ = 1, max_attempts do + local seeds = M.place_seeds(size, spacing, random) + if relaxation > 0 then M.relax(size, spacing, seeds, relaxation) end + local grid = M.partition(size, spacing, seeds) + local neighbors = M.adjacency(grid, size) + local colors = M.color(g * g, neighbors, num_ores) + if colors then + -- rarest colour (highest, from lowest-first colouring) -> last ore (stone); + -- permute the rest among the remaining ores for per-seed variety. + local ore_of = {} + local perm = {} + for i = 1, num_ores - 1 do perm[i] = i end + for i = num_ores - 1, 2, -1 do + local j = random(i) + perm[i], perm[j] = perm[j], perm[i] + end + for c = 1, num_ores - 1 do ore_of[c] = perm[c] end + ore_of[num_ores] = num_ores + + local seed_ore = {} + for id = 1, g * g do seed_ore[id] = ore_of[colors[id]] end + return { size = size, spacing = spacing, g = g, seeds = seeds, seed_ore = seed_ore } + end + end + error('voronoi_layout: could not ' .. num_ores .. '-colour after ' .. max_attempts .. ' attempts') +end + +-- Smooth per-point ore lookup: ore of the seed nearest to continuous cell-space (fx,fy), +-- both already reduced into [0,size). Gives tile-resolution (non-blocky) Voronoi boundaries. +function M.ore_at(layout, fx, fy) + local size, spacing, g, seeds = layout.size, layout.spacing, layout.g, layout.seeds + local gi = floor(fx / spacing) + local gj = floor(fy / spacing) + local best_id, best_d = 1, huge + for di = -2, 2 do + for dj = -2, 2 do + local si = (gi + di) % g + local sj = (gj + dj) % g + local s = seeds[si][sj] + local d = torus_d2(fx, fy, s.x, s.y, size) + if d < best_d then best_d = d; best_id = si * g + sj + 1 end + end + end + return layout.seed_ore[best_id] +end + +-- Convenience: rasterise the smooth layout to an ore_grid[x][y] (used by tests). +function M.generate(opts) + local layout = M.build(opts) + local size = layout.size + local ore_grid = {} + for x = 0, size - 1 do + ore_grid[x] = {} + for y = 0, size - 1 do + ore_grid[x][y] = M.ore_at(layout, x, y) + end + end + return ore_grid +end + +return M diff --git a/map_gen/maps/danger_ores/modules/voronoi_layout.test.lua b/map_gen/maps/danger_ores/modules/voronoi_layout.test.lua new file mode 100644 index 000000000..cb03167ec --- /dev/null +++ b/map_gen/maps/danger_ores/modules/voronoi_layout.test.lua @@ -0,0 +1,144 @@ +-- Standalone unit tests for the pure Voronoi layout algorithm. +-- Run from the repo root: lua map_gen/maps/danger_ores/modules/voronoi_layout.test.lua +package.path = './?.lua;' .. package.path + +local Layout = require 'map_gen.maps.danger_ores.modules.voronoi_layout' + +local failures = 0 +local function check(cond, msg) + if cond then + print('ok: ' .. msg) + else + failures = failures + 1 + print('FAIL: ' .. msg) + end +end + +local function rand(n) return math.random(n) end + +-- partition: every cell is assigned a valid region id, and it is deterministic per seed. +math.randomseed(1) +local SIZE, SPACING = 16, 4 +local seeds = Layout.place_seeds(SIZE, SPACING, rand) +local grid = Layout.partition(SIZE, SPACING, seeds) +local g = math.floor(SIZE / SPACING) +local unassigned, out_of_range = 0, 0 +for x = 0, SIZE - 1 do + for y = 0, SIZE - 1 do + local id = grid[x][y] + if id == nil then unassigned = unassigned + 1 + elseif id < 1 or id > g * g then out_of_range = out_of_range + 1 end + end +end +check(unassigned == 0, 'every cell assigned a region, unassigned=' .. unassigned) +check(out_of_range == 0, 'all region ids in range, out_of_range=' .. out_of_range) + +math.randomseed(42) +local s1 = Layout.place_seeds(SIZE, SPACING, rand) +local g1 = Layout.partition(SIZE, SPACING, s1) +math.randomseed(42) +local s2 = Layout.place_seeds(SIZE, SPACING, rand) +local g2 = Layout.partition(SIZE, SPACING, s2) +local identical = true +for x = 0, SIZE - 1 do for y = 0, SIZE - 1 do if g1[x][y] ~= g2[x][y] then identical = false end end end +check(identical, 'partition is deterministic for a fixed random sequence') + +-- relax: keeps full coverage, is deterministic, and evens out cell sizes (lower variance). +local function cell_count_variance(grd, sz, gg) + local counts = {} + for id = 1, gg * gg do counts[id] = 0 end + for x = 0, sz - 1 do for y = 0, sz - 1 do counts[grd[x][y]] = counts[grd[x][y]] + 1 end end + local n, mean = gg * gg, (sz * sz) / (gg * gg) + local v = 0 + for id = 1, n do local d = counts[id] - mean; v = v + d * d end + return v / n +end + +math.randomseed(7) +local rseeds = Layout.place_seeds(SIZE, SPACING, rand) +local var_before = cell_count_variance(Layout.partition(SIZE, SPACING, rseeds), SIZE, g) +Layout.relax(SIZE, SPACING, rseeds, 3) +local rgrid = Layout.partition(SIZE, SPACING, rseeds) +local var_after = cell_count_variance(rgrid, SIZE, g) + +local runassigned = 0 +for x = 0, SIZE - 1 do for y = 0, SIZE - 1 do if rgrid[x][y] == nil then runassigned = runassigned + 1 end end end +check(runassigned == 0, 'relaxed partition still covers every cell, unassigned=' .. runassigned) +check(var_after <= var_before, 'relaxation does not increase cell-size variance (' + .. string.format('%.1f -> %.1f', var_before, var_after) .. ')') + +math.randomseed(11) +local ra = Layout.place_seeds(SIZE, SPACING, rand); Layout.relax(SIZE, SPACING, ra, 2) +math.randomseed(11) +local rb = Layout.place_seeds(SIZE, SPACING, rand); Layout.relax(SIZE, SPACING, rb, 2) +local rdet = true +for i = 0, g - 1 do for j = 0, g - 1 do + if ra[i][j].x ~= rb[i][j].x or ra[i][j].y ~= rb[i][j].y then rdet = false end +end end +check(rdet, 'relaxation is deterministic') + +-- clean borders: adjacent cells from DIFFERENT regions must get DIFFERENT ores (incl. wrap). +math.randomseed(3) +local cseeds = Layout.place_seeds(SIZE, SPACING, rand) +Layout.relax(SIZE, SPACING, cseeds, 2) +local cgrid = Layout.partition(SIZE, SPACING, cseeds) +local remap, count = {}, 0 +for x = 0, SIZE - 1 do for y = 0, SIZE - 1 do + local id = cgrid[x][y] + if not remap[id] then count = count + 1; remap[id] = count end + cgrid[x][y] = remap[id] +end end +local nb = Layout.adjacency(cgrid, SIZE) +local colors = Layout.color(count, nb, 4) +check(colors ~= nil, 'color returns a valid 4-colouring') +if colors then + local bad = 0 + for x = 0, SIZE - 1 do for y = 0, SIZE - 1 do + local id = cgrid[x][y] + local right, down = cgrid[(x + 1) % SIZE][y], cgrid[x][(y + 1) % SIZE] + if right ~= id and colors[right] == colors[id] then bad = bad + 1 end + if down ~= id and colors[down] == colors[id] then bad = bad + 1 end + end end + check(bad == 0, 'no two touching regions share an ore (incl. wrap), violations=' .. bad) +end + +-- generate: deterministic per seed; different seeds differ. +math.randomseed(5) +local a = Layout.generate { size = 16, spacing = 4, relaxation = 2, num_ores = 4, random = rand } +math.randomseed(5) +local b = Layout.generate { size = 16, spacing = 4, relaxation = 2, num_ores = 4, random = rand } +local same = true +for x = 0, 15 do for y = 0, 15 do if a[x][y] ~= b[x][y] then same = false end end end +check(same, 'generate is deterministic for a fixed seed') +math.randomseed(6) +local c2 = Layout.generate { size = 16, spacing = 4, relaxation = 2, num_ores = 4, random = rand } +local diff = false +for x = 0, 15 do for y = 0, 15 do if a[x][y] ~= c2[x][y] then diff = true end end end +check(diff, 'different seeds produce different layouts') + +-- production size guard + stone scarcity. +do + local PROD, SP = 64, 4 + local ok_count = 0 + local totals = { 0, 0, 0, 0 } + for seed = 1, 25 do + math.randomseed(seed) + local ok, grd = pcall(function() + return Layout.generate { size = PROD, spacing = SP, relaxation = 2, num_ores = 4, random = rand } + end) + if ok then + ok_count = ok_count + 1 + for x = 0, PROD - 1 do for y = 0, PROD - 1 do totals[grd[x][y]] = totals[grd[x][y]] + 1 end end + end + end + check(ok_count == 25, 'generate succeeds for all 25 seeds at production size 64, got ' .. ok_count) + local min_ore = math.min(totals[1], totals[2], totals[3], totals[4]) + check(totals[4] == min_ore, 'stone (ore 4) is the least-used ore') +end + +if failures == 0 then + print('\nALL PASSED') +else + print('\n' .. failures .. ' FAILURE(S)') + os.exit(1) +end diff --git a/map_gen/maps/danger_ores/presets/danger_ore.lua b/map_gen/maps/danger_ores/presets/danger_ore.lua index 838fac58e..093f23c9a 100644 --- a/map_gen/maps/danger_ores/presets/danger_ore.lua +++ b/map_gen/maps/danger_ores/presets/danger_ore.lua @@ -4,8 +4,8 @@ local ScenarioInfo = require 'features.gui.info' ScenarioInfo.set_map_name('Danger Ores') ScenarioInfo.add_map_extra_info([[ - This map is split in three sectors [item=iron-ore] [item=copper-ore] [item=coal]. - Each sector has a main resource and the other resources at a lower ratio. + This map is split in three sectors [item=iron-ore] [item=copper-ore] [item=coal]. + Each sector has a main resource and the other resources at a lower ratio. ]]) DOC.biter_drops.enabled = false diff --git a/map_gen/maps/danger_ores/presets/danger_ore_3way.lua b/map_gen/maps/danger_ores/presets/danger_ore_3way.lua index 55598f056..05499ef90 100644 --- a/map_gen/maps/danger_ores/presets/danger_ore_3way.lua +++ b/map_gen/maps/danger_ores/presets/danger_ore_3way.lua @@ -5,8 +5,8 @@ local ScenarioInfo = require 'features.gui.info' ScenarioInfo.set_map_name('Danger Ores - 3way') ScenarioInfo.add_map_extra_info([[ - This map is split in three sectors [item=iron-ore] [item=copper-ore] [item=coal]. - Each sector has a main resource and the other resources at a lower ratio. + This map is split in three sectors [item=iron-ore] [item=copper-ore] [item=coal]. + Each sector has a main resource and the other resources at a lower ratio. ]]) DOC.scenario_name = 'danger-ore-3way' @@ -19,18 +19,18 @@ DOC.map_config.water = nil local t_h_bound, t_v_bound = B.line_x(128), B.line_y(128) local t_crop = function(_, y) - return y < -64 + return y < -64 end local t_cross = B.any { t_h_bound, t_v_bound } local terraforming_bounds = B.subtract(t_cross, t_crop) DOC.terraforming = { - enabled = true, - start_size = 10 * 32, - min_pollution = 600, - max_pollution = 24000, - pollution_increment = 9, - bounds = terraforming_bounds, + enabled = true, + start_size = 10 * 32, + min_pollution = 600, + max_pollution = 24000, + pollution_increment = 9, + bounds = terraforming_bounds, } return Scenario.register(DOC) diff --git a/map_gen/maps/danger_ores/presets/danger_ore_angel.lua b/map_gen/maps/danger_ores/presets/danger_ore_angel.lua index 1081959cc..6be841506 100644 --- a/map_gen/maps/danger_ores/presets/danger_ore_angel.lua +++ b/map_gen/maps/danger_ores/presets/danger_ore_angel.lua @@ -1,9 +1,12 @@ local B = require 'map_gen.shared.builders' local H = require 'map_gen.maps.danger_ores.modules.helper' local DOC = require 'map_gen.maps.danger_ores.configuration' +local ModCompatibility = require 'utils.mod_compatibility' local Scenario = require 'map_gen.maps.danger_ores.scenario' local ScenarioInfo = require 'features.gui.info' +ModCompatibility.check(require 'map_gen.maps.danger_ores.compatibility.angel.mod-list') + ScenarioInfo.set_map_name('Danger Ores - Angel\'s') ScenarioInfo.add_map_extra_info([[ This map is split in 7 sectors. Each sector has a main resource. diff --git a/map_gen/maps/danger_ores/presets/danger_ore_bob.lua b/map_gen/maps/danger_ores/presets/danger_ore_bob.lua index ab0b304e5..36b4bdeb9 100644 --- a/map_gen/maps/danger_ores/presets/danger_ore_bob.lua +++ b/map_gen/maps/danger_ores/presets/danger_ore_bob.lua @@ -1,9 +1,12 @@ local B = require 'map_gen.shared.builders' local H = require 'map_gen.maps.danger_ores.modules.helper' local DOC = require 'map_gen.maps.danger_ores.configuration' +local ModCompatibility = require 'utils.mod_compatibility' local Scenario = require 'map_gen.maps.danger_ores.scenario' local ScenarioInfo = require 'features.gui.info' +ModCompatibility.check(require 'map_gen.maps.danger_ores.compatibility.bob.mod-list') + ScenarioInfo.set_map_name('Danger Ores - Bob\'s') ScenarioInfo.add_map_extra_info([[ This map is split in 16 sectors. Each sector has a main resource. @@ -36,7 +39,7 @@ DOC.map_gen_settings.settings = H.empty_map_settings{ --'bob-sulfur', 'bob-thorium-ore', 'bob-tin-ore', - 'bob-tungsten-ore', + 'tungsten-ore', 'uranium-ore', 'bob-zinc-ore', } diff --git a/map_gen/maps/danger_ores/presets/danger_ore_bob_angel.lua b/map_gen/maps/danger_ores/presets/danger_ore_bob_angel.lua index d9b5991d9..1928f83cd 100644 --- a/map_gen/maps/danger_ores/presets/danger_ore_bob_angel.lua +++ b/map_gen/maps/danger_ores/presets/danger_ore_bob_angel.lua @@ -1,9 +1,15 @@ local B = require 'map_gen.shared.builders' local H = require 'map_gen.maps.danger_ores.modules.helper' local DOC = require 'map_gen.maps.danger_ores.configuration' +local ModCompatibility = require 'utils.mod_compatibility' local Scenario = require 'map_gen.maps.danger_ores.scenario' local ScenarioInfo = require 'features.gui.info' +ModCompatibility.check(ModCompatibility.combine( + require 'map_gen.maps.danger_ores.compatibility.angel.mod-list', + require 'map_gen.maps.danger_ores.compatibility.bob.mod-list' +)) + ScenarioInfo.set_map_name('Danger Ores - Bob & Angel\'s') ScenarioInfo.add_map_extra_info([[ This map is split in 7 sectors. Each sector has a main resource. diff --git a/map_gen/maps/danger_ores/presets/danger_ore_bz.lua b/map_gen/maps/danger_ores/presets/danger_ore_bz.lua index 51ee0edbd..cb81d003a 100644 --- a/map_gen/maps/danger_ores/presets/danger_ore_bz.lua +++ b/map_gen/maps/danger_ores/presets/danger_ore_bz.lua @@ -1,11 +1,14 @@ local H = require 'map_gen.maps.danger_ores.modules.helper' local DOC = require 'map_gen.maps.danger_ores.configuration' +local ModCompatibility = require 'utils.mod_compatibility' local Scenario = require 'map_gen.maps.danger_ores.scenario' local ScenarioInfo = require 'features.gui.info' +ModCompatibility.check(require 'map_gen.maps.danger_ores.compatibility.bz.mod-list') + ScenarioInfo.set_map_name('Danger Ores - Very BZ') ScenarioInfo.add_map_extra_info([[ - This map is split in 15 sectors. Each sector has a main resource. + This map is split in 15 sectors. Each sector has a main resource. ]]) DOC.scenario_name = 'danger-ore-bz' @@ -15,26 +18,26 @@ DOC.map_config.main_ores = require 'map_gen.maps.danger_ores.compatibility.bz.or DOC.map_config.resource_patches_config = require 'map_gen.maps.danger_ores.compatibility.bz.resource_patches' DOC.map_config.spawn_tile = script.active_mods['alien-biomes'] and 'volcanic-green-heat-2' or 'grass-1' DOC.rocket_launched.win_satellite_count = 100 -DOC.map_gen_settings.settings = H.empty_map_settings{ - -- fluid patches - 'crude-oil', - 'gas', - -- ore patches - 'aluminum-ore', - 'coal', - 'copper-ore', - 'gold-ore', - 'graphite', - 'iron-ore', - 'lead-ore', - 'rich-copper-ore', - 'salt', - 'stone', - 'tin-ore', - 'titanium-ore', - 'tungsten-ore', - 'uranium-ore', - 'zircon', +DOC.map_gen_settings.settings = H.empty_map_settings { + -- fluid patches + 'crude-oil', + 'gas', + -- ore patches + 'aluminum-ore', + 'coal', + 'copper-ore', + 'gold-ore', + 'graphite', + 'iron-ore', + 'lead-ore', + 'rich-copper-ore', + 'salt', + 'stone', + 'tin-ore', + 'titanium-ore', + 'tungsten-ore', + 'uranium-ore', + 'zircon', } return Scenario.register(DOC) diff --git a/map_gen/maps/danger_ores/presets/danger_ore_chessboard.lua b/map_gen/maps/danger_ores/presets/danger_ore_chessboard.lua index 6091571cb..48d033367 100644 --- a/map_gen/maps/danger_ores/presets/danger_ore_chessboard.lua +++ b/map_gen/maps/danger_ores/presets/danger_ore_chessboard.lua @@ -4,8 +4,8 @@ local ScenarioInfo = require 'features.gui.info' ScenarioInfo.set_map_name('Danger Ores - Chessboard') ScenarioInfo.add_map_extra_info([[ - This map is split in three sectors [item=iron-ore] [item=copper-ore] [item=coal]. - Each sector has a main resource and the other resources at a lower ratio. + This map is split in three sectors [item=iron-ore] [item=copper-ore] [item=coal]. + Each sector has a main resource and the other resources at a lower ratio. ]]) DOC.scenario_name = 'danger-ore-chessboard' diff --git a/map_gen/maps/danger_ores/presets/danger_ore_circles.lua b/map_gen/maps/danger_ores/presets/danger_ore_circles.lua index c6ac9a26a..5b7c2d3ce 100644 --- a/map_gen/maps/danger_ores/presets/danger_ore_circles.lua +++ b/map_gen/maps/danger_ores/presets/danger_ore_circles.lua @@ -4,8 +4,8 @@ local ScenarioInfo = require 'features.gui.info' ScenarioInfo.set_map_name('Danger Ores - Circles') ScenarioInfo.add_map_extra_info([[ - This map is split in three sectors [item=iron-ore] [item=copper-ore] [item=coal]. - Each sector has a main resource and the other resources at a lower ratio. + This map is split in three sectors [item=iron-ore] [item=copper-ore] [item=coal]. + Each sector has a main resource and the other resources at a lower ratio. ]]) DOC.scenario_name = 'danger-ore-circles' diff --git a/map_gen/maps/danger_ores/presets/danger_ore_collapse.lua b/map_gen/maps/danger_ores/presets/danger_ore_collapse.lua index ddc12cb5a..9ede739ca 100644 --- a/map_gen/maps/danger_ores/presets/danger_ore_collapse.lua +++ b/map_gen/maps/danger_ores/presets/danger_ore_collapse.lua @@ -1,8 +1,13 @@ local DOC = require 'map_gen.maps.danger_ores.configuration' +local ModCompatibility = require 'utils.mod_compatibility' local Scenario = require 'map_gen.maps.danger_ores.scenario' local ScenarioInfo = require 'features.gui.info' +ModCompatibility.check { + dependencies = {{ name = 'ore-evolution' }} +} + ScenarioInfo.set_map_name('Danger Ores - Collapse') ScenarioInfo.add_map_extra_info([[ This map is covered in [item=coal] with mixed dense patches containing [item=iron-ore] [item=copper-ore] [item=stone]. diff --git a/map_gen/maps/danger_ores/presets/danger_ore_exotic_industries.lua b/map_gen/maps/danger_ores/presets/danger_ore_exotic_industries.lua index 525feb821..822bfb14c 100644 --- a/map_gen/maps/danger_ores/presets/danger_ore_exotic_industries.lua +++ b/map_gen/maps/danger_ores/presets/danger_ore_exotic_industries.lua @@ -1,12 +1,15 @@ local H = require 'map_gen.maps.danger_ores.modules.helper' local DOC = require 'map_gen.maps.danger_ores.configuration' +local ModCompatibility = require 'utils.mod_compatibility' local Scenario = require 'map_gen.maps.danger_ores.scenario' local ScenarioInfo = require 'features.gui.info' +ModCompatibility.check(require 'map_gen.maps.danger_ores.compatibility.exotic_industries.mod-list') + ScenarioInfo.set_map_name('Danger Ores - Exotic Industries') ScenarioInfo.add_map_extra_info([[ - This map is split in 3 sectors. Each sector has a main resource. - Resource veins are scattered across the map. + This map is split in 3 sectors. Each sector has a main resource. + Resource veins are scattered across the map. ]]) storage.config.redmew_qol.loaders = false @@ -16,21 +19,21 @@ DOC.compatibility.redmew_data.remove_resource_patches = false DOC.game.technology_price_multiplier = 1 DOC.map_config.resource_patches_config = require 'map_gen.maps.danger_ores.compatibility.exotic_industries.resource_patches' DOC.allowed_entities.allowed_entities['ei_alien-stabilizer'] = true -DOC.map_gen_settings.settings = H.empty_map_settings{ - -- point patches - 'crude-oil', - 'ei_coal-patch', - 'ei_copper-patch', - 'ei_gold-patch', - 'ei_iron-patch', - 'ei_lead-patch', - 'ei_neodym-patch', - 'ei_sulfur-patch', - 'ei_uranium-patch', - -- ore patches - 'coal', - 'copper-ore', - 'iron-ore', +DOC.map_gen_settings.settings = H.empty_map_settings { + -- point patches + 'crude-oil', + 'ei_coal-patch', + 'ei_copper-patch', + 'ei_gold-patch', + 'ei_iron-patch', + 'ei_lead-patch', + 'ei_neodym-patch', + 'ei_sulfur-patch', + 'ei_uranium-patch', + -- ore patches + 'coal', + 'copper-ore', + 'iron-ore', } DOC.biter_drops.enabled = false diff --git a/map_gen/maps/danger_ores/presets/danger_ore_exotic_industries_spiral.lua b/map_gen/maps/danger_ores/presets/danger_ore_exotic_industries_spiral.lua index afe6292ff..8ed2aaa64 100644 --- a/map_gen/maps/danger_ores/presets/danger_ore_exotic_industries_spiral.lua +++ b/map_gen/maps/danger_ores/presets/danger_ore_exotic_industries_spiral.lua @@ -1,12 +1,15 @@ local H = require 'map_gen.maps.danger_ores.modules.helper' local DOC = require 'map_gen.maps.danger_ores.configuration' +local ModCompatibility = require 'utils.mod_compatibility' local Scenario = require 'map_gen.maps.danger_ores.scenario' local ScenarioInfo = require 'features.gui.info' +ModCompatibility.check(require 'map_gen.maps.danger_ores.compatibility.exotic_industries.mod-list') + ScenarioInfo.set_map_name('Danger Ores - Exotic Industries Spiral') ScenarioInfo.add_map_extra_info([[ - This map is split in 3 sectors. Each sector has a main resource. - Resource veins are scattered across the map. + This map is split in 3 sectors. Each sector has a main resource. + Resource veins are scattered across the map. ]]) storage.config.redmew_qol.loaders = false @@ -19,21 +22,21 @@ DOC.map_config.no_resource_patch_shape = nil DOC.map_config.resource_patches_config = require 'map_gen.maps.danger_ores.compatibility.exotic_industries.resource_patches' DOC.map_config.spawn_tile = 'landfill' DOC.allowed_entities.allowed_entities['ei_alien-stabilizer'] = true -DOC.map_gen_settings.settings = H.empty_map_settings{ - -- point patches - 'crude-oil', - 'ei_coal-patch', - 'ei_copper-patch', - 'ei_gold-patch', - 'ei_iron-patch', - 'ei_lead-patch', - 'ei_neodym-patch', - 'ei_sulfur-patch', - 'ei_uranium-patch', - -- ore patches - 'coal', - 'copper-ore', - 'iron-ore', +DOC.map_gen_settings.settings = H.empty_map_settings { + -- point patches + 'crude-oil', + 'ei_coal-patch', + 'ei_copper-patch', + 'ei_gold-patch', + 'ei_iron-patch', + 'ei_lead-patch', + 'ei_neodym-patch', + 'ei_sulfur-patch', + 'ei_uranium-patch', + -- ore patches + 'coal', + 'copper-ore', + 'iron-ore', } DOC.biter_drops.enabled = false diff --git a/map_gen/maps/danger_ores/presets/danger_ore_expanse.lua b/map_gen/maps/danger_ores/presets/danger_ore_expanse.lua index 848d5f436..729e60688 100644 --- a/map_gen/maps/danger_ores/presets/danger_ore_expanse.lua +++ b/map_gen/maps/danger_ores/presets/danger_ore_expanse.lua @@ -5,43 +5,43 @@ local ScenarioInfo = require 'features.gui.info' ScenarioInfo.set_map_name('Danger Ores - Expanse') ScenarioInfo.set_map_description([[ - DangerOres meets The Expanse! + DangerOres meets The Expanse! - Clear the ore to expand the base, - focus mining efforts on specific sectors to ensure - proper material ratios, consume as much resources as possible! + Clear the ore to expand the base, + focus mining efforts on specific sectors to ensure + proper material ratios, consume as much resources as possible! -- AND -- - Feed the hungry blue chests with the materials they require. - The Elder Tree and the Infinity Stone you find at spawn will - provide you with all the wood and ores you ever desired. + Feed the hungry blue chests with the materials they require. + The Elder Tree and the Infinity Stone you find at spawn will + provide you with all the wood and ores you ever desired. ]]) ScenarioInfo.add_map_extra_info([[ - This map is split in three sectors [item=iron-ore] [item=copper-ore] [item=coal]. - Each sector has a main resource and the other resources at a lower ratio. - - You may not build the factory on ore patches. Exceptions: - [item=burner-mining-drill] [item=electric-mining-drill] [item=pumpjack] [item=small-electric-pole] [item=medium-electric-pole] [item=big-electric-pole] [item=substation] [item=car] [item=tank] [item=spidertron] [item=locomotive] [item=cargo-wagon] [item=fluid-wagon] [item=artillery-wagon] - [item=transport-belt] [item=fast-transport-belt] [item=express-transport-belt] [item=underground-belt] [item=fast-underground-belt] [item=express-underground-belt] [item=rail] [item=rail-signal] [item=rail-chain-signal] [item=train-stop] - - The map size is restricted by the Hungry Chests. Provide the requested materials to unlock new chunks. - Use the Elder Tree [entity=tree-01], the Infinity Rock [entity=huge-rock], and the Precious Oil patch [entity=crude-oil] located at spawn [gps=0,0.redmew] - to draw more resources when in need, but always favor Danger Ores first if you can. - If you find yourself stuck with the requests, insert a Coin [item=coin] into the Hungry Chest [item=requester-chest] to reroll the request. - You can fulfill part of the request & then reroll to change the remaining part (it will always reroll based on its remaining content to be fulfilled). - Unlocking new land may or may not reward you with another Coin. + This map is split in three sectors [item=iron-ore] [item=copper-ore] [item=coal]. + Each sector has a main resource and the other resources at a lower ratio. + + You may not build the factory on ore patches. Exceptions: + [item=burner-mining-drill] [item=electric-mining-drill] [item=pumpjack] [item=small-electric-pole] [item=medium-electric-pole] [item=big-electric-pole] [item=substation] [item=car] [item=tank] [item=spidertron] [item=locomotive] [item=cargo-wagon] [item=fluid-wagon] [item=artillery-wagon] + [item=transport-belt] [item=fast-transport-belt] [item=express-transport-belt] [item=underground-belt] [item=fast-underground-belt] [item=express-underground-belt] [item=rail] [item=rail-signal] [item=rail-chain-signal] [item=train-stop] + + The map size is restricted by the Hungry Chests. Provide the requested materials to unlock new chunks. + Use the Elder Tree [entity=tree-01], the Infinity Rock [entity=huge-rock], and the Precious Oil patch [entity=crude-oil] located at spawn [gps=0,0.redmew] + to draw more resources when in need, but always favor Danger Ores first if you can. + If you find yourself stuck with the requests, insert a Coin [item=coin] into the Hungry Chest [item=requester-chest] to reroll the request. + You can fulfill part of the request & then reroll to change the remaining part (it will always reroll based on its remaining content to be fulfilled). + Unlocking new land may or may not reward you with another Coin. ]]) Config.market.enabled = false Config.player_rewards.enabled = true Config.player_create.starting_items = { - { count = 1, name = 'burner-mining-drill' }, - { count = 1, name = 'stone-furnace' }, - { count = 1, name = 'wood' }, - { count = 1, name = 'pistol' }, - { count = 20, name = 'firearm-magazine' }, - { count = 5, name = 'coin' }, + { count = 1, name = 'burner-mining-drill' }, + { count = 1, name = 'stone-furnace' }, + { count = 1, name = 'wood' }, + { count = 1, name = 'pistol' }, + { count = 20, name = 'firearm-magazine' }, + { count = 5, name = 'coin' }, } DOC.scenario_name = 'danger-ore-expanse' diff --git a/map_gen/maps/danger_ores/presets/danger_ore_for_the_swarm.lua b/map_gen/maps/danger_ores/presets/danger_ore_for_the_swarm.lua index 9db42da41..97dc3e9bc 100644 --- a/map_gen/maps/danger_ores/presets/danger_ore_for_the_swarm.lua +++ b/map_gen/maps/danger_ores/presets/danger_ore_for_the_swarm.lua @@ -5,23 +5,23 @@ local ScenarioInfo = require 'features.gui.info' ScenarioInfo.set_map_name('Danger Ores For The Swarm') ScenarioInfo.add_map_extra_info([[ - The Swarm hungers [item=spidertron], feed it all the ore to expand the base, - focus mining efforts on specific sectors to ensure - proper material ratios, expand the map with pollution! + The Swarm hungers [item=spidertron], feed it all the ore to expand the base, + focus mining efforts on specific sectors to ensure + proper material ratios, expand the map with pollution! - This map is split in four sectors [item=iron-ore] [item=copper-ore] [item=coal] [item=stone]. - Each sector has a main resource and the other resources at a lower ratio. + This map is split in four sectors [item=iron-ore] [item=copper-ore] [item=coal] [item=stone]. + Each sector has a main resource and the other resources at a lower ratio. ]]) Config.player_create.starting_items = { - { count = 1, name = 'power-armor' }, - { count = 9, name = 'personal-roboport-equipment' }, - { count = 13, name = 'solar-panel-equipment' }, - { count = 1000, name = 'early-construction-robot' }, - { count = 1, name = 'spidertron' }, - { count = 1, name = 'spidertron-powersource' }, - { count = 10, name = 'spidertron-battery' }, - { count = 3, name = 'spidertron-leg-augment' }, + { count = 1, name = 'power-armor' }, + { count = 9, name = 'personal-roboport-equipment' }, + { count = 13, name = 'solar-panel-equipment' }, + { count = 1000, name = 'early-construction-robot' }, + { count = 1, name = 'spidertron' }, + { count = 1, name = 'spidertron-powersource' }, + { count = 10, name = 'spidertron-battery' }, + { count = 3, name = 'spidertron-leg-augment' }, } DOC.scenario_name = 'danger-ore-for-the-swarm' diff --git a/map_gen/maps/danger_ores/presets/danger_ore_gradient.lua b/map_gen/maps/danger_ores/presets/danger_ore_gradient.lua index 1c8beb29f..bd799d912 100644 --- a/map_gen/maps/danger_ores/presets/danger_ore_gradient.lua +++ b/map_gen/maps/danger_ores/presets/danger_ore_gradient.lua @@ -4,8 +4,8 @@ local ScenarioInfo = require 'features.gui.info' ScenarioInfo.set_map_name('Danger Ores - Gradient') ScenarioInfo.add_map_extra_info([[ - This map is split in three sectors [item=iron-ore] [item=copper-ore] [item=coal]. - Each sector has a main resource and the other resources at a lower ratio. + This map is split in three sectors [item=iron-ore] [item=copper-ore] [item=coal]. + Each sector has a main resource and the other resources at a lower ratio. ]]) DOC.scenario_name = 'danger-ore-gradient' diff --git a/map_gen/maps/danger_ores/presets/danger_ore_grid_factory.lua b/map_gen/maps/danger_ores/presets/danger_ore_grid_factory.lua index e56aad464..0792174b0 100644 --- a/map_gen/maps/danger_ores/presets/danger_ore_grid_factory.lua +++ b/map_gen/maps/danger_ores/presets/danger_ore_grid_factory.lua @@ -5,8 +5,8 @@ local ScenarioInfo = require 'features.gui.info' ScenarioInfo.set_map_name('Danger Ores - Grid Factory') ScenarioInfo.add_map_extra_info([[ - This map is divided in quadrants of [item=iron-ore] [item=copper-ore] [item=coal]. - Each sector has a main resource and the other resources at a lower ratio. + This map is divided in quadrants of [item=iron-ore] [item=copper-ore] [item=coal]. + Each sector has a main resource and the other resources at a lower ratio. ]]) DOC.scenario_name = 'danger-ore-grid-factory' diff --git a/map_gen/maps/danger_ores/presets/danger_ore_gridlocked.lua b/map_gen/maps/danger_ores/presets/danger_ore_gridlocked.lua index daf17f9f5..63de65f65 100644 --- a/map_gen/maps/danger_ores/presets/danger_ore_gridlocked.lua +++ b/map_gen/maps/danger_ores/presets/danger_ore_gridlocked.lua @@ -1,17 +1,22 @@ local B = require 'map_gen.shared.builders' local DOC = require 'map_gen.maps.danger_ores.configuration' +local ModCompatibility = require 'utils.mod_compatibility' local Scenario = require 'map_gen.maps.danger_ores.scenario' local ScenarioInfo = require 'features.gui.info' +ModCompatibility.check { + dependencies = {{ name = 'gridlocked' }} +} + ScenarioInfo.set_map_name('Danger Ores - Gridlocked') ScenarioInfo.add_map_extra_info([[ - This map is divided in quadrants of [item=iron-ore] [item=copper-ore] [item=coal] [item=stone]. - Each sector has a main resource and the other resources at a lower ratio. + This map is divided in quadrants of [item=iron-ore] [item=copper-ore] [item=coal] [item=stone]. + Each sector has a main resource and the other resources at a lower ratio. - Unlock new chunks via [font=default-bold]Chunk claim tool (Alt + K)[/font]. - Chunk purchases can be reverted within 30s from purchase. - Chunk points are awarded by completing [technology=gl-additional-chunk-space-science-pack] Technology: Additional chunks. - Chunk cost is computed based on adjacient chunks. + Unlock new chunks via [font=default-bold]Chunk claim tool (Alt + K)[/font]. + Chunk purchases can be reverted within 30s from purchase. + Chunk points are awarded by completing [technology=gl-additional-chunk-space-science-pack] Technology: Additional chunks. + Chunk cost is computed based on adjacient chunks. ]]) DOC.scenario_name = 'danger-ore-gridlocked' diff --git a/map_gen/maps/danger_ores/presets/danger_ore_hub_spiral.lua b/map_gen/maps/danger_ores/presets/danger_ore_hub_spiral.lua index dc12e71aa..768aaf288 100644 --- a/map_gen/maps/danger_ores/presets/danger_ore_hub_spiral.lua +++ b/map_gen/maps/danger_ores/presets/danger_ore_hub_spiral.lua @@ -5,15 +5,15 @@ local sqrt = math.sqrt ScenarioInfo.set_map_name('Danger Ores - Hub Spiral') ScenarioInfo.add_map_extra_info([[ - This map is split in three sectors [item=iron-ore] [item=copper-ore] [item=coal]. - Each sector has a main resource and the other resources at a lower ratio. + This map is split in three sectors [item=iron-ore] [item=copper-ore] [item=coal]. + Each sector has a main resource and the other resources at a lower ratio. ]]) DOC.scenario_name = 'danger-ore-hub-spiral' DOC.map_config.main_ores_builder = require 'map_gen.maps.danger_ores.modules.main_ores_hub_spiral' DOC.map_config.water_scale = function(x, y) - local d = sqrt(x * x + y * y) - return 1 / (24 + (0.1 * d)) + local d = sqrt(x * x + y * y) + return 1 / (24 + (0.1 * d)) end return Scenario.register(DOC) diff --git a/map_gen/maps/danger_ores/presets/danger_ore_industrial_revolution_3.lua b/map_gen/maps/danger_ores/presets/danger_ore_industrial_revolution_3.lua index 03edee764..a341a0a57 100644 --- a/map_gen/maps/danger_ores/presets/danger_ore_industrial_revolution_3.lua +++ b/map_gen/maps/danger_ores/presets/danger_ore_industrial_revolution_3.lua @@ -1,50 +1,53 @@ local H = require 'map_gen.maps.danger_ores.modules.helper' local DOC = require 'map_gen.maps.danger_ores.configuration' local Config = require 'config' +local ModCompatibility = require 'utils.mod_compatibility' local Scenario = require 'map_gen.maps.danger_ores.scenario' local ScenarioInfo = require 'features.gui.info' +ModCompatibility.check(require 'map_gen.maps.danger_ores.compatibility.industrial_revolution_3.mod-list') + ScenarioInfo.set_map_name('Danger Ores - Industrial Revolution 3') ScenarioInfo.add_map_extra_info([[ - This map is split in 6 sectors. Each sector has a main resource. Gas fissures are scattered across the map. + This map is split in 6 sectors. Each sector has a main resource. Gas fissures are scattered across the map. ]]) Config.redmew_qol.loaders = false Config.player_create.starting_items = { - { count = 1, name = 'shotgun' }, - { count = 4, name = 'burner-mining-drill' }, - { count = 4, name = 'stone-furnace' }, - { count = 25, name = 'copper-rivet' }, - { count = 25, name = 'copper-rod' }, - { count = 25, name = 'tin-gear-wheel' }, - { count = 25, name = 'tin-plate' }, - { count = 25, name = 'tin-rod' }, - { count = 50, name = 'copper-gear-wheel' }, - { count = 50, name = 'copper-plate' }, - { count = 50, name = 'shotgun-shell' }, - { count = 100, name = 'tin-scrap' }, - { count = 150, name = 'copper-scrap' }, + { count = 1, name = 'shotgun' }, + { count = 4, name = 'burner-mining-drill' }, + { count = 4, name = 'stone-furnace' }, + { count = 25, name = 'copper-rivet' }, + { count = 25, name = 'copper-rod' }, + { count = 25, name = 'tin-gear-wheel' }, + { count = 25, name = 'tin-plate' }, + { count = 25, name = 'tin-rod' }, + { count = 50, name = 'copper-gear-wheel' }, + { count = 50, name = 'copper-plate' }, + { count = 50, name = 'shotgun-shell' }, + { count = 100, name = 'tin-scrap' }, + { count = 150, name = 'copper-scrap' }, } DOC.scenario_name = 'danger-ore-industrial-revolution-3' DOC.game.technology_price_multiplier = 5 DOC.map_config.main_ores = require 'map_gen.maps.danger_ores.compatibility.industrial_revolution_3.ores' DOC.map_config.resource_patches_config = require 'map_gen.maps.danger_ores.compatibility.industrial_revolution_3.resource_patches' -DOC.map_gen_settings.settings = H.empty_map_settings{ - -- point patches - 'crude-oil', - 'dirty-steam-fissure', - 'natural-gas-fissure', - 'steam-fissure', - 'sulphur-gas-fissure', - -- ore patches - 'coal', - 'copper-ore', - 'iron-ore', - 'stone', - 'uranium-ore', - 'gold-ore', - 'tin-ore', +DOC.map_gen_settings.settings = H.empty_map_settings { + -- point patches + 'crude-oil', + 'dirty-steam-fissure', + 'natural-gas-fissure', + 'steam-fissure', + 'sulphur-gas-fissure', + -- ore patches + 'coal', + 'copper-ore', + 'iron-ore', + 'stone', + 'uranium-ore', + 'gold-ore', + 'tin-ore', } return Scenario.register(DOC) diff --git a/map_gen/maps/danger_ores/presets/danger_ore_industrial_revolution_3_grid_factory.lua b/map_gen/maps/danger_ores/presets/danger_ore_industrial_revolution_3_grid_factory.lua index 5831684f2..665c7e46c 100644 --- a/map_gen/maps/danger_ores/presets/danger_ore_industrial_revolution_3_grid_factory.lua +++ b/map_gen/maps/danger_ores/presets/danger_ore_industrial_revolution_3_grid_factory.lua @@ -2,29 +2,32 @@ local B = require 'map_gen.shared.builders' local H = require 'map_gen.maps.danger_ores.modules.helper' local DOC = require 'map_gen.maps.danger_ores.configuration' local Config = require 'config' +local ModCompatibility = require 'utils.mod_compatibility' local Scenario = require 'map_gen.maps.danger_ores.scenario' local ScenarioInfo = require 'features.gui.info' +ModCompatibility.check(require 'map_gen.maps.danger_ores.compatibility.industrial_revolution_3.mod-list') + ScenarioInfo.set_map_name('Danger Ores - Industrial Revolution 3 Grid Factory') ScenarioInfo.add_map_extra_info([[ - This map is split in 6 sectors. Each sector has a main resource. Gas fissures are scattered across the map. + This map is split in 6 sectors. Each sector has a main resource. Gas fissures are scattered across the map. ]]) Config.redmew_qol.loaders = false Config.player_create.starting_items = { - { count = 1, name = 'shotgun' }, - { count = 4, name = 'burner-mining-drill' }, - { count = 4, name = 'stone-furnace' }, - { count = 25, name = 'copper-rivet' }, - { count = 25, name = 'copper-rod' }, - { count = 25, name = 'tin-gear-wheel' }, - { count = 25, name = 'tin-plate' }, - { count = 25, name = 'tin-rod' }, - { count = 50, name = 'copper-gear-wheel' }, - { count = 50, name = 'copper-plate' }, - { count = 50, name = 'shotgun-shell' }, - { count = 100, name = 'tin-scrap' }, - { count = 150, name = 'copper-scrap' }, + { count = 1, name = 'shotgun' }, + { count = 4, name = 'burner-mining-drill' }, + { count = 4, name = 'stone-furnace' }, + { count = 25, name = 'copper-rivet' }, + { count = 25, name = 'copper-rod' }, + { count = 25, name = 'tin-gear-wheel' }, + { count = 25, name = 'tin-plate' }, + { count = 25, name = 'tin-rod' }, + { count = 50, name = 'copper-gear-wheel' }, + { count = 50, name = 'copper-plate' }, + { count = 50, name = 'shotgun-shell' }, + { count = 100, name = 'tin-scrap' }, + { count = 150, name = 'copper-scrap' }, } DOC.scenario_name = 'danger-ore-industrial-revolution-3-grid-factory' @@ -36,21 +39,21 @@ DOC.map_config.spawn_tile = 'tarmac' DOC.map_config.spawn_shape = B.circle(20) DOC.map_config.start_ore_shape = B.circle(40) DOC.map_config.no_resource_patch_shape = B.circle(80) -DOC.map_gen_settings.settings = H.empty_map_settings{ - -- point patches - 'crude-oil', - 'dirty-steam-fissure', - 'natural-gas-fissure', - 'steam-fissure', - 'sulphur-gas-fissure', - -- ore patches - 'coal', - 'copper-ore', - 'iron-ore', - 'stone', - 'uranium-ore', - 'gold-ore', - 'tin-ore', +DOC.map_gen_settings.settings = H.empty_map_settings { + -- point patches + 'crude-oil', + 'dirty-steam-fissure', + 'natural-gas-fissure', + 'steam-fissure', + 'sulphur-gas-fissure', + -- ore patches + 'coal', + 'copper-ore', + 'iron-ore', + 'stone', + 'uranium-ore', + 'gold-ore', + 'tin-ore', } return Scenario.register(DOC) diff --git a/map_gen/maps/danger_ores/presets/danger_ore_krastorio2.lua b/map_gen/maps/danger_ores/presets/danger_ore_krastorio2.lua index 5a1a2450c..a5b95bdf7 100644 --- a/map_gen/maps/danger_ores/presets/danger_ore_krastorio2.lua +++ b/map_gen/maps/danger_ores/presets/danger_ore_krastorio2.lua @@ -1,31 +1,34 @@ local H = require 'map_gen.maps.danger_ores.modules.helper' local DOC = require 'map_gen.maps.danger_ores.configuration' local Config = require 'config' +local ModCompatibility = require 'utils.mod_compatibility' local Scenario = require 'map_gen.maps.danger_ores.scenario' local ScenarioInfo = require 'features.gui.info' +ModCompatibility.check(require 'map_gen.maps.danger_ores.compatibility.krastorio2.mod-list') + ScenarioInfo.set_map_name('Danger Ores - Krastorio2') ScenarioInfo.add_map_extra_info([[ - This map is split in four sectors [item=iron-ore] [item=copper-ore] [item=coal] [item=stone]. - Each sector has a main resource and the other resources at a lower ratio. + This map is split in four sectors [item=iron-ore] [item=copper-ore] [item=coal] [item=stone]. + Each sector has a main resource and the other resources at a lower ratio. ]]) Config.redmew_qol.loaders = false Config.player_create.starting_items = { - { count = 1, name = 'assembling-machine-1' }, - { count = 1, name = 'burner-mining-drill' }, - { count = 200, name = 'copper-cable' }, - { count = 25, name = 'electronic-circuit' }, - { count = 35, name = 'iron-gear-wheel' }, - { count = 400, name = 'iron-plate' }, - { count = 1, name = 'kr-medium-container' }, - { count = 5, name = 'kr-sentinel' }, - { count = 5, name = 'kr-wind-turbine' }, - { count = 1, name = 'lab' }, - { count = 5, name = 'medium-electric-pole' }, - { count = 1, name = 'steel-chest' }, - { count = 1, name = 'stone-furnace' }, - { count = 50, name = 'wood' }, + { count = 1, name = 'assembling-machine-1' }, + { count = 1, name = 'burner-mining-drill' }, + { count = 200, name = 'copper-cable' }, + { count = 25, name = 'electronic-circuit' }, + { count = 35, name = 'iron-gear-wheel' }, + { count = 400, name = 'iron-plate' }, + { count = 1, name = 'kr-medium-container' }, + { count = 5, name = 'kr-sentinel' }, + { count = 5, name = 'kr-wind-turbine' }, + { count = 1, name = 'lab' }, + { count = 5, name = 'medium-electric-pole' }, + { count = 1, name = 'steel-chest' }, + { count = 1, name = 'stone-furnace' }, + { count = 50, name = 'wood' }, } DOC.scenario_name = 'danger-ore-krastorio2' @@ -33,23 +36,23 @@ DOC.compatibility.deadlock.items = require 'map_gen.maps.danger_ores.compatibili DOC.game.technology_price_multiplier = 5 DOC.map_config.spawn_tile = 'landfill' DOC.map_config.main_ores = require 'map_gen.maps.danger_ores.compatibility.krastorio2.ores' -DOC.map_gen_settings.settings = H.empty_map_settings{ - 'coal', - 'copper-ore', - 'crude-oil', - 'kr-imersite', - 'iron-ore', - 'kr-mineral-water', - 'kr-rare-metal-ore', - 'stone', - 'uranium-ore', +DOC.map_gen_settings.settings = H.empty_map_settings { + 'coal', + 'copper-ore', + 'crude-oil', + 'kr-imersite', + 'iron-ore', + 'kr-mineral-water', + 'kr-rare-metal-ore', + 'stone', + 'uranium-ore', } DOC.terraforming = { - enabled = true, - start_size = 10 * 32, - min_pollution = 400, - max_pollution = 16000, - pollution_increment = 8, + enabled = true, + start_size = 10 * 32, + min_pollution = 400, + max_pollution = 16000, + pollution_increment = 8, } --[[ Win condition in K2: build intergalactic transceiver ]] diff --git a/map_gen/maps/danger_ores/presets/danger_ore_landfill.lua b/map_gen/maps/danger_ores/presets/danger_ore_landfill.lua index 7b6b34cec..9130de377 100644 --- a/map_gen/maps/danger_ores/presets/danger_ore_landfill.lua +++ b/map_gen/maps/danger_ores/presets/danger_ore_landfill.lua @@ -4,8 +4,8 @@ local ScenarioInfo = require 'features.gui.info' ScenarioInfo.set_map_name('Danger Ores - Landfill') ScenarioInfo.add_map_extra_info([[ - This map is split in three sectors [item=iron-ore] [item=copper-ore] [item=coal]. - Each sector has a main resource and the other resources at a lower ratio. + This map is split in three sectors [item=iron-ore] [item=copper-ore] [item=coal]. + Each sector has a main resource and the other resources at a lower ratio. ]]) DOC.scenario_name = 'danger-ore-landfill' diff --git a/map_gen/maps/danger_ores/presets/danger_ore_lazy_one.lua b/map_gen/maps/danger_ores/presets/danger_ore_lazy_one.lua index 333dc5501..a6583f041 100644 --- a/map_gen/maps/danger_ores/presets/danger_ore_lazy_one.lua +++ b/map_gen/maps/danger_ores/presets/danger_ore_lazy_one.lua @@ -5,26 +5,26 @@ local ScenarioInfo = require 'features.gui.info' ScenarioInfo.set_map_name('Danger Ores - Lazy One') ScenarioInfo.add_map_extra_info([[ - This map is split in three sectors [item=iron-ore] [item=copper-ore] [item=coal]. - Each sector has a main resource and the other resources at a lower ratio. + This map is split in three sectors [item=iron-ore] [item=copper-ore] [item=coal]. + Each sector has a main resource and the other resources at a lower ratio. ]]) Config.permissions.presets.no_handcraft = true Config.player_create.starting_items = { - { count = 1, name = 'steel-furnace' }, - { count = 1, name = 'electric-mining-drill-2' }, - { count = 1, name = 'medium-electric-pole' }, - { count = 1, name = 'offshore-pump' }, - { count = 1, name = 'boiler-2' }, - { count = 1, name = 'steam-turbine' }, - { count = 1, name = 'assembling-machine-2' }, - { count = 1, name = 'fast-inserter' }, - { count = 1, name = 'long-handed-inserter' }, - { count = 1, name = 'steel-chest' }, - { count = 1, name = 'storehouse-basic' }, - { count = 1, name = 'lab' }, - { count = 1, name = 'radar' }, - { count = 1, name = 'rocket-fuel' }, + { count = 1, name = 'steel-furnace' }, + { count = 1, name = 'electric-mining-drill-2' }, + { count = 1, name = 'medium-electric-pole' }, + { count = 1, name = 'offshore-pump' }, + { count = 1, name = 'boiler-2' }, + { count = 1, name = 'steam-turbine' }, + { count = 1, name = 'assembling-machine-2' }, + { count = 1, name = 'fast-inserter' }, + { count = 1, name = 'long-handed-inserter' }, + { count = 1, name = 'steel-chest' }, + { count = 1, name = 'storehouse-basic' }, + { count = 1, name = 'lab' }, + { count = 1, name = 'radar' }, + { count = 1, name = 'rocket-fuel' }, } DOC.scenario_name = 'danger-ore-lazy-one' diff --git a/map_gen/maps/danger_ores/presets/danger_ore_normal_science.lua b/map_gen/maps/danger_ores/presets/danger_ore_normal_science.lua index f63cf1ca6..f367e1a2e 100644 --- a/map_gen/maps/danger_ores/presets/danger_ore_normal_science.lua +++ b/map_gen/maps/danger_ores/presets/danger_ore_normal_science.lua @@ -5,50 +5,50 @@ local ScenarioInfo = require 'features.gui.info' ScenarioInfo.set_map_name('Danger Ores - Normal Science') ScenarioInfo.add_map_extra_info([[ - This map is split in three sectors [item=iron-ore] [item=copper-ore] [item=coal]. - Each sector has a main resource and the other resources at a lower ratio. + This map is split in three sectors [item=iron-ore] [item=copper-ore] [item=coal]. + Each sector has a main resource and the other resources at a lower ratio. ]]) Config.hail_hydra.enabled = true Config.hail_hydra.online_player_scale_enabled = false Config.hail_hydra.hydras = { - -- spitters - ['medium-spitter'] = { - ['small-worm-turret'] = { min = 0.250, max = 0.50 }, - }, - ['big-spitter'] = { - ['big-worm-turret'] = { min = 0.250, max = 0.50 }, - }, - ['behemoth-spitter'] = { - ['big-worm-turret'] = { min = 0.250, max = 0.50 }, - }, - -- biters - ['medium-biter'] = { - ['small-worm-turret'] = { min = 0.250, max = 0.50 }, - }, - ['big-biter'] = { - ['big-worm-turret'] = { min = 0.250, max = 0.50 }, - }, - ['behemoth-biter'] = { - ['big-worm-turret'] = { min = 0.250, max = 0.50 }, - }, - -- worms - ['small-worm-turret'] = { - ['small-biter'] = { min = 0.125, max = 0.25 }, - ['small-spitter'] = { min = 0.125, max = 0.25 }, - }, - ['medium-worm-turret'] = { - ['medium-biter'] = { min = 0.125, max = 0.25 }, - ['medium-spitter'] = { min = 0.125, max = 0.25 }, - }, - ['big-worm-turret'] = { - ['big-biter'] = { min = 0.125, max = 0.25 }, - ['big-spitter'] = { min = 0.125, max = 0.25 }, - }, - ['behemoth-worm-turret'] = { - ['behemoth-biter'] = { min = 0.125, max = 0.25 }, - ['behemoth-spitter'] = { min = 0.125, max = 0.25 }, - }, + -- spitters + ['medium-spitter'] = { + ['small-worm-turret'] = { min = 0.250, max = 0.50 }, + }, + ['big-spitter'] = { + ['big-worm-turret'] = { min = 0.250, max = 0.50 }, + }, + ['behemoth-spitter'] = { + ['big-worm-turret'] = { min = 0.250, max = 0.50 }, + }, + -- biters + ['medium-biter'] = { + ['small-worm-turret'] = { min = 0.250, max = 0.50 }, + }, + ['big-biter'] = { + ['big-worm-turret'] = { min = 0.250, max = 0.50 }, + }, + ['behemoth-biter'] = { + ['big-worm-turret'] = { min = 0.250, max = 0.50 }, + }, + -- worms + ['small-worm-turret'] = { + ['small-biter'] = { min = 0.125, max = 0.25 }, + ['small-spitter'] = { min = 0.125, max = 0.25 }, + }, + ['medium-worm-turret'] = { + ['medium-biter'] = { min = 0.125, max = 0.25 }, + ['medium-spitter'] = { min = 0.125, max = 0.25 }, + }, + ['big-worm-turret'] = { + ['big-biter'] = { min = 0.125, max = 0.25 }, + ['big-spitter'] = { min = 0.125, max = 0.25 }, + }, + ['behemoth-worm-turret'] = { + ['behemoth-biter'] = { min = 0.125, max = 0.25 }, + ['behemoth-spitter'] = { min = 0.125, max = 0.25 }, + }, } DOC.biter_drops.enabled = false diff --git a/map_gen/maps/danger_ores/presets/danger_ore_omnimatter.lua b/map_gen/maps/danger_ores/presets/danger_ore_omnimatter.lua index 348188a75..de6a3480c 100644 --- a/map_gen/maps/danger_ores/presets/danger_ore_omnimatter.lua +++ b/map_gen/maps/danger_ores/presets/danger_ore_omnimatter.lua @@ -3,21 +3,24 @@ local H = require 'map_gen.maps.danger_ores.modules.helper' local DOC = require 'map_gen.maps.danger_ores.configuration' local Event = require 'utils.event' local Config = require 'config' +local ModCompatibility = require 'utils.mod_compatibility' local Scenario = require 'map_gen.maps.danger_ores.scenario' local ScenarioInfo = require 'features.gui.info' +ModCompatibility.check(require 'map_gen.maps.danger_ores.compatibility.omnimatter.mod-list') + ScenarioInfo.set_map_name('Danger Ores - Omnimatter') ScenarioInfo.add_map_extra_info([[ - This map is covered in [item=omnite]. - Mine it to make room for your factory. + This map is covered in [item=omnite]. + Mine it to make room for your factory. ]]) Config.player_create.starting_items = { - { count = 1, name = 'stone-furnace' }, - { count = 2, name = 'burner-mining-drill' }, - { count = 50, name = 'wood' }, - { count = 1, name = 'burner-omnitractor' }, - { count = 1, name = 'burner-omniphlog' }, + { count = 1, name = 'stone-furnace' }, + { count = 2, name = 'burner-mining-drill' }, + { count = 50, name = 'wood' }, + { count = 1, name = 'burner-omnitractor' }, + { count = 1, name = 'burner-omniphlog' }, } DOC.scenario_name = 'danger-ore-omnimatter' @@ -29,23 +32,23 @@ DOC.map_config.spawn_shape = B.square_diamond(36 * 2) DOC.map_config.spawn_tile = 'landfill' DOC.map_config.start_ore_shape = B.square_diamond(44 * 2) DOC.rocket_launched.win_satellite_count = 100 -DOC.map_gen_settings.settings = H.empty_map_settings{ - 'infinite-omnite', - 'omnite', +DOC.map_gen_settings.settings = H.empty_map_settings { + 'infinite-omnite', + 'omnite', } local hide_mining_prod = function() - local p = game.forces.player - for _, name in pairs({ - 'omnipressed-mining-productivity-1', - 'omnipressed-mining-productivity-2', - 'omnipressed-mining-productivity-3', - 'omnipressed-mining-productivity-4', - }) do - if p.technologies[name] then - p.technologies[name].enabled = false + local p = game.forces.player + for _, name in pairs({ + 'omnipressed-mining-productivity-1', + 'omnipressed-mining-productivity-2', + 'omnipressed-mining-productivity-3', + 'omnipressed-mining-productivity-4', + }) do + if p.technologies[name] then + p.technologies[name].enabled = false + end end - end end Event.on_init(hide_mining_prod) diff --git a/map_gen/maps/danger_ores/presets/danger_ore_omnimatter_cages.lua b/map_gen/maps/danger_ores/presets/danger_ore_omnimatter_cages.lua index b79f5248f..befef1991 100644 --- a/map_gen/maps/danger_ores/presets/danger_ore_omnimatter_cages.lua +++ b/map_gen/maps/danger_ores/presets/danger_ore_omnimatter_cages.lua @@ -3,21 +3,24 @@ local H = require 'map_gen.maps.danger_ores.modules.helper' local DOC = require 'map_gen.maps.danger_ores.configuration' local Event = require 'utils.event' local Config = require 'config' +local ModCompatibility = require 'utils.mod_compatibility' local Scenario = require 'map_gen.maps.danger_ores.scenario' local ScenarioInfo = require 'features.gui.info' +ModCompatibility.check(require 'map_gen.maps.danger_ores.compatibility.omnimatter.mod-list') + ScenarioInfo.set_map_name('Danger Ores - Omnimatter Cages') ScenarioInfo.add_map_extra_info([[ - This map is covered in [item=omnite] and [item=infinite-omnite]. - Mine it to make room for your factory. + This map is covered in [item=omnite] and [item=infinite-omnite]. + Mine it to make room for your factory. ]]) Config.player_create.starting_items = { - { count = 1, name = 'stone-furnace' }, - { count = 2, name = 'burner-mining-drill' }, - { count = 50, name = 'wood' }, - { count = 1, name = 'burner-omnitractor' }, - { count = 1, name = 'burner-omniphlog' }, + { count = 1, name = 'stone-furnace' }, + { count = 2, name = 'burner-mining-drill' }, + { count = 50, name = 'wood' }, + { count = 1, name = 'burner-omnitractor' }, + { count = 1, name = 'burner-omniphlog' }, } DOC.scenario_name = 'danger-ore-omnimatter-cages' @@ -30,23 +33,23 @@ DOC.map_config.spawn_shape = B.square_diamond(36 * 2) DOC.map_config.spawn_tile = 'landfill' DOC.map_config.start_ore_shape = B.square_diamond(44 * 2) DOC.rocket_launched.win_satellite_count = 100 -DOC.map_gen_settings.settings = H.empty_map_settings{ - 'infinite-omnite', - 'omnite', +DOC.map_gen_settings.settings = H.empty_map_settings { + 'infinite-omnite', + 'omnite', } local hide_mining_prod = function() - local p = game.forces.player - for _, name in pairs({ - 'omnipressed-mining-productivity-1', - 'omnipressed-mining-productivity-2', - 'omnipressed-mining-productivity-3', - 'omnipressed-mining-productivity-4', - }) do - if p.technologies[name] then - p.technologies[name].enabled = false + local p = game.forces.player + for _, name in pairs({ + 'omnipressed-mining-productivity-1', + 'omnipressed-mining-productivity-2', + 'omnipressed-mining-productivity-3', + 'omnipressed-mining-productivity-4', + }) do + if p.technologies[name] then + p.technologies[name].enabled = false + end end - end end Event.on_init(hide_mining_prod) diff --git a/map_gen/maps/danger_ores/presets/danger_ore_omnimatter_maze.lua b/map_gen/maps/danger_ores/presets/danger_ore_omnimatter_maze.lua new file mode 100644 index 000000000..da4076e81 --- /dev/null +++ b/map_gen/maps/danger_ores/presets/danger_ore_omnimatter_maze.lua @@ -0,0 +1,60 @@ +local B = require 'map_gen.shared.builders' +local H = require 'map_gen.maps.danger_ores.modules.helper' +local DOC = require 'map_gen.maps.danger_ores.configuration' +local Event = require 'utils.event' +local Config = require 'config' +local ModCompatibility = require 'utils.mod_compatibility' +local Scenario = require 'map_gen.maps.danger_ores.scenario' +local ScenarioInfo = require 'features.gui.info' + +ModCompatibility.check(require 'map_gen.maps.danger_ores.compatibility.omnimatter.mod-list') + +ScenarioInfo.set_map_name('Danger Ores - Omnimatter Maze') +ScenarioInfo.add_map_extra_info([[ + This maze is covered in [item=omnite]. + Mine it to make room for your factory, and explore the corridors to expand. +]]) + +Config.player_create.starting_items = { + { count = 1, name = 'stone-furnace' }, + { count = 2, name = 'burner-mining-drill' }, + { count = 50, name = 'wood' }, + { count = 1, name = 'burner-omnitractor' }, + { count = 1, name = 'burner-omniphlog' }, +} + +DOC.scenario_name = 'danger-ore-omnimatter-maze' +DOC.concrete_on_landfill.refund_tile = 'omnite-refined-concrete' +DOC.game.technology_price_multiplier = 1 +DOC.map_config.main_ores = require 'map_gen.maps.danger_ores.compatibility.omnimatter.ores' +DOC.map_config.main_ores_rotate = nil +DOC.map_config.no_resource_patch_shape = B.translate(B.rectangle(80), 2, 2) +DOC.map_config.spawn_shape = B.translate(B.rectangle(64), 2, 2) +DOC.map_config.spawn_tile = 'landfill' +DOC.map_config.start_ore_shape = B.translate(B.rectangle(68), 2, 2) +DOC.maze.enabled = true +DOC.terraforming.enabled = false +DOC.rocket_launched.win_satellite_count = 100 +DOC.map_gen_settings.settings = H.empty_map_settings { + 'infinite-omnite', + 'omnite', +} + +local hide_mining_prod = function() + local p = game.forces.player + for _, name in pairs({ + 'omnipressed-mining-productivity-1', + 'omnipressed-mining-productivity-2', + 'omnipressed-mining-productivity-3', + 'omnipressed-mining-productivity-4', + }) do + if p.technologies[name] then + p.technologies[name].enabled = false + end + end +end + +Event.on_init(hide_mining_prod) +Event.on_configuration_changed(hide_mining_prod) + +return Scenario.register(DOC) diff --git a/map_gen/maps/danger_ores/presets/danger_ore_one_direction.lua b/map_gen/maps/danger_ores/presets/danger_ore_one_direction.lua index 6177b6536..0d116abbe 100644 --- a/map_gen/maps/danger_ores/presets/danger_ore_one_direction.lua +++ b/map_gen/maps/danger_ores/presets/danger_ore_one_direction.lua @@ -5,8 +5,8 @@ local ScenarioInfo = require 'features.gui.info' ScenarioInfo.set_map_name('Danger Ores - One Direction') ScenarioInfo.add_map_extra_info([[ - This map is split in three sectors [item=iron-ore] [item=copper-ore] [item=coal]. - Each sector has a main resource and the other resources at a lower ratio. + This map is split in three sectors [item=iron-ore] [item=copper-ore] [item=coal]. + Each sector has a main resource and the other resources at a lower ratio. ]]) DOC.scenario_name = 'danger-ore-one-direction' @@ -19,25 +19,25 @@ DOC.map_config.spawn_shape = B.rectangle(72) DOC.map_config.start_ore_shape = B.rectangle(88) DOC.map_config.water = nil DOC.map_config.post_map_func = function(map_shape) - local function map_bounds(x, y) - return x > -44 and y > -48 and y < 48 - end - local function water_bounds(x, y) - return x > -46 and y > -50 and y < 50 - end - local water_border = B.tile('water') - water_border = B.choose(water_bounds, water_border, B.empty_shape) - return B.choose(map_bounds, map_shape, water_border) + local function map_bounds(x, y) + return x > -44 and y > -48 and y < 48 + end + local function water_bounds(x, y) + return x > -46 and y > -50 and y < 50 + end + local water_border = B.tile('water') + water_border = B.choose(water_bounds, water_border, B.empty_shape) + return B.choose(map_bounds, map_shape, water_border) end DOC.terraforming = { - enabled = true, - start_size = 12 * 32, - min_pollution = 200, - max_pollution = 16000, - pollution_increment = 4, - bounds = function(x, y) - return x > -64 and y > -64 and y < 64 - end, + enabled = true, + start_size = 12 * 32, + min_pollution = 200, + max_pollution = 16000, + pollution_increment = 4, + bounds = function(x, y) + return x > -64 and y > -64 and y < 64 + end, } table.insert(DOC.map_gen_settings.settings, { height = 32 * 3 }) diff --git a/map_gen/maps/danger_ores/presets/danger_ore_one_direction_wide.lua b/map_gen/maps/danger_ores/presets/danger_ore_one_direction_wide.lua index ed6ae935f..876c837ae 100644 --- a/map_gen/maps/danger_ores/presets/danger_ore_one_direction_wide.lua +++ b/map_gen/maps/danger_ores/presets/danger_ore_one_direction_wide.lua @@ -5,8 +5,8 @@ local ScenarioInfo = require 'features.gui.info' ScenarioInfo.set_map_name('Danger Ores - One Direction Wide') ScenarioInfo.add_map_extra_info([[ - This map is split in three sectors [item=iron-ore] [item=copper-ore] [item=coal]. - Each sector has a main resource and the other resources at a lower ratio. + This map is split in three sectors [item=iron-ore] [item=copper-ore] [item=coal]. + Each sector has a main resource and the other resources at a lower ratio. ]]) DOC.scenario_name = 'danger-ore-one-direction-wide' @@ -19,32 +19,32 @@ DOC.map_config.spawn_shape = B.rectangle(40, 264) DOC.map_config.start_ore_shape = B.rectangle(56, 280) DOC.map_config.water = nil DOC.map_config.post_map_func = function(map_shape) - local function map_bounds(x, y) - return x > -28 and y > -144 and y < 144 - end - local function water_bounds(x, y) - return x > -30 and y > -146 and y < 146 - end - local function line(x, y) - return x > 256 and y > -1 and y < 1 - end - local water_line = B.change_tile(line, true, 'water') - local top_water_line = B.translate(water_line, 0, -48) - local bottom_water_line = B.translate(water_line, 0, 48) - map_shape = B.any({ top_water_line, bottom_water_line, map_shape }) - local water_border = B.tile('water') - water_border = B.choose(water_bounds, water_border, B.empty_shape) - return B.choose(map_bounds, map_shape, water_border) + local function map_bounds(x, y) + return x > -28 and y > -144 and y < 144 + end + local function water_bounds(x, y) + return x > -30 and y > -146 and y < 146 + end + local function line(x, y) + return x > 256 and y > -1 and y < 1 + end + local water_line = B.change_tile(line, true, 'water') + local top_water_line = B.translate(water_line, 0, -48) + local bottom_water_line = B.translate(water_line, 0, 48) + map_shape = B.any({ top_water_line, bottom_water_line, map_shape }) + local water_border = B.tile('water') + water_border = B.choose(water_bounds, water_border, B.empty_shape) + return B.choose(map_bounds, map_shape, water_border) end DOC.terraforming = { - enabled = true, - start_size = 10 * 32, - min_pollution = 450, - max_pollution = 24000, - pollution_increment = 9, - bounds = function(x, y) - return x > -64 and y > -160 and y < 160 - end, + enabled = true, + start_size = 10 * 32, + min_pollution = 450, + max_pollution = 24000, + pollution_increment = 9, + bounds = function(x, y) + return x > -64 and y > -160 and y < 160 + end, } table.insert(DOC.map_gen_settings.settings, { height = 32 * 10 }) diff --git a/map_gen/maps/danger_ores/presets/danger_ore_permanence.lua b/map_gen/maps/danger_ores/presets/danger_ore_permanence.lua index 66387f5ee..cdc355ce1 100644 --- a/map_gen/maps/danger_ores/presets/danger_ore_permanence.lua +++ b/map_gen/maps/danger_ores/presets/danger_ore_permanence.lua @@ -4,16 +4,16 @@ local ScenarioInfo = require 'features.gui.info' ScenarioInfo.set_map_name('Danger Ores - Permanence') ScenarioInfo.add_map_extra_info([[ - This map is divided in quadrants of [item=iron-ore] [item=copper-ore] [item=coal]. - Each sector has a main resource and the other resources at a lower ratio. + This map is divided in quadrants of [item=iron-ore] [item=copper-ore] [item=coal]. + Each sector has a main resource and the other resources at a lower ratio. - Mined entities will create ore drops beneath them, encouraging players to strategize their factory layouts. + Mined entities will create ore drops beneath them, encouraging players to strategize their factory layouts. - Only specific machines, such as assembling machines, furnaces, roboports, chemical plants... can generate ore drops, - while entities already allowed on ore like miners, belts, and power poles will not. + Only specific machines, such as assembling machines, furnaces, roboports, chemical plants... can generate ore drops, + while entities already allowed on ore like miners, belts, and power poles will not. - Additionally, upgrading your base will also spawn resources, so plan and upgrade carefully! - Transform your gameplay and embrace the permanence of your factory's footprint! + Additionally, upgrading your base will also spawn resources, so plan and upgrade carefully! + Transform your gameplay and embrace the permanence of your factory's footprint! ]]) DOC.scenario_name = 'danger-ore-grid-permanence' diff --git a/map_gen/maps/danger_ores/presets/danger_ore_poor_mans_coal_fields.lua b/map_gen/maps/danger_ores/presets/danger_ore_poor_mans_coal_fields.lua index 77201d25d..57e6c4d7e 100644 --- a/map_gen/maps/danger_ores/presets/danger_ore_poor_mans_coal_fields.lua +++ b/map_gen/maps/danger_ores/presets/danger_ore_poor_mans_coal_fields.lua @@ -5,8 +5,8 @@ local ScenarioInfo = require 'features.gui.info' ScenarioInfo.set_map_name('Danger Ores - Poor man\'s coal fields') ScenarioInfo.add_map_extra_info([[ - This map is split in three sectors [item=iron-ore] [item=copper-ore] [item=coal]. - Each sector has a main resource and the other resources at a lower ratio. + This map is split in three sectors [item=iron-ore] [item=copper-ore] [item=coal]. + Each sector has a main resource and the other resources at a lower ratio. ]]) DOC.scenario_name = 'danger-ore-poor-mans-coal-fields' @@ -18,17 +18,17 @@ DOC.map_config.spawn_water_tile = 'water-shallow' DOC.map_config.start_ore_shape = B.rectangle(32 * 3 + 15) DOC.rocket_launched.win_satellite_count = 300 DOC.game.on_init = function() - game.forces.player.technologies['atomic-bomb'].enabled = false - game.forces.player.technologies['cliff-explosives'].enabled = false - game.forces.player.technologies['railway'].enabled = false - game.map_settings.pollution.pollution_per_tree_damage = 0 - game.map_settings.pollution.pollution_restored_per_tree_damage = 0 + game.forces.player.technologies['atomic-bomb'].enabled = false + game.forces.player.technologies['cliff-explosives'].enabled = false + game.forces.player.technologies['railway'].enabled = false + game.map_settings.pollution.pollution_per_tree_damage = 0 + game.map_settings.pollution.pollution_restored_per_tree_damage = 0 end DOC.terraforming = { - start_size = 8 * 32, - min_pollution = 600, - max_pollution = 24000, - pollution_increment = 9, + start_size = 8 * 32, + min_pollution = 600, + max_pollution = 24000, + pollution_increment = 9, } return Scenario.register(DOC) diff --git a/map_gen/maps/danger_ores/presets/danger_ore_pyfe.lua b/map_gen/maps/danger_ores/presets/danger_ore_pyfe.lua index a28dff6be..662b45a67 100644 --- a/map_gen/maps/danger_ores/presets/danger_ore_pyfe.lua +++ b/map_gen/maps/danger_ores/presets/danger_ore_pyfe.lua @@ -1,13 +1,16 @@ local B = require 'map_gen.shared.builders' local H = require 'map_gen.maps.danger_ores.modules.helper' local DOC = require 'map_gen.maps.danger_ores.configuration' +local ModCompatibility = require 'utils.mod_compatibility' local Scenario = require 'map_gen.maps.danger_ores.scenario' local ScenarioInfo = require 'features.gui.info' +ModCompatibility.check(require 'map_gen.maps.danger_ores.compatibility.pyanodon.mod-list') + ScenarioInfo.set_map_name('Danger Ores - Pyanodon Fusion Energy') ScenarioInfo.add_map_extra_info([[ - This map is split in 6 sectors. - Each sector has a main resource. + This map is split in 6 sectors. + Each sector has a main resource. ]]) DOC.scenario_name = 'danger-ore-pyfe' @@ -23,30 +26,30 @@ DOC.allowed_entities.types['inserter'] = true DOC.allowed_entities.types['splitter'] = true DOC.game.technology_price_multiplier = 1 DOC.game.on_init = function() - game.map_settings.pollution.diffusion_ratio = 0.01 - game.map_settings.pollution.min_to_diffuse = 300 + game.map_settings.pollution.diffusion_ratio = 0.01 + game.map_settings.pollution.min_to_diffuse = 300 end -DOC.map_gen_settings.settings = H.empty_map_settings{ - -- point patches - 'crude-oil', - 'regolites', - 'volcanic-pipe', - -- ore patches - 'coal', - 'stone', - 'copper-ore', - 'uranium-ore', - 'iron-ore', - 'borax', - 'molybdenum-ore', - 'niobium', +DOC.map_gen_settings.settings = H.empty_map_settings { + -- point patches + 'crude-oil', + 'regolites', + 'volcanic-pipe', + -- ore patches + 'coal', + 'stone', + 'copper-ore', + 'uranium-ore', + 'iron-ore', + 'borax', + 'molybdenum-ore', + 'niobium', } DOC.terraforming = { - enabled = true, - start_size = 12 * 32, - min_pollution = 300, - max_pollution = 16000, - pollution_increment = 2, + enabled = true, + start_size = 12 * 32, + min_pollution = 300, + max_pollution = 16000, + pollution_increment = 2, } DOC.rocket_launched.enabled = false @@ -55,14 +58,14 @@ rocket_launched() local tech_scaling = require 'map_gen.maps.danger_ores.modules.tech_scaling' tech_scaling({ - effects = { - ['automation-science-pack'] = 1.00, - ['logistic-science-pack'] = 0.75, - ['chemical-science-pack'] = 0.50, - ['production-science-pack'] = 0.25, - ['utility-science-pack'] = 0.20, - ['space-science-pack'] = 0.10, - }, + effects = { + ['automation-science-pack'] = 1.00, + ['logistic-science-pack'] = 0.75, + ['chemical-science-pack'] = 0.50, + ['production-science-pack'] = 0.25, + ['utility-science-pack'] = 0.20, + ['space-science-pack'] = 0.10, + }, }) return Scenario.register(DOC) diff --git a/map_gen/maps/danger_ores/presets/danger_ore_scrap.lua b/map_gen/maps/danger_ores/presets/danger_ore_scrap.lua index f816fa928..d1036b3ee 100644 --- a/map_gen/maps/danger_ores/presets/danger_ore_scrap.lua +++ b/map_gen/maps/danger_ores/presets/danger_ore_scrap.lua @@ -2,20 +2,29 @@ local B = require 'map_gen.shared.builders' local H = require 'map_gen.maps.danger_ores.modules.helper' local DOC = require 'map_gen.maps.danger_ores.configuration' local Config = require 'config' +local ModCompatibility = require 'utils.mod_compatibility' local Scenario = require 'map_gen.maps.danger_ores.scenario' local ScenarioInfo = require 'features.gui.info' +ModCompatibility.check { + dependencies = { + { name = 'scrap-resource' }, + { name = 'recycler' }, + { name = 'redmew-data' }, + }, +} + ScenarioInfo.set_map_name('Danger Ores - Scrapworld') ScenarioInfo.add_map_extra_info([[ - This map is covered in [entity=scrap]. - Mine it to make room for your factory. + This map is covered in [entity=scrap]. + Mine it to make room for your factory. ]]) Config.player_create.starting_items = { - { count = 2, name = 'burner-mining-drill' }, - { count = 5, name = 'iron-chest' }, - { count = 50, name = 'wood' }, - { count = 1, name = 'recycler' }, + { count = 2, name = 'burner-mining-drill' }, + { count = 5, name = 'iron-chest' }, + { count = 50, name = 'wood' }, + { count = 1, name = 'recycler' }, } DOC.scenario_name = 'danger-ore-scrap' @@ -26,19 +35,19 @@ DOC.map_config.spawn_tile = 'landfill' DOC.map_config.start_ore_shape = B.square_diamond(44 * 2) DOC.game.technology_price_multiplier = 5 DOC.game.on_init = function() - game.forces.player.technologies['automation'].researched = true - game.forces.player.technologies['recycling'].researched = true + game.forces.player.technologies['automation'].researched = true + game.forces.player.technologies['recycling'].researched = true end -DOC.map_gen_settings.settings = H.empty_map_settings{ - -- fluid patches - 'crude-oil', - -- ore patches - 'coal', - 'copper-ore', - 'iron-ore', - 'scrap', - 'stone', - 'uranium-ore', +DOC.map_gen_settings.settings = H.empty_map_settings { + -- fluid patches + 'crude-oil', + -- ore patches + 'coal', + 'copper-ore', + 'iron-ore', + 'scrap', + 'stone', + 'uranium-ore', } return Scenario.register(DOC) diff --git a/map_gen/maps/danger_ores/presets/danger_ore_scrap_maze.lua b/map_gen/maps/danger_ores/presets/danger_ore_scrap_maze.lua new file mode 100644 index 000000000..0ebdef981 --- /dev/null +++ b/map_gen/maps/danger_ores/presets/danger_ore_scrap_maze.lua @@ -0,0 +1,56 @@ +local B = require 'map_gen.shared.builders' +local H = require 'map_gen.maps.danger_ores.modules.helper' +local DOC = require 'map_gen.maps.danger_ores.configuration' +local Config = require 'config' +local ModCompatibility = require 'utils.mod_compatibility' +local Scenario = require 'map_gen.maps.danger_ores.scenario' +local ScenarioInfo = require 'features.gui.info' + +ModCompatibility.check { + dependencies = { + { name = 'scrap-resource' }, + { name = 'recycler' }, + { name = 'redmew-data' }, + }, +} + +ScenarioInfo.set_map_name('Danger Ores - Scrapworld Maze') +ScenarioInfo.add_map_extra_info([[ + This maze is covered in [entity=scrap]. + Mine it to make room for your factory, and explore the corridors to expand. +]]) + +Config.player_create.starting_items = { + { count = 2, name = 'burner-mining-drill' }, + { count = 5, name = 'iron-chest' }, + { count = 50, name = 'wood' }, + { count = 1, name = 'recycler' }, +} + +DOC.scenario_name = 'danger-ore-scrap-maze' +DOC.map_config.main_ores = require 'map_gen.maps.danger_ores.config.scrap' +DOC.map_config.main_ores_rotate = nil +DOC.map_config.no_resource_patch_shape = B.translate(B.rectangle(80), 2, 2) +DOC.map_config.spawn_shape = B.translate(B.rectangle(64), 2, 2) +DOC.map_config.spawn_tile = 'landfill' +DOC.map_config.start_ore_shape = B.translate(B.rectangle(68), 2, 2) +DOC.maze.enabled = true +DOC.terraforming.enabled = false +DOC.game.technology_price_multiplier = 5 +DOC.game.on_init = function() + game.forces.player.technologies['automation'].researched = true + game.forces.player.technologies['recycling'].researched = true +end +DOC.map_gen_settings.settings = H.empty_map_settings { + -- fluid patches + 'crude-oil', + -- ore patches + 'coal', + 'copper-ore', + 'iron-ore', + 'scrap', + 'stone', + 'uranium-ore', +} + +return Scenario.register(DOC) diff --git a/map_gen/maps/danger_ores/presets/danger_ore_space_age.lua b/map_gen/maps/danger_ores/presets/danger_ore_space_age.lua index 1c42897fc..aab623916 100644 --- a/map_gen/maps/danger_ores/presets/danger_ore_space_age.lua +++ b/map_gen/maps/danger_ores/presets/danger_ore_space_age.lua @@ -1,9 +1,12 @@ local H = require 'map_gen.maps.danger_ores.modules.helper' local DOC = require 'map_gen.maps.danger_ores.configuration' +local ModCompatibility = require 'utils.mod_compatibility' local Scenario = require 'map_gen.maps.danger_ores.scenario' local ScenarioInfo = require 'features.gui.info' +ModCompatibility.check(require 'map_gen.maps.danger_ores.compatibility.space-age.mod-list') + ScenarioInfo.set_map_name('Danger Ores - Space Age') ScenarioInfo.add_map_extra_info([[ This map is covered in [item=coal] with mixed dense patches containing [item=iron-ore] [item=copper-ore] [item=stone] [item=calcite] [item=tungsten-ore] [item=holmium-ore]. diff --git a/map_gen/maps/danger_ores/presets/danger_ore_spiral.lua b/map_gen/maps/danger_ores/presets/danger_ore_spiral.lua index c59b86375..6c87d63df 100644 --- a/map_gen/maps/danger_ores/presets/danger_ore_spiral.lua +++ b/map_gen/maps/danger_ores/presets/danger_ore_spiral.lua @@ -4,8 +4,8 @@ local ScenarioInfo = require 'features.gui.info' ScenarioInfo.set_map_name('Danger Ores - Spiral') ScenarioInfo.add_map_extra_info([[ - This map is split in three sectors [item=iron-ore] [item=copper-ore] [item=coal]. - Each sector has a main resource and the other resources at a lower ratio. + This map is split in three sectors [item=iron-ore] [item=copper-ore] [item=coal]. + Each sector has a main resource and the other resources at a lower ratio. ]]) DOC.scenario_name = 'danger-ore-spiral' diff --git a/map_gen/maps/danger_ores/presets/danger_ore_split.lua b/map_gen/maps/danger_ores/presets/danger_ore_split.lua index 297772b9d..f8a9a0f85 100644 --- a/map_gen/maps/danger_ores/presets/danger_ore_split.lua +++ b/map_gen/maps/danger_ores/presets/danger_ore_split.lua @@ -4,8 +4,8 @@ local ScenarioInfo = require 'features.gui.info' ScenarioInfo.set_map_name('Danger Ores - Split') ScenarioInfo.add_map_extra_info([[ - This map is split in multiple sectors [item=iron-ore] [item=copper-ore] [item=coal]. - Each sector has a main resource and the other resources at a lower ratio. + This map is split in multiple sectors [item=iron-ore] [item=copper-ore] [item=coal]. + Each sector has a main resource and the other resources at a lower ratio. ]]) DOC.scenario_name = 'danger-ore-split' diff --git a/map_gen/maps/danger_ores/presets/danger_ore_square.lua b/map_gen/maps/danger_ores/presets/danger_ore_square.lua index 5e5ebd268..ff96d9495 100644 --- a/map_gen/maps/danger_ores/presets/danger_ore_square.lua +++ b/map_gen/maps/danger_ores/presets/danger_ore_square.lua @@ -5,8 +5,8 @@ local ScenarioInfo = require 'features.gui.info' ScenarioInfo.set_map_name('Danger Ores - Square') ScenarioInfo.add_map_extra_info([[ - This map is split in three sectors [item=iron-ore] [item=copper-ore] [item=coal]. - Each sector has a main resource and the other resources at a lower ratio. + This map is split in three sectors [item=iron-ore] [item=copper-ore] [item=coal]. + Each sector has a main resource and the other resources at a lower ratio. ]]) local start_ore_offset = 44 @@ -22,25 +22,25 @@ DOC.map_config.no_water_shape = B.circle(192) DOC.map_config.spawn_shape = B.rectangle(72) DOC.map_config.start_ore_shape = B.translate(B.rectangle(88), -start_ore_offset, start_ore_offset) DOC.map_config.post_map_func = function(map_shape) - local function map_bounds(x, y) - return x > -44 and y < 44 - end - local function water_bounds(x, y) - return x > -46 and y < 46 - end - local water_border = B.tile('water') - water_border = B.choose(water_bounds, water_border, B.empty_shape) - return B.choose(map_bounds, map_shape, water_border) + local function map_bounds(x, y) + return x > -44 and y < 44 + end + local function water_bounds(x, y) + return x > -46 and y < 46 + end + local water_border = B.tile('water') + water_border = B.choose(water_bounds, water_border, B.empty_shape) + return B.choose(map_bounds, map_shape, water_border) end DOC.terraforming = { - enabled = true, - start_size = 8 * 32, - min_pollution = 450, - max_pollution = 24000, - pollution_increment = 9, - bounds = function(x, y) - return x > -64 and y < 64 - end, + enabled = true, + start_size = 8 * 32, + min_pollution = 450, + max_pollution = 24000, + pollution_increment = 9, + bounds = function(x, y) + return x > -64 and y < 64 + end, } return Scenario.register(DOC) diff --git a/map_gen/maps/danger_ores/presets/danger_ore_terraforming.lua b/map_gen/maps/danger_ores/presets/danger_ore_terraforming.lua index 16cc4c4f8..f3dfde92f 100644 --- a/map_gen/maps/danger_ores/presets/danger_ore_terraforming.lua +++ b/map_gen/maps/danger_ores/presets/danger_ore_terraforming.lua @@ -4,17 +4,17 @@ local ScenarioInfo = require 'features.gui.info' ScenarioInfo.set_map_name('Danger Ores - Terraforming') ScenarioInfo.add_map_extra_info([[ - This map is split in three sectors [item=iron-ore] [item=copper-ore] [item=coal]. - Each sector has a main resource and the other resources at a lower ratio. + This map is split in three sectors [item=iron-ore] [item=copper-ore] [item=coal]. + Each sector has a main resource and the other resources at a lower ratio. ]]) DOC.scenario_name = 'danger-ore-terraforming' DOC.terraforming = { - enabled = true, - start_size = 8 * 32, - min_pollution = 400, - max_pollution = 16000, - pollution_increment = 4, + enabled = true, + start_size = 8 * 32, + min_pollution = 400, + max_pollution = 16000, + pollution_increment = 4, } return Scenario.register(DOC) diff --git a/map_gen/maps/danger_ores/presets/danger_ore_tetrominoes.lua b/map_gen/maps/danger_ores/presets/danger_ore_tetrominoes.lua new file mode 100644 index 000000000..6436550dc --- /dev/null +++ b/map_gen/maps/danger_ores/presets/danger_ore_tetrominoes.lua @@ -0,0 +1,19 @@ +local DOC = require 'map_gen.maps.danger_ores.configuration' +local Scenario = require 'map_gen.maps.danger_ores.scenario' +local ScenarioInfo = require 'features.gui.info' + +ScenarioInfo.set_map_name('Danger Ores - Tetrominoes') +ScenarioInfo.add_map_extra_info([[ + The ore field is tiled by interlocking tetromino pieces of + [item=iron-ore] [item=copper-ore] [item=coal] [item=stone]. + Each piece has a main resource and the others at a lower ratio, + and no two touching pieces share the same main resource. + Every seed lays the pieces out differently. +]]) + +DOC.scenario_name = 'danger-ore-tetrominoes' +DOC.map_config.main_ores_builder = require 'map_gen.maps.danger_ores.modules.main_ores_tetrominoes' +DOC.map_config.main_ores = require 'map_gen.maps.danger_ores.config.tetromino_ores' +DOC.map_config.main_ores_rotate = nil + +return Scenario.register(DOC) diff --git a/map_gen/maps/danger_ores/presets/danger_ore_voronoi.lua b/map_gen/maps/danger_ores/presets/danger_ore_voronoi.lua new file mode 100644 index 000000000..f5659fb40 --- /dev/null +++ b/map_gen/maps/danger_ores/presets/danger_ore_voronoi.lua @@ -0,0 +1,19 @@ +local DOC = require 'map_gen.maps.danger_ores.configuration' +local Scenario = require 'map_gen.maps.danger_ores.scenario' +local ScenarioInfo = require 'features.gui.info' + +ScenarioInfo.set_map_name('Danger Ores - Voronoi') +ScenarioInfo.add_map_extra_info([[ + The ore field is split into irregular Voronoi cells of + [item=iron-ore] [item=copper-ore] [item=coal] [item=stone]. + Each cell has a main resource and the others at a lower ratio, + and no two touching cells share the same main resource. + Every seed lays the cells out differently. +]]) + +DOC.scenario_name = 'danger-ore-voronoi' +DOC.map_config.main_ores_builder = require 'map_gen.maps.danger_ores.modules.main_ores_voronoi' +DOC.map_config.main_ores = require 'map_gen.maps.danger_ores.config.voronoi_ores' +DOC.map_config.main_ores_rotate = nil + +return Scenario.register(DOC) diff --git a/map_gen/maps/danger_ores/presets/danger_ore_x_cross.lua b/map_gen/maps/danger_ores/presets/danger_ore_x_cross.lua index ce293499b..25a7f21e9 100644 --- a/map_gen/maps/danger_ores/presets/danger_ore_x_cross.lua +++ b/map_gen/maps/danger_ores/presets/danger_ore_x_cross.lua @@ -5,8 +5,8 @@ local ScenarioInfo = require 'features.gui.info' ScenarioInfo.set_map_name('Danger Ores - X Cross') ScenarioInfo.add_map_extra_info([[ - This map is split in four sectors [item=iron-ore] [item=copper-ore] [item=coal] [item=stone]. - Each sector has a main resource and the other resources at a lower ratio. + This map is split in four sectors [item=iron-ore] [item=copper-ore] [item=coal] [item=stone]. + Each sector has a main resource and the other resources at a lower ratio. ]]) local h_bound, v_bound = B.line_x(182), B.line_y(182) diff --git a/map_gen/maps/danger_ores/presets/danger_ore_xmas_tree.lua b/map_gen/maps/danger_ores/presets/danger_ore_xmas_tree.lua index 381a5dce5..8ba5d897b 100644 --- a/map_gen/maps/danger_ores/presets/danger_ore_xmas_tree.lua +++ b/map_gen/maps/danger_ores/presets/danger_ore_xmas_tree.lua @@ -5,8 +5,8 @@ local ScenarioInfo = require 'features.gui.info' ScenarioInfo.set_map_name('Danger Ores - Christmas Tree') ScenarioInfo.add_map_extra_info([[ - This map is split in three sectors [item=iron-ore] [item=copper-ore] [item=coal]. - Each sector has a main resource and the other resources at a lower ratio. + This map is split in three sectors [item=iron-ore] [item=copper-ore] [item=coal]. + Each sector has a main resource and the other resources at a lower ratio. ]]) Config.day_night.enabled = true @@ -20,14 +20,14 @@ DOC.map_config.main_ores_rotate = nil DOC.map_config.water = nil DOC.game.always_day = false DOC.game.on_init = function() - game.forces.player.technologies['landfill'].enabled = false + game.forces.player.technologies['landfill'].enabled = false end DOC.terraforming = { - enabled = true, - start_size = 12 * 32, - min_pollution = 450, - max_pollution = 24000, - pollution_increment = 9, + enabled = true, + start_size = 12 * 32, + min_pollution = 450, + max_pollution = 24000, + pollution_increment = 9, } return Scenario.register(DOC) diff --git a/map_gen/maps/danger_ores/scenario.lua b/map_gen/maps/danger_ores/scenario.lua index 757878e59..34f945d2f 100644 --- a/map_gen/maps/danger_ores/scenario.lua +++ b/map_gen/maps/danger_ores/scenario.lua @@ -5,35 +5,35 @@ local ScenarioInfo = require 'features.gui.info' ScenarioInfo.add_extra_rule({ 'info.rules_text_danger_ore' }) ScenarioInfo.set_map_description([[ - Clear the ore to expand the base, focus mining efforts on specific sectors to ensure proper material ratios. + Clear the ore to expand the base, focus mining efforts on specific sectors to ensure proper material ratios. - You may not build the factory on ore patches. Exceptions: - - pipes, underground pipes & pumps - - belts & underground belts - - rails, stations, trains and vehicles - - power poles - - mining drills and pumpjacks + You may not build the factory on ore patches. Exceptions: + - pipes, underground pipes & pumps + - belts & underground belts + - rails, stations, trains and vehicles + - power poles + - mining drills and pumpjacks - The map size is restricted to the pollution generated. - A significant amount of pollution must affect a section of the map before it is revealed. - Pollution does not affect biter evolution. + The map size is restricted to the pollution generated. + A significant amount of pollution must affect a section of the map before it is revealed. + Pollution does not affect biter evolution. ]]) ScenarioInfo.set_new_info(require 'map_gen.maps.danger_ores.changelog') Config.apocalypse.enabled = false Config.dump_offline_inventories = { - enabled = true, - offline_timeout_mins = 30, -- time after which a player logs off that their inventory is provided to the team - startup_gear_drop_hours = 24, -- time after which players will keep at least their armor when disconnecting + enabled = true, + offline_timeout_mins = 30, -- time after which a player logs off that their inventory is provided to the team + startup_gear_drop_hours = 24, -- time after which players will keep at least their armor when disconnecting } Config.market.enabled = false Config.paint.enabled = false Config.permissions.presets.no_blueprints = false Config.player_create.starting_items = { - { count = 4, name = 'burner-mining-drill' }, - { count = 4, name = 'stone-furnace' }, - { count = 8, name = 'iron-gear-wheel' }, - { count = 16, name = 'iron-plate' }, + { count = 4, name = 'burner-mining-drill' }, + { count = 4, name = 'stone-furnace' }, + { count = 8, name = 'iron-gear-wheel' }, + { count = 16, name = 'iron-plate' }, } Config.player_rewards.enabled = false Config.player_shortcuts.enabled = true @@ -41,100 +41,100 @@ Config.player_shortcuts.shortcuts.battery_charge = false Config.reactor_meltdown.enabled = false Config.redmew_surface.use_default = true -local allowed_entities = require 'map_gen.maps.danger_ores.modules.allowed_entities'.register -local concrete_on_landfill = require 'map_gen.maps.danger_ores.modules.concrete_on_landfill' -local container_dump = require 'map_gen.maps.danger_ores.modules.container_dump'.register -local map_builder = require 'map_gen.maps.danger_ores.modules.map' -local mining_productivity = require 'map_gen.maps.danger_ores.modules.mining_productivity'.register -local maze = require 'map_gen.maps.danger_ores.modules.maze' -local restart_command = require 'map_gen.maps.danger_ores.modules.restart_command' -local rocket_launched = require 'map_gen.maps.danger_ores.modules.rocket_launched_simple' -local technologies = require 'map_gen.maps.danger_ores.modules.technologies' -local terraforming = require 'map_gen.maps.danger_ores.modules.terraforming' +local allowed_entities = require 'map_gen.maps.danger_ores.modules.allowed_entities'.register +local concrete_on_landfill = require 'map_gen.maps.danger_ores.modules.concrete_on_landfill' +local container_dump = require 'map_gen.maps.danger_ores.modules.container_dump'.register +local map_builder = require 'map_gen.maps.danger_ores.modules.map' +local mining_productivity = require 'map_gen.maps.danger_ores.modules.mining_productivity'.register +local maze = require 'map_gen.maps.danger_ores.modules.maze' +local restart_command = require 'map_gen.maps.danger_ores.modules.restart_command' +local rocket_launched = require 'map_gen.maps.danger_ores.modules.rocket_launched_simple' +local technologies = require 'map_gen.maps.danger_ores.modules.technologies' +local terraforming = require 'map_gen.maps.danger_ores.modules.terraforming' local Public = {} Public.register = function(danger_ores_config) - local _C = danger_ores_config + local _C = danger_ores_config - if _C.allowed_entities.enabled then - allowed_entities(_C.allowed_entities) - end - if _C.biter_drops.enabled then - require 'map_gen.maps.danger_ores.modules.biter_drops' - end - if _C.compatibility.aai_loaders.enabled then - require 'map_gen.maps.danger_ores.compatibility.aai_loaders.disable_vanilla_loaders' - end - if _C.compatibility.deadlock.enabled then - require 'map_gen.maps.danger_ores.compatibility.deadlock.allow_stacked_recipes'(_C.compatibility.deadlock.items) - end - if _C.compatibility.early_construction.enabled then - require 'map_gen.maps.danger_ores.compatibility.early_construction.starting_items' - end - if _C.compatibility.redmew_data.enabled then - if _C.compatibility.redmew_data.remove_resource_patches then - _C.map_config.resource_patches = nil - end - end - if _C.concrete_on_landfill.enabled then - concrete_on_landfill(_C.concrete_on_landfill) - end - if _C.container_dump.enabled then - container_dump(_C.container_dump) - end - if _C.disable_mining_productivity.enabled then - mining_productivity(_C.disable_mining_productivity) - end - if _C.map_poll.enabled then - require 'map_gen.maps.danger_ores.modules.map_poll' - end - if _C.map_gen_settings.enabled then - RS.set_map_gen_settings(_C.map_gen_settings.settings or {}) - end - if _C.maze.enabled then - maze(_C.maze) - end - if _C.prevent_quality_mining.enabled then - require 'map_gen.maps.danger_ores.modules.prevent_quality_mining' - end - if _C.radioactivity.enabled then - require 'map_gen.maps.danger_ores.modules.radioactivity' - end - if _C.restart_command.enabled then - restart_command({ scenario_name = _C.scenario_name }) - end - if _C.rocket_launched.enabled then - rocket_launched(_C.rocket_launched) - end - if _C.terraforming.enabled then - terraforming(_C.terraforming) - end - if _C.technologies.enabled then - technologies(_C.technologies) - end - - Event.on_init(function() - game.draw_resource_selection = _C.game.draw_resource_selection or false - if _C.game.manual_mining_speed_modifier then - game.forces.player.manual_mining_speed_modifier = _C.game.manual_mining_speed_modifier + if _C.allowed_entities.enabled then + allowed_entities(_C.allowed_entities) + end + if _C.biter_drops.enabled then + require 'map_gen.maps.danger_ores.modules.biter_drops' + end + if _C.compatibility.aai_loaders.enabled then + require 'map_gen.maps.danger_ores.compatibility.aai_loaders.disable_vanilla_loaders' + end + if _C.compatibility.deadlock.enabled then + require 'map_gen.maps.danger_ores.compatibility.deadlock.allow_stacked_recipes'(_C.compatibility.deadlock.items) + end + if _C.compatibility.early_construction.enabled then + require 'map_gen.maps.danger_ores.compatibility.early_construction.starting_items' + end + if _C.compatibility.redmew_data.enabled then + if _C.compatibility.redmew_data.remove_resource_patches then + _C.map_config.resource_patches = nil + end + end + if _C.concrete_on_landfill.enabled then + concrete_on_landfill(_C.concrete_on_landfill) + end + if _C.container_dump.enabled then + container_dump(_C.container_dump) + end + if _C.disable_mining_productivity.enabled then + mining_productivity(_C.disable_mining_productivity) end - if _C.game.technology_price_multiplier then - game.difficulty_settings.technology_price_multiplier = game.difficulty_settings.technology_price_multiplier * _C.game.technology_price_multiplier + if _C.map_poll.enabled then + require 'map_gen.maps.danger_ores.modules.map_poll' end - if _C.game.enemy_evolution then - game.map_settings.enemy_evolution = _C.game.enemy_evolution + if _C.map_gen_settings.enabled then + RS.set_map_gen_settings(_C.map_gen_settings.settings or {}) end - RS.get_surface().always_day = _C.game.always_day or false - RS.get_surface().peaceful_mode = _C.game.peaceful_mode or false - if _C.game.on_init then - _C.game.on_init() + if _C.maze.enabled then + maze(_C.maze) + end + if _C.prevent_quality_mining.enabled then + require 'map_gen.maps.danger_ores.modules.prevent_quality_mining' + end + if _C.radioactivity.enabled then + require 'map_gen.maps.danger_ores.modules.radioactivity' + end + if _C.restart_command.enabled then + restart_command({ scenario_name = _C.scenario_name }) + end + if _C.rocket_launched.enabled then + rocket_launched(_C.rocket_launched) + end + if _C.terraforming.enabled then + terraforming(_C.terraforming) + end + if _C.technologies.enabled then + technologies(_C.technologies) end - end) - if _C.map_config.enabled then - return map_builder(_C.map_config) - end + Event.on_init(function() + game.draw_resource_selection = _C.game.draw_resource_selection or false + if _C.game.manual_mining_speed_modifier then + game.forces.player.manual_mining_speed_modifier = _C.game.manual_mining_speed_modifier + end + if _C.game.technology_price_multiplier then + game.difficulty_settings.technology_price_multiplier = game.difficulty_settings.technology_price_multiplier * _C.game.technology_price_multiplier + end + if _C.game.enemy_evolution then + game.map_settings.enemy_evolution = _C.game.enemy_evolution + end + RS.get_surface().always_day = _C.game.always_day or false + RS.get_surface().peaceful_mode = _C.game.peaceful_mode or false + if _C.game.on_init then + _C.game.on_init() + end + end) + + if _C.map_config.enabled then + return map_builder(_C.map_config) + end end -return Public \ No newline at end of file +return Public diff --git a/map_gen/maps/frontier/modules/enemy.lua b/map_gen/maps/frontier/modules/enemy.lua index 4bf577764..ea177b08c 100644 --- a/map_gen/maps/frontier/modules/enemy.lua +++ b/map_gen/maps/frontier/modules/enemy.lua @@ -336,7 +336,7 @@ Enemy.turret_activation_callback = Token.register(function(data) if not entity.valid then return end - entity.active = true + entity.disabled_by_script = false end) function Enemy.roll_turret(x_distance, evolution) @@ -414,7 +414,7 @@ function Enemy.spawn_turret_outpost(position) direction = v.direction, } if turret and turret.valid then - turret.active = false + turret.disabled_by_script = true Task.set_timeout_in_ticks(20 + i * 20, Enemy.turret_activation_callback, { entity = turret }) EnemyTurret.register(turret, refill_name) end diff --git a/map_gen/maps/frontier/modules/rocket_silo.lua b/map_gen/maps/frontier/modules/rocket_silo.lua index 32a6b7c68..b6a7e71aa 100644 --- a/map_gen/maps/frontier/modules/rocket_silo.lua +++ b/map_gen/maps/frontier/modules/rocket_silo.lua @@ -177,7 +177,7 @@ function RocketSilo.move_silo(position) if new_silo and new_silo.valid then new_silo.destructible = false new_silo.minable_flag = false - new_silo.active = true + new_silo.disabled_by_script = false new_silo.get_output_inventory().clear() this.rocket_silo = new_silo this.x = new_silo.position.x @@ -276,7 +276,7 @@ function RocketSilo.on_rocket_launched(event) Task.set_timeout(25, RocketSilo.bard_message_token, bard_messages_2[3]) Task.set_timeout_in_ticks(ticks + 30, RocketSilo.move_silo_token) local silo = event.rocket_silo - if silo then silo.active = false end + if silo then silo.disabled_by_script = true end end function RocketSilo.on_player_died(event) diff --git a/map_gen/maps/minesweeper.lua b/map_gen/maps/minesweeper.lua index 064dfb050..db1a8a4bf 100644 --- a/map_gen/maps/minesweeper.lua +++ b/map_gen/maps/minesweeper.lua @@ -1,7 +1,10 @@ -local Event = require 'utils.event' -local Popup = require 'features.gui.popup' +local ModCompatibility = require 'utils.mod_compatibility' local ScenarioInfo = require 'features.gui.info' +ModCompatibility.check { + dependencies = {{ name = 'mine-sweeper' }} +} + ScenarioInfo.set_map_name('Minesweeper') ScenarioInfo.set_map_description('Minesweeper - in Factorio!') ScenarioInfo.set_map_extra_info([[ @@ -33,26 +36,3 @@ Config.player_create.starting_items = { { count = 32, name = 'firearm-magazine' }, { count = 20, name = 'wood' }, } - -local INFO = { - mod_name = 'mine-sweeper', - popup_name = 'minesweeper-mod-required', - title = 'Scenario mod mismatch', - message = [[ - This scenario needs Minesweeper mod in order to work correctly. - You can download it from the mod portal: https://mods.factorio.com/mod/mine-sweeper - ]], - sprite_path = 'virtual-signal.signal-alert' -} - -if not script.active_mods[INFO.mod_name] then - Event.add(defines.events.on_player_joined_game, function(event) - Popup.player( - game.get_player(event.player_index), - INFO.message, - INFO.title, - INFO.sprite_path, - INFO.mod_name - ) - end) -end diff --git a/map_gen/shared/entity_placement_restriction.lua b/map_gen/shared/entity_placement_restriction.lua index 6c0ac28d8..911e3a40c 100644 --- a/map_gen/shared/entity_placement_restriction.lua +++ b/map_gen/shared/entity_placement_restriction.lua @@ -143,20 +143,20 @@ local function entities_with_inventory(entity, player) for _, item_stack in pairs(entity.get_inventory(defines.inventory.fuel).get_contents()) do spill_item_stack(entity, item_stack) end - for _, item_stack in pairs(entity.get_inventory(defines.inventory.furnace_result).get_contents()) do + for _, item_stack in pairs(entity.get_inventory(defines.inventory.crafter_output).get_contents()) do spill_item_stack(entity, item_stack) end - for _, item_stack in pairs(entity.get_inventory(defines.inventory.furnace_source).get_contents()) do + for _, item_stack in pairs(entity.get_inventory(defines.inventory.crafter_input).get_contents()) do spill_item_stack(entity, item_stack) end elseif type == 'assembling-machine' then - for _, item_stack in pairs(entity.get_inventory(defines.inventory.assembling_machine_input).get_contents()) do + for _, item_stack in pairs(entity.get_inventory(defines.inventory.crafter_input).get_contents()) do spill_item_stack(entity, item_stack) end - for _, item_stack in pairs(entity.get_inventory(defines.inventory.assembling_machine_modules).get_contents()) do + for _, item_stack in pairs(entity.get_inventory(defines.inventory.crafter_modules).get_contents()) do spill_item_stack(entity, item_stack) end - for _, item_stack in pairs(entity.get_inventory(defines.inventory.assembling_machine_output).get_contents()) do + for _, item_stack in pairs(entity.get_inventory(defines.inventory.crafter_output).get_contents()) do spill_item_stack(entity, item_stack) end elseif type == 'ammo-turret' then diff --git a/scenario_templates/danger-ore-omnimatter-maze/map_selection.lua b/scenario_templates/danger-ore-omnimatter-maze/map_selection.lua new file mode 100644 index 000000000..09be13444 --- /dev/null +++ b/scenario_templates/danger-ore-omnimatter-maze/map_selection.lua @@ -0,0 +1 @@ +return require 'map_gen.maps.danger_ores.presets.danger_ore_omnimatter_maze' diff --git a/scenario_templates/danger-ore-scrap-maze/map_selection.lua b/scenario_templates/danger-ore-scrap-maze/map_selection.lua new file mode 100644 index 000000000..f76e06aca --- /dev/null +++ b/scenario_templates/danger-ore-scrap-maze/map_selection.lua @@ -0,0 +1 @@ +return require 'map_gen.maps.danger_ores.presets.danger_ore_scrap_maze' diff --git a/scenario_templates/danger-ore-tetrominoes/map_selection.lua b/scenario_templates/danger-ore-tetrominoes/map_selection.lua new file mode 100644 index 000000000..1268e9819 --- /dev/null +++ b/scenario_templates/danger-ore-tetrominoes/map_selection.lua @@ -0,0 +1 @@ +return require 'map_gen.maps.danger_ores.presets.danger_ore_tetrominoes' diff --git a/scenario_templates/danger-ore-voronoi/map_selection.lua b/scenario_templates/danger-ore-voronoi/map_selection.lua new file mode 100644 index 000000000..0b610fa9f --- /dev/null +++ b/scenario_templates/danger-ore-voronoi/map_selection.lua @@ -0,0 +1 @@ +return require 'map_gen.maps.danger_ores.presets.danger_ore_voronoi' diff --git a/utils/event_core.lua b/utils/event_core.lua index fbd132f0d..b843e2975 100644 --- a/utils/event_core.lua +++ b/utils/event_core.lua @@ -21,6 +21,7 @@ local script_on_nth_tick = script.on_nth_tick local error_handler = ErrorLogging.error_handler local call_handlers +local log_handler_registration if _DEBUG then function call_handlers(handlers, event) for i = #handlers, 1, -1 do @@ -28,6 +29,43 @@ if _DEBUG then handler(event) end end + + -- map of event key string (e.g. "on_player_created") to registered handler count + local handler_counts = {} + -- map of event_name id to its key string, seeded with the non-defines.events pseudo events + local event_id_to_key = { + [init_event_name] = 'on_init', + [load_event_name] = 'on_load', + [configuration_changed_name] = 'on_configuration_changed' + } + + local function get_event_key(event_name) + if type(event_name) == 'string' then + return event_name + end + + local key = event_id_to_key[event_name] + if key then + return key + end + + for name, id in pairs(defines.events) do + if id == event_name then + event_id_to_key[event_name] = name + return name + end + end + + key = 'unknown_event_' .. tostring(event_name) + event_id_to_key[event_name] = key + return key + end + + function log_handler_registration(event_name, count) + local key = get_event_key(event_name) + handler_counts[key] = count + helpers.write_file('event_handler_registry.json', helpers.table_to_json(handler_counts), false) + end else function call_handlers(handlers, event) for i = #handlers, 1, -1 do @@ -95,6 +133,10 @@ function Public.add(event_name, handler) script_on_event(event_name, on_event) end end + + if _DEBUG then + log_handler_registration(event_name, #event_handlers[event_name]) + end end --- Do not use this function, use Event.on_init instead as it has safety checks. @@ -109,6 +151,10 @@ function Public.on_init(handler) script.on_init(on_init) end end + + if _DEBUG then + log_handler_registration(init_event_name, #event_handlers[init_event_name]) + end end --- Do not use this function, use Event.on_load instead as it has safety checks. @@ -123,6 +169,10 @@ function Public.on_load(handler) script.on_load(on_load) end end + + if _DEBUG then + log_handler_registration(load_event_name, #event_handlers[load_event_name]) + end end --- Do not use this function, use Event.on_configuration_changed instead as it has safety checks. @@ -137,6 +187,10 @@ function Public.on_configuration_changed(handler) script.on_configuration_changed(configuration_changed) end end + + if _DEBUG then + log_handler_registration(configuration_changed_name, #event_handlers[configuration_changed_name]) + end end --- Do not use this function, use Event.on_nth_tick instead as it has safety checks. @@ -151,6 +205,10 @@ function Public.on_nth_tick(tick, handler) script_on_nth_tick(tick, on_nth_tick_event) end end + + if _DEBUG then + log_handler_registration('on_nth_tick_' .. tick, #on_nth_tick_event_handlers[tick]) + end end function Public.get_event_handlers() diff --git a/utils/gui.lua b/utils/gui.lua index 7d70e6bd9..7bd75ab7d 100644 --- a/utils/gui.lua +++ b/utils/gui.lua @@ -321,6 +321,42 @@ Gui.on_value_changed = handler_factory(defines.events.on_gui_value_changed) -- Adds a player field to the event table. Gui.on_switch_state_changed = handler_factory(defines.events.on_gui_switch_state_changed) +-- Register a handler for the on_gui_confirmed event for LuaGuiElements with element_name. +-- Can only have one handler per element name. +-- Guarantees that the element and the player are valid when calling the handler. +-- Adds a player field to the event table. +Gui.on_confirmed = handler_factory(defines.events.on_gui_confirmed) + +-- Register a handler for the on_gui_hover event for LuaGuiElements with element_name. +-- Can only have one handler per element name. +-- Guarantees that the element and the player are valid when calling the handler. +-- Adds a player field to the event table. +Gui.on_hover = handler_factory(defines.events.on_gui_hover) + +-- Register a handler for the on_gui_inventory_action event for LuaGuiElements with element_name. +-- Can only have one handler per element name. +-- Guarantees that the element and the player are valid when calling the handler. +-- Adds a player field to the event table. +Gui.on_inventory_action = handler_factory(defines.events.on_gui_inventory_action) + +-- Register a handler for the on_gui_leave event for LuaGuiElements with element_name. +-- Can only have one handler per element name. +-- Guarantees that the element and the player are valid when calling the handler. +-- Adds a player field to the event table. +Gui.on_leave = handler_factory(defines.events.on_gui_leave) + +-- Register a handler for the on_gui_location_changed event for LuaGuiElements with element_name. +-- Can only have one handler per element name. +-- Guarantees that the element and the player are valid when calling the handler. +-- Adds a player field to the event table. +Gui.on_location_changed = handler_factory(defines.events.on_gui_location_changed) + +-- Register a handler for the on_gui_selected_tab_changed event for LuaGuiElements with element_name. +-- Can only have one handler per element name. +-- Guarantees that the element and the player are valid when calling the handler. +-- Adds a player field to the event table. +Gui.on_selected_tab_changed = handler_factory(defines.events.on_gui_selected_tab_changed) + -- Register a handler for when the player shows the top LuaGuiElements with element_name. -- Assuming the element_name has been added with Gui.allow_player_to_toggle_top_element_visibility. -- Can only have one handler per element name. diff --git a/utils/mod_compatibility.lua b/utils/mod_compatibility.lua new file mode 100644 index 000000000..3c361ec93 --- /dev/null +++ b/utils/mod_compatibility.lua @@ -0,0 +1,220 @@ +--- Mod compatibility checker. +-- Lets a scenario declare which mods it needs, conflicts with, or merely works better with, +-- then handles the reporting for each case automatically. +-- +-- Usage (top of a map/scenario file): +-- local ModCompatibility = require 'utils.mod_compatibility' +-- ModCompatibility.check { +-- dependencies = {{name = 'alien-biomes', version = '0.7.2'}, {name = 'redmew-data', version = '1.1.0'}}, +-- incompatibles = {{name = 'some-conflicting-mod'}}, +-- recommended = {{name = 'squeak-through-2'}}, +-- discouraged = {{name = 'rate-calculator'}}, +-- } +local Event = require 'utils.event' +local Task = require 'utils.task' +local Token = require 'utils.token' +local Popup = require 'features.gui.popup' + +local Public = {} + +--- A mod to check for, with an optional minimum version. +---@class ModRef +---@field name string +---@field version string? + +-- How long after a player is created before recommended/discouraged warnings are shown, in seconds. +local WARNING_DELAY_SECONDS = 10 + +--- Builds a human readable "name >= version" (or just "name") line per mod entry. +---@param mods ModRef[] +---@return string +local function format_mod_list(mods) + local lines = {} + for i, mod in pairs(mods) do + if mod.version then + lines[i] = (' - %s >= %s'):format(mod.name, mod.version) + else + lines[i] = (' - %s'):format(mod.name) + end + end + return table.concat(lines, '\n') +end + +--- Returns true if the mod is active and, when a version is given, at least that version. +---@param mod ModRef +---@return boolean +local function mod_satisfied(mod) + local active_version = script.active_mods[mod.name] + if not active_version then + return false + end + if mod.version and helpers.compare_versions(active_version, mod.version) < 0 then + return false + end + return true +end + +--- Returns true if the mod is missing or below the required version. +---@param mod ModRef +---@return boolean +local function mod_missing(mod) + return not mod_satisfied(mod) +end + +--- Returns true if the mod is active (version, if given, is only used for the displayed message). +---@param mod ModRef +---@return boolean +local function mod_present(mod) + return script.active_mods[mod.name] ~= nil +end + +--- Runs `predicate` over `mods` and, if any match, throws `message` followed by the pretty-printed list. +-- Used for the two hard-fail checks (dependencies/incompatibles), which only differ in +-- which predicate selects the offending mods and what message is shown. +---@param mods ModRef[] +---@param predicate fun(mod: ModRef): boolean selects mods to report +---@param message string +local function error_if_any(mods, predicate, message) + local matches = {} + for _, mod in pairs(mods) do + if predicate(mod) then + matches[#matches + 1] = mod + end + end + + if #matches > 0 then + error(('%s\n%s'):format(message, format_mod_list(matches)), 0) + end +end + +--- Soft suggestions and warnings, shown to a player as a popup dialog some time after they +-- join rather than thrown as an error, since neither of these prevent the scenario from working. +---@param player LuaPlayer +---@param recommended ModRef[] +---@param discouraged ModRef[] +local function show_soft_warnings(player, recommended, discouraged) + if not player or not player.valid then + return + end + + local missing_recommended = {} + for _, mod in pairs(recommended) do + if not mod_satisfied(mod) then + missing_recommended[#missing_recommended + 1] = mod + end + end + + local present_discouraged = {} + for _, mod in pairs(discouraged) do + if mod_present(mod) then + present_discouraged[#present_discouraged + 1] = mod + end + end + + if #missing_recommended > 0 then + Popup.player( + player, + { 'mod_compatibility.recommended_message', format_mod_list(missing_recommended) }, + { 'mod_compatibility.recommended_title' }, + 'utility/warning_icon', + 'mod-compatibility-recommended' + ) + end + + if #present_discouraged > 0 then + Popup.player( + player, + { 'mod_compatibility.discouraged_message', format_mod_list(present_discouraged) }, + { 'mod_compatibility.discouraged_title' }, + 'utility/danger_icon', + 'mod-compatibility-discouraged' + ) + end +end + +local show_soft_warnings_token = Token.register(function(params) + show_soft_warnings(game.get_player(params.player_index), params.recommended, params.discouraged) +end) + +--- The category keys understood by `Public.check`, each holding a `ModRef[]`. +local CATEGORIES = { 'dependencies', 'incompatibles', 'recommended', 'discouraged' } + +--- Combines several mod-list tables into a single one suitable for `Public.check`. +-- Unlike `table.merge`/`table.meld`, which merge by key and therefore let the entries of one +-- list overwrite the same-indexed entries of another, this appends the arrays under each +-- category so every entry from every list is kept. +-- +-- Usage: +-- ModCompatibility.check(ModCompatibility.combine( +-- require 'map_gen.maps.danger_ores.compatibility.angel.mod-list', +-- require 'map_gen.maps.danger_ores.compatibility.bob.mod-list' +-- )) +---@param ... table mod-list tables, each with any of the `CATEGORIES` keys +---@return table combined mod-list table +function Public.combine(...) + local combined = {} + for _, category in pairs(CATEGORIES) do + combined[category] = {} + end + + -- Per category, the index into `combined[category]` at which each mod name was first seen, + -- so later duplicates can be deduped in place rather than appended again. + local seen = {} + for _, category in pairs(CATEGORIES) do + seen[category] = {} + end + + local lists = { ... } + for _, list in pairs(lists) do + for _, category in pairs(CATEGORIES) do + local entries = list[category] + if entries then + local target = combined[category] + local seen_category = seen[category] + for _, mod in pairs(entries) do + local existing_index = seen_category[mod.name] + if not existing_index then + target[#target + 1] = mod + seen_category[mod.name] = #target + else + -- Same mod seen again: keep whichever pins the later version. + -- A missing version means "any", which loses to any pinned version. + local existing = target[existing_index] + if mod.version and (not existing.version or helpers.compare_versions(mod.version, existing.version) > 0) then + target[existing_index] = mod + end + end + end + end + end + end + + return combined +end + +--- Validates and reports on the mods used by a scenario. +-- dependencies/incompatibles are checked immediately and error out the game if violated. +-- recommended/discouraged are checked per-player, 10 seconds after they join. +---@param args table +---@field dependencies ModRef[]? mods that MUST be enabled or the scenario breaks +---@field incompatibles ModRef[]? mods that must NOT be enabled or the scenario breaks +---@field recommended ModRef[]? mods that are not required but improve the experience +---@field discouraged ModRef[]? mods that are known to potentially cause issues but won't outright break the scenario +function Public.check(args) + args = args or {} + local dependencies = args.dependencies or {} + local incompatibles = args.incompatibles or {} + local recommended = args.recommended or {} + local discouraged = args.discouraged or {} + + error_if_any(dependencies, mod_missing, 'Missing dependencies. Please check that the following mods have been correctly installed:') + error_if_any(incompatibles, mod_present, 'Incompatible mods detected. Please remove the following mods:') + + if #recommended > 0 or #discouraged > 0 then + Event.add(defines.events.on_player_created, function(event) + Task.set_timeout(WARNING_DELAY_SECONDS, show_soft_warnings_token, { player_index = event.player_index, recommended = recommended, discouraged = discouraged }) + end) + end +end + +return Public