local locations = require(mod_name .. '.lualib.locations') local quest_gui = require(mod_name .. '.lualib.quest_gui') local trigger = require(mod_name .. '.lualib.trigger') local effect = require(mod_name .. '.lualib.effects') local cutscene = require(mod_name .. '.lualib.cutscene') local compi = require(mod_name .. '.lualib.compi') local function_save = require(mod_name .. '.lualib.function_save') local misc = require(mod_name .. '.lualib.misc') local story = require('story_2') local base_controller = {} local bases_list -- initialised in on_load local base_controller_data = { base_stages = {} } local check_set_up = function() if bases_list == nil then error("trying to use base_controller before it has been set up by on_load!") end end base_controller.get_cutscene_show_full_base_parameters = function(base_name, player) check_set_up() local base_data = bases_list[base_name] return misc.get_cutscene_show_area_parameters(locations.get_area(base_data.perimeter), player.display_resolution) end base_controller.generate_mainframe_story_nodes = function(base_name) check_set_up() local base_data = bases_list[base_name] local base_powered = function() local lamp_1 = locations.get_surface_ent_from_tag(global.main_surface, base_data.lamp_1) local lamp_2 = locations.get_surface_ent_from_tag(global.main_surface, base_data.lamp_2) return lamp_1.energy > 0 or lamp_2.energy > 0 end local connect_power = { name = base_name .. "_connect_power", init = function() local quest_layout = { { item_name = 'power-' .. base_name, icons = {'utility/electricity_icon'}, }, } quest_gui.set('power-' .. base_name, quest_layout) end, condition = function() local done = base_powered() if done then quest_gui.update_state('power-' .. base_name, 3) else quest_gui.update_state('power-' .. base_name, 1) end return done end, action = function() quest_gui.unset() end } local go_to_mainframe = { name = base_name .. "_go_to_mainframe", init = function() trigger.add_trigger('base_trigger_' .. base_name, locations.get_area(base_data.trigger)) local quest_layout = { { item_name = 'go-to-mainframe-' .. base_name, icons = {'utility/electricity_icon'}, }, } quest_gui.set('override-' .. base_name, quest_layout) end, update = function() local still_powered = base_powered() if not still_powered then trigger.remove_trigger('base_trigger_' .. base_name) story.jump_to_node('main_story', base_name .. '_connect_power') end end, condition = function() local triggered = trigger.is_trigger_done('base_trigger_' .. base_name, true) return triggered end, action = function() quest_gui.unset() end } local compi_override_mainframe_1 = { name = base_name .. "_override_mainframe_1", init = function() local switch_pos = locations.get_surface_ent_from_tag(global.main_surface, base_data.switch).position switch_pos.x = switch_pos.x - 1 switch_pos.y = switch_pos.y + 1 compi.walk_to(switch_pos) compi.set_direction(defines.direction.northeast) for _, player in pairs(game.connected_players) do local show_base_params = base_controller.get_cutscene_show_full_base_parameters(base_name, player) local activate_mainframe_cutscene = { type=defines.controllers.cutscene, waypoints = { { target = global.compilatron.entity, zoom = 1.5, transition_time = 60 * 1, time_to_wait = 60 * 1 }, { target = global.compilatron.entity, zoom = 2, transition_time = 60 * 1, time_to_wait = 0 }, { target = global.compilatron.entity, zoom = 2, transition_time = 0, time_to_wait = 60 * 2 }, { target = global.compilatron.entity, zoom = 2, transition_time = 0, time_to_wait = 60 * 2 }, { position = show_base_params.position, transition_time = 60 * 1, time_to_wait = 60 * 3, zoom = show_base_params.zoom }, { position = show_base_params.position, transition_time = 0, time_to_wait = 60 * 5, zoom = show_base_params.zoom } }, final_transition_time = 60 * 2 } cutscene.play(activate_mainframe_cutscene, {player}) end end, condition = function() return cutscene.get_last_waypoint_reached() == 1 end } local compi_override_mainframe_2 = { name = base_name .. "_override_mainframe_2", init = function() compi.say("Initialising Mainframe...") end, condition = function() return cutscene.get_last_waypoint_reached() == 2 end } local compi_override_mainframe_3 = { name = base_name .. "_override_mainframe_3", init = function() compi.set_direction() compi.say("Mainframe Initialised") end, condition = function() return cutscene.get_last_waypoint_reached() == 3 end, action = function() compi.say() end } local compi_override_mainframe_4 = { name = base_name .. "_override_mainframe_4", init = function() local base_area = locations.get_area(base_data.perimeter) local tiles = global.main_surface.find_tiles_filtered { area = base_area, name = "refined-hazard-concrete-right" } local tile_lines_tmp = {} for _, tile in pairs(tiles) do if tile_lines_tmp[tile.position.x] == nil then tile_lines_tmp[tile.position.x] = {} end table.insert(tile_lines_tmp[tile.position.x], tile) end local tile_lines = {} for _, line in pairs(tile_lines_tmp) do table.insert(tile_lines, line) end table.sort(tile_lines, function(a, b) return a[1].position.x > b[1].position.x end) local tick = game.tick + 60 * 1 local time = 60 * 2.5 local step = time / #tile_lines for _, line in pairs(tile_lines) do function_save.run_at_tick(math.floor(tick), "convert_tiles", line) tick = tick + step end end, condition = function() return cutscene.get_last_waypoint_reached() == 4 end } local compi_override_mainframe_5 = { name = base_name .. "_override_mainframe_5", init = function() local switch = locations.get_surface_ent_from_tag(global.main_surface, base_data.switch) switch.power_switch_state = true global.main_surface.play_sound{path="mainframe-activated"} end, condition = function() return not cutscene.is_any_cutscene_playing() end, -- Convert base entities to player force and unlock tech action = function() local entities = global.main_surface.find_entities_filtered { area = locations.get_area(base_data.perimeter), force = "pre-placed" } for _, entity in pairs(entities) do if entity.name == 'assembling-machine-1' or entity.name == 'assembling-machine-2' or entity.name == 'assembling-machine-3' then entity.recipe_locked = false end if entity.prototype.name == "gate" then entity.operable = true end if entity.operable then entity.force = "player" entity.minable = true entity.rotatable = true end end effect.unlock_technologies(base_data.override_tech) end } return { connect_power, go_to_mainframe, compi_override_mainframe_1, compi_override_mainframe_2, compi_override_mainframe_3, compi_override_mainframe_4, compi_override_mainframe_5 } end local convert_tiles = function(tiles) local set_tiles_data = {} for _, tile in pairs(tiles) do table.insert(set_tiles_data, {name = "refined-concrete", position = tile.position}) end global.main_surface.set_tiles(set_tiles_data) global.main_surface.play_sound{path="entity-build/substation"} end function_save.add_function("convert_tiles", convert_tiles) base_controller.init = function() global.base_controller_data = base_controller_data end -- validates base data, and fills in optional fields with empty tables local validate_base_data = function(base_data) local filled_base_data = {} for name, base in pairs(base_data) do if locations.get_area(base.perimeter) == nil then error("base_controller: cant find perimeter area -"..base.perimeter) end if locations.get_area(base.trigger) == nil then error("base_controller: cant find trigger area -"..base.trigger) end if locations.get_pos(base.compi_spawn) == nil then error("base_controller: cant find compi spawn point -"..base.compi_spawn) end if locations.get_pos(base.compi_stand) == nil then error("base_controller: cant find compi stand point -"..base.compi_stand) end local this_base_data = { name = name, perimeter = base.perimeter, trigger = base.trigger, mainframe_tech = base.mainframe_tech or {}, override_tech = base.override_tech or {}, mainframe_goal = base.mainframe_goal or {}, override_goal = base.override_goal or {}, compi_spawn = base.compi_spawn, compi_stand = base.compi_stand, lamp_1 = base.lamp_1, lamp_2 = base.lamp_2, switch = base.switch } -- If this is run from on_load, we don't have access to game. -- It's not the biggest deal, as this is just validation anyway, so we can just skip it if game then for _, techname in pairs(this_base_data.mainframe_tech) do if game.forces.player.technologies[techname] == nil then error("base_controller: Invalid mainframe_tech -"..techname) end end for _, techname in pairs(this_base_data.override_tech) do if game.forces.player.technologies[techname] == nil then error("base_controller: Invalid override_tech -"..techname) end end for _, techname in pairs(this_base_data.mainframe_goal) do if game.forces.player.technologies[techname] == nil then error("base_controller: Invalid mainframe_goal -"..techname) end end for _, techname in pairs(this_base_data.override_goal) do if game.forces.player.technologies[techname] == nil then error("base_controller: Invalid override_goal -"..techname) end end end filled_base_data[name] = this_base_data end return filled_base_data end base_controller.setup = function(bases) if bases_list == nil then bases_list = validate_base_data(bases) end end base_controller.on_load = function(bases) base_controller.setup(bases) base_controller_data = global.base_controller_data end return base_controller