local Balance = require 'maps.pirates.balance' local _inspect = require 'utils.inspect'.inspect local Memory = require 'maps.pirates.memory' local Math = require 'maps.pirates.math' local Common = require 'maps.pirates.common' -- local Parrot = require 'maps.pirates.parrot' local CoreData = require 'maps.pirates.coredata' local Server = require 'utils.server' local Utils = require 'maps.pirates.utils_local' local Surfaces = require 'maps.pirates.surfaces.surfaces' -- local Structures = require 'maps.pirates.structures.structures' local Boats = require 'maps.pirates.structures.boats.boats' local Crowsnest = require 'maps.pirates.surfaces.crowsnest' local Hold = require 'maps.pirates.surfaces.hold' local Lobby = require 'maps.pirates.surfaces.lobby' local Cabin = require 'maps.pirates.surfaces.cabin' local Roles = require 'maps.pirates.roles.roles' local Classes = require 'maps.pirates.roles.classes' local Token = require 'utils.token' local Task = require 'utils.task' local SurfacesCommon = require 'maps.pirates.surfaces.common' local Public = {} local enum = { ADVENTURING = 'adventuring', LEAVING_INITIAL_DOCK = 'leavinginitialdock' } Public.enum = enum function Public.difficulty_vote(player_index, difficulty_id) local memory = Memory.get_crew_memory() if not (memory.difficulty_votes) then memory.difficulty_votes = {} end local player = game.players[player_index] if not (player and player.valid) then return end if memory.difficulty_votes[player_index] and memory.difficulty_votes[player_index] == difficulty_id then return nil else local option = CoreData.difficulty_options[difficulty_id] if not option then return end local color = option.associated_color Common.notify_force(memory.force, player.name .. ' voted [color=' .. color.r .. ',' .. color.g .. ',' .. color.b .. ']for difficulty ' .. option.text .. '[/color]') memory.difficulty_votes[player_index] = difficulty_id Public.update_difficulty() end end function Public.update_difficulty() local memory = Memory.get_crew_memory() local vote_counts = {} for _, difficulty_id in pairs(memory.difficulty_votes) do if not vote_counts[difficulty_id] then vote_counts[difficulty_id] = 1 else vote_counts[difficulty_id] = vote_counts[difficulty_id] + 1 end end local modal_id = 1 local modal_count = 0 for difficulty_id, votes in pairs(vote_counts) do if votes > modal_count or (votes == modal_count and difficulty_id < modal_id) then modal_count = votes modal_id = difficulty_id end end if modal_id ~= memory.difficulty_option then local color = CoreData.difficulty_options[modal_id].associated_color local message1 = 'Difficulty [color=' .. color.r .. ',' .. color.g .. ',' .. color.b .. ']changed to ' .. CoreData.difficulty_options[modal_id].text .. '[/color].' local message2 = 'Difficulty changed to ' .. CoreData.difficulty_options[modal_id].text .. '.' Common.notify_force(memory.force, message1) Server.to_discord_embed_raw(CoreData.comfy_emojis.kewl .. '[' .. memory.name .. '] ' .. message2) memory.difficulty_option = modal_id memory.difficulty = CoreData.difficulty_options[modal_id].value end end function Public.try_add_extra_time_at_sea(ticks) local memory = Memory.get_crew_memory() if not memory.extra_time_at_sea then memory.extra_time_at_sea = 0 end if memory.extra_time_at_sea >= CoreData.max_extra_seconds_at_sea * 60 then return false end -- if memory.boat and memory.boat.state and memory.boat.state == Boats.enum_state.ATSEA_LOADING_MAP then return false end memory.extra_time_at_sea = memory.extra_time_at_sea + ticks return true end function Public.get_crewmembers_printable_string() local crewmembers_string = '' for _, player in pairs(Common.crew_get_crew_members()) do if player.valid then if crewmembers_string ~= '' then crewmembers_string = crewmembers_string .. ', ' end crewmembers_string = crewmembers_string .. player.name end end if crewmembers_string ~= '' then crewmembers_string = crewmembers_string .. '.' end return crewmembers_string end function Public.try_lose(reason) local memory = Memory.get_crew_memory() if (not memory.game_lost) then -- if (not memory.game_lost) and (not memory.game_won) then memory.game_lost = true memory.crew_disband_tick = game.tick + 360 local playtimetext = Utils.time_longform((memory.age or 0)/60) Server.to_discord_embed_raw(CoreData.comfy_emojis.trashbin .. '[' .. memory.name .. '] Game over — ' .. reason ..'. Playtime: ' .. playtimetext .. ' since 1st island. Crewmembers: ' .. Public.get_crewmembers_printable_string()) Common.notify_game('[' .. memory.name .. '] Game over — ' .. reason ..'. Playtime: [font=default-large-semibold]' .. playtimetext .. '[/font] since 1st island.', CoreData.colors.notify_gameover) local force = memory.force if not (force and force.valid) then return end force.play_sound{path='utility/game_lost', volume_modifier=0.75} --playing to the whole game might scare ppl end end function Public.try_win() local memory = Memory.get_crew_memory() if (not (memory.game_lost or memory.game_won)) then -- if (not memory.game_lost) and (not memory.game_won) then memory.completion_time = Math.floor((memory.age or 0)/60) local speedrun_time = (memory.age or 0)/60 local speedrun_time_str = Utils.time_longform(speedrun_time) memory.game_won = true -- memory.crew_disband_tick = game.tick + 1200 Server.to_discord_embed_raw(CoreData.comfy_emojis.goldenobese .. '[' .. memory.name .. '] Victory, on v' .. CoreData.version_string .. ', ' .. CoreData.difficulty_options[memory.difficulty_option].text .. ', capacity ' .. CoreData.capacity_options[memory.capacity_option].text3 .. '. Playtime: ' .. speedrun_time_str .. ' since 1st island. Crewmembers: ' .. Public.get_crewmembers_printable_string()) Common.notify_game('[' .. memory.name .. '] Victory, on v' .. CoreData.version_string .. ', ' .. CoreData.difficulty_options[memory.difficulty_option].text .. ', capacity ' .. CoreData.capacity_options[memory.capacity_option].text3 .. '. Playtime: [font=default-large-semibold]' .. speedrun_time_str .. '[/font] since 1st island. Crewmembers: ' .. Public.get_crewmembers_printable_string(), CoreData.colors.notify_victory) game.play_sound{path='utility/game_won', volume_modifier=0.9} memory.victory_pause_until_tick = game.tick + 60*18 memory.victory_continue_message = true end end function Public.choose_crew_members() -- local global_memory = Memory.get_global_memory() local memory = Memory.get_crew_memory() local capacity = memory.capacity local boat = memory.boat -- if the boat is over capacity, should prefer original endorsers over everyone else: local crew_members = {} local crew_members_count = 0 for _, player in pairs(game.connected_players) do if crew_members_count < capacity and player.surface.name == CoreData.lobby_surface_name and Boats.on_boat(boat, player.position) then -- check if they were an endorser local endorser = false for _, index in pairs(memory.original_proposal.endorserindices) do if player.index == index then endorser = true end end if endorser then crew_members[player.index] = player crew_members_count = crew_members_count + 1 end end end if crew_members_count < capacity then for _, player in pairs(game.connected_players) do if crew_members_count < capacity and (not crew_members[player.index]) and player.surface.name == CoreData.lobby_surface_name and Boats.on_boat(boat, player.position) then crew_members[player.index] = player crew_members_count = crew_members_count + 1 end end end for _, player in pairs(crew_members) do player.force = memory.force memory.crewplayerindices[#memory.crewplayerindices + 1] = player.index end return crew_members end function Public.join_spectators(player, crewid) if crewid > 0 then Memory.set_working_id(crewid) local memory = Memory.get_crew_memory() local force = game.forces[string.format('crew-%03d', crewid)] if not (force and force.valid and Common.validate_player(player)) then return end local surface = game.surfaces[CoreData.lobby_surface_name] local adventuring = false local spectating = false if memory.crewstatus and memory.crewstatus == enum.ADVENTURING then for _, playerindex in pairs(memory.crewplayerindices) do if player.index == playerindex then adventuring = true end end for _, playerindex in pairs(memory.spectatorplayerindices) do if player.index == playerindex then spectating = true end end end if not spectating then if adventuring then local char = player.character if char and char.valid then local p = char.position -- local surface_name = char.surface.name local message = player.name .. ' left the crew' if p then Common.notify_force(force, message .. ' to become a spectator.') -- Server.to_discord_embed_raw(CoreData.comfy_emojis.feel .. '[' .. memory.name .. '] ' .. message) end -- if p then -- Common.notify_force(force, message .. ' to become a spectator.' .. ' [gps=' .. Math.ceil(p.x) .. ',' .. Math.ceil(p.y) .. ',' .. surface_name ..']') -- -- Server.to_discord_embed_raw(CoreData.comfy_emojis.feel .. '[' .. memory.name .. '] ' .. message) -- end Common.send_important_items_from_player_to_crew(player, true) char.die(memory.force_name) player.set_controller{type = defines.controllers.spectator} else local message = player.name .. ' left the crew' Common.notify_force(force, message .. ' to become a spectator.') -- Server.to_discord_embed_raw(CoreData.comfy_emojis.feel .. '[' .. memory.name .. '] ' .. message) player.set_controller{type = defines.controllers.spectator} end local c = surface.create_entity{name = 'character', position = surface.find_non_colliding_position('character', Common.lobby_spawnpoint, 32, 0.5) or Common.lobby_spawnpoint, force = 'player'} player.associate_character(c) player.set_controller{type = defines.controllers.spectator} memory.crewplayerindices = Utils.ordered_table_with_values_removed(memory.crewplayerindices, player.index) Roles.player_left_so_redestribute_roles(player) else Public.player_abandon_endorsements(player) local c = player.character player.set_controller{type = defines.controllers.spectator} player.teleport(memory.spawnpoint, game.surfaces[Common.current_destination().surface_name]) player.force = force player.associate_character(c) Common.notify_force(force, player.name .. ' joined as a spectator.') Common.notify_lobby(player.name .. ' left the lobby to spectate ' .. memory.name .. '.') end memory.spectatorplayerindices[#memory.spectatorplayerindices + 1] = player.index memory.tempbanned_from_joining_data[player.index] = game.tick -- if #Common.crew_get_crew_members() == 0 then -- memory.crew_disband_tick = game.tick + 30 -- -- memory.crew_disband_tick = game.tick + 60*60*2 --give players time to log back in after a crash or save -- end if not (memory.difficulty_votes) then memory.difficulty_votes = {} end memory.difficulty_votes[player.index] = nil end end end function Public.leave_spectators(player, quiet) quiet = quiet or false local memory = Memory.get_crew_memory() local surface = game.surfaces[CoreData.lobby_surface_name] if not Common.validate_player(player) then return end if not quiet then Common.notify_force(player.force, player.name .. ' stopped spectating and returned to the lobby.') end local chars = player.get_associated_characters() if #chars > 0 then player.teleport(chars[1].position, surface) player.set_controller{type = defines.controllers.character, character = chars[1]} else player.set_controller{type = defines.controllers.god} player.teleport(surface.find_non_colliding_position('character', Common.lobby_spawnpoint, 32, 0.5) or Common.lobby_spawnpoint, surface) player.create_character() end memory.spectatorplayerindices = Utils.ordered_table_with_values_removed(memory.spectatorplayerindices, player.index) if #Common.crew_get_crew_members() == 0 then if Common.autodisband_ticks then memory.crew_disband_tick = game.tick + Common.autodisband_ticks end if _DEBUG then memory.crew_disband_tick = game.tick + 30*60*60 end end player.force = 'player' end function Public.join_crew(player, crewid, rejoin) if crewid then Memory.set_working_id(crewid) local memory = Memory.get_crew_memory() if not Common.validate_player(player) then return end -- local startsurface = game.surfaces[CoreData.lobby_surface_name] local boat = memory.boat local surface if boat and boat.surface_name and game.surfaces[boat.surface_name] and game.surfaces[boat.surface_name].valid then surface = game.surfaces[boat.surface_name] else surface = game.surfaces[Common.current_destination().surface_name] end -- local adventuring = false local spectating = false if memory.crewstatus and memory.crewstatus == enum.ADVENTURING then -- for _, playerindex in pairs(memory.crewplayerindices) do -- if player.index == playerindex then adventuring = true end -- end for _, playerindex in pairs(memory.spectatorplayerindices) do if player.index == playerindex then spectating = true end end end if spectating then local chars = player.get_associated_characters() for _, char in pairs(chars) do char.destroy() end player.teleport(surface.find_non_colliding_position('character', memory.spawnpoint, 32, 0.5) or memory.spawnpoint, surface) player.set_controller{type = defines.controllers.god} player.create_character() memory.spectatorplayerindices = Utils.ordered_table_with_values_removed(memory.spectatorplayerindices, player.index) else Public.player_abandon_endorsements(player) player.force = game.forces[string.format('crew-%03d', memory.id)] player.teleport(surface.find_non_colliding_position('character', memory.spawnpoint, 32, 0.5) or memory.spawnpoint, surface) Common.notify_lobby(player.name .. ' left the lobby to join ' .. memory.name .. '.') end local message = player.name .. ' joined the crew.' Common.notify_force(player.force, message) -- Server.to_discord_embed_raw(CoreData.comfy_emojis.yum1 .. '[' .. memory.name .. '] ' .. message) memory.crewplayerindices[#memory.crewplayerindices + 1] = player.index -- don't give them items if they've been in the crew recently: if not (memory.tempbanned_from_joining_data and memory.tempbanned_from_joining_data[player.index] and game.tick < memory.tempbanned_from_joining_data[player.index] + 8 * Common.ban_from_rejoining_crew_ticks) and (not rejoin) then for item, amount in pairs(Balance.starting_items_player_late) do player.insert({name = item, count = amount}) end end Roles.confirm_captain_exists(player) if #Common.crew_get_crew_members() == 1 and memory.crew_disband_tick then memory.crew_disband_tick = nil --to prevent disbanding the crew after saving the game (booting everyone) and loading it again (joining the crew as the only member) end local personal_str = 'You have joined the crew \'' .. memory.name if memory.overworldx > 0 then local color = CoreData.difficulty_options[memory.difficulty_option].associated_color personal_str = personal_str .. '\' [Capacity ' .. CoreData.capacity_options[memory.capacity_option].text3 .. ', Difficulty [color=' .. color.r .. ',' .. color.g .. ',' .. color.b .. ']' .. CoreData.difficulty_options[memory.difficulty_option].text .. '[/color]].' else personal_str = personal_str .. '\' [Capacity ' .. CoreData.capacity_options[memory.capacity_option].text3 .. '].' end Common.notify_player_announce(player, personal_str) end end function Public.leave_crew(player, to_lobby, quiet) quiet = quiet or false local memory = Memory.get_crew_memory() local surface = game.surfaces[CoreData.lobby_surface_name] if not Common.validate_player(player) then return end local char = player.character if char and char.valid then -- local p = char.position -- local surface_name = char.surface.name local message if not quiet then message = player.name .. ' left the crew.' Common.notify_force(player.force, message) -- else -- message = player.name .. ' left.' end -- if p then -- Common.notify_force(player.force, message .. ' [gps=' .. Math.ceil(p.x) .. ',' .. Math.ceil(p.y) .. ',' .. surface_name ..']') -- -- Server.to_discord_embed_raw(CoreData.comfy_emojis.feel .. '[' .. memory.name .. '] ' .. message) -- end if to_lobby then Common.send_important_items_from_player_to_crew(player, true) char.die(memory.force_name) else Common.send_important_items_from_player_to_crew(player) memory.temporarily_logged_off_characters[player.index] = game.tick end -- else -- if not quiet then -- -- local message = player.name .. ' left the crew.' -- -- Common.notify_force(player.force, message) -- end end if to_lobby then player.set_controller{type = defines.controllers.god} player.teleport(surface.find_non_colliding_position('character', Common.lobby_spawnpoint, 32, 0.5) or Common.lobby_spawnpoint, surface) player.force = 'player' player.create_character() end memory.crewplayerindices = Utils.ordered_table_with_values_removed(memory.crewplayerindices, player.index) -- setting it to this won't ban them from rejoining, it just affects the loot they spawn in with: memory.tempbanned_from_joining_data[player.index] = game.tick - Common.ban_from_rejoining_crew_ticks if not (memory.difficulty_votes) then memory.difficulty_votes = {} end memory.difficulty_votes[player.index] = nil if #Common.crew_get_crew_members() == 0 then if Common.autodisband_ticks then memory.crew_disband_tick = game.tick + Common.autodisband_ticks end -- memory.crew_disband_tick = game.tick + 60*60*2 --give players time to log back in after a crash or save if _DEBUG then memory.crew_disband_tick = game.tick + 30*60*60 end else Roles.player_left_so_redestribute_roles(player) end end function Public.get_unaffiliated_players() local global_memory = Memory.get_global_memory() local playerlist = {} for _, player in pairs(game.connected_players) do local found = false for _, id in pairs(global_memory.crew_active_ids) do Memory.set_working_id(id) for _, player2 in pairs(Common.crew_get_crew_members_and_spectators()) do if player == player2 then found = true end end end if not found then playerlist[#playerlist + 1] = player end end return playerlist end function Public.plank(captain, player) local memory = Memory.get_crew_memory() if Utils.contains(Common.crew_get_crew_members(), player) then if (not (captain.index == player.index)) then local message = "%s planked %s!" Server.to_discord_embed_raw(CoreData.comfy_emojis.monkas .. string.format(message, captain.name, player.name)) Common.notify_force(player.force, string.format(message, captain.name, player.name)) Public.join_spectators(player, memory.id) memory.tempbanned_from_joining_data[player.index] = game.tick + 60 * 120 return true else Common.notify_player_error(captain, 'Command error: Can\'t plank yourself.') return false end else Common.notify_player_error(captain, 'Command error: Player is not a crewmember.') return false end end function Public.disband_crew(donotprint) local global_memory = Memory.get_global_memory() local memory = Memory.get_crew_memory() if not memory.name then return end local id = memory.id local players = Common.crew_get_crew_members_and_spectators() for _,player in pairs(players) do if player.controller_type == defines.controllers.editor then player.toggle_map_editor() end player.force = 'player' end if (not donotprint) then local message = '[' .. memory.name .. '] Disbanded after ' .. Utils.time_longform((memory.real_age or 0)/60) .. '.' Common.notify_game(message) Server.to_discord_embed_raw(CoreData.comfy_emojis.monkas .. message) -- if memory.game_won then -- game.print({'chronosphere.message_game_won_restart'}, {r=0.98, g=0.66, b=0.22}) -- end end Public.reset_crew_and_enemy_force(id) local lobby = game.surfaces[CoreData.lobby_surface_name] for _, player in pairs(players) do if player.character then player.character.destroy() player.character = nil end player.set_controller({type=defines.controllers.god}) if player.get_associated_characters() and #player.get_associated_characters() == 1 then local char = player.get_associated_characters()[1] player.teleport(char.position, char.surface) player.set_controller({type=defines.controllers.character, character=char}) else local pos = lobby.find_non_colliding_position('character', Common.lobby_spawnpoint, 32, 0.5) or Common.lobby_spawnpoint player.teleport(pos, lobby) player.create_character() end end if memory.sea_name then local seasurface = game.surfaces[memory.sea_name] if seasurface then game.delete_surface(seasurface) end end for i = 1, memory.hold_surface_count do local holdname = Hold.get_hold_surface_name(i) if game.surfaces[holdname] then game.delete_surface(game.surfaces[holdname]) end end local cabinname = Cabin.get_cabin_surface_name() if game.surfaces[cabinname] then game.delete_surface(game.surfaces[cabinname]) end local s = Hold.get_hold_surface(1) if s and s.valid then log('hold failed to delete') end s = Cabin.get_cabin_surface() if s and s.valid then log(_inspect(cabinname)) log('cabin failed to delete') end local crowsnestname = SurfacesCommon.encode_surface_name(memory.id, 0, Surfaces.enum.CROWSNEST, nil) if game.surfaces[crowsnestname] then game.delete_surface(game.surfaces[crowsnestname]) end for _, destination in pairs(memory.destinations) do if game.surfaces[destination.surface_name] then game.delete_surface(game.surfaces[destination.surface_name]) end end global_memory.crew_memories[id] = nil for k, idd in pairs(global_memory.crew_active_ids) do if idd == id then table.remove(global_memory.crew_active_ids, k) end end Lobby.place_starting_dock_showboat(id) end function Public.generate_new_crew_id() local global_memory = Memory.get_global_memory() if not global_memory.crew_memories[1] then return 1 elseif not global_memory.crew_memories[2] then return 2 elseif not global_memory.crew_memories[3] then return 3 else return end end function Public.player_abandon_proposal(player) local global_memory = Memory.get_global_memory() for k, proposal in pairs(global_memory.crewproposals) do if proposal.endorserindices and proposal.endorserindices[1] and proposal.endorserindices[1] == player.index then proposal.endorserindices[k] = nil Common.notify_lobby('Proposal ' .. proposal.name .. ' retracted.') -- Server.to_discord_embed(message) global_memory.crewproposals[k] = nil end end end function Public.player_abandon_endorsements(player) local global_memory = Memory.get_global_memory() for k, proposal in pairs(global_memory.crewproposals) do for k2, i in pairs(proposal.endorserindices) do if i == player.index then proposal.endorserindices[k2] = nil if #proposal.endorserindices == 0 then Common.notify_lobby('Proposal ' .. proposal.name .. ' abandoned.') -- Server.to_discord_embed(message) global_memory.crewproposals[k] = nil end end end end end local crowsnest_delayed = Token.register( function(data) Memory.set_working_id(data.crew_id) Crowsnest.crowsnest_surface_delayed_init() end ) function Public.initialise_crowsnest() local memory = Memory.get_crew_memory() Crowsnest.create_crowsnest_surface() Task.set_timeout_in_ticks(5, crowsnest_delayed, {crew_id = memory.id}) end function Public.initialise_crowsnest_1() Crowsnest.create_crowsnest_surface() end function Public.initialise_crowsnest_2() Crowsnest.crowsnest_surface_delayed_init() end function Public.initialise_crew(accepted_proposal) local global_memory = Memory.get_global_memory() local new_id = Public.generate_new_crew_id() global_memory.crew_active_ids[#global_memory.crew_active_ids + 1] = new_id Memory.initialise_crew_memory(new_id) Memory.set_working_id(new_id) game.reset_time_played() -- affects the multiplayer lobby view local memory = Memory.get_crew_memory() local secs = Server.get_current_time() if not secs then secs = 0 end memory.secs_id = secs memory.id = new_id memory.force_name = string.format('crew-%03d', new_id) memory.enemy_force_name = string.format('enemy-%03d', new_id) memory.ancient_enemy_force_name = string.format('ancient-hostile-%03d', new_id) memory.ancient_friendly_force_name = string.format('ancient-friendly-%03d', new_id) memory.force = game.forces[string.format('crew-%03d', new_id)] memory.enemy_force = game.forces[string.format('enemy-%03d', new_id)] memory.ancient_enemy_force = game.forces[string.format('ancient-hostile-%03d', new_id)] memory.ancient_friendly_force = game.forces[string.format('ancient-friendly-%03d', new_id)] memory.evolution_factor = 0 memory.delayed_tasks = {} memory.buffered_tasks = {} memory.crewplayerindices = {} memory.spectatorplayerindices = {} memory.tempbanned_from_joining_data = {} memory.destinations = {} memory.temporarily_logged_off_characters = {} memory.hold_surface_count = 1 memory.speed_boost_characters = {} memory.original_proposal = accepted_proposal memory.name = accepted_proposal.name memory.difficulty_option = accepted_proposal.difficulty_option memory.capacity_option = accepted_proposal.capacity_option -- memory.mode_option = accepted_proposal.mode_option memory.difficulty = CoreData.difficulty_options[accepted_proposal.difficulty_option].value memory.capacity = CoreData.capacity_options[accepted_proposal.capacity_option].value -- memory.mode = CoreData.mode_options[accepted_proposal.mode_option].value memory.destinationsvisited_indices = {} memory.stored_fuel = Balance.starting_fuel memory.available_classes_pool = Classes.initial_class_pool() memory.playtesting_stats = { coins_gained_by_biters = 0, coins_gained_by_nests_and_worms = 0, coins_gained_by_trees_and_rocks = 0, coins_gained_by_ore = 0, coins_gained_by_rocket_launches = 0, coins_gained_by_markets = 0, coins_gained_by_krakens = 0, } memory.captain_accrued_time_data = {} memory.max_players_recorded = 0 memory.classes_table = {} memory.officers_table = {} memory.spare_classes = {} memory.healthbars = {} memory.overworld_krakens = {} memory.kraken_stream_registrations = {} memory.overworldx = 0 memory.overworldy = 0 memory.seaname = SurfacesCommon.encode_surface_name(memory.id, 0, SurfacesCommon.enum.SEA, enum.DEFAULT) local surface = game.surfaces[CoreData.lobby_surface_name] memory.spawnpoint = Common.lobby_spawnpoint local crew_force = game.forces[string.format('crew-%03d', new_id)] crew_force.set_spawn_position(memory.spawnpoint, surface) local message = '[' .. accepted_proposal.name .. '] Launched.' Common.notify_game(message) -- Server.to_discord_embed_raw(CoreData.comfy_emojis.pogkot .. message .. ' Difficulty: ' .. CoreData.difficulty_options[memory.difficulty_option].text .. ', Capacity: ' .. CoreData.capacity_options[memory.capacity_option].text3 .. '.') Server.to_discord_embed_raw(CoreData.comfy_emojis.pogkot .. message .. ' Capacity: ' .. CoreData.capacity_options[memory.capacity_option].text3 .. '.') game.surfaces[CoreData.lobby_surface_name].play_sound{path='utility/new_objective', volume_modifier=0.75} memory.boat = global_memory.lobby_boats[new_id] local boat = memory.boat for _, e in pairs(memory.boat.cannons_temporary_reference or {}) do Common.new_healthbar(true, e, 2000, nil, e.health, 0.3, -0.1, memory.boat) end boat.dockedposition = boat.position boat.speed = 0 boat.cannonscount = 2 end function Public.summon_crew() local memory = Memory.get_crew_memory() local boat = memory.boat local print = false for _, player in pairs(game.connected_players) do if player.surface and player.surface.valid and boat.surface_name and player.surface.name == boat.surface_name and (not Boats.on_boat(boat, player.position)) then local p = player.surface.find_non_colliding_position('character', memory.spawnpoint, 5, 0.1) if p then player.teleport(p) else player.teleport(memory.spawnpoint) end print = true end end if print then Common.notify_force(memory.force, 'Crew summoned.') end end function Public.reset_crew_and_enemy_force(id) local crew_force = game.forces[string.format('crew-%03d', id)] local enemy_force = game.forces[string.format('enemy-%03d', id)] local ancient_friendly_force = game.forces[string.format('ancient-friendly-%03d', id)] local ancient_enemy_force = game.forces[string.format('ancient-hostile-%03d', id)] crew_force.reset() enemy_force.reset() ancient_friendly_force.reset() ancient_enemy_force.reset() ancient_enemy_force.set_turret_attack_modifier('gun-turret', 0.2) enemy_force.reset_evolution() for _, tech in pairs(crew_force.technologies) do crew_force.set_saved_technology_progress(tech, 0) end local lobby = game.surfaces[CoreData.lobby_surface_name] crew_force.set_spawn_position(Common.lobby_spawnpoint, lobby) enemy_force.ai_controllable = true crew_force.set_friend('player', true) game.forces['player'].set_friend(crew_force, true) crew_force.set_friend(ancient_friendly_force, true) ancient_friendly_force.set_friend(crew_force, true) enemy_force.set_friend(ancient_friendly_force, true) ancient_friendly_force.set_friend(enemy_force, true) enemy_force.set_friend(ancient_enemy_force, true) ancient_enemy_force.set_friend(enemy_force, true) -- enemy_force.set_friend(environment_force, true) -- environment_force.set_friend(enemy_force, true) -- environment_force.set_friend(ancient_enemy_force, true) -- ancient_enemy_force.set_friend(environment_force, true) -- environment_force.set_friend(ancient_friendly_force, true) -- ancient_friendly_force.set_friend(environment_force, true) -- maybe make these dependent on map... it could be slower to mine on poor maps, so that players jump more often rather than getting every last drop crew_force.mining_drill_productivity_bonus = 1 -- crew_force.mining_drill_productivity_bonus = 1.25 crew_force.manual_mining_speed_modifier = 3 crew_force.character_inventory_slots_bonus = 10 crew_force.character_running_speed_modifier = Balance.base_extra_character_speed crew_force.laboratory_productivity_bonus = 0 crew_force.ghost_time_to_live = 8 * 60 * 60 for k, v in pairs(Balance.player_ammo_damage_modifiers()) do crew_force.set_ammo_damage_modifier(k, v) end for k, v in pairs(Balance.player_gun_speed_modifiers()) do crew_force.set_gun_speed_modifier(k, v) end for k, v in pairs(Balance.player_turret_attack_modifiers()) do crew_force.set_turret_attack_modifier(k, v) end crew_force.technologies['circuit-network'].researched = true crew_force.technologies['uranium-processing'].researched = true crew_force.technologies['kovarex-enrichment-process'].researched = true crew_force.technologies['gun-turret'].researched = true crew_force.technologies['electric-energy-distribution-1'].researched = true crew_force.technologies['electric-energy-distribution-2'].researched = true crew_force.technologies['advanced-material-processing'].researched = true crew_force.technologies['advanced-material-processing-2'].researched = true crew_force.technologies['solar-energy'].researched = true crew_force.technologies['inserter-capacity-bonus-1'].researched = true --needed to make stack inserters different to fast inserters -- crew_force.technologies['inserter-capacity-bonus-2'].researched = true --as prerequisites for uranium ammo and automation 3: crew_force.technologies['speed-module'].researched = true crew_force.technologies['tank'].researched = true crew_force.recipes['speed-module'].enabled = false crew_force.recipes['tank'].enabled = false crew_force.recipes['cannon-shell'].enabled = false crew_force.recipes['explosive-cannon-shell'].enabled = false --@TRYING this out: crew_force.technologies['coal-liquefaction'].enabled = true crew_force.technologies['coal-liquefaction'].researched = true crew_force.technologies['automobilism'].enabled = false -- note: many of these recipes are overwritten after tech researched!!!!!!! like pistol. check elsewhere in code crew_force.recipes['pistol'].enabled = false -- these are redundant I think...?: crew_force.recipes['centrifuge'].enabled = false crew_force.recipes['flamethrower-turret'].enabled = false crew_force.technologies['railway'].researched = true --needed for purple sci crew_force.recipes['rail'].enabled = true --needed for purple sci crew_force.recipes['locomotive'].enabled = false crew_force.recipes['car'].enabled = false crew_force.recipes['cargo-wagon'].enabled = false crew_force.recipes['nuclear-fuel'].enabled = false -- reduce clutter -- crew_force.recipes['underground-belt'].enabled = false -- crew_force.recipes['fast-underground-belt'].enabled = false -- crew_force.recipes['express-underground-belt'].enabled = false crew_force.technologies['land-mine'].enabled = false crew_force.technologies['landfill'].enabled = false crew_force.technologies['cliff-explosives'].enabled = false crew_force.technologies['rail-signals'].enabled = false crew_force.technologies['logistic-system'].enabled = false crew_force.technologies['tank'].enabled = false crew_force.technologies['rocketry'].enabled = false crew_force.technologies['artillery'].enabled = false crew_force.technologies['destroyer'].enabled = false crew_force.technologies['spidertron'].enabled = false crew_force.technologies['atomic-bomb'].enabled = false crew_force.technologies['explosive-rocketry'].enabled = false crew_force.technologies['research-speed-1'].enabled = false crew_force.technologies['research-speed-2'].enabled = false crew_force.technologies['research-speed-3'].enabled = false crew_force.technologies['research-speed-4'].enabled = false crew_force.technologies['research-speed-5'].enabled = false crew_force.technologies['research-speed-6'].enabled = false -- crew_force.technologies['follower-robot-count-1'].enabled = false -- crew_force.technologies['follower-robot-count-2'].enabled = false -- crew_force.technologies['follower-robot-count-3'].enabled = false -- crew_force.technologies['follower-robot-count-4'].enabled = false -- crew_force.technologies['inserter-capacity-bonus-3'].enabled = false -- crew_force.technologies['inserter-capacity-bonus-4'].enabled = false -- crew_force.technologies['inserter-capacity-bonus-5'].enabled = false -- crew_force.technologies['inserter-capacity-bonus-6'].enabled = false -- crew_force.technologies['refined-flammables-3'].enabled = false -- crew_force.technologies['refined-flammables-4'].enabled = false -- crew_force.technologies['refined-flammables-5'].enabled = false -- for lategame balance: -- crew_force.technologies['worker-robots-storage-1'].enabled = false crew_force.technologies['worker-robots-storage-2'].enabled = false crew_force.technologies['worker-robots-storage-3'].enabled = false crew_force.technologies['worker-robots-speed-5'].enabled = false crew_force.technologies['worker-robots-speed-6'].enabled = false crew_force.technologies['follower-robot-count-5'].enabled = false crew_force.technologies['follower-robot-count-6'].enabled = false crew_force.technologies['follower-robot-count-7'].enabled = false crew_force.technologies['inserter-capacity-bonus-6'].enabled = false crew_force.technologies['inserter-capacity-bonus-7'].enabled = false crew_force.technologies['weapon-shooting-speed-6'].enabled = false crew_force.technologies['laser-shooting-speed-6'].enabled = false crew_force.technologies['laser-shooting-speed-7'].enabled = false crew_force.technologies['refined-flammables-5'].enabled = false crew_force.technologies['refined-flammables-6'].enabled = false crew_force.technologies['refined-flammables-7'].enabled = false crew_force.technologies['energy-weapons-damage-5'].enabled = false --5 makes krakens too easy crew_force.technologies['energy-weapons-damage-6'].enabled = false crew_force.technologies['energy-weapons-damage-7'].enabled = false crew_force.technologies['physical-projectile-damage-5'].enabled = false crew_force.technologies['physical-projectile-damage-6'].enabled = false crew_force.technologies['physical-projectile-damage-7'].enabled = false crew_force.technologies['stronger-explosives-5'].enabled = false crew_force.technologies['stronger-explosives-6'].enabled = false crew_force.technologies['stronger-explosives-7'].enabled = false -- these require 2000 white sci each: crew_force.technologies['artillery-shell-range-1'].enabled = false --infinite techs crew_force.technologies['artillery-shell-speed-1'].enabled = false --infinite techs crew_force.technologies['steel-axe'].enabled = false crew_force.technologies['concrete'].enabled = false crew_force.technologies['nuclear-power'].enabled = false crew_force.technologies['effect-transmission'].enabled = true -- exploit?: crew_force.technologies['gate'].enabled = true crew_force.technologies['productivity-module-2'].enabled = true crew_force.technologies['productivity-module-3'].enabled = false crew_force.technologies['speed-module'].enabled = false crew_force.technologies['speed-module-2'].enabled = false crew_force.technologies['speed-module-3'].enabled = false crew_force.technologies['effectivity-module'].enabled = false crew_force.technologies['effectivity-module-2'].enabled = false crew_force.technologies['effectivity-module-3'].enabled = false crew_force.technologies['automation-3'].enabled = true crew_force.technologies['rocket-control-unit'].enabled = false crew_force.technologies['rocket-silo'].enabled = false crew_force.technologies['space-science-pack'].enabled = false crew_force.technologies['mining-productivity-4'].enabled = false crew_force.technologies['logistics-3'].enabled = true crew_force.technologies['nuclear-fuel-reprocessing'].enabled = false -- crew_force.technologies['railway'].enabled = false crew_force.technologies['automated-rail-transportation'].enabled = false crew_force.technologies['braking-force-1'].enabled = false crew_force.technologies['braking-force-2'].enabled = false crew_force.technologies['braking-force-3'].enabled = false crew_force.technologies['braking-force-4'].enabled = false crew_force.technologies['braking-force-5'].enabled = false crew_force.technologies['braking-force-6'].enabled = false crew_force.technologies['braking-force-7'].enabled = false crew_force.technologies['fluid-wagon'].enabled = false crew_force.technologies['production-science-pack'].enabled = true crew_force.technologies['utility-science-pack'].enabled = true crew_force.technologies['modular-armor'].enabled = false crew_force.technologies['power-armor'].enabled = false crew_force.technologies['solar-panel-equipment'].enabled = false crew_force.technologies['personal-roboport-equipment'].enabled = false crew_force.technologies['personal-laser-defense-equipment'].enabled = false crew_force.technologies['night-vision-equipment'].enabled = false crew_force.technologies['energy-shield-equipment'].enabled = false crew_force.technologies['belt-immunity-equipment'].enabled = false crew_force.technologies['exoskeleton-equipment'].enabled = false crew_force.technologies['battery-equipment'].enabled = false crew_force.technologies['fusion-reactor-equipment'].enabled = false crew_force.technologies['power-armor-mk2'].enabled = false crew_force.technologies['energy-shield-mk2-equipment'].enabled = false crew_force.technologies['personal-roboport-mk2-equipment'].enabled = false crew_force.technologies['battery-mk2-equipment'].enabled = false crew_force.technologies['discharge-defense-equipment'].enabled = false crew_force.technologies['distractor'].enabled = false crew_force.technologies['military-4'].enabled = true crew_force.technologies['uranium-ammo'].enabled = true end return Public