2022-06-01 20:50:36 +02:00
-- This file is part of thesixthroc's Pirate Ship softmod, licensed under GPLv3 and stored at https://github.com/danielmartin0/ComfyFactorio-Pirates.
2021-10-13 10:21:53 +02:00
local Memory = require ' maps.pirates.memory '
local Math = require ' maps.pirates.math '
local Balance = require ' maps.pirates.balance '
local Common = require ' maps.pirates.common '
local CoreData = require ' maps.pirates.coredata '
local Utils = require ' maps.pirates.utils_local '
2022-03-19 23:20:55 +02:00
local _inspect = require ' utils.inspect ' . inspect
2021-10-13 10:21:53 +02:00
local Boats = require ' maps.pirates.structures.boats.boats '
2022-03-19 23:20:55 +02:00
-- local Lobby = require 'maps.pirates.surfaces.lobby'
-- local Dock = require 'maps.pirates.surfaces.dock'
2021-10-13 10:21:53 +02:00
local Hold = require ' maps.pirates.surfaces.hold '
local Cabin = require ' maps.pirates.surfaces.cabin '
2022-03-19 23:20:55 +02:00
-- local Sea = require 'maps.pirates.surfaces.sea.sea'
2021-10-13 10:21:53 +02:00
local Islands = require ' maps.pirates.surfaces.islands.islands '
local Crowsnest = require ' maps.pirates.surfaces.crowsnest '
local Quest = require ' maps.pirates.quest '
2022-05-29 13:43:31 +02:00
-- local Parrot = require 'maps.pirates.parrot'
2021-10-13 10:21:53 +02:00
local ShopMerchants = require ' maps.pirates.shop.merchants '
local SurfacesCommon = require ' maps.pirates.surfaces.common '
2022-03-19 23:20:55 +02:00
-- local Roles = require 'maps.pirates.roles.roles'
2022-03-04 19:57:58 +02:00
local Classes = require ' maps.pirates.roles.classes '
2022-10-10 21:03:51 +02:00
local IslandEnum = require ' maps.pirates.surfaces.islands.island_enum '
2021-10-13 10:21:53 +02:00
local Server = require ' utils.server '
local Public = { }
local enum = SurfacesCommon.enum
Public.enum = enum
Public [ enum.SEA ] = require ' maps.pirates.surfaces.sea.sea '
Public [ enum.ISLAND ] = require ' maps.pirates.surfaces.islands.islands '
Public [ enum.DOCK ] = require ' maps.pirates.surfaces.dock '
Public [ enum.CROWSNEST ] = require ' maps.pirates.surfaces.crowsnest '
Public [ enum.LOBBY ] = require ' maps.pirates.surfaces.lobby '
Public [ enum.HOLD ] = require ' maps.pirates.surfaces.hold '
Public [ enum.CABIN ] = require ' maps.pirates.surfaces.cabin '
Public [ enum.CHANNEL ] = require ' maps.pirates.surfaces.channel.channel '
Public [ ' SurfacesCommon ' ] = require ' maps.pirates.surfaces.common '
function Public . initialise_destination ( o )
o = o or { }
local memory = Memory.get_crew_memory ( )
assert ( memory.destinations , o.overworld_position )
local scope = Public.get_scope ( o )
o.destination_index = # memory.destinations + 1 --assuming none are deleted
memory.destinations [ o.destination_index ] = o
o.dynamic_data = o.dynamic_data or { }
o.static_params = o.static_params or Utils.deepcopy ( Public.get_scope ( o ) . Data.static_params_default )
o.seed = o.seed or Math.random ( 1 , 10000000 )
o.iconized_map = o.iconized_map or { }
o.boat_extra_distance_from_shore = o.boat_extra_distance_from_shore or 0
o.surface_name = o.surface_name or SurfacesCommon.encode_surface_name ( memory.id , o.destination_index , o.type , o.subtype )
2022-03-04 19:57:58 +02:00
o.dynamic_data . other_map_generation_data = o.dynamic_data . other_map_generation_data or { }
2021-10-13 10:21:53 +02:00
if o.type == enum.ISLAND then
2022-03-19 23:20:55 +02:00
2021-10-13 10:21:53 +02:00
o.init_boat_state = Boats.enum_state . APPROACHING
2022-03-19 23:20:55 +02:00
2021-10-13 10:21:53 +02:00
Public.generate_detailed_island_data ( o )
elseif o.type == enum.DOCK then
o.init_boat_state = Boats.enum_state . APPROACHING
o.iconized_map_width = scope.Data . iconized_map_width
o.iconized_map_height = scope.Data . iconized_map_height
end
return o
end
function Public . get_scope ( destination )
if destination.type then
if destination.subtype then
return Public [ destination.type ] [ destination.subtype ]
else
return Public [ destination.type ]
end
else
return { }
end
end
function Public . on_surface_generation ( destination )
2022-03-19 23:20:55 +02:00
-- local memory = Memory.get_crew_memory()
2021-10-13 10:21:53 +02:00
-- game.map_settings.pollution.enemy_attack_pollution_consumption_modifier = Balance.defaultai_attack_pollution_consumption_modifier()
-- Event_functions.flamer_nerfs()
if destination.type == enum.ISLAND then
local subtype = destination.subtype
destination.dynamic_data . rocketsilomaxhp = Balance.silo_max_hp
destination.dynamic_data . rocketsilohp = Balance.silo_max_hp
2022-02-24 21:39:03 +02:00
destination.dynamic_data . rocketsilochargedbools = { }
2021-10-13 10:21:53 +02:00
destination.dynamic_data . rocketsiloenergyconsumed = 0
destination.dynamic_data . rocketsiloenergyconsumedwithinlasthalfsecond = 0
destination.dynamic_data . energychargedinsilosincelastcheck = 0
destination.dynamic_data . silocharged = false
destination.dynamic_data . rocketlaunched = false
2022-10-10 21:03:51 +02:00
if subtype ~= IslandEnum.enum . STANDARD and subtype ~= IslandEnum.enum . STANDARD_VARIANT and subtype ~= IslandEnum.enum . RADIOACTIVE and subtype ~= IslandEnum.enum . RED_DESERT then
2021-10-13 10:21:53 +02:00
destination.dynamic_data . hidden_ore_remaining_abstract = Utils.deepcopy ( destination.static_params . abstract_ore_amounts )
end
2022-10-02 23:37:54 +02:00
2022-10-10 21:03:51 +02:00
if subtype == IslandEnum.enum . CAVE then
2022-10-02 23:37:54 +02:00
if not destination.dynamic_data . cave_miner then
destination.dynamic_data . cave_miner = { }
destination.dynamic_data . cave_miner.reveal_queue = { }
destination.dynamic_data . cave_miner.cave_surface = nil
2022-10-10 21:03:51 +02:00
Islands [ IslandEnum.enum . CAVE ] . roll_source_surface ( destination )
2022-10-02 23:37:54 +02:00
end
end
2021-10-13 10:21:53 +02:00
destination.dynamic_data . wood_remaining = destination.static_params . starting_wood
destination.dynamic_data . rock_material_remaining = destination.static_params . starting_rock_material
destination.dynamic_data . treasure_remaining = destination.static_params . starting_treasure
destination.dynamic_data . ore_types_spawned = { }
destination.dynamic_data . buried_treasure = { }
2022-03-19 23:20:55 +02:00
-- elseif destination.type == enum.DOCK then
2021-10-13 10:21:53 +02:00
end
end
2021-10-14 11:23:34 +02:00
function Public . destination_on_collide ( destination )
local memory = Memory.get_crew_memory ( )
local name = destination.static_params . name and destination.static_params . name or ' NameNotFound '
2022-05-29 13:36:27 +02:00
local message = { ' ' , ' [ ' .. memory.name .. ' ] ' , { ' pirates.approaching_destination ' , memory.destinationsvisited_indices and ( # memory.destinationsvisited_indices + 1 ) or 0 , name } } --notify the whole server
2021-10-14 11:23:34 +02:00
Common.notify_game ( message )
if destination.type ~= Public.enum . DOCK then
local index = destination.destination_index
Crowsnest.paint_around_destination ( index , CoreData.overworld_loading_tile )
end
2022-03-14 14:44:30 +02:00
if destination and destination.static_params and destination.static_params . base_cost_to_undock then
2021-10-14 11:23:34 +02:00
local replace = { }
2022-03-14 14:44:30 +02:00
for item , count in pairs ( destination.static_params . base_cost_to_undock ) do
2022-03-04 19:57:58 +02:00
if item == ' uranium-235 ' or item == ' launch_rocket ' then
2021-10-14 11:23:34 +02:00
replace [ item ] = count
else
2022-02-27 01:33:19 +02:00
replace [ item ] = Math.ceil ( count * Balance.cost_to_leave_multiplier ( ) )
2021-10-14 11:23:34 +02:00
end
end
2022-03-14 14:44:30 +02:00
destination.static_params . base_cost_to_undock = replace
2021-10-14 11:23:34 +02:00
end
if destination.type == Public.enum . ISLAND then
local index = destination.destination_index
Crowsnest.paint_around_destination ( index , CoreData.overworld_loading_tile )
2022-03-10 23:09:06 +02:00
2022-10-10 21:03:51 +02:00
if destination.subtype == IslandEnum.enum . RADIOACTIVE then
2022-05-29 13:36:27 +02:00
Common.parrot_speak ( memory.force , { ' pirates.parrot_radioactive_tip_1 ' } )
2022-03-10 23:09:06 +02:00
2022-10-10 21:03:51 +02:00
elseif destination.subtype == IslandEnum.enum . CAVE then
2022-10-02 23:37:54 +02:00
Common.parrot_speak ( memory.force , { ' pirates.parrot_cave_tip_1 ' } )
else
2022-03-14 14:44:30 +02:00
local scheduled_raft_raids
-- temporarily placed this back here, as moving it to shorehit broke things:
local playercount = Common.activecrewcount ( )
local max_evo
2022-03-15 20:50:19 +02:00
2022-05-30 17:51:08 +02:00
local difficulty_name = CoreData.get_difficulty_option_informal_name_from_value ( Common.difficulty_scale ( ) )
if difficulty_name == ' easy ' then
2022-03-14 14:44:30 +02:00
if memory.overworldx / 40 < 20 then
max_evo = 0.9 - ( 20 - memory.overworldx / 40 ) * 1 / 100
else
max_evo = 0.91 + ( memory.overworldx / 40 - 20 ) * 0.25 / 100
end
2022-05-30 17:51:08 +02:00
elseif difficulty_name == ' normal ' then
2022-03-14 14:44:30 +02:00
if memory.overworldx / 40 < 15 then
max_evo = 0.9 - ( 15 - memory.overworldx / 40 ) * 0.5 / 100
else
max_evo = 0.91 + ( memory.overworldx / 40 - 15 ) * 0.25 / 100
end
2022-03-15 20:50:19 +02:00
else
2022-03-14 14:44:30 +02:00
if memory.overworldx / 40 < 12 then
max_evo = 0.9
else
max_evo = 0.91 + ( memory.overworldx / 40 - 12 ) * 0.25 / 100
end
2022-03-10 23:09:06 +02:00
end
2022-03-19 23:20:55 +02:00
2022-10-02 23:37:54 +02:00
-- Currently biter boats don't spawn properly for cave island, so disabling it for now
2022-10-10 21:03:51 +02:00
if destination.subtype ~= IslandEnum.enum . CAVE then
2022-10-02 23:37:54 +02:00
if memory.overworldx > 200 then
scheduled_raft_raids = { }
local times = { 600 , 360 , 215 , 210 , 120 , 30 , 10 , 5 }
for i = 1 , # times do
local t = times [ i ]
if Math.random ( 6 ) == 1 and # scheduled_raft_raids < 6 then
scheduled_raft_raids [ # scheduled_raft_raids + 1 ] = { timeinseconds = t , max_evo = max_evo }
-- scheduled_raft_raids[#scheduled_raft_raids + 1] = {timeinseconds = t, max_bonus_evolution = 0.52}
end
end
elseif memory.overworldx == 200 then
local times
if playercount <= 2 then
times = { 1 , 5 , 10 , 15 , 20 }
elseif playercount <= 8 then
times = { 1 , 5 , 10 , 15 , 20 , 25 }
elseif playercount <= 15 then
times = { 1 , 5 , 10 , 15 , 20 , 25 , 30 }
elseif playercount <= 21 then
times = { 1 , 5 , 10 , 15 , 20 , 25 , 30 , 35 }
else
times = { 1 , 5 , 10 , 15 , 20 , 25 , 30 , 35 , 40 }
end
scheduled_raft_raids = { }
for _ , t in pairs ( times ) do
-- scheduled_raft_raids[#scheduled_raft_raids + 1] = {timeinseconds = t, max_bonus_evolution = 0.62}
2022-03-14 14:44:30 +02:00
scheduled_raft_raids [ # scheduled_raft_raids + 1 ] = { timeinseconds = t , max_evo = max_evo }
end
end
2022-03-19 23:20:55 +02:00
2022-10-02 23:37:54 +02:00
destination.static_params . scheduled_raft_raids = scheduled_raft_raids
end
2022-03-10 23:09:06 +02:00
end
2021-10-14 11:23:34 +02:00
end
2022-03-14 14:44:30 +02:00
if memory.overworldx == 40 * 5 then
2022-05-29 13:36:27 +02:00
Common.parrot_speak ( memory.force , { ' pirates.parrot_boats_warning ' } )
2022-05-06 02:47:27 +02:00
-- elseif memory.overworldx == 800 then
-- Parrot.parrot_800_tip()
2021-10-14 11:23:34 +02:00
end
end
2021-10-13 10:21:53 +02:00
function Public . destination_on_arrival ( destination )
local memory = Memory.get_crew_memory ( )
-- game.map_settings.pollution.enemy_attack_pollution_consumption_modifier = Balance.defaultai_attack_pollution_consumption_modifier()
2022-05-06 14:00:57 +02:00
-- Event_functions.flamer_nerfs()
log ( ' Playthrough stats: ' )
log ( _inspect ( memory.playtesting_stats ) )
2021-10-13 10:21:53 +02:00
memory.floating_pollution = 0
2022-03-13 20:19:59 +02:00
-- catching a fallthrough error I've observed
if not memory.active_sea_enemies then memory.active_sea_enemies = { } end
memory.active_sea_enemies . krakens = { }
2021-10-13 10:21:53 +02:00
if destination.type == enum.ISLAND then
destination.dynamic_data . rocketsiloenergyneeded = Balance.silo_energy_needed_MJ ( ) * 1000000
2022-05-07 22:41:45 +02:00
destination.dynamic_data . rocketcoalreward = Balance.rocket_launch_fuel_reward ( )
2021-10-13 10:21:53 +02:00
2022-10-10 21:03:51 +02:00
if destination.subtype == IslandEnum.enum . RADIOACTIVE then
2021-10-13 10:21:53 +02:00
destination.dynamic_data . time_remaining = - 1
2022-10-10 21:03:51 +02:00
elseif destination.subtype == IslandEnum.enum . MAZE then --more time
2022-05-05 10:55:48 +02:00
destination.dynamic_data . time_remaining = Math.ceil ( 1.05 * Balance.max_time_on_island ( ) )
2021-10-13 10:21:53 +02:00
else
destination.dynamic_data . time_remaining = Math.ceil ( Balance.max_time_on_island ( ) )
end
2022-10-10 21:03:51 +02:00
if destination.subtype ~= IslandEnum.enum . FIRST and destination.subtype ~= IslandEnum.enum . RADIOACTIVE and destination.destination_index ~= 2 then
2022-05-29 13:36:27 +02:00
-- if not destination.overworld_position.x ~= Common.first_cost_to_leave_macrox * 40 then
2022-10-10 21:03:51 +02:00
if destination.subtype == IslandEnum.enum . CAVE then
2022-10-02 23:37:54 +02:00
Quest.initialise_random_cave_island_quest ( )
else
Quest.initialise_random_quest ( )
end
2022-03-19 23:20:55 +02:00
-- else
2021-10-13 10:21:53 +02:00
-- if _DEBUG then
-- Quest.initialise_random_quest()
-- end
end
2022-03-04 19:57:58 +02:00
memory.enemy_force . reset_evolution ( )
2022-03-17 03:40:18 +02:00
local base_evo = Balance.base_evolution_leagues ( memory.overworldx )
2022-03-01 23:59:48 +02:00
Common.set_evo ( base_evo )
2021-10-13 10:21:53 +02:00
destination.dynamic_data . evolution_accrued_leagues = base_evo
destination.dynamic_data . evolution_accrued_time = 0
2022-10-10 21:03:51 +02:00
if destination.subtype == IslandEnum.enum . RED_DESERT then
2022-03-17 03:40:18 +02:00
destination.dynamic_data . evolution_accrued_sandwurms = 0
else
destination.dynamic_data . evolution_accrued_nests = 0
end
2022-10-10 21:03:51 +02:00
if destination.subtype ~= IslandEnum.enum . RADIOACTIVE then
2022-03-17 03:40:18 +02:00
destination.dynamic_data . evolution_accrued_silo = 0
end
2021-10-13 10:21:53 +02:00
memory.scripted_biters = { }
memory.scripted_unit_groups = { }
memory.floating_pollution = 0
2022-10-10 21:03:51 +02:00
if destination.subtype == IslandEnum.enum . RADIOACTIVE then
Islands [ IslandEnum.enum . RADIOACTIVE ] . spawn_structures ( )
2021-10-13 10:21:53 +02:00
end
-- -- invulnerable bases on islands 21-25
-- if memory.overworldx >= 21 and memory.overworldx < 25 then
-- local surface = game.surfaces[destination.surface_name]
-- if not (surface and surface.valid) then return end
-- local spawners = surface.find_entities_filtered({type = 'unit-spawner', force = memory.enemy_force_name})
-- for _, s in pairs(spawners) do
-- s.destructible = false
-- end
-- end
2022-03-19 23:20:55 +02:00
2021-10-13 10:21:53 +02:00
elseif destination.type == enum.DOCK then
-- -- kick players out of crow's nest
-- local crowsnestname = SurfacesCommon.encode_surface_name(memory.id, 0, enum.CROWSNEST, nil)
-- for _, player in pairs(game.connected_players) do
-- if player.surface.name == crowsnestname then
-- Public.player_exit_crows_nest(player, {x = 5, y = 0})
-- end
-- end
2022-02-25 02:01:28 +02:00
2022-03-07 11:50:25 +02:00
-- New dock class sales:
local class_for_sale = Classes.generate_class_for_sale ( )
destination.static_params . class_for_sale = class_for_sale
2021-10-13 10:21:53 +02:00
end
local name = destination.static_params . name and destination.static_params . name or ' NameNotFound '
2022-05-29 13:36:27 +02:00
local message = { ' pirates.approaching_destination ' , memory.destinationsvisited_indices and # memory.destinationsvisited_indices or 0 , name }
2021-10-13 10:21:53 +02:00
if not ( # memory.destinationsvisited_indices and # memory.destinationsvisited_indices == 1 ) then --don't need to notify for the first island
2022-10-23 18:03:43 +02:00
Server.to_discord_embed_raw ( { ' ' , ( destination.static_params . discord_emoji or CoreData.comfy_emojis . hype ) .. ' [ ' .. memory.name .. ' ] Approaching ' , name , ' , ' .. memory.overworldx .. ' leagues. ' } , true )
2021-10-13 10:21:53 +02:00
end
2022-04-30 00:48:34 +02:00
-- if destination.static_params.name == 'Dock' then
-- message = message .. ' ' .. 'New trades are available in the Captain\'s Store.'
-- end
2022-03-04 19:57:58 +02:00
Common.notify_force ( memory.force , message )
2021-10-13 10:21:53 +02:00
if destination.type == enum.ISLAND then
2022-07-03 16:58:44 +02:00
--game.print('spawning ores, quest structures, etc.')
2021-10-13 10:21:53 +02:00
local points_to_avoid = { }
2022-07-03 16:58:44 +02:00
-- add special chunk structures(small mining base, etc.) to avoid list
local structures = destination.dynamic_data . structures_waiting_to_be_placed
2022-07-07 22:01:45 +02:00
if structures then
for i = # structures , 1 , - 1 do
local structure = structures [ i ]
local special = structure.data
local position = special.position
local avoid_radius = math.sqrt ( special.width * special.width + special.height * special.height ) / 2 + 5
points_to_avoid [ # points_to_avoid + 1 ] = { x = position.x , y = position.y , r = avoid_radius }
end
2022-07-03 16:58:44 +02:00
end
2022-10-10 21:03:51 +02:00
if ( memory.overworldx >= Balance.quest_structures_first_appear_at and destination.subtype ~= IslandEnum.enum . RADIOACTIVE ) or _DEBUG then
2022-10-02 23:37:54 +02:00
local class_for_sale = Classes.generate_class_for_sale ( )
destination.static_params . class_for_sale = class_for_sale
end
-- Caves won't have these fancy things for now, because starting place for this island is so small, weird stuff happens (like quest structure spawning on ship)
2022-10-10 21:03:51 +02:00
if destination.subtype == IslandEnum.enum . CAVE then
2022-10-02 23:37:54 +02:00
return
end
2022-07-03 16:58:44 +02:00
-- game.print('spawning silo')
2022-10-10 21:03:51 +02:00
if destination.subtype ~= IslandEnum.enum . RADIOACTIVE then
2022-07-03 16:58:44 +02:00
local silo_position = Islands.spawn_silo_setup ( points_to_avoid )
2022-03-04 19:57:58 +02:00
if silo_position then
points_to_avoid [ # points_to_avoid + 1 ] = { x = silo_position.x , y = silo_position.y , r = 22 }
end
2021-10-13 10:21:53 +02:00
end
2022-03-04 19:57:58 +02:00
Islands.spawn_ores_on_arrival ( destination , points_to_avoid )
2022-10-10 21:03:51 +02:00
if ( memory.overworldx >= Balance.quest_structures_first_appear_at and destination.subtype ~= IslandEnum.enum . RADIOACTIVE ) or _DEBUG then
2022-05-29 13:36:27 +02:00
local covered = Islands.spawn_quest_structure ( destination , points_to_avoid )
2022-06-01 20:50:36 +02:00
if covered then
points_to_avoid [ # points_to_avoid + 1 ] = { x = covered.x , y = covered.y , r = 25 }
end
2021-10-13 10:21:53 +02:00
end
2022-03-19 23:20:55 +02:00
2021-10-13 10:21:53 +02:00
Islands.spawn_treasure_maps ( destination , points_to_avoid )
Islands.spawn_ghosts ( destination , points_to_avoid )
2022-03-04 19:57:58 +02:00
2022-10-10 21:03:51 +02:00
if destination.subtype == IslandEnum.enum . MAZE then
2022-03-04 19:57:58 +02:00
local force = memory.force
2022-06-03 15:54:43 +02:00
force.manual_mining_speed_modifier = 1
2022-03-04 19:57:58 +02:00
end
end
end
function Public . destination_on_departure ( destination )
local memory = Memory.get_crew_memory ( )
2022-03-19 23:20:55 +02:00
-- local boat = memory.boat
2022-03-04 19:57:58 +02:00
2022-05-06 14:00:57 +02:00
-- need to put tips only where we know there are islands:
2022-03-06 01:42:47 +02:00
if memory.overworldx == 40 * 9 then
2022-05-29 13:36:27 +02:00
Common.parrot_speak ( memory.force , { ' pirates.parrot_kraken_warning ' } )
2022-03-06 01:42:47 +02:00
end
2022-03-04 19:57:58 +02:00
2022-10-10 21:03:51 +02:00
if destination.subtype and destination.subtype == IslandEnum.enum . MAZE then
2022-03-04 19:57:58 +02:00
local force = memory.force
force.manual_mining_speed_modifier = 3 --put back to normal
2021-10-13 10:21:53 +02:00
end
end
function Public . destination_on_crewboat_hits_shore ( destination )
local memory = Memory.get_crew_memory ( )
local boat = memory.boat
destination.dynamic_data . timeratlandingtime = Common.current_destination ( ) . dynamic_data.timer
Boats.place_landingtrack ( boat , CoreData.landing_tile )
Boats.place_boat ( boat , CoreData.static_boat_floor , false , false )
if destination.type == enum.ISLAND then
2022-05-05 10:55:48 +02:00
destination.dynamic_data . initial_spawner_count = Common.spawner_count ( game.surfaces [ destination.surface_name ] )
2021-10-13 10:21:53 +02:00
if memory.overworldx == 0 then
2022-05-29 13:36:27 +02:00
Common.parrot_speak ( memory.force , { ' pirates.parrot_0 ' } )
2022-05-06 14:43:59 +02:00
elseif memory.overworldx == 80 then
2022-05-29 13:36:27 +02:00
Common.parrot_speak ( memory.force , { ' pirates.parrot_night_warning ' } )
2021-10-13 10:21:53 +02:00
end
2022-10-10 21:03:51 +02:00
if destination.subtype == IslandEnum.enum . RADIOACTIVE then
2021-10-13 10:21:53 +02:00
-- replace all miners, so that they sit on uranium properly:
local surface = game.surfaces [ destination.surface_name ]
local miners = surface.find_entities_filtered ( { name = ' electric-mining-drill ' } )
for _ , m in pairs ( miners ) do
local direction = m.direction
local position = m.position
m.destroy ( )
surface.create_entity { name = ' electric-mining-drill ' , direction = direction , position = position }
end
2022-03-19 23:20:55 +02:00
2022-05-29 13:36:27 +02:00
Common.parrot_speak ( memory.force , { ' pirates.parrot_radioactive_tip_2 ' } )
2022-10-10 21:03:51 +02:00
elseif destination.subtype == IslandEnum.enum . MAZE and memory.overworldx == Common.maze_minimap_jam_league then
2022-05-29 13:36:27 +02:00
Common.parrot_speak ( memory.force , { ' pirates.parrot_maze_tip_1 ' } )
2021-10-13 10:21:53 +02:00
end
2022-10-10 21:03:51 +02:00
if ( memory.merchant_ships_unlocked or _DEBUG ) and destination.subtype ~= IslandEnum.enum . CAVE then
2021-10-13 10:21:53 +02:00
Islands.spawn_merchant_ship ( destination )
ShopMerchants.generate_merchant_trades ( destination.dynamic_data . merchant_market )
end
end
end
function Public . generate_detailed_island_data ( destination )
local scope = Public.get_scope ( destination )
local frame_width = scope.Data . terraingen_frame_width
local frame_height = scope.Data . terraingen_frame_height
local boat_extra_distance_from_shore = destination.boat_extra_distance_from_shore
-- scale 1:32
local chunks_horizontal = 2 * Math.floor ( frame_width / 64 )
local chunks_vertical = 2 * Math.floor ( frame_height / 64 )
local entities = { }
local entitymap = { }
local tiles = { }
local tiles2 = { }
local leftboundary , rightboundary , topboundary , bottomboundary = chunks_horizontal / 2 + 1 , - chunks_horizontal / 2 - 1 , chunks_vertical / 2 + 1 , - chunks_vertical / 2 - 1 -- reversed, because we'll iterate
-- local subtype = destination.subtype
local terrain_fn = scope.terrain
2022-03-19 23:20:55 +02:00
2021-10-13 10:21:53 +02:00
local noise_generator = Utils.noise_generator ( scope.Data . noiseparams , destination.seed )
for y = - chunks_vertical / 2 , chunks_vertical / 2 - 1 , 1 do
for x = - chunks_horizontal / 2 , chunks_horizontal / 2 - 1 , 1 do
local macroposition = { x = x + 0.5 , y = y + 0.5 }
local chunk_frameposition_topleft = { x = x * 32 , y = y * 32 }
-- average over the chunk
local modalcounts = { }
for y2 = 5 , 27 , 11 do
for x2 = 5 , 27 , 11 do
local p2 = { x = chunk_frameposition_topleft.x + x2 , y = chunk_frameposition_topleft.y + y2 }
local tiles3 , entities3 = { } , { }
2022-10-02 23:37:54 +02:00
terrain_fn {
p = p2 ,
noise_generator = noise_generator ,
static_params = destination.static_params ,
tiles = tiles3 ,
entities = entities3 ,
decoratives = { } ,
2022-10-23 14:16:39 +02:00
specials = { } ,
2022-10-02 23:37:54 +02:00
seed = destination.seed ,
iconized_generation = true
}
2021-10-13 10:21:53 +02:00
local tile = tiles3 [ 1 ]
if modalcounts [ tile.name ] then
modalcounts [ tile.name ] = modalcounts [ tile.name ] + 1
else
modalcounts [ tile.name ] = 1
end
if y2 == 16 and x2 == 16 and # entities3 > 0 and entities3 [ 1 ] and entities3 [ 1 ] . visible_on_overworld then
entitymap [ macroposition ] = entities3 [ 1 ] . name
end
end
end
local modaltile , max = ' hazard-concrete-left ' , 0
for k , v in pairs ( modalcounts ) do
if v > max then
modaltile , max = k , v
end
end
tiles [ # tiles + 1 ] = { name = modaltile , position = macroposition }
if ( not Utils.contains ( CoreData.water_tile_names , modaltile ) ) then
leftboundary , rightboundary , topboundary , bottomboundary = Math.min ( leftboundary , x ) , Math.max ( rightboundary , x + 1 ) , Math.min ( topboundary , y ) , Math.max ( bottomboundary , y + 1 )
end
end
end
leftboundary , rightboundary , topboundary , bottomboundary = leftboundary - 1 , rightboundary + 1 , topboundary - 1 , bottomboundary + 1 --push out by one step to get some water
-- construct image, and record where entities can be placed:
local positions_free_to_hold_resources = { }
for _ , tile in pairs ( tiles ) do
local x = tile.position . x
local y = tile.position . y
if tile.name ~= ' water ' and x >= leftboundary and x <= rightboundary and y >= topboundary and y <= bottomboundary then --nil represents water
--arrange image so that {0,0} is on the centre of the left edge:
local p = { x = x - leftboundary , y = y - ( topboundary + bottomboundary ) / 2 }
if ( topboundary + bottomboundary ) / 2 % 1 ~= 0 then
p.y = p.y + 0.5 --adjust so that tiles land on half-integer positions
end
tiles2 [ # tiles2 + 1 ] = { name = tile.name , position = p }
if ( not Utils.contains ( CoreData.tiles_that_conflict_with_resource_layer , tile.name ) ) then
2022-03-19 23:20:55 +02:00
2021-10-13 10:21:53 +02:00
local ename = entitymap [ tile.position ]
if ename then
entities [ # entities + 1 ] = { name = ename , position = p }
else
if ( p.x + 2 ) % 4 <= 2 and ( p.y ) % 4 <= 2 then --for the ingame minimap, the ore texture checker only colors these squares
local nearby_es = {
entitymap [ { x = tile.position . x + 1 , y = tile.position . y } ] ,
entitymap [ { x = tile.position . x - 1 , y = tile.position . y } ] ,
entitymap [ { x = tile.position . x , y = tile.position . y + 1 } ] ,
entitymap [ { x = tile.position . x , y = tile.position . y - 1 } ] ,
}
if not ( nearby_es [ 1 ] or nearby_es [ 2 ] or nearby_es [ 3 ] or nearby_es [ 4 ] ) then
positions_free_to_hold_resources [ # positions_free_to_hold_resources + 1 ] = p
-- if destination.destination_index == 3 then
-- game.print(p)
-- end
end
end
end
end
end
end
if # positions_free_to_hold_resources > 0 then
local orestoadd = { }
for k , v in pairs ( destination.static_params . abstract_ore_amounts ) do
if k == ' crude-oil ' then
2022-03-01 23:59:48 +02:00
local count = Math.ceil ( ( v / 20 ) ^ ( 1 / 2 ) ) --assuming the abstract values are about 20 times as big as for other ores
2021-10-13 10:21:53 +02:00
orestoadd [ k ] = { count = count , sizing_each = Common.oil_abstract_to_real ( v ) / count }
else
2022-03-01 23:59:48 +02:00
local count = Math.ceil ( v ^ ( 1 / 2 ) )
2021-10-13 10:21:53 +02:00
orestoadd [ k ] = { count = count , sizing_each = Common.ore_abstract_to_real ( v ) / count }
end
end
for k , v in pairs ( orestoadd ) do
for i = 1 , v.count do
if # positions_free_to_hold_resources > 0 then
local random_index = Math.random ( # positions_free_to_hold_resources )
local p = positions_free_to_hold_resources [ random_index ]
2022-03-19 23:20:55 +02:00
2021-10-13 10:21:53 +02:00
entities [ # entities + 1 ] = { name = k , position = p , amount = v.sizing_each }
2022-03-19 23:20:55 +02:00
2021-10-13 10:21:53 +02:00
for j = random_index , # positions_free_to_hold_resources - 1 do
positions_free_to_hold_resources [ j ] = positions_free_to_hold_resources [ j + 1 ]
end
positions_free_to_hold_resources [ # positions_free_to_hold_resources ] = nil
end
end
end
end
-- get more precise understanding of left-hand shore
local xcorrection = 0
for ystep = - 10 , 10 , 10 do
2022-10-02 23:37:54 +02:00
for xstep = 0 , 300 , 3 do
2021-10-13 10:21:53 +02:00
local x = leftboundary * 32 + 16 + xstep
local y = ( topboundary * 32 + bottomboundary * 32 ) / 2 + ystep
local tiles3 = { }
2022-10-02 23:37:54 +02:00
terrain_fn {
p = { x = x , y = y } ,
noise_generator = noise_generator ,
static_params = destination.static_params ,
tiles = tiles3 ,
entities = { } ,
decoratives = { } ,
2022-10-23 14:16:39 +02:00
specials = { } ,
2022-10-02 23:37:54 +02:00
seed = destination.seed ,
iconized_generation = true
}
2021-10-13 10:21:53 +02:00
local tile = tiles3 [ 1 ]
if ( not Utils.contains ( CoreData.water_tile_names , tile.name ) ) then
xcorrection = Math.max ( xcorrection , xstep + Math.abs ( ystep ) )
break
end
end
end
-- if xcorrection == 0 then xcorrection = 300 end
local iconwidth , iconheight = rightboundary - leftboundary , bottomboundary - topboundary
iconwidth = iconwidth > 0 and iconwidth or 0 --make them 0 if negative
iconheight = iconheight > 0 and iconheight or 0
local extension_to_left = Math.ceil ( Common.boat_default_starting_distance_from_shore + boat_extra_distance_from_shore + Common.mapedge_distance_from_boat_starting_position - xcorrection )
local terraingen_coordinates_offset = { x = ( leftboundary * 32 + rightboundary * 32 ) / 2 - extension_to_left / 2 , y = ( topboundary * 32 + bottomboundary * 32 ) / 2 }
local width = rightboundary * 32 - leftboundary * 32 + extension_to_left
local height = bottomboundary * 32 - topboundary * 32
local deepwater_terraingenframe_xposition = leftboundary * 32 - Common.deepwater_distance_from_leftmost_shore
local islandcenter_position = { x = extension_to_left / 2 , y = 0 }
local deepwater_xposition = deepwater_terraingenframe_xposition - terraingen_coordinates_offset.x
2022-03-19 23:20:55 +02:00
2021-10-13 10:21:53 +02:00
-- -- must ceil this, because if it's a half integer big things will teleport badly:
-- local boat_starting_xposition = Math.ceil(- width/2 + Common.mapedge_distance_from_boat_starting_position)
-- worse, must make this even due to rails:
local boat_starting_xposition = 2 * Math.ceil (
( - width / 2 + Common.mapedge_distance_from_boat_starting_position ) / 2
)
destination.static_params . terraingen_coordinates_offset = terraingen_coordinates_offset
destination.static_params . width = width
destination.static_params . height = height
destination.static_params . islandcenter_position = islandcenter_position
destination.static_params . deepwater_xposition = deepwater_xposition
destination.static_params . deepwater_terraingenframe_xposition = deepwater_terraingenframe_xposition
destination.static_params . boat_starting_xposition = boat_starting_xposition
destination.iconized_map . tiles = tiles2
destination.iconized_map . entities = entities
2022-03-19 23:20:55 +02:00
2021-10-13 10:21:53 +02:00
destination.iconized_map_width = iconwidth
destination.iconized_map_height = iconheight
end
function Public . create_surface ( destination )
local surface_name = destination.surface_name
if game.surfaces [ surface_name ] then return end
-- maybe can set width and height to be 0 here? if so, will need to change references to map_gen_settings.width elsewhere in code
-- local mgs = Utils.deepcopy(Common.default_map_gen_settings(
-- self.static_params.width or 512,
-- self.static_params.height or 512,
-- self.seed or Math.random(1, 1000000)
-- ))
local mgs = Utils.deepcopy ( Common.default_map_gen_settings (
Math.max ( 0 , destination.static_params . width ) or 128 ,
Math.max ( 0 , destination.static_params . height ) or 128 ,
destination.seed or Math.random ( 1 , 1000000 )
) )
--todo: put into static_params
mgs.autoplace_settings . decorative.treat_missing_as_default = destination.static_params . default_decoratives
local surface = game.create_surface ( surface_name , mgs )
surface.solar_power_multiplier = destination.static_params . solar_power_multiplier or 1
surface.show_clouds = destination.static_params . clouds or false
2022-03-17 03:40:18 +02:00
surface.min_brightness = destination.static_params . min_brightness or 0.15
2021-10-13 10:21:53 +02:00
surface.brightness_visual_weights = destination.static_params . brightness_visual_weights or { 1 , 1 , 1 }
surface.daytime = destination.static_params . starting_time_of_day or 0
2022-03-12 00:53:36 +02:00
2021-10-13 10:21:53 +02:00
local daynightcycletype = destination.static_params . daynightcycletype or 1
local ticksperday = CoreData.daynightcycle_types [ daynightcycletype ] . ticksperday or 0
if ticksperday == 0 then
surface.freeze_daytime = true
ticksperday = ticksperday + 1 -- avoid divide by zero
else
surface.freeze_daytime = false
end
surface.ticks_per_day = ticksperday
Public.on_surface_generation ( destination )
end
function Public . clean_up ( destination )
2022-07-08 22:06:35 +02:00
-- game.print('clean_up')
2021-10-13 10:21:53 +02:00
local memory = Memory.get_crew_memory ( )
local oldsurface = game.surfaces [ destination.surface_name ]
if not ( oldsurface and oldsurface.valid ) then return end
-- assuming sea is always default subtype:
local seasurface = game.surfaces [ memory.sea_name ]
2022-03-19 23:20:55 +02:00
2021-10-13 10:21:53 +02:00
Quest.try_resolve_quest ( )
-- handle players that were left on the island
-- if there is more than one crew on a surface, this will need to be generalised
for _ , player in pairs ( game.connected_players ) do
if ( player.surface == oldsurface ) then
2022-03-04 19:57:58 +02:00
if player.character and player.character . valid then player.character . die ( memory.force ) end
2021-10-13 10:21:53 +02:00
player.teleport ( memory.spawnpoint , seasurface )
end
end
2022-10-10 21:03:51 +02:00
Islands [ IslandEnum.enum . CAVE ] . cleanup_cave_surface ( destination )
2022-10-02 23:37:54 +02:00
2021-10-13 10:21:53 +02:00
destination.dynamic_data = { }
memory.scripted_biters = nil
memory.scripted_unit_groups = nil
memory.floating_pollution = nil
if memory.enemy_force_name then
2022-03-04 19:57:58 +02:00
local ef = memory.enemy_force
2021-10-13 10:21:53 +02:00
if ef and ef.valid then
2022-03-04 19:57:58 +02:00
memory.enemy_force . reset_evolution ( )
2022-03-17 03:40:18 +02:00
local base_evo = Balance.base_evolution_leagues ( memory.overworldx )
2022-03-01 23:59:48 +02:00
Common.set_evo ( base_evo )
2021-10-13 10:21:53 +02:00
end
end
2022-03-19 23:20:55 +02:00
2021-10-13 10:21:53 +02:00
game.delete_surface ( oldsurface )
end
-- function Public.crowsnest_init_destinations()
-- local memory = Memory.get_crew_memory()
-- local tiles, entities = {}, {}
-- Overworld.try_overworld_move{x = 0, y = 0}
-- -- for _, destination_data in pairs(memory.destinations) do
-- -- local iconized_map = SurfacesCommon.fetch_iconized_map(destination_data.destination_index)
-- -- for _, t in pairs(iconized_map.tiles) do
-- -- local x = Crowsnest.platformrightmostedge + destination_data.overworld_position.x + t.position.x
-- -- local y = destination_data.overworld_position.y + t.position.y
-- -- if Math.abs(x) < Crowsnest.Data.width/2 and Math.abs(y) < Crowsnest.Data.height/2 then
-- -- tiles[#tiles+1] = {name = t.name, position = {x = x, y = y}}
-- -- end
-- -- end
-- -- for _, e in pairs(iconized_map.entities) do
-- -- local x = Crowsnest.platformrightmostedge + destination_data.overworld_position.x + e.position.x
-- -- local y = destination_data.overworld_position.y + e.position.y
-- -- if Math.abs(x) < Crowsnest.Data.width/2 then
-- -- local e2 = Utils.deepcopy(e)
-- -- e2.position = {x = x, y = y}
-- -- entities[#entities+1] = e2
-- -- end
-- -- end
-- -- end
-- -- Crowsnest.update_surface(tiles, entities)
-- end
function Public . player_goto_crows_nest ( player , player_relative_pos )
local memory = Memory.get_crew_memory ( )
local surface = game.surfaces [ SurfacesCommon.encode_surface_name ( memory.id , 0 , enum.CROWSNEST , nil ) ]
2022-03-19 23:20:55 +02:00
2021-10-13 10:21:53 +02:00
local carpos
if player_relative_pos.x < 0 then
carpos = { x = - 2.29687 , y = 0 }
else
carpos = { x = 3.29687 , y = 0 }
end
local newpos = { x = memory.overworldx + carpos.x - player_relative_pos.x , y = memory.overworldy + carpos.y + player_relative_pos.y }
local newpos2 = surface.find_non_colliding_position ( ' character ' , newpos , 5 , 0.2 ) or newpos
if newpos2 then player.teleport ( newpos2 , surface ) end
-- player.minimap_enabled = false
end
function Public . player_exit_crows_nest ( player , player_relative_pos )
local memory = Memory.get_crew_memory ( )
local surface
2022-07-26 22:59:42 +02:00
if Boats.is_boat_at_sea ( ) then
2021-10-13 10:21:53 +02:00
surface = game.surfaces [ SurfacesCommon.encode_surface_name ( memory.id , 0 , Public.enum . SEA , Public.Sea . enum.DEFAULT ) ]
else
surface = game.surfaces [ Common.current_destination ( ) . surface_name ]
end
local carpos
if player_relative_pos.x > 0 then
carpos = Boats.get_scope ( memory.boat ) . Data.entercrowsnest_cars . right
else
carpos = Boats.get_scope ( memory.boat ) . Data.entercrowsnest_cars . left
end
local newpos = { x = memory.boat . position.x + carpos.x - player_relative_pos.x , y = memory.boat . position.y + carpos.y + player_relative_pos.y }
local newpos2 = surface.find_non_colliding_position ( ' character ' , newpos , 10 , 0.2 ) or newpos
if newpos2 then player.teleport ( newpos2 , surface ) end
-- player.minimap_enabled = true
end
function Public . player_goto_hold ( player , relative_pos , nth )
2022-03-19 23:20:55 +02:00
-- local memory = Memory.get_crew_memory()
2021-10-13 10:21:53 +02:00
local surface = Hold.get_hold_surface ( nth )
2022-03-19 23:20:55 +02:00
2021-10-13 10:21:53 +02:00
local newpos = { x = Hold.Data . loco_offset.x + 1 + relative_pos.x , y = Hold.Data . loco_offset.y + relative_pos.y }
local newpos2 = surface.find_non_colliding_position ( ' character ' , newpos , 5 , 0.2 ) or newpos
if newpos2 then player.teleport ( newpos2 , surface ) end
end
function Public . player_exit_hold ( player , relative_pos )
local memory = Memory.get_crew_memory ( )
local surface
2022-07-26 22:59:42 +02:00
if Boats.is_boat_at_sea ( ) then
2021-10-13 10:21:53 +02:00
surface = game.surfaces [ SurfacesCommon.encode_surface_name ( memory.id , 0 , Public.enum . SEA , Public.Sea . enum.DEFAULT ) ]
else
surface = game.surfaces [ Common.current_destination ( ) . surface_name ]
end
local locopos = Boats.get_scope ( memory.boat ) . Data.loco_pos
local newpos = { x = memory.boat . position.x + locopos.x + relative_pos.x , y = memory.boat . position.y + locopos.y + relative_pos.y }
local newpos2 = surface.find_non_colliding_position ( ' character ' , newpos , 10 , 0.2 ) or newpos
if newpos2 then player.teleport ( newpos2 , surface ) end
end
function Public . player_goto_cabin ( player , relative_pos )
2022-05-29 13:36:27 +02:00
local memory = Memory.get_crew_memory ( )
2021-10-13 10:21:53 +02:00
local surface = Cabin.get_cabin_surface ( )
2022-03-19 23:20:55 +02:00
2021-10-13 10:21:53 +02:00
local newpos = { x = Cabin.Data . car_pos.x - relative_pos.x , y = Cabin.Data . car_pos.y + relative_pos.y }
local newpos2 = surface.find_non_colliding_position ( ' character ' , newpos , 5 , 0.2 ) or newpos
if newpos2 then player.teleport ( newpos2 , surface ) end
2022-05-29 13:36:27 +02:00
if ( not memory.captain_cabin_hint_given ) and Common.is_captain ( player ) then
memory.captain_cabin_hint_given = true
Common.parrot_speak ( memory.force , { ' pirates.parrot_captain_first_time_in_cabin_hint ' } )
end
2021-10-13 10:21:53 +02:00
end
function Public . player_exit_cabin ( player , relative_pos )
local memory = Memory.get_crew_memory ( )
local surface
2022-07-26 22:59:42 +02:00
if Boats.is_boat_at_sea ( ) then
2021-10-13 10:21:53 +02:00
surface = game.surfaces [ SurfacesCommon.encode_surface_name ( memory.id , 0 , Public.enum . SEA , Public.Sea . enum.DEFAULT ) ]
else
surface = game.surfaces [ Common.current_destination ( ) . surface_name ]
end
local carpos = Boats.get_scope ( memory.boat ) . Data.cabin_car
local newpos = { x = memory.boat . position.x + carpos.x - relative_pos.x , y = memory.boat . position.y + carpos.y + relative_pos.y }
local newpos2 = surface.find_non_colliding_position ( ' character ' , newpos , 10 , 0.2 ) or newpos
if newpos2 then player.teleport ( newpos2 , surface ) end
end
return Public