-- This file is part of thesixthroc's Pirate Ship softmod, licensed under GPLv3 and stored at https://github.com/ComfyFactory/ComfyFactorio and https://github.com/danielmartin0/ComfyFactorio-Pirates. local Public = {} 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' -- local _inspect = require 'utils.inspect'.inspect -- local Server = require 'utils.server' -- local Structures = require 'maps.pirates.structures.structures' local Boats = require 'maps.pirates.structures.boats.boats' local Surfaces = require 'maps.pirates.surfaces.surfaces' local Crowsnest = require 'maps.pirates.surfaces.crowsnest' local Dock = require 'maps.pirates.surfaces.dock' local Islands = require 'maps.pirates.surfaces.islands.islands' -- local Sea = require 'maps.pirates.surfaces.sea.sea' local Crew = require 'maps.pirates.crew' -- local Roles = require 'maps.pirates.roles.roles' -- local Classes = require 'maps.pirates.roles.classes' -- local Quest = require 'maps.pirates.quest' -- local Parrot = require 'maps.pirates.parrot' -- local Hold = require 'maps.pirates.surfaces.hold' -- local Cabin = require 'maps.pirates.surfaces.cabin' local Shop = require 'maps.pirates.shop.shop' local Upgrades = require 'maps.pirates.boat_upgrades' local Kraken = require 'maps.pirates.surfaces.sea.kraken' local Highscore = require 'maps.pirates.highscore' local CustomEvents = require 'maps.pirates.custom_events' local IslandEnum = require 'maps.pirates.surfaces.islands.island_enum' local NIL = 'none' local DOCK = 'dock' local FIRST = IslandEnum.enum.FIRST local RED_DESERT = IslandEnum.enum.RED_DESERT local SWAMP = IslandEnum.enum.SWAMP local STANDARD = IslandEnum.enum.STANDARD local WALKWAYS = IslandEnum.enum.WALKWAYS local MAZE = IslandEnum.enum.MAZE local RADIOACTIVE = IslandEnum.enum.RADIOACTIVE local HORSESHOE = IslandEnum.enum.HORSESHOE local STANDARD2 = IslandEnum.enum.STANDARD_VARIANT local CAVE = IslandEnum.enum.CAVE local A = {STANDARD2, RED_DESERT, HORSESHOE, WALKWAYS} local B = {NIL, NIL, NIL, STANDARD, STANDARD2, RED_DESERT, HORSESHOE, WALKWAYS, CAVE} local C = {STANDARD, STANDARD2, RED_DESERT, HORSESHOE, WALKWAYS} local D = {NIL, NIL, NIL, STANDARD, STANDARD2, RED_DESERT, HORSESHOE, WALKWAYS, SWAMP, CAVE} local destinationScheme = { [0] = {FIRST, NIL, NIL}, [1] = {HORSESHOE, HORSESHOE, HORSESHOE}, --map where you break rocks [2] = {STANDARD2, STANDARD2, STANDARD2}, --aesthetically different to previous map [3] = {DOCK, NIL, NIL}, [4] = {A, A, NIL}, [5] = {STANDARD, STANDARD, STANDARD}, --biter boats appear. large island works well so players run off [6] = {MAZE, MAZE, MAZE}, [7] = {DOCK, B, B}, [8] = {NIL, NIL, NIL}, [9] = {B, B, B}, [10] = {NIL, NIL, NIL}, [11] = {DOCK, B, B}, [12] = {SWAMP, SWAMP, C}, --gotta steer if you don't want to do swamp [13] = {B, B, B}, [14] = {B, B, B}, [15] = {DOCK, B, B}, [16] = {RADIOACTIVE, RADIOACTIVE, RADIOACTIVE}, [17] = {B, B, B}, [18] = {C, C, C}, --first showing of robot frame cost [19] = {DOCK, B, B}, [20] = {WALKWAYS, WALKWAYS, WALKWAYS}, --rocket launch cost begins [21] = {SWAMP, RED_DESERT, STANDARD2}, -- uniquely, this has a rocket launch cost, but still has an auto-undock timer [22] = {NIL, NIL, NIL}, [23] = {C, C, C}, [24] = {MAZE, MAZE, MAZE}, -- current 'boss map' [25] = {NIL, NIL, NIL}, } function Public.generate_destination_type_and_subtype(overworld_position) local macro_p = {x = overworld_position.x/40, y = overworld_position.y/24} local macro_x = macro_p.x local macro_y = macro_p.y local type2, subtype if destinationScheme[macro_x] then subtype = destinationScheme[macro_x][macro_y + 2] else if (macro_x - 22) % 20 == 0 then subtype = RADIOACTIVE elseif (macro_x - 22) % 20 == 18 then subtype = MAZE elseif macro_y == -1 and (macro_x % 4) == 3 then subtype = DOCK else subtype = D end end if type(subtype) == 'table' then if destinationScheme[macro_x - 1] then local previous = destinationScheme[macro_x - 1][macro_y + 2] if previous and type(previous) ~= 'table' and previous ~= NIL and previous ~= DOCK then subtype = Utils.deepcopy(subtype) subtype = Utils.ordered_table_with_values_removed(subtype, previous) --avoid duplicate subtype twice in a row in the same lane end end subtype = subtype[Math.random(#subtype)] end if subtype == NIL then type2 = nil subtype = nil elseif subtype == DOCK then type2 = Surfaces.enum.DOCK subtype = nil else type2 = Surfaces.enum.ISLAND end return {type = type2, subtype = subtype} -- return {type = Surfaces.enum.ISLAND, subtype = IslandEnum.enum.CAVE} end function Public.generate_destination_base_cost_to_undock(p, subtype) local macro_p = {x = p.x/40, y = p.y/24} local base_cost_to_undock local normal_costitems = {'electronic-circuit', 'advanced-circuit'} -- local special_costitems = {'rocket-fuel', 'flying-robot-frame'} -- These need to scale up slightly slower than the static fuel depletion rate, so you're increasingly incentivised to leave: local base_cost_1 = { ['electronic-circuit'] = Math.ceil(((macro_p.x-2)^(2/3))*120), } local base_cost_2 = { ['electronic-circuit'] = Math.ceil(((macro_p.x-2)^(2/3))*200), ['advanced-circuit'] = Math.ceil(((macro_p.x-14)^(2/3))*20), -- the below got this response from a new player: "This feels... underwhelming." -- ['electronic-circuit'] = Math.ceil(((macro_p.x-2)^(2/3))*120), -- ['advanced-circuit'] = Math.ceil(((macro_p.x-14)^(2/3))*18), } local base_cost_2b = { ['electronic-circuit'] = Math.ceil(((macro_p.x-2)^(2/3))*200), ['flying-robot-frame'] = 5, } local base_cost_3 = { ['electronic-circuit'] = Math.ceil(((macro_p.x-2)^(2/3))*160), ['advanced-circuit'] = Math.ceil(((macro_p.x-14)^(2/3))*20), ['launch_rocket'] = true, } local base_cost_4 = { ['electronic-circuit'] = Math.ceil(((macro_p.x-2)^(2/3))*140), ['advanced-circuit'] = Math.ceil(((macro_p.x-14)^(2/3))*20), ['flying-robot-frame'] = Math.ceil(((macro_p.x-18)^(2/3))*25), ['launch_rocket'] = true, } local base_cost_5 = { ['electronic-circuit'] = Math.ceil(((macro_p.x-2)^(2/3))*140), ['advanced-circuit'] = Math.ceil(((macro_p.x-14)^(2/3))*20), ['flying-robot-frame'] = Math.ceil(((macro_p.x-18)^(2/3))*10), -- ['rocket-fuel'] = Math.ceil(((macro_p.x-18)^(2/3))*10), -- ['electronic-circuit'] = Math.ceil(((macro_p.x-2)^(2/3))*100), -- ['advanced-circuit'] = Math.ceil(((macro_p.x-14)^(2/3))*20), -- ['flying-robot-frame'] = Math.ceil(((macro_p.x-18)^(2/3))*10), } -- if macro_p.x == 0 then -- if _DEBUG then -- base_cost_to_undock = { -- ['electronic-circuit'] = 5, -- ['engine-unit'] = 5, -- ['advanced-circuit'] = 5, -- ['flying-robot-frame'] = 5, -- } -- end -- base_cost_to_undock = nil -- elseif macro_p.x <= 6 then if macro_p.x <= Common.first_cost_to_leave_macrox - 1 then -- base_cost_to_undock = {['electronic-circuit'] = 5} base_cost_to_undock = nil elseif macro_p.x <= 9 then base_cost_to_undock = base_cost_1 elseif macro_p.x <= 15 then if macro_p.x % 3 > 0 then base_cost_to_undock = base_cost_1 else base_cost_to_undock = nil end elseif macro_p.x == 18 then --a super small amount of flying-robot-frame on a relatively early level so that they see they need lubricant base_cost_to_undock = base_cost_2b elseif macro_p.x <= 19 then if macro_p.x % 3 == 0 then base_cost_to_undock = nil else base_cost_to_undock = base_cost_2 end -- after this point, mandatory to pay. except for 21 elseif macro_p.x == 21 then base_cost_to_undock = base_cost_2 elseif macro_p.x <= 23 then base_cost_to_undock = base_cost_3 elseif macro_p.x <= 24 then base_cost_to_undock = base_cost_4 else base_cost_to_undock = Utils.deepcopy(base_cost_5) local delete = normal_costitems[Math.random(#normal_costitems)] base_cost_to_undock[delete] = nil -- local delete2 = special_costitems[Math.random(#special_costitems)] -- base_cost_to_undock[delete2] = nil if macro_p.x < 50 then if macro_p.x % 2 == 0 then base_cost_to_undock['launch_rocket'] = true end else --now we're just trying to kill you base_cost_to_undock['launch_rocket'] = true end end -- override: if subtype == IslandEnum.enum.RADIOACTIVE then base_cost_to_undock = { ['uranium-235'] = Math.ceil(Math.ceil(65 + 2 * (macro_p.x - 1))), -- people now have access to uranium tech and can make it on ship -- ['uranium-235'] = Math.ceil(Math.ceil(80 + (macro_p.x - 1))), -- ['uranium-235'] = Math.ceil(Math.ceil(80 + (macro_p.x)/2)), --tried adding beacons instead of this } elseif subtype == IslandEnum.enum.RED_DESERT or subtype == IslandEnum.enum.CAVE then if base_cost_to_undock and base_cost_to_undock['launch_rocket'] == true then base_cost_to_undock['launch_rocket'] = nil end end -- -- debug override: -- if _DEBUG then -- base_cost_to_undock = { -- ['electronic-circuit'] = 200, -- ['launch_rocket'] = true, -- } -- end return base_cost_to_undock -- Multiplication by Balance.cost_to_leave_multiplier() happens later, in destination_on_collide. end local infront_positions = {} for x = -6, -3 do for y = - 3, 3 do infront_positions[#infront_positions + 1] = {x = x, y = y} end end local interior_positions = {} for x = 1, 14 do for y = - 3, 3 do interior_positions[#interior_positions + 1] = {x = x, y = y} end end function Public.generate_overworld_destination(p) -- be careful when calling any Balance functions that depend on overworldx — they will be evaluated when the island is chosen, not on arrival local memory = Memory.get_crew_memory() local macro_p = {x = p.x/40, y = p.y/24} local type_data = Public.generate_destination_type_and_subtype(p) local type = type_data.type local subtype = type_data.subtype if type == Surfaces.enum.ISLAND then local scope = Surfaces[Surfaces.enum.ISLAND][subtype] local static_params = Utils.deepcopy(scope.Data.static_params_default) static_params.base_cost_to_undock = Public.generate_destination_base_cost_to_undock(p, subtype) -- Multiplication by Balance.cost_to_leave_multiplier() happens later, in destination_on_collide. static_params.undock_cost_decreases = true if Boats.need_resources_to_undock(p.x, subtype) then static_params.undock_cost_decreases = false end --scheduled raft raids moved to destination_on_arrival local ores_multiplier = Balance.game_ores_scale(p.x) local base_ores = scope.Data.base_ores() local rngs = {} local rngsum = 0 local rngcount = 0 for k, _ in pairs(base_ores) do if k ~= 'coal' then -- It's preferred to create variance with different island types, rather than this, as it's important to have low variance in early islands for easier balance and predictable early gameplay. -- Here we increase "rng" element on later islands as that's when "rng" shouldn't matter too much once players got solid start. local rng if p.x <= 400 then rng = Math.random_float_in_range(0.8, 1.2) else rng = Math.random_float_in_range(0.5, 1.5) end -- local rng = 2*Math.random() -- such huge variance hard to reason and balance around, considering resources aren't equally worth. -- local rng = 1 + ((2*Math.random() - 1)^3) --lower variances rngs[k] = rng rngsum = rngsum + rng rngcount = rngcount + 1 end end local abstract_ore_amounts = {} for k, v in pairs(base_ores) do local rng = 1 if not (k == 'coal' or macro_p.x == 0) then rng = rngs[k] / (rngsum/rngcount) --average of 1 end abstract_ore_amounts[k] = ores_multiplier * v * rng end static_params.abstract_ore_amounts = abstract_ore_amounts static_params.radius_squared_modifier = (2 + 2 * Math.random()) if macro_p.x == 0 then static_params.radius_squared_modifier = 1.75 end static_params.discord_emoji = scope.Data.discord_emoji local rng = 0.5 + 1 * Math.random() static_params.starting_treasure_maps = Math.ceil((static_params.base_starting_treasure_maps or 0) * rng) static_params.starting_wood = static_params.base_starting_wood or 1000 static_params.starting_wood = Math.ceil(static_params.starting_wood * Balance.game_resources_scale(p.x)) static_params.starting_rock_material = Math.ceil(static_params.base_starting_rock_material or 300) * Balance.game_resources_scale(p.x) rng = 0.5 + 1 * Math.random() static_params.starting_treasure = Math.ceil((static_params.base_starting_treasure or 1000) * Balance.game_resources_scale(p.x) * rng) static_params.name = scope.Data.display_names[Math.random(#scope.Data.display_names)] local dest = Surfaces.initialise_destination{ static_params = static_params, type = type, subtype = subtype, overworld_position = p, } Crowsnest.draw_destination(dest) elseif type == Surfaces.enum.DOCK then local boat_for_sale_type -- if macro_p.x == 3 then -- boat_for_sale_type = Boats.enum.CUTTER -- elseif macro_p.x == 7 or macro_p.x == 0 then -- boat_for_sale_type = Boats.enum.SLOOP_WITH_HOLD -- end boat_for_sale_type = Boats.enum.SLOOP local upgrade_for_sale = nil -- These upgrades have been made to be exclusive purchase at captain's cabin -- local upgrade_for_sale -- if macro_p.x == 0 then -- upgrade_for_sale = nil -- elseif macro_p.x == 3 then -- upgrade_for_sale = Upgrades.enum.MORE_POWER -- elseif macro_p.x == 7 then -- upgrade_for_sale = Upgrades.enum.EXTRA_HOLD -- elseif macro_p.x % 16 < 8 then -- upgrade_for_sale = Upgrades.enum.MORE_POWER -- else -- upgrade_for_sale = Upgrades.enum.EXTRA_HOLD -- end --upgrades like UNLOCK_MERCHANTS will slot themselves in when necessary, due to .overwrite_a_dock_upgrade() (not anymore) -- one day it's worth making this system more readable -- NOTE: When DOCK frequency changes, this needs to change too (kinda bad design, but whatever) -- NOTE: I couldn't manage to make upgrade overwriting to work so I made it here -- TODO: Perhaps always have something special to sell (or remove the upgrade market if it has no offers?) if macro_p.x % 16 == 15 and (not memory.rockets_for_sale) then upgrade_for_sale = Upgrades.enum.ROCKETS_FOR_SALE elseif macro_p.x % 16 == 3 and macro_p.x > 16 and (not memory.merchant_ships_unlocked) then upgrade_for_sale = Upgrades.enum.UNLOCK_MERCHANTS elseif (macro_p.x % 8) == 3 then upgrade_for_sale = Upgrades.enum.UPGRADE_CANNONS end local static_params = Utils.deepcopy(Dock.Data.static_params_default) static_params.upgrade_for_sale = upgrade_for_sale static_params.boat_for_sale_type = boat_for_sale_type static_params.name = Dock.Data.display_names[Math.random(#Dock.Data.display_names)] local dest = Surfaces.initialise_destination{ static_params = static_params, type = type, subtype = subtype, overworld_position = {x = p.x, y = -36}, -- overworld_position = {x = p.x, y = 36}, } Crowsnest.draw_destination(dest) -- renderings e.g. for docks local surface = Crowsnest.get_crowsnest_surface() local x = Crowsnest.platformrightmostedge + dest.overworld_position.x local y = dest.overworld_position.y if dest.static_params.upgrade_for_sale then local display_form = {'', Upgrades.crowsnest_display_form[dest.static_params.upgrade_for_sale], ':'} if not dest.dynamic_data.crowsnest_renderings then dest.dynamic_data.crowsnest_renderings = {} end dest.dynamic_data.crowsnest_renderings.base_text_rendering = rendering.draw_text{ text = display_form, surface = surface, target = {x = x + 5.5, y = y + 2.5}, color = CoreData.colors.renderingtext_green, scale = 7, font = 'default-game', alignment = 'right', visible = false, } local i = 1 for price_name, price_count in pairs(Shop.Captains.main_shop_data_1[dest.static_params.upgrade_for_sale].base_cost) do local sprite if price_name == 'fuel' then sprite = 'item/coal' else sprite = 'item/coin' end dest.dynamic_data.crowsnest_renderings[price_name] = { text_rendering = rendering.draw_text{ text = Utils.bignumber_abbrevform2(price_count), surface = surface, target = {x = x + 6, y = y + 8.3 - i * 3.5}, color = CoreData.colors.renderingtext_green, scale = 5.2, font = 'default-game', alignment = 'left', visible = false, }, sprite_rendering = rendering.draw_sprite{ sprite = sprite, surface = surface, target = {x = x + 14.1, y = y + 10.8 - i * 3.5}, x_scale = 4.5, y_scale = 4.5, visible = false, } } i = i + 1 end end end --== krakens ==-- local kraken_count = 0 local position_candidates if type == nil then kraken_count = Balance.krakens_per_free_slot(p.x) position_candidates = interior_positions elseif type ~= Surfaces.enum.DOCK then kraken_count = Balance.krakens_per_slot() position_candidates = infront_positions end -- override: if macro_p.x < 10 then kraken_count = 0 elseif macro_p.x == 10 then kraken_count = 1 elseif macro_p.x == 22 then kraken_count = 2 end -- if _DEBUG then -- kraken_count = 1 -- end if position_candidates then local random_indices = Math.random_unique_array_indices(#position_candidates, Math.min(kraken_count, 10)) if random_indices then for _, idx in ipairs(random_indices) do local p_chosen = position_candidates[idx] local p_kraken = Utils.psum{p_chosen, p} Crowsnest.draw_kraken(p_kraken) memory.overworld_krakens[#memory.overworld_krakens + 1] = p_kraken end end end end function Public.ensure_lane_generated_up_to(lane_yvalue, x) -- make sure lane_yvalue=0 is painted first local memory = Memory.get_crew_memory() local highest_x = memory['greatest_overworldx_generated_for_' .. lane_yvalue] or -40 local whilesafety = 0 while whilesafety < 10 and highest_x < x do whilesafety = whilesafety + 1 highest_x = highest_x + 32 + 7 + 1 -- should be at least maximum island size plus crowsnest platform size plus 1 if lane_yvalue == 0 then Crowsnest.paint_water_between_overworld_positions(highest_x + 32 + 7 + 1, highest_x + 32 + 7 + 1 + 40) -- a little hack that we're updating this here rather than Crowsnest, due to the dependency on Shop to avoid a loop... almost finished 1.0, so too late to figure out how to restructure things for now! for _, dest in pairs(memory.destinations) do if dest.static_params.upgrade_for_sale and dest.dynamic_data.crowsnest_renderings then if rendering.is_valid(dest.dynamic_data.crowsnest_renderings.base_text_rendering) then rendering.set_text(dest.dynamic_data.crowsnest_renderings.base_text_rendering, {'', Upgrades.crowsnest_display_form[dest.static_params.upgrade_for_sale], ':'}) end for rendering_name, r in pairs(dest.dynamic_data.crowsnest_renderings) do if type(r) == 'table' and r.text_rendering and rendering.is_valid(r.text_rendering) then rendering.set_text(r.text_rendering, Utils.bignumber_abbrevform2(Shop.Captains.main_shop_data_1[dest.static_params.upgrade_for_sale].base_cost[rendering_name])) end end end end Crowsnest.update_destination_renderings() end Public.generate_overworld_destination{x = highest_x, y = lane_yvalue} end memory['greatest_overworldx_generated_for_' .. lane_yvalue] = highest_x end function Public.is_position_free_to_move_to(p) local memory = Memory.get_crew_memory() local ret = true for _, destination_data in pairs(memory.destinations) do if p.x >= destination_data.overworld_position.x + 1 and p.x <= destination_data.overworld_position.x + destination_data.iconized_map_width + Crowsnest.platformwidth - 1 and p.y >= destination_data.overworld_position.y - destination_data.iconized_map_width/2 - Crowsnest.platformheight/2 + 1 and p.y <= destination_data.overworld_position.y + destination_data.iconized_map_width/2 + Crowsnest.platformheight/2 - 1 then ret = false break end end return ret end function Public.check_for_kraken_collisions() local memory = Memory.get_crew_memory() for i = #memory.overworld_krakens, 1, -1 do local k = memory.overworld_krakens[i] local relativex = Crowsnest.platformrightmostedge + k.x - memory.overworldx local relativey = k.y - memory.overworldy if (relativex <= 3.5 and relativex >= -3.5 and relativey >= -4 and relativey <= 4) then Kraken.try_spawn_kraken() memory.overworld_krakens = Utils.ordered_table_with_index_removed(memory.overworld_krakens, i) end end end function Public.check_for_destination_collisions() local memory = Memory.get_crew_memory() -- if memory.overworldx > CoreData.victory_x - 10 then return end -- to avoid crashing into the finish line... for _, destination_data in pairs(memory.destinations) do local relativex = Crowsnest.platformrightmostedge + destination_data.overworld_position.x - memory.overworldx local relativey = destination_data.overworld_position.y - memory.overworldy if (relativex == 4 and relativey + destination_data.iconized_map_height/2 >= -3.5 and relativey - destination_data.iconized_map_height/2 <= 3.5) then --or (relativey - destination_data.iconized_map.height/2 == 5 and (relativex >= -3.5 or relativex <= 4.5)) or (relativey + destination_data.iconized_map.height/2 == -4 and (relativex >= -3.5 or relativex <= 4.5)) -- Surfaces.clean_up(Common.current_destination()) Surfaces.create_surface(destination_data) local index = destination_data.destination_index memory.loadingticks = 0 memory.mapbeingloadeddestination_index = index memory.currentdestination_index = index memory.boat.state = Boats.enum_state.ATSEA_LOADING_MAP script.raise_event(CustomEvents.enum['update_crew_progress_gui'], {}) local destination = Common.current_destination() Surfaces.destination_on_collide(destination) Public.cleanup_old_destination_data() return true end end return false end function Public.cleanup_old_destination_data() --we do actually access destinations behind us (during the cleanup process and for marooned players), so only fire this when safe. (EDIT: Can this be refactored now that we no longer maroon?) local memory = Memory.get_crew_memory() for i, destination_data in pairs(memory.destinations) do if destination_data.overworld_position.x < memory.overworldx then Islands[IslandEnum.enum.CAVE].cleanup_cave_surface(memory.destinations[i]) memory.destinations[i] = nil end end end function Public.try_overworld_move_v2(vector) --islands stay, crowsnest moves local memory = Memory.get_crew_memory() -- if memory.game_lost or (memory.victory_pause_until_tick and game.tick < memory.victory_pause_until_tick) then return end -- if memory.victory_continue_message then -- memory.victory_continue_message = false -- Common.notify_force(memory.force, {'pirates.crew_continue_on_freeplay'}, CoreData.colors.notify_victory) -- end if vector.x > 0 then Public.ensure_lane_generated_up_to(0, memory.overworldx + Crowsnest.Data.visibilitywidth) Public.ensure_lane_generated_up_to(24, memory.overworldx + Crowsnest.Data.visibilitywidth) Public.ensure_lane_generated_up_to(-24, memory.overworldx + Crowsnest.Data.visibilitywidth) -- Public.overwrite_a_dock_upgrade() end if not Public.is_position_free_to_move_to{x = memory.overworldx + vector.x, y = memory.overworldy+ vector.y} then if _DEBUG then log(string.format('can\'t move by ' .. vector.x .. ', ' .. vector.y)) end return false else Crowsnest.move_crowsnest(vector.x, vector.y) if vector.x > 0 then -- merchant is disabled -- crew bonus resources per x: -- local crew = Common.crew_get_crew_members() -- for _, player in pairs(crew) do -- if Common.validate_player_and_character(player) then -- local player_index = player.index -- if memory.classes_table and memory.classes_table[player_index] == Classes.enum.MERCHANT then -- Common.flying_text_small(player.surface, player.position, '[color=0.97,0.9,0.2]+[/color]') -- Common.give_items_to_crew{{name = 'coin', count = 50 * vector.x}} -- end -- end -- end -- other freebies: -- for i=1,vector.x do -- Common.give_items_to_crew(Balance.periodic_free_resources_per_x()) -- end Balance.apply_crew_buffs_from_leagues(memory.force, memory.overworldx, memory.overworldx + vector.x) -- add some evo: (this will get reset upon arriving at a destination anyway, so this is just relevant for sea monsters and the like:) local extra_evo = Balance.base_evolution_leagues(memory.overworldx) - Balance.base_evolution_leagues(memory.overworldx - vector.x) Common.increment_evo(extra_evo) end if memory.overworldx >= CoreData.victory_x then Crew.try_win() end if memory.overworldx % 40 == 0 then local modal_captain = nil local modal_captain_time = 0 for name, time in pairs(memory.captain_accrued_time_data) do if time > modal_captain_time then modal_captain_time = time modal_captain = name end end Highscore.write_score(memory.secs_id, memory.name, modal_captain, memory.completion_time or 0, memory.overworldx, CoreData.version_string, memory.difficulty, memory.max_players_recorded or 0) end return true end end -- UNUSED function Public.overwrite_a_dock_upgrade() local memory = Memory.get_crew_memory() if (memory.overworldx % (40*8)) == (40*4-1) then -- pick a point that _must_ be visited, i.e. right before a destination -- POWER upgrade is disabled at docks -- if (memory.overworldx) == (40*4-1) then -- LEAVE A GAP at x=40*11, because we haven't developed an upgrade to put there yet -- for _, dest in pairs(memory.destinations) do -- if dest.type == Surfaces.enum.DOCK then -- if dest.overworld_position.x == memory.overworldx + 1 + (40*7) then -- dest.static_params.upgrade_for_sale = Upgrades.enum.MORE_POWER -- end -- end -- end -- else local upgrade_to_overwrite_with if not memory.dock_overwrite_variable then memory.dock_overwrite_variable = 1 end local possible_overwrites = {} if (not memory.merchant_ships_unlocked) then possible_overwrites[#possible_overwrites + 1] = Upgrades.enum.UNLOCK_MERCHANTS end if (not memory.rockets_for_sale) then possible_overwrites[#possible_overwrites + 1] = Upgrades.enum.ROCKETS_FOR_SALE end if #possible_overwrites > 0 then if memory.dock_overwrite_variable > #possible_overwrites then memory.dock_overwrite_variable = 1 end upgrade_to_overwrite_with = possible_overwrites[memory.dock_overwrite_variable] -- bump the variable up, but only if the list hasn't reduced in length. use a second variable to track this: if memory.dock_overwrite_variable_2 and memory.dock_overwrite_variable_2 == #possible_overwrites then memory.dock_overwrite_variable = memory.dock_overwrite_variable + 1 end memory.dock_overwrite_variable_2 = #possible_overwrites end if upgrade_to_overwrite_with then for _, dest in pairs(memory.destinations) do if dest.type == Surfaces.enum.DOCK then if dest.overworld_position.x == memory.overworldx + 1 + (40*7) then dest.static_params.upgrade_for_sale = upgrade_to_overwrite_with end end end end -- end end end return Public