--luacheck: ignore local Map_functions = require 'tools.map_functions' local Server = require 'utils.server' local Get_noise = require 'utils.get_noise' local Constants = require 'maps.journey.constants' local Unique_modifiers = require 'maps.journey.unique_modifiers' local math_sqrt = math.sqrt local math_random = math.random local math_floor = math.floor local math_abs = math.abs local Public = {} local mixed_ores = {'copper-ore', 'iron-ore', 'stone', 'coal'} local function clear_selectors(journey) for k, world_selector in pairs(journey.world_selectors) do for _, ID in pairs(world_selector.texts) do rendering.destroy(ID) end journey.world_selectors[k].texts = {} journey.world_selectors[k].activation_level = 0 end for _, ID in pairs(journey.reroll_selector.texts) do rendering.destroy(ID) end journey.reroll_selector.texts = {} journey.reroll_selector.activation_level = 0 end function Public.place_mixed_ore(event, journey) if math_random(1, 192) ~= 1 then return end local surface = event.surface local x = event.area.left_top.x + math_random(0, 31) local y = event.area.left_top.y + math_random(0, 31) local base_amount = 1000 + math_sqrt(x ^ 2 + y ^ 2) * 5 local richness = journey.mixed_ore_richness Map_functions.draw_rainbow_patch({x = x, y = y}, surface, math_random(17, 22), base_amount * richness + 100) end local function place_teleporter(journey, surface, position) local tiles = {} for x = -1, 0, 1 do for y = -1, 0, 1 do local position = {x = position.x + x, y = position.y + y} table.insert(tiles, {name = Constants.teleporter_tile, position = position}) end end surface.set_tiles(tiles, false) surface.create_entity({name = 'electric-beam-no-sound', position = position, source = {x = position.x - 1, y = position.y - 1}, target = {x = position.x + 1, y = position.y - 0.5}}) surface.create_entity({name = 'electric-beam-no-sound', position = position, source = {x = position.x + 1, y = position.y - 1}, target = {x = position.x + 1, y = position.y + 1.5}}) surface.create_entity({name = 'electric-beam-no-sound', position = position, source = {x = position.x + 1, y = position.y + 1}, target = {x = position.x - 1, y = position.y + 1.5}}) surface.create_entity({name = 'electric-beam-no-sound', position = position, source = {x = position.x - 1, y = position.y + 1}, target = {x = position.x - 1, y = position.y - 0.5}}) surface.destroy_decoratives({area = {{position.x - 1, position.y - 1}, {position.x + 1, position.y + 1}}}) end local function destroy_teleporter(journey, surface, position) local tiles = {} for x = -1, 0, 1 do for y = -1, 0, 1 do local position = {x = position.x + x, y = position.y + y} table.insert(tiles, {name = "lab-dark-1", position = position}) end end surface.set_tiles(tiles, true) for _, e in pairs(surface.find_entities_filtered({name = "electric-beam-no-sound", area = {{position.x - 1, position.y - 1}, {position.x + 1, position.y + 1}}})) do e.destroy() end end local function drop_player_items(player) local character = player.character if not character then return end if not character.valid then return end player.clear_cursor() for i = 1, player.crafting_queue_size, 1 do if player.crafting_queue_size > 0 then player.cancel_crafting{index = 1, count = 99999999} end end local surface = player.surface local spill_blockage = surface.create_entity{name = "stone-furnace", position = player.position} for _, define in pairs({defines.inventory.character_main, defines.inventory.character_guns, defines.inventory.character_ammo, defines.inventory.character_armor, defines.inventory.character_vehicle, defines.inventory.character_trash}) do local inventory = character.get_inventory(define) if inventory and inventory.valid then for i = 1, #inventory, 1 do local slot = inventory[i] if slot.valid and slot.valid_for_read then surface.spill_item_stack(player.position, slot, true, nil, false) end end inventory.clear() end end spill_blockage.destroy() end function Public.clear_player(player) local character = player.character if not character then return end if not character.valid then return end player.character.destroy() player.set_controller({type = defines.controllers.god}) player.create_character() player.clear_items_inside() end local function remove_offline_players(maximum_age_in_hours) local maximum_age_in_ticks = maximum_age_in_hours * 216000 local t = game.tick - maximum_age_in_ticks if t < 0 then return end local players_to_remove = {} for _, player in pairs(game.players) do if player.last_online < t then table.insert(players_to_remove, player) end end game.remove_offline_players(players_to_remove) end local function get_current_modifier_percentage(name, journey) local mgs = game.surfaces.nauvis.map_gen_settings for _, autoplace in pairs({"iron-ore", "copper-ore", "uranium-ore", "coal", "stone", "crude-oil", "stone", "trees", "enemy-base"}) do if name == autoplace then return mgs.autoplace_controls[name].richness end end if name == "cliff_settings" then return 40 / mgs.cliff_settings.cliff_elevation_interval end if name == "water" then return mgs.water end if name == "time_factor" then return game.map_settings.enemy_evolution.time_factor * 250000 end if name == "destroy_factor" then return game.map_settings.enemy_evolution.destroy_factor * 500 end if name == "pollution_factor" then return game.map_settings.enemy_evolution.pollution_factor * 1111000 end if name == "expansion_cooldown" then return (game.map_settings.enemy_expansion.min_expansion_cooldown / 144) * 0.01 end if name == "technology_price_multiplier" then return game.difficulty_settings.technology_price_multiplier * 2 end if name == "enemy_attack_pollution_consumption_modifier" then return game.map_settings.pollution.enemy_attack_pollution_consumption_modifier end if name == "ageing" then return game.map_settings.pollution.ageing end if name == "diffusion_ratio" then return game.map_settings.pollution.diffusion_ratio * 50 end if name == "tree_durability" then return game.map_settings.pollution.pollution_restored_per_tree_damage * 0.1 end if name == "max_unit_group_size" then return game.map_settings.unit_group.max_unit_group_size * 0.005 end if name == "mixed_ore" then return journey.mixed_ore_richness end end local function delete_nauvis_chunks(journey) local surface = game.surfaces.nauvis if not journey.nauvis_chunk_positions then journey.nauvis_chunk_positions = {} for chunk in surface.get_chunks() do table.insert(journey.nauvis_chunk_positions, {chunk.x, chunk.y}) end journey.size_of_nauvis_chunk_positions = #journey.nauvis_chunk_positions for _, e in pairs(surface.find_entities_filtered{type = "radar"}) do e.destroy() end for _, player in pairs(game.players) do local button = player.gui.top.add({type = "sprite-button", name = "chunk_progress", caption = ""}) button.style.font = "heading-1" button.style.font_color = {222, 222, 222} button.style.minimal_height = 38 button.style.minimal_width = 240 button.style.padding = -2 end end if journey.size_of_nauvis_chunk_positions == 0 then return end for c = 1, 12, 1 do local chunk_position = journey.nauvis_chunk_positions[journey.size_of_nauvis_chunk_positions] if chunk_position then surface.delete_chunk(chunk_position) journey.size_of_nauvis_chunk_positions = journey.size_of_nauvis_chunk_positions - 1 else break end end local caption = "Deleting Chunks.. " .. journey.size_of_nauvis_chunk_positions for _, player in pairs(game.connected_players) do if player.gui.top.chunk_progress then player.gui.top.chunk_progress.caption = caption end end return true end function Public.mothership_message_queue(journey) local text = journey.mothership_messages[1] if not text then return end if text ~= "" then text = "[font=default-game][color=200,200,200]" .. text .. "[/color][/font]" text = "[font=heading-1][color=255,155,155] [/color][/font]" .. text game.print(text) end table.remove(journey.mothership_messages, 1) end function Public.deny_building(event) local entity = event.created_entity if not entity.valid then return end if entity.surface.name ~= "mothership" then return end if Constants.build_type_whitelist[entity.type] then entity.destructible = false return end entity.die() end function Public.register_built_silo(event, journey) local entity = event.created_entity if not entity.valid then return end if entity.surface.index ~= 1 then return end if entity.type ~= "rocket-silo" then return end entity.auto_launch = false table.insert(journey.rocket_silos, entity) end function Public.draw_gui(journey) local surface = game.surfaces.nauvis local mgs = surface.map_gen_settings local caption = "World " .. journey.world_number .. " | " .. Constants.unique_world_traits[journey.world_trait][1] local tooltip = Constants.unique_world_traits[journey.world_trait][2] .. "\n\n" for k, v in pairs(Constants.modifiers) do tooltip = tooltip .. v[3] .. " - " .. math.round(get_current_modifier_percentage(k, journey) * 100, 1) .. "%\n" end tooltip = tooltip .. "\nCapsules:\n" local c = 0 for k, v in pairs(journey.bonus_goods) do tooltip = tooltip .. v .. "x " .. k .. " " c = c + 1 if c % 2 == 0 then tooltip = tooltip .. "\n" end end for _, player in pairs(game.connected_players) do if not player.gui.top.journey_button then local element = player.gui.top.add({type = "sprite-button", name = "journey_button", caption = ""}) element.style.font = "heading-1" element.style.font_color = {222, 222, 222} element.style.minimal_height = 38 element.style.minimal_width = 250 element.style.padding = -2 end local gui = player.gui.top.journey_button gui.caption = caption gui.tooltip = tooltip end local fuel_requirement = journey.mothership_cargo_space["uranium-fuel-cell"] local value if fuel_requirement == 0 then value = 1 else value = journey.mothership_cargo["uranium-fuel-cell"] / fuel_requirement end local tooltip = "Fuel requirement to advance to next world:\n" .. fuel_requirement .. "\n\nNuclear Fuel Cells in Mothership Cargo:\n" .. journey.mothership_cargo["uranium-fuel-cell"] for _, player in pairs(game.connected_players) do if not player.gui.top.journey_fuel then local frame = player.gui.top.add({type = 'frame', name = 'journey_fuel'}) frame.style.padding = 0 local element = frame.add({type = 'sprite', sprite = 'item/uranium-fuel-cell', name = "journey_fuel_sprite"}) element.style.minimal_width = 32 element.style.minimal_height = 32 element.style.maximal_width = 32 element.style.maximal_height = 32 element.style.margin = 0 element.style.padding = 0 local element = frame.add({type = 'progressbar', name = 'journey_fuel_progressbar', value = 0}) element.style.minimal_width = 100 element.style.maximal_width = 100 element.style.top_margin = 12 element.style.right_margin = 12 end local gui = player.gui.top.journey_fuel gui.tooltip = tooltip local gui = player.gui.top.journey_fuel.journey_fuel_sprite gui.tooltip = tooltip local gui = player.gui.top.journey_fuel.journey_fuel_progressbar gui.value = value gui.tooltip = tooltip end local max_sattelites = journey.mothership_cargo_space["satellite"] local value = journey.mothership_cargo["satellite"] / max_sattelites local tooltip = "Room for satellites in Mothership cargo:\n" .. max_sattelites .. "\n\nSatellites stored:\n" .. journey.mothership_cargo["satellite"] for _, player in pairs(game.connected_players) do if not player.gui.top.journey_satellites then local frame = player.gui.top.add({type = 'frame', name = 'journey_satellites'}) frame.style.left_margin = 4 frame.style.padding = 0 local element = frame.add({type = 'sprite', sprite = 'item/satellite', name = "journey_satellites_sprite"}) element.style.minimal_width = 32 element.style.minimal_height = 32 element.style.maximal_width = 32 element.style.maximal_height = 32 element.style.margin = 0 element.style.padding = 0 local element = frame.add({type = 'progressbar', name = 'journey_satellites_progressbar', value = 0}) element.style.minimal_width = 100 element.style.maximal_width = 100 element.style.top_margin = 12 element.style.right_margin = 12 end local gui = player.gui.top.journey_satellites gui.tooltip = tooltip local gui = player.gui.top.journey_satellites.journey_satellites_sprite gui.tooltip = tooltip local gui = player.gui.top.journey_satellites.journey_satellites_progressbar gui.value = value gui.tooltip = tooltip end end local function is_mothership(position) if math.abs(position.x) > Constants.mothership_radius then return false end if math.abs(position.y) > Constants.mothership_radius then return false end local p = {x = position.x, y = position.y} if p.x > 0 then p.x = p.x + 1 end if p.y > 0 then p.y = p.y + 1 end local d = math.sqrt(p.x ^ 2 + p.y ^ 2) if d < Constants.mothership_radius then return true end end function Public.on_mothership_chunk_generated(event) local left_top = event.area.left_top local surface = event.surface local seed = surface.map_gen_settings.seed local tiles = {} for x = 0, 31, 1 do for y = 0, 31, 1 do local position = {x = left_top.x + x, y = left_top.y + y} if is_mothership(position) then table.insert(tiles, {name = "black-refined-concrete", position = position}) else table.insert(tiles, {name = "out-of-map", position = position}) end end end surface.set_tiles(tiles, true) end function Public.hard_reset(journey) if game.surfaces.mothership and game.surfaces.mothership.valid then game.delete_surface(game.surfaces.mothership) end game.forces.enemy.character_inventory_slots_bonus = 9999 game.map_settings.enemy_expansion.enabled = true game.map_settings.enemy_expansion.max_expansion_distance = 20 game.map_settings.enemy_expansion.settler_group_min_size = 5 game.map_settings.enemy_expansion.settler_group_max_size = 50 game.map_settings.enemy_expansion.min_expansion_cooldown = 14400 game.map_settings.enemy_expansion.max_expansion_cooldown = 216000 game.map_settings.pollution.enabled = true game.map_settings.pollution.ageing = 1 game.map_settings.pollution.diffusion_ratio = 0.02 game.map_settings.pollution.enemy_attack_pollution_consumption_modifier = 1 game.map_settings.pollution.min_pollution_to_damage_trees = 60 game.map_settings.pollution.pollution_restored_per_tree_damage = 10 game.map_settings.unit_group.max_unit_group_size = 200 game.difficulty_settings.technology_price_multiplier = 0.5 game.map_settings.enemy_evolution.time_factor = 0.000004 game.map_settings.enemy_evolution.destroy_factor = 0.002 game.map_settings.enemy_evolution.pollution_factor = 0.0000009 local surface = game.surfaces[1] local mgs = surface.map_gen_settings mgs.water = 1 mgs.starting_area = 1 mgs.cliff_settings = {cliff_elevation_interval = 40, cliff_elevation_0 = 10} mgs.autoplace_controls = { ["coal"] = {frequency = 1, size = 1, richness = 1}, ["stone"] = {frequency = 1, size = 1, richness = 1}, ["copper-ore"] = {frequency = 1, size = 1, richness = 1}, ["iron-ore"] = {frequency = 1, size = 1, richness = 1}, ["uranium-ore"] = {frequency = 1, size = 1, richness = 1}, ["crude-oil"] = {frequency = 1, size = 1, richness = 1}, ["trees"] = {frequency = 1, size = 1, richness = 1}, ["enemy-base"] = {frequency = 1, size = 1, richness = 1}, } surface.map_gen_settings = mgs surface.clear(true) surface.daytime = math.random(1, 100) * 0.01 if journey.world_selectors and journey.world_selectors[1].border then for k, world_selector in pairs(journey.world_selectors) do for _, ID in pairs(world_selector.rectangles) do rendering.destroy(ID) end rendering.destroy(world_selector.border) end end journey.world_selectors = {} journey.reroll_selector = {activation_level = 0} for i = 1, 3, 1 do journey.world_selectors[i] = {activation_level = 0, texts = {}} end journey.mothership_speed = 0.5 journey.characters_in_mothership = 0 journey.world_color_filters = {} journey.mixed_ore_richness = 1 journey.mothership_messages = {} journey.mothership_cargo = {} journey.mothership_cargo["uranium-fuel-cell"] = 10 journey.mothership_cargo["satellite"] = 1 journey.mothership_cargo_space = { ["satellite"] = 1, ["uranium-fuel-cell"] = 0, } journey.bonus_goods = {} journey.nauvis_chunk_positions = nil journey.world_number = 0 journey.world_trait = "lush" journey.game_state = "create_mothership" end function Public.create_mothership(journey) local surface = game.create_surface("mothership", Constants.mothership_gen_settings) surface.request_to_generate_chunks({x = 0, y = 0}, 6) surface.force_generate_chunk_requests() surface.freeze_daytime = true journey.game_state = "draw_mothership" end function Public.draw_mothership(journey) local surface = game.surfaces.mothership local positions = {} for x = Constants.mothership_radius * -1, Constants.mothership_radius, 1 do for y = Constants.mothership_radius * -1, Constants.mothership_radius, 1 do local position = {x = x, y = y} if is_mothership(position) then table.insert(positions, position) end end end table.shuffle_table(positions) for _, position in pairs(positions) do if surface.count_tiles_filtered({area = {{position.x - 1, position.y - 1}, {position.x + 2, position.y + 2}}, name = "out-of-map"}) > 0 then local e = surface.create_entity({name = "stone-wall", position = position, force = "player"}) e.destructible = false e.minable = false end if surface.count_tiles_filtered({area = {{position.x - 1, position.y - 1}, {position.x + 2, position.y + 2}}, name = "lab-dark-1"}) < 4 then surface.set_tiles({{name = "lab-dark-1", position = position}}, true) end end for _, tile in pairs(surface.find_tiles_filtered({area = {{Constants.mothership_teleporter_position.x - 2, Constants.mothership_teleporter_position.y - 2}, {Constants.mothership_teleporter_position.x + 2, Constants.mothership_teleporter_position.y + 2}}})) do surface.set_tiles({{name = "lab-dark-1", position = tile.position}}, true) end for k, area in pairs(Constants.world_selector_areas) do journey.world_selectors[k].rectangles = {} local position = area.left_top local rectangle = rendering.draw_rectangle { width = 1, filled=true, surface = surface, left_top = position, right_bottom = {position.x + Constants.world_selector_width, position.y + Constants.world_selector_height}, color = Constants.world_selector_colors[k], draw_on_ground = true, only_in_alt_mode = false } table.insert(journey.world_selectors[k].rectangles, rectangle) journey.world_selectors[k].border = rendering.draw_rectangle { width = 8, filled=false, surface = surface, left_top = position, right_bottom = {position.x + Constants.world_selector_width, position.y + Constants.world_selector_height}, color = {r = 100, g = 100, b = 100, a = 255}, draw_on_ground = true, only_in_alt_mode = false } end journey.reroll_selector.rectangle = rendering.draw_rectangle { width = 8, filled=true, surface = surface, left_top = Constants.reroll_selector_area.left_top, right_bottom = Constants.reroll_selector_area.right_bottom, color = Constants.reroll_selector_area_color, draw_on_ground = true, only_in_alt_mode = false } journey.reroll_selector.border = rendering.draw_rectangle { width = 8, filled=false, surface = surface, left_top = Constants.reroll_selector_area.left_top, right_bottom = Constants.reroll_selector_area.right_bottom, color = {r = 100, g = 100, b = 100, a = 255}, draw_on_ground = true, only_in_alt_mode = false } for k, item_name in pairs({"arithmetic-combinator", "constant-combinator", "decider-combinator", "programmable-speaker", "red-wire", "green-wire", "small-lamp", "substation", "pipe", "gate", "stone-wall", "transport-belt"}) do local e = surface.create_entity({name = 'infinity-chest', position = {-7 + k, Constants.mothership_radius - 3}, force = 'player'}) e.set_infinity_container_filter(1, {name = item_name, count = game.item_prototypes[item_name].stack_size}) e.minable = false e.destructible = false e.operable = false local e = surface.create_entity({name = "express-loader", position = {-7 + k, Constants.mothership_radius - 4}, force = "player"}) e.minable = false e.destructible = false e.direction = 4 end for m = -1, 1, 2 do local e = surface.create_entity({name = "electric-energy-interface", position = {11 * m, Constants.mothership_radius - 4}, force = "player"}) e.minable = false e.destructible = false local e = surface.create_entity({name = "substation", position = {9 * m, Constants.mothership_radius - 4}, force = "player"}) e.minable = false e.destructible = false end for m = -1, 1, 2 do local x = Constants.mothership_radius - 3 if m > 0 then x = x - 1 end local y = Constants.mothership_radius * 0.5 - 7 local e = surface.create_entity({name = "artillery-turret", position = {x * m, y}, force = "player"}) e.direction = 4 e.minable = false e.destructible = false e.operable = false local e = surface.create_entity({name = "burner-inserter", position = {(x - 1) * m, y}, force = "player"}) e.direction = 4 + m * 2 e.rotatable = false e.minable = false e.destructible = false e.operable = false local e = surface.create_entity({name = 'infinity-chest', position = {(x - 2) * m, y}, force = 'player'}) e.set_infinity_container_filter(1, {name = "solid-fuel", count = 50}) e.set_infinity_container_filter(2, {name = "artillery-shell", count = 1}) e.minable = false e.destructible = false e.operable = false end for _ = 1, 3, 1 do local e = surface.create_entity({name = "compilatron", position = Constants.mothership_teleporter_position, force = "player"}) e.destructible = false end Public.draw_gui(journey) surface.daytime = 0.5 journey.game_state = "set_world_selectors" end function Public.teleport_players_to_mothership(journey) local surface = game.surfaces.mothership for _, player in pairs(game.connected_players) do if player.surface.name ~= "mothership" then Public.clear_player(player) player.teleport(surface.find_non_colliding_position("character", {0,0}, 32, 0.5), surface) journey.characters_in_mothership = journey.characters_in_mothership + 1 table.insert(journey.mothership_messages, "Welcome home " .. player.name .. "!") return end end end local function get_activation_level(surface, area) local player_count_in_area = surface.count_entities_filtered({area = area, name = "character"}) local player_count_for_max_activation = #game.connected_players * 0.66 local level = player_count_in_area / player_count_for_max_activation level = math.round(level, 2) return level end local function animate_selectors(journey) for k, world_selector in pairs(journey.world_selectors) do local activation_level = journey.world_selectors[k].activation_level if activation_level < 0.2 then activation_level = 0.2 end if activation_level > 1 then activation_level = 1 end for _, rectangle in pairs(world_selector.rectangles) do local color = Constants.world_selector_colors[k] rendering.set_color(rectangle, {r = color.r * activation_level, g = color.g * activation_level, b = color.b * activation_level, a = 255}) end end local activation_level = journey.reroll_selector.activation_level if activation_level < 0.2 then activation_level = 0.2 end if activation_level > 1 then activation_level = 1 end local color = Constants.reroll_selector_area_color rendering.set_color(journey.reroll_selector.rectangle, {r = color.r * activation_level, g = color.g * activation_level, b = color.b * activation_level, a = 255}) end local function draw_background(journey, surface) if journey.characters_in_mothership == 0 then return end local speed = journey.mothership_speed for c = 1, 16 * speed, 1 do local position = Constants.particle_spawn_vectors[math.random(1, Constants.size_of_particle_spawn_vectors)] surface.create_entity({name = "shotgun-pellet", position = position, target = {position[1], position[2] + Constants.mothership_radius * 2}, speed = speed}) end for c = 1, 16 * speed, 1 do local position = Constants.particle_spawn_vectors[math.random(1, Constants.size_of_particle_spawn_vectors)] surface.create_entity({name = "piercing-shotgun-pellet", position = position, target = {position[1], position[2] + Constants.mothership_radius * 2}, speed = speed}) end for c = 1, 2 * speed, 1 do local position = Constants.particle_spawn_vectors[math.random(1, Constants.size_of_particle_spawn_vectors)] surface.create_entity({name = "cannon-projectile", position = position, target = {position[1], position[2] + Constants.mothership_radius * 2}, speed = speed}) end for c = 1, 1 * speed, 1 do local position = Constants.particle_spawn_vectors[math.random(1, Constants.size_of_particle_spawn_vectors)] surface.create_entity({name = "uranium-cannon-projectile", position = position, target = {position[1], position[2] + Constants.mothership_radius * 2}, speed = speed}) end if math.random(1, 32) == 1 then local position = Constants.particle_spawn_vectors[math.random(1, Constants.size_of_particle_spawn_vectors)] surface.create_entity({name = "explosive-uranium-cannon-projectile", position = position, target = {position[1], position[2] + Constants.mothership_radius * 3}, speed = speed}) end if math.random(1, 90) == 1 then local position_x = math.random(64, 160) local position_y = math.random(64, 160) if math.random(1, 2) == 1 then position_x = position_x * -1 end if math.random(1, 2) == 1 then position_y = position_y * -1 end surface.create_entity({name = "big-worm-turret", position = {position_x, position_y}, force = "enemy"}) end end function Public.set_world_selectors(journey) local surface = game.surfaces.mothership local x = Constants.reroll_selector_area.left_top.x + 3.2 journey.reroll_selector.texts = { rendering.draw_text{ text = journey.mothership_cargo.satellite .. " x ", surface = surface, target = {x, Constants.reroll_selector_area.left_top.y - 1.5}, color = {255, 255, 255, 255}, scale = 1.5, font = "default-large-bold", alignment = "center", scale_with_zoom = false, }, rendering.draw_sprite{ sprite = "item/satellite", surface = surface, y_scale = 1.5, x_scale = 1.5, target = {x + 1.6, Constants.reroll_selector_area.left_top.y - 1}, }, } local modifier_names = {} for k, _ in pairs(Constants.modifiers) do table.insert(modifier_names, k) end local bonus_goods_keys = {} for i = 1, #Constants.starter_goods_pool, 1 do table.insert(bonus_goods_keys, i) end local unique_world_traits = {} for k, _ in pairs(Constants.unique_world_traits) do table.insert(unique_world_traits, k) end table.shuffle_table(unique_world_traits) for k, world_selector in pairs(journey.world_selectors) do table.shuffle_table(bonus_goods_keys) table.shuffle_table(modifier_names) world_selector.modifiers = {} world_selector.bonus_goods = {} world_selector.world_trait = unique_world_traits[k] world_selector.fuel_requirement = math.random(25, 50) local position = Constants.world_selector_areas[k].left_top local texts = world_selector.texts local modifiers = world_selector.modifiers local bonus_goods = world_selector.bonus_goods local y_modifier = -9.7 for i = 1, 8, 1 do local modifier = modifier_names[i] local v = math.random(Constants.modifiers[modifier][1], Constants.modifiers[modifier][2]) if i > 6 then v = v * -0.5 end v = math.floor(v) modifiers[i] = {modifier, v} end table.insert(texts, rendering.draw_text{ text = Constants.unique_world_traits[world_selector.world_trait][1], surface = surface, target = {position.x + Constants.world_selector_width * 0.5, position.y + y_modifier}, color = {100, 0, 255, 255}, scale = 1.25, font = "default-large-bold", alignment = "center", scale_with_zoom = false }) for k2, modifier in pairs(modifiers) do y_modifier = y_modifier + 0.8 local text = "" if modifier[2] > 0 then text = text .. "+" end text = text .. modifier[2] .. "% " text = text .. Constants.modifiers[modifier[1]][3] local color if k2 < 7 then color = {200, 0, 0, 255} else color = {0, 200, 0, 255} end table.insert(texts, rendering.draw_text{ text = text, surface = surface, target = {position.x + Constants.world_selector_width * 0.5, position.y + y_modifier}, color = color, scale = 1.25, font = "default-large", alignment = "center", scale_with_zoom = false }) end y_modifier = y_modifier + 0.85 table.insert(texts, rendering.draw_text{ text = "Fuel requirement +" .. world_selector.fuel_requirement, surface = surface, target = {position.x + Constants.world_selector_width * 0.5, position.y + y_modifier}, color = {155, 155, 0, 255}, scale = 1.25, font = "default-large", alignment = "center", scale_with_zoom = false }) table.insert(texts, rendering.draw_sprite{ sprite = "item/uranium-fuel-cell", surface = surface, target = {position.x + Constants.world_selector_width * 0.5 + 3.7, position.y + y_modifier + 0.5}, }) for i = 1, 3, 1 do local key = bonus_goods_keys[i] local bonus_good = Constants.starter_goods_pool[key] bonus_goods[i] = {bonus_good[1], math.random(bonus_good[2], bonus_good[3])} end y_modifier = y_modifier + 1.1 local x_modifier = -0.5 for k2, good in pairs(world_selector.bonus_goods) do local render_id = rendering.draw_text{ text = "+" .. good[2], surface = surface, target = {position.x + x_modifier, position.y + y_modifier}, color = {200, 200, 0, 255}, scale = 1.25, font = "default-large", alignment = "center", scale_with_zoom = false } table.insert(texts, render_id) x_modifier = x_modifier + 0.95 if good[2] >= 10 then x_modifier = x_modifier + 0.18 end if good[2] >= 100 then x_modifier = x_modifier + 0.18 end local render_id = rendering.draw_sprite{ sprite = "item/" .. good[1], surface = surface, target = {position.x + x_modifier, position.y + 0.5 + y_modifier}, } table.insert(texts, render_id) x_modifier = x_modifier + 1.70 end end destroy_teleporter(journey, game.surfaces.nauvis, Constants.mothership_teleporter_position) destroy_teleporter(journey, surface, Constants.mothership_teleporter_position) Server.to_discord_embed("World " .. journey.world_number .. " selection has started!") journey.game_state = "delete_nauvis_chunks" end function Public.delete_nauvis_chunks(journey) local surface = game.surfaces.mothership Public.teleport_players_to_mothership(journey) draw_background(journey, surface) if delete_nauvis_chunks(journey) then return end for _, player in pairs(game.players) do if player.gui.top.chunk_progress then player.gui.top.chunk_progress.destroy() end end journey.game_state = "mothership_world_selection" end function Public.reroll_worlds(journey) local surface = game.surfaces.mothership Public.teleport_players_to_mothership(journey) draw_background(journey, surface) animate_selectors(journey) local reroll_selector_activation_level = get_activation_level(surface, Constants.reroll_selector_area) journey.reroll_selector.activation_level = reroll_selector_activation_level for i = 1, 3, 1 do local activation_level = get_activation_level(surface, Constants.world_selector_areas[i]) journey.world_selectors[i].activation_level = activation_level end if reroll_selector_activation_level > 1 then journey.mothership_speed = journey.mothership_speed + 0.025 if journey.mothership_speed > 4 then journey.mothership_speed = 4 clear_selectors(journey) journey.mothership_cargo.satellite = journey.mothership_cargo.satellite - 1 Public.draw_gui(journey) table.insert(journey.mothership_messages, "New lands have been discovered!") journey.game_state = "set_world_selectors" end else journey.mothership_speed = journey.mothership_speed - 0.25 if journey.mothership_speed < 0.35 then table.insert(journey.mothership_messages, "Aborting..") journey.game_state = "mothership_world_selection" journey.mothership_speed = 0.35 end end end function Public.mothership_world_selection(journey) Public.teleport_players_to_mothership(journey) local surface = game.surfaces.mothership local daytime = surface.daytime daytime = daytime - 0.025 if daytime < 0 then daytime = 0 end surface.daytime = daytime local reroll_selector_activation_level = get_activation_level(surface, Constants.reroll_selector_area) journey.reroll_selector.activation_level = reroll_selector_activation_level journey.selected_world = false for i = 1, 3, 1 do local activation_level = get_activation_level(surface, Constants.world_selector_areas[i]) journey.world_selectors[i].activation_level = activation_level if activation_level > 1 then journey.selected_world = i end end if reroll_selector_activation_level > 1 and journey.mothership_speed == 0.35 and journey.mothership_cargo.satellite > 0 then journey.game_state = "reroll_worlds" table.insert(journey.mothership_messages, "Dispatching satellite..") return end if journey.selected_world then if not journey.mothership_advancing_to_world then table.insert(journey.mothership_messages, "Advancing to selected world.") journey.mothership_advancing_to_world = game.tick + math.random(60 * 45, 60 * 75) else local seconds_left = math.floor((journey.mothership_advancing_to_world - game.tick) / 60) if seconds_left <= 0 then journey.mothership_advancing_to_world = false table.insert(journey.mothership_messages, "Arriving at targeted destination!") journey.game_state = "mothership_arrives_at_world" return end if seconds_left % 15 == 0 then table.insert(journey.mothership_messages, "Estimated arrival in " .. seconds_left .. " seconds.") end end journey.mothership_speed = journey.mothership_speed + 0.1 if journey.mothership_speed > 4 then journey.mothership_speed = 4 end else if journey.mothership_advancing_to_world then table.insert(journey.mothership_messages, "Aborting travling sequence.") journey.mothership_advancing_to_world = false end journey.mothership_speed = journey.mothership_speed - 0.25 if journey.mothership_speed < 0.35 then journey.mothership_speed = 0.35 end end draw_background(journey, surface) animate_selectors(journey) end function Public.mothership_arrives_at_world(journey) local surface = game.surfaces.mothership Public.teleport_players_to_mothership(journey) if journey.mothership_speed == 0.15 then for _ = 1, 16, 1 do table.insert(journey.mothership_messages, "") end table.insert(journey.mothership_messages, "[img=item/uranium-fuel-cell] Fuel cells depleted ;_;") for _ = 1, 16, 1 do table.insert(journey.mothership_messages, "") end table.insert(journey.mothership_messages, "Refuel via supply rocket required!") for i = 1, 3, 1 do journey.world_selectors[i].activation_level = 0 end animate_selectors(journey) journey.game_state = "clear_modifiers" else journey.mothership_speed = journey.mothership_speed - 0.15 end if journey.mothership_speed < 0.15 then journey.mothership_speed = 0.15 end draw_background(journey, surface) end function Public.clear_modifiers(journey) local unique_modifier = Unique_modifiers[journey.world_trait] local clear = unique_modifier.clear if clear then clear(journey) end local force = game.forces.player force.reset() force.reset_technologies() force.reset_technology_effects() for a = 1, 7, 1 do force.technologies['refined-flammables-' .. a].enabled = false end journey.game_state = "create_the_world" end function Public.create_the_world(journey) local surface = game.surfaces.nauvis local mgs = surface.map_gen_settings mgs.seed = math.random(1, 4294967295) mgs.terrain_segmentation = math.random(10, 20) * 0.1 mgs.peaceful_mode = false local modifiers = journey.world_selectors[journey.selected_world].modifiers for _, modifier in pairs(modifiers) do local m = (100 + modifier[2]) * 0.01 local name = modifier[1] for _, autoplace in pairs({"iron-ore", "copper-ore", "uranium-ore", "coal", "stone", "crude-oil"}) do if name == autoplace then mgs.autoplace_controls[name].richness = mgs.autoplace_controls[name].richness * m break end end if name == "mixed_ore" then journey.mixed_ore_richness = journey.mixed_ore_richness * m end for _, autoplace in pairs({"trees", "enemy-base"}) do if name == autoplace then for k, v in pairs(mgs.autoplace_controls[name]) do mgs.autoplace_controls[name][k] = mgs.autoplace_controls[name][k] * m end break end end if name == "cliff_settings" then --smaller value = more cliffs local m2 = (100 - modifier[2]) * 0.01 mgs.cliff_settings.cliff_elevation_interval = mgs.cliff_settings.cliff_elevation_interval * m2 mgs.cliff_settings.cliff_elevation_0 = mgs.cliff_settings.cliff_elevation_0 * m2 end if name == "water" then mgs.water = mgs.water * m end for _, evo in pairs({"time_factor", "destroy_factor", "pollution_factor"}) do if name == evo then game.map_settings.enemy_evolution[name] = game.map_settings.enemy_evolution[name] * m break end end if name == "expansion_cooldown" then game.map_settings.enemy_expansion.min_expansion_cooldown = game.map_settings.enemy_expansion.min_expansion_cooldown * m game.map_settings.enemy_expansion.max_expansion_cooldown = game.map_settings.enemy_expansion.max_expansion_cooldown * m end if name == "technology_price_multiplier" then game.difficulty_settings.technology_price_multiplier = game.difficulty_settings.technology_price_multiplier * m end if name == "enemy_attack_pollution_consumption_modifier" then game.map_settings.pollution.enemy_attack_pollution_consumption_modifier = game.map_settings.pollution.enemy_attack_pollution_consumption_modifier * m end if name == "ageing" then game.map_settings.pollution.ageing = game.map_settings.pollution.ageing * m end if name == "diffusion_ratio" then game.map_settings.pollution.diffusion_ratio = game.map_settings.pollution.diffusion_ratio * m end if name == "tree_durability" then game.map_settings.pollution.min_pollution_to_damage_trees = game.map_settings.pollution.min_pollution_to_damage_trees * m game.map_settings.pollution.pollution_restored_per_tree_damage = game.map_settings.pollution.pollution_restored_per_tree_damage * m end if name == "max_unit_group_size" then game.map_settings.unit_group.max_unit_group_size = game.map_settings.unit_group.max_unit_group_size * m end end surface.map_gen_settings = mgs surface.clear(false) journey.world_trait = journey.world_selectors[journey.selected_world].world_trait journey.nauvis_chunk_positions = nil journey.rocket_silos = {} journey.mothership_cargo["uranium-fuel-cell"] = 0 journey.world_number = journey.world_number + 1 journey.mothership_cargo_space["satellite"] = math_floor(journey.world_number * 0.334) + 1 journey.mothership_cargo_space["uranium-fuel-cell"] = journey.mothership_cargo_space["uranium-fuel-cell"] + journey.world_selectors[journey.selected_world].fuel_requirement game.forces.enemy.reset_evolution() for _, good in pairs(journey.world_selectors[journey.selected_world].bonus_goods) do if journey.bonus_goods[good[1]] then journey.bonus_goods[good[1]] = journey.bonus_goods[good[1]] + good[2] else journey.bonus_goods[good[1]] = good[2] end end journey.goods_to_dispatch = {} for k, v in pairs(journey.bonus_goods) do table.insert(journey.goods_to_dispatch, {k, v}) end table.shuffle_table(journey.goods_to_dispatch) journey.game_state = "wipe_offline_players" end function Public.wipe_offline_players(journey) remove_offline_players(168) for _, player in pairs(game.players) do if not player.connected then player.force = game.forces.enemy end end journey.game_state = "set_unique_modifiers" end function Public.set_unique_modifiers(journey) local unique_modifier = Unique_modifiers[journey.world_trait] local on_world_start = unique_modifier.on_world_start if on_world_start then on_world_start(journey) end Public.draw_gui(journey) journey.game_state = "place_teleporter_into_world" end function Public.place_teleporter_into_world(journey) local surface = game.surfaces.nauvis surface.request_to_generate_chunks({x = 0, y = 0}, 3) surface.force_generate_chunk_requests() place_teleporter(journey, surface, Constants.mothership_teleporter_position) journey.game_state = "make_it_night" end function Public.make_it_night(journey) draw_background(journey, game.surfaces.mothership) local surface = game.surfaces.mothership local daytime = surface.daytime daytime = daytime + 0.02 surface.daytime = daytime if daytime > 0.5 then clear_selectors(journey) game.reset_time_played() place_teleporter(journey, surface, Constants.mothership_teleporter_position) table.insert(journey.mothership_messages, "Teleporter deployed. [gps=" .. Constants.mothership_teleporter_position.x .. "," .. Constants.mothership_teleporter_position.y .. ",mothership]") journey.game_state = "dispatch_goods" end end function Public.dispatch_goods(journey) draw_background(journey, game.surfaces.mothership) if journey.characters_in_mothership == #game.connected_players then return end local goods_to_dispatch = journey.goods_to_dispatch local size_of_goods_to_dispatch = #goods_to_dispatch if size_of_goods_to_dispatch == 0 then for _ = 1, 30, 1 do table.insert(journey.mothership_messages, "") end table.insert(journey.mothership_messages, "Capsule storage depleted.") for _ = 1, 30, 1 do table.insert(journey.mothership_messages, "") end table.insert(journey.mothership_messages, "Good luck on your adventure! ^.^") journey.game_state = "world" return end if journey.dispatch_beacon and journey.dispatch_beacon.valid then return end local surface = game.surfaces.nauvis if journey.dispatch_beacon_position then local good = goods_to_dispatch[journey.dispatch_key] surface.spill_item_stack(journey.dispatch_beacon_position, {name = good[1], count = good[2]}, true, nil, false) table.remove(journey.goods_to_dispatch, journey.dispatch_key) journey.dispatch_beacon = nil journey.dispatch_beacon_position = nil journey.dispatch_key = nil return end local chunk = surface.get_random_chunk() if math.abs(chunk.x) > 4 or math.abs(chunk.y) > 4 then return end local position = {x = chunk.x * 32 + math.random(0, 31), y = chunk.y * 32 + math.random(0, 31)} position = surface.find_non_colliding_position("rocket-silo", position, 32, 1) if not position then return end journey.dispatch_beacon = surface.create_entity({name = "stone-wall", position = position, force = "neutral"}) journey.dispatch_beacon.minable = false journey.dispatch_beacon_position = {x = position.x, y = position.y} journey.dispatch_key = math.random(1, size_of_goods_to_dispatch) local good = goods_to_dispatch[journey.dispatch_key] table.insert(journey.mothership_messages, "Capsule containing " .. good[2] .. "x [img=item/" .. good[1] .. "] dispatched. [gps=" .. position.x .. "," .. position.y .. ",nauvis]") surface.create_entity({name = "artillery-projectile", position = {x = position.x - 256 + math.random(0, 512), y = position.y - 256}, target = position, speed = 0.2}) end function Public.world(journey) if journey.mothership_cargo["uranium-fuel-cell"] then if journey.mothership_cargo["uranium-fuel-cell"] >= journey.mothership_cargo_space["uranium-fuel-cell"] then table.insert(journey.mothership_messages, "[img=item/uranium-fuel-cell] Refuel operation successful!! =^.^=") Server.to_discord_embed("Refuel operation complete!") journey.game_state = "mothership_waiting_for_players" end end draw_background(journey, game.surfaces.mothership) if game.tick % 1800 ~= 0 then return end for k, silo in pairs(journey.rocket_silos) do if not silo or not silo.valid then table.remove(journey.rocket_silos, k) break end local inventory = silo.get_inventory(defines.inventory.rocket_silo_rocket) if inventory then local fuel_cells_required = journey.mothership_cargo_space["uranium-fuel-cell"] - journey.mothership_cargo["uranium-fuel-cell"] if fuel_cells_required > 50 then fuel_cells_required = 50 end if inventory.get_item_count('satellite') == 1 or inventory.get_item_count('uranium-fuel-cell') >= fuel_cells_required then if silo.launch_rocket() then table.insert(journey.mothership_messages, "Launching rocket [gps=" .. silo.position.x .. "," .. silo.position.y .. ",nauvis]") end end end end end function Public.mothership_waiting_for_players(journey) if journey.characters_in_mothership > #game.connected_players * 0.5 then journey.game_state = "set_world_selectors" return end if math.random(1, 2) == 1 then return end local tick = game.tick % 3600 if tick == 0 then local messages = Constants.mothership_messages.waiting table.insert(journey.mothership_messages, messages[math.random(1, #messages)]) end end function Public.teleporters(journey, player) if not player.character then return end if not player.character.valid then return end local surface = player.surface if surface.get_tile(player.position).name ~= Constants.teleporter_tile then return end local base_position = {0,0} if surface.index == 1 then drop_player_items(player) local position = game.surfaces.mothership.find_non_colliding_position("character", base_position, 32, 0.5) if position then player.teleport(position, game.surfaces.mothership) else player.teleport(base_position, game.surfaces.mothership) end journey.characters_in_mothership = journey.characters_in_mothership + 1 return end if surface.name == "mothership" then Public.clear_player(player) local position = game.surfaces.nauvis.find_non_colliding_position("character", base_position, 32, 0.5) if position then player.teleport(position, game.surfaces.nauvis) else player.teleport(base_position, game.surfaces.nauvis) end journey.characters_in_mothership = journey.characters_in_mothership - 1 return end end return Public